From e3d3e76d6169baeb0b804114f843de94e77bc738 Mon Sep 17 00:00:00 2001 From: Staars Date: Tue, 20 Oct 2020 15:22:23 +0200 Subject: [PATCH] Revert "tasmota EPS-Now mesh driver" This reverts commit 90ee6f3995bcd468ef6e7f6c21451b24238fad39. --- tasmota/support_tasmesh.ino | 283 ----------------- tasmota/xdrv_02_mqtt.ino | 15 - tasmota/xdrv_44_tasmesh.ino | 613 ------------------------------------ 3 files changed, 911 deletions(-) delete mode 100644 tasmota/support_tasmesh.ino delete mode 100644 tasmota/xdrv_44_tasmesh.ino diff --git a/tasmota/support_tasmesh.ino b/tasmota/support_tasmesh.ino deleted file mode 100644 index 5b6336068..000000000 --- a/tasmota/support_tasmesh.ino +++ /dev/null @@ -1,283 +0,0 @@ -/* - support_tasmesh.ino - mesh via ESP-Now support for Sonoff-Tasmota - - Copyright (C) 2020 Theo Arends & Christian Baars - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - -------------------------------------------------------------------------------------------- - Version Date Action Description - -------------------------------------------------------------------------------------------- -*/ - -#define USE_TASMESH -#ifdef USE_TASMESH - -#include -#include - -#ifdef ESP32 -#include -#include -#else -#include //ESP8266 ... why Espressif, why?? -#endif //ESP32 - -#define MESH_PAYLOAD_SIZE 160 // default 180 - with header of 20 bytes, stays at 200 bytes, which is reported to work with ESP8266 -#define MESH_TOPICSZ 64 // max supported topic size -#define MESH_BUFFERS 4 // max buffers number for splitted messages - -struct mesh_packet_t{ - uint8_t sender[6]; //MAC - uint8_t receiver[6]; //MAC - uint32_t counter:4; //endless counter to identify a packet - uint32_t type:6; //command,mqtt,... - uint32_t chunks:6; //number of chunks - uint32_t chunk:6; //chunk number - uint32_t chunkSize:8; //chunk size - uint32_t TTL:2; //time to live, counting down - union{ - uint32_t senderTime; //UTC-timestamp from every sender in the MESH - uint32_t peerIndex; //only for resending in the MESH - }; - uint8_t tag[16]; //tag for de/encryption - uint8_t payload[MESH_PAYLOAD_SIZE]; -} __attribute__((packed)); - -struct mesh_packet_header_t{ - uint8_t sender[6]; //MAC - uint8_t receiver[6]; //MAC - uint32_t counter:4; //endless counter to identify a packet - uint32_t type:6; //command,mqtt,... - uint32_t chunks:6; //number of chunks - uint32_t chunk:6; //chunk number - uint32_t chunkSize:8; //chunk size - uint32_t TTL:2; //time to live, counting down - union{ - uint32_t senderTime; //UTC-timestamp from every sender in the MESH - uint32_t peerIndex; //only for resending in the MESH - }; - uint8_t tag[16]; //tag for de/encryption -} __attribute__((packed)); - -struct mesh_peer_t{ - uint8_t MAC[6]; - uint32_t lmfp; //time of last message from peer -#ifdef ESP32 - char topic[MESH_TOPICSZ]; -#endif //ESP32 -}; - -struct mesh_broker_flags_t{ - uint8_t brokerNeedsTopic:1; -}; - -struct mesh_packet_combined_t{ - mesh_packet_header_t header; - uint8_t receivedChunks; - char raw[MESH_PAYLOAD_SIZE*6]; -}; - -struct{ - uint8_t broker[6]; - uint8_t role; - uint8_t channel; //Wifi channel - uint8_t counter; //for every message - uint32_t lmfb; //time of last message from broker - uint32_t lmfap; //time of last message from any peer - uint8_t pmk[32]; - mesh_broker_flags_t flags; - mesh_packet_t sendPacket; - std::vector peers; - std::queue packetToResend; - std::queue packetToConsume; - std::vector packetsAlreadySended; - std::vector multiPackets; -}MESH; - -/*********************************************************************************************\ - * declarations for functions with custom types -\*********************************************************************************************/ - -void MESHsendPacket(mesh_packet_t *_packet); -bool MESHencryptPayload(mesh_packet_t *_packet, int _encrypt); // 1 encryption; 0 decryption - -/*********************************************************************************************\ - * enumerations -\*********************************************************************************************/ - -enum MESH_Role { - ROLE_NONE = 0, // not initialized - ROLE_BROKER, // ESP32 will connect mesh to WLAN - ROLE_NODE_SMALL, // Node will only talk to the broker - ROLE_NODE_FULL // Node will listen and resend every message for MESH functionality -}; - -enum MESH_Packet_Type { // Type of packet - PACKET_TYPE_TIME = 0, // - PACKET_TYPE_SENSOR, // - PACKET_TYPE_COMMAND, // - PACKET_TYPE_TOPIC, // announce mqtt topic to ESP32-proxy - PACKET_TYPE_MQTT // -}; - -/*********************************************************************************************\ - * -\*********************************************************************************************/ -#ifdef ESP32 -void MESHsendTime(uint32_t _peerNumber){ //only from broker to nodes - MESH.sendPacket.counter++; - MESH.sendPacket.type = PACKET_TYPE_TIME; - MESH.sendPacket.TTL = 3; - memcpy(MESH.sendPacket.receiver,MESH.peers[_peerNumber].MAC,6); - MESH.sendPacket.senderTime = Rtc.utc_time; - MESH.sendPacket.payload[0] = 0; - mesh_broker_flags_t *_flags = (mesh_broker_flags_t *)MESH.sendPacket.payload; - if(MESH.peers[_peerNumber].topic[0]==0){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: broker wants topic from peer: %u"), _peerNumber); - _flags->brokerNeedsTopic = 1; - } - MESH.sendPacket.chunkSize = 0; - MESHsendPacket(&MESH.sendPacket); - // esp_now_send(MESH.sendPacket.receiver, (uint8_t *)&MESH.sendPacket, sizeof(MESH.sendPacket)-MESH_PAYLOAD_SIZE+1); -} -#endif //ESP32 - -void MESHcheckPeerList(const uint8_t *MAC){ - for(auto &_peer : MESH.peers){ - if(memcmp(_peer.MAC,MAC,6)==0){ - _peer.lmfp = millis(); - return; - } - } - MESHaddPeer((uint8_t *)MAC); -} - - -void MESHcountPeers(void){ - #ifdef ESP32 - esp_now_peer_num_t _num; - esp_now_get_peer_num(&_num); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TAS-MESH peers: %u"),_num.total_num); -#else - uint8_t _num; - uint8_t _numEnc; - esp_now_get_cnt_info(&_num,&_numEnc); - AddLog_P2(LOG_LEVEL_INFO, PSTR("TAS-MESH peers: %u"),_num); -#endif -} - - -void MESHaddPeer(uint8_t *_MAC ){ - mesh_peer_t _newPeer; - memcpy(_newPeer.MAC,_MAC,6); - _newPeer.lmfp = millis(); -#ifdef ESP32 - _newPeer.topic[0] = 0; -#endif - MESH.peers.push_back(_newPeer); - int err; -#ifdef ESP32 - esp_now_peer_info_t _peer; - _peer.channel = WiFi.channel(); - _peer.encrypt = false; - _peer.ifidx = ESP_IF_WIFI_AP; - memcpy(_peer.peer_addr, _MAC, 6); - err = esp_now_add_peer(&_peer); -#else - err = esp_now_add_peer(_MAC, ESP_NOW_ROLE_COMBO, MESH.channel, NULL, 0); -#endif - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: peer added, err: %d"), err); - AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t *)_MAC,6); -#ifdef ESP32 - if(MESH.role == ROLE_BROKER) MESHsendTime(MESH.peers.size()-1); -#endif //ESP32 -} - -//helper functions -void MESHstripColon(char* _string){ - uint32_t _length = strlen(_string); - uint32_t _index = 0; - while (_index < _length) { - char c = _string[_index]; - if(c==':'){ - memmove(_string+_index,_string+_index+1,_length-_index); - } - _index++; - } - _string[_index] = 0; -} - -void MESHMACStringToBytes(char* _string,uint8_t _MAC[]) { //uppercase - uint32_t index = 0; - uint32_t _end = 12; - while (index < _end) { - char c = _string[index]; - uint8_t value = 0; - if(c >= '0' && c <= '9') - value = (c - '0'); - else if (c >= 'A' && c <= 'F') - value = (10 + (c - 'A')); - _MAC[(index/2)] += value << (((index + 1) % 2) * 4); - index++; - } -} - -void MESHsendPacket(mesh_packet_t *_packet){ - MESHencryptPayload(_packet,1); - esp_now_send(_packet->receiver, (uint8_t *)_packet, sizeof(MESH.sendPacket) - MESH_PAYLOAD_SIZE + _packet->chunkSize); -} - -void MESHsetPMK(uint8_t* _key){ // must be 32 bytes!!! - char* _pw = SettingsText(SET_STAPWD1 + Settings.sta_active); - size_t _length = strlen(_pw); - memset(_key,0,32); - if(_length>32) _length = 32; - memcpy(_key,_pw,_length); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: set crypto key to PASSWORD1")); -} - - -bool MESHencryptPayload(mesh_packet_t *_packet, int _encrypt){ - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: will encrypt: %u"), _encrypt); - -size_t _size = _packet->chunkSize; -char _tag[16]; - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("cc: %u, _size: %u"), _counter,_size); -// AddLogBuffer(LOG_LEVEL_DEBUG,(uint8_t*)_tag,16); - -br_chacha20_run bc = br_chacha20_ct_run; - -br_poly1305_ctmul32_run((void*)MESH.pmk, (const void *)_packet, -(void *)_packet->payload, _size, (void*)&_packet->senderTime, 4, -_tag, bc, _encrypt); - -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: encryption done ")); - -if(_encrypt==1){ - memcpy(_packet->tag,_tag,16); - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: payload encrypted")); - return true; -} -if(memcmp(_packet->tag,_tag,16)==0){ - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: payload decrypted")); - return true; -} -AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: payload decryption error")); -return false; -} - -#endif //USE_TASMESH diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index 70d83df77..58fd04c2c 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -214,13 +214,6 @@ bool MqttPublishLib(const char* topic, bool retained) mqtt_cmnd_blocked++; } } -#ifdef USE_TASMESH -if(MESH.role == ROLE_NODE_SMALL){ - MESHredirectMQTT(topic, mqtt_data, retained); - yield(); - return true; -} -#endif //USE_TASMESH bool result = MqttClient.publish(topic, mqtt_data, retained); yield(); // #3313 @@ -252,14 +245,6 @@ void MqttDataHandler(char* mqtt_topic, uint8_t* mqtt_data, unsigned int data_len char data[data_len +1]; memcpy(data, mqtt_data, sizeof(data)); -#ifdef USE_TASMESH -#ifdef ESP32 -if(MESH.role == ROLE_BROKER){ - if (MESHinterceptMQTT(topic, (uint8_t*)data, data_len+1)) return; -} -#endif //ESP32 -#endif //USE_TASMESH - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_MQTT D_RECEIVED_TOPIC " \"%s\", " D_DATA_SIZE " %d, " D_DATA " \"%s\""), topic, data_len, data); // if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) { Serial.println(data); } diff --git a/tasmota/xdrv_44_tasmesh.ino b/tasmota/xdrv_44_tasmesh.ino deleted file mode 100644 index c88cfce31..000000000 --- a/tasmota/xdrv_44_tasmesh.ino +++ /dev/null @@ -1,613 +0,0 @@ -/* - xdrv_44_tasmesh.ino - Mesh support for Tasmota using ESP-Now - - Copyright (C) 2020 Christian Baars and Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - -------------------------------------------------------------------------------------------- - Version yyyymmdd Action Description - -------------------------------------------------------------------------------------------- - 0.9.0.0 20200927 started - from scratch - -*/ - - -#ifdef USE_TASMESH - -/*********************************************************************************************\ -* Build a mesh of nodes using ESP-Now -* Connect it through an ESP32-broker to WLAN -\*********************************************************************************************/ - -#define XDRV_44 44 - -/*********************************************************************************************\ - * constants -\*********************************************************************************************/ - -#define D_CMND_MESH "MESH" - -const char S_JSON_MESH_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_MESH "%s\":%d}"; -const char S_JSON_MESH_COMMAND[] PROGMEM = "{\"" D_CMND_MESH "%s\"}"; -const char kMESH_Commands[] PROGMEM = "Broker|Node|Peer|Channel"; - -/*********************************************************************************************\ - * enumerations -\*********************************************************************************************/ - -enum MESH_Commands { // commands useable in console or rules - CMND_MESH_BROKER, // start broker on ESP32 - CMND_MESH_NODE, // start node and connect to broker based on MAC address - CMND_MESH_PEER, // add node to peer list of a broker or node - CMND_MESH_CHANNEL}; // set wifi channel on node - -/*********************************************************************************************\ - * Callbacks -\*********************************************************************************************/ - -#ifdef ESP32 -void CB_MESHDataSent(const uint8_t *MAC, esp_now_send_status_t sendStatus); -void CB_MESHDataSent(const uint8_t *MAC, esp_now_send_status_t sendStatus) { - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("BROKER sended packet")); -} - -void CB_MESHDataReceived(const uint8_t *MAC, const uint8_t *packet, int len) { - MESH.lmfap = millis(); - MESHcheckPeerList((const uint8_t *)MAC); - mesh_packet_t *_recvPacket = (mesh_packet_t*)packet; - MESH.packetToConsume.push(*_recvPacket); -} -#else //ESP8266 -void CB_MESHDataSent( uint8_t *MAC, uint8_t sendStatus) { -} - -void CB_MESHDataReceived(uint8_t *MAC, uint8_t *packet, uint8_t len) { - MESH.lmfap = millis(); //any peer - if(memcmp(MAC,MESH.broker,6)==0) MESH.lmfb = millis(); //directly from the broker - mesh_packet_t *_recvPacket = (mesh_packet_t*)packet; - if(memcmp(_recvPacket->receiver,MESH.sendPacket.sender,6)!=0){ //MESH.sendPacket.sender simply stores the MAC of the node - //pass packet back to the MESH - _recvPacket->peerIndex = 0; - MESH.packetToResend.push(*_recvPacket); - return; - } - switch(_recvPacket->type){ - case PACKET_TYPE_TIME: - Rtc.utc_time = _recvPacket->senderTime; - Rtc.user_time_entry = true; - memcpy((uint8_t*)&MESH.flags,_recvPacket->payload,1); - break; - default: - MESH.packetToConsume.push(*_recvPacket); - break; - } -} -#endif //ESP32 - -/*********************************************************************************************\ - * init driver -\*********************************************************************************************/ - -void MESHInit(void) { - MESH.role == ROLE_NONE; - AddLog_P2(LOG_LEVEL_INFO, PSTR("TAS-MESH initialized: %u"),Settings.tele_period); - - MESH.sendPacket.counter = 0; - MESH.sendPacket.chunks = 1; - MESH.sendPacket.chunk = 0; - MESH.sendPacket.type = PACKET_TYPE_TIME; - MESH.sendPacket.TTL = 2; -} - -/*********************************************************************************************\ - * MQTT proxy functions -\*********************************************************************************************/ -#ifdef ESP32 -/** - * @brief Subscribes as a proxy - * - * @param topic - received from the referring node - */ -void MESHsubscribe(char *topic){ - char stopic[TOPSZ]; - GetTopic_P(stopic, CMND, topic, PSTR("#")); - MqttSubscribe(stopic); -} - -void MESHunsubscribe(char *topic){ - char stopic[TOPSZ]; - GetTopic_P(stopic, CMND, topic, PSTR("#")); - MqttUnsubscribe(stopic); -} - -void MESHconnectMQTT(void){ - for(auto &_peer : MESH.peers){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: reconnect topic: %s"),_peer.topic); - if(_peer.topic[0]!=0){ - MESHsubscribe(_peer.topic); - } - } -} - -/** - * @brief Intercepts mqtt message, that the broker (ESP32) subscribes to as a proxy for a node. - * Is called from xdrv_02_mqtt.ino. Will send the message in the payload via ESP-NOW. - * - * @param _topic - * @param _data - * @param data_len - * @return true - * @return false - */ -bool MESHinterceptMQTT(char* _topic, uint8_t* _data, unsigned int data_len){ - char stopic[TOPSZ]; - // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: Intercept topic: %s"),_topic); - for(auto &_peer : MESH.peers){ - GetTopic_P(stopic, CMND, _peer.topic, PSTR("")); //cmnd/topic/ - if(strlen(_topic)!= strlen(_topic)) return false; // prevent false result when _topic is the leading substring of stopic - if(memcmp(_topic, stopic,strlen(stopic)) == 0){ - MESH.sendPacket.chunkSize = strlen(_topic)+1; - memcpy(MESH.sendPacket.payload,_topic,MESH.sendPacket.chunkSize); - memcpy(MESH.sendPacket.payload+MESH.sendPacket.chunkSize,_data,data_len); - MESH.sendPacket.chunkSize += data_len; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("MESH: Intercept payload: %s"),MESH.sendPacket.payload); - MESH.sendPacket.type = PACKET_TYPE_MQTT; - MESH.sendPacket.senderTime = Rtc.utc_time; - MESHsendPacket(&MESH.sendPacket); - // int result = esp_now_send(MESH.sendPacket.receiver, (uint8_t *)&MESH.sendPacket, (sizeof(MESH.sendPacket))-(MESH_PAYLOAD_SIZE-MESH.sendPacket.chunkSize)); - //send to Node - return true; - } - } - return false; -} - -#else //ESP8266 -void MESHreceiveMQTT(mesh_packet_t *_packet); -void MESHreceiveMQTT(mesh_packet_t *_packet){ - uint32_t _slength = strlen((char*)_packet->payload); - if(_packet->chunks==1){ //single chunk message - MqttDataHandler((char*)_packet->payload, (uint8_t*)(_packet->payload)+_slength+1, (_packet->chunkSize)-_slength); - } - else{ - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: multiple chunks: %u"),_packet->chunks); - // TODO: reconstruct message in buffer - } -} -#endif //ESP32 - -/** - * @brief Redirects the mqtt message on the node just before it would have been sended to - * the broker via ESP-NOW - * - * @param _topic - * @param _data - * @param _retained - currently unused - * @return true - * @return false - */ -bool MESHredirectMQTT(const char* _topic, char* _data, bool _retained){ - size_t _bytesLeft = strlen(_topic)+strlen(_data)+2; - MESH.sendPacket.counter++; - MESH.sendPacket.chunk = 0; - MESH.sendPacket.chunks = ((_bytesLeft+2)/MESH_PAYLOAD_SIZE)+1; - memcpy(MESH.sendPacket.receiver,MESH.broker,6); - MESH.sendPacket.type = PACKET_TYPE_MQTT; - MESH.sendPacket.chunkSize = MESH_PAYLOAD_SIZE; - MESH.sendPacket.peerIndex = 0; - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: chunks: %u, counter: %u"),MESH.sendPacket.chunks,MESH.sendPacket.counter); - size_t _topicSize = strlen(_topic)+1; - size_t _offsetData = 0; - while(_bytesLeft>0){ - size_t _byteLeftInChunk = MESH_PAYLOAD_SIZE; - // MESH.sendPacket.chunkSize = MESH_PAYLOAD_SIZE; - if(MESH.sendPacket.chunk == 0){ - memcpy(MESH.sendPacket.payload,_topic,_topicSize); - MESH.sendPacket.chunkSize = _topicSize; - _bytesLeft -= _topicSize; - _byteLeftInChunk -= _topicSize; - // AddLog_P2(LOG_LEVEL_INFO, PSTR("topic in payload %s"),(char*)MESH.sendPacket.payload); - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: after topic -> chunk:%u, pre-size: %u"),MESH.sendPacket.chunk,MESH.sendPacket.chunkSize); - } - if(_byteLeftInChunk>0){ - if(_byteLeftInChunk>_bytesLeft){ - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: only last chunk bL:%u bLiC:%u oSD:%u"),_bytesLeft,_byteLeftInChunk,_offsetData); - _byteLeftInChunk = _bytesLeft; - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: only last chunk after correction -> chunk:%u, pre-size: %u"),MESH.sendPacket.chunk,MESH.sendPacket.chunkSize); - } - if(MESH.sendPacket.chunk>0) _topicSize = 0; - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: %u"),_offsetPayload); - memcpy(MESH.sendPacket.payload + _topicSize, _data + _offsetData,_byteLeftInChunk); - // AddLog_P2(LOG_LEVEL_INFO, PSTR("data in payload %s"),(char*)MESH.sendPacket.payload + _offsetPayload); - _offsetData += _byteLeftInChunk; - _bytesLeft -= _byteLeftInChunk; - } - MESH.sendPacket.chunkSize += _byteLeftInChunk; - MESH.packetToResend.push(MESH.sendPacket); - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: chunk:%u, size: %u"),MESH.sendPacket.chunk,MESH.sendPacket.chunkSize); - // AddLogBuffer(LOG_LEVEL_INFO, (uint8_t*)MESH.sendPacket.payload, MESH.sendPacket.chunkSize); - - if(MESH.sendPacket.chunk==MESH.sendPacket.chunks){ - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: too many chunks: %u"),MESH.sendPacket.chunk+1); - } - MESH.sendPacket.chunk++; - MESH.sendPacket.chunkSize = 0; - } - //send to pipeline - return true; -} - -/** - * @brief The node sends its mqtt topic to the broker - * - */ -void MESHanounceTopic(){ - memset(MESH.sendPacket.payload,0,MESH_PAYLOAD_SIZE); - strcpy((char*)MESH.sendPacket.payload,mqtt_topic); - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: topic: %s"),(char*)MESH.sendPacket.payload); - MESH.sendPacket.chunkSize = strlen((char*)MESH.sendPacket.payload) + 1; - MESH.sendPacket.type = PACKET_TYPE_TOPIC; - MESHsendPacket(&MESH.sendPacket); - // int result = esp_now_send(MESH.sendPacket.receiver, (uint8_t *)&MESH.sendPacket, (sizeof(MESH.sendPacket))-(MESH_PAYLOAD_SIZE-MESH.sendPacket.chunkSize-1)); -} - -/*********************************************************************************************\ - * generic functions -\*********************************************************************************************/ - -void MESHstartNode(int32_t _channel){ - MESH.channel = _channel; - WiFi.mode(WIFI_STA); - WiFi.begin("","",MESH.channel, nullptr, false); //fake connection attempt to set channel - WiFi.disconnect(); - if (esp_now_init() != 0) { - return; - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: Node initialized, channel: %u"),MESH.channel); -#ifdef ESP8266 - esp_now_set_self_role(ESP_NOW_ROLE_COMBO); -#endif //ESP8266 - - esp_now_register_send_cb(CB_MESHDataSent); - esp_now_register_recv_cb(CB_MESHDataReceived); - MESHsetPMK(MESH.pmk); - memcpy(MESH.sendPacket.receiver,MESH.broker,6); - WiFi.macAddress(MESH.sendPacket.sender); - MESHaddPeer(MESH.broker); //must always be peer 0!! - MESHcountPeers(); - MESH.role = ROLE_NODE_SMALL; - MESHanounceTopic(); -} - -void MESHstartBroker(){ -#ifdef ESP32 - WiFi.mode(WIFI_AP_STA); - // WiFi.softAP("SSID_NOW","PASSWORD_NOW",9,1); - // AddLogBuffer(LOG_LEVEL_INFO,(uint8_t *)WiFi.softAPmacAddress(),6); - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: Broker MAC: %s"),WiFi.softAPmacAddress().c_str()); - WiFi.softAPmacAddress(MESH.broker); - - uint32_t _channel = WiFi.channel(); - esp_wifi_set_promiscuous(true); - esp_wifi_set_channel(_channel, WIFI_SECOND_CHAN_NONE); - esp_wifi_set_promiscuous(false); - - if (esp_now_init() != 0) { - return; - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: Broker initialized on channel: %u"), _channel); - esp_now_register_send_cb(CB_MESHDataSent); - esp_now_register_recv_cb(CB_MESHDataReceived); - MESHsetPMK(MESH.pmk); - MESHcountPeers(); - memcpy(MESH.sendPacket.sender,MESH.broker,6); - MESH.role = ROLE_BROKER; -#endif //ESP32 -} - -/*********************************************************************************************\ - * main loops -\*********************************************************************************************/ -#ifdef ESP32 - -void MESHevery50MSecond(){ - // if(MESH.packetToResend.size()>0){ - // // pass the packets - // } - if(MESH.packetToConsume.size()>0){ - // do something on the node - MESHencryptPayload(&MESH.packetToConsume.front(),0); - switch(MESH.packetToConsume.front().type){ - case PACKET_TYPE_TOPIC: - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: received topic: %s"), (char*)MESH.packetToConsume.front().payload); - AddLogBuffer(LOG_LEVEL_INFO,(uint8_t *)&MESH.packetToConsume.front().payload,MESH.packetToConsume.front().chunkSize+5); - for(auto &_peer : MESH.peers){ - if(memcmp(_peer.MAC,MESH.packetToConsume.front().sender,6)==0){ - strcpy(_peer.topic,(char*)MESH.packetToConsume.front().payload); - MESHsubscribe((char*)&_peer.topic); - } - } - break; - // case PACKET_TYPE_SENSOR: - // for(auto &_peer : MESH.peers){ - // if(memcmp(_peer.MAC,MESH.packetToConsume.front().sender,6)==0){ - // // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: received sensor output: %s"), (char*)MESH.packetToConsume.front().payload); - // char stopic[MESH_TOPICSZ]; - // GetTopic_P(stopic, TELE, _peer.topic, PSTR("SENSOR")); - // MqttClient.publish(stopic, (char*)MESH.packetToConsume.front().payload); - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: topic: %s output: %s"), stopic, (char*)MESH.packetToConsume.front().payload); - // yield(); // #3313 - // break; - // } - // } - case PACKET_TYPE_MQTT: // redirected MQTT from node in packet [char* _space_ char*] - { - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: received node output: %s"), (char*)MESH.packetToConsume.front().payload); - if(MESH.packetToConsume.front().chunks>1){ - bool _foundMultiPacket = false; - for(auto &_packet_combined : MESH.multiPackets){ - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: append to multipacket")); - if(memcmp(_packet_combined.header.sender,MESH.packetToConsume.front().sender,12)==0){ - if(_packet_combined.header.counter == MESH.packetToConsume.front().counter){ - memcpy(_packet_combined.raw+(MESH.packetToConsume.front().chunk * MESH_PAYLOAD_SIZE),MESH.packetToConsume.front().payload,MESH.packetToConsume.front().chunkSize); - bitSet(_packet_combined.receivedChunks,MESH.packetToConsume.front().chunk); - _foundMultiPacket = true; - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: recChunks= %u"),_packet_combined.receivedChunks); - } - } - uint32_t _temp = (1 << (uint8_t)MESH.packetToConsume.front().chunks)-1 ; //example: 1+2+4 == (2^3)-1 - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: _temp: %u = %u"),_temp,_packet_combined.receivedChunks); - if(_packet_combined.receivedChunks==_temp){ - char * _data = (char*)_packet_combined.raw + strlen((char*)_packet_combined.raw) + 1; - MqttClient.publish((char*)_packet_combined.raw, _data); - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: combined done: %s = %s"),(char*)_packet_combined.raw,_data); - // AddLogBuffer(LOG_LEVEL_INFO,(uint8_t*)_packet_combined.raw,50); - } - } - if(!_foundMultiPacket){ - mesh_packet_combined_t _packet; - memcpy(_packet.header.sender,MESH.packetToConsume.front().sender,sizeof(_packet.header)); - memcpy(_packet.raw+(MESH.packetToConsume.front().chunk*MESH_PAYLOAD_SIZE),MESH.packetToConsume.front().payload,MESH.packetToConsume.front().chunkSize); - _packet.receivedChunks = 0; - bitSet(_packet.receivedChunks,MESH.packetToConsume.front().chunk); - MESH.multiPackets.push_back(_packet); - // AddLog_P2(LOG_LEVEL_INFO, PSTR("new multipacket with chunks: %u"),_packet.header.chunks); - } - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: no support yet for multiple chunks: %u"),MESH.packetToConsume.front().chunks); - break; - } - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: chunk: %u size: %u"), MESH.packetToConsume.front().chunk, MESH.packetToConsume.front().chunkSize); - // if (MESH.packetToConsume.front().chunk==0) AddLogBuffer(LOG_LEVEL_INFO,(uint8_t *)&MESH.packetToConsume.front().payload,MESH.packetToConsume.front().chunkSize); - char * _data = (char*)MESH.packetToConsume.front().payload + strlen((char*)MESH.packetToConsume.front().payload)+1; - MqttClient.publish((char*)MESH.packetToConsume.front().payload, _data); - // AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: topic: %s output: %s"), (char*)MESH.packetToConsume.front().payload, _data); - // AddLogBuffer(LOG_LEVEL_INFO,(uint8_t *)&MESH.packetToConsume.front().payload,MESH.packetToConsume.front().chunkSize); - yield(); // #3313 - } - break; - default: - AddLogBuffer(LOG_LEVEL_INFO,(uint8_t *)&MESH.packetToConsume.front(),MESH.packetToConsume.front().chunkSize+5); - break; - } - MESH.packetToConsume.pop(); - } -} - -void MESHEverySecond(){ - static uint32_t _second = 0; - _second++; - // send a time packet every x seconds - uint32_t _peerNumber = _second%60; - if(_peerNumber3){ - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: multi packets in buffer: %u"),MESH.multiPackets.size()); - MESH.multiPackets.erase(MESH.multiPackets.begin()); - } -} - -#else //ESP8266 -void MESHevery50MSecond(){ - if(MESH.packetToResend.size()>0){ - uint32_t _tempIndex = MESH.packetToResend.front().peerIndex; - if(MESH.peers.size()>_tempIndex){ - MESH.packetToResend.front().senderTime = Rtc.utc_time; - if (MESH.packetToResend.front().TTL>0){ - MESH.packetToResend.front().TTL--; - if(memcmp(MESH.packetToResend.front().sender,MESH.broker,6) != 0){ //do not send back the packet to the broker TODO: guarantee that peer[0] is always the broker - MESHsendPacket(&MESH.packetToResend.front()); - // int result = esp_now_send(MESH.packetToResend.front().receiver, (uint8_t *)&MESH.packetToResend.front(), (sizeof(MESH.sendPacket))-(MESH_PAYLOAD_SIZE-MESH.packetToResend.front().chunkSize)); - } - } - MESH.packetToResend.front().peerIndex = _tempIndex + 1; - } - else{ - MESH.packetToResend.pop(); - } - // pass the packets - } - - if(MESH.packetToConsume.size()>0){ - MESHencryptPayload(&MESH.packetToConsume.front(),0); - switch(MESH.packetToConsume.front().type){ - case PACKET_TYPE_MQTT: - if(memcmp(MESH.packetToConsume.front().sender,MESH.sendPacket.sender,6)==0){ - //discard echo - break; - } - AddLog_P2(LOG_LEVEL_INFO, PSTR("MESH: node received topic: %s"), (char*)MESH.packetToConsume.front().payload); - MESHreceiveMQTT(&MESH.packetToConsume.front()); - break; - default: - break; - } - MESH.packetToConsume.pop(); - } -} - - -void MESHEverySecond(){ - static uint32_t _second = 0; - static uint32_t _tele_period = Settings.tele_period; - if (MESH.role == ROLE_NODE_SMALL){ - _tele_period--; - if(_tele_period == 0){ - // uint8_t broadcastAddress[6] = {0x30,0xAE,0xA4,0x26,0xE7,0x29}; - // memcpy(MESH.sendPacket.receiver,MESH.broker,6); - // _tele_period = Settings.tele_period; - // mqtt_data[0] = 0; - - // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("SENSOR: %s %u"), mqtt_data, strlen(mqtt_data)); - // MESH.sendPacket.chunkSize = strlen(mqtt_data); - // memcpy(MESH.sendPacket.payload,mqtt_data,MESH.sendPacket.chunkSize); - // MESH.sendPacket.type = PACKET_TYPE_SENSOR; - // MESH.sendPacket.senderTime = Rtc.utc_time; - // int result = esp_now_send(MESH.sendPacket.receiver, (uint8_t *)&MESH.sendPacket, (sizeof(MESH.sendPacket))-(MESH_PAYLOAD_SIZE-MESH.sendPacket.chunkSize)); - // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("send error: %d, tele: %u"), result, tele_period); - } - if(MESH.flags.brokerNeedsTopic == 1){ - MESHanounceTopic(); - MESH.flags.brokerNeedsTopic = 0; - } - } -} -#endif //ESP8266 - -/*********************************************************************************************\ - * presentation -\*********************************************************************************************/ -void MESHshow(bool json){ - if (json) { - if(MESH.role != ROLE_NONE){ - if(MESH.role != ROLE_BROKER) ResponseAppend_P(PSTR(",\"MESH\":{\"broker\":%u"),MESH.channel); - else ResponseAppend_P(PSTR(",\"MESH\":{\"node\":%u"),MESH.channel); - ResponseJsonEnd(); - } - } else { -#ifdef ESP32 - if(MESH.role == ROLE_BROKER){ - WSContentSend_PD(PSTR("TAS-MESH:
")); - WSContentSend_PD(PSTR("Broker MAC: %s
"),WiFi.softAPmacAddress().c_str()); - WSContentSend_PD(PSTR("Broker Channel: %u
"),WiFi.channel()); - for(auto &_peer : MESH.peers){ - char _MAC[18]; - ToHex_P(_peer.MAC,6,_MAC,18,':'); - WSContentSend_PD(PSTR("Node MAC: %s
"),_MAC); - WSContentSend_PD(PSTR("Node last message: %u
"),_peer.lmfp); - WSContentSend_PD(PSTR("Node MQTT topic: %s
"),_peer.topic); - } - } -#endif //ESP32 - } -} - - -/*********************************************************************************************\ - * check the MESH commands -\*********************************************************************************************/ - -bool MESHCmd(void) { - char command[CMDSZ]; - bool serviced = true; - uint8_t disp_len = strlen(D_CMND_MESH); - - if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_MESH), disp_len)) { // prefix - int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + disp_len, kMESH_Commands); - - switch (command_code) { - case CMND_MESH_BROKER: - MESHstartBroker(); - Response_P(S_JSON_MESH_COMMAND_NVALUE, command, MESH.channel); - break; - case CMND_MESH_NODE: - if (XdrvMailbox.data_len > 0) { - MESHstripColon(XdrvMailbox.data); - MESHMACStringToBytes(XdrvMailbox.data,MESH.broker); - MESHstartNode(MESH.channel); - Response_P(S_JSON_MESH_COMMAND_NVALUE, command, MESH.channel); - } - break; - case CMND_MESH_CHANNEL: - if (XdrvMailbox.data_len > 0) { - AddLog_P2(LOG_LEVEL_DEBUG,PSTR("channel: %u"), XdrvMailbox.payload); - MESH.channel = XdrvMailbox.payload; - } - break; - case CMND_MESH_PEER: - if (XdrvMailbox.data_len > 0) { - uint8_t _MAC[6] = {0}; - MESHstripColon(XdrvMailbox.data); - MESHMACStringToBytes(XdrvMailbox.data,_MAC); - // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MAC-string: %s"), XdrvMailbox.data); - // AddLogBuffer(LOG_LEVEL_INFO,(uint8_t *)_MAC,6); - MESHaddPeer(_MAC); - MESHcountPeers(); - } - break; - default: - // else for Unknown command - serviced = false; - break; - } - } else { - return false; - } - return serviced; -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -bool Xdrv44(uint8_t function) -{ - bool result = false; - - switch (function) { - case FUNC_PRE_INIT: - MESHInit(); // TODO: save state - break; - case FUNC_EVERY_50_MSECOND: - MESHevery50MSecond(); - break; - case FUNC_EVERY_SECOND: - MESHEverySecond(); - break; - case FUNC_COMMAND: - result = MESHCmd(); - break; - case FUNC_WEB_SENSOR: -#ifdef USE_WEBSERVER - MESHshow(0); -#endif - break; - case FUNC_JSON_APPEND: - MESHshow(1); - break; -#ifdef ESP32 - case FUNC_MQTT_SUBSCRIBE: - MESHconnectMQTT(); - break; -#endif //ESP32 - // case FUNC_SHOW_SENSOR: - // if(MESH.role == ROLE_NODE_SMALL) MESHsendTeleSensor(); - // break; - } -return result; -} - -#endif // USE_TASMESH