diff --git a/docs/software/device-api.md b/docs/software/device-api.md index 933cd7c3..2f1845f1 100644 --- a/docs/software/device-api.md +++ b/docs/software/device-api.md @@ -33,6 +33,7 @@ Typical flow when a phone connects to the device should be the following (if you - There are only three relevant endpoints (and they have built in BLE documentation - so use a BLE tool of your choice to watch them): FromRadio, FromNum (sends notifies when new data is available in FromRadio) and ToRadio - SetMTU size to 512 - Write a ToRadio.startConfig protobuf to the "ToRadio" endpoint" - this tells the radio you are a new connection and you need the entire NodeDB sent down. +- Wrote a ToRadio.peerInfo protobuf to the endpoint - this tells the radio important information about your application version and if you are able to forward MQTT packets (see below). Sending this protobuf is optional but highly recommended. - Read repeatedly from the "FromRadio" endpoint. Each time you read you will get back a FromRadio protobuf (see Meshtatastic-protobuf). Keep reading from this endpoint until you get back and empty buffer. - See below for the expected sequence for your initial download. - After the initial download, you should subscribe for BLE "notify" on the "FromNum" endpoint. If a notification arrives, that means there are now one or more FromRadio packets waiting inside FromRadio. Read from FromRadio until you get back an empty packet. @@ -113,7 +114,7 @@ Characteristics | e272ebac-d463-4b98-bc84-5cc1a39ee517 | write | data, variable sized, recommended 512 bytes, write one for each block of file | | 4826129c-c22a-43a3-b066-ce8f0d5bacc6 | write | crc32, write last - writing this will complete the OTA operation, now you can read result | | 5e134862-7411-4424-ac4a-210937432c77 | read,notify | result code, readable but will notify when the OTA operation completes | -| 5e134862-7411-4424-ac4a-210937432c67 | write | sets the region for programming, currently only 0 (app) or 100 (spiffs) are defined, if not set app is assumed | +| 5e134862-7411-4424-ac4a-210937432c67 | write | sets the region for programming, currently only 0 (app) or 100 (spiffs) are defined, if not set app is assumed | | GATT_UUID_SW_VERSION_STR/0x2a28 | read | We also implement these standard GATT entries because SW update probably needs them: | | GATT_UUID_MANU_NAME/0x2a29 | read | | | GATT_UUID_HW_VERSION_STR/0x2a27 | read | | diff --git a/proto b/proto index 858d816b..ff66c549 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 858d816b8c18911fd4dc2aee3fa421fd67325631 +Subproject commit ff66c549498052a1a3cf75f8ad1a66a4adcdc413 diff --git a/src/mesh/generated/mesh.pb.c b/src/mesh/generated/mesh.pb.c index b2cc65f0..8a4a1d0a 100644 --- a/src/mesh/generated/mesh.pb.c +++ b/src/mesh/generated/mesh.pb.c @@ -39,6 +39,9 @@ PB_BIND(FromRadio, FromRadio, 2) PB_BIND(ToRadio, ToRadio, 2) +PB_BIND(ToRadio_PeerInfo, ToRadio_PeerInfo, AUTO) + + diff --git a/src/mesh/generated/mesh.pb.h b/src/mesh/generated/mesh.pb.h index 93bb63cd..d31fee6f 100644 --- a/src/mesh/generated/mesh.pb.h +++ b/src/mesh/generated/mesh.pb.h @@ -129,6 +129,11 @@ typedef struct _RouteDiscovery { uint32_t route[8]; } RouteDiscovery; +typedef struct _ToRadio_PeerInfo { + uint32_t app_version; + bool mqtt_gateway; +} ToRadio_PeerInfo; + typedef struct _User { char id[16]; char long_name[40]; @@ -193,6 +198,7 @@ typedef struct _ToRadio { pb_size_t which_payloadVariant; union { MeshPacket packet; + ToRadio_PeerInfo peer_info; uint32_t want_config_id; bool disconnect; }; @@ -241,6 +247,7 @@ extern "C" { #define LogRecord_init_default {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_default {0, 0, {MyNodeInfo_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} +#define ToRadio_PeerInfo_init_default {0, 0} #define Position_init_zero {0, 0, 0, 0, 0} #define User_init_zero {"", "", "", {0}, _HardwareModel_MIN, 0} #define RouteDiscovery_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0}} @@ -252,6 +259,7 @@ extern "C" { #define LogRecord_init_zero {"", 0, "", _LogRecord_Level_MIN} #define FromRadio_init_zero {0, 0, {MyNodeInfo_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} +#define ToRadio_PeerInfo_init_zero {0, 0} /* Field tags (for use in manual encoding/decoding) */ #define Data_portnum_tag 1 @@ -283,6 +291,8 @@ extern "C" { #define Position_battery_level_tag 4 #define Position_time_tag 9 #define RouteDiscovery_route_tag 2 +#define ToRadio_PeerInfo_app_version_tag 1 +#define ToRadio_PeerInfo_mqtt_gateway_tag 2 #define User_id_tag 1 #define User_long_name_tag 2 #define User_short_name_tag 3 @@ -317,6 +327,7 @@ extern "C" { #define FromRadio_rebooted_tag 9 #define FromRadio_packet_tag 11 #define ToRadio_packet_tag 2 +#define ToRadio_peer_info_tag 3 #define ToRadio_want_config_id_tag 100 #define ToRadio_disconnect_tag 104 @@ -434,11 +445,19 @@ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 11) #define ToRadio_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,packet,packet), 2) \ +X(a, STATIC, ONEOF, MESSAGE, (payloadVariant,peer_info,peer_info), 3) \ X(a, STATIC, ONEOF, UINT32, (payloadVariant,want_config_id,want_config_id), 100) \ X(a, STATIC, ONEOF, BOOL, (payloadVariant,disconnect,disconnect), 104) #define ToRadio_CALLBACK NULL #define ToRadio_DEFAULT NULL #define ToRadio_payloadVariant_packet_MSGTYPE MeshPacket +#define ToRadio_payloadVariant_peer_info_MSGTYPE ToRadio_PeerInfo + +#define ToRadio_PeerInfo_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, app_version, 1) \ +X(a, STATIC, SINGULAR, BOOL, mqtt_gateway, 2) +#define ToRadio_PeerInfo_CALLBACK NULL +#define ToRadio_PeerInfo_DEFAULT NULL extern const pb_msgdesc_t Position_msg; extern const pb_msgdesc_t User_msg; @@ -451,6 +470,7 @@ extern const pb_msgdesc_t MyNodeInfo_msg; extern const pb_msgdesc_t LogRecord_msg; extern const pb_msgdesc_t FromRadio_msg; extern const pb_msgdesc_t ToRadio_msg; +extern const pb_msgdesc_t ToRadio_PeerInfo_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define Position_fields &Position_msg @@ -464,6 +484,7 @@ extern const pb_msgdesc_t ToRadio_msg; #define LogRecord_fields &LogRecord_msg #define FromRadio_fields &FromRadio_msg #define ToRadio_fields &ToRadio_msg +#define ToRadio_PeerInfo_fields &ToRadio_PeerInfo_msg /* Maximum encoded size of messages (where known) */ #define Position_size 37 @@ -477,6 +498,7 @@ extern const pb_msgdesc_t ToRadio_msg; #define LogRecord_size 81 #define FromRadio_size 318 #define ToRadio_size 312 +#define ToRadio_PeerInfo_size 8 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index ddaf78a0..8a2cb760 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -24,16 +24,19 @@ void MQTT::onPublish(char *topic, byte *payload, unsigned int length) if (!pb_decode_from_bytes(payload, length, ServiceEnvelope_fields, &e)) { DEBUG_MSG("Invalid MQTT service envelope, topic %s, len %u!\n", topic, length); } else { - DEBUG_MSG("Received MQTT topic %s, len=%u\n", topic, length); + if (strcmp(e.gateway_id, owner.id) == 0) + DEBUG_MSG("Ignoring downlink message we originally sent.\n"); + else { + if (e.packet) { + DEBUG_MSG("Received MQTT topic %s, len=%u\n", topic, length); + MeshPacket *p = packetPool.allocCopy(*e.packet); - if (e.packet) { - MeshPacket *p = packetPool.allocCopy(*e.packet); - - // ignore messages sent by us or if we don't have the channel key - if (router && p->from != nodeDB.getNodeNum() && perhapsDecode(p)) - router->enqueueReceivedMessage(p); - else - packetPool.release(p); + // ignore messages sent by us or if we don't have the channel key + if (router && p->from != nodeDB.getNodeNum() && perhapsDecode(p)) + router->enqueueReceivedMessage(p); + else + packetPool.release(p); + } } // make sure to free both strings and the MeshPacket (passing in NULL is acceptable)