mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-24 06:47:17 +00:00
Merge branch 'arendst/development' into development
This commit is contained in:
commit
d93b9971a5
@ -13,7 +13,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute!
|
||||
### Development
|
||||
[](https://travis-ci.org/arendst/Sonoff-Tasmota)
|
||||
|
||||
Current version is **5.14.0a** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **5.14.0b** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/development/sonoff/_releasenotes.ino) for change information.
|
||||
|
||||
### Quick install
|
||||
Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki.
|
||||
@ -22,7 +22,7 @@ Download one of the released binaries from https://github.com/arendst/Sonoff-Tas
|
||||
If you want to compile Sonoff-Tasmota yourself keep in mind the following:
|
||||
|
||||
- Only Flash Mode **DOUT** is supported. Do not use Flash Mode DIO / QIO / QOUT as it might seem to brick your device. See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki/Theo's-Tasmota-Tips) for background information.
|
||||
- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisite](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisite).
|
||||
- Sonoff-Tasmota uses a 1M linker script WITHOUT spiffs **1M (no SPIFFS)** for optimal code space. If you compile using ESP/Arduino library 2.3.0 then download the provided new linker script to your Arduino IDE or Platformio base folder. Later version of ESP/Arduino library already contain the correct linker script. See [Wiki > Prerequisite](https://github.com/arendst/Sonoff-Tasmota/wiki/Prerequisite).
|
||||
- To make compile time changes to Sonoff-Tasmota it can use the ``user_config_override.h`` file. It assures keeping your settings when you download and compile a new version. To use ``user_config.override.h`` you will have to make a copy of the provided ``user_config.override_sample.h`` file and add your setting overrides. To enable the override file you will need to use a compile define as documented in the ``user_config_override_sample.h`` file.
|
||||
|
||||
### Version Information
|
||||
|
37
lib/ESPAsyncUDP-master/.travis.yml
Normal file
37
lib/ESPAsyncUDP-master/.travis.yml
Normal file
@ -0,0 +1,37 @@
|
||||
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
|
10
lib/ESPAsyncUDP-master/README.md
Normal file
10
lib/ESPAsyncUDP-master/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# ESPAsyncUDP
|
||||
Async UDP Library for ESP8266 Arduino [](https://travis-ci.org/me-no-dev/ESPAsyncUDP)
|
||||
|
||||
[](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
|
@ -0,0 +1,51 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#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);
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#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?");
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#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?");
|
||||
}
|
33
lib/ESPAsyncUDP-master/keywords.txt
Normal file
33
lib/ESPAsyncUDP-master/keywords.txt
Normal file
@ -0,0 +1,33 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Ultrasound
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
AsyncUDP KEYWORD1
|
||||
AsyncUDPPacket 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
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
17
lib/ESPAsyncUDP-master/library.json
Normal file
17
lib/ESPAsyncUDP-master/library.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"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"
|
||||
}
|
9
lib/ESPAsyncUDP-master/library.properties
Normal file
9
lib/ESPAsyncUDP-master/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
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=*
|
427
lib/ESPAsyncUDP-master/src/AsyncUDP.cpp
Normal file
427
lib/ESPAsyncUDP-master/src/AsyncUDP.cpp
Normal file
@ -0,0 +1,427 @@
|
||||
#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<ip_hdr*>(data - UDP_HLEN - IP_HLEN);
|
||||
ip_addr_t daddr;
|
||||
daddr.addr = iphdr->dest.addr;
|
||||
|
||||
udp_hdr* udphdr = reinterpret_cast<udp_hdr*>(((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<AsyncUDP*>(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<uint8_t*>(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());
|
||||
}
|
130
lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h
Normal file
130
lib/ESPAsyncUDP-master/src/ESPAsyncUDP.h
Normal file
@ -0,0 +1,130 @@
|
||||
#ifndef ESPASYNCUDP_H
|
||||
#define ESPASYNCUDP_H
|
||||
|
||||
#include "IPAddress.h"
|
||||
#include "Print.h"
|
||||
#include <functional>
|
||||
#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<void(AsyncUDPPacket& packet)> AuPacketHandlerFunction;
|
||||
typedef std::function<void(void * arg, AsyncUDPPacket& packet)> 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
|
23
lib/ESPAsyncUDP-master/travis/common.sh
Normal file
23
lib/ESPAsyncUDP-master/travis/common.sh
Normal file
@ -0,0 +1,23 @@
|
||||
#!/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
|
||||
}
|
@ -69,4 +69,4 @@ typedef struct __color
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
} color_t;
|
||||
} color_t;
|
@ -33,10 +33,11 @@ void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t da
|
||||
cemi_msg->additional_info_len = 0;
|
||||
cemi_service_t *cemi_data = &cemi_msg->data.service_information;
|
||||
cemi_data->control_1.bits.confirm = 0;
|
||||
cemi_data->control_1.bits.ack = 0;
|
||||
//cemi_data->control_1.bits.ack = 1;
|
||||
cemi_data->control_1.bits.ack = 0; // ask for ACK? 0-no 1-yes
|
||||
cemi_data->control_1.bits.priority = B11;
|
||||
cemi_data->control_1.bits.system_broadcast = 0x01;
|
||||
cemi_data->control_1.bits.repeat = 0x01;
|
||||
cemi_data->control_1.bits.repeat = 0x01; // 0 = repeated telegram, 1 = not repeated telegram
|
||||
cemi_data->control_1.bits.reserved = 0;
|
||||
cemi_data->control_1.bits.frame_type = 0x01;
|
||||
cemi_data->control_2.bits.extended_frame_format = 0x00;
|
||||
@ -47,10 +48,13 @@ void ESPKNXIP::send(address_t const &receiver, knx_command_type_t ct, uint8_t da
|
||||
//cemi_data->destination.bytes.high = (area << 3) | line;
|
||||
//cemi_data->destination.bytes.low = member;
|
||||
cemi_data->data_len = data_len;
|
||||
cemi_data->pci.apci = (ct & 0x0C) >> 2;
|
||||
cemi_data->pci.tpci_seq_number = 0x00; // ???
|
||||
cemi_data->pci.tpci_comm_type = KNX_COT_UDP; // ???
|
||||
cemi_data->pci.apci = (ct & 0x0C) >> 2;
|
||||
//cemi_data->pci.apci = KNX_COT_NCD_ACK;
|
||||
cemi_data->pci.tpci_seq_number = 0x00;
|
||||
cemi_data->pci.tpci_comm_type = KNX_COT_UDP; // Type of communication: DATA PACKAGE or CONTROL DATA
|
||||
//cemi_data->pci.tpci_comm_type = KNX_COT_NCD; // Type of communication: DATA PACKAGE or CONTROL DATA
|
||||
memcpy(cemi_data->data, data, data_len);
|
||||
//cemi_data->data[0] = (cemi_data->data[0] & 0x3F) | ((KNX_COT_NCD_ACK & 0x03) << 6);
|
||||
cemi_data->data[0] = (cemi_data->data[0] & 0x3F) | ((ct & 0x03) << 6);
|
||||
|
||||
#if SEND_CHECKSUM
|
||||
@ -73,9 +77,13 @@ 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)
|
@ -96,7 +96,12 @@ void ESPKNXIP::__start()
|
||||
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()
|
||||
@ -511,7 +516,9 @@ 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();
|
||||
@ -523,9 +530,16 @@ 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)
|
||||
{
|
||||
return;
|
||||
@ -534,19 +548,31 @@ 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"));
|
||||
DEBUG_PRINT(buf[i], 16);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
DEBUG_PRINTLN(F(""));
|
||||
|
||||
knx_ip_pkt_t *knx_pkt = (knx_ip_pkt_t *)buf;
|
@ -7,6 +7,14 @@
|
||||
#ifndef ESP_KNX_IP_H
|
||||
#define ESP_KNX_IP_H
|
||||
|
||||
//#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) )
|
||||
// check line 57 on esp-knx-ip.h file is uncommented: #include <ESPAsyncUDP.h>
|
||||
// Comment out that line when using UDP WIFI to avoid compiling issues on PlatformIO with ESP8266 Library Version 2.3.0
|
||||
|
||||
/**
|
||||
* CONFIG
|
||||
* All MAX_ values must not exceed 255 (1 byte, except MAC_CONFIG_SPACE which can go up to 2 bytes, so 0xffff in theory) and must not be negative!
|
||||
@ -25,8 +33,8 @@
|
||||
#define ALLOW_MULTIPLE_CALLBACKS_PER_ADDRESS 1 // [Default 0] Set to 1 to always test all assigned callbacks. This allows for multiple callbacks being assigned to the same address. If disabled, only the first assigned will be called.
|
||||
|
||||
// Webserver related
|
||||
#define USE_BOOTSTRAP 1 // [Default 1] Set to 1 to enable use of bootstrap CSS for nicer webconfig. CSS is loaded from bootstrapcdn.com. Set to 0 to disable
|
||||
#define ROOT_PREFIX "" // [Default ""] This gets prepended to all webserver paths, default is empty string "". Set this to "/knx" if you want the config to be available on http://<ip>/knx
|
||||
#define USE_BOOTSTRAP 0 // [Default 1] Set to 1 to enable use of bootstrap CSS for nicer webconfig. CSS is loaded from bootstrapcdn.com. Set to 0 to disable
|
||||
#define ROOT_PREFIX "/knx" // [Default ""] This gets prepended to all webserver paths, default is empty string "". Set this to "/knx" if you want the config to be available on http://<ip>/knx
|
||||
#define DISABLE_EEPROM_BUTTONS 1 // [Default 0] Set to 1 to disable the EEPROM buttons in the web ui.
|
||||
#define DISABLE_REBOOT_BUTTON 1 // [Default 0] Set to 1 to disable the reboot button in the web ui.
|
||||
#define DISABLE_RESTORE_BUTTON 1 // [Default 0] Set to 1 to disable the "restore defaults" button in the web ui.
|
||||
@ -45,7 +53,13 @@
|
||||
#include "Arduino.h"
|
||||
#include <EEPROM.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
|
||||
#ifdef USE_ASYNC_UDP
|
||||
//#include <ESPAsyncUDP.h>
|
||||
#else
|
||||
#include <WiFiUdp.h>
|
||||
#endif
|
||||
|
||||
#include <ESP8266WebServer.h>
|
||||
|
||||
#include "DPT.h"
|
||||
@ -157,6 +171,14 @@ typedef enum __knx_communication_type {
|
||||
KNX_COT_NCD = 0x03, // Numbered Control Data
|
||||
} knx_communication_type_t;
|
||||
|
||||
/**
|
||||
* acpi for KNX_COT_NCD
|
||||
*/
|
||||
typedef enum __knx_cot_ncd_ack_type {
|
||||
KNX_COT_NCD_ACK = 0x10, // Inform positively reception of the Previouly received telegram
|
||||
KNX_COT_NCD_NACK = 0x11, // Inform negatively reception of the Previouly received telegram
|
||||
} knx_cot_ncd_ack_type_t;
|
||||
|
||||
/**
|
||||
* KNX/IP header
|
||||
*/
|
||||
@ -217,7 +239,7 @@ typedef struct __cemi_service
|
||||
uint8_t ack:1; // 0 = no ack, 1 = ack
|
||||
uint8_t priority:2; // 0 = system, 1 = high, 2 = urgent/alarm, 3 = normal
|
||||
uint8_t system_broadcast:1; // 0 = system broadcast, 1 = broadcast
|
||||
uint8_t repeat:1; // 0 = repeat on error, 1 = do not repeat
|
||||
uint8_t repeat:1; // 0 = repeated telegram, 1 = not repeated telegram
|
||||
uint8_t reserved:1; // always zero
|
||||
uint8_t frame_type:1; // 0 = extended, 1 = standard
|
||||
} bits;
|
||||
@ -509,7 +531,12 @@ class ESPKNXIP {
|
||||
|
||||
private:
|
||||
void __start();
|
||||
|
||||
#ifdef USE_ASYNC_UDP
|
||||
void __loop_knx(AsyncUDPPacket &packet);
|
||||
#else
|
||||
void __loop_knx();
|
||||
#endif
|
||||
|
||||
// Webserver functions
|
||||
void __loop_webserver();
|
||||
@ -544,7 +571,12 @@ 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;
|
@ -1,5 +1,5 @@
|
||||
name=ESP KNX IP Library
|
||||
version=0.5
|
||||
version=0.5.1
|
||||
author=Nico Weichbrodt <envy>
|
||||
maintainer=Nico Weichbrodt <envy>
|
||||
sentence=ESP8266 library for KNX/IP communication.
|
@ -33,11 +33,15 @@ env_default = sonoff
|
||||
;env_default = sonoff-TW
|
||||
|
||||
[common] ; ************************************************************
|
||||
; *** Esp8266 core for Arduino version
|
||||
platform = espressif8266@1.5.0 ; v2.3.0
|
||||
;platform = espressif8266@1.6.0 ; v2.4.0
|
||||
;platform = espressif8266@1.7.0 ; v2.4.1
|
||||
; *** Esp8266 core for Arduino version 2.3.0
|
||||
platform = espressif8266@1.5.0
|
||||
; *** Esp8266 core for Arduino version 2.4.0
|
||||
;platform = espressif8266@1.6.0
|
||||
; *** Esp8266 core for Arduino version 2.4.1
|
||||
;platform = espressif8266@1.7.0
|
||||
; *** Esp8266 core for Arduino version latest beta
|
||||
;platform = https://github.com/platformio/platform-espressif8266.git#feature/stage
|
||||
; *** Esp8266 core for Arduino current version
|
||||
;platform = espressif8266
|
||||
|
||||
framework = arduino
|
||||
@ -50,20 +54,19 @@ build_unflags = -Wall
|
||||
build_flags =
|
||||
-Wl,-Tesp8266.flash.1m0.ld
|
||||
-DVTABLES_IN_FLASH
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
-DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
; -DUSE_CONFIG_OVERRIDE
|
||||
|
||||
; *** Fix Esp/Arduino core 2.4.x induced Tasmota unused floating point includes
|
||||
extra_scripts = pio/strip-floats.py
|
||||
|
||||
; *** Serial Monitor options
|
||||
monitor_baud = 115200
|
||||
monitor_speed = 115200
|
||||
|
||||
; *** Upload Serial reset method for Wemos and NodeMCU
|
||||
;upload_speed = 115200
|
||||
upload_speed = 512000
|
||||
upload_resetmethod = nodemcu
|
||||
upload_port = COM5
|
||||
; *** Fix Esp/Arduino core 2.4.x induced Tasmota unused floating point includes
|
||||
extra_scripts = pio/strip-floats.py
|
||||
|
||||
; *** Upload file to OTA server using SCP
|
||||
;upload_port = user@host:/path
|
||||
@ -82,7 +85,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags}
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
upload_port = ${common.upload_port}
|
||||
@ -95,7 +98,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DBE_MINIMAL
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -107,7 +110,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_CLASSIC
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -119,7 +122,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_KNX_NO_EMULATION
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -131,7 +134,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_ALL_SENSORS
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -143,7 +146,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=bg-BG
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -155,7 +158,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-BR
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -167,7 +170,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-CN
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -179,7 +182,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=cs-CZ
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -191,7 +194,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=de-DE
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -203,7 +206,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=es-AR
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -215,7 +218,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=fr-FR
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -227,7 +230,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=el-GR
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -239,7 +242,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=hu-HU
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -251,7 +254,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=it-IT
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -263,7 +266,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=nl-NL
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -275,7 +278,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=pl-PL
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -287,7 +290,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=pt-PT
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -299,7 +302,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=ru-RU
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
@ -311,7 +314,7 @@ board = ${common.board}
|
||||
board_flash_mode = ${common.board_flash_mode}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DMY_LANGUAGE=zh-TW
|
||||
monitor_baud = ${common.monitor_baud}
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_speed = ${common.upload_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
extra_scripts = ${common.extra_scripts}
|
||||
|
@ -1,5 +1,24 @@
|
||||
/* 5.14.0a
|
||||
* Updated to latest release
|
||||
/* 5.14.0b
|
||||
* Add two rule sets of 511 characters using commands rule1, rule2 and rule3
|
||||
* Add rule support for IrReceive and RfReceive (#2758)
|
||||
*
|
||||
* 5.14.0a
|
||||
* Add feature information to Status 4
|
||||
* Add tools folder with python script decode-status.py for decoding some status fields like SetOption and Features
|
||||
* Add Eastron SDM630 energy meter by Gennaro Tortone (#2735)
|
||||
* Add KNX communication enhancement by Adrian Scillato (#2742)
|
||||
* Add KNX energy data by Adrian Scillato (#2750)
|
||||
* Add python script fw-server.py in tools folder to create a simple OTA server by Gennaro Tortone (#2759)
|
||||
* Add rules %mem1% to %mem5% variable names storing data in flash (#2780)
|
||||
* Add rules test on %varx% or %memx% (#2780)
|
||||
* Add optional token %id% substituting the unique MAC address to fulltopic by Michael Graf (#2794)
|
||||
* Fix display selection of un-available GPIO options in Module Configuration webpage (#2718)
|
||||
* Fix timer re-trigger within one minute after restart (#2744)
|
||||
* Fix IRSend not accepting data value of 0 by David Conran (#2751)
|
||||
* Fix vars on rules by Adrian Scillato (#2769)
|
||||
* Fix bug in KNX menu by Adrian Scillato (#2770)
|
||||
* Fix anomalies in rules (#2778)
|
||||
* Fix HUE bridge V1 software version by Heiko Krupp (#2788)
|
||||
*
|
||||
* 5.14.0 20180515
|
||||
* Update language files
|
||||
@ -14,13 +33,13 @@
|
||||
* Fix KNX config error (#2628)
|
||||
* Fix sensor MHZ-19 vanishing data over time (#2659)
|
||||
* Fix KNX reconnection issue (#2679)
|
||||
* Fix DST and STD time for Southern Hemisphere (#2684, #2714)
|
||||
* Fix DST and STD time for Southern Hemisphere by Adrian Scillato (#2684, #2714)
|
||||
* Add Portuguese in Brazil language file
|
||||
* Add SetOption26 to enforce use of indexes even when only one relay is present (#1055)
|
||||
* Add support for sensor SI1145 UV Index / IR / Visible light (#2496)
|
||||
* Add rule state test for On/Off in addition to 0/1 (#2613)
|
||||
* Add hardware serial option to MHZ-19 sensor (#2659)
|
||||
* Add Eastron SDM120 energy meter (#2694)
|
||||
* Add Eastron SDM120 energy meter by Gennaro Tortone (#2694)
|
||||
* Add user entry DST/STD using commands TimeStd and TimeDst (See wiki for parameter syntax) (#2721)
|
||||
*
|
||||
* 5.13.1 20180501
|
||||
|
@ -57,6 +57,7 @@
|
||||
#define D_JSON_EVERY "Every"
|
||||
#define D_JSON_FAILED "Failed"
|
||||
#define D_JSON_FALLBACKTOPIC "FallbackTopic"
|
||||
#define D_JSON_FEATURES "Features"
|
||||
#define D_JSON_FLASHMODE "FlashMode"
|
||||
#define D_JSON_FLASHSIZE "FlashSize"
|
||||
#define D_JSON_FREEMEMORY "Free"
|
||||
@ -391,6 +392,9 @@
|
||||
#define INCLUDE_FILE(x) QUOTEME(language/x.h)
|
||||
#include INCLUDE_FILE(MY_LANGUAGE)
|
||||
#endif
|
||||
#ifndef LANGUAGE_LCID
|
||||
#define LANGUAGE_LCID 2057 // en-GB
|
||||
#endif
|
||||
|
||||
// Common
|
||||
enum UnitNames {
|
||||
|
@ -28,11 +28,12 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v5.13.1c
|
||||
* Updated until v5.14.0a
|
||||
\*********************************************************************/
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1026
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "bg"
|
||||
|
||||
@ -109,7 +110,7 @@
|
||||
#define D_LWT "LWT"
|
||||
#define D_MODULE "Модул"
|
||||
#define D_MQTT "MQTT"
|
||||
#define D_MULTI_PRESS "многократно натискане"
|
||||
#define D_MULTI_PRESS "множествено натискане"
|
||||
#define D_NOISE "Шум"
|
||||
#define D_NONE "Няма"
|
||||
#define D_OFF "Изкл."
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Друго"
|
||||
#define D_SENT_TO "изпратен до"
|
||||
#define D_KNX_WARNING "Груповият адрес ( 0 / 0 / 0 ) е резервиран и не може да бъде използван."
|
||||
#define D_KNX_ENHANCEMENT "Подобрена комуникация"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Използвана енергия днес"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1029
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "cs"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Jiné"
|
||||
#define D_SENT_TO "pošli"
|
||||
#define D_KNX_WARNING "Skupinová adresa ( 0 / 0 / 0 ) je rezervována a nemůže být použita."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Spotřeba Dnes"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1031
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "de"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Energie heute"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1032
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "el"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Αλλο"
|
||||
#define D_SENT_TO "αποστολή σε"
|
||||
#define D_KNX_WARNING "Η Ομάδα Διευθύνσεων ( 0 / 0 / 0 ) είναι δεσμευμένη και δεν μπορεί να χρησιμοποιηθεί."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Energy Σήμερα"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -28,11 +28,12 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v5.12.0n
|
||||
* Updated until v5.14.0a
|
||||
\*********************************************************************/
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 2057
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "en"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Energy Today"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -28,11 +28,12 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v5.13.1c
|
||||
* Updated until v5.14.0a
|
||||
\*********************************************************************/
|
||||
|
||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 11274
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "es"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Otro"
|
||||
#define D_SENT_TO "enviada a"
|
||||
#define D_KNX_WARNING "La dirección de grupo ( 0 / 0 / 0 ) está reservada y no puede ser utilizada."
|
||||
#define D_KNX_ENHANCEMENT "Mejora de Comunicación"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Energía Hoy"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -28,11 +28,12 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v5.12.0m
|
||||
* Updated until v5.14.0a
|
||||
\*********************************************************************/
|
||||
|
||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1036
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "fr"
|
||||
|
||||
@ -91,7 +92,7 @@
|
||||
#define D_FALSE "Faux"
|
||||
#define D_FILE "Fichier"
|
||||
#define D_FREE_MEMORY "Mémoire libre"
|
||||
#define D_FREQUENCY "Frequency"
|
||||
#define D_FREQUENCY "Fréquence"
|
||||
#define D_GAS "Gaz"
|
||||
#define D_GATEWAY "Passerelle"
|
||||
#define D_GROUP "Groupe"
|
||||
@ -102,7 +103,7 @@
|
||||
#define D_IMMEDIATE "immédiat" // Button immediate
|
||||
#define D_INDEX "Index"
|
||||
#define D_INFO "Info"
|
||||
#define D_INFRARED "Infrared"
|
||||
#define D_INFRARED "Infra-rouge"
|
||||
#define D_INITIALIZED "Initialisé"
|
||||
#define D_IP_ADDRESS "Adresse IP"
|
||||
#define D_LIGHT "Lumière"
|
||||
@ -121,9 +122,9 @@
|
||||
#define D_PORT "Port"
|
||||
#define D_POWER_FACTOR "Facteur de puissance"
|
||||
#define D_POWERUSAGE "Puissance"
|
||||
#define D_POWERUSAGE_ACTIVE "Active Power"
|
||||
#define D_POWERUSAGE_APPARENT "Apparent Power"
|
||||
#define D_POWERUSAGE_REACTIVE "Reactive Power"
|
||||
#define D_POWERUSAGE_ACTIVE "Puissance Active"
|
||||
#define D_POWERUSAGE_APPARENT "Puissance Apparente"
|
||||
#define D_POWERUSAGE_REACTIVE "Puissance Réactive"
|
||||
#define D_PRESSURE "Pression"
|
||||
#define D_PRESSUREATSEALEVEL "PressionMer"
|
||||
#define D_PROGRAM_FLASH_SIZE "Taille Flash Programme"
|
||||
@ -159,7 +160,7 @@
|
||||
#define D_UPTIME "Durée d'activité"
|
||||
#define D_USER "Utilisateur"
|
||||
#define D_UTC_TIME "UTC"
|
||||
#define D_UV_INDEX "Index UV"
|
||||
#define D_UV_INDEX "Indice UV"
|
||||
#define D_UV_LEVEL "Niveau UV"
|
||||
#define D_VERSION "Version"
|
||||
#define D_VOLTAGE "Tension"
|
||||
@ -220,7 +221,7 @@
|
||||
#define D_DEVICE_WILL_RESTART "Le module va redémarrer dans quelques secondes"
|
||||
#define D_BUTTON_TOGGLE "on/off"
|
||||
#define D_CONFIGURATION "Configuration"
|
||||
#define D_INFORMATION "Information"
|
||||
#define D_INFORMATION "Informations"
|
||||
#define D_FIRMWARE_UPGRADE "Mise à jour du Firmware"
|
||||
#define D_CONSOLE "Console"
|
||||
#define D_CONFIRM_RESTART "Confirmer redémarrage"
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Autre"
|
||||
#define D_SENT_TO "envoyé à"
|
||||
#define D_KNX_WARNING "L'Adresse de Groupe ( 0 / 0 / 0 ) est réservée et ne peut être utilisée."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xsns_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Énergie aujourd'hui"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1038
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "hu"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Mai Energia"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -28,11 +28,12 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v5.13.1a
|
||||
* Updated until v5.14.0
|
||||
\*********************************************************************/
|
||||
|
||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1040
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "it"
|
||||
|
||||
@ -75,7 +76,7 @@
|
||||
#define D_DARKLIGHT "Scuro"
|
||||
#define D_DEBUG "Debug"
|
||||
#define D_DISABLED "Disabilitato"
|
||||
#define D_DISTANCE "Distance"
|
||||
#define D_DISTANCE "Distanza"
|
||||
#define D_DNS_SERVER "DNS Server"
|
||||
#define D_DONE "Fatto"
|
||||
#define D_DST_TIME "DST"
|
||||
@ -145,14 +146,14 @@
|
||||
#define D_SUBNET_MASK "Maschera sottorete"
|
||||
#define D_SUBSCRIBE_TO "Sottoscrivi a"
|
||||
#define D_SUCCESSFUL "Riuscito"
|
||||
#define D_SUNRISE "Sunrise"
|
||||
#define D_SUNSET "Sunset"
|
||||
#define D_SUNRISE "Alba"
|
||||
#define D_SUNSET "Tramonto"
|
||||
#define D_TEMPERATURE "Temperatura"
|
||||
#define D_TO "a"
|
||||
#define D_TOGGLE "Toggle"
|
||||
#define D_TOPIC "Topic"
|
||||
#define D_TRANSMIT "Trasmesso"
|
||||
#define D_TRUE "True"
|
||||
#define D_TRUE "Vero"
|
||||
#define D_TVOC "TVOC"
|
||||
#define D_UPGRADE "aggiornamento"
|
||||
#define D_UPLOAD "Invio"
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Altro"
|
||||
#define D_SENT_TO "invia a"
|
||||
#define D_KNX_WARNING "L'indirizzo del gruppo ( 0 / 0 / 0 ) è riservato e non può essere usato."
|
||||
#define D_KNX_ENHANCEMENT "Miglioramento Comunicazione"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Energia Oggi"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -28,11 +28,12 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v5.13.1c
|
||||
* Updated until v5.14.0a
|
||||
\*********************************************************************/
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1043
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "nl"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Overige"
|
||||
#define D_SENT_TO "verzend naar"
|
||||
#define D_KNX_WARNING "Groep adres (0/0/0) is gereserveerd en mag niet worden gebruikt."
|
||||
#define D_KNX_ENHANCEMENT "Verbeter verbinding"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Verbruik vandaag"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1045
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "pl"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Energia Dzisiaj"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1046
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "pt"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Outros"
|
||||
#define D_SENT_TO "Enviar para"
|
||||
#define D_KNX_WARNING "O endereço ( 0 / 0 / 0 ) é reservado e não pode ser usado."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Consumo energético de hoje"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 2070
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "pt"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Consumo energético de hoje"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1049
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "ru"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "Энергия Сегодня"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 2052
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "zh"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "今日用电量"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
//#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
||||
#define LANGUAGE_LCID 1028
|
||||
// HTML (ISO 639-1) Language Code
|
||||
#define D_HTML_LANGUAGE "zh"
|
||||
|
||||
@ -400,6 +401,7 @@
|
||||
#define D_KNX_COMMAND_OTHER "Other"
|
||||
#define D_SENT_TO "sent to"
|
||||
#define D_KNX_WARNING "The group address ( 0 / 0 / 0 ) is reserved and can not be used."
|
||||
#define D_KNX_ENHANCEMENT "Communication Enhancement"
|
||||
|
||||
// xdrv_03_energy.ino
|
||||
#define D_ENERGY_TODAY "今日用電量"
|
||||
@ -461,6 +463,8 @@
|
||||
#define D_SENSOR_SR04_ECHO "SR04 Ech"
|
||||
#define D_SENSOR_SDM120_TX "SDM120 Tx"
|
||||
#define D_SENSOR_SDM120_RX "SDM120 Rx"
|
||||
#define D_SENSOR_SDM630_TX "SDM630 Tx"
|
||||
#define D_SENSOR_SDM630_RX "SDM630 Rx"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安"
|
||||
|
@ -48,11 +48,11 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
||||
uint32_t not_power_linked : 1; // bit 20 (v5.11.1f)
|
||||
uint32_t no_power_on_check : 1; // bit 21 (v5.11.1i)
|
||||
uint32_t mqtt_serial : 1; // bit 22 (v5.12.0f)
|
||||
uint32_t rules_enabled : 1; // bit 23 (v5.12.0j)
|
||||
uint32_t rules_once : 1; // bit 24 (v5.12.0k)
|
||||
uint32_t rules_enabled : 1; // bit 23 (v5.12.0j) - free since v5.14.0b
|
||||
uint32_t rules_once : 1; // bit 24 (v5.12.0k) - free since v5.14.0b
|
||||
uint32_t knx_enabled : 1; // bit 25 (v5.12.0l) KNX
|
||||
uint32_t device_index_enable : 1; // bit 26 (v5.13.1a)
|
||||
uint32_t spare27 : 1;
|
||||
uint32_t knx_enable_enhancement : 1; // bit 27 (v5.14.0a) KNX
|
||||
uint32_t spare28 : 1;
|
||||
uint32_t spare29 : 1;
|
||||
uint32_t spare30 : 1;
|
||||
@ -232,9 +232,8 @@ struct SYSCFG {
|
||||
uint8_t light_color[5]; // 498
|
||||
uint8_t light_correction; // 49D
|
||||
uint8_t light_dimmer; // 49E
|
||||
|
||||
byte free_49F[2]; // 49F
|
||||
|
||||
uint8_t rule_enabled; // 49F
|
||||
uint8_t rule_once; // 4A0
|
||||
uint8_t light_fade; // 4A1
|
||||
uint8_t light_speed; // 4A2
|
||||
uint8_t light_scheme; // 4A3
|
||||
@ -271,11 +270,14 @@ struct SYSCFG {
|
||||
byte knx_GA_param[MAX_KNX_GA]; // 6E2 Type of Input (relay changed, button pressed, sensor read <-teleperiod)
|
||||
byte knx_CB_param[MAX_KNX_CB]; // 6EC Type of Output (set relay, toggle relay, reply sensor value)
|
||||
|
||||
byte free_6f6[266]; // 6F6
|
||||
byte free_6f6[216]; // 6F6
|
||||
|
||||
char rules[MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m
|
||||
char mems[RULES_MAX_MEMS][10]; // 7CE
|
||||
// 800 Full - no more free locations
|
||||
|
||||
// A00 - FFF free locations
|
||||
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
|
||||
|
||||
// E00 - FFF free locations
|
||||
} Settings;
|
||||
|
||||
struct RTCMEM {
|
||||
@ -286,6 +288,7 @@ struct RTCMEM {
|
||||
unsigned long energy_kWhtotal; // 008
|
||||
unsigned long pulse_counter[MAX_COUNTERS]; // 00C
|
||||
power_t power; // 01C
|
||||
// 020 next free location
|
||||
} RtcSettings;
|
||||
|
||||
struct TIME_T {
|
||||
|
@ -143,6 +143,7 @@ extern "C" uint32_t _SPIFFS_end;
|
||||
|
||||
uint32_t settings_hash = 0;
|
||||
uint32_t settings_location = SETTINGS_LOCATION;
|
||||
uint8_t *settings_buffer = NULL;
|
||||
|
||||
/********************************************************************************************/
|
||||
/*
|
||||
@ -167,6 +168,24 @@ void SetFlashModeDout()
|
||||
delete[] _buffer;
|
||||
}
|
||||
|
||||
void SettingsBufferFree()
|
||||
{
|
||||
if (settings_buffer != NULL) {
|
||||
free(settings_buffer);
|
||||
settings_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool SettingsBufferAlloc()
|
||||
{
|
||||
SettingsBufferFree();
|
||||
if (!(settings_buffer = (uint8_t *)malloc(sizeof(Settings)))) {
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_UPLOAD_ERR_2)); // Not enough (memory) space
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t GetSettingsHash()
|
||||
{
|
||||
uint32_t hash = 0;
|
||||
@ -870,7 +889,7 @@ void SettingsDelta()
|
||||
Settings.longitude = (int)((double)LONGITUDE * 1000000);
|
||||
}
|
||||
if (Settings.version < 0x050C000B) {
|
||||
memset(&Settings.rules, 0x00, sizeof(Settings.rules));
|
||||
Settings.rules[0][0] = '\0';
|
||||
}
|
||||
if (Settings.version < 0x050C000D) {
|
||||
memmove(Settings.rules, Settings.rules -256, sizeof(Settings.rules)); // move rules up by 256 bytes
|
||||
@ -887,6 +906,13 @@ void SettingsDelta()
|
||||
if (Settings.version < 0x050D0103) {
|
||||
SettingsDefaultSet_5_13_1c();
|
||||
}
|
||||
if (Settings.version < 0x050E0002) {
|
||||
for (byte i = 1; i < MAX_RULE_SETS; i++) {
|
||||
Settings.rules[i][0] = '\0';
|
||||
}
|
||||
Settings.rule_enabled = Settings.flag.rules_enabled;
|
||||
Settings.rule_once = Settings.flag.rules_once;
|
||||
}
|
||||
|
||||
Settings.version = VERSION;
|
||||
SettingsSave(1);
|
||||
|
@ -50,10 +50,13 @@ typedef unsigned long power_t; // Power (Relay) type
|
||||
#define MAX_DOMOTICZ_SNS_IDX 12 // Max number of Domoticz sensors indices
|
||||
#define MAX_KNX_GA 10 // Max number of KNX Group Addresses to read that can be set
|
||||
#define MAX_KNX_CB 10 // Max number of KNX Group Addresses to write that can be set
|
||||
#define RULES_MAX_MEMS 5 // Max number of saved vars
|
||||
#define MAX_RULE_SETS 3 // Max number of rule sets of size 512 characters
|
||||
#define MAX_RULE_SIZE 512 // Max number of characters in rules
|
||||
|
||||
#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x]
|
||||
#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
|
||||
#define MQTT_TOKEN_ID "%id%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
|
||||
|
||||
#define WIFI_HOSTNAME "%s-%04d" // Expands to <MQTT_TOPIC>-<last 4 decimal chars of MAC address>
|
||||
|
||||
@ -86,7 +89,7 @@ typedef unsigned long power_t; // Power (Relay) type
|
||||
#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog
|
||||
#define OTA_ATTEMPTS 5 // Number of times to try fetching the new firmware
|
||||
|
||||
#define INPUT_BUFFER_SIZE 512 // Max number of characters in (serial and http) command buffer
|
||||
#define INPUT_BUFFER_SIZE 520 // Max number of characters in (serial and http) command buffer
|
||||
#define CMDSZ 24 // Max number of characters in command
|
||||
#define TOPSZ 100 // Max number of characters in topic string
|
||||
#define LOGSZ 512 // Max number of characters in log
|
||||
@ -112,6 +115,9 @@ typedef unsigned long power_t; // Power (Relay) type
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
*/
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
//enum ws2812NeopixelbusFeature { NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_3LED, NEO_RGBW, NEO_GRBW }; // Doesn't work
|
||||
#define NEO_RGB 0 // Neopixel RGB leds
|
||||
#define NEO_GRB 1 // Neopixel GRB leds
|
||||
@ -131,6 +137,18 @@ typedef unsigned long power_t; // Power (Relay) type
|
||||
#define DAWN_NAUTIC -12.0
|
||||
#define DAWN_ASTRONOMIC -18.0
|
||||
|
||||
// Sensor definition for KNX Driver
|
||||
#define KNX_TEMPERATURE 17
|
||||
#define KNX_HUMIDITY 18
|
||||
#define KNX_ENERGY_VOLTAGE 19
|
||||
#define KNX_ENERGY_CURRENT 20
|
||||
#define KNX_ENERGY_POWER 21
|
||||
#define KNX_ENERGY_POWERFACTOR 22
|
||||
#define KNX_ENERGY_DAILY 23
|
||||
#define KNX_ENERGY_START 24
|
||||
#define KNX_ENERGY_TOTAL 25
|
||||
#define KNX_MAX_device_param 25
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Enumeration
|
||||
\*********************************************************************************************/
|
||||
@ -170,7 +188,7 @@ enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_R
|
||||
enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
|
||||
|
||||
enum XsnsFunctions {FUNC_INIT, FUNC_LOOP, FUNC_EVERY_50_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_COMMAND, FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA, FUNC_SET_POWER, FUNC_SHOW_SENSOR, FUNC_RULES_PROCESS};
|
||||
|
||||
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
|
||||
====================================================*/
|
||||
|
||||
#define VERSION 0x050E0001 // 5.14.0a
|
||||
#define VERSION 0x050E0002 // 5.14.0b
|
||||
|
||||
// Location specific includes
|
||||
#include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
@ -97,6 +97,10 @@ const char kTasmotaCommands[] PROGMEM =
|
||||
D_CMND_I2CSCAN "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALDELIMITER;
|
||||
|
||||
// Global variables
|
||||
unsigned long feature_drv1; // Compiled driver feature map
|
||||
unsigned long feature_drv2; // Compiled driver feature map
|
||||
unsigned long feature_sns1; // Compiled sensor feature map
|
||||
unsigned long feature_sns2; // Compiled sensor feature map
|
||||
int baudrate = APP_BAUDRATE; // Serial interface baud rate
|
||||
SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit
|
||||
byte serial_in_byte; // Received byte
|
||||
@ -176,7 +180,6 @@ uint8_t spi_flg = 0; // SPI configured
|
||||
uint8_t light_type = 0; // Light types
|
||||
bool pwm_present = false; // Any PWM channel configured with SetOption15 0
|
||||
boolean mdns_begun = false;
|
||||
unsigned long features = 0UL;
|
||||
uint8_t ntp_force_sync = 0; // Force NTP sync
|
||||
|
||||
char my_version[33]; // Composed version string
|
||||
@ -266,6 +269,9 @@ void GetTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic)
|
||||
}
|
||||
fulltopic.replace(F(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]);
|
||||
fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic);
|
||||
String token_id = WiFi.macAddress();
|
||||
token_id.replace(":", "");
|
||||
fulltopic.replace(F(MQTT_TOKEN_ID), token_id);
|
||||
}
|
||||
fulltopic.replace(F("#"), "");
|
||||
fulltopic.replace(F("//"), "/");
|
||||
@ -1171,11 +1177,9 @@ boolean SendKey(byte key, byte device, byte state)
|
||||
MqttPublishDirect(stopic, (key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain);
|
||||
#endif // USE_DOMOTICZ
|
||||
result = true;
|
||||
#ifdef USE_RULES
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state);
|
||||
result = RulesProcess();
|
||||
#endif // USE_RULES
|
||||
result = XdrvRulesProcess();
|
||||
}
|
||||
#ifdef USE_KNX
|
||||
KnxSendButtonPower(key, device, state);
|
||||
@ -1294,11 +1298,11 @@ void ExecuteCommand(char *cmnd)
|
||||
|
||||
void PublishStatus(uint8_t payload)
|
||||
{
|
||||
uint8_t option = 1;
|
||||
uint8_t option = STAT;
|
||||
char stemp[MAX_FRIENDLYNAMES * (sizeof(Settings.friendlyname[0]) +4)];
|
||||
|
||||
// Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX
|
||||
if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) option++;
|
||||
if (!strcmp(Settings.mqtt_prefix[0],Settings.mqtt_prefix[1]) && (!payload)) option++; // TELE
|
||||
|
||||
if ((!Settings.flag.mqtt_enabled) && (6 == payload)) payload = 99;
|
||||
if (!energy_flg && (9 == payload)) payload = 99;
|
||||
@ -1333,8 +1337,8 @@ void PublishStatus(uint8_t payload)
|
||||
}
|
||||
|
||||
if ((0 == payload) || (4 == payload)) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHMODE "\":%d}}"),
|
||||
ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipMode());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"),
|
||||
ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipMode(), LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2);
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4"));
|
||||
}
|
||||
|
||||
@ -2162,6 +2166,7 @@ void SerialInput()
|
||||
serial_in_buffer[serial_in_byte_counter] = 0; // serial data completed
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||
// XdrvRulesProcess();
|
||||
serial_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
@ -2372,6 +2377,8 @@ void setup()
|
||||
|
||||
OsWatchInit();
|
||||
|
||||
GetFeatures();
|
||||
|
||||
baudrate = Settings.baudrate * 1200;
|
||||
seriallog_level = Settings.seriallog_level;
|
||||
seriallog_timer = SERIALLOG_TIMER;
|
||||
|
@ -95,6 +95,8 @@ enum UserSelectablePins {
|
||||
GPIO_SR04_ECHO, // SR04 Echo pin
|
||||
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_SENSOR_END };
|
||||
|
||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||
@ -139,7 +141,8 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_PMS5003 "|" D_SENSOR_SDS0X1 "|"
|
||||
D_SENSOR_SBR_TX "|" D_SENSOR_SBR_RX "|"
|
||||
D_SENSOR_SR04_TRIG "|" D_SENSOR_SR04_ECHO "|"
|
||||
D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX;
|
||||
D_SENSOR_SDM120_TX "|" D_SENSOR_SDM120_RX "|"
|
||||
D_SENSOR_SDM630_TX "|" D_SENSOR_SDM630_RX;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
|
@ -482,6 +482,96 @@ int GetStateNumber(char *state_text)
|
||||
return state_number;
|
||||
}
|
||||
|
||||
boolean GetUsedInModule(byte val, uint8_t *arr)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
if (!val) { return false; } // None
|
||||
#ifndef USE_I2C
|
||||
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
|
||||
#ifndef USE_IR_REMOTE
|
||||
if (GPIO_IRSEND == val) { return true; }
|
||||
#ifndef USE_IR_RECEIVE
|
||||
if (GPIO_IRRECV == val) { return true; }
|
||||
#endif
|
||||
#endif
|
||||
#ifndef USE_MHZ19
|
||||
if (GPIO_MHZ_TXD == val) { return true; }
|
||||
if (GPIO_MHZ_RXD == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_PZEM004T
|
||||
if (GPIO_PZEM_TX == val) { return true; }
|
||||
if (GPIO_PZEM_RX == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_SENSEAIR
|
||||
if (GPIO_SAIR_TX == val) { return true; }
|
||||
if (GPIO_SAIR_RX == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_SPI
|
||||
if (GPIO_SPI_CS == val) { return true; }
|
||||
if (GPIO_SPI_DC == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_DISPLAY
|
||||
if (GPIO_BACKLIGHT == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_PMS5003
|
||||
if (GPIO_PMS5003 == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_NOVA_SDS
|
||||
if (GPIO_SDS0X1 == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_SERIAL_BRIDGE
|
||||
if (GPIO_SBR_TX == val) { return true; }
|
||||
if (GPIO_SBR_RX == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_SR04
|
||||
if (GPIO_SR04_TRIG == val) { return true; }
|
||||
if (GPIO_SR04_ECHO == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_SDM120
|
||||
if (GPIO_SDM120_TX == val) { return true; }
|
||||
if (GPIO_SDM120_RX == val) { return true; }
|
||||
#endif
|
||||
#ifndef USE_SDM630
|
||||
if (GPIO_SDM630_TX == val) { return true; }
|
||||
if (GPIO_SDM630_RX == val) { return true; }
|
||||
#endif
|
||||
if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) {
|
||||
offset = (GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) {
|
||||
offset = -(GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) {
|
||||
offset = (GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) {
|
||||
offset = -(GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) {
|
||||
offset = (GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) {
|
||||
offset = -(GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (arr[i] == val) { return true; }
|
||||
if (arr[i] == val + offset) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetSerialBaudrate(int baudrate)
|
||||
{
|
||||
Settings.baudrate = baudrate / 1200;
|
||||
@ -516,6 +606,235 @@ uint32_t GetHash(const char *buffer, size_t size)
|
||||
return hash;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Fill feature list
|
||||
\*********************************************************************************************/
|
||||
|
||||
void GetFeatures()
|
||||
{
|
||||
feature_drv1 = 0x00000000; // xdrv_00_mqtt.ino, xdrv_01_light.ino, xdrv_04_snfbridge.ino
|
||||
|
||||
// feature_drv1 |= 0x00000001;
|
||||
// feature_drv1 |= 0x00000002;
|
||||
|
||||
#ifdef USE_I2C
|
||||
feature_drv1 |= 0x00000004; // sonoff.ino
|
||||
#endif
|
||||
#ifdef USE_SPI
|
||||
feature_drv1 |= 0x00000008; // sonoff.ino
|
||||
#endif
|
||||
#ifdef USE_DISCOVERY
|
||||
feature_drv1 |= 0x00000010; // sonoff.ino
|
||||
#endif
|
||||
#ifdef USE_ARDUINO_OTA
|
||||
feature_drv1 |= 0x00000020; // sonoff.ino
|
||||
#endif
|
||||
#ifdef USE_MQTT_TLS
|
||||
feature_drv1 |= 0x00000040; // sonoff.ino
|
||||
#endif
|
||||
#ifdef USE_WEBSERVER
|
||||
feature_drv1 |= 0x00000080; // webserver.ino
|
||||
#endif
|
||||
#ifdef WEBSERVER_ADVERTISE
|
||||
feature_drv1 |= 0x00000100; // webserver.ino
|
||||
#endif
|
||||
#ifdef USE_EMULATION
|
||||
feature_drv1 |= 0x00000200; // xplg_wemohue.ino
|
||||
#endif
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_PUBSUBCLIENT)
|
||||
feature_drv1 |= 0x00000400; // xdrv_00_mqtt.ino
|
||||
#endif
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_TASMOTAMQTT)
|
||||
feature_drv1 |= 0x00000800; // xdrv_00_mqtt.ino
|
||||
#endif
|
||||
#if (MQTT_LIBRARY_TYPE == MQTT_ESPMQTTARDUINO)
|
||||
feature_drv1 |= 0x00001000; // xdrv_00_mqtt.ino
|
||||
#endif
|
||||
#ifdef MQTT_HOST_DISCOVERY
|
||||
feature_drv1 |= 0x00002000; // xdrv_00_mqtt.ino
|
||||
#endif
|
||||
#ifdef USE_ARILUX_RF
|
||||
feature_drv1 |= 0x00004000; // xdrv_01_light.ino
|
||||
#endif
|
||||
#ifdef USE_WS2812
|
||||
feature_drv1 |= 0x00008000; // xdrv_01_light.ino
|
||||
#endif
|
||||
#ifdef USE_WS2812_DMA
|
||||
feature_drv1 |= 0x00010000; // xdrv_01_light.ino
|
||||
#endif
|
||||
#ifdef USE_IR_REMOTE
|
||||
feature_drv1 |= 0x00020000; // xdrv_02_irremote.ino
|
||||
#endif
|
||||
#ifdef USE_IR_HVAC
|
||||
feature_drv1 |= 0x00040000; // xdrv_02_irremote.ino
|
||||
#endif
|
||||
#ifdef USE_IR_RECEIVE
|
||||
feature_drv1 |= 0x00080000; // xdrv_02_irremote.ino
|
||||
#endif
|
||||
#ifdef USE_DOMOTICZ
|
||||
feature_drv1 |= 0x00100000; // xdrv_05_domoticz.ino
|
||||
#endif
|
||||
#ifdef USE_DISPLAY
|
||||
feature_drv1 |= 0x00200000; // xdrv_06_display.ino
|
||||
#endif
|
||||
#ifdef USE_HOME_ASSISTANT
|
||||
feature_drv1 |= 0x00400000; // xdrv_07_home_assistant.ino
|
||||
#endif
|
||||
#ifdef USE_SERIAL_BRIDGE
|
||||
feature_drv1 |= 0x00800000; // xdrv_08_serial_bridge.ino
|
||||
#endif
|
||||
#ifdef USE_TIMERS
|
||||
feature_drv1 |= 0x01000000; // xdrv_09_timers.ino
|
||||
#endif
|
||||
#ifdef USE_SUNRISE
|
||||
feature_drv1 |= 0x02000000; // xdrv_09_timers.ino
|
||||
#endif
|
||||
#ifdef USE_TIMERS_WEB
|
||||
feature_drv1 |= 0x04000000; // xdrv_09_timers.ino
|
||||
#endif
|
||||
#ifdef USE_RULES
|
||||
feature_drv1 |= 0x08000000; // xdrv_10_rules.ino
|
||||
#endif
|
||||
#ifdef USE_KNX
|
||||
feature_drv1 |= 0x10000000; // xdrv_11_knx.ino
|
||||
#endif
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
feature_drv2 = 0x00000000;
|
||||
|
||||
#ifdef USE_CONFIG_OVERRIDE
|
||||
feature_drv2 |= 0x00000001; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef BE_MINIMAL
|
||||
feature_drv2 |= 0x00000002; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef USE_ALL_SENSORS
|
||||
feature_drv2 |= 0x00000004; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef USE_CLASSIC
|
||||
feature_drv2 |= 0x00000008; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef USE_KNX_NO_EMULATION
|
||||
feature_drv2 |= 0x00000010; // user_config(_override).h
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef VTABLES_IN_FLASH
|
||||
feature_drv2 |= 0x04000000; // platformio.ini
|
||||
#endif
|
||||
#ifdef PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
|
||||
feature_drv2 |= 0x08000000; // platformio.ini
|
||||
#endif
|
||||
#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
feature_drv2 |= 0x10000000; // platformio.ini
|
||||
#endif
|
||||
#ifdef PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
feature_drv2 |= 0x20000000; // platformio.ini
|
||||
#endif
|
||||
#ifdef DEBUG_THEO
|
||||
feature_drv2 |= 0x40000000; // xdrv_99_debug.ino
|
||||
#endif
|
||||
#ifdef USE_DEBUG_DRIVER
|
||||
feature_drv2 |= 0x80000000; // xdrv_99_debug.ino
|
||||
#endif
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
feature_sns1 = 0x00000000; // xsns_01_counter.ino, xsns_04_snfsc.ino
|
||||
|
||||
// feature_sns1 |= 0x00000001;
|
||||
|
||||
#ifdef USE_ADC_VCC
|
||||
feature_sns1 |= 0x00000002; // support.ino (ADC)
|
||||
#endif
|
||||
#ifdef USE_ENERGY_SENSOR
|
||||
feature_sns1 |= 0x00000004; // xdrv_03_energy.ino
|
||||
#endif
|
||||
#ifdef USE_PZEM004T
|
||||
feature_sns1 |= 0x00000008; // xdrv_03_energy.ino
|
||||
#endif
|
||||
#ifdef USE_DS18B20
|
||||
feature_sns1 |= 0x00000010; // xsns_05_ds18b20.ino
|
||||
#endif
|
||||
#ifdef USE_DS18x20_LEGACY
|
||||
feature_sns1 |= 0x00000020; // xsns_05_ds18x20_legacy.ino
|
||||
#endif
|
||||
#ifdef USE_DS18x20
|
||||
feature_sns1 |= 0x00000040; // xsns_05_ds18x20.ino
|
||||
#endif
|
||||
#ifdef USE_DHT
|
||||
feature_sns1 |= 0x00000080; // xsns_06_dht.ino
|
||||
#endif
|
||||
#ifdef USE_SHT
|
||||
feature_sns1 |= 0x00000100; // xsns_07_sht1x.ino
|
||||
#endif
|
||||
#ifdef USE_HTU
|
||||
feature_sns1 |= 0x00000200; // xsns_08_htu21.ino
|
||||
#endif
|
||||
#ifdef USE_BMP
|
||||
feature_sns1 |= 0x00000400; // xsns_09_bmp.ino
|
||||
#endif
|
||||
#ifdef USE_BME680
|
||||
feature_sns1 |= 0x00000800; // xsns_09_bmp.ino - BME680
|
||||
#endif
|
||||
#ifdef USE_BH1750
|
||||
feature_sns1 |= 0x00001000; // xsns_10_bh1750.ino
|
||||
#endif
|
||||
#ifdef USE_VEML6070
|
||||
feature_sns1 |= 0x00002000; // xsns_11_veml6070.ino
|
||||
#endif
|
||||
#ifdef USE_ADS1115_I2CDEV
|
||||
feature_sns1 |= 0x00004000; // xsns_12_ads1115_i2cdev.ino
|
||||
#endif
|
||||
#ifdef USE_ADS1115
|
||||
feature_sns1 |= 0x00008000; // xsns_12_ads1115.ino
|
||||
#endif
|
||||
#ifdef USE_INA219
|
||||
feature_sns1 |= 0x00010000; // xsns_13_ina219.ino
|
||||
#endif
|
||||
#ifdef USE_SHT3X
|
||||
feature_sns1 |= 0x00020000; // xsns_14_sht3x.ino
|
||||
#endif
|
||||
#ifdef USE_MHZ19
|
||||
feature_sns1 |= 0x00040000; // xsns_15_mhz19.ino
|
||||
#endif
|
||||
#ifdef USE_TSL2561
|
||||
feature_sns1 |= 0x00080000; // xsns_16_tsl2561.ino
|
||||
#endif
|
||||
#ifdef USE_SENSEAIR
|
||||
feature_sns1 |= 0x00100000; // xsns_17_senseair.ino
|
||||
#endif
|
||||
#ifdef USE_PMS5003
|
||||
feature_sns1 |= 0x00200000; // xsns_18_pms5003.ino
|
||||
#endif
|
||||
#ifdef USE_MGS
|
||||
feature_sns1 |= 0x00400000; // xsns_19_mgs.ino
|
||||
#endif
|
||||
#ifdef USE_NOVA_SDS
|
||||
feature_sns1 |= 0x00800000; // xsns_20_novasds.ino
|
||||
#endif
|
||||
#ifdef USE_SGP30
|
||||
feature_sns1 |= 0x01000000; // xsns_21_sgp30.ino
|
||||
#endif
|
||||
#ifdef USE_SR04
|
||||
feature_sns1 |= 0x02000000; // xsns_22_sr04.ino
|
||||
#endif
|
||||
#ifdef USE_SDM120
|
||||
feature_sns1 |= 0x04000000; // xsns_23_sdm120.ino
|
||||
#endif
|
||||
#ifdef USE_SI1145
|
||||
feature_sns1 |= 0x08000000; // xsns_24_si1145.ino
|
||||
#endif
|
||||
#ifdef USE_SDM630
|
||||
feature_sns1 |= 0x10000000; // xsns_25_sdm630.ino
|
||||
#endif
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
feature_sns2 = 0x00000000;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Wifi
|
||||
\*********************************************************************************************/
|
||||
@ -1381,14 +1700,12 @@ void RtcSecond()
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION "(" D_UTC_TIME ") %s, (" D_DST_TIME ") %s, (" D_STD_TIME ") %s"),
|
||||
GetTime(0).c_str(), GetTime(2).c_str(), GetTime(3).c_str());
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
#ifdef USE_RULES
|
||||
if (local_time < 1451602800) { // 2016-01-01
|
||||
strncpy_P(mqtt_data, PSTR("{\"Time\":{\"Initialized\":1}}"), sizeof(mqtt_data));
|
||||
} else {
|
||||
strncpy_P(mqtt_data, PSTR("{\"Time\":{\"Set\":1}}"), sizeof(mqtt_data));
|
||||
}
|
||||
RulesProcess();
|
||||
#endif // USE_RULES
|
||||
XdrvRulesProcess();
|
||||
} else {
|
||||
ntp_sync_minute++; // Try again in next minute
|
||||
}
|
||||
@ -1469,7 +1786,7 @@ void AdcEvery50ms()
|
||||
adc_last_value = new_value;
|
||||
uint16_t value = adc_last_value / 10;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value);
|
||||
RulesProcess();
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -268,7 +268,7 @@
|
||||
#define USE_BH1750 // Add I2C code for BH1750 sensor (+0k5 code)
|
||||
// #define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0k5 code)
|
||||
// #define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Joba_Tsl2561 (+2k3 code)
|
||||
#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code)
|
||||
// #define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code)
|
||||
// #define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (no library needed) (+0k7 code)
|
||||
// #define USE_ADS1115_I2CDEV // Add I2C code for ADS1115 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code)
|
||||
// #define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code)
|
||||
@ -293,6 +293,8 @@
|
||||
#define USE_SERIAL_BRIDGE // Add support for software Serial Bridge (+0k8 code)
|
||||
#define USE_SDM120 // Add support for Eastron SDM120-Modbus energy meter (+1k7 code)
|
||||
#define SDM120_SPEED 9600 // SDM120-Modbus RS485 serial speed (default: 2400 baud)
|
||||
#define USE_SDM630 // Add support for Eastron SDM630-Modbus energy meter (+2k code)
|
||||
#define SDM630_SPEED 9600 // SDM630-Modbus RS485 serial speed (default: 9600 baud)
|
||||
|
||||
// -- Low level interface devices -----------------
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0k3 mem, 48 iram)
|
||||
|
@ -25,9 +25,6 @@
|
||||
* Based on source by AlexT (https://github.com/tzapu)
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
|
||||
const char HTTP_HEAD[] PROGMEM =
|
||||
"<!DOCTYPE html><html lang=\"" D_HTML_LANGUAGE "\" class=\"\">"
|
||||
"<head>"
|
||||
@ -331,7 +328,6 @@ uint8_t upload_progress_dot_count;
|
||||
uint8_t config_block_count = 0;
|
||||
uint8_t config_xor_on = 0;
|
||||
uint8_t config_xor_on_set = CONFIG_FILE_XOR;
|
||||
uint8_t *settings_new = NULL;
|
||||
|
||||
// Helper function to avoid code duplication (saves 4k Flash)
|
||||
static void WebGetArg(const char* arg, char* out, size_t max)
|
||||
@ -642,52 +638,6 @@ void HandleConfiguration()
|
||||
ShowPage(page);
|
||||
}
|
||||
|
||||
boolean GetUsedInModule(byte val, uint8_t *arr)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
if (!val) { return false; } // None
|
||||
#ifndef USE_I2C
|
||||
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
|
||||
#ifndef USE_IR_REMOTE
|
||||
if (GPIO_IRSEND == val) { return true; }
|
||||
#endif
|
||||
if ((val >= GPIO_REL1) && (val < GPIO_REL1 + MAX_RELAYS)) {
|
||||
offset = (GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
if ((val >= GPIO_REL1_INV) && (val < GPIO_REL1_INV + MAX_RELAYS)) {
|
||||
offset = -(GPIO_REL1_INV - GPIO_REL1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_LED1) && (val < GPIO_LED1 + MAX_LEDS)) {
|
||||
offset = (GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
if ((val >= GPIO_LED1_INV) && (val < GPIO_LED1_INV + MAX_LEDS)) {
|
||||
offset = -(GPIO_LED1_INV - GPIO_LED1);
|
||||
}
|
||||
|
||||
if ((val >= GPIO_PWM1) && (val < GPIO_PWM1 + MAX_PWMS)) {
|
||||
offset = (GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
if ((val >= GPIO_PWM1_INV) && (val < GPIO_PWM1_INV + MAX_PWMS)) {
|
||||
offset = -(GPIO_PWM1_INV - GPIO_PWM1);
|
||||
}
|
||||
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
|
||||
if (arr[i] == val) { return true; }
|
||||
if (arr[i] == val + offset) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandleModuleConfiguration()
|
||||
{
|
||||
if (HttpUser()) { return; }
|
||||
@ -964,25 +914,36 @@ void HandleBackupConfiguration()
|
||||
if (HttpUser()) { return; }
|
||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_BACKUP_CONFIGURATION));
|
||||
|
||||
uint8_t buffer[sizeof(Settings)];
|
||||
if (!SettingsBufferAlloc()) { return; }
|
||||
|
||||
WiFiClient myClient = WebServer->client();
|
||||
WebServer->setContentLength(sizeof(buffer));
|
||||
WebServer->setContentLength(sizeof(Settings));
|
||||
|
||||
char attachment[100];
|
||||
char friendlyname[sizeof(Settings.friendlyname[0])];
|
||||
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"), NoAlNumToUnderscore(friendlyname, Settings.friendlyname[0]), my_version);
|
||||
WebServer->sendHeader(F("Content-Disposition"), attachment);
|
||||
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_STREAM), "");
|
||||
memcpy(buffer, &Settings, sizeof(buffer));
|
||||
buffer[0] = CONFIG_FILE_SIGN;
|
||||
buffer[1] = (!config_xor_on_set) ? 0 : 1;
|
||||
if (buffer[1]) {
|
||||
for (uint16_t i = 2; i < sizeof(buffer); i++) {
|
||||
buffer[i] ^= (config_xor_on_set +i);
|
||||
memcpy(settings_buffer, &Settings, sizeof(Settings));
|
||||
settings_buffer[0] = CONFIG_FILE_SIGN;
|
||||
settings_buffer[1] = (!config_xor_on_set) ? 0 : 1;
|
||||
if (settings_buffer[1]) {
|
||||
for (uint16_t i = 2; i < sizeof(Settings); i++) {
|
||||
settings_buffer[i] ^= (config_xor_on_set +i);
|
||||
}
|
||||
}
|
||||
myClient.write((const char*)buffer, sizeof(buffer));
|
||||
|
||||
#ifdef ARDUINO_ESP8266_RELEASE_2_3_0
|
||||
size_t written = myClient.write((const char*)settings_buffer, sizeof(Settings));
|
||||
if (written < sizeof(Settings)) { // https://github.com/esp8266/Arduino/issues/3218
|
||||
myClient.write((const char*)settings_buffer +written, sizeof(Settings) -written);
|
||||
}
|
||||
#else
|
||||
myClient.write((const char*)settings_buffer, sizeof(Settings));
|
||||
#endif
|
||||
|
||||
SettingsBufferFree();
|
||||
}
|
||||
|
||||
void HandleSaveSettings()
|
||||
@ -1235,14 +1196,6 @@ void HandleUpgradeFirmwareStart()
|
||||
ExecuteCommand(svalue);
|
||||
}
|
||||
|
||||
void SettingsNewFree()
|
||||
{
|
||||
if (settings_new != NULL) {
|
||||
free(settings_new);
|
||||
settings_new = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void HandleUploadDone()
|
||||
{
|
||||
if (HttpUser()) { return; }
|
||||
@ -1282,7 +1235,7 @@ void HandleUploadDone()
|
||||
page += FPSTR(HTTP_MSG_RSTRT);
|
||||
restart_flag = 2;
|
||||
}
|
||||
SettingsNewFree();
|
||||
SettingsBufferFree();
|
||||
page += F("</div><br/>");
|
||||
page += FPSTR(HTTP_BTN_MAIN);
|
||||
ShowPage(page);
|
||||
@ -1311,8 +1264,7 @@ void HandleUploadLoop()
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD D_FILE " %s ..."), upload.filename.c_str());
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
if (upload_file_type) {
|
||||
SettingsNewFree();
|
||||
if (!(settings_new = (uint8_t *)malloc(sizeof(Settings)))) {
|
||||
if (!SettingsBufferAlloc()) {
|
||||
upload_error = 2;
|
||||
return;
|
||||
}
|
||||
@ -1360,7 +1312,7 @@ void HandleUploadLoop()
|
||||
upload_error = 9;
|
||||
return;
|
||||
}
|
||||
memcpy(settings_new + (config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize);
|
||||
memcpy(settings_buffer + (config_block_count * HTTP_UPLOAD_BUFLEN), upload.buf, upload.currentSize);
|
||||
config_block_count++;
|
||||
}
|
||||
} else { // firmware
|
||||
@ -1381,13 +1333,13 @@ void HandleUploadLoop()
|
||||
if (upload_file_type) {
|
||||
if (config_xor_on) {
|
||||
for (uint16_t i = 2; i < sizeof(Settings); i++) {
|
||||
settings_new[i] ^= (config_xor_on_set +i);
|
||||
settings_buffer[i] ^= (config_xor_on_set +i);
|
||||
}
|
||||
}
|
||||
SettingsDefaultSet2();
|
||||
memcpy((char*)&Settings +16, settings_new +16, sizeof(Settings) -16);
|
||||
memcpy((char*)&Settings +8, settings_new +8, 4); // Restore version and auto upgrade
|
||||
SettingsNewFree();
|
||||
memcpy((char*)&Settings +16, settings_buffer +16, sizeof(Settings) -16);
|
||||
memcpy((char*)&Settings +8, settings_buffer +8, 4); // Restore version and auto upgrade
|
||||
SettingsBufferFree();
|
||||
} else {
|
||||
if (!Update.end(true)) { // true to set the size to the current progress
|
||||
if (_serialoutput) { Update.printError(Serial); }
|
||||
|
@ -315,10 +315,8 @@ void MqttDisconnected(int state)
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND),
|
||||
Settings.mqtt_host, Settings.mqtt_port, state, mqtt_retry_counter);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
#ifdef USE_RULES
|
||||
strncpy_P(mqtt_data, PSTR("{\"MQTT\":{\"Disconnected\":1}}"), sizeof(mqtt_data));
|
||||
RulesProcess();
|
||||
#endif // USE_RULES
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
|
||||
void MqttConnected()
|
||||
@ -370,17 +368,13 @@ void MqttConnected()
|
||||
tele_period = Settings.tele_period -9;
|
||||
}
|
||||
status_update_timer = 2;
|
||||
#ifdef USE_RULES
|
||||
strncpy_P(mqtt_data, PSTR("{\"System\":{\"Boot\":1}}"), sizeof(mqtt_data));
|
||||
RulesProcess();
|
||||
#endif // USE_RULES
|
||||
XdrvRulesProcess();
|
||||
XdrvCall(FUNC_MQTT_INIT);
|
||||
}
|
||||
mqtt_initial_connection_state = 0;
|
||||
#ifdef USE_RULES
|
||||
strncpy_P(mqtt_data, PSTR("{\"MQTT\":{\"Connected\":1}}"), sizeof(mqtt_data));
|
||||
RulesProcess();
|
||||
#endif // USE_RULES
|
||||
XdrvRulesProcess();
|
||||
}
|
||||
|
||||
#ifdef USE_MQTT_TLS
|
||||
|
@ -110,6 +110,7 @@ void IrReceiveCheck()
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":\"%lX\"}}"),
|
||||
GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, (uint32_t)results.value);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED));
|
||||
XdrvRulesProcess();
|
||||
#ifdef USE_DOMOTICZ
|
||||
unsigned long value = results.value | (iridx << 28); // [Protocol:4, Data:28]
|
||||
DomoticzSensor(DZ_COUNT, value); // Send data as Domoticz Counter value
|
||||
@ -298,7 +299,7 @@ boolean IrSendCommand()
|
||||
protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))];
|
||||
bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))];
|
||||
data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0);
|
||||
if (protocol && bits && data) {
|
||||
if (protocol && bits) {
|
||||
int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols);
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"),
|
||||
@ -384,7 +385,7 @@ boolean IrSendCommand()
|
||||
}
|
||||
#endif // USE_IR_HVAC
|
||||
else serviced = false; // Unknown command
|
||||
|
||||
|
||||
return serviced;
|
||||
}
|
||||
|
||||
|
@ -1113,6 +1113,17 @@ void EnergyShow(boolean json)
|
||||
DomoticzSensor(DZ_CURRENT, energy_current_chr); // Current
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_KNX
|
||||
if (show_energy_period) {
|
||||
KnxSensor(KNX_ENERGY_VOLTAGE, energy_voltage);
|
||||
KnxSensor(KNX_ENERGY_CURRENT, energy_current);
|
||||
KnxSensor(KNX_ENERGY_POWER, energy_power);
|
||||
KnxSensor(KNX_ENERGY_POWERFACTOR, energy_power_factor);
|
||||
KnxSensor(KNX_ENERGY_DAILY, energy_daily);
|
||||
KnxSensor(KNX_ENERGY_TOTAL, energy_total);
|
||||
KnxSensor(KNX_ENERGY_START, energy_start);
|
||||
}
|
||||
#endif // USE_KNX
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS, mqtt_data, energy_voltage_chr, energy_current_chr, energy_power_chr, energy_power_factor_chr, energy_daily_chr, energy_yesterday_chr, energy_total_chr);
|
||||
|
@ -97,6 +97,7 @@ void SonoffBridgeReceived()
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\",\"" D_CMND_RFKEY "\":%s}}"),
|
||||
sync_time, low_time, high_time, received_id, rfkey);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED));
|
||||
XdrvRulesProcess();
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_COUNT, received_id); // Send rid as Domoticz Counter value
|
||||
#endif // USE_DOMOTICZ
|
||||
|
@ -61,6 +61,7 @@ void SerialBridgeInput()
|
||||
serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // serial data completed
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer);
|
||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED));
|
||||
// XdrvRulesProcess();
|
||||
serial_bridge_in_byte_counter = 0;
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,7 @@ void TimerEverySecond()
|
||||
{
|
||||
if (RtcTime.valid) {
|
||||
if (!RtcTime.hour && !RtcTime.minute && !RtcTime.second) { TimerSetRandomWindows(); } // Midnight
|
||||
if (RtcTime.minute != timer_last_minute) { // Execute every minute only once
|
||||
if ((uptime > 60) && (RtcTime.minute != timer_last_minute)) { // Execute from one minute after restart every minute only once
|
||||
timer_last_minute = RtcTime.minute;
|
||||
int16_t time = (RtcTime.hour *60) + RtcTime.minute;
|
||||
uint8_t days = 1 << (RtcTime.day_of_week -1);
|
||||
@ -287,7 +287,7 @@ void TimerEverySecond()
|
||||
#ifdef USE_RULES
|
||||
if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1);
|
||||
RulesProcess();
|
||||
XdrvRulesProcess();
|
||||
} else
|
||||
#endif // USE_RULES
|
||||
if (devices_present) { ExecuteCommandPower(xtimer.device +1, xtimer.power); }
|
||||
|
@ -72,11 +72,13 @@
|
||||
#define D_CMND_RULE "Rule"
|
||||
#define D_CMND_RULETIMER "RuleTimer"
|
||||
#define D_CMND_EVENT "Event"
|
||||
#define D_CMND_VAR "Var"
|
||||
#define D_CMND_MEM "Mem"
|
||||
|
||||
#define D_JSON_INITIATED "Initiated"
|
||||
|
||||
enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT };
|
||||
const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT ;
|
||||
enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM };
|
||||
const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM ;
|
||||
|
||||
String rules_event_value;
|
||||
unsigned long rules_timer[MAX_RULE_TIMERS] = { 0 };
|
||||
@ -84,10 +86,12 @@ uint8_t rules_quota = 0;
|
||||
long rules_new_power = -1;
|
||||
long rules_old_power = -1;
|
||||
|
||||
uint32_t rules_triggers = 0;
|
||||
uint8_t rules_trigger_count = 0;
|
||||
uint32_t rules_triggers[MAX_RULE_SETS] = { 0 };
|
||||
uint8_t rules_trigger_count[MAX_RULE_SETS] = { 0 };
|
||||
uint8_t rules_teleperiod = 0;
|
||||
|
||||
char vars[RULES_MAX_VARS][10] = { 0 };
|
||||
|
||||
/*******************************************************************************************/
|
||||
|
||||
long TimeDifference(unsigned long prev, unsigned long next)
|
||||
@ -137,13 +141,14 @@ bool TimeReached(unsigned long timer)
|
||||
|
||||
/*******************************************************************************************/
|
||||
|
||||
bool RulesRuleMatch(String &event, String &rule)
|
||||
bool RulesRuleMatch(byte rule_set, String &event, String &rule)
|
||||
{
|
||||
// event = {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089}}
|
||||
// event = {"System":{"Boot":1}}
|
||||
// rule = "INA219#CURRENT>0.100"
|
||||
|
||||
bool match = false;
|
||||
char stemp[10];
|
||||
|
||||
// Step1: Analyse rule
|
||||
int pos = rule.indexOf('#');
|
||||
@ -174,15 +179,32 @@ bool RulesRuleMatch(String &event, String &rule)
|
||||
}
|
||||
}
|
||||
|
||||
char tmp_value[CMDSZ] = { 0 };
|
||||
char rule_svalue[CMDSZ] = { 0 };
|
||||
double rule_value = 0;
|
||||
if (pos > 0) {
|
||||
snprintf(tmp_value, sizeof(tmp_value), rule_name.substring(pos + 1).c_str());
|
||||
int temp_value = GetStateNumber(tmp_value);
|
||||
String rule_param = rule_name.substring(pos + 1);
|
||||
for (byte i = 0; i < RULES_MAX_VARS; i++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1);
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
rule_param = vars[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (byte i = 0; i < RULES_MAX_MEMS; i++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%MEM%d%%"), i +1);
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
rule_param = Settings.mems[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
rule_param.toUpperCase();
|
||||
snprintf(rule_svalue, sizeof(rule_svalue), rule_param.c_str());
|
||||
|
||||
int temp_value = GetStateNumber(rule_svalue);
|
||||
if (temp_value > -1) {
|
||||
rule_value = temp_value;
|
||||
} else {
|
||||
rule_value = CharToDouble((char*)tmp_value); // 0.1 - This saves 9k code over toFLoat()!
|
||||
rule_value = CharToDouble((char*)rule_svalue); // 0.1 - This saves 9k code over toFLoat()!
|
||||
}
|
||||
rule_name = rule_name.substring(0, pos); // "CURRENT"
|
||||
}
|
||||
@ -196,7 +218,7 @@ bool RulesRuleMatch(String &event, String &rule)
|
||||
const char* str_value = root[rule_task][rule_name];
|
||||
|
||||
//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"),
|
||||
// rule_task.c_str(), rule_name.c_str(), tmp_value, rules_trigger_count, bitRead(rules_triggers, rules_trigger_count), event.c_str(), (str_value) ? str_value : "none");
|
||||
// rule_task.c_str(), rule_name.c_str(), rule_svalue, rules_trigger_count[rule_set], bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set]), event.c_str(), (str_value) ? str_value : "none");
|
||||
//AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
if (!root[rule_task][rule_name].success()) { return false; }
|
||||
@ -209,13 +231,14 @@ bool RulesRuleMatch(String &event, String &rule)
|
||||
value = CharToDouble((char*)str_value);
|
||||
switch (compare) {
|
||||
case '>':
|
||||
if (value > rule_value) match = true;
|
||||
if (value > rule_value) { match = true; }
|
||||
break;
|
||||
case '<':
|
||||
if (value < rule_value) match = true;
|
||||
if (value < rule_value) { match = true; }
|
||||
break;
|
||||
case '=':
|
||||
if (value == rule_value) match = true;
|
||||
// if (value == rule_value) { match = true; } // Compare values - only decimals or partly hexadecimals
|
||||
if (!strcasecmp(str_value, rule_svalue)) { match = true; } // Compare strings - this also works for hexadecimals
|
||||
break;
|
||||
case ' ':
|
||||
match = true; // Json value but not needed
|
||||
@ -225,13 +248,13 @@ bool RulesRuleMatch(String &event, String &rule)
|
||||
|
||||
if (Settings.flag.rules_once) {
|
||||
if (match) { // Only allow match state changes
|
||||
if (!bitRead(rules_triggers, rules_trigger_count)) {
|
||||
bitSet(rules_triggers, rules_trigger_count);
|
||||
if (!bitRead(rules_triggers[rule_set], rules_trigger_count[rule_set])) {
|
||||
bitSet(rules_triggers[rule_set], rules_trigger_count[rule_set]);
|
||||
} else {
|
||||
match = false;
|
||||
}
|
||||
} else {
|
||||
bitClear(rules_triggers, rules_trigger_count);
|
||||
bitClear(rules_triggers[rule_set], rules_trigger_count[rule_set]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,25 +263,19 @@ bool RulesRuleMatch(String &event, String &rule)
|
||||
|
||||
/*******************************************************************************************/
|
||||
|
||||
bool RulesProcess()
|
||||
bool RuleSetProcess(byte rule_set, String &event_saved)
|
||||
{
|
||||
bool serviced = false;
|
||||
char vars[RULES_MAX_VARS][10] = { 0 };
|
||||
char stemp[10];
|
||||
|
||||
delay(0); // Prohibit possible loop software watchdog
|
||||
|
||||
//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event = %s, Rule = %s"), mqtt_data, Settings.rules);
|
||||
//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event = %s, Rule = %s"), event_saved.c_str(), Settings.rules[rule_set]);
|
||||
//AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
if (!Settings.flag.rules_enabled) { return serviced; } // Not enabled
|
||||
if (!strlen(Settings.rules)) { return serviced; } // No rules
|
||||
String rules = Settings.rules[rule_set];
|
||||
|
||||
String event_saved = mqtt_data;
|
||||
event_saved.toUpperCase();
|
||||
String rules = Settings.rules;
|
||||
|
||||
rules_trigger_count = 0;
|
||||
rules_trigger_count[rule_set] = 0;
|
||||
int plen = 0;
|
||||
while (true) {
|
||||
rules = rules.substring(plen); // Select relative to last rule
|
||||
@ -283,54 +300,69 @@ bool RulesProcess()
|
||||
//snprintf_P(log_data, sizeof(log_data), PSTR("RUL: Event |%s|, Rule |%s|, Command(s) |%s|"), event.c_str(), event_trigger.c_str(), commands.c_str());
|
||||
//AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
if (RulesRuleMatch(event, event_trigger)) {
|
||||
if (RulesRuleMatch(rule_set, event, event_trigger)) {
|
||||
commands.trim();
|
||||
String ucommand = commands;
|
||||
ucommand.toUpperCase();
|
||||
if (ucommand.startsWith("VAR")) {
|
||||
uint8_t idx = ucommand.charAt(3) - '1';
|
||||
if ((idx >= 0) && (idx < RULES_MAX_VARS)) { snprintf(vars[idx], sizeof(vars[idx]), rules_event_value.c_str()); }
|
||||
} else {
|
||||
// if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race condition
|
||||
commands.replace(F("%value%"), rules_event_value);
|
||||
for (byte i = 0; i < RULES_MAX_VARS; i++) {
|
||||
if (strlen(vars[i])) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1);
|
||||
commands.replace(stemp, vars[i]);
|
||||
}
|
||||
}
|
||||
char command[commands.length() +1];
|
||||
snprintf(command, sizeof(command), commands.c_str());
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
|
||||
// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED);
|
||||
// MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE));
|
||||
|
||||
ExecuteCommand(command);
|
||||
// if (!ucommand.startsWith("BACKLOG")) { commands = "backlog " + commands; } // Always use Backlog to prevent power race exception
|
||||
if (ucommand.indexOf("EVENT ") != -1) { commands = "backlog " + commands; } // Always use Backlog with event to prevent rule event loop exception
|
||||
commands.replace(F("%value%"), rules_event_value);
|
||||
for (byte i = 0; i < RULES_MAX_VARS; i++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%var%d%%"), i +1);
|
||||
commands.replace(stemp, vars[i]);
|
||||
}
|
||||
for (byte i = 0; i < RULES_MAX_MEMS; i++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%mem%d%%"), i +1);
|
||||
commands.replace(stemp, Settings.mems[i]);
|
||||
}
|
||||
char command[commands.length() +1];
|
||||
snprintf(command, sizeof(command), commands.c_str());
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
|
||||
// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED);
|
||||
// MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE));
|
||||
|
||||
ExecuteCommand(command);
|
||||
serviced = true;
|
||||
}
|
||||
rules_trigger_count++;
|
||||
rules_trigger_count[rule_set]++;
|
||||
}
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*******************************************************************************************/
|
||||
|
||||
bool RulesProcess()
|
||||
{
|
||||
bool serviced = false;
|
||||
|
||||
String event_saved = mqtt_data;
|
||||
event_saved.toUpperCase();
|
||||
|
||||
for (byte i = 0; i < MAX_RULE_SETS; i++) {
|
||||
if (strlen(Settings.rules[i]) && bitRead(Settings.rule_enabled, i)) {
|
||||
if (RuleSetProcess(i, event_saved)) { serviced = true; }
|
||||
}
|
||||
}
|
||||
return serviced;
|
||||
}
|
||||
|
||||
void RulesInit()
|
||||
{
|
||||
if (Settings.rules[0] == '\0') {
|
||||
Settings.flag.rules_enabled = 0;
|
||||
Settings.flag.rules_once = 0;
|
||||
for (byte i = 0; i < MAX_RULE_SETS; i++) {
|
||||
if (Settings.rules[i][0] == '\0') {
|
||||
bitWrite(Settings.rule_enabled, i, 0);
|
||||
bitWrite(Settings.rule_once, i, 0);
|
||||
}
|
||||
}
|
||||
rules_teleperiod = 0;
|
||||
}
|
||||
|
||||
void RulesEvery50ms()
|
||||
{
|
||||
if (Settings.flag.rules_enabled) {
|
||||
if (Settings.rule_enabled) { // Any rule enabled
|
||||
if (rules_new_power != rules_old_power) {
|
||||
if (rules_old_power != -1) {
|
||||
for (byte i = 0; i < devices_present; i++) {
|
||||
@ -362,7 +394,7 @@ void RulesEvery50ms()
|
||||
|
||||
void RulesEverySecond()
|
||||
{
|
||||
if (Settings.flag.rules_enabled) {
|
||||
if (Settings.rule_enabled) { // Any rule enabled
|
||||
for (byte i = 0; i < MAX_RULE_TIMERS; i++) {
|
||||
if (rules_timer[i] != 0L) { // Timer active?
|
||||
if (TimeReached(rules_timer[i])) { // Timer finished?
|
||||
@ -397,39 +429,32 @@ boolean RulesCommand()
|
||||
if (-1 == command_code) {
|
||||
serviced = false; // Unknown command
|
||||
}
|
||||
else if (CMND_RULE == command_code) {
|
||||
if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules))) {
|
||||
else if ((CMND_RULE == command_code) && (index > 0) && (index <= MAX_RULE_SETS)) {
|
||||
if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.rules[index -1]))) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 6)) {
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 0: // Off
|
||||
case 1: // On
|
||||
Settings.flag.rules_enabled = XdrvMailbox.payload;
|
||||
bitWrite(Settings.rule_enabled, index -1, XdrvMailbox.payload);
|
||||
break;
|
||||
case 2: // Toggle
|
||||
Settings.flag.rules_enabled ^= 1;
|
||||
bitWrite(Settings.rule_enabled, index -1, bitRead(Settings.rule_enabled, index -1) ^1);
|
||||
break;
|
||||
case 4: // Off
|
||||
case 5: // On
|
||||
Settings.flag.rules_once = XdrvMailbox.payload &1;
|
||||
bitWrite(Settings.rule_once, index -1, XdrvMailbox.payload &1);
|
||||
break;
|
||||
case 6: // Toggle
|
||||
Settings.flag.rules_once ^= 1;
|
||||
bitWrite(Settings.rule_once, index -1, bitRead(Settings.rule_once, index -1) ^1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
String uc_data = XdrvMailbox.data; // Do not allow Rule to be used within a rule
|
||||
uc_data.toUpperCase();
|
||||
String uc_command = command;
|
||||
uc_command += " "; // Distuingish from RuleTimer
|
||||
uc_command.toUpperCase();
|
||||
if (!uc_data.indexOf(uc_command)) { strlcpy(Settings.rules, XdrvMailbox.data, sizeof(Settings.rules)); }
|
||||
*/
|
||||
strlcpy(Settings.rules, XdrvMailbox.data, sizeof(Settings.rules));
|
||||
strlcpy(Settings.rules[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.rules[index -1]));
|
||||
}
|
||||
rules_triggers = 0; // Reset once flag
|
||||
rules_triggers[index -1] = 0; // Reset once flag
|
||||
}
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"%s\",\"Once\":\"%s\",\"Rules\":\"%s\"}"), command, GetStateText(Settings.flag.rules_enabled), GetStateText(Settings.flag.rules_once), Settings.rules);
|
||||
snprintf_P (mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":\"%s\",\"Once\":\"%s\",\"Free\":%d,\"Rules\":\"%s\"}"),
|
||||
command, index, GetStateText(bitRead(Settings.rule_enabled, index -1)), GetStateText(bitRead(Settings.rule_once, index -1)), sizeof(Settings.rules[index -1]) - strlen(Settings.rules[index -1]) -1, Settings.rules[index -1]);
|
||||
}
|
||||
else if ((CMND_RULETIMER == command_code) && (index > 0) && (index <= MAX_RULE_TIMERS)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
@ -453,6 +478,18 @@ boolean RulesCommand()
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE);
|
||||
}
|
||||
else if ((CMND_VAR == command_code) && (index > 0) && (index <= RULES_MAX_VARS)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
strlcpy(vars[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(vars[index -1]));
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]);
|
||||
}
|
||||
else if ((CMND_MEM == command_code) && (index > 0) && (index <= RULES_MAX_MEMS)) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
strlcpy(Settings.mems[index -1], ('"' == XdrvMailbox.data[0]) ? "" : XdrvMailbox.data, sizeof(Settings.mems[index -1]));
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]);
|
||||
}
|
||||
else serviced = false; // Unknown command
|
||||
|
||||
return serviced;
|
||||
@ -484,8 +521,11 @@ boolean Xdrv10(byte function)
|
||||
case FUNC_COMMAND:
|
||||
result = RulesCommand();
|
||||
break;
|
||||
case FUNC_RULES_PROCESS:
|
||||
result = RulesProcess();
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_RULES
|
||||
#endif // USE_RULES
|
||||
|
@ -48,21 +48,26 @@ byte Settings.knx_CB_param[MAX_KNX_CB] Type of Output (set relay, t
|
||||
|
||||
\*********************************************************************************************/
|
||||
|
||||
#include <esp-knx-ip.h>
|
||||
#include <esp-knx-ip.h> // KNX Library
|
||||
// Note: Inside the <esp-knx-ip.h> 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 KNX_IP Library
|
||||
//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
|
||||
|
||||
#define KNX_Empty 255
|
||||
#define KNX_TEMPERATURE 17
|
||||
#define KNX_HUMIDITY 18
|
||||
#define KNX_MAX_device_param 18
|
||||
|
||||
#define TOGGLE_INHIBIT_TIME 15 // 15*50mseg = 750mseg (inhibit time for not toggling again relays by a KNX toggle command)
|
||||
|
||||
float last_temp;
|
||||
float last_hum;
|
||||
byte toggle_inhibit;
|
||||
|
||||
typedef struct __device_parameters
|
||||
{
|
||||
@ -103,6 +108,13 @@ device_parameters_t device_param[] = {
|
||||
{ 16, false, false, KNX_Empty }, // device_param[15] = Button 8
|
||||
{ KNX_TEMPERATURE, false, false, KNX_Empty }, // device_param[16] = Temperature
|
||||
{ KNX_HUMIDITY , false, false, KNX_Empty }, // device_param[17] = humidity
|
||||
{ KNX_ENERGY_VOLTAGE , false, false, KNX_Empty },
|
||||
{ KNX_ENERGY_CURRENT , false, false, KNX_Empty },
|
||||
{ KNX_ENERGY_POWER , false, false, KNX_Empty },
|
||||
{ KNX_ENERGY_POWERFACTOR , false, false, KNX_Empty },
|
||||
{ KNX_ENERGY_DAILY , false, false, KNX_Empty },
|
||||
{ KNX_ENERGY_START , false, false, KNX_Empty },
|
||||
{ KNX_ENERGY_TOTAL , false, false, KNX_Empty },
|
||||
{ KNX_Empty, false, false, KNX_Empty}
|
||||
};
|
||||
|
||||
@ -126,6 +138,13 @@ const char * device_param_ga[] = {
|
||||
D_SENSOR_BUTTON " 8", // Button 8
|
||||
D_TEMPERATURE , // Temperature
|
||||
D_HUMIDITY , // Humidity
|
||||
D_VOLTAGE ,
|
||||
D_CURRENT ,
|
||||
D_POWERUSAGE ,
|
||||
D_POWER_FACTOR ,
|
||||
D_ENERGY_TODAY ,
|
||||
D_ENERGY_YESTERDAY ,
|
||||
D_ENERGY_TOTAL ,
|
||||
nullptr
|
||||
};
|
||||
|
||||
@ -149,6 +168,13 @@ const char *device_param_cb[] = {
|
||||
D_TIMER_OUTPUT " 8 " D_BUTTON_TOGGLE,
|
||||
D_REPLY " " D_TEMPERATURE, // Reply Temperature
|
||||
D_REPLY " " D_HUMIDITY, // Reply Humidity
|
||||
D_REPLY " " D_VOLTAGE ,
|
||||
D_REPLY " " D_CURRENT ,
|
||||
D_REPLY " " D_POWERUSAGE ,
|
||||
D_REPLY " " D_POWER_FACTOR ,
|
||||
D_REPLY " " D_ENERGY_TODAY ,
|
||||
D_REPLY " " D_ENERGY_YESTERDAY ,
|
||||
D_REPLY " " D_ENERGY_TOTAL ,
|
||||
nullptr
|
||||
};
|
||||
|
||||
@ -411,6 +437,17 @@ void KNX_INIT()
|
||||
if (GetUsedInModule(GPIO_DHT22, my_module.gp.io)) { device_param[KNX_HUMIDITY-1].show = true; }
|
||||
if (GetUsedInModule(GPIO_SI7021, my_module.gp.io)) { device_param[KNX_HUMIDITY-1].show = true; }
|
||||
|
||||
// Sonoff 31 or Sonoff Pow or any HLW8012 based device or Sonoff POW R2 or Any device with a Pzem004T
|
||||
if ( ( SONOFF_S31 == Settings.module ) || ( SONOFF_POW_R2 == Settings.module ) || ( energy_flg != ENERGY_NONE ) ) {
|
||||
device_param[KNX_ENERGY_POWER-1].show = true;
|
||||
device_param[KNX_ENERGY_DAILY-1].show = true;
|
||||
device_param[KNX_ENERGY_START-1].show = true;
|
||||
device_param[KNX_ENERGY_TOTAL-1].show = true;
|
||||
device_param[KNX_ENERGY_VOLTAGE-1].show = true;
|
||||
device_param[KNX_ENERGY_CURRENT-1].show = true;
|
||||
device_param[KNX_ENERGY_POWERFACTOR-1].show = true;
|
||||
}
|
||||
|
||||
// Delete from KNX settings all configuration is not anymore related to this device
|
||||
if (KNX_CONFIG_NOT_MATCH()) {
|
||||
Settings.knx_GA_registered = 0;
|
||||
@ -461,21 +498,38 @@ void KNX_CB_Action(message_t const &msg, void *arg)
|
||||
}
|
||||
else if (chan->type < 17) // Toggle Relays
|
||||
{
|
||||
ExecuteCommandPower((chan->type) -8, 2);
|
||||
if (!toggle_inhibit) {
|
||||
ExecuteCommandPower((chan->type) -8, 2);
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
toggle_inhibit = TOGGLE_INHIBIT_TIME;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KNX_CT_READ:
|
||||
if (chan->type < 9) // reply Relays status
|
||||
{
|
||||
knx.answer_1bit(msg.received_on, chan->last_state);
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
knx.answer_1bit(msg.received_on, chan->last_state);
|
||||
knx.answer_1bit(msg.received_on, chan->last_state);
|
||||
}
|
||||
}
|
||||
else if (chan->type = KNX_TEMPERATURE) // Reply Temperature
|
||||
{
|
||||
knx.answer_2byte_float(msg.received_on, last_temp);
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
knx.answer_2byte_float(msg.received_on, last_temp);
|
||||
knx.answer_2byte_float(msg.received_on, last_temp);
|
||||
}
|
||||
}
|
||||
else if (chan->type = KNX_HUMIDITY) // Reply Humidity
|
||||
{
|
||||
knx.answer_2byte_float(msg.received_on, last_hum);
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
knx.answer_2byte_float(msg.received_on, last_hum);
|
||||
knx.answer_2byte_float(msg.received_on, last_hum);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -493,6 +547,10 @@ void KnxUpdatePowerState(byte device, power_t state)
|
||||
while ( i != KNX_Empty ) {
|
||||
KNX_addr.value = Settings.knx_GA_addr[i];
|
||||
knx.write_1bit(KNX_addr, device_param[device -1].last_state);
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
knx.write_1bit(KNX_addr, device_param[device -1].last_state);
|
||||
knx.write_1bit(KNX_addr, device_param[device -1].last_state);
|
||||
}
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"),
|
||||
device_param_ga[device -1], device_param[device -1].last_state,
|
||||
@ -522,6 +580,10 @@ void KnxSendButtonPower(byte key, byte device, byte state)
|
||||
while ( i != KNX_Empty ) {
|
||||
KNX_addr.value = Settings.knx_GA_addr[i];
|
||||
knx.write_1bit(KNX_addr, !(state == 0));
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
knx.write_1bit(KNX_addr, !(state == 0));
|
||||
knx.write_1bit(KNX_addr, !(state == 0));
|
||||
}
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s = %d " D_SENT_TO " %d.%d.%d"),
|
||||
device_param_ga[device + 7], !(state == 0),
|
||||
@ -550,6 +612,10 @@ void KnxSensor(byte sensor_type, float value)
|
||||
while ( i != KNX_Empty ) {
|
||||
KNX_addr.value = Settings.knx_GA_addr[i];
|
||||
knx.write_2byte_float(KNX_addr, value);
|
||||
if (Settings.flag.knx_enable_enhancement) {
|
||||
knx.write_2byte_float(KNX_addr, value);
|
||||
knx.write_2byte_float(KNX_addr, value);
|
||||
}
|
||||
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX "%s " D_SENT_TO " %d.%d.%d "),
|
||||
device_param_ga[sensor_type -1],
|
||||
@ -578,8 +644,11 @@ const char HTTP_FORM_KNX[] PROGMEM =
|
||||
"<br/><br/>" D_KNX_PHYSICAL_ADDRESS_NOTE "<br/><br/>"
|
||||
"<input style='width:10%;' id='b1' name='b1' type='checkbox'";
|
||||
|
||||
const char HTTP_FORM_KNX1[] PROGMEM =
|
||||
"><b>" D_KNX_ENABLE " </b><input style='width:10%;' id='b2' name='b2' type='checkbox'";
|
||||
|
||||
const char HTTP_FORM_KNX2[] PROGMEM =
|
||||
"><b>" D_KNX_ENABLE "</b><br/></center><br/>"
|
||||
"><b>" D_KNX_ENHANCEMENT "</b><br/></center><br/>"
|
||||
|
||||
"<fieldset><center>"
|
||||
"<b>" D_KNX_GROUP_ADDRESS_TO_WRITE "</b><hr>"
|
||||
@ -696,6 +765,8 @@ void HandleKNXConfiguration()
|
||||
page.replace(F("{knl"), String(KNX_physs_addr.pa.line));
|
||||
page.replace(F("{knm"), String(KNX_physs_addr.pa.member));
|
||||
if ( Settings.flag.knx_enabled ) { page += F(" checked"); }
|
||||
page += FPSTR(HTTP_FORM_KNX1);
|
||||
if ( Settings.flag.knx_enable_enhancement ) { page += F(" checked"); }
|
||||
|
||||
page += FPSTR(HTTP_FORM_KNX2);
|
||||
for (byte i = 0; i < KNX_MAX_device_param ; i++)
|
||||
@ -822,8 +893,9 @@ void KNX_Save_Settings()
|
||||
address_t KNX_addr;
|
||||
|
||||
Settings.flag.knx_enabled = WebServer->hasArg("b1");
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_ENABLED ": %d "),
|
||||
Settings.flag.knx_enabled);
|
||||
Settings.flag.knx_enable_enhancement = WebServer->hasArg("b2");
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_KNX D_ENABLED ": %d, " D_KNX_ENHANCEMENT ": %d"),
|
||||
Settings.flag.knx_enabled, Settings.flag.knx_enable_enhancement );
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
|
||||
stmp = WebServer->arg("area");
|
||||
@ -883,6 +955,11 @@ boolean Xdrv11(byte function)
|
||||
case FUNC_LOOP:
|
||||
knx.loop(); // Process knx events
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
if (toggle_inhibit) {
|
||||
toggle_inhibit--;
|
||||
}
|
||||
break;
|
||||
// case FUNC_COMMAND:
|
||||
// result = KNXCommand();
|
||||
// break;
|
||||
|
@ -175,6 +175,11 @@ boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t
|
||||
return XdrvCall(FUNC_MQTT_DATA);
|
||||
}
|
||||
|
||||
boolean XdrvRulesProcess()
|
||||
{
|
||||
return XdrvCall(FUNC_RULES_PROCESS);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Function call to all xdrv
|
||||
*
|
||||
@ -188,6 +193,7 @@ boolean XdrvMqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uint16_t
|
||||
* FUNC_SHOW_SENSOR
|
||||
* FUNC_EVERY_SECOND
|
||||
* FUNC_EVERY_50_MSECOND
|
||||
* FUNC_RULES_PROCESS
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean XdrvCall(byte Function)
|
||||
|
@ -489,7 +489,7 @@ const char HueConfigResponse_JSON[] PROGMEM =
|
||||
"\"last use date\":\"{dt\","
|
||||
"\"create date\":\"{dt\","
|
||||
"\"name\":\"Remote\"}},"
|
||||
"\"swversion\":\"01039019\","
|
||||
"\"swversion\":\"01041302\","
|
||||
"\"apiversion\":\"1.17.0\","
|
||||
"\"swupdate\":{\"updatestate\":0,\"url\":\"\",\"text\":\"\",\"notify\": false},"
|
||||
"\"linkbutton\":false,"
|
||||
|
355
sonoff/xsns_25_sdm630.ino
Normal file
355
sonoff/xsns_25_sdm630.ino
Normal file
@ -0,0 +1,355 @@
|
||||
/*
|
||||
xsns_25_sdm630.ino - Eastron SDM630-Modbus energy meter support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2018 Gennaro Tortone
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_SDM630
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Eastron SDM630-Modbus energy meter
|
||||
*
|
||||
* Based on: https://github.com/reaper7/SDM_Energy_Meter
|
||||
\*********************************************************************************************/
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
TasmotaSerial *SDM630Serial;
|
||||
|
||||
uint8_t sdm630_type = 1;
|
||||
uint8_t sdm630_state = 0;
|
||||
|
||||
float sdm630_voltage[] = {0,0,0};
|
||||
float sdm630_current[] = {0,0,0};
|
||||
float sdm630_active_power[] = {0,0,0};
|
||||
float sdm630_reactive_power[] = {0,0,0};
|
||||
float sdm630_power_factor[] = {0,0,0};
|
||||
float sdm630_energy_total = 0;
|
||||
|
||||
bool SDM630_ModbusReceiveReady()
|
||||
{
|
||||
return (SDM630Serial->available() > 1);
|
||||
}
|
||||
|
||||
void SDM630_ModbusSend(uint8_t function_code, uint16_t start_address, uint16_t register_count)
|
||||
{
|
||||
uint8_t frame[8];
|
||||
|
||||
frame[0] = 0x01; // default SDM630 Modbus 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 = SDM630_calculateCRC(frame, 6); // calculate out crc only from first 6 bytes
|
||||
frame[6] = lowByte(crc);
|
||||
frame[7] = highByte(crc);
|
||||
|
||||
while (SDM630Serial->available() > 0) { // read serial if any old data is available
|
||||
SDM630Serial->read();
|
||||
}
|
||||
|
||||
SDM630Serial->flush();
|
||||
SDM630Serial->write(frame, sizeof(frame));
|
||||
}
|
||||
|
||||
uint8_t SDM630_ModbusReceive(float *value)
|
||||
{
|
||||
uint8_t buffer[9];
|
||||
|
||||
*value = NAN;
|
||||
uint8_t len = 0;
|
||||
while (SDM630Serial->available() > 0) {
|
||||
buffer[len++] = (uint8_t)SDM630Serial->read();
|
||||
}
|
||||
|
||||
if (len < 9)
|
||||
return 3; // SDM_ERR_NOT_ENOUGHT_BYTES
|
||||
|
||||
if (len == 9) {
|
||||
|
||||
if (buffer[0] == 0x01 && buffer[1] == 0x04 && buffer[2] == 4) { // check node number, op code and reply bytes count
|
||||
|
||||
if((SDM630_calculateCRC(buffer, 7)) == ((buffer[8] << 8) | buffer[7])) { //calculate crc from first 7 bytes and compare with received crc (bytes 7 & 8)
|
||||
|
||||
((uint8_t*)value)[3] = buffer[3];
|
||||
((uint8_t*)value)[2] = buffer[4];
|
||||
((uint8_t*)value)[1] = buffer[5];
|
||||
((uint8_t*)value)[0] = buffer[6];
|
||||
|
||||
} else return 1; // SDM_ERR_CRC_ERROR
|
||||
|
||||
} else return 2; // SDM_ERR_WRONG_BYTES
|
||||
}
|
||||
|
||||
return 0; // SDM_ERR_NO_ERROR
|
||||
}
|
||||
|
||||
uint16_t SDM630_calculateCRC(uint8_t *frame, uint8_t num)
|
||||
{
|
||||
uint16_t crc, flag;
|
||||
crc = 0xFFFF;
|
||||
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;
|
||||
}
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
const uint16_t sdm630_start_addresses[] {
|
||||
0x0000, // L1 - SDM630_VOLTAGE [V]
|
||||
0x0002, // L2 - SDM630_VOLTAGE [V]
|
||||
0x0004, // L3 - SDM630_VOLTAGE [V]
|
||||
0x0006, // L1 - SDM630_CURRENT [A]
|
||||
0x0008, // L2 - SDM630_CURRENT [A]
|
||||
0x000A, // L3 - SDM630_CURRENT [A]
|
||||
0x000C, // L1 - SDM630_POWER [W]
|
||||
0x000E, // L2 - SDM630_POWER [W]
|
||||
0x0010, // L3 - SDM630_POWER [W]
|
||||
0x0018, // L1 - SDM630_REACTIVE_POWER [VAR]
|
||||
0x001A, // L2 - SDM630_REACTIVE_POWER [VAR]
|
||||
0x001C, // L3 - SDM630_REACTIVE_POWER [VAR]
|
||||
0x001E, // L1 - SDM630_POWER_FACTOR
|
||||
0x0020, // L2 - SDM630_POWER_FACTOR
|
||||
0x0022, // L3 - SDM630_POWER_FACTOR
|
||||
0x0156 // Total - SDM630_TOTAL_ACTIVE_ENERGY [Wh]
|
||||
};
|
||||
|
||||
uint8_t sdm630_read_state = 0;
|
||||
uint8_t sdm630_send_retry = 0;
|
||||
|
||||
void SDM63050ms() // Every 50 mSec
|
||||
{
|
||||
sdm630_state++;
|
||||
if (6 == sdm630_state) { // Every 300 mSec
|
||||
sdm630_state = 0;
|
||||
|
||||
float value = 0;
|
||||
bool data_ready = SDM630_ModbusReceiveReady();
|
||||
|
||||
if (data_ready) {
|
||||
uint8_t error = SDM630_ModbusReceive(&value);
|
||||
if (error) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_DEBUG "SDM630 response error %d"), error);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
} else {
|
||||
switch(sdm630_read_state) {
|
||||
case 0:
|
||||
sdm630_voltage[0] = value;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
sdm630_voltage[1] = value;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
sdm630_voltage[2] = value;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
sdm630_current[0] = value;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
sdm630_current[1] = value;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
sdm630_current[2] = value;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
sdm630_active_power[0] = value;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
sdm630_active_power[1] = value;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
sdm630_active_power[2] = value;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
sdm630_reactive_power[0] = value;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
sdm630_reactive_power[1] = value;
|
||||
break;
|
||||
|
||||
case 11:
|
||||
sdm630_reactive_power[2] = value;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
sdm630_power_factor[0] = value;
|
||||
break;
|
||||
|
||||
case 13:
|
||||
sdm630_power_factor[1] = value;
|
||||
break;
|
||||
|
||||
case 14:
|
||||
sdm630_power_factor[2] = value;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
sdm630_energy_total = value;
|
||||
break;
|
||||
} // end switch
|
||||
|
||||
sdm630_read_state++;
|
||||
|
||||
if (sizeof(sdm630_start_addresses)/2 == sdm630_read_state) {
|
||||
sdm630_read_state = 0;
|
||||
}
|
||||
}
|
||||
} // end data ready
|
||||
|
||||
if (0 == sdm630_send_retry || data_ready) {
|
||||
sdm630_send_retry = 5;
|
||||
SDM630_ModbusSend(0x04, sdm630_start_addresses[sdm630_read_state], 2);
|
||||
} else {
|
||||
sdm630_send_retry--;
|
||||
}
|
||||
} // end 300 ms
|
||||
}
|
||||
|
||||
void SDM630Init()
|
||||
{
|
||||
sdm630_type = 0;
|
||||
if ((pin[GPIO_SDM630_RX] < 99) && (pin[GPIO_SDM630_TX] < 99)) {
|
||||
SDM630Serial = new TasmotaSerial(pin[GPIO_SDM630_RX], pin[GPIO_SDM630_TX], 1);
|
||||
#ifdef SDM630_SPEED
|
||||
if (SDM630Serial->begin(SDM630_SPEED)) {
|
||||
#else
|
||||
if (SDM630Serial->begin(2400)) {
|
||||
#endif
|
||||
if (SDM630Serial->hardwareSerial()) { ClaimSerial(); }
|
||||
sdm630_type = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_SDM630_DATA[] PROGMEM = "%s"
|
||||
"{s}SDM630 " D_VOLTAGE "{m}%s/%s/%s " D_UNIT_VOLT "{e}"
|
||||
"{s}SDM630 " D_CURRENT "{m}%s/%s/%s " D_UNIT_AMPERE "{e}"
|
||||
"{s}SDM630 " D_POWERUSAGE_ACTIVE "{m}%s/%s/%s " D_UNIT_WATT "{e}"
|
||||
"{s}SDM630 " D_POWERUSAGE_REACTIVE "{m}%s/%s/%s " D_UNIT_VAR "{e}"
|
||||
"{s}SDM630 " D_POWER_FACTOR "{m}%s/%s/%s{e}"
|
||||
"{s}SDM630 " D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}";
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void SDM630Show(boolean json)
|
||||
{
|
||||
char voltage_l1[10];
|
||||
char voltage_l2[10];
|
||||
char voltage_l3[10];
|
||||
char current_l1[10];
|
||||
char current_l2[10];
|
||||
char current_l3[10];
|
||||
char active_power_l1[10];
|
||||
char active_power_l2[10];
|
||||
char active_power_l3[10];
|
||||
char reactive_power_l1[10];
|
||||
char reactive_power_l2[10];
|
||||
char reactive_power_l3[10];
|
||||
char power_factor_l1[10];
|
||||
char power_factor_l2[10];
|
||||
char power_factor_l3[10];
|
||||
char energy_total[10];
|
||||
|
||||
dtostrfd(sdm630_voltage[0], Settings.flag2.voltage_resolution, voltage_l1);
|
||||
dtostrfd(sdm630_voltage[1], Settings.flag2.voltage_resolution, voltage_l2);
|
||||
dtostrfd(sdm630_voltage[2], Settings.flag2.voltage_resolution, voltage_l3);
|
||||
dtostrfd(sdm630_current[0], Settings.flag2.current_resolution, current_l1);
|
||||
dtostrfd(sdm630_current[1], Settings.flag2.current_resolution, current_l2);
|
||||
dtostrfd(sdm630_current[2], Settings.flag2.current_resolution, current_l3);
|
||||
dtostrfd(sdm630_active_power[0], Settings.flag2.wattage_resolution, active_power_l1);
|
||||
dtostrfd(sdm630_active_power[1], Settings.flag2.wattage_resolution, active_power_l2);
|
||||
dtostrfd(sdm630_active_power[2], Settings.flag2.wattage_resolution, active_power_l3);
|
||||
dtostrfd(sdm630_reactive_power[0], Settings.flag2.wattage_resolution, reactive_power_l1);
|
||||
dtostrfd(sdm630_reactive_power[1], Settings.flag2.wattage_resolution, reactive_power_l2);
|
||||
dtostrfd(sdm630_reactive_power[2], Settings.flag2.wattage_resolution, reactive_power_l3);
|
||||
dtostrfd(sdm630_power_factor[0], 2, power_factor_l1);
|
||||
dtostrfd(sdm630_power_factor[1], 2, power_factor_l2);
|
||||
dtostrfd(sdm630_power_factor[2], 2, power_factor_l3);
|
||||
dtostrfd(sdm630_energy_total, Settings.flag2.energy_resolution, energy_total);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\""
|
||||
D_JSON_ACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_REACTIVE_POWERUSAGE "\":[%s,%s,%s],\""
|
||||
D_JSON_POWERFACTOR "\":[%s,%s,%s],\"" D_JSON_VOLTAGE "\":[%s,%s,%s],\"" D_JSON_CURRENT "\":[%s,%s,%s]}"),
|
||||
mqtt_data, energy_total, active_power_l1, active_power_l2, active_power_l3,
|
||||
reactive_power_l1, reactive_power_l2, reactive_power_l3,
|
||||
power_factor_l1, power_factor_l2, power_factor_l3,
|
||||
voltage_l1, voltage_l2, voltage_l3,
|
||||
current_l1, current_l2, current_l3);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SDM630_DATA, mqtt_data,
|
||||
voltage_l1, voltage_l2, voltage_l3, current_l1, current_l2, current_l3,
|
||||
active_power_l1, active_power_l2, active_power_l3,
|
||||
reactive_power_l1, reactive_power_l2, reactive_power_l3,
|
||||
power_factor_l1, power_factor_l2, power_factor_l3, energy_total);
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_25
|
||||
|
||||
boolean Xsns25(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (sdm630_type) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
SDM630Init();
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
SDM63050ms();
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
SDM630Show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_APPEND:
|
||||
SDM630Show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
183
tools/decode-status.py
Normal file
183
tools/decode-status.py
Normal file
@ -0,0 +1,183 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
decode-status.py - decode status 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Requirements:
|
||||
- Python
|
||||
- pip json pycurl
|
||||
|
||||
Instructions:
|
||||
Execute command with option -d to retrieve status report from device or
|
||||
get a copy of the status message with http command http://sonoff/cm?cmnd=status%200
|
||||
and store it in file status.json
|
||||
|
||||
Usage:
|
||||
./decode-status.py -d <hostname or IP address>
|
||||
or
|
||||
./decode-status.py -f <JSON status information file>
|
||||
|
||||
Example:
|
||||
./decode-status.py -d sonoff1
|
||||
or
|
||||
./decode-status.py -f status.json
|
||||
"""
|
||||
|
||||
import io
|
||||
import os.path
|
||||
import json
|
||||
import pycurl
|
||||
from sys import exit
|
||||
from optparse import OptionParser
|
||||
from StringIO import StringIO
|
||||
|
||||
a_on_off = ["OFF","ON "]
|
||||
|
||||
a_setoption = [
|
||||
"Save power state and use after restart",
|
||||
"Restrict button actions to single, double and hold",
|
||||
"Show value units in JSON messages",
|
||||
"MQTT",
|
||||
"Respond as Command topic instead of RESULT",
|
||||
"MQTT retain on Power",
|
||||
"MQTT retain on Button",
|
||||
"MQTT retain on Switch",
|
||||
"Convert temperature to Fahrenheit",
|
||||
"MQTT retain on Sensor",
|
||||
"MQTT retained LWT to OFFLINE when topic changes",
|
||||
"Swap Single and Double press Button",
|
||||
"Do not use flash page rotate",
|
||||
"Button single press only",
|
||||
"Power interlock mode",
|
||||
"Do not allow PWM control",
|
||||
"Reverse clock",
|
||||
"Allow entry of decimal color values",
|
||||
"CO2 color to light signal",
|
||||
"HASS discovery",
|
||||
"Do not control Power with Dimmer",
|
||||
"Energy monitoring while powered off",
|
||||
"MQTT serial",
|
||||
"Rules",
|
||||
"Rules once mode",
|
||||
"KNX",
|
||||
"Use Power device index on single relay devices",
|
||||
"KNX enhancement",
|
||||
"","","",""]
|
||||
|
||||
a_features = [[
|
||||
"","","USE_I2C","USE_SPI",
|
||||
"USE_DISCOVERY","USE_ARDUINO_OTA","USE_MQTT_TLS","USE_WEBSERVER",
|
||||
"WEBSERVER_ADVERTISE","USE_EMULATION","MQTT_PUBSUBCLIENT","MQTT_TASMOTAMQTT",
|
||||
"MQTT_ESPMQTTARDUINO","MQTT_HOST_DISCOVERY","USE_ARILUX_RF","USE_WS2812",
|
||||
"USE_WS2812_DMA","USE_IR_REMOTE","USE_IR_HVAC","USE_IR_RECEIVE",
|
||||
"USE_DOMOTICZ","USE_DISPLAY","USE_HOME_ASSISTANT","USE_SERIAL_BRIDGE",
|
||||
"USE_TIMERS","USE_SUNRISE","USE_TIMERS_WEB","USE_RULES",
|
||||
"USE_KNX","","",""],[
|
||||
"USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_ALL_SENSORS","USE_CLASSIC",
|
||||
"USE_KNX_NO_EMULATION","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","VTABLES_IN_FLASH","PIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH",
|
||||
"PIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY","PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH","DEBUG_THEO","USE_DEBUG_DRIVER"],[
|
||||
"","USE_ADC_VCC","USE_ENERGY_SENSOR","USE_PZEM004T",
|
||||
"USE_DS18B20","USE_DS18x20_LEGACY","USE_DS18x20","USE_DHT",
|
||||
"USE_SHT","USE_HTU","USE_BMP","USE_BME680",
|
||||
"USE_BH1750","USE_VEML6070","USE_ADS1115_I2CDEV","USE_ADS1115",
|
||||
"USE_INA219","USE_SHT3X","USE_MHZ19","USE_TSL2561",
|
||||
"USE_SENSEAIR","USE_PMS5003","USE_MGS","USE_NOVA_SDS",
|
||||
"USE_SGP30","USE_SR04","USE_SDM120","USE_SI1145",
|
||||
"USE_SDM630","","",""],[
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","",""]]
|
||||
|
||||
usage = "usage: decode-status {-d | -f} arg"
|
||||
parser = OptionParser(usage)
|
||||
parser.add_option("-d", "--dev", action="store", type="string",
|
||||
dest="device", help="device to retrieve status from")
|
||||
parser.add_option("-f", "--file", metavar="FILE",
|
||||
dest="jsonfile", default="status.json", help="status json file (default: status.json)")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if (options.device):
|
||||
buffer = StringIO()
|
||||
url = str("http://{}/cm?cmnd=status%200".format(options.device))
|
||||
c = pycurl.Curl()
|
||||
c.setopt(c.URL, url)
|
||||
c.setopt(c.WRITEDATA, buffer)
|
||||
c.perform()
|
||||
c.close()
|
||||
body = buffer.getvalue()
|
||||
obj = json.loads(body)
|
||||
else:
|
||||
jsonfile = options.jsonfile
|
||||
fp = open(jsonfile, "r")
|
||||
obj = json.load(fp)
|
||||
fp.close()
|
||||
|
||||
def StartDecode():
|
||||
# print("Decoding\n{}".format(obj))
|
||||
|
||||
if ("Time" in obj["StatusSNS"]):
|
||||
time = str(" from status report taken at {}".format(obj["StatusSNS"]["Time"]))
|
||||
if ("FriendlyName" in obj["Status"]):
|
||||
print("\nDecoding information for device {}{}".format(obj["Status"]["FriendlyName"][0], time))
|
||||
|
||||
if ("SetOption" in obj["StatusLOG"]):
|
||||
options = []
|
||||
option = obj["StatusLOG"]["SetOption"][0]
|
||||
i_option = int(option,16)
|
||||
for i in range(len(a_setoption)):
|
||||
if (a_setoption[i]):
|
||||
state = (i_option >> i) & 1
|
||||
options.append(str("{0:2d} ({1}) {2}".format(i, a_on_off[state], a_setoption[i])))
|
||||
|
||||
print("\nOptions")
|
||||
for i in range(len(options)):
|
||||
print(" {}".format(options[i]))
|
||||
|
||||
|
||||
if ("Features" in obj["StatusMEM"]):
|
||||
features = []
|
||||
for f in range(5):
|
||||
feature = obj["StatusMEM"]["Features"][f]
|
||||
i_feature = int(feature,16)
|
||||
if (f == 0):
|
||||
features.append(str("Language LCID = {}".format(i_feature & 0xFFFF)))
|
||||
else:
|
||||
for i in range(len(a_features[f -1])):
|
||||
if ((i_feature >> i) & 1):
|
||||
features.append(a_features[f -1][i])
|
||||
|
||||
features.sort()
|
||||
print("\nFeatures")
|
||||
for i in range(len(features)):
|
||||
print(" {}".format(features[i]))
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
StartDecode()
|
||||
except Exception as e:
|
||||
print("E: {}".format(e))
|
83
tools/fw-server.py
Normal file
83
tools/fw-server.py
Normal file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
fw-server.py - firmware server for Sonoff-Tasmota OTA upgrade
|
||||
|
||||
Copyright (C) 2018 Gennaro Tortone
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Requirements:
|
||||
- Python3
|
||||
- pip install netifaces flask
|
||||
|
||||
Instructions:
|
||||
Copy Sonoff-Tasmota firmware binary files in 'fw' directory.
|
||||
A set of prebuilt files can be downloaded by Sonoff-Tasmota release page:
|
||||
https://github.com/arendst/Sonoff-Tasmota/releases
|
||||
|
||||
Configure your Sonoff-Tasmota device with your fw-server URL:
|
||||
Firmware Upgrade -> Upgrade by web server
|
||||
http://<ip_address>:5000/sonoff-minimal.bin
|
||||
|
||||
Usage:
|
||||
./fw-server.py -d <net_iface> (default: eth0)
|
||||
or
|
||||
./fw-server.py -i <ip_address>
|
||||
|
||||
Example:
|
||||
./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
|
||||
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)")
|
||||
parser.add_option("-i", "--ip", action="store", type="string",
|
||||
dest="ip", help="IP address to bind")
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
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)
|
||||
else:
|
||||
netip = options.ip
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route('/<filename>')
|
||||
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 __name__ == "__main__":
|
||||
try:
|
||||
app.run(host=netip)
|
||||
except Exception as e:
|
||||
print("E: {}".format(e))
|
3
tools/fw/README
Normal file
3
tools/fw/README
Normal file
@ -0,0 +1,3 @@
|
||||
Copy Sonoff-Tasmota firmware binary files in this directory.
|
||||
A set of prebuilt files can be downloaded by Sonoff-Tasmota release page:
|
||||
https://github.com/arendst/Sonoff-Tasmota/releases
|
Loading…
x
Reference in New Issue
Block a user