4545#define CMD_GET_CUSTOM_VARS 40
4646#define CMD_SET_CUSTOM_VAR 41
4747#define CMD_GET_ADVERT_PATH 42
48+ #define CMD_GET_TUNING_PARAMS 43
49+ // NOTE: CMD range 44..49 parked, potentially for WiFi operations
50+ #define CMD_SEND_BINARY_REQ 50
51+ #define CMD_FACTORY_RESET 51
4852
4953#define RESP_CODE_OK 0
5054#define RESP_CODE_ERR 1
6973#define RESP_CODE_SIGNATURE 20
7074#define RESP_CODE_CUSTOM_VARS 21
7175#define RESP_CODE_ADVERT_PATH 22
76+ #define RESP_CODE_TUNING_PARAMS 23
7277
7378#define SEND_TIMEOUT_BASE_MILLIS 500
7479#define FLOOD_SEND_TIMEOUT_FACTOR 16 .0f
9196#define PUSH_CODE_TRACE_DATA 0x89
9297#define PUSH_CODE_NEW_ADVERT 0x8A
9398#define PUSH_CODE_TELEMETRY_RESPONSE 0x8B
99+ #define PUSH_CODE_BINARY_RESPONSE 0x8C
94100
95101#define ERR_CODE_UNSUPPORTED_CMD 1
96102#define ERR_CODE_NOT_FOUND 2
@@ -319,13 +325,17 @@ void MyMesh::queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packe
319325 uint8_t frame[1 ];
320326 frame[0 ] = PUSH_CODE_MSG_WAITING; // send push 'tickle'
321327 _serial->writeFrame (frame, 1 );
322- } else {
323- #ifdef DISPLAY_CLASS
324- ui_task.soundBuzzer (UIEventType::contactMessage);
325- #endif
326328 }
329+
327330#ifdef DISPLAY_CLASS
328- ui_task.newMsg (path_len, from.name , text, offline_queue_len);
331+ // we only want to show text messages on display, not cli data
332+ bool should_display = txt_type == TXT_TYPE_PLAIN || txt_type == TXT_TYPE_SIGNED_PLAIN;
333+ if (should_display) {
334+ ui_task.newMsg (path_len, from.name , text, offline_queue_len);
335+ if (!_serial->isConnected ()) {
336+ ui_task.soundBuzzer (UIEventType::contactMessage);
337+ }
338+ }
329339#endif
330340}
331341
@@ -462,6 +472,7 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
462472 i += 6 ; // pub_key_prefix
463473 memcpy (&out_frame[i], &tag, 4 );
464474 i += 4 ; // NEW: include server timestamp
475+ out_frame[i++] = data[7 ]; // NEW (v7): ACL permissions
465476 } else {
466477 out_frame[i++] = PUSH_CODE_LOGIN_FAIL;
467478 out_frame[i++] = 0 ; // reserved
@@ -484,7 +495,7 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
484495 memcpy (&out_frame[i], &data[4 ], len - 4 );
485496 i += (len - 4 );
486497 _serial->writeFrame (out_frame, i);
487- } else if (len > 4 && tag == pending_telemetry) { // check for telemetry response
498+ } else if (len > 4 && tag == pending_telemetry) { // check for matching response tag
488499 pending_telemetry = 0 ;
489500
490501 int i = 0 ;
@@ -495,6 +506,17 @@ void MyMesh::onContactResponse(const ContactInfo &contact, const uint8_t *data,
495506 memcpy (&out_frame[i], &data[4 ], len - 4 );
496507 i += (len - 4 );
497508 _serial->writeFrame (out_frame, i);
509+ } else if (len > 4 && tag == pending_req) { // check for matching response tag
510+ pending_req = 0 ;
511+
512+ int i = 0 ;
513+ out_frame[i++] = PUSH_CODE_BINARY_RESPONSE;
514+ out_frame[i++] = 0 ; // reserved
515+ memcpy (&out_frame[i], &tag, 4 ); // app needs to match this to RESP_CODE_SENT.tag
516+ i += 4 ;
517+ memcpy (&out_frame[i], &data[4 ], len - 4 );
518+ i += (len - 4 );
519+ _serial->writeFrame (out_frame, i);
498520 }
499521}
500522
@@ -560,7 +582,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
560582 _cli_rescue = false ;
561583 offline_queue_len = 0 ;
562584 app_target_ver = 0 ;
563- pending_login = pending_status = pending_telemetry = 0 ;
585+ pending_login = pending_status = pending_telemetry = pending_req = 0 ;
564586 next_ack_idx = 0 ;
565587 sign_data = NULL ;
566588 dirty_contacts_expiry = 0 ;
@@ -1012,6 +1034,13 @@ void MyMesh::handleCmdFrame(size_t len) {
10121034 _prefs.airtime_factor = ((float )af) / 1000 .0f ;
10131035 savePrefs ();
10141036 writeOKFrame ();
1037+ } else if (cmd_frame[0 ] == CMD_GET_TUNING_PARAMS) {
1038+ uint32_t rx = _prefs.rx_delay_base * 1000 , af = _prefs.airtime_factor * 1000 ;
1039+ int i = 0 ;
1040+ out_frame[i++] = RESP_CODE_TUNING_PARAMS;
1041+ memcpy (&out_frame[i], &rx, 4 ); i += 4 ;
1042+ memcpy (&out_frame[i], &af, 4 ); i += 4 ;
1043+ _serial->writeFrame (out_frame, i);
10151044 } else if (cmd_frame[0 ] == CMD_SET_OTHER_PARAMS) {
10161045 _prefs.manual_add_contacts = cmd_frame[1 ];
10171046 if (len >= 3 ) {
@@ -1090,7 +1119,7 @@ void MyMesh::handleCmdFrame(size_t len) {
10901119 if (result == MSG_SEND_FAILED) {
10911120 writeErrFrame (ERR_CODE_TABLE_FULL);
10921121 } else {
1093- pending_telemetry = pending_status = 0 ;
1122+ pending_req = pending_telemetry = pending_status = 0 ;
10941123 memcpy (&pending_login, recipient->id .pub_key , 4 ); // match this to onContactResponse()
10951124 out_frame[0 ] = RESP_CODE_SENT;
10961125 out_frame[1 ] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0 ;
@@ -1110,7 +1139,7 @@ void MyMesh::handleCmdFrame(size_t len) {
11101139 if (result == MSG_SEND_FAILED) {
11111140 writeErrFrame (ERR_CODE_TABLE_FULL);
11121141 } else {
1113- pending_telemetry = pending_login = 0 ;
1142+ pending_req = pending_telemetry = pending_login = 0 ;
11141143 // FUTURE: pending_status = tag; // match this in onContactResponse()
11151144 memcpy (&pending_status, recipient->id .pub_key , 4 ); // legacy matching scheme
11161145 out_frame[0 ] = RESP_CODE_SENT;
@@ -1122,7 +1151,7 @@ void MyMesh::handleCmdFrame(size_t len) {
11221151 } else {
11231152 writeErrFrame (ERR_CODE_NOT_FOUND); // contact not found
11241153 }
1125- } else if (cmd_frame[0 ] == CMD_SEND_TELEMETRY_REQ && len >= 4 + PUB_KEY_SIZE) {
1154+ } else if (cmd_frame[0 ] == CMD_SEND_TELEMETRY_REQ && len >= 4 + PUB_KEY_SIZE) { // can deprecate, in favour of CMD_SEND_BINARY_REQ
11261155 uint8_t *pub_key = &cmd_frame[4 ];
11271156 ContactInfo *recipient = lookupContactByPubKey (pub_key, PUB_KEY_SIZE);
11281157 if (recipient) {
@@ -1131,7 +1160,7 @@ void MyMesh::handleCmdFrame(size_t len) {
11311160 if (result == MSG_SEND_FAILED) {
11321161 writeErrFrame (ERR_CODE_TABLE_FULL);
11331162 } else {
1134- pending_status = pending_login = 0 ;
1163+ pending_status = pending_login = pending_req = 0 ;
11351164 pending_telemetry = tag; // match this in onContactResponse()
11361165 out_frame[0 ] = RESP_CODE_SENT;
11371166 out_frame[1 ] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0 ;
@@ -1157,6 +1186,27 @@ void MyMesh::handleCmdFrame(size_t len) {
11571186 memcpy (&out_frame[i], telemetry.getBuffer (), tlen);
11581187 i += tlen;
11591188 _serial->writeFrame (out_frame, i);
1189+ } else if (cmd_frame[0 ] == CMD_SEND_BINARY_REQ && len >= 2 + PUB_KEY_SIZE) {
1190+ uint8_t *pub_key = &cmd_frame[1 ];
1191+ ContactInfo *recipient = lookupContactByPubKey (pub_key, PUB_KEY_SIZE);
1192+ if (recipient) {
1193+ uint8_t *req_data = &cmd_frame[1 + PUB_KEY_SIZE];
1194+ uint32_t tag, est_timeout;
1195+ int result = sendRequest (*recipient, req_data, len - (1 + PUB_KEY_SIZE), tag, est_timeout);
1196+ if (result == MSG_SEND_FAILED) {
1197+ writeErrFrame (ERR_CODE_TABLE_FULL);
1198+ } else {
1199+ pending_status = pending_login = pending_telemetry = 0 ;
1200+ pending_req = tag; // match this in onContactResponse()
1201+ out_frame[0 ] = RESP_CODE_SENT;
1202+ out_frame[1 ] = (result == MSG_SEND_SENT_FLOOD) ? 1 : 0 ;
1203+ memcpy (&out_frame[2 ], &tag, 4 );
1204+ memcpy (&out_frame[6 ], &est_timeout, 4 );
1205+ _serial->writeFrame (out_frame, 10 );
1206+ }
1207+ } else {
1208+ writeErrFrame (ERR_CODE_NOT_FOUND); // contact not found
1209+ }
11601210 } else if (cmd_frame[0 ] == CMD_HAS_CONNECTION && len >= 1 + PUB_KEY_SIZE) {
11611211 uint8_t *pub_key = &cmd_frame[1 ];
11621212 if (hasConnectionTo (pub_key)) {
@@ -1312,6 +1362,15 @@ void MyMesh::handleCmdFrame(size_t len) {
13121362 } else {
13131363 writeErrFrame (ERR_CODE_NOT_FOUND);
13141364 }
1365+ } else if (cmd_frame[0 ] == CMD_FACTORY_RESET && memcmp (&cmd_frame[1 ], " reset" , 5 ) == 0 ) {
1366+ bool success = _store->formatFileSystem ();
1367+ if (success) {
1368+ writeOKFrame ();
1369+ delay (1000 );
1370+ board.reboot (); // doesn't return
1371+ } else {
1372+ writeErrFrame (ERR_CODE_FILE_IO_ERROR);
1373+ }
13151374 } else {
13161375 writeErrFrame (ERR_CODE_UNSUPPORTED_CMD);
13171376 MESH_DEBUG_PRINTLN (" ERROR: unknown command: %02X" , cmd_frame[0 ]);
0 commit comments