diff --git a/README.md b/README.md index 2112fb62..c465dd12 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ ESPurna ("spark" in Catalan) is a custom firmware for ESP8285/ESP8266 based smar It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries. [![version](https://img.shields.io/badge/version-1.13.3a-brightgreen.svg)](CHANGELOG.md) -[![branch](https://img.shields.io/badge/branch-dev-orange.svg)](https://github.com/xoseperez/espurna/tree/dev/) -[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=dev)](https://travis-ci.org/xoseperez/espurna) +[![branch](https://img.shields.io/badge/branch-dev-orange.svg)](https://github.com/ColinShorts/espurna.git/tree/dev/) +[![travis](https://travis-ci.org/ColinShorts/espurna.git.svg?branch=dev)](https://travis-ci.org/ColinShorts/espurna.git) [![codacy](https://api.codacy.com/project/badge/Grade/c9496e25cf07434cba786b462cb15f49)](https://www.codacy.com/app/xoseperez/espurna/dashboard) [![license](https://img.shields.io/github/license/xoseperez/espurna.svg)](LICENSE)
diff --git a/code/espurna/config/all.h b/code/espurna/config/all.h index 03d55c92..d734e0ba 100644 --- a/code/espurna/config/all.h +++ b/code/espurna/config/all.h @@ -35,7 +35,3 @@ #include "sensors.h" #include "webui.h" #include "progmem.h" - -#ifdef USE_CORE_VERSION_H -#include "core_version.h" -#endif diff --git a/code/espurna/config/arduino.h b/code/espurna/config/arduino.h index cc5810d3..0d0c4de8 100644 --- a/code/espurna/config/arduino.h +++ b/code/espurna/config/arduino.h @@ -98,6 +98,7 @@ //#define XIAOMI_SMART_DESK_LAMP //#define ALLTERCO_SHELLY2 //#define PHYX_ESP12_RGB +//#define IWOOLE_LED_TABLE_LAMP //-------------------------------------------------------------------------------- // Features (values below are non-default values) diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index b1d8df90..256a0f11 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -2765,6 +2765,30 @@ #define LIGHT_CH2_INVERSE 0 #define LIGHT_CH3_INVERSE 0 +// ----------------------------------------------------------------------------- +// iWoole LED Table Lamp +// http://iwoole.com/newst-led-smart-night-light-7w-smart-table-light-rgbw-wifi-app-remote-control-110v-220v-us-eu-plug-smart-lamp-google-home-decore-p00022p1.html +// ----------------------------------------------------------------------------- + +#elif defined(IWOOLE_LED_TABLE_LAMP) + + // Info + #define MANUFACTURER "IWOOLE" + #define DEVICE "LED_TABLE_LAMP" + #define RELAY_PROVIDER RELAY_PROVIDER_LIGHT + #define LIGHT_PROVIDER LIGHT_PROVIDER_DIMMER + #define DUMMY_RELAY_COUNT 1 + + // Light + #define LIGHT_CHANNELS 4 + #define LIGHT_CH1_PIN 12 // RED + #define LIGHT_CH2_PIN 5 // GREEN + #define LIGHT_CH3_PIN 14 // BLUE + #define LIGHT_CH4_PIN 4 // WHITE + #define LIGHT_CH1_INVERSE 0 + #define LIGHT_CH2_INVERSE 0 + #define LIGHT_CH3_INVERSE 0 + #define LIGHT_CH4_INVERSE 0 // ----------------------------------------------------------------------------- // TEST boards (do not use!!) diff --git a/code/espurna/config/prototypes.h b/code/espurna/config/prototypes.h index 4cc80db9..d8cf3430 100644 --- a/code/espurna/config/prototypes.h +++ b/code/espurna/config/prototypes.h @@ -2,6 +2,7 @@ #include #include #include +#include extern "C" { #include "user_interface.h" @@ -35,6 +36,25 @@ extern "C" { void custom_crash_callback(struct rst_info*, uint32_t, uint32_t); } +// Core version 2.4.2 and higher changed the cont_t structure to a pointer: +// https://github.com/esp8266/Arduino/commit/5d5ea92a4d004ab009d5f642629946a0cb8893dd#diff-3fa12668b289ccb95b7ab334833a4ba8L35 +// Core version 2.5.0 introduced EspClass helper method: +// https://github.com/esp8266/Arduino/commit/0e0e34c614fe8a47544c9998201b1d9b3c24eb18 +extern "C" { + #include +#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) \ + || defined(ARDUINO_ESP8266_RELEASE_2_4_0) \ + || defined(ARDUINO_ESP8266_RELEASE_2_4_1) + extern cont_t g_cont; + #define getFreeStack() cont_get_free_stack(&g_cont) +#elif defined(ARDUINO_ESP8266_RELEASE_2_4_2) + extern cont_t* g_pcont; + #define getFreeStack() cont_get_free_stack(g_pcont) +#else + #define getFreeStack() ESP.getFreeContStack() +#endif +} + // ----------------------------------------------------------------------------- // Domoticz // ----------------------------------------------------------------------------- diff --git a/code/espurna/migrate.ino b/code/espurna/migrate.ino index 2f1009d2..806a82e5 100644 --- a/code/espurna/migrate.ino +++ b/code/espurna/migrate.ino @@ -1189,6 +1189,21 @@ void migrate() { setSetting("chLogic", 1, 0); setSetting("chLogic", 3, 0); + #elif defined(IWOOLE_LED_TABLE_LAMP) + + setSetting("board", 90); + setSetting("relayProvider", RELAY_PROVIDER_LIGHT); + setSetting("lightProvider", LIGHT_PROVIDER_DIMMER); + setSetting("chGPIO", 0, 12); + setSetting("chGPIO", 1, 5); + setSetting("chGPIO", 2, 14); + setSetting("chGPIO", 3, 4); + setSetting("chLogic", 0, 0); + setSetting("chLogic", 1, 0); + setSetting("chLogic", 2, 0); + setSetting("chLogic", 3, 0); + setSetting("relays", 1); + #else // Allow users to define new settings without migration config diff --git a/code/espurna/utils.ino b/code/espurna/utils.ino index 16cf7a47..fc156f0d 100644 --- a/code/espurna/utils.ino +++ b/code/espurna/utils.ino @@ -6,11 +6,6 @@ Copyright (C) 2017-2018 by Xose Pérez */ -extern "C" { - #include - extern cont_t g_cont; -} - #include Ticker _defer_reset; @@ -81,10 +76,6 @@ unsigned int getUsedHeap() { return getInitialFreeHeap() - getFreeHeap(); } -unsigned int getFreeStack() { - return cont_get_free_stack(&g_cont); -} - String getEspurnaModules() { return FPSTR(espurna_modules); } diff --git a/code/html/custom.css b/code/html/custom.css index 6f03f475..af494464 100644 --- a/code/html/custom.css +++ b/code/html/custom.css @@ -50,10 +50,6 @@ h2 { display: block; } -.content { - margin: 0; -} - .page { margin-top: 10px; } @@ -98,16 +94,12 @@ div.center { display: none; } -#credentials { - font-size: 200%; - height: 100px; - left: 50%; - margin-left: -200px; - margin-top: -50px; - position: fixed; - text-align: center; - top: 50%; - width: 400px; +.content #password { + margin: 0 auto; +} + +.content #layout { + margin: 0; } div.state { @@ -206,6 +198,10 @@ div.state { background: rgb(255, 128, 0); /* orange */ } +.button-generate-password { + background: rgb(66, 184, 221); /* blue */ +} + .button-upgrade-browse, .button-clear-filters, .button-clear-messages, @@ -448,3 +444,53 @@ table.dataTable.display tbody td { height: 400px; margin-bottom: 10px; } + +/* ----------------------------------------------------------------------------- + Password input controls + -------------------------------------------------------------------------- */ +.password-reveal { + font-family: EmojiSymbols,Segoe UI Symbol; + background: rgba(0,0,0,0); + display: inline-block; + float: right; + z-index: 50; + margin-top: 6px; + margin-left: -30px; + vertical-align: middle; + font-size: 1.2em; + height: 100%; +} + +.password-reveal:after { + content: "👁"; +} + +input[type="password"] + .password-reveal { + color: rgba(205, 205, 205, 0.3); +} + +input[type="text"] + .password-reveal { + color: rgba(66, 184, 221, 0.8); +} + +.no-select { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +input::-ms-clear, +input::-ms-reveal { + display: none; +} + +/* css minifier must not combine these. + * style will not apply otherwise */ +input::-ms-input-placeholder { + color: #ccd; +} + +input::placeholder { + color: #ccc; +} diff --git a/code/html/custom.js b/code/html/custom.js index e0646b30..de0c5af7 100644 --- a/code/html/custom.js +++ b/code/html/custom.js @@ -146,8 +146,7 @@ function loadTimeZones() { } -function validateForm(form) { - +function validatePassword(password) { // http://www.the-art-of-web.com/javascript/validate-password/ // at least one lowercase and one uppercase letter or number // at least eight characters (letters, numbers or special characters) @@ -155,16 +154,26 @@ function validateForm(form) { // MUST be 8..63 printable ASCII characters. See: // https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#Target_users_(authentication_key_distribution) // https://github.com/xoseperez/espurna/issues/1151 + var re_password = /^(?=.*[A-Z\d])(?=.*[a-z])[\w~!@#$%^&*\(\)<>,.\?;:{}\[\]\\|]{8,63}$/; + return ( + (password !== undefined) + && (typeof password === "string") + && (password.length > 0) + && re_password.test(password) + ); +} + +function validateForm(form) { // password var adminPass1 = $("input[name='adminPass']", form).first().val(); - if (adminPass1.length > 0 && !re_password.test(adminPass1)) { + if (!validatePassword(adminPass1)) { alert("The password you have entered is not valid, it must be 8..63 characters and have at least 1 lowercase and 1 uppercase / number!"); return false; } - var adminPass2 = $("input[name='adminPass']", form).last().val(); + var adminPass2 = $("input[name='adminPass_confirm']", form).last().val(); if (adminPass1 !== adminPass2) { alert("Passwords are different!"); return false; @@ -225,6 +234,12 @@ function addValue(data, name, value) { "node", "key", "topic" ]; + + // join both adminPass and ..._confirm + if (name.startsWith("adminPass")) { + name = "adminPass"; + } + if (name in data) { if (!Array.isArray(data[name])) { data[name] = [data[name]]; @@ -260,26 +275,67 @@ function getData(form) { } -function randomString(length, chars) { - var mask = ""; - if (chars.indexOf("a") > -1) { mask += "abcdefghijklmnopqrstuvwxyz"; } - if (chars.indexOf("A") > -1) { mask += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } - if (chars.indexOf("#") > -1) { mask += "0123456789"; } - if (chars.indexOf("@") > -1) { mask += "ABCDEF"; } - if (chars.indexOf("!") > -1) { mask += "~`!@#$%^&*()_+-={}[]:\";'<>?,./|\\"; } - var result = ""; - for (var i = length; i > 0; --i) { - result += mask[Math.round(Math.random() * (mask.length - 1))]; +function randomString(length, args) { + if (typeof args === "undefined") { + args = { + lowercase: true, + uppercase: true, + numbers: true, + special: true + } } - return result; + + var mask = ""; + if (args.lowercase) { mask += "abcdefghijklmnopqrstuvwxyz"; } + if (args.uppercase) { mask += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } + if (args.numbers || args.hex) { mask += "0123456789"; } + if (args.hex) { mask += "ABCDEF"; } + if (args.special) { mask += "~`!@#$%^&*()_+-={}[]:\";'<>?,./|\\"; } + + var source = new Uint32Array(length); + var result = new Array(length); + + window.crypto.getRandomValues(source).forEach(function(value, i) { + result[i] = mask[value % mask.length]; + }); + + return result.join(""); } function generateAPIKey() { - var apikey = randomString(16, "@#"); + var apikey = randomString(16, {hex: true}); $("input[name='apiKey']").val(apikey); return false; } +function generatePassword() { + var password = ""; + do { + password = randomString(10); + } while (!validatePassword(password)); + + return password; +} + +function toggleVisiblePassword() { + var elem = this.previousElementSibling; + if (elem.type === "password") { + elem.type = "text"; + } else { + elem.type = "password"; + } + return false; +} + +function doGeneratePassword() { + $("input", $("#formPassword")) + .val(generatePassword()) + .each(function() { + this.type = "text"; + }); + return false; +} + function getJson(str) { try { return JSON.parse(str); @@ -476,11 +532,11 @@ function doReconnect(ask) { function doUpdate() { - var form = $("#formSave"); - if (validateForm(form)) { + var forms = $(".form-settings"); + if (validateForm(forms)) { // Get data - sendConfig(getData(form)); + sendConfig(getData(forms)); // Empty special fields $(".pwrExpected").val(0); @@ -753,6 +809,7 @@ function addNetwork() { $(this).attr("tabindex", tabindex); tabindex++; }); + $(".password-reveal", line).on("click", toggleVisiblePassword); $(line).find(".button-del-network").on("click", delNetwork); $(line).find(".button-more-network").on("click", moreNetwork); line.appendTo("#networks"); @@ -1575,12 +1632,15 @@ $(function() { createCheckboxes(); setInterval(function() { keepTime(); }, 1000); + $(".password-reveal").on("click", toggleVisiblePassword); + $("#menuLink").on("click", toggleMenu); $(".pure-menu-link").on("click", showPanel); $("progress").attr({ value: 0, max: 100 }); $(".button-update").on("click", doUpdate); $(".button-update-password").on("click", doUpdatePassword); + $(".button-generate-password").on("click", doGeneratePassword); $(".button-reboot").on("click", doReboot); $(".button-reconnect").on("click", doReconnect); $(".button-wifi-scan").on("click", doScan); diff --git a/code/html/index.html b/code/html/index.html index bde3aaa9..4d3b0cb5 100644 --- a/code/html/index.html +++ b/code/html/index.html @@ -28,40 +28,45 @@
-
+ -
+

SECURITY

-

Before using this device you have to change the default password for the user 'admin'. This password will be used for the AP mode hotspot, the web interface (where you are now) and the over-the-air updates.

+

Before using this device you have to change the default password for the user admin. This password will be used for the AP mode hotspot, the web interface (where you are now) and the over-the-air updates.

-
- - -
-
- The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).
- It must be 8..63 characters (numbers and letters and any of these special characters: _,.;:~!?@#$%^&*<>\|(){}[]) and have at least one lowercase and one uppercase or one number.
+ + +
- - + + +
+
-
- +
+
+ Password must be 8..63 characters (numbers and letters and any of these special characters: _,.;:~!?@#$%^&*<>\|(){}[]) and have at least one lowercase and one uppercase or one number.
+
+ + +
+ +
+ +
-
-
@@ -309,8 +314,7 @@
-
- +
@@ -382,7 +386,9 @@
+
+
@@ -414,8 +420,10 @@
+
- + +
@@ -501,8 +509,10 @@
- +
+ +
@@ -523,18 +533,18 @@
- + + +
+ + +
The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).
It must be 8..63 characters (numbers and letters and any of these special characters: _,.;:~!?@#$%^&*<>\|(){}[]) and have at least one lowercase and one uppercase or one number.
-
- - -
-
@@ -615,7 +625,9 @@
+ +
@@ -657,7 +669,9 @@
+
+
@@ -681,8 +695,10 @@
+
- + +
@@ -711,10 +727,12 @@
+
+
+
-

MESSAGES

@@ -753,8 +771,10 @@

- +
+ +
@@ -783,12 +803,13 @@
- +
- + +
@@ -873,7 +894,9 @@
+ +
@@ -917,7 +940,9 @@
+
+
@@ -964,7 +989,9 @@
+
+
@@ -1018,7 +1045,9 @@
+
+
@@ -1060,7 +1089,9 @@
+
+
@@ -1096,19 +1127,22 @@
- +
- + +
+
+
@@ -1140,8 +1174,10 @@
+
- + +
@@ -1297,9 +1333,11 @@
- +
+ - + +
@@ -1319,10 +1357,10 @@
-
- +
+
@@ -1363,7 +1401,8 @@
- + + @@ -1586,7 +1625,7 @@
-
+
diff --git a/code/ota.py b/code/ota.py index 0cd6a12c..a52ea7e0 100755 --- a/code/ota.py +++ b/code/ota.py @@ -15,6 +15,7 @@ import socket import subprocess import sys import time +import os from zeroconf import ServiceBrowser, ServiceStateChange, Zeroconf @@ -232,13 +233,24 @@ def boardname(board): def store(device, env): source = ".pioenvs/%s/firmware.elf" % env destination = ".pioenvs/elfs/%s.elf" % boardname(device).lower() + + dst_dir = os.path.dirname(destination) + if not os.path.exists(dst_dir): + os.mkdir(dst_dir) + shutil.move(source, destination) def run(device, env): print("Building and flashing image over-the-air...") - command = "ESPURNA_IP=\"%s\" ESPURNA_BOARD=\"%s\" ESPURNA_AUTH=\"%s\" ESPURNA_FLAGS=\"%s\" platformio run --silent --environment %s -t upload" - command = command % (device['ip'], device['board'], device['auth'], device['flags'], env) - subprocess.check_call(command, shell=True) + environ = os.environ.copy() + environ["ESPURNA_IP"] = device["ip"] + environ["ESPURNA_BOARD"] = device["board"] + environ["ESPURNA_AUTH"] = device["auth"] + environ["ESPURNA_FLAGS"] = device["flags"] + + command = ("platformio", "run", "--silent", "--environment", env, "-t", "upload") + subprocess.check_call(command, env=environ) + store(device, env) # ------------------------------------------------------------------------------- @@ -308,6 +320,8 @@ if __name__ == '__main__': if len(queue) == 0: sys.exit(0) + queue = sorted(queue, key=lambda device: device.get('board', '')) + # Flash eash board for board in queue: @@ -315,7 +329,7 @@ if __name__ == '__main__': if args.core > 0: board['flags'] = "-DESPURNA_CORE " + board['flags'] - env = "esp8266-%sm-ota" % board['size'] + env = "esp8266-%dm-ota" % board['size'] # Summary print() diff --git a/code/platformio.ini b/code/platformio.ini index 24cbf693..d00c48d1 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -18,6 +18,7 @@ platform_150 = espressif8266@1.5.0 platform_160 = espressif8266@1.6.0 platform_173 = espressif8266@1.7.3 platform_180 = espressif8266@1.8.0 +platform_latest = ${common.platform_180} platform = ${common.platform_150} # ------------------------------------------------------------------------------ @@ -193,7 +194,7 @@ monitor_speed = ${common.monitor_speed} extra_scripts = ${common.extra_scripts} [env:travis02] -platform = ${common.platform_173} +platform = ${common.platform_latest} framework = ${common.framework} board = ${common.board_4m} board_build.flash_mode = ${common.flash_mode} @@ -204,7 +205,7 @@ monitor_speed = ${common.monitor_speed} extra_scripts = ${common.extra_scripts} [env:travis03] -platform = ${common.platform_173} +platform = ${common.platform_latest} framework = ${common.framework} board = ${common.board_4m} board_build.flash_mode = ${common.flash_mode} @@ -2202,6 +2203,32 @@ upload_port = ${common.upload_port} upload_flags = ${common.upload_flags} extra_scripts = ${common.extra_scripts} +[env:iwoole-led-table-lamp] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board_1m} +board_build.flash_mode = ${common.flash_mode} +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m0m} -DIWOOLE_LED_TABLE_LAMP +monitor_speed = ${common.monitor_speed} +extra_scripts = ${common.extra_scripts} + +[env:iwoole-led-table-lamp-ota] +platform = ${common.platform} +framework = ${common.framework} +board = ${common.board_1m} +board_build.flash_mode = ${common.flash_mode} +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +build_flags = ${common.build_flags_1m0m} -DIWOOLE_LED_TABLE_LAMP +upload_speed = ${common.upload_speed} +upload_port = ${common.upload_port} +upload_flags = ${common.upload_flags} +monitor_speed = ${common.monitor_speed} +extra_scripts = ${common.extra_scripts} + + # ------------------------------------------------------------------------------ # GENERIC OTA ENVIRONMENTS # ------------------------------------------------------------------------------ diff --git a/images/devices/aithinker-ai-light.jpg b/images/devices/aithinker-ai-light.jpg index 535c61de..584c3a9d 100644 Binary files a/images/devices/aithinker-ai-light.jpg and b/images/devices/aithinker-ai-light.jpg differ diff --git a/images/devices/arilux-al-lc01.jpg b/images/devices/arilux-al-lc01.jpg index de036d83..5de40342 100644 Binary files a/images/devices/arilux-al-lc01.jpg and b/images/devices/arilux-al-lc01.jpg differ diff --git a/images/devices/arilux-al-lc06.jpg b/images/devices/arilux-al-lc06.jpg index df173391..49451f55 100644 Binary files a/images/devices/arilux-al-lc06.jpg and b/images/devices/arilux-al-lc06.jpg differ diff --git a/images/devices/arilux-e27.jpg b/images/devices/arilux-e27.jpg index 3dbe44ab..2675a777 100644 Binary files a/images/devices/arilux-e27.jpg and b/images/devices/arilux-e27.jpg differ diff --git a/images/devices/authometion-lyt8266.jpg b/images/devices/authometion-lyt8266.jpg index 12f37544..851cd311 100644 Binary files a/images/devices/authometion-lyt8266.jpg and b/images/devices/authometion-lyt8266.jpg differ diff --git a/images/devices/electrodragon-wifi-iot.jpg b/images/devices/electrodragon-wifi-iot.jpg index 4d567edd..34abdcf1 100644 Binary files a/images/devices/electrodragon-wifi-iot.jpg and b/images/devices/electrodragon-wifi-iot.jpg differ diff --git a/images/devices/exs-wifi-relay-v31.jpg b/images/devices/exs-wifi-relay-v31.jpg index fda8d78c..4f8eeab4 100644 Binary files a/images/devices/exs-wifi-relay-v31.jpg and b/images/devices/exs-wifi-relay-v31.jpg differ diff --git a/images/devices/geiger_espurna_configuration.png b/images/devices/geiger_espurna_configuration.png index 1316084d..d85c4060 100644 Binary files a/images/devices/geiger_espurna_configuration.png and b/images/devices/geiger_espurna_configuration.png differ diff --git a/images/devices/geiger_espurna_status.png b/images/devices/geiger_espurna_status.png index 26bd8185..429c550c 100644 Binary files a/images/devices/geiger_espurna_status.png and b/images/devices/geiger_espurna_status.png differ diff --git a/images/devices/geiger_grafana_dashboard.png b/images/devices/geiger_grafana_dashboard.png index d997f7a4..5bc6765e 100644 Binary files a/images/devices/geiger_grafana_dashboard.png and b/images/devices/geiger_grafana_dashboard.png differ diff --git a/images/devices/geiger_scope_following_pulses.png b/images/devices/geiger_scope_following_pulses.png index 63fd5b5a..303b784d 100755 Binary files a/images/devices/geiger_scope_following_pulses.png and b/images/devices/geiger_scope_following_pulses.png differ diff --git a/images/devices/geiger_scope_single_pulse.png b/images/devices/geiger_scope_single_pulse.png index d5d38782..cdf8e2c2 100755 Binary files a/images/devices/geiger_scope_single_pulse.png and b/images/devices/geiger_scope_single_pulse.png differ diff --git a/images/devices/geiger_wiring_diagram.png b/images/devices/geiger_wiring_diagram.png index 730a0845..a07ba496 100644 Binary files a/images/devices/geiger_wiring_diagram.png and b/images/devices/geiger_wiring_diagram.png differ diff --git a/images/devices/generic-ag-l4-1.jpg b/images/devices/generic-ag-l4-1.jpg index 6b7eec4d..64ffdccc 100644 Binary files a/images/devices/generic-ag-l4-1.jpg and b/images/devices/generic-ag-l4-1.jpg differ diff --git a/images/devices/generic-ag-l4-2.jpg b/images/devices/generic-ag-l4-2.jpg index a6f96338..c24e1ae1 100644 Binary files a/images/devices/generic-ag-l4-2.jpg and b/images/devices/generic-ag-l4-2.jpg differ diff --git a/images/devices/generic-ag-l4-3.jpg b/images/devices/generic-ag-l4-3.jpg index 7f4c5d6e..76f09d3e 100644 Binary files a/images/devices/generic-ag-l4-3.jpg and b/images/devices/generic-ag-l4-3.jpg differ diff --git a/images/devices/generic-ag-l4-4.jpg b/images/devices/generic-ag-l4-4.jpg index 8e39d6d3..d2b538f4 100644 Binary files a/images/devices/generic-ag-l4-4.jpg and b/images/devices/generic-ag-l4-4.jpg differ diff --git a/images/devices/generic-ag-l4-5.jpg b/images/devices/generic-ag-l4-5.jpg index ed8b285f..a62f7815 100644 Binary files a/images/devices/generic-ag-l4-5.jpg and b/images/devices/generic-ag-l4-5.jpg differ diff --git a/images/devices/generic-geiger-diy.png b/images/devices/generic-geiger-diy.png index 1f083897..d2cb9f95 100644 Binary files a/images/devices/generic-geiger-diy.png and b/images/devices/generic-geiger-diy.png differ diff --git a/images/devices/generic-relay-40.jpg b/images/devices/generic-relay-40.jpg index 62a9144d..68a91f2a 100644 Binary files a/images/devices/generic-relay-40.jpg and b/images/devices/generic-relay-40.jpg differ diff --git a/images/devices/generic-rgbled-10.jpg b/images/devices/generic-rgbled-10.jpg index 24e8ad65..d368d39a 100644 Binary files a/images/devices/generic-rgbled-10.jpg and b/images/devices/generic-rgbled-10.jpg differ diff --git a/images/devices/generic-v9261f.jpg b/images/devices/generic-v9261f.jpg index 3fd12208..1569ebab 100644 Binary files a/images/devices/generic-v9261f.jpg and b/images/devices/generic-v9261f.jpg differ diff --git a/images/devices/heygo-hy02.jpg b/images/devices/heygo-hy02.jpg index 4bda4563..64995593 100644 Binary files a/images/devices/heygo-hy02.jpg and b/images/devices/heygo-hy02.jpg differ diff --git a/images/devices/huacanxing-h801.jpg b/images/devices/huacanxing-h801.jpg index 4f15cf5d..4472ff1f 100644 Binary files a/images/devices/huacanxing-h801.jpg and b/images/devices/huacanxing-h801.jpg differ diff --git a/images/devices/intermittech-quinled-2.6.jpg b/images/devices/intermittech-quinled-2.6.jpg index 6c491b93..84b5475e 100644 Binary files a/images/devices/intermittech-quinled-2.6.jpg and b/images/devices/intermittech-quinled-2.6.jpg differ diff --git a/images/devices/itead-1ch-inching.jpg b/images/devices/itead-1ch-inching.jpg index 74920b7e..71e7f2ef 100644 Binary files a/images/devices/itead-1ch-inching.jpg and b/images/devices/itead-1ch-inching.jpg differ diff --git a/images/devices/itead-bn-sz01.jpg b/images/devices/itead-bn-sz01.jpg index 1b1055f1..071b84b4 100644 Binary files a/images/devices/itead-bn-sz01.jpg and b/images/devices/itead-bn-sz01.jpg differ diff --git a/images/devices/itead-motor.jpg b/images/devices/itead-motor.jpg index 20bdc183..e29d3346 100644 Binary files a/images/devices/itead-motor.jpg and b/images/devices/itead-motor.jpg differ diff --git a/images/devices/itead-s20.jpg b/images/devices/itead-s20.jpg index 9c620610..99ab344d 100644 Binary files a/images/devices/itead-s20.jpg and b/images/devices/itead-s20.jpg differ diff --git a/images/devices/itead-s26.jpg b/images/devices/itead-s26.jpg index 9f102635..1bf1682e 100644 Binary files a/images/devices/itead-s26.jpg and b/images/devices/itead-s26.jpg differ diff --git a/images/devices/itead-slampher.jpg b/images/devices/itead-slampher.jpg index 1f406bbd..e31c004f 100644 Binary files a/images/devices/itead-slampher.jpg and b/images/devices/itead-slampher.jpg differ diff --git a/images/devices/itead-sonoff-4ch-pro.jpg b/images/devices/itead-sonoff-4ch-pro.jpg index 632ad0ff..ba10966a 100644 Binary files a/images/devices/itead-sonoff-4ch-pro.jpg and b/images/devices/itead-sonoff-4ch-pro.jpg differ diff --git a/images/devices/itead-sonoff-4ch.jpg b/images/devices/itead-sonoff-4ch.jpg index ecb3477e..b0fc108b 100644 Binary files a/images/devices/itead-sonoff-4ch.jpg and b/images/devices/itead-sonoff-4ch.jpg differ diff --git a/images/devices/itead-sonoff-b1.jpg b/images/devices/itead-sonoff-b1.jpg index 3b8b7315..e338d094 100644 Binary files a/images/devices/itead-sonoff-b1.jpg and b/images/devices/itead-sonoff-b1.jpg differ diff --git a/images/devices/itead-sonoff-basic.jpg b/images/devices/itead-sonoff-basic.jpg index 9e7008d8..bf52a349 100644 Binary files a/images/devices/itead-sonoff-basic.jpg and b/images/devices/itead-sonoff-basic.jpg differ diff --git a/images/devices/itead-sonoff-dual.jpg b/images/devices/itead-sonoff-dual.jpg index f9439cbf..8f4db5b7 100644 Binary files a/images/devices/itead-sonoff-dual.jpg and b/images/devices/itead-sonoff-dual.jpg differ diff --git a/images/devices/itead-sonoff-ifan02.jpg b/images/devices/itead-sonoff-ifan02.jpg index 2627cf4d..cbb0cb92 100644 Binary files a/images/devices/itead-sonoff-ifan02.jpg and b/images/devices/itead-sonoff-ifan02.jpg differ diff --git a/images/devices/itead-sonoff-led.jpg b/images/devices/itead-sonoff-led.jpg index 051d84cd..0edcf16a 100644 Binary files a/images/devices/itead-sonoff-led.jpg and b/images/devices/itead-sonoff-led.jpg differ diff --git a/images/devices/itead-sonoff-pow.jpg b/images/devices/itead-sonoff-pow.jpg index fa5e61dd..fda2fc5b 100644 Binary files a/images/devices/itead-sonoff-pow.jpg and b/images/devices/itead-sonoff-pow.jpg differ diff --git a/images/devices/itead-sonoff-rf.jpg b/images/devices/itead-sonoff-rf.jpg index b86bd0fe..50224d0a 100644 Binary files a/images/devices/itead-sonoff-rf.jpg and b/images/devices/itead-sonoff-rf.jpg differ diff --git a/images/devices/itead-sonoff-sv.jpg b/images/devices/itead-sonoff-sv.jpg index 3b3514c1..33189872 100644 Binary files a/images/devices/itead-sonoff-sv.jpg and b/images/devices/itead-sonoff-sv.jpg differ diff --git a/images/devices/itead-sonoff-t1.jpg b/images/devices/itead-sonoff-t1.jpg index a081afbd..233c1d11 100644 Binary files a/images/devices/itead-sonoff-t1.jpg and b/images/devices/itead-sonoff-t1.jpg differ diff --git a/images/devices/itead-sonoff-th.jpg b/images/devices/itead-sonoff-th.jpg index ee3c64ae..24ffd316 100644 Binary files a/images/devices/itead-sonoff-th.jpg and b/images/devices/itead-sonoff-th.jpg differ diff --git a/images/devices/jangoe-wifi-relay.jpg b/images/devices/jangoe-wifi-relay.jpg index 1d317921..5b60dd53 100644 Binary files a/images/devices/jangoe-wifi-relay.jpg and b/images/devices/jangoe-wifi-relay.jpg differ diff --git a/images/devices/jorgegarcia-wifi-relays.jpg b/images/devices/jorgegarcia-wifi-relays.jpg index 7aa64595..c653a902 100644 Binary files a/images/devices/jorgegarcia-wifi-relays.jpg and b/images/devices/jorgegarcia-wifi-relays.jpg differ diff --git a/images/devices/kmc-70011.jpg b/images/devices/kmc-70011.jpg index ed07a7d0..c58ab298 100644 Binary files a/images/devices/kmc-70011.jpg and b/images/devices/kmc-70011.jpg differ diff --git a/images/devices/lingan-swa1.jpg b/images/devices/lingan-swa1.jpg index 122a6967..708de71e 100644 Binary files a/images/devices/lingan-swa1.jpg and b/images/devices/lingan-swa1.jpg differ diff --git a/images/devices/lohas-9w.jpg b/images/devices/lohas-9w.jpg index 2c85f215..7cecfddd 100644 Binary files a/images/devices/lohas-9w.jpg and b/images/devices/lohas-9w.jpg differ diff --git a/images/devices/magichome-led-controller.jpg b/images/devices/magichome-led-controller.jpg index b8604977..290d7320 100644 Binary files a/images/devices/magichome-led-controller.jpg and b/images/devices/magichome-led-controller.jpg differ diff --git a/images/devices/mancavemade-esp-live.jpg b/images/devices/mancavemade-esp-live.jpg index bfe3b379..f0645292 100644 Binary files a/images/devices/mancavemade-esp-live.jpg and b/images/devices/mancavemade-esp-live.jpg differ diff --git a/images/devices/neo-coolcam-wifi.jpg b/images/devices/neo-coolcam-wifi.jpg index db894a24..3d07a4a8 100644 Binary files a/images/devices/neo-coolcam-wifi.jpg and b/images/devices/neo-coolcam-wifi.jpg differ diff --git a/images/devices/nodemcu-lolin-v3.jpg b/images/devices/nodemcu-lolin-v3.jpg index e9392742..677c17a2 100644 Binary files a/images/devices/nodemcu-lolin-v3.jpg and b/images/devices/nodemcu-lolin-v3.jpg differ diff --git a/images/devices/openenergymonitor-mqtt-relay.jpg b/images/devices/openenergymonitor-mqtt-relay.jpg index 5563f234..43c38546 100644 Binary files a/images/devices/openenergymonitor-mqtt-relay.jpg and b/images/devices/openenergymonitor-mqtt-relay.jpg differ diff --git a/images/devices/schuko-wifi-plug.jpg b/images/devices/schuko-wifi-plug.jpg index d4fef2be..2ae71b89 100644 Binary files a/images/devices/schuko-wifi-plug.jpg and b/images/devices/schuko-wifi-plug.jpg differ diff --git a/images/devices/tinkerman-espurna-h.jpg b/images/devices/tinkerman-espurna-h.jpg index 29400268..e33a4b02 100644 Binary files a/images/devices/tinkerman-espurna-h.jpg and b/images/devices/tinkerman-espurna-h.jpg differ diff --git a/images/devices/tonbux-powerstrip02.jpg b/images/devices/tonbux-powerstrip02.jpg index 070955e4..1a8c143a 100644 Binary files a/images/devices/tonbux-powerstrip02.jpg and b/images/devices/tonbux-powerstrip02.jpg differ diff --git a/images/devices/wemos-d1-mini-relayshield.jpg b/images/devices/wemos-d1-mini-relayshield.jpg index a57c03bd..cb963e56 100644 Binary files a/images/devices/wemos-d1-mini-relayshield.jpg and b/images/devices/wemos-d1-mini-relayshield.jpg differ diff --git a/images/devices/wion-50055.jpg b/images/devices/wion-50055.jpg index 1a78abd2..24b1be5c 100644 Binary files a/images/devices/wion-50055.jpg and b/images/devices/wion-50055.jpg differ diff --git a/images/devices/witty-cloud.jpg b/images/devices/witty-cloud.jpg index c343f940..220ea9cc 100644 Binary files a/images/devices/witty-cloud.jpg and b/images/devices/witty-cloud.jpg differ diff --git a/images/devices/workchoice-ecoplug.jpg b/images/devices/workchoice-ecoplug.jpg index 49929ed8..8273de30 100644 Binary files a/images/devices/workchoice-ecoplug.jpg and b/images/devices/workchoice-ecoplug.jpg differ diff --git a/images/devices/xenon-sm-pw702u.jpg b/images/devices/xenon-sm-pw702u.jpg index 93173820..330368d2 100644 Binary files a/images/devices/xenon-sm-pw702u.jpg and b/images/devices/xenon-sm-pw702u.jpg differ