Skip to content

Commit 3da1431

Browse files
authored
Merge pull request #741 from sparkfun/nsUpdates
Modify ESP-NOW for asynchronous operation
2 parents c3ca1f0 + e3583cd commit 3da1431

File tree

12 files changed

+357
-229
lines changed

12 files changed

+357
-229
lines changed

Firmware/RTK_Everywhere/Developer.ino

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,15 +187,15 @@ bool webServerIsRunning() {return false;}
187187

188188
#ifndef COMPILE_ESPNOW
189189

190-
bool espNowGetState() {return ESPNOW_OFF;}
191190
bool espNowIsPaired() {return false;}
191+
bool espNowIsPairing() {return false;}
192+
bool espNowIsBroadcasting() {return false;}
192193
void espNowProcessRTCM(byte incoming) {}
193194
bool espNowProcessRxPairedMessage() {return true;}
194195
esp_err_t espNowRemovePeer(const uint8_t *peerMac) {return ESP_OK;}
195196
esp_err_t espNowSendPairMessage(const uint8_t *sendToMac) {return ESP_OK;}
196197
bool espNowSetChannel(uint8_t channelNumber) {return false;}
197198
bool espNowStart() {return true;}
198-
void espNowStaticPairing() {}
199199
bool espNowStop() {return true;}
200200
void espNowUpdate() {}
201201

Firmware/RTK_Everywhere/Display.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,7 @@ void paintKeyProvisionFail(uint16_t displayTime)
30943094
// Show screen while ESP-NOW is pairing
30953095
void paintEspNowPairing()
30963096
{
3097-
displayMessage("ESP-NOW Pairing", 0);
3097+
displayMessage("ESP-NOW Pairing", 2000);
30983098
}
30993099
void paintEspNowPaired()
31003100
{

Firmware/RTK_Everywhere/ESPNOW.ino

Lines changed: 165 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
frame is not critical.
2222
**********************************************************************/
2323

24+
bool espnowRequestPair = false; // Modified by states.ino, menuRadio, or CLI
25+
2426
#ifdef COMPILE_ESPNOW
2527

2628
//****************************************
@@ -47,6 +49,7 @@ uint8_t espNowOutgoing[250]; // ESP NOW has max of 250 characters
4749
uint8_t espNowOutgoingSpot; // ESP Now has a max of 250 characters
4850
uint8_t espNowReceivedMAC[6]; // Holds the MAC received during pairing
4951
ESPNOWState espNowState;
52+
ESPNOWState espNowPrePairingState;
5053

5154
//*********************************************************************
5255
// Add a peer to the ESP-NOW network
@@ -96,9 +99,25 @@ void espNowBeginPairing()
9699
}
97100

98101
// Start ESP-NOW if necessary
99-
// If no peers are on file, automatically add the broadcast MAC to the peer list
100102
wifiEspNowOn(__FILE__, __LINE__);
101103

104+
// If this device has been paired to other units, the broadcastMAC is not yet enabled. Enable it for pairing.
105+
if (esp_now_is_peer_exist(espNowBroadcastAddr) == false)
106+
{
107+
// Add the broadcast peer
108+
esp_err_t result = espNowAddPeer(espNowBroadcastAddr);
109+
if (settings.debugEspNow == true)
110+
{
111+
if (result != ESP_OK)
112+
systemPrintln("Failed to add broadcast peer");
113+
else
114+
systemPrintln("Broadcast peer added");
115+
}
116+
}
117+
118+
espNowPrePairingState =
119+
espNowState; // Once pairing is completed or canceled, we will need to return to the original state
120+
102121
espNowSetState(ESPNOW_PAIRING);
103122
}
104123

@@ -109,6 +128,16 @@ bool espNowIsPaired()
109128
return (espNowState == ESPNOW_PAIRED);
110129
}
111130

131+
bool espNowIsPairing()
132+
{
133+
return (espNowState == ESPNOW_PAIRING);
134+
}
135+
136+
bool espNowIsBroadcasting()
137+
{
138+
return (espNowState == ESPNOW_BROADCASTING);
139+
}
140+
112141
//*********************************************************************
113142
// Callback when data is received
114143
void espNowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingData, int len)
@@ -249,46 +278,6 @@ void espNowProcessRTCM(byte incoming)
249278
// ESPNOW_PAIRED states.
250279
//*********************************************************************
251280

