Update libki

This commit is contained in:
sieja
2025-07-21 21:31:40 +02:00
parent d145590bd3
commit a9fba3267d
47 changed files with 2072 additions and 914 deletions

View File

@@ -62,9 +62,13 @@
// Note that once HomeSpan is paired with HomeKit, additional NVS records will be consumed to store the
// pairing information for each verified HomeKit Controller.
// Note also that when compiling under the Arduino IDE, the IDE reports the size of partition based on the
// Partition Scheme you selected in the IDE menu, even though that scheme is not actually used if you have your
// own "partition.csv" file, as in this example. This may lead the IDE to report an incorrect partition size.
// IMPORTANT!! When compiling under the Arduino IDE, the IDE itself first needs to make sure the size of your
// sketch is not larger than the size of the application partitions in your partition table. However, the IDE
// has no access to your custom "partition.csv" file and instead computes the size of the application partitions
// based on the Partition Scheme you selected in the IDE menu, even though that scheme is not actually used if
// you have your own "partitions.csv" file, as in this example. Before compiling, you MUST select a Partition Scheme
// in the IDE that has an application partition size matching the size of the application parititions in your
// custom "partitions.csv" file.
///////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,75 @@
/*********************************************************************************
* MIT License
*
* Copyright (c) 2020-2025 Gregg E. Berman
*
* https://github.com/HomeSpan/HomeSpan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
********************************************************************************/
// This sketch provides a variation of Example 1 (a Simple LightBulb Accessory) that demonstrates
// the use of multi-threaded functionality to periodically flip the power of the light from a thread
// outside of the main HomeSpan polling process. You will be able to turn on/off the LightBulb
// Accessory from the Home App as usual, but every 10 seconds the light will flip state automatically
// (turning it ON if it is OFF, or turning it OFF if it is ON).
// Note this example does not implement an actual LED, just the logic to show how things work from
// within the Home App.
// This sketch can be used with both single- and dual-processor devices.
#include "HomeSpan.h"
Characteristic::On *power; // NEW! Create a global pointer to the On Characterstic (to be used below)
//////////////////////////////////////
void setup() {
Serial.begin(115200);
homeSpan.begin(Category::Lighting,"HomeSpan LightBulb");
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
new Service::LightBulb();
power = new Characteristic::On(); // NEW! Save the pointer to the Characteristic in the global variable, power
homeSpan.autoPoll(); // NEW! Start autopolling. HomeSpan will run its polling process in separate thread
}
//////////////////////////////////////
void loop(){
// NOTE: we DO NOT call homeSpan.poll() from this loop() since we already started polling in a separate thread above by calling homeSpan.autoPoll()
delay(10000); // sleep for 10 seconds - note this has no effect on HomeSpan since the polling process is in a different thread
Serial.printf("*** Flipping power of Light!\n");
homeSpanPAUSE; // temporarily pause the HomeSpan polling process
power->setVal(1-power->getVal()); // flip the value of the On Characteristic using the pointer we saved above
} // note once at the end of the loop() code block HomeSpan polling automatically resumes (no need to call homeSpanRESUME)

View File

@@ -0,0 +1,121 @@
/*********************************************************************************
* MIT License
*
* Copyright (c) 2024 Gregg E. Berman
*
* https://github.com/HomeSpan/HomeSpan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
********************************************************************************/
// HomeSpan Addressable RGBCW LED Example. Demonstrates use of two separate Accessories to control a SINGLE
// NeoPixel LED Strip. The first controls the RGB LEDs and the second controls the Warm-White and Cool-White LEDs.
// Both sets can be on at the same time.
//
// Note use of Pixel::CCT() method to convert color temperature into values for the White LEDs.
//
// Also note that HomeKit uses the Mirek scale for color temperture instead of the Kelvin scale. To convert from
// one to the other, divide into 1 million: Mirek=1.0e6/Kelvin and Kelvin=1.0e6/Mirek.
//
#define NEOPIXEL_PIN 23 // pin number to which NeoPixel strand is attached
#define NPIXELS 100 // number of controllable pixels in strand (which may be less than actual number of LEDs)
#define WARM_LED_TEMP 3000 // temperature (in Kelvin) of Warm-White LED
#define COOL_LED_TEMP 6500 // temperature (in Kelvin) of Cool-White LED
#include "HomeSpan.h"
Pixel pixel(NEOPIXEL_PIN,"GRBWC"); // create a global instance of a Pixel strand supporting RGB LEDs plus warm AND cool white LED
Pixel::Color colorRGB; // create a global instance of a Pixel color to be used to store the RGB color
Pixel::Color colorWC; // create a global instance of a Pixel color to be used to store the WC color
///////////////////////////////
struct NeoPixel_RGB : Service::LightBulb { // define an RGB Lightbulb to control the RGB LEDs on the NeoPixel Light Strip
Characteristic::On power{0,true};
Characteristic::Hue H{0,true};
Characteristic::Saturation S{0,true};
Characteristic::Brightness V{100,true};
NeoPixel_RGB() : Service::LightBulb(){
V.setRange(5,100,1);
update(); // manually call update() to set pixel with restored initial values
}
boolean update() override {
colorRGB=pixel.HSV(H.getNewVal(), S.getNewVal(), V.getNewVal()*power.getNewVal());
pixel.set(colorRGB+colorWC,NPIXELS);
return(true);
}
};
///////////////////////////////
struct NeoPixel_WC : Service::LightBulb { // define WC Lightbulb to control the Warm White and Cool White LEDs on the NeoPixel Light Strip
Characteristic::On power{0,true};
Characteristic::Brightness V{100,true};
Characteristic::ColorTemperature T{(uint32_t)1.0e6/((COOL_LED_TEMP+WARM_LED_TEMP)/2),true}; // set initial value to average of Warm and Cool Temp
NeoPixel_WC() : Service::LightBulb(){
V.setRange(5,100,1);
T.setRange(1.0e6/COOL_LED_TEMP,1.0e6/WARM_LED_TEMP); // set range of control to match range of Warm-White and Cool-White LEDs
update(); // manually call update() to set pixel with restored initial values
}
boolean update() override {
colorWC=pixel.CCT(1.0e6/T.getNewVal(), V.getNewVal()*power.getNewVal()); // convert HomeKit temperature (in Mirek) to Kelvin
pixel.set(colorRGB+colorWC,NPIXELS);
return(true);
}
};
///////////////////////////////
void setup() {
Serial.begin(115200);
pixel.setTemperatures(WARM_LED_TEMP,COOL_LED_TEMP); // set color temperatures of Warm-White and Cool-White LEDs
homeSpan.begin(Category::Lighting,"RGBWC Light");
SPAN_ACCESSORY();
SPAN_ACCESSORY("Neo RGB");
new NeoPixel_RGB();
SPAN_ACCESSORY("Neo WC");
new NeoPixel_WC();
}
///////////////////////////////
void loop() {
homeSpan.poll();
}
///////////////////////////////

View File

@@ -110,7 +110,7 @@ struct NeoPixel_RGBW : Service::LightBulb { // Addressable single-wire RGBW
NeoPixel_RGBW(uint8_t pin, int nPixels) : Service::LightBulb(){
V.setRange(5,100,1); // sets the range of the Brightness to be from a min of 5%, to a max of 100%, in steps of 1%
pixel=new Pixel(pin,PixelType::GRBW); // creates Pixel RGBW LED on specified pin (with order of colors chnanged to reflect this specific NeoPixel device)
pixel=new Pixel(pin,"GRBW"); // creates Pixel RGBW LED on specified pin (with order of colors changed to reflect this specific NeoPixel device)
this->nPixels=nPixels; // save number of Pixels in this LED Strand
update(); // manually call update() to set pixel with restored initial values
}

View File

@@ -27,105 +27,146 @@
/////////////////////// PIXEL TESTER //////////////////////////
// This sketch is designed to help identify the proper settings to use for a NeoPixel, NeoPixel Strip,
// or any device containing one or more single-wire addressable RGB or RGBW LEDs (the "Pixel Device").
// This sketch is designed to help identify the proper settings to use for a NeoPixel,
// NeoPixel Strip, or any device containing one or more single-wire addressable RGB-style LEDs
// Before compiling, set PIXEL_PIN to the ESP32 pin that is connected to your Pixel Device, and set NPIXELS to
// the numnber of Pixels in the Pixel Device. Note that for some strips a single chip controls more than one LED,
// in which case NPIXELS should be set to the number of controlling chips, NOT the number of LEDs.
// To start, the second argument of the Pixel constructor for the testPixel object below should remain
// set to PixelType::RGBW
// When run, the sketch will repeatedly cycle colors by setting ALL pixels in the device first to RED, then GREEN,
// followed by BLUE, and then finally WHITE. After a short pause, the cycle repeats.
// For each color the brightness will increase from 0 through MAX_BRIGHTNESS, and then back to 0. You can change
// MAX_BRIGHTNESS to something lower than 255 if you want to limit how bright the pixels get.
// For Pixel Devices with more than one pixel, diagnostics are as follows:
//
// * If all 4 colors repeatedly flash in the order expected, this means the base setting of PixelType::RGBW is correct!
//
// * If instead of each pixel being set to the same color, the pixels in the strip each light up with a different color
// (or no color at all), this means you have an RGB LED, not an RGBW LED. Change the second parameter of the constructor
// to PixelType::RGB and re-run the sketch.
//
// * If all of the pixels are being set to the same color, but the sequence is NOT in the order RED, GREEN, BLUE, change
// the second parameter of the constructor so that the order of the PixelType colors match the sequence of the colors
// that appear on the Pixel Device. For example, if your RGBW Pixel Device flashes GREEN, RED, BLUE, and than WHITE, use
// PixelType::GRBW.
// For Pixel Devices with only a single pixel, diagnostics are as follows:
// * If all 4 colors repeatedly flash in the order expected, this means the base setting of PixelType::RGBW is correct!
//
// * If the pixel does not light at all when set to WHITE this means you have an RGB LED, not an RGBW LED. Change the
// second parameter of the constructor to PixelType::RGB and re-run the sketch.
//
// * If all of the pixels are being set to the same color, but the sequence is NOT in the order RED, GREEN, BLUE, change
// the second parameter of the constructor so that the order of the PixelType colors match the sequence of the colors
// that appear on the Pixel Device. For example, if your RGB Pixel Device flashes GREEN, RED, and then BLUE, use
// PixelType::GRB.
// DIRECTIONS: Run sketch and and follow on-screen instructions
//////////////////////////////////////
#include "HomeSpan.h"
//////////////////////////////////////
#define MAX_BRIGHTNESS 255 // lower this value (max=255) if pixels LEDs are too bright to look at when perfoming this test
#define MAX_BRIGHTNESS 255 // maximum brightness when flashing RGBW [0-255]
int pin=-1;
int nPixels=0;
#define PIXEL_PIN 26 // set this to whatever pin you are using - note pin cannot be "input only"
#define NPIXELS 8 // set to number of pixels in strip
Pixel::Color colors[5]={
Pixel::RGB(MAX_BRIGHTNESS,0,0,0,0),
Pixel::RGB(0,MAX_BRIGHTNESS,0,0,0),
Pixel::RGB(0,0,MAX_BRIGHTNESS,0,0),
Pixel::RGB(0,0,0,MAX_BRIGHTNESS,0),
Pixel::RGB(0,0,0,0,MAX_BRIGHTNESS)
};
Pixel testPixel(PIXEL_PIN, PixelType::RGBW); // change the second argument until device operates with correct colors
Pixel *testPixel;
//////////////////////////////////////
void setup() {
Serial.begin(115200);
delay(1000);
Serial.printf("\n\nPixel Test on pin %d with %d pixels\n\n",PIXEL_PIN,NPIXELS);
char *getSerial(){
static char buf[9];
strcpy(buf,"");
return(Utils::readSerial(buf,8));
}
//////////////////////////////////////
void flashColor(boolean r, boolean g, boolean b, boolean w){
void setup() {
Serial.begin(115200);
delay(1000);
for(int i=0;i<MAX_BRIGHTNESS;i++){
testPixel.set(Pixel::RGB(i*r,i*g,i*b,i*w),NPIXELS);
delay(4);
Serial.printf("\n\n*************** PIXEL TESTER **********************\n\n");
Serial.printf("This sketch helps you identity your Pixel Type\n\n");
while(pin<0){
Serial.printf("Enter PIN number to which NeoPixel is connected: ");
sscanf(getSerial(),"%d",&pin);
if(pin<0)
Serial.printf("(invalid entry)\n");
else
Serial.printf("%d\n",pin);
}
for(int i=MAX_BRIGHTNESS;i>=0;i--){
testPixel.set(Pixel::RGB(i*r,i*g,i*b,i*w),NPIXELS);
delay(4);
testPixel=new Pixel(pin,"01234");
while(nPixels<=0){
Serial.printf("Enter number of PIXELS in NeoPixel device: ");
sscanf(getSerial(),"%d",&nPixels);
if(nPixels<=0)
Serial.printf("(invalid entry)\n");
else
Serial.printf("%d\n",nPixels);
}
Serial.printf("\nFor each test below, specify COLORS shown using the following characters:\n\n");
if(nPixels==1){
Serial.printf(" 'R' = Red\n");
Serial.printf(" 'G' = Green\n");
Serial.printf(" 'B' = Blue\n");
Serial.printf(" 'W' = White (or Warm-White)\n");
Serial.printf(" 'C' = Cool White\n");
Serial.printf(" '-' = Pixel is NOT lit\n");
}
else{
Serial.printf(" 'R' = FIRST Pixel is Red\n");
Serial.printf(" 'G' = FIRST Pixel is Green\n");
Serial.printf(" 'B' = FIRST Pixel is Blue\n");
Serial.printf(" 'W' = FIRST Pixel is White (or Warm-White)\n");
Serial.printf(" 'C' = FIRST Pixel is Cool White\n");
Serial.printf(" '-' = neither FIRST nor SECOND Pixel is lit\n");
Serial.printf(" 'X' = FIRST Pixel is not lit, but SECOND Pixel is lit (any color)\n");
}
Serial.printf("\nNote: entries are case-insensitive.\n\n");
char pType[6]="";
for(int i=0;i<5;i++){
testPixel->set(colors[i]);
while(strlen(pType)==i){
Serial.printf("Test #%d - enter COLOR: ",i+1);
if(nPixels==1)
sscanf(getSerial(),"%1[RGBWCrgbwc-]",pType+i);
else
sscanf(getSerial(),"%1[RGBWCrgbwcxX-]",pType+i);
if(strlen(pType)==i)
Serial.printf("(invalid entry)\n");
else{
pType[i]=toupper(pType[i]);
Serial.printf("'%s'\n",pType+i);
}
}
if(pType[i]=='X')
break;
}
while(strlen(pType)>3 && ((pType[strlen(pType)-1]=='-' && nPixels==1) || pType[strlen(pType)-1]=='X'))
pType[strlen(pType)-1]='\0';
Serial.printf("\nTest Concluded. Best match for your Pixel Type is '%s'\n\n",pType);
testPixel=new Pixel(pin,pType);
testPixel->set(Pixel::RGB(0,0,0,0,0),nPixels);
Serial.printf("Hit ENTER to verify with flashing test\n\n");
getSerial();
}
//////////////////////////////////////
void loop(){
char c[]="RGBWC";
Serial.printf("Red...");
flashColor(1,0,0,0);
Serial.printf("Green...");
flashColor(0,1,0,0);
Serial.printf("Blue...");
flashColor(0,0,1,0);
if(testPixel.isRGBW()){
Serial.printf("White...");
flashColor(0,0,0,1);
for(int i=0;i<5;i++){
if(testPixel->hasColor(c[i])){
Serial.printf("Color '%c'...",c[i]);
for(int v=0;v<MAX_BRIGHTNESS;v++){
testPixel->set(Pixel::RGB(i==0?v:0,i==1?v:0,i==2?v:0,i==3?v:0,i==4?v:0),nPixels);
delay(4*255/MAX_BRIGHTNESS);
}
for(int v=MAX_BRIGHTNESS;v>=0;v--){
testPixel->set(Pixel::RGB(i==0?v:0,i==1?v:0,i==2?v:0,i==3?v:0,i==4?v:0),nPixels);
delay(4*255/MAX_BRIGHTNESS);
}
}
}
Serial.printf("Pausing.\n");
delay(1000);
testPixel->set(Pixel::RGB(0,0,0,0,0),nPixels);
Serial.printf("Done.\n");
Serial.printf("Hit ENTER to repeat with flashing test, or type 'R' to restart program...\n");
if(toupper(getSerial()[0])=='R')
ESP.restart();
}
//////////////////////////////////////

View File

@@ -79,9 +79,9 @@ void setup() {
homeSpan.setLogLevel(1);
homeSpan.setHostNameSuffix(""); // use null string for suffix (rather than the HomeSpan device ID)
homeSpan.setPortNum(1201); // change port number for HomeSpan so we can use port 80 for the Web Server
homeSpan.setWifiCallback(setupWeb); // need to start Web Server after WiFi is established
homeSpan.setHostNameSuffix(""); // use null string for suffix (rather than the HomeSpan device ID)
homeSpan.setPortNum(1201); // change port number for HomeSpan so we can use port 80 for the Web Server
homeSpan.setConnectionCallback(setupWeb); // need to start Web Server after WiFi is established
homeSpan.begin(Category::Lighting,"HomeSpan Light Hub",HUB_NAME);
@@ -264,7 +264,10 @@ void listAccessories(const char *buf){
///////////////////////////
void setupWeb(){
void setupWeb(int count){
if(count>1)
return;
Serial.printf("Starting Light Server Hub at %s.local\n\n",HUB_NAME);
webServer.begin();

View File

@@ -51,7 +51,7 @@ struct RemoteTempSensor : Service::TemperatureSensor {
const char *name;
float temperature;
RemoteTempSensor(const char *name, const char*macAddress) : Service::TemperatureSensor(){
RemoteTempSensor(const char *name, const char*macAddress, boolean is8266=false) : Service::TemperatureSensor(){
this->name=name;
@@ -60,7 +60,7 @@ struct RemoteTempSensor : Service::TemperatureSensor {
fault=new Characteristic::StatusFault(1); // set initial state = fault
remoteTemp=new SpanPoint(macAddress,0,sizeof(float)); // create a SpanPoint with send size=0 and receive size=sizeof(float)
remoteTemp=new SpanPoint(macAddress,0,sizeof(float),1,is8266); // create a SpanPoint with send size=0 and receive size=sizeof(float)
} // end constructor
@@ -99,13 +99,13 @@ void setup() {
new Service::AccessoryInformation();
new Characteristic::Identify();
new Characteristic::Name("Indoor Temp");
new RemoteTempSensor("Device 1","AC:67:B2:77:42:20"); // pass MAC Address of Remote Device
new RemoteTempSensor("Device 1","BC:FF:4D:40:8E:71",true); // pass MAC Address of Remote Device with flag noting it is an ESP8266
new SpanAccessory();
new Service::AccessoryInformation();
new Characteristic::Identify();
new Characteristic::Name("Outdoor Temp");
new RemoteTempSensor("Device 2","84:CC:A8:11:B4:84"); // pass MAC Address of Remote Device
new RemoteTempSensor("Device 2","84:CC:A8:11:B4:84"); // pass MAC Address of Remote Device
} // end of setup()

View File

@@ -57,12 +57,12 @@ void setup() {
Serial.begin(115200);
delay(1000);
Serial.printf("\n\nThis is a REMOTE Device with MAC Address = %s\n",WiFi.macAddress().c_str());
Serial.printf("\n\nThis is a REMOTE Device with MAC Address = %s\n",Network.macAddress().c_str());
Serial.printf("NOTE: This MAC Address must be entered into the corresponding SpanPoint() call of the MAIN Device.\n\n");
// In the line below, replace the MAC Address with that of your MAIN HOMESPAN DEVICE
mainDevice=new SpanPoint("84:CC:A8:11:B4:84",sizeof(float),0); // create a SpanPoint with send size=sizeof(float) and receive size=0
mainDevice=new SpanPoint("AC:67:B2:77:42:20",sizeof(float),0); // create a SpanPoint with send size=sizeof(float) and receive size=0
homeSpan.setLogLevel(1);
}

View File

@@ -0,0 +1,129 @@
/*********************************************************************************
* MIT License
*
* Copyright (c) 2023 Gregg E. Berman
*
* https://github.com/HomeSpan/HomeSpan
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
********************************************************************************/
#ifndef ARDUINO_ARCH_ESP8266
#error ERROR: THIS SKETCH IS DESIGNED FOR ESP8266 MICROCONTROLLERS!
#endif
// *** THIS SKETCH IS FOR AN ESP8266, NOT AN ESP32 *** //
// This sketch is similar to HomeSpan's RemoteDevice.ino example (designed for an ESP32 running HomeSpan) in which we simulate
// a Remote Temperature Sensor using HomeSpan's SpanPoint class. However, since neither HomeSpan nor SpanPoint is designed to
// run on an ESP8266, we will implement the BASIC communication functionality of SpanPoint by directly calling the equivalent
// ESP-NOW commands that are supported by the ESP8266. This sketch does NOT seek to replicate all of SpanPoint's features, and
// does not include automatic channel calibration or queue management.
// Start by including the following ESP8266 libraries
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Crypto.h> // this library is needed to implement the hash-code process SpanPoint uses to generate ESP-NOW encryption keys
float temp=-10.0; // this global variable represents our "simulated" temperature (in degrees C)
// Below we encode the MAC Address of the Main ESP32 Device running HomeSpan to which this ESP8266 device will connect
// IMPORTANT: ESP32 devices have TWO MAC Addresses. One is used when the ESP32 is operating in Station (STA) mode. It is the address returned
// by the WiFi.macAddress() function. The other is used when the ESP32 is operating in Access Point (AP) mode. This address is returned by the
// WiFi.softAPmacAddress() function. HomeSpan normally operates the ESP32 with both modes (STA+AP), so both MAC Addresses are active.
// On ESP32 devices, ESP-NOW seems to work fine when each device sends data to other devices via their STA MAC Address. The same is true for ESP8266
// devices sending data to an ESP32 device via ESP-NOW with one critical exception: Once the ESP32 connects (via STA mode) to a WiFi network, which it must
// do to run HomeSpan, for some reason ESP8266 devices can no longer send data via ESP-NOW to the ESP32 using its STA MAC Address.
// The solution is to instead have the ESP8266 send data via ESP-NOW to the ESP32's AP MAC Address. This seems to work regardless of whether or not
// the ESP32 is connected to a central WiFi newtork. To support such use on the ESP32, the SpanPoint constructor includes a fifth, optional parameter
// called "useAPaddress". When creating SpanPoint links of the ESP32 using HomeSpan, set useAPaddress to TRUE if the Remote Device SpanPoint is connecting
// to is an ESP8266. Set "useAPaddress" to FALSE (or leave unspecified, since FALSE is the default) if the Remote Device is an ESP32.
// When HomeSpan first starts (and whenever you type 'i' into the CLI), the Serial Monitor will display the details of each SpanPoint object you instantiated
// in your ESP32 sketch. This output includes the MAC Address at which SpanPoint will be listening for incoming data from Remote Devices. The MAC Address
// shown for the instance of SpanPoint corresponding to this Remote Deivce (i.e. this sketch) is the MAC Address you should use below.
uint8_t main_mac[6]={0xAC,0x67,0xB2,0x77,0x42,0x21}; // this is the **AP MAC Address** of the Main Device running HomeSpan on an ESP32 as reported in the HomeSpan Serial Monitor
// Next we create a simple, standard ESP-NOW callback function to report on the status of each data transmission
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.printf("Last Packet Send Status: %s\n",sendStatus==0?"Success":"Fail");
}
//////////////////////
void setup() {
Serial.begin(115200);
delay(1000);
Serial.printf("\nMAC Address: %s\n",WiFi.macAddress().c_str()); // enter this MAC address as the first argument of the matching SpanPoint object on the ESP32 running HomeSpan
WiFi.mode(WIFI_STA); // set the mode to Station
wifi_set_channel(3); // you also need to manually set the channel to match whatever channel is used by the ESP32 after it connects to your WiFi network
// Hint: As an alterntive, you can add code to this sketch to connect to the same WiFi network that HomeSpan uses. Though this sketch won't make any use of that WiFi network,
// by establishing the connection the ESP8266 automatically configures the channel, which will now match the ESP32.
// Next, initialize ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error initializing ESP-NOW");
return;
}
// SpanPoint uses ESP-NOW encryption for all communication. This encrpytion is based on two 16-byte keys: a local master key (LMK) and a primary master key (PMK). To generate
// these keys, SpanPoint takes a text-based password (the default is the word "HomeSpan"), creates a 32 byte (256 bit) hash of the text (using the SHA256 method), and uses
// the first 16 bytes as the LMK and the last 16 bytes as the PMK. This is easily replicated as follows:
uint8_t hash[32]; // create space to store as 32-byte hash code
char password[]="HomeSpan"; // specify the password
experimental::crypto::SHA256::hash(password,strlen(password),hash); // create the hash code to be used further below
esp_now_register_send_cb(OnDataSent); // register the callback function we defined above
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER); // set the role of this device to be a controller (i.e. it sends data to the ESP32)
esp_now_set_kok(hash+16,16); // next we set the PMK. For some reason this is called KOK on the ESP8266. Note you must set the PMK BEFORE adding any peers
esp_now_add_peer(main_mac, ESP_NOW_ROLE_COMBO, 0, hash, 16); // now we add in the peer, set its role, and specify the LMK
// Hint: The third argument above is the WiFi Channel. However, this is only a reference number stored by ESP-NOW. ESP-NOW does NOT actually set the channel for you.
// We already set the WiFi channel above. To make things easier, ESP-NOW allows you to set the channel as zero, which means ESP-NOW should expect the channel to be whatever was
// already set for the WiFi controller. Recommend always setting this to zero to avoid having any mismatches if you instead specified a real channel.
}
//////////////////////
void loop() {
Serial.printf("Sending Temperature: %f\n",temp);
esp_now_send(main_mac, (uint8_t *)&temp, sizeof(temp)); // Send the Data to the Main Device!
temp+=0.5; // increment the "temperature" by 0.5 C
if(temp>35.0)
temp=-10.0;
delay(5000); // wait 5 seconds before sending another update
}

View File

@@ -70,7 +70,7 @@ void setup() {
homeSpan.setLogLevel(1);
Serial.begin(115200);
delay(1000);
Serial.printf("Starting Remote Temperature Sensor. MAC Address of this device = %s\n",WiFi.macAddress().c_str());
Serial.printf("Starting Remote Temperature Sensor. MAC Address of this device = %s\n",Network.macAddress().c_str());
#endif
// In the line below, replace the MAC Address with that of your MAIN HOMESPAN DEVICE

View File

@@ -26,9 +26,8 @@
********************************************************************************/
// This example demonstrates how to control a real-world Servo Motor using HomeSpan's
// ServoPin Class, as included in "extras/PwmPin.h" The code builds upon the
// WindowShade Accessory from Example 13 by adding a Horizontal Tilt Characteristic that
// is controlled by a Servo connected to the ESP32.
// ServoPin Class. The code builds upon the WindowShade Accessory from Example 13 by
// adding a Horizontal Tilt Characteristic that is controlled by a Servo connected to the ESP32.
#include "HomeSpan.h"
#include "DEV_DoorsWindows.h"