From 7e6cb255528751f172477d1ef3590f5bdb7127c2 Mon Sep 17 00:00:00 2001 From: denisfrench Date: Sat, 7 Jan 2017 15:53:39 +1100 Subject: [PATCH] Add support for WiFi MQTT Relay / Thermostat from OpenEnergyMonitor here; https://guide.openenergymonitor.org/integrations/mqtt-relay/ --- README.md | 4 ++ code/espurna/config/hardware.h | 126 ++++++++++++--------------------- code/platformio.ini | 20 ++++++ images/devices/wifi-relay.jpg | Bin 0 -> 7106 bytes 4 files changed, 69 insertions(+), 81 deletions(-) create mode 100644 images/devices/wifi-relay.jpg diff --git a/README.md b/README.md index 4b8b0bb6..77b72e6f 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,11 @@ For more information please refer to the [ESPurna Wiki](https://bitbucket.org/xo |![IteadStudio Sonoff Dual](images/devices/sonoff-dual.jpg) **IteadStudio Sonoff Dual**|![IteadStudio Sonoff POW](images/devices/sonoff-pow.jpg) **IteadStudio Sonoff POW**|![IteadStudio Sonoff TH10/TH16](images/devices/sonoff-th10-th16.jpg) **IteadStudio Sonoff TH10/TH16**| |![IteadStudio Sonoff RF](images/devices/sonoff-rf.jpg) **IteadStudio Sonoff RF**|![IteadStudio Sonoff SV](images/devices/sonoff-sv.jpg) **IteadStudio Sonoff SV**|![IteadStudio Sonoff Touch](images/devices/sonoff-touch.jpg) **IteadStudio Sonoff Touch**| |![Wemos D1 Mini Relay Shield](images/devices/d1mini.jpg) **Wemos D1 Mini Relay Shield**|![Electrodragon Relay Board](images/devices/electrodragon-relay-board.jpg) **Electrodragon Relay Board**|![WorkChoice EcoPlug](images/devices/workchoice-ecoplug.jpg) **WorkChoice EcoPlug**| +<<<<<<< HEAD |![JanGoe Wifi Relay (NO/NC)](images/devices/jangoe-wifi-relay.png) **JanGoe Wifi Relay (NO/NC)**||| +======= +|![WiFi MQTT Relay / Thermostat](images/devices/wifi-relay.jpg) **WiFi MQTT Relay / Thermostat**| +>>>>>>> Add support for WiFi MQTT Relay / Thermostat from OpenEnergyMonitor here; https://guide.openenergymonitor.org/integrations/mqtt-relay/ ## License diff --git a/code/espurna/config/hardware.h b/code/espurna/config/hardware.h index 2d0dd5f2..771773bf 100644 --- a/code/espurna/config/hardware.h +++ b/code/espurna/config/hardware.h @@ -1,3 +1,35 @@ +//-------------------------------------------------------------------------------- +// HARDWARE +// This setting is normally provided by PlatformIO +// Uncomment the appropiate line to build from the Arduino IDE +//-------------------------------------------------------------------------------- + +//#define NODEMCUV2 +//#define SONOFF +//#define SONOFF_TH +//#define SLAMPHER +//#define S20 +//#define SONOFF_SV +//#define SONOFF_POW +//#define SONOFF_DUAL +//#define SONOFF_4CH +//#define ESP_RELAY_BOARD +//#define ECOPLUG +//#define ESPURNA +//#define WIFI_RELAY + +//#define ENABLE_DHT 1 +//#define ENABLE_DS18B20 1 +//#define ENABLE_EMON 1 +//#define ENABLE_HLW8018 1 +//#define ENABLE_RF 1 +//#define ENABLE_FAUXMO 0 +//#define ENABLE_NOFUSS 1 + +#ifndef ENABLE_FAUXMO + #define ENABLE_FAUXMO 1 +#endif + // ----------------------------------------------------------------------------- // Development boards // ----------------------------------------------------------------------------- @@ -7,9 +39,7 @@ #define MANUFACTURER "NODEMCU" #define DEVICE "LOLIN" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 2 #define LED1_PIN_INVERSE 1 @@ -18,7 +48,6 @@ #define MANUFACTURER "WEMOS" #define DEVICE "D1_MINI" #define RELAY1_PIN 5 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 2 #define LED1_PIN_INVERSE 1 @@ -31,9 +60,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 @@ -42,9 +69,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_TH" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 @@ -53,9 +78,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_SV" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 @@ -64,9 +87,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SLAMPHER" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 @@ -75,9 +96,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "S20" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 @@ -86,9 +105,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_TOUCH" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 @@ -97,9 +114,7 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_POW" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 15 #define LED1_PIN_INVERSE 0 #define ENABLE_POW 1 @@ -119,42 +134,16 @@ #define MANUFACTURER "ITEAD" #define DEVICE "SONOFF_4CH" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define BUTTON2_PIN 9 - #define BUTTON2_RELAY 2 #define BUTTON3_PIN 10 - #define BUTTON3_RELAY 3 #define BUTTON4_PIN 14 - #define BUTTON4_RELAY 4 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define RELAY2_PIN 5 - #define RELAY2_PIN_INVERSE 0 #define RELAY3_PIN 4 - #define RELAY3_PIN_INVERSE 0 #define RELAY4_PIN 15 - #define RELAY4_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 1 -#elif defined(ITEAD_1CH_INCHING) - - // Note: definitions for this board are based on third party data - // and have not been fully tested yet. If you have the chance to - // test them, please report back. Thank you. - - #define MANUFACTURER "ITEAD" - #define DEVICE "1CH_INCHING" - #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 - #define BUTTON2_PIN 15 - #define BUTTON2_RELAY 0 - #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 - #define LED1_PIN 13 - #define LED1_PIN_INVERSE 0 - #define LED_PULSE 14 - // ----------------------------------------------------------------------------- // Electrodragon boards // ----------------------------------------------------------------------------- @@ -164,13 +153,9 @@ #define MANUFACTURER "ELECTRODRAGON" #define DEVICE "ESP_RELAY_BOARD" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define BUTTON2_PIN 2 - #define BUTTON2_RELAY 2 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define RELAY2_PIN 13 - #define RELAY2_PIN_INVERSE 0 #define LED1_PIN 16 #define LED1_PIN_INVERSE 0 @@ -183,42 +168,10 @@ #define MANUFACTURER "WORKCHOICE" #define DEVICE "ECOPLUG" #define BUTTON1_PIN 13 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 15 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 2 #define LED1_PIN_INVERSE 0 -// ----------------------------------------------------------------------------- -// JanGoe Wifi Relay (https://github.com/JanGoe/esp8266-wifi-relay) -// ----------------------------------------------------------------------------- - -#elif defined(WIFI_RELAY_NC) - - #define MANUFACTURER "JANGOE" - #define DEVICE "WIFI_RELAY_NC" - #define BUTTON1_PIN 12 - #define BUTTON1_RELAY 1 - #define BUTTON2_PIN 13 - #define BUTTON2_RELAY 2 - #define RELAY1_PIN 2 - #define RELAY1_PIN_INVERSE 1 - #define RELAY2_PIN 14 - #define RELAY2_PIN_INVERSE 1 - -#elif defined(WIFI_RELAY_NO) - - #define MANUFACTURER "JANGOE" - #define DEVICE "WIFI_RELAY_NO" - #define BUTTON1_PIN 12 - #define BUTTON1_RELAY 1 - #define BUTTON2_PIN 13 - #define BUTTON2_RELAY 2 - #define RELAY1_PIN 2 - #define RELAY1_PIN_INVERSE 0 - #define RELAY2_PIN 14 - #define RELAY2_PIN_INVERSE 0 - // ----------------------------------------------------------------------------- // ESPurna board (still beta) // ----------------------------------------------------------------------------- @@ -228,12 +181,23 @@ #define MANUFACTURER "TINKERMAN" #define DEVICE "ESPURNA" #define BUTTON1_PIN 0 - #define BUTTON1_RELAY 1 #define RELAY1_PIN 12 - #define RELAY1_PIN_INVERSE 0 #define LED1_PIN 13 #define LED1_PIN_INVERSE 0 +// ----------------------------------------------------------------------------- +// WiFi MQTT Relay / Thermostat +// ----------------------------------------------------------------------------- + +#elif defined(WIFI_RELAY) + + #define MANUFACTURER "OPENENERGYMONITOR" + #define DEVICE "WIFI_RELAY" + #define BUTTON1_PIN 0 + #define RELAY1_PIN 12 + #define LED1_PIN 16 + #define LED1_PIN_INVERSE 0 + // ----------------------------------------------------------------------------- // Unknown hardware // ----------------------------------------------------------------------------- diff --git a/code/platformio.ini b/code/platformio.ini index cb9ca7eb..6a58662c 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -264,6 +264,7 @@ upload_speed = 115200 upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 +<<<<<<< HEAD [env:jangoe-debug] platform = espressif8266 framework = arduino @@ -281,6 +282,25 @@ lib_deps = ${common.lib_deps} lib_ignore = ${common.lib_ignore} extra_script = pio_hooks.py build_flags = -g -DDEBUG_PORT=Serial -DWIFI_RELAY_NC +======= +[env:wifi-relay-debug] +platform = espressif8266 +framework = arduino +board = esp_wroom_02 +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -DDEBUG_PORT=Serial -DDEBUG_FAUXMO=Serial -DNOWSAUTH -DWIFI_RELAY -DENABLE_DS18B20=1 + +[env:wifi-relay-debug-ota] +platform = espressif8266 +framework = arduino +board = esp_wroom_02 +lib_deps = ${common.lib_deps} +lib_ignore = ${common.lib_ignore} +extra_script = pio_hooks.py +build_flags = -g -DDEBUG_PORT=Serial -DDEBUG_FAUXMO=Serial -DNOWSAUTH -DWIFI_RELAY -DENABLE_DS18B20=1 +>>>>>>> Add support for WiFi MQTT Relay / Thermostat from OpenEnergyMonitor here; https://guide.openenergymonitor.org/integrations/mqtt-relay/ upload_speed = 115200 upload_port = "192.168.4.1" upload_flags = --auth=fibonacci --port 8266 diff --git a/images/devices/wifi-relay.jpg b/images/devices/wifi-relay.jpg new file mode 100644 index 0000000000000000000000000000000000000000..942bbc4dda31c24e6cbd20aad69da278171e0d6f GIT binary patch literal 7106 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