252-
//*********************************************************************
253-
// Regularly call during pairing to see if we've received a Pairing message
254-
bool espNowProcessRxPairedMessage()
255-
{
256-
if (espNowState != ESPNOW_MAC_RECEIVED)
257-
return false;
258-
259-
// Remove broadcast peer
260-
espNowRemovePeer(espNowBroadcastAddr);
261-
262-
// Is the received MAC already paired?
263-
if (esp_now_is_peer_exist(espNowReceivedMAC) == true)
264-
{
265-
// Yes, already paired
266-
if (settings.debugEspNow == true)
267-
systemPrintln("Peer already exists");
268-
}
269-
else
270-
{
271-
// No, add new peer to system
272-
espNowAddPeer(espNowReceivedMAC);
273-
274-
// Record this MAC to peer list
275-
memcpy(settings.espnowPeers[settings.espnowPeerCount], espNowReceivedMAC, 6);
276-
settings.espnowPeerCount++;
277-
settings.espnowPeerCount %= ESPNOW_MAX_PEERS;
278-
}
279-
280-
// Send message directly to the received MAC (not unicast), then exit
281-
espNowSendPairMessage(espNowReceivedMAC);
282-
283-
// Enable radio. User may have arrived here from the setup menu rather than serial menu.
284-
settings.enableEspNow = true;
285-
286-
// Record enableEspNow and espnowPeerCount to NVM
287-
recordSystemSettings();
288-
espNowSetState(ESPNOW_PAIRED);
289-
return (true);
290-
}
291-
292281
//*********************************************************************
293282
// Remove a given MAC address from the peer list
294283
esp_err_t espNowRemovePeer(const uint8_t *peerMac)
@@ -323,6 +312,9 @@ esp_err_t espNowSendPairMessage(const uint8_t *sendToMac)
323312
for (int x = 0; x < 6; x++)
324313
pairMessage.crc += wifiMACAddress[x];
325314

315+
if (settings.debugEspNow == true && !inMainMenu)
316+
systemPrintln("ESPNOW send pair message\r\n");
317+
326318
return (esp_now_send(sendToMac, (uint8_t *)&pairMessage, sizeof(pairMessage))); // Send packet to given MAC
327319
}
328320

@@ -400,6 +392,11 @@ bool espNowStart()
400392
break;
401393
}
402394

395+
// Using ESP-NOW, a receiver will receive all packets addressed to its MAC and the broadcast MAC
396+
// with no peers added. It is the transmitter that needs peers assigned to filter out packets.
397+
// Therefore, if ESP-NOW is enabled, we add the broadcast MAC to the peer list by default to allow
398+
// the link to function without pairing, and allow pairing messages if pairing is started.
399+
403400
// Check for peers listed in settings
404401
if (settings.espnowPeerCount == 0)
405402
{
@@ -424,7 +421,7 @@ bool espNowStart()
424421
}
425422
espNowSetState(ESPNOW_BROADCASTING);
426423
}
427-
else
424+
else // settings.espnowPeerCount > 0
428425
{
429426
// If we have peers, move to paired state
430427
espNowSetState(ESPNOW_PAIRED);
@@ -485,50 +482,6 @@ bool espNowStart()
485482
return started;
486483
}
487484

488-
//*********************************************************************
489-
// A blocking function that is used to pair two devices
490-
// either through the serial menu or AP config
491-
void espNowStaticPairing()
492-
{
493-
systemPrintln("Begin ESP NOW Pairing");
494-
495-
// Start ESP-NOW if needed, put ESP-NOW into broadcast state
496-
espNowBeginPairing();
497-
498-
// Begin sending our MAC every 250ms until a remote device sends us there info
499-
randomSeed(millis());
500-
501-
systemPrintln("Begin pairing. Place other unit in pairing mode. Press any key to exit.");
502-
clearBuffer();
503-
504-
bool exitPair = false;
505-
while (exitPair == false)
506-
{
507-
if (systemAvailable())
508-
{
509-
systemPrintln("User pressed button. Pairing canceled.");
510-
break;
511-
}
512-
513-
int timeout = 1000 + random(0, 100); // Delay 1000 to 1100ms
514-
for (int x = 0; x < timeout; x++)
515-
{
516-
delay(1);
517-
518-
if (espNowProcessRxPairedMessage() == true) // Check if we've received a pairing message
519-
{
520-
systemPrintln("Pairing compete");
521-
exitPair = true;
522-
break;
523-
}
524-
}
525-
526-
espNowSendPairMessage(espNowBroadcastAddr); // Send unit's MAC address over broadcast, no ack, no encryption
527-
528-
systemPrintln("Scanning for other radio...");
529-
}
530-
}
531-
532485
//*********************************************************************
533486
// Stop ESP-NOW layer
534487
bool espNowStop()
@@ -651,38 +604,142 @@ bool espNowStop()
651604

652605
//*********************************************************************
653606
// Called from main loop
607+
// Update the ESP-NOW state machine to allow for broadcasting partial packets, pairing, etc.
654608
// Control incoming/outgoing RTCM data from internal ESP NOW radio
655-
// Use the ESP32 to directly transmit/receive RTCM over 2.4GHz (no WiFi needed)
656609
void espNowUpdate()
657610
{
658-
if (settings.enableEspNow == true)
611+
// Override setting because user has initiated pairing via the display menu or CLI
612+
// We don't save settings here; they are saved after successful pairing.
613+
if (espnowRequestPair == true && settings.enableEspNow == false)
614+
settings.enableEspNow = true;
615+
616+
switch (espNowState)
659617
{
660-
if (espNowState == ESPNOW_PAIRED || espNowState == ESPNOW_BROADCASTING)
618+
case ESPNOW_OFF:
619+
if (settings.enableEspNow == true)
620+
{
621+
wifiEspNowOn(__FILE__, __LINE__); // Turn on ESP-NOW hardware
622+
623+
if (settings.espnowPeerCount == 0)
624+
espNowSetState(ESPNOW_BROADCASTING);
625+
else
626+
espNowSetState(ESPNOW_PAIRED);
627+
}
628+
629+
break;
630+
631+
case ESPNOW_PAIRED:
632+
case ESPNOW_BROADCASTING:
633+
if (settings.enableEspNow == false)
634+
{
635+
wifiEspNowOff(__FILE__, __LINE__); // Turn off ESP-NOW hardware
636+
espNowSetState(ESPNOW_OFF);
637+
}
638+
639+
// If it's been longer than 50ms since we last added a byte to the buffer
640+
// then we've reached the end of the RTCM stream. Send partial buffer.
641+
if (espNowOutgoingSpot > 0 && (millis() - espNowLastAdd) > 50)
661642
{
662-
// If it's been longer than a few ms since we last added a byte to the buffer
663-
// then we've reached the end of the RTCM stream. Send partial buffer.
664-
if (espNowOutgoingSpot > 0 && (millis() - espNowLastAdd) > 50)
643+
if (espNowState == ESPNOW_PAIRED)
644+
esp_now_send(0, (uint8_t *)&espNowOutgoing, espNowOutgoingSpot); // Send partial packet to all peers
645+
else // if (espNowState == ESPNOW_BROADCASTING)
646+
esp_now_send(espNowBroadcastAddr, (uint8_t *)&espNowOutgoing,
647+
espNowOutgoingSpot); // Send packet via broadcast
648+
649+
if (settings.debugEspNow == true && !inMainMenu)
650+
systemPrintf("ESPNOW transmitted %d RTCM bytes\r\n", espNowBytesSent + espNowOutgoingSpot);
651+
espNowBytesSent = 0;
652+
espNowOutgoingSpot = 0; // Reset
653+
}
654+
655+
// If we don't receive an ESP NOW packet after some time, set RSSI to very negative
656+
// This removes the ESPNOW icon from the display when the link goes down
657+
if (millis() - espNowLastRssiUpdate > 5000 && espNowRSSI > -255)
658+
espNowRSSI = -255;
659+
660+
// The display menu, serial menu, or CLI may request pairing be started
661+
if (espnowRequestPair == true)
662+
{
663+
// Start ESP-NOW if needed, put ESP-NOW into broadcast state
664+
espNowBeginPairing();
665+
}
666+
break;
667+
668+
case ESPNOW_PAIRING:
669+
if (settings.enableEspNow == false)
670+
{
671+
wifiEspNowOff(__FILE__, __LINE__); // Turn off ESP-NOW hardware
672+
espNowSetState(ESPNOW_OFF);
673+
}
674+
675+
if (espnowRequestPair == false) // The menuRadio can cancel a pairing request. We also end once paired.
676+
{
677+
espNowSetState(espNowPrePairingState); // Return to the original state
678+
}
679+
else
680+
{
681+
// Send our MAC at random intervals until we receive a remote MAC
682+
randomSeed(millis());
683+
static unsigned long lastMacSend = millis();
684+
static int timeout = 1000 + random(0, 100); // Pick a random number between 1000 to 1100ms
685+
if (millis() - lastMacSend > timeout)
665686
{
666-
if (espNowState == ESPNOW_PAIRED)
667-
esp_now_send(0, (uint8_t *)&espNowOutgoing, espNowOutgoingSpot); // Send partial packet to all peers
668-
else // if (espNowState == ESPNOW_BROADCASTING)
669-
esp_now_send(espNowBroadcastAddr, (uint8_t *)&espNowOutgoing,
670-
espNowOutgoingSpot); // Send packet via broadcast
687+
lastMacSend = millis();
688+
espNowSendPairMessage(
689+
espNowBroadcastAddr); // Send unit's MAC address over broadcast, no ack, no encryption
671690

672-
if (!inMainMenu)
673-
{
674-
if (settings.debugEspNow == true)
675-
systemPrintf("ESPNOW transmitted %d RTCM bytes\r\n", espNowBytesSent + espNowOutgoingSpot);
676-
}
677-
espNowBytesSent = 0;
678-
espNowOutgoingSpot = 0; // Reset
691+
systemPrintln("Scanning for other radio...");
679692
}
680693

681-
// If we don't receive an ESP NOW packet after some time, set RSSI to very negative
682-
// This removes the ESPNOW icon from the display when the link goes down
683-
if (millis() - espNowLastRssiUpdate > 5000 && espNowRSSI > -255)
684-
espNowRSSI = -255;
694+
// Callback espNowOnDataReceived() will change state if a MAC is received
685695
}
696+
697+
break;
698+
699+
case ESPNOW_MAC_RECEIVED:
700+
if (settings.enableEspNow == false)
701+
{
702+
wifiEspNowOff(__FILE__, __LINE__); // Turn off ESP-NOW hardware
703+
espNowSetState(ESPNOW_OFF);
704+
}
705+
706+
paintEspNowPaired();
707+
708+
// Remove broadcast peer
709+
espNowRemovePeer(espNowBroadcastAddr);
710+
711+
// Is the received MAC already paired?
712+
if (esp_now_is_peer_exist(espNowReceivedMAC) == true)
713+
{
714+
// Yes, already paired
715+
if (settings.debugEspNow == true)
716+
systemPrintln("Peer already exists");
717+
}
718+
else
719+
{
720+
// No, add new peer to system
721+
espNowAddPeer(espNowReceivedMAC);
722+
723+
// Record this MAC to peer list
724+
memcpy(settings.espnowPeers[settings.espnowPeerCount], espNowReceivedMAC, 6);
725+
settings.espnowPeerCount++;
726+
settings.espnowPeerCount %= ESPNOW_MAX_PEERS;
727+
}
728+
729+
// Send message directly to the received MAC (not unicast)
730+
espNowSendPairMessage(espNowReceivedMAC);
731+
732+
// Report success to the CLI
733+
commandSendStringOkResponse((char *)"SPEXE", (char *)"UPDATEPAIR", "SUCCESS");
734+
735+
// Record enableEspNow setting and espnowPeerCount to NVM
736+
recordSystemSettings();
737+
738+
espNowSetState(ESPNOW_PAIRED);
739+
740+
systemPrintln("Pairing complete");
741+
espnowRequestPair = false;
742+
break;
686743
}
687744
}
688745

Firmware/RTK_Everywhere/RTK_Everywhere.ino

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,7 @@ char *incomingSettings;
680680
int incomingSettingsSpot;
681681
unsigned long timeSinceLastIncomingSetting;
682682
unsigned long lastDynamicDataUpdate;
683+
bool websocketConnected = false;
683684

684685
#ifdef COMPILE_WIFI
685686
#ifdef COMPILE_AP
@@ -689,8 +690,6 @@ unsigned long lastDynamicDataUpdate;
689690
#include <WebServer.h> // Port 80
690691
#include <esp_http_server.h> // Needed for web sockets only - on port 81
691692

692-
bool websocketConnected = false;
693-
694693
#endif // COMPILE_AP
695694
#endif // COMPILE_WIFI
696695

0 commit comments

Comments
 (0)