mirror of https://github.com/arendst/Tasmota.git
parent
414e5f382c
commit
e3d3e76d61
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
--------------------------------------------------------------------------------------------
|
||||
Version Date Action Description
|
||||
--------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define USE_TASMESH
|
||||
#ifdef USE_TASMESH
|
||||
|
||||
#include <queue>
|
||||
#include <t_bearssl_block.h>
|
||||
|
||||
#ifdef ESP32
|
||||
#include <esp_now.h>
|
||||
#include <esp_wifi.h>
|
||||
#else
|
||||
#include <espnow.h> //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<mesh_peer_t> peers;
|
||||
std::queue<mesh_packet_t> packetToResend;
|
||||
std::queue<mesh_packet_t> packetToConsume;
|
||||
std::vector<mesh_packet_header_t> packetsAlreadySended;
|
||||
std::vector<mesh_packet_combined_t> 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
|
|
@ -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); }
|
||||
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
--------------------------------------------------------------------------------------------
|
||||
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(_peerNumber<MESH.peers.size()) {
|
||||
MESHsendTime(_peerNumber);
|
||||
return;
|
||||
}
|
||||
if(MESH.multiPackets.size()>3){
|
||||
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:<br>"));
|
||||
WSContentSend_PD(PSTR("Broker MAC: %s <br>"),WiFi.softAPmacAddress().c_str());
|
||||
WSContentSend_PD(PSTR("Broker Channel: %u <hr>"),WiFi.channel());
|
||||
for(auto &_peer : MESH.peers){
|
||||
char _MAC[18];
|
||||
ToHex_P(_peer.MAC,6,_MAC,18,':');
|
||||
WSContentSend_PD(PSTR("Node MAC: %s <br>"),_MAC);
|
||||
WSContentSend_PD(PSTR("Node last message: %u <br>"),_peer.lmfp);
|
||||
WSContentSend_PD(PSTR("Node MQTT topic: %s <hr>"),_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
|
Loading…
Reference in New Issue