Merge pull request #18 from HomeSpan/Development

Merge Development into Master for Release v1.1.3
This commit is contained in:
HomeSpan 2021-01-09 13:37:38 -06:00 committed by GitHub
commit a03adabc95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 184 additions and 149 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 Gregg E. Berman
Copyright (c) 2020, 2021 Gregg E. Berman
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -11,7 +11,7 @@ void setup() {
Serial.print("\n\nHomeSpan RF Transmitter Example\n\n");
RFControl rf(LED_BUILTIN); // create an instance of RFControl with signal output to the ESP32's Built-In LED
RFControl rf(13); // create an instance of RFControl with signal output to pin 13 of the ESP32
rf.clear(); // clear the pulse train memory buffer

View File

@ -16,7 +16,7 @@ At startup, HomeSpan:
If there are any errors with how you constructed your HAP Database, HomeSpan will report them and **halt** the program.
Next, HomeSpan checks to see if the device has been configured with WiFi Credentials. If none are found, HomeSpan will indicate this, and then complete its initialization routine by indicating is now READY. If WiFi Credentials are found, HomeSpan will repeatedly try to connect to the specified network until it either succeeds (in which case it then completes its initialization routine by indicating it is now READY), or you cancel the process by typing `X <return>` (in which case HomeSpan erases its stored WiFi Credentials and restarts).
Next, HomeSpan checks to see if the device has been configured with WiFi Credentials. If none are found, HomeSpan will indicate this, and then complete its initialization routine by indicating is now READY. If WiFi Credentials are found, HomeSpan repeatedly tries to connect to the specified network in the background and informs you of its progress. During this time, any of the commands below will work, including those related to re-configuring or erasing the device's WiFi Credentials.
### Log Levels

View File

@ -96,7 +96,7 @@ void setup() {
Serial.print("\n\nHomeSpan RF Transmitter Example\n\n");
RFControl rf(LED_BUILTIN); // create an instance of RFControl with signal output to the ESP32's Built-In LED
RFControl rf(13); // create an instance of RFControl with signal output to pin 13 on the ESP32
rf.clear(); // clear the pulse train memory buffer

View File

@ -50,7 +50,7 @@ In addition to being able to configure a HomeSpan device using the [HomeSpan CLI
1. a normally-open single-pole pushbutton to function as the HomeSpan Control Button, and
1. an LED to function as the HomeSpan Status LED.
The Control Button should be installed between the HomeSpan Control Pin on the ESP32 and ground. The HomeSpan Control Pin defaults to pin 21, but can be set to any other pin during HomeSpan initializaton (see the [HomeSpan API Reference](Reference.md) for details). The LED can similarly be connected to any pin you specify, but defaults to the LED_BUILTIN pin defined for your ESP32 board, in which case you can use your board's built-in LED and avoid having to install a separate LED.
The Control Button should be installed between the HomeSpan Control Pin on the ESP32 and ground. The HomeSpan Control Pin defaults to pin 21, but can be set to any other pin during HomeSpan initializaton (see the [HomeSpan API Reference](Reference.md) for details). The LED can similarly be connected to any pin you specify, but defaults to pin 13, which for some boards is connected to a built-in LED, thereby saving you the need to install a separate LED.
The use of these two components to configure a standalone HomeSpan device, including starting HomeSpan's temporary WiFi network to configure the device's WiFi Credentials and HomeKit Setup Code, are fully explained in the [HomeSpan User Guide](UserGuide.md).

Binary file not shown.

View File

@ -30,8 +30,8 @@ The following **optional** `homeSpan` methods override various HomeSpan initiali
* sets the ESP32 pin to use for the HomeSpan Control Button (default=21)
* `void setStatusPin(uint8_t pin)`
* sets the ESP32 pin to use for the HomeSpan Status LED (default=LED_BUILTIN)
* sets the ESP32 pin to use for the HomeSpan Status LED (default=13). There is also a corresponding `getStatusPin()` method that returns this pin number
* `void setApSSID(char *ssid)`
* sets the SSID (network name) of the HomeSpan Setup Access Point (default="HomeSpan-Setup")
@ -59,6 +59,7 @@ The following **optional** `homeSpan` methods override various HomeSpan initiali
Creating an instance of this **class** adds a new HAP Accessory to the HomeSpan HAP Database.
* every HomeSpan sketch requires at least one Accessory
* a sketch can contain a maximum of 41 Accessories per sketch (if exceeded, a runtime error will the thrown and the sketch will halt)
* there are no associated methods
* the argument *aid* is optional.

View File

@ -31,8 +31,6 @@ If you are new to HomeSpan and are configuring a new device for the first time,
If you are setting up an existing device that has been previously configured in some unknown fashion, you may want to first perform a [Factory Reset](#factory-reset) to start with a fresh setup.
And if you run into any troubles, see [Troubleshooting](#troubleshooting) for tips and tricks.
Enjoy!
## HomeSpan Device States
@ -49,13 +47,16 @@ If the Status LED blinks twice every 3 seconds, the device is connected to a WiF
#### PAIRED
If the Status LED is steady ON, the device is connected to a local WiFi network and is paired to Apple HomeKit. A device in this state should be fully operational. If not, see [Troubleshooting](#troubleshooting) for potential resolutions to common problems.
If the Status LED is steady ON, the device is connected to a local WiFi network and is paired to Apple HomeKit. A device in this state should be fully operational.
#### CONNECTING
If the Status LED is repeatedly flashing ON for 1 second and then OFF for 1 second, the device is actively seeking to connect to a WiFi network using the WiFi Credentials stored on the device. The device will remain in this state until HomeSpan either successfully connects to a WiFi network, or you cancel the connection process.
If the Status LED is repeatedly flashing ON for 1 second and then OFF for 1 second, the device is actively seeking to connect to a WiFi network using the WiFi Credentials stored on the device. The device will remain in this state until:
* HomeSpan successfully connects to a WiFi network;
* you modify or erase the device's WiFi Credentials and restart HomeSpan via the [Device Configuration Mode](#device-configuration-mode) below;
* you perform a [Factory Reset](#factory-reset).
To cancel the connection process, press and hold the HomeSpan Control Button for 3 seconds, at which point the Status LED should begin to flash rapidly (10 times per second). Upon releasing the Control Button, HomeSpan will erase the WiFi Credentials stored and reboot the device in the **NOWIFI** state.
Note that the Status LED is always active, so if the LED is completely off (not even blinking), the device is not powered!
## Device Configuration Mode
@ -72,7 +73,7 @@ Within Device Configuration Mode you can choose one of five possible Actions:
1. *Launch HomeSpans temporary WiFi network*. HomeSpans temporary WiFi network provides a simple web interface for you to input your home networks WiFi credentials and (optionally) create your own HomeKit Setup Code. See [Setting HomeSpans WiFi Credentials and Setup Code](#setting-homespans-wifi-credentials-and-setup-code) for step-by-step instructions.
1. Unpair the device from Apple HomeKit. Under normal operation, you control the pairing and unpairing of all HomeKit devices from the Home App on your iPhone or Mac. However, there are some circumstances in which a device may need to be manually unpaired. This is typically done by performing a full [Factory Reset](#factory-reset) of the device, but that also deletes your WiFi Credentials. This action allows you to unpair the device while preserving all other device settings. See [Troubleshooting](#troubleshooting) for details.
1. Unpair the device from Apple HomeKit. Under normal operation, you control the pairing and unpairing of all HomeKit devices from the Home App on your iPhone or Mac. However, there are some circumstances in which a device may need to be manually unpaired. This is typically done by performing a full [Factory Reset](#factory-reset) of the device, but that also deletes your WiFi Credentials. This action allows you to unpair the device while preserving all other device settings.
1. *Erase stored WiFi Credentials*. This allows you delete your WiFi Credentials from the device without losing any HomeKit pairing data, after which the device can be set up with new WiFi Credentials.
@ -106,7 +107,7 @@ You can also force a termination of the setup process at any time by pressing an
## Pairing to HomeKit
HomeSpan devices can be paired to Apple HomeKit anytime the device is in the **READYTOPAIR** state. If the device is in the **NOWIFI state**, it must first be connected to your home WiFi network before it can be paired to HomeKit (see [Setting HomeSpans WiFi Credentials and Setup Code](#setting-homespans-wifi-credentials-and-setup-code)). If the device is already in the **PAIRED** state but it is not appearing in HomeKit, you may need to manually unpair the device so it can be re-paired (see [Troubleshooting](#troubleshooting)).
HomeSpan devices can be paired to Apple HomeKit anytime the device is in the **READYTOPAIR** state. If the device is in the **NOWIFI state**, it must first be connected to your home WiFi network before it can be paired to HomeKit (see [Setting HomeSpans WiFi Credentials and Setup Code](#setting-homespans-wifi-credentials-and-setup-code)). If the device is already in the **PAIRED** state but it is not appearing in HomeKit, you may need to manually unpair the device so it can be re-paired.
To reduce the possibility that a bad actor can remotely pair with a HomeKit device and take over control, HomeKit requires the use of a device-specific Setup Code to authorize the pairing process. This unique 8-digit code is not stored on the device itself (to prevent a hacker from extracting the code), but is usually found written on a tag attached to the device. Only someone who has physical access to the tag will know the Setup Code and therefore be able to pair the device to HomeKit.
@ -122,7 +123,7 @@ To start the pairing process, open the Home App on your iPhone, select Add Acces
* If you have modified the Setup Code, and have also created a scannable tag with that code, scan it now.
* If you have modified the Setup Code but have not created a scannable tag, select the option that indicates you cant scan your code, in which case you will be able to type it manually later in the process.
The Home App should next display a list of available HomeKit accessories. Select your HomeSpan device (if does not appear, exit the process and try again. See Troubleshooting for other potential solutions).
The Home App should next display a list of available HomeKit accessories. Select your HomeSpan device (if does not appear, exit the process and try again).
If youve already scanned the Setup Code for this device from a scannable tag, the Home App will begin the pairing process. If not, it will now ask you to enter it manually.
@ -156,11 +157,6 @@ The box can be bigger or smaller as long as you keep the same proportions. For
Note that if you cant find *Scancardium* listed as a font choice in either the *Pages* or *Keynote* font dropdown boxes, select Format → Font → Show Fonts from the menu bar of the *Pages* or *Keynote* application to bring up a list of all installed fonts where you can search for, and select, *Scancardium*.
## Troubleshooting
This section contains potential solutions to common problems.
(coming soon)
---
[↩️](README.md) Back to the Welcome page

Binary file not shown.

View File

@ -23,9 +23,9 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
// How HomeKit Identifies Devices:
@ -39,20 +39,22 @@ struct DEV_Identify : Service::AccessoryInformation {
// There are many ways to implement some form of identification. For an LED, you could blink it one or more times.
// For a LightBulb, you can flash it on and off. For window shade, you could raise and lower it.
// Most commerical devices don't do anything. Because HomeSpan can be used to control many different types of
// device, below we implement a very generic routine that simply blinks the internal LED of the ESP32 the
// number of times specified above. In principle, this code could call a user-defined routine that is different
// for each physcially-attached device (light, shade, fan, etc), but in practice this is overkill.
// device, below we implement a very generic routine that simply blinks the Status LED the number of times specified above.
// In principle, this code could call a user-defined routine that is different for each physcially-attached device (light, shade, fan, etc),
// but in practice this is overkill.
// Note that the blink routine below starts by turning off the built-in LED and then leaves it on once it has blinked
// Note that the blink routine below starts by turning off the Status LED and then leaves it on once it has blinked
// the specified number of times. This is because when HomeSpan starts up if confirms to user that it has connected
// to the WiFi network by turning on the built-in LED. Thus we want to leave it on when blinking is completed.
// to the WiFi network by turning on the Status LED. Thus we want to leave it on when blinking is completed.
// Also note we use the homeSpan.getStatusPin() method to find the pin number associated with the Status LED
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -17,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -17,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -17,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -17,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -7,8 +7,6 @@ struct DEV_Identify : Service::AccessoryInformation {
int nBlinks; // number of times to blink built-in LED in identify routine
SpanCharacteristic *identify; // reference to the Identify Characteristic
// NEW! modified constructor() method to include optional ServiceType argument
DEV_Identify(const char *name, const char *manu, const char *sn, const char *model, const char *version, int nBlinks) : Service::AccessoryInformation(){
@ -19,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -7,8 +7,6 @@ struct DEV_Identify : Service::AccessoryInformation {
int nBlinks; // number of times to blink built-in LED in identify routine
SpanCharacteristic *identify; // reference to the Identify Characteristic
// NEW! modified constructor() method to include optional ServiceType argument
DEV_Identify(const char *name, const char *manu, const char *sn, const char *model, const char *version, int nBlinks) : Service::AccessoryInformation(){
@ -19,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -17,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -17,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -17,17 +17,17 @@ struct DEV_Identify : Service::AccessoryInformation {
new Characteristic::FirmwareRevision(version);
identify=new Characteristic::Identify(); // store a reference to the Identify Characteristic for use below
this->nBlinks=nBlinks; // store the number of times to blink the built-in LED
this->nBlinks=nBlinks; // store the number of times to blink the LED
pinMode(LED_BUILTIN,OUTPUT); // make sure built-in LED is set for output
pinMode(homeSpan.getStatusPin(),OUTPUT); // make sure LED is set for output
}
boolean update(){
for(int i=0;i<nBlinks;i++){
digitalWrite(LED_BUILTIN,LOW);
digitalWrite(homeSpan.getStatusPin(),LOW);
delay(250);
digitalWrite(LED_BUILTIN,HIGH);
digitalWrite(homeSpan.getStatusPin(),HIGH);
delay(250);
}

View File

@ -1,5 +1,5 @@
name=HomeSpan
version=1.1.2
version=1.1.3
author=Gregg <homespan@icloud.com>
maintainer=Gregg <homespan@icloud.com>
sentence=A robust and extremely easy-to-use HomeKit implementation for the Espressif ESP32 running on the Arduino IDE.

View File

@ -1381,10 +1381,18 @@ void HAPClient::sendEncrypted(char *body, uint8_t *dataBuf, int dataLen){
int count=0;
unsigned long long nBytes;
httpBuf[count]=bodyLen%256; // store number of bytes in first frame that encrypts the Body (AAD bytes)
httpBuf[count+1]=bodyLen/256;
int totalBytes=2+bodyLen+16; // 2-byte AAD + bodyLen + 16-byte authentication tag
totalBytes+=(dataLen/FRAME_SIZE)*(2+FRAME_SIZE+16); // number of full frames * size of full frame with 2-byte AAD + 16-byte authentication tag
if(dataLen%FRAME_SIZE) // if there is a residual last partial frame
totalBytes+=2+dataLen%FRAME_SIZE+16; // 2-byte AAD + residual of last partial frame + 16-byte authentication tag
TempBuffer <uint8_t> tBuf(totalBytes);
crypto_aead_chacha20poly1305_ietf_encrypt(httpBuf+count+2,&nBytes,(uint8_t *)body,bodyLen,httpBuf+count,2,NULL,a2cNonce.get(),a2cKey); // encrypt the Body with authentication tag appended
tBuf.buf[count]=bodyLen%256; // store number of bytes in first frame that encrypts the Body (AAD bytes)
tBuf.buf[count+1]=bodyLen/256;
crypto_aead_chacha20poly1305_ietf_encrypt(tBuf.buf+count+2,&nBytes,(uint8_t *)body,bodyLen,tBuf.buf+count,2,NULL,a2cNonce.get(),a2cKey); // encrypt the Body with authentication tag appended
a2cNonce.inc(); // increment nonce
@ -1397,17 +1405,17 @@ void HAPClient::sendEncrypted(char *body, uint8_t *dataBuf, int dataLen){
if(n>FRAME_SIZE) // maximum number of bytes to encrypt=FRAME_SIZE
n=FRAME_SIZE;
httpBuf[count]=n%256; // store number of bytes that encrypts this frame (AAD bytes)
httpBuf[count+1]=n/256;
tBuf.buf[count]=n%256; // store number of bytes that encrypts this frame (AAD bytes)
tBuf.buf[count+1]=n/256;
crypto_aead_chacha20poly1305_ietf_encrypt(httpBuf+count+2,&nBytes,dataBuf+i,n,httpBuf+count,2,NULL,a2cNonce.get(),a2cKey); // encrypt the next portion of dataBuf with authentication tag appended
crypto_aead_chacha20poly1305_ietf_encrypt(tBuf.buf+count+2,&nBytes,dataBuf+i,n,tBuf.buf+count,2,NULL,a2cNonce.get(),a2cKey); // encrypt the next portion of dataBuf with authentication tag appended
a2cNonce.inc(); // increment nonce
count+=2+n+16; // increment count by 2-byte AAD record + length of JSON + 16-byte authentication tag
}
client.write(httpBuf,count); // transmit all encrypted frames to Client
client.write(tBuf.buf,count); // transmit all encrypted frames to Client
LOG2("-------- SENT ENCRYPTED! --------\n");

View File

@ -76,6 +76,7 @@ struct HAPClient {
static const int MAX_HTTP=8095; // max number of bytes in HTTP message buffer
static const int MAX_CONTROLLERS=16; // maximum number of paired controllers (HAP requires at least 16)
static const int MAX_ACCESSORIES=41; // maximum number of allowed Acessories (HAP limit=150, but not enough memory in ESP32 to run that many)
static TLV<kTLVType,10> tlv8; // TLV8 structure (HAP Section 14.1) with space for 10 TLV records of type kTLVType (HAP Table 5-6)
static nvs_handle hapNVS; // handle for non-volatile-storage of HAP data

View File

@ -67,7 +67,7 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
"** Please ensure serial monitor is set to transmit <newlines>\n\n");
Serial.print("Message Logs: Level ");
Serial.print(homeSpan.logLevel);
Serial.print(logLevel);
Serial.print("\nStatus LED: Pin ");
Serial.print(statusPin);
Serial.print("\nDevice Control: Pin ");
@ -82,7 +82,7 @@ void Span::begin(Category catID, const char *displayName, const char *hostNameBa
Serial.print(__TIME__);
Serial.print("\n\nDevice Name: ");
Serial.print(homeSpan.displayName);
Serial.print(displayName);
Serial.print("\n\n");
} // begin
@ -122,11 +122,11 @@ void Span::poll() {
HAPClient::init(); // read NVS and load HAP settings
if(strlen(network.wifiData.ssid)>0){
initWifi();
} else {
Serial.print("*** WIFI CREDENTIALS DATA NOT FOUND -- PLEASE CONFIGURE BY TYPING 'W <RETURN>' OR PRESS CONTROL BUTTON FOR 3 SECONDS TO START ACCESS POINT.\n\n");
if(!strlen(network.wifiData.ssid)){
Serial.print("*** WIFI CREDENTIALS DATA NOT FOUND. YOU MAY CONFIGURE BY TYPING 'W <RETURN>'.\n\n");
statusLED.start(LED_WIFI_NEEDED);
} else {
homeSpan.statusLED.start(LED_WIFI_CONNECTING);
}
controlButton.reset();
@ -137,8 +137,8 @@ void Span::poll() {
} // isInitialized
if(strlen(network.wifiData.ssid)>0 && WiFi.status()!=WL_CONNECTED){
initWifi();
if(strlen(network.wifiData.ssid)>0){
checkConnect();
}
char cBuf[17]="?";
@ -308,7 +308,54 @@ void Span::commandMode(){
//////////////////////////////////////
void Span::initWifi(){
void Span::checkConnect(){
if(connected){
if(WiFi.status()==WL_CONNECTED)
return;
Serial.print("\n\n*** WiFi Connection Lost!\n"); // losing and re-establishing connection has not been tested
connected=false;
waitTime=60000;
alarmConnect=0;
homeSpan.statusLED.start(LED_WIFI_CONNECTING);
}
if(WiFi.status()!=WL_CONNECTED){
if(millis()<alarmConnect) // not yet time to try to try connecting
return;
if(waitTime==60000)
waitTime=1000;
else
waitTime*=2;
if(waitTime==32000){
Serial.print("\n*** Can't connect to ");
Serial.print(network.wifiData.ssid);
Serial.print(". You may type 'W <return>' to re-configure WiFi, or 'X <return>' to erase WiFi credentials. Will try connecting again in 60 seconds.\n\n");
waitTime=60000;
} else {
Serial.print("Trying to connect to ");
Serial.print(network.wifiData.ssid);
Serial.print(". Waiting ");
Serial.print(waitTime/1000);
Serial.print(" second(s) for response...\n");
WiFi.begin(network.wifiData.ssid,network.wifiData.pwd);
}
alarmConnect=millis()+waitTime;
return;
}
connected=true;
Serial.print("Successfully connected to ");
Serial.print(network.wifiData.ssid);
Serial.print("! IP Address: ");
Serial.print(WiFi.localIP());
Serial.print("\n");
char id[18]; // create string version of Accessory ID for MDNS broadcast
memcpy(id,HAPClient::accessory.ID,17); // copy ID bytes
@ -319,54 +366,6 @@ void Span::initWifi(){
int nChars=snprintf(NULL,0,"%s-%.2s%.2s%.2s%.2s%.2s%.2s",hostNameBase,id,id+3,id+6,id+9,id+12,id+15);
char hostName[nChars+1];
sprintf(hostName,"%s-%.2s%.2s%.2s%.2s%.2s%.2s",hostNameBase,id,id+3,id+6,id+9,id+12,id+15);
statusLED.start(LED_WIFI_CONNECTING);
controlButton.reset();
int nTries=0;
Serial.print("Attempting connection to: ");
Serial.print(network.wifiData.ssid);
Serial.print(". Type 'X <return>' or press Control Button for 3 seconds at any time to terminate search and delete WiFi credentials.");
while(WiFi.status()!=WL_CONNECTED){
if(nTries++ == 0)
Serial.print("\nConnecting..");
if(WiFi.begin(network.wifiData.ssid,network.wifiData.pwd)!=WL_CONNECTED){
int delayTime;
char buf[8]="";
if(nTries<=10){
delayTime=2000;
Serial.print(".");
} else {
nTries=0;
delayTime=60000;
Serial.print(" Can't connect! Will re-try in ");
Serial.print(delayTime/1000);
Serial.print(" seconds...");
}
long sTime=millis();
while(millis()-sTime<delayTime){
if(controlButton.triggered(9999,3000)){
Serial.print(" TERMINATED!\n");
statusLED.start(LED_ALERT);
controlButton.wait();
processSerialCommand("X"); // DELETE WiFi Data and Restart
}
if (Serial.available() && readSerial(buf,1) && (buf[0]=='X')){
Serial.print(" TERMINATED!\n");
processSerialCommand("X"); // DELETE WiFi Data and Restart
}
}
}
} // WiFi not yet connected
Serial.print(" Success!\nIP: ");
Serial.print(WiFi.localIP());
Serial.print("\n");
Serial.print("\nStarting MDNS...\n");
Serial.print("Broadcasting as: ");
@ -1062,6 +1061,14 @@ int Span::sprintfAttributes(char **ids, int numIDs, int flags, char *cBuf){
SpanAccessory::SpanAccessory(uint32_t aid){
if(!homeSpan.Accessories.empty()){
if(homeSpan.Accessories.size()==HAPClient::MAX_ACCESSORIES){
Serial.print("\n\n*** FATAL ERROR: Can't create more than ");
Serial.print(HAPClient::MAX_ACCESSORIES);
Serial.print(" Accessories. Program Halting.\n\n");
while(1);
}
this->aid=homeSpan.Accessories.back()->aid+1;
if(!homeSpan.Accessories.back()->Services.empty())

View File

@ -84,6 +84,10 @@ struct Span{
int nFatalErrors=0; // number of fatal errors in user-defined configuration
String configLog; // log of configuration process, including any errors
boolean isBridge=true; // flag indicating whether device is configured as a bridge (i.e. first Accessory contains nothing but AccessoryInformation and HAPProtocolInformation)
boolean connected=false; // WiFi connection status
unsigned long waitTime=60000; // time to wait (in milliseconds) between WiFi connection attempts
unsigned long alarmConnect=0; // time after which WiFi connection attempt should be tried again
const char *defaultSetupCode=DEFAULT_SETUP_CODE; // Setup Code used for pairing
uint8_t statusPin=DEFAULT_STATUS_PIN; // pin for status LED
@ -112,7 +116,7 @@ struct Span{
void poll(); // poll HAP Clients and process any new HAP requests
int getFreeSlot(); // returns free HAPClient slot number. HAPClients slot keep track of each active HAPClient connection
void initWifi(); // initialize and connect to WiFi network
void checkConnect(); // check WiFi connection; connect if needed
void commandMode(); // allows user to control and reset HomeSpan settings with the control button
void processSerialCommand(const char *c); // process command 'c' (typically from readSerial, though can be called with any 'c')
@ -130,6 +134,7 @@ struct Span{
void setControlPin(uint8_t pin){controlPin=pin;} // sets Control Pin
void setStatusPin(uint8_t pin){statusPin=pin;} // sets Status Pin
int getStatusPin(){return(statusPin);} // gets Status Pin
void setApSSID(char *ssid){network.apSSID=ssid;} // sets Access Point SSID
void setApPassword(char *pwd){network.apPassword=pwd;} // sets Access Point Password
void setApTimeout(uint16_t nSec){network.lifetime=nSec*1000;} // sets Access Point Timeout (seconds)

View File

@ -273,11 +273,12 @@ void Network::processRequest(char *body, char *formData){
getFormValue(formData,"network",wifiData.ssid,MAX_SSID);
getFormValue(formData,"pwd",wifiData.pwd,MAX_PWD);
timer=millis();
homeSpan.statusLED.start(LED_WIFI_CONNECTING);
responseBody+="<meta http-equiv = \"refresh\" content = \"2; url = /wifi-status\" />"
responseBody+="<meta http-equiv = \"refresh\" content = \"" + String(waitTime) + "; url = /wifi-status\" />"
"<p>Initiating WiFi connection to:</p><p><b>" + String(wifiData.ssid) + "</p>";
WiFi.begin(wifiData.ssid,wifiData.pwd);
} else
@ -306,12 +307,17 @@ void Network::processRequest(char *body, char *formData){
LOG1("In Get WiFi Status...\n");
if(WiFi.status()!=WL_CONNECTED && WiFi.begin(wifiData.ssid,wifiData.pwd)!=WL_CONNECTED){
responseHead+="Refresh: 5\r\n";
responseBody+="<p>Re-trying connection to:</p><p><b>" + String(wifiData.ssid) + "</p>";
responseBody+="<p>Timeout in " + String((alarmTimeOut-millis())/1000) + " seconds.</p>";
if(WiFi.status()!=WL_CONNECTED){
waitTime+=2;
if(waitTime==12)
waitTime=2;
responseHead+="Refresh: " + String(waitTime) + "\r\n";
responseBody+="<p>Re-initiating connection to:</p><p><b>" + String(wifiData.ssid) + "</b></p>";
responseBody+="<p>(waiting " + String(waitTime) + " seconds to check for response)</p>";
responseBody+="<p>Access Point termination in " + String((alarmTimeOut-millis())/1000) + " seconds.</p>";
responseBody+="<center><button onclick=\"document.location='/hotspot-detect.html'\">Cancel</button></center>";
WiFi.begin(wifiData.ssid,wifiData.pwd);
} else {
homeSpan.statusLED.start(LED_AP_CONNECTED); // slow double-blink
@ -335,6 +341,7 @@ void Network::processRequest(char *body, char *formData){
LOG1("In Landing Page...\n");
homeSpan.statusLED.start(LED_AP_CONNECTED);
waitTime=2;
responseBody+="<p>Welcome to HomeSpan! This page allows you to configure the above HomeSpan device to connect to your WiFi network.</p>"
"<p>The LED on this device should be <em>double-blinking</em> during this configuration.</p>"
@ -391,8 +398,14 @@ int Network::getFormValue(char *formData, const char *tag, char *value, int maxS
int len=0; // track length of value
while(*v!='\0' && *v!='&' && len<maxSize){ // copy the value until null, '&', or maxSize is reached
if(*v=='%'){ // this is an escaped character of form %XX
v++;
sscanf(v,"%2x",value++);
v+=2;
} else {
*value++=*v++;
}
len++;
*value++=*v++;
}
*value='\0'; // add terminating null

View File

@ -50,7 +50,7 @@ struct Network {
int numSSID;
WiFiClient client; // client used for HTTP calls
unsigned long timer; // length of time of trying to connect to WiFi
int waitTime; // time to wait between HTTP refreshed when checking for WiFi connection
unsigned long alarmTimeOut; // alarm time after which access point is shut down and HomeSpan is re-started
int apStatus; // tracks access point status (0=timed-out, -1=cancel, 1=save)

View File

@ -34,7 +34,7 @@
#define HS_MAJOR 1
#define HS_MINOR 1
#define HS_PATCH 2
#define HS_PATCH 3
#define STRINGIFY(x) _STR(x)
#define _STR(x) #x
@ -62,7 +62,7 @@
#define DEFAULT_SETUP_CODE "46637726" // changed during network setup or with 'S' command
#define DEFAULT_CONTROL_PIN 21 // change with homeSpan.setControlPin(pin)
#define DEFAULT_STATUS_PIN LED_BUILTIN // change with homeSpan.setStatusPin(pin)
#define DEFAULT_STATUS_PIN 13 // change with homeSpan.setStatusPin(pin)
#define DEFAULT_AP_SSID "HomeSpan-Setup" // change with homeSpan.setApSSID(pwd)
#define DEFAULT_AP_PASSWORD "homespan" // change with homeSpan.setApPassword(pwd)

View File

@ -48,7 +48,13 @@ struct TempBuffer {
TempBuffer(size_t len){
nBytes=len*sizeof(bufType);
buf=(bufType *)heap_caps_malloc(nBytes,MALLOC_CAP_8BIT);
buf=(bufType *)heap_caps_malloc(nBytes,MALLOC_CAP_8BIT);
if(buf==NULL){
Serial.print("\n\n*** FATAL ERROR: Requested allocation of ");
Serial.print(nBytes);
Serial.print(" bytes failed. Program Halting.\n\n");
while(1);
}
}
~TempBuffer(){

View File

@ -10,7 +10,7 @@ void setup() {
homeSpan.setLogLevel(2);
homeSpan.begin();
homeSpan.begin(Category::Lighting,"HomeSpanTest");
new SpanAccessory(); // Begin by creating a new Accessory using SpanAccessory(), which takes no arguments