5858#define CMD_GET_AUTOADD_CONFIG 59
5959#define CMD_GET_ALLOWED_REPEAT_FREQ 60
6060#define CMD_SET_PATH_HASH_MODE 61
61+ #define CMD_SEND_CHANNEL_DATA 62
6162
6263// Stats sub-types for CMD_GET_STATS
6364#define STATS_TYPE_CORE 0
9192#define RESP_CODE_STATS 24 // v8+, second byte is stats type
9293#define RESP_CODE_AUTOADD_CONFIG 25
9394#define RESP_ALLOWED_REPEAT_FREQ 26
95+ #define RESP_CODE_CHANNEL_DATA_RECV 27
96+
97+ #define MAX_CHANNEL_DATA_LENGTH (MAX_FRAME_SIZE - 9 )
9498
9599#define SEND_TIMEOUT_BASE_MILLIS 500
96100#define FLOOD_SEND_TIMEOUT_FACTOR 16 .0f
@@ -204,7 +208,8 @@ void MyMesh::updateContactFromFrame(ContactInfo &contact, uint32_t& last_mod, co
204208}
205209
206210bool MyMesh::Frame::isChannelMsg () const {
207- return buf[0 ] == RESP_CODE_CHANNEL_MSG_RECV || buf[0 ] == RESP_CODE_CHANNEL_MSG_RECV_V3;
211+ return buf[0 ] == RESP_CODE_CHANNEL_MSG_RECV || buf[0 ] == RESP_CODE_CHANNEL_MSG_RECV_V3 ||
212+ buf[0 ] == RESP_CODE_CHANNEL_DATA_RECV;
208213}
209214
210215void MyMesh::addToOfflineQueue (const uint8_t frame[], int len) {
@@ -564,6 +569,41 @@ void MyMesh::onChannelMessageRecv(const mesh::GroupChannel &channel, mesh::Packe
564569#endif
565570}
566571
572+ void MyMesh::onChannelDataRecv (const mesh::GroupChannel &channel, mesh::Packet *pkt, uint16_t data_type,
573+ const uint8_t *data, size_t data_len) {
574+ if (data_len > MAX_CHANNEL_DATA_LENGTH) {
575+ MESH_DEBUG_PRINTLN (" onChannelDataRecv: dropping payload_len=%d exceeds frame limit=%d" ,
576+ (uint32_t )data_len, (uint32_t )MAX_CHANNEL_DATA_LENGTH);
577+ return ;
578+ }
579+
580+ int i = 0 ;
581+ out_frame[i++] = RESP_CODE_CHANNEL_DATA_RECV;
582+ out_frame[i++] = (int8_t )(pkt->getSNR () * 4 );
583+ out_frame[i++] = 0 ; // reserved1
584+ out_frame[i++] = 0 ; // reserved2
585+
586+ uint8_t channel_idx = findChannelIdx (channel);
587+ out_frame[i++] = channel_idx;
588+ out_frame[i++] = pkt->isRouteFlood () ? pkt->path_len : 0xFF ;
589+ out_frame[i++] = (uint8_t )(data_type & 0xFF );
590+ out_frame[i++] = (uint8_t )(data_type >> 8 );
591+ out_frame[i++] = (uint8_t )data_len;
592+
593+ int copy_len = (int )data_len;
594+ if (copy_len > 0 ) {
595+ memcpy (&out_frame[i], data, copy_len);
596+ i += copy_len;
597+ }
598+ addToOfflineQueue (out_frame, i);
599+
600+ if (_serial->isConnected ()) {
601+ uint8_t frame[1 ];
602+ frame[0 ] = PUSH_CODE_MSG_WAITING; // send push 'tickle'
603+ _serial->writeFrame (frame, 1 );
604+ }
605+ }
606+
567607uint8_t MyMesh::onContactRequest (const ContactInfo &contact, uint32_t sender_timestamp, const uint8_t *data,
568608 uint8_t len, uint8_t *reply) {
569609 if (data[0 ] == REQ_TYPE_GET_TELEMETRY_DATA) {
@@ -1041,7 +1081,7 @@ void MyMesh::handleCmdFrame(size_t len) {
10411081 ? ERR_CODE_NOT_FOUND
10421082 : ERR_CODE_UNSUPPORTED_CMD); // unknown recipient, or unsuported TXT_TYPE_*
10431083 }
1044- } else if (cmd_frame[0 ] == CMD_SEND_CHANNEL_TXT_MSG) { // send GroupChannel msg
1084+ } else if (cmd_frame[0 ] == CMD_SEND_CHANNEL_TXT_MSG) { // send GroupChannel text msg
10451085 int i = 1 ;
10461086 uint8_t txt_type = cmd_frame[i++]; // should be TXT_TYPE_PLAIN
10471087 uint8_t channel_idx = cmd_frame[i++];
@@ -1061,6 +1101,31 @@ void MyMesh::handleCmdFrame(size_t len) {
10611101 writeErrFrame (ERR_CODE_NOT_FOUND); // bad channel_idx
10621102 }
10631103 }
1104+ } else if (cmd_frame[0 ] == CMD_SEND_CHANNEL_DATA) { // send GroupChannel datagram
1105+ if (len < 4 ) {
1106+ writeErrFrame (ERR_CODE_ILLEGAL_ARG);
1107+ return ;
1108+ }
1109+ int i = 1 ;
1110+ uint16_t data_type = ((uint16_t )cmd_frame[i]) | (((uint16_t )cmd_frame[i + 1 ]) << 8 );
1111+ i += 2 ;
1112+ uint8_t channel_idx = cmd_frame[i++];
1113+ const uint8_t *payload = &cmd_frame[i];
1114+ int payload_len = (len > (size_t )i) ? (int )(len - i) : 0 ;
1115+
1116+ ChannelDetails channel;
1117+ if (!getChannel (channel_idx, channel)) {
1118+ writeErrFrame (ERR_CODE_NOT_FOUND); // bad channel_idx
1119+ } else if (data_type == 0 ) {
1120+ writeErrFrame (ERR_CODE_ILLEGAL_ARG);
1121+ } else if (payload_len > MAX_CHANNEL_DATA_LENGTH) {
1122+ MESH_DEBUG_PRINTLN (" CMD_SEND_CHANNEL_DATA payload too long: %d > %d" , payload_len, MAX_CHANNEL_DATA_LENGTH);
1123+ writeErrFrame (ERR_CODE_ILLEGAL_ARG);
1124+ } else if (sendGroupData (channel.channel , data_type, payload, payload_len)) {
1125+ writeOKFrame ();
1126+ } else {
1127+ writeErrFrame (ERR_CODE_TABLE_FULL);
1128+ }
10641129 } else if (cmd_frame[0 ] == CMD_GET_CONTACTS) { // get Contact list
10651130 if (_iter_started) {
10661131 writeErrFrame (ERR_CODE_BAD_STATE); // iterator is currently busy
0 commit comments