#include "../new_common.h" #include "http_fns.h" #include "../new_pins.h" #include "../new_cfg.h" #include "../ota/ota.h" // Commands register, execution API and cmd tokenizer #include "../cmnds/cmd_public.h" #include "../driver/drv_tuyaMCU.h" #include "../driver/drv_public.h" #include "../hal/hal_wifi.h" #include "../hal/hal_pins.h" #include "../hal/hal_flashConfig.h" #include "../logging/logging.h" #include "../devicegroups/deviceGroups_public.h" #include "../mqtt/new_mqtt.h" #include "hass.h" #include "../cJSON/cJSON.h" #ifdef WINDOWS // nothing #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 #elif PLATFORM_XR809 #include #elif defined(PLATFORM_BK7231N) // tuya-iotos-embeded-sdk-wifi-ble-bk7231n/sdk/include/tuya_hal_storage.h #include "tuya_hal_storage.h" #include "BkDriverFlash.h" #else // REALLY? A typo in Tuya SDK? Storge? // tuya-iotos-embeded-sdk-wifi-ble-bk7231t/platforms/bk7231t/tuya_os_adapter/include/driver/tuya_hal_storge.h #include "tuya_hal_storge.h" #include "BkDriverFlash.h" #endif /* function send_ha_disc(){ var xhr = new XMLHttpRequest(); xhr.open("GET", "/ha_discovery?prefix="+document.getElementById("ha_disc_topic").value, false); xhr.onload = function() { if (xhr.status === 200) { alert("MQTT discovery queued"); } else if (xhr.status === 404) { alert("Error invoking ha_discovery"); } } xhr.onerror = function() { alert("Error invoking ha_discovery"); } xhr.send(); } */ const char HomeAssistantDiscoveryScript[] = ""; typedef struct template_s { void (*setter)(); const char *name; } template_t; template_t g_templates [] = { { Setup_Device_Empty, "Empty"}, // BK7231N devices { Setup_Device_BK7231N_CB2S_QiachipSmartSwitch, "[BK7231N][CB2S] QiaChip Smart Switch"}, { Setup_Device_BK7231N_KS_602_TOUCH, "[BK7231N] KS 602 Touch Switch US"}, { Setup_Device_Aubess_Mini_Smart_Switch_16A, "[BK7231N] Aubess Mini Smart Switch 16A"}, // BK7231T devices { Setup_Device_BK7231T_WB2S_QiachipSmartSwitch, "[BK7231T][WB2S] QiaChip Smart Switch"}, { Setup_Device_TuyaWL_SW01_16A, "WL SW01 16A"}, { Setup_Device_TuyaSmartLife4CH10A, "Smart Life 4CH 10A"}, { Setup_Device_IntelligentLife_NF101A, "Intelligent Life NF101A"}, { Setup_Device_TuyaLEDDimmerSingleChannel, "Tuya LED Dimmer Single Channel PWM WB3S"}, { Setup_Device_CalexLEDDimmerFiveChannel, "Calex RGBWW LED Dimmer Five Channel PWM BK7231S"}, { Setup_Device_CalexPowerStrip_900018_1v1_0UK, "Calex UK power strip 900018.1 v1.0 UK"}, { Setup_Device_ArlecCCTDownlight, "Arlec CCT LED Downlight ALD029CHA"}, { Setup_Device_NedisWIFIPO120FWT_16A, "Nedis WIFIPO120FWT SmartPlug 16A"}, { Setup_Device_NedisWIFIP130FWT_10A, "Nedis WIFIP130FWT SmartPlug 10A"}, { Setup_Device_BK7231T_Raw_PrimeWiFiSmartOutletsOutdoor_CCWFIO232PK, "Prime SmartOutlet Outdoor 2x Costco"}, { Setup_Device_EmaxHome_EDU8774, "Emax Home EDU8774 SmartPlug 16A"}, { Setup_Device_BK7231N_TuyaLightBulb_RGBCW_5PWMs, "Tuya E27 LED RGBCW 5PWMs BK7231N"}, { Setup_Device_TuyaSmartPFW02G, "Tuya Smart PFW02-G"}, { Setup_Device_AvatarASL04, "Avatar ASL04 5v LED strip"}, { Setup_Device_BL602_MagicHome_IR_RGB_LedStrip, "BL602 Magic Home LED RGB IR Strip"}, { Setup_Device_BL602_MagicHome_CCT_LedStrip, "BL602 Magic Home LED CCT Strip"}, { Setup_Device_Sonoff_MiniR3, "Sonoff MiniR3"}, { Setup_Device_WiFi_DIY_Switch_WB2S_ZN268131, "WB2S WiFi DIY Switch ZN268131"}, { Setup_Device_DS_102_1Gang_WB3S, "DS-102 1 Gang Switch"}, { Setup_Device_DS_102_2Gang_WB3S, "DS-102 2 Gang Switch"}, { Setup_Device_DS_102_3Gang_WB3S, "DS-102 3 Gang Switch"}, { Setup_Device_TuyaSmartWIFISwith_4Gang_CB3S, "[BK7231N][CB3S] Tuya Smart Wifi Switch 4 Gang"}, { Setup_Device_BK7231N_CB2S_LSPA9_BL0942, "[BK7231N][CB2S] LSPA9 power metering plug BL0942 version"}, { Setup_Device_LSC_Smart_Connect_Plug_CB2S, "[BK7231N][CB2S] LSC Smart Connect Plug"}, { Setup_Device_BK7231T_Gosund_Switch_SW5_A_V2_1, "BK7231T Gosund Smart Switch SW5-A-V2.1"}, { Setup_Device_13A_Socket_CB2S, "BK7231N CB2S 13A Aliexpress socket"}, { Setup_Device_Deta_Smart_Double_Power_Point_6922HA_Series2, "BK7231T DETA SMART Double Power Point 6922HA-Series 2"}, { Setup_Device_ArlecRGBCCTDownlight, "Arlec RGB+CCT LED Downlight ALD092RHA"}, { Setup_Device_CasaLifeCCTDownlight, "CasaLife CCT LED Downlight SMART-AL2017-TGTS"}, { Setup_Device_Enbrighten_WFD4103, "Enbrighten WFD4103 WiFi Switch BK7231T WB2S"} , { Setup_Device_Zemismart_Light_Switch_KS_811_3, "Zemismart Light Switch (Neutral Optional) KS_811_3"} , { Setup_Device_TeslaSmartPlus_TSL_SPL_1, "Tesla Smart Plug. Model: (TSL-SPL-1)"} }; int g_total_templates = sizeof(g_templates)/sizeof(g_templates[0]); unsigned char hexdigit( char hex ) { return (hex <= '9') ? hex - '0' : toupper((unsigned char)hex) - 'A' + 10 ; } unsigned char hexbyte( const char* hex ) { return (hexdigit(*hex) << 4) | hexdigit(*(hex+1)) ; } int http_fn_empty_url(http_request_t *request) { poststr(request,"HTTP/1.1 302 OK\nLocation: /index\nConnection: close\n\n"); poststr(request, NULL); return 0; } void postFormAction(http_request_t *request, char *action, char *value){ //"
" hprintf128(request,"
", action, value); } /// @brief Generate a pair of label and field elements. /// @param request /// @param label /// @param fieldId This also gets used as the field name /// @param value /// @param preContent void add_label_input(http_request_t *request, char *inputType, char *label, char *fieldId, const char *value, char *preContent){ if (strlen(preContent) > 0){ poststr(request, preContent); } //These individual strings should be less than 256 .. yes hprintf128 uses 256 char buffer hprintf128(request, "
", fieldId, label); hprintf128(request, "", inputType, fieldId, fieldId, value); } /// @brief Generates a pair of label and text field elements. /// @param request /// @param label Label for the field /// @param fieldId Field id, this also gets used as the name /// @param value String value /// @param preContent Content before the label void add_label_text_field(http_request_t *request, char *label, char *fieldId, const char *value, char *preContent){ add_label_input(request, "text", label, fieldId, value, preContent); } /// @brief Generate a pair of label and numeric field elements. /// @param request /// @param label Label for the field /// @param fieldId Field id, this also gets used as the name /// @param value Integer value /// @param preContent Content before the label void add_label_numeric_field(http_request_t *request, char *label, char *fieldId, int value, char *preContent){ char strValue[32]; sprintf(strValue, "%i", value); add_label_input(request, "number", label, fieldId, strValue, preContent); } int http_fn_testmsg(http_request_t *request) { poststr(request,"This is just a test msg\n\n"); poststr(request, NULL); return 0; } int http_fn_index(http_request_t *request) { int j, i; char tmpA[128]; int bRawPWMs; int forceShowRGBCW; bRawPWMs = CFG_HasFlag(OBK_FLAG_LED_RAWCHANNELSMODE); forceShowRGBCW = CFG_HasFlag(OBK_FLAG_LED_FORCESHOWRGBCWCONTROLLER); // use ?state URL parameter to only request current state if(!http_getArg(request->url, "state", tmpA, sizeof(tmpA))) { http_setup(request, httpMimeTypeHTML); http_html_start(request, NULL); poststr(request, "
"); if(http_getArg(request->url,"tgl",tmpA,sizeof(tmpA))) { j = atoi(tmpA); if(j == SPECIAL_CHANNEL_LEDPOWER) { hprintf128(request,"

