diff --git a/API.md b/API.md new file mode 100644 index 000000000..23e45369d --- /dev/null +++ b/API.md @@ -0,0 +1,65 @@ +## Sonoff-Tasmota basic API information +Sonoff-Tasmota can easily be extended by developers using provided function pointers as callback Ids. This document lists the available callback function Ids. See the wiki (https://github.com/arendst/Sonoff-Tasmota/wiki/Sensor-API) for more information. + +Callback availability can be checked by searching for either XdrvCall, XsnsCall, XdspCall and XnrgCall. + +## Driver, Sensor and Energy Callback Ids +The following table lists Callback Ids and their availability for a Driver, Sensor or Energy service. + +Callback Id | Bool | Version | xdrv | xsns | xnrg | Description +----------------------------|------|----------|------|------|------|---------------------------------- +FUNC_SETTINGS_OVERRIDE | | 6.2.1.19 | x | | | Override start-up settings +FUNC_MODULE_INIT | x | 6.2.1.17 | x | | | Init module specific parameters +FUNC_PRE_INIT | | | x | | x | Once GPIO have been established +FUNC_INIT | | | x | x | x | At end of initialisation +FUNC_LOOP | | | x | | | In main loop +FUNC_EVERY_50_MSECOND | | | x | x | | +FUNC_EVERY_100_MSECOND | | | x | x | | +FUNC_EVERY_200_MSECOND | | | | x | x | +FUNC_EVERY_250_MSECOND | | | x | | | +FUNC_EVERY_SECOND | | | x | x | x | +FUNC_PREP_BEFORE_TELEPERIOD | | | | x | | Deprecated. Use a FUNC_EVERY_ +FUNC_JSON_APPEND | | | | x | | Extend teleperiod JSON text +FUNC_WEB_APPEND | | | | x | | Extend webgui ajax info +FUNC_SAVE_BEFORE_RESTART | | | | x | | Just before a planned restart +FUNC_COMMAND | x | | x | x | | When a command is not recognized +FUNC_MQTT_SUBSCRIBE | | 5.12.0k | x | | | At end of MQTT subscriptions +FUNC_MQTT_INIT | | 5.12.0k | x | | | Once at end of MQTT connection +FUNC_MQTT_DATA | x | 5.12.0k | x | | | Before decoding command +FUNC_SET_POWER | | | x | | | Before setting relays +FUNC_SET_DEVICE_POWER | x | 6.2.1.18 | x | | | Set relay +FUNC_SHOW_SENSOR | | | x | | | When FUNC_JSON_APPEND completes +FUNC_RULES_PROCESS | x | 6.0.0 | x | | | Process specific rule +FUNC_SERIAL | x | | x | | x | Process serial data +FUNC_FREE_MEM | | | x | | | Show free memory for debugging +FUNC_BUTTON_PRESSED | x | 6.2.1.18 | x | | | When a button is pressed +FUNC_WEB_ADD_BUTTON | | 6.2.1.14 | x | x | | Add a Configuration Button to GUI +FUNC_WEB_ADD_MAIN_BUTTON | | 6.2.1.14 | x | x | | Add a main button to GUI +FUNC_WEB_ADD_HANDLER | | 6.2.1.14 | x | x | | Add a webserver handler + +## Display Call back Ids +The following table lists all Callback Ids for a Display service. + +Callback Id | Bool | Version | Description +------------------------------|------|----------|--------------------- +FUNC_DISPLAY_INIT_DRIVER | | 6.1.1.7 | +FUNC_DISPLAY_INIT | | 6.1.1.7 | +FUNC_DISPLAY_EVERY_50_MSECOND | | 6.1.1.7 | +FUNC_DISPLAY_EVERY_SECOND | | 6.1.1.7 | +FUNC_DISPLAY_MODEL | x | 6.1.1.7 | +FUNC_DISPLAY_MODE | | 6.1.1.7 | +FUNC_DISPLAY_POWER | | 6.1.1.7 | +FUNC_DISPLAY_CLEAR | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_FRAME | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_HLINE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_VLINE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_LINE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_CIRCLE | | 6.1.1.7 | +FUNC_DISPLAY_FILL_CIRCLE | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_RECTANGLE | | 6.1.1.7 | +FUNC_DISPLAY_FILL_RECTANGLE | | 6.1.1.7 | +FUNC_DISPLAY_TEXT_SIZE | | 6.1.1.7 | +FUNC_DISPLAY_FONT_SIZE | | 6.1.1.7 | +FUNC_DISPLAY_ROTATION | | 6.1.1.7 | +FUNC_DISPLAY_DRAW_STRING | | 6.1.1.7 | +FUNC_DISPLAY_ONOFF | | 6.1.1.7 | diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 8cf1a0022..a98f96b33 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -55,7 +55,7 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_SUNRISE | - | - | x | x | x | | USE_RULES | - | - | x | x | x | | | | | | | | -| USE_ADC_VCC | x | x | x | x | x | +| USE_ADC_VCC | x | x | x | x | | | USE_DS18B20 | - | - | - | - | - | Single sensor | USE_DS18x20 | - | x | x | x | x | Multiple sensors | USE_DS18x20_LEGACY | - | - | - | - | - | Multiple sensors @@ -79,9 +79,11 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_LM75AD | - | - | x | x | x | | USE_APDS9960 | - | - | - | - | - | | USE_MCP230xx | - | - | - | - | - | +| USE_PCA9685 | - | - | - | - | - | | USE_MPR121 | - | - | - | - | - | | USE_CCS811 | - | - | - | - | - | | USE_MPU6050 | - | - | - | - | - | +| USE_DS3231 | - | - | - | - | - | | | | | | | | | Feature or Sensor | minimal | classic | sonoff | knx | sensors | | USE_SPI | - | - | - | - | - | @@ -90,9 +92,13 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_PMS5003 | - | - | x | x | x | | USE_NOVA_SDS | - | - | x | x | x | | USE_PZEM004T | - | - | x | x | x | +| USE_PZEM_AC | - | - | x | x | x | +| USE_PZEM_DC | - | - | x | x | x | +| USE_MCP39F501 | - | - | x | x | x | | USE_SERIAL_BRIDGE | - | - | x | x | x | | USE_SDM120 | - | - | - | - | x | | USE_SDM630 | - | - | - | - | x | +| USE_MP3_PLAYER | - | - | - | - | - | | USE_IR_REMOTE | - | - | x | x | x | | USE_IR_HVAC | - | - | - | - | x | | USE_IR_RECEIVE | - | - | x | x | x | @@ -101,7 +107,11 @@ See [Tasmota ESP/Arduino library version related issues](https://github.com/aren | USE_ARILUX_RF | - | - | x | x | x | | USE_SR04 | - | - | x | x | x | | USE_TM1638 | - | - | - | - | - | +| USE_HX711 | - | - | x | x | x | | USE_RF_FLASH | - | - | x | x | x | +| USE_TUYA_DIMMER | - | - | x | x | x | +| USE_TX20_WIND_SENSOR | - | - | x | x | x | +| USE_DISPLAY | - | - | - | - | - | ## Changelog Version 6.2.1 20180905 diff --git a/lib/ESPAsyncUDP-master/.travis.yml b/lib/ESPAsyncUDP-master/.travis.yml deleted file mode 100644 index c1ef4ec8f..000000000 --- a/lib/ESPAsyncUDP-master/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -sudo: false -language: bash -os: - - linux - -script: - - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 - - sleep 3 - - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz - - tar xf arduino-1.6.5-linux64.tar.xz - - mv arduino-1.6.5 $HOME/arduino_ide - - export PATH="$HOME/arduino_ide:$PATH" - - which arduino - - mkdir -p $HOME/Arduino/libraries - - cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESPAsyncUDP - - cd $HOME/arduino_ide/hardware - - mkdir esp8266com - - cd esp8266com - - git clone https://github.com/esp8266/Arduino.git esp8266 - - cd esp8266/tools - - python get.py - - source $TRAVIS_BUILD_DIR/travis/common.sh - - arduino --board esp8266com:esp8266:generic --save-prefs - - arduino --get-pref sketchbook.path - - build_sketches arduino $HOME/Arduino/libraries/ESPAsyncUDP esp8266 - -notifications: - email: - on_success: change - on_failure: change - webhooks: - urls: - - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 - on_success: change # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: false # default: false diff --git a/lib/ESPAsyncUDP-master/README.md b/lib/ESPAsyncUDP-master/README.md deleted file mode 100644 index 997a7cc26..000000000 --- a/lib/ESPAsyncUDP-master/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# ESPAsyncUDP -Async UDP Library for ESP8266 Arduino [![Build Status](https://travis-ci.org/me-no-dev/ESPAsyncUDP.svg?branch=master)](https://travis-ci.org/me-no-dev/ESPAsyncUDP) - -[![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - -This is a fully asynchronous UDP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP8266 MCUs. - -The library is easy to use and includes support for Unicast, Broadcast and Multicast environments - -Latest GIT version of ESP8266 Arduino might be required for this library to work diff --git a/lib/ESPAsyncUDP-master/examples/AsyncUDPClient/AsyncUDPClient.ino b/lib/ESPAsyncUDP-master/examples/AsyncUDPClient/AsyncUDPClient.ino deleted file mode 100644 index cf528fe12..000000000 --- a/lib/ESPAsyncUDP-master/examples/AsyncUDPClient/AsyncUDPClient.ino +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include "ESPAsyncUDP.h" - -const char * ssid = "***********"; -const char * password = "***********"; - -AsyncUDP udp; - -void setup() -{ - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.println("WiFi Failed"); - while(1) { - delay(1000); - } - } - if(udp.connect(IPAddress(192,168,1,100), 1234)) { - Serial.println("UDP connected"); - udp.onPacket([](AsyncUDPPacket packet) { - Serial.print("UDP Packet Type: "); - Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast"); - Serial.print(", From: "); - Serial.print(packet.remoteIP()); - Serial.print(":"); - Serial.print(packet.remotePort()); - Serial.print(", To: "); - Serial.print(packet.localIP()); - Serial.print(":"); - Serial.print(packet.localPort()); - Serial.print(", Length: "); - Serial.print(packet.length()); - Serial.print(", Data: "); - Serial.write(packet.data(), packet.length()); - Serial.println(); - //reply to the client - packet.printf("Got %u bytes of data", packet.length()); - }); - //Send unicast - udp.print("Hello Server!"); - } -} - -void loop() -{ - delay(1000); - //Send broadcast on port 1234 - udp.broadcastTo("Anyone here?", 1234); -} diff --git a/lib/ESPAsyncUDP-master/examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino b/lib/ESPAsyncUDP-master/examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino deleted file mode 100644 index bb3e69c9b..000000000 --- a/lib/ESPAsyncUDP-master/examples/AsyncUDPMulticastServer/AsyncUDPMulticastServer.ino +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include "ESPAsyncUDP.h" - -const char * ssid = "***********"; -const char * password = "***********"; - -AsyncUDP udp; - -void setup() -{ - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.println("WiFi Failed"); - while(1) { - delay(1000); - } - } - if(udp.listenMulticast(IPAddress(239,1,2,3), 1234)) { - Serial.print("UDP Listening on IP: "); - Serial.println(WiFi.localIP()); - udp.onPacket([](AsyncUDPPacket packet) { - Serial.print("UDP Packet Type: "); - Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast"); - Serial.print(", From: "); - Serial.print(packet.remoteIP()); - Serial.print(":"); - Serial.print(packet.remotePort()); - Serial.print(", To: "); - Serial.print(packet.localIP()); - Serial.print(":"); - Serial.print(packet.localPort()); - Serial.print(", Length: "); - Serial.print(packet.length()); - Serial.print(", Data: "); - Serial.write(packet.data(), packet.length()); - Serial.println(); - //reply to the client - packet.printf("Got %u bytes of data", packet.length()); - }); - //Send multicast - udp.print("Hello!"); - } -} - -void loop() -{ - delay(1000); - //Send multicast - udp.print("Anyone here?"); -} diff --git a/lib/ESPAsyncUDP-master/examples/AsyncUDPServer/AsyncUDPServer.ino b/lib/ESPAsyncUDP-master/examples/AsyncUDPServer/AsyncUDPServer.ino deleted file mode 100644 index fc12a7fc3..000000000 --- a/lib/ESPAsyncUDP-master/examples/AsyncUDPServer/AsyncUDPServer.ino +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include "ESPAsyncUDP.h" - -const char * ssid = "***********"; -const char * password = "***********"; - -AsyncUDP udp; - -void setup() -{ - Serial.begin(115200); - WiFi.mode(WIFI_STA); - WiFi.begin(ssid, password); - if (WiFi.waitForConnectResult() != WL_CONNECTED) { - Serial.println("WiFi Failed"); - while(1) { - delay(1000); - } - } - if(udp.listen(1234)) { - Serial.print("UDP Listening on IP: "); - Serial.println(WiFi.localIP()); - udp.onPacket([](AsyncUDPPacket packet) { - Serial.print("UDP Packet Type: "); - Serial.print(packet.isBroadcast()?"Broadcast":packet.isMulticast()?"Multicast":"Unicast"); - Serial.print(", From: "); - Serial.print(packet.remoteIP()); - Serial.print(":"); - Serial.print(packet.remotePort()); - Serial.print(", To: "); - Serial.print(packet.localIP()); - Serial.print(":"); - Serial.print(packet.localPort()); - Serial.print(", Length: "); - Serial.print(packet.length()); - Serial.print(", Data: "); - Serial.write(packet.data(), packet.length()); - Serial.println(); - //reply to the client - packet.printf("Got %u bytes of data", packet.length()); - }); - } -} - -void loop() -{ - delay(1000); - //Send broadcast - udp.broadcast("Anyone here?"); -} diff --git a/lib/ESPAsyncUDP-master/library.json b/lib/ESPAsyncUDP-master/library.json deleted file mode 100644 index fe300b6e6..000000000 --- a/lib/ESPAsyncUDP-master/library.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name":"ESPAsyncUDP", - "description":"Asynchronous UDP Library for ESP8266", - "keywords":"async,udp,server,client,multicast,broadcast", - "authors": - { - "name": "Hristo Gochkov", - "maintainer": true - }, - "repository": - { - "type": "git", - "url": "https://github.com/me-no-dev/ESPAsyncUDP.git" - }, - "frameworks": "arduino", - "platforms":"espressif" -} diff --git a/lib/ESPAsyncUDP-master/library.properties b/lib/ESPAsyncUDP-master/library.properties deleted file mode 100644 index 1aa6ef1ad..000000000 --- a/lib/ESPAsyncUDP-master/library.properties +++ /dev/null @@ -1,9 +0,0 @@ -name=ESP Async UDP -version=1.0.0 -author=Me-No-Dev -maintainer=Me-No-Dev -sentence=Async UDP Library for ESP8266 -paragraph=Async UDP Library for ESP8266 -category=Other -url=https://github.com/me-no-dev/ESPAsyncUDP -architectures=* diff --git a/lib/ESPAsyncUDP-master/src/AsyncUDP.cpp b/lib/ESPAsyncUDP-master/src/AsyncUDP.cpp deleted file mode 100644 index 9e433b1f4..000000000 --- a/lib/ESPAsyncUDP-master/src/AsyncUDP.cpp +++ /dev/null @@ -1,432 +0,0 @@ -#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 // This Library will only work with ARDUINO_ESP8266_RELEASE_2_4_0 and up - -#include "Arduino.h" -#include "ESPAsyncUDP.h" - -extern "C" { -#include "user_interface.h" -#include "lwip/opt.h" -#include "lwip/inet.h" -#include "lwip/udp.h" -#include "lwip/igmp.h" -} - -AsyncUDPMessage::AsyncUDPMessage(size_t size) -{ - _index = 0; - if(size > 1460) { - size = 1460; - } - _size = size; - _buffer = (uint8_t *)malloc(size); -} - -AsyncUDPMessage::~AsyncUDPMessage() -{ - if(_buffer) { - free(_buffer); - } -} - -size_t AsyncUDPMessage::write(const uint8_t *data, size_t len) -{ - if(_buffer == NULL) { - return 0; - } - size_t s = space(); - if(len > s) { - len = s; - } - memcpy(_buffer + _index, data, len); - _index += len; - return len; -} - -size_t AsyncUDPMessage::write(uint8_t data) -{ - return write(&data, 1); -} - -size_t AsyncUDPMessage::space() -{ - if(_buffer == NULL) { - return 0; - } - return _size - _index; -} - -uint8_t * AsyncUDPMessage::data() -{ - return _buffer; -} - -size_t AsyncUDPMessage::length() -{ - return _index; -} - -void AsyncUDPMessage::flush() -{ - _index = 0; -} - - -AsyncUDPPacket::AsyncUDPPacket(AsyncUDP *udp, ip_addr_t *localIp, uint16_t localPort, ip_addr_t *remoteIp, uint16_t remotePort, uint8_t *data, size_t len) -{ - _udp = udp; - _localIp = localIp; - _localPort = localPort; - _remoteIp = remoteIp; - _remotePort = remotePort; - _data = data; - _len = len; -} - -AsyncUDPPacket::~AsyncUDPPacket() -{ - -} - -uint8_t * AsyncUDPPacket::data() -{ - return _data; -} - -size_t AsyncUDPPacket::length() -{ - return _len; -} - -IPAddress AsyncUDPPacket::localIP() -{ - return IPAddress(_localIp->addr); -} - -uint16_t AsyncUDPPacket::localPort() -{ - return _localPort; -} - -IPAddress AsyncUDPPacket::remoteIP() -{ - return IPAddress(_remoteIp->addr); -} - -uint16_t AsyncUDPPacket::remotePort() -{ - return _remotePort; -} - -bool AsyncUDPPacket::isBroadcast() -{ - return _localIp->addr == 0xFFFFFFFF || _localIp->addr == (uint32_t)(0); -} - -bool AsyncUDPPacket::isMulticast() -{ - return ip_addr_ismulticast(_localIp); -} - -size_t AsyncUDPPacket::write(const uint8_t *data, size_t len) -{ - return _udp->writeTo(data, len, _remoteIp, _remotePort); -} - -size_t AsyncUDPPacket::write(uint8_t data) -{ - return write(&data, 1); -} - -size_t AsyncUDPPacket::send(AsyncUDPMessage &message) -{ - return write(message.data(), message.length()); -} - - - -AsyncUDP::AsyncUDP() -{ - _pcb = NULL; - _connected = false; - _handler = NULL; -} - -AsyncUDP::~AsyncUDP() -{ - close(); -} - -AsyncUDP::operator bool() -{ - return _connected; -} - -bool AsyncUDP::connected() -{ - return _connected; -} - -void AsyncUDP::onPacket(AuPacketHandlerFunctionWithArg cb, void * arg) -{ - onPacket(std::bind(cb, arg, std::placeholders::_1)); -} - -void AsyncUDP::onPacket(AuPacketHandlerFunction cb) -{ - _handler = cb; -} - -void AsyncUDP::_recv(udp_pcb *upcb, pbuf *pb, ip_addr_t *addr, uint16_t port) -{ - (void)upcb; // its unused, avoid warning - while(pb != NULL) { - if(_handler) { - uint8_t * data = (uint8_t*)((pb)->payload); - size_t len = pb->len; - - ip_hdr* iphdr = reinterpret_cast(data - UDP_HLEN - IP_HLEN); - ip_addr_t daddr; - daddr.addr = iphdr->dest.addr; - - udp_hdr* udphdr = reinterpret_cast(((uint8_t*)((pb)->payload)) - UDP_HLEN); - uint16_t dport = ntohs(udphdr->dest); - - AsyncUDPPacket packet(this, &daddr, dport, addr, port, data, len); - _handler(packet); - } - - pbuf * this_pb = pb; - pb = pb->next; - this_pb->next = NULL; - pbuf_free(this_pb); - } -} - -#if LWIP_VERSION_MAJOR == 1 -void AsyncUDP::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, ip_addr_t *addr, uint16_t port) -#else -void AsyncUDP::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port) -#endif -{ - reinterpret_cast(arg)->_recv(upcb, p, (ip_addr_t *)addr, port); -} - -bool AsyncUDP::listen(ip_addr_t *addr, uint16_t port) -{ - close(); - _pcb = udp_new(); - if(_pcb == NULL) { - return false; - } - err_t err = udp_bind(_pcb, addr, port); - if(err != ERR_OK) { - close(); - return false; - } - udp_recv(_pcb, &_s_recv, (void *) this); - _connected = true; - return true; -} - -bool AsyncUDP::listenMulticast(ip_addr_t *addr, uint16_t port, uint8_t ttl) -{ - close(); - if(!ip_addr_ismulticast(addr)) { - return false; - } - ip_addr_t multicast_if_addr; - struct ip_info ifIpInfo; - int mode = wifi_get_opmode(); - if(mode & STATION_MODE) { - wifi_get_ip_info(STATION_IF, &ifIpInfo); - multicast_if_addr.addr = ifIpInfo.ip.addr; - } else if (mode & SOFTAP_MODE) { - wifi_get_ip_info(SOFTAP_IF, &ifIpInfo); - multicast_if_addr.addr = ifIpInfo.ip.addr; - } else { - return false; - } - if (igmp_joingroup(&multicast_if_addr, addr)!= ERR_OK) { - return false; - } - if(!listen(IPADDR_ANY, port)) { - return false; - } -#if LWIP_VERSION_MAJOR == 1 - udp_set_multicast_netif_addr(_pcb, multicast_if_addr); -#else - udp_set_multicast_netif_addr(_pcb, &multicast_if_addr); -#endif - udp_set_multicast_ttl(_pcb, ttl); - ip_addr_copy(_pcb->remote_ip, *addr); - _pcb->remote_port = port; - return true; -} - -bool AsyncUDP::connect(ip_addr_t *addr, uint16_t port) -{ - close(); - _pcb = udp_new(); - if(_pcb == NULL) { - return false; - } - err_t err = udp_connect(_pcb, addr, port); - if(err != ERR_OK) { - close(); - return false; - } - udp_recv(_pcb, &_s_recv, (void *) this); - _connected = true; - return true; -} - -void AsyncUDP::close() -{ - if(_pcb != NULL) { - if(_connected) { - udp_disconnect(_pcb); - } - udp_remove(_pcb); - _connected = false; - _pcb = NULL; - } -} - -size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, ip_addr_t *addr, uint16_t port) -{ - if(!_pcb && !connect(addr, port)) { - return 0; - } - if(len > 1460) { - len = 1460; - } - pbuf* pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); - if(pbt != NULL) { - uint8_t* dst = reinterpret_cast(pbt->payload); - memcpy(dst, data, len); - err_t err = udp_sendto(_pcb, pbt, addr, port); - pbuf_free(pbt); - if(err < ERR_OK) { - return 0; - } - return len; - } - return 0; -} - -bool AsyncUDP::listen(const IPAddress addr, uint16_t port) -{ - ip_addr_t laddr; - laddr.addr = addr; - return listen(&laddr, port); -} - -bool AsyncUDP::listen(uint16_t port) -{ - return listen(IPAddress((uint32_t)INADDR_ANY), port); -} - -bool AsyncUDP::listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl) -{ - ip_addr_t laddr; - laddr.addr = addr; - return listenMulticast(&laddr, port, ttl); -} - -bool AsyncUDP::connect(const IPAddress addr, uint16_t port) -{ - ip_addr_t daddr; - daddr.addr = addr; - return connect(&daddr, port); -} - -size_t AsyncUDP::writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port) -{ - ip_addr_t daddr; - daddr.addr = addr; - return writeTo(data, len, &daddr, port); -} - -size_t AsyncUDP::write(const uint8_t *data, size_t len) -{ - //return writeTo(data, len, &(_pcb->remote_ip), _pcb->remote_port); - if(_pcb){ // Patch applied (https://github.com/me-no-dev/ESPAsyncUDP/pull/21) - return writeTo(data, len, &(_pcb->remote_ip), _pcb->remote_port); - } - return 0; -} - -size_t AsyncUDP::write(uint8_t data) -{ - return write(&data, 1); -} - -size_t AsyncUDP::broadcastTo(uint8_t *data, size_t len, uint16_t port) -{ - ip_addr_t daddr; - daddr.addr = 0xFFFFFFFF; - return writeTo(data, len, &daddr, port); -} - -size_t AsyncUDP::broadcastTo(const char * data, uint16_t port) -{ - return broadcastTo((uint8_t *)data, strlen(data), port); -} - -size_t AsyncUDP::broadcast(uint8_t *data, size_t len) -{ - if(_pcb->local_port != 0) { - return broadcastTo(data, len, _pcb->local_port); - } - return 0; -} - -size_t AsyncUDP::broadcast(const char * data) -{ - return broadcast((uint8_t *)data, strlen(data)); -} - - -size_t AsyncUDP::sendTo(AsyncUDPMessage &message, ip_addr_t *addr, uint16_t port) -{ - if(!message) { - return 0; - } - return writeTo(message.data(), message.length(), addr, port); -} - -size_t AsyncUDP::sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port) -{ - //if(!message) { - if((!message) || (!_pcb)) { // Patch applied (https://github.com/me-no-dev/ESPAsyncUDP/pull/21) - return 0; - } - return writeTo(message.data(), message.length(), addr, port); -} - -size_t AsyncUDP::send(AsyncUDPMessage &message) -{ - if(!message) { - return 0; - } - return writeTo(message.data(), message.length(), &(_pcb->remote_ip), _pcb->remote_port); -} - -size_t AsyncUDP::broadcastTo(AsyncUDPMessage &message, uint16_t port) -{ - if(!message) { - return 0; - } - return broadcastTo(message.data(), message.length(), port); -} - -size_t AsyncUDP::broadcast(AsyncUDPMessage &message) -{ - if(!message) { - return 0; - } - return broadcast(message.data(), message.length()); -} - -#endif diff --git a/lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h b/lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h deleted file mode 100644 index 8e5a70b21..000000000 --- a/lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef ESPASYNCUDP_H -#define ESPASYNCUDP_H - -#include "IPAddress.h" -#include "Print.h" -#include -#include "lwip/init.h" - -class AsyncUDP; -class AsyncUDPPacket; -class AsyncUDPMessage; -struct udp_pcb; -struct pbuf; -#if LWIP_VERSION_MAJOR == 1 -struct ip_addr; -typedef struct ip_addr ip_addr_t; -#else -struct ip4_addr; -typedef struct ip4_addr ip_addr_t; -#endif - -class AsyncUDPMessage : public Print -{ -protected: - uint8_t *_buffer; - size_t _index; - size_t _size; -public: - AsyncUDPMessage(size_t size=1460); - virtual ~AsyncUDPMessage(); - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data); - size_t space(); - uint8_t * data(); - size_t length(); - void flush(); - operator bool() - { - return _buffer != NULL; - } -}; - -class AsyncUDPPacket : public Print -{ -protected: - AsyncUDP *_udp; - ip_addr_t *_localIp; - uint16_t _localPort; - ip_addr_t *_remoteIp; - uint16_t _remotePort; - uint8_t *_data; - size_t _len; -public: - AsyncUDPPacket(AsyncUDP *udp, ip_addr_t *localIp, uint16_t localPort, ip_addr_t *remoteIp, uint16_t remotePort, uint8_t *data, size_t len); - virtual ~AsyncUDPPacket(); - - uint8_t * data(); - size_t length(); - bool isBroadcast(); - bool isMulticast(); - - IPAddress localIP(); - uint16_t localPort(); - IPAddress remoteIP(); - uint16_t remotePort(); - - size_t send(AsyncUDPMessage &message); - - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data); -}; - -typedef std::function AuPacketHandlerFunction; -typedef std::function AuPacketHandlerFunctionWithArg; - -class AsyncUDP : public Print -{ -protected: - udp_pcb *_pcb; - bool _connected; - AuPacketHandlerFunction _handler; - - void _recv(udp_pcb *upcb, pbuf *pb, ip_addr_t *addr, uint16_t port); -#if LWIP_VERSION_MAJOR == 1 - static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, ip_addr_t *addr, uint16_t port); -#else - static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port); -#endif - -public: - AsyncUDP(); - virtual ~AsyncUDP(); - - void onPacket(AuPacketHandlerFunctionWithArg cb, void * arg=NULL); - void onPacket(AuPacketHandlerFunction cb); - - bool listen(ip_addr_t *addr, uint16_t port); - bool listen(const IPAddress addr, uint16_t port); - bool listen(uint16_t port); - - bool listenMulticast(ip_addr_t *addr, uint16_t port, uint8_t ttl=1); - bool listenMulticast(const IPAddress addr, uint16_t port, uint8_t ttl=1); - - bool connect(ip_addr_t *addr, uint16_t port); - bool connect(const IPAddress addr, uint16_t port); - - void close(); - - size_t writeTo(const uint8_t *data, size_t len, ip_addr_t *addr, uint16_t port); - size_t writeTo(const uint8_t *data, size_t len, const IPAddress addr, uint16_t port); - size_t write(const uint8_t *data, size_t len); - size_t write(uint8_t data); - - size_t broadcastTo(uint8_t *data, size_t len, uint16_t port); - size_t broadcastTo(const char * data, uint16_t port); - size_t broadcast(uint8_t *data, size_t len); - size_t broadcast(const char * data); - - size_t sendTo(AsyncUDPMessage &message, ip_addr_t *addr, uint16_t port); - size_t sendTo(AsyncUDPMessage &message, const IPAddress addr, uint16_t port); - size_t send(AsyncUDPMessage &message); - - size_t broadcastTo(AsyncUDPMessage &message, uint16_t port); - size_t broadcast(AsyncUDPMessage &message); - - bool connected(); - operator bool(); -}; - -#endif diff --git a/lib/ESPAsyncUDP-master/travis/common.sh b/lib/ESPAsyncUDP-master/travis/common.sh deleted file mode 100644 index 57bede343..000000000 --- a/lib/ESPAsyncUDP-master/travis/common.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -function build_sketches() -{ - local arduino=$1 - local srcpath=$2 - local platform=$3 - local sketches=$(find $srcpath -name *.ino) - for sketch in $sketches; do - local sketchdir=$(dirname $sketch) - if [[ -f "$sketchdir/.$platform.skip" ]]; then - echo -e "\n\n ------------ Skipping $sketch ------------ \n\n"; - continue - fi - echo -e "\n\n ------------ Building $sketch ------------ \n\n"; - $arduino --verify $sketch; - local result=$? - if [ $result -ne 0 ]; then - echo "Build failed ($1)" - return $result - fi - done -} diff --git a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py deleted file mode 100644 index f23ef71c1..000000000 --- a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_basic.py +++ /dev/null @@ -1,39 +0,0 @@ -import unittest -import settings -import time -import mosquitto - - -def on_message(mosq, obj, msg): - obj.message_queue.append(msg) - - -class mqtt_basic(unittest.TestCase): - - message_queue = [] - - @classmethod - def setUpClass(self): - self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) - self.client.connect(settings.server_ip) - self.client.on_message = on_message - self.client.subscribe("outTopic", 0) - - @classmethod - def tearDownClass(self): - self.client.disconnect() - - def test_one(self): - i = 30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - self.assertTrue(i > 0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue[0] - self.assertEqual(msg.mid, 0, "message id not 0") - self.assertEqual(msg.topic, "outTopic", "message topic incorrect") - self.assertEqual(msg.payload, "hello world") - self.assertEqual(msg.qos, 0, "message qos not 0") - self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py b/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py deleted file mode 100644 index 45b0a8515..000000000 --- a/lib/PubSubClient-2.6.09/tests/testcases/mqtt_publish_in_callback.py +++ /dev/null @@ -1,59 +0,0 @@ -import unittest -import settings -import time -import mosquitto - - -def on_message(mosq, obj, msg): - obj.message_queue.append(msg) - - -class mqtt_publish_in_callback(unittest.TestCase): - - message_queue = [] - - @classmethod - def setUpClass(self): - self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True, obj=self) - self.client.connect(settings.server_ip) - self.client.on_message = on_message - self.client.subscribe("outTopic", 0) - - @classmethod - def tearDownClass(self): - self.client.disconnect() - - def test_connect(self): - i = 30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - self.assertTrue(i > 0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue.pop(0) - self.assertEqual(msg.mid, 0, "message id not 0") - self.assertEqual(msg.topic, "outTopic", "message topic incorrect") - self.assertEqual(msg.payload, "hello world") - self.assertEqual(msg.qos, 0, "message qos not 0") - self.assertEqual(msg.retain, False, "message retain flag incorrect") - - def test_publish(self): - self.assertEqual(len(self.message_queue), 0, "message queue not empty") - payload = "abcdefghij" - self.client.publish("inTopic", payload) - - i = 30 - while len(self.message_queue) == 0 and i > 0: - self.client.loop() - time.sleep(0.5) - i -= 1 - - self.assertTrue(i > 0, "message receive timed-out") - self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") - msg = self.message_queue.pop(0) - self.assertEqual(msg.mid, 0, "message id not 0") - self.assertEqual(msg.topic, "outTopic", "message topic incorrect") - self.assertEqual(msg.payload, payload) - self.assertEqual(msg.qos, 0, "message qos not 0") - self.assertEqual(msg.retain, False, "message retain flag incorrect") diff --git a/lib/PubSubClient-2.6.09/tests/testsuite.py b/lib/PubSubClient-2.6.09/tests/testsuite.py deleted file mode 100644 index 788fc5d97..000000000 --- a/lib/PubSubClient-2.6.09/tests/testsuite.py +++ /dev/null @@ -1,181 +0,0 @@ -#!/usr/bin/env python -import os -import os.path -import sys -import shutil -from subprocess import call -import importlib -import unittest -import re - -from testcases import settings - - -class Workspace(object): - - def __init__(self): - self.root_dir = os.getcwd() - self.build_dir = os.path.join(self.root_dir, "tmpbin") - self.log_dir = os.path.join(self.root_dir, "logs") - self.tests_dir = os.path.join(self.root_dir, "testcases") - self.examples_dir = os.path.join(self.root_dir, "../PubSubClient/examples") - self.examples = [] - self.tests = [] - if not os.path.isdir("../PubSubClient"): - raise Exception("Cannot find PubSubClient library") - try: - return __import__('ino') - except ImportError: - raise Exception("ino tool not installed") - - def init(self): - if os.path.isdir(self.build_dir): - shutil.rmtree(self.build_dir) - os.mkdir(self.build_dir) - if os.path.isdir(self.log_dir): - shutil.rmtree(self.log_dir) - os.mkdir(self.log_dir) - - os.chdir(self.build_dir) - call(["ino", "init"]) - - shutil.copytree("../../PubSubClient", "lib/PubSubClient") - - filenames = [] - for root, dirs, files in os.walk(self.examples_dir): - filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] - filenames.sort() - for e in filenames: - self.examples.append(Sketch(self, e)) - - filenames = [] - for root, dirs, files in os.walk(self.tests_dir): - filenames += [os.path.join(root, f) for f in files if f.endswith(".ino")] - filenames.sort() - for e in filenames: - self.tests.append(Sketch(self, e)) - - def clean(self): - shutil.rmtree(self.build_dir) - - -class Sketch(object): - def __init__(self, wksp, fn): - self.w = wksp - self.filename = fn - self.basename = os.path.basename(self.filename) - self.build_log = os.path.join(self.w.log_dir, "%s.log" % (os.path.basename(self.filename),)) - self.build_err_log = os.path.join(self.w.log_dir, "%s.err.log" % (os.path.basename(self.filename),)) - self.build_upload_log = os.path.join(self.w.log_dir, "%s.upload.log" % (os.path.basename(self.filename),)) - - def build(self): - sys.stdout.write(" Build: ") - sys.stdout.flush() - - # Copy sketch over, replacing IP addresses as necessary - fin = open(self.filename, "r") - lines = fin.readlines() - fin.close() - fout = open(os.path.join(self.w.build_dir, "src", "sketch.ino"), "w") - for l in lines: - if re.match(r"^byte server\[\] = {", l): - fout.write("byte server[] = { %s };\n" % (settings.server_ip.replace(".", ", "),)) - elif re.match(r"^byte ip\[\] = {", l): - fout.write("byte ip[] = { %s };\n" % (settings.arduino_ip.replace(".", ", "),)) - else: - fout.write(l) - fout.flush() - fout.close() - - # Run build - fout = open(self.build_log, "w") - ferr = open(self.build_err_log, "w") - rc = call(["ino", "build"], stdout=fout, stderr=ferr) - fout.close() - ferr.close() - if rc == 0: - sys.stdout.write("pass") - sys.stdout.write("\n") - return True - else: - sys.stdout.write("fail") - sys.stdout.write("\n") - with open(self.build_err_log) as f: - for line in f: - print(" " + line) - return False - - def upload(self): - sys.stdout.write(" Upload: ") - sys.stdout.flush() - fout = open(self.build_upload_log, "w") - rc = call(["ino", "upload"], stdout=fout, stderr=fout) - fout.close() - if rc == 0: - sys.stdout.write("pass") - sys.stdout.write("\n") - return True - else: - sys.stdout.write("fail") - sys.stdout.write("\n") - with open(self.build_upload_log) as f: - for line in f: - print(" " + line) - return False - - def test(self): - # import the matching test case, if it exists - try: - basename = os.path.basename(self.filename)[:-4] - i = importlib.import_module("testcases." + basename) - except: - sys.stdout.write(" Test: no tests found") - sys.stdout.write("\n") - return - c = getattr(i, basename) - - testmethods = [m for m in dir(c) if m.startswith("test_")] - testmethods.sort() - tests = [] - for m in testmethods: - tests.append(c(m)) - - result = unittest.TestResult() - c.setUpClass() - if self.upload(): - sys.stdout.write(" Test: ") - sys.stdout.flush() - for t in tests: - t.run(result) - print(str(result.testsRun - len(result.failures) - len(result.errors)) + "/" + str(result.testsRun)) - if not result.wasSuccessful(): - if len(result.failures) > 0: - for f in result.failures: - print("-- " + str(f[0])) - print(f[1]) - if len(result.errors) > 0: - print(" Errors:") - for f in result.errors: - print("-- " + str(f[0])) - print(f[1]) - c.tearDownClass() - - -if __name__ == '__main__': - run_tests = True - - w = Workspace() - w.init() - - for e in w.examples: - print("--------------------------------------") - print("[" + e.basename + "]") - if e.build() and run_tests: - e.test() - for e in w.tests: - print("--------------------------------------") - print("[" + e.basename + "]") - if e.build() and run_tests: - e.test() - - w.clean() diff --git a/lib/PubSubClient-2.6.09/.gitignore b/lib/PubSubClient-EspEasy-2.6.09/.gitignore similarity index 100% rename from lib/PubSubClient-2.6.09/.gitignore rename to lib/PubSubClient-EspEasy-2.6.09/.gitignore diff --git a/lib/PubSubClient-2.6.09/.travis.yml b/lib/PubSubClient-EspEasy-2.6.09/.travis.yml similarity index 100% rename from lib/PubSubClient-2.6.09/.travis.yml rename to lib/PubSubClient-EspEasy-2.6.09/.travis.yml diff --git a/lib/PubSubClient-2.6.09/CHANGES.txt b/lib/PubSubClient-EspEasy-2.6.09/CHANGES.txt similarity index 100% rename from lib/PubSubClient-2.6.09/CHANGES.txt rename to lib/PubSubClient-EspEasy-2.6.09/CHANGES.txt diff --git a/lib/PubSubClient-2.6.09/LICENSE.txt b/lib/PubSubClient-EspEasy-2.6.09/LICENSE.txt similarity index 100% rename from lib/PubSubClient-2.6.09/LICENSE.txt rename to lib/PubSubClient-EspEasy-2.6.09/LICENSE.txt diff --git a/lib/PubSubClient-2.6.09/README.md b/lib/PubSubClient-EspEasy-2.6.09/README.md similarity index 100% rename from lib/PubSubClient-2.6.09/README.md rename to lib/PubSubClient-EspEasy-2.6.09/README.md diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_auth/mqtt_auth.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_auth/mqtt_auth.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_auth/mqtt_auth.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_basic/mqtt_basic.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_basic/mqtt_basic.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_basic/mqtt_basic.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino similarity index 94% rename from lib/PubSubClient-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino index 34333c9c1..e46f85f3e 100644 --- a/lib/PubSubClient-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino +++ b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_esp8266/mqtt_esp8266.ino @@ -38,6 +38,14 @@ long lastMsg = 0; char msg[50]; int value = 0; +void setup() { + pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output + Serial.begin(115200); + setup_wifi(); + client.setServer(mqtt_server, 1883); + client.setCallback(callback); +} + void setup_wifi() { delay(10); @@ -53,8 +61,6 @@ void setup_wifi() { Serial.print("."); } - randomSeed(micros()); - Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); @@ -85,11 +91,8 @@ void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); - // Create a random client ID - String clientId = "ESP8266Client-"; - clientId += String(random(0xffff), HEX); // Attempt to connect - if (client.connect(clientId.c_str())) { + if (client.connect("ESP8266Client")) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("outTopic", "hello world"); @@ -104,15 +107,6 @@ void reconnect() { } } } - -void setup() { - pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output - Serial.begin(115200); - setup_wifi(); - client.setServer(mqtt_server, 1883); - client.setCallback(callback); -} - void loop() { if (!client.connected()) { diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_publish_in_callback/mqtt_publish_in_callback.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_reconnect_nonblocking/mqtt_reconnect_nonblocking.ino diff --git a/lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino b/lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_stream/mqtt_stream.ino similarity index 100% rename from lib/PubSubClient-2.6.09/examples/mqtt_stream/mqtt_stream.ino rename to lib/PubSubClient-EspEasy-2.6.09/examples/mqtt_stream/mqtt_stream.ino diff --git a/lib/PubSubClient-2.6.09/keywords.txt b/lib/PubSubClient-EspEasy-2.6.09/keywords.txt similarity index 100% rename from lib/PubSubClient-2.6.09/keywords.txt rename to lib/PubSubClient-EspEasy-2.6.09/keywords.txt diff --git a/lib/PubSubClient-2.6.09/library.json b/lib/PubSubClient-EspEasy-2.6.09/library.json similarity index 100% rename from lib/PubSubClient-2.6.09/library.json rename to lib/PubSubClient-EspEasy-2.6.09/library.json diff --git a/lib/PubSubClient-2.6.09/library.properties b/lib/PubSubClient-EspEasy-2.6.09/library.properties similarity index 100% rename from lib/PubSubClient-2.6.09/library.properties rename to lib/PubSubClient-EspEasy-2.6.09/library.properties diff --git a/lib/PubSubClient-2.6.09/src/PubSubClient.cpp b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp similarity index 95% rename from lib/PubSubClient-2.6.09/src/PubSubClient.cpp rename to lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp index 11e1c874a..79eb2d52e 100644 --- a/lib/PubSubClient-2.6.09/src/PubSubClient.cpp +++ b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.cpp @@ -117,8 +117,8 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass if (!connected()) { int result = 0; - if (domain != NULL) { - result = _client->connect(this->domain, this->port); + if (domain.length() != 0) { + result = _client->connect(this->domain.c_str(), this->port); } else { result = _client->connect(this->ip, this->port); } @@ -209,7 +209,7 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass boolean PubSubClient::readByte(uint8_t * result) { uint32_t previousMillis = millis(); while(!_client->available()) { - delay(1); // Add esp8266 de-blocking (Tasmota #790) + delay(1); // Add esp8266 de-blocking (Tasmota #790, EspEasy #1943) uint32_t currentMillis = millis(); if(currentMillis - previousMillis >= ((int32_t) MQTT_SOCKET_TIMEOUT * 1000)){ return false; @@ -241,11 +241,17 @@ uint16_t PubSubClient::readPacket(uint8_t* lengthLength) { uint8_t start = 0; do { + if (len == 6) { + // Invalid remaining length encoding - kill the connection + _state = MQTT_DISCONNECTED; + _client->stop(); + return 0; + } if(!readByte(&digit)) return 0; buffer[len++] = digit; length += (digit & 127) * multiplier; multiplier *= 128; - } while ((digit & 128) != 0); + } while ((digit & 128) != 0 && len < (MQTT_MAX_PACKET_SIZE -2)); *lengthLength = len-1; if (isPublish) { @@ -336,6 +342,9 @@ boolean PubSubClient::loop() { } else if (type == MQTTPINGRESP) { pingOutstanding = false; } + } else if (!connected()) { + // readPacket has closed the connection + return false; } } return true; @@ -419,7 +428,7 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig lastOutActivity = millis(); - return rc == tlen + 4 + plength; + return rc == tlen + 3 + llen + plength; } boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) { @@ -469,7 +478,7 @@ boolean PubSubClient::subscribe(const char* topic) { } boolean PubSubClient::subscribe(const char* topic, uint8_t qos) { - if (qos < 0 || qos > 1) { + if (qos > 1) { return false; } if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) { @@ -514,9 +523,12 @@ boolean PubSubClient::unsubscribe(const char* topic) { void PubSubClient::disconnect() { buffer[0] = MQTTDISCONNECT; buffer[1] = 0; - _client->write(buffer,2); + if (_client != NULL) { + _client->write(buffer,2); + _client->flush(); + _client->stop(); + } _state = MQTT_DISCONNECTED; - _client->stop(); lastInActivity = lastOutActivity = millis(); } @@ -524,7 +536,7 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po const char* idp = string; uint16_t i = 0; pos += 2; - while (*idp) { + while (*idp && pos < (MQTT_MAX_PACKET_SIZE - 2)) { buf[pos++] = *idp++; i++; } @@ -559,7 +571,7 @@ PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) { PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) { this->ip = ip; this->port = port; - this->domain = NULL; + this->domain = ""; return *this; } diff --git a/lib/PubSubClient-2.6.09/src/PubSubClient.h b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h similarity index 97% rename from lib/PubSubClient-2.6.09/src/PubSubClient.h rename to lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h index 7e37a472d..003df770e 100644 --- a/lib/PubSubClient-2.6.09/src/PubSubClient.h +++ b/lib/PubSubClient-EspEasy-2.6.09/src/PubSubClient.h @@ -24,13 +24,13 @@ // MQTT_MAX_PACKET_SIZE : Maximum packet size #ifndef MQTT_MAX_PACKET_SIZE //#define MQTT_MAX_PACKET_SIZE 128 -//#define MQTT_MAX_PACKET_SIZE 512 // Tasmota #define MQTT_MAX_PACKET_SIZE 1000 // Tasmota v5.11.1c #endif // MQTT_KEEPALIVE : keepAlive interval in Seconds +// Keepalive timeout for default MQTT Broker is 10s #ifndef MQTT_KEEPALIVE -#define MQTT_KEEPALIVE 15 +#define MQTT_KEEPALIVE 10 #endif // MQTT_SOCKET_TIMEOUT: socket timeout interval in Seconds @@ -75,7 +75,7 @@ #define MQTTQOS1 (1 << 1) #define MQTTQOS2 (2 << 1) -#ifdef ESP8266 +#if defined(ESP8266) || defined(ESP32) #include #define MQTT_CALLBACK_SIGNATURE std::function callback #else @@ -97,7 +97,7 @@ private: boolean write(uint8_t header, uint8_t* buf, uint16_t length); uint16_t writeString(const char* string, uint8_t* buf, uint16_t pos); IPAddress ip; - const char* domain; + String domain; uint16_t port; Stream* stream; int _state; @@ -116,6 +116,7 @@ public: PubSubClient(const char*, uint16_t, Client& client, Stream&); PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client); PubSubClient(const char*, uint16_t, MQTT_CALLBACK_SIGNATURE,Client& client, Stream&); + virtual ~PubSubClient() {} PubSubClient& setServer(IPAddress ip, uint16_t port); PubSubClient& setServer(uint8_t * ip, uint16_t port); diff --git a/lib/PubSubClient-2.6.09/tests/.gitignore b/lib/PubSubClient-EspEasy-2.6.09/tests/.gitignore similarity index 100% rename from lib/PubSubClient-2.6.09/tests/.gitignore rename to lib/PubSubClient-EspEasy-2.6.09/tests/.gitignore diff --git a/lib/PubSubClient-2.6.09/tests/Makefile b/lib/PubSubClient-EspEasy-2.6.09/tests/Makefile similarity index 100% rename from lib/PubSubClient-2.6.09/tests/Makefile rename to lib/PubSubClient-EspEasy-2.6.09/tests/Makefile diff --git a/lib/PubSubClient-2.6.09/tests/README.md b/lib/PubSubClient-EspEasy-2.6.09/tests/README.md similarity index 100% rename from lib/PubSubClient-2.6.09/tests/README.md rename to lib/PubSubClient-EspEasy-2.6.09/tests/README.md diff --git a/lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp similarity index 92% rename from lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp index 3c46e0cc4..69f18646f 100644 --- a/lib/PubSubClient-2.6.09/tests/src/connect_spec.cpp +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/src/connect_spec.cpp @@ -133,23 +133,6 @@ int test_connect_accepts_username_no_password() { END_IT } -int test_connect_accepts_username_blank_password() { - IT("accepts a username and blank password"); - ShimClient shimClient; - shimClient.setAllowConnect(true); - - byte connect[] = { 0x10,0x20,0x0,0x4,0x4d,0x51,0x54,0x54,0x4,0xc2,0x0,0xf,0x0,0xc,0x63,0x6c,0x69,0x65,0x6e,0x74,0x5f,0x74,0x65,0x73,0x74,0x31,0x0,0x4,0x75,0x73,0x65,0x72,0x0,0x0}; - byte connack[] = { 0x20, 0x02, 0x00, 0x00 }; - shimClient.expect(connect,0x26); - shimClient.respond(connack,4); - - PubSubClient client(server, 1883, callback, shimClient); - int rc = client.connect((char*)"client_test1",(char*)"user",(char*)"pass"); - IS_TRUE(rc); - IS_FALSE(shimClient.error()); - - END_IT -} int test_connect_ignores_password_no_username() { IT("ignores a password but no username"); diff --git a/lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/keepalive_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/keepalive_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/keepalive_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Arduino.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Arduino.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Arduino.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/BDDTest.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/BDDTest.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp similarity index 86% rename from lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp index f07759a3a..59a2fbbbd 100644 --- a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.cpp +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.cpp @@ -2,13 +2,9 @@ #include "Arduino.h" Buffer::Buffer() { - this->pos = 0; - this->length = 0; } Buffer::Buffer(uint8_t* buf, size_t size) { - this->pos = 0; - this->length = 0; this->add(buf,size); } bool Buffer::available() { diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Buffer.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Buffer.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Client.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Client.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Client.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Client.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/IPAddress.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/IPAddress.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/ShimClient.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/ShimClient.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Stream.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/Stream.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/Stream.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/Stream.h diff --git a/lib/PubSubClient-2.6.09/tests/src/lib/trace.h b/lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/trace.h similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/lib/trace.h rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/lib/trace.h diff --git a/lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/publish_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/publish_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/publish_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/receive_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/receive_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/receive_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp b/lib/PubSubClient-EspEasy-2.6.09/tests/src/subscribe_spec.cpp similarity index 100% rename from lib/PubSubClient-2.6.09/tests/src/subscribe_spec.cpp rename to lib/PubSubClient-EspEasy-2.6.09/tests/src/subscribe_spec.cpp diff --git a/lib/PubSubClient-2.6.09/tests/testcases/__init__.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/__init__.py similarity index 100% rename from lib/PubSubClient-2.6.09/tests/testcases/__init__.py rename to lib/PubSubClient-EspEasy-2.6.09/tests/testcases/__init__.py diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py new file mode 100644 index 000000000..1b0cc65bb --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_basic.py @@ -0,0 +1,43 @@ +import unittest +import settings + +import time +import mosquitto + +import serial + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + +class mqtt_basic(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic",0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_one(self): + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue[0] + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,"hello world") + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py new file mode 100644 index 000000000..7989f7f17 --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/mqtt_publish_in_callback.py @@ -0,0 +1,64 @@ +import unittest +import settings + +import time +import mosquitto + +import serial + +def on_message(mosq, obj, msg): + obj.message_queue.append(msg) + +class mqtt_publish_in_callback(unittest.TestCase): + + message_queue = [] + + @classmethod + def setUpClass(self): + self.client = mosquitto.Mosquitto("pubsubclient_ut", clean_session=True,obj=self) + self.client.connect(settings.server_ip) + self.client.on_message = on_message + self.client.subscribe("outTopic",0) + + @classmethod + def tearDownClass(self): + self.client.disconnect() + + def test_connect(self): + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,"hello world") + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + def test_publish(self): + self.assertEqual(len(self.message_queue), 0, "message queue not empty") + payload = "abcdefghij" + self.client.publish("inTopic",payload) + + i=30 + while len(self.message_queue) == 0 and i > 0: + self.client.loop() + time.sleep(0.5) + i -= 1 + + self.assertTrue(i>0, "message receive timed-out") + self.assertEqual(len(self.message_queue), 1, "unexpected number of messages received") + msg = self.message_queue.pop(0) + self.assertEqual(msg.mid,0,"message id not 0") + self.assertEqual(msg.topic,"outTopic","message topic incorrect") + self.assertEqual(msg.payload,payload) + self.assertEqual(msg.qos,0,"message qos not 0") + self.assertEqual(msg.retain,False,"message retain flag incorrect") + + + diff --git a/lib/PubSubClient-2.6.09/tests/testcases/settings.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testcases/settings.py similarity index 100% rename from lib/PubSubClient-2.6.09/tests/testcases/settings.py rename to lib/PubSubClient-EspEasy-2.6.09/tests/testcases/settings.py diff --git a/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py b/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py new file mode 100644 index 000000000..0a8e70dfd --- /dev/null +++ b/lib/PubSubClient-EspEasy-2.6.09/tests/testsuite.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +import os +import os.path +import sys +import shutil +from subprocess import call +import importlib +import unittest +import re + +from testcases import settings + +class Workspace(object): + + def __init__(self): + self.root_dir = os.getcwd() + self.build_dir = os.path.join(self.root_dir,"tmpbin"); + self.log_dir = os.path.join(self.root_dir,"logs"); + self.tests_dir = os.path.join(self.root_dir,"testcases"); + self.examples_dir = os.path.join(self.root_dir,"../PubSubClient/examples") + self.examples = [] + self.tests = [] + if not os.path.isdir("../PubSubClient"): + raise Exception("Cannot find PubSubClient library") + try: + import ino + except: + raise Exception("ino tool not installed") + + def init(self): + if os.path.isdir(self.build_dir): + shutil.rmtree(self.build_dir) + os.mkdir(self.build_dir) + if os.path.isdir(self.log_dir): + shutil.rmtree(self.log_dir) + os.mkdir(self.log_dir) + + os.chdir(self.build_dir) + call(["ino","init"]) + + shutil.copytree("../../PubSubClient","lib/PubSubClient") + + filenames = [] + for root, dirs, files in os.walk(self.examples_dir): + filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.examples.append(Sketch(self,e)) + + filenames = [] + for root, dirs, files in os.walk(self.tests_dir): + filenames += [os.path.join(root,f) for f in files if f.endswith(".ino")] + filenames.sort() + for e in filenames: + self.tests.append(Sketch(self,e)) + + def clean(self): + shutil.rmtree(self.build_dir) + +class Sketch(object): + def __init__(self,wksp,fn): + self.w = wksp + self.filename = fn + self.basename = os.path.basename(self.filename) + self.build_log = os.path.join(self.w.log_dir,"%s.log"%(os.path.basename(self.filename),)) + self.build_err_log = os.path.join(self.w.log_dir,"%s.err.log"%(os.path.basename(self.filename),)) + self.build_upload_log = os.path.join(self.w.log_dir,"%s.upload.log"%(os.path.basename(self.filename),)) + + def build(self): + sys.stdout.write(" Build: ") + sys.stdout.flush() + + # Copy sketch over, replacing IP addresses as necessary + fin = open(self.filename,"r") + lines = fin.readlines() + fin.close() + fout = open(os.path.join(self.w.build_dir,"src","sketch.ino"),"w") + for l in lines: + if re.match(r"^byte server\[\] = {",l): + fout.write("byte server[] = { %s };\n"%(settings.server_ip.replace(".",", "),)) + elif re.match(r"^byte ip\[\] = {",l): + fout.write("byte ip[] = { %s };\n"%(settings.arduino_ip.replace(".",", "),)) + else: + fout.write(l) + fout.flush() + fout.close() + + # Run build + fout = open(self.build_log, "w") + ferr = open(self.build_err_log, "w") + rc = call(["ino","build"],stdout=fout,stderr=ferr) + fout.close() + ferr.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_err_log) as f: + for line in f: + print " ",line, + return False + + def upload(self): + sys.stdout.write(" Upload: ") + sys.stdout.flush() + fout = open(self.build_upload_log, "w") + rc = call(["ino","upload"],stdout=fout,stderr=fout) + fout.close() + if rc == 0: + sys.stdout.write("pass") + sys.stdout.write("\n") + return True + else: + sys.stdout.write("fail") + sys.stdout.write("\n") + with open(self.build_upload_log) as f: + for line in f: + print " ",line, + return False + + + def test(self): + # import the matching test case, if it exists + try: + basename = os.path.basename(self.filename)[:-4] + i = importlib.import_module("testcases."+basename) + except: + sys.stdout.write(" Test: no tests found") + sys.stdout.write("\n") + return + c = getattr(i,basename) + + testmethods = [m for m in dir(c) if m.startswith("test_")] + testmethods.sort() + tests = [] + for m in testmethods: + tests.append(c(m)) + + result = unittest.TestResult() + c.setUpClass() + if self.upload(): + sys.stdout.write(" Test: ") + sys.stdout.flush() + for t in tests: + t.run(result) + print "%d/%d"%(result.testsRun-len(result.failures)-len(result.errors),result.testsRun) + if not result.wasSuccessful(): + if len(result.failures) > 0: + for f in result.failures: + print "-- %s"%(str(f[0]),) + print f[1] + if len(result.errors) > 0: + print " Errors:" + for f in result.errors: + print "-- %s"%(str(f[0]),) + print f[1] + c.tearDownClass() + +if __name__ == '__main__': + run_tests = True + + w = Workspace() + w.init() + + for e in w.examples: + print "--------------------------------------" + print "[%s]"%(e.basename,) + if e.build() and run_tests: + e.test() + for e in w.tests: + print "--------------------------------------" + print "[%s]"%(e.basename,) + if e.build() and run_tests: + e.test() + + w.clean() diff --git a/lib/TasmotaSerial-2.0.0/README.md b/lib/TasmotaModbus-1.1.0/README.md similarity index 100% rename from lib/TasmotaSerial-2.0.0/README.md rename to lib/TasmotaModbus-1.1.0/README.md diff --git a/lib/TasmotaModbus-1.1.0/examples/modbustest/modbustest.ino b/lib/TasmotaModbus-1.1.0/examples/modbustest/modbustest.ino new file mode 100644 index 000000000..6fb4720c0 --- /dev/null +++ b/lib/TasmotaModbus-1.1.0/examples/modbustest/modbustest.ino @@ -0,0 +1,31 @@ + +#include + +TasmotaModbus Modbus(14, 12); + +void setup() { + Serial.begin(115200); + Modbus.Begin(9600); + + Serial.println("\nTasmotaModbus test started"); + + Modbus.Send(0x01, 0x04, 0, 8); +} + +void loop() { + if (Modbus.ReceiveReady()) { + uint8_t buffer[26]; + + uint8_t error = Modbus.ReceiveBuffer(buffer, 8); + if (error) { + Serial.print("Modbus response error "); + Serial.println(error); + } else { + Serial.print("Modbus received:"); + for (int i = 0; i < (buffer[2]) ? buffer[2] +5 : sizeof(buffer); i++) { + Serial.print(" "); + Serial.print(buffer[i], HEX); + } + } + } +} diff --git a/lib/ESPAsyncUDP-master/keywords.txt b/lib/TasmotaModbus-1.1.0/keywords.txt similarity index 55% rename from lib/ESPAsyncUDP-master/keywords.txt rename to lib/TasmotaModbus-1.1.0/keywords.txt index 67c0b97a7..e019564cf 100644 --- a/lib/ESPAsyncUDP-master/keywords.txt +++ b/lib/TasmotaModbus-1.1.0/keywords.txt @@ -1,33 +1,26 @@ ####################################### -# Syntax Coloring Map For Ultrasound +# Syntax Coloring Map for TasmotaModbus +# (esp8266) ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### -AsyncUDP KEYWORD1 -AsyncUDPPacket KEYWORD1 +TasmotaModbus KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### -connect KEYWORD2 -connected KEYWORD2 -listen KEYWORD2 -listenMulticast KEYWORD2 -close KEYWORD2 -write KEYWORD2 -broadcast KEYWORD2 -onPacket KEYWORD2 -data KEYWORD2 -length KEYWORD2 -localIP KEYWORD2 -localPort KEYWORD2 -remoteIP KEYWORD2 -remotePort KEYWORD2 +Begin KEYWORD2 +Send KEYWORD2 +ReceiveReady KEYWORD2 +ReceiveBuffer KEYWORD2 +Receive16BitRegister KEYWORD2 +Receive32BitRegister KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### + diff --git a/lib/TasmotaModbus-1.1.0/library.json b/lib/TasmotaModbus-1.1.0/library.json new file mode 100644 index 000000000..d983bec32 --- /dev/null +++ b/lib/TasmotaModbus-1.1.0/library.json @@ -0,0 +1,15 @@ +{ + "name": "TasmotaModbus", + "version": "1.1.0", + "keywords": [ + "serial", "io", "TasmotaModbus" + ], + "description": "Basic modbus wrapper for TasmotaSerial for ESP8266.", + "repository": + { + "type": "git", + "url": "https://github.com/arendst/Sonoff-Tasmota/lib/TasmotaModbus" + }, + "frameworks": "arduino", + "platforms": "espressif8266" +} diff --git a/lib/TasmotaModbus-1.1.0/library.properties b/lib/TasmotaModbus-1.1.0/library.properties new file mode 100644 index 000000000..bb42fb372 --- /dev/null +++ b/lib/TasmotaModbus-1.1.0/library.properties @@ -0,0 +1,9 @@ +name=TasmotaModbus +version=1.1.0 +author=Theo Arends +maintainer=Theo Arends +sentence=Basic modbus wrapper for TasmotaSerial for ESP8266. +paragraph= +category=Signal Input/Output +url= +architectures=esp8266 diff --git a/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp new file mode 100644 index 000000000..0be2c9de3 --- /dev/null +++ b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.cpp @@ -0,0 +1,147 @@ +/* + TasmotaModbus.cpp - Basic modbus wrapper for TasmotaSerial for Tasmota + + Copyright (C) 2018 Theo Arends + + This library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "TasmotaModbus.h" + +TasmotaModbus::TasmotaModbus(int receive_pin, int transmit_pin) : TasmotaSerial(receive_pin, transmit_pin, 1) +{ + mb_address = 0; +} + +uint16_t CalculateCRC(uint8_t *frame, uint8_t num) +{ + uint16_t crc = 0xFFFF; + uint16_t flag; + + for (uint8_t i = 0; i < num; i++) { + crc ^= frame[i]; + for (uint8_t j = 8; j; j--) { + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } else { // Else LSB is not set + crc >>= 1; // Just shift right + } + } + } + return crc; +} + +int TasmotaModbus::Begin(long speed, int stop_bits) +{ + int result = 0; + + if (begin(speed, stop_bits)) { + result = 1; + if (hardwareSerial()) { result = 2; } + } + return result; +} + +void TasmotaModbus::Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count) +{ + uint8_t frame[8]; + + mb_address = device_address; // Save address for receipt check + + frame[0] = mb_address; // 0xFE default device address or dedicated like 0x01 + frame[1] = function_code; + frame[2] = (uint8_t)(start_address >> 8); + frame[3] = (uint8_t)(start_address); + frame[4] = (uint8_t)(register_count >> 8); + frame[5] = (uint8_t)(register_count); + uint16_t crc = CalculateCRC(frame, 6); + frame[6] = (uint8_t)(crc); + frame[7] = (uint8_t)(crc >> 8); + + flush(); + write(frame, sizeof(frame)); +} + +bool TasmotaModbus::ReceiveReady() +{ + return (available() > 4); +} + +uint8_t TasmotaModbus::ReceiveBuffer(uint8_t *buffer, uint8_t register_count) +{ + uint8_t len = 0; + uint32_t last = millis(); + while ((available() > 0) && (len < (register_count *2) + 5) && (millis() - last < 10)) { + uint8_t data = (uint8_t)read(); + if (!len) { // Skip leading data as provided by hardware serial + if (mb_address == data) { + buffer[len++] = data; + } + } else { + buffer[len++] = data; + if (3 == len) { + if (buffer[1] & 0x80) { // 01 84 02 f2 f1 + return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error + } + } + } + last = millis(); + } + + if (len < 7) { return 7; } // 7 = Not enough data + if (len != buffer[2] + 5) { return 8; } // 8 = Unexpected result + + uint16_t crc = (buffer[len -1] << 8) | buffer[len -2]; + if (CalculateCRC(buffer, len -2) != crc) { return 9; } // 9 = crc error + + return 0; // 0 = No error +} + +uint8_t TasmotaModbus::Receive16BitRegister(uint16_t *value) +{ + // 0 1 2 3 4 5 6 + // 01 04 02 43 21 HH LL + // Id Cc Sz Regis Crc-- + + uint8_t buffer[7]; + + uint8_t error = ReceiveBuffer(buffer, 1); // 1 x 16bit register + if (!error) { + *value = (buffer[3] << 8) | buffer[4]; + } + + return error; +} + +uint8_t TasmotaModbus::Receive32BitRegister(float *value) +{ + // 0 1 2 3 4 5 6 7 8 + // 01 04 04 87 65 43 21 HH LL + // Id Cc Sz Register--- Crc-- + + uint8_t buffer[9]; + + *value = NAN; + + uint8_t error = ReceiveBuffer(buffer, 2); // 1 x 32bit register + if (!error) { + ((uint8_t*)value)[3] = buffer[3]; + ((uint8_t*)value)[2] = buffer[4]; + ((uint8_t*)value)[1] = buffer[5]; + ((uint8_t*)value)[0] = buffer[6]; + } + + return error; +} diff --git a/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.h b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.h new file mode 100644 index 000000000..5176aa89e --- /dev/null +++ b/lib/TasmotaModbus-1.1.0/src/TasmotaModbus.h @@ -0,0 +1,57 @@ +/* + TasmotaModbus.h - Basic modbus wrapper for TasmotaSerial for Tasmota + + Copyright (C) 2018 Theo Arends + + This library is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef TasmotaModbus_h +#define TasmotaModbus_h + +#include +#include + +#define TM_MODBUS_BAUDRATE 9600 // Default baudrate + +class TasmotaModbus : public TasmotaSerial { + public: + TasmotaModbus(int receive_pin, int transmit_pin); + virtual ~TasmotaModbus() {} + + int Begin(long speed = TM_MODBUS_BAUDRATE, int stop_bits = 1); + + void Send(uint8_t device_address, uint8_t function_code, uint16_t start_address, uint16_t register_count); + + bool ReceiveReady(); + + /* Return codes: + * 0 - No error + * 1 - Illegal function + * 2 - Illegal address + * 3 - Illegal data + * 4 - Slave error + * 7 - Not enough minimal data received + * 8 - Not enough data receieved + * 9 - Crc error + */ + uint8_t ReceiveBuffer(uint8_t *buffer, uint8_t register_count); + uint8_t Receive16BitRegister(uint16_t *value); + uint8_t Receive32BitRegister(float *value); + + private: + uint8_t mb_address; +}; + +#endif // TasmotaModbus_h diff --git a/lib/TasmotaSerial-2.1.0/README.md b/lib/TasmotaSerial-2.1.0/README.md new file mode 100644 index 000000000..019aafc07 --- /dev/null +++ b/lib/TasmotaSerial-2.1.0/README.md @@ -0,0 +1,7 @@ +# TasmotaSerial + +Implementation of software serial with hardware serial fallback library for the ESP8266 + +Allows for several instances to be active at the same time. + +Please note that due to the fact that the ESP always have other activities ongoing, there will be some inexactness in interrupt timings. This may lead to bit errors when having heavy data traffic. diff --git a/lib/TasmotaSerial-2.0.0/examples/swsertest/swsertest.ino b/lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino similarity index 100% rename from lib/TasmotaSerial-2.0.0/examples/swsertest/swsertest.ino rename to lib/TasmotaSerial-2.1.0/examples/swsertest/swsertest.ino diff --git a/lib/TasmotaSerial-2.0.0/keywords.txt b/lib/TasmotaSerial-2.1.0/keywords.txt similarity index 100% rename from lib/TasmotaSerial-2.0.0/keywords.txt rename to lib/TasmotaSerial-2.1.0/keywords.txt diff --git a/lib/TasmotaSerial-2.0.0/library.json b/lib/TasmotaSerial-2.1.0/library.json similarity index 94% rename from lib/TasmotaSerial-2.0.0/library.json rename to lib/TasmotaSerial-2.1.0/library.json index 00a2a9e0f..59d06ad5f 100644 --- a/lib/TasmotaSerial-2.0.0/library.json +++ b/lib/TasmotaSerial-2.1.0/library.json @@ -1,6 +1,6 @@ { "name": "TasmotaSerial", - "version": "2.0.0", + "version": "2.1.0", "keywords": [ "serial", "io", "TasmotaSerial" ], diff --git a/lib/TasmotaSerial-2.0.0/library.properties b/lib/TasmotaSerial-2.1.0/library.properties similarity index 94% rename from lib/TasmotaSerial-2.0.0/library.properties rename to lib/TasmotaSerial-2.1.0/library.properties index b250399b9..93f4a1d39 100644 --- a/lib/TasmotaSerial-2.0.0/library.properties +++ b/lib/TasmotaSerial-2.1.0/library.properties @@ -1,5 +1,5 @@ name=TasmotaSerial -version=2.0.0 +version=2.1.0 author=Theo Arends maintainer=Theo Arends sentence=Implementation of software serial with hardware serial fallback for ESP8266. diff --git a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.cpp b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp similarity index 91% rename from lib/TasmotaSerial-2.0.0/src/TasmotaSerial.cpp rename to lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp index cbd2a3523..d9fc29e6f 100644 --- a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.cpp +++ b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.cpp @@ -80,6 +80,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa { m_valid = false; m_hardserial = 0; + m_stop_bits = 1; if (!((isValidGPIOpin(receive_pin)) && (isValidGPIOpin(transmit_pin) || transmit_pin == 16))) { return; } @@ -106,15 +107,33 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fa m_valid = true; } +TasmotaSerial::~TasmotaSerial() +{ + if (!m_hardserial) { + if (m_rx_pin > -1) { + detachInterrupt(m_rx_pin); + tms_obj_list[m_rx_pin] = NULL; + if (m_buffer) { + free(m_buffer); + } + } + } +} + bool TasmotaSerial::isValidGPIOpin(int pin) { return (pin >= -1 && pin <= 5) || (pin >= 12 && pin <= 15); } -bool TasmotaSerial::begin(long speed) { +bool TasmotaSerial::begin(long speed, int stop_bits) { + m_stop_bits = ((stop_bits -1) &1) +1; if (m_hardserial) { Serial.flush(); - Serial.begin(speed, SERIAL_8N1); + if (2 == m_stop_bits) { + Serial.begin(speed, SERIAL_8N2); + } else { + Serial.begin(speed, SERIAL_8N1); + } } else { // Use getCycleCount() loop to get as exact timing as possible m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed; @@ -195,9 +214,11 @@ size_t TasmotaSerial::write(uint8_t b) TM_SERIAL_WAIT; b >>= 1; } - // Stop bit - digitalWrite(m_tx_pin, HIGH); - TM_SERIAL_WAIT; + // Stop bit(s) + for (int i = 0; i < m_stop_bits; i++) { + digitalWrite(m_tx_pin, HIGH); + TM_SERIAL_WAIT; + } if (m_high_speed) sei(); return 1; } @@ -220,8 +241,12 @@ void TasmotaSerial::rxRead() rec >>= 1; if (digitalRead(m_rx_pin)) rec |= 0x80; } - // Stop bit + // Stop bit(s) TM_SERIAL_WAIT; + if (2 == m_stop_bits) { + digitalRead(m_rx_pin); + TM_SERIAL_WAIT; + } // Store the received value in the buffer unless we have an overflow int next = (m_in_pos+1) % TM_SERIAL_BUFFER_SIZE; if (next != (int)m_out_pos) { diff --git a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.h b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h similarity index 95% rename from lib/TasmotaSerial-2.0.0/src/TasmotaSerial.h rename to lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h index d4c993368..e40c34ee8 100644 --- a/lib/TasmotaSerial-2.0.0/src/TasmotaSerial.h +++ b/lib/TasmotaSerial-2.1.0/src/TasmotaSerial.h @@ -33,12 +33,15 @@ #define TM_SERIAL_USE_IRAM // Enable to use iram (+368 bytes) #endif +#include #include class TasmotaSerial : public Stream { public: TasmotaSerial(int receive_pin, int transmit_pin, bool hardware_fallback = false); - bool begin(long speed); + virtual ~TasmotaSerial(); + + bool begin(long speed, int stop_bits = 1); bool begin(); bool hardwareSerial(); int peek(); @@ -62,6 +65,7 @@ class TasmotaSerial : public Stream { bool m_high_speed; int m_rx_pin; int m_tx_pin; + int m_stop_bits; unsigned long m_bit_time; unsigned int m_in_pos; unsigned int m_out_pos; diff --git a/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties b/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties new file mode 100644 index 000000000..07a9e0a07 --- /dev/null +++ b/lib/esp-epaper-29-ws-20171230-gemu-1.0/library.properties @@ -0,0 +1,9 @@ +name=Waveshare esp 2.9 inch e-paper display driver +version=1.0 +author=Gerhard Muntz +maintainer=Gerhard Muntz +sentence=ESP8266 library for Waveshare e-paper display. +paragraph= +category=Display +url=https://github.com/gemu2015/Sonoff-Tasmota/tree/displays/lib/esp-epaper-29-ws-20171230-gemu-1.0# +architectures=esp8266 diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp b/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp index 624e08d18..23ee319e6 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip-send.cpp @@ -77,13 +77,10 @@ void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t da DEBUG_PRINTLN(F("")); #endif -#ifdef USE_ASYNC_UDP - udp.writeTo(buf, len, MULTICAST_IP, MULTICAST_PORT); -#else udp.beginPacketMulticast(MULTICAST_IP, MULTICAST_PORT, WiFi.localIP()); udp.write(buf, len); udp.endPacket(); -#endif + } void ESPKNXIP::send_1bit(address_t const &receiver, knx_command_type_t ct, uint8_t bit) diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp b/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp index 767fa9752..5917e62f3 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip.cpp @@ -95,13 +95,7 @@ void ESPKNXIP::__start() #endif server->begin(); } - -#ifdef USE_ASYNC_UDP - udp.listenMulticast(MULTICAST_IP, MULTICAST_PORT); - udp.onPacket([this](AsyncUDPPacket &packet) { __loop_knx(packet); }); -#else udp.beginMulticast(WiFi.localIP(), MULTICAST_IP, MULTICAST_PORT); -#endif } void ESPKNXIP::save_to_eeprom() @@ -516,9 +510,7 @@ feedback_id_t ESPKNXIP::feedback_register_action(String name, feedback_action_fp void ESPKNXIP::loop() { - #ifndef USE_ASYNC_UDP __loop_knx(); - #endif if (server != nullptr) { __loop_webserver(); @@ -530,15 +522,9 @@ void ESPKNXIP::__loop_webserver() server->handleClient(); } -#ifdef USE_ASYNC_UDP -void ESPKNXIP::__loop_knx(AsyncUDPPacket &packet) -{ - size_t read = packet.length(); -#else void ESPKNXIP::__loop_knx() { int read = udp.parsePacket(); -#endif if (!read) { @@ -548,23 +534,15 @@ void ESPKNXIP::__loop_knx() DEBUG_PRINT(F("LEN: ")); DEBUG_PRINTLN(read); -#ifdef USE_ASYNC_UDP - uint8_t *buf = packet.data(); -#else uint8_t buf[read]; udp.read(buf, read); udp.flush(); -#endif DEBUG_PRINT(F("Got packet:")); #ifdef ESP_KNX_DEBUG -#ifdef USE_ASYNC_UDP - for (size_t i = 0; i < read; ++i) -#else for (int i = 0; i < read; ++i) -#endif { DEBUG_PRINT(F(" 0x")); diff --git a/lib/esp-knx-ip-0.5.1/esp-knx-ip.h b/lib/esp-knx-ip-0.5.1/esp-knx-ip.h index 515a5d843..e2346c5a3 100644 --- a/lib/esp-knx-ip-0.5.1/esp-knx-ip.h +++ b/lib/esp-knx-ip-0.5.1/esp-knx-ip.h @@ -45,18 +45,7 @@ #include "Arduino.h" #include #include - -#include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) -#ifndef ARDUINO_ESP8266_RELEASE_2_3_0 -#define USE_ASYNC_UDP // UDP WIFI Library Selection for Multicast -#endif - -#ifdef USE_ASYNC_UDP -#include -#else #include -#endif - #include #include "DPT.h" @@ -529,11 +518,7 @@ class ESPKNXIP { private: void __start(); -#ifdef USE_ASYNC_UDP - void __loop_knx(AsyncUDPPacket &packet); -#else void __loop_knx(); -#endif // Webserver functions void __loop_webserver(); @@ -569,11 +554,7 @@ class ESPKNXIP { ESP8266WebServer *server; address_t physaddr; -#ifdef USE_ASYNC_UDP - AsyncUDP udp; -#else WiFiUDP udp; -#endif callback_assignment_id_t registered_callback_assignments; callback_assignment_id_t free_callback_assignment_slots; diff --git a/lib/rc-switch-2.6.2.13/.gitignore b/lib/rc-switch-2.6.2.13/.gitignore new file mode 100644 index 000000000..d0972bb47 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/.gitignore @@ -0,0 +1,17 @@ +# Mac stuff +.DS_Store + +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + diff --git a/lib/rc-switch-2.6.2.13/.travis.yml b/lib/rc-switch-2.6.2.13/.travis.yml new file mode 100644 index 000000000..16cadf8a2 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/.travis.yml @@ -0,0 +1,69 @@ +language: c +python: + - "2.7" + +# Cache PlatformIO packages using Travis CI container-based infrastructure +cache: + pip: true + directories: + - "~/.platformio" + +env: + - > + PLATFORMIO_CI_SRC=$PWD/examples/Webserver + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/Webserver.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + - > + PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Simple + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Simple.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeC_Intertechno + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeC_Intertechno.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeD_REV + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeD_REV.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches_Lightweight + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches_Lightweight.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/TypeB_WithRotaryOrSlidingSwitches + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeB_WithRotaryOrSlidingSwitches.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24" + - > + PLATFORMIO_CI_SRC=$PWD/examples/SendDemo + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/SendDemo.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + - > + PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Advanced + ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Advanced.ino + BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01" + +before_install: + # Arduino IDE + - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" + - sleep 3 + - export DISPLAY=:1.0 + - wget http://downloads.arduino.cc/arduino-1.6.9-linux64.tar.xz + - tar xf arduino-1.6.9-linux64.tar.xz + - sudo mv arduino-1.6.9 /usr/local/share/arduino + - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino + +install: + # Arduino IDE + - ln -s $PWD /usr/local/share/arduino/libraries/rc-switch + # PlatformIO + - sudo pip install -U platformio + +script: + # Arduino IDE + - arduino --verify --board arduino:avr:uno ${ARDUINOIDE_CI_SRC} + # PlatformIO + - platformio ci --lib="." ${BOARDS} diff --git a/lib/rc-switch-2.6.2.13/RCSwitch.cpp b/lib/rc-switch-2.6.2.13/RCSwitch.cpp new file mode 100644 index 000000000..1a6736e24 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/RCSwitch.cpp @@ -0,0 +1,701 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Andreas Steinel / A.(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + - Johann Richard / .(at)gmail(dot)com + - Vlad Gheorghe / .(at)gmail(dot)com https://github.com/vgheo + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "RCSwitch.h" + +#ifdef RaspberryPi + // PROGMEM and _P functions are for AVR based microprocessors, + // so we must normalize these for the ARM processor: + #define PROGMEM + #define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) +#endif + +#if defined(ESP8266) || defined(ESP32) + // interrupt handler and related code must be in RAM on ESP8266, + // according to issue #46. + #define RECEIVE_ATTR ICACHE_RAM_ATTR +#else + #define RECEIVE_ATTR +#endif + + +/* Format for protocol definitions: + * {pulselength, Sync bit, "0" bit, "1" bit} + * + * pulselength: pulse length in microseconds, e.g. 350 + * Sync bit: {1, 31} means 1 high pulse and 31 low pulses + * (perceived as a 31*pulselength long pulse, total length of sync bit is + * 32*pulselength microseconds), i.e: + * _ + * | |_______________________________ (don't count the vertical bars) + * "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse + * and 3 low pulses, total length (1+3)*pulselength, i.e: + * _ + * | |___ + * "1" bit: waveform for a data bit of value "1", e.g. {3,1}: + * ___ + * | |_ + * + * These are combined to form Tri-State bits when sending or receiving codes. + */ +#if defined(ESP8266) || defined(ESP32) +static const RCSwitch::Protocol proto[] = { +#else +static const RCSwitch::Protocol PROGMEM proto[] = { +#endif + { 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1 + { 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2 + { 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3 + { 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4 + { 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5 + { 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B) + { 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false } // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote) +}; + +enum { + numProto = sizeof(proto) / sizeof(proto[0]) +}; + +#if not defined( RCSwitchDisableReceiving ) +volatile unsigned long RCSwitch::nReceivedValue = 0; +volatile unsigned int RCSwitch::nReceivedBitlength = 0; +volatile unsigned int RCSwitch::nReceivedDelay = 0; +volatile unsigned int RCSwitch::nReceivedProtocol = 0; +int RCSwitch::nReceiveTolerance = 60; +const unsigned int RCSwitch::nSeparationLimit = 4300; +// separationLimit: minimum microseconds between received codes, closer codes are ignored. +// according to discussion on issue #14 it might be more suitable to set the separation +// limit to the same time as the 'low' part of the sync signal for the current protocol. +unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; +#endif + +RCSwitch::RCSwitch() { + this->nTransmitterPin = -1; + this->setRepeatTransmit(10); + this->setProtocol(1); + #if not defined( RCSwitchDisableReceiving ) + this->nReceiverInterrupt = -1; + this->setReceiveTolerance(60); + RCSwitch::nReceivedValue = 0; + #endif +} + +/** + * Sets the protocol to send. + */ +void RCSwitch::setProtocol(Protocol protocol) { + this->protocol = protocol; +} + +/** + * Sets the protocol to send, from a list of predefined protocols + */ +void RCSwitch::setProtocol(int nProtocol) { + if (nProtocol < 1 || nProtocol > numProto) { + nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ??? + } +#if defined(ESP8266) || defined(ESP32) + this->protocol = proto[nProtocol-1]; +#else + memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol)); +#endif +} + +/** + * Sets the protocol to send with pulse length in microseconds. + */ +void RCSwitch::setProtocol(int nProtocol, int nPulseLength) { + setProtocol(nProtocol); + this->setPulseLength(nPulseLength); +} + + +/** + * Sets pulse length in microseconds + */ +void RCSwitch::setPulseLength(int nPulseLength) { + this->protocol.pulseLength = nPulseLength; +} + +/** + * Sets Repeat Transmits + */ +void RCSwitch::setRepeatTransmit(int nRepeatTransmit) { + this->nRepeatTransmit = nRepeatTransmit; +} + +/** + * Set Receiving Tolerance + */ +#if not defined( RCSwitchDisableReceiving ) +void RCSwitch::setReceiveTolerance(int nPercent) { + RCSwitch::nReceiveTolerance = nPercent; +} +#endif + + +/** + * Enable transmissions + * + * @param nTransmitterPin Arduino Pin to which the sender is connected to + */ +void RCSwitch::enableTransmit(int nTransmitterPin) { + this->nTransmitterPin = nTransmitterPin; + pinMode(this->nTransmitterPin, OUTPUT); +} + +/** + * Disable transmissions + */ +void RCSwitch::disableTransmit() { + this->nTransmitterPin = -1; +} + +/** + * Switch a remote switch on (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOn(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOff(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOn(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) ); +} + +/** + * Switch a remote switch off (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOff(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) ); +} + +/** + * Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOn(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOn(sGroup, code[nChannel]); +} + +/** + * Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOff(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOff(sGroup, code[nChannel]); +} + +/** + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOn(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) ); +} + +/** + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOff(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) ); +} + + +/** + * Returns a char[13], representing the code word to be send. + * + */ +char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0'; + } + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0'; + } + + sReturn[nReturnPos++] = bStatus ? '0' : 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for type B switches with two rotary/sliding switches. + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-----------------------------+----------+------------+ + * | 4 bits address | 4 bits address | 3 bits | 1 bit | + * | switch group | switch number | not used | on / off | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 | + * +-----------------------------+-----------------------------+----------+------------+ + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { + return 0; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F'; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F'; + } + + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Like getCodeWord (Type C = Intertechno) + */ +char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + int nFamily = (int)sFamily - 'a'; + if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { + return 0; + } + + // encode the family into four bits + sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0'; + + // encode the device and group + sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0'; + + // encode the status code + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for the REV Switch Type + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-------------------+----------+--------------+ + * | 4 bits address | 3 bits address | 3 bits | 2 bits | + * | switch group | device number | not used | on / off | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 | + * +-----------------------------+-------------------+----------+--------------+ + * + * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ + * + * @param sGroup Name of the switch group (A..D, resp. a..d) + * @param nDevice Number of the switch itself (1..3) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + // sGroup must be one of the letters in "abcdABCD" + int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A'; + if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) { + return 0; + } + + for (int i = 0; i < 4; i++) { + sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F'; + } + + for (int i = 1; i <= 3; i++) { + sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F'; + } + + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + + sReturn[nReturnPos++] = bStatus ? '1' : '0'; + sReturn[nReturnPos++] = bStatus ? '0' : '1'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * @param sCodeWord a tristate code word consisting of the letter 0, 1, F + */ +void RCSwitch::sendTriState(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 2L; + switch (*p) { + case '0': + // bit pattern 00 + break; + case 'F': + // bit pattern 01 + code |= 1L; + break; + case '1': + // bit pattern 11 + code |= 3L; + break; + } + length += 2; + } + this->send(code, length); +} + +/** + * @param sCodeWord a binary code word consisting of the letter 0, 1 + */ +void RCSwitch::send(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 1L; + if (*p != '0') + code |= 1L; + length++; + } + this->send(code, length); +} + +/** + * Transmit the first 'length' bits of the integer 'code'. The + * bits are sent from MSB to LSB, i.e., first the bit at position length-1, + * then the bit at position length-2, and so on, till finally the bit at position 0. + */ +void RCSwitch::send(unsigned long code, unsigned int length) { + if (this->nTransmitterPin == -1) + return; + +#if not defined( RCSwitchDisableReceiving ) + // make sure the receiver is disabled while we transmit + int nReceiverInterrupt_backup = nReceiverInterrupt; + if (nReceiverInterrupt_backup != -1) { + this->disableReceive(); + } +#endif + + for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { + for (int i = length-1; i >= 0; i--) { + if (code & (1L << i)) + this->transmit(protocol.one); + else + this->transmit(protocol.zero); + } + this->transmit(protocol.syncFactor); + } + + // Disable transmit after sending (i.e., for inverted protocols) + digitalWrite(this->nTransmitterPin, LOW); + +#if not defined( RCSwitchDisableReceiving ) + // enable receiver again if we just disabled it + if (nReceiverInterrupt_backup != -1) { + this->enableReceive(nReceiverInterrupt_backup); + } +#endif +} + +/** + * Transmit a single high-low pulse. + */ +void RCSwitch::transmit(HighLow pulses) { + uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH; + uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW; + + digitalWrite(this->nTransmitterPin, firstLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.high); + digitalWrite(this->nTransmitterPin, secondLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.low); +} + + +#if not defined( RCSwitchDisableReceiving ) +/** + * Enable receiving data + */ +void RCSwitch::enableReceive(int interrupt) { + this->nReceiverInterrupt = interrupt; + this->enableReceive(); +} + +void RCSwitch::enableReceive() { + if (this->nReceiverInterrupt != -1) { + RCSwitch::nReceivedValue = 0; + RCSwitch::nReceivedBitlength = 0; +#if defined(RaspberryPi) // Raspberry Pi + wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); +#else // Arduino + attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); +#endif + } +} + +/** + * Disable receiving data + */ +void RCSwitch::disableReceive() { +#if not defined(RaspberryPi) // Arduino + detachInterrupt(this->nReceiverInterrupt); +#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR + this->nReceiverInterrupt = -1; +} + +bool RCSwitch::available() { + return RCSwitch::nReceivedValue != 0; +} + +void RCSwitch::resetAvailable() { + RCSwitch::nReceivedValue = 0; +} + +unsigned long RCSwitch::getReceivedValue() { + return RCSwitch::nReceivedValue; +} + +unsigned int RCSwitch::getReceivedBitlength() { + return RCSwitch::nReceivedBitlength; +} + +unsigned int RCSwitch::getReceivedDelay() { + return RCSwitch::nReceivedDelay; +} + +unsigned int RCSwitch::getReceivedProtocol() { + return RCSwitch::nReceivedProtocol; +} + +unsigned int* RCSwitch::getReceivedRawdata() { + return RCSwitch::timings; +} + +/* helper function for the receiveProtocol method */ +static inline unsigned int diff(int A, int B) { + return abs(A - B); +} + +/** + * + */ +bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) { +#if defined(ESP8266) || defined(ESP32) + const Protocol &pro = proto[p-1]; +#else + Protocol pro; + memcpy_P(&pro, &proto[p-1], sizeof(Protocol)); +#endif + + unsigned long code = 0; + //Assuming the longer pulse length is the pulse captured in timings[0] + const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high); + const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses; + const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + + /* For protocols that start low, the sync period looks like + * _________ + * _____________| |XXXXXXXXXXXX| + * + * |--1st dur--|-2nd dur-|-Start data-| + * + * The 3rd saved duration starts the data. + * + * For protocols that start high, the sync period looks like + * + * ______________ + * | |____________|XXXXXXXXXXXXX| + * + * |-filtered out-|--1st dur--|--Start data--| + * + * The 2nd saved duration starts the data + */ + const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1); + + for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) { + code <<= 1; + if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { + // zero + } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) { + // one + code |= 1; + } else { + // Failed + return false; + } + } + + if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = p; + return true; + } + + return false; +} + +void RECEIVE_ATTR RCSwitch::handleInterrupt() { + + static unsigned int changeCount = 0; + static unsigned long lastTime = 0; + static unsigned int repeatCount = 0; + + const long time = micros(); + const unsigned int duration = time - lastTime; + + if (duration > RCSwitch::nSeparationLimit) { + // A long stretch without signal level change occurred. This could + // be the gap between two transmission. + if (diff(duration, RCSwitch::timings[0]) < 200) { + // This long signal is close in length to the long signal which + // started the previously recorded timings; this suggests that + // it may indeed by a a gap between two transmissions (we assume + // here that a sender will send the signal multiple times, + // with roughly the same gap between them). + repeatCount++; + if (repeatCount == 2) { + for(unsigned int i = 1; i <= numProto; i++) { + if (receiveProtocol(i, changeCount)) { + // receive succeeded for protocol i + break; + } + } + repeatCount = 0; + } + } + changeCount = 0; + } + + // detect overflow + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + + RCSwitch::timings[changeCount++] = duration; + lastTime = time; +} +#endif diff --git a/lib/rc-switch-2.6.2.13/RCSwitch.h b/lib/rc-switch-2.6.2.13/RCSwitch.h new file mode 100644 index 000000000..b7755e0b4 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/RCSwitch.h @@ -0,0 +1,184 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _RCSwitch_h +#define _RCSwitch_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific + #include "Energia.h" +#elif defined(RPI) // Raspberry Pi + #define RaspberryPi + + // Include libraries for RPi: + #include /* memcpy */ + #include /* abs */ + #include +#elif defined(SPARK) + #include "application.h" +#else + #include "WProgram.h" +#endif + +#include + + +// At least for the ATTiny X4/X5, receiving has to be disabled due to +// missing libm depencies (udivmodhi4) +#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ ) +#define RCSwitchDisableReceiving +#endif + +// Number of maximum high/Low changes per packet. +// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync +#define RCSWITCH_MAX_CHANGES 67 + +class RCSwitch { + + public: + RCSwitch(); + + void switchOn(int nGroupNumber, int nSwitchNumber); + void switchOff(int nGroupNumber, int nSwitchNumber); + void switchOn(const char* sGroup, int nSwitchNumber); + void switchOff(const char* sGroup, int nSwitchNumber); + void switchOn(char sFamily, int nGroup, int nDevice); + void switchOff(char sFamily, int nGroup, int nDevice); + void switchOn(const char* sGroup, const char* sDevice); + void switchOff(const char* sGroup, const char* sDevice); + void switchOn(char sGroup, int nDevice); + void switchOff(char sGroup, int nDevice); + + void sendTriState(const char* sCodeWord); + void send(unsigned long code, unsigned int length); + void send(const char* sCodeWord); + + #if not defined( RCSwitchDisableReceiving ) + void enableReceive(int interrupt); + void enableReceive(); + void disableReceive(); + bool available(); + void resetAvailable(); + + unsigned long getReceivedValue(); + unsigned int getReceivedBitlength(); + unsigned int getReceivedDelay(); + unsigned int getReceivedProtocol(); + unsigned int* getReceivedRawdata(); + #endif + + void enableTransmit(int nTransmitterPin); + void disableTransmit(); + void setPulseLength(int nPulseLength); + void setRepeatTransmit(int nRepeatTransmit); + #if not defined( RCSwitchDisableReceiving ) + void setReceiveTolerance(int nPercent); + #endif + + /** + * Description of a single pule, which consists of a high signal + * whose duration is "high" times the base pulse length, followed + * by a low signal lasting "low" times the base pulse length. + * Thus, the pulse overall lasts (high+low)*pulseLength + */ + struct HighLow { + uint8_t high; + uint8_t low; + }; + + /** + * A "protocol" describes how zero and one bits are encoded into high/low + * pulses. + */ + struct Protocol { + /** base pulse length in microseconds, e.g. 350 */ + uint16_t pulseLength; + + HighLow syncFactor; + HighLow zero; + HighLow one; + + /** + * If true, interchange high and low logic levels in all transmissions. + * + * By default, RCSwitch assumes that any signals it sends or receives + * can be broken down into pulses which start with a high signal level, + * followed by a a low signal level. This is e.g. the case for the + * popular PT 2260 encoder chip, and thus many switches out there. + * + * But some devices do it the other way around, and start with a low + * signal level, followed by a high signal level, e.g. the HT6P20B. To + * accommodate this, one can set invertedSignal to true, which causes + * RCSwitch to change how it interprets any HighLow struct FOO: It will + * then assume transmissions start with a low signal lasting + * FOO.high*pulseLength microseconds, followed by a high signal lasting + * FOO.low*pulseLength microseconds. + */ + bool invertedSignal; + }; + + void setProtocol(Protocol protocol); + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + + private: + char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus); + char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus); + char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus); + char* getCodeWordD(char group, int nDevice, bool bStatus); + void transmit(HighLow pulses); + + #if not defined( RCSwitchDisableReceiving ) + static void handleInterrupt(); + static bool receiveProtocol(const int p, unsigned int changeCount); + int nReceiverInterrupt; + #endif + int nTransmitterPin; + int nRepeatTransmit; + + Protocol protocol; + + #if not defined( RCSwitchDisableReceiving ) + static int nReceiveTolerance; + volatile static unsigned long nReceivedValue; + volatile static unsigned int nReceivedBitlength; + volatile static unsigned int nReceivedDelay; + volatile static unsigned int nReceivedProtocol; + const static unsigned int nSeparationLimit; + /* + * timings[0] contains sync timing, followed by a number of bits + */ + static unsigned int timings[RCSWITCH_MAX_CHANGES]; + #endif + + +}; + +#endif diff --git a/lib/rc-switch-2.6.2.13/README.md b/lib/rc-switch-2.6.2.13/README.md new file mode 100644 index 000000000..bf12543be --- /dev/null +++ b/lib/rc-switch-2.6.2.13/README.md @@ -0,0 +1,41 @@ +# rc-switch +[![Build Status](https://travis-ci.org/sui77/rc-switch.svg?branch=master)](https://travis-ci.org/sui77/rc-switch) + +Use your Arduino or Raspberry Pi to operate remote radio controlled devices + +## Download +https://github.com/sui77/rc-switch/releases/latest + +rc-switch is also listed in the arduino library manager. + +## Wiki +https://github.com/sui77/rc-switch/wiki + +## Info +### Send RC codes + +Use your Arduino or Raspberry Pi to operate remote radio controlled devices. +This will most likely work with all popular low cost power outlet sockets. If +yours doesn't work, you might need to adjust the pulse length. + +All you need is a Arduino or Raspberry Pi, a 315/433MHz AM transmitter and one +or more devices with one of the supported chipsets: + + - SC5262 / SC5272 + - HX2262 / HX2272 + - PT2262 / PT2272 + - EV1527 / RT1527 / FP1527 / HS1527 + - Intertechno outlets + - HT6P20X + +### Receive and decode RC codes + +Find out what codes your remote is sending. Use your remote to control your +Arduino. + +All you need is an Arduino, a 315/433MHz AM receiver (altough there is no +instruction yet, yes it is possible to hack an existing device) and a remote +hand set. + +For the Raspberry Pi, clone the https://github.com/ninjablocks/433Utils project to +compile a sniffer tool and transmission commands. diff --git a/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino new file mode 100644 index 000000000..18380d336 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino @@ -0,0 +1,24 @@ +/* + Example for receiving + + https://github.com/sui77/rc-switch/ + + If you want to visualize a telegram copy the raw data and + paste it into http://test.sui.li/oszi/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); + mySwitch.resetAvailable(); + } +} diff --git a/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/output.ino b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/output.ino new file mode 100644 index 000000000..31e61ba69 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Advanced/output.ino @@ -0,0 +1,70 @@ +static const char* bin2tristate(const char* bin); +static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength); + +void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) { + + const char* b = dec2binWzerofill(decimal, length); + Serial.print("Decimal: "); + Serial.print(decimal); + Serial.print(" ("); + Serial.print( length ); + Serial.print("Bit) Binary: "); + Serial.print( b ); + Serial.print(" Tri-State: "); + Serial.print( bin2tristate( b) ); + Serial.print(" PulseLength: "); + Serial.print(delay); + Serial.print(" microseconds"); + Serial.print(" Protocol: "); + Serial.println(protocol); + + Serial.print("Raw data: "); + for (unsigned int i=0; i<= length*2; i++) { + Serial.print(raw[i]); + Serial.print(","); + } + Serial.println(); + Serial.println(); +} + +static const char* bin2tristate(const char* bin) { + static char returnValue[50]; + int pos = 0; + int pos2 = 0; + while (bin[pos]!='\0' && bin[pos+1]!='\0') { + if (bin[pos]=='0' && bin[pos+1]=='0') { + returnValue[pos2] = '0'; + } else if (bin[pos]=='1' && bin[pos+1]=='1') { + returnValue[pos2] = '1'; + } else if (bin[pos]=='0' && bin[pos+1]=='1') { + returnValue[pos2] = 'F'; + } else { + return "not applicable"; + } + pos = pos+2; + pos2++; + } + returnValue[pos2] = '\0'; + return returnValue; +} + +static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) { + static char bin[64]; + unsigned int i=0; + + while (Dec > 0) { + bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0'; + Dec = Dec >> 1; + } + + for (unsigned int j = 0; j< bitLength; j++) { + if (j >= bitLength - i) { + bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; + } else { + bin[j] = '0'; + } + } + bin[bitLength] = '\0'; + + return bin; +} diff --git a/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino new file mode 100644 index 000000000..bb1076387 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino @@ -0,0 +1,29 @@ +/* + Simple example for receiving + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + + Serial.print("Received "); + Serial.print( mySwitch.getReceivedValue() ); + Serial.print(" / "); + Serial.print( mySwitch.getReceivedBitlength() ); + Serial.print("bit "); + Serial.print("Protocol: "); + Serial.println( mySwitch.getReceivedProtocol() ); + + mySwitch.resetAvailable(); + } +} diff --git a/lib/rc-switch-2.6.2.13/examples/SendDemo/SendDemo.ino b/lib/rc-switch-2.6.2.13/examples/SendDemo/SendDemo.ino new file mode 100644 index 000000000..5acb4958c --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/SendDemo/SendDemo.ino @@ -0,0 +1,57 @@ +/* + Example for different sending methods + + https://github.com/sui77/rc-switch/ + +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + Serial.begin(9600); + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set protocol (default is 1, will work for most outlets) + // mySwitch.setProtocol(2); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + + // Optional set number of transmission repetitions. + // mySwitch.setRepeatTransmit(15); + +} + +void loop() { + + /* See Example: TypeA_WithDIPSwitches */ + mySwitch.switchOn("11111", "00010"); + delay(1000); + mySwitch.switchOff("11111", "00010"); + delay(1000); + + /* Same switch as above, but using decimal code */ + mySwitch.send(5393, 24); + delay(1000); + mySwitch.send(5396, 24); + delay(1000); + + /* Same switch as above, but using binary code */ + mySwitch.send("000000000001010100010001"); + delay(1000); + mySwitch.send("000000000001010100010100"); + delay(1000); + + /* Same switch as above, but tri-state code */ + mySwitch.sendTriState("00000FFF0F0F"); + delay(1000); + mySwitch.sendTriState("00000FFF0FF0"); + delay(1000); + + delay(20000); +} diff --git a/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino new file mode 100644 index 000000000..14f7d2a6c --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with a 10 pole DIP switch. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first 5 DIP switches. + // In this example it's ON-ON-OFF-OFF-ON. + // + // The second parameter represents the setting of the last 5 DIP switches. + // In this example the last 5 DIP switches are OFF-ON-OFF-ON-OFF. + mySwitch.switchOn("11001", "01010"); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff("11001", "01010"); + + // Wait another second + delay(1000); + +} diff --git a/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino new file mode 100644 index 000000000..214daf41a --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino @@ -0,0 +1,43 @@ +/* + This is a minimal sketch without using the library at all but only works for + the 10 pole dip switch sockets. It saves a lot of memory and thus might be + very useful to use with ATTinys :) + + https://github.com/sui77/rc-switch/ +*/ + +int RCLpin = 7; + +void setup() { + pinMode(RCLpin, OUTPUT); +} + +void loop() { + RCLswitch(0b010001000001); // DIPs an Steckdose: 0100010000 An:01 + delay(2000); + + RCLswitch(0b010001000010); // DIPs an Steckdose: 0100010000 Aus:10 + delay(2000); +} + +void RCLswitch(uint16_t code) { + for (int nRepeat=0; nRepeat<6; nRepeat++) { + for (int i=4; i<16; i++) { + RCLtransmit(1,3); + if (((code << (i-4)) & 2048) > 0) { + RCLtransmit(1,3); + } else { + RCLtransmit(3,1); + } + } + RCLtransmit(1,31); + } +} + +void RCLtransmit(int nHighPulses, int nLowPulses) { + digitalWrite(RCLpin, HIGH); + delayMicroseconds( 350 * nHighPulses); + digitalWrite(RCLpin, LOW); + delayMicroseconds( 350 * nLowPulses); +} + diff --git a/lib/rc-switch-2.6.2.13/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino b/lib/rc-switch-2.6.2.13/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino new file mode 100644 index 000000000..e8568e25b --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with two rotary/sliding switches. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first rotary switch. + // In this example it's switched to "1" or "A" or "I". + // + // The second parameter represents the setting of the second rotary switch. + // In this example it's switched to "4" or "D" or "IV". + mySwitch.switchOn(1, 4); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff(1, 4); + + // Wait another second + delay(1000); + +} diff --git a/lib/rc-switch-2.6.2.13/examples/TypeC_Intertechno/TypeC_Intertechno.ino b/lib/rc-switch-2.6.2.13/examples/TypeC_Intertechno/TypeC_Intertechno.ino new file mode 100644 index 000000000..0fc69c7c8 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeC_Intertechno/TypeC_Intertechno.ino @@ -0,0 +1,40 @@ +/* + Example for Intertechno outlets + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the familycode (a, b, c, ... f) + // The second parameter represents the group number + // The third parameter represents the device number + // + // In this example it's family 'b', group #3, device #2 + mySwitch.switchOn('b', 3, 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('b', 3, 2); + + // Wait another second + delay(1000); + +} \ No newline at end of file diff --git a/lib/rc-switch-2.6.2.13/examples/TypeD_REV/TypeD_REV.ino b/lib/rc-switch-2.6.2.13/examples/TypeD_REV/TypeD_REV.ino new file mode 100644 index 000000000..878272945 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/TypeD_REV/TypeD_REV.ino @@ -0,0 +1,41 @@ +/* + Example for REV outlets (e.g. 8342L) + + https://github.com/sui77/rc-switch/ + + Need help? http://forum.ardumote.com +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // set pulse length. + mySwitch.setPulseLength(360); + +} + +void loop() { + + // Switch on: + // The first parameter represents the channel (a, b, c, d) + // The second parameter represents the device number + // + // In this example it's family 'd', device #2 + mySwitch.switchOn('d', 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('d', 2); + + // Wait another second + delay(1000); + +} diff --git a/lib/rc-switch-2.6.2.13/examples/Webserver/Webserver.ino b/lib/rc-switch-2.6.2.13/examples/Webserver/Webserver.ino new file mode 100644 index 000000000..66668e76a --- /dev/null +++ b/lib/rc-switch-2.6.2.13/examples/Webserver/Webserver.ino @@ -0,0 +1,154 @@ +/* + A simple RCSwitch/Ethernet/Webserver demo + + https://github.com/sui77/rc-switch/ +*/ + +#include +#include +#include + +// Ethernet configuration +uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC Address +uint8_t ip[] = { 192,168,0, 2 }; // IP Address +EthernetServer server(80); // Server Port 80 + +// RCSwitch configuration +RCSwitch mySwitch = RCSwitch(); +int RCTransmissionPin = 7; + +// More to do... +// You should also modify the processCommand() and +// httpResponseHome() functions to fit your needs. + + + +/** + * Setup + */ +void setup() { + Ethernet.begin(mac, ip); + server.begin(); + mySwitch.enableTransmit( RCTransmissionPin ); +} + +/** + * Loop + */ +void loop() { + char* command = httpServer(); +} + +/** + * Command dispatcher + */ +void processCommand(char* command) { + if (strcmp(command, "1-on") == 0) { + mySwitch.switchOn(1,1); + } else if (strcmp(command, "1-off") == 0) { + mySwitch.switchOff(1,1); + } else if (strcmp(command, "2-on") == 0) { + mySwitch.switchOn(1,2); + } else if (strcmp(command, "2-off") == 0) { + mySwitch.switchOff(1,2); + } +} + +/** + * HTTP Response with homepage + */ +void httpResponseHome(EthernetClient c) { + c.println("HTTP/1.1 200 OK"); + c.println("Content-Type: text/html"); + c.println(); + c.println(""); + c.println(""); + c.println( "RCSwitch Webserver Demo"); + c.println( ""); + c.println(""); + c.println(""); + c.println( "

