Created SpanPoint

Verified ESP-NOW is communicating correctly with HomeSpan.  Verified encryption works.  Next step - create linkages between incoming data and Services; create queue structure to transfer data.
This commit is contained in:
Gregg 2022-09-25 13:53:54 -05:00
parent 22cfa130b4
commit 4f983051ce
3 changed files with 83 additions and 11 deletions

View File

@ -31,10 +31,10 @@
#include <WiFi.h> #include <WiFi.h>
#include <driver/ledc.h> #include <driver/ledc.h>
#include <mbedtls/version.h> #include <mbedtls/version.h>
#include <mbedtls/sha256.h>
#include <esp_task_wdt.h> #include <esp_task_wdt.h>
#include <esp_sntp.h> #include <esp_sntp.h>
#include <esp_ota_ops.h> #include <esp_ota_ops.h>
#include <esp_now.h>
#include "HomeSpan.h" #include "HomeSpan.h"
#include "HAP.h" #include "HAP.h"
@ -140,11 +140,7 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
Serial.print(__TIME__); Serial.print(__TIME__);
Serial.printf("\nPartition: %s",esp_ota_get_running_partition()->label); Serial.printf("\nPartition: %s",esp_ota_get_running_partition()->label);
Serial.printf("\nMAC Address: %s",WiFi.macAddress().c_str());
if(espNowEnabled){
esp_now_init(); // initialize ESP NOW
Serial.print("\nESP-NOW: ENABLED");
}
Serial.print("\n\nDevice Name: "); Serial.print("\n\nDevice Name: ");
Serial.print(displayName); Serial.print(displayName);
@ -449,7 +445,6 @@ void Span::checkConnect(){
connected++; connected++;
addWebLog(true,"WiFi Connected! IP Address = %s",WiFi.localIP().toString().c_str()); addWebLog(true,"WiFi Connected! IP Address = %s",WiFi.localIP().toString().c_str());
Serial.printf("MAC Address = %s, Channel = %d\n",WiFi.macAddress().c_str(),WiFi.channel());
if(connected>1) // Do not initialize everything below if this is only a reconnect if(connected>1) // Do not initialize everything below if this is only a reconnect
return; return;
@ -2155,6 +2150,57 @@ void SpanOTA::error(ota_error_t err){
else if (err == OTA_END_ERROR) Serial.println("End Failed\n"); else if (err == OTA_END_ERROR) Serial.println("End Failed\n");
} }
///////////////////////////////
// SpanPoint //
///////////////////////////////
SpanPoint::SpanPoint(const char *macAddress){
if(homeSpan.Accessories.empty() || homeSpan.Accessories.back()->Services.empty()){
Serial.printf("\nFATAL ERROR! Can't create new SpanPoint(\"%s\") without a defined Service ***\n",macAddress);
Serial.printf("\n=== PROGRAM HALTED ===");
while(1);
}
init();
if(sscanf(macAddress,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",peerInfo.peer_addr,peerInfo.peer_addr+1,peerInfo.peer_addr+2,peerInfo.peer_addr+3,peerInfo.peer_addr+4,peerInfo.peer_addr+5)!=6){
Serial.printf("\nFATAL ERROR! Can't create new SpanPoint(\"%s\") - Invalid MAC Address ***\n",macAddress);
Serial.printf("\n=== PROGRAM HALTED ===");
while(1);
}
peerInfo.channel=0; // 0=matches current WiFi channel
peerInfo.ifidx=WIFI_IF_STA; // must specify interface
peerInfo.encrypt=true; // turn on encryption for this peer
memcpy(peerInfo.lmk, lmk, 16); // set local key
esp_now_add_peer(&peerInfo); // add peer to ESP-NOW
}
///////////////////////////////
void SpanPoint::init(const char *password){
if(initialized)
return;
uint8_t hash[32];
mbedtls_sha256_ret((const unsigned char *)password,strlen(password),hash,0); // produce 256-bit bit hash from password
esp_now_init(); // initialize ESP-NOW
memcpy(lmk, hash, 16); // store first 16 bytes of hash for later use as local key
esp_now_set_pmk(hash+16); // set hash for primary key using last 16 bytes of hash
esp_now_register_recv_cb(dataReceived); // set callback for receiving data
initialized=true;
}
///////////////////////////////
void SpanPoint::dataReceived(const uint8_t *mac, const uint8_t *incomingData, int len){
Serial.printf("SpanPoint: %d bytes received from %02X:%02X:%02X:%02X:%02X:%02X\n",len,mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
}
/////////////////////////////// ///////////////////////////////
void __attribute__((weak)) loop(){ void __attribute__((weak)) loop(){
@ -2166,5 +2212,7 @@ int SpanOTA::otaPercent;
boolean SpanOTA::safeLoad; boolean SpanOTA::safeLoad;
boolean SpanOTA::enabled=false; boolean SpanOTA::enabled=false;
boolean SpanOTA::auth; boolean SpanOTA::auth;
uint8_t SpanPoint::lmk[16];
boolean SpanPoint::initialized=false;

View File

@ -39,6 +39,7 @@
#include <unordered_set> #include <unordered_set>
#include <nvs.h> #include <nvs.h>
#include <ArduinoOTA.h> #include <ArduinoOTA.h>
#include <esp_now.h>
#include "extras/Blinker.h" #include "extras/Blinker.h"
#include "extras/Pixel.h" #include "extras/Pixel.h"
@ -155,6 +156,25 @@ struct SpanOTA{ // manages OTA process
// USER API CLASSES BEGINS HERE // // USER API CLASSES BEGINS HERE //
////////////////////////////////////// //////////////////////////////////////
class SpanPoint {
friend class Span;
esp_now_peer_info_t peerInfo;
static uint8_t lmk[16];
static boolean initialized;
static void dataReceived(const uint8_t *mac, const uint8_t *incomingData, int len);
static void init(const char *password="HomeSpan");
public:
SpanPoint(const char *macAddress);
};
///////////////////////////////
class Span{ class Span{
friend class SpanAccessory; friend class SpanAccessory;
@ -167,6 +187,7 @@ class Span{
friend class SpanOTA; friend class SpanOTA;
friend class Network; friend class Network;
friend class HAPClient; friend class HAPClient;
friend class SpanPoint;
const char *displayName; // display name for this device - broadcast as part of Bonjour MDNS const char *displayName; // display name for this device - broadcast as part of Bonjour MDNS
const char *hostNameBase; // base of hostName of this device - full host name broadcast by Bonjour MDNS will have 6-byte accessoryID as well as '.local' automatically appended const char *hostNameBase; // base of hostName of this device - full host name broadcast by Bonjour MDNS will have 6-byte accessoryID as well as '.local' automatically appended
@ -185,7 +206,6 @@ class Span{
char pairingCodeCommand[12]=""; // user-specified Pairing Code - only needed if Pairing Setup Code is specified in sketch using setPairingCode() char pairingCodeCommand[12]=""; // user-specified Pairing Code - only needed if Pairing Setup Code is specified in sketch using setPairingCode()
String lastClientIP="0.0.0.0"; // IP address of last client accessing device through encrypted channel String lastClientIP="0.0.0.0"; // IP address of last client accessing device through encrypted channel
boolean newCode; // flag indicating new application code has been loaded (based on keeping track of app SHA256) boolean newCode; // flag indicating new application code has been loaded (based on keeping track of app SHA256)
boolean espNowEnabled=false; // flag indicating if ESP-NOW is enabled
int connected=0; // WiFi connection status (increments upon each connect and disconnect) int connected=0; // WiFi connection status (increments upon each connect and disconnect)
unsigned long waitTime=60000; // time to wait (in milliseconds) between WiFi connection attempts unsigned long waitTime=60000; // time to wait (in milliseconds) between WiFi connection attempts
@ -284,8 +304,8 @@ class Span{
void setApFunction(void (*f)()){apFunction=f;} // sets an optional user-defined function to call when activating the WiFi Access Point void setApFunction(void (*f)()){apFunction=f;} // sets an optional user-defined function to call when activating the WiFi Access Point
void enableAutoStartAP(){autoStartAPEnabled=true;} // enables auto start-up of Access Point when WiFi Credentials not found void enableAutoStartAP(){autoStartAPEnabled=true;} // enables auto start-up of Access Point when WiFi Credentials not found
void setWifiCredentials(const char *ssid, const char *pwd); // sets WiFi Credentials void setWifiCredentials(const char *ssid, const char *pwd); // sets WiFi Credentials
void enableEspNOW(){espNowEnabled=true;}; // enables ESP-NOW void setSpanPointPassword(const char *pwd){SpanPoint::init(pwd);}; // sets SpanPoint password
void setPairingCode(const char *s){sprintf(pairingCodeCommand,"S %9s",s);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead void setPairingCode(const char *s){sprintf(pairingCodeCommand,"S %9s",s);} // sets the Pairing Code - use is NOT recommended. Use 'S' from CLI instead
void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS void deleteStoredValues(){processSerialCommand("V");} // deletes stored Characteristic values from NVS
@ -305,7 +325,7 @@ class Span{
void autoPoll(uint32_t stackSize=CONFIG_ARDUINO_LOOP_STACK_SIZE){xTaskCreateUniversal([](void *parms){for(;;)homeSpan.pollTask();}, "pollTask", stackSize, NULL, 1, &pollTaskHandle, 0);} // start pollTask() void autoPoll(uint32_t stackSize=CONFIG_ARDUINO_LOOP_STACK_SIZE){xTaskCreateUniversal([](void *parms){for(;;)homeSpan.pollTask();}, "pollTask", stackSize, NULL, 1, &pollTaskHandle, 0);} // start pollTask()
void setTimeServerTimeout(uint32_t tSec){webLog.waitTime=tSec*1000;} // sets wait time (in seconds) for optional web log time server to connect void setTimeServerTimeout(uint32_t tSec){webLog.waitTime=tSec*1000;} // sets wait time (in seconds) for optional web log time server to connect
[[deprecated("Please use reserveSocketConnections(n) method instead.")]] [[deprecated("Please use reserveSocketConnections(n) method instead.")]]
void setMaxConnections(uint8_t n){requestedMaxCon=n;} // sets maximum number of simultaneous HAP connections void setMaxConnections(uint8_t n){requestedMaxCon=n;} // sets maximum number of simultaneous HAP connections
}; };
@ -319,6 +339,7 @@ class SpanAccessory{
friend class SpanCharacteristic; friend class SpanCharacteristic;
friend class SpanButton; friend class SpanButton;
friend class SpanRange; friend class SpanRange;
friend class SpanPoint;
uint32_t aid=0; // Accessory Instance ID (HAP Table 6-1) uint32_t aid=0; // Accessory Instance ID (HAP Table 6-1)
int iidCount=0; // running count of iid to use for Services and Characteristics associated with this Accessory int iidCount=0; // running count of iid to use for Services and Characteristics associated with this Accessory

View File

@ -42,6 +42,8 @@ void setup() {
homeSpan.begin(Category::Lighting,"HomeSpan Lamp Server","homespan"); homeSpan.begin(Category::Lighting,"HomeSpan Lamp Server","homespan");
homeSpan.setSpanPointPassword("Hello Thert");
new SpanAccessory(); // Begin by creating a new Accessory using SpanAccessory(), which takes no arguments new SpanAccessory(); // Begin by creating a new Accessory using SpanAccessory(), which takes no arguments
new Service::AccessoryInformation(); // HAP requires every Accessory to implement an AccessoryInformation Service, which has 6 required Characteristics new Service::AccessoryInformation(); // HAP requires every Accessory to implement an AccessoryInformation Service, which has 6 required Characteristics
@ -63,6 +65,7 @@ void setup() {
new Characteristic::Name("Light 1"); new Characteristic::Name("Light 1");
new Characteristic::ColorTemperature(); new Characteristic::ColorTemperature();
new Characteristic::Active(); new Characteristic::Active();
new SpanPoint("AC:67:B2:77:42:20");
new Service::LightBulb(); new Service::LightBulb();
new Characteristic::On(0,true); new Characteristic::On(0,true);
(new Characteristic::Brightness(50,false))->setRange(10,100,5); (new Characteristic::Brightness(50,false))->setRange(10,100,5);