Toggled LED power!

",j); } else { hprintf128(request,"

Toggled %i!

",j); } CHANNEL_Toggle(j); } if(http_getArg(request->url,"on",tmpA,sizeof(tmpA))) { j = atoi(tmpA); hprintf128(request,"

Enabled %i!

",j); CHANNEL_Set(j,255,1); } if(http_getArg(request->url,"rgb",tmpA,sizeof(tmpA))) { hprintf128(request,"

Set RGB to %s!

",tmpA); LED_SetBaseColor(0,"led_basecolor",tmpA,0); } if(http_getArg(request->url,"off",tmpA,sizeof(tmpA))) { j = atoi(tmpA); hprintf128(request,"

Disabled %i!

",j); CHANNEL_Set(j,0,1); } if(http_getArg(request->url,"pwm",tmpA,sizeof(tmpA))) { int newPWMValue = atoi(tmpA); http_getArg(request->url,"pwmIndex",tmpA,sizeof(tmpA)); j = atoi(tmpA); if(j == SPECIAL_CHANNEL_TEMPERATURE) { hprintf128(request,"

Changed Temperature to %i!

",newPWMValue); } else { hprintf128(request,"

Changed pwm %i to %i!

",j,newPWMValue); } CHANNEL_Set(j,newPWMValue,1); } if(http_getArg(request->url,"dim",tmpA,sizeof(tmpA))) { int newDimmerValue = atoi(tmpA); http_getArg(request->url,"dimIndex",tmpA,sizeof(tmpA)); j = atoi(tmpA); if(j == SPECIAL_CHANNEL_BRIGHTNESS) { hprintf128(request,"

Changed LED brightness to %i!

",newDimmerValue); } else { hprintf128(request,"

Changed dimmer %i to %i!

",j,newDimmerValue); } CHANNEL_Set(j,newDimmerValue,1); } if(http_getArg(request->url,"set",tmpA,sizeof(tmpA))) { int newSetValue = atoi(tmpA); http_getArg(request->url,"setIndex",tmpA,sizeof(tmpA)); j = atoi(tmpA); hprintf128(request,"

Changed channel %i to %i!

",j,newSetValue); CHANNEL_Set(j,newSetValue,1); } if(http_getArg(request->url,"restart",tmpA,sizeof(tmpA))) { poststr(request,"
Module will restart soon
"); RESET_ScheduleModuleReset(3); } poststr(request, "
"); // end div#change poststr(request, "
"); // replaceable content follows } poststr(request, ""); for (i = 0; i < CHANNEL_MAX; i++) { int channelType; channelType = CHANNEL_GetType(i); if (h_isChannelRelay(i) || channelType == ChType_Toggle) { if (i <= 1) { hprintf128(request, ""); } if (CHANNEL_Check(i)) { poststr(request, ""); } else { poststr(request, ""); } if (i == CHANNEL_MAX - 1) { poststr(request, ""); } } } poststr(request, "
ONOFF
"); poststr(request, ""); for(i = 0; i < CHANNEL_MAX; i++) { int channelType; channelType = CHANNEL_GetType(i); if(channelType == ChType_Temperature) { int iValue; iValue = CHANNEL_Get(i); poststr(request, ""); } else if(channelType == ChType_Temperature_div10) { int iValue; float fValue; iValue = CHANNEL_Get(i); fValue = iValue * 0.1f; poststr(request, ""); } else if(channelType == ChType_Humidity) { int iValue; iValue = CHANNEL_Get(i); poststr(request, ""); } else if(channelType == ChType_Humidity_div10) { int iValue; float fValue; iValue = CHANNEL_Get(i); fValue = iValue * 0.1f; poststr(request, ""); } else if(channelType == ChType_LowMidHigh) { const char *types[]={"Low","Mid","High"}; int iValue; iValue = CHANNEL_Get(i); poststr(request, ""); } else if(channelType == ChType_OffLowMidHigh || channelType == ChType_OffLowestLowMidHighHighest || channelType == ChType_LowestLowMidHighHighest) { const char **types; const char *types4[] = {"Off","Low","Mid","High"}; const char *types6[] = {"Off", "Lowest", "Low", "Mid", "High", "Highest"}; const char *types5NoOff[] = { "Lowest", "Low", "Mid", "High", "Highest"}; int numTypes; int iValue; if(channelType == ChType_OffLowMidHigh) { types = types4; numTypes = 4; } else if(channelType == ChType_LowestLowMidHighHighest) { types = types5NoOff; numTypes = 5; } else { types = types6; numTypes = 6; } iValue = CHANNEL_Get(i); poststr(request, ""); } else if(channelType == ChType_TextField) { int iValue; iValue = CHANNEL_Get(i); poststr(request, ""); } else if(channelType == ChType_ReadOnly) { int iValue; iValue = CHANNEL_Get(i); poststr(request, ""); } else if (h_isChannelRelay(i) || channelType == ChType_Toggle) { if (i <= 1) { hprintf128(request, ""); } const char *c; if(CHANNEL_Check(i)) { c = "bgrn"; } else { c = "bred"; } poststr(request,"",c,i); if (i == CHANNEL_MAX-1) { poststr(request, ""); } } else if((bRawPWMs&&h_isChannelPWM(i)) || (channelType == ChType_Dimmer)) { // PWM and dimmer both use a slider control const char *inputName = h_isChannelPWM(i) ? "pwm" : "dim"; int pwmValue; pwmValue = CHANNEL_Get(i); poststr(request, ""); } } if(bRawPWMs == 0 || forceShowRGBCW) { int c_pwms; int lm; lm = LED_GetMode(); c_pwms = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n); if(forceShowRGBCW) { c_pwms = 5; } if(c_pwms > 0) { const char *c; if(CHANNEL_Check(SPECIAL_CHANNEL_LEDPOWER)) { c = "bgrn"; } else { c = "bred"; } poststr(request, ""); } if(c_pwms > 0) { int pwmValue; const char *inputName; inputName = "dim"; pwmValue = LED_GetDimmer(); poststr(request, ""); } if(c_pwms >= 3) { char colorValue[16]; const char *inputName = "rgb"; const char *activeStr = ""; if(lm == Light_RGB) { activeStr = "[ACTIVE]"; } LED_GetBaseColorString(colorValue); poststr(request, ""); } if(c_pwms == 2 || c_pwms == 5) { // TODO: temperature slider int pwmValue; const char *inputName; const char *activeStr = ""; if(lm == Light_Temperature) { activeStr = "[ACTIVE]"; } inputName = "pwm"; pwmValue = LED_GetTemperature(); poststr(request, ""); } } poststr(request, "
"); hprintf128(request,"Temperature Channel %i value %i C
",i, iValue); poststr(request, "
"); hprintf128(request,"Temperature Channel %i value %f C
",i, fValue); poststr(request, "
"); hprintf128(request,"Humidity Channel %i value %i Percent
",i, iValue); poststr(request, "
"); hprintf128(request,"Humidity Channel %i value %f Percent
",i, fValue); poststr(request, "
"); hprintf128(request,"

Select speed:

"); hprintf128(request,"",i); for(j = 0; j < 3; j++) { const char *check; if(j == iValue) check = "checked"; else check = ""; hprintf128(request,"%s",j,check,types[j]); } hprintf128(request,"
"); poststr(request, "
"); hprintf128(request,"

Select speed:

"); hprintf128(request,"",i); for(j = 0; j < numTypes; j++) { const char *check; if(j == iValue) check = "checked"; else check = ""; hprintf128(request,"%s",j,check,types[j]); } hprintf128(request,"
"); poststr(request, "
"); hprintf128(request,"

Change channel %i value:

",i); hprintf128(request,"",i); hprintf128(request,"",iValue); hprintf128(request,"
"); hprintf128(request,""); poststr(request, "
"); hprintf128(request,"Channel %i = %i",i,iValue); poststr(request, "
"); hprintf128(request,"",i); hprintf128(request,"
"); hprintf128(request,"
",i); hprintf128(request,"",inputName,i,pwmValue); hprintf128(request,"",inputName,i); hprintf128(request,"
",i); poststr(request, "
"); poststr(request,"
"); hprintf128(request,"",SPECIAL_CHANNEL_LEDPOWER); hprintf128(request,"
",c); poststr(request, "
"); hprintf128(request,"
LED Dimmer/Brightness
"); hprintf128(request,"
",SPECIAL_CHANNEL_BRIGHTNESS); hprintf128(request,"",inputName,SPECIAL_CHANNEL_BRIGHTNESS,pwmValue); hprintf128(request,"",inputName,SPECIAL_CHANNEL_BRIGHTNESS); hprintf128(request,"
",SPECIAL_CHANNEL_BRIGHTNESS); poststr(request, "
"); hprintf128(request,"
LED RGB Color %s
",activeStr); hprintf128(request,"
",SPECIAL_CHANNEL_BASECOLOR); hprintf128(request,"",inputName,SPECIAL_CHANNEL_BASECOLOR,colorValue); hprintf128(request,"",inputName,SPECIAL_CHANNEL_BASECOLOR); hprintf128(request,"
"); poststr(request, "
"); hprintf128(request,"
LED Temperature Slider %s (cur=%i, min=%i, max=%i) (Cold <--- ---> Warm)
",activeStr,pwmValue,HASS_TEMPERATURE_MIN,HASS_TEMPERATURE_MAX); hprintf128(request,"
",SPECIAL_CHANNEL_TEMPERATURE); hprintf128(request,"",inputName,SPECIAL_CHANNEL_TEMPERATURE,pwmValue); hprintf128(request,"",inputName,SPECIAL_CHANNEL_TEMPERATURE); hprintf128(request,"
",SPECIAL_CHANNEL_TEMPERATURE); poststr(request, "
"); #ifndef OBK_DISABLE_ALL_DRIVERS DRV_AppendInformationToHTTPIndexPage(request); #endif if(1) { int bFirst = true; hprintf128(request,"
"); for(i = 0; i < CHANNEL_MAX; i++) { if(CHANNEL_IsInUse(i)) { int value = CHANNEL_Get(i); if(bFirst == false) { hprintf128(request,", "); } hprintf128(request,"Channel %i = %i",i,value); bFirst = false; } } hprintf128(request,"
"); } hprintf128(request,"
Cfg size: %i, change counter: %i, ota counter: %i, boot incompletes %i (might change to 0 if you wait to 30 sec)!
", sizeof(g_cfg),g_cfg.changeCounter,g_cfg.otaCounter,Main_GetLastRebootBootFailures()); hprintf128(request,"
Ping watchdog - %i lost, %i ok!
", PingWatchDog_GetTotalLost(),PingWatchDog_GetTotalReceived()); hprintf128(request,"
MQTT State: %s RES: %d(%s)
", (Main_HasMQTTConnected()==1)?"connected":"disconnected", MQTT_GetConnectResult(), get_error_name(MQTT_GetConnectResult()) ); hprintf128(request,"MQTT ErrMsg: %s
", (MQTT_GetStatusMessage()!=NULL)?MQTT_GetStatusMessage():""); hprintf128(request,"MQTT Stats:CONN: %d PUB: %d RECV: %d ERR: %d
", MQTT_GetConnectEvents(), MQTT_GetPublishEventCounter(), MQTT_GetReceivedEventCounter(), MQTT_GetPublishErrorCounter()); // for normal page loads, show the rest of the HTML if(!http_getArg(request->url,"state",tmpA,sizeof(tmpA))) { poststr(request, "
"); // end div#state // Shared UI elements poststr(request, "
"); poststr(request, "
" "" "" "
"); poststr(request, "
"); poststr(request, "
"); poststr(request, htmlFooterRefreshLink); http_html_end(request); // refresh status section every 3 seconds poststr( request, "" ); } poststr(request, NULL); return 0; } int http_fn_about(http_request_t *request){ http_setup(request, httpMimeTypeHTML); http_html_start(request, "About"); poststr(request,"

Open source firmware for BK7231N, BK7231T, XR809 and BL602 by OpenSHWProjects

"); poststr(request,htmlFooterReturnToMenu); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_mqtt(http_request_t *request) { http_setup(request, httpMimeTypeHTML); http_html_start(request, "MQTT"); poststr(request,"

Use this to connect to your MQTT

"); add_label_text_field(request, "Host", "host", CFG_GetMQTTHost(), "
"); add_label_numeric_field(request, "Port", "port", CFG_GetMQTTPort(), "
"); add_label_text_field(request, "Client", "client", CFG_GetMQTTClientId(), "

"); add_label_text_field(request, "User", "user", CFG_GetMQTTUserName(), "
"); add_label_text_field(request, "Password", "password", CFG_GetMQTTPass(), "
"); poststr(request,"
\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_mqtt_set(http_request_t *request) { char tmpA[128]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Saving MQTT"); if(http_getArg(request->url,"host",tmpA,sizeof(tmpA))) { CFG_SetMQTTHost(tmpA); } if(http_getArg(request->url,"port",tmpA,sizeof(tmpA))) { CFG_SetMQTTPort(atoi(tmpA)); } if(http_getArg(request->url,"user",tmpA,sizeof(tmpA))) { CFG_SetMQTTUserName(tmpA); } if(http_getArg(request->url,"password",tmpA,sizeof(tmpA))) { CFG_SetMQTTPass(tmpA); } if(http_getArg(request->url,"client",tmpA,sizeof(tmpA))) { CFG_SetMQTTClientId(tmpA); } CFG_Save_SetupTimer(); poststr(request,"Please wait for module to connect... if there is problem, restart it from Index html page..."); poststr(request,"
"); poststr(request,"Return to MQTT settings"); poststr(request,"
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_webapp(http_request_t *request) { http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set Webapp"); poststr(request,"

Use this to set the URL of the Webapp

"); add_label_text_field(request, "Url", "url", CFG_GetWebappRoot(), "
"); poststr(request,"
\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_webapp_set(http_request_t *request) { char tmpA[128]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Saving Webapp"); if(http_getArg(request->url,"url",tmpA,sizeof(tmpA))) { if(CFG_SetWebappRoot(tmpA)) { hprintf128(request,"Webapp url set to %s", tmpA); } else { hprintf128(request,"Webapp url change error - failed to save to flash."); } } else { poststr(request,"Webapp url not set because you didn't specify the argument."); } poststr(request,"
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_ping(http_request_t *request) { char tmpA[128]; int bChanged; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set Watchdog"); bChanged = 0; poststr(request,"

Ping watchdog (backup reconnect mechanism)

"); poststr(request,"

By default, all OpenBeken devices automatically tries to reconnect to WiFi when a connection is lost."); poststr(request," I have tested the reconnect mechanism many times by restarting my router and it always worked reliably."); poststr(request," However, according to some reports, there are still some edge cases when a device fails to reconnect to WIFi."); poststr(request," This is why this mechanism has been added.

"); poststr(request,"

This mechanism keeps pinging certain host and reconnects to WiFi if it doesn't respond at all for a certain amount of seconds.

"); poststr(request,"

USAGE: For a host, choose the main address of your router and make sure it responds to a pings. Interval is 1 second or so, timeout can be set by user, to eg. 60 sec

"); if(http_getArg(request->url,"host",tmpA,sizeof(tmpA))) { CFG_SetPingHost(tmpA); poststr(request,"

New ping host set!

"); bChanged = 1; } /* if(http_getArg(request->url,"interval",tmpA,sizeof(tmpA))) { CFG_SetPingIntervalSeconds(atoi(tmpA)); poststr(request,"

New ping interval set!

"); bChanged = 1; }*/ if(http_getArg(request->url,"disconnectTime",tmpA,sizeof(tmpA))) { CFG_SetPingDisconnectedSecondsToRestart(atoi(tmpA)); poststr(request,"

New ping disconnectTime set!

"); bChanged = 1; } if(http_getArg(request->url,"clear",tmpA,sizeof(tmpA))) { CFG_SetPingDisconnectedSecondsToRestart(0); CFG_SetPingIntervalSeconds(0); CFG_SetPingHost(""); poststr(request,"

Ping watchdog disabled!

"); bChanged = 1; } if(bChanged) { poststr(request,"

Changes will be applied after restarting

"); } poststr(request,"
\ \ \
"); poststr(request,"

Use this to enable pinger

"); add_label_text_field(request, "Host", "host", CFG_GetPingHost(), "
"); add_label_numeric_field(request, "Take action after this number of seconds with no reply", "disconnectTime", CFG_GetPingDisconnectedSecondsToRestart(), "
"); poststr(request,"

\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_wifi(http_request_t *request) { // for a test, show password as well... char tmpA[128]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set Wifi"); /*bChanged = 0; if(http_getArg(recvbuf,"ssid",tmpA,sizeof(tmpA))) { CFG_SetWiFiSSID(tmpA); poststr(request,"

WiFi SSID set!

"); bChanged = 1; } if(http_getArg(recvbuf,"pass",tmpA,sizeof(tmpA))) { CFG_SetWiFiPass(tmpA); poststr(request,"

WiFi Password set!

"); bChanged = 1; } if(bChanged) { poststr(request,"

Device will reconnect after restarting

"); }*/ poststr(request,"

Check networks reachable by module

This will lag few seconds.
"); if(http_getArg(request->url,"scan",tmpA,sizeof(tmpA))) { #ifdef WINDOWS poststr(request,"Not available on Windows
"); #elif PLATFORM_XR809 poststr(request,"TODO XR809
"); #elif PLATFORM_W600 || PLATFORM_W800 poststr(request,"TODO W800
"); #elif PLATFORM_BL602 poststr(request,"TODO BL602
"); #elif PLATFORM_BK7231T int i; AP_IF_S *ar; uint32_t num; bk_printf("Scan begin...\r\n"); tuya_hal_wifi_all_ap_scan(&ar,&num); bk_printf("Scan returned %i networks\r\n",num); for(i = 0; i < num; i++) { hprintf128(request,"[%i/%i] SSID: %s, Channel: %i, Signal %i
",i,(int)num,ar[i].ssid, ar[i].channel, ar[i].rssi); } tuya_hal_wifi_release_ap(ar); #elif PLATFORM_BK7231N int i; AP_IF_S *ar; uint32_t num; bk_printf("Scan begin...\r\n"); tuya_os_adapt_wifi_all_ap_scan(&ar,&num); bk_printf("Scan returned %i networks\r\n",num); for(i = 0; i < num; i++) { hprintf128(request,"[%i/%i] SSID: %s, Channel: %i, Signal %i
",i + 1,(int)num,ar[i].ssid, ar[i].channel, ar[i].rssi); } tuya_os_adapt_wifi_release_ap(ar); #else #error "Unknown platform" poststr(request,"Unknown platform
"); #endif } poststr(request,"
\ \ \
"); poststr(request,"

Use this to disconnect from your WiFi

"); poststr(request,"
\ \ \
"); poststr(request,"

Use this to connect to your WiFi

"); add_label_text_field(request, "SSID", "ssid", CFG_GetWiFiSSID(), "
"); add_label_text_field(request, "Password", "pass", CFG_GetWiFiPass(), "
"); poststr(request,"

\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_name(http_request_t *request) { // for a test, show password as well... char tmpA[128]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set name"); poststr(request,"

Change device names for display.

"); if(http_getArg(request->url,"shortName",tmpA,sizeof(tmpA))) { CFG_SetShortDeviceName(tmpA); } if(http_getArg(request->url,"name",tmpA,sizeof(tmpA))) { CFG_SetDeviceName(tmpA); } poststr(request,"

Use this to change device names

"); add_label_text_field(request, "ShortName", "shortName", CFG_GetShortDeviceName(), "
"); add_label_text_field(request, "Full Name", "name", CFG_GetDeviceName(), "
"); poststr(request,"

"); poststr(request, ""); poststr(request, "
"); //poststr(request,htmlReturnToCfg); //HTTP_AddBuildFooter(request); //poststr(request,htmlEnd); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_wifi_set(http_request_t *request) { char tmpA[128]; addLogAdv(LOG_INFO, LOG_FEATURE_HTTP,"HTTP_ProcessPacket: generating cfg_wifi_set \r\n"); http_setup(request, httpMimeTypeHTML); http_html_start(request, "Saving Wifi"); if(http_getArg(request->url,"open",tmpA,sizeof(tmpA))) { CFG_SetWiFiSSID(""); CFG_SetWiFiPass(""); poststr(request,"WiFi mode set: open access point."); } else { if(http_getArg(request->url,"ssid",tmpA,sizeof(tmpA))) { CFG_SetWiFiSSID(tmpA); } if(http_getArg(request->url,"pass",tmpA,sizeof(tmpA))) { CFG_SetWiFiPass(tmpA); } poststr(request,"WiFi mode set: connect to WLAN."); } CFG_Save_SetupTimer(); poststr(request,"Please wait for module to reset..."); RESET_ScheduleModuleReset(3); poststr(request,"
"); poststr(request,"Return to WiFi settings"); poststr(request,"
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_loglevel_set(http_request_t *request) { char tmpA[128]; addLogAdv(LOG_INFO, LOG_FEATURE_HTTP,"HTTP_ProcessPacket: generating cfg_loglevel_set \r\n"); http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set log level"); if(http_getArg(request->url,"loglevel",tmpA,sizeof(tmpA))) { #if WINDOWS #else loglevel = atoi(tmpA); #endif poststr(request,"LOG level changed."); } tmpA[0] = 0; #if WINDOWS add_label_text_field(request, "Loglevel", "loglevel", "", "
"); #else add_label_numeric_field(request, "Loglevel", "loglevel", loglevel, ""); #endif poststr(request,"

\ \
"); poststr(request,"
"); poststr(request,"Return to config settings"); poststr(request,"
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_mac(http_request_t *request) { // must be unsigned, else print below prints negatives as e.g. FFFFFFFe unsigned char mac[6]; char tmpA[128]; int i; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set MAC address"); if(http_getArg(request->url,"mac",tmpA,sizeof(tmpA))) { for( i = 0; i < 6; i++ ) { mac[i] = hexbyte( &tmpA[i * 2] ) ; } //sscanf(tmpA,"%02X%02X%02X%02X%02X%02X",&mac[0],&mac[1],&mac[2],&mac[3],&mac[4],&mac[5]); if(WiFI_SetMacAddress((char*)mac)) { poststr(request,"

New MAC set!

"); } else { poststr(request,"

MAC change error?

"); } CFG_Save_IfThereArePendingChanges(); } WiFI_GetMacAddress((char *)mac); poststr(request,"

Here you can change MAC address.

"); char macStr[16]; sprintf(macStr,"%02X%02X%02X%02X%02X%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]); add_label_text_field(request, "MAC", "mac",macStr , "
"); poststr(request,"

\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_flash_read_tool(http_request_t *request) { int len = 16; int ofs = 1970176; int res; int rem; int now; int nowOfs; int hex; int i; char tmpA[128]; char tmpB[64]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Flash read"); poststr(request,"

Flash Read Tool

"); if( http_getArg(request->url,"hex",tmpA,sizeof(tmpA))){ hex = atoi(tmpA); } else { hex = 0; } if( http_getArg(request->url,"offset",tmpA,sizeof(tmpA)) && http_getArg(request->url,"len",tmpB,sizeof(tmpB))) { unsigned char buffer[128]; len = atoi(tmpB); ofs = atoi(tmpA); hprintf128(request,"Memory at %i with len %i reads: ",ofs,len); poststr(request,"
"); ///res = bekken_hal_flash_read (ofs, buffer,len); //sprintf(tmpA,"Result %i",res); // strcat(outbuf,tmpA); /// strcat(outbuf,"
"); nowOfs = ofs; rem = len; while(1) { if(rem > sizeof(buffer)) { now = sizeof(buffer); } else { now = rem; } #if PLATFORM_XR809 //uint32_t flash_read(uint32_t flash, uint32_t addr,void *buf, uint32_t size) #define FLASH_INDEX_XR809 0 res = flash_read(FLASH_INDEX_XR809, nowOfs, buffer, now); #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 #else res = bekken_hal_flash_read (nowOfs, buffer,now); #endif for(i = 0; i < now; i++) { unsigned char val = buffer[i]; if(!hex && isprint(val)) { hprintf128(request,"'%c' ",val); } else { hprintf128(request,"%02X ",val); } } rem -= now; nowOfs += now; if(rem <= 0) { break; } } poststr(request,"
"); } poststr(request,"
"); poststr(request,"
"); add_label_numeric_field(request, "Offset", "offset", ofs, ""); add_label_numeric_field(request, "Length", "len", len, "
"); poststr(request,"

\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cmd_tool(http_request_t *request) { int i; char tmpA[128]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Command tool"); poststr(request,"

Command Tool

"); if( http_getArg(request->url,"cmd",tmpA,sizeof(tmpA))) { i = CMD_ExecuteCommand(tmpA, COMMAND_FLAG_SOURCE_CONSOLE); if(i == 0) { poststr(request,"Command not found"); } else { poststr(request,"Executed"); } poststr(request,"
"); } add_label_text_field(request, "Command", "cmd", tmpA, "
"); poststr(request,"

\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_startup_command(http_request_t *request) { char tmpA[512]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Set startup command"); poststr(request,"

Set/Change/Clear startup command line

"); poststr(request,"
Startup command is a shorter, smaller alternative to LittleFS autoexec.bat." "The startup commands are ran at device startup." "You can use them to init peripherals and drivers, like BL0942 energy sensor
"); if(http_getArg(request->url,"data",tmpA,sizeof(tmpA))) { // hprintf128(request,"

Set command to %s!

",tmpA); // tmpA can be longer than 128 bytes and this would crash hprintf128(request,"

Command changed!

"); CFG_SetShortStartupCommand(tmpA); CFG_Save_IfThereArePendingChanges(); } else { } add_label_text_field(request, "Startup command", "data", CFG_GetShortStartupCommand(), "
"); poststr(request,"

\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_uart_tool(http_request_t *request) { char tmpA[256]; int resultLen = 0; http_setup(request, httpMimeTypeHTML); http_html_start(request, "UART tool"); poststr(request,"

UART Tool

"); if(http_getArg(request->url,"data",tmpA,sizeof(tmpA))) { #ifndef OBK_DISABLE_ALL_DRIVERS byte results[128]; hprintf128(request,"

Sent %s!

",tmpA); if(0){ TuyaMCU_Send((byte *)tmpA, strlen(tmpA)); // bk_send_string(0,tmpA); } else { byte b; const char *p; p = tmpA; while(*p) { b = hexbyte(p); results[resultLen] = b; resultLen++; p+=2; } TuyaMCU_Send(results, resultLen); } #endif } else { strcpy(tmpA,"Hello UART world"); } add_label_text_field(request, "Data", "data", tmpA, "
"); poststr(request,"
\ \
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_config_dump_table(http_request_t *request) { http_setup(request, httpMimeTypeHTML); http_html_start(request, "Dump config"); poststr(request,"Not implemented
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_quick(http_request_t *request) { char tmpA[128]; int j; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Quick Config"); poststr(request,"

Quick Config

"); if(http_getArg(request->url,"dev",tmpA,sizeof(tmpA))) { j = atoi(tmpA); hprintf128(request,"

Set dev %i!

",j); g_templates[j].setter(); } poststr(request,"
"); poststr(request, ""); poststr(request,"
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } /// @brief Computes the Relay and PWM count. /// @param relayCount /// @param pwmCount void get_Relay_PWM_Count(int *relayCount, int *pwmCount){ (*relayCount) = 0; (*pwmCount) = 0; for(int i = 0; i < PLATFORM_GPIO_MAX; i++) { int role = PIN_GetPinRoleForPinIndex(i); if(role == IOR_Relay || role == IOR_Relay_n || role == IOR_LED || role == IOR_LED_n) { (*relayCount)++; } else if(role == IOR_PWM || role == IOR_PWM_n) { (*pwmCount)++; } } } /// @brief Sends HomeAssistant discovery MQTT messages. /// @param request /// @return int http_fn_ha_discovery(http_request_t *request) { int i; char topic[32]; int relayCount = 0; int pwmCount = 0; char bLedDriverChipRunning; http_setup(request, httpMimeTypeText); get_Relay_PWM_Count(&relayCount, &pwmCount); #ifndef OBK_DISABLE_ALL_DRIVERS bLedDriverChipRunning = DRV_IsRunning("SM2135") || DRV_IsRunning("BP5758D"); #else bLedDriverChipRunning = 0; #endif if ((relayCount == 0) && (pwmCount == 0)) { poststr(request, NULL); return 0; } if (!http_getArg(request->url, "prefix", topic, sizeof(topic))) { sprintf(topic, "homeassistant"); //default discovery topic is `homeassistant` } struct cJSON_Hooks hooks; hooks.malloc_fn = os_malloc; hooks.free_fn = os_free; cJSON_InitHooks(&hooks); if(relayCount > 0) { for(i = 0; i < CHANNEL_MAX; i++) { if(h_isChannelRelay(i)) { HassDeviceInfo *dev_info = hass_init_relay_device_info(i); MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); hass_free_device_info(dev_info); } } } if (pwmCount == 5 || bLedDriverChipRunning) { // Enable + RGB control + CW control HassDeviceInfo *dev_info = hass_init_light_device_info(ENTITY_LIGHT_RGBCW, -1); MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); hass_free_device_info(dev_info); } else if (pwmCount == 3) { // Enable + RGB control HassDeviceInfo *dev_info = hass_init_light_device_info(ENTITY_LIGHT_RGB, -1); MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); hass_free_device_info(dev_info); } else if(pwmCount > 0) { for(i = 0; i < CHANNEL_MAX; i++) { if(h_isChannelPWM(i)) { HassDeviceInfo *dev_info = hass_init_light_device_info(ENTITY_LIGHT_PWM, i); MQTT_QueuePublish(topic, dev_info->channel, hass_build_discovery_json(dev_info), OBK_PUBLISH_FLAG_RETAIN); hass_free_device_info(dev_info); } } } poststr(request, NULL); return 0; } int http_fn_ha_cfg(http_request_t *request) { int relayCount = 0; int pwmCount = 0; const char *shortDeviceName; const char *clientId; int i; char mqttAdded = 0; char switchAdded = 0; char lightAdded = 0; int bLedDriverChipRunning; shortDeviceName = CFG_GetShortDeviceName(); clientId = CFG_GetMQTTClientId(); http_setup(request, httpMimeTypeHTML); http_html_start(request, "Home Assistant Setup"); poststr(request,"

Home Assistant Cfg

"); hprintf128(request,"

Note that your short device name is: %s

",shortDeviceName); poststr(request,"

Paste this to configuration yaml

"); poststr(request,"
Make sure that you have \"switch:\" keyword only once! Home Assistant doesn't like dup keywords.
"); poststr(request,"
You can also use \"switch MyDeviceName:\" to avoid keyword duplication!
"); poststr(request,""); poststr(request,"
 

"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, HomeAssistantDiscoveryScript); poststr(request, NULL); return 0; } // https://tasmota.github.io/docs/Commands/#with-mqtt /* http:///cm?cmnd=Power%20TOGGLE http:///cm?cmnd=Power%20On http:///cm?cmnd=Power%20off http:///cm?user=admin&password=joker&cmnd=Power%20Toggle */ // https://www.elektroda.com/rtvforum/viewtopic.php?p=19330027#19330027 // Web browser sends: GET /cm?cmnd=POWER1 // System responds with state int http_tasmota_json_power(http_request_t *request) { int numRelays; int numPWMs; int i; int lastRelayState; // try to return status numPWMs = PIN_CountPinsWithRoleOrRole(IOR_PWM, IOR_PWM_n); numRelays = 0; // LED driver (if has PWMs) if(numPWMs > 0){ if(LED_GetEnableAll() == 0) { poststr(request,"{\"POWER\":\"OFF\"}"); } else { poststr(request,"{\"POWER\":\"ON\"}"); } } else { // relays driver for(i = 0; i < CHANNEL_MAX; i++) { if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) { numRelays++; lastRelayState = CHANNEL_Get(i); } } if(numRelays == 1) { if(lastRelayState) { poststr(request,"{\"POWER\":\"ON\"}"); } else { poststr(request,"{\"POWER\":\"OFF\"}"); } } else { for(i = 0; i < CHANNEL_MAX; i++) { if (h_isChannelRelay(i) || CHANNEL_GetType(i) == ChType_Toggle) { lastRelayState = CHANNEL_Get(i); if(lastRelayState) { hprintf128(request,"{\"POWER%i\":\"ON\"}",i); } else { hprintf128(request,"{\"POWER%i\":\"OFF\"}",i); } } } } } return 0; } /* {"StatusSNS":{"Time":"2022-07-30T10:11:26","ENERGY":{"TotalStartTime":"2022-05-12T10:56:31","Total":0.003,"Yesterday":0.003,"Today":0.000,"Power": 0,"ApparentPower": 0,"ReactivePower": 0,"Factor":0.00,"Voltage":236,"Current":0.000}}} */ int http_tasmota_json_status_SNS(http_request_t *request) { float power, factor, voltage, current; #ifndef OBK_DISABLE_ALL_DRIVERS factor = 0; // TODO voltage = DRV_GetReading(OBK_VOLTAGE); current = DRV_GetReading(OBK_CURRENT); power = DRV_GetReading(OBK_POWER); #else factor = 0; voltage = 0; current = 0; power = 0; #endif hprintf128(request,"{\"StatusSNS\":{\"ENERGY\":{"); hprintf128(request,"\"Power\": %f,", power); hprintf128(request,"\"ApparentPower\": 0,\"ReactivePower\": 0,\"Factor\":%f,", factor); hprintf128(request,"\"Voltage\":%f,", voltage); hprintf128(request,"\"Current\":%f}}}", current); return 0; } /* {"Status":{"Module":0,"DeviceName":"Tasmota","FriendlyName":["Tasmota"],"Topic":"tasmota_48E7F3","ButtonTopic":"0","Power":1,"PowerOnState":3,"LedState":1,"LedMask":"FFFF","SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0,"InfoRetain":0,"StateRetain":0}} */ int http_tasmota_json_status_generic(http_request_t *request) { const char *deviceName; const char *friendlyName; const char *clientId; deviceName = CFG_GetShortDeviceName(); friendlyName = CFG_GetDeviceName(); clientId = CFG_GetMQTTClientId(); hprintf128(request,"{\"Status\":{\"Module\":0,\"DeviceName\":\"%s\"",deviceName); hprintf128(request,",\"FriendlyName\":[\"%s\"]",friendlyName); hprintf128(request,",\"Topic\":\"%s\",\"ButtonTopic\":\"0\"",clientId); hprintf128(request,",\"Power\":1,\"PowerOnState\":3,\"LedState\":1"); hprintf128(request,",\"LedMask\":\"FFFF\",\"SaveData\":1,\"SaveState\":1"); hprintf128(request,",\"SwitchTopic\":\"0\",\"SwitchMode\":[0,0,0,0,0,0,0,0]"); hprintf128(request,",\"ButtonRetain\":0,\"SwitchRetain\":0,\"SensorRetain\":0"); hprintf128(request,",\"PowerRetain\":0,\"InfoRetain\":0,\"StateRetain\":0}}"); return 0; } int http_fn_cm(http_request_t *request) { char tmpA[128]; http_setup(request, httpMimeTypeJson); // exec command if( http_getArg(request->url,"cmnd",tmpA,sizeof(tmpA))) { CMD_ExecuteCommand(tmpA,COMMAND_FLAG_SOURCE_HTTP); if(!wal_strnicmp(tmpA,"POWER",5)) { http_tasmota_json_power(request); } else if(!wal_strnicmp(tmpA,"STATUS 8",8)) { http_tasmota_json_status_SNS(request); } else { http_tasmota_json_status_generic(request); } } poststr(request, NULL); return 0; } int http_fn_cfg(http_request_t *request) { http_setup(request, httpMimeTypeHTML); http_html_start(request, "Config"); postFormAction(request, "cfg_pins", "Configure Module"); postFormAction(request, "cfg_generic", "Configure General"); postFormAction(request, "cfg_startup", "Configure Startup"); postFormAction(request, "cfg_dgr", "Configure Device Groups"); postFormAction(request, "cfg_quick","Quick Config"); postFormAction(request, "cfg_wifi", "Configure WiFi"); postFormAction(request, "cfg_mqtt", "Configure MQTT"); postFormAction(request, "cfg_name", "Configure Names"); postFormAction(request, "cfg_mac", "Change MAC"); postFormAction(request, "cfg_ping", "Ping Watchdog (Network lost restarter)"); postFormAction(request, "cfg_webapp", "Configure Webapp"); postFormAction(request, "ha_cfg", "Generate Home Assistant cfg"); postFormAction(request, "ota", "OTA (update software by WiFi)"); postFormAction(request, "cmd_tool", "Execute custom command"); postFormAction(request, "flash_read_tool" ,"Flash Read Tool"); postFormAction(request, "uart_tool", "UART Tool"); postFormAction(request, "startup_command", "Change startup command text"); #if 0 #if PLATFORM_BK7231T | PLATFORM_BK7231N { int i,j,k; k = config_get_tableOffsets(BK_PARTITION_NET_PARAM,&i,&j); hprintf128(request,"BK_PARTITION_NET_PARAM: bOk %i, at %i, len %i
",k,i,j); k = config_get_tableOffsets(BK_PARTITION_RF_FIRMWARE,&i,&j); hprintf128(request,"BK_PARTITION_RF_FIRMWARE: bOk %i, at %i, len %i
",k,i,j); k = config_get_tableOffsets(BK_PARTITION_OTA,&i,&j); hprintf128(request,"BK_PARTITION_OTA: bOk %i, at %i, len %i
",k,i,j); } #endif #endif poststr(request,htmlFooterReturnToMenu); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_pins(http_request_t *request) { int iChanged = 0; int iChangedRequested = 0; int i; char tmpA[128]; char tmpB[64]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Pin config"); poststr(request,"
First textfield is used to enter channel index (relay index), used to support multiple relays and buttons
"); poststr(request,"
(so, first button and first relay should have channel 1, second button and second relay have channel 2, etc)
"); poststr(request,"
Second textfield (only for buttons) is used to enter channel to toggle when doing double click
"); poststr(request,"
(second textfield shows up when you change role to button and save...)
"); #if PLATFORM_BK7231N || PLATFORM_BK7231T poststr(request,"
BK7231N/BK7231T supports PWM only on pins 6, 7, 8, 9, 24 and 26!
"); #endif for(i = 0; i < PLATFORM_GPIO_MAX; i++) { sprintf(tmpA, "%i",i); if(http_getArg(request->url,tmpA,tmpB,sizeof(tmpB))) { int role; int pr; iChangedRequested++; role = atoi(tmpB); pr = PIN_GetPinRoleForPinIndex(i); if(pr != role) { PIN_SetPinRoleForPinIndex(i,role); iChanged++; } } sprintf(tmpA, "r%i",i); if(http_getArg(request->url,tmpA,tmpB,sizeof(tmpB))) { int rel; int prevRel; iChangedRequested++; rel = atoi(tmpB); prevRel = PIN_GetPinChannelForPinIndex(i); if(prevRel != rel) { PIN_SetPinChannelForPinIndex(i,rel); iChanged++; } } sprintf(tmpA, "e%i",i); if(http_getArg(request->url,tmpA,tmpB,sizeof(tmpB))) { int rel; int prevRel; iChangedRequested++; rel = atoi(tmpB); prevRel = PIN_GetPinChannel2ForPinIndex(i); if(prevRel != rel) { PIN_SetPinChannel2ForPinIndex(i,rel); iChanged++; } } } if(iChangedRequested>0) { // Anecdotally, if pins are configured badly, the // second-timer breaks. To reconfigure, force // saving the configuration instead of waiting. //CFG_Save_SetupTimer(); CFG_Save_IfThereArePendingChanges(); hprintf128(request, "Pins update - %i reqs, %i changed!

",iChangedRequested,iChanged); } // strcat(outbuf,""); poststr(request,"
"); for(i = 0; i < PLATFORM_GPIO_MAX; i++) { int si, ch, ch2; int j; const char *alias; // On BL602, any GPIO can be mapped to one of 5 PWM channels // But on Beken chips, only certain pins can be PWM int bCanThisPINbePWM; si = PIN_GetPinRoleForPinIndex(i); ch = PIN_GetPinChannelForPinIndex(i); ch2 = PIN_GetPinChannel2ForPinIndex(i); bCanThisPINbePWM = HAL_PIN_CanThisPinBePWM(i); // if available.. alias = HAL_PIN_GetPinNameAlias(i); poststr(request, "
"); if(alias) { poststr(request,alias); poststr(request," "); } else { hprintf128(request, "P%i ",i); } hprintf128(request, ""); hprintf128(request, "",i,ch); if(si == IOR_Button || si == IOR_Button_n) { // extra param. For button, is relay index to toggle on double click hprintf128(request, "",i,ch2); } poststr(request,"
"); } poststr(request,"
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } const char *g_obk_flagNames[] = { "[MQTT] Broadcast led params together (send dimmer and color when dimmer or color changes, topic name: YourDevName/led_basecolor_rgb/get, YourDevName/led_dimmer/get)", "[MQTT] Broadcast led final color (topic name: YourDevName/led_finalcolor_rgb/get)", "[MQTT] Broadcast self state every minute (May cause device disconnect's, DONT USE IT YET)", "[LED][Debug] Show raw PWM controller on WWW index instead of new LED RGB/CW/etc picker", "[LED] Force show RGBCW controller (for example, for SM2135 LEDs, or for DGR sender)", "[CMD] Enable TCP console command server (for Putty, etc)", "[BTN] Instant touch reaction instead of waiting for release (aka SetOption 13)", "[MQTT] [Debug] Always set Retain flag to all published values", "[LED] Alternate CW light mode (first PWM for warm/cold slider, second for brightness)", "[SM2135] Use separate RGB/CW modes instead of writing all 5 values as RGB", "[MQTT] Broadcast self state on MQTT connect", "[PWM] BK7231 use 600hz instead of 1khz default", "[LED] remember LED driver state (RGBCW, enable, brightness, temperature) after reboot", "error", "error", }; int http_fn_cfg_generic(http_request_t *request) { int i; char tmpA[64]; char tmpB[64]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Generic config"); if( http_getArg(request->url,"boot_ok_delay",tmpA,sizeof(tmpA))) { i = atoi(tmpA); if(i <= 0) { poststr(request,"
Boot ok delay must be at least 1 second
"); i = 1; } hprintf128(request,"
Setting boot OK delay to %i
",i); CFG_SetBootOkSeconds(i); } if( http_getArg(request->url,"setFlags",tmpA,sizeof(tmpA))) { for(i = 0; i < OBK_TOTAL_FLAGS; i++) { int ni; sprintf(tmpB,"flag%i",i); if( http_getArg(request->url,tmpB,tmpA,sizeof(tmpA))) { ni = atoi(tmpA); } else { ni = 0; } hprintf128(request,"
Setting flag %i to %i
",i,ni); CFG_SetFlag(i,ni); } } CFG_Save_IfThereArePendingChanges(); hprintf128(request,"
Flags (Current value=%i)
",CFG_GetFlags()); poststr(request,"
"); for(i = 0; i < OBK_TOTAL_FLAGS; i++) { const char *flagName = g_obk_flagNames[i]; /*
*/ hprintf128(request, "
", i, i, (CFG_HasFlag(i) ?" checked":"")); //this is less that 128 char hprintf128(request,"
"); } poststr(request,""); poststr(request,"
"); add_label_numeric_field(request, "Uptime seconds required to mark boot as ok", "boot_ok_delay", CFG_GetBootOkSeconds(), "
"); poststr(request,"
"); poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_startup(http_request_t *request) { int channelIndex; int newValue; int i; char tmpA[128]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Config startup"); hprintf128(request,"
Here you can set pin start values
"); hprintf128(request,"
For relays, simply use 1 or 0
"); hprintf128(request,"
For 'remember last power state', use -1 as a special value
"); hprintf128(request,"
For dimmers, range is 0 to 100
"); hprintf128(request,"
For custom values, you can set any number you want to
"); hprintf128(request,"
Remember that you can also use short startup command to run commands like led_baseColor #FF0000 and led_enableAll 1 etc
"); hprintf128(request,"
Remembering last state of LED driver is not yet fully supported, please wait!
"); if( http_getArg(request->url,"idx",tmpA,sizeof(tmpA))) { channelIndex = atoi(tmpA); if( http_getArg(request->url,"value",tmpA,sizeof(tmpA))) { newValue = atoi(tmpA); CFG_SetChannelStartupValue(channelIndex,newValue); // also save current value if marked as saved Channel_SaveInFlashIfNeeded(channelIndex); hprintf128(request,"
Setting channel %i start value to %i
",channelIndex,newValue); CFG_Save_IfThereArePendingChanges(); } } for(i = 0; i < CHANNEL_MAX; i++) { if(CHANNEL_IsInUse(i)) { int startValue; startValue = CFG_GetChannelStartupValue(i); poststr(request,"
\
\ "); poststr(request,"
"); poststr(request,"
"); } } poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_cfg_dgr(http_request_t *request) { char tmpA[128]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "Device groups"); hprintf128(request,"
Here you can configure Tasmota Device Groups
"); if( http_getArg(request->url,"name",tmpA,sizeof(tmpA))) { int newSendFlags; int newRecvFlags; newSendFlags = 0; newRecvFlags = 0; if(http_getArgInteger(request->url,"s_pwr")) newSendFlags |= DGR_SHARE_POWER; if(http_getArgInteger(request->url,"r_pwr")) newRecvFlags |= DGR_SHARE_POWER; if(http_getArgInteger(request->url,"s_lbr")) newSendFlags |= DGR_SHARE_LIGHT_BRI; if(http_getArgInteger(request->url,"r_lbr")) newRecvFlags |= DGR_SHARE_LIGHT_BRI; if(http_getArgInteger(request->url,"s_lcl")) newSendFlags |= DGR_SHARE_LIGHT_COLOR; if(http_getArgInteger(request->url,"r_lcl")) newRecvFlags |= DGR_SHARE_LIGHT_COLOR; CFG_DeviceGroups_SetName(tmpA); CFG_DeviceGroups_SetSendFlags(newSendFlags); CFG_DeviceGroups_SetRecvFlags(newRecvFlags); if(tmpA[0] != 0) { #ifndef OBK_DISABLE_ALL_DRIVERS DRV_StartDriver("DGR"); #endif } CFG_Save_IfThereArePendingChanges(); } { int newSendFlags; int newRecvFlags; const char *groupName = CFG_DeviceGroups_GetName(); newSendFlags = CFG_DeviceGroups_GetSendFlags(); newRecvFlags = CFG_DeviceGroups_GetRecvFlags(); add_label_text_field(request, "Group name", "name", groupName, "
"); poststr(request,"
"); poststr(request," "); poststr(request," "); poststr(request," "); poststr(request," "); poststr(request," "); poststr(request,"
NameTasmota CodeReceiveSend
Power1
Light Brightness 2
Light Color 16
"); } poststr(request,htmlFooterReturnToCfgLink); http_html_end(request); poststr(request, NULL); return 0; } void XR809_RequestOTAHTTP(const char *s); int http_fn_ota_exec(http_request_t *request) { char tmpA[128]; //char tmpB[64]; http_setup(request, httpMimeTypeHTML); http_html_start(request, "OTA request"); if(http_getArg(request->url,"host",tmpA,sizeof(tmpA))) { hprintf128(request,"

OTA requested for %s!

",tmpA); addLogAdv(LOG_INFO, LOG_FEATURE_HTTP,"http_fn_ota_exec: will try to do OTA for %s \r\n",tmpA); #if WINDOWS #elif PLATFORM_BL602 #elif PLATFORM_W600 || PLATFORM_W800 t_http_fwup(tmpA); #elif PLATFORM_XR809 XR809_RequestOTAHTTP(tmpA); #else otarequest(tmpA); #endif } poststr(request,htmlFooterReturnToMenu); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_ota(http_request_t *request) { http_setup(request, httpMimeTypeHTML); http_html_start(request, "OTA system"); poststr(request,"

Simple OTA system (you should rather use the OTA from App panel where you can drag and drop file easily without setting up server). Use RBL file for OTA. In the OTA below, you should paste link to RBL file (you need HTTP server).

"); add_label_text_field(request, "URL for new bin file", "host", "", "
"); poststr(request,"
\ \
"); poststr(request,htmlFooterReturnToMenu); http_html_end(request); poststr(request, NULL); return 0; } int http_fn_other(http_request_t *request) { http_setup(request, httpMimeTypeHTML); http_html_start(request, "Not found"); poststr(request,"Not found.
"); poststr(request,htmlFooterReturnToMenu); http_html_end(request); poststr(request, NULL); return 0; }