Compare commits

..

No commits in common. "main" and "v1.1" have entirely different histories.
main ... v1.1

6 changed files with 276 additions and 209 deletions

138
README.md
View File

@ -4,15 +4,14 @@ A simple library for creating ESP-NOW based Mesh network for ESP8266/ESP32.
## Features ## Features
1. The maximum size of transmitted data is 200 bytes. 1. The maximum size of transmitted data is 200 bytes. Currently only unencrypted messages.
2. Encrypted and unencrypted messages. Simple XOR crypting. 2. All nodes are not visible to the network scanner (for the ESP_NOW mode only).
3. All nodes are not visible to the network scanner. 3. Not required a pre-pairings for data transfer.
4. Not required a pre-pairings for data transfer. 4. Broadcast or unicast data transmission.
5. Broadcast or unicast data transmissions. 5. There are no periodic/synchronous messages on the network. All devices are in "silent mode" and do not "hum" into the air (for the ESP_NOW mode only).
6. There are no periodic/synchronous messages on the network. All devices are in "silent mode" and do not "hum" into the air. 6. Each node has its own independent routing table, updated only as needed.
7. Each node has its own independent routing table, updated only as needed. 7. Each node will receive/send a message if it "sees" at least one device on the network.
8. Each node will receive/send a message if it "sees" at least one device on the network. 8. The number of devices on the network and the area of use is not limited (hypothetically). :-)
9. The number of devices on the network and the area of use is not limited (hypothetically). :-)
## Testing ## Testing
@ -23,11 +22,6 @@ A simple library for creating ESP-NOW based Mesh network for ESP8266/ESP32.
5. Voila. ;-) 5. Voila. ;-)
6. P.S. Uncomment #define PRINT_LOG in ZHNetwork.h for display to serial port the full operation log. 6. P.S. Uncomment #define PRINT_LOG in ZHNetwork.h for display to serial port the full operation log.
## Notes
1. Possibility uses WiFi AP or STA modes at the same time with ESP-NOW using the standard libraries.
2. For correct work at ESP-NOW + STA mode your WiFi router must be set on channel 1 and set gateway mode.
## Function descriptions ## Function descriptions
### Sets the callback function for processing a received broadcast message ### Sets the callback function for processing a received broadcast message
@ -60,35 +54,82 @@ Note. Called only at broadcast or unicast with confirm message. Status will alwa
```cpp ```cpp
myNet.setOnConfirmReceivingCallback(onConfirmReceiving); myNet.setOnConfirmReceivingCallback(onConfirmReceiving);
void onConfirmReceiving(const uint8_t *target, const uint16_t id, const bool status) void onConfirmReceiving(const uint8_t *target, const bool status)
{ {
// Do something when receiving a delivery/undelivery confirm message. // Do something when receiving a delivery/undelivery confirm message.
} }
``` ```
### ESP-NOW Mesh network initialization ### Sets one of the three possibility operating modes
* ESP_NOW. Default mode. ESP-NOW Mesh network only.
* ESP_NOW_AP. ESP-NOW Mesh network + access point.
* ESP_NOW_STA. ESP-NOW Mesh network + connect to your WiFi router.
Attention! For correct work on ESP_NOW_STA mode at ESP8266 your WiFi router must be set on channel 1.
```cpp
myNet.setWorkMode(ESP_NOW);
```
### Gets used operating mode
```cpp
myNet.getWorkMode();
```
### Sets ESP-NOW Mesh network name
1-20 characters. 1-20 characters.
Note. If network name not set node will work with all ESP-NOW networks. If set node will work with only one network. Note. If network name not set node will work with all ESP-NOW networks. If set node will work with only one network.
```cpp ```cpp
myNet.begin("ZHNetwork"); myNet.setNetName("ZHNetwork");
myNet.begin("ZHNetwork", true); // Gateway mode. ```
### Gets used ESP-NOW Mesh network name
```cpp
myNet.getNetName();
```
### Sets WiFi ssid and password for ESP_NOW_STA mode
Note. Must be called before Mesh network initialization.
```cpp
myNet.setStaSetting("SSID", "PASSWORD");
```
### Sets access point ssid and password for ESP_NOW_AP mode
Note. Must be called before Mesh network initialization.
```cpp
myNet.setApSetting("SSID", "PASSWORD");
```
### ESP-NOW Mesh network initialization
```cpp
myNet.begin();
```
### ESP-NOW Mesh network deinitialization
```cpp
myNet.stop();
``` ```
### Sends broadcast message to all nodes ### Sends broadcast message to all nodes
Returns message ID.
```cpp ```cpp
myNet.sendBroadcastMessage("Hello world!"); myNet.sendBroadcastMessage("Hello world!");
``` ```
### Sends unicast message to node ### Sends unicast message to node
Returns message ID.
```cpp ```cpp
myNet.sendUnicastMessage("Hello world!", target); // Without confirm. myNet.sendUnicastMessage("Hello world!", target); // Without confirm.
myNet.sendUnicastMessage("Hello world!", target, true); // With confirm. myNet.sendUnicastMessage("Hello world!", target, true); // With confirm.
@ -108,6 +149,12 @@ myNet.maintenance();
myNet.getNodeMac(); myNet.getNodeMac();
``` ```
### Gets node IP address
```cpp
myNet.getNodeIp();
```
### Gets version of this library ### Gets version of this library
```cpp ```cpp
@ -127,14 +174,6 @@ uint8_t mac[6]
myNet.stringToMac(string, mac); myNet.stringToMac(string, mac);
``` ```
### Sets crypt key
1-20 characters.
```cpp
myNet.setCryptKey("VERY_LONG_CRYPT_KEY");
```
### Sets max number of attempts to send message ### Sets max number of attempts to send message
1-10. 3 default value. 1-10. 3 default value.
@ -184,11 +223,11 @@ myNet.getMaxWaitingTimeForRoutingInfo();
void onBroadcastReceiving(const char *data, const uint8_t *sender); void onBroadcastReceiving(const char *data, const uint8_t *sender);
void onUnicastReceiving(const char *data, const uint8_t *sender); void onUnicastReceiving(const char *data, const uint8_t *sender);
void onConfirmReceiving(const uint8_t *target, const uint16_t id, const bool status); void onConfirmReceiving(const uint8_t *target, const bool status);
ZHNetwork myNet; ZHNetwork myNet;
uint64_t messageLastTime{0}; uint64_t messagelastTime{0};
uint16_t messageTimerDelay{5000}; uint16_t messageTimerDelay{5000};
const uint8_t target[6]{0xA8, 0x48, 0xFA, 0xDC, 0x5B, 0xFA}; const uint8_t target[6]{0xA8, 0x48, 0xFA, 0xDC, 0x5B, 0xFA};
@ -196,13 +235,27 @@ void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
Serial.println(); Serial.println();
myNet.begin("ZHNetwork"); // *** ESP-NOW mode only.
// myNet.setCryptKey("VERY_LONG_CRYPT_KEY"); // If encryption is used, the key must be set same of all another ESP-NOW devices in network. myNet.setWorkMode(ESP_NOW);
// *** Or ESP-NOW + access point mode.
// myNet.setWorkMode(ESP_NOW_AP);
// myNet.setApSetting("ESP NODE TEST", "12345678");
// *** Or ESP-NOW + connect to your router mode.
// myNet.setWorkMode(ESP_NOW_STA);
// myNet.setStaSetting("SSID", "PASSWORD");
// ***
myNet.setNetName("ZHNetwork"); // Optional.
myNet.setMaxNumberOfAttempts(3); // Optional.
myNet.setMaxWaitingTimeBetweenTransmissions(50); // Optional.
myNet.setMaxWaitingTimeForRoutingInfo(500); // Optional.
myNet.begin();
myNet.setOnBroadcastReceivingCallback(onBroadcastReceiving); myNet.setOnBroadcastReceivingCallback(onBroadcastReceiving);
myNet.setOnUnicastReceivingCallback(onUnicastReceiving); myNet.setOnUnicastReceivingCallback(onUnicastReceiving);
myNet.setOnConfirmReceivingCallback(onConfirmReceiving); myNet.setOnConfirmReceivingCallback(onConfirmReceiving);
Serial.print("MAC: "); Serial.print("MAC: ");
Serial.print(myNet.getNodeMac()); Serial.print(myNet.getNodeMac());
Serial.print(". IP: ");
Serial.print(myNet.getNodeIp());
Serial.print(". Firmware version: "); Serial.print(". Firmware version: ");
Serial.print(myNet.getFirmwareVersion()); Serial.print(myNet.getFirmwareVersion());
Serial.println("."); Serial.println(".");
@ -210,23 +263,19 @@ void setup()
void loop() void loop()
{ {
if ((millis() - messageLastTime) > messageTimerDelay) if ((millis() - messagelastTime) > messageTimerDelay)
{ {
Serial.println("Broadcast message sended."); Serial.println("Broadcast message sended.");
myNet.sendBroadcastMessage("Hello world!"); myNet.sendBroadcastMessage("Hello world!");
Serial.print("Unicast message to MAC "); Serial.print("Unicast message to MAC ");
Serial.print(myNet.macToString(target)); Serial.print(myNet.macToString(target));
Serial.println(" sended."); Serial.println(" sended.");
myNet.sendUnicastMessage("Hello world!", target); myNet.sendUnicastMessage("Hello world!", target);
Serial.print("Unicast with confirm message to MAC "); Serial.print("Unicast with confirm message to MAC ");
Serial.print(myNet.macToString(target)); Serial.print(myNet.macToString(target));
Serial.print(" ID ");
Serial.print(myNet.sendUnicastMessage("Hello world!", target, true));
Serial.println(" sended."); Serial.println(" sended.");
myNet.sendUnicastMessage("Hello world!", target, true);
messageLastTime = millis(); messagelastTime = millis();
} }
myNet.maintenance(); myNet.maintenance();
} }
@ -239,7 +288,6 @@ void onBroadcastReceiving(const char *data, const uint8_t *sender)
Serial.print("Message: "); Serial.print("Message: ");
Serial.println(data); Serial.println(data);
} }
void onUnicastReceiving(const char *data, const uint8_t *sender) void onUnicastReceiving(const char *data, const uint8_t *sender)
{ {
Serial.print("Unicast message from MAC "); Serial.print("Unicast message from MAC ");
@ -249,14 +297,10 @@ void onUnicastReceiving(const char *data, const uint8_t *sender)
Serial.println(data); Serial.println(data);
} }
void onConfirmReceiving(const uint8_t *target, const uint16_t id, const bool status) void onConfirmReceiving(const uint8_t *target, const bool status)
{ {
Serial.print("Message to MAC "); Serial.print("Message to MAC ");
Serial.print(myNet.macToString(target)); Serial.print(myNet.macToString(target));
Serial.print(" ID ");
Serial.print(id);
Serial.println(status ? " delivered." : " undelivered."); Serial.println(status ? " delivered." : " undelivered.");
} }
``` ```
Any feedback via [e-mail](mailto:github@zh.com.ru) would be appreciated. Or... [Buy me a coffee](https://paypal.me/aZholtikov).

View File

@ -9,12 +9,26 @@ void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
Serial.println(); Serial.println();
myNet.begin("ZHNetwork"); // *** ESP-NOW mode only.
// myNet.setCryptKey("VERY_LONG_CRYPT_KEY"); // If encryption is used, the key must be set same of all another ESP-NOW devices in network. myNet.setWorkMode(ESP_NOW);
// *** Or ESP-NOW + access point mode.
// myNet.setWorkMode(ESP_NOW_AP);
// myNet.setApSetting("ESP NODE TEST", "12345678");
// *** Or ESP-NOW + connect to your router mode.
// myNet.setWorkMode(ESP_NOW_STA);
// myNet.setStaSetting("SSID", "PASSWORD");
// ***
myNet.setNetName("ZHNetwork"); // Optional.
myNet.setMaxNumberOfAttempts(3); // Optional.
myNet.setMaxWaitingTimeBetweenTransmissions(50); // Optional.
myNet.setMaxWaitingTimeForRoutingInfo(500); // Optional.
myNet.begin();
myNet.setOnBroadcastReceivingCallback(onBroadcastReceiving); myNet.setOnBroadcastReceivingCallback(onBroadcastReceiving);
myNet.setOnUnicastReceivingCallback(onUnicastReceiving); myNet.setOnUnicastReceivingCallback(onUnicastReceiving);
Serial.print("MAC: "); Serial.print("MAC: ");
Serial.print(myNet.getNodeMac()); Serial.print(myNet.getNodeMac());
Serial.print(". IP: ");
Serial.print(myNet.getNodeIp());
Serial.print(". Firmware version: "); Serial.print(". Firmware version: ");
Serial.print(myNet.getFirmwareVersion()); Serial.print(myNet.getFirmwareVersion());
Serial.println("."); Serial.println(".");
@ -33,7 +47,6 @@ void onBroadcastReceiving(const char *data, const uint8_t *sender)
Serial.print("Message: "); Serial.print("Message: ");
Serial.println(data); Serial.println(data);
} }
void onUnicastReceiving(const char *data, const uint8_t *sender) void onUnicastReceiving(const char *data, const uint8_t *sender)
{ {
Serial.print("Unicast message from MAC "); Serial.print("Unicast message from MAC ");

View File

@ -1,10 +1,10 @@
#include "ZHNetwork.h" #include "ZHNetwork.h"
void onConfirmReceiving(const uint8_t *target, const uint16_t id, const bool status); void onConfirmReceiving(const uint8_t *target, const bool status);
ZHNetwork myNet; ZHNetwork myNet;
uint64_t messageLastTime{0}; uint64_t messagelastTime{0};
uint16_t messageTimerDelay{5000}; uint16_t messageTimerDelay{5000};
const uint8_t target[6]{0xA8, 0x48, 0xFA, 0xDC, 0x5B, 0xFA}; const uint8_t target[6]{0xA8, 0x48, 0xFA, 0xDC, 0x5B, 0xFA};
@ -12,11 +12,25 @@ void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
Serial.println(); Serial.println();
myNet.begin("ZHNetwork"); // *** ESP-NOW mode only.
// myNet.setCryptKey("VERY_LONG_CRYPT_KEY"); // If encryption is used, the key must be set same of all another ESP-NOW devices in network. myNet.setWorkMode(ESP_NOW);
// *** Or ESP-NOW + access point mode.
// myNet.setWorkMode(ESP_NOW_AP);
// myNet.setApSetting("ESP NODE TEST", "12345678");
// *** Or ESP-NOW + connect to your router mode.
// myNet.setWorkMode(ESP_NOW_STA);
// myNet.setStaSetting("SSID", "PASSWORD");
// ***
myNet.setNetName("ZHNetwork"); // Optional.
myNet.setMaxNumberOfAttempts(3); // Optional.
myNet.setMaxWaitingTimeBetweenTransmissions(50); // Optional.
myNet.setMaxWaitingTimeForRoutingInfo(500); // Optional.
myNet.begin();
myNet.setOnConfirmReceivingCallback(onConfirmReceiving); myNet.setOnConfirmReceivingCallback(onConfirmReceiving);
Serial.print("MAC: "); Serial.print("MAC: ");
Serial.print(myNet.getNodeMac()); Serial.print(myNet.getNodeMac());
Serial.print(". IP: ");
Serial.print(myNet.getNodeIp());
Serial.print(". Firmware version: "); Serial.print(". Firmware version: ");
Serial.print(myNet.getFirmwareVersion()); Serial.print(myNet.getFirmwareVersion());
Serial.println("."); Serial.println(".");
@ -24,32 +38,26 @@ void setup()
void loop() void loop()
{ {
if ((millis() - messageLastTime) > messageTimerDelay) if ((millis() - messagelastTime) > messageTimerDelay)
{ {
Serial.println("Broadcast message sended."); Serial.println("Broadcast message sended.");
myNet.sendBroadcastMessage("Hello world!"); myNet.sendBroadcastMessage("Hello world!");
Serial.print("Unicast message to MAC "); Serial.print("Unicast message to MAC ");
Serial.print(myNet.macToString(target)); Serial.print(myNet.macToString(target));
Serial.println(" sended."); Serial.println(" sended.");
myNet.sendUnicastMessage("Hello world!", target); myNet.sendUnicastMessage("Hello world!", target);
Serial.print("Unicast with confirm message to MAC "); Serial.print("Unicast with confirm message to MAC ");
Serial.print(myNet.macToString(target)); Serial.print(myNet.macToString(target));
Serial.print(" ID ");
Serial.print(myNet.sendUnicastMessage("Hello world!", target, true));
Serial.println(" sended."); Serial.println(" sended.");
myNet.sendUnicastMessage("Hello world!", target, true);
messageLastTime = millis(); messagelastTime = millis();
} }
myNet.maintenance(); myNet.maintenance();
} }
void onConfirmReceiving(const uint8_t *target, const uint16_t id, const bool status) void onConfirmReceiving(const uint8_t *target, const bool status)
{ {
Serial.print("Message to MAC "); Serial.print("Message to MAC ");
Serial.print(myNet.macToString(target)); Serial.print(myNet.macToString(target));
Serial.print(" ID ");
Serial.print(id);
Serial.println(status ? " delivered." : " undelivered."); Serial.println(status ? " delivered." : " undelivered.");
} }

View File

@ -1,5 +1,5 @@
name=ZHNetwork name=ZHNetwork
version=1.41 version=1.1
author=Alexey Zholtikov author=Alexey Zholtikov
maintainer=Alexey Zholtikov maintainer=Alexey Zholtikov
sentence=ESP-NOW based Mesh network for ESP8266/ESP32 sentence=ESP-NOW based Mesh network for ESP8266/ESP32

View File

@ -1,19 +1,31 @@
#include "ZHNetwork.h" #include "ZHNetwork.h"
routing_vector_t ZHNetwork::routingVector; routing_vector_t routingVector;
confirmation_vector_t ZHNetwork::confirmationVector; incoming_queue_t queueForIncomingData;
incoming_queue_t ZHNetwork::queueForIncomingData; outgoing_queue_t queueForOutgoingData;
outgoing_queue_t ZHNetwork::queueForOutgoingData; waiting_queue_t queueForRoutingVectorWaiting;
waiting_queue_t ZHNetwork::queueForRoutingVectorWaiting;
bool ZHNetwork::criticalProcessSemaphore{false}; const char *firmware PROGMEM{"1.1"};
bool ZHNetwork::sentMessageSemaphore{false}; const uint8_t broadcastMAC[6]{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
bool ZHNetwork::confirmReceivingSemaphore{false};
bool ZHNetwork::confirmReceiving{false}; bool criticalProcessSemaphore{false};
char ZHNetwork::netName_[20]{0}; bool sentMessageSemaphore{false};
char ZHNetwork::key_[20]{0}; bool confirmReceivingSemaphore{false};
uint8_t ZHNetwork::localMAC[6]{0}; bool confirmReceiving{false};
uint16_t ZHNetwork::lastMessageID[10]{0}; uint8_t localMAC[6]{0};
uint8_t numberOfAttemptsToSend{1};
uint16_t lastMessageID[10]{0};
uint64_t lastMessageSentTime{0};
work_mode_t workMode_{ESP_NOW};
char netName_[20]{0};
char apSsid_[32]{"ESP-NOW NODE"};
char apPassword_[64]{0};
char staSsid_[32]{0};
char staPassword_[64]{0};
uint8_t maxNumberOfAttempts_{3};
uint8_t maxWaitingTimeBetweenTransmissions_{50};
uint16_t maxTimeForRoutingInfoWaiting_{500};
ZHNetwork &ZHNetwork::setOnBroadcastReceivingCallback(on_message_t onBroadcastReceivingCallback) ZHNetwork &ZHNetwork::setOnBroadcastReceivingCallback(on_message_t onBroadcastReceivingCallback)
{ {
@ -33,41 +45,108 @@ ZHNetwork &ZHNetwork::setOnConfirmReceivingCallback(on_confirm_t onConfirmReceiv
return *this; return *this;
} }
error_code_t ZHNetwork::begin(const char *netName, const bool gateway) error_code_t ZHNetwork::setWorkMode(const work_mode_t workMode)
{ {
#if defined(ESP8266) if (workMode < ESP_NOW || workMode > ESP_NOW_STA)
randomSeed(os_random()); return ERROR;
#endif workMode_ = workMode;
#if defined(ESP32) return SUCCESS;
randomSeed(esp_random()); }
#endif
if (strlen(netName) >= 1 && strlen(netName) <= 20) work_mode_t ZHNetwork::getWorkMode()
strcpy(netName_, netName); {
return workMode_;
}
error_code_t ZHNetwork::setNetName(const char *netName)
{
if (strlen(netName) < 1 || strlen(netName) > 20)
return ERROR;
strcpy(netName_, netName);
return SUCCESS;
}
String ZHNetwork::getNetName()
{
return netName_;
}
error_code_t ZHNetwork::setStaSetting(const char *ssid, const char *password)
{
if (strlen(ssid) < 1 || strlen(ssid) > 32 || strlen(password) > 64)
return ERROR;
strcpy(staSsid_, ssid);
strcpy(staPassword_, password);
return SUCCESS;
}
error_code_t ZHNetwork::setApSetting(const char *ssid, const char *password)
{
if (strlen(ssid) < 1 || strlen(ssid) > 32 || strlen(password) < 8 || strlen(password) > 64)
return ERROR;
strcpy(apSsid_, ssid);
strcpy(apPassword_, password);
return SUCCESS;
}
error_code_t ZHNetwork::begin()
{
randomSeed(analogRead(0));
#ifdef PRINT_LOG #ifdef PRINT_LOG
Serial.begin(115200); Serial.begin(115200);
#endif #endif
WiFi.mode(gateway ? WIFI_AP_STA : WIFI_STA); switch (workMode_)
{
case ESP_NOW:
WiFi.mode(WIFI_STA);
break;
case ESP_NOW_AP:
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(apSsid_, apPassword_);
break;
case ESP_NOW_STA:
WiFi.mode(WIFI_STA);
WiFi.begin(staSsid_, staPassword_);
while (WiFi.status() != WL_CONNECTED)
{
if (WiFi.status() == WL_NO_SSID_AVAIL || WiFi.status() == WL_CONNECT_FAILED)
return ERROR;
delay(500);
}
break;
default:
break;
}
esp_now_init(); esp_now_init();
#if defined(ESP8266) #if defined(ESP8266)
wifi_get_macaddr(gateway ? SOFTAP_IF : STATION_IF, localMAC); wifi_get_macaddr(STATION_IF, localMAC);
esp_now_set_self_role(ESP_NOW_ROLE_COMBO); esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
#endif #endif
#if defined(ESP32) #if defined(ESP32)
esp_wifi_get_mac(gateway ? (wifi_interface_t)ESP_IF_WIFI_AP : (wifi_interface_t)ESP_IF_WIFI_STA, localMAC); esp_wifi_get_mac((wifi_interface_t)ESP_IF_WIFI_STA, localMAC);
#endif #endif
esp_now_register_send_cb(onDataSent); esp_now_register_send_cb(onDataSent);
esp_now_register_recv_cb(onDataReceive); esp_now_register_recv_cb(onDataReceive);
return SUCCESS; return SUCCESS;
} }
uint16_t ZHNetwork::sendBroadcastMessage(const char *data) error_code_t stop()
{ {
return broadcastMessage(data, broadcastMAC, BROADCAST); WiFi.mode(WIFI_OFF);
esp_now_deinit();
esp_now_unregister_recv_cb();
esp_now_unregister_send_cb();
return SUCCESS;
} }
uint16_t ZHNetwork::sendUnicastMessage(const char *data, const uint8_t *target, const bool confirm) void ZHNetwork::sendBroadcastMessage(const char *data)
{ {
return unicastMessage(data, target, localMAC, confirm ? UNICAST_WITH_CONFIRM : UNICAST); broadcastMessage(data, broadcastMAC, BROADCAST);
}
void ZHNetwork::sendUnicastMessage(const char *data, const uint8_t *target, const bool confirm)
{
unicastMessage(data, target, localMAC, confirm ? UNICAST_WITH_CONFIRM : UNICAST);
} }
void ZHNetwork::maintenance() void ZHNetwork::maintenance()
@ -87,15 +166,7 @@ void ZHNetwork::maintenance()
esp_now_del_peer(outgoingData.intermediateTargetMAC); esp_now_del_peer(outgoingData.intermediateTargetMAC);
#endif #endif
if (onConfirmReceivingCallback && macToString(outgoingData.transmittedData.originalSenderMAC) == macToString(localMAC) && outgoingData.transmittedData.messageType == BROADCAST) if (onConfirmReceivingCallback && macToString(outgoingData.transmittedData.originalSenderMAC) == macToString(localMAC) && outgoingData.transmittedData.messageType == BROADCAST)
onConfirmReceivingCallback(outgoingData.transmittedData.originalTargetMAC, outgoingData.transmittedData.messageID, true); onConfirmReceivingCallback(outgoingData.transmittedData.originalTargetMAC, true);
if (macToString(outgoingData.transmittedData.originalSenderMAC) == macToString(localMAC) && outgoingData.transmittedData.messageType == UNICAST_WITH_CONFIRM)
{
confirmation_waiting_data_t confirmationData;
confirmationData.time = millis();
memcpy(&confirmationData.targetMAC, &outgoingData.transmittedData.originalTargetMAC, 6);
memcpy(&confirmationData.messageID, &outgoingData.transmittedData.messageID, 2);
confirmationVector.push_back(confirmationData);
}
} }
else else
{ {
@ -198,12 +269,7 @@ void ZHNetwork::maintenance()
Serial.println(F(" received.")); Serial.println(F(" received."));
#endif #endif
if (onBroadcastReceivingCallback) if (onBroadcastReceivingCallback)
{
if (key_[0])
for (uint8_t i{0}; i < strlen(incomingData.transmittedData.message); ++i)
incomingData.transmittedData.message[i] = incomingData.transmittedData.message[i] ^ key_[i % strlen(key_)];
onBroadcastReceivingCallback(incomingData.transmittedData.message, incomingData.transmittedData.originalSenderMAC); onBroadcastReceivingCallback(incomingData.transmittedData.message, incomingData.transmittedData.originalSenderMAC);
}
forward = true; forward = true;
break; break;
case UNICAST: case UNICAST:
@ -219,12 +285,7 @@ void ZHNetwork::maintenance()
if (macToString(incomingData.transmittedData.originalTargetMAC) == macToString(localMAC)) if (macToString(incomingData.transmittedData.originalTargetMAC) == macToString(localMAC))
{ {
if (onUnicastReceivingCallback) if (onUnicastReceivingCallback)
{
if (key_[0])
for (uint8_t i{0}; i < strlen(incomingData.transmittedData.message); ++i)
incomingData.transmittedData.message[i] = incomingData.transmittedData.message[i] ^ key_[i % strlen(key_)];
onUnicastReceivingCallback(incomingData.transmittedData.message, incomingData.transmittedData.originalSenderMAC); onUnicastReceivingCallback(incomingData.transmittedData.message, incomingData.transmittedData.originalSenderMAC);
}
} }
else else
unicastMessage(incomingData.transmittedData.message, incomingData.transmittedData.originalTargetMAC, incomingData.transmittedData.originalSenderMAC, UNICAST); unicastMessage(incomingData.transmittedData.message, incomingData.transmittedData.originalTargetMAC, incomingData.transmittedData.originalSenderMAC, UNICAST);
@ -242,17 +303,8 @@ void ZHNetwork::maintenance()
if (macToString(incomingData.transmittedData.originalTargetMAC) == macToString(localMAC)) if (macToString(incomingData.transmittedData.originalTargetMAC) == macToString(localMAC))
{ {
if (onUnicastReceivingCallback) if (onUnicastReceivingCallback)
{
if (key_[0])
for (uint8_t i{0}; i < strlen(incomingData.transmittedData.message); ++i)
incomingData.transmittedData.message[i] = incomingData.transmittedData.message[i] ^ key_[i % strlen(key_)];
onUnicastReceivingCallback(incomingData.transmittedData.message, incomingData.transmittedData.originalSenderMAC); onUnicastReceivingCallback(incomingData.transmittedData.message, incomingData.transmittedData.originalSenderMAC);
} unicastMessage("", incomingData.transmittedData.originalSenderMAC, localMAC, DELIVERY_CONFIRM_RESPONSE);
confirmation_id_t id;
memcpy(&id.messageID, &incomingData.transmittedData.messageID, 2);
char temp[sizeof(transmitted_data_t::message)];
memcpy(&temp, &id, sizeof(transmitted_data_t::message));
unicastMessage(temp, incomingData.transmittedData.originalSenderMAC, localMAC, DELIVERY_CONFIRM_RESPONSE);
} }
else else
unicastMessage(incomingData.transmittedData.message, incomingData.transmittedData.originalTargetMAC, incomingData.transmittedData.originalSenderMAC, UNICAST_WITH_CONFIRM); unicastMessage(incomingData.transmittedData.message, incomingData.transmittedData.originalTargetMAC, incomingData.transmittedData.originalSenderMAC, UNICAST_WITH_CONFIRM);
@ -270,17 +322,7 @@ void ZHNetwork::maintenance()
if (macToString(incomingData.transmittedData.originalTargetMAC) == macToString(localMAC)) if (macToString(incomingData.transmittedData.originalTargetMAC) == macToString(localMAC))
{ {
if (onConfirmReceivingCallback) if (onConfirmReceivingCallback)
{ onConfirmReceivingCallback(incomingData.transmittedData.originalSenderMAC, true);
confirmation_id_t id;
memcpy(&id.messageID, &incomingData.transmittedData.message, 2);
for (uint16_t i{0}; i < confirmationVector.size(); ++i)
{
confirmation_waiting_data_t confirmationData = confirmationVector[i];
if (confirmationData.messageID == id.messageID)
confirmationVector.erase(confirmationVector.begin() + i);
}
onConfirmReceivingCallback(incomingData.transmittedData.originalSenderMAC, id.messageID, true);
}
} }
else else
unicastMessage(incomingData.transmittedData.message, incomingData.transmittedData.originalTargetMAC, incomingData.transmittedData.originalSenderMAC, DELIVERY_CONFIRM_RESPONSE); unicastMessage(incomingData.transmittedData.message, incomingData.transmittedData.originalTargetMAC, incomingData.transmittedData.originalSenderMAC, DELIVERY_CONFIRM_RESPONSE);
@ -418,21 +460,7 @@ void ZHNetwork::maintenance()
#endif #endif
if (waitingData.transmittedData.messageType == UNICAST_WITH_CONFIRM && macToString(waitingData.transmittedData.originalSenderMAC) == macToString(localMAC)) if (waitingData.transmittedData.messageType == UNICAST_WITH_CONFIRM && macToString(waitingData.transmittedData.originalSenderMAC) == macToString(localMAC))
if (onConfirmReceivingCallback) if (onConfirmReceivingCallback)
onConfirmReceivingCallback(waitingData.transmittedData.originalTargetMAC, waitingData.transmittedData.messageID, false); onConfirmReceivingCallback(waitingData.transmittedData.originalTargetMAC, false);
}
}
if (confirmationVector.size())
{
for (uint16_t i{0}; i < confirmationVector.size(); ++i)
{
confirmation_waiting_data_t confirmationData = confirmationVector[i];
if ((millis() - confirmationData.time) > maxTimeForRoutingInfoWaiting_)
{
confirmationVector.erase(confirmationVector.begin() + i);
broadcastMessage("", confirmationData.targetMAC, SEARCH_REQUEST);
if (onConfirmReceivingCallback)
onConfirmReceivingCallback(confirmationData.targetMAC, confirmationData.messageID, false);
}
} }
} }
} }
@ -442,6 +470,15 @@ String ZHNetwork::getNodeMac()
return macToString(localMAC); return macToString(localMAC);
} }
IPAddress ZHNetwork::getNodeIp()
{
if (workMode_ == ESP_NOW_AP)
return WiFi.softAPIP();
if (workMode_ == ESP_NOW_STA)
return WiFi.localIP();
return IPAddress(0, 0, 0, 0);
}
String ZHNetwork::getFirmwareVersion() String ZHNetwork::getFirmwareVersion()
{ {
return firmware; return firmware;
@ -469,13 +506,6 @@ uint8_t *ZHNetwork::stringToMac(const String &string, uint8_t *mac)
return mac; return mac;
} }
error_code_t ZHNetwork::setCryptKey(const char *key)
{
if (strlen(key) >= 1 && strlen(key) <= 20)
strcpy(key_, key);
return SUCCESS;
}
error_code_t ZHNetwork::setMaxNumberOfAttempts(const uint8_t maxNumberOfAttempts) error_code_t ZHNetwork::setMaxNumberOfAttempts(const uint8_t maxNumberOfAttempts)
{ {
if (maxNumberOfAttempts < 1 || maxNumberOfAttempts > 10) if (maxNumberOfAttempts < 1 || maxNumberOfAttempts > 10)
@ -570,7 +600,7 @@ void IRAM_ATTR ZHNetwork::onDataReceive(uint8_t *mac, uint8_t *data, uint8_t len
criticalProcessSemaphore = false; criticalProcessSemaphore = false;
} }
uint16_t ZHNetwork::broadcastMessage(const char *data, const uint8_t *target, message_type_t type) void ZHNetwork::broadcastMessage(const char *data, const uint8_t *target, message_type_t type)
{ {
outgoing_data_t outgoingData; outgoing_data_t outgoingData;
outgoingData.transmittedData.messageType = type; outgoingData.transmittedData.messageType = type;
@ -579,9 +609,6 @@ uint16_t ZHNetwork::broadcastMessage(const char *data, const uint8_t *target, me
memcpy(&outgoingData.transmittedData.originalTargetMAC, target, 6); memcpy(&outgoingData.transmittedData.originalTargetMAC, target, 6);
memcpy(&outgoingData.transmittedData.originalSenderMAC, &localMAC, 6); memcpy(&outgoingData.transmittedData.originalSenderMAC, &localMAC, 6);
strcpy(outgoingData.transmittedData.message, data); strcpy(outgoingData.transmittedData.message, data);
if (key_[0] && outgoingData.transmittedData.messageType == BROADCAST)
for (uint8_t i{0}; i < strlen(outgoingData.transmittedData.message); ++i)
outgoingData.transmittedData.message[i] = outgoingData.transmittedData.message[i] ^ key_[i % strlen(key_)];
memcpy(&outgoingData.intermediateTargetMAC, &broadcastMAC, 6); memcpy(&outgoingData.intermediateTargetMAC, &broadcastMAC, 6);
queueForOutgoingData.push(outgoingData); queueForOutgoingData.push(outgoingData);
#ifdef PRINT_LOG #ifdef PRINT_LOG
@ -605,10 +632,9 @@ uint16_t ZHNetwork::broadcastMessage(const char *data, const uint8_t *target, me
Serial.print(macToString(outgoingData.transmittedData.originalTargetMAC)); Serial.print(macToString(outgoingData.transmittedData.originalTargetMAC));
Serial.println(F(" added to queue.")); Serial.println(F(" added to queue."));
#endif #endif
return outgoingData.transmittedData.messageID;
} }
uint16_t ZHNetwork::unicastMessage(const char *data, const uint8_t *target, const uint8_t *sender, message_type_t type) void ZHNetwork::unicastMessage(const char *data, const uint8_t *target, const uint8_t *sender, message_type_t type)
{ {
outgoing_data_t outgoingData; outgoing_data_t outgoingData;
outgoingData.transmittedData.messageType = type; outgoingData.transmittedData.messageType = type;
@ -617,9 +643,6 @@ uint16_t ZHNetwork::unicastMessage(const char *data, const uint8_t *target, cons
memcpy(&outgoingData.transmittedData.originalTargetMAC, target, 6); memcpy(&outgoingData.transmittedData.originalTargetMAC, target, 6);
memcpy(&outgoingData.transmittedData.originalSenderMAC, sender, 6); memcpy(&outgoingData.transmittedData.originalSenderMAC, sender, 6);
strcpy(outgoingData.transmittedData.message, data); strcpy(outgoingData.transmittedData.message, data);
if (key_[0] && macToString(outgoingData.transmittedData.originalSenderMAC) == macToString(localMAC) && outgoingData.transmittedData.messageType != DELIVERY_CONFIRM_RESPONSE)
for (uint8_t i{0}; i < strlen(outgoingData.transmittedData.message); ++i)
outgoingData.transmittedData.message[i] = outgoingData.transmittedData.message[i] ^ key_[i % strlen(key_)];
for (uint16_t i{0}; i < routingVector.size(); ++i) for (uint16_t i{0}; i < routingVector.size(); ++i)
{ {
routing_table_t routingTable = routingVector[i]; routing_table_t routingTable = routingVector[i];
@ -655,7 +678,7 @@ uint16_t ZHNetwork::unicastMessage(const char *data, const uint8_t *target, cons
Serial.print(macToString(outgoingData.intermediateTargetMAC)); Serial.print(macToString(outgoingData.intermediateTargetMAC));
Serial.println(F(" added to queue.")); Serial.println(F(" added to queue."));
#endif #endif
return outgoingData.transmittedData.messageID; return;
} }
} }
memcpy(&outgoingData.intermediateTargetMAC, target, 6); memcpy(&outgoingData.intermediateTargetMAC, target, 6);
@ -688,5 +711,4 @@ uint16_t ZHNetwork::unicastMessage(const char *data, const uint8_t *target, cons
Serial.print(macToString(outgoingData.intermediateTargetMAC)); Serial.print(macToString(outgoingData.intermediateTargetMAC));
Serial.println(F(" added to queue.")); Serial.println(F(" added to queue."));
#endif #endif
return outgoingData.transmittedData.messageID;
} }

View File

@ -50,18 +50,12 @@ typedef struct
uint8_t intermediateTargetMAC[6]{0}; uint8_t intermediateTargetMAC[6]{0};
} routing_table_t; } routing_table_t;
typedef struct typedef enum
{ {
uint16_t messageID{0}; ESP_NOW = 1,
char empty[198]{0}; // Just only to prevent compiler warnings. ESP_NOW_AP,
} confirmation_id_t; ESP_NOW_STA
} work_mode_t;
typedef struct
{
uint64_t time{0};
uint8_t targetMAC[6]{0};
uint16_t messageID{0};
} confirmation_waiting_data_t;
typedef enum typedef enum
{ {
@ -80,9 +74,8 @@ typedef enum // Just for further development.
} error_code_t; } error_code_t;
typedef std::function<void(const char *, const uint8_t *)> on_message_t; typedef std::function<void(const char *, const uint8_t *)> on_message_t;
typedef std::function<void(const uint8_t *, const uint16_t, const bool)> on_confirm_t; typedef std::function<void(const uint8_t *, const bool)> on_confirm_t;
typedef std::vector<routing_table_t> routing_vector_t; typedef std::vector<routing_table_t> routing_vector_t;
typedef std::vector<confirmation_waiting_data_t> confirmation_vector_t;
typedef std::queue<outgoing_data_t> outgoing_queue_t; typedef std::queue<outgoing_data_t> outgoing_queue_t;
typedef std::queue<incoming_data_t> incoming_queue_t; typedef std::queue<incoming_data_t> incoming_queue_t;
typedef std::queue<waiting_data_t> waiting_queue_t; typedef std::queue<waiting_data_t> waiting_queue_t;
@ -94,21 +87,31 @@ public:
ZHNetwork &setOnUnicastReceivingCallback(on_message_t onUnicastReceivingCallback); ZHNetwork &setOnUnicastReceivingCallback(on_message_t onUnicastReceivingCallback);
ZHNetwork &setOnConfirmReceivingCallback(on_confirm_t onConfirmReceivingCallback); ZHNetwork &setOnConfirmReceivingCallback(on_confirm_t onConfirmReceivingCallback);
error_code_t begin(const char *netName = "", const bool gateway = false); error_code_t setWorkMode(const work_mode_t workMode);
work_mode_t getWorkMode(void);
uint16_t sendBroadcastMessage(const char *data); error_code_t setNetName(const char *netName);
uint16_t sendUnicastMessage(const char *data, const uint8_t *target, const bool confirm = false); String getNetName(void);
error_code_t setStaSetting(const char *ssid, const char *password);
error_code_t setApSetting(const char *ssid, const char *password);
error_code_t begin(void);
error_code_t stop(void);
void sendBroadcastMessage(const char *data);
void sendUnicastMessage(const char *data, const uint8_t *target, const bool confirm = false);
void maintenance(void); void maintenance(void);
String getNodeMac(void); String getNodeMac(void);
IPAddress getNodeIp(void);
String getFirmwareVersion(void); String getFirmwareVersion(void);
String readErrorCode(error_code_t code); // Just for further development. String readErrorCode(error_code_t code); // Just for further development.
static String macToString(const uint8_t *mac); static String macToString(const uint8_t *mac);
uint8_t *stringToMac(const String &string, uint8_t *mac); uint8_t *stringToMac(const String &string, uint8_t *mac);
error_code_t setCryptKey(const char *key = "");
error_code_t setMaxNumberOfAttempts(const uint8_t maxNumberOfAttempts); error_code_t setMaxNumberOfAttempts(const uint8_t maxNumberOfAttempts);
uint8_t getMaxNumberOfAttempts(void); uint8_t getMaxNumberOfAttempts(void);
error_code_t setMaxWaitingTimeBetweenTransmissions(const uint8_t maxWaitingTimeBetweenTransmissions); error_code_t setMaxWaitingTimeBetweenTransmissions(const uint8_t maxWaitingTimeBetweenTransmissions);
@ -117,29 +120,6 @@ public:
uint16_t getMaxWaitingTimeForRoutingInfo(void); uint16_t getMaxWaitingTimeForRoutingInfo(void);
private: private:
static routing_vector_t routingVector;
static confirmation_vector_t confirmationVector;
static incoming_queue_t queueForIncomingData;
static outgoing_queue_t queueForOutgoingData;
static waiting_queue_t queueForRoutingVectorWaiting;
static bool criticalProcessSemaphore;
static bool sentMessageSemaphore;
static bool confirmReceivingSemaphore;
static bool confirmReceiving;
static uint8_t localMAC[6];
static uint16_t lastMessageID[10];
static char netName_[20];
static char key_[20];
const char *firmware{"1.41"};
const uint8_t broadcastMAC[6]{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t maxNumberOfAttempts_{3};
uint8_t maxWaitingTimeBetweenTransmissions_{50};
uint8_t numberOfAttemptsToSend{1};
uint16_t maxTimeForRoutingInfoWaiting_{500};
uint32_t lastMessageSentTime{0};
#if defined(ESP8266) #if defined(ESP8266)
static void onDataSent(uint8_t *mac, uint8_t status); static void onDataSent(uint8_t *mac, uint8_t status);
static void onDataReceive(uint8_t *mac, uint8_t *data, uint8_t length); static void onDataReceive(uint8_t *mac, uint8_t *data, uint8_t length);
@ -148,8 +128,8 @@ private:
static void onDataSent(const uint8_t *mac, esp_now_send_status_t status); static void onDataSent(const uint8_t *mac, esp_now_send_status_t status);
static void onDataReceive(const uint8_t *mac, const uint8_t *data, int length); static void onDataReceive(const uint8_t *mac, const uint8_t *data, int length);
#endif #endif
uint16_t broadcastMessage(const char *data, const uint8_t *target, message_type_t type); void broadcastMessage(const char *data, const uint8_t *target, message_type_t type);
uint16_t unicastMessage(const char *data, const uint8_t *target, const uint8_t *sender, message_type_t type); void unicastMessage(const char *data, const uint8_t *target, const uint8_t *sender, message_type_t type);
on_message_t onBroadcastReceivingCallback; on_message_t onBroadcastReceivingCallback;
on_message_t onUnicastReceivingCallback; on_message_t onUnicastReceivingCallback;
on_confirm_t onConfirmReceivingCallback; on_confirm_t onConfirmReceivingCallback;