"
+ "%s | " // name
+ "%s | " // sbatt (Battery Indicator)
+ "" // slqi
+ "\0"
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //=ZB_WEB_BATTERY
+ " "
+ "\0"
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //=ZB_WEB_LAST_SEEN
+ " 🕗%02d%c"
+ "\0"
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //=ZB_WEB_COLOR_RGB
+ " #%02X%02X%02X"
+ "\0"
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //=ZB_WEB_LINE_START
+ " | ┆"
+ "\0"
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //=ZB_WEB_LIGHT_CT
+ " ⚪ %dK"
+ "\0"
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //=ZB_WEB_END_STATUS
+ " | " // Close LQI
+ "%s{e}" // dhm (Last Seen)
+ "\0"
+ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ //=ZB_WEB_LINE_END
+ "" // Close LQI
+ "%s{e}" // dhm (Last Seen)
+ "\0"
+ ; // end of list
+
+// Use the tool at https://tasmota.hadinger.fr/util and choose "Compress Strings template with Unishox"
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// ++++++++++++++++++++ DO NOT EDIT BELOW ++++++++++++++++++++
+// ++++++++++++++++++++vvvvvvvvvvvvvvvvvvv++++++++++++++++++++
+enum {
+ ZB_WEB_CSS=0,
+ ZB_WEB_PERMITJOIN_ACTIVE=512,
+ ZB_WEB_VIS_JS_BEFORE=566,
+ ZB_WEB_VIS_JS_AFTER=1039,
+ ZB_WEB_AUTO_REFRESH=1103,
+ ZB_WEB_MAP_REFRESH=1169,
+ ZB_WEB_STATUS_LINE=1235,
+ ZB_WEB_BATTERY=1344,
+ ZB_WEB_LAST_SEEN=1394,
+ ZB_WEB_COLOR_RGB=1442,
+ ZB_WEB_LINE_START=1502,
+ ZB_WEB_LIGHT_CT=1542,
+ ZB_WEB_END_STATUS=1597,
+ ZB_WEB_LINE_END=1614,
+};
+
+// Compressed from 1631 to 1109, -32.0%
+const char ZB_WEB[] PROGMEM = "\x00\x66\x3D\x0E\xCA\xB1\xC1\x33\xF0\xF6\xD1\xEE\x3D\x3D\x46\x41\x33\xF0\xE8\x6D"
+ "\xA1\x15\x08\x79\xF6\x51\xDD\x3C\xCC\x6F\xFD\x47\x58\x62\xB4\x21\x0E\xF1\xED\x1F"
+ "\xD1\x28\x51\xE6\x72\x99\x0C\x36\x1E\x0C\x67\x51\xD7\xED\x36\xB3\xCC\xE7\x99\xF4"
+ "\x7D\x1E\xE2\x04\x3C\x40\x2B\x04\x3C\x28\x10\xB0\x93\x99\xA4\x30\xD8\x08\x36\x8E"
+ "\x83\xA8\xF6\x8D\xBF\x8F\x6F\x1D\x7F\xD1\xE1\x54\x79\x9C\x8C\x86\x1B\x0F\x07\xB8"
+ "\xE8\x2A\x2B\xBE\x7B\x42\xDE\x67\x58\xA7\xA3\xC2\xA8\xF3\x39\x4C\x86\x1B\x0F\x71"
+ "\xD0\x71\xB0\xF6\x82\x14\xC3\x93\x08\x61\xB0\xF0\x08\x39\x49\xC9\x84\x30\xD8\x78"
+ "\x13\x7C\x30\x2B\x32\x3C\xF7\x82\xDE\x67\x58\xE0\xB0\x33\x43\xC0\xEC\xF8\x8F\xE7"
+ "\x99\xC8\x43\x0D\x8B\xD8\x16\x88\x83\x17\xFF\xBE\xA2\x0F\x02\xCF\x9E\x07\x58\x66"
+ "\x83\xDF\xC1\x7C\x21\xD6\x1E\x05\x9F\x3C\xCC\xEF\xE7\x74\xEB\x3A\xC3\x08\xEA\x3C"
+ "\x8C\x18\x30\x77\x8F\x71\xD3\xDE\xD3\xDA\x09\x59\xA1\x80\x99\xB0\xF1\x61\x68\xF7"
+ "\x1D\x7B\x4C\x6F\x8F\x33\x01\x33\x61\xD6\xF8\x43\xC0\x21\xEE\x87\x34\x86\x1B\x0F"
+ "\x03\x2C\x41\x37\x87\x8F\x33\x8C\xF7\x1D\x0B\xDE\xD5\xA0\x85\xC2\x91\xCB\x21\x86"
+ "\xC3\xC0\x24\xF0\x90\x30\xD8\x08\x5C\x2A\x01\x1D\x7F\xB1\x34\x5F\x8F\x33\x96\x43"
+ "\x0D\x80\x9B\xBA\x1E\x4D\xB0\x41\xC9\x8E\x83\x8E\x32\x04\x3E\x17\x4E\x56\x9F\x47"
+ "\xD1\x02\x1D\x13\x90\x81\x0E\x89\xCD\x64\x08\xB4\x4E\x51\x02\x1D\x13\x9E\x20\x46"
+ "\xC1\x8E\x59\x02\x27\x13\x87\x1B\x3E\x8F\xA3\xDC\x74\x2C\x39\x6C\xF6\x96\x0C\xB0"
+ "\xF6\x8C\x8F\x33\xA1\xCB\x3D\xC7\xA1\xD8\x40\x83\xCA\x4C\xE1\x7C\xF4\x18\x7E\x1E"
+ "\x83\x8F\xC3\xDE\x47\xA7\x86\x5F\x2F\x51\x90\x4C\xF8\x7D\x82\x16\xD4\x71\xFD\x9E"
+ "\x0F\xB3\xF0\xFA\x2F\x1E\x87\x67\x86\x5F\x1F\x88\xF7\xCF\x43\xB0\x71\xF8\x7A\x1D"
+ "\x83\x0F\xC9\xC2\xF9\xE9\xE0\xFF\xA3\x29\x51\x90\xC6\x7C\x3D\x94\xCD\x94\x76\x1A"
+ "\xEC\xCE\xC1\x06\x91\xEC\x5E\xF8\x67\xC3\xD8\x2A\x2B\xA8\x67\x8F\x33\xB0\xEC\x17"
+ "\xC3\x0D\x07\x8E\x81\xE0\xD3\xB0\xCF\x7C\x75\xF3\xA1\xFC\xF9\xA1\xD9\xEA\xBE\x12"
+ "\xC2\xCE\x67\x60\xB1\xA2\x02\x3D\x73\xA0\xDD\xE3\xA1\xAF\xC7\xB0\xFC\x3D\x0E\xC0"
+ "\x41\xCB\x0F\xC3\xD0\x4D\x33\x5A\x21\xF0\xF6\x0D\x32\x04\x2C\x2A\x01\xF6\x02\x17"
+ "\x2A\x01\xC7\xB0\x13\x78\x9F\x30\x60\xC1\xE0\x10\xF8\x1C\x38\xD9\x02\x17\x32\xC7"
+ "\x3E\xD9\x0C\x36\x02\x1F\x22\xC7\x31\xB2\x04\x4E\x3A\xC1\x1B\x98\xF0\xB4\x78\x55"
+ "\x0F\x7E\xCC\x8F\x1F\x7E\xD3\x6B\x3C\xC7\x65\x0A\x3C\x1E\xC3\xF0\x85\xF5\x8E\x09"
+ "\xAA\xC4\x16\x58\x88\xCF\x7C\x74\x35\xF8\xF4\x3B\x04\xD3\x33\xF0\x16\x78\x63\x3F"
+ "\x0C\xEF\xE8\x3C\xEA\xBD\xE7\xF3\xE0\x98\x18\xB1\xAF\xA8\xE8\x3C\xE8\x98\x4C\x6B"
+ "\xEA\x21\xC6\x45\xA2\x1D\xD0\x46\xE0\xC8\xEF\x1E\x0C\xEF\xEB\x06\x56\xE7\x78\xF8"
+ "\x7B\x47\xBF\x82\xC6\x78\xF3\x3D\xB8\x79\x9E\xDF\x0A\xB1\x8C\xF3\x3D\x81\xEF\xC3"
+ "\x09\x9E\xC3\xA8\x10\x78\x3D\x3D\x87\x90\x87\x37\x4F\x61\xEE\x3A\x8B\xE0\x89\x70"
+ "\x76\x1B\x01\x16\xC9\x81\xC7\x3C\x7B\x0F\x71\xD4\x4C\x11\x2C\xB0\x82\xD1\x9E\x04"
+ "\x6C\x6A\xC4\x30\x7B\x0F\x71\xEE\x3D\xC7\x83\x3B\xFA\x12\xEA\xCF\x87\xB6\x70\xBE"
+ "\x08\x32\x41\x0B\x6C\x3E\x73\x1F\x46\x7B\xE3\xA1\x70\x20\xCC\x3B\xA0\x89\xC1\x49"
+ "\xD4\x25\xD5\x9D\x40\x85\xC0\x29\xDE\x3C\x02\x27\x20\xC0\x87\xCB\xA9\xF9\xE7\x45"
+ "\x5A\x35\xE0\xBA\x3B\xA6\x05\xF0\x75\xB9\xC7\x74\xEF\x1E\xD0\xB0\x3B\xAD\xCE\x3A"
+ "\x7D\x85\x96\x21\xDD\x3B\xC7\x83\xDC\x75\x1C\x89\x32\x04\x8C\x78\x61\xF8\x7A\x1D"
+ "\x83\x0F\xC3\xD0\xC6\x7C\x6A\xB0\xEB\x73\x8F\x87\xD9\xB4\x77\xCF\xB4\x35\xD0\xAC"
+ "\x10\xF8\x7D\x8F\x3A\x3E\xCF\xC3\xD0\x70\xBA\xAC\xE3\xF0\xFA\xF1\xE8\x76\x02\x14"
+ "\x73\xD0\xEC\x31\x9F\x1A\x7E\x4E\x17\xCF\x4A\xFA\x0C\x2B\xF7\x8F\x87\xD9\xB6\x84"
+ "\x42\xAB\xE7\xD9\xF8\x7A\x50\x87\xE1\xE8\x39\x56\xD0\x4C\xF8\x7D\x9C\x64\x6C\x3E"
+ "\x8E\x3C\x22\x36\x23\xEB\xC8\xEB\x47\xD7\x81\x07\xA0\x7E\x38\xFC\x3D\x0E\xCA\x10"
+ "\xFC\x3D\x28\x43\xF0\xFA\xF0\x22\x47\x3D\x04\xD3\x30\x43\xC4\x88\x22\x35\x16\xA3"
+ "\xEB\xC7\xD8\x21\xE7\x1E\xF6\x9F\x67\xE4\xE1\x7C\xF4\xD0\x42\x98\x7B\x07\x51\xEC"
+ "\x04\x2C\x18\xF6\x1F\x42\x1F\x47\xD0\x22\x73\xFE\x75\x9D\x63\x82\x3C\xCF\xA1\x06"
+ "\x1B\x0F\x61\xF8\x7A\x1D\x9A\x7E\x4E\x17\xCF\x4A\x10\x10\xEB\x82\x17\x40\x10\xFA"
+ "\x38\xE8\x8D\x87\xD1\xC7\x44\x6C\x3E\x8E\x3A\x23\x61\xEC\x3F\x0F\xD1\xE4\x6C\x39"
+ "\x08\x8C\x1C\xDD\xF1\xE0\xFA\x74\x42\x1F\x41\xCE\x17\xD0\x23\x67\xE6\xC0\x46\xCC"
+ "\x83\x08\xF3\x3C\x8F\xA3\x8E\x88\x8D\x87\xD1\xC7\x44\x46\xC3\xE8\xE3\xA2\x23\x60"
+ "\x20\xE7\x60\x91\x3C\x11\xF8\x67\x04\x3E\x18\xD0\x78\x17\x86\x5F\x1F\x0F\x61\xCC"
+ "\x3D\x87\xE1\xFA\x3C\x96\x7B\xE7\x82\x9C\x2F\x82\x17\x45\x6C\x10\xB8\x1B\x20\xCA"
+ "\x91\xF4\x21\xEC\x3F\x0F\x4F\x0D\xB0\x82\x3F\x0F\xD1\xE4\x71\x7D\x7C\xF0\x77\x0F"
+ "\x43\xB0\x81\x06\x61\xF4\x21\x1A\x02\x17\x45\xB6\x70\xBE\x08\x5D\x06\x23\xB2\x84"
+ "\x3F\x0F\xAF\x1E\xD6\x7B\x81\x32\x6C\xE1\x7C";
+
+// ++++++++++++++++++++^^^^^^^^^^^^^^^^^^^++++++++++++++++++++
+// ++++++++++++++++++++ DO NOT EDIT ABOVE ++++++++++++++++++++
+// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
extern "C" {
// comparator function used to sort Zigbee devices by alphabetical order (if friendlyname)
// then by shortaddr if they don't have friendlyname
@@ -1710,15 +1899,10 @@ extern "C" {
}
} // extern "C"
-#define WEB_HANDLE_ZB_MAP "Zigbee Map"
-#define WEB_HANDLE_ZB_PERMIT_JOIN "Zigbee Permit Join"
-#define WEB_HANDLE_ZB_MAP_REFRESH "Zigbee Map Refresh"
const char HTTP_BTN_ZB_BUTTONS[] PROGMEM =
- ""
+ ""
""
- "";
-const char HTTP_AUTO_REFRESH_PAGE[] PROGMEM = "";
-const char HTTP_BTN_ZB_MAP_REFRESH[] PROGMEM = "";
+ "";
void ZigbeeShow(bool json)
{
@@ -1726,26 +1910,13 @@ void ZigbeeShow(bool json)
return;
#ifdef USE_WEBSERVER
} else {
+ UnishoxStrings msg(ZB_WEB);
uint32_t zigbee_num = zigbee_devices.devicesSize();
if (!zigbee_num) { return; }
if (zigbee_num > 255) { zigbee_num = 255; }
- WSContentSend_P(PSTR("{t}")); // Terminate current two column table and open new table
- WSContentSend_P(PSTR(
- ""
- ));
+ WSContentSend_P(msg[ZB_WEB_CSS]);
+ // WSContentSend_compressed(ZB_WEB, 0);
// sort elements by name, then by id
uint8_t sorted_idx[zigbee_num];
@@ -1771,7 +1942,7 @@ void ZigbeeShow(bool json)
snprintf_P(sbatt, sizeof(sbatt), PSTR(" "));
if (device.validBatteryPercent()) {
snprintf_P(sbatt, sizeof(sbatt),
- PSTR(""),
+ msg[ZB_WEB_BATTERY],
device.batterypercent, changeUIntScale(device.batterypercent, 0, 100, 0, 14)
);
}
@@ -1786,12 +1957,8 @@ void ZigbeeShow(bool json)
snprintf_P(slqi, sizeof(slqi), PSTR("%d"), device.lqi);
}
- WSContentSend_PD(PSTR(
- " "
- "%s | " // name
- "%s | " // sbatt (Battery Indicator)
- "" // slqi
- ), shortaddr,
+ WSContentSend_PD(msg[ZB_WEB_STATUS_LINE],
+ shortaddr,
device.modelId ? device.modelId : "",
device.manufacturerId ? device.manufacturerId : "",
name, sbatt, slqi);
@@ -1808,15 +1975,12 @@ void ZigbeeShow(bool json)
uint8_t color;
uint16_t val = convert_seconds_to_dhm(now - device.last_seen, &unit, &color);
if (val < 100) {
- snprintf_P(dhm, sizeof(dhm), PSTR(" 🕗%02d%c"),
+ snprintf_P(dhm, sizeof(dhm), msg[ZB_WEB_LAST_SEEN],
color, color, color, val, unit);
}
}
- WSContentSend_PD(PSTR(
- " | " // Close LQI
- "%s{e}" // dhm (Last Seen)
- ), dhm );
+ WSContentSend_PD(msg[ZB_WEB_END_STATUS], dhm );
// Sensors
const Z_Data_Thermo & thermo = device.data.find ();
@@ -1829,7 +1993,7 @@ void ZigbeeShow(bool json)
bool validPressure = thermo.validPressure();
if (validTemp || validTempTarget || validThSetpoint || validHumidity || validPressure) {
- WSContentSend_P(PSTR("┆"));
+ WSContentSend_P(msg[ZB_WEB_LINE_START]);
if (validTemp) {
char buf[12];
dtostrf(thermo.getTemperature() / 100.0f, 3, 1, buf);
@@ -1865,7 +2029,7 @@ void ZigbeeShow(bool json)
if (onoff_display || light_display || plug_voltage || plug_power) {
int8_t channels = device.getLightChannels();
if (channels < 0) { channels = 5; } // if number of channel is unknown, display all known attributes
- WSContentSend_P(PSTR(" | ┆"));
+ WSContentSend_P(msg[ZB_WEB_LINE_START]);
if (onoff_display) {
WSContentSend_P(PSTR(" %s"), onoff.getPower() ? PSTR(D_ON) : PSTR(D_OFF));
}
@@ -1875,17 +2039,17 @@ void ZigbeeShow(bool json)
}
if (light.validCT() && ((channels == 2) || (channels == 5))) {
uint32_t ct_k = (((1000000 / light.getCT()) + 25) / 50) * 50;
- WSContentSend_P(PSTR(" ⚪ %dK"), light.getCT(), ct_k);
+ WSContentSend_P(msg[ZB_WEB_LIGHT_CT], light.getCT(), ct_k);
}
if (light.validHue() && light.validSat() && (channels >= 3)) {
uint8_t r,g,b;
uint8_t sat = changeUIntScale(light.getSat(), 0, 254, 0, 255); // scale to 0..255
LightStateClass::HsToRgb(light.getHue(), sat, &r, &g, &b);
- WSContentSend_P(PSTR(" #%02X%02X%02X"), r,g,b,r,g,b);
+ WSContentSend_P(msg[ZB_WEB_COLOR_RGB], r,g,b,r,g,b);
} else if (light.validX() && light.validY() && (channels >= 3)) {
uint8_t r,g,b;
LightStateClass::XyToRgb(light.getX() / 65535.0f, light.getY() / 65535.0f, &r, &g, &b);
- WSContentSend_P(PSTR(" #%02X%02X%02X"), r,g,b,r,g,b);
+ WSContentSend_P(msg[ZB_WEB_COLOR_RGB], r,g,b,r,g,b);
}
}
if (plug_voltage || plug_power) {
@@ -1901,10 +2065,11 @@ void ZigbeeShow(bool json)
}
}
- WSContentSend_P(PSTR("{t}")); // Terminate current multi column table and open new table
+ WSContentSend_P(msg[ZB_WEB_LINE_END]); // Terminate current multi column table and open new table
if (zigbee.permit_end_time) {
// PermitJoin in progress
- WSContentSend_P(PSTR(" [ Devices allowed to join ] ")); // Terminate current multi column table and open new table
+
+ WSContentSend_P(msg[ZB_WEB_PERMITJOIN_ACTIVE], D_ZIGBEE_PERMITJOIN_ACTIVE);
}
#endif
}
@@ -1928,35 +2093,26 @@ void ZigbeeShowMap(void) {
ZigbeeMapAllDevices();
}
- WSContentStart_P(PSTR("Tasmota Zigbee Mapping"));
+ UnishoxStrings msg(ZB_WEB);
+ WSContentStart_P(PSTR(D_ZIGBEE_MAPPING_TITLE));
WSContentSendStyle();
if (zigbee.init_phase) {
- WSContentSend_P(PSTR("Zigbee not started"));
+ WSContentSend_P(PSTR(D_ZIGBEE_NOT_STARTED));
} else if (zigbee.mapping_in_progress) {
int32_t mapping_remaining = 1 + (zigbee.mapping_end_time - millis()) / 1000;
if (mapping_remaining < 0) { mapping_remaining = 0; }
- WSContentSend_P(PSTR("Mapping in progress (%d s. remaining)"), mapping_remaining);
- WSContentSend_P(HTTP_AUTO_REFRESH_PAGE);
+ WSContentSend_P(PSTR(D_ZIGBEE_MAPPING_IN_PROGRESS_SEC), mapping_remaining);
+ WSContentSend_P(msg[ZB_WEB_AUTO_REFRESH]);
} else if (!zigbee.mapping_ready) {
- WSContentSend_P(PSTR("No mapping"));
+ WSContentSend_P(PSTR(D_ZIGBEE_MAPPING_NOT_PRESENT));
} else {
- WSContentSend_P(PSTR(
- ""
- "Unable to load vis.js "
- ""
- ));
- WSContentSend_P(HTTP_BTN_ZB_MAP_REFRESH);
+ WSContentSend_P(msg[ZB_WEB_VIS_JS_AFTER]);
+ WSContentSend_P(msg[ZB_WEB_MAP_REFRESH], PSTR(D_ZIGBEE_MAP_REFRESH));
}
WSContentSpaceButton(BUTTON_MAIN);
WSContentStop();
| | |