Added DATA format
Includes 3 new methods: getData(), getNewData(), and setData()
This commit is contained in:
parent
f3f2c5c4c8
commit
72b4ece64d
|
|
@ -48,7 +48,8 @@ enum FORMAT { // HAP Table 6-5
|
|||
UINT64=4,
|
||||
INT=5,
|
||||
FLOAT=6,
|
||||
STRING=7
|
||||
STRING=7,
|
||||
DATA=8
|
||||
};
|
||||
|
||||
///////////////////////////////
|
||||
|
|
@ -195,6 +196,8 @@ struct HapCharacteristics {
|
|||
HAPCHAR( VolumeSelector, EA, PW, UINT8, true );
|
||||
HAPCHAR( WaterLevel, B5, PR+EV, FLOAT, false );
|
||||
|
||||
HAPCHAR( EveTest, 12345678-079E-48FF-8F27-9C2605A29F52, PW+PR+EV, DATA, false );
|
||||
|
||||
};
|
||||
|
||||
extern HapCharacteristics hapChars;
|
||||
|
|
|
|||
|
|
@ -934,7 +934,7 @@ void Span::processSerialCommand(const char *c){
|
|||
Serial.printf("%s%s",(foundPerms++)?"+":"",pNames[i]);
|
||||
}
|
||||
|
||||
if((*chr)->format!=FORMAT::STRING && (*chr)->format!=FORMAT::BOOL){
|
||||
if((*chr)->format!=FORMAT::STRING && (*chr)->format!=FORMAT::BOOL && (*chr)->format!=FORMAT::DATA){
|
||||
if((*chr)->validValues)
|
||||
Serial.printf(", Valid Values=%s",(*chr)->validValues);
|
||||
else if((*chr)->uvGet<double>((*chr)->stepValue)>0)
|
||||
|
|
@ -1378,7 +1378,7 @@ int Span::updateCharacteristics(char *buf, SpanBuf *pObj){
|
|||
if(status==StatusCode::OK){ // if status is okay
|
||||
pObj[j].characteristic->uvSet(pObj[j].characteristic->value,pObj[j].characteristic->newValue); // update characteristic value with new value
|
||||
if(pObj[j].characteristic->nvsKey){ // if storage key found
|
||||
if(pObj[j].characteristic->format != FORMAT::STRING)
|
||||
if(pObj[j].characteristic->format!=FORMAT::STRING && pObj[j].characteristic->format!=FORMAT::DATA)
|
||||
nvs_set_blob(charNVS,pObj[j].characteristic->nvsKey,&(pObj[j].characteristic->value),sizeof(pObj[j].characteristic->value)); // store data
|
||||
else
|
||||
nvs_set_str(charNVS,pObj[j].characteristic->nvsKey,pObj[j].characteristic->value.STRING); // store data
|
||||
|
|
@ -1771,7 +1771,7 @@ SpanCharacteristic::~SpanCharacteristic(){
|
|||
free(validValues);
|
||||
free(nvsKey);
|
||||
|
||||
if(format==FORMAT::STRING){
|
||||
if(format==FORMAT::STRING || format==FORMAT::DATA){
|
||||
free(value.STRING);
|
||||
free(newValue.STRING);
|
||||
}
|
||||
|
|
@ -1786,7 +1786,7 @@ int SpanCharacteristic::sprintfAttributes(char *cBuf, int flags){
|
|||
|
||||
const char permCodes[][7]={"pr","pw","ev","aa","tw","hd","wr"};
|
||||
|
||||
const char formatCodes[][8]={"bool","uint8","uint16","uint32","uint64","int","float","string"};
|
||||
const char formatCodes[][9]={"bool","uint8","uint16","uint32","uint64","int","float","string","data"};
|
||||
|
||||
nBytes+=snprintf(cBuf,cBuf?64:0,"{\"iid\":%d",iid);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <nvs.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <esp_now.h>
|
||||
#include <mbedtls/base64.h>
|
||||
|
||||
#include "extras/Blinker.h"
|
||||
#include "extras/Pixel.h"
|
||||
|
|
@ -476,6 +477,7 @@ class SpanCharacteristic{
|
|||
sprintf(c,"%g",u.FLOAT);
|
||||
return(String(c));
|
||||
case FORMAT::STRING:
|
||||
case FORMAT::DATA:
|
||||
sprintf(c,"\"%s\"",u.STRING);
|
||||
return(String(c));
|
||||
} // switch
|
||||
|
|
@ -483,7 +485,7 @@ class SpanCharacteristic{
|
|||
}
|
||||
|
||||
void uvSet(UVal &dest, UVal &src){
|
||||
if(format==FORMAT::STRING)
|
||||
if(format==FORMAT::STRING || format==FORMAT::DATA)
|
||||
uvSet(dest,(const char *)src.STRING);
|
||||
else
|
||||
dest=src;
|
||||
|
|
@ -518,6 +520,7 @@ class SpanCharacteristic{
|
|||
u.FLOAT=(double)val;
|
||||
break;
|
||||
case FORMAT::STRING:
|
||||
case FORMAT::DATA:
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
|
@ -540,6 +543,7 @@ class SpanCharacteristic{
|
|||
case FORMAT::FLOAT:
|
||||
return((T) u.FLOAT);
|
||||
case FORMAT::STRING:
|
||||
case FORMAT::DATA:
|
||||
break;
|
||||
}
|
||||
return(0); // included to prevent compiler warnings
|
||||
|
|
@ -560,7 +564,7 @@ class SpanCharacteristic{
|
|||
sprintf(nvsKey,"%04X%08X%03X",t,aid,iid&0xFFF);
|
||||
size_t len;
|
||||
|
||||
if(format != FORMAT::STRING){
|
||||
if(format!=FORMAT::STRING && format!=FORMAT::DATA){
|
||||
if(!nvs_get_blob(homeSpan.charNVS,nvsKey,NULL,&len)){
|
||||
nvs_get_blob(homeSpan.charNVS,nvsKey,&value,&len);
|
||||
}
|
||||
|
|
@ -583,7 +587,7 @@ class SpanCharacteristic{
|
|||
|
||||
uvSet(newValue,value);
|
||||
|
||||
if(format != FORMAT::STRING) {
|
||||
if(format!=FORMAT::STRING && format!=FORMAT::DATA) {
|
||||
uvSet(minValue,min);
|
||||
uvSet(maxValue,max);
|
||||
uvSet(stepValue,0);
|
||||
|
|
@ -643,6 +647,61 @@ class SpanCharacteristic{
|
|||
|
||||
} // setString()
|
||||
|
||||
size_t getData(uint8_t *data, size_t len){
|
||||
if(format!=FORMAT::DATA)
|
||||
return(0);
|
||||
|
||||
size_t olen;
|
||||
int ret=mbedtls_base64_decode(data,len,&olen,(uint8_t *)value.STRING,strlen(value.STRING));
|
||||
|
||||
if(data==NULL)
|
||||
return(olen);
|
||||
|
||||
if(ret==MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
|
||||
Serial.printf("\n*** WARNING: Can't decode Characteristic::%s with getData(). Destination buffer is too small (%d out of %d bytes needed)\n\n",hapName,len,olen);
|
||||
else if(ret==MBEDTLS_ERR_BASE64_INVALID_CHARACTER)
|
||||
Serial.printf("\n*** WARNING: Can't decode Characteristic::%s with getData(). Data is not in base-64 format\n\n",hapName);
|
||||
|
||||
return(olen);
|
||||
}
|
||||
|
||||
size_t getNewData(uint8_t *data, size_t len){
|
||||
if(format!=FORMAT::DATA)
|
||||
return(0);
|
||||
|
||||
size_t olen;
|
||||
int ret=mbedtls_base64_decode(data,len,&olen,(uint8_t *)newValue.STRING,strlen(newValue.STRING));
|
||||
|
||||
if(data==NULL)
|
||||
return(olen);
|
||||
|
||||
if(ret==MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
|
||||
Serial.printf("\n*** WARNING: Can't decode Characteristic::%s with getData(). Destination buffer is too small (%d out of %d bytes needed)\n\n",hapName,len,olen);
|
||||
else if(ret==MBEDTLS_ERR_BASE64_INVALID_CHARACTER)
|
||||
Serial.printf("\n*** WARNING: Can't decode Characteristic::%s with getData(). Data is not in base-64 format\n\n",hapName);
|
||||
|
||||
return(olen);
|
||||
}
|
||||
|
||||
void setData(uint8_t *data, size_t len){
|
||||
|
||||
if((perms & EV) == 0){
|
||||
Serial.printf("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. No NOTIFICATION permission on this characteristic\n\n",hapName);
|
||||
return;
|
||||
}
|
||||
|
||||
if(len<1){
|
||||
Serial.printf("\n*** WARNING: Attempt to update Characteristic::%s with setData() ignored. Size of data buffer must be greater than zero\n\n",hapName);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t olen;
|
||||
mbedtls_base64_encode(NULL,0,&olen,data,len); // get length of string buffer needed (mbedtls includes the trailing null in this size)
|
||||
TempBuffer<char> tBuf(olen); // create temporary string buffer, with room for trailing null
|
||||
mbedtls_base64_encode((uint8_t*)tBuf.buf,olen,&olen,data,len ); // encode data into string buf
|
||||
setString(tBuf.buf); // call setString to continue processing as if characteristic was a string
|
||||
}
|
||||
|
||||
template <typename T> void setVal(T val, boolean notify=true){
|
||||
|
||||
if((perms & EV) == 0){
|
||||
|
|
|
|||
|
|
@ -526,6 +526,8 @@ namespace Characteristic {
|
|||
CREATE_CHAR(uint8_t,VolumeSelector,0,0,1);
|
||||
CREATE_CHAR(double,WaterLevel,0,0,100);
|
||||
|
||||
CREATE_CHAR(const char *,EveTest,"AAAA",0,1);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
|
|
|||
170
src/src.ino
170
src/src.ino
|
|
@ -3,168 +3,42 @@
|
|||
// as well as compile and test from this point. This file is ignored when the library is included in other sketches.
|
||||
|
||||
#include "HomeSpan.h"
|
||||
#include "FeatherPins.h"
|
||||
#include "extras/Pixel.h"
|
||||
#include "extras/RFControl.h"
|
||||
#include "extras/Blinker.h"
|
||||
#include "extras/PwmPin.h"
|
||||
|
||||
|
||||
#define STRING_t const char * // WORK-AROUND
|
||||
|
||||
CUSTOM_CHAR(LightMode, AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA, PR, STRING, "ANY_VALUE", NULL, NULL, true);
|
||||
CUSTOM_CHAR_STRING(DarkMode, AAAAAAAA-BBBB-AAAA-AAAA-AAAAAAAAAAAA, PR, "MY_VALUE");
|
||||
|
||||
SpanPoint *dev1;
|
||||
SpanPoint *dev2;
|
||||
|
||||
struct message_t {
|
||||
char a[32];
|
||||
int b;
|
||||
float c;
|
||||
bool d;
|
||||
} message;
|
||||
Characteristic::EveTest *eveTest;
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
// homeSpan.setLogLevel(2);
|
||||
homeSpan.setControlPin(F25);
|
||||
homeSpan.setStatusPin(F26);
|
||||
// homeSpan.setStatusPin(new LED(F26));
|
||||
|
||||
// new Pixel(F27);
|
||||
homeSpan.setLogLevel(2);
|
||||
homeSpan.begin(Category::Lighting,"HomeSpan LightBulb");
|
||||
|
||||
homeSpan.setHostNameSuffix("-lamp1");
|
||||
homeSpan.setPortNum(1201);
|
||||
// homeSpan.setMaxConnections(6);
|
||||
// homeSpan.setQRID("One1");
|
||||
homeSpan.enableOTA();
|
||||
homeSpan.setSketchVersion("OTA Test 8");
|
||||
homeSpan.setWifiCallback(wifiEstablished);
|
||||
|
||||
homeSpan.setStatusCallback(statusUpdate);
|
||||
|
||||
new SpanUserCommand('d',"- My Description",userCom1);
|
||||
new SpanUserCommand('e',"- My second Description",userCom2);
|
||||
|
||||
// homeSpan.enableAutoStartAP();
|
||||
// homeSpan.setApFunction(myWiFiAP);
|
||||
|
||||
homeSpan.enableWebLog(10,"pool.ntp.org","UTC","myLog"); // creates a web log on the URL /HomeSpan-[DEVICE-ID].local:[TCP-PORT]/myLog
|
||||
|
||||
SpanPoint::setChannelMask(1<<13);
|
||||
|
||||
SpanPoint::setPassword("Hello Thert");
|
||||
|
||||
homeSpan.setLogLevel(1);
|
||||
|
||||
dev2=new SpanPoint("7C:DF:A1:61:E4:A8",sizeof(int),sizeof(message_t));
|
||||
dev1=new SpanPoint("AC:67:B2:77:42:20",sizeof(int),0);
|
||||
|
||||
homeSpan.begin(Category::Lighting,"HomeSpan Lamp Server","homespan");
|
||||
|
||||
new SpanAccessory(); // Begin by creating a new Accessory using SpanAccessory(), which takes no arguments
|
||||
|
||||
new Service::AccessoryInformation(); // HAP requires every Accessory to implement an AccessoryInformation Service, which has 6 required Characteristics
|
||||
new Characteristic::Name("HomeSpan Test"); // Name of the Accessory, which shows up on the HomeKit "tiles", and should be unique across Accessories
|
||||
new Characteristic::Manufacturer("HomeSpan"); // Manufacturer of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::SerialNumber("HSL-123"); // Serial Number of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::Model("HSL Test"); // Model of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::FirmwareRevision(HOMESPAN_VERSION); // Firmware of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::Identify(); // Create the required Identify
|
||||
|
||||
new Service::HAPProtocolInformation(); // Create the HAP Protcol Information Service
|
||||
new Characteristic::Version("1.1.0"); // Set the Version Characteristic to "1.1.0" as required by HAP
|
||||
new SpanAccessory();
|
||||
|
||||
new Service::AccessoryInformation();
|
||||
new Characteristic::Identify();
|
||||
|
||||
new Service::LightBulb();
|
||||
new Characteristic::On(0);
|
||||
new Characteristic::LightMode("HELLO");
|
||||
new Characteristic::DarkMode();
|
||||
new Characteristic::Brightness(50);
|
||||
new Characteristic::Name("Light 1");
|
||||
new Characteristic::ColorTemperature();
|
||||
new Characteristic::Active();
|
||||
new Characteristic::On();
|
||||
new Characteristic::ConfiguredName();
|
||||
eveTest=new Characteristic::EveTest();
|
||||
|
||||
|
||||
new Service::LightBulb();
|
||||
new Characteristic::On(0,true);
|
||||
(new Characteristic::Brightness())->setRange(10,100,5);
|
||||
new Characteristic::Name("Light 2");
|
||||
uint8_t x[]={0x01,0x26,0xFF,0x01,0x26,0xFF};
|
||||
eveTest->setData(x,6);
|
||||
uint8_t y[6]={0};
|
||||
int n=eveTest->getData(y,10);
|
||||
Serial.printf("%d:",n);
|
||||
for(int i=0;i<n;i++)
|
||||
Serial.printf(" %02X",y[i]);
|
||||
Serial.printf("\n\n");
|
||||
|
||||
|
||||
new SpanAccessory(); // Begin by creating a new Accessory using SpanAccessory(), which takes no arguments
|
||||
|
||||
new Service::AccessoryInformation(); // HAP requires every Accessory to implement an AccessoryInformation Service, which has 6 required Characteristics
|
||||
new Characteristic::Name("HomeSpan Test"); // Name of the Accessory, which shows up on the HomeKit "tiles", and should be unique across Accessories
|
||||
new Characteristic::Manufacturer("HomeSpan"); // Manufacturer of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::SerialNumber("HSL-123"); // Serial Number of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::Model("HSL Test"); // Model of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::FirmwareRevision(HOMESPAN_VERSION); // Firmware of the Accessory (arbitrary text string, and can be the same for every Accessory)
|
||||
new Characteristic::Identify(); // Create the required Identify
|
||||
|
||||
new Service::HAPProtocolInformation(); // Create the HAP Protcol Information Service
|
||||
new Characteristic::Version("1.1.0"); // Set the Version Characteristic to "1.1.0" as required by HAP
|
||||
|
||||
new Service::LightBulb();
|
||||
new Characteristic::On(0,true);
|
||||
(new Characteristic::Brightness(50,true))->setRange(10,100,5);
|
||||
new Characteristic::Name("Light 3");
|
||||
new Characteristic::TargetPosition();
|
||||
new Characteristic::OzoneDensity();
|
||||
(new Characteristic::OzoneDensity())->addPerms(PW|AA)->removePerms(EV|PR);
|
||||
|
||||
} // end of setup()
|
||||
|
||||
unsigned long alarmTime=0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void loop(){
|
||||
|
||||
homeSpan.poll();
|
||||
// if(dev1->get(&message))
|
||||
// Serial.printf("DEV1: '%s' %d %f %d\n",message.a,message.b,message.c,message.d);
|
||||
// if(dev2->get(&message))
|
||||
// Serial.printf("DEV2: '%s' %d %f %d\n",message.a,message.b,message.c,message.d);
|
||||
//
|
||||
// if(millis()-alarmTime>5000){
|
||||
// alarmTime=millis();
|
||||
// boolean success = dev2->send(&alarmTime);
|
||||
// Serial.printf("Success = %d\n",success);
|
||||
// }
|
||||
|
||||
} // end of loop()
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void myWiFiAP(){
|
||||
Serial.print("Calling My WIFI AP\n\n");
|
||||
homeSpan.setWifiCredentials("MY_NETWORK","MY_PASSWORD");
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void wifiEstablished(){
|
||||
Serial.print("IN CALLBACK FUNCTION\n\n");
|
||||
Serial.printf("MODE = %d\n",WiFi.getMode());
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void userCom1(const char *v){
|
||||
Serial.printf("In User Command 1: '%s'\n\n",v);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void userCom2(const char *v){
|
||||
Serial.printf("In User Command 2: '%s'\n\n",v);
|
||||
}
|
||||
|
||||
//////////////////////////////////////
|
||||
|
||||
void statusUpdate(HS_STATUS status){
|
||||
Serial.printf("\n*** HOMESPAN STATUS CHANGE: %s\n",homeSpan.statusString(status));
|
||||
homeSpan.poll(); // run HomeSpan!
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue