Browse Source

Added wifi/mqtt reconnection and resubscription

master
chodak166 4 years ago
parent
commit
6132458036
  1. 6
      components/firmware/include/nx/firmware/MqttClient.h
  2. 24
      components/firmware/src/MqttClient.c
  3. 6
      components/software/include/nx/software/AppSettings.h
  4. 7
      components/software/src/AppSettings.c
  5. 8
      components/software/src/SystemSettingsApi.c
  6. 62
      main/Main.c
  7. 4
      main/static/app.html
  8. 2
      main/static/index.html
  9. 50
      main/static/index.js
  10. 4
      main/static/min/app.html
  11. 2
      main/static/min/index.html
  12. 11
      main/static/min/index.js

6
components/firmware/include/nx/firmware/MqttClient.h

@ -31,10 +31,12 @@ typedef struct MqttSettings
MqttErrorCallback errorCb; MqttErrorCallback errorCb;
} MqttSettings; } MqttSettings;
void nxStartMqttClient(const MqttSettings* settings); bool nxStartMqttClient(const MqttSettings* settings);
bool nxMqttSubscribe(const char* topic, uint8_t qos); bool nxMqttSubscribe(const char* topic, uint8_t qos);
uint32_t nxMqttPublish(const char* topic, uint8_t qos, const char* data, size_t size, uint8_t retain); int32_t nxMqttPublish(const char* topic, uint8_t qos, const char* data, size_t size, uint8_t retain);
bool nxMqttIsConnected(void);
#endif /* COMPONENTS_FIRMWARE_INCLUDE_NX_FIRMWARE_MQTTCLIENT_H_ */ #endif /* COMPONENTS_FIRMWARE_INCLUDE_NX_FIRMWARE_MQTTCLIENT_H_ */

24
components/firmware/src/MqttClient.c

@ -16,6 +16,9 @@
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
#define RECONNECTION_TIMEOUT_MS 5000
#define KEEPALIVE_SEC 30 // broker ping
static const char* TAG = "MQTT"; static const char* TAG = "MQTT";
static const MqttSettings* settings = NULL; static const MqttSettings* settings = NULL;
@ -84,13 +87,13 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
// --------- Public API --------- // // --------- Public API --------- //
void nxStartMqttClient(const MqttSettings* mqttSettings) bool nxStartMqttClient(const MqttSettings* mqttSettings)
{ {
ESP_LOGI(TAG, "Initializing MQTT"); ESP_LOGI(TAG, "Initializing MQTT");
if (strlen(mqttSettings->brokerAddr) == 0) { if (strlen(mqttSettings->brokerAddr) == 0) {
ESP_LOGW(TAG, "Empty broker address, skipping MQTT initialization"); ESP_LOGW(TAG, "Empty broker address, skipping MQTT initialization");
return; return false;
} }
settings = mqttSettings; settings = mqttSettings;
@ -103,9 +106,15 @@ void nxStartMqttClient(const MqttSettings* mqttSettings)
mqtt_cfg.username = settings->user; mqtt_cfg.username = settings->user;
mqtt_cfg.password = settings->password; mqtt_cfg.password = settings->password;
mqtt_cfg.disable_clean_session = false;
mqtt_cfg.disable_auto_reconnect = false;
mqtt_cfg.reconnect_timeout_ms = RECONNECTION_TIMEOUT_MS;
mqtt_cfg.refresh_connection_after_ms = 0;
mqtt_cfg.keepalive = KEEPALIVE_SEC;
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client); esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);
esp_mqtt_client_start(client); return esp_mqtt_client_start(client) == ESP_OK;
} }
bool nxMqttSubscribe(const char* topic, uint8_t qos) bool nxMqttSubscribe(const char* topic, uint8_t qos)
@ -117,17 +126,18 @@ bool nxMqttSubscribe(const char* topic, uint8_t qos)
int msg_id = esp_mqtt_client_subscribe(clientHandle, settings->apiTopic, qos); int msg_id = esp_mqtt_client_subscribe(clientHandle, settings->apiTopic, qos);
if (msg_id == -1) { if (msg_id == -1) {
ESP_LOGE(TAG, "Subscribtion of topic %s failed", topic); ESP_LOGE(TAG, "Subscription of topic %s failed", topic);
if (settings->errorCb) { if (settings->errorCb) {
settings->errorCb(); settings->errorCb();
} }
return false; return false;
} }
ESP_LOGI(TAG, "Subscription of topic %s done", topic);
return true; return true;
} }
uint32_t nxMqttPublish(const char* topic, uint8_t qos, const char* data, size_t size, uint8_t retain) int32_t nxMqttPublish(const char* topic, uint8_t qos, const char* data, size_t size, uint8_t retain)
{ {
if (!clientHandle) { if (!clientHandle) {
ESP_LOGE(TAG, "MQTT client not initialized, aborting data publishing in topic %s", topic); ESP_LOGE(TAG, "MQTT client not initialized, aborting data publishing in topic %s", topic);
@ -136,3 +146,7 @@ uint32_t nxMqttPublish(const char* topic, uint8_t qos, const char* data, size_t
return esp_mqtt_client_publish(clientHandle, topic, data, size, qos, retain); return esp_mqtt_client_publish(clientHandle, topic, data, size, qos, retain);
} }
bool nxMqttIsConnected(void)
{
return clientHandle != NULL;
}

6
components/software/include/nx/software/AppSettings.h

@ -8,8 +8,8 @@
#define WIFI_STRINGS_MAX_LEN 32 #define WIFI_STRINGS_MAX_LEN 32
#define URI_MAX_SIZE 64 #define URI_MAX_SIZE 64
#define USER_DATA_MAX_SIZE 16 #define USER_DATA_MAX_SIZE 16
#define CA_CERT_MAX_SIZE 1500
#define DEVICE_NAME_MAX_LEN 64 #define DEVICE_NAME_MAX_LEN 64
#define CA_CERT_MAX_SIZE 1500
typedef bool (*StorageReadFn)(const char* key, void* data, size_t size); typedef bool (*StorageReadFn)(const char* key, void* data, size_t size);
@ -24,10 +24,10 @@ typedef struct AppSettings {
char mqttUser[USER_DATA_MAX_SIZE]; char mqttUser[USER_DATA_MAX_SIZE];
char mqttPassword[USER_DATA_MAX_SIZE]; char mqttPassword[USER_DATA_MAX_SIZE];
uint16_t mqttHbIntervalSec; uint16_t mqttHbIntervalSec;
uint8_t mqttUseTls; bool mqttUseTls;
char caCert[CA_CERT_MAX_SIZE];
bool overrideDevName; bool overrideDevName;
char customDevName[DEVICE_NAME_MAX_LEN]; char customDevName[DEVICE_NAME_MAX_LEN];
char caCert[CA_CERT_MAX_SIZE];
} AppSettings; } AppSettings;

7
components/software/src/AppSettings.c

@ -76,7 +76,10 @@ void nxInitAppSettings(StorageWriteFn writeFn,
settingsUpdatedCb = updateCb; settingsUpdatedCb = updateCb;
if (firstRun()) { if (firstRun()) {
SettingsUpdatedCb cb = settingsUpdatedCb;
settingsUpdatedCb = NULL; // skip callback during first init
nxRestoreAppDefaultSettings(); nxRestoreAppDefaultSettings();
settingsUpdatedCb = cb;
} }
else { else {
loadSettings(); loadSettings();
@ -95,16 +98,16 @@ void nxRestoreAppDefaultSettings(void)
printf("Restoring DEFAULT application settings\n"); printf("Restoring DEFAULT application settings\n");
settings.mqttHbIntervalSec = DEFAULT_MQTT_HB_SEC; settings.mqttHbIntervalSec = DEFAULT_MQTT_HB_SEC;
settings.mqttUseTls = DEFAULT_MQTT_TLS; settings.mqttUseTls = DEFAULT_MQTT_TLS;
settings.overrideDevName = DEFAULT_OV_DEVNAME;
strcpy(settings.mqttHbUri , DEFAULT_MQTT_HB_URI ); strcpy(settings.mqttHbUri , DEFAULT_MQTT_HB_URI );
strcpy(settings.mqttApiUri , DEFAULT_MQTT_API_URI ); strcpy(settings.mqttApiUri , DEFAULT_MQTT_API_URI );
strcpy(settings.mqttHost , DEFAULT_MQTT_HOST ); strcpy(settings.mqttHost , DEFAULT_MQTT_HOST );
strcpy(settings.mqttUser , DEFAULT_MQTT_USER ); strcpy(settings.mqttUser , DEFAULT_MQTT_USER );
strcpy(settings.mqttPassword , DEFAULT_MQTT_PASS ); strcpy(settings.mqttPassword , DEFAULT_MQTT_PASS );
strcpy(settings.caCert , DEFAULT_CA_CERT );
strcpy(settings.customDevName , DEFAULT_CUSTOM_DEVNAME); strcpy(settings.customDevName , DEFAULT_CUSTOM_DEVNAME);
strcpy(settings.caCert , DEFAULT_CA_CERT );
settings.overrideDevName = DEFAULT_OV_DEVNAME;
nxWriteAppSettings(); nxWriteAppSettings();
} }

8
components/software/src/SystemSettingsApi.c

@ -104,8 +104,8 @@ void nxApiGetSystemSettings(const uint8_t* msg, size_t msgLen,
sprintf(responseBuffer, sprintf(responseBuffer,
"{" "{"
"\"%s\":\"%s\", " // ssid "\"%s\":\"%s\", " // ssid
"\"%s\":%s, " // power save "\"%s\":%i, " // power save
"\"%s\":%s, " // use static ip "\"%s\":%i, " // use static ip
"\"%s\":\"%i.%i.%i.%i\", " // ip "\"%s\":\"%i.%i.%i.%i\", " // ip
"\"%s\":\"%i.%i.%i.%i\", " // gw "\"%s\":\"%i.%i.%i.%i\", " // gw
"\"%s\":\"%i.%i.%i.%i\"," // mask "\"%s\":\"%i.%i.%i.%i\"," // mask
@ -116,8 +116,8 @@ void nxApiGetSystemSettings(const uint8_t* msg, size_t msgLen,
"\"%s\":\"%s\"" // dn "\"%s\":\"%s\"" // dn
"}", "}",
API_KEY_SSID, settings->wifiSsid, API_KEY_SSID, settings->wifiSsid,
API_KEY_WPWSAVE, settings->wifiPowerSave ? "true" : "false", API_KEY_WPWSAVE, settings->wifiPowerSave,
API_KEY_USE_STATIC, settings->useStaticAddr ? "true" : "false", API_KEY_USE_STATIC, settings->useStaticAddr,
API_KEY_IPV4ADDR, settings->ip4addr[0], settings->ip4addr[1], settings->ip4addr[2], settings->ip4addr[3], API_KEY_IPV4ADDR, settings->ip4addr[0], settings->ip4addr[1], settings->ip4addr[2], settings->ip4addr[3],
API_KEY_IPV4GW, settings->ip4gw[0], settings->ip4gw[1], settings->ip4gw[2], settings->ip4gw[3], API_KEY_IPV4GW, settings->ip4gw[0], settings->ip4gw[1], settings->ip4gw[2], settings->ip4gw[3],
API_KEY_IPV4MASK, settings->ip4mask[0], settings->ip4mask[1], settings->ip4mask[2], settings->ip4mask[3], API_KEY_IPV4MASK, settings->ip4mask[0], settings->ip4mask[1], settings->ip4mask[2], settings->ip4mask[3],

62
main/Main.c

@ -45,6 +45,9 @@ static AppSettings* appSettings = NULL;
static WifiSettings wifiSettings; static WifiSettings wifiSettings;
static MqttSettings mqttSettings; static MqttSettings mqttSettings;
static bool wifiStarted = false;
static bool mqttStarted = false;
static const MqTriggerHttpCallbacks httpCallbacks = { static const MqTriggerHttpCallbacks httpCallbacks = {
.getRoot = rootHandler, .getRoot = rootHandler,
.getJs = jsHandler, .getJs = jsHandler,
@ -66,12 +69,22 @@ void app_main(void)
nxInitStorage(); nxInitStorage();
// uncomment to force default NVS initialization for development
// uint8_t zero = 0;
// nxStorageWrite("ledinit", &zero, 1);
// nxStorageWrite("sysinit", &zero, 1);
nxInitSystemSettings(nxStorageWrite, nxStorageRead); nxInitSystemSettings(nxStorageWrite, nxStorageRead);
nxInitAppSettings(nxStorageWrite, nxStorageRead, onAppSettingsUpdate); nxInitAppSettings(nxStorageWrite, nxStorageRead, onAppSettingsUpdate);
systemSettings = nxGetSystemSettings(); systemSettings = nxGetSystemSettings();
appSettings = nxGetAppSettings(); appSettings = nxGetAppSettings();
// uncomment to force WiFi settings for development
// strcpy(systemSettings->wifiSsid, "androidAp");
// strcpy(systemSettings->wifiPassword, "password");
// systemSettings->useStaticAddr = false;
nxStartRestarter(systemSettings->rsSchedule, systemSettings->tzEnv); nxStartRestarter(systemSettings->rsSchedule, systemSettings->tzEnv);
nxSetWifiConnectedCallback(onWifiConnected); nxSetWifiConnectedCallback(onWifiConnected);
@ -83,9 +96,6 @@ void app_main(void)
static void startWifi(void) static void startWifi(void)
{ {
systemSettings->useStaticAddr = true;
systemSettings->ip4addr[3] = 91;
wifiSettings = (struct WifiSettings){ wifiSettings = (struct WifiSettings){
.wname = systemSettings->wifiSsid, .wname = systemSettings->wifiSsid,
.wpass = systemSettings->wifiPassword, .wpass = systemSettings->wifiPassword,
@ -106,6 +116,13 @@ static void startWifi(void)
static void onWifiConnected(void) static void onWifiConnected(void)
{ {
nxUpdateStatus(STATUS_OK);
if (wifiStarted) {
return;
}
wifiStarted = true;
systemSettings->deviceName = nxGetWifiDeviceName(); systemSettings->deviceName = nxGetWifiDeviceName();
nxInitSntpClient(SNTP_RETRIES, systemSettings->sntpAddr, systemSettings->tzEnv); nxInitSntpClient(SNTP_RETRIES, systemSettings->sntpAddr, systemSettings->tzEnv);
@ -127,7 +144,9 @@ static void onWifiConnected(void)
mqttSettings.disconnectedCb = onMqttDisconnected; mqttSettings.disconnectedCb = onMqttDisconnected;
mqttSettings.errorCb = onMqttError; mqttSettings.errorCb = onMqttError;
nxStartMqttClient(&mqttSettings); if (!nxStartMqttClient(&mqttSettings)) {
onMqttError();
}
nxSetMqTriggerHttpCallbacks(&httpCallbacks); nxSetMqTriggerHttpCallbacks(&httpCallbacks);
nxStartMqTriggerHttpServer(); nxStartMqTriggerHttpServer();
@ -154,8 +173,14 @@ static void onWifiError()
static void onMqttConnected() static void onMqttConnected()
{ {
ESP_LOGI(TAG, "MQTT CONNECTED"); ESP_LOGI(TAG, "MQTT CONNECTED");
if (nxMqttSubscribe(appSettings->mqttApiUri, API_QOS)) {
if (!mqttStarted) {
xTaskCreate(&hbTask, "hb_task", 2048, NULL, 1, NULL); xTaskCreate(&hbTask, "hb_task", 2048, NULL, 1, NULL);
mqttStarted = true;
}
// (re)subscribe
if (nxMqttSubscribe(appSettings->mqttApiUri, API_QOS)) {
nxUpdateStatus(STATUS_OK); nxUpdateStatus(STATUS_OK);
} }
} }
@ -186,16 +211,23 @@ static void hbTask(void* param)
} }
while (1) { while (1) {
ESP_LOGI(TAG, "Sending MQTT heartbeat"); if (nxMqttIsConnected()) {
ESP_LOGI(TAG, "Sending MQTT heartbeat");
char timeStr[DT_FORMAT_LEN];
nxGetTimeStr(timeStr); char timeStr[DT_FORMAT_LEN];
char hbMessage[DT_FORMAT_LEN + strlen(nxGetWifiDeviceName()) + 2]; nxGetTimeStr(timeStr);
strcpy(hbMessage, nxGetWifiDeviceName()); char hbMessage[DT_FORMAT_LEN + strlen(nxGetWifiDeviceName()) + 2];
strcat(hbMessage, " "); strcpy(hbMessage, nxGetWifiDeviceName());
strcat(hbMessage, timeStr); strcat(hbMessage, " ");
strcat(hbMessage, timeStr);
nxMqttPublish(appSettings->mqttHbUri, HB_QOS, hbMessage, strlen(hbMessage), 1);
if(nxMqttPublish(appSettings->mqttHbUri, HB_QOS, hbMessage, strlen(hbMessage), 1) < 0) {
ESP_LOGE(TAG, "Cannot publish heartbeat message");
}
}
else {
ESP_LOGW(TAG, "Skipping MQTT heartbeat due to the disconnected client");
}
vTaskDelay(appSettings->mqttHbIntervalSec*1000 / portTICK_PERIOD_MS); vTaskDelay(appSettings->mqttHbIntervalSec*1000 / portTICK_PERIOD_MS);
} }

4
main/static/app.html

@ -16,13 +16,13 @@
</p> </p>
<p> <p>
<label>Heartbeat topic [TODO]: <label>Heartbeat topic:
<input type="text" name="mqhb"> <input type="text" name="mqhb">
</label> </label>
</p> </p>
<p> <p>
<label>Heartbeat interval (sec) [TODO] <label>Heartbeat interval (sec)
<input type="number" name="mqhbs"> <input type="number" name="mqhbs">
</label> </label>
</p> </p>

2
main/static/index.html

@ -33,7 +33,7 @@
<footer> <footer>
<div class="col-sm col-md-10 col-md-offset-1"> <div class="col-sm col-md-10 col-md-offset-1">
<p> <p>
Copyright &copy; Łukasz Chodyła 2022 MqTrigger v1.1 2022
</p> </p>
</div> </div>
</footer> </footer>

50
main/static/index.js

@ -71,8 +71,25 @@ function loadContent(url) {
http.send(); http.send();
} }
function fillInputs(element, jsonString) {
let obj = JSON.parse(jsonString);
if (obj) {
for (var key of Object.keys(obj)) {
console.log(key + " -> " + obj[key])
let input = element.querySelector("[name='" + key + "'");
if (input) { //TODO: checkbox/radio
input.value = obj[key];
if (input.hasAttribute('data-onset')) {
eval(input.getAttribute("data-onset"));
}
}
}
}
}
function loadValues(element) { function loadValues(element) {
valuesCache = {};
const forms = element.querySelectorAll('form'); const forms = element.querySelectorAll('form');
for (i = 0; i < forms.length; ++i) { for (i = 0; i < forms.length; ++i) {
const srcUrl = forms[i].getAttribute('data-values-src'); const srcUrl = forms[i].getAttribute('data-values-src');
@ -82,20 +99,7 @@ function loadValues(element) {
if (valuesCache[srcUrl]) { if (valuesCache[srcUrl]) {
console.log("Source values already cached: " + valuesCache[srcUrl]); console.log("Source values already cached: " + valuesCache[srcUrl]);
//TODO: dry fillInputs(element, valuesCache[srcUrl]);
let obj = JSON.parse(valuesCache[srcUrl]);
if (obj) {
for (var key of Object.keys(obj)) {
console.log(key + " -> " + obj[key])
let input = element.querySelector("[name='" + key + "'");
if (input) { //TODO: checkbox/radio
input.value = obj[key];
if (input.hasAttribute('data-onset')) {
eval(input.getAttribute("data-onset"));
}
}
}
}
continue; continue;
} }
@ -111,21 +115,7 @@ function loadValues(element) {
if (http.readyState == 4 && http.status == 200) { if (http.readyState == 4 && http.status == 200) {
console.log("Values received: " + http.responseText); console.log("Values received: " + http.responseText);
valuesCache[srcUrl] = http.responseText; valuesCache[srcUrl] = http.responseText;
fillInputs(element, http.responseText);
//TODO: dry
let obj = JSON.parse(http.responseText);
if (obj) {
for (var key of Object.keys(obj)) {
console.log(key + " -> " + obj[key])
let input = element.querySelector("[name='" + key + "'");
if (input) { //TODO: checkbox/radio
input.value = obj[key];
if (input.hasAttribute('data-onset')) {
eval(input.getAttribute("data-onset"));
}
}
}
}
} }
} }
http.send(); http.send();

4
main/static/min/app.html

@ -1,7 +1,7 @@
<h1>Application settings</h1><h3>MQTT settings</h3><form id=app-settings action=/app data-values-src=/app><p><label>MQTT host address: <h1>Application settings</h1><h3>MQTT settings</h3><form id=app-settings action=/app data-values-src=/app><p><label>MQTT host address:
<input name=mqhost></label><p><label>API topic: <input name=mqhost></label><p><label>API topic:
<input name=mqapi></label><p><label>Heartbeat topic [TODO]: <input name=mqapi></label><p><label>Heartbeat topic:
<input name=mqhb></label><p><label>Heartbeat interval (sec) [TODO] <input name=mqhb></label><p><label>Heartbeat interval (sec)
<input type=number name=mqhbs></label><p><label>User name: <input type=number name=mqhbs></label><p><label>User name:
<input name=mquser></label><p><label>Password: <input name=mquser></label><p><label>Password:
<input type=password name=mqpass></label><p><label class=label>Use TLS: <input type=password name=mqpass></label><p><label class=label>Use TLS:

2
main/static/min/index.html

@ -1,2 +1,2 @@
<meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon type=image/png href=data:image/png,%89PNG%0D%0A%1A%0A><link rel=stylesheet href=index.css><script src=index.js></script><header class="sticky row"><div class="col-sm col-md-10 col-md-offset-1"><a id=app-btn href=# role=button class=nav-btn data-dst=/app/form>App</a> <meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon type=image/png href=data:image/png,%89PNG%0D%0A%1A%0A><link rel=stylesheet href=index.css><script src=index.js></script><header class="sticky row"><div class="col-sm col-md-10 col-md-offset-1"><a id=app-btn href=# role=button class=nav-btn data-dst=/app/form>App</a>
<a href=# role=button class=nav-btn data-dst=/sys/form>System</a></div></header><div class=container><div class="row cols-sm-12 cols-md-10"><div class=col-md-offset-1 id=content><h1>Loading</h1><p>Loading content... Please make sure that JavaScript is enabled.</div><div class=col-md-offset-1><hr></div></div></div><footer><div class="col-sm col-md-10 col-md-offset-1"><p>Copyright &copy; Łukasz Chodyła 2022</div></footer><script>initNavButtons();document.getElementById('app-btn').click();</script> <a href=# role=button class=nav-btn data-dst=/sys/form>System</a></div></header><div class=container><div class="row cols-sm-12 cols-md-10"><div class=col-md-offset-1 id=content><h1>Loading</h1><p>Loading content... Please make sure that JavaScript is enabled.</div><div class=col-md-offset-1><hr></div></div></div><footer><div class="col-sm col-md-10 col-md-offset-1"><p>MqTrigger v1.1 2022</div></footer><script>initNavButtons();document.getElementById('app-btn').click();</script>

11
main/static/min/index.js

@ -5,12 +5,11 @@ else{console.log("Ignoring "+element.name);}}});console.log("params: "+params);p
function initFormSendButtons(form){const btns=form.querySelectorAll('.send');for(i=0;i<btns.length;++i){btns[i].addEventListener('click',sendClickHandler);}} function initFormSendButtons(form){const btns=form.querySelectorAll('.send');for(i=0;i<btns.length;++i){btns[i].addEventListener('click',sendClickHandler);}}
function loadContent(url){let http=new XMLHttpRequest();http.open('GET',url,true);let element=document.getElementById('content');element.innerHTML="LOADING...";http.onreadystatechange=function(){if(http.readyState==4&&http.status==200){console.log("Content received");element.innerHTML=http.responseText;loadValues(element);initFormSendButtons(element);}} function loadContent(url){let http=new XMLHttpRequest();http.open('GET',url,true);let element=document.getElementById('content');element.innerHTML="LOADING...";http.onreadystatechange=function(){if(http.readyState==4&&http.status==200){console.log("Content received");element.innerHTML=http.responseText;loadValues(element);initFormSendButtons(element);}}
http.send();} http.send();}
function loadValues(element){const forms=element.querySelectorAll('form');for(i=0;i<forms.length;++i){const srcUrl=forms[i].getAttribute('data-values-src');if(!srcUrl){continue;} function fillInputs(element,jsonString){let obj=JSON.parse(jsonString);if(obj){for(var key of Object.keys(obj)){console.log(key+" -> "+obj[key])
if(valuesCache[srcUrl]){console.log("Source values already cached: "+valuesCache[srcUrl]);let obj=JSON.parse(valuesCache[srcUrl]);if(obj){for(var key of Object.keys(obj)){console.log(key+" -> "+obj[key]) let input=element.querySelector("[name='"+key+"'");if(input){input.value=obj[key];if(input.hasAttribute('data-onset')){eval(input.getAttribute("data-onset"));}}}}}
let input=element.querySelector("[name='"+key+"'");if(input){input.value=obj[key];if(input.hasAttribute('data-onset')){eval(input.getAttribute("data-onset"));}}}} function loadValues(element){valuesCache={};const forms=element.querySelectorAll('form');for(i=0;i<forms.length;++i){const srcUrl=forms[i].getAttribute('data-values-src');if(!srcUrl){continue;}
continue;} if(valuesCache[srcUrl]){console.log("Source values already cached: "+valuesCache[srcUrl]);fillInputs(element,valuesCache[srcUrl]);continue;}
console.log("Getting values from "+srcUrl);let http=new XMLHttpRequest();http.open('GET',srcUrl,false);http.onreadystatechange=function(){if(http.readyState==4&&http.status==200){console.log("Values received: "+http.responseText);valuesCache[srcUrl]=http.responseText;let obj=JSON.parse(http.responseText);if(obj){for(var key of Object.keys(obj)){console.log(key+" -> "+obj[key]) console.log("Getting values from "+srcUrl);let http=new XMLHttpRequest();http.open('GET',srcUrl,false);http.onreadystatechange=function(){if(http.readyState==4&&http.status==200){console.log("Values received: "+http.responseText);valuesCache[srcUrl]=http.responseText;fillInputs(element,http.responseText);}}
let input=element.querySelector("[name='"+key+"'");if(input){input.value=obj[key];if(input.hasAttribute('data-onset')){eval(input.getAttribute("data-onset"));}}}}}}
http.send();}} http.send();}}
function postParams(url,params){var http=new XMLHttpRequest();http.open('POST',url,true);http.setRequestHeader('Content-type','application/x-www-form-urlencoded');http.onreadystatechange=function(){if(http.readyState==4&&http.status==200){alert(http.responseText);}} function postParams(url,params){var http=new XMLHttpRequest();http.open('POST',url,true);http.setRequestHeader('Content-type','application/x-www-form-urlencoded');http.onreadystatechange=function(){if(http.readyState==4&&http.status==200){alert(http.responseText);}}
http.send(params);} http.send(params);}

Loading…
Cancel
Save