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

@@ -1,7 +1,7 @@
/*********************************************************************************
* MIT License
*
* Copyright (c) 2020-2024 Gregg E. Berman
* Copyright (c) 2020-2025 Gregg E. Berman
*
* https://github.com/HomeSpan/HomeSpan
*
@@ -233,6 +233,8 @@ void HAPClient::processRequest(){
} // PUT request
if(!strncmp(body,"GET ",4)){ // this is a GET request
int refreshTime;
if(!strncmp(body,"GET /accessories ",17)) // GET ACCESSORIES
getAccessoriesURL();
@@ -240,8 +242,8 @@ void HAPClient::processRequest(){
else if(!strncmp(body,"GET /characteristics?",21)) // GET CHARACTERISTICS
getCharacteristicsURL(body+21);
else if(homeSpan.webLog.isEnabled && !strncmp(body,homeSpan.webLog.statusURL.c_str(),homeSpan.webLog.statusURL.length())) // GET STATUS - AN OPTIONAL, NON-HAP-R2 FEATURE
getStatusURL(this,NULL,NULL);
else if(homeSpan.webLog.isEnabled && (refreshTime=homeSpan.webLog.check(body+4))>=0) // OPTIONAL (NON-HAP) STATUS REQUEST
getStatusURL(this,NULL,NULL,refreshTime);
else {
notFoundError();
@@ -914,6 +916,9 @@ int HAPClient::getCharacteristicsURL(char *urlBuf){
LOG1("In Get Characteristics #%d (%s)...\n",clientNumber,client.remoteIP().toString().c_str());
if(homeSpan.getCharacteristicsCallback)
homeSpan.getCharacteristicsCallback(urlBuf);
int len=strlen(urlBuf); // determine number of IDs specified by counting commas in URL
int numIDs=1;
for(int i=0;i<len;i++)
@@ -982,17 +987,14 @@ int HAPClient::putCharacteristicsURL(char *json){
LOG1("In Put Characteristics #%d (%s)...\n",clientNumber,client.remoteIP().toString().c_str());
int n=homeSpan.countCharacteristics(json); // count number of objects in JSON request
if(n==0) // if no objects found, return
return(0);
SpanBuf pObj[n]; // reserve space for objects
if(!homeSpan.updateCharacteristics(json, pObj)) // perform update
SpanBufVec pVec;
if(!homeSpan.updateCharacteristics(json, pVec)) // perform update and check for success
return(0); // return if failed to update (error message will have been printed in update)
boolean multiCast=false;
for(int i=0;i<n && !multiCast;i++) // for each characterstic, check if any status is either NOT OKAY, or if WRITE-RESPONSE is requested
if(pObj[i].status!=StatusCode::OK || pObj[i].wr) // if so, to use multicast response
boolean multiCast=false;
for(auto it=pVec.begin();it!=pVec.end() && !multiCast;it++) // for each characteristic, check if any status is either NOT OKAY, or if WRITE-RESPONSE is requested
if((*it).status!=StatusCode::OK || (*it).wr) // if so, must use multicast response
multiCast=true;
LOG2("\n>>>>>>>>>> %s >>>>>>>>>>\n",client.remoteIP().toString().c_str());
@@ -1005,13 +1007,13 @@ int HAPClient::putCharacteristicsURL(char *json){
} else { // multicast respose is required
homeSpan.printfAttributes(pObj,n);
homeSpan.printfAttributes(pVec);
size_t nBytes=hapOut.getSize();
hapOut.flush();
hapOut.setLogLevel(2).setHapClient(this);
hapOut << "HTTP/1.1 207 Multi-Status\r\nContent-Type: application/hap+json\r\nContent-Length: " << nBytes << "\r\n\r\n";
homeSpan.printfAttributes(pObj,n);
homeSpan.printfAttributes(pVec);
hapOut.flush();
}
@@ -1019,7 +1021,7 @@ int HAPClient::putCharacteristicsURL(char *json){
// Create and send Event Notifications if needed
eventNotify(pObj,n,this); // transmit EVENT Notification for "n" pObj objects, except DO NOT notify client making request
eventNotify(pVec,this); // transmit EVENT Notification for objects, except DO NOT notify client making request
return(1);
}
@@ -1043,7 +1045,7 @@ int HAPClient::putPrepareURL(char *json){
uint64_t pid;
if((cBuf=strstr(json,ttlToken)))
sscanf(cBuf+strlen(ttlToken),"%u",&ttl);
sscanf(cBuf+strlen(ttlToken),"%lu",&ttl);
if((cBuf=strstr(json,pidToken)))
sscanf(cBuf+strlen(ttlToken),"%llu",&pid);
@@ -1074,8 +1076,10 @@ int HAPClient::putPrepareURL(char *json){
//////////////////////////////////////
void HAPClient::getStatusURL(HAPClient *hapClient, void (*callBack)(const char *, void *), void *user_data){
void HAPClient::getStatusURL(HAPClient *hapClient, void (*callBack)(const char *, void *), void *user_data, int refreshTime){
std::shared_lock readLock(homeSpan.webLog.mux); // wait for mux to be unlocked, or already locked non-exclusively, and then lock *non-exclusively* to prevent writing in vLog
char clocktime[33];
if(homeSpan.webLog.timeInit){
@@ -1100,8 +1104,12 @@ void HAPClient::getStatusURL(HAPClient *hapClient, void (*callBack)(const char *
hapOut.setHapClient(hapClient).setLogLevel(2).setCallback(callBack).setCallbackUserData(user_data);
if(!callBack)
hapOut << "HTTP/1.1 200 OK\r\nContent-type: text/html; charset=utf-8\r\n\r\n";
if(!callBack){
hapOut << "HTTP/1.1 200 OK\r\nContent-type: text/html; charset=utf-8\r\n";
if(refreshTime>0)
hapOut << "Refresh: " << refreshTime << "\r\n";
hapOut << "\r\n";
}
hapOut << "<html><head><title>" << homeSpan.displayName << "</title>\n";
hapOut << "<style>body {background-color:lightblue;} th, td {padding-right: 10px; padding-left: 10px; border:1px solid black;}" << homeSpan.webLog.css.c_str() << "</style></head>\n";
@@ -1111,51 +1119,26 @@ void HAPClient::getStatusURL(HAPClient *hapClient, void (*callBack)(const char *
hapOut << "<tr><td>Up Time:</td><td>" << uptime << "</td></tr>\n";
hapOut << "<tr><td>Current Time:</td><td>" << clocktime << "</td></tr>\n";
hapOut << "<tr><td>Boot Time:</td><td>" << homeSpan.webLog.bootTime << "</td></tr>\n";
hapOut << "<tr><td>Reset Reason:</td><td>";
switch(esp_reset_reason()) {
case ESP_RST_UNKNOWN:
hapOut << "Cannot be determined";
break;
case ESP_RST_POWERON:
hapOut << "Power-on event";
break;
case ESP_RST_EXT:
hapOut << "External pin";
break;
case ESP_RST_SW:
hapOut << "Software reboot via esp_restart";
break;
case ESP_RST_PANIC:
hapOut << "Software Exception/Panic";
break;
case ESP_RST_INT_WDT:
hapOut << "Interrupt watchdog";
break;
case ESP_RST_TASK_WDT:
hapOut << "Task watchdog";
break;
case ESP_RST_WDT:
hapOut << "Other watchdogs";
break;
case ESP_RST_DEEPSLEEP:
hapOut << "Exiting deep sleep mode";
break;
case ESP_RST_BROWNOUT:
hapOut << "Brownout";
break;
case ESP_RST_SDIO:
hapOut << "SDIO";
break;
default:
hapOut << "Unknown Reset Code";
hapOut << "<tr><td>Reset Reason:</td><td>" << Utils::resetReason() << " (" << esp_reset_reason() << ")</td></tr>\n";
if(homeSpan.compileTime)
hapOut << "<tr><td>Compile Time:</td><td>" << homeSpan.compileTime << "</td></tr>\n";
if(!homeSpan.ethernetEnabled){
hapOut << "<tr><td>WiFi Disconnects:</td><td>" << homeSpan.connected/2 << "</td></tr>\n";
hapOut << "<tr><td>WiFi Signal:</td><td>" << (int)WiFi.RSSI() << " dBm</td></tr>\n";
if(homeSpan.bssidNames.count(WiFi.BSSIDstr().c_str()))
hapOut << "<tr><td>BSSID:</td><td>" << WiFi.BSSIDstr().c_str() << " \"" << homeSpan.bssidNames[WiFi.BSSIDstr().c_str()].c_str() << "\"" << "</td></tr>\n";
else
hapOut << "<tr><td>BSSID:</td><td>" << WiFi.BSSIDstr().c_str() << "</td></tr>\n";
hapOut << "<tr><td>WiFi Local IP:</td><td>" << WiFi.localIP().toString().c_str() << "</td></tr>\n";
hapOut << "<tr><td>WiFi Gateway:</td><td>" << WiFi.gatewayIP().toString().c_str() << "</td></tr>\n";
} else {
hapOut << "<tr><td>Ethernet Disconnects:</td><td>" << homeSpan.connected/2 << "</td></tr>\n";
hapOut << "<tr><td>Ethernet Local IP:</td><td>" << ETH.localIP().toString().c_str() << "</td></tr>\n";
hapOut << "<tr><td>Ethernet Gateway:</td><td>" << ETH.gatewayIP().toString().c_str() << "</td></tr>\n";
}
hapOut << " (" << esp_reset_reason() << ")</td></tr>\n";
hapOut << "<tr><td>WiFi Disconnects:</td><td>" << homeSpan.connected/2 << "</td></tr>\n";
hapOut << "<tr><td>WiFi Signal:</td><td>" << (int)WiFi.RSSI() << " dBm</td></tr>\n";
hapOut << "<tr><td>WiFi Gateway:</td><td>" << WiFi.gatewayIP().toString().c_str() << "</td></tr>\n";
hapOut << "<tr><td>ESP32 Board:</td><td>" << ARDUINO_BOARD << "</td></tr>\n";
hapOut << "<tr><td>Arduino-ESP Version:</td><td>" << ARDUINO_ESP_VERSION << "</td></tr>\n";
hapOut << "<tr><td>ESP-IDF Version:</td><td>" << ESP_IDF_VERSION_MAJOR << "." << ESP_IDF_VERSION_MINOR << "." << ESP_IDF_VERSION_PATCH << "</td></tr>\n";
@@ -1218,9 +1201,9 @@ void HAPClient::getStatusURL(HAPClient *hapClient, void (*callBack)(const char *
void HAPClient::checkNotifications(){
if(!homeSpan.Notifications.empty()){ // if there are Notifications to process
eventNotify(&homeSpan.Notifications[0],homeSpan.Notifications.size()); // transmit EVENT Notifications
homeSpan.Notifications.clear(); // clear Notifications vector
if(!homeSpan.Notifications.empty()){ // if there are Notifications to process
eventNotify(homeSpan.Notifications); // transmit EVENT Notifications
homeSpan.Notifications.clear(); // clear Notifications vector
}
}
@@ -1233,7 +1216,7 @@ void HAPClient::checkTimedWrites(){
auto tw=homeSpan.TimedWrites.begin();
while(tw!=homeSpan.TimedWrites.end()){
if(cTime>tw->second){ // timer has expired
LOG2("Removing PID=%llu ALARM=%u\n",tw->first,tw->second);
LOG2("Removing PID=%llu ALARM=%lu\n",tw->first,tw->second);
tw=homeSpan.TimedWrites.erase(tw);
}
else
@@ -1243,22 +1226,22 @@ void HAPClient::checkTimedWrites(){
//////////////////////////////////////
void HAPClient::eventNotify(SpanBuf *pObj, int nObj, HAPClient *ignore){
void HAPClient::eventNotify(SpanBufVec &pVec, HAPClient *ignore){
for(auto it=homeSpan.hapList.begin(); it!=homeSpan.hapList.end(); ++it){ // loop over all connection slots
if(&(*it)!=ignore){ // if NOT flagged to be ignored (in cases where it is the client making a PUT request)
homeSpan.printfNotify(pObj,nObj,&(*it)); // create JSON (which may be of zero length if there are no applicable notifications for this cNum)
homeSpan.printfNotify(pVec,&(*it)); // create JSON (which may be of zero length if there are no applicable notifications for this cNum)
size_t nBytes=hapOut.getSize();
hapOut.flush();
if(nBytes>0){ // if there ARE notifications to send to client cNum
if(nBytes>0){ // if there ARE notifications to send to client cNum
LOG2("\n>>>>>>>>>> %s >>>>>>>>>>\n",it->client.remoteIP().toString().c_str());
hapOut.setLogLevel(2).setHapClient(&(*it));
hapOut << "EVENT/1.0 200 OK\r\nContent-Type: application/hap+json\r\nContent-Length: " << nBytes << "\r\n\r\n";
homeSpan.printfNotify(pObj,nObj,&(*it));
homeSpan.printfNotify(pVec,&(*it));
hapOut.flush();
LOG2("\n-------- SENT ENCRYPTED! --------\n");
@@ -1555,7 +1538,7 @@ HapOut::HapStreamBuffer::HapStreamBuffer(){
ctx = (mbedtls_sha512_context *)heap_caps_malloc(sizeof(mbedtls_sha512_context),caps); // space for hash context
mbedtls_sha512_init(ctx); // initialize context
mbedtls_sha512_starts_ret(ctx,1); // start SHA-384 hash (note second argument=1)
mbedtls_sha512_starts(ctx,1); // start SHA-384 hash (note second argument=1)
setp(buffer, buffer+bufSize-1); // assign buffer pointers
}
@@ -1607,7 +1590,7 @@ void HapOut::HapStreamBuffer::flushBuffer(){
delay(1);
}
mbedtls_sha512_update_ret(ctx,(uint8_t *)buffer,num); // update hash
mbedtls_sha512_update(ctx,(uint8_t *)buffer,num); // update hash
pbump(-num); // reset buffer pointers
}
@@ -1643,8 +1626,8 @@ int HapOut::HapStreamBuffer::sync(){
callBackUserData=NULL;
}
mbedtls_sha512_finish_ret(ctx,hash); // finish SHA-384 and store hash
mbedtls_sha512_starts_ret(ctx,1); // re-start hash for next time
mbedtls_sha512_finish(ctx,hash); // finish SHA-384 and store hash
mbedtls_sha512_starts(ctx,1); // re-start hash for next time
return(0);
}