Update libki
This commit is contained in:
@@ -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.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user