|
50 | 50 | #define CMD_SEND_BINARY_REQ 50 |
51 | 51 | #define CMD_FACTORY_RESET 51 |
52 | 52 | #define CMD_SEND_PATH_DISCOVERY_REQ 52 |
| 53 | +#define CMD_SET_FLOOD_SCOPE 54 // v8+ |
| 54 | +#define CMD_SEND_CONTROL_DATA 55 // v8+ |
53 | 55 |
|
54 | 56 | #define RESP_CODE_OK 0 |
55 | 57 | #define RESP_CODE_ERR 1 |
|
99 | 101 | #define PUSH_CODE_TELEMETRY_RESPONSE 0x8B |
100 | 102 | #define PUSH_CODE_BINARY_RESPONSE 0x8C |
101 | 103 | #define PUSH_CODE_PATH_DISCOVERY_RESPONSE 0x8D |
| 104 | +#define PUSH_CODE_CONTROL_DATA 0x8E // v8+ |
102 | 105 |
|
103 | 106 | #define ERR_CODE_UNSUPPORTED_CMD 1 |
104 | 107 | #define ERR_CODE_NOT_FOUND 2 |
@@ -378,6 +381,35 @@ void MyMesh::queueMessage(const ContactInfo &from, uint8_t txt_type, mesh::Packe |
378 | 381 | #endif |
379 | 382 | } |
380 | 383 |
|
| 384 | +bool MyMesh::filterRecvFloodPacket(mesh::Packet* packet) { |
| 385 | + // REVISIT: try to determine which Region (from transport_codes[1]) that Sender is indicating for replies/responses |
| 386 | + // if unknown, fallback to finding Region from transport_codes[0], the 'scope' used by Sender |
| 387 | + return false; |
| 388 | +} |
| 389 | + |
| 390 | +void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) { |
| 391 | + // TODO: dynamic send_scope, depending on recipient and current 'home' Region |
| 392 | + if (send_scope.isNull()) { |
| 393 | + sendFlood(pkt, delay_millis); |
| 394 | + } else { |
| 395 | + uint16_t codes[2]; |
| 396 | + codes[0] = send_scope.calcTransportCode(pkt); |
| 397 | + codes[1] = 0; // REVISIT: set to 'home' Region, for sender/return region? |
| 398 | + sendFlood(pkt, codes, delay_millis); |
| 399 | + } |
| 400 | +} |
| 401 | +void MyMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis) { |
| 402 | + // TODO: have per-channel send_scope |
| 403 | + if (send_scope.isNull()) { |
| 404 | + sendFlood(pkt, delay_millis); |
| 405 | + } else { |
| 406 | + uint16_t codes[2]; |
| 407 | + codes[0] = send_scope.calcTransportCode(pkt); |
| 408 | + codes[1] = 0; // REVISIT: set to 'home' Region, for sender/return region? |
| 409 | + sendFlood(pkt, codes, delay_millis); |
| 410 | + } |
| 411 | +} |
| 412 | + |
381 | 413 | void MyMesh::onMessageRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t sender_timestamp, |
382 | 414 | const char *text) { |
383 | 415 | markConnectionActive(from); // in case this is from a server, and we have a connection |
@@ -596,6 +628,26 @@ bool MyMesh::onContactPathRecv(ContactInfo& contact, uint8_t* in_path, uint8_t i |
596 | 628 | return BaseChatMesh::onContactPathRecv(contact, in_path, in_path_len, out_path, out_path_len, extra_type, extra, extra_len); |
597 | 629 | } |
598 | 630 |
|
| 631 | +void MyMesh::onControlDataRecv(mesh::Packet *packet) { |
| 632 | + if (packet->payload_len + 4 > sizeof(out_frame)) { |
| 633 | + MESH_DEBUG_PRINTLN("onControlDataRecv(), payload_len too long: %d", packet->payload_len); |
| 634 | + return; |
| 635 | + } |
| 636 | + int i = 0; |
| 637 | + out_frame[i++] = PUSH_CODE_CONTROL_DATA; |
| 638 | + out_frame[i++] = (int8_t)(_radio->getLastSNR() * 4); |
| 639 | + out_frame[i++] = (int8_t)(_radio->getLastRSSI()); |
| 640 | + out_frame[i++] = packet->path_len; |
| 641 | + memcpy(&out_frame[i], packet->payload, packet->payload_len); |
| 642 | + i += packet->payload_len; |
| 643 | + |
| 644 | + if (_serial->isConnected()) { |
| 645 | + _serial->writeFrame(out_frame, i); |
| 646 | + } else { |
| 647 | + MESH_DEBUG_PRINTLN("onControlDataRecv(), data received while app offline"); |
| 648 | + } |
| 649 | +} |
| 650 | + |
599 | 651 | void MyMesh::onRawDataRecv(mesh::Packet *packet) { |
600 | 652 | if (packet->payload_len + 4 > sizeof(out_frame)) { |
601 | 653 | MESH_DEBUG_PRINTLN("onRawDataRecv(), payload_len too long: %d", packet->payload_len); |
@@ -663,6 +715,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe |
663 | 715 | sign_data = NULL; |
664 | 716 | dirty_contacts_expiry = 0; |
665 | 717 | memset(advert_paths, 0, sizeof(advert_paths)); |
| 718 | + memset(send_scope.key, 0, sizeof(send_scope.key)); |
666 | 719 |
|
667 | 720 | // defaults |
668 | 721 | memset(&_prefs, 0, sizeof(_prefs)); |
@@ -1485,6 +1538,21 @@ void MyMesh::handleCmdFrame(size_t len) { |
1485 | 1538 | } else { |
1486 | 1539 | writeErrFrame(ERR_CODE_FILE_IO_ERROR); |
1487 | 1540 | } |
| 1541 | + } else if (cmd_frame[0] == CMD_SET_FLOOD_SCOPE && len >= 2 && cmd_frame[1] == 0) { |
| 1542 | + if (len >= 2 + 16) { |
| 1543 | + memcpy(send_scope.key, &cmd_frame[2], sizeof(send_scope.key)); // set curr scope TransportKey |
| 1544 | + } else { |
| 1545 | + memset(send_scope.key, 0, sizeof(send_scope.key)); // set scope to null |
| 1546 | + } |
| 1547 | + writeOKFrame(); |
| 1548 | + } else if (cmd_frame[0] == CMD_SEND_CONTROL_DATA && len >= 2 && (cmd_frame[1] & 0x80) != 0) { |
| 1549 | + auto resp = createControlData(&cmd_frame[1], len - 1); |
| 1550 | + if (resp) { |
| 1551 | + sendZeroHop(resp); |
| 1552 | + writeOKFrame(); |
| 1553 | + } else { |
| 1554 | + writeErrFrame(ERR_CODE_TABLE_FULL); |
| 1555 | + } |
1488 | 1556 | } else { |
1489 | 1557 | writeErrFrame(ERR_CODE_UNSUPPORTED_CMD); |
1490 | 1558 | MESH_DEBUG_PRINTLN("ERROR: unknown command: %02X", cmd_frame[0]); |
|
0 commit comments