RCSwitch Webserver Demo

"); + c.println( ""); + c.println( ""); + c.println( "
"); + c.println( "https://github.com/sui77/rc-switch/"); + c.println(""); + c.println(""); +} + +/** + * HTTP Redirect to homepage + */ +void httpResponseRedirect(EthernetClient c) { + c.println("HTTP/1.1 301 Found"); + c.println("Location: /"); + c.println(); +} + +/** + * HTTP Response 414 error + * Command must not be longer than 30 characters + **/ +void httpResponse414(EthernetClient c) { + c.println("HTTP/1.1 414 Request URI too long"); + c.println("Content-Type: text/plain"); + c.println(); + c.println("414 Request URI too long"); +} + +/** + * Process HTTP requests, parse first request header line and + * call processCommand with GET query string (everything after + * the ? question mark in the URL). + */ +char* httpServer() { + EthernetClient client = server.available(); + if (client) { + char sReturnCommand[32]; + int nCommandPos=-1; + sReturnCommand[0] = '\0'; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + if ((c == '\n') || (c == ' ' && nCommandPos>-1)) { + sReturnCommand[nCommandPos] = '\0'; + if (strcmp(sReturnCommand, "\0") == 0) { + httpResponseHome(client); + } else { + processCommand(sReturnCommand); + httpResponseRedirect(client); + } + break; + } + if (nCommandPos>-1) { + sReturnCommand[nCommandPos++] = c; + } + if (c == '?' && nCommandPos == -1) { + nCommandPos = 0; + } + } + if (nCommandPos > 30) { + httpResponse414(client); + sReturnCommand[0] = '\0'; + break; + } + } + if (nCommandPos!=-1) { + sReturnCommand[nCommandPos] = '\0'; + } + // give the web browser time to receive the data + delay(1); + client.stop(); + + return sReturnCommand; + } + return '\0'; +} \ No newline at end of file diff --git a/lib/rc-switch-2.6.2.13/keywords.txt b/lib/rc-switch-2.6.2.13/keywords.txt new file mode 100644 index 000000000..2474367c4 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/keywords.txt @@ -0,0 +1,57 @@ +####################################### +# Syntax Coloring Map For RCSwitch +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +RCSwitch KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +########## +#SENDS Begin +########## +switchOn KEYWORD2 +switchOff KEYWORD2 +sendTriState KEYWORD2 +send KEYWORD2 +########## +#SENDS End +########## + +########## +#RECEIVE Begin +########## +enableReceive KEYWORD2 +disableReceive KEYWORD2 +available KEYWORD2 +resetAvailable KEYWORD2 +setReceiveTolerance KEYWORD2 +getReceivedValue KEYWORD2 +getReceivedBitlength KEYWORD2 +getReceivedDelay KEYWORD2 +getReceivedProtocol KEYWORD2 +getReceivedRawdata KEYWORD2 +########## +#RECEIVE End +########## + +########## +#OTHERS Begin +########## +enableTransmit KEYWORD2 +disableTransmit KEYWORD2 +setPulseLength KEYWORD2 +setProtocol KEYWORD2 +setRepeatTransmit KEYWORD2 +########## +#OTHERS End +########## + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/lib/rc-switch-2.6.2.13/library.json b/lib/rc-switch-2.6.2.13/library.json new file mode 100644 index 000000000..1d7d2e367 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/library.json @@ -0,0 +1,21 @@ +{ + "name": "rc-switch", + "description": "Use your Arduino or Raspberry Pi to operate remote radio controlled devices", + "keywords": "rf, radio, wireless", + "authors": + { + "name": "Suat Ozgur" + }, + "repository": + { + "type": "git", + "url": "https://github.com/sui77/rc-switch.git" + }, + "version": "2.6.2", + "frameworks": [ + "arduino", + "energia", + "wiringpi" + ], + "platforms": "*" +} diff --git a/lib/rc-switch-2.6.2.13/library.properties b/lib/rc-switch-2.6.2.13/library.properties new file mode 100644 index 000000000..b4c7388d6 --- /dev/null +++ b/lib/rc-switch-2.6.2.13/library.properties @@ -0,0 +1,10 @@ +name=rc-switch +version=2.6.2 +author=sui77 +maintainer=sui77,fingolfin +sentence=Operate 433/315Mhz devices. +paragraph=Use your Arduino, ESP8266/ESP32 or Raspberry Pi to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets. +category=Device Control +url=https://github.com/sui77/rc-switch +architectures=avr,esp8266,esp32 +includes=RCSwitch.h diff --git a/platformio.ini b/platformio.ini index 5dfd0a442..852db9128 100644 --- a/platformio.ini +++ b/platformio.ini @@ -62,7 +62,10 @@ board_build.f_cpu = 80000000L build_unflags = -Wall build_flags = - -Wl,-Tesp8266.flash.1m0.ld +; if using esp8266 core 2.5.0 (stage) or up +; -Wl,-Tesp8266.flash.1m.ld -Wl,-Map,firmware.map +; if using esp8266 core < 2.5.0 + -Wl,-Tesp8266.flash.1m0.ld -Wl,-Map,firmware.map -mtarget-align ; -DUSE_CONFIG_OVERRIDE ; lwIP 1.4 (Default) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 9a81d11bd..563e555d1 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,7 +1,37 @@ -/* 6.2.1.15 20181012 +/* 6.2.1.19 20181023 + * Fix header file execution order by renaming user_config.h to my_user_config.h + * Fix invalid JSON floating point result from nan (Not a Number) and inf (Infinity) into null (#4147) + * Fix rule mqtt#connected trigger when mqtt is disabled (#4149) + * Initial release of RF transceiving using library RcSwitch (#2702) + * + * 6.2.1.18 20181019 + * Add more API callbacks and document API.md + * Add support for La Crosse TX20 Anemometer (#2654, #3146) + * Add optional HX711 scale interface to web GUI demonstrating easy GUI plug-in + * Resize HX711 weight_item field from 16 bit to 32 bit + * + * 6.2.1.17 20181017 + * Enable updated non-blocking PubSubClient as default MQTT client + * Update TasmotaModbus and TasmotaSerial libraries for support of serial 8N2 communication + * Add support for Pzem-003/017 DC Energy monitoring module (#3694) + * Change support for Pzem-014/016 AC Energy monitoring module (#3694) + * Rewrite Tuya Dimmer code + * + * 6.2.1.16 20181015 + * Add TasmotaModbus library for very basic modbus wrapper for TasmotaSerial + * Change xsns_17_senseair.ino to use TasmotaModbus library + * Fix xnrg_05_pzem2.ino for PZEM-014/016 support using TasmotaModbus library (#3694) + * Fix RfRaw and SerialSend5 regression from 6.2.1.15 (#4072) + * Fix Sonoff Bridge RfRaw receive (#4080, #4085) + * Add support for Tuya Dimmer (#469, #4075) + * Fix possible wifi connection error (#4044, #4083) + * Update PubSubClient Mqtt library to non-blocking EspEasy version + * + * 6.2.1.15 20181012 * Fix Color Temperature slider functionality regression from 6.2.1.5 (#4037) * Add auto reload of main web page to some web restarts * Add whitespace removal from RfRaw and SerialSend5 (#4020) + * Add commands Reset 4 (reset to defaults but keep wifi params) and Reset 5 (as reset 4 and also erase flash) (#4061) * * 6.2.1.14 20181010 * Rewrite Webserver page handler for easier extension (thx to Adrian Scillato) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index a7d3fca7d..7f56e33d3 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Няма" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 2886b130f..a29f5741a 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Vložte referenční zátěž" #define D_HX_CAL_DONE "Zkalibrováno" #define D_HX_CAL_FAIL "Chyba kalibrace" +#define D_RESET_HX711 "Reset váhy" +#define D_CONFIGURE_HX711 "Konfigurace váhy" +#define D_HX711_PARAMETERS "Parametry váhy" +#define D_ITEM_WEIGHT "Vlastní hmotnost" +#define D_REFERENCE_WEIGHT "Referenční hmotnost" +#define D_CALIBRATE "Kalibruj" +#define D_CALIBRATION "Kalibrace" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Směr větru" +#define D_TX20_WIND_SPEED "Rychlost větru" +#define D_TX20_WIND_SPEED_AVG "Průměrná rychlost větru" +#define D_TX20_WIND_SPEED_MAX "Maximální rychlost větru" +#define D_TX20_NORTH "S" +#define D_TX20_EAST "V" +#define D_TX20_SOUTH "J" +#define D_TX20_WEST "Z" // sonoff_template.h #define D_SENSOR_NONE "Není" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "hod" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" +#define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 299e8207a..9f11e57ca 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Referenzgewicht auflegen" #define D_HX_CAL_DONE "kalibriert" #define D_HX_CAL_FAIL "Kalibrierung fehlgeschlagen" +#define D_RESET_HX711 "Tara" +#define D_CONFIGURE_HX711 "Tara Wert?" +#define D_HX711_PARAMETERS "Skala Parameter" +#define D_ITEM_WEIGHT "Wägegut Gewicht" +#define D_REFERENCE_WEIGHT "Referenz Gewicht" +#define D_CALIBRATE "kalibriert" +#define D_CALIBRATION "Kalibrierung" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Richtung" +#define D_TX20_WIND_SPEED "Windgeschwindigkeit" +#define D_TX20_WIND_SPEED_AVG "Ø Windgeschwindigkeit" +#define D_TX20_WIND_SPEED_MAX "max Windgeschwindigkeit" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "O" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "None" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRRecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 2f320211d..beaaef57d 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Κανένας" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index ad3762f8d..4e3aa0080 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "None" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index b57985803..39f198681 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Poner Peso de Referencia" #define D_HX_CAL_DONE "Calibrado" #define D_HX_CAL_FAIL "Falló Calibración" +#define D_RESET_HX711 "Restableces Escala" +#define D_CONFIGURE_HX711 "Configurar Escala" +#define D_HX711_PARAMETERS "Parámetros de Escala" +#define D_ITEM_WEIGHT "Peso" +#define D_REFERENCE_WEIGHT "Peso de Referencia" +#define D_CALIBRATE "Calibrar" +#define D_CALIBRATION "Calibración" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Dirección del Viento" +#define D_TX20_WIND_SPEED "Vel. del Viento" +#define D_TX20_WIND_SPEED_AVG "Vel. Prom. del Viento" +#define D_TX20_WIND_SPEED_MAX "Vel. Max. del Viento" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "O" // sonoff_template.h #define D_SENSOR_NONE "Ninguno" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IR RX" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 7e1098bed..44ecea2b1 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Aucun" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "RécptIR" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kΩ" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index c6aec9681..73b44c67b 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "None" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index 857cfec12..532d45643 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Nincs" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRvevő" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "ó" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 6b922cb4d..61f361b89 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Nessuno" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index eb938970d..d2e913357 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Plaats ijkgewicht" #define D_HX_CAL_DONE "Ge-ijkt" #define D_HX_CAL_FAIL "Ijken is mislukt" +#define D_RESET_HX711 "Nulstelling weegschaal" +#define D_CONFIGURE_HX711 "Configureer Weegschaal" +#define D_HX711_PARAMETERS "Weegschaal parameters" +#define D_ITEM_WEIGHT "Gewicht van onderdeel" +#define D_REFERENCE_WEIGHT "Ijkgewicht" +#define D_CALIBRATE "Ijken" +#define D_CALIBRATION "Ijken" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Windrichting" +#define D_TX20_WIND_SPEED "Windsnelheid" +#define D_TX20_WIND_SPEED_AVG "Windsnelheid gemiddeld" +#define D_TX20_WIND_SPEED_MAX "Windsnelhied maximaal" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Geen" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "h" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 0b6a07e7d..0f1303b30 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Brak" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Godz" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index f4c556ed9..54d8448d7 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Nenhum" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHz Rx" #define D_SENSOR_MHZ_TX "MHz Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAIR Rx" #define D_SENSOR_SAIR_TX "SAIR Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "H" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index f79f7a14c..0c8e03d62 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "Nenhum" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index 4cea913e6..11fdf90b0 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "-нет-" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "А" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Ч" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index b24a355d8..86838d0df 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "None" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "A" @@ -512,6 +534,7 @@ #define D_UNIT_HOUR "Hr" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "kOhm" #define D_UNIT_KILOWATTHOUR "kWh" #define D_UNIT_LUX "lx" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 93b5f32cd..efc125351 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "-відсутньо-" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "А" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "Г" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "кОм" #define D_UNIT_KILOWATTHOUR "кВт" #define D_UNIT_LUX "лк" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 42a381f18..3414bc8d1 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "无" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "安" @@ -512,6 +534,7 @@ #define D_UNIT_HOUR "时" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "千欧" #define D_UNIT_KILOWATTHOUR "千瓦时" #define D_UNIT_LUX "勒克斯" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 92193f483..b5f14dace 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -461,6 +461,23 @@ #define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_FAIL "Calibration failed" +#define D_RESET_HX711 "Reset Scale" +#define D_CONFIGURE_HX711 "Configure Scale" +#define D_HX711_PARAMETERS "Scale parameters" +#define D_ITEM_WEIGHT "Item weight" +#define D_REFERENCE_WEIGHT "Reference weigth" +#define D_CALIBRATE "Calibrate" +#define D_CALIBRATION "Calibration" + +//xsns_35_tx20.ino +#define D_TX20_WIND_DIRECTION "Wind Direction" +#define D_TX20_WIND_SPEED "Wind Speed" +#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" +#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" +#define D_TX20_NORTH "N" +#define D_TX20_EAST "E" +#define D_TX20_SOUTH "S" +#define D_TX20_WEST "W" // sonoff_template.h #define D_SENSOR_NONE "None" @@ -482,8 +499,10 @@ #define D_SENSOR_IRRECV "IRrecv" #define D_SENSOR_MHZ_RX "MHZ Rx" #define D_SENSOR_MHZ_TX "MHZ Tx" -#define D_SENSOR_PZEM_RX "PZEM Rx" -#define D_SENSOR_PZEM_TX "PZEM Tx" +#define D_SENSOR_PZEM004_RX "PZEM004 Rx" +#define D_SENSOR_PZEM016_RX "PZEM016 Rx" +#define D_SENSOR_PZEM017_RX "PZEM017 Rx" +#define D_SENSOR_PZEM0XX_TX "PZEM0XX Tx" #define D_SENSOR_SAIR_RX "SAir Rx" #define D_SENSOR_SAIR_TX "SAir Tx" #define D_SENSOR_SPI_CS "SPI CS" @@ -505,6 +524,9 @@ #define D_SENSOR_TM1638_STB "TM16 STB" #define D_SENSOR_HX711_SCK "HX711 SCK" #define D_SENSOR_HX711_DAT "HX711 DAT" +#define D_SENSOR_TX20_TX "TX20" +#define D_SENSOR_RFSEND "RFSend" +#define D_SENSOR_RFRECV "RFrecv" // Units #define D_UNIT_AMPERE "安" @@ -513,6 +535,7 @@ #define D_UNIT_HOUR "時" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" +#define D_UNIT_KILOMETER_PER_HOUR "kmph" // or "km/h" #define D_UNIT_KILOOHM "千歐" #define D_UNIT_KILOWATTHOUR "千瓦時" #define D_UNIT_LUX "勒克斯" diff --git a/sonoff/user_config.h b/sonoff/my_user_config.h similarity index 95% rename from sonoff/user_config.h rename to sonoff/my_user_config.h index 740027277..e970bcdf5 100644 --- a/sonoff/user_config.h +++ b/sonoff/my_user_config.h @@ -1,5 +1,5 @@ /* - user_config.h - user specific configuration for Sonoff-Tasmota + my_user_config.h - user specific configuration for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _USER_CONFIG_H_ -#define _USER_CONFIG_H_ +#ifndef _MY_USER_CONFIG_H_ +#define _MY_USER_CONFIG_H_ /*********************************************************************************************\ * This file consists of TWO sections. @@ -55,9 +55,9 @@ // -- Wifi ---------------------------------------- #define WIFI_IP_ADDRESS "0.0.0.0" // [IpAddress1] Set to 0.0.0.0 for using DHCP or IP address -#define WIFI_GATEWAY "192.168.2.254" // [IpAddress2] If not using DHCP set Gateway IP address +#define WIFI_GATEWAY "192.168.1.1" // [IpAddress2] If not using DHCP set Gateway IP address #define WIFI_SUBNETMASK "255.255.255.0" // [IpAddress3] If not using DHCP set Network mask -#define WIFI_DNS "192.168.2.27" // [IpAddress4] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY) +#define WIFI_DNS "192.168.1.1" // [IpAddress4] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY) #define STA_SSID1 "" // [Ssid1] Wifi SSID #define STA_PASS1 "" // [Password1] Wifi password @@ -219,12 +219,12 @@ /*-------------------------------------------------------------------------------------------*\ * Select ONE of possible MQTT library types below \*-------------------------------------------------------------------------------------------*/ - // Default MQTT driver for both non-TLS and TLS connections. Blocks network if MQTT server is unavailable. -//#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library + // Default MQTT driver for both non-TLS and TLS connections. Latest library version (20181016) does not block network if MQTT server is unavailable. +#define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library // Alternative MQTT driver does not block network when MQTT server is unavailable. No TLS support //#define MQTT_LIBRARY_TYPE MQTT_TASMOTAMQTT // Use TasmotaMqtt library (+4k4 (core 2.3.0), +14k4 (core 2.4.2 lwip2) code, +4k mem) - non-TLS only // Alternative MQTT driver does not block network when MQTT server is unavailable. TLS should work but needs to be tested. -#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) +//#define MQTT_LIBRARY_TYPE MQTT_ARDUINOMQTT // Use arduino-mqtt (lwmqtt) library (+3k3 code, +2k mem) // -- MQTT ---------------------------------------- #define MQTT_TELE_RETAIN 0 // Tele messages may send retain flag (0 = off, 1 = on) @@ -271,9 +271,9 @@ // -- One wire sensors ---------------------------- // WARNING: Select none for default one DS18B20 sensor or enable one of the following two options for multiple sensors -#define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) -//#define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors //#define USE_DS18x20_LEGACY // Optional for more than one DS18x20 sensors with dynamic scan using library OneWire (+1k5 code) +#define USE_DS18x20 // Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code) +// #define W1_PARASITE_POWER // If using USE_DS18x20 then optimize for parasite powered sensors // -- I2C sensors --------------------------------- #define USE_I2C // I2C using library wire (+10k code, 0k2 mem, 124 iram) @@ -356,7 +356,8 @@ // Power monitoring sensors ----------------------- #define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code) -#define USE_PZEM2 // Add support for PZEM003,014,016,017 Energy monitor (+1k1 code) +#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code) +#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code) #define USE_MCP39F501 // Add support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code) // -- Low level interface devices ----------------- @@ -374,9 +375,17 @@ //#define USE_TM1638 // Add support for TM1638 switches copying Switch1 .. Switch8 (+1k code) #define USE_HX711 // Add support for HX711 load cell (+1k5 code) +// #define USE_HX711_GUI // Add optional web GUI to HX711 as scale (+1k8 code) #define USE_RF_FLASH // Add support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (+3k code) +#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer + #define TUYA_DIMMER_ID 3 // Default dimmer Id + +#define USE_TX20_WIND_SENSOR // Add support for La Crosse TX20 anemometer (+2k code) + +#define USE_RC_SWITCH // Add support for RF transceiver using library RcSwitch (+2k7 code) + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ @@ -403,4 +412,4 @@ #error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with" #endif -#endif // _USER_CONFIG_H_ +#endif // _MY_USER_CONFIG_H_ diff --git a/sonoff/settings.h b/sonoff/settings.h index e9e1fd110..29aaf2121 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -188,8 +188,8 @@ struct SYSCFG { byte seriallog_level; // 09E uint8_t sta_config; // 09F byte sta_active; // 0A0 - char sta_ssid[2][33]; // 0A1 - char sta_pwd[2][65]; // 0E3 + char sta_ssid[2][33]; // 0A1 - Keep together with sta_pwd as being copied as one chunck with reset 4/5 + char sta_pwd[2][65]; // 0E3 - Keep together with sta_ssid as being copied as one chunck with reset 4/5 char hostname[33]; // 165 char syslog_host[33]; // 186 uint8_t rule_stop; // 1A7 @@ -322,11 +322,12 @@ struct SYSCFG { uint16_t mcp230xx_int_timer; // 718 uint8_t rgbwwTable[5]; // 71A - byte free_71F[93]; // 71F + byte free_71F[153]; // 71F + + unsigned long weight_item; // 7B8 Weight of one item in gram * 10 + + byte free_7BC[2]; // 7BC - char custom1[32]; // 77C Custom - char custom2[32]; // 79C Custom - uint16_t weight_item; // 7BC Weight of one item in gram * 10 uint16_t weight_max; // 7BE Total max weight in kilogram unsigned long weight_reference; // 7C0 Reference weight in gram unsigned long weight_calibration; // 7C4 diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index a573849d3..70e0e9a3d 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -202,19 +202,23 @@ enum ButtonStates { PRESSED, NOT_PRESSED }; enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER }; -enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; +enum SettingsParmaIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MAX_PARAM8}; enum DomoticzSensors {DZ_TEMP, DZ_TEMP_HUM, DZ_TEMP_HUM_BARO, DZ_POWER_ENERGY, DZ_ILLUMINANCE, DZ_COUNT, DZ_VOLTAGE, DZ_CURRENT, DZ_AIRQUALITY, DZ_MAX_SENSORS}; enum Ws2812ClockIndex { WS_SECOND, WS_MINUTE, WS_HOUR, WS_MARKER }; enum Ws2812Color { WS_RED, WS_GREEN, WS_BLUE }; -enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; +enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_SERIAL, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC}; enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC}; enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX}; -enum XsnsFunctions {FUNC_PRE_INIT, FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, FUNC_PREP_BEFORE_TELEPERIOD, - FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, - FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER}; +enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT, + FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND, + FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_APPEND, FUNC_SAVE_BEFORE_RESTART, FUNC_COMMAND, + FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, + FUNC_SET_POWER, FUNC_SET_DEVICE_POWER, FUNC_SHOW_SENSOR, + FUNC_RULES_PROCESS, FUNC_SERIAL, FUNC_FREE_MEM, FUNC_BUTTON_PRESSED, + FUNC_WEB_ADD_BUTTON, FUNC_WEB_ADD_MAIN_BUTTON, FUNC_WEB_ADD_HANDLER}; const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 }; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ca42c2bbf..153e55fb7 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -28,13 +28,13 @@ // Location specific includes #include // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0) #include "sonoff_version.h" // Sonoff-Tasmota version information -#include "sonoff.h" // Enumeration used in user_config.h -#include "user_config.h" // Fixed user configurable options +#include "sonoff.h" // Enumeration used in my_user_config.h +#include "my_user_config.h" // Fixed user configurable options #ifdef USE_CONFIG_OVERRIDE - #include "user_config_override.h" // Configuration overrides for user_config.h + #include "user_config_override.h" // Configuration overrides for my_user_config.h #endif #include "sonoff_post.h" // Configuration overrides for all previous includes -#include "i18n.h" // Language support configured by user_config.h +#include "i18n.h" // Language support configured by my_user_config.h #include "sonoff_template.h" // Hardware configuration #ifdef ARDUINO_ESP8266_RELEASE_2_4_0 @@ -340,9 +340,14 @@ void SetDevicePower(power_t rpower, int source) } XdrvMailbox.index = rpower; - XdrvCall(FUNC_SET_POWER); + XdrvCall(FUNC_SET_POWER); // Signal power state - if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { + XdrvMailbox.index = rpower; + XdrvMailbox.payload = source; + if (XdrvCall(FUNC_SET_DEVICE_POWER)) { // Set power state and stop if serviced + // Serviced + } + else if ((SONOFF_DUAL == Settings.module) || (CH4 == Settings.module)) { Serial.write(0xA0); Serial.write(0x04); Serial.write(rpower &0xFF); @@ -751,19 +756,16 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) } } else { // SetOption32 .. 49 -/* + uint8_t param_low = 0; + uint8_t param_high = 255; switch (pindex) { case P_HOLD_TIME: case P_MAX_POWER_RETRY: - if ((payload >= 1) && (payload <= 250)) { - Settings.param[pindex] = payload; - } + param_low = 1; + param_high = 250; break; - default: - ptype = 99; // Command Error } -*/ - if ((payload >= 1) && (payload <= 250)) { + if ((payload >= param_low) && (payload <= param_high)) { Settings.param[pindex] = payload; } } @@ -1002,7 +1004,7 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) Serial.printf("%s", Unescape(dataBuf, &dat_len)); // "Hello\f" } else if (5 == index) { - SerialSendRaw(RemoveSpace(dataBuf), strlen(dataBuf)); // "AA004566" + SerialSendRaw(RemoveSpace(dataBuf)); // "AA004566" } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } @@ -1149,6 +1151,8 @@ void MqttDataHandler(char* topic, byte* data, unsigned int data_len) break; case 2: case 3: + case 4: + case 5: restart_flag = 210 + payload; snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; @@ -1702,7 +1706,12 @@ void ButtonHandler() } if (button_present) { - if (SONOFF_4CHPRO == Settings.module) { + XdrvMailbox.index = button_index; + XdrvMailbox.payload = button; + if (XdrvCall(FUNC_BUTTON_PRESSED)) { + // Serviced + } + else if (SONOFF_4CHPRO == Settings.module) { if (holdbutton[button_index]) { holdbutton[button_index]--; } boolean button_pressed = false; @@ -1722,7 +1731,8 @@ void ButtonHandler() ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally } } - } else { + } + else { if ((PRESSED == button) && (NOT_PRESSED == lastbutton[button_index])) { if (Settings.flag.button_single) { // Allow only single button press for immediate action snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1); @@ -2041,7 +2051,8 @@ void Every250mSeconds() ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(mqtt_data)); #else // If using core stage or 2.5.0+ the syntax has changed - ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(EspClient, mqtt_data)); + WiFiClient OTAclient; + ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data)); #endif if (!ota_result) { #ifndef BE_MINIMAL @@ -2092,10 +2103,21 @@ void Every250mSeconds() } } if (restart_flag && (backlog_pointer == backlog_index)) { - if (213 == restart_flag) { + if ((214 == restart_flag) || (215 == restart_flag)) { + char storage[sizeof(Settings.sta_ssid) + sizeof(Settings.sta_pwd)]; + memcpy(storage, Settings.sta_ssid, sizeof(storage)); // Backup current SSIDs and Passwords + if (215 == restart_flag) { + SettingsErase(0); // Erase all flash from program end to end of physical flash + } + SettingsDefault(); + memcpy(Settings.sta_ssid, storage, sizeof(storage)); // Restore current SSIDs and Passwords + restart_flag = 2; + } + else if (213 == restart_flag) { SettingsSdkErase(); // Erase flash SDK parameters restart_flag = 2; - } else if (212 == restart_flag) { + } + else if (212 == restart_flag) { SettingsErase(0); // Erase all flash from program end to end of physical flash restart_flag = 211; } @@ -2305,11 +2327,10 @@ void SerialInput() snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); -// XdrvRulesProcess(); +// XdrvRulesProcess(); serial_in_byte_counter = 0; } } - /********************************************************************************************/ void GpioSwitchPinMode(uint8_t index) @@ -2436,7 +2457,10 @@ void GpioInit() baudrate = 19200; } - if (SONOFF_DUAL == Settings.module) { + if (XdrvCall(FUNC_MODULE_INIT)) { + // Serviced + } + else if (SONOFF_DUAL == Settings.module) { Settings.flag.mqtt_serial = 0; devices_present = 2; baudrate = 19200; @@ -2551,6 +2575,10 @@ void setup() GetFeatures(); + if (1 == RtcReboot.fast_reboot_count) { // Allow setting override only when all is well + XdrvCall(FUNC_SETTINGS_OVERRIDE); + } + baudrate = Settings.baudrate * 1200; seriallog_level = Settings.seriallog_level; seriallog_timer = SERIALLOG_TIMER; @@ -2563,19 +2591,19 @@ void setup() sleep = Settings.sleep; // Disable functionality as possible cause of fast restart within BOOT_LOOP_TIME seconds (Exception, WDT or restarts) - if (RtcReboot.fast_reboot_count > 1) { // Restart twice + if (RtcReboot.fast_reboot_count > 1) { // Restart twice Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI - if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times + if (RtcReboot.fast_reboot_count > 2) { // Restart 3 times for (byte i = 0; i < MAX_RULE_SETS; i++) { if (bitRead(Settings.rule_stop, i)) { bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop } } } - if (RtcReboot.fast_reboot_count > 3) { // Restarted 4 times + if (RtcReboot.fast_reboot_count > 3) { // Restarted 4 times Settings.rule_enabled = 0; // Disable all rules } - if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times + if (RtcReboot.fast_reboot_count > 4) { // Restarted 5 times Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic Settings.last_module = SONOFF_BASIC; for (byte i = 0; i < MAX_GPIO_PIN; i++) { diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index bc747155e..62b3fc88a 100755 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -124,6 +124,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define MQTT_LIBRARY_TYPE MQTT_PUBSUBCLIENT // Use PubSubClient library #undef USE_ARDUINO_OTA // Disable support for Arduino OTA #undef USE_KNX // Disable KNX IP Protocol Support +#undef USE_CUSTOM // Disable Custom features #undef USE_TIMERS // Disable support for up to 16 timers #undef USE_TIMERS_WEB // Disable support for timer webpage #undef USE_SUNRISE // Disable support for Sunrise and sunset tools @@ -135,7 +136,8 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor #undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor #undef USE_PZEM004T // Disable PZEM004T energy sensor -#undef USE_PZEM2 // Disable PZEM003,014,016,017 Energy monitor +#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor +#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor #undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge #undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter #undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter @@ -144,7 +146,10 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // USE_CLASSIC @@ -211,6 +216,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set #undef USE_KNX // Disable KNX IP Protocol Support //#undef USE_WEBSERVER // Disable Webserver +#undef USE_CUSTOM // Disable Custom features #undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server #undef USE_EMULATION // Disable Wemo or Hue emulation #undef USE_TIMERS // Disable support for up to 16 timers @@ -237,7 +243,10 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_ARILUX_RF // Disable support for Arilux RF remote controller #undef USE_SR04 // Disable support for for HC-SR04 ultrasonic devices #undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8 +#undef USE_HX711 // Disable support for HX711 load cell #undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB +#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer +#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // BE_MINIMAL diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index bac97a65c..13a6ffd0c 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -86,8 +86,8 @@ enum UserSelectablePins { GPIO_LED4_INV, GPIO_MHZ_TXD, // MH-Z19 Serial interface GPIO_MHZ_RXD, // MH-Z19 Serial interface - GPIO_PZEM_TX, // PZEM004T Serial interface - GPIO_PZEM_RX, // PZEM004T Serial interface + GPIO_PZEM0XX_TX, // PZEM0XX Serial interface + GPIO_PZEM004_RX, // PZEM004T Serial interface GPIO_SAIR_TX, // SenseAir Serial interface GPIO_SAIR_RX, // SenseAir Serial interface GPIO_SPI_CS, // SPI Chip Select @@ -122,12 +122,15 @@ enum UserSelectablePins { GPIO_CNTR2_NP, GPIO_CNTR3_NP, GPIO_CNTR4_NP, - GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface - GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface + GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface + GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_HX711_SCK, // HX711 Load Cell clock GPIO_HX711_DAT, // HX711 Load Cell data + GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin + GPIO_RFSEND, // RF transmitter + GPIO_RFRECV, // RF receiver GPIO_SENSOR_END }; // Programmer selectable GPIO functionality offset by user selectable GPIOs @@ -168,7 +171,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_LED "1|" D_SENSOR_LED "2|" D_SENSOR_LED "3|" D_SENSOR_LED "4|" D_SENSOR_LED "1i|" D_SENSOR_LED "2i|" D_SENSOR_LED "3i|" D_SENSOR_LED "4i|" D_SENSOR_MHZ_TX "|" D_SENSOR_MHZ_RX "|" - D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" + D_SENSOR_PZEM0XX_TX "|" D_SENSOR_PZEM004_RX "|" D_SENSOR_SAIR_TX "|" D_SENSOR_SAIR_RX "|" D_SENSOR_SPI_CS "|" D_SENSOR_SPI_DC "|" D_SENSOR_BACKLIGHT "|" D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1_RX "|" @@ -180,9 +183,11 @@ const char kSensorNames[] PROGMEM = D_SENSOR_SWITCH "1n|" D_SENSOR_SWITCH "2n|" D_SENSOR_SWITCH "3n|" D_SENSOR_SWITCH "4n|" D_SENSOR_SWITCH "5n|" D_SENSOR_SWITCH "6n|" D_SENSOR_SWITCH "7n|" D_SENSOR_SWITCH "8n|" D_SENSOR_BUTTON "1n|" D_SENSOR_BUTTON "2n|" D_SENSOR_BUTTON "3n|" D_SENSOR_BUTTON "4n|" D_SENSOR_COUNTER "1n|" D_SENSOR_COUNTER "2n|" D_SENSOR_COUNTER "3n|" D_SENSOR_COUNTER "4n|" - D_SENSOR_PZEM_TX "|" D_SENSOR_PZEM_RX "|" + D_SENSOR_PZEM016_RX "|" D_SENSOR_PZEM017_RX "|" D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|" - D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT; + D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|" + D_SENSOR_TX20_TX "|" + D_SENSOR_RFSEND "|" D_SENSOR_RFRECV; /********************************************************************************************/ @@ -241,6 +246,7 @@ enum SupportedModules { OBI, TECKIN, APLIC_WDP303075, + TUYA_DIMMER, MAXMODULE }; /********************************************************************************************/ @@ -338,6 +344,8 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_WS2812, // WS2812 Led string GPIO_IRSEND, // IR remote GPIO_IRRECV, // IR receiver + GPIO_RFSEND, // RF transmitter + GPIO_RFRECV, // RF receiver GPIO_SR04_TRIG, // SR04 Trigger pin GPIO_SR04_ECHO, // SR04 Echo pin GPIO_TM16CLK, // TM1638 Clock @@ -353,16 +361,17 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = { GPIO_SAIR_RX, // SenseAir Serial interface GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface GPIO_SDS0X1_RX, // Nova Fitness SDS011 Serial interface - GPIO_PZEM_TX, // PZEM004T Serial interface - GPIO_PZEM_RX, // PZEM004T Serial interface - GPIO_PZEM2_TX, // PZEM-003,014,016,017 Serial interface - GPIO_PZEM2_RX, // PZEM-003,014,016,017 Serial interface + GPIO_PZEM0XX_TX, // PZEM0XX Serial interface + GPIO_PZEM004_RX, // PZEM004T Serial interface + GPIO_PZEM016_RX, // PZEM-014,016 Serial Modbus interface + GPIO_PZEM017_RX, // PZEM-003,017 Serial Modbus interface GPIO_SDM120_TX, // SDM120 Serial interface GPIO_SDM120_RX, // SDM120 Serial interface GPIO_SDM630_TX, // SDM630 Serial interface GPIO_SDM630_RX, // SDM630 Serial interface GPIO_PMS5003, // Plantower PMS5003 Serial interface - GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface + GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin + GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { @@ -407,6 +416,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { NEO_COOLCAM, // Socket Relay Devices OBI, ESP_SWITCH, // Switch Devices + TUYA_DIMMER, // Dimmer Devices H801, // Light Devices MAGICHOME, ARILUX_LC01, @@ -1100,14 +1110,17 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_REL1_INV, // GPIO16 Green Led 1 (0 = On, 1 = Off) }, { "OBI Socket", // OBI socket (ESP8266) - https://www.obi.de/hausfunksteuerung/wifi-stecker-schuko/p/2291706 - 0, 0, 0, 0, - GPIO_LED1, // GPIO04 LED on top and in switch button - GPIO_REL1, // GPIO05 Relay 1 (0 = Off, 1 = On) + GPIO_USER, // GPIO00 + 0,0,0, + GPIO_LED1, // GPIO04 Blue LED + GPIO_REL1, // GPIO05 (Relay OFF, but used as Relay Switch) 0, 0, 0, 0, 0, 0, // Flash connection - GPIO_LED2, // GPIO12 - 0, // GPIO13 - GPIO_KEY1, // GPIO14 switch button - 0, 0, 0 + GPIO_LED2, // GPIO12 (Relay ON, but set to LOW, so we can switch with GPIO05) + GPIO_USER, // GPIO13 + GPIO_KEY1, // GPIO14 Button + 0, + GPIO_USER, // GPIO16 + GPIO_ADC0 // ADC0 A0 Analog input }, { "Teckin", // https://www.amazon.de/gp/product/B07D5V139R 0, @@ -1133,6 +1146,22 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_LED1_INV, // GPIO13 LED (0 = On, 1 = Off) GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On ) 0, 0, 0 + }, + { "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer) + // https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1 + GPIO_KEY1, // Virtual Button (controlled by MCU) + GPIO_TXD, // GPIO01 MCU serial control + GPIO_USER, + GPIO_RXD, // GPIO03 MCU serial control + GPIO_USER, + GPIO_USER, + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_USER, + GPIO_USER, + GPIO_LED1, // GPIO14 Green Led + GPIO_USER, + GPIO_USER, + 0 } }; diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index d283e0476..2c70d6928 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0602010F +#define VERSION 0x06020112 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index a81699a8c..88545e211 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -196,7 +196,12 @@ int TextToInt(char *str) char* dtostrfd(double number, unsigned char prec, char *s) { - return dtostrf(number, 1, prec, s); + if ((isnan(number)) || (isinf(number))) { // Fix for JSON output (https://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript) + strcpy(s, "null"); + return s; + } else { + return dtostrf(number, 1, prec, s); + } } char* Unescape(char* buffer, uint16_t* size) @@ -630,10 +635,6 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_I2C_SCL == val) { return true; } if (GPIO_I2C_SDA == val) { return true; } #endif -#ifndef USE_SR04 - if (GPIO_SR04_TRIG == val) { return true; } - if (GPIO_SR04_ECHO == val) { return true; } -#endif #ifndef USE_WS2812 if (GPIO_WS2812 == val) { return true; } #endif @@ -647,14 +648,22 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_MHZ_TXD == val) { return true; } if (GPIO_MHZ_RXD == val) { return true; } #endif + + int pzem = 3; #ifndef USE_PZEM004T - if (GPIO_PZEM_TX == val) { return true; } - if (GPIO_PZEM_RX == val) { return true; } + pzem--; + if (GPIO_PZEM004_RX == val) { return true; } #endif -#ifndef USE_PZEM2 - if (GPIO_PZEM2_TX == val) { return true; } - if (GPIO_PZEM2_RX == val) { return true; } +#ifndef USE_PZEM_AC + pzem--; + if (GPIO_PZEM016_RX == val) { return true; } #endif +#ifndef USE_PZEM_DC + pzem--; + if (GPIO_PZEM017_RX == val) { return true; } +#endif + if (!pzem && (GPIO_PZEM0XX_TX == val)) { return true; } + #ifndef USE_SENSEAIR if (GPIO_SAIR_TX == val) { return true; } if (GPIO_SAIR_RX == val) { return true; } @@ -698,6 +707,15 @@ boolean GetUsedInModule(byte val, uint8_t *arr) if (GPIO_HX711_SCK == val) { return true; } if (GPIO_HX711_DAT == val) { return true; } #endif +#ifndef USE_TX20_WIND_SENSOR + if (GPIO_TX20_TXD_BLACK == val) { return true; } +#endif +#ifndef USE_RC_SWITCH + if (GPIO_RFSEND == val) { return true; } + if (GPIO_RFRECV == val) { return true; } +#endif + + if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) { offset = (GPIO_REL1_INV - GPIO_REL1); } @@ -750,12 +768,14 @@ void ClaimSerial() Settings.baudrate = baudrate / 1200; } -void SerialSendRaw(char *codes, int size) +void SerialSendRaw(char *codes) { char *p; char stemp[3]; uint8_t code; + int size = strlen(codes); + while (size > 0) { snprintf(stemp, sizeof(stemp), codes); code = strtol(stemp, &p, 16); @@ -1003,6 +1023,16 @@ void GetFeatures() #ifdef USE_MP3_PLAYER feature_drv2 |= 0x00002000; // xdrv_14_mp3.ino #endif +#ifdef USE_PCA9685 + feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino +#endif +#ifdef USE_TUYA_DIMMER + feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino +#endif +#ifdef USE_RC_SWITCH + feature_drv2 |= 0x00010000; // xdrv_17_rcswitch.ino +#endif + #ifdef NO_EXTRA_4K_HEAP @@ -1164,15 +1194,23 @@ void GetFeatures() #ifdef USE_MCP39F501 feature_sns2 |= 0x00000100; // xnrg_04_mcp39f501.ino #endif -#ifdef USE_PZEM2 - feature_sns2 |= 0x00000200; // xnrg_05_pzem2.ino +#ifdef USE_PZEM_AC + feature_sns2 |= 0x00000200; // xnrg_05_pzem_ac.ino #endif #ifdef USE_DS3231 feature_sns2 |= 0x00000400; // xsns_33_ds3231.ino #endif #ifdef USE_HX711 - feature_sns2 |= 0x00000400; // xsns_34_hx711.ino + feature_sns2 |= 0x00000800; // xsns_34_hx711.ino #endif +#ifdef USE_PZEM_DC + feature_sns2 |= 0x00001000; // xnrg_06_pzem_dc.ino +#endif +#ifdef USE_TX20_WIND_SENSOR + feature_sns2 |= 0x00002000; // xsns_35_tx20.ino +#endif + + } @@ -1348,6 +1386,7 @@ void WifiBegin(uint8_t flag) WiFi.mode(WIFI_OFF); // See https://github.com/esp8266/Arduino/issues/2186 #endif + WiFi.persistent(false); // Solve possible wifi init errors (re-add at 6.2.1.16 #4044, #4083) WiFi.disconnect(true); // Delete SDK wifi config delay(200); WiFi.mode(WIFI_STA); // Disable AP mode diff --git a/sonoff/user_config_override_sample.h b/sonoff/user_config_override_sample.h index 8b3203904..8d0abb22f 100644 --- a/sonoff/user_config_override_sample.h +++ b/sonoff/user_config_override_sample.h @@ -1,5 +1,5 @@ /* - user_config_override.h - user configuration overrides user_config.h for Sonoff-Tasmota + user_config_override.h - user configuration overrides my_user_config.h for Sonoff-Tasmota Copyright (C) 2018 Theo Arends @@ -25,7 +25,7 @@ /*****************************************************************************************************\ * USAGE: - * To modify the stock configuration without changing the user_config.h file: + * To modify the stock configuration without changing the my_user_config.h file: * (1) copy this file to "user_config_override.h" (It will be ignored by Git) * (2) define your own settings below * (3) for platformio: @@ -33,12 +33,12 @@ * ie1 : export PLATFORMIO_BUILD_FLAGS='-DUSE_CONFIG_OVERRIDE' * ie2 : enable in file platformio.ini "build_flags = -Wl,-Tesp8266.flash.1m0.ld -DUSE_CONFIG_OVERRIDE" * for Arduino IDE: - * enable define USE_CONFIG_OVERRIDE in user_config.h + * enable define USE_CONFIG_OVERRIDE in my_user_config.h ****************************************************************************************************** * ATTENTION: * - Changes to SECTION1 PARAMETER defines will only override flash settings if you change define CFG_HOLDER. * - Expect compiler warnings when no ifdef/undef/endif sequence is used. - * - You still need to update user_config.h for major define USE_MQTT_TLS. + * - You still need to update my_user_config.h for major define USE_MQTT_TLS. * - All parameters can be persistent changed online using commands via MQTT, WebConsole or Serial. \*****************************************************************************************************/ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 894806919..3cb2b31cb 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -77,10 +77,10 @@ const char HTTP_HEAD[] PROGMEM = "lt=setTimeout(la,{a});" // Settings.web_refresh "}" "function lb(p){" - "la('?d='+p);" + "la('?d='+p);" // ?d related to WebGetArg("d", tmp, sizeof(tmp)); "}" "function lc(p){" - "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); + "la('?t='+p);" // ?t related to WebGetArg("t", tmp, sizeof(tmp)); "}"; const char HTTP_HEAD_RELOAD[] PROGMEM = @@ -293,7 +293,7 @@ const char HTTP_END[] PROGMEM = "" ""; -const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; +const char HTTP_DEVICE_CONTROL[] PROGMEM = ""; // ?o is related to WebGetArg("o", tmp, sizeof(tmp)); const char HTTP_DEVICE_STATE[] PROGMEM = "%s%s"; // {c} = %'>
"), idx, idx); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), idx, idx); // ?k is related to WebGetArg("k", tmp, sizeof(tmp)); page += mqtt_data; } } @@ -606,6 +607,7 @@ void HandleRoot() #ifndef BE_MINIMAL mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON); + XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON); page += String(mqtt_data); #endif // Not BE_MINIMAL @@ -711,6 +713,7 @@ void HandleConfiguration() mqtt_data[0] = '\0'; XdrvCall(FUNC_WEB_ADD_BUTTON); + XsnsCall(FUNC_WEB_ADD_BUTTON); page += String(mqtt_data); page += FPSTR(HTTP_BTN_MENU4); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 89cddbd6c..bb1a86e13 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -398,8 +398,11 @@ void MqttConnected() XdrvCall(FUNC_MQTT_INIT); } mqtt_initial_connection_state = 0; - rules_flag.mqtt_connected = 1; + global_state.mqtt_down = 0; + if (Settings.flag.mqtt_enabled) { + rules_flag.mqtt_connected = 1; + } } #ifdef USE_MQTT_TLS diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 6c8aa938d..c5ba2acc7 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -359,7 +359,7 @@ void LightInit() pinMode(pin[GPIO_PWM1 +i], OUTPUT); } } - if (LT_PWM1 == light_type) { + if (LT_PWM1 == light_type || LT_SERIAL == light_type) { Settings.light_color[0] = 255; // One PWM channel only supports Dimmer but needs max color } if (SONOFF_LED == Settings.module) { // Fix Sonoff Led instabilities @@ -391,6 +391,9 @@ void LightInit() max_scheme = LS_MAX + WS2812_SCHEMES; } #endif // USE_WS2812 ************************************************************************ + else if (LT_SERIAL == light_type) { + light_subtype = LST_SINGLE; + } else { light_pdi_pin = pin[GPIO_DI]; light_pdcki_pin = pin[GPIO_DCKI]; @@ -821,6 +824,11 @@ void LightAnimate() if (light_type > LT_WS2812) { LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]); } +#ifdef USE_TUYA_DIMMER + if (light_type == LT_SERIAL) { + LightSerialDuty(cur_col[0]); + } +#endif // USE_TUYA_DIMMER } } } diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 0533e2d4a..8e9201b43 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -301,7 +301,7 @@ void SonoffBridgeReceived() boolean SonoffBridgeSerialInput() { // iTead Rf Universal Transceiver Module Serial Protocol Version 1.0 (20170420) - int8_t receive_len = 0; + static int8_t receive_len = 0; if (sonoff_bridge_receive_flag) { if (sonoff_bridge_receive_raw_flag) { @@ -309,12 +309,12 @@ boolean SonoffBridgeSerialInput() serial_in_buffer[serial_in_byte_counter++] = 0xAA; } serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; - if (serial_in_byte_counter > 2) { + if (serial_in_byte_counter == 3) { if ((0xA6 == serial_in_buffer[1]) || (0xAB == serial_in_buffer[1])) { // AA A6 06 023908010155 55 - 06 is receive_len - receive_len = serial_in_buffer[2] + 3 - serial_in_byte_counter; // Get at least receive_len bytes + receive_len = serial_in_buffer[2] + 4; // Get at least receive_len bytes } } - if ((0 == receive_len) && (0x55 == serial_in_byte)) { // 0x55 - End of text + if ((!receive_len && (0x55 == serial_in_byte)) || (receive_len && (serial_in_byte_counter == receive_len))) { // 0x55 - End of text SonoffBridgeReceivedRaw(); sonoff_bridge_receive_flag = 0; return 1; @@ -345,6 +345,7 @@ boolean SonoffBridgeSerialInput() serial_in_byte_counter = 0; serial_in_byte = 0; sonoff_bridge_receive_flag = 1; + receive_len = 0; } return 0; } @@ -536,12 +537,12 @@ boolean SonoffBridgeCommand() sonoff_bridge_receive_raw_flag = 1; break; case 192: // 0xC0 - Beep - char beep[] = "AAC000C055"; - SerialSendRaw(beep, sizeof(beep)); + char beep[] = "AAC000C055\0"; + SerialSendRaw(beep); break; } } else { - SerialSendRaw(RemoveSpace(XdrvMailbox.data), strlen(XdrvMailbox.data)); + SerialSendRaw(RemoveSpace(XdrvMailbox.data)); sonoff_bridge_receive_raw_flag = 1; } } diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 6132133ae..944f1ba90 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -49,14 +49,6 @@ byte Settings.knx_CB_param[MAX_KNX_CB] Type of Output (set relay, t \*********************************************************************************************/ #include // KNX Library - // Note: Inside the file there is a //#define USE_ASYNC_UDP // UDP WIFI Library Selection for Multicast - // If commented out, the esp-knx-ip library will use WIFI_UDP Library that is compatible with ESP8266 Library Version 2.3.0 and up - // If not commented out, the esp-knx-ip library will use ESPAsyncUDP Library that is compatible with ESP8266 Library Version 2.4.0 and up - // The ESPAsyncUDP Library have a more reliable multicast communication - // Please Use it with Patch (https://github.com/me-no-dev/ESPAsyncUDP/pull/21) ) - -//void KNX_CB_Action(message_t const &msg, void *arg); // Define function (action callback) to be called by the Esp-KNX-IP Library - // when an action is requested by another KNX Device address_t KNX_physs_addr; // Physical KNX address of this device address_t KNX_addr; // KNX Address converter variable diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 3bbf32bd0..ae0c69fd0 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -141,7 +141,7 @@ void MP3PlayerInit(void) { delay(1000); MP3_CMD(MP3_CMD_RESET, MP3_CMD_RESET_VALUE); // reset the player to defaults delay(3000); - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the user_config.h + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the my_user_config.h } return; } @@ -167,7 +167,7 @@ void MP3_CMD(uint8_t mp3cmd,uint16_t val) { MP3Player->write(cmd, sizeof(cmd)); // write mp3 data array to player delay(1000); if (mp3cmd == MP3_CMD_RESET) { - MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the user_config.h + MP3_CMD(MP3_CMD_VOLUME, MP3_VOLUME); // after reset set volume depending on the entry in the my_user_config.h } return; } diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino new file mode 100644 index 000000000..1a5776d4a --- /dev/null +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -0,0 +1,282 @@ +/* + xdrv_16_tuyadimmer.ino - Tuya dimmer support for Sonoff-Tasmota + + Copyright (C) 2018 digiblur, Joel Stein and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_TUYA_DIMMER + +#ifndef TUYA_DIMMER_ID +#define TUYA_DIMMER_ID 3 +#endif + +uint8_t tuya_new_dim = 0; // Tuya dimmer value temp +boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction +uint8_t tuya_cmd_status = 0; // Current status of serial-read +uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command +uint8_t tuya_data_len = 0; // Data lenght of command + +boolean TuyaSetPower() +{ + boolean status = false; + + uint8_t rpower = XdrvMailbox.index; + int16_t source = XdrvMailbox.payload; + + if (source != SRC_SWITCH ) { // ignore to prevent loop from pushing state from faceplate interaction + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower); + AddLog(LOG_LEVEL_DEBUG); + + Serial.write(0x55); // Tuya header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x06); // Tuya command 06 + Serial.write(0x00); + Serial.write(0x05); // following data length 0x05 + Serial.write(0x01); // relay number 1,2,3 + Serial.write(0x01); + Serial.write(0x00); + Serial.write(0x01); + Serial.write(rpower); // status + Serial.write(0x0D + rpower); // checksum sum of all bytes in packet mod 256 + Serial.flush(); + + status = true; + } + return status; +} + +void LightSerialDuty(uint8_t duty) +{ + if (duty > 0 && !tuya_ignore_dim ) { + if (duty < 25) { + duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself + } + Serial.write(0x55); // Tuya header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x06); // Tuya command 06 - send order + Serial.write(0x00); + Serial.write(0x08); // following data length 0x08 + Serial.write(Settings.param[P_TUYA_DIMMER_ID]); // dimmer id + Serial.write(0x02); // type=value + Serial.write(0x00); // length hi + Serial.write(0x04); // length low + Serial.write(0x00); // + Serial.write(0x00); // + Serial.write(0x00); // + Serial.write( duty ); // dim value (0-255) + Serial.write( byte(Settings.param[P_TUYA_DIMMER_ID] + 19 + duty) ); // checksum:sum of all bytes in packet mod 256 + Serial.flush(); + + snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]); + AddLog(LOG_LEVEL_DEBUG); + + } else { + tuya_ignore_dim = false; // reset flag + + snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Dim Level skipped due to 0 or already set. Value=%d"), duty); + AddLog(LOG_LEVEL_DEBUG); + + } +} + +void TuyaPacketProcess() +{ + char scmnd[20]; + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Packet Size=%d"), serial_in_byte_counter); + AddLog(LOG_LEVEL_DEBUG); + + if (serial_in_byte_counter == 7 && serial_in_buffer[3] == 14 ) { // heartbeat packet + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat")); + } + else if (serial_in_byte_counter == 12 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 5) { // on/off packet + + snprintf_P(log_data, sizeof(log_data),PSTR("TYA: Rcvd - %s State"),serial_in_buffer[10]?"On":"Off"); + AddLog(LOG_LEVEL_DEBUG); + + if((power || Settings.light_dimmer > 0) && (power != serial_in_buffer[10])) { + ExecuteCommandPower(1, serial_in_buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction + } + } + else if (serial_in_byte_counter == 15 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 8) { // dim packet + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), serial_in_buffer[13]); + AddLog(LOG_LEVEL_DEBUG); + + tuya_new_dim = round(serial_in_buffer[13] * (100. / 255.)); + if((power) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 2)) { + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim ); + AddLog(LOG_LEVEL_DEBUG); + + snprintf_P(scmnd, sizeof(scmnd), PSTR(D_CMND_DIMMER " %d"), tuya_new_dim ); + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER_STR=%s"), scmnd ); + AddLog(LOG_LEVEL_DEBUG); + + tuya_ignore_dim = true; + ExecuteCommand(scmnd, SRC_SWITCH); + } + } + else if (serial_in_byte_counter == 8 && serial_in_buffer[3] == 5 && serial_in_buffer[5] == 1 && serial_in_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd")); + + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " 2"); + ExecuteCommand(scmnd, SRC_BUTTON); + } +} + +void TuyaSerialInput() +{ + while (Serial.available()) { + yield(); + serial_in_byte = Serial.read(); + + //snprintf_P(log_data, sizeof(log_data), PSTR("TYA: serial_in_byte %d, tuya_cmd_status %d, tuya_cmd_checksum %d, tuya_data_len %d, serial_in_byte_counter %d"), serial_in_byte, tuya_cmd_status, tuya_cmd_checksum, tuya_data_len, serial_in_byte_counter); + //AddLog(LOG_LEVEL_DEBUG); + + if (serial_in_byte == 0x55) { // Start TUYA Packet + tuya_cmd_status = 1; + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + tuya_cmd_checksum += serial_in_byte; + } + else if (tuya_cmd_status == 1 && serial_in_byte == 0xAA){ // Only packtes with header 0x55AA are valid + tuya_cmd_status = 2; + + AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: 0x55AA Packet Start")); + + serial_in_byte_counter = 0; + serial_in_buffer[serial_in_byte_counter++] = 0x55; + serial_in_buffer[serial_in_byte_counter++] = 0xAA; + tuya_cmd_checksum = 0xFF; + } + else if (tuya_cmd_status == 2){ + if(serial_in_byte_counter == 5){ // Get length of data + tuya_cmd_status = 3; + tuya_data_len = serial_in_byte; + } + tuya_cmd_checksum += serial_in_byte; + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + } + else if ((tuya_cmd_status == 3) && (serial_in_byte_counter == (6 + tuya_data_len)) && (tuya_cmd_checksum == serial_in_byte)){ // Compare checksum and process packet + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + + snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \"")); + for (int i = 0; i < serial_in_byte_counter; i++) { + snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, serial_in_buffer[i]); + } + snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data); + AddLog(LOG_LEVEL_DEBUG); + + TuyaPacketProcess(); + serial_in_byte_counter = 0; + tuya_cmd_status = 0; + tuya_cmd_checksum = 0; + tuya_data_len = 0; + } // read additional packets from TUYA + else if(serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits + serial_in_buffer[serial_in_byte_counter++] = serial_in_byte; + tuya_cmd_checksum += serial_in_byte; + } else { + serial_in_byte_counter = 0; + tuya_cmd_status = 0; + tuya_cmd_checksum = 0; + tuya_data_len = 0; + } + } +} + +boolean TuyaModuleSelected() +{ + baudrate = 9600; + light_type = LT_SERIAL; + return true; +} + +void TuyaInit() +{ + if (!Settings.param[P_TUYA_DIMMER_ID]) { + Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; + } + Serial.setDebugOutput(false); + ClaimSerial(); + + // Get current status of MCU + snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state"); + AddLog(LOG_LEVEL_DEBUG); + Serial.write(0x55); // header 55AA + Serial.write(0xAA); + Serial.write(0x00); // version 00 + Serial.write(0x08); // command 08 - get status + Serial.write(0x00); + Serial.write(0x00); // following data length 0x00 + Serial.write(0x07); // checksum:sum of all bytes in packet mod 256 + Serial.flush(); +} + +boolean TuyaButtonPressed() +{ + if ((PRESSED == XdrvMailbox.payload) && (NOT_PRESSED == lastbutton[XdrvMailbox.index])) { + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_LEVEL_10), XdrvMailbox.index +1); + AddLog(LOG_LEVEL_DEBUG); + + if (!Settings.flag.button_restrict) { + char scmnd[20]; + snprintf_P(scmnd, sizeof(scmnd), D_CMND_WIFICONFIG " %d", 2); + ExecuteCommand(scmnd, SRC_BUTTON); + } + } + return true; // Serviced here +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XDRV_16 + +boolean Xdrv16(byte function) +{ + boolean result = false; + + if (TUYA_DIMMER == Settings.module) { + switch (function) { + case FUNC_MODULE_INIT: + result = TuyaModuleSelected(); + break; + case FUNC_INIT: + TuyaInit(); + break; + case FUNC_LOOP: + TuyaSerialInput(); + break; + case FUNC_SET_DEVICE_POWER: + result = TuyaSetPower(); + break; + case FUNC_BUTTON_PRESSED: + result = TuyaButtonPressed(); + break; + } + } + return result; +} + +#endif // USE_TUYA_DIMMER diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino new file mode 100644 index 000000000..6c65dd3b0 --- /dev/null +++ b/sonoff/xdrv_17_rcswitch.ino @@ -0,0 +1,184 @@ +/* + xdrv_17_rcswitch.ino - RF transceiver using RcSwitch library for Sonoff-Tasmota + + Copyright (C) 2017 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_RC_SWITCH +/*********************************************************************************************\ + * RF send and receive using RCSwitch library +\*********************************************************************************************/ + +#define D_JSON_RF_PROTOCOL "Protocol" +#define D_JSON_RF_BITS "Bits" +#define D_JSON_RF_DATA "Data" + +#define D_CMND_RFSEND "RFSend" +#define D_JSON_RF_PULSE "Pulse" +#define D_JSON_RF_REPEAT "Repeat" + +#include + +RCSwitch mySwitch = RCSwitch(); + +#define RF_TIME_AVOID_DUPLICATE 500 // Milliseconds + +unsigned long rf_lasttime = 0; + +void RfReceiveCheck() +{ + if (mySwitch.available()) { + + unsigned long value = mySwitch.getReceivedValue(); + unsigned int bit_length = mySwitch.getReceivedBitlength(); + unsigned int delay = mySwitch.getReceivedDelay(); + unsigned int protocol = mySwitch.getReceivedProtocol(); + + snprintf_P(log_data, sizeof(log_data), PSTR("RFR: BitLen %d, Delay %d, Protocol %d, Value %lX (%u)"), + bit_length, delay, protocol, value, value); + AddLog(LOG_LEVEL_DEBUG); + + unsigned long now = millis(); + if ((now - rf_lasttime > RF_TIME_AVOID_DUPLICATE) && (value > 0)) { + rf_lasttime = now; + + char stemp[16]; + if (Settings.flag.rf_receive_decimal) { + snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)value); + } else { + snprintf_P(stemp, sizeof(stemp), PSTR("\"%lX\""), (uint32_t)value); + } + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_DATA "\":%s}}"), + protocol, bit_length, stemp); + MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); + XdrvRulesProcess(); +#ifdef USE_DOMOTICZ + DomoticzSensor(DZ_COUNT, value); // Send value as Domoticz Counter value +#endif // USE_DOMOTICZ + } + mySwitch.resetAvailable(); + } +} + +void RfInit() +{ + if (pin[GPIO_RFSEND] < 99) { + mySwitch.enableTransmit(pin[GPIO_RFSEND]); + } + if (pin[GPIO_RFRECV] < 99) { + mySwitch.enableReceive(pin[GPIO_RFRECV]); + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +/* + * ArduinoJSON entry used to calculate jsonBuf: JSON_OBJECT_SIZE(3) + 40 = 96 + RFsend: + { "protocol":1, "pulse":320, "repeat":15, "bits":24, "data":551502015 } +*/ + +boolean RfSendCommand() +{ + boolean serviced = true; + + boolean error = false; + char dataBufUc[XdrvMailbox.data_len]; + + uint32_t protocol = 0; + uint32_t pulse = 0; + uint32_t repeat = 0; + uint32_t bits = 0; + uint32_t data = 0; + + UpperCase(dataBufUc, XdrvMailbox.data); + if (!strcasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_RFSEND))) { + if (XdrvMailbox.data_len) { + StaticJsonBuffer<128> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_INVALID_JSON "\"}")); // JSON decode failed + } + else { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}")); + + char parm_uc[10]; + protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; + pulse = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PULSE))]; + repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; + bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; + data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], NULL, 0); + + if (!protocol) { protocol = 1; } + mySwitch.setProtocol(protocol); + if (!pulse) { pulse = 350; } // Default pulse length for protocol 1 + mySwitch.setPulseLength(pulse); + if (!repeat) { repeat = 10; } // Default at init + mySwitch.setRepeatTransmit(repeat); + if (!bits) { bits = 24; } // Default 24 bits + if (data) { + mySwitch.send(data, bits); + } + else { + error = true; + } + } + } + else { + error = true; + } + if (error) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_PROTOCOL ", " D_JSON_RF_PULSE ", " D_JSON_RF_REPEAT ", " D_JSON_RF_BITS " " D_JSON_OR " " D_JSON_RF_DATA "\"}")); + } + } + else serviced = false; // Unknown command + + return serviced; +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XDRV_17 + +boolean Xdrv17(byte function) +{ + boolean result = false; + + if ((pin[GPIO_RFSEND] < 99) || (pin[GPIO_RFRECV] < 99)) { + switch (function) { + case FUNC_INIT: + RfInit(); + break; + case FUNC_EVERY_50_MSECOND: + if (pin[GPIO_RFRECV] < 99) { + RfReceiveCheck(); + } + break; + case FUNC_COMMAND: + if (pin[GPIO_RFSEND] < 99) { + result = RfSendCommand(); + } + break; + } + } + return result; +} + +#endif // USE_RC_SWITCH diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index a88d3b5f8..c80bb27d4 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -98,6 +98,54 @@ boolean (* const xdrv_func_ptr[])(byte) PROGMEM = { // Driver Function Pointer &Xdrv20, #endif +#ifdef XDRV_21 + &Xdrv21, +#endif + +#ifdef XDRV_22 + &Xdrv22, +#endif + +#ifdef XDRV_23 + &Xdrv23, +#endif + +#ifdef XDRV_24 + &Xdrv24, +#endif + +#ifdef XDRV_25 + &Xdrv25, +#endif + +#ifdef XDRV_26 + &Xdrv26, +#endif + +#ifdef XDRV_27 + &Xdrv27, +#endif + +#ifdef XDRV_28 + &Xdrv28, +#endif + +#ifdef XDRV_29 + &Xdrv29, +#endif + +#ifdef XDRV_30 + &Xdrv30, +#endif + +#ifdef XDRV_31 + &Xdrv31, +#endif + +#ifdef XDRV_32 + &Xdrv32, +#endif + // Optional user defined drivers in range 91 - 99 #ifdef XDRV_91 diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index 3dfbc3879..dae285b01 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -25,7 +25,7 @@ * Source: Victor Ferrer https://github.com/vicfergar/Sonoff-MQTT-OTA-Arduino * Based on: PZEM004T library https://github.com/olehs/PZEM004T * - * Hardware Serial will be selected if GPIO1 = [PZEM Rx] and [GPIO3 = PZEM Tx] + * Hardware Serial will be selected if GPIO1 = [63 PZEM004 Rx] and GPIO3 = [62 PZEM0XX Tx] \*********************************************************************************************/ #define XNRG_03 3 @@ -203,7 +203,7 @@ void PzemEvery200ms() void PzemSnsInit() { // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - PzemSerial = new TasmotaSerial(pin[GPIO_PZEM_RX], pin[GPIO_PZEM_TX], 1); + PzemSerial = new TasmotaSerial(pin[GPIO_PZEM004_RX], pin[GPIO_PZEM0XX_TX], 1); if (PzemSerial->begin(9600)) { if (PzemSerial->hardwareSerial()) { ClaimSerial(); } } else { @@ -214,7 +214,7 @@ void PzemSnsInit() void PzemDrvInit() { if (!energy_flg) { - if ((pin[GPIO_PZEM_RX] < 99) && (pin[GPIO_PZEM_TX] < 99)) { // Any device with a Pzem004T + if ((pin[GPIO_PZEM004_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { // Any device with a Pzem004T energy_flg = XNRG_03; } } diff --git a/sonoff/xnrg_05_pzem2.ino b/sonoff/xnrg_05_pzem2.ino deleted file mode 100644 index bb0f4864d..000000000 --- a/sonoff/xnrg_05_pzem2.ino +++ /dev/null @@ -1,230 +0,0 @@ -/* - xnrg_06_pzem2.ino - PZEM-003,017 and PZEM-014,016 Modbus energy sensor support for Sonoff-Tasmota - - Copyright (C) 2018 Theo Arends - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifdef USE_ENERGY_SENSOR -#ifdef USE_PZEM2 -/*********************************************************************************************\ - * PZEM-003 - DC 300V 10A Energy - * PZEM-014 - AC 220V 10A Energy - * PZEM-016 - AC 220V 100A Energy - * PZEM-017 - DC 300V 50A - 300A Energy - * - * Based on: - * PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37 - * PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv - * - * Hardware Serial will be selected if GPIO1 = [99 PZEM Rx] and GPIO3 = [98 PZEM Tx] -\*********************************************************************************************/ - -#define XNRG_05 5 - -#define PZEM2_TYPES_003_017 8 // Result 16 bit register count -#define PZEM2_TYPES_014_016 10 // Result 16 bit register count - -#define PZEM2_READ_RESULT 0x04 - -#include - -TasmotaSerial *Pzem2Serial; - -uint8_t pzem2_type = PZEM2_TYPES_014_016; - -/*********************************************************************************************/ - -uint16_t Pzem2ModbusCalculateCRC(uint8_t *frame, uint8_t num) -{ - uint16_t crc = 0xFFFF; - uint16_t flag; - - for (uint8_t i = 0; i < num; i++) { - crc ^= frame[i]; - for (uint8_t j = 8; j; j--) { - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 - crc ^= 0xA001; - } else { // Else LSB is not set - crc >>= 1; // Just shift right - } - } - } - return crc; -} - -void Pzem2ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = 0xFE; // Any Address - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - uint16_t crc = Pzem2ModbusCalculateCRC(frame, 6); - frame[6] = (uint8_t)((crc >> 8) & 0xFF); - frame[7] = (uint8_t)(crc & 0xFF); - - Pzem2Serial->flush(); - Pzem2Serial->write(frame, sizeof(frame)); -} - -bool Pzem2ModbusReceiveReady() -{ - return (Pzem2Serial->available() >= 5); // 5 - Error frame, 21 or 25 - Ok frame -} - -uint8_t Pzem2ModbusReceive(uint8_t *buffer, uint8_t register_count) -{ - // 0 1 2 3 4 5 6 - // FE 04 02 08 98 HH LL - // Id Cc Sz Regis Crc-- - - uint8_t len = 0; - while ((Pzem2Serial->available() > 0) && (len < (register_count *2) + 5)) { - buffer[len++] = (uint8_t)Pzem2Serial->read(); - if (3 == len) { - if (buffer[1] & 0x80) { // fe 84 02 f2 f1 - return buffer[2]; // 1 = Illegal Function, 2 = Illegal Address, 3 = Illegal Data, 4 = Slave Error - } - } - } - - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len < 7) { return 7; } // 7 = Not enough data - if (len != buffer[2] + 5) { return 8; } // 8 = Unexpected result - - uint16_t crc = (buffer[len -2] << 8) | buffer[len -1]; - if (Pzem2ModbusCalculateCRC(buffer, len -3) != crc) { return 9; } // 9 = crc error - - return 0; // 0 = No error -} - -/*********************************************************************************************/ - -uint8_t pzem2_sendRetry = 0; - -void Pzem2Every200ms() -{ - bool data_ready = Pzem2ModbusReceiveReady(); - - if (data_ready) { - uint8_t buffer[26]; - uint8_t error = Pzem2ModbusReceive(buffer, pzem2_type); - if (error) { - snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PZEM2 response error %d"), error); - AddLog(LOG_LEVEL_DEBUG); -// if (9 == error) { - if (PZEM2_TYPES_014_016 == pzem2_type) { - pzem2_type = PZEM2_TYPES_003_017; - } else { - pzem2_type = PZEM2_TYPES_014_016; - } -// } - } else { - float energy = 0; - - if (PZEM2_TYPES_003_017 == pzem2_type) { - energy_type_dc = true; - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - // FE 04 10 27 10 00 64 03 E8 00 00 00 00 00 00 00 00 00 00 HH LL = PZEM-017 - // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V - energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A - energy_active_power = (float)((uint32_t)buffer[9] << 24 + (uint32_t)buffer[10] << 16 + (uint32_t)buffer[7] << 8 + buffer[8]) / 10.0; // 429496729.0 W - energy = (float)((uint32_t)buffer[13] << 24 + (uint32_t)buffer[14] << 16 + (uint32_t)buffer[11] << 8 + buffer[12]); // 4294967295 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; - EnergyUpdateToday(); - } - else if (PZEM2_TYPES_014_016 == pzem2_type) { // PZEM-014,016 - energy_type_dc = false; - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - // FE 04 14 08 98 03 E8 00 00 08 98 00 00 00 00 00 00 01 F4 00 64 00 00 HH LL = PZEM-014 - // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- - energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V - energy_current = (float)((uint32_t)buffer[7] << 24 + (uint32_t)buffer[8] << 16 + (uint32_t)buffer[5] << 8 + buffer[6]) / 1000.0; // 4294967.000 A - energy_active_power = (float)((uint32_t)buffer[11] << 24 + (uint32_t)buffer[12] << 16 + (uint32_t)buffer[9] << 8 + buffer[10]) / 10.0; // 429496729.0 W - energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz - energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 - energy = (float)((uint32_t)buffer[15] << 24 + (uint32_t)buffer[16] << 16 + (uint32_t)buffer[13] << 8 + buffer[14]); // 4294967295 Wh - if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any - energy_kWhtoday += (energy - energy_start) * 100; - energy_start = energy; - EnergyUpdateToday(); - } - } - } - - if (0 == pzem2_sendRetry || data_ready) { - pzem2_sendRetry = 5; - Pzem2ModbusSend(PZEM2_READ_RESULT, 0, pzem2_type); - } - else { - pzem2_sendRetry--; - } -} - -void Pzem2SnsInit() -{ - // Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions - Pzem2Serial = new TasmotaSerial(pin[GPIO_PZEM2_RX], pin[GPIO_PZEM2_TX], 1); - if (Pzem2Serial->begin(9600)) { - if (Pzem2Serial->hardwareSerial()) { ClaimSerial(); } - } else { - energy_flg = ENERGY_NONE; - } -} - -void Pzem2DrvInit() -{ - if (!energy_flg) { - if ((pin[GPIO_PZEM2_RX] < 99) && (pin[GPIO_PZEM2_TX] < 99)) { // Any device with a Pzem-003,014,016,017 - energy_flg = XNRG_05; - } - } -} - -/*********************************************************************************************\ - * Interface -\*********************************************************************************************/ - -int Xnrg05(byte function) -{ - int result = 0; - - if (FUNC_PRE_INIT == function) { - Pzem2DrvInit(); - } - else if (XNRG_05 == energy_flg) { - switch (function) { - case FUNC_INIT: - Pzem2SnsInit(); - break; - case FUNC_EVERY_200_MSECOND: - Pzem2Every200ms(); - break; - } - } - return result; -} - -#endif // USE_PZEM2 -#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_05_pzem_ac.ino b/sonoff/xnrg_05_pzem_ac.ino new file mode 100644 index 000000000..ca2262bb5 --- /dev/null +++ b/sonoff/xnrg_05_pzem_ac.ino @@ -0,0 +1,126 @@ +/* + xnrg_05_pzem_ac.ino - PZEM-014,016 Modbus AC energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_AC +/*********************************************************************************************\ + * PZEM-014 - AC 220V 10A Energy + * PZEM-016 - AC 220V 100A Energy + * + * Based on: + * PZEM-014,016 docs https://pan.baidu.com/s/1B0MdMgURyjtO1oQa2lavKw password ytkv + * + * Hardware Serial will be selected if GPIO1 = [98 PZEM016 Rx] and GPIO3 = [62 PZEM0XX Tx] +\*********************************************************************************************/ + +#define XNRG_05 5 + +#define PZEM_AC_DEVICE_ADDRESS 0x01 // PZEM default address + +#include +TasmotaModbus *PzemAcModbus; + +void PzemAcEverySecond() +{ + static uint8_t send_retry = 0; + + bool data_ready = PzemAcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[26]; + + uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, 10); + AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + + if (error) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemAc response error %d"), error); + AddLog(LOG_LEVEL_DEBUG); + } else { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 + // 01 04 14 08 D1 00 6C 00 00 00 F4 00 00 00 26 00 00 01 F4 00 64 00 00 51 34 + // Id Cc Sz Volt- Current---- Power------ Energy----- Frequ PFact Alarm Crc-- + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 10.0; // 6553.0 V + energy_current = (float)((buffer[7] << 24) + (buffer[8] << 16) + (buffer[5] << 8) + buffer[6]) / 1000.0; // 4294967.000 A + energy_active_power = (float)((buffer[11] << 24) + (buffer[12] << 16) + (buffer[9] << 8) + buffer[10]) / 10.0; // 429496729.0 W + energy_frequency = (float)((buffer[17] << 8) + buffer[18]) / 10.0; // 50.0 Hz + energy_power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00 + float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh + + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + } + + if (0 == send_retry || data_ready) { + send_retry = 5; + PzemAcModbus->Send(PZEM_AC_DEVICE_ADDRESS, 0x04, 0, 10); + } + else { + send_retry--; + } +} + +void PzemAcSnsInit() +{ + PzemAcModbus = new TasmotaModbus(pin[GPIO_PZEM016_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemAcModbus->Begin(9600); + if (result) { + if (2 == result) { ClaimSerial(); } + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemAcDrvInit() +{ + if (!energy_flg) { + if ((pin[GPIO_PZEM016_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_05; + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg05(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + PzemAcDrvInit(); + } + else if (XNRG_05 == energy_flg) { + switch (function) { + case FUNC_INIT: + PzemAcSnsInit(); + break; + case FUNC_EVERY_SECOND: + PzemAcEverySecond(); + break; + } + } + return result; +} + +#endif // USE_PZEM_AC +#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_06_pzem_dc.ino b/sonoff/xnrg_06_pzem_dc.ino new file mode 100644 index 000000000..b7a693bef --- /dev/null +++ b/sonoff/xnrg_06_pzem_dc.ino @@ -0,0 +1,125 @@ +/* + xnrg_06_pzem_dc.ino - PZEM-003,017 Modbus DC energy sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_ENERGY_SENSOR +#ifdef USE_PZEM_DC +/*********************************************************************************************\ + * PZEM-003 - DC 300V 10A Energy + * PZEM-017 - DC 300V 50A - 300A Energy + * + * Based on: + * PZEM-003,017 docs Https://pan.baidu.com/s/1V9bDWj3RK2u6_fbBJ3GtqQ password rq37 + * + * Hardware Serial will be selected if GPIO1 = [99 PZEM017 Rx] and GPIO3 = [62 PZEM0XX Tx] +\*********************************************************************************************/ + +#define XNRG_06 6 + +#define PZEM_DC_DEVICE_ADDRESS 0x01 // PZEM default address + +#include +TasmotaModbus *PzemDcModbus; + +void PzemDcEverySecond() +{ + static uint8_t send_retry = 0; + + bool data_ready = PzemDcModbus->ReceiveReady(); + + if (data_ready) { + uint8_t buffer[22]; + + uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, 8); + AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer)); + + if (error) { + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "PzemDc response error %d"), error); + AddLog(LOG_LEVEL_DEBUG); + } else { + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 + // 01 04 10 05 40 00 0A 00 0D 00 00 00 02 00 00 00 00 00 00 D6 29 + // Id Cc Sz Volt- Curre Power------ Energy----- HiAlm LoAlm Crc-- + energy_voltage = (float)((buffer[3] << 8) + buffer[4]) / 100.0; // 655.00 V + energy_current = (float)((buffer[5] << 8) + buffer[6]) / 100.0; // 655.00 A + energy_active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W + float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh + + if (!energy_start || (energy < energy_start)) { energy_start = energy; } // Init after restart and hanlde roll-over if any + energy_kWhtoday += (energy - energy_start) * 100; + energy_start = energy; + EnergyUpdateToday(); + } + } + + if (0 == send_retry || data_ready) { + send_retry = 5; + PzemDcModbus->Send(PZEM_DC_DEVICE_ADDRESS, 0x04, 0, 8); + } + else { + send_retry--; + } +} + +void PzemDcSnsInit() +{ + PzemDcModbus = new TasmotaModbus(pin[GPIO_PZEM017_RX], pin[GPIO_PZEM0XX_TX]); + uint8_t result = PzemDcModbus->Begin(9600, 2); // Uses two stop bits!! + if (result) { + if (2 == result) { ClaimSerial(); } + energy_type_dc = true; + } else { + energy_flg = ENERGY_NONE; + } +} + +void PzemDcDrvInit() +{ + if (!energy_flg) { + if ((pin[GPIO_PZEM017_RX] < 99) && (pin[GPIO_PZEM0XX_TX] < 99)) { + energy_flg = XNRG_06; + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +int Xnrg06(byte function) +{ + int result = 0; + + if (FUNC_PRE_INIT == function) { + PzemDcDrvInit(); + } + else if (XNRG_06 == energy_flg) { + switch (function) { + case FUNC_INIT: + PzemDcSnsInit(); + break; + case FUNC_EVERY_SECOND: + PzemDcEverySecond(); + break; + } + } + return result; +} + +#endif // USE_PZEM_DC +#endif // USE_ENERGY_SENSOR diff --git a/sonoff/xnrg_interface.ino b/sonoff/xnrg_interface.ino index d9726ac05..015d5d284 100644 --- a/sonoff/xnrg_interface.ino +++ b/sonoff/xnrg_interface.ino @@ -39,7 +39,47 @@ int (* const xnrg_func_ptr[])(byte) PROGMEM = { // Energy driver Function Poin #endif #ifdef XNRG_06 - &Xnrg06 + &Xnrg06, +#endif + +#ifdef XNRG_07 + &Xnrg07, +#endif + +#ifdef XNRG_08 + &Xnrg08, +#endif + +#ifdef XNRG_09 + &Xnrg09, +#endif + +#ifdef XNRG_10 + &Xnrg10, +#endif + +#ifdef XNRG_11 + &Xnrg11, +#endif + +#ifdef XNRG_12 + &Xnrg12, +#endif + +#ifdef XNRG_13 + &Xnrg13, +#endif + +#ifdef XNRG_14 + &Xnrg14, +#endif + +#ifdef XNRG_15 + &Xnrg15, +#endif + +#ifdef XNRG_16 + &Xnrg16 #endif }; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index d43ca90b1..f8eff5ddc 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -660,11 +660,11 @@ void HueLights(String *path) if ((device < 1) || (device > maxhue)) { device = 1; } - if (1 == WebServer->args()) { + if (WebServer->args()) { response = "["; StaticJsonBuffer<400> jsonBuffer; - JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg(0)); + JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1)); if (hue_json.containsKey("on")) { response += FPSTR(HUE_LIGHT_RESPONSE_JSON); diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index 6ebd00014..a810a0e27 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -26,7 +26,9 @@ * Hardware Serial will be selected if GPIO1 = [SAir Rx] and GPIO3 = [SAir Tx] \*********************************************************************************************/ -#include +#define SENSEAIR_MODBUS_SPEED 9600 +#define SENSEAIR_DEVICE_ADDRESS 0xFE // Any address +#define SENSEAIR_READ_REGISTER 0x04 // Command Read #ifndef CO2_LOW #define CO2_LOW 800 // Below this CO2 value show green light @@ -35,7 +37,8 @@ #define CO2_HIGH 1200 // Above this CO2 value show red light #endif -TasmotaSerial *SensairSerial; +#include +TasmotaModbus *SenseairModbus; const char kSenseairTypes[] PROGMEM = "Kx0|S8"; @@ -48,68 +51,6 @@ float senseair_humidity = 0; //uint8_t senseair_state = 0; -/*********************************************************************************************/ - -void ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count) -{ - uint8_t frame[8]; - - frame[0] = 0xFE; // Any Address - frame[1] = function_code; - frame[2] = (uint8_t)(start_address >> 8); - frame[3] = (uint8_t)(start_address); - frame[4] = (uint8_t)(register_count >> 8); - frame[5] = (uint8_t)(register_count); - uint16_t crc = 0xFFFF; - for (uint8_t pos = 0; pos < sizeof(frame) -2; pos++) { - crc ^= (uint16_t)frame[pos]; // XOR byte into least sig. byte of crc - for (uint8_t i = 8; i != 0; i--) { // Loop over each bit - if ((crc & 0x0001) != 0) { // If the LSB is set - crc >>= 1; // Shift right and XOR 0xA001 - crc ^= 0xA001; - } - else { // Else LSB is not set - crc >>= 1; // Just shift right - } - } - } - frame[7] = (uint8_t)((crc >> 8) & 0xFF); - frame[6] = (uint8_t)(crc & 0xFF); - - SensairSerial->flush(); - SensairSerial->write(frame, sizeof(frame)); -} - -bool ModbusReceiveReady() -{ - return (SensairSerial->available() >= 5); // 5 - Error frame, 7 - Ok frame -} - -uint8_t ModbusReceive(uint16_t *value) -{ - uint8_t buffer[7]; - - uint8_t len = 0; - while (SensairSerial->available() > 0) { - buffer[len++] = (uint8_t)SensairSerial->read(); - if (3 == len) { - if (buffer[1] & 0x80) { // fe 84 02 f2 f1 - return buffer[2]; // 1 = Illegal Function, 2 = Illegal Data Address, 3 = Illegal Data Value - } - } - } - - AddLogSerial(LOG_LEVEL_DEBUG_MORE, buffer, len); - - if (len != sizeof(buffer)) { - return 9; // 9 = Unexpected result - } - *value = (buffer[3] << 8) | buffer[4]; - return 0; // 0 = No error -} - -/*********************************************************************************************/ - const uint8_t start_addresses[] { 0x1A, 0x00, 0x03, 0x04, 0x05, 0x1C, 0x0A }; uint8_t senseair_read_state = 0; @@ -122,10 +63,10 @@ void Senseair250ms() // Every 250 mSec // senseair_state = 0; uint16_t value = 0; - bool data_ready = ModbusReceiveReady(); + bool data_ready = SenseairModbus->ReceiveReady(); if (data_ready) { - uint8_t error = ModbusReceive(&value); + uint8_t error = SenseairModbus->Receive16BitRegister(&value); if (error) { snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SenseAir response error %d"), error); AddLog(LOG_LEVEL_DEBUG); @@ -179,7 +120,7 @@ void Senseair250ms() // Every 250 mSec if (0 == senseair_send_retry || data_ready) { senseair_send_retry = 5; - ModbusSend(0x04, (uint16_t)start_addresses[senseair_read_state], 1); + SenseairModbus->Send(SENSEAIR_DEVICE_ADDRESS, SENSEAIR_READ_REGISTER, (uint16_t)start_addresses[senseair_read_state], 1); } else { senseair_send_retry--; } @@ -193,9 +134,10 @@ void SenseairInit() { senseair_type = 0; if ((pin[GPIO_SAIR_RX] < 99) && (pin[GPIO_SAIR_TX] < 99)) { - SensairSerial = new TasmotaSerial(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX], 1); - if (SensairSerial->begin(9600)) { - if (SensairSerial->hardwareSerial()) { ClaimSerial(); } + SenseairModbus = new TasmotaModbus(pin[GPIO_SAIR_RX], pin[GPIO_SAIR_TX]); + uint8_t result = SenseairModbus->Begin(SENSEAIR_MODBUS_SPEED); + if (result) { + if (2 == result) { ClaimSerial(); } senseair_type = 1; } } diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index cc4fba3ab..86191c079 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -1,29 +1,29 @@ /** - * + * * @file xsns_30_mpr121.ino - * + * * @package Sonoff-Tasmota * @subpackage Sensors * @name MPR121 - * + * * @description Driver for up to 4x Freescale MPR121 Proximity Capacitive Touch Sensor Controllers (Only touch buttons). - * + * * @author Rene 'Renne' Bartsch, B.Sc. Informatics, * @copyright Rene 'Renne' Bartsch 2018 * @date $Date$ * @version $Id$ - * - * @link https://github.com/arendst/Sonoff-Tasmota/wiki/MPR121 \endlink - * @link https://www.sparkfun.com/datasheets/Components/MPR121.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3891.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3892.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3893.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3894.pdf \endlink - * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3895.pdf \endlink - * + * + * @link https://github.com/arendst/Sonoff-Tasmota/wiki/MPR121 \endlink + * @link https://www.sparkfun.com/datasheets/Components/MPR121.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3891.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3892.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3893.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3894.pdf \endlink + * @link http://cache.freescale.com/files/sensors/doc/app_note/AN3895.pdf \endlink + * * @license GNU GPL v.3 */ - + /* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -178,9 +178,9 @@ /** * MPR121 sensors status and data struct. * - * The struct mpr121 uses the indices of i2c_addr and id to link the specific sensors to an I2C address and a human-readable ID + * The struct mpr121 uses the indices of i2c_addr and id to link the specific sensors to an I2C address and a human-readable ID * and the indices of the arrays connected, running, current and previous to store sensor status and data of a specific sensor. - * + * */ typedef struct mpr121 mpr121; struct mpr121 { @@ -195,12 +195,12 @@ struct mpr121 { /** * The function Mpr121Init() soft-resets, detects and configures up to 4x MPR121 sensors. - * + * * @param struct *pS Struct with MPR121 status and data. * @return void * @pre None. * @post None. - * + * */ void Mpr121Init(struct mpr121 *pS) { @@ -301,16 +301,16 @@ void Mpr121Init(struct mpr121 *pS) /** * Publishes the sensor information. - * + * * The function Mpr121Show() reads sensor data, checks for over-current exceptions and * creates strings with button states for the web-interface and near real-time/ telemetriy MQTT. - * + * * @param struct *pS Struct with MPR121 status and data. * @param byte function Tasmota function ID. * @return void * @pre Call Mpr121Init() once. * @post None. - * + * */ void Mpr121Show(struct mpr121 *pS, byte function) { @@ -365,7 +365,7 @@ void Mpr121Show(struct mpr121 *pS, byte function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"Button%i\":%i,"), mqtt_data, j, BITC(i, j)); + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"Button%i\":%i"), mqtt_data, (j > 0 ? "," : ""), j, BITC(i, j)); } } // for-loop j @@ -392,18 +392,18 @@ void Mpr121Show(struct mpr121 *pS, byte function) /** * The function Xsns30() interfaces Tasmota with the driver. - * + * * It provides the function IDs * FUNC_INIT to initialize a driver, * FUNC_EVERY_50_MSECOND for near real-time operation, * FUNC_JSON_APPEND for telemetry data and * FUNC_WEB_APPEND for displaying data in the Tasmota web-interface - * + * * @param byte function Tasmota function ID. * @return boolean ??? * @pre None. * @post None. - * + * */ boolean Xsns30(byte function) { diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 91d987ba5..e46f1d445 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -32,25 +32,30 @@ * - Execute command Sensor34 2 and follow messages shown \*********************************************************************************************/ -#define XSNS_34 34 +#define XSNS_34 34 #ifndef HX_MAX_WEIGHT -#define HX_MAX_WEIGHT 20000 // Default max weight in gram +#define HX_MAX_WEIGHT 20000 // Default max weight in gram #endif #ifndef HX_REFERENCE -#define HX_REFERENCE 250 // Default reference weight for calibration in gram +#define HX_REFERENCE 250 // Default reference weight for calibration in gram #endif #ifndef HX_SCALE -#define HX_SCALE 120 // Default result of measured weight / reference weight when scale is 1 +#define HX_SCALE 120 // Default result of measured weight / reference weight when scale is 1 #endif -#define HX_TIMEOUT 120 // A reading at default 10Hz (pin RATE to Gnd on HX711) can take up to 100 milliseconds -#define HX_SAMPLES 10 // Number of samples for average calculation -#define HX_CAL_TIMEOUT 15 // Calibration step window in number of seconds +#define HX_TIMEOUT 120 // A reading at default 10Hz (pin RATE to Gnd on HX711) can take up to 100 milliseconds +#define HX_SAMPLES 10 // Number of samples for average calculation +#define HX_CAL_TIMEOUT 15 // Calibration step window in number of seconds -#define HX_GAIN_128 1 // Channel A, gain factor 128 -#define HX_GAIN_32 2 // Channel B, gain factor 32 -#define HX_GAIN_64 3 // Channel A, gain factor 64 +#define HX_GAIN_128 1 // Channel A, gain factor 128 +#define HX_GAIN_32 2 // Channel B, gain factor 32 +#define HX_GAIN_64 3 // Channel A, gain factor 64 + +#define D_JSON_WEIGHT_REF "WeightRef" +#define D_JSON_WEIGHT_CAL "WeightCal" +#define D_JSON_WEIGHT_MAX "WeightMax" +#define D_JSON_WEIGHT_ITEM "WeightItem" enum HxCalibrationSteps { HX_CAL_END, HX_CAL_LIMBO, HX_CAL_FINISH, HX_CAL_FAIL, HX_CAL_DONE, HX_CAL_FIRST, HX_CAL_RESET, HX_CAL_START }; @@ -169,7 +174,7 @@ bool HxCommand() hx_calibrate_timer = 1; HxCalibrationStateTextJson(3); break; - case 3: // WeightSet to user reference + case 3: // WeightRef to user reference if (strstr(XdrvMailbox.data, ",")) { Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); } @@ -190,7 +195,7 @@ bool HxCommand() break; case 6: // WeightItem if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_item = (uint16_t)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); + Settings.weight_item = (unsigned long)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); } show_parms = true; break; @@ -201,7 +206,7 @@ bool HxCommand() if (show_parms) { char item[10]; dtostrfd((float)Settings.weight_item / 10, 1, item); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Sensor34\":{\"WeightSet\":%d,\"WeightCal\":%d,\"WeightMax\":%d,\"WeightItem\":%s}}"), + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s}}"), Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item); } @@ -210,6 +215,11 @@ bool HxCommand() /*********************************************************************************************/ +long HxWeight() +{ + return (hx_calibrate_step < HX_CAL_FAIL) ? hx_weight : 0; +} + void HxInit() { hx_type = 0; @@ -353,6 +363,109 @@ void HxShow(boolean json) } } +#ifdef USE_WEBSERVER +#ifdef USE_HX711_GUI +/*********************************************************************************************\ + * Optional GUI +\*********************************************************************************************/ + +#define WEB_HANDLE_HX711 "s34" + +const char S_CONFIGURE_HX711[] PROGMEM = D_CONFIGURE_HX711; + +const char HTTP_BTN_MENU_MAIN_HX711[] PROGMEM = + "
"; + +const char HTTP_BTN_MENU_HX711[] PROGMEM = + "
"; + +const char HTTP_FORM_HX711[] PROGMEM = + "
 " D_CALIBRATION " " + "
" + "
" D_REFERENCE_WEIGHT " (" D_UNIT_KILOGRAM ")

" + "

" + "
" + "


" + + "
 " D_HX711_PARAMETERS " " + "
" + "
" D_ITEM_WEIGHT " (" D_UNIT_KILOGRAM ")

"; + +void HandleHxAction() +{ + if (HttpUser()) { return; } + if (!WebAuthenticate()) { return WebServer->requestAuthentication(); } + AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_CONFIGURE_HX711); + + if (WebServer->hasArg("save")) { + HxSaveSettings(); + HandleConfiguration(); + return; + } + + char tmp[100]; + + if (WebServer->hasArg("reset")) { + snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 1")); // Reset + ExecuteWebCommand(tmp, SRC_WEBGUI); + + HandleRoot(); // Return to main screen + return; + } + + if (WebServer->hasArg("calibrate")) { + WebGetArg("p1", tmp, sizeof(tmp)); + Settings.weight_reference = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 1000); + + HxLogUpdates(); + + snprintf_P(tmp, sizeof(tmp), PSTR("Sensor34 2")); // Start calibration + ExecuteWebCommand(tmp, SRC_WEBGUI); + + HandleRoot(); // Return to main screen + return; + } + + String page = FPSTR(HTTP_HEAD); + page.replace(F("{v}"), FPSTR(D_CONFIGURE_HX711)); + page += FPSTR(HTTP_HEAD_STYLE); + page += FPSTR(HTTP_FORM_HX711); + dtostrfd((float)Settings.weight_reference / 1000, 3, tmp); + page.replace("{1", String(tmp)); + dtostrfd((float)Settings.weight_item / 10000, 4, tmp); + page.replace("{2", String(tmp)); + + page += FPSTR(HTTP_FORM_END); + page += FPSTR(HTTP_BTN_CONF); + ShowPage(page); +} + +void HxSaveSettings() +{ + char tmp[100]; + + WebGetArg("p2", tmp, sizeof(tmp)); + Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 10000); + + HxLogUpdates(); +} + +void HxLogUpdates() +{ + char weigth_ref_chr[10]; + char weigth_item_chr[10]; + + dtostrfd((float)Settings.weight_reference / 1000, Settings.flag2.weight_resolution, weigth_ref_chr); + dtostrfd((float)Settings.weight_item / 10000, 4, weigth_item_chr); + + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_WIFI D_JSON_WEIGHT_REF " %s, " D_JSON_WEIGHT_ITEM " %s"), + weigth_ref_chr, weigth_item_chr); + AddLog(LOG_LEVEL_INFO); +} + +#endif // USE_HX711_GUI +#endif // USE_WEBSERVER + /*********************************************************************************************\ * Interface \*********************************************************************************************/ @@ -381,6 +494,17 @@ boolean Xsns34(byte function) case FUNC_WEB_APPEND: HxShow(0); break; +#ifdef USE_HX711_GUI + case FUNC_WEB_ADD_MAIN_BUTTON: + strncat_P(mqtt_data, HTTP_BTN_MENU_MAIN_HX711, sizeof(mqtt_data)); + break; + case FUNC_WEB_ADD_BUTTON: + strncat_P(mqtt_data, HTTP_BTN_MENU_HX711, sizeof(mqtt_data)); + break; + case FUNC_WEB_ADD_HANDLER: + WebServer->on("/" WEB_HANDLE_HX711, HandleHxAction); + break; +#endif // USE_HX711_GUI #endif // USE_WEBSERVER } } diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino new file mode 100644 index 000000000..d87c6de25 --- /dev/null +++ b/sonoff/xsns_35_tx20.ino @@ -0,0 +1,224 @@ +/* + xsns_35_Tx20.ino - La Crosse Tx20 wind sensor support for Sonoff-Tasmota + + Copyright (C) 2018 Thomas Eckerstorfer and Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_TX20_WIND_SENSOR +/*********************************************************************************************\ + * La Crosse Tx20 wind sensor + * + * based on https://github.com/bunnyhu/ESP8266_TX20_wind_sensor/ + * http://blog.bubux.de/windsensor-tx20-mit-esp8266/ + * https://www.john.geek.nz/2011/07/la-crosse-tx20-anemometer-communication-protocol/ +\*********************************************************************************************/ + +#define TX20_BIT_TIME 1220 // microseconds +#define TX20_RESET_VALUES 60 // seconds + +// The Arduino standard GPIO routines are not enough, +// must use some from the Espressif SDK as well +extern "C" { +#include "gpio.h" +} + +#ifdef USE_WEBSERVER + +const char HTTP_SNS_TX20[] PROGMEM = "%s" + "{s}TX20 " D_TX20_WIND_SPEED "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_SPEED_AVG "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_SPEED_MAX "{m}%s " D_UNIT_KILOMETER_PER_HOUR "{e}" + "{s}TX20 " D_TX20_WIND_DIRECTION "{m}%s{e}"; + +#endif // USE_WEBSERVER + +const char kTx20Directions[] PROGMEM = D_TX20_NORTH "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_EAST "|" + D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST D_TX20_NORTH D_TX20_EAST "|" + D_TX20_EAST "|" + D_TX20_EAST D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_EAST "|" + D_TX20_SOUTH "|" + D_TX20_SOUTH D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST D_TX20_SOUTH D_TX20_WEST "|" + D_TX20_WEST "|" + D_TX20_WEST D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_WEST "|" + D_TX20_NORTH D_TX20_NORTH D_TX20_WEST; + +uint8_t tx20_sa = 0; +uint8_t tx20_sb = 0; +uint8_t tx20_sd = 0; +uint8_t tx20_se = 0; +uint16_t tx20_sc = 0; +uint16_t tx20_sf = 0; + +float tx20_wind_speed_kmh = 0; +float tx20_wind_speed_max = 0; +float tx20_wind_speed_avg = 0; +float tx20_wind_sum = 0; +int tx20_count = 0; +uint8_t tx20_wind_direction = 0; + +boolean tx20_available = false; + +void Tx20StartRead() +{ + /* La Crosse TX20 Anemometer datagram every 2 seconds + * 0-0 11011 0011 111010101111 0101 1100 000101010000 0-0 - Received pin data at 1200 uSec per bit + * sa sb sc sd se sf + * 00100 1100 000101010000 1010 1100 000101010000 - sa to sd inverted user data, LSB first + * sa - Start frame always 00100 + * sb - Wind direction 0 - 15 + * sc - Wind speed 0 - 511 + * sd - Checksum + * se - Wind direction 0 - 15 + * sf - Wind speed 0 - 511 + */ + + tx20_available = false; + + tx20_sa = 0; + tx20_sb = 0; + tx20_sd = 0; + tx20_se = 0; + tx20_sc = 0; + tx20_sf = 0; + + delayMicroseconds(TX20_BIT_TIME / 2); + + for (int bitcount = 41; bitcount > 0; bitcount--) { + uint8_t dpin = (digitalRead(pin[GPIO_TX20_TXD_BLACK])); + if (bitcount > 41 - 5) { + // start, inverted + tx20_sa = (tx20_sa << 1) | (dpin ^ 1); + } else if (bitcount > 41 - 5 - 4) { + // wind dir, inverted + tx20_sb = tx20_sb >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12) { + // windspeed, inverted + tx20_sc = tx20_sc >> 1 | ((dpin ^ 1) << 11); + } else if (bitcount > 41 - 5 - 4 - 12 - 4) { + // checksum, inverted + tx20_sd = tx20_sd >> 1 | ((dpin ^ 1) << 3); + } else if (bitcount > 41 - 5 - 4 - 12 - 4 - 4) { + // wind dir + tx20_se = tx20_se >> 1 | (dpin << 3); + } else { + // windspeed + tx20_sf = tx20_sf >> 1 | (dpin << 11); + } + + delayMicroseconds(TX20_BIT_TIME); + } + + uint8_t chk = (tx20_sb + (tx20_sc & 0xf) + ((tx20_sc >> 4) & 0xf) + ((tx20_sc >> 8) & 0xf)); + chk &= 0xf; + + if ((chk == tx20_sd) && (tx20_sc < 400)) { // if checksum seems to be ok and wind speed below 40 m/s + tx20_available = true; + } +/* + if ((tx20_sb == tx20_se) && (tx20_sc == tx20_sf) && (tx20_sc < 400)) { + tx20_available = true; + } +*/ + // Must clear this bit in the interrupt register, + // it gets set even when interrupts are disabled + GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << pin[GPIO_TX20_TXD_BLACK]); +} + +void Tx20Read() +{ + if (!(uptime % TX20_RESET_VALUES)) { + tx20_count = 0; + tx20_wind_sum = 0; + tx20_wind_speed_max = 0; + } + else if (tx20_available) { + tx20_wind_speed_kmh = float(tx20_sc) * 0.36; + if (tx20_wind_speed_kmh > tx20_wind_speed_max) { + tx20_wind_speed_max = tx20_wind_speed_kmh; + } + tx20_count++; + tx20_wind_sum += tx20_wind_speed_kmh; + tx20_wind_speed_avg = tx20_wind_sum / tx20_count; + tx20_wind_direction = tx20_sb; + } +} + +void Tx20Init() { + pinMode(pin[GPIO_TX20_TXD_BLACK], INPUT); + attachInterrupt(pin[GPIO_TX20_TXD_BLACK], Tx20StartRead, RISING); +} + +void Tx20Show(boolean json) +{ + char wind_speed_string[10]; + char wind_speed_max_string[10]; + char wind_speed_avg_string[10]; + char wind_direction_string[4]; + + dtostrfd(tx20_wind_speed_kmh, 2, wind_speed_string); + dtostrfd(tx20_wind_speed_max, 2, wind_speed_max_string); + dtostrfd(tx20_wind_speed_avg, 2, wind_speed_avg_string); + GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); + + if (json) { + snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), + mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#ifdef USE_WEBSERVER + } else { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TX20, mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); +#endif // USE_WEBSERVER + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +#define XSNS_35 + +boolean Xsns35(byte function) +{ + boolean result = false; + + if (pin[GPIO_TX20_TXD_BLACK] < 99) { + switch (function) { + case FUNC_INIT: + Tx20Init(); + break; + case FUNC_EVERY_SECOND: + Tx20Read(); + break; + case FUNC_JSON_APPEND: + Tx20Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_APPEND: + Tx20Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_TX20_WIND_SENSOR \ No newline at end of file diff --git a/sonoff/xsns_interface.ino b/sonoff/xsns_interface.ino index 2f0468b9e..408e68af9 100644 --- a/sonoff/xsns_interface.ino +++ b/sonoff/xsns_interface.ino @@ -178,6 +178,46 @@ boolean (* const xsns_func_ptr[])(byte) PROGMEM = { // Sensor Function Pointers &Xsns40, #endif +#ifdef XSNS_41 + &Xsns41, +#endif + +#ifdef XSNS_42 + &Xsns42, +#endif + +#ifdef XSNS_43 + &Xsns43, +#endif + +#ifdef XSNS_44 + &Xsns44, +#endif + +#ifdef XSNS_45 + &Xsns45, +#endif + +#ifdef XSNS_46 + &Xsns46, +#endif + +#ifdef XSNS_47 + &Xsns47, +#endif + +#ifdef XSNS_48 + &Xsns48, +#endif + +#ifdef XSNS_49 + &Xsns49, +#endif + +#ifdef XSNS_50 + &Xsns50, +#endif + // Optional user defined sensors in range 91 - 99 #ifdef XSNS_91 diff --git a/tools/decode-config.py b/tools/decode-config.py index c3d4af9b3..ffa78c031 100644 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -781,14 +781,7 @@ Setting_6_2_1_14.update({ 'web_refresh': ('. - You should have received a copy of the GNU General Public License - along with this program. If not, see . Requirements: - Python3 @@ -31,26 +32,28 @@ Instructions: Firmware Upgrade -> Upgrade by web server http://:5000/sonoff-minimal.bin + Usage: - ./fw-server.py -d (default: eth0) - or - ./fw-server.py -i + ./fw-server.py -d (default: eth0) + or + ./fw-server.py -i Example: - ./fw-server.py -d wlan0 - or - ./fw-server.py -i 192.168.1.10 + ./fw-server.py -d wlan0 + or + ./fw-server.py -i 192.168.1.10 """ -import io import os.path -from sys import exit -from flask import Flask, send_file from optparse import OptionParser +from sys import exit + +from flask import Flask, send_file import netifaces as ni usage = "usage: fw-server {-d | -i} arg" + parser = OptionParser(usage) parser.add_option("-d", "--dev", action="store", type="string", dest="netdev", default="eth0", help="network interface (default: eth0)") @@ -58,23 +61,30 @@ parser.add_option("-i", "--ip", action="store", type="string", dest="ip", help="IP address to bind") (options, args) = parser.parse_args() +netip = None + if options.ip is None: - try: - netip = ni.ifaddresses(options.netdev)[ni.AF_INET][0]['addr'] - except Exception as e: - print("E: network interface error - {}".format(e)) - exit(1) + try: + netip = ni.ifaddresses(options.netdev)[ni.AF_INET][0]['addr'] + except Exception as e: + print("E: network interface error - {}".format(e)) + exit(1) else: - netip = options.ip + netip = options.ip + app = Flask(__name__) + @app.route('/') def fw(filename): - if(os.path.exists("fw/" + str(filename))): - return send_file("fw/" + str(filename), attachment_filename=filename, mimetype='application/octet-stream') - else: - return("ERROR: file not found") + if os.path.exists("fw/" + str(filename)): + return send_file("fw/" + str(filename), + attachment_filename=filename, + mimetype='application/octet-stream') + + return "ERROR: file not found" + if __name__ == "__main__": try: