Update NOW.md
This commit is contained in:
parent
ec11a56154
commit
495a7f81ec
87
docs/NOW.md
87
docs/NOW.md
|
|
@ -1,84 +1,47 @@
|
||||||
# SpanPoint: Point-to-Point Communication between ESP32 Devices
|
# SpanPoint: Point-to-Point Communication between ESP32 Devices
|
||||||
|
|
||||||
SpanPoint is HomeSpan's easy-to-use implementation of Espressif's ESP-NOW protocol. ESP-NOW provides bi-directional, point-to-point communication between ESP32 devices without the need for a central WiFi network.
|
SpanPoint is HomeSpan's easy-to-use implementation of the Espressif ESP-NOW protocol. SpanPoint provides bi-directional, point-to-point communication of small, fixed-size messages directly between ESP32 devices based on their MAC Addresses without the need for a central WiFi network.
|
||||||
|
|
||||||
In a typical "Remote Sensor" setup, a "Main" ESP32 device runs a complete HomeSpan sketch, whereas one or more "Remote" ESP32 devices run simple sketches designed to take measurements (temperature, humidity, etc.). The Main device is paired to HomeKit and communicates with the Home App over your WiFi network in the usual fashion. In contrast, the Remote devices do not connect to your WiFi network or to HomeKit, but instead send their data directly to the Main device using an encrypted ESP-NOW channel. The Main device is then responsible for reading this data and determining what, if any, actions to take or updates to send to HomeKit.
|
To establish connectivity between any two devices, say **DEV-A** and **DEV-B**, simply create a SpanPoint object on each device that includes the MAC Address of the other device, the size of the messages (if any) to be sent from **DEV-A** to **DEV-B**, and the size of the messages (if any) to be sent from **DEV-B** to **DEV-A**.
|
||||||
|
|
||||||
Note that since ESP-NOW does not require always-on WiFi connectivity, it draws very little power. This means you can operate Remote devices with a battery instead of wall-power, which opens up many possibilities, such as installing temperature sensors in remote (outdoor) locations where wall-power may be unavailable.
|
Then, whenever needed, use the corresponding SpanPoint object's `send()` and `get()` methods to *send* a message from one device to the other, and *get* the message on the other device once it is received.
|
||||||
|
|
||||||
You are of course not limited to the above Main/Remote scenario. SpanPoint can be used to send messages back and forth among any combination of ESP32 devices, regardless if none or them, some of them, or all of them, are running a complete HomeSpan sketch.
|
SpanPoint takes takes care of all the underlying ESP-NOW structures and processes, configures ESP-NOW to encrypt all message traffic, manages internal data queues to make sure messages are not dropped, and automatically calibrates the WiFi channel used by ESP-NOW to match whatever is needed by any devices that are also connected to HomeKit through your central WiFi network.
|
||||||
|
|
||||||
SpanPoint is part of the main HomeSpan library, so all you need to do is place `#include "HomeSpan.h"` near the top of your sketch to access the *SpanPoint* class and all of its methods.
|
SpanPoint is part of the main HomeSpan library and is accessible by adding `#include "HomeSpan.h"` near the top of your sketch. Detailed descriptions of the SpanPoint class and all of its methods are provided below.
|
||||||
|
|
||||||
## *SpanPoint(const char \*macAddress, int sendSize, int receiveSize, int queueDepth=1)*
|
## *SpanPoint(const char \*macAddress, int sendSize, int receiveSize, int queueDepth=1)*
|
||||||
|
|
||||||
Creating an instance of this **class** enables the device to send messages to, and/or receive messages from, a "matching" instance of *SpanPoint* on another ESP32 device. Arguments, along with their defaults if left unspecified, are as follows:
|
Creating an instance of this **class** enables the device to send messages to, and/or receive messages from, a "corresponding" instance of *SpanPoint* on another ESP32 device. Arguments, along with their defaults if left unspecified, are as follows:
|
||||||
|
|
||||||
* *macAddress* - the MAC Address of the other device to which you want to send data to, and/or receive data from, in the standard 6-byte format "XX:XX:XX:XX:XX:XX", where each XX represents a single 2-digit hexidecimal byte from 00 to FF
|
* *macAddress* - the MAC Address of the *other* device to which you want to send data to, and/or receive data from, in the standard 6-byte format "XX:XX:XX:XX:XX:XX", where each XX represents a single 2-digit hexidecimal byte from 00 to FF
|
||||||
* *sendSize* - the size, in bytes, of any message that will be sent from this device to the device with MAC Address specified above. Maximum allowed size = 200 bytes. Set to zero if you will *not* be sending any messages from this device over this instance of *SpanPoint*
|
* *sendSize* - the size, in bytes, of any messages that will be sent from this device to the *other* device. Allowed range is 0 to 200, where a value of 0 is used to indicate to SpanPoint that you will **not** be using `send()` to transmit any messages from this device to the *other* device
|
||||||
* *receiveSize* - the size, in bytes, of any message that will be received by this device from the device with MAC Address specified above. Maximum allowed size = 200 bytes. Set to zero if you do not intend to be reading any messages from the other device over this instance of *SpanPoint* (in which case any messages the other device happens to transmit to this device will be ignored)
|
* *receiveSize* - the size, in bytes, of any messages that will be received by this device from the *other* device. Allowed range is 0 to 200, where a value of 0 is used to indicate to SpanPoint that you will **not** be using `get()` to retreive any messages transmitted by the *other* device and received on this device
|
||||||
* *queueDepth* - the depth of the queue reserved to hold incoming messages of *receiveSize* bytes. Default=1 is left unspecified, which should be sufficient for most applications. Set to greater than 1 if you expect to receive incoming messages from the other device at a rate that is faster than can be read and processed by the current device (a very unlikely scenario)
|
* *queueDepth* - the depth of the queue reserved to hold messages of *receiveSize* bytes that were received by this device from the *other* device, but not yet retreived using `get()`. See below for further details. Default=1 if left unspecified, which should be sufficient for most applications
|
||||||
|
|
||||||
For example, if:
|
SpanPoint objects created on two separate devices are considered "corresponding" if the MAC Addresses specified in each object reference each other, and the *sendSize* and *receiveSize* of one the SpanPoint object on one device matches the *receiveSize* and *sendSize* of the SpanPoint object on the "other" device, with the exception that it is always okay to set either the *sendSize* or *receiveSize* to zero regardless of the value set on the "other" device.
|
||||||
|
|
||||||
* **Device A** (MAC Address=*A1:A2:A3:A4:A5:A6*) is going to send 4-byte messages to both **Device B** (MAC Address=*B1:B2:B3:B4:B5:B6*) and **Device C** (MAC Addresses=*C1:C2:C3:C4:C5:C6*), and
|
SpanPoint will throw a fatal error and halt the sketch if:
|
||||||
* **Device B** is going to send 128-byte messages to **Device A**, and
|
* the *macAddress* specified is ill-formed, or
|
||||||
* **Device C** is going to send 91-byte messages to **Device A**,
|
* either *sendSize* or *receiveSize* is set to greater than 200, or
|
||||||
|
* both *sendSize* and *receiveSize* are set to 0, since there is no purpose for a SpanPoint that will neither transmit nor receive data
|
||||||
|
|
||||||
then the sketch for **Device A** would contain something like this:
|
The following SpanPoint methods are used to transmit and receive messages from a SpanPoint object on one device to a corresponding SpanPoint object on the "other" device:
|
||||||
|
|
||||||
```C++
|
* `boolean send(const void *data)`
|
||||||
#include "HomeSpan.h"
|
|
||||||
|
|
||||||
SpanPoint *devB, *devC;
|
* transmits a message using data pointed to by *data* (which may be a standard data type, such as *uint16_t*, or a user-defined *struct*) to the *other* device
|
||||||
|
* the size of the *data* element to be transmitted much match the *sendSize* parameter specified when the SpanPoint object was created
|
||||||
void setup(){
|
* returns **true** if transmission was successful, otherwise **false** if transmission failed. Note that transmission is considered successful as long as the device can find and connect to the *other* device based on its MAC Address, regardless of whether or not the other device has a corresponding SpanPoint object
|
||||||
devB = new SpanPoint("B1:B2:B3:B4:B5:B6",4,128); // create SpanPoint to device B with sendSize=4 and receiveSize=128
|
|
||||||
devC = new SpanPoint("C1:C2:C3:C4:C5:C6",4,91); // create SpanPoint to device C with sendSize=4 and receiveSize=91
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
the sketch for **Device B** would contain something like this:
|
|
||||||
|
|
||||||
```C++
|
|
||||||
#include "HomeSpan.h"
|
|
||||||
|
|
||||||
SpanPoint *devA;
|
|
||||||
|
|
||||||
void setup(){
|
|
||||||
devA = new SpanPoint("A1:A2:A3:A4:A5:A6",128,4); // create SpanPoint to device A with sendSize=128 and receiveSize=4
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
and the sketch for **Device C** would contain something like this:
|
|
||||||
|
|
||||||
```C++
|
|
||||||
#include "HomeSpan.h"
|
|
||||||
|
|
||||||
SpanPoint *devA;
|
|
||||||
|
|
||||||
void setup(){
|
|
||||||
devA = new SpanPoint("A1:A2:A3:A4:A5:A6",91,4); // create SpanPoint to device A with sendSize=91 and receiveSize=4
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Once instances of *SpanPoint* are created, the following methods can be used to send and receive messages:
|
|
||||||
|
|
||||||
* `boolean send(void *data)`
|
|
||||||
|
|
||||||
* transmits data referenced by the pointer *data* to the other device
|
|
||||||
* returns **true** if transmission was successful, otherwise **false** if transmission failed. Note that this method will return **true** as long as it can find and connect to the device with the *macAddress* specified when the relevant SpanPoint object was instantiated, regardless of whether or not the other device successful reads the message
|
|
||||||
* example (using the above scenario): `float humidity=35.8; devB->send(&humidity);` sends a 4-byte floating number to **Device B**. Note that the pointer *data* should always reference a data element or structure whose size exactly matches the *sendSize* parameter specified when the relevant SpanPoint object was instantiated
|
|
||||||
|
|
||||||
* `boolean get(void *dataBuf)`
|
* `boolean get(void *dataBuf)`
|
||||||
|
|
||||||
* checks to see if a message has been received into SpanPoint's internal queue from a device with the *macAddress* specified when the relevant SpanPoint object was instantiated. If so, the message is copied into the memory pointed to by *dataBuf*, the internal queue is cleared, and the method returns **true**. If no message is available, the *dataBuf* memory is unmodified and the method returns **false**
|
* checks to see if a message has been received into SpanPoint's internal message queue from the *other* device
|
||||||
* note that the pointer *dataBuf* should always reference a data element or structure whose size equals or exceeds the *receiveSize* parameter specified when the relevant SpanPoint object was instantiated
|
* if no message is available, the method returns **false** and *dataBuf* is unmodified
|
||||||
* once the internal SpanPoint queue is full, any messages received from the same device are discarded until the queue is cleared by calling this *get()* method. Setting the optional *queueDepth* parameter to a number greater than one when the relevant SpanPoint object was instantiated allows SpanPoint to retain up to *queueDepth* messages even without a call to the *get()* method. However, once the queue is full, additional messages received will be discarded until messages are "gotten" off the queue with the *get()* method
|
* if a message is available, it is **moved** from the internal message queue into *dataBuf* and the method returns **true**
|
||||||
|
* the size of the message will always be equal to the *receiveSize* parameter specified when the SpanPoint object was created, so make sure *dataBuf* is sufficiently sized to store such a message
|
||||||
|
|
||||||
|
Note that whether or or not you call the `get()` method, SpanPoint is configured to store in an internal queue any SpanPoint messages it receives from *other* devices, provided that (a) there is room in the internal queue, and (b) the size of the message received matches the *receiveSize* parameter specified when the relevant SpanPoint object was instantiated (i.e. each SpanPoint object maintains its own internal queue). If the internal queue is already full, the message will be ignored and thus never retrievable by the `get()` method. To avoid this, set the *queueDepth* to something greater than 1 when instantating the SpanPoint object. If the queue is not full, but the sie of the message
|
||||||
|
|
||||||
|
|
||||||
See tutorial sketch [#10 (RGB_LED)](../examples/10-RGB_LED) for an example of using LedPin to control an RGB LED.
|
See tutorial sketch [#10 (RGB_LED)](../examples/10-RGB_LED) for an example of using LedPin to control an RGB LED.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue