diff --git a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.cpp old mode 100644 new mode 100755 similarity index 65% rename from lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c rename to lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.cpp index b82457ca5..db6c3e905 --- a/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.c +++ b/lib/libesp32_div/ESP32-HomeKit/src/hap_platform_keystore.cpp @@ -21,25 +21,169 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ + + #include #include #include +#include #define HAP_PLATFORM_DEF_NVS_PARTITION "nvs" #define HAP_PLATFORM_DEF_FACTORY_NVS_PARTITION "factory_nvs" +extern "C" { + static const char *TAG = "hap_platform_keystore"; -char * hap_platform_keystore_get_nvs_partition_name() -{ +const char * hap_platform_keystore_get_nvs_partition_name() { return HAP_PLATFORM_DEF_NVS_PARTITION; } -char * hap_platform_keystore_get_factory_nvs_partition_name() -{ +const char * hap_platform_keystore_get_factory_nvs_partition_name() { return HAP_PLATFORM_DEF_FACTORY_NVS_PARTITION; } +#define HAP_USE_LITTLEFS + +#ifdef HAP_USE_LITTLEFS + +#include + +extern FS *ffsp; + +int hap_platform_keystore_init_partition(const char *part_name, bool read_only) { + return 0; +} + +int hap_platform_keystore_get(const char *part_name, const char *name_space, const char *key, uint8_t *val, size_t *val_size) { + char path[48]; + strcpy(path, "/"); + strcat(path, part_name); + + File fp = ffsp->open(path, "r"); + if (!fp) { + ffsp->mkdir(path); + return -1; + } + fp.close(); + + strcat(path, "/"); + strcat(path, name_space); + fp = ffsp->open(path, "r"); + if (!fp) { + ffsp->mkdir(path); + return -1; + } + fp.close(); + + strcat(path, "/"); + strcat(path, key); + fp = ffsp->open(path, "r"); + if (fp) { + fp.read(val, *val_size); + fp.close(); + } else { + *val_size = 0; + return -1; + } + return 0; +} + +int hap_platform_keystore_set(const char *part_name, const char *name_space, const char *key, const uint8_t *val, const size_t val_len) { + char path[48]; + strcpy(path, "/"); + strcat(path, part_name); + + File fp = ffsp->open(path, "r"); + if (!fp) { + ffsp->mkdir(path); + } + fp.close(); + + strcat(path, "/"); + strcat(path, name_space); + fp = ffsp->open(path, "r"); + if (!fp) { + ffsp->mkdir(path); + } + fp.close(); + + strcat(path, "/"); + strcat(path, key); + fp = ffsp->open(path, "w"); + if (fp) { + fp.write(val, val_len); + fp.close(); + } else { + return -1; + } + return 0; +} + +int hap_platform_keystore_delete(const char *part_name, const char *name_space, const char *key) { + char path[48]; + strcpy(path, "/"); + strcat(path, part_name); + strcat(path, "/"); + strcat(path, name_space); + strcat(path, "/"); + strcat(path, key); + ffsp->remove(path); + return 0; +} + +// should +int hap_platform_keystore_delete_namespace(const char *part_name, const char *name_space) { + char path[48]; + strcpy(path, "/"); + strcat(path, part_name); + strcat(path, "/"); + strcat(path, name_space); + File fp = ffsp->open(path, "r"); + if (fp.isDirectory()) { + while (true) { + File entry = fp.openNextFile(); + if (!entry) break; + char fp[48]; + strcpy(fp,path); + strcat(fp, "/"); + strcat(fp, entry.name()); + ffsp->remove(fp); + entry.close(); + } + } + return 0; +} + +// last resort only +int hap_platfrom_keystore_erase_partition(const char *part_name) { +// LITTLEFS.format(); +char path[48]; +strcpy(path, "/"); +strcat(path, part_name); +File fp = ffsp->open(path, "r"); +if (fp.isDirectory()) { + while (true) { + File entry = fp.openNextFile(); + if (!entry) break; + char fp[48]; + strcpy(fp,path); + strcat(fp, "/"); + strcat(fp, entry.name()); + if (entry.isDirectory()) { + hap_platform_keystore_delete_namespace(part_name, entry.name()); + ffsp->rmdir(fp); + } else { + ffsp->remove(fp); + } + entry.close(); + } +} + return 0; +} + +#else + #ifdef CONFIG_NVS_ENCRYPTION int hap_platform_keystore_init_partition(const char *part_name, bool read_only) { @@ -185,3 +329,6 @@ int hap_platfrom_keystore_erase_partition(const char *part_name) } return -1; } +#endif // USE_LITTLEFS + +} diff --git a/tasmota/homekit.c b/tasmota/homekit.c index f8bb77e22..44f1dc536 100755 --- a/tasmota/homekit.c +++ b/tasmota/homekit.c @@ -24,6 +24,9 @@ /* HomeKit Smart Outlet Example */ +//#define USE_HOMEKIT + + #ifdef USE_HOMEKIT #ifdef ESP32 @@ -49,6 +52,7 @@ static const char *TAG = "HAP outlet"; char *hk_desc; char hk_code[12]; +uint8_t hk_services; extern void Ext_Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize); extern uint32_t Ext_UpdVar(char *vname, float *fvar, uint32_t mode); @@ -194,6 +198,8 @@ static int sensor_read(hap_char_t *hc, hap_status_t *status_code, void *serv_pri const char *hcp = hap_char_get_type_uuid(hc); + printf("read values %s\n", hcp ); + if (!strcmp(hcp, HAP_CHAR_UUID_CURRENT_TEMPERATURE) || !strcmp(hcp, HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY) || !strcmp(hcp, HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL) @@ -228,6 +234,24 @@ static int sensor_read(hap_char_t *hc, hap_status_t *status_code, void *serv_pri hap_char_update_val(hc, &new_val); *status_code = HAP_STATUS_SUCCESS; } + if (!strcmp(hcp, HAP_CHAR_UUID_BATTERY_LEVEL)) { + Ext_UpdVar(hap_devs[index].var_name, &fvar, 0); + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } + if (!strcmp(hcp, HAP_CHAR_UUID_STATUS_LOW_BATTERY)) { + Ext_UpdVar(hap_devs[index].var2_name, &fvar, 0); + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } + if (!strcmp(hcp, HAP_CHAR_UUID_CHARGING_STATE)) { + Ext_UpdVar(hap_devs[index].var3_name, &fvar, 0); + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + *status_code = HAP_STATUS_SUCCESS; + } return HAP_SUCCESS; } @@ -324,6 +348,7 @@ uint32_t cnt; return cnt; } +float tsim = 20; uint32_t str2c(char **sp, char *vp, uint32_t len) { char *lp = *sp; @@ -440,7 +465,8 @@ static void smart_outlet_thread_entry(void *p) { uint8_t product_data[] = {'E','S','P','3','2','H','A','P'}; hap_acc_add_product_data(hap_devs[index].accessory, product_data, sizeof(product_data)); - int ret = hap_serv_add_char(hap_devs[index].service, hap_char_name_create(hap_devs[index].hap_name)); + int ret; + switch (hap_cfg.cid) { case HAP_CID_LIGHTING: { float fvar = 0; @@ -467,13 +493,22 @@ static void smart_outlet_thread_entry(void *p) { case 0: hap_devs[index].service = hap_serv_temperature_sensor_create(fvar); break; case 1: hap_devs[index].service = hap_serv_humidity_sensor_create(fvar); break; case 2: hap_devs[index].service = hap_serv_light_sensor_create(fvar); break; + case 3: + { float fvar1 = 0, fvar2 = 0; + Ext_UpdVar(hap_devs[index].var2_name, &fvar1, 0); + Ext_UpdVar(hap_devs[index].var3_name, &fvar2, 0); + hap_devs[index].service = hap_serv_battery_service_create(fvar, fvar1, fvar2); + } + break; } } break; + + default: hap_devs[index].service = hap_serv_outlet_create(true, true); } - + hap_serv_add_char(hap_devs[index].service, hap_char_name_create(hap_devs[index].hap_name)); hap_set_read(hap_devs[index].service, index); hap_set_write(hap_devs[index].service, index); @@ -497,7 +532,7 @@ nextline: lp++; } } - + hk_services = index; /* Initialize the appliance specific hardware. This enables out-in-use detection */ smart_outlet_hardware_init(OUTLET_IN_USE_GPIO); @@ -538,7 +573,7 @@ nextline: /* Start Wi-Fi */ //app_wifi_start(portMAX_DELAY); - uint32_t io_num = OUTLET_IN_USE_GPIO; + int32_t io_num = OUTLET_IN_USE_GPIO; if (io_num >= 0) { hap_val_t appliance_value = { .b = true, @@ -561,25 +596,112 @@ nextline: } } } else { - while (1) { + // vTaskDelete(NULL); + // update values every 100 ms + while (1) { + delay(100); + float fvar; + hap_char_t *hc; + hap_val_t new_val; + for (uint32_t cnt = 0; cnt < hk_services; cnt++) { + switch (hap_devs[cnt].hap_cid) { + case HAP_CID_SENSOR: + switch (hap_devs[cnt].type) { + case 0: + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_CURRENT_TEMPERATURE); + if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) { + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + } + break; + case 1: + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_CURRENT_RELATIVE_HUMIDITY); + if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) { + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + } + break; + case 2: + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_CURRENT_AMBIENT_LIGHT_LEVEL); + if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) { + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + } + break; + case 3: + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_BATTERY_LEVEL); + if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) { + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + } + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_STATUS_LOW_BATTERY); + if (Ext_UpdVar(hap_devs[cnt].var2_name, &fvar, 0)) { + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + } + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_STATUS_LOW_BATTERY); + if (Ext_UpdVar(hap_devs[cnt].var3_name, &fvar, 0)) { + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + } + break; + } + break; + case HAP_CID_OUTLET: + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_ON); + if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) { + new_val.b = fvar; + hap_char_update_val(hc, &new_val); + } + break; + case HAP_CID_LIGHTING: + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_ON); + if (Ext_UpdVar(hap_devs[cnt].var_name, &fvar, 0)) { + new_val.b = fvar; + hap_char_update_val(hc, &new_val); + } + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_HUE); + if (Ext_UpdVar(hap_devs[cnt].var2_name, &fvar, 0)) { + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + } + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_SATURATION); + if (Ext_UpdVar(hap_devs[cnt].var3_name, &fvar, 0)) { + new_val.f = fvar; + hap_char_update_val(hc, &new_val); + } + hc = hap_serv_get_char_by_uuid(hap_devs[cnt].service, HAP_CHAR_UUID_BRIGHTNESS); + if (Ext_UpdVar(hap_devs[cnt].var4_name, &fvar, 0)) { + new_val.u = fvar; + hap_char_update_val(hc, &new_val); + } + break; + } } + } } } -#define HK_MAXSIZE 1024 +#define HK_PASSCODE "111-11-111" -void homekit_main(char *desc) { +void homekit_main(char *desc, uint32_t flag ) { if (desc) { char *cp = desc; cp += 2; while (*cp == ' ') cp++; // "111-11-111" - uint32_t cnt; - for (cnt = 0; cnt < 10; cnt++) { - hk_code[cnt] = *cp++; + + if (*cp == '*') { + strlcpy(hk_code, HK_PASSCODE, 10); + cp++; + } else { + uint32_t cnt; + for (cnt = 0; cnt < 10; cnt++) { + hk_code[cnt] = *cp++; + } + hk_code[cnt] = 0; } - hk_code[cnt] = 0; if (*cp != '\n') { printf("init error\n"); return; @@ -587,7 +709,12 @@ void homekit_main(char *desc) { cp++; hk_desc = cp; } else { - hap_platfrom_keystore_erase_partition("nvs"); + if (flag == 99) { + hap_reset_to_factory(); + } else { + // not yet implemented + hap_stop(); + } return; } @@ -595,7 +722,8 @@ void homekit_main(char *desc) { /* Create the application thread */ xTaskCreate(smart_outlet_thread_entry, SMART_OUTLET_TASK_NAME, SMART_OUTLET_TASK_STACKSIZE, NULL, SMART_OUTLET_TASK_PRIORITY, NULL); + } #endif // ESP32 -#endif // USE_HOMEKIT \ No newline at end of file +#endif // USE_HOMEKIT diff --git a/tasmota/xdrv_10_scripter.ino b/tasmota/xdrv_10_scripter.ino index 3c230c8b1..7e34f8102 100755 --- a/tasmota/xdrv_10_scripter.ino +++ b/tasmota/xdrv_10_scripter.ino @@ -56,7 +56,9 @@ keywords if then else endif, or, and are better readable for beginners (others m #define MAXFILT 5 #endif #define SCRIPT_SVARSIZE 20 +#ifndef SCRIPT_MAXSSIZE #define SCRIPT_MAXSSIZE 48 +#endif #define SCRIPT_EOL '\n' #define SCRIPT_FLOAT_PRECISION 2 #define PMEM_SIZE sizeof(Settings.script_pram) @@ -221,7 +223,7 @@ extern FS *ufsp; #endif // USE_UFILESYS -extern "C" void homekit_main(char *); +extern "C" void homekit_main(char *, uint32_t); #ifdef SUPPORT_MQTT_EVENT #include // Import LinkedList library @@ -244,7 +246,7 @@ extern VButton *buttons[MAX_TOUCH_BUTTONS]; #endif typedef union { -#ifdef USE_SCRIPT_GLOBVARS +#if defined(USE_SCRIPT_GLOBVARS) || defined(USE_HOMEKIT) uint16_t data; #else uint8_t data; @@ -260,6 +262,9 @@ typedef union { uint8_t constant : 1; #ifdef USE_SCRIPT_GLOBVARS uint8_t global : 1; +#endif +#ifdef USE_SCRIPT_GLOBVARS + uint8_t hchanged : 1; #endif }; } SCRIPT_TYPE; @@ -490,7 +495,7 @@ void ScriptEverySecond(void) { uint8_t homekit_found = Run_Scripter(">h", -2, 0); if (homekit_found == 99) { if (!TasmotaGlobal.global_state.wifi_down) { - homekit_main(glob_script_mem.section_ptr); + homekit_main(glob_script_mem.section_ptr, 0); glob_script_mem.homekit_running = true; } } @@ -504,6 +509,15 @@ void RulesTeleperiod(void) { if (bitRead(Settings.rule_enabled, 0) && TasmotaGlobal.mqtt_data[0]) Run_Scripter(">T", 2, TasmotaGlobal.mqtt_data); } +void SetChanged(uint32_t index) { + glob_script_mem.type[index].bits.changed = 1; +#ifdef USE_HOMEKIT + glob_script_mem.type[index].bits.hchanged = 1; +#endif +//AddLog(LOG_LEVEL_INFO, PSTR("Change: %d"), index); +} + + #define SCRIPT_SKIP_SPACES while (*lp==' ' || *lp=='\t') lp++; #define SCRIPT_SKIP_EOL while (*lp==SCRIPT_EOL) lp++; @@ -1015,7 +1029,7 @@ void Script_PollUdp(void) { if (res) { // mark changed glob_script_mem.last_udp_ip = glob_script_mem.Script_PortUdp.remoteIP(); - glob_script_mem.type[index].bits.changed = 1; + SetChanged(index); if (glob_script_mem.glob_script == 99) { Run_Scripter(">G", 2, 0); } @@ -2497,14 +2511,16 @@ chknext: #endif //USE_LIGHT #ifdef USE_HOMEKIT - if (!strncmp(vname, "hki", 3)) { + if (!strncmp(vname, "hki(", 4)) { if (!TasmotaGlobal.global_state.wifi_down) { // erase nvs - homekit_main(0); + lp = GetNumericArgument(lp + 4, OPER_EQU, &fvar, gv); + homekit_main(0, fvar); // restart homekit - glob_script_mem.homekit_running = false; + TasmotaGlobal.restart_flag = 2; } - fvar = 0; + lp++; + len = 0; goto exit; } #endif @@ -3568,32 +3584,40 @@ char *ForceStringVar(char *lp, char *dstr) { return lp; } +#ifdef USE_HOMEKIT extern "C" { uint32_t Ext_UpdVar(char *vname, float *fvar, uint32_t mode) { return UpdVar(vname, fvar, mode); } } -uint32_t UpdVar(char *vname, float *fvar, uint32_t mode) { +int32_t UpdVar(char *vname, float *fvar, uint32_t mode) { struct T_INDEX ind; uint8_t vtype; float res = *fvar; + uint8_t index; isvar(vname, &vtype, &ind, fvar, 0, 0); if (vtype != VAR_NV) { // found variable as result if (vtype == NUM_RES || (vtype & STYPE) == 0) { if (mode) { // set var - uint8_t index = glob_script_mem.type[ind.index].index; + index = glob_script_mem.type[ind.index].index; glob_script_mem.fvars[index] = res; - glob_script_mem.type[index].bits.changed = 1; + SetChanged(ind.index); + return 0; + } else { + // get var + //index = glob_script_mem.type[ind.index].index; + int32_t ret = glob_script_mem.type[ind.index].bits.hchanged; + glob_script_mem.type[ind.index].bits.hchanged = 0; + return ret; } - return 0; } else { // break; } } - return 1; + return -1; } @@ -3602,6 +3626,9 @@ extern "C" { Replace_Cmd_Vars(srcbuf, srcsize, dstbuf, dstsize); } } + +#endif // USE_HOMEKIT + // replace vars in cmd %var% void Replace_Cmd_Vars(char *srcbuf, uint32_t srcsize, char *dstbuf, uint32_t dstsize) { char *cp; @@ -4575,7 +4602,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { break; } // var was changed - glob_script_mem.type[globvindex].bits.changed = 1; + SetChanged(globvindex); #ifdef USE_SCRIPT_GLOBVARS if (glob_script_mem.type[globvindex].bits.global) { script_udp_sendvar(varname, dfvar, 0); @@ -4633,7 +4660,7 @@ int16_t Run_script_sub(const char *type, int8_t tlen, struct GVARS *gv) { if (!glob_script_mem.var_not_found) { // var was changed - glob_script_mem.type[globvindex].bits.changed = 1; + SetChanged(globvindex); #ifdef USE_SCRIPT_GLOBVARS if (glob_script_mem.type[globvindex].bits.global) { script_udp_sendvar(varname, 0, str); @@ -5631,7 +5658,7 @@ void Script_Handle_Hue(String *path) { glob_script_mem.fvars[hue_script[index].index[0] - 1] = 1; response.replace("{re", "true"); } - glob_script_mem.type[hue_script[index].vindex[0]].bits.changed = 1; + SetChanged(hue_script[index].vindex[0]); resp = true; } @@ -5647,7 +5674,7 @@ void Script_Handle_Hue(String *path) { response.replace("{cm", "bri"); response.replace("{re", String(tmp)); glob_script_mem.fvars[hue_script[index].index[1] - 1] = bri; - glob_script_mem.type[hue_script[index].vindex[1]].bits.changed = 1; + SetChanged(hue_script[index].vindex[1]); resp = true; } @@ -5670,9 +5697,9 @@ void Script_Handle_Hue(String *path) { response.replace("{cm", "xy"); response.replace("{re", "[" + x_str + "," + y_str + "]"); glob_script_mem.fvars[hue_script[index].index[2]-1] = hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed = 1; + SetChanged(hue_script[index].vindex[2]); glob_script_mem.fvars[hue_script[index].index[3]-1] = sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed = 1; + SetChanged(hue_script[index].vindex[3]); resp = true; } @@ -5688,7 +5715,7 @@ void Script_Handle_Hue(String *path) { response.replace("{cm", "hue"); response.replace("{re", String(tmp)); glob_script_mem.fvars[hue_script[index].index[2] - 1] = hue; - glob_script_mem.type[hue_script[index].vindex[2]].bits.changed = 1; + SetChanged(hue_script[index].vindex[2]); resp = true; } @@ -5703,7 +5730,7 @@ void Script_Handle_Hue(String *path) { response.replace("{cm", "sat"); response.replace("{re", String(tmp)); glob_script_mem.fvars[hue_script[index].index[3] - 1] = sat; - glob_script_mem.type[hue_script[index].vindex[3]].bits.changed = 1; + SetChanged(hue_script[index].vindex[3]); resp = true; } @@ -5716,7 +5743,7 @@ void Script_Handle_Hue(String *path) { response.replace("{cm", "ct"); response.replace("{re", String(ct)); glob_script_mem.fvars[hue_script[index].index[4] - 1] = ct; - glob_script_mem.type[hue_script[index].vindex[4]].bits.changed = 1; + SetChanged(hue_script[index].vindex[4]); resp = true; } response += "]";