unparsed response handling; async for most calls

This commit is contained in:
Ben Menking
2026-06-23 17:20:50 -04:00
parent 985e76c938
commit c5ac643299
3 changed files with 86 additions and 47 deletions
+10 -3
View File
@@ -22,6 +22,7 @@ use Menking\Meshcore\Model\MessageResponse;
use Menking\Meshcore\Model\MessagesWaitingResponse;
use Menking\Meshcore\Model\NoMoreMessagesResponse;
use Menking\Meshcore\Model\OkResponse;
use Menking\Meshcore\Model\UnparsedResponse;
class CoreParser {
/**
@@ -34,7 +35,6 @@ class CoreParser {
case CoreProtocol::RESP_CODE_OK:
return self::parseOk($payload);
case CoreProtocol::RESP_CODE_ERR:
//throw new \Exception("Protocol error: " . CoreProtocol::getErrorText(ord($payload[1])));
return self::parseError($payload);
case CoreProtocol::RESP_CODE_CONTACT:
return self::getContact($payload);
@@ -76,11 +76,18 @@ class CoreParser {
case CoreProtocol::PUSH_CODE_CONTACTS_FULL:
return new ContactsFullResponse();
default:
echo "Unparsed response: " . \Menking\Meshcore\Util\Debug::hexDump($payload) . "\n";
return $payload;
return self::unparsed($payload);
}
}
protected static function unparsed(string $payload): UnparsedResponse {
$m = new UnparsedResponse();
$m->code = ord($payload[0]);
$m->payload = $payload;
return $m;
}
protected static function parseOk(string $payload): OkResponse {
$m = new OkResponse();
$m->code = ord($payload[0]);
+67 -44
View File
@@ -40,22 +40,24 @@ class Meshcore {
/**
*
* @param string $app_name
* @param bool $async
* @return null|AppStartResponse
*/
public function appStart(string $app_name): ?AppStartResponse {
public function appStart(string $app_name, bool $async = false): ?AppStartResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_APP_START) . chr(0x00) . " " . $app_name);
return $this->waitForResponse([AppStartResponse::class]);
return $this->waitForResponse([AppStartResponse::class], $async);
}
/**
*
* @param bool $async
* @return null|BatteryStorageResponse
*/
public function getBatteryAndStorage(): ?BatteryStorageResponse {
public function getBatteryAndStorage(bool $async = false): ?BatteryStorageResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_GET_BATT_AND_STORAGE));
return $this->waitForResponse([BatteryStorageResponse::class]);
return $this->waitForResponse([BatteryStorageResponse::class], $async);
}
/**
@@ -68,23 +70,25 @@ class Meshcore {
/**
*
* @param bool $async
* @return null|DeviceInfoResponse
*/
public function getDeviceInfo(): ?DeviceInfoResponse {
public function getDeviceInfo(bool $async = false): ?DeviceInfoResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_DEVICE_QUERY) . 0x03);
return $this->waitForResponse([DeviceInfoResponse::class]);
return $this->waitForResponse([DeviceInfoResponse::class], $async);
}
/**
*
* @param int $channel_idx
* @param bool $async
* @return null|ChannelResponse
*/
public function getChannel(int $channel_idx): ?ChannelResponse {
public function getChannel(int $channel_idx, bool $async = false): ?ChannelResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_GET_CHANNEL) . chr($channel_idx));
return $this->waitForResponse([ChannelResponse::class]);
return $this->waitForResponse([ChannelResponse::class], $async);
}
/**
@@ -93,9 +97,10 @@ class Meshcore {
* @param float $bw
* @param int $sf
* @param int $cr
* @param bool $async
* @return null|OkResponse
*/
public function setRadioParams(float $freq, float $bw, int $sf, int $cr): ?OkResponse {
public function setRadioParams(float $freq, float $bw, int $sf, int $cr, bool $async = false): ?OkResponse {
$payload = chr(CoreProtocol::CMD_SET_RADIO_PARAMS)
. pack('V', $freq * 1000)
. pack('V', $bw * 1000)
@@ -105,7 +110,7 @@ class Meshcore {
CoreProtocol::writeFrame($this->serial, $payload);
return $this->waitForResponse([OkResponse::class]);
return $this->waitForResponse([OkResponse::class], $async);
}
/**
@@ -132,164 +137,182 @@ class Meshcore {
/**
*
* @param bool $async
* @return null|MessageResponse
*/
public function getNextMessage(): ?MessageResponse {
public function getNextMessage(bool $async = false): ?MessageResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_SYNC_NEXT_MESSAGE));
return $this->waitForResponse([MessageResponse::class, NoMoreMessagesResponse::class]);
return $this->waitForResponse([MessageResponse::class, NoMoreMessagesResponse::class], $async);
}
/**
*
* @param string $message
* @param int $channel_idx
* @param bool $async
* @return null|CodeSentResponse
*/
public function sendChannelTxtMessage(string $message, int $channel_idx): ?CodeSentResponse {
public function sendChannelTxtMessage(string $message, int $channel_idx, bool $async = false): ?CodeSentResponse {
$payload = chr(CoreProtocol::CMD_SEND_CHANNEL_TXT_MSG) . chr(0x00) . chr($channel_idx) . pack('V', time()) . "$message\0";
CoreProtocol::writeFrame($this->serial, $payload);
return $this->waitForResponse([CodeSentResponse::class]);
return $this->waitForResponse([CodeSentResponse::class], $async);
}
/**
*
* @param bool $async
* @return null|CurrentTimeResponse
*/
public function getDeviceTime(): ?CurrentTimeResponse {
public function getDeviceTime(bool $async = false): ?CurrentTimeResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_GET_DEVICE_TIME));
return $this->waitForResponse([CurrentTimeResponse::class]);
return $this->waitForResponse([CurrentTimeResponse::class], $async);
}
/**
* Sets the time on the device to the current system time.
*
* @param bool $async
* @return null|OkResponse
*/
public function setDeviceTime(): ?OkResponse {
public function setDeviceTime(bool $async = false): ?OkResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_SET_DEVICE_TIME) . pack('V', time()));
return $this->waitForResponse([OkResponse::class]);
return $this->waitForResponse([OkResponse::class], $async);
}
/**
*
* @param string $contact_pk
* @param string $password
* @param bool $async
* @return null|CodeSentResponse
*/
public function login(string $contact_pk, string $password): ?CodeSentResponse {
public function login(string $contact_pk, string $password, bool $async = false): ?CodeSentResponse {
$payload = chr(CoreProtocol::CMD_SEND_LOGIN) . str_pad(base64_decode($contact_pk), CoreProtocol::PUB_KEY_SIZE, "\0") . $password . chr(0x00);
CoreProtocol::writeFrame($this->serial, $payload);
return $this->waitForResponse([CodeSentResponse::class]);
return $this->waitForResponse([CodeSentResponse::class], $async);
}
/**
*
* @param string $contact_pk
* @param bool $async
* @return null|OkResponse
*/
public function disconnect(string $contact_pk): ?OkResponse {
public function disconnect(string $contact_pk, bool $async = false): ?OkResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_LOGOUT) . base64_decode($contact_pk) . "\0");
return $this->waitForResponse([OkResponse::class]);
return $this->waitForResponse([OkResponse::class], $async);
}
/**
*
* @param string $contact_pk
* @param bool $async
* @return null|CodeSentResponse
*/
public function statusRequest(string $contact_pk ): ?CodeSentResponse {
public function statusRequest(string $contact_pk, bool $async = false): ?CodeSentResponse {
$payload = chr(CoreProtocol::CMD_SEND_STATUS_REQ) . base64_decode($contact_pk);
CoreProtocol::writeFrame($this->serial, $payload);
return $this->waitForResponse([CodeSentResponse::class]);
return $this->waitForResponse([CodeSentResponse::class], $async);
}
/**
*
* @param string $contact_pk
* @param bool $async
* @return null|OkResponse
*/
public function connected(string $contact_pk): ?OkResponse {
public function connected(string $contact_pk, bool $async = false): ?OkResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_HAS_CONNECTION) . base64_decode($contact_pk) . "\0");
return $this->waitForResponse([OkResponse::class]);
return $this->waitForResponse([OkResponse::class], $async);
}
/**
*
* @param string $contact_pk
* @param bool $async
* @return null|OkResponse
*/
public function getTelemetryRequest(string $contact_pk): ?OkResponse {
public function getTelemetryRequest(string $contact_pk, bool $async = false): ?OkResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_SEND_TELEMETRY_REQ) . base64_decode($contact_pk));
return $this->waitForResponse([OkResponse::class]);
return $this->waitForResponse([OkResponse::class], $async);
}
/**
*
* @param string $contact_pk
* @param bool $async
* @return null|OkResponse
*/
public function sendAnonRequest(string $contact_pk): ?OkResponse {
public function sendAnonRequest(string $contact_pk, bool $async = false): ?OkResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_SEND_ANON_REQ) . base64_decode($contact_pk) . "\0");
return $this->waitForResponse([OkResponse::class]);
return $this->waitForResponse([OkResponse::class], $async);
}
/**
*
* @param string $request
* @param bool $async
* @return null|CodeSentResponse
*/
public function sendBinaryRequest(string $request): ?CodeSentResponse {
public function sendBinaryRequest(string $request, bool $async = false): ?CodeSentResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_SEND_BINARY_REQ) . $request);
return $this->waitForResponse([CodeSentResponse::class]);
return $this->waitForResponse([CodeSentResponse::class], $async);
}
/**
*
* @param string $contact_pk
* @param bool $async
* @return null|AdvertPathResponse
*/
public function getAdvertPath(string $contact_pk): ?AdvertPathResponse {
public function getAdvertPath(string $contact_pk, bool $async = false): ?AdvertPathResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_GET_ADVERT_PATH) . chr(0x00) . base64_decode($contact_pk));
return $this->waitForResponse([AdvertPathResponse::class]);
return $this->waitForResponse([AdvertPathResponse::class], $async);
}
/**
*
* @param int $type
* @param bool $async
* @return null|CodeStatusResponse
*/
public function getStats(int $type): ?CodeStatusResponse {
public function getStats(int $type, bool $async = false): ?CodeStatusResponse {
CoreProtocol::writeFrame($this->serial, chr(CoreProtocol::CMD_GET_STATS) . chr($type));
return $this->waitForResponse([CodeStatusResponse::class]);
return $this->waitForResponse([CodeStatusResponse::class], $async);
}
public function setChannel(int $idx, string $name, string $secret): ?OkResponse {
echo "secret length: " . strlen($secret) . "\n";
/**
*
* @param int $idx
* @param string $name
* @param string $secret
* @param bool $async
* @return null|OkResponse
*/
public function setChannel(int $idx, string $name, string $secret, bool $async = false): ?OkResponse {
$payload = chr(CoreProtocol::CMD_SET_CHANNEL)
. chr($idx)
. str_pad($name, 32, "\0")
. $secret;
echo "payload length: " . strlen($payload) . "\n";
echo \Menking\Meshcore\Util\Debug::hexDump($payload) . "\n";
CoreProtocol::writeFrame($this->serial, $payload);
return $this->waitForResponse([OkResponse::class]);
return $this->waitForResponse([OkResponse::class], $async);
}
/**
@@ -337,7 +360,7 @@ class Meshcore {
* @return mixed
* @throws InvalidArgumentException
*/
private function waitForResponse(array $classes_expected): mixed {
private function waitForResponse(array $classes_expected, bool $async = false): mixed {
foreach($classes_expected as $class) {
if( !class_exists($class) ) {
throw new \InvalidArgumentException("Class $class does not exist");
@@ -354,7 +377,7 @@ class Meshcore {
array_push($this->msg_queue, $obj);
}
}
while((time() - $mark) < 5 && !in_array(get_class($obj), $classes_expected));
while(!$async && (time() - $mark) < 5 && !in_array(get_class($obj), $classes_expected));
return in_array(get_class($obj), $classes_expected)?$obj:null;
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace Menking\Meshcore\Model;
class UnparsedResponse extends Response {
public int $code;
public string $payload;
}