Remove json component

This commit is contained in:
Edward Firmo
2024-03-20 19:21:31 +01:00
parent 98aae56235
commit 7455df28e8
18 changed files with 165 additions and 603 deletions

View File

@@ -0,0 +1,88 @@
// json.h
#pragma once
#include "cJSON.h"
#include <cmath>
#include <cstdio>
#include <cstring>
// The `nspanel_ha_blueprint` namespace encapsulates utility functions for JSON manipulation
// tailored for the NSPanel Home Assistant Blueprint project.
namespace nspanel_ha_blueprint {
/**
* Compares the string value of a cJSON object with a target C-string.
*
* This function checks if the given cJSON object is not NULL, is a string type,
* and its value matches the target string provided.
*
* @param json_item The cJSON object whose string value is to be compared.
* @param target_str The target C-string to compare against the cJSON object's value.
* @return True if the cJSON object's string value matches the target string, false otherwise.
*/
bool json_cmp_string(const cJSON* json_item, const char* target_str) {
if (json_item != NULL && cJSON_IsString(json_item) && json_item->valuestring != NULL) {
return strcmp(json_item->valuestring, target_str) == 0;
}
return false;
}
/**
* Compares the integer value of a cJSON object with a target unsigned integer.
*
* This function checks if the given cJSON object is not NULL, represents a number,
* and its integer value matches the target unsigned integer provided. It's particularly
* useful for JSON fields that are expected to contain numeric boolean values (e.g., 0 or 1)
* or other unsigned integer values.
*
* @param json_item The cJSON object whose integer value is to be compared.
* @param target_uint The target unsigned integer to compare against the cJSON object's value.
* @return True if the cJSON object's integer value matches the target unsigned integer, false otherwise.
*/
bool json_cmp_uint(const cJSON* json_item, unsigned int target_uint) {
if (json_item != NULL && cJSON_IsNumber(json_item)) {
return (unsigned int)json_item->valueint == target_uint;
}
return false;
}
/**
* Retrieves a floating-point value from a cJSON object.
*
* @param json_item The cJSON object from which to retrieve the value.
* @return The floating-point value of the cJSON object if it is a number, NaN otherwise.
*/
float json_get_float(const cJSON* json_item) {
if (json_item != NULL && cJSON_IsNumber(json_item)) {
return static_cast<float>(json_item->valuedouble);
}
return std::nan(""); // Return NaN if not a valid number
}
/**
* Converts a JSON integer percentage value to a string representing a floating-point number between 0.00 and 1.00.
*
* @param json_item The cJSON object containing the integer percentage value.
* @return A string representation of the floating-point number, or an empty string if the input is invalid.
*/
std::string json_percentage_to_float_string(const cJSON* json_item) {
// Ensure the item is a valid number
if (json_item != NULL && cJSON_IsNumber(json_item)) {
// Convert the integer percentage to a float between 0.00 and 1.00
float percentage = static_cast<float>(json_item->valueint) / 100.0f;
// Buffer to hold the formatted string, large enough for "0.00" plus null terminator
char buffer[8];
// Format the floating-point number with two decimal places
snprintf(buffer, sizeof(buffer), "%.2f", percentage);
// Return the formatted string
return std::string(buffer);
}
// Return an empty string to indicate invalid input or non-numeric JSON item
return "";
}
} // namespace nspanel_ha_blueprint

View File

@@ -17,7 +17,7 @@ substitutions:
temp_units: "°C"
invalid_cooldown: "100ms"
##### DON'T CHANGE THIS ######
version: "4.3.1"
version: "4.3.2d1"
##############################
##### External components #####
@@ -874,6 +874,18 @@ display:
break;
}
break;
case 1: // Home
switch (component_id) {
case 4: // indr_temp
case 27: // indr_temp_icon
if (!touch_event) { // Release
detailed_entity->publish_state((id(is_embedded_thermostat)) ? "embedded_climate" : "");
disp1->set_component_value("climate.embedded", id(is_embedded_thermostat) ? 1 : 0);
goto_page->execute("climate");
}
break;
}
break;
case 8: // Settings
switch (component_id) {
case 9: // Reboot button
@@ -1672,44 +1684,6 @@ text_sensor:
name: Notification Text
platform: template
##### NSPanel event sensor, the main action sensor - push to HA #####
- id: disp1_nspanel_event
name: NSPanel event
platform: nextion
nextion_id: disp1
component_name: nspanelevent
internal: true
filters:
- lambda: |-
x = x.c_str();
x.shrink_to_fit();
return x;
on_value:
then:
- lambda: |-
ESP_LOGE("text_sensor.nspanelevent", "Obsolete call");
DynamicJsonDocument doc(1024);
deserializeJson(doc, x);
std::string page = doc["page"];
std::string component = doc["component"];
if (not (component == "currentpage" and (page == "screensaver" or page == "home"))) timer_reset_all->execute();
std::string value = doc["value"];
std::string entity = detailed_entity->state.c_str(); // doc["entity"];
esphome::api::CustomAPIDevice ha_event;
ha_event.fire_homeassistant_event("esphome.nspanel_ha_blueprint",
{
{"device_name", device_name->state.c_str()},
{"type", "generic"},
{"page", page},
{"component", component},
{"value", value},
{"entity", entity}
});
ESP_LOGE("text_sensor.nspanelevent", " Page: %s", page.c_str());
ESP_LOGE("text_sensor.nspanelevent", " Component: %s", component.c_str());
ESP_LOGE("text_sensor.nspanelevent", " Value: %s", value.c_str());
ESP_LOGE("text_sensor.nspanelevent", " Entity: %s", entity.c_str());
##### NSPanel event - Execute actions from ESPHome - NO push to HA #####
- id: disp1_local_event
name: NSPanel local event
@@ -1725,80 +1699,74 @@ text_sensor:
on_value:
then:
- lambda: |-
DynamicJsonDocument doc(1024);
deserializeJson(doc, x);
std::string page = doc["page"];
std::string event = doc["event"];
std::string component = doc["component"];
std::string key = doc["key"];
std::string value = doc["value"];
std::string entity = detailed_entity->state.c_str(); // doc["entity"];
int embedded = doc["embedded"];
std::string service = "";
cJSON *json = cJSON_Parse(x.c_str());
if (!json) {
ESP_LOGE("text_sensor.disp1_local_event", "Error parsing json: %s", x.c_str());
} else {
const cJSON* page = cJSON_GetObjectItemCaseSensitive(json, "page");
const cJSON* event = cJSON_GetObjectItemCaseSensitive(json, "event");
const cJSON* component = cJSON_GetObjectItemCaseSensitive(json, "component");
const cJSON* key = cJSON_GetObjectItemCaseSensitive(json, "key");
const cJSON* value = cJSON_GetObjectItemCaseSensitive(json, "value");
const cJSON* embedded = cJSON_GetObjectItemCaseSensitive(json, "embedded");
// Send event to Home Assistant
if (event == "short_click" or event == "long_click") {
ha_button->execute(page.c_str(), component.c_str(), event.c_str());
} else if (event == "click" and page == "home" and component == "climate") {
detailed_entity->publish_state((id(is_embedded_thermostat)) ? "embedded_climate" : "");
disp1->set_component_value("climate.embedded", id(is_embedded_thermostat) ? 1 : 0);
goto_page->execute("climate");
} else if (page == "light" or page == "climate") { // Generic event
// Send event to Home Assistant
if (json_cmp_string(event, "short_click") or json_cmp_string(event, "long_click")) {
ha_button->execute(page->valuestring, component->valuestring, event->valuestring);
} else if (json_cmp_string(page, "light") or json_cmp_string(page, "climate")) { // Generic event
esphome::api::CustomAPIDevice ha_event;
ha_event.fire_homeassistant_event("esphome.nspanel_ha_blueprint", {
{"device_name", device_name->state.c_str()},
{"type", "generic"},
{"page", page},
{"event", event},
{"value", value},
{"entity", entity}
{"page", page->valuestring},
{"component", component->valuestring},
{"event", event->valuestring},
{"value", value->valuestring},
{"entity", detailed_entity->state.c_str()}
});
}
// page based actions
if (page == "alarm")
{
std::string code_format = doc["code_format"];
std::string code_arm_req = doc["code_arm_req"];
std::string title = doc["mui"];
if (code_format == "number" and (key == "disarm" or code_arm_req == "1"))
{
goto_page->execute("keyb_num");
disp1->set_component_value("keyb_num.page_id", 23); //Calling from Alarm page
disp1->set_component_text("keyb_num.domain", page.c_str());
disp1->set_component_text("keyb_num.key", key.c_str());
disp1->set_component_text("keyb_num.value", value.c_str());
disp1->set_component_text("keyb_num.entity", entity.c_str());
disp1->set_component_text("keyb_num.title", title.c_str());
}
else service_call_alarm_control_panel->execute(entity.c_str(), key.c_str(), code_format.c_str(), "");
// page based actions
if (json_cmp_string(page, "alarm")) {
const cJSON* code_format = cJSON_GetObjectItemCaseSensitive(json, "code_format");
const cJSON* code_arm_req = cJSON_GetObjectItemCaseSensitive(json, "code_arm_req");
const cJSON* title = cJSON_GetObjectItemCaseSensitive(json, "mui");
if (json_cmp_string(code_format, "number") and (json_cmp_string(key, "disarm") or json_cmp_string(code_arm_req, "1"))) {
goto_page->execute("keyb_num");
disp1->set_component_value("keyb_num.page_id", 23); //Calling from Alarm page
disp1->set_component_text("keyb_num.domain", page->valuestring);
disp1->set_component_text("keyb_num.key", key->valuestring);
disp1->set_component_text("keyb_num.value", value->valuestring);
disp1->set_component_text("keyb_num.entity", detailed_entity->state.c_str());
disp1->set_component_text("keyb_num.title", title->valuestring);
} else service_call_alarm_control_panel->execute(detailed_entity->state.c_str(), key->valuestring, code_format->valuestring, "");
} else if (json_cmp_string(page, "climate")) {
change_climate_state->execute((embedded != NULL and cJSON_IsNumber(embedded) and embedded->valueint == 1), key->valuestring, value->valuestring);
} else if (json_cmp_string(page, "cover")) {
if (json_cmp_string(key, "position")) ha_call_service->execute("cover.set_cover_position", key->valuestring, value->valuestring, detailed_entity->state.c_str());
else ha_call_service->execute((std::string("cover.") + key->valuestring), "", "", detailed_entity->state.c_str());
} else if (json_cmp_string(page, "fan")) {
if (json_cmp_string(key, "stop") or json_cmp_string(value, "0") == 0) ha_call_service->execute("fan.turn_off", "", "", detailed_entity->state.c_str());
else ha_call_service->execute("fan.turn_on", key->valuestring, value->valuestring, detailed_entity->state.c_str());
} else if (json_cmp_string(page, "keyb_num") == 0) {
const cJSON* base_domain = cJSON_GetObjectItemCaseSensitive(json, "base_domain");
if (json_cmp_string(base_domain, "alarm")) {
const cJSON* code_format = cJSON_GetObjectItemCaseSensitive(json, "code_format");
const cJSON* pin = cJSON_GetObjectItemCaseSensitive(json, "pin");
service_call_alarm_control_panel->execute(detailed_entity->state.c_str(), key->valuestring, code_format->valuestring, pin->valuestring);
}
goto_page->execute((base_domain != NULL && cJSON_IsString(base_domain)) ? base_domain->valuestring : "home");
}
else if (page == "climate") {
change_climate_state->execute((embedded==1), key.c_str(), value.c_str());
}
else if (page == "cover") {
if (key == "position") ha_call_service->execute("cover.set_cover_position", key.c_str(), value.c_str(), entity.c_str());
else ha_call_service->execute((std::string("cover.") + key.c_str()), "", "", entity.c_str());
}
else if (page == "fan") {
if (key == "stop" or value == "0") ha_call_service->execute("fan.turn_off", "", "", entity.c_str());
else ha_call_service->execute("fan.turn_on", key.c_str(), value.c_str(), entity.c_str());
}
else if (page == "keyb_num") {
std::string base_domain = doc["base_domain"];
if (base_domain == "alarm") {
std::string code_format = doc["code_format"];
std::string pin = doc["pin"];
service_call_alarm_control_panel->execute(entity.c_str(), key.c_str(), code_format.c_str(), pin.c_str());
else if (json_cmp_string(page, "light")) ha_call_service->execute("light.turn_on", key->valuestring, value->valuestring, detailed_entity->state.c_str());
else if (json_cmp_string(page, "media_player")) {
if (json_cmp_string(key, "volume_mute"))
ha_call_service->execute("media_player.volume_mute", "is_volume_muted", value->valuestring, detailed_entity->state.c_str());
else if (json_cmp_string(key, "volume_set"))
ha_call_service->execute("media_player.volume_set", "volume_level", json_percentage_to_float_string(value).c_str()), detailed_entity->state.c_str());
else if ((key != NULL and key->valuestring != NULL and key->valuestring[0] != '\0'))
ha_call_service->execute((std::string("media_player.") + key->valuestring), "", "", detailed_entity->state.c_str());
}
else if (base_domain == "" or base_domain.empty()) base_domain = "home";
goto_page->execute(base_domain.c_str());
}
else if (page == "light") ha_call_service->execute("light.turn_on", key.c_str(), value.c_str(), entity.c_str());
else if (page == "media_player") {
if (key == "volume_mute") ha_call_service->execute("media_player.volume_mute", "is_volume_muted", value.c_str(), entity.c_str());
else if (key == "volume_set") ha_call_service->execute("media_player.volume_set", "volume_level", to_string(stof(value) / 100), entity.c_str());
else if (not key.empty()) ha_call_service->execute((std::string("media_player.") + key.c_str()), "", "", entity.c_str());
cJSON_Delete(json);
}
##### Versioning #####

View File

@@ -1,440 +0,0 @@
Page utilities2
Attributes
ID : 0
Scope : local
Dragging : 0
Send Component ID : on press and release
Locked : no
Swide up page ID : disabled
Swide down page ID : disabled
Swide left page ID : disabled
Swide right page ID: disabled
Events
Preinitialize Event
if(api==0)
{
page home
}
vis unavailable,0
Postinitialize Event
sendme
Text title
Attributes
ID : 1
Scope : local
Dragging : 0
Send Component ID : on press and release
Associated Keyboard: none
Text : Power Dashboard
Max. Text Size : 100
Text title_icon
Attributes
ID : 2
Scope : local
Dragging : 0
Send Component ID : on press and release
Associated Keyboard: none
Text : 
Max. Text Size : 10
Text unavailable
Attributes
ID : 5
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text :
Max. Text Size : 1
Text t1
Attributes
ID : 6
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 賈
Max. Text Size : 4
Text t2
Attributes
ID : 7
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 
Max. Text Size : 4
Text t3
Attributes
ID : 8
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 
Max. Text Size : 4
Text t4
Attributes
ID : 9
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Green
Max. Text Size : 10
Text t5
Attributes
ID : 10
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Fossil
Max. Text Size : 10
Text t7
Attributes
ID : 13
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 全
Max. Text Size : 4
Text t8
Attributes
ID : 14
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Solar
Max. Text Size : 10
Text t9
Attributes
ID : 16
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 98%
Max. Text Size : 10
Text t10
Attributes
ID : 17
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 2%
Max. Text Size : 10
Text t11
Attributes
ID : 18
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 豈
Max. Text Size : 4
Text t12
Attributes
ID : 19
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Battery
Max. Text Size : 10
Text t13
Attributes
ID : 21
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 暑
Max. Text Size : 4
Text t14
Attributes
ID : 22
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Heating
Max. Text Size : 10
Text t15
Attributes
ID : 24
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 1.7 kW
Max. Text Size : 10
Text t16
Attributes
ID : 25
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 21.7°C
Max. Text Size : 10
Text t17
Attributes
ID : 26
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 1.1 kW
Max. Text Size : 10
Text t18
Attributes
ID : 27
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : -2.1 kW
Max. Text Size : 10
Text t19
Attributes
ID : 28
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 0.8 kW
Max. Text Size : 10
Text t20
Attributes
ID : 29
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 慎
Max. Text Size : 4
Text t21
Attributes
ID : 30
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Wind
Max. Text Size : 10
Text t22
Attributes
ID : 32
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 1.1 kW
Max. Text Size : 10
Text t23
Attributes
ID : 33
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : î—°
Max. Text Size : 4
Text t24
Attributes
ID : 34
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Car
Max. Text Size : 10
Text t25
Attributes
ID : 36
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 1.1 kW
Max. Text Size : 10
Text t0
Attributes
ID : 37
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : î—°
Max. Text Size : 4
Text t6
Attributes
ID : 38
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : Car
Max. Text Size : 10
Text t26
Attributes
ID : 40
Scope : local
Dragging : 0
Send Component ID : disabled
Associated Keyboard: none
Text : 1.1 kW
Max. Text Size : 10
Slider h1
Attributes
ID : 11
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Slider h2
Attributes
ID : 12
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Slider h3
Attributes
ID : 15
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Slider h4
Attributes
ID : 20
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Slider h5
Attributes
ID : 23
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Slider h6
Attributes
ID : 31
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Slider h7
Attributes
ID : 35
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Slider h0
Attributes
ID : 39
Scope : local
Dragging : 0
Send Component ID: disabled
Position : 50
Upper range limit: 100
Lower range limit: 0
Button button_back
Attributes
ID : 3
Scope : local
Dragging : 0
Send Component ID: on press and release
State : unpressed
Text : î…˜
Max. Text Size : 3
Events
Touch Press Event
page back_page_id
Timer wakeup_timer
Attributes
ID : 4
Scope : local
Period (ms): 100
Enabled : yes
Events
Timer Event
if(dim<brightness)
{
dimdelta=brightness-dim
dimdelta/=10
if(dimdelta<1)
{
dimdelta=1
}
dim+=dimdelta
}else
{
wakeup_timer.en=0
}

View File

@@ -96,7 +96,7 @@ Text tft_version
Dragging : 0
Send Component ID : on press and release
Associated Keyboard: none
Text : 4.3.1
Text : 4.3.2d1
Max. Text Size : 9
Text esph_version

View File

@@ -83,15 +83,6 @@ Text indr_temp
Text :
Max. Text Size : 8
Events
Touch Release Event
printh 92
prints "localevent",0
printh 00
prints "{\"page\": \"home\", \"component\": \"climate\", \"event\": \"click\"}",0
printh 00
printh FF FF FF
Text outdoor_temp
Attributes
ID : 5
@@ -326,15 +317,6 @@ Text indr_temp_icon
Text :
Max. Text Size : 3
Events
Touch Release Event
printh 92
prints "localevent",0
printh 00
prints "{\"page\": \"home\", \"component\": \"climate\", \"event\": \"click\"}",0
printh 00
printh FF FF FF
Text bt_notific
Attributes
ID : 28

View File

@@ -383,7 +383,7 @@ Picture colorwheel
covx b,va3.txt,0,0
lightsetting.txt="{\"page\": \"light\", \"component\": \"rgb_color\", \"value\": ["+va1.txt+", "+va2.txt+", "+va3.txt+"]}"
printh 92
prints "nspanelevent",0
prints "localevent",0
printh 00
prints lightsetting.txt,0
printh 00

View File

@@ -96,7 +96,7 @@ Text tft_version
Dragging : 0
Send Component ID : on press and release
Associated Keyboard: none
Text : 4.3.1
Text : 4.3.2d1
Max. Text Size : 9
Events

View File

@@ -83,15 +83,6 @@ Text indr_temp
Text :
Max. Text Size : 8
Events
Touch Release Event
printh 92
prints "localevent",0
printh 00
prints "{\"page\": \"home\", \"component\": \"climate\", \"event\": \"click\"}",0
printh 00
printh FF FF FF
Text outdoor_temp
Attributes
ID : 5
@@ -326,15 +317,6 @@ Text indr_temp_icon
Text :
Max. Text Size : 3
Events
Touch Release Event
printh 92
prints "localevent",0
printh 00
prints "{\"page\": \"home\", \"component\": \"climate\", \"event\": \"click\"}",0
printh 00
printh FF FF FF
Text bt_notific
Attributes
ID : 28

View File

@@ -383,7 +383,7 @@ Picture colorwheel
covx b,va3.txt,0,0
lightsetting.txt="{\"page\": \"light\", \"component\": \"rgb_color\", \"value\": ["+va1.txt+", "+va2.txt+", "+va3.txt+"]}"
printh 92
prints "nspanelevent",0
prints "localevent",0
printh 00
prints lightsetting.txt,0
printh 00

View File

@@ -96,7 +96,7 @@ Text tft_version
Dragging : 0
Send Component ID : on press and release
Associated Keyboard: none
Text : 4.3.1
Text : 4.3.2d1
Max. Text Size : 9
Text esph_version

View File

@@ -83,15 +83,6 @@ Text indr_temp
Text :
Max. Text Size : 8
Events
Touch Release Event
printh 92
prints "localevent",0
printh 00
prints "{\"page\": \"home\", \"component\": \"climate\", \"event\": \"click\"}",0
printh 00
printh FF FF FF
Text outdoor_temp
Attributes
ID : 5
@@ -326,15 +317,6 @@ Text indr_temp_icon
Text :
Max. Text Size : 3
Events
Touch Release Event
printh 92
prints "localevent",0
printh 00
prints "{\"page\": \"home\", \"component\": \"climate\", \"event\": \"click\"}",0
printh 00
printh FF FF FF
Text bt_notific
Attributes
ID : 28

View File

@@ -383,7 +383,7 @@ Picture colorwheel
covx b,va3.txt,0,0
lightsetting.txt="{\"page\": \"light\", \"component\": \"rgb_color\", \"value\": ["+va1.txt+", "+va2.txt+", "+va3.txt+"]}"
printh 92
prints "nspanelevent",0
prints "localevent",0
printh 00
prints lightsetting.txt,0
printh 00

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.