mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-30 14:16:32 +00:00
Merged from upstream
This commit is contained in:
commit
4a41c13738
@ -53,7 +53,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// this template method class is used to track the data being sent on the uart
|
// this template method class is used to track the data being sent on the uart
|
||||||
// when using our own UART ISR
|
// when using our own UART ISR
|
||||||
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
|
// used with NeoEsp8266Uart and NeoEsp8266AsyncUart classes
|
||||||
//
|
//
|
||||||
class NeoEsp8266UartInterruptContext : NeoEsp8266UartContext
|
class NeoEsp8266UartInterruptContext : NeoEsp8266UartContext
|
||||||
@ -77,12 +77,12 @@ public:
|
|||||||
private:
|
private:
|
||||||
volatile const uint8_t* _asyncBuff;
|
volatile const uint8_t* _asyncBuff;
|
||||||
volatile const uint8_t* _asyncBuffEnd;
|
volatile const uint8_t* _asyncBuffEnd;
|
||||||
volatile static NeoEsp8266UartInterruptContext* s_uartInteruptContext[2];
|
volatile static NeoEsp8266UartInterruptContext* s_uartInteruptContext[2];
|
||||||
|
|
||||||
static void ICACHE_RAM_ATTR Isr(void* param);
|
static void ICACHE_RAM_ATTR Isr(void* param);
|
||||||
};
|
};
|
||||||
|
|
||||||
// this template feature class is used a base for all others and contains
|
// this template feature class is used a base for all others and contains
|
||||||
// common methods
|
// common methods
|
||||||
//
|
//
|
||||||
class UartFeatureBase
|
class UartFeatureBase
|
||||||
@ -129,7 +129,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// this template method class is used a base for all others and contains
|
// this template method class is used a base for all others and contains
|
||||||
// common properties and methods
|
// common properties and methods
|
||||||
//
|
//
|
||||||
// used by NeoEsp8266Uart and NeoEsp8266AsyncUart
|
// used by NeoEsp8266Uart and NeoEsp8266AsyncUart
|
||||||
@ -233,14 +233,14 @@ protected:
|
|||||||
}
|
}
|
||||||
// detach context, which will disable intr, may disable ISR
|
// detach context, which will disable intr, may disable ISR
|
||||||
_context.Detach(T_UARTFEATURE::Index);
|
_context.Detach(T_UARTFEATURE::Index);
|
||||||
|
|
||||||
free(_pixelsSending);
|
free(_pixelsSending);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ICACHE_RAM_ATTR InitializeUart(uint32_t uartBaud)
|
void ICACHE_RAM_ATTR InitializeUart(uint32_t uartBaud)
|
||||||
{
|
{
|
||||||
T_UARTFEATURE::Init(uartBaud);
|
T_UARTFEATURE::Init(uartBaud);
|
||||||
|
|
||||||
// attach the context, which will enable the ISR
|
// attach the context, which will enable the ISR
|
||||||
_context.Attach(T_UARTFEATURE::Index);
|
_context.Attach(T_UARTFEATURE::Index);
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ protected:
|
|||||||
void UpdateUart(bool maintainBufferConsistency)
|
void UpdateUart(bool maintainBufferConsistency)
|
||||||
{
|
{
|
||||||
// Instruct ESP8266 hardware uart to send the pixels asynchronously
|
// Instruct ESP8266 hardware uart to send the pixels asynchronously
|
||||||
_context.StartSending(T_UARTFEATURE::Index,
|
_context.StartSending(T_UARTFEATURE::Index,
|
||||||
_pixels,
|
_pixels,
|
||||||
_pixels + _sizePixels);
|
_pixels + _sizePixels);
|
||||||
|
|
||||||
@ -264,7 +264,10 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// swap so the user can modify without affecting the async operation
|
// swap so the user can modify without affecting the async operation
|
||||||
std::swap(_pixelsSending, _pixels);
|
// std::swap(_pixelsSending, _pixels);
|
||||||
|
uint8_t *temp = _pixelsSending;
|
||||||
|
_pixelsSending = _pixels;
|
||||||
|
_pixels = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -383,7 +386,7 @@ private:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// uart 0
|
// uart 0
|
||||||
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Ws2812xMethod;
|
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2812x, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Ws2812xMethod;
|
||||||
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Sk6812Method;
|
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedSk6812, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Sk6812Method;
|
||||||
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Apa106Method;
|
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedApa106, NeoEsp8266Uart<UartFeature0, NeoEsp8266UartContext>> NeoEsp8266Uart0Apa106Method;
|
||||||
|
304
lib/SENDMAIL/sendemail.cpp
Executable file
304
lib/SENDMAIL/sendemail.cpp
Executable file
@ -0,0 +1,304 @@
|
|||||||
|
#include "sendemail.h"
|
||||||
|
|
||||||
|
// enable serial debugging
|
||||||
|
//#define DEBUG_EMAIL_PORT Serial
|
||||||
|
|
||||||
|
SendEmail::SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used) :
|
||||||
|
host(host), port(port), user(user), passwd(passwd), timeout(timeout), ssl(ssl), auth_used(auth_used), client(new WiFiClientSecure())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String SendEmail::readClient()
|
||||||
|
{
|
||||||
|
String r = client->readStringUntil('\n');
|
||||||
|
r.trim();
|
||||||
|
while (client->available()) {
|
||||||
|
delay(0);
|
||||||
|
r += client->readString();
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSerialBaudrate(int baudrate);
|
||||||
|
|
||||||
|
bool SendEmail::send(const String& from, const String& to, const String& subject, const String& msg)
|
||||||
|
{
|
||||||
|
if (!host.length())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
client->setTimeout(timeout);
|
||||||
|
// smtp connect
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
SetSerialBaudrate(115200);
|
||||||
|
DEBUG_EMAIL_PORT.print("Connecting: ");
|
||||||
|
DEBUG_EMAIL_PORT.print(host);
|
||||||
|
DEBUG_EMAIL_PORT.print(":");
|
||||||
|
DEBUG_EMAIL_PORT.println(port);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
|
||||||
|
#else
|
||||||
|
client->setInsecure();
|
||||||
|
bool mfln = client->probeMaxFragmentLength(host.c_str(), port, 512);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.printf("MFLN supported: %s\n", mfln ? "yes" : "no");
|
||||||
|
#endif
|
||||||
|
if (mfln) {
|
||||||
|
client->setBufferSizes(512, 512);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if (!client->connect(host.c_str(), port))
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println("Connection failed");
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("220")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
buffer = F("EHLO ");
|
||||||
|
buffer += client->localIP().toString();
|
||||||
|
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("250")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (user.length()>0 && passwd.length()>0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
//buffer = F("STARTTLS");
|
||||||
|
//client->println(buffer);
|
||||||
|
|
||||||
|
if (auth_used==1) {
|
||||||
|
// plain
|
||||||
|
#ifdef USE_PLAIN
|
||||||
|
buffer = F("AUTH PLAIN");
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("334")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char plainAuth[100];
|
||||||
|
memset(plainAuth,sizeof(plainAuth),0);
|
||||||
|
plainAuth[0] = '\0';
|
||||||
|
strcpy(&plainAuth[1], user.c_str());
|
||||||
|
strcpy(&plainAuth[2+user.length()],passwd.c_str());
|
||||||
|
const char* pA = (const char*)&plainAuth;
|
||||||
|
char buf[100];
|
||||||
|
base64_encode(buf, pA, user.length()+passwd.length()+2);
|
||||||
|
client->println(buf);
|
||||||
|
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buf);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("235")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
buffer = F("AUTH LOGIN");
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("334")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
base64 b;
|
||||||
|
//buffer = user;
|
||||||
|
//buffer = b.encode(buffer);
|
||||||
|
buffer = b.encode(user);
|
||||||
|
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
//DEBUG_EMAIL_PORT.println(user);
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("334")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//buffer = this->passwd;
|
||||||
|
//buffer = b.encode(buffer);
|
||||||
|
buffer = b.encode(passwd);
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
//DEBUG_EMAIL_PORT.println(passwd);
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("235")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// smtp send mail
|
||||||
|
buffer = F("MAIL FROM:");
|
||||||
|
buffer += from;
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("250")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer = F("RCPT TO:");
|
||||||
|
buffer += to;
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("250")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
buffer = F("DATA");
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = readClient();
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
if (!buffer.startsWith(F("354")))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buffer = F("From: ");
|
||||||
|
buffer += from;
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = F("To: ");
|
||||||
|
buffer += to;
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = F("Subject: ");
|
||||||
|
buffer += subject;
|
||||||
|
buffer += F("\r\n");
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = msg;
|
||||||
|
client->println(buffer);
|
||||||
|
client->println('.');
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
buffer = F("QUIT");
|
||||||
|
client->println(buffer);
|
||||||
|
#ifdef DEBUG_EMAIL_PORT
|
||||||
|
DEBUG_EMAIL_PORT.println(buffer);
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef USE_PLAIN
|
||||||
|
void SendEmail::a3_to_a4(unsigned char * a4, unsigned char * a3) {
|
||||||
|
a4[0] = (a3[0] & 0xfc) >> 2;
|
||||||
|
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
|
||||||
|
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
|
||||||
|
a4[3] = (a3[2] & 0x3f);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendEmail::base64_encode(char *output, const char *input, int inputLen) {
|
||||||
|
const char* _b64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
int i = 0, j = 0;
|
||||||
|
int encLen = 0;
|
||||||
|
unsigned char a3[3];
|
||||||
|
unsigned char a4[4];
|
||||||
|
while(inputLen--) {
|
||||||
|
a3[i++] = *(input++);
|
||||||
|
if(i == 3) {
|
||||||
|
a3_to_a4(a4, a3);
|
||||||
|
for(i = 0; i < 4; i++) {
|
||||||
|
output[encLen++] = _b64_alphabet[a4[i]];
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i) {
|
||||||
|
for(j = i; j < 3; j++) {
|
||||||
|
a3[j] = '\0';
|
||||||
|
}
|
||||||
|
a3_to_a4(a4, a3);
|
||||||
|
for(j = 0; j < i + 1; j++) {
|
||||||
|
output[encLen++] = _b64_alphabet[a4[j]];
|
||||||
|
}
|
||||||
|
while((i++ < 3)) {
|
||||||
|
output[encLen++] = '=';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output[encLen] = '\0';
|
||||||
|
return encLen;
|
||||||
|
}
|
||||||
|
#endif
|
39
lib/SENDMAIL/sendemail.h
Executable file
39
lib/SENDMAIL/sendemail.h
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __SENDEMAIL_H
|
||||||
|
#define __SENDEMAIL_H
|
||||||
|
|
||||||
|
//#define DEBUG_EMAIL_PORT
|
||||||
|
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
|
#include <base64.h>
|
||||||
|
#include <core_version.h>
|
||||||
|
|
||||||
|
class SendEmail
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const String host;
|
||||||
|
const int port;
|
||||||
|
const String user;
|
||||||
|
const String passwd;
|
||||||
|
const int timeout;
|
||||||
|
const bool ssl;
|
||||||
|
const int auth_used;
|
||||||
|
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
|
||||||
|
WiFiClient* client;
|
||||||
|
#else
|
||||||
|
// use bear ssl
|
||||||
|
// #include "WiFiClientSecureLightBearSSL.h"
|
||||||
|
// BearSSL::WiFiClientSecure_light *client;
|
||||||
|
BearSSL::WiFiClientSecure* client;
|
||||||
|
//WiFiClientSecure* client;
|
||||||
|
#endif
|
||||||
|
String readClient();
|
||||||
|
void a3_to_a4(unsigned char * a4, unsigned char * a3);
|
||||||
|
int base64_encode(char *output, const char *input, int inputLen);
|
||||||
|
public:
|
||||||
|
SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const int auth_used);
|
||||||
|
bool send(const String& from, const String& to, const String& subject, const String& msg);
|
||||||
|
~SendEmail() {client->stop(); delete client;}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,4 +1,12 @@
|
|||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
|
* 6.6.0.11 20190907
|
||||||
|
* Change Settings crc calculation allowing short term backward compatibility
|
||||||
|
*
|
||||||
|
* 6.6.0.10 20190905
|
||||||
|
* Redesign Tuya support by Shantur Rathore (#6353)
|
||||||
|
* Add command Reset 99 to reset bootcount to zero (#684, #6351)
|
||||||
|
* Change command Time 1/2/3 to select JSON time format ISO, ISO + Epoch or Epoch for legacy reason
|
||||||
|
*
|
||||||
* 6.6.0.9 20190828
|
* 6.6.0.9 20190828
|
||||||
* Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294)
|
* Change theoretical baudrate range to 300..19660500 bps in 300 increments (#6294)
|
||||||
* Add Full support of all protocols in IRremoteESP8266, to be used on dedicated-IR Tasmota version. Warning: +81k Flash when compiling with USE_IR_REMOTE_FULL
|
* Add Full support of all protocols in IRremoteESP8266, to be used on dedicated-IR Tasmota version. Warning: +81k Flash when compiling with USE_IR_REMOTE_FULL
|
||||||
@ -6,6 +14,9 @@
|
|||||||
* Add 'sonoff-ir' pre-packaged IR-dedicated firmware and 'sonoff-ircustom' to customize firmware with IR Full protocol support
|
* Add 'sonoff-ir' pre-packaged IR-dedicated firmware and 'sonoff-ircustom' to customize firmware with IR Full protocol support
|
||||||
* Add Zigbee support phase 2 - cc2530 initialization and basic ZCL decoding
|
* Add Zigbee support phase 2 - cc2530 initialization and basic ZCL decoding
|
||||||
* Add driver USE_SDM120_2 with Domoticz P1 Smart Meter functionality as future replacement for USE_SDM120 - Pls test and report
|
* Add driver USE_SDM120_2 with Domoticz P1 Smart Meter functionality as future replacement for USE_SDM120 - Pls test and report
|
||||||
|
* Add command Power0 0/1/2/Off/On/Toggle to control all power outputs at once (#6340)
|
||||||
|
* Add time to more events (#6337)
|
||||||
|
* Add command Time 1/2/3 to select JSON time format ISO + Epoch, ISO or Epoch
|
||||||
*
|
*
|
||||||
* 6.6.0.8 20190827
|
* 6.6.0.8 20190827
|
||||||
* Add Tuya Energy monitoring by Shantur Rathore
|
* Add Tuya Energy monitoring by Shantur Rathore
|
||||||
|
@ -96,6 +96,7 @@
|
|||||||
#define D_JSON_LOW "Low"
|
#define D_JSON_LOW "Low"
|
||||||
#define D_JSON_MAC "Mac"
|
#define D_JSON_MAC "Mac"
|
||||||
#define D_JSON_MASK "Mask"
|
#define D_JSON_MASK "Mask"
|
||||||
|
#define D_JSON_MEMORY_ERROR "Memory error"
|
||||||
#define D_JSON_MINIMAL "minimal"
|
#define D_JSON_MINIMAL "minimal"
|
||||||
#define D_JSON_MODEL "Model"
|
#define D_JSON_MODEL "Model"
|
||||||
#define D_JSON_MQTT_COUNT "MqttCount"
|
#define D_JSON_MQTT_COUNT "MqttCount"
|
||||||
@ -326,6 +327,7 @@
|
|||||||
#define D_CMND_WEBCOLOR "WebColor"
|
#define D_CMND_WEBCOLOR "WebColor"
|
||||||
#define D_CMND_WEBSENSOR "WebSensor"
|
#define D_CMND_WEBSENSOR "WebSensor"
|
||||||
#define D_CMND_EMULATION "Emulation"
|
#define D_CMND_EMULATION "Emulation"
|
||||||
|
#define D_CMND_SENDMAIL "Sendmail"
|
||||||
|
|
||||||
// Commands xdrv_03_energy.ino
|
// Commands xdrv_03_energy.ino
|
||||||
#define D_CMND_POWERLOW "PowerLow"
|
#define D_CMND_POWERLOW "PowerLow"
|
||||||
@ -444,6 +446,10 @@
|
|||||||
#define D_CMND_LATITUDE "Latitude"
|
#define D_CMND_LATITUDE "Latitude"
|
||||||
#define D_CMND_LONGITUDE "Longitude"
|
#define D_CMND_LONGITUDE "Longitude"
|
||||||
|
|
||||||
|
// Commands xdrv_16_tuyadimmer.ino
|
||||||
|
|
||||||
|
#define D_CMND_TUYA_MCU "TuyaMCU"
|
||||||
|
|
||||||
// Commands xdrv_23_zigbee.ino
|
// Commands xdrv_23_zigbee.ino
|
||||||
#define D_CMND_ZIGBEEZNPSEND "ZigbeeZNPSend"
|
#define D_CMND_ZIGBEEZNPSEND "ZigbeeZNPSend"
|
||||||
#define D_JSON_ZIGBEEZNPRECEIVED "ZigbeeZNPReceived"
|
#define D_JSON_ZIGBEEZNPRECEIVED "ZigbeeZNPReceived"
|
||||||
|
@ -147,9 +147,9 @@
|
|||||||
#define D_START "Start"
|
#define D_START "Start"
|
||||||
#define D_STD_TIME "STD"
|
#define D_STD_TIME "STD"
|
||||||
#define D_STOP "Stop"
|
#define D_STOP "Stop"
|
||||||
#define D_SUBNET_MASK "Maschera sottorete"
|
#define D_SUBNET_MASK "Maschera Subnet"
|
||||||
#define D_SUBSCRIBE_TO "Sottoscrivi a"
|
#define D_SUBSCRIBE_TO "Sottoscrivi a"
|
||||||
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
|
#define D_UNSUBSCRIBE_FROM "Cancella da"
|
||||||
#define D_SUCCESSFUL "Riuscito"
|
#define D_SUCCESSFUL "Riuscito"
|
||||||
#define D_SUNRISE "Alba"
|
#define D_SUNRISE "Alba"
|
||||||
#define D_SUNSET "Tramonto"
|
#define D_SUNSET "Tramonto"
|
||||||
@ -161,16 +161,16 @@
|
|||||||
#define D_TRANSMIT "Trasmesso"
|
#define D_TRANSMIT "Trasmesso"
|
||||||
#define D_TRUE "Vero"
|
#define D_TRUE "Vero"
|
||||||
#define D_TVOC "TVOC"
|
#define D_TVOC "TVOC"
|
||||||
#define D_UPGRADE "aggiornamento"
|
#define D_UPGRADE "Aggiornamento"
|
||||||
#define D_UPLOAD "Invio"
|
#define D_UPLOAD "Invio"
|
||||||
#define D_UPTIME "Uptime"
|
#define D_UPTIME "Uptime"
|
||||||
#define D_USER "Utente"
|
#define D_USER "Utente"
|
||||||
#define D_UTC_TIME "UTC"
|
#define D_UTC_TIME "UTC"
|
||||||
#define D_UV_INDEX "Indice UV"
|
#define D_UV_INDEX "Indice UV"
|
||||||
#define D_UV_INDEX_1 "Low"
|
#define D_UV_INDEX_1 "Basso"
|
||||||
#define D_UV_INDEX_2 "Mid"
|
#define D_UV_INDEX_2 "Medio"
|
||||||
#define D_UV_INDEX_3 "High"
|
#define D_UV_INDEX_3 "Alto"
|
||||||
#define D_UV_INDEX_4 "Danger"
|
#define D_UV_INDEX_4 "Pericolo"
|
||||||
#define D_UV_INDEX_5 "BurnL1/2"
|
#define D_UV_INDEX_5 "BurnL1/2"
|
||||||
#define D_UV_INDEX_6 "BurnL3"
|
#define D_UV_INDEX_6 "BurnL3"
|
||||||
#define D_UV_INDEX_7 "OoR"
|
#define D_UV_INDEX_7 "OoR"
|
||||||
@ -186,7 +186,7 @@
|
|||||||
#define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni"
|
#define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni"
|
||||||
#define D_LEVEL_10 "level 1-0"
|
#define D_LEVEL_10 "level 1-0"
|
||||||
#define D_LEVEL_01 "level 0-1"
|
#define D_LEVEL_01 "level 0-1"
|
||||||
#define D_SERIAL_LOGGING_DISABLED "Log seriale disabilitato"
|
#define D_SERIAL_LOGGING_DISABLED "Log Seriale disabilitato"
|
||||||
#define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato"
|
#define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato"
|
||||||
|
|
||||||
#define D_SET_BAUDRATE_TO "Baudrate impostato a"
|
#define D_SET_BAUDRATE_TO "Baudrate impostato a"
|
||||||
@ -198,11 +198,11 @@
|
|||||||
#define D_OSWATCH "osWatch"
|
#define D_OSWATCH "osWatch"
|
||||||
#define D_BLOCKED_LOOP "Ciclo Bloccato"
|
#define D_BLOCKED_LOOP "Ciclo Bloccato"
|
||||||
#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato"
|
#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato"
|
||||||
#define D_ACTIVE_FOR_3_MINUTES "attivo per 3 minuti"
|
#define D_ACTIVE_FOR_3_MINUTES "Attivo per 3 minuti"
|
||||||
#define D_FAILED_TO_START "partenza fallita"
|
#define D_FAILED_TO_START "partenza fallita"
|
||||||
#define D_PATCH_ISSUE_2186 "Patch issue 2186"
|
#define D_PATCH_ISSUE_2186 "Patch issue 2186"
|
||||||
#define D_CONNECTING_TO_AP "Connessione ad AP"
|
#define D_CONNECTING_TO_AP "Connessione ad AP"
|
||||||
#define D_IN_MODE "in modalità"
|
#define D_IN_MODE "In modalità"
|
||||||
#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto"
|
#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto"
|
||||||
#define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile"
|
#define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile"
|
||||||
#define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta"
|
#define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta"
|
||||||
@ -259,8 +259,8 @@
|
|||||||
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
|
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
|
||||||
#define D_ADC "ADC"
|
#define D_ADC "ADC"
|
||||||
#define D_GPIO "GPIO"
|
#define D_GPIO "GPIO"
|
||||||
#define D_SERIAL_IN "Serial In"
|
#define D_SERIAL_IN "Seriale In"
|
||||||
#define D_SERIAL_OUT "Serial Out"
|
#define D_SERIAL_OUT "Seriale Out"
|
||||||
|
|
||||||
#define D_WIFI_PARAMETERS "Parametri Wifi"
|
#define D_WIFI_PARAMETERS "Parametri Wifi"
|
||||||
#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi"
|
#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi"
|
||||||
@ -283,30 +283,30 @@
|
|||||||
#define D_FULL_TOPIC "Full Topic"
|
#define D_FULL_TOPIC "Full Topic"
|
||||||
|
|
||||||
#define D_LOGGING_PARAMETERS "Parametri Logging"
|
#define D_LOGGING_PARAMETERS "Parametri Logging"
|
||||||
#define D_SERIAL_LOG_LEVEL "Seriale livello di log"
|
#define D_SERIAL_LOG_LEVEL "Livello di log Seriale"
|
||||||
#define D_WEB_LOG_LEVEL "Web livello di log"
|
#define D_WEB_LOG_LEVEL "livello di log Web"
|
||||||
#define D_SYS_LOG_LEVEL "Sys livello di log"
|
#define D_SYS_LOG_LEVEL "livello di log Sys"
|
||||||
#define D_MORE_DEBUG "Debug aggiuntivo"
|
#define D_MORE_DEBUG "Debug aggiuntivo"
|
||||||
#define D_SYSLOG_HOST "Syslog host"
|
#define D_SYSLOG_HOST "Syslog host"
|
||||||
#define D_SYSLOG_PORT "Syslog porta"
|
#define D_SYSLOG_PORT "Syslog porta"
|
||||||
#define D_TELEMETRY_PERIOD "Periodo Telemetria"
|
#define D_TELEMETRY_PERIOD "Periodo Telemetria"
|
||||||
|
|
||||||
#define D_OTHER_PARAMETERS "Altri parametri"
|
#define D_OTHER_PARAMETERS "Altri parametri"
|
||||||
#define D_TEMPLATE "Template"
|
#define D_TEMPLATE "Modello"
|
||||||
#define D_ACTIVATE "Activate"
|
#define D_ACTIVATE "Attivare"
|
||||||
#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web"
|
#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web"
|
||||||
#define D_MQTT_ENABLE "Abilita MQTT"
|
#define D_MQTT_ENABLE "Abilita MQTT"
|
||||||
#define D_FRIENDLY_NAME "Nome confidenziale"
|
#define D_FRIENDLY_NAME "Nome amichevole"
|
||||||
#define D_BELKIN_WEMO "Belkin WeMo"
|
#define D_BELKIN_WEMO "Belkin WeMo"
|
||||||
#define D_HUE_BRIDGE "Hue Bridge"
|
#define D_HUE_BRIDGE "Hue Bridge"
|
||||||
#define D_SINGLE_DEVICE "dispositivo singolo"
|
#define D_SINGLE_DEVICE "dispositivo singolo"
|
||||||
#define D_MULTI_DEVICE "dispositivo multiplo"
|
#define D_MULTI_DEVICE "dispositivo multiplo"
|
||||||
|
|
||||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
#define D_CONFIGURE_TEMPLATE "Configurare Modello"
|
||||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
#define D_TEMPLATE_PARAMETERS "Parametri Modello"
|
||||||
#define D_TEMPLATE_NAME "Name"
|
#define D_TEMPLATE_NAME "Nome"
|
||||||
#define D_BASE_TYPE "Based on"
|
#define D_BASE_TYPE "Baseto nel"
|
||||||
#define D_TEMPLATE_FLAGS "Options"
|
#define D_TEMPLATE_FLAGS "Opzioni"
|
||||||
|
|
||||||
#define D_SAVE_CONFIGURATION "Salva configurazione"
|
#define D_SAVE_CONFIGURATION "Salva configurazione"
|
||||||
#define D_CONFIGURATION_SAVED "Configurazione salvata"
|
#define D_CONFIGURATION_SAVED "Configurazione salvata"
|
||||||
@ -464,12 +464,12 @@
|
|||||||
#define D_PARTICALS_BEYOND "Particelle"
|
#define D_PARTICALS_BEYOND "Particelle"
|
||||||
|
|
||||||
// xsns_32_mpu6050.ino
|
// xsns_32_mpu6050.ino
|
||||||
#define D_AX_AXIS "Accel. X-Axis"
|
#define D_AX_AXIS "Accel. Asse-X"
|
||||||
#define D_AY_AXIS "Accel. Y-Axis"
|
#define D_AY_AXIS "Accel. Asse-Y"
|
||||||
#define D_AZ_AXIS "Accel. Z-Axis"
|
#define D_AZ_AXIS "Accel. Asse-Z"
|
||||||
#define D_GX_AXIS "Gyro X-Axis"
|
#define D_GX_AXIS "Gyro Asse-X"
|
||||||
#define D_GY_AXIS "Gyro Y-Axis"
|
#define D_GY_AXIS "Gyro Asse-Y"
|
||||||
#define D_GZ_AXIS "Gyro Z-Axis"
|
#define D_GZ_AXIS "Gyro Asse-Z"
|
||||||
|
|
||||||
// xsns_34_hx711.ino
|
// xsns_34_hx711.ino
|
||||||
#define D_HX_CAL_REMOVE "Rimuovere peso"
|
#define D_HX_CAL_REMOVE "Rimuovere peso"
|
||||||
|
@ -65,8 +65,8 @@
|
|||||||
#define D_BY "por" // Write by me
|
#define D_BY "por" // Write by me
|
||||||
#define D_BYTES "Bytes"
|
#define D_BYTES "Bytes"
|
||||||
#define D_CELSIUS "Celsius"
|
#define D_CELSIUS "Celsius"
|
||||||
#define D_CHANNEL "Channel"
|
#define D_CHANNEL "Canal"
|
||||||
#define D_CO2 "Dióxido de carbono"
|
#define D_CO2 "CO2"
|
||||||
#define D_CODE "Código" // Button code
|
#define D_CODE "Código" // Button code
|
||||||
#define D_COLDLIGHT "Luz fria"
|
#define D_COLDLIGHT "Luz fria"
|
||||||
#define D_COMMAND "Comando"
|
#define D_COMMAND "Comando"
|
||||||
@ -93,14 +93,14 @@
|
|||||||
#define D_FALLBACK_TOPIC "Tópico para retornar"
|
#define D_FALLBACK_TOPIC "Tópico para retornar"
|
||||||
#define D_FALSE "Falso"
|
#define D_FALSE "Falso"
|
||||||
#define D_FILE "Arquivo"
|
#define D_FILE "Arquivo"
|
||||||
#define D_FLOW_RATE "Flow rate"
|
#define D_FLOW_RATE "Quociente de vazão"
|
||||||
#define D_FREE_MEMORY "Memória livre"
|
#define D_FREE_MEMORY "Memória livre"
|
||||||
#define D_FREQUENCY "Frequência"
|
#define D_FREQUENCY "Frequência"
|
||||||
#define D_GAS "Gás"
|
#define D_GAS "Gás"
|
||||||
#define D_GATEWAY "Gateway"
|
#define D_GATEWAY "Gateway"
|
||||||
#define D_GROUP "Grupo"
|
#define D_GROUP "Grupo"
|
||||||
#define D_HOST "Anfitrião"
|
#define D_HOST "Host"
|
||||||
#define D_HOSTNAME "Nome do anfitrião"
|
#define D_HOSTNAME "Nome do Host"
|
||||||
#define D_HUMIDITY "Umidade"
|
#define D_HUMIDITY "Umidade"
|
||||||
#define D_ILLUMINANCE "Luminância"
|
#define D_ILLUMINANCE "Luminância"
|
||||||
#define D_IMMEDIATE "Imediato" // Button immediate
|
#define D_IMMEDIATE "Imediato" // Button immediate
|
||||||
@ -167,10 +167,10 @@
|
|||||||
#define D_USER "Usuário"
|
#define D_USER "Usuário"
|
||||||
#define D_UTC_TIME "UTC"
|
#define D_UTC_TIME "UTC"
|
||||||
#define D_UV_INDEX "Índice UV"
|
#define D_UV_INDEX "Índice UV"
|
||||||
#define D_UV_INDEX_1 "Low"
|
#define D_UV_INDEX_1 "Baixo"
|
||||||
#define D_UV_INDEX_2 "Mid"
|
#define D_UV_INDEX_2 "Médio"
|
||||||
#define D_UV_INDEX_3 "High"
|
#define D_UV_INDEX_3 "Alto"
|
||||||
#define D_UV_INDEX_4 "Danger"
|
#define D_UV_INDEX_4 "Perigro"
|
||||||
#define D_UV_INDEX_5 "BurnL1/2"
|
#define D_UV_INDEX_5 "BurnL1/2"
|
||||||
#define D_UV_INDEX_6 "BurnL3"
|
#define D_UV_INDEX_6 "BurnL3"
|
||||||
#define D_UV_INDEX_7 "OoR"
|
#define D_UV_INDEX_7 "OoR"
|
||||||
@ -178,7 +178,7 @@
|
|||||||
#define D_UV_POWER "UV Power"
|
#define D_UV_POWER "UV Power"
|
||||||
#define D_VERSION "Versão"
|
#define D_VERSION "Versão"
|
||||||
#define D_VOLTAGE "Voltagem"
|
#define D_VOLTAGE "Voltagem"
|
||||||
#define D_WEIGHT "Weight"
|
#define D_WEIGHT "Peso"
|
||||||
#define D_WARMLIGHT "Luz quente"
|
#define D_WARMLIGHT "Luz quente"
|
||||||
#define D_WEB_SERVER "Servidor WEB"
|
#define D_WEB_SERVER "Servidor WEB"
|
||||||
|
|
||||||
@ -186,7 +186,7 @@
|
|||||||
#define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes"
|
#define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes"
|
||||||
#define D_LEVEL_10 "nível 1-0"
|
#define D_LEVEL_10 "nível 1-0"
|
||||||
#define D_LEVEL_01 "nível 0-1"
|
#define D_LEVEL_01 "nível 0-1"
|
||||||
#define D_SERIAL_LOGGING_DISABLED "Registro em série desabilitado"
|
#define D_SERIAL_LOGGING_DISABLED "Registro Serial desabilitado"
|
||||||
#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado"
|
#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado"
|
||||||
|
|
||||||
#define D_SET_BAUDRATE_TO "Ajuste da velocidade para"
|
#define D_SET_BAUDRATE_TO "Ajuste da velocidade para"
|
||||||
@ -292,7 +292,7 @@
|
|||||||
#define D_TELEMETRY_PERIOD "Período de telemetria"
|
#define D_TELEMETRY_PERIOD "Período de telemetria"
|
||||||
|
|
||||||
#define D_OTHER_PARAMETERS "Outros parâmetros"
|
#define D_OTHER_PARAMETERS "Outros parâmetros"
|
||||||
#define D_TEMPLATE "Template"
|
#define D_TEMPLATE "Modelo"
|
||||||
#define D_ACTIVATE "Activate"
|
#define D_ACTIVATE "Activate"
|
||||||
#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin"
|
#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin"
|
||||||
#define D_MQTT_ENABLE "MQTT habilitado"
|
#define D_MQTT_ENABLE "MQTT habilitado"
|
||||||
@ -302,11 +302,11 @@
|
|||||||
#define D_SINGLE_DEVICE "Dispositivo único"
|
#define D_SINGLE_DEVICE "Dispositivo único"
|
||||||
#define D_MULTI_DEVICE "Múltiplos dispositivos"
|
#define D_MULTI_DEVICE "Múltiplos dispositivos"
|
||||||
|
|
||||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
#define D_CONFIGURE_TEMPLATE "Configurar Modelo"
|
||||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
#define D_TEMPLATE_PARAMETERS "Parâmetros Modelo"
|
||||||
#define D_TEMPLATE_NAME "Name"
|
#define D_TEMPLATE_NAME "Nome"
|
||||||
#define D_BASE_TYPE "Based on"
|
#define D_BASE_TYPE "Baseado em"
|
||||||
#define D_TEMPLATE_FLAGS "Options"
|
#define D_TEMPLATE_FLAGS "Opções"
|
||||||
|
|
||||||
#define D_SAVE_CONFIGURATION "Gravar configuração"
|
#define D_SAVE_CONFIGURATION "Gravar configuração"
|
||||||
#define D_CONFIGURATION_SAVED "Configuração gravada"
|
#define D_CONFIGURATION_SAVED "Configuração gravada"
|
||||||
@ -347,10 +347,10 @@
|
|||||||
#define D_UPLOAD_ERR_7 "Envio cancelado"
|
#define D_UPLOAD_ERR_7 "Envio cancelado"
|
||||||
#define D_UPLOAD_ERR_8 "Arquivo inválido"
|
#define D_UPLOAD_ERR_8 "Arquivo inválido"
|
||||||
#define D_UPLOAD_ERR_9 "Arquivo muito grande"
|
#define D_UPLOAD_ERR_9 "Arquivo muito grande"
|
||||||
#define D_UPLOAD_ERR_10 "Failed to init RF chip"
|
#define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF"
|
||||||
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
|
#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF"
|
||||||
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
|
#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF"
|
||||||
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
|
#define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF"
|
||||||
#define D_UPLOAD_ERROR_CODE "Código de erro do envio"
|
#define D_UPLOAD_ERROR_CODE "Código de erro do envio"
|
||||||
|
|
||||||
#define D_ENTER_COMMAND "Inserir comando"
|
#define D_ENTER_COMMAND "Inserir comando"
|
||||||
@ -472,27 +472,27 @@
|
|||||||
#define D_GZ_AXIS "Gyro Z-Axis"
|
#define D_GZ_AXIS "Gyro Z-Axis"
|
||||||
|
|
||||||
// xsns_34_hx711.ino
|
// xsns_34_hx711.ino
|
||||||
#define D_HX_CAL_REMOVE "Remove weigth"
|
#define D_HX_CAL_REMOVE "Remover peso"
|
||||||
#define D_HX_CAL_REFERENCE "Load reference weigth"
|
#define D_HX_CAL_REFERENCE "Peso de referência de carga"
|
||||||
#define D_HX_CAL_DONE "Calibrated"
|
#define D_HX_CAL_DONE "Calibrado"
|
||||||
#define D_HX_CAL_FAIL "Calibration failed"
|
#define D_HX_CAL_FAIL "Falha na calibração"
|
||||||
#define D_RESET_HX711 "Reset Scale"
|
#define D_RESET_HX711 "Redefinir escala"
|
||||||
#define D_CONFIGURE_HX711 "Configure Scale"
|
#define D_CONFIGURE_HX711 "Configurar escala"
|
||||||
#define D_HX711_PARAMETERS "Scale parameters"
|
#define D_HX711_PARAMETERS "Parâmetros de escala"
|
||||||
#define D_ITEM_WEIGHT "Item weight"
|
#define D_ITEM_WEIGHT "Peso do Item"
|
||||||
#define D_REFERENCE_WEIGHT "Reference weigth"
|
#define D_REFERENCE_WEIGHT "Peso de referência"
|
||||||
#define D_CALIBRATE "Calibrate"
|
#define D_CALIBRATE "Calibrar"
|
||||||
#define D_CALIBRATION "Calibration"
|
#define D_CALIBRATION "Calibração"
|
||||||
|
|
||||||
//xsns_35_tx20.ino
|
//xsns_35_tx20.ino
|
||||||
#define D_TX20_WIND_DIRECTION "Wind Direction"
|
#define D_TX20_WIND_DIRECTION "Direção do vento"
|
||||||
#define D_TX20_WIND_SPEED "Wind Speed"
|
#define D_TX20_WIND_SPEED "Velocidade do vento"
|
||||||
#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg"
|
#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento"
|
||||||
#define D_TX20_WIND_SPEED_MAX "Wind Speed Max"
|
#define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima"
|
||||||
#define D_TX20_NORTH "N"
|
#define D_TX20_NORTH "N"
|
||||||
#define D_TX20_EAST "E"
|
#define D_TX20_EAST "L"
|
||||||
#define D_TX20_SOUTH "S"
|
#define D_TX20_SOUTH "S"
|
||||||
#define D_TX20_WEST "W"
|
#define D_TX20_WEST "O"
|
||||||
|
|
||||||
//xsns_43_hre.ino
|
//xsns_43_hre.ino
|
||||||
#define D_LOG_HRE "HRE: "
|
#define D_LOG_HRE "HRE: "
|
||||||
@ -657,37 +657,37 @@
|
|||||||
#define D_LOG_WIFI "WIF: " // Wifi
|
#define D_LOG_WIFI "WIF: " // Wifi
|
||||||
|
|
||||||
//SDM220
|
//SDM220
|
||||||
#define D_PHASE_ANGLE "Phase Angle"
|
#define D_PHASE_ANGLE "Ângulo de Fase"
|
||||||
#define D_IMPORT_ACTIVE "Import Active"
|
#define D_IMPORT_ACTIVE "Importar Ativo"
|
||||||
#define D_EXPORT_ACTIVE "Export Active"
|
#define D_EXPORT_ACTIVE "Exportar Ativo"
|
||||||
#define D_IMPORT_REACTIVE "Import Reactive"
|
#define D_IMPORT_REACTIVE "Importar Reativo"
|
||||||
#define D_EXPORT_REACTIVE "Export Reactive"
|
#define D_EXPORT_REACTIVE "Exportar Reativo"
|
||||||
#define D_TOTAL_REACTIVE "Total Reactive"
|
#define D_TOTAL_REACTIVE "Reativo total"
|
||||||
#define D_UNIT_KWARH "kVArh"
|
#define D_UNIT_KWARH "kVArh"
|
||||||
#define D_UNIT_ANGLE "Deg"
|
#define D_UNIT_ANGLE "Deg"
|
||||||
|
|
||||||
//SOLAXX1
|
//SOLAXX1
|
||||||
#define D_PV1_VOLTAGE "PV1 Voltage"
|
#define D_PV1_VOLTAGE "PV1 Voltagem"
|
||||||
#define D_PV1_CURRENT "PV1 Current"
|
#define D_PV1_CURRENT "PV1 Corrente"
|
||||||
#define D_PV1_POWER "PV1 Power"
|
#define D_PV1_POWER "PV1 Energia"
|
||||||
#define D_PV2_VOLTAGE "PV2 Voltage"
|
#define D_PV2_VOLTAGE "PV2 Voltagem"
|
||||||
#define D_PV2_CURRENT "PV2 Current"
|
#define D_PV2_CURRENT "PV2 Corrente"
|
||||||
#define D_PV2_POWER "PV2 Power"
|
#define D_PV2_POWER "PV2 Energia"
|
||||||
#define D_SOLAR_POWER "Solar Power"
|
#define D_SOLAR_POWER "Energia Solar"
|
||||||
#define D_INVERTER_POWER "Inverter Power"
|
#define D_INVERTER_POWER "Potência do Inversor"
|
||||||
#define D_STATUS "Status"
|
#define D_STATUS "Status"
|
||||||
#define D_WAITING "Waiting"
|
#define D_WAITING "Esperando"
|
||||||
#define D_CHECKING "Checking"
|
#define D_CHECKING "Verificando"
|
||||||
#define D_WORKING "Working"
|
#define D_WORKING "Trabalhando"
|
||||||
#define D_FAILURE "Failure"
|
#define D_FAILURE "Falha"
|
||||||
#define D_SOLAX_ERROR_0 "No Error Code"
|
#define D_SOLAX_ERROR_0 "Nenhum código de erro"
|
||||||
#define D_SOLAX_ERROR_1 "Grid Lost Fault"
|
#define D_SOLAX_ERROR_1 "Erro Grid Perdida"
|
||||||
#define D_SOLAX_ERROR_2 "Grid Voltage Fault"
|
#define D_SOLAX_ERROR_2 "Falha na Tensão da rede"
|
||||||
#define D_SOLAX_ERROR_3 "Grid Frequency Fault"
|
#define D_SOLAX_ERROR_3 "Falha na Frequência do Grid"
|
||||||
#define D_SOLAX_ERROR_4 "Pv Voltage Fault"
|
#define D_SOLAX_ERROR_4 "Pv Falha de Tensão"
|
||||||
#define D_SOLAX_ERROR_5 "Isolation Fault"
|
#define D_SOLAX_ERROR_5 "Falha de Isolamento"
|
||||||
#define D_SOLAX_ERROR_6 "Over Temperature Fault"
|
#define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva"
|
||||||
#define D_SOLAX_ERROR_7 "Fan Fault"
|
#define D_SOLAX_ERROR_7 "Falha no Ventilador"
|
||||||
#define D_SOLAX_ERROR_8 "Other Device Fault"
|
#define D_SOLAX_ERROR_8 "Outra falha do dispositivo"
|
||||||
|
|
||||||
#endif // _LANGUAGE_PT_BR_H_
|
#endif // _LANGUAGE_PT_BR_H_
|
||||||
|
@ -307,7 +307,7 @@
|
|||||||
// -- Optional modules ----------------------------
|
// -- Optional modules ----------------------------
|
||||||
#define USE_BUZZER // Add support for a buzzer (+0k6 code)
|
#define USE_BUZZER // Add support for a buzzer (+0k6 code)
|
||||||
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
||||||
#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer
|
#define USE_TUYA_MCU // Add support for Tuya Serial MCU
|
||||||
#define TUYA_DIMMER_ID 0 // Default dimmer Id
|
#define TUYA_DIMMER_ID 0 // Default dimmer Id
|
||||||
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
|
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
|
||||||
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||||
|
@ -78,7 +78,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
|
|||||||
uint32_t no_hold_retain : 1; // bit 12 (v6.4.1.19) - SetOption62 - Don't use retain flag on HOLD messages
|
uint32_t no_hold_retain : 1; // bit 12 (v6.4.1.19) - SetOption62 - Don't use retain flag on HOLD messages
|
||||||
uint32_t no_power_feedback : 1; // bit 13 (v6.5.0.9) - SetOption63 - Don't scan relay power state at restart
|
uint32_t no_power_feedback : 1; // bit 13 (v6.5.0.9) - SetOption63 - Don't scan relay power state at restart
|
||||||
uint32_t use_underscore : 1; // bit 14 (v6.5.0.12) - SetOption64 - Enable "_" instead of "-" as sensor index separator
|
uint32_t use_underscore : 1; // bit 14 (v6.5.0.12) - SetOption64 - Enable "_" instead of "-" as sensor index separator
|
||||||
uint32_t tuya_disable_dimmer : 1; // bit 15 (v6.5.0.15) - SetOption65 - Enable or Disable Tuya Serial Dimmer control
|
uint32_t ex_tuya_disable_dimmer : 1; // bit 15 (v6.5.0.15) - SetOption65 - (Enable or Disable Tuya Serial Dimmer control) - free since 6.6.0.10
|
||||||
uint32_t tuya_dimmer_range_255 : 1; // bit 16 (v6.6.0.1) - SetOption66 - Enable or Disable Dimmer range 255 slider control
|
uint32_t tuya_dimmer_range_255 : 1; // bit 16 (v6.6.0.1) - SetOption66 - Enable or Disable Dimmer range 255 slider control
|
||||||
uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available
|
uint32_t buzzer_enable : 1; // bit 17 (v6.6.0.1) - SetOption67 - Enable buzzer when available
|
||||||
uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM
|
uint32_t pwm_multi_channels : 1; // bit 18 (v6.6.0.3) - SetOption68 - Enable multi-channels PWM instead of Color PWM
|
||||||
@ -105,8 +105,7 @@ typedef union {
|
|||||||
uint32_t spare01 : 1;
|
uint32_t spare01 : 1;
|
||||||
uint32_t spare02 : 1;
|
uint32_t spare02 : 1;
|
||||||
uint32_t spare03 : 1;
|
uint32_t spare03 : 1;
|
||||||
uint32_t spare04 : 1;
|
uint32_t time_format : 2; // (v6.6.0.9) - CMND_TIME
|
||||||
uint32_t spare05 : 1;
|
|
||||||
uint32_t calc_resolution : 3;
|
uint32_t calc_resolution : 3;
|
||||||
uint32_t weight_resolution : 2;
|
uint32_t weight_resolution : 2;
|
||||||
uint32_t frequency_resolution : 2;
|
uint32_t frequency_resolution : 2;
|
||||||
@ -186,6 +185,14 @@ typedef struct {
|
|||||||
uint32_t last_return_kWhtotal;
|
uint32_t last_return_kWhtotal;
|
||||||
} EnergyUsage;
|
} EnergyUsage;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t fnid = 0;
|
||||||
|
uint8_t dpid = 0;
|
||||||
|
} TuyaFnidDpidMap;
|
||||||
|
|
||||||
|
const uint8_t MAX_TUYA_FUNCTIONS = 16;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
struct SYSCFG {
|
struct SYSCFG {
|
||||||
unsigned long cfg_holder; // 000 Pre v6 header
|
unsigned long cfg_holder; // 000 Pre v6 header
|
||||||
@ -364,6 +371,7 @@ struct SYSCFG {
|
|||||||
unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight
|
unsigned long energy_frequency_calibration; // 7C8 also used by HX711 to save last weight
|
||||||
uint16_t web_refresh; // 7CC
|
uint16_t web_refresh; // 7CC
|
||||||
char mems[MAX_RULE_MEMS][10]; // 7CE
|
char mems[MAX_RULE_MEMS][10]; // 7CE
|
||||||
|
<<<<<<< HEAD
|
||||||
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
|
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
|
||||||
uint8_t data8[32]; // E00
|
uint8_t data8[32]; // E00
|
||||||
uint16_t data16[16]; // E20
|
uint16_t data16[16]; // E20
|
||||||
@ -372,8 +380,15 @@ struct SYSCFG {
|
|||||||
|
|
||||||
uint8_t free_e20[432]; // E50
|
uint8_t free_e20[432]; // E50
|
||||||
|
|
||||||
|
=======
|
||||||
|
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
|
||||||
|
TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes
|
||||||
|
|
||||||
// FFF last location
|
uint8_t free_e20[472]; // E20
|
||||||
|
>>>>>>> upstream/development
|
||||||
|
|
||||||
|
uint32_t cfg_timestamp; // FF8
|
||||||
|
uint32_t cfg_crc32; // FFC
|
||||||
} Settings;
|
} Settings;
|
||||||
|
|
||||||
struct RTCRBT {
|
struct RTCRBT {
|
||||||
|
@ -273,8 +273,8 @@ const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses
|
|||||||
// Version 5.2 allow for more flash space
|
// Version 5.2 allow for more flash space
|
||||||
const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads)
|
const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads)
|
||||||
|
|
||||||
uint16_t settings_crc = 0;
|
|
||||||
uint32_t settings_location = SETTINGS_LOCATION;
|
uint32_t settings_location = SETTINGS_LOCATION;
|
||||||
|
uint32_t settings_crc32 = 0;
|
||||||
uint8_t *settings_buffer = nullptr;
|
uint8_t *settings_buffer = nullptr;
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
@ -318,19 +318,42 @@ bool SettingsBufferAlloc(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t GetSettingsCrc(void)
|
uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size)
|
||||||
{
|
{
|
||||||
uint16_t crc = 0;
|
uint16_t crc = 0;
|
||||||
uint8_t *bytes = (uint8_t*)&Settings;
|
|
||||||
|
|
||||||
// Fix miscalculation if previous Settings was 3584 and current Settings is 4096 as of 0x06060007
|
|
||||||
uint32_t size = (Settings.version < 0x06060007) ? 3584 : sizeof(SYSCFG);
|
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } // Skip crc
|
if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } // Skip crc
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t GetSettingsCrc(void)
|
||||||
|
{
|
||||||
|
// Fix miscalculation if previous Settings was 3584 and current Settings is 4096 between 0x06060007 and 0x0606000A
|
||||||
|
uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG);
|
||||||
|
return GetCfgCrc16((uint8_t*)&Settings, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size)
|
||||||
|
{
|
||||||
|
// https://create.stephan-brumme.com/crc32/#bitwise
|
||||||
|
uint32_t crc = 0;
|
||||||
|
|
||||||
|
while (size--) {
|
||||||
|
crc ^= *bytes++;
|
||||||
|
for (uint32_t j = 0; j < 8; j++) {
|
||||||
|
crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GetSettingsCrc32(void)
|
||||||
|
{
|
||||||
|
return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); // Skip crc32
|
||||||
|
}
|
||||||
|
|
||||||
void SettingsSaveAll(void)
|
void SettingsSaveAll(void)
|
||||||
{
|
{
|
||||||
if (Settings.flag.save_state) {
|
if (Settings.flag.save_state) {
|
||||||
@ -340,9 +363,6 @@ void SettingsSaveAll(void)
|
|||||||
}
|
}
|
||||||
XsnsCall(FUNC_SAVE_BEFORE_RESTART);
|
XsnsCall(FUNC_SAVE_BEFORE_RESTART);
|
||||||
XdrvCall(FUNC_SAVE_BEFORE_RESTART);
|
XdrvCall(FUNC_SAVE_BEFORE_RESTART);
|
||||||
#ifdef USE_EEPROM
|
|
||||||
EepromCommit();
|
|
||||||
#endif
|
|
||||||
SettingsSave(0);
|
SettingsSave(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +386,7 @@ void SettingsSave(uint8_t rotate)
|
|||||||
* stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1)
|
* stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1)
|
||||||
*/
|
*/
|
||||||
#ifndef FIRMWARE_MINIMAL
|
#ifndef FIRMWARE_MINIMAL
|
||||||
if ((GetSettingsCrc() != settings_crc) || rotate) {
|
if ((GetSettingsCrc32() != settings_crc32) || rotate) {
|
||||||
if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade)
|
if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade)
|
||||||
stop_flash_rotate = 1;
|
stop_flash_rotate = 1;
|
||||||
}
|
}
|
||||||
@ -381,32 +401,19 @@ void SettingsSave(uint8_t rotate)
|
|||||||
settings_location = SETTINGS_LOCATION;
|
settings_location = SETTINGS_LOCATION;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Settings.save_flag++;
|
|
||||||
Settings.cfg_size = sizeof(SYSCFG);
|
|
||||||
Settings.cfg_crc = GetSettingsCrc();
|
|
||||||
|
|
||||||
#ifdef USE_EEPROM
|
Settings.save_flag++;
|
||||||
if (SPIFFS_END == settings_location) {
|
if (UtcTime() > START_VALID_TIME) {
|
||||||
uint8_t* flash_buffer;
|
Settings.cfg_timestamp = UtcTime();
|
||||||
flash_buffer = new uint8_t[SPI_FLASH_SEC_SIZE];
|
|
||||||
if (eeprom_data && eeprom_size) {
|
|
||||||
size_t flash_offset = SPI_FLASH_SEC_SIZE - eeprom_size;
|
|
||||||
memcpy(flash_buffer + flash_offset, eeprom_data, eeprom_size); // Write dirty EEPROM data
|
|
||||||
} else {
|
|
||||||
ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)flash_buffer, SPI_FLASH_SEC_SIZE); // Read EEPROM area
|
|
||||||
}
|
|
||||||
memcpy(flash_buffer, &Settings, sizeof(Settings));
|
|
||||||
ESP.flashEraseSector(settings_location);
|
|
||||||
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)flash_buffer, SPI_FLASH_SEC_SIZE);
|
|
||||||
delete[] flash_buffer;
|
|
||||||
} else {
|
} else {
|
||||||
ESP.flashEraseSector(settings_location);
|
Settings.cfg_timestamp++;
|
||||||
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
|
|
||||||
}
|
}
|
||||||
#else
|
Settings.cfg_size = sizeof(SYSCFG);
|
||||||
|
Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade
|
||||||
|
Settings.cfg_crc32 = GetSettingsCrc32();
|
||||||
|
|
||||||
ESP.flashEraseSector(settings_location);
|
ESP.flashEraseSector(settings_location);
|
||||||
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
|
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
|
||||||
#endif // USE_EEPROM
|
|
||||||
|
|
||||||
if (!stop_flash_rotate && rotate) {
|
if (!stop_flash_rotate && rotate) {
|
||||||
for (uint32_t i = 1; i < CFG_ROTATES; i++) {
|
for (uint32_t i = 1; i < CFG_ROTATES; i++) {
|
||||||
@ -417,7 +424,7 @@ void SettingsSave(uint8_t rotate)
|
|||||||
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG));
|
||||||
|
|
||||||
settings_crc = Settings.cfg_crc;
|
settings_crc32 = Settings.cfg_crc32;
|
||||||
}
|
}
|
||||||
#endif // FIRMWARE_MINIMAL
|
#endif // FIRMWARE_MINIMAL
|
||||||
RtcSettingsSave();
|
RtcSettingsSave();
|
||||||
@ -442,7 +449,10 @@ void SettingsLoad(void)
|
|||||||
|
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
if (Settings.version > 0x06000000) {
|
if (Settings.version > 0x06000000) {
|
||||||
bool almost_valid = (Settings.cfg_crc == GetSettingsCrc());
|
bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32());
|
||||||
|
if (Settings.version < 0x0606000B) {
|
||||||
|
almost_valid = (Settings.cfg_crc == GetSettingsCrc());
|
||||||
|
}
|
||||||
// Sometimes CRC on pages below FB, overwritten by OTA, is fine but Settings are still invalid. So check cfg_holder too
|
// Sometimes CRC on pages below FB, overwritten by OTA, is fine but Settings are still invalid. So check cfg_holder too
|
||||||
if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder
|
if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder
|
||||||
valid = (cfg_holder == Settings.cfg_holder);
|
valid = (cfg_holder == Settings.cfg_holder);
|
||||||
@ -471,7 +481,7 @@ void SettingsLoad(void)
|
|||||||
if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h
|
if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h
|
||||||
SettingsDefault();
|
SettingsDefault();
|
||||||
}
|
}
|
||||||
settings_crc = GetSettingsCrc();
|
settings_crc32 = GetSettingsCrc32();
|
||||||
#endif // FIRMWARE_MINIMAL
|
#endif // FIRMWARE_MINIMAL
|
||||||
|
|
||||||
RtcSettingsLoad();
|
RtcSettingsLoad();
|
||||||
@ -1096,6 +1106,41 @@ void SettingsDelta(void)
|
|||||||
Settings.sbaudrate = Settings.ex_sbaudrate * 4;
|
Settings.sbaudrate = Settings.ex_sbaudrate * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Settings.version < 0x0606000A) {
|
||||||
|
uint8_t tuyaindex = 0;
|
||||||
|
if (Settings.param[P_ex_TUYA_DIMMER_ID] > 0) { // ex SetOption34
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].fnid = 21; // TUYA_MCU_FUNC_DIMMER - Move Tuya Dimmer Id to Map
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_DIMMER_ID];
|
||||||
|
tuyaindex++;
|
||||||
|
} else if (Settings.flag3.ex_tuya_disable_dimmer == 1) { // ex SetOption65
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].fnid = 11; // TUYA_MCU_FUNC_REL1 - Create FnID for Switches
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].dpid = 1;
|
||||||
|
tuyaindex++;
|
||||||
|
}
|
||||||
|
if (Settings.param[P_ex_TUYA_RELAYS] > 0) {
|
||||||
|
for (uint8_t i = 0 ; i < Settings.param[P_ex_TUYA_RELAYS]; i++) { // ex SetOption41
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].fnid = 12 + i; // TUYA_MCU_FUNC_REL2 - Create FnID for Switches
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].dpid = i + 2;
|
||||||
|
tuyaindex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Settings.param[P_ex_TUYA_POWER_ID] > 0) { // ex SetOption46
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].fnid = 31; // TUYA_MCU_FUNC_POWER - Move Tuya Power Id to Map
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_POWER_ID];
|
||||||
|
tuyaindex++;
|
||||||
|
}
|
||||||
|
if (Settings.param[P_ex_TUYA_VOLTAGE_ID] > 0) { // ex SetOption44
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].fnid = 33; // TUYA_MCU_FUNC_VOLTAGE - Move Tuya Voltage Id to Map
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_VOLTAGE_ID];
|
||||||
|
tuyaindex++;
|
||||||
|
}
|
||||||
|
if (Settings.param[P_ex_TUYA_CURRENT_ID] > 0) { // ex SetOption45
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].fnid = 32; // TUYA_MCU_FUNC_CURRENT - Move Tuya Current Id to Map
|
||||||
|
Settings.tuya_fnid_map[tuyaindex].dpid = Settings.param[P_ex_TUYA_CURRENT_ID];
|
||||||
|
tuyaindex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Settings.version = VERSION;
|
Settings.version = VERSION;
|
||||||
SettingsSave(1);
|
SettingsSave(1);
|
||||||
}
|
}
|
||||||
|
@ -130,6 +130,8 @@ const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms
|
|||||||
const uint32_t ZIGBEE_POLLING = 100; // Serial receive polling in ms
|
const uint32_t ZIGBEE_POLLING = 100; // Serial receive polling in ms
|
||||||
const uint8_t MAX_STATUS = 11; // Max number of status lines
|
const uint8_t MAX_STATUS = 11; // Max number of status lines
|
||||||
|
|
||||||
|
const uint32_t START_VALID_TIME = 1451602800; // Time is synced and after 2016-01-01
|
||||||
|
|
||||||
const uint32_t DRIVER_BOOT_DELAY = 1; // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting
|
const uint32_t DRIVER_BOOT_DELAY = 1; // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting
|
||||||
const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to go through the main loop using delay when needed
|
const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to go through the main loop using delay when needed
|
||||||
|
|
||||||
@ -231,7 +233,11 @@ enum EmulationOptions {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
|
|||||||
|
|
||||||
enum TopicOptions { CMND, STAT, TELE, nu1, RESULT_OR_CMND, RESULT_OR_STAT, RESULT_OR_TELE };
|
enum TopicOptions { CMND, STAT, TELE, nu1, RESULT_OR_CMND, RESULT_OR_STAT, RESULT_OR_TELE };
|
||||||
|
|
||||||
enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP, power_nu1, POWER_OFF_NO_STATE, POWER_ON_NO_STATE, power_nu2, POWER_SHOW_STATE };
|
enum ExecuteCommandPowerOptions { POWER_OFF, POWER_ON, POWER_TOGGLE, POWER_BLINK, POWER_BLINK_STOP,
|
||||||
|
POWER_OFF_NO_STATE = 8, POWER_ON_NO_STATE, POWER_TOGGLE_NO_STATE,
|
||||||
|
POWER_SHOW_STATE = 16 };
|
||||||
|
enum SendKeyPowerOptions { POWER_HOLD = 3, CLEAR_RETAIN = 9 };
|
||||||
|
enum SendKeyOptions { KEY_BUTTON, KEY_SWITCH };
|
||||||
|
|
||||||
enum PowerOnStateOptions { POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON };
|
enum PowerOnStateOptions { POWER_ALL_OFF, POWER_ALL_ON, POWER_ALL_SAVED_TOGGLE, POWER_ALL_SAVED, POWER_ALL_ALWAYS_ON, POWER_ALL_OFF_PULSETIME_ON };
|
||||||
|
|
||||||
@ -239,9 +245,9 @@ enum ButtonStates { PRESSED, NOT_PRESSED };
|
|||||||
|
|
||||||
enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER };
|
enum Shortcuts { SC_CLEAR, SC_DEFAULT, SC_USER };
|
||||||
|
|
||||||
enum SettingsParamIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38
|
enum SettingsParamIndex {P_HOLD_TIME, P_MAX_POWER_RETRY, P_ex_TUYA_DIMMER_ID, P_MDNS_DELAYED_START, P_BOOT_LOOP_OFFSET, P_RGB_REMAP, P_IR_UNKNOW_THRESHOLD, // SetOption32 .. SetOption38
|
||||||
P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42
|
P_CSE7766_INVALID_POWER, P_HOLD_IGNORE, P_ex_TUYA_RELAYS, P_OVER_TEMP, // SetOption39 .. SetOption42
|
||||||
P_TUYA_DIMMER_MAX, P_TUYA_VOLTAGE_ID, P_TUYA_CURRENT_ID, P_TUYA_POWER_ID, // SetOption43 .. SetOption46
|
P_TUYA_DIMMER_MAX, P_ex_TUYA_VOLTAGE_ID, P_ex_TUYA_CURRENT_ID, P_ex_TUYA_POWER_ID, // SetOption43 .. SetOption46
|
||||||
P_ENERGY_TARIFF1, P_ENERGY_TARIFF2, // SetOption47 .. SetOption48
|
P_ENERGY_TARIFF1, P_ENERGY_TARIFF2, // SetOption47 .. SetOption48
|
||||||
P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49
|
P_MAX_PARAM8}; // Max is PARAM8_SIZE (18) - SetOption32 until SetOption49
|
||||||
|
|
||||||
@ -257,7 +263,7 @@ enum LightTypes { LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT
|
|||||||
enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
|
enum LightSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
|
||||||
|
|
||||||
enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT,
|
enum XsnsFunctions {FUNC_SETTINGS_OVERRIDE, FUNC_PIN_STATE, FUNC_MODULE_INIT, FUNC_PRE_INIT, FUNC_INIT,
|
||||||
FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_SECOND,
|
FUNC_LOOP, FUNC_EVERY_50_MSECOND, FUNC_EVERY_100_MSECOND, FUNC_EVERY_200_MSECOND, FUNC_EVERY_250_MSECOND, FUNC_EVERY_300_MSECOND, FUNC_EVERY_SECOND,
|
||||||
FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART,
|
FUNC_SAVE_AT_MIDNIGHT, FUNC_SAVE_BEFORE_RESTART,
|
||||||
FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER,
|
FUNC_PREP_BEFORE_TELEPERIOD, FUNC_JSON_APPEND, FUNC_WEB_SENSOR, FUNC_COMMAND, FUNC_COMMAND_SENSOR, FUNC_COMMAND_DRIVER,
|
||||||
FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA,
|
FUNC_MQTT_SUBSCRIBE, FUNC_MQTT_INIT, FUNC_MQTT_DATA,
|
||||||
|
@ -90,6 +90,7 @@ unsigned long pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer
|
|||||||
unsigned long blink_timer = 0; // Power cycle timer
|
unsigned long blink_timer = 0; // Power cycle timer
|
||||||
unsigned long backlog_delay = 0; // Command backlog delay
|
unsigned long backlog_delay = 0; // Command backlog delay
|
||||||
power_t power = 0; // Current copy of Settings.power
|
power_t power = 0; // Current copy of Settings.power
|
||||||
|
power_t last_power = 0; // Last power set state
|
||||||
power_t blink_power; // Blink power state
|
power_t blink_power; // Blink power state
|
||||||
power_t blink_mask = 0; // Blink relay active mask
|
power_t blink_mask = 0; // Blink relay active mask
|
||||||
power_t blink_powersave; // Blink start power save state
|
power_t blink_powersave; // Blink start power save state
|
||||||
@ -172,7 +173,7 @@ String backlog[MAX_BACKLOG]; // Command backlog
|
|||||||
char* Format(char* output, const char* input, int size)
|
char* Format(char* output, const char* input, int size)
|
||||||
{
|
{
|
||||||
char *token;
|
char *token;
|
||||||
uint8_t digits = 0;
|
uint32_t digits = 0;
|
||||||
|
|
||||||
if (strstr(input, "%") != nullptr) {
|
if (strstr(input, "%") != nullptr) {
|
||||||
strlcpy(output, input, size);
|
strlcpy(output, input, size);
|
||||||
@ -201,7 +202,9 @@ char* Format(char* output, const char* input, int size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!digits) { strlcpy(output, input, size); }
|
if (!digits) {
|
||||||
|
strlcpy(output, input, size);
|
||||||
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,7 +222,7 @@ char* GetOtaUrl(char *otaurl, size_t otaurl_size)
|
|||||||
return otaurl;
|
return otaurl;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic)
|
char* GetTopic_P(char *stopic, uint32_t prefix, char *topic, const char* subtopic)
|
||||||
{
|
{
|
||||||
/* prefix 0 = Cmnd
|
/* prefix 0 = Cmnd
|
||||||
prefix 1 = Stat
|
prefix 1 = Stat
|
||||||
@ -258,25 +261,29 @@ char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic
|
|||||||
}
|
}
|
||||||
fulltopic.replace(F("#"), "");
|
fulltopic.replace(F("#"), "");
|
||||||
fulltopic.replace(F("//"), "/");
|
fulltopic.replace(F("//"), "/");
|
||||||
if (!fulltopic.endsWith("/")) fulltopic += "/";
|
if (!fulltopic.endsWith("/")) {
|
||||||
|
fulltopic += "/";
|
||||||
|
}
|
||||||
snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram);
|
snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram);
|
||||||
return stopic;
|
return stopic;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* GetFallbackTopic_P(char *stopic, uint8_t prefix, const char* subtopic)
|
char* GetFallbackTopic_P(char *stopic, uint32_t prefix, const char* subtopic)
|
||||||
{
|
{
|
||||||
return GetTopic_P(stopic, prefix +4, nullptr, subtopic);
|
return GetTopic_P(stopic, prefix +4, nullptr, subtopic);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* GetStateText(uint8_t state)
|
char* GetStateText(uint32_t state)
|
||||||
{
|
{
|
||||||
if (state > 3) { state = 1; }
|
if (state > 3) {
|
||||||
|
state = 1;
|
||||||
|
}
|
||||||
return Settings.state_text[state];
|
return Settings.state_text[state];
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
void SetLatchingRelay(power_t lpower, uint8_t state)
|
void SetLatchingRelay(power_t lpower, uint32_t state)
|
||||||
{
|
{
|
||||||
// power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off
|
// power xx00 - toggle REL1 (Off) and REL3 (Off) - device 1 Off, device 2 Off
|
||||||
// power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off
|
// power xx01 - toggle REL2 (On) and REL3 (Off) - device 1 On, device 2 Off
|
||||||
@ -289,17 +296,15 @@ void SetLatchingRelay(power_t lpower, uint8_t state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < devices_present; i++) {
|
for (uint32_t i = 0; i < devices_present; i++) {
|
||||||
uint8_t port = (i << 1) + ((latching_power >> i) &1);
|
uint32_t port = (i << 1) + ((latching_power >> i) &1);
|
||||||
if (pin[GPIO_REL1 +port] < 99) {
|
if (pin[GPIO_REL1 +port] < 99) {
|
||||||
digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state);
|
digitalWrite(pin[GPIO_REL1 +port], bitRead(rel_inverted, port) ? !state : state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDevicePower(power_t rpower, int source)
|
void SetDevicePower(power_t rpower, uint32_t source)
|
||||||
{
|
{
|
||||||
uint8_t state;
|
|
||||||
|
|
||||||
ShowSource(source);
|
ShowSource(source);
|
||||||
|
|
||||||
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on
|
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) { // All on and stay on
|
||||||
@ -310,9 +315,11 @@ void SetDevicePower(power_t rpower, int source)
|
|||||||
if (Settings.flag.interlock) { // Allow only one or no relay set
|
if (Settings.flag.interlock) { // Allow only one or no relay set
|
||||||
for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) {
|
for (uint32_t i = 0; i < MAX_INTERLOCKS; i++) {
|
||||||
power_t mask = 1;
|
power_t mask = 1;
|
||||||
uint8_t count = 0;
|
uint32_t count = 0;
|
||||||
for (uint32_t j = 0; j < devices_present; j++) {
|
for (uint32_t j = 0; j < devices_present; j++) {
|
||||||
if ((Settings.interlock[i] & mask) && (rpower & mask)) { count++; }
|
if ((Settings.interlock[i] & mask) && (rpower & mask)) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
}
|
}
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
@ -323,6 +330,10 @@ void SetDevicePower(power_t rpower, int source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rpower) { // Any power set
|
||||||
|
last_power = rpower;
|
||||||
|
}
|
||||||
|
|
||||||
XdrvMailbox.index = rpower;
|
XdrvMailbox.index = rpower;
|
||||||
XdrvCall(FUNC_SET_POWER); // Signal power state
|
XdrvCall(FUNC_SET_POWER); // Signal power state
|
||||||
|
|
||||||
@ -344,7 +355,7 @@ void SetDevicePower(power_t rpower, int source)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (uint32_t i = 0; i < devices_present; i++) {
|
for (uint32_t i = 0; i < devices_present; i++) {
|
||||||
state = rpower &1;
|
power_t state = rpower &1;
|
||||||
if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) {
|
if ((i < MAX_RELAYS) && (pin[GPIO_REL1 +i] < 99)) {
|
||||||
digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state);
|
digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? !state : state);
|
||||||
}
|
}
|
||||||
@ -353,13 +364,59 @@ void SetDevicePower(power_t rpower, int source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLedPowerIdx(uint8_t led, uint8_t state)
|
void RestorePower(bool publish_power, uint32_t source)
|
||||||
{
|
{
|
||||||
if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present
|
if (power != last_power) {
|
||||||
if (pin[GPIO_LED2] < 99) { led = 1; }
|
SetDevicePower(last_power, source);
|
||||||
|
if (publish_power) {
|
||||||
|
MqttPublishAllPowerState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetAllPower(uint32_t state, uint32_t source)
|
||||||
|
{
|
||||||
|
// state 0 = POWER_OFF = Relay Off
|
||||||
|
// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled)
|
||||||
|
// state 2 = POWER_TOGGLE = Toggle relay
|
||||||
|
// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState
|
||||||
|
// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState
|
||||||
|
// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState
|
||||||
|
// state 16 = POWER_SHOW_STATE = Show power state
|
||||||
|
|
||||||
|
bool publish_power = true;
|
||||||
|
if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) {
|
||||||
|
state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE
|
||||||
|
publish_power = false;
|
||||||
|
}
|
||||||
|
if ((state >= POWER_OFF) && (state <= POWER_TOGGLE)) {
|
||||||
|
power_t all_on = (1 << devices_present) -1;
|
||||||
|
switch (state) {
|
||||||
|
case POWER_OFF:
|
||||||
|
power = 0;
|
||||||
|
break;
|
||||||
|
case POWER_ON:
|
||||||
|
power = all_on;
|
||||||
|
break;
|
||||||
|
case POWER_TOGGLE:
|
||||||
|
power ^= all_on; // Complement current state
|
||||||
|
}
|
||||||
|
SetDevicePower(power, source);
|
||||||
|
}
|
||||||
|
if (publish_power) {
|
||||||
|
MqttPublishAllPowerState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLedPowerIdx(uint32_t led, uint32_t state)
|
||||||
|
{
|
||||||
|
if ((99 == pin[GPIO_LEDLNK]) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present
|
||||||
|
if (pin[GPIO_LED2] < 99) {
|
||||||
|
led = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pin[GPIO_LED1 + led] < 99) {
|
if (pin[GPIO_LED1 + led] < 99) {
|
||||||
uint8_t mask = 1 << led;
|
uint32_t mask = 1 << led;
|
||||||
if (state) {
|
if (state) {
|
||||||
state = 1;
|
state = 1;
|
||||||
led_power |= mask;
|
led_power |= mask;
|
||||||
@ -370,13 +427,13 @@ void SetLedPowerIdx(uint8_t led, uint8_t state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLedPower(uint8_t state)
|
void SetLedPower(uint32_t state)
|
||||||
{
|
{
|
||||||
if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2
|
if (99 == pin[GPIO_LEDLNK]) { // Legacy - Only use LED1 and/or LED2
|
||||||
SetLedPowerIdx(0, state);
|
SetLedPowerIdx(0, state);
|
||||||
} else {
|
} else {
|
||||||
power_t mask = 1;
|
power_t mask = 1;
|
||||||
for (uint32_t i = 0; i < leds_present; i++) { // Map leds to power
|
for (uint32_t i = 0; i < leds_present; i++) { // Map leds to power
|
||||||
bool tstate = (power & mask);
|
bool tstate = (power & mask);
|
||||||
SetLedPowerIdx(i, tstate);
|
SetLedPowerIdx(i, tstate);
|
||||||
mask <<= 1;
|
mask <<= 1;
|
||||||
@ -384,18 +441,18 @@ void SetLedPower(uint8_t state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLedPowerAll(uint8_t state)
|
void SetLedPowerAll(uint32_t state)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < leds_present; i++) {
|
for (uint32_t i = 0; i < leds_present; i++) {
|
||||||
SetLedPowerIdx(i, state);
|
SetLedPowerIdx(i, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetLedLink(uint8_t state)
|
void SetLedLink(uint32_t state)
|
||||||
{
|
{
|
||||||
uint8_t led_pin = pin[GPIO_LEDLNK];
|
uint32_t led_pin = pin[GPIO_LEDLNK];
|
||||||
uint8_t led_inv = ledlnk_inverted;
|
uint32_t led_inv = ledlnk_inverted;
|
||||||
if (99 == led_pin) { // Legacy - LED1 is status
|
if (99 == led_pin) { // Legacy - LED1 is status
|
||||||
led_pin = pin[GPIO_LED1];
|
led_pin = pin[GPIO_LED1];
|
||||||
led_inv = bitRead(led_inverted, 0);
|
led_inv = bitRead(led_inverted, 0);
|
||||||
}
|
}
|
||||||
@ -405,34 +462,32 @@ void SetLedLink(uint8_t state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPulseTimer(uint8_t index, uint16_t time)
|
void SetPulseTimer(uint32_t index, uint32_t time)
|
||||||
{
|
{
|
||||||
pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L;
|
pulse_timer[index] = (time > 111) ? millis() + (1000 * (time - 100)) : (time > 0) ? millis() + (100 * time) : 0L;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t GetPulseTimer(uint8_t index)
|
uint32_t GetPulseTimer(uint32_t index)
|
||||||
{
|
{
|
||||||
uint16_t result = 0;
|
|
||||||
|
|
||||||
long time = TimePassedSince(pulse_timer[index]);
|
long time = TimePassedSince(pulse_timer[index]);
|
||||||
if (time < 0) {
|
if (time < 0) {
|
||||||
time *= -1;
|
time *= -1;
|
||||||
result = (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0;
|
return (time > 11100) ? (time / 1000) + 100 : (time > 0) ? time / 100 : 0;
|
||||||
}
|
}
|
||||||
return result;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
bool SendKey(uint8_t key, uint8_t device, uint8_t state)
|
bool SendKey(uint32_t key, uint32_t device, uint32_t state)
|
||||||
{
|
{
|
||||||
// key 0 = button_topic
|
// key 0 = KEY_BUTTON = button_topic
|
||||||
// key 1 = switch_topic
|
// key 1 = KEY_SWITCH = switch_topic
|
||||||
// state 0 = off
|
// state 0 = POWER_OFF = off
|
||||||
// state 1 = on
|
// state 1 = POWER_ON = on
|
||||||
// state 2 = toggle
|
// state 2 = POWER_TOGGLE = toggle
|
||||||
// state 3 = hold
|
// state 3 = POWER_HOLD = hold
|
||||||
// state 9 = clear retain flag
|
// state 9 = CLEAR_RETAIN = clear retain flag
|
||||||
|
|
||||||
char stopic[TOPSZ];
|
char stopic[TOPSZ];
|
||||||
char scommand[CMDSZ];
|
char scommand[CMDSZ];
|
||||||
@ -442,23 +497,25 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state)
|
|||||||
char *tmp = (key) ? Settings.switch_topic : Settings.button_topic;
|
char *tmp = (key) ? Settings.switch_topic : Settings.button_topic;
|
||||||
Format(key_topic, tmp, sizeof(key_topic));
|
Format(key_topic, tmp, sizeof(key_topic));
|
||||||
if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
|
if (Settings.flag.mqtt_enabled && MqttIsConnected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
|
||||||
if (!key && (device > devices_present)) { device = 1; } // Only allow number of buttons up to number of devices
|
if (!key && (device > devices_present)) {
|
||||||
|
device = 1; // Only allow number of buttons up to number of devices
|
||||||
|
}
|
||||||
GetTopic_P(stopic, CMND, key_topic,
|
GetTopic_P(stopic, CMND, key_topic,
|
||||||
GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx
|
GetPowerDevice(scommand, device, sizeof(scommand), (key + Settings.flag.device_index_enable))); // cmnd/switchtopic/POWERx
|
||||||
if (9 == state) {
|
if (CLEAR_RETAIN == state) {
|
||||||
mqtt_data[0] = '\0';
|
mqtt_data[0] = '\0';
|
||||||
} else {
|
} else {
|
||||||
if ((Settings.flag3.button_switch_force_local || !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) && (2 == state)) {
|
if ((Settings.flag3.button_switch_force_local || !strcmp(mqtt_topic, key_topic) || !strcmp(Settings.mqtt_grptopic, key_topic)) && (POWER_TOGGLE == state)) {
|
||||||
state = ~(power >> (device -1)) &1;
|
state = ~(power >> (device -1)) &1; // POWER_OFF or POWER_ON
|
||||||
}
|
}
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state));
|
snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(state));
|
||||||
}
|
}
|
||||||
#ifdef USE_DOMOTICZ
|
#ifdef USE_DOMOTICZ
|
||||||
if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) {
|
if (!(DomoticzSendKey(key, device, state, strlen(mqtt_data)))) {
|
||||||
MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain));
|
MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != 3 || !Settings.flag3.no_hold_retain));
|
MqttPublishDirect(stopic, ((key) ? Settings.flag.mqtt_switch_retain : Settings.flag.mqtt_button_retain) && (state != POWER_HOLD || !Settings.flag3.no_hold_retain));
|
||||||
#endif // USE_DOMOTICZ
|
#endif // USE_DOMOTICZ
|
||||||
result = !Settings.flag3.button_switch_force_local;
|
result = !Settings.flag3.button_switch_force_local;
|
||||||
} else {
|
} else {
|
||||||
@ -471,17 +528,18 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteCommandPower(uint8_t device, uint8_t state, int source)
|
void ExecuteCommandPower(uint32_t device, uint32_t state, uint32_t source)
|
||||||
{
|
{
|
||||||
// device = Relay number 1 and up
|
// device = Relay number 1 and up
|
||||||
// state 0 = Relay Off
|
// state 0 = POWER_OFF = Relay Off
|
||||||
// state 1 = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled)
|
// state 1 = POWER_ON = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled)
|
||||||
// state 2 = Toggle relay
|
// state 2 = POWER_TOGGLE = Toggle relay
|
||||||
// state 3 = Blink relay
|
// state 3 = POWER_BLINK = Blink relay
|
||||||
// state 4 = Stop blinking relay
|
// state 4 = POWER_BLINK_STOP = Stop blinking relay
|
||||||
// state 6 = Relay Off and no publishPowerState
|
// state 8 = POWER_OFF_NO_STATE = Relay Off and no publishPowerState
|
||||||
// state 7 = Relay On and no publishPowerState
|
// state 9 = POWER_ON_NO_STATE = Relay On and no publishPowerState
|
||||||
// state 9 = Show power state
|
// state 10 = POWER_TOGGLE_NO_STATE = Toggle relay and no publishPowerState
|
||||||
|
// state 16 = POWER_SHOW_STATE = Show power state
|
||||||
|
|
||||||
// ShowSource(source);
|
// ShowSource(source);
|
||||||
|
|
||||||
@ -495,16 +553,20 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source)
|
|||||||
}
|
}
|
||||||
#endif // USE_SONOFF_IFAN
|
#endif // USE_SONOFF_IFAN
|
||||||
|
|
||||||
uint8_t publish_power = 1;
|
bool publish_power = true;
|
||||||
if ((POWER_OFF_NO_STATE == state) || (POWER_ON_NO_STATE == state)) {
|
if ((state >= POWER_OFF_NO_STATE) && (state <= POWER_TOGGLE_NO_STATE)) {
|
||||||
state &= 1;
|
state &= 3; // POWER_OFF, POWER_ON or POWER_TOGGLE
|
||||||
publish_power = 0;
|
publish_power = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((device < 1) || (device > devices_present)) device = 1;
|
if ((device < 1) || (device > devices_present)) {
|
||||||
|
device = 1;
|
||||||
|
}
|
||||||
active_device = device;
|
active_device = device;
|
||||||
|
|
||||||
if (device <= MAX_PULSETIMERS) { SetPulseTimer(device -1, 0); }
|
if (device <= MAX_PULSETIMERS) {
|
||||||
|
SetPulseTimer(device -1, 0);
|
||||||
|
}
|
||||||
power_t mask = 1 << (device -1); // Device to control
|
power_t mask = 1 << (device -1); // Device to control
|
||||||
if (state <= POWER_TOGGLE) {
|
if (state <= POWER_TOGGLE) {
|
||||||
if ((blink_mask & mask)) {
|
if ((blink_mask & mask)) {
|
||||||
@ -546,7 +608,9 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source)
|
|||||||
#ifdef USE_KNX
|
#ifdef USE_KNX
|
||||||
KnxUpdatePowerState(device, power);
|
KnxUpdatePowerState(device, power);
|
||||||
#endif // USE_KNX
|
#endif // USE_KNX
|
||||||
if (publish_power && Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); }
|
if (publish_power && Settings.flag3.hass_tele_on_power) {
|
||||||
|
MqttPublishTeleState();
|
||||||
|
}
|
||||||
if (device <= MAX_PULSETIMERS) { // Restart PulseTime if powered On
|
if (device <= MAX_PULSETIMERS) { // Restart PulseTime if powered On
|
||||||
SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0);
|
SetPulseTimer(device -1, (((POWER_ALL_OFF_PULSETIME_ON == Settings.poweronstate) ? ~power : power) & mask) ? Settings.pulse_timer[device -1] : 0);
|
||||||
}
|
}
|
||||||
@ -563,13 +627,17 @@ void ExecuteCommandPower(uint8_t device, uint8_t state, int source)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (POWER_BLINK_STOP == state) {
|
else if (POWER_BLINK_STOP == state) {
|
||||||
uint8_t flag = (blink_mask & mask);
|
bool flag = (blink_mask & mask);
|
||||||
blink_mask &= (POWER_MASK ^ mask); // Clear device mask
|
blink_mask &= (POWER_MASK ^ mask); // Clear device mask
|
||||||
MqttPublishPowerBlinkState(device);
|
MqttPublishPowerBlinkState(device);
|
||||||
if (flag) ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state
|
if (flag) {
|
||||||
|
ExecuteCommandPower(device, (blink_powersave >> (device -1))&1, SRC_IGNORE); // Restore state
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (publish_power) MqttPublishPowerState(device);
|
if (publish_power) {
|
||||||
|
MqttPublishPowerState(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StopAllPowerBlink(void)
|
void StopAllPowerBlink(void)
|
||||||
@ -586,18 +654,6 @@ void StopAllPowerBlink(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAllPower(uint8_t state, int source)
|
|
||||||
{
|
|
||||||
if ((POWER_ALL_OFF == state) || (POWER_ALL_ON == state)) {
|
|
||||||
power = 0;
|
|
||||||
if (POWER_ALL_ON == state) {
|
|
||||||
power = (1 << devices_present) -1;
|
|
||||||
}
|
|
||||||
SetDevicePower(power, source);
|
|
||||||
MqttPublishAllPowerState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MqttShowPWMState(void)
|
void MqttShowPWMState(void)
|
||||||
{
|
{
|
||||||
ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{"));
|
ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{"));
|
||||||
@ -824,7 +880,7 @@ void Every250mSeconds(void)
|
|||||||
{
|
{
|
||||||
// As the max amount of sleep = 250 mSec this loop should always be taken...
|
// As the max amount of sleep = 250 mSec this loop should always be taken...
|
||||||
|
|
||||||
uint8_t blinkinterval = 1;
|
uint32_t blinkinterval = 1;
|
||||||
|
|
||||||
state_250mS++;
|
state_250mS++;
|
||||||
state_250mS &= 0x3;
|
state_250mS &= 0x3;
|
||||||
@ -1178,7 +1234,7 @@ void SerialInput(void)
|
|||||||
if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) {
|
if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) {
|
||||||
serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed
|
serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed
|
||||||
char hex_char[(serial_in_byte_counter * 2) + 2];
|
char hex_char[(serial_in_byte_counter * 2) + 2];
|
||||||
Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"),
|
ResponseTime_P(PSTR(",\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"),
|
||||||
(Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer);
|
(Settings.flag.mqtt_serial_raw) ? ToHex_P((unsigned char*)serial_in_buffer, serial_in_byte_counter, hex_char, sizeof(hex_char)) : serial_in_buffer);
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED));
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
@ -1190,10 +1246,10 @@ void SerialInput(void)
|
|||||||
|
|
||||||
void GpioInit(void)
|
void GpioInit(void)
|
||||||
{
|
{
|
||||||
uint8_t mpin;
|
uint32_t mpin;
|
||||||
|
|
||||||
if (!ValidModule(Settings.module)) {
|
if (!ValidModule(Settings.module)) {
|
||||||
uint8_t module = MODULE;
|
uint32_t module = MODULE;
|
||||||
if (!ValidModule(MODULE)) { module = SONOFF_BASIC; }
|
if (!ValidModule(MODULE)) { module = SONOFF_BASIC; }
|
||||||
Settings.module = module;
|
Settings.module = module;
|
||||||
Settings.last_module = module;
|
Settings.last_module = module;
|
||||||
@ -1230,7 +1286,7 @@ void GpioInit(void)
|
|||||||
my_adc0 = Settings.my_adc0; // Set User selected Module sensors
|
my_adc0 = Settings.my_adc0; // Set User selected Module sensors
|
||||||
}
|
}
|
||||||
my_module_flag = ModuleFlag();
|
my_module_flag = ModuleFlag();
|
||||||
uint8_t template_adc0 = my_module_flag.data &15;
|
uint32_t template_adc0 = my_module_flag.data &15;
|
||||||
if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) {
|
if ((template_adc0 > ADC0_NONE) && (template_adc0 < ADC0_USER)) {
|
||||||
my_adc0 = template_adc0; // Force Template override
|
my_adc0 = template_adc0; // Force Template override
|
||||||
}
|
}
|
||||||
@ -1604,8 +1660,6 @@ void setup(void)
|
|||||||
XsnsCall(FUNC_INIT);
|
XsnsCall(FUNC_INIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t _counter = 0;
|
|
||||||
|
|
||||||
void loop(void)
|
void loop(void)
|
||||||
{
|
{
|
||||||
uint32_t my_sleep = millis();
|
uint32_t my_sleep = millis();
|
||||||
|
@ -85,7 +85,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
|
|||||||
|
|
||||||
// -- Optional modules -------------------------
|
// -- Optional modules -------------------------
|
||||||
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
||||||
#define USE_TUYA_DIMMER // Add support for Tuya Serial Dimmer
|
#define USE_TUYA_MCU // Add support for Tuya Serial MCU
|
||||||
#ifndef TUYA_DIMMER_ID
|
#ifndef TUYA_DIMMER_ID
|
||||||
#define TUYA_DIMMER_ID 0 // Default dimmer Id
|
#define TUYA_DIMMER_ID 0 // Default dimmer Id
|
||||||
#endif
|
#endif
|
||||||
@ -217,7 +217,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
|
|||||||
//#ifndef USE_SONOFF_IFAN
|
//#ifndef USE_SONOFF_IFAN
|
||||||
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
||||||
//#endif
|
//#endif
|
||||||
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
|
#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
|
||||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||||
#undef ROTARY_V1 // Disable support for MI Desk Lamp
|
#undef ROTARY_V1 // Disable support for MI Desk Lamp
|
||||||
@ -345,7 +345,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
|
|||||||
// -- Optional modules -------------------------
|
// -- Optional modules -------------------------
|
||||||
#undef USE_BUZZER // Disable support for a buzzer (+0k6 code)
|
#undef USE_BUZZER // Disable support for a buzzer (+0k6 code)
|
||||||
#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
|
#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
|
||||||
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
|
#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
|
||||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||||
#undef USE_DS18x20 // Disable Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code)
|
#undef USE_DS18x20 // Disable Optional for more than one DS18x20 sensors with id sort, single scan and read retry (+1k3 code)
|
||||||
@ -436,7 +436,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
|
|||||||
|
|
||||||
// -- Optional modules -------------------------
|
// -- Optional modules -------------------------
|
||||||
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
#define USE_SONOFF_IFAN // Add support for Sonoff iFan02 and iFan03 (+2k code)
|
||||||
//#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
|
//#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
|
||||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||||
#undef ROTARY_V1 // Disable support for MI Desk Lamp
|
#undef ROTARY_V1 // Disable support for MI Desk Lamp
|
||||||
@ -517,7 +517,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
|
|||||||
|
|
||||||
// -- Optional modules -------------------------
|
// -- Optional modules -------------------------
|
||||||
#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
|
#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
|
||||||
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
|
#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
|
||||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||||
#undef ROTARY_V1 // Disable support for MI Desk Lamp
|
#undef ROTARY_V1 // Disable support for MI Desk Lamp
|
||||||
|
@ -541,7 +541,7 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
|||||||
GPIO_SM16716_DAT, // SM16716 DATA
|
GPIO_SM16716_DAT, // SM16716 DATA
|
||||||
GPIO_SM16716_SEL, // SM16716 SELECT
|
GPIO_SM16716_SEL, // SM16716 SELECT
|
||||||
#endif // USE_SM16716
|
#endif // USE_SM16716
|
||||||
#ifdef USE_TUYA_DIMMER
|
#ifdef USE_TUYA_MCU
|
||||||
GPIO_TUYA_TX, // Tuya Serial interface
|
GPIO_TUYA_TX, // Tuya Serial interface
|
||||||
GPIO_TUYA_RX, // Tuya Serial interface
|
GPIO_TUYA_RX, // Tuya Serial interface
|
||||||
#endif
|
#endif
|
||||||
@ -749,7 +749,7 @@ const uint8_t kModuleNiceList[] PROGMEM = {
|
|||||||
OBI2,
|
OBI2,
|
||||||
MANZOKU_EU_4,
|
MANZOKU_EU_4,
|
||||||
ESP_SWITCH, // Switch Devices
|
ESP_SWITCH, // Switch Devices
|
||||||
#ifdef USE_TUYA_DIMMER
|
#ifdef USE_TUYA_MCU
|
||||||
TUYA_DIMMER, // Dimmer Devices
|
TUYA_DIMMER, // Dimmer Devices
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ARMTRONIX_DIMMERS
|
#ifdef USE_ARMTRONIX_DIMMERS
|
||||||
@ -1728,7 +1728,7 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
|||||||
GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On )
|
GPIO_REL1, // GPIO14 Relay SRU 5VDC SDA (0 = Off, 1 = On )
|
||||||
0, 0, 0
|
0, 0, 0
|
||||||
},
|
},
|
||||||
{ "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer)
|
{ "Tuya MCU", // Tuya MCU device (ESP8266 w/ separate MCU)
|
||||||
// https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
|
// https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
|
||||||
GPIO_USER, // Virtual Button (controlled by MCU)
|
GPIO_USER, // Virtual Button (controlled by MCU)
|
||||||
GPIO_USER, // GPIO01 MCU serial control
|
GPIO_USER, // GPIO01 MCU serial control
|
||||||
|
@ -20,6 +20,6 @@
|
|||||||
#ifndef _SONOFF_VERSION_H_
|
#ifndef _SONOFF_VERSION_H_
|
||||||
#define _SONOFF_VERSION_H_
|
#define _SONOFF_VERSION_H_
|
||||||
|
|
||||||
const uint32_t VERSION = 0x06060009;
|
const uint32_t VERSION = 0x0606000B;
|
||||||
|
|
||||||
#endif // _SONOFF_VERSION_H_
|
#endif // _SONOFF_VERSION_H_
|
||||||
|
@ -870,7 +870,24 @@ uint32_t WebColor(uint32_t i)
|
|||||||
* Response data handling
|
* Response data handling
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
int Response_P(const char* format, ...) // Content send snprintf_P char data
|
const uint16_t TIMESZ = 100; // Max number of characters in time string
|
||||||
|
|
||||||
|
char* ResponseGetTime(uint32_t format, char* time_str)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case 1:
|
||||||
|
snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":%u"), UtcTime());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
snprintf_P(time_str, TIMESZ, PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||||
|
}
|
||||||
|
return time_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Response_P(const char* format, ...) // Content send snprintf_P char data
|
||||||
{
|
{
|
||||||
// This uses char strings. Be aware of sending %% if % is needed
|
// This uses char strings. Be aware of sending %% if % is needed
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -880,6 +897,20 @@ int Response_P(const char* format, ...) // Content send snprintf_P char data
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ResponseTime_P(const char* format, ...) // Content send snprintf_P char data
|
||||||
|
{
|
||||||
|
// This uses char strings. Be aware of sending %% if % is needed
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
|
||||||
|
ResponseGetTime(Settings.flag2.time_format, mqtt_data);
|
||||||
|
|
||||||
|
int mlen = strlen(mqtt_data);
|
||||||
|
int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args);
|
||||||
|
va_end(args);
|
||||||
|
return len + mlen;
|
||||||
|
}
|
||||||
|
|
||||||
int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char data
|
int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char data
|
||||||
{
|
{
|
||||||
// This uses char strings. Be aware of sending %% if % is needed
|
// This uses char strings. Be aware of sending %% if % is needed
|
||||||
@ -891,15 +922,15 @@ int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char d
|
|||||||
return len + mlen;
|
return len + mlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResponseAppendTime(void)
|
int ResponseAppendTimeFormat(uint32_t format)
|
||||||
{
|
{
|
||||||
return ResponseAppend_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%u"), GetDateAndTime(DT_LOCAL).c_str(), UtcTime());
|
char time_str[TIMESZ];
|
||||||
|
return ResponseAppend_P(ResponseGetTime(format, time_str));
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResponseBeginTime(void)
|
int ResponseAppendTime(void)
|
||||||
{
|
{
|
||||||
mqtt_data[0] = '\0';
|
return ResponseAppendTimeFormat(Settings.flag2.time_format);
|
||||||
return ResponseAppendTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResponseJsonEnd(void)
|
int ResponseJsonEnd(void)
|
||||||
|
@ -165,7 +165,7 @@ void ButtonHandler(void)
|
|||||||
if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second
|
if (!Button.hold_timer[button_index]) { button_pressed = true; } // Do not allow within 1 second
|
||||||
}
|
}
|
||||||
if (button_pressed) {
|
if (button_pressed) {
|
||||||
if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
|
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
|
||||||
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
|
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,7 +174,7 @@ void ButtonHandler(void)
|
|||||||
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
|
if ((PRESSED == button) && (NOT_PRESSED == Button.last_state[button_index])) {
|
||||||
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
|
if (Settings.flag.button_single) { // SetOption13 (0) - Allow only single button press for immediate action
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_BUTTON "%d " D_IMMEDIATE), button_index +1);
|
||||||
if (!SendKey(0, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
|
if (!SendKey(KEY_BUTTON, button_index +1, POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
|
||||||
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
|
ExecuteCommandPower(button_index +1, POWER_TOGGLE, SRC_BUTTON); // Execute Toggle command internally
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -199,14 +199,14 @@ void ButtonHandler(void)
|
|||||||
if (Settings.flag.button_restrict) { // SetOption1 (0) - Button restriction
|
if (Settings.flag.button_restrict) { // SetOption1 (0) - Button restriction
|
||||||
if (Settings.param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
|
if (Settings.param[P_HOLD_IGNORE] > 0) { // SetOption40 (0) - Do not ignore button hold
|
||||||
if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) {
|
if (Button.hold_timer[button_index] > loops_per_second * Settings.param[P_HOLD_IGNORE] / 10) {
|
||||||
Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
|
Button.hold_timer[button_index] = 0; // Reset button hold counter to stay below hold trigger
|
||||||
Button.press_counter[button_index] = 0; // Discard button press to disable functionality
|
Button.press_counter[button_index] = 0; // Discard button press to disable functionality
|
||||||
DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]);
|
DEBUG_CORE_LOG(PSTR("BTN: " D_BUTTON "%d cancel by " D_CMND_SETOPTION "40 %d"), button_index +1, Settings.param[P_HOLD_IGNORE]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
|
if (Button.hold_timer[button_index] == loops_per_second * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button hold
|
||||||
Button.press_counter[button_index] = 0;
|
Button.press_counter[button_index] = 0;
|
||||||
SendKey(0, button_index +1, 3); // Execute Hold command via MQTT if ButtonTopic is set
|
SendKey(KEY_BUTTON, button_index +1, POWER_HOLD); // Execute Hold command via MQTT if ButtonTopic is set
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
|
if (Button.hold_timer[button_index] == loops_per_second * hold_time_extent * Settings.param[P_HOLD_TIME] / 10) { // SetOption32 (40) - Button held for factor times longer
|
||||||
@ -241,7 +241,7 @@ void ButtonHandler(void)
|
|||||||
#if defined(USE_LIGHT) && defined(ROTARY_V1)
|
#if defined(USE_LIGHT) && defined(ROTARY_V1)
|
||||||
if (!((0 == button_index) && RotaryButtonPressed())) {
|
if (!((0 == button_index) && RotaryButtonPressed())) {
|
||||||
#endif
|
#endif
|
||||||
if (single_press && SendKey(0, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
|
if (single_press && SendKey(KEY_BUTTON, button_index + Button.press_counter[button_index], POWER_TOGGLE)) { // Execute Toggle command via MQTT if ButtonTopic is set
|
||||||
// Success
|
// Success
|
||||||
} else {
|
} else {
|
||||||
if (Button.press_counter[button_index] < 3) { // Single or Double press
|
if (Button.press_counter[button_index] < 3) { // Single or Double press
|
||||||
|
@ -257,11 +257,20 @@ void CmndDelay(void)
|
|||||||
void CmndPower(void)
|
void CmndPower(void)
|
||||||
{
|
{
|
||||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) {
|
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= devices_present)) {
|
||||||
if ((XdrvMailbox.payload < 0) || (XdrvMailbox.payload > 4)) { XdrvMailbox.payload = 9; }
|
if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_BLINK_STOP)) {
|
||||||
// Settings.flag.device_index_enable = user_index;
|
XdrvMailbox.payload = POWER_SHOW_STATE;
|
||||||
|
}
|
||||||
|
// Settings.flag.device_index_enable = XdrvMailbox.usridx;
|
||||||
ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE);
|
ExecuteCommandPower(XdrvMailbox.index, XdrvMailbox.payload, SRC_IGNORE);
|
||||||
mqtt_data[0] = '\0';
|
mqtt_data[0] = '\0';
|
||||||
}
|
}
|
||||||
|
else if (0 == XdrvMailbox.index) {
|
||||||
|
if ((XdrvMailbox.payload < POWER_OFF) || (XdrvMailbox.payload > POWER_TOGGLE)) {
|
||||||
|
XdrvMailbox.payload = POWER_SHOW_STATE;
|
||||||
|
}
|
||||||
|
SetAllPower(XdrvMailbox.payload, SRC_IGNORE);
|
||||||
|
mqtt_data[0] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndStatus(void)
|
void CmndStatus(void)
|
||||||
@ -607,26 +616,23 @@ void CmndSetoption(void)
|
|||||||
#endif // USE_HOME_ASSISTANT
|
#endif // USE_HOME_ASSISTANT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (1 == ptype) { // SetOption50 .. 81
|
else if (1 == ptype) { // SetOption50 .. 81
|
||||||
if (XdrvMailbox.payload <= 1) {
|
if (XdrvMailbox.payload <= 1) {
|
||||||
bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload);
|
bitWrite(Settings.flag3.data, pindex, XdrvMailbox.payload);
|
||||||
if (5 == pindex) { // SetOption55
|
if (5 == pindex) { // SetOption55
|
||||||
if (0 == XdrvMailbox.payload) {
|
if (0 == XdrvMailbox.payload) {
|
||||||
restart_flag = 2; // Disable mDNS needs restart
|
restart_flag = 2; // Disable mDNS needs restart
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (10 == pindex) { // SetOption60 enable or disable traditional sleep
|
if (10 == pindex) { // SetOption60 enable or disable traditional sleep
|
||||||
WiFiSetSleepMode(); // Update WiFi sleep mode accordingly
|
WiFiSetSleepMode(); // Update WiFi sleep mode accordingly
|
||||||
}
|
}
|
||||||
if (18 == pindex) { // SetOption68 for multi-channel PWM, requires a reboot
|
if (18 == pindex) { // SetOption68 for multi-channel PWM, requires a reboot
|
||||||
restart_flag = 2;
|
|
||||||
}
|
|
||||||
if (15 == pindex) { // SetOption65 for tuya_disable_dimmer requires a reboot
|
|
||||||
restart_flag = 2;
|
restart_flag = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // SetOption32 .. 49
|
else { // SetOption32 .. 49
|
||||||
uint32_t param_low = 0;
|
uint32_t param_low = 0;
|
||||||
uint32_t param_high = 255;
|
uint32_t param_high = 255;
|
||||||
switch (pindex) {
|
switch (pindex) {
|
||||||
@ -635,9 +641,6 @@ void CmndSetoption(void)
|
|||||||
param_low = 1;
|
param_low = 1;
|
||||||
param_high = 250;
|
param_high = 250;
|
||||||
break;
|
break;
|
||||||
case P_TUYA_RELAYS:
|
|
||||||
param_high = 8;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) {
|
if ((XdrvMailbox.payload >= param_low) && (XdrvMailbox.payload <= param_high)) {
|
||||||
Settings.param[pindex] = XdrvMailbox.payload;
|
Settings.param[pindex] = XdrvMailbox.payload;
|
||||||
@ -652,11 +655,7 @@ void CmndSetoption(void)
|
|||||||
IrReceiveUpdateThreshold();
|
IrReceiveUpdateThreshold();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_TUYA_DIMMER
|
#ifdef USE_TUYA_MCU
|
||||||
case P_TUYA_RELAYS:
|
|
||||||
case P_TUYA_POWER_ID:
|
|
||||||
case P_TUYA_CURRENT_ID:
|
|
||||||
case P_TUYA_VOLTAGE_ID:
|
|
||||||
case P_TUYA_DIMMER_MAX:
|
case P_TUYA_DIMMER_MAX:
|
||||||
restart_flag = 2; // Need a restart to update GUI
|
restart_flag = 2; // Need a restart to update GUI
|
||||||
break;
|
break;
|
||||||
@ -1260,6 +1259,10 @@ void CmndReset(void)
|
|||||||
restart_flag = 210 + XdrvMailbox.payload;
|
restart_flag = 210 + XdrvMailbox.payload;
|
||||||
Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}"));
|
Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}"));
|
||||||
break;
|
break;
|
||||||
|
case 99:
|
||||||
|
Settings.bootcount = 0;
|
||||||
|
ResponseCmndDone();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ResponseCmndChar(D_JSON_ONE_TO_RESET);
|
ResponseCmndChar(D_JSON_ONE_TO_RESET);
|
||||||
}
|
}
|
||||||
@ -1267,10 +1270,25 @@ void CmndReset(void)
|
|||||||
|
|
||||||
void CmndTime(void)
|
void CmndTime(void)
|
||||||
{
|
{
|
||||||
|
// payload 0 = (re-)enable NTP
|
||||||
|
// payload 1 = Time format {"Time":"2019-09-04T14:31:29"}
|
||||||
|
// payload 2 = Time format {"Time":"2019-09-04T14:31:29","Epoch":1567600289}
|
||||||
|
// payload 3 = Time format {"Time":1567600289}
|
||||||
|
// payload 4 = reserved
|
||||||
|
// payload 1451602800 - disable NTP and set time to epoch
|
||||||
|
|
||||||
|
uint32_t format = Settings.flag2.time_format;
|
||||||
if (XdrvMailbox.data_len > 0) {
|
if (XdrvMailbox.data_len > 0) {
|
||||||
RtcSetTime(XdrvMailbox.payload);
|
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 4)) {
|
||||||
|
Settings.flag2.time_format = XdrvMailbox.payload -1;
|
||||||
|
format = Settings.flag2.time_format;
|
||||||
|
} else {
|
||||||
|
format = 1; // {"Time":"2019-09-04T14:31:29","Epoch":1567600289}
|
||||||
|
RtcSetTime(XdrvMailbox.payload);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ResponseBeginTime();
|
mqtt_data[0] = '\0';
|
||||||
|
ResponseAppendTimeFormat(format);
|
||||||
ResponseJsonEnd();
|
ResponseJsonEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ void GetFeatures(void)
|
|||||||
#ifdef USE_PCA9685
|
#ifdef USE_PCA9685
|
||||||
feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino
|
feature_drv2 |= 0x00004000; // xdrv_15_pca9685.ino
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_LIGHT) && defined(USE_TUYA_DIMMER)
|
#if defined(USE_LIGHT) && defined(USE_TUYA_MCU)
|
||||||
feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino
|
feature_drv2 |= 0x00008000; // xdrv_16_tuyadimmer.ino
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_RC_SWITCH
|
#ifdef USE_RC_SWITCH
|
||||||
|
@ -143,7 +143,7 @@ void SwitchHandler(uint8_t mode)
|
|||||||
if (Switch.hold_timer[i]) {
|
if (Switch.hold_timer[i]) {
|
||||||
Switch.hold_timer[i]--;
|
Switch.hold_timer[i]--;
|
||||||
if (0 == Switch.hold_timer[i]) {
|
if (0 == Switch.hold_timer[i]) {
|
||||||
SendKey(1, i +1, 3); // Execute command via MQTT
|
SendKey(KEY_SWITCH, i +1, POWER_HOLD); // Execute command via MQTT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,10 +152,10 @@ void SwitchHandler(uint8_t mode)
|
|||||||
// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION};
|
// enum SwitchModeOptions {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, PUSHBUTTON_TOGGLE, MAX_SWITCH_OPTION};
|
||||||
|
|
||||||
if (button != Switch.last_state[i]) {
|
if (button != Switch.last_state[i]) {
|
||||||
switchflag = 3;
|
switchflag = POWER_TOGGLE +1;
|
||||||
switch (Settings.switchmode[i]) {
|
switch (Settings.switchmode[i]) {
|
||||||
case TOGGLE:
|
case TOGGLE:
|
||||||
switchflag = 2; // Toggle
|
switchflag = POWER_TOGGLE; // Toggle
|
||||||
break;
|
break;
|
||||||
case FOLLOW:
|
case FOLLOW:
|
||||||
switchflag = button &1; // Follow wall switch state
|
switchflag = button &1; // Follow wall switch state
|
||||||
@ -165,17 +165,17 @@ void SwitchHandler(uint8_t mode)
|
|||||||
break;
|
break;
|
||||||
case PUSHBUTTON:
|
case PUSHBUTTON:
|
||||||
if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) {
|
if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i])) {
|
||||||
switchflag = 2; // Toggle with pushbutton to Gnd
|
switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PUSHBUTTON_INV:
|
case PUSHBUTTON_INV:
|
||||||
if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) {
|
if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i])) {
|
||||||
switchflag = 2; // Toggle with releasing pushbutton from Gnd
|
switchflag = POWER_TOGGLE; // Toggle with releasing pushbutton from Gnd
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PUSHBUTTON_TOGGLE:
|
case PUSHBUTTON_TOGGLE:
|
||||||
if (button != Switch.last_state[i]) {
|
if (button != Switch.last_state[i]) {
|
||||||
switchflag = 2; // Toggle with any pushbutton change
|
switchflag = POWER_TOGGLE; // Toggle with any pushbutton change
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PUSHBUTTONHOLD:
|
case PUSHBUTTONHOLD:
|
||||||
@ -184,7 +184,7 @@ void SwitchHandler(uint8_t mode)
|
|||||||
}
|
}
|
||||||
if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
|
if ((NOT_PRESSED == button) && (PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
|
||||||
Switch.hold_timer[i] = 0;
|
Switch.hold_timer[i] = 0;
|
||||||
switchflag = 2; // Toggle with pushbutton to Gnd
|
switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PUSHBUTTONHOLD_INV:
|
case PUSHBUTTONHOLD_INV:
|
||||||
@ -193,13 +193,13 @@ void SwitchHandler(uint8_t mode)
|
|||||||
}
|
}
|
||||||
if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
|
if ((PRESSED == button) && (NOT_PRESSED == Switch.last_state[i]) && (Switch.hold_timer[i])) {
|
||||||
Switch.hold_timer[i] = 0;
|
Switch.hold_timer[i] = 0;
|
||||||
switchflag = 2; // Toggle with pushbutton to Gnd
|
switchflag = POWER_TOGGLE; // Toggle with pushbutton to Gnd
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchflag < 3) {
|
if (switchflag <= POWER_TOGGLE) {
|
||||||
if (!SendKey(1, i +1, switchflag)) { // Execute command via MQTT
|
if (!SendKey(KEY_SWITCH, i +1, switchflag)) { // Execute command via MQTT
|
||||||
ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present)
|
ExecuteCommandPower(i +1, switchflag, SRC_SWITCH); // Execute command internally (if i < devices_present)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,7 @@ static bool WifiIsInManagerMode(){
|
|||||||
return (HTTP_MANAGER == Web.state || HTTP_MANAGER_RESET_ONLY == Web.state);
|
return (HTTP_MANAGER == Web.state || HTTP_MANAGER_RESET_ONLY == Web.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowWebSource(int source)
|
void ShowWebSource(uint32_t source)
|
||||||
{
|
{
|
||||||
if ((source > 0) && (source < SRC_MAX)) {
|
if ((source > 0) && (source < SRC_MAX)) {
|
||||||
char stemp1[20];
|
char stemp1[20];
|
||||||
@ -508,7 +508,7 @@ void ShowWebSource(int source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExecuteWebCommand(char* svalue, int source)
|
void ExecuteWebCommand(char* svalue, uint32_t source)
|
||||||
{
|
{
|
||||||
ShowWebSource(source);
|
ShowWebSource(source);
|
||||||
ExecuteCommand(svalue, SRC_IGNORE);
|
ExecuteCommand(svalue, SRC_IGNORE);
|
||||||
@ -1053,6 +1053,7 @@ bool HandleRootStatusRefresh(void)
|
|||||||
#ifdef USE_SCRIPT_WEB_DISPLAY
|
#ifdef USE_SCRIPT_WEB_DISPLAY
|
||||||
XdrvCall(FUNC_WEB_SENSOR);
|
XdrvCall(FUNC_WEB_SENSOR);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
WSContentSend_P(PSTR("</table>"));
|
WSContentSend_P(PSTR("</table>"));
|
||||||
|
|
||||||
if (devices_present) {
|
if (devices_present) {
|
||||||
@ -1686,8 +1687,8 @@ void HandleBackupConfiguration(void)
|
|||||||
|
|
||||||
WSSend(200, CT_STREAM, "");
|
WSSend(200, CT_STREAM, "");
|
||||||
|
|
||||||
uint16_t cfg_crc = Settings.cfg_crc;
|
uint32_t cfg_crc32 = Settings.cfg_crc32;
|
||||||
Settings.cfg_crc = GetSettingsCrc(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918)
|
Settings.cfg_crc32 = GetSettingsCrc32(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918)
|
||||||
|
|
||||||
memcpy(settings_buffer, &Settings, sizeof(Settings));
|
memcpy(settings_buffer, &Settings, sizeof(Settings));
|
||||||
if (Web.config_xor_on_set) {
|
if (Web.config_xor_on_set) {
|
||||||
@ -1707,7 +1708,7 @@ void HandleBackupConfiguration(void)
|
|||||||
|
|
||||||
SettingsBufferFree();
|
SettingsBufferFree();
|
||||||
|
|
||||||
Settings.cfg_crc = cfg_crc; // Restore crc in case savedata = 0 to make sure settings will be noted as changed
|
Settings.cfg_crc32 = cfg_crc32; // Restore crc in case savedata = 0 to make sure settings will be noted as changed
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------------------*/
|
||||||
@ -2092,12 +2093,13 @@ void HandleUploadLoop(void)
|
|||||||
unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8];
|
unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8];
|
||||||
if (buffer_version > 0x06000000) {
|
if (buffer_version > 0x06000000) {
|
||||||
uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2];
|
uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2];
|
||||||
uint16_t buffer_crc = settings_buffer[15] << 8 | settings_buffer[14];
|
if (buffer_version > 0x0606000A) {
|
||||||
uint16_t crc = 0;
|
uint32_t buffer_crc32 = settings_buffer[4095] << 24 | settings_buffer[4094] << 16 | settings_buffer[4093] << 8 | settings_buffer[4092];
|
||||||
for (uint32_t i = 0; i < buffer_size; i++) {
|
valid_settings = (GetCfgCrc32(settings_buffer, buffer_size -4) == buffer_crc32);
|
||||||
if ((i < 14) || (i > 15)) { crc += settings_buffer[i]*(i+1); } // Skip crc
|
} else {
|
||||||
|
uint16_t buffer_crc16 = settings_buffer[15] << 8 | settings_buffer[14];
|
||||||
|
valid_settings = (GetCfgCrc16(settings_buffer, buffer_size) == buffer_crc16);
|
||||||
}
|
}
|
||||||
valid_settings = (buffer_crc == crc);
|
|
||||||
} else {
|
} else {
|
||||||
valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN);
|
valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN);
|
||||||
}
|
}
|
||||||
@ -2350,6 +2352,151 @@ String UrlEncode(const String& text)
|
|||||||
return encoded;
|
return encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_SENDMAIL
|
||||||
|
|
||||||
|
#include "sendemail.h"
|
||||||
|
|
||||||
|
//SendEmail(const String& host, const int port, const String& user, const String& passwd, const int timeout, const bool ssl);
|
||||||
|
//SendEmail::send(const String& from, const String& to, const String& subject, const String& msg)
|
||||||
|
// sendmail [server:port:user:passwd:from:to:subject] data
|
||||||
|
// sendmail [*:*:*:*:*:to:subject] data uses defines from user_config
|
||||||
|
// sendmail currently only works with core 2.4.2
|
||||||
|
|
||||||
|
#define SEND_MAIL_MINRAM 19*1024
|
||||||
|
|
||||||
|
uint16_t SendMail(char *buffer) {
|
||||||
|
uint16_t count;
|
||||||
|
char *params,*oparams;
|
||||||
|
char *mserv;
|
||||||
|
uint16_t port;
|
||||||
|
char *user;
|
||||||
|
char *pstr;
|
||||||
|
char *passwd;
|
||||||
|
char *from;
|
||||||
|
char *to;
|
||||||
|
char *subject;
|
||||||
|
char *cmd;
|
||||||
|
char secure=0,auth=0;
|
||||||
|
uint16_t status=1;
|
||||||
|
SendEmail *mail=0;
|
||||||
|
|
||||||
|
//DebugFreeMem();
|
||||||
|
|
||||||
|
// return if not enough memory
|
||||||
|
uint16_t mem=ESP.getFreeHeap();
|
||||||
|
if (mem<SEND_MAIL_MINRAM) {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*buffer==' ') buffer++;
|
||||||
|
|
||||||
|
// copy params
|
||||||
|
oparams=(char*)calloc(strlen(buffer)+2,1);
|
||||||
|
if (!oparams) return 4;
|
||||||
|
|
||||||
|
params=oparams;
|
||||||
|
|
||||||
|
strcpy(params,buffer);
|
||||||
|
|
||||||
|
if (*params=='p') {
|
||||||
|
auth=1;
|
||||||
|
params++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*params!='[') {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
params++;
|
||||||
|
|
||||||
|
mserv=strtok(params,":");
|
||||||
|
if (!mserv) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// port
|
||||||
|
pstr=strtok(NULL,":");
|
||||||
|
if (!pstr) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef EMAIL_PORT
|
||||||
|
if (*pstr=='*') {
|
||||||
|
port=EMAIL_PORT;
|
||||||
|
} else {
|
||||||
|
port=atoi(pstr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
port=atoi(pstr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
user=strtok(NULL,":");
|
||||||
|
if (!user) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
passwd=strtok(NULL,":");
|
||||||
|
if (!passwd) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
from=strtok(NULL,":");
|
||||||
|
if (!from) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
to=strtok(NULL,":");
|
||||||
|
if (!to) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
subject=strtok(NULL,"]");
|
||||||
|
if (!subject) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd=subject+strlen(subject)+1;
|
||||||
|
|
||||||
|
#ifdef EMAIL_USER
|
||||||
|
if (*user=='*') {
|
||||||
|
user=(char*)EMAIL_USER;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef EMAIL_PASSWORD
|
||||||
|
if (*passwd=='*') {
|
||||||
|
passwd=(char*)EMAIL_PASSWORD;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef EMAIL_SERVER
|
||||||
|
if (*mserv=='*') {
|
||||||
|
mserv=(char*)EMAIL_SERVER;
|
||||||
|
}
|
||||||
|
#endif //USE_SENDMAIL
|
||||||
|
|
||||||
|
// auth = 0 => AUTH LOGIN 1 => PLAIN LOGIN
|
||||||
|
// 2 seconds timeout
|
||||||
|
#define MAIL_TIMEOUT 2000
|
||||||
|
mail = new SendEmail(mserv, port,user,passwd, MAIL_TIMEOUT, auth);
|
||||||
|
|
||||||
|
#ifdef EMAIL_FROM
|
||||||
|
if (*from=='*') {
|
||||||
|
from=(char*)EMAIL_FROM;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (mail) {
|
||||||
|
bool result=mail->send(from,to,subject,cmd);
|
||||||
|
delete mail;
|
||||||
|
if (result==true) status=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (oparams) free(oparams);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int WebSend(char *buffer)
|
int WebSend(char *buffer)
|
||||||
{
|
{
|
||||||
// [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON
|
// [sonoff] POWER1 ON --> Sends http://sonoff/cm?cmnd=POWER1 ON
|
||||||
@ -2462,17 +2609,23 @@ bool JsonWebColor(const char* dataBuf)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND ;
|
const char kWebSendStatus[] PROGMEM = D_JSON_DONE "|" D_JSON_WRONG_PARAMETERS "|" D_JSON_CONNECT_FAILED "|" D_JSON_HOST_NOT_FOUND "|" D_JSON_MEMORY_ERROR;
|
||||||
|
|
||||||
const char kWebCommands[] PROGMEM = "|" // No prefix
|
const char kWebCommands[] PROGMEM = "|" // No prefix
|
||||||
#ifdef USE_EMULATION
|
#ifdef USE_EMULATION
|
||||||
D_CMND_EMULATION "|"
|
D_CMND_EMULATION "|"
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SENDMAIL
|
||||||
|
D_CMND_SENDMAIL "|"
|
||||||
#endif
|
#endif
|
||||||
D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR;
|
D_CMND_WEBSERVER "|" D_CMND_WEBPASSWORD "|" D_CMND_WEBLOG "|" D_CMND_WEBREFRESH "|" D_CMND_WEBSEND "|" D_CMND_WEBCOLOR "|" D_CMND_WEBSENSOR;
|
||||||
|
|
||||||
void (* const WebCommand[])(void) PROGMEM = {
|
void (* const WebCommand[])(void) PROGMEM = {
|
||||||
#ifdef USE_EMULATION
|
#ifdef USE_EMULATION
|
||||||
&CmndEmulation,
|
&CmndEmulation,
|
||||||
|
#endif
|
||||||
|
#ifdef USE_SENDMAIL
|
||||||
|
&CmndSendmail,
|
||||||
#endif
|
#endif
|
||||||
&CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor };
|
&CmndWebServer, &CmndWebPassword, &CmndWeblog, &CmndWebRefresh, &CmndWebSend, &CmndWebColor, &CmndWebSensor };
|
||||||
|
|
||||||
@ -2500,6 +2653,18 @@ void CmndEmulation(void)
|
|||||||
}
|
}
|
||||||
#endif // USE_EMULATION
|
#endif // USE_EMULATION
|
||||||
|
|
||||||
|
#ifdef USE_SENDMAIL
|
||||||
|
void CmndSendmail(void)
|
||||||
|
{
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
uint8_t result = SendMail(XdrvMailbox.data);
|
||||||
|
char stemp1[20];
|
||||||
|
ResponseCmndChar(GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // USE_SENDMAIL
|
||||||
|
|
||||||
|
|
||||||
void CmndWebServer(void)
|
void CmndWebServer(void)
|
||||||
{
|
{
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) {
|
||||||
|
@ -894,7 +894,7 @@ void CmndButtonRetain(void)
|
|||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||||
if (!XdrvMailbox.payload) {
|
if (!XdrvMailbox.payload) {
|
||||||
for (uint32_t i = 1; i <= MAX_KEYS; i++) {
|
for (uint32_t i = 1; i <= MAX_KEYS; i++) {
|
||||||
SendKey(0, i, 9); // Clear MQTT retain in broker
|
SendKey(KEY_BUTTON, i, CLEAR_RETAIN); // Clear MQTT retain in broker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Settings.flag.mqtt_button_retain = XdrvMailbox.payload;
|
Settings.flag.mqtt_button_retain = XdrvMailbox.payload;
|
||||||
@ -907,7 +907,7 @@ void CmndSwitchRetain(void)
|
|||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) {
|
||||||
if (!XdrvMailbox.payload) {
|
if (!XdrvMailbox.payload) {
|
||||||
for (uint32_t i = 1; i <= MAX_SWITCHES; i++) {
|
for (uint32_t i = 1; i <= MAX_SWITCHES; i++) {
|
||||||
SendKey(1, i, 9); // Clear MQTT retain in broker
|
SendKey(KEY_SWITCH, i, CLEAR_RETAIN); // Clear MQTT retain in broker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Settings.flag.mqtt_switch_retain = XdrvMailbox.payload;
|
Settings.flag.mqtt_switch_retain = XdrvMailbox.payload;
|
||||||
|
@ -83,9 +83,9 @@ struct ENERGY {
|
|||||||
float total = 0; // 12345.12345 kWh tariff 1 + 2
|
float total = 0; // 12345.12345 kWh tariff 1 + 2
|
||||||
float total1 = 0; // 12345.12345 kWh tariff 1 - off-peak
|
float total1 = 0; // 12345.12345 kWh tariff 1 - off-peak
|
||||||
|
|
||||||
unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only)
|
unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only)
|
||||||
|
unsigned long kWhtoday_offset = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
||||||
unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
||||||
unsigned long kWhtoday1; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
|
||||||
unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
|
||||||
|
|
||||||
uint8_t fifth_second = 0;
|
uint8_t fifth_second = 0;
|
||||||
@ -129,23 +129,40 @@ void EnergyUpdateToday(void)
|
|||||||
Energy.kWhtoday_delta -= (delta * 1000);
|
Energy.kWhtoday_delta -= (delta * 1000);
|
||||||
Energy.kWhtoday += delta;
|
Energy.kWhtoday += delta;
|
||||||
}
|
}
|
||||||
uint32_t energy_diff = Energy.kWhtoday - RtcSettings.energy_kWhtoday;
|
|
||||||
|
|
||||||
RtcSettings.energy_kWhtoday = Energy.kWhtoday;
|
uint32_t energy_diff = Energy.kWhtoday_offset + Energy.kWhtoday - RtcSettings.energy_kWhtoday;
|
||||||
Energy.daily = (float)Energy.kWhtoday / 100000;
|
|
||||||
Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday) / 100000;
|
RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday;
|
||||||
|
Energy.daily = (float)(RtcSettings.energy_kWhtoday) / 100000;
|
||||||
|
Energy.total = (float)(RtcSettings.energy_kWhtotal + RtcSettings.energy_kWhtoday) / 100000;
|
||||||
|
|
||||||
if ((RtcTime.hour < Settings.param[P_ENERGY_TARIFF2]) || // Tarrif1 = Off-Peak
|
if ((RtcTime.hour < Settings.param[P_ENERGY_TARIFF2]) || // Tarrif1 = Off-Peak
|
||||||
(RtcTime.hour >= Settings.param[P_ENERGY_TARIFF1]) ||
|
(RtcTime.hour >= Settings.param[P_ENERGY_TARIFF1]) ||
|
||||||
(Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) ||
|
(Settings.flag3.energy_weekend && ((RtcTime.day_of_week == 1) ||
|
||||||
(RtcTime.day_of_week == 7)))
|
(RtcTime.day_of_week == 7)))
|
||||||
) {
|
) {
|
||||||
Energy.kWhtoday1 += energy_diff;
|
RtcSettings.energy_usage.usage1_kWhtoday += energy_diff;
|
||||||
RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1;
|
Energy.total1 = (float)(RtcSettings.energy_usage.usage1_kWhtotal + RtcSettings.energy_usage.usage1_kWhtoday) / 100000;
|
||||||
Energy.total1 = (float)(RtcSettings.energy_usage.usage1_kWhtotal + Energy.kWhtoday1) / 100000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EnergyUpdateTotal(float value, bool kwh)
|
||||||
|
{
|
||||||
|
char energy_total_chr[FLOATSZ];
|
||||||
|
dtostrfd(value, 4, energy_total_chr);
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: Energy Total %s %sWh"), energy_total_chr, (kwh) ? "k" : "");
|
||||||
|
|
||||||
|
uint32_t multiplier = (kwh) ? 100000 : 100; // kWh or Wh to deca milli Wh
|
||||||
|
|
||||||
|
if (0 == Energy.start_energy || (value < Energy.start_energy)) {
|
||||||
|
Energy.start_energy = value; // Init after restart and handle roll-over if any
|
||||||
|
}
|
||||||
|
else if (value != Energy.start_energy) {
|
||||||
|
Energy.kWhtoday = (unsigned long)((value - Energy.start_energy) * multiplier);
|
||||||
|
}
|
||||||
|
EnergyUpdateToday();
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
void Energy200ms(void)
|
void Energy200ms(void)
|
||||||
@ -160,16 +177,17 @@ void Energy200ms(void)
|
|||||||
|
|
||||||
if (RtcTime.valid) {
|
if (RtcTime.valid) {
|
||||||
if (LocalTime() == Midnight()) {
|
if (LocalTime() == Midnight()) {
|
||||||
Settings.energy_kWhyesterday = Energy.kWhtoday;
|
Settings.energy_kWhyesterday = RtcSettings.energy_kWhtoday;
|
||||||
|
|
||||||
Settings.energy_kWhtotal += Energy.kWhtoday;
|
RtcSettings.energy_kWhtotal += RtcSettings.energy_kWhtoday;
|
||||||
RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal;
|
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
|
||||||
Energy.kWhtoday = 0;
|
Energy.kWhtoday = 0;
|
||||||
|
Energy.kWhtoday_offset = 0;
|
||||||
RtcSettings.energy_kWhtoday = 0;
|
RtcSettings.energy_kWhtoday = 0;
|
||||||
|
Energy.start_energy = 0;
|
||||||
|
|
||||||
Settings.energy_usage.usage1_kWhtotal += Energy.kWhtoday1;
|
RtcSettings.energy_usage.usage1_kWhtotal += RtcSettings.energy_usage.usage1_kWhtoday;
|
||||||
RtcSettings.energy_usage.usage1_kWhtotal = Settings.energy_usage.usage1_kWhtotal;
|
Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal;
|
||||||
Energy.kWhtoday1 = 0;
|
|
||||||
RtcSettings.energy_usage.usage1_kWhtoday = 0;
|
RtcSettings.energy_usage.usage1_kWhtoday = 0;
|
||||||
|
|
||||||
Energy.kWhtoday_delta = 0;
|
Energy.kWhtoday_delta = 0;
|
||||||
@ -195,12 +213,10 @@ void EnergySaveState(void)
|
|||||||
{
|
{
|
||||||
Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0;
|
Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0;
|
||||||
|
|
||||||
Settings.energy_kWhtoday = Energy.kWhtoday;
|
Settings.energy_kWhtoday = RtcSettings.energy_kWhtoday;
|
||||||
RtcSettings.energy_kWhtoday = Energy.kWhtoday;
|
|
||||||
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
|
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
|
||||||
|
|
||||||
Settings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1;
|
Settings.energy_usage.usage1_kWhtoday = RtcSettings.energy_usage.usage1_kWhtoday;
|
||||||
RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday1;
|
|
||||||
Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal;
|
Settings.energy_usage.usage1_kWhtotal = RtcSettings.energy_usage.usage1_kWhtotal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,10 +313,10 @@ void EnergyMarginCheck(void)
|
|||||||
} else {
|
} else {
|
||||||
Energy.mplh_counter--;
|
Energy.mplh_counter--;
|
||||||
if (!Energy.mplh_counter) {
|
if (!Energy.mplh_counter) {
|
||||||
Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : "");
|
ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : "");
|
||||||
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
|
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
|
||||||
EnergyMqttShow();
|
EnergyMqttShow();
|
||||||
ExecuteCommandPower(1, POWER_OFF, SRC_MAXPOWER);
|
SetAllPower(POWER_ALL_OFF, SRC_MAXPOWER);
|
||||||
if (!Energy.mplr_counter) {
|
if (!Energy.mplr_counter) {
|
||||||
Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1;
|
Energy.mplr_counter = Settings.param[P_MAX_POWER_RETRY] +1;
|
||||||
}
|
}
|
||||||
@ -320,11 +336,11 @@ void EnergyMarginCheck(void)
|
|||||||
if (Energy.mplr_counter) {
|
if (Energy.mplr_counter) {
|
||||||
Energy.mplr_counter--;
|
Energy.mplr_counter--;
|
||||||
if (Energy.mplr_counter) {
|
if (Energy.mplr_counter) {
|
||||||
Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1));
|
ResponseTime_P(PSTR(",\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1));
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR));
|
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR));
|
||||||
ExecuteCommandPower(1, POWER_ON, SRC_MAXPOWER);
|
RestorePower(true, SRC_MAXPOWER);
|
||||||
} else {
|
} else {
|
||||||
Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0));
|
ResponseTime_P(PSTR(",\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0));
|
||||||
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
|
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
|
||||||
EnergyMqttShow();
|
EnergyMqttShow();
|
||||||
}
|
}
|
||||||
@ -338,17 +354,17 @@ void EnergyMarginCheck(void)
|
|||||||
energy_daily_u = (uint16_t)(Energy.daily * 1000);
|
energy_daily_u = (uint16_t)(Energy.daily * 1000);
|
||||||
if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) {
|
if (!Energy.max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) {
|
||||||
Energy.max_energy_state = 1;
|
Energy.max_energy_state = 1;
|
||||||
Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1));
|
ResponseTime_P(PSTR(",\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1));
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR));
|
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR));
|
||||||
ExecuteCommandPower(1, POWER_ON, SRC_MAXENERGY);
|
RestorePower(true, SRC_MAXENERGY);
|
||||||
}
|
}
|
||||||
else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) {
|
else if ((1 == Energy.max_energy_state ) && (energy_daily_u >= Settings.energy_max_energy)) {
|
||||||
Energy.max_energy_state = 2;
|
Energy.max_energy_state = 2;
|
||||||
dtostrfd(Energy.daily, 3, mqtt_data);
|
dtostrfd(Energy.daily, 3, mqtt_data);
|
||||||
Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : "");
|
ResponseTime_P(PSTR(",\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : "");
|
||||||
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
|
MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING);
|
||||||
EnergyMqttShow();
|
EnergyMqttShow();
|
||||||
ExecuteCommandPower(1, POWER_OFF, SRC_MAXENERGY);
|
SetAllPower(POWER_ALL_OFF, SRC_MAXENERGY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // USE_ENERGY_POWER_LIMIT
|
#endif // USE_ENERGY_POWER_LIMIT
|
||||||
@ -359,9 +375,10 @@ void EnergyMarginCheck(void)
|
|||||||
void EnergyMqttShow(void)
|
void EnergyMqttShow(void)
|
||||||
{
|
{
|
||||||
// {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}}
|
// {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}}
|
||||||
ResponseBeginTime();
|
|
||||||
int tele_period_save = tele_period;
|
int tele_period_save = tele_period;
|
||||||
tele_period = 2;
|
tele_period = 2;
|
||||||
|
mqtt_data[0] = '\0';
|
||||||
|
ResponseAppendTime();
|
||||||
EnergyShow(true);
|
EnergyShow(true);
|
||||||
tele_period = tele_period_save;
|
tele_period = tele_period_save;
|
||||||
ResponseJsonEnd();
|
ResponseJsonEnd();
|
||||||
@ -422,13 +439,14 @@ void CmndEnergyReset(void)
|
|||||||
if (p != XdrvMailbox.data) {
|
if (p != XdrvMailbox.data) {
|
||||||
switch (XdrvMailbox.index) {
|
switch (XdrvMailbox.index) {
|
||||||
case 1:
|
case 1:
|
||||||
Energy.kWhtoday = lnum *100;
|
Energy.kWhtoday_offset = lnum *100;
|
||||||
|
Energy.kWhtoday = 0;
|
||||||
Energy.kWhtoday_delta = 0;
|
Energy.kWhtoday_delta = 0;
|
||||||
Energy.period = Energy.kWhtoday;
|
Energy.period = Energy.kWhtoday_offset;
|
||||||
Settings.energy_kWhtoday = Energy.kWhtoday;
|
Settings.energy_kWhtoday = Energy.kWhtoday_offset;
|
||||||
RtcSettings.energy_kWhtoday = Energy.kWhtoday;
|
RtcSettings.energy_kWhtoday = Energy.kWhtoday_offset;
|
||||||
Energy.daily = (float)Energy.kWhtoday / 100000;
|
Energy.daily = (float)Energy.kWhtoday_offset / 100000;
|
||||||
if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday) {
|
if (!RtcSettings.energy_kWhtotal && !Energy.kWhtoday_offset) {
|
||||||
Settings.energy_kWhtotal_time = LocalTime();
|
Settings.energy_kWhtotal_time = LocalTime();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -438,14 +456,14 @@ void CmndEnergyReset(void)
|
|||||||
case 3:
|
case 3:
|
||||||
RtcSettings.energy_kWhtotal = lnum *100;
|
RtcSettings.energy_kWhtotal = lnum *100;
|
||||||
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
|
Settings.energy_kWhtotal = RtcSettings.energy_kWhtotal;
|
||||||
Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday) / 100000;
|
Energy.total = (float)(RtcSettings.energy_kWhtotal + Energy.kWhtoday_offset + Energy.kWhtoday) / 100000;
|
||||||
Settings.energy_kWhtotal_time = (!Energy.kWhtoday) ? LocalTime() : Midnight();
|
Settings.energy_kWhtotal_time = (!Energy.kWhtoday_offset) ? LocalTime() : Midnight();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Energy.kWhtoday1 > Energy.kWhtoday) {
|
if (RtcSettings.energy_usage.usage1_kWhtoday > (Energy.kWhtoday_offset + Energy.kWhtoday)) {
|
||||||
Energy.kWhtoday1 = Energy.kWhtoday;
|
RtcSettings.energy_usage.usage1_kWhtoday = Energy.kWhtoday_offset + Energy.kWhtoday;
|
||||||
}
|
}
|
||||||
if (Settings.energy_usage.usage1_kWhtoday > Settings.energy_kWhtoday) {
|
if (Settings.energy_usage.usage1_kWhtoday > Settings.energy_kWhtoday) {
|
||||||
Settings.energy_usage.usage1_kWhtoday = Settings.energy_kWhtoday;
|
Settings.energy_usage.usage1_kWhtoday = Settings.energy_kWhtoday;
|
||||||
@ -686,10 +704,20 @@ void EnergySnsInit(void)
|
|||||||
XnrgCall(FUNC_INIT);
|
XnrgCall(FUNC_INIT);
|
||||||
|
|
||||||
if (energy_flg) {
|
if (energy_flg) {
|
||||||
Energy.kWhtoday = (RtcSettingsValid()) ? RtcSettings.energy_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_kWhtoday : 0;
|
if (RtcSettingsValid()) {
|
||||||
Energy.kWhtoday1 = (RtcSettingsValid()) ? RtcSettings.energy_usage.usage1_kWhtoday : (RtcTime.day_of_year == Settings.energy_kWhdoy) ? Settings.energy_usage.usage1_kWhtoday : 0;
|
Energy.kWhtoday_offset = RtcSettings.energy_kWhtoday;
|
||||||
|
}
|
||||||
|
else if (RtcTime.day_of_year == Settings.energy_kWhdoy) {
|
||||||
|
Energy.kWhtoday_offset = Settings.energy_kWhtoday;
|
||||||
|
RtcSettings.energy_usage.usage1_kWhtoday = Settings.energy_usage.usage1_kWhtoday;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Energy.kWhtoday_offset = 0;
|
||||||
|
RtcSettings.energy_usage.usage1_kWhtoday = 0;
|
||||||
|
}
|
||||||
|
Energy.kWhtoday = 0;
|
||||||
Energy.kWhtoday_delta = 0;
|
Energy.kWhtoday_delta = 0;
|
||||||
Energy.period = Energy.kWhtoday;
|
Energy.period = Energy.kWhtoday_offset;
|
||||||
EnergyUpdateToday();
|
EnergyUpdateToday();
|
||||||
ticker_energy.attach_ms(200, Energy200ms);
|
ticker_energy.attach_ms(200, Energy200ms);
|
||||||
}
|
}
|
||||||
@ -770,8 +798,8 @@ void EnergyShow(bool json)
|
|||||||
float energy = 0;
|
float energy = 0;
|
||||||
char energy_period_chr[FLOATSZ];
|
char energy_period_chr[FLOATSZ];
|
||||||
if (show_energy_period) {
|
if (show_energy_period) {
|
||||||
if (Energy.period) energy = (float)(Energy.kWhtoday - Energy.period) / 100;
|
if (Energy.period) energy = (float)(RtcSettings.energy_kWhtoday - Energy.period) / 100;
|
||||||
Energy.period = Energy.kWhtoday;
|
Energy.period = RtcSettings.energy_kWhtoday;
|
||||||
dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr);
|
dtostrfd(energy, Settings.flag2.wattage_resolution, energy_period_chr);
|
||||||
snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr);
|
snprintf_P(speriod, sizeof(speriod), PSTR(",\"" D_JSON_PERIOD "\":%s"), energy_period_chr);
|
||||||
}
|
}
|
||||||
@ -806,7 +834,7 @@ void EnergyShow(bool json)
|
|||||||
char energy_total1_chr[FLOATSZ];
|
char energy_total1_chr[FLOATSZ];
|
||||||
dtostrfd(Energy.total1 * 1000, 1, energy_total1_chr); // Tariff1
|
dtostrfd(Energy.total1 * 1000, 1, energy_total1_chr); // Tariff1
|
||||||
char energy_non[2] = "0";
|
char energy_non[2] = "0";
|
||||||
DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, energy_non, energy_non, (int)Energy.active_power, 0);
|
DomoticzSensorP1SmartMeter(energy_total1_chr, energy_total_chr, energy_non, energy_non, (int)Energy.active_power);
|
||||||
|
|
||||||
if (Energy.voltage_available) {
|
if (Energy.voltage_available) {
|
||||||
DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage
|
DomoticzSensor(DZ_VOLTAGE, voltage_chr); // Voltage
|
||||||
@ -870,6 +898,9 @@ bool Xdrv03(uint8_t function)
|
|||||||
case FUNC_LOOP:
|
case FUNC_LOOP:
|
||||||
XnrgCall(FUNC_LOOP);
|
XnrgCall(FUNC_LOOP);
|
||||||
break;
|
break;
|
||||||
|
case FUNC_EVERY_250_MSECOND:
|
||||||
|
XnrgCall(FUNC_EVERY_250_MSECOND);
|
||||||
|
break;
|
||||||
#ifdef USE_ENERGY_MARGIN_DETECTION
|
#ifdef USE_ENERGY_MARGIN_DETECTION
|
||||||
case FUNC_SET_POWER:
|
case FUNC_SET_POWER:
|
||||||
Energy.power_steady_counter = 2;
|
Energy.power_steady_counter = 2;
|
||||||
|
@ -154,7 +154,7 @@ void IrReceiveCheck(void)
|
|||||||
} else {
|
} else {
|
||||||
snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue);
|
snprintf_P(svalue, sizeof(svalue), PSTR("\"0x%s\""), hvalue);
|
||||||
}
|
}
|
||||||
Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"),
|
ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"),
|
||||||
GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, svalue);
|
GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, svalue);
|
||||||
|
|
||||||
if (Settings.flag3.receive_raw) {
|
if (Settings.flag3.receive_raw) {
|
||||||
|
@ -220,7 +220,7 @@ void IrReceiveCheck(void)
|
|||||||
// if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) {
|
// if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) {
|
||||||
if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) {
|
if (!irsend_active && (now - ir_lasttime > IR_TIME_AVOID_DUPLICATE)) {
|
||||||
ir_lasttime = now;
|
ir_lasttime = now;
|
||||||
Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str());
|
ResponseTime_P(PSTR(",\"" D_JSON_IRRECEIVED "\":%s"), sendIRJsonState(results).c_str());
|
||||||
|
|
||||||
if (Settings.flag3.receive_raw) {
|
if (Settings.flag3.receive_raw) {
|
||||||
ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":["));
|
ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":["));
|
||||||
|
@ -214,7 +214,7 @@ void SonoffBridgeReceivedRaw(void)
|
|||||||
|
|
||||||
if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } // Bucket sniffing
|
if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } // Bucket sniffing
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\""));
|
ResponseTime_P(PSTR(",\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\""));
|
||||||
for (uint32_t i = 0; i < serial_in_byte_counter; i++) {
|
for (uint32_t i = 0; i < serial_in_byte_counter; i++) {
|
||||||
ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]);
|
ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]);
|
||||||
if (0xB1 == serial_in_buffer[1]) {
|
if (0xB1 == serial_in_buffer[1]) {
|
||||||
@ -226,6 +226,7 @@ void SonoffBridgeReceivedRaw(void)
|
|||||||
}
|
}
|
||||||
ResponseAppend_P(PSTR("\"}}"));
|
ResponseAppend_P(PSTR("\"}}"));
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW));
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW));
|
||||||
|
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +295,7 @@ void SonoffBridgeReceived(void)
|
|||||||
} else {
|
} else {
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id);
|
snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id);
|
||||||
}
|
}
|
||||||
Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"),
|
ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"),
|
||||||
sync_time, low_time, high_time, stemp, rfkey);
|
sync_time, low_time, high_time, stemp, rfkey);
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED));
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED));
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
|
@ -306,7 +306,7 @@ bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg
|
|||||||
if (device <= MAX_DOMOTICZ_IDX) {
|
if (device <= MAX_DOMOTICZ_IDX) {
|
||||||
if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) {
|
if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) {
|
||||||
Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"),
|
Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"),
|
||||||
(key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off");
|
(key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (POWER_TOGGLE == state) ? "Toggle" : "On" : "Off");
|
||||||
MqttPublish(domoticz_in_topic);
|
MqttPublish(domoticz_in_topic);
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
@ -383,14 +383,19 @@ void DomoticzSensorPowerEnergy(int power, char *energy)
|
|||||||
DomoticzSensor(DZ_POWER_ENERGY, data);
|
DomoticzSensor(DZ_POWER_ENERGY, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int consumed, int produced)
|
void DomoticzSensorP1SmartMeter(char *usage1, char *usage2, char *return1, char *return2, int power)
|
||||||
{
|
{
|
||||||
//usage1 = energy usage meter tariff 1, This is an incrementing counter
|
//usage1 = energy usage meter tariff 1, This is an incrementing counter
|
||||||
//usage2 = energy usage meter tariff 2, This is an incrementing counter
|
//usage2 = energy usage meter tariff 2, This is an incrementing counter
|
||||||
//return1 = energy return meter tariff 1, This is an incrementing counter
|
//return1 = energy return meter tariff 1, This is an incrementing counter
|
||||||
//return2 = energy return meter tariff 2, This is an incrementing counter
|
//return2 = energy return meter tariff 2, This is an incrementing counter
|
||||||
//consumed = actual usage power (Watt)
|
//power = if >= 0 actual usage power. if < 0 actual return power (Watt)
|
||||||
//produced = actual return power (Watt)
|
int consumed = power;
|
||||||
|
int produced = 0;
|
||||||
|
if (power < 0) {
|
||||||
|
consumed = 0;
|
||||||
|
produced = -power;
|
||||||
|
}
|
||||||
char data[64];
|
char data[64];
|
||||||
snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced);
|
snprintf_P(data, sizeof(data), PSTR("%s;%s;%s;%s;%d;%d"), usage1, usage2, return1, return2, consumed, produced);
|
||||||
DomoticzSensor(DZ_P1_SMART_METER, data);
|
DomoticzSensor(DZ_P1_SMART_METER, data);
|
||||||
|
@ -71,7 +71,7 @@ void SerialBridgeInput(void)
|
|||||||
if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) {
|
if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) {
|
||||||
serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed
|
serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed
|
||||||
char hex_char[(serial_bridge_in_byte_counter * 2) + 2];
|
char hex_char[(serial_bridge_in_byte_counter * 2) + 2];
|
||||||
Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"),
|
ResponseTime_P(PSTR(",\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"),
|
||||||
(serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer);
|
(serial_bridge_raw) ? ToHex_P((unsigned char*)serial_bridge_buffer, serial_bridge_in_byte_counter, hex_char, sizeof(hex_char)) : serial_bridge_buffer);
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED));
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED));
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
|
@ -296,7 +296,7 @@ void TimerEverySecond(void)
|
|||||||
if (xtimer.days & days) {
|
if (xtimer.days & days) {
|
||||||
Settings.timer[i].arm = xtimer.repeat;
|
Settings.timer[i].arm = xtimer.repeat;
|
||||||
#if defined(USE_RULES) || defined(USE_SCRIPT)
|
#if defined(USE_RULES) || defined(USE_SCRIPT)
|
||||||
if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands
|
if (POWER_BLINK == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands
|
||||||
Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1);
|
Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1);
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
} else
|
} else
|
||||||
|
@ -575,7 +575,7 @@ void KNX_CB_Action(message_t const &msg, void *arg)
|
|||||||
else if (chan->type < 17) // Toggle Relays
|
else if (chan->type < 17) // Toggle Relays
|
||||||
{
|
{
|
||||||
if (!toggle_inhibit) {
|
if (!toggle_inhibit) {
|
||||||
ExecuteCommandPower((chan->type) -8, 2, SRC_KNX);
|
ExecuteCommandPower((chan->type) -8, POWER_TOGGLE, SRC_KNX);
|
||||||
if (Settings.flag.knx_enable_enhancement) {
|
if (Settings.flag.knx_enable_enhancement) {
|
||||||
toggle_inhibit = TOGGLE_INHIBIT_TIME;
|
toggle_inhibit = TOGGLE_INHIBIT_TIME;
|
||||||
}
|
}
|
||||||
|
@ -1247,6 +1247,12 @@ void DisplayInitDriver(void)
|
|||||||
{
|
{
|
||||||
XdspCall(FUNC_DISPLAY_INIT_DRIVER);
|
XdspCall(FUNC_DISPLAY_INIT_DRIVER);
|
||||||
|
|
||||||
|
if (renderer) {
|
||||||
|
renderer->setTextFont(Settings.display_font);
|
||||||
|
renderer->setTextSize(Settings.display_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model);
|
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "Display model %d"), Settings.display_model);
|
||||||
|
|
||||||
if (Settings.display_model) {
|
if (Settings.display_model) {
|
||||||
@ -1376,14 +1382,18 @@ void CmndDisplaySize(void)
|
|||||||
{
|
{
|
||||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
|
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
|
||||||
Settings.display_size = XdrvMailbox.payload;
|
Settings.display_size = XdrvMailbox.payload;
|
||||||
|
if (renderer) renderer->setTextSize(Settings.display_size);
|
||||||
|
else DisplaySetSize(Settings.display_size);
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(Settings.display_size);
|
ResponseCmndNumber(Settings.display_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndDisplayFont(void)
|
void CmndDisplayFont(void)
|
||||||
{
|
{
|
||||||
if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) {
|
if ((XdrvMailbox.payload >=0) && (XdrvMailbox.payload <= 4)) {
|
||||||
Settings.display_font = XdrvMailbox.payload;
|
Settings.display_font = XdrvMailbox.payload;
|
||||||
|
if (renderer) renderer->setTextFont(Settings.display_font);
|
||||||
|
else DisplaySetFont(Settings.display_font);
|
||||||
}
|
}
|
||||||
ResponseCmndNumber(Settings.display_font);
|
ResponseCmndNumber(Settings.display_font);
|
||||||
}
|
}
|
||||||
@ -1804,7 +1814,7 @@ void Restore_graph(uint8_t num, char *path) {
|
|||||||
if (!fp) return;
|
if (!fp) return;
|
||||||
char vbuff[32];
|
char vbuff[32];
|
||||||
char *cp=vbuff;
|
char *cp=vbuff;
|
||||||
char buf[2];
|
uint8_t buf[2];
|
||||||
uint8_t findex=0;
|
uint8_t findex=0;
|
||||||
|
|
||||||
for (uint32_t count=0;count<=gp->xs+4;count++) {
|
for (uint32_t count=0;count<=gp->xs+4;count++) {
|
||||||
|
@ -166,8 +166,7 @@ bool PCA9685_Command(void)
|
|||||||
|
|
||||||
void PCA9685_OutputTelemetry(bool telemetry) {
|
void PCA9685_OutputTelemetry(bool telemetry) {
|
||||||
if (0 == pca9685_detected) { return; } // We do not do this if the PCA9685 has not been detected
|
if (0 == pca9685_detected) { return; } // We do not do this if the PCA9685 has not been detected
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq);
|
||||||
ResponseAppend_P(PSTR(",\"PCA9685\":{\"PWM_FREQ\":%i,"),pca9685_freq);
|
|
||||||
for (uint32_t pin=0;pin<16;pin++) {
|
for (uint32_t pin=0;pin<16;pin++) {
|
||||||
ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]);
|
ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
xdrv_16_tuyadimmer.ino - Tuya dimmer support for Sonoff-Tasmota
|
xdrv_16_tuyamcu.ino - Tuya MCU support for Sonoff-Tasmota
|
||||||
|
|
||||||
Copyright (C) 2019 digiblur, Joel Stein and Theo Arends
|
Copyright (C) 2019 digiblur, Joel Stein and Theo Arends
|
||||||
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
#ifdef USE_TUYA_DIMMER
|
#ifdef USE_TUYA_MCU
|
||||||
|
|
||||||
#define XDRV_16 16
|
#define XDRV_16 16
|
||||||
#define XNRG_08 8
|
#define XNRG_08 8
|
||||||
@ -61,10 +61,156 @@ struct TUYA {
|
|||||||
int byte_counter = 0; // Index in serial receive buffer
|
int byte_counter = 0; // Index in serial receive buffer
|
||||||
} Tuya;
|
} Tuya;
|
||||||
|
|
||||||
|
|
||||||
|
enum TuyaSupportedFunctions {
|
||||||
|
TUYA_MCU_FUNC_NONE,
|
||||||
|
TUYA_MCU_FUNC_SWT1 = 1, // Buttons
|
||||||
|
TUYA_MCU_FUNC_SWT2,
|
||||||
|
TUYA_MCU_FUNC_SWT3,
|
||||||
|
TUYA_MCU_FUNC_SWT4,
|
||||||
|
TUYA_MCU_FUNC_REL1 = 11, // Relays
|
||||||
|
TUYA_MCU_FUNC_REL2,
|
||||||
|
TUYA_MCU_FUNC_REL3,
|
||||||
|
TUYA_MCU_FUNC_REL4,
|
||||||
|
TUYA_MCU_FUNC_REL5,
|
||||||
|
TUYA_MCU_FUNC_REL6,
|
||||||
|
TUYA_MCU_FUNC_REL7,
|
||||||
|
TUYA_MCU_FUNC_REL8,
|
||||||
|
TUYA_MCU_FUNC_DIMMER = 21,
|
||||||
|
TUYA_MCU_FUNC_POWER = 31,
|
||||||
|
TUYA_MCU_FUNC_CURRENT,
|
||||||
|
TUYA_MCU_FUNC_VOLTAGE,
|
||||||
|
TUYA_MCU_FUNC_REL1_INV = 41, // Inverted Relays
|
||||||
|
TUYA_MCU_FUNC_REL2_INV,
|
||||||
|
TUYA_MCU_FUNC_REL3_INV,
|
||||||
|
TUYA_MCU_FUNC_REL4_INV,
|
||||||
|
TUYA_MCU_FUNC_REL5_INV,
|
||||||
|
TUYA_MCU_FUNC_REL6_INV,
|
||||||
|
TUYA_MCU_FUNC_REL7_INV,
|
||||||
|
TUYA_MCU_FUNC_REL8_INV,
|
||||||
|
TUYA_MCU_FUNC_LAST = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
const char kTuyaCommand[] PROGMEM = "|" // No prefix
|
||||||
|
D_CMND_TUYA_MCU;
|
||||||
|
|
||||||
|
void (* const TuyaCommand[])(void) PROGMEM = {
|
||||||
|
&CmndTuyaMcu
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
TuyaMcu fnid,dpid
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void CmndTuyaMcu(void) {
|
||||||
|
if (XdrvMailbox.data_len > 0) {
|
||||||
|
char *p;
|
||||||
|
uint8_t i = 0;
|
||||||
|
uint8_t parm[3] = { 0 };
|
||||||
|
for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 2; str = strtok_r(nullptr, ", ", &p)) {
|
||||||
|
parm[i] = strtoul(str, nullptr, 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TuyaFuncIdValid(parm[0])) {
|
||||||
|
TuyaAddMcuFunc(parm[0], parm[1]);
|
||||||
|
restart_flag = 2;
|
||||||
|
} else {
|
||||||
|
AddLog_P2(LOG_LEVEL_ERROR, PSTR("TYA: TuyaMcu Invalid function id=%d"), parm[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Response_P(PSTR("["));
|
||||||
|
bool added = false;
|
||||||
|
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
|
||||||
|
if (Settings.tuya_fnid_map[i].fnid != 0) {
|
||||||
|
if (added) {
|
||||||
|
ResponseAppend_P(PSTR(","));
|
||||||
|
}
|
||||||
|
ResponseAppend_P(PSTR("{\"fnId\":%d, \"dpId\":%d}" ), Settings.tuya_fnid_map[i].fnid, Settings.tuya_fnid_map[i].dpid);
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResponseAppend_P(PSTR("]"));
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Internal Functions
|
* Internal Functions
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
void TuyaAddMcuFunc(uint8_t fnId, uint8_t dpId) {
|
||||||
|
bool added = false;
|
||||||
|
|
||||||
|
if (fnId == 0 || dpId == 0) { // Delete entry
|
||||||
|
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
|
||||||
|
if ((dpId > 0 && Settings.tuya_fnid_map[i].dpid == dpId) || (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].fnid == fnId)) {
|
||||||
|
Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
|
||||||
|
Settings.tuya_fnid_map[i].dpid = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // Add or update
|
||||||
|
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
|
||||||
|
if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].dpid == 0 || Settings.tuya_fnid_map[i].fnid == fnId || Settings.tuya_fnid_map[i].fnid == 0) {
|
||||||
|
if (!added) { // Update entry if exisiting entry or add
|
||||||
|
Settings.tuya_fnid_map[i].fnid = fnId;
|
||||||
|
Settings.tuya_fnid_map[i].dpid = dpId;
|
||||||
|
added = true;
|
||||||
|
} else if (Settings.tuya_fnid_map[i].dpid == dpId || Settings.tuya_fnid_map[i].fnid == fnId) { // Remove existing entry if added to empty place
|
||||||
|
Settings.tuya_fnid_map[i].fnid = TUYA_MCU_FUNC_NONE;
|
||||||
|
Settings.tuya_fnid_map[i].dpid = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UpdateDevices();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateDevices() {
|
||||||
|
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
|
||||||
|
uint8_t fnId = Settings.tuya_fnid_map[i].fnid;
|
||||||
|
if (fnId > TUYA_MCU_FUNC_NONE && Settings.tuya_fnid_map[i].dpid > 0) {
|
||||||
|
|
||||||
|
if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) { //Relay
|
||||||
|
bitClear(rel_inverted, fnId - TUYA_MCU_FUNC_REL1);
|
||||||
|
} else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) { // Inverted Relay
|
||||||
|
bitSet(rel_inverted, fnId - TUYA_MCU_FUNC_REL1_INV);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool TuyaFuncIdValid(uint8_t fnId) {
|
||||||
|
return (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) ||
|
||||||
|
(fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) ||
|
||||||
|
fnId == TUYA_MCU_FUNC_DIMMER ||
|
||||||
|
(fnId >= TUYA_MCU_FUNC_POWER && fnId <= TUYA_MCU_FUNC_VOLTAGE) ||
|
||||||
|
(fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TuyaGetFuncId(uint8_t dpid) {
|
||||||
|
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
|
||||||
|
if (Settings.tuya_fnid_map[i].dpid == dpid) {
|
||||||
|
return Settings.tuya_fnid_map[i].fnid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TUYA_MCU_FUNC_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t TuyaGetDpId(uint8_t fnId) {
|
||||||
|
for (uint8_t i = 0; i < MAX_TUYA_FUNCTIONS; i++) {
|
||||||
|
if (Settings.tuya_fnid_map[i].fnid == fnId) {
|
||||||
|
return Settings.tuya_fnid_map[i].dpid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0)
|
void TuyaSendCmd(uint8_t cmd, uint8_t payload[] = nullptr, uint16_t payload_len = 0)
|
||||||
{
|
{
|
||||||
uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF));
|
uint8_t checksum = (0xFF + cmd + (payload_len >> 8) + (payload_len & 0xFF));
|
||||||
@ -131,7 +277,7 @@ bool TuyaSetPower(void)
|
|||||||
int16_t source = XdrvMailbox.payload;
|
int16_t source = XdrvMailbox.payload;
|
||||||
|
|
||||||
if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction
|
if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction
|
||||||
TuyaSendBool(active_device, bitRead(rpower, active_device-1));
|
TuyaSendBool(active_device, bitRead(rpower, active_device-1) ^ bitRead(rel_inverted, active_device-1));
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
@ -146,24 +292,22 @@ bool TuyaSetChannels(void)
|
|||||||
|
|
||||||
void LightSerialDuty(uint8_t duty)
|
void LightSerialDuty(uint8_t duty)
|
||||||
{
|
{
|
||||||
if (duty > 0 && !Tuya.ignore_dim && TuyaSerial) {
|
uint8_t dpid = TuyaGetDpId(TUYA_MCU_FUNC_DIMMER);
|
||||||
|
if (duty > 0 && !Tuya.ignore_dim && TuyaSerial && dpid > 0) {
|
||||||
if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default
|
if (Settings.flag3.tuya_dimmer_min_limit) { // Enable dimming limit SetOption69: Enabled by default
|
||||||
if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
|
if (duty < 25) { duty = 25; } // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
|
||||||
}
|
}
|
||||||
|
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
|
||||||
if (Settings.flag3.tuya_disable_dimmer == 0) {
|
if (Tuya.new_dim != duty) {
|
||||||
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, dpid);
|
||||||
if (Tuya.new_dim != duty) {
|
TuyaSendValue(dpid, duty);
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]);
|
|
||||||
TuyaSendValue(Settings.param[P_TUYA_DIMMER_ID], duty);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else if (dpid > 0) {
|
||||||
Tuya.ignore_dim = false; // reset flag
|
Tuya.ignore_dim = false; // reset flag
|
||||||
if (Settings.flag3.tuya_disable_dimmer == 0) {
|
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
|
||||||
duty = changeUIntScale(duty, 0, 255, 0, Settings.param[P_TUYA_DIMMER_MAX]);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Send dim skipped value=%d"), duty); // due to 0 or already set
|
} else {
|
||||||
}
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Cannot set dimmer. Dimmer Id unknown")); //
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,6 +333,7 @@ void TuyaResetWifi(void)
|
|||||||
void TuyaPacketProcess(void)
|
void TuyaPacketProcess(void)
|
||||||
{
|
{
|
||||||
char scmnd[20];
|
char scmnd[20];
|
||||||
|
uint8_t fnId = TUYA_MCU_FUNC_NONE;
|
||||||
|
|
||||||
switch (Tuya.buffer[3]) {
|
switch (Tuya.buffer[3]) {
|
||||||
|
|
||||||
@ -201,24 +346,33 @@ void TuyaPacketProcess(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TUYA_CMD_STATE:
|
case TUYA_CMD_STATE:
|
||||||
if (Tuya.buffer[5] == 5) { // on/off packet
|
fnId = TuyaGetFuncId(Tuya.buffer[6]);
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: FnId=%d is set for dpId=%d"), fnId, Tuya.buffer[6]);
|
||||||
|
// if (TuyaFuncIdValid(fnId)) {
|
||||||
|
if (Tuya.buffer[5] == 5) { // on/off packet
|
||||||
|
|
||||||
/*if ((power || Settings.light_dimmer > 0) && (power != Tuya.buffer[10])) {
|
if (fnId >= TUYA_MCU_FUNC_REL1 && fnId <= TUYA_MCU_FUNC_REL8) {
|
||||||
ExecuteCommandPower(1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10]?"On":"Off",bitRead(power, fnId - TUYA_MCU_FUNC_REL1)?"On":"Off");
|
||||||
}*/
|
if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1))) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Device-%d --> MCU State: %s Current State:%s"),Tuya.buffer[6],Tuya.buffer[10]?"On":"Off",bitRead(power, Tuya.buffer[6]-1)?"On":"Off");
|
ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1 + 1, Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
||||||
if ((power || Settings.light_dimmer > 0) && (Tuya.buffer[10] != bitRead(power, Tuya.buffer[6]-1))) {
|
}
|
||||||
ExecuteCommandPower(Tuya.buffer[6], Tuya.buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
} else if (fnId >= TUYA_MCU_FUNC_REL1_INV && fnId <= TUYA_MCU_FUNC_REL8_INV) {
|
||||||
}
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Relay-%d-Inverted --> MCU State: %s Current State:%s"), fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10]?"Off":"On",bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1?"Off":"On");
|
||||||
}
|
if (Tuya.buffer[10] != bitRead(power, fnId - TUYA_MCU_FUNC_REL1_INV) ^ 1) {
|
||||||
else if (Tuya.buffer[5] == 8) { // Long value packet
|
ExecuteCommandPower(fnId - TUYA_MCU_FUNC_REL1_INV + 1, Tuya.buffer[10] ^ 1, SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
||||||
|
}
|
||||||
|
} else if (fnId >= TUYA_MCU_FUNC_SWT1 && fnId <= TUYA_MCU_FUNC_SWT4) {
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Switch-%d --> MCU State: %d Current State:%d"),fnId - TUYA_MCU_FUNC_SWT1 + 1,Tuya.buffer[10], SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1));
|
||||||
|
|
||||||
if (Settings.flag3.tuya_disable_dimmer == 0) {
|
if (SwitchGetVirtual(fnId - TUYA_MCU_FUNC_SWT1) != Tuya.buffer[10]) {
|
||||||
if (!Settings.param[P_TUYA_DIMMER_ID]) {
|
SwitchSetVirtual(fnId - TUYA_MCU_FUNC_SWT1, Tuya.buffer[10]);
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Autoconfiguring Dimmer ID %d"), Tuya.buffer[6]);
|
SwitchHandler(1);
|
||||||
Settings.param[P_TUYA_DIMMER_ID] = Tuya.buffer[6];
|
}
|
||||||
}
|
}
|
||||||
if (Settings.param[P_TUYA_DIMMER_ID] == Tuya.buffer[6]) {
|
|
||||||
|
}
|
||||||
|
else if (Tuya.buffer[5] == 8) { // Long value packet
|
||||||
|
if (fnId == TUYA_MCU_FUNC_DIMMER) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Dim State=%d"), Tuya.buffer[13]);
|
||||||
Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100);
|
Tuya.new_dim = changeUIntScale((uint8_t) Tuya.buffer[13], 0, Settings.param[P_TUYA_DIMMER_MAX], 0, 100);
|
||||||
if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) {
|
if ((power || Settings.flag3.tuya_apply_o20) && (Tuya.new_dim > 0) && (abs(Tuya.new_dim - Settings.light_dimmer) > 1)) {
|
||||||
@ -228,30 +382,30 @@ void TuyaPacketProcess(void)
|
|||||||
ExecuteCommand(scmnd, SRC_SWITCH);
|
ExecuteCommand(scmnd, SRC_SWITCH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_ENERGY_SENSOR
|
#ifdef USE_ENERGY_SENSOR
|
||||||
if (Settings.param[P_TUYA_VOLTAGE_ID] == Tuya.buffer[6]) {
|
else if (fnId == TUYA_MCU_FUNC_VOLTAGE) {
|
||||||
Energy.voltage = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
Energy.voltage = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Settings.param[P_TUYA_VOLTAGE_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Voltage=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
||||||
} else if (Settings.param[P_TUYA_CURRENT_ID] == Tuya.buffer[6]) {
|
} else if (fnId == TUYA_MCU_FUNC_CURRENT) {
|
||||||
Energy.current = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000;
|
Energy.current = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 1000;
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Settings.param[P_TUYA_CURRENT_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Current=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
||||||
} else if (Settings.param[P_TUYA_POWER_ID] == Tuya.buffer[6]) {
|
} else if (fnId == TUYA_MCU_FUNC_POWER) {
|
||||||
Energy.active_power = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
Energy.active_power = (float)(Tuya.buffer[12] << 8 | Tuya.buffer[13]) / 10;
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Settings.param[P_TUYA_POWER_ID], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Rx ID=%d Active_Power=%d"), Tuya.buffer[6], (Tuya.buffer[12] << 8 | Tuya.buffer[13]));
|
||||||
|
|
||||||
if (Tuya.lastPowerCheckTime != 0 && Energy.active_power > 0) {
|
if (Tuya.lastPowerCheckTime != 0 && Energy.active_power > 0) {
|
||||||
Energy.kWhtoday += (float)Energy.active_power * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36;
|
Energy.kWhtoday += (float)Energy.active_power * (Rtc.utc_time - Tuya.lastPowerCheckTime) / 36;
|
||||||
EnergyUpdateToday();
|
EnergyUpdateToday();
|
||||||
|
}
|
||||||
|
Tuya.lastPowerCheckTime = Rtc.utc_time;
|
||||||
}
|
}
|
||||||
Tuya.lastPowerCheckTime = Rtc.utc_time;
|
#endif // USE_ENERGY_SENSOR
|
||||||
} else if (Settings.param[P_TUYA_DIMMER_ID] != Tuya.buffer[6]){
|
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX Unknown ID=%d"), Tuya.buffer[6]);
|
|
||||||
}
|
|
||||||
#endif // USE_ENERGY_SENSOR
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// } else {
|
||||||
|
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: Unknown FnId=%s for dpId=%s"), fnId, Tuya.buffer[6]);
|
||||||
|
// }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUYA_CMD_WIFI_RESET:
|
case TUYA_CMD_WIFI_RESET:
|
||||||
@ -266,9 +420,9 @@ void TuyaPacketProcess(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case TUYA_CMD_MCU_CONF:
|
case TUYA_CMD_MCU_CONF:
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("TYA: RX MCU configuration Mode=%d"), Tuya.buffer[5]);
|
||||||
|
|
||||||
if (Tuya.buffer[5] == 2) {
|
if (Tuya.buffer[5] == 2) { // Processing by ESP module mode
|
||||||
uint8_t led1_gpio = Tuya.buffer[6];
|
uint8_t led1_gpio = Tuya.buffer[6];
|
||||||
uint8_t key1_gpio = Tuya.buffer[7];
|
uint8_t key1_gpio = Tuya.buffer[7];
|
||||||
bool key1_set = false;
|
bool key1_set = false;
|
||||||
@ -307,21 +461,41 @@ bool TuyaModuleSelected(void)
|
|||||||
Settings.my_gp.io[3] = GPIO_TUYA_RX;
|
Settings.my_gp.io[3] = GPIO_TUYA_RX;
|
||||||
restart_flag = 2;
|
restart_flag = 2;
|
||||||
}
|
}
|
||||||
if (Settings.flag3.tuya_disable_dimmer == 0) {
|
|
||||||
|
if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) == 0 && TUYA_DIMMER_ID > 0) {
|
||||||
|
TuyaAddMcuFunc(TUYA_MCU_FUNC_DIMMER, TUYA_DIMMER_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool relaySet = false;
|
||||||
|
|
||||||
|
devices_present--;
|
||||||
|
|
||||||
|
for (uint8_t i = 0 ; i < MAX_TUYA_FUNCTIONS; i++) {
|
||||||
|
if ((Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1 && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8 ) ||
|
||||||
|
(Settings.tuya_fnid_map[i].fnid >= TUYA_MCU_FUNC_REL1_INV && Settings.tuya_fnid_map[i].fnid <= TUYA_MCU_FUNC_REL8_INV )) {
|
||||||
|
relaySet = true;
|
||||||
|
devices_present++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!relaySet) {
|
||||||
|
TuyaAddMcuFunc(TUYA_MCU_FUNC_REL1, 1);
|
||||||
|
devices_present++;
|
||||||
|
SettingsSaveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TuyaGetDpId(TUYA_MCU_FUNC_DIMMER) != 0) {
|
||||||
light_type = LT_SERIAL1;
|
light_type = LT_SERIAL1;
|
||||||
} else {
|
} else {
|
||||||
light_type = LT_BASIC;
|
light_type = LT_BASIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateDevices();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TuyaInit(void)
|
void TuyaInit(void)
|
||||||
{
|
{
|
||||||
devices_present += Settings.param[P_TUYA_RELAYS]; // SetOption41 - Add virtual relays if present
|
|
||||||
if (!Settings.param[P_TUYA_DIMMER_ID]) {
|
|
||||||
Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID;
|
|
||||||
}
|
|
||||||
Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE));
|
Tuya.buffer = (char*)(malloc(TUYA_BUFFER_SIZE));
|
||||||
if (Tuya.buffer != nullptr) {
|
if (Tuya.buffer != nullptr) {
|
||||||
TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2);
|
TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2);
|
||||||
@ -434,11 +608,11 @@ int Xnrg08(uint8_t function)
|
|||||||
if (TUYA_DIMMER == my_module_type) {
|
if (TUYA_DIMMER == my_module_type) {
|
||||||
if (FUNC_PRE_INIT == function) {
|
if (FUNC_PRE_INIT == function) {
|
||||||
if (!energy_flg) {
|
if (!energy_flg) {
|
||||||
if (Settings.param[P_TUYA_POWER_ID] != 0) {
|
if (TuyaGetDpId(TUYA_MCU_FUNC_POWER) != 0) {
|
||||||
if (Settings.param[P_TUYA_CURRENT_ID] == 0) {
|
if (TuyaGetDpId(TUYA_MCU_FUNC_CURRENT) == 0) {
|
||||||
Energy.current_available = false;
|
Energy.current_available = false;
|
||||||
}
|
}
|
||||||
if (Settings.param[P_TUYA_VOLTAGE_ID] == 0) {
|
if (TuyaGetDpId(TUYA_MCU_FUNC_VOLTAGE) == 0) {
|
||||||
Energy.voltage_available = false;
|
Energy.voltage_available = false;
|
||||||
}
|
}
|
||||||
energy_flg = XNRG_08;
|
energy_flg = XNRG_08;
|
||||||
@ -486,10 +660,13 @@ bool Xdrv16(uint8_t function)
|
|||||||
case FUNC_SET_CHANNELS:
|
case FUNC_SET_CHANNELS:
|
||||||
result = TuyaSetChannels();
|
result = TuyaSetChannels();
|
||||||
break;
|
break;
|
||||||
|
case FUNC_COMMAND:
|
||||||
|
result = DecodeCommand(kTuyaCommand, TuyaCommand);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // USE_TUYA_DIMMER
|
#endif // USE_TUYA_MCU
|
||||||
#endif // USE_LIGHT
|
#endif // USE_LIGHT
|
@ -67,7 +67,7 @@ void RfReceiveCheck(void)
|
|||||||
} else {
|
} else {
|
||||||
snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data);
|
snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data);
|
||||||
}
|
}
|
||||||
Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"),
|
ResponseTime_P(PSTR(",\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"),
|
||||||
stemp, bits, protocol, delay);
|
stemp, bits, protocol, delay);
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED));
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED));
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
|
@ -96,7 +96,7 @@ void SonoffIFanSetFanspeed(uint8_t fanspeed, bool sequence)
|
|||||||
fans = kIFan03Speed[fanspeed];
|
fans = kIFan03Speed[fanspeed];
|
||||||
}
|
}
|
||||||
for (uint32_t i = 2; i < 5; i++) {
|
for (uint32_t i = 2; i < 5; i++) {
|
||||||
uint8_t state = (fans &1) + 6; // Add no publishPowerState
|
uint8_t state = (fans &1) + POWER_OFF_NO_STATE; // Add no publishPowerState
|
||||||
ExecuteCommandPower(i, state, SRC_IGNORE); // Use relay 2, 3 and 4
|
ExecuteCommandPower(i, state, SRC_IGNORE); // Use relay 2, 3 and 4
|
||||||
fans >>= 1;
|
fans >>= 1;
|
||||||
}
|
}
|
||||||
|
@ -156,10 +156,10 @@ public:
|
|||||||
void publishMQTTReceived(void) {
|
void publishMQTTReceived(void) {
|
||||||
char hex_char[_payload.len()*2+2];
|
char hex_char[_payload.len()*2+2];
|
||||||
ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char));
|
ToHex_P((unsigned char*)_payload.getBuffer(), _payload.len(), hex_char, sizeof(hex_char));
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEEZCLRECEIVED "\":{\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d,"
|
ResponseTime_P(PSTR(",\"" D_JSON_ZIGBEEZCLRECEIVED "\":{\"fc\":\"0x%02X\",\"manuf\":\"0x%04X\",\"transact\":%d,"
|
||||||
"\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"),
|
"\"cmdid\":\"0x%02X\",\"payload\":\"%s\"}}"),
|
||||||
_frame_control, _manuf_code, _transact_seq, _cmd_id,
|
_frame_control, _manuf_code, _transact_seq, _cmd_id,
|
||||||
hex_char);
|
hex_char);
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLSENT));
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZCLSENT));
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
}
|
}
|
||||||
@ -834,7 +834,7 @@ void ZigbeeInput(void)
|
|||||||
SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); // remove SOF, LEN and FCS
|
SBuffer znp_buffer = zigbee_buffer->subBuffer(2, zigbee_frame_len - 3); // remove SOF, LEN and FCS
|
||||||
|
|
||||||
ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char));
|
ToHex_P((unsigned char*)znp_buffer.getBuffer(), znp_buffer.len(), hex_char, sizeof(hex_char));
|
||||||
Response_P(PSTR("{\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char);
|
ResponseTime_P(PSTR(",\"" D_JSON_ZIGBEEZNPRECEIVED "\":\"%s\"}"), hex_char);
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPRECEIVED));
|
MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_ZIGBEEZNPRECEIVED));
|
||||||
XdrvRulesProcess();
|
XdrvRulesProcess();
|
||||||
|
|
||||||
|
@ -145,13 +145,13 @@ void SH1106Refresh(void) // Every second
|
|||||||
if (Settings.display_mode) { // Mode 0 is User text
|
if (Settings.display_mode) { // Mode 0 is User text
|
||||||
switch (Settings.display_mode) {
|
switch (Settings.display_mode) {
|
||||||
case 1: // Time
|
case 1: // Time
|
||||||
Ssd1306Time();
|
SH1106Time();
|
||||||
break;
|
break;
|
||||||
case 2: // Local
|
case 2: // Local
|
||||||
case 3: // Local
|
case 3: // Local
|
||||||
case 4: // Mqtt
|
case 4: // Mqtt
|
||||||
case 5: // Mqtt
|
case 5: // Mqtt
|
||||||
Ssd1306PrintLog();
|
SH1106PrintLog();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,13 +124,19 @@ void ILI9488_InitDriver()
|
|||||||
|
|
||||||
#ifdef USE_TOUCH_BUTTONS
|
#ifdef USE_TOUCH_BUTTONS
|
||||||
void ILI9488_MQTT(uint8_t count,const char *cp) {
|
void ILI9488_MQTT(uint8_t count,const char *cp) {
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7);
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"RA8876\":{\"%s%d\":\"%d\"}}"), mqtt_data,cp,count+1,(buttons[count]->vpower&0x80)>>7);
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ILI9488_RDW_BUTT(uint32_t count,uint32_t pwr) {
|
||||||
|
buttons[count]->xdrawButton(pwr);
|
||||||
|
if (pwr) buttons[count]->vpower|=0x80;
|
||||||
|
else buttons[count]->vpower&=0x7f;
|
||||||
|
}
|
||||||
// check digitizer hit
|
// check digitizer hit
|
||||||
void FT6236Check() {
|
void FT6236Check() {
|
||||||
uint16_t temp;
|
uint16_t temp;
|
||||||
|
uint8_t rbutt=0,vbutt=0;
|
||||||
ili9488_ctouch_counter++;
|
ili9488_ctouch_counter++;
|
||||||
if (2 == ili9488_ctouch_counter) {
|
if (2 == ili9488_ctouch_counter) {
|
||||||
// every 100 ms should be enough
|
// every 100 ms should be enough
|
||||||
@ -158,17 +164,17 @@ if (2 == ili9488_ctouch_counter) {
|
|||||||
// now must compare with defined buttons
|
// now must compare with defined buttons
|
||||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||||
if (buttons[count]) {
|
if (buttons[count]) {
|
||||||
|
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||||
if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) {
|
if (buttons[count]->contains(ili9488_pLoc.x,ili9488_pLoc.y)) {
|
||||||
// did hit
|
// did hit
|
||||||
buttons[count]->press(true);
|
buttons[count]->press(true);
|
||||||
if (buttons[count]->justPressed()) {
|
if (buttons[count]->justPressed()) {
|
||||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
|
||||||
if (!bflags) {
|
if (!bflags) {
|
||||||
// real button
|
uint8_t pwr=bitRead(power,rbutt);
|
||||||
if (!SendKey(0, count+1, POWER_TOGGLE)) {
|
if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) {
|
||||||
ExecuteCommandPower(count+1, POWER_TOGGLE, SRC_BUTTON);
|
ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON);
|
||||||
|
ILI9488_RDW_BUTT(count,!pwr);
|
||||||
}
|
}
|
||||||
buttons[count]->xdrawButton(bitRead(power,count));
|
|
||||||
} else {
|
} else {
|
||||||
// virtual button
|
// virtual button
|
||||||
const char *cp;
|
const char *cp;
|
||||||
@ -186,6 +192,11 @@ if (2 == ili9488_ctouch_counter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!bflags) {
|
||||||
|
rbutt++;
|
||||||
|
} else {
|
||||||
|
vbutt++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,15 +204,27 @@ if (2 == ili9488_ctouch_counter) {
|
|||||||
// no hit
|
// no hit
|
||||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||||
if (buttons[count]) {
|
if (buttons[count]) {
|
||||||
|
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||||
buttons[count]->press(false);
|
buttons[count]->press(false);
|
||||||
if (buttons[count]->justReleased()) {
|
if (buttons[count]->justReleased()) {
|
||||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||||
if (bflags>1) {
|
if (bflags>0) {
|
||||||
// push button
|
if (bflags>1) {
|
||||||
buttons[count]->vpower&=0x7f;
|
// push button
|
||||||
ILI9488_MQTT(count,"PBT");
|
buttons[count]->vpower&=0x7f;
|
||||||
|
ILI9488_MQTT(count,"PBT");
|
||||||
|
}
|
||||||
|
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
||||||
}
|
}
|
||||||
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
}
|
||||||
|
if (!bflags) {
|
||||||
|
// check if power button stage changed
|
||||||
|
uint8_t pwr=bitRead(power,rbutt);
|
||||||
|
uint8_t vpwr=(buttons[count]->vpower&0x80)>>7;
|
||||||
|
if (pwr!=vpwr) {
|
||||||
|
ILI9488_RDW_BUTT(count,pwr);
|
||||||
|
}
|
||||||
|
rbutt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,14 +109,20 @@ void RA8876_InitDriver()
|
|||||||
|
|
||||||
#ifdef USE_TOUCH_BUTTONS
|
#ifdef USE_TOUCH_BUTTONS
|
||||||
void RA8876_MQTT(uint8_t count,const char *cp) {
|
void RA8876_MQTT(uint8_t count,const char *cp) {
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
ResponseTime_P(PSTR(",\"RA8876\":{\"%s%d\":\"%d\"}}"), cp,count+1,(buttons[count]->vpower&0x80)>>7);
|
||||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"RA8876\":{\"%s%d\":\"%d\"}}"), mqtt_data,cp,count+1,(buttons[count]->vpower&0x80)>>7);
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RA8876_RDW_BUTT(uint32_t count,uint32_t pwr) {
|
||||||
|
buttons[count]->xdrawButton(pwr);
|
||||||
|
if (pwr) buttons[count]->vpower|=0x80;
|
||||||
|
else buttons[count]->vpower&=0x7f;
|
||||||
|
}
|
||||||
|
|
||||||
// check digitizer hit
|
// check digitizer hit
|
||||||
void FT5316Check() {
|
void FT5316Check() {
|
||||||
uint16_t temp;
|
uint16_t temp;
|
||||||
|
uint8_t rbutt=0,vbutt=0;
|
||||||
ra8876_ctouch_counter++;
|
ra8876_ctouch_counter++;
|
||||||
if (2 == ra8876_ctouch_counter) {
|
if (2 == ra8876_ctouch_counter) {
|
||||||
// every 100 ms should be enough
|
// every 100 ms should be enough
|
||||||
@ -153,23 +159,26 @@ if (2 == ra8876_ctouch_counter) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %d,%d"),ra8876_pLoc.x,ra8876_pLoc.y);
|
||||||
|
|
||||||
|
|
||||||
//Serial.printf("loc x: %d , loc y: %d\n",pLoc.x,pLoc.y);
|
//Serial.printf("loc x: %d , loc y: %d\n",pLoc.x,pLoc.y);
|
||||||
|
|
||||||
// now must compare with defined buttons
|
// now must compare with defined buttons
|
||||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||||
if (buttons[count]) {
|
if (buttons[count]) {
|
||||||
|
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||||
if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) {
|
if (buttons[count]->contains(ra8876_pLoc.x,ra8876_pLoc.y)) {
|
||||||
// did hit
|
// did hit
|
||||||
buttons[count]->press(true);
|
buttons[count]->press(true);
|
||||||
if (buttons[count]->justPressed()) {
|
if (buttons[count]->justPressed()) {
|
||||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
|
||||||
if (!bflags) {
|
if (!bflags) {
|
||||||
// real button
|
// real button
|
||||||
if (!SendKey(0, count+1, POWER_TOGGLE)) {
|
uint8_t pwr=bitRead(power,rbutt);
|
||||||
ExecuteCommandPower(count+1, POWER_TOGGLE, SRC_BUTTON);
|
if (!SendKey(KEY_BUTTON, rbutt+1, POWER_TOGGLE)) {
|
||||||
|
ExecuteCommandPower(rbutt+1, POWER_TOGGLE, SRC_BUTTON);
|
||||||
|
RA8876_RDW_BUTT(count,!pwr);
|
||||||
}
|
}
|
||||||
buttons[count]->xdrawButton(bitRead(power,count));
|
|
||||||
} else {
|
} else {
|
||||||
// virtual button
|
// virtual button
|
||||||
const char *cp;
|
const char *cp;
|
||||||
@ -187,6 +196,11 @@ if (2 == ra8876_ctouch_counter) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!bflags) {
|
||||||
|
rbutt++;
|
||||||
|
} else {
|
||||||
|
vbutt++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,15 +208,26 @@ if (2 == ra8876_ctouch_counter) {
|
|||||||
// no hit
|
// no hit
|
||||||
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
for (uint8_t count=0; count<MAXBUTTONS; count++) {
|
||||||
if (buttons[count]) {
|
if (buttons[count]) {
|
||||||
|
uint8_t bflags=buttons[count]->vpower&0x7f;
|
||||||
buttons[count]->press(false);
|
buttons[count]->press(false);
|
||||||
if (buttons[count]->justReleased()) {
|
if (buttons[count]->justReleased()) {
|
||||||
uint8_t bflags=buttons[count]->vpower&0x7f;
|
if (bflags>0) {
|
||||||
if (bflags>1) {
|
if (bflags>1) {
|
||||||
// push button
|
// push button
|
||||||
buttons[count]->vpower&=0x7f;
|
buttons[count]->vpower&=0x7f;
|
||||||
RA8876_MQTT(count,"PBT");
|
RA8876_MQTT(count,"PBT");
|
||||||
|
}
|
||||||
|
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
||||||
}
|
}
|
||||||
buttons[count]->xdrawButton(buttons[count]->vpower&0x80);
|
}
|
||||||
|
if (!bflags) {
|
||||||
|
// check if power button stage changed
|
||||||
|
uint8_t pwr=bitRead(power,rbutt);
|
||||||
|
uint8_t vpwr=(buttons[count]->vpower&0x80)>>7;
|
||||||
|
if (pwr!=vpwr) {
|
||||||
|
RA8876_RDW_BUTT(count,pwr);
|
||||||
|
}
|
||||||
|
rbutt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,12 +181,7 @@ void PzemEvery200ms(void)
|
|||||||
Energy.active_power = value;
|
Energy.active_power = value;
|
||||||
break;
|
break;
|
||||||
case 4: // Total energy as 99999Wh
|
case 4: // Total energy as 99999Wh
|
||||||
if (!Energy.start_energy || (value < Energy.start_energy)) Energy.start_energy = value; // Init after restart and hanlde roll-over if any
|
EnergyUpdateTotal(value, false);
|
||||||
if (value != Energy.start_energy) {
|
|
||||||
Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * 100);
|
|
||||||
Energy.start_energy = value;
|
|
||||||
}
|
|
||||||
EnergyUpdateToday();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pzem_read_state++;
|
pzem_read_state++;
|
||||||
|
@ -64,7 +64,7 @@ void PzemAcEverySecond(void)
|
|||||||
uint8_t buffer[26];
|
uint8_t buffer[26];
|
||||||
|
|
||||||
uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, 10);
|
uint8_t error = PzemAcModbus->ReceiveBuffer(buffer, 10);
|
||||||
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer));
|
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemAc response error %d"), error);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemAc response error %d"), error);
|
||||||
@ -82,12 +82,7 @@ void PzemAcEverySecond(void)
|
|||||||
Energy.power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
|
Energy.power_factor = (float)((buffer[19] << 8) + buffer[20]) / 100.0; // 1.00
|
||||||
float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh
|
float energy = (float)((buffer[15] << 24) + (buffer[16] << 16) + (buffer[13] << 8) + buffer[14]); // 4294967295 Wh
|
||||||
|
|
||||||
if (!Energy.start_energy || (energy < Energy.start_energy)) { Energy.start_energy = energy; } // Init after restart and handle roll-over if any
|
EnergyUpdateTotal(energy, false);
|
||||||
if (energy != Energy.start_energy) {
|
|
||||||
Energy.kWhtoday += (unsigned long)((energy - Energy.start_energy) * 100);
|
|
||||||
Energy.start_energy = energy;
|
|
||||||
}
|
|
||||||
EnergyUpdateToday();
|
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,7 @@ void PzemDcEverySecond(void)
|
|||||||
uint8_t buffer[22];
|
uint8_t buffer[22];
|
||||||
|
|
||||||
uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, 8);
|
uint8_t error = PzemDcModbus->ReceiveBuffer(buffer, 8);
|
||||||
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer));
|
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemDc response error %d"), error);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "PzemDc response error %d"), error);
|
||||||
@ -61,12 +61,7 @@ void PzemDcEverySecond(void)
|
|||||||
Energy.active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W
|
Energy.active_power = (float)((buffer[9] << 24) + (buffer[10] << 16) + (buffer[7] << 8) + buffer[8]) / 10.0; // 429496729.0 W
|
||||||
float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh
|
float energy = (float)((buffer[13] << 24) + (buffer[14] << 16) + (buffer[11] << 8) + buffer[12]); // 4294967295 Wh
|
||||||
|
|
||||||
if (!Energy.start_energy || (energy < Energy.start_energy)) { Energy.start_energy = energy; } // Init after restart and handle roll-over if any
|
EnergyUpdateTotal(energy, false);
|
||||||
if (energy != Energy.start_energy) {
|
|
||||||
Energy.kWhtoday += (unsigned long)((energy - Energy.start_energy) * 100);
|
|
||||||
Energy.start_energy = energy;
|
|
||||||
}
|
|
||||||
EnergyUpdateToday();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ struct SDM220 {
|
|||||||
|
|
||||||
/*********************************************************************************************/
|
/*********************************************************************************************/
|
||||||
|
|
||||||
void SDM120Every200ms(void)
|
void SDM120Every250ms(void)
|
||||||
{
|
{
|
||||||
bool data_ready = Sdm120Modbus->ReceiveReady();
|
bool data_ready = Sdm120Modbus->ReceiveReady();
|
||||||
|
|
||||||
@ -86,15 +86,18 @@ void SDM120Every200ms(void)
|
|||||||
uint8_t buffer[9];
|
uint8_t buffer[9];
|
||||||
|
|
||||||
uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2);
|
uint32_t error = Sdm120Modbus->ReceiveBuffer(buffer, 2);
|
||||||
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, (buffer[2]) ? buffer[2] +5 : sizeof(buffer));
|
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, buffer, sizeof(buffer));
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "SDM120 response error %d"), error);
|
||||||
} else {
|
} else {
|
||||||
Energy.data_valid = 0;
|
Energy.data_valid = 0;
|
||||||
|
|
||||||
|
// 0 1 2 3 4 5 6 7 8
|
||||||
|
// SA FC BC Fh Fl Sh Sl Cl Ch
|
||||||
|
// 01 04 04 43 66 33 34 1B 38 = 230.2 Volt
|
||||||
float value;
|
float value;
|
||||||
((uint8_t*)&value)[3] = buffer[3]; // Get float values
|
((uint8_t*)&value)[3] = buffer[3]; // Get float values
|
||||||
((uint8_t*)&value)[2] = buffer[4];
|
((uint8_t*)&value)[2] = buffer[4];
|
||||||
((uint8_t*)&value)[1] = buffer[5];
|
((uint8_t*)&value)[1] = buffer[5];
|
||||||
((uint8_t*)&value)[0] = buffer[6];
|
((uint8_t*)&value)[0] = buffer[6];
|
||||||
@ -129,14 +132,7 @@ void SDM120Every200ms(void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case 7:
|
||||||
if (!Energy.start_energy || (value < Energy.start_energy)) { // 484.708 kWh
|
EnergyUpdateTotal(value, true); // 484.708 kWh
|
||||||
Energy.start_energy = value; // Init after restart and hanlde roll-over if any
|
|
||||||
}
|
|
||||||
if (value != Energy.start_energy) {
|
|
||||||
Energy.kWhtoday += (unsigned long)((value - Energy.start_energy) * 100000); // kWh to deca milli Wh
|
|
||||||
Energy.start_energy = value;
|
|
||||||
}
|
|
||||||
EnergyUpdateToday();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef USE_SDM220
|
#ifdef USE_SDM220
|
||||||
@ -266,8 +262,8 @@ int Xnrg09(uint8_t function)
|
|||||||
case FUNC_INIT:
|
case FUNC_INIT:
|
||||||
Sdm120SnsInit();
|
Sdm120SnsInit();
|
||||||
break;
|
break;
|
||||||
case FUNC_EVERY_200_MSECOND:
|
case FUNC_EVERY_250_MSECOND:
|
||||||
if (uptime > 4) { SDM120Every200ms(); }
|
if (uptime > 4) { SDM120Every250ms(); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef USE_SDM220
|
#ifdef USE_SDM220
|
||||||
|
@ -303,8 +303,7 @@ void MCP230xx_CheckForInterrupt(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (int_tele) {
|
if (int_tele) {
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"),
|
||||||
ResponseAppend_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"),
|
|
||||||
intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int);
|
intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int);
|
||||||
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT"));
|
MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT"));
|
||||||
}
|
}
|
||||||
@ -730,8 +729,7 @@ void MCP230xx_OutputTelemetry(void) {
|
|||||||
}
|
}
|
||||||
if (outputcount) {
|
if (outputcount) {
|
||||||
char stt[7];
|
char stt[7];
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"MCP230_OUT\":{"));
|
||||||
ResponseAppend_P(PSTR(",\"MCP230_OUT\":{"));
|
|
||||||
for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) {
|
for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) {
|
||||||
if (Settings.mcp230xx_config[pinx].pinmode >= 5) {
|
if (Settings.mcp230xx_config[pinx].pinmode >= 5) {
|
||||||
sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode));
|
sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode));
|
||||||
@ -746,8 +744,7 @@ void MCP230xx_OutputTelemetry(void) {
|
|||||||
#endif // USE_MCP230xx_OUTPUT
|
#endif // USE_MCP230xx_OUTPUT
|
||||||
|
|
||||||
void MCP230xx_Interrupt_Counter_Report(void) {
|
void MCP230xx_Interrupt_Counter_Report(void) {
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"MCP230_INTTIMER\":{"));
|
||||||
ResponseAppend_P(PSTR(",\"MCP230_INTTIMER\":{"));
|
|
||||||
for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) {
|
for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) {
|
||||||
if (Settings.mcp230xx_config[pinx].int_count_en) { // Counting is enabled for this pin so we add to report
|
if (Settings.mcp230xx_config[pinx].int_count_en) { // Counting is enabled for this pin so we add to report
|
||||||
ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]);
|
ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]);
|
||||||
@ -761,8 +758,7 @@ void MCP230xx_Interrupt_Counter_Report(void) {
|
|||||||
|
|
||||||
void MCP230xx_Interrupt_Retain_Report(void) {
|
void MCP230xx_Interrupt_Retain_Report(void) {
|
||||||
uint16_t retainresult = 0;
|
uint16_t retainresult = 0;
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"MCP_INTRETAIN\":{"));
|
||||||
ResponseAppend_P(PSTR(",\"MCP_INTRETAIN\":{"));
|
|
||||||
for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) {
|
for (uint32_t pinx = 0;pinx < mcp230xx_pincount;pinx++) {
|
||||||
if (Settings.mcp230xx_config[pinx].int_retain_flag) {
|
if (Settings.mcp230xx_config[pinx].int_retain_flag) {
|
||||||
ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]);
|
ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]);
|
||||||
|
@ -494,12 +494,10 @@ void PN532_ScanForTag(void)
|
|||||||
pn532_function = 0;
|
pn532_function = 0;
|
||||||
#endif // USE_PN532_DATA_FUNCTION
|
#endif // USE_PN532_DATA_FUNCTION
|
||||||
|
|
||||||
ResponseBeginTime();
|
|
||||||
|
|
||||||
#ifdef USE_PN532_DATA_FUNCTION
|
#ifdef USE_PN532_DATA_FUNCTION
|
||||||
ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas);
|
ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas);
|
||||||
#else
|
#else
|
||||||
ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids);
|
ResponseTime_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids);
|
||||||
#endif // USE_PN532_DATA_FUNCTION
|
#endif // USE_PN532_DATA_FUNCTION
|
||||||
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
@ -541,8 +539,7 @@ bool PN532_Command(void)
|
|||||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) {
|
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) {
|
||||||
pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00...
|
pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00...
|
||||||
AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be erased"));
|
AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be erased"));
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"E\"}}"));
|
||||||
ResponseAppend_P(PSTR(",\"PN532\":{\"COMMAND\":\"E\"}}"));
|
|
||||||
return serviced;
|
return serviced;
|
||||||
}
|
}
|
||||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) {
|
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) {
|
||||||
@ -558,8 +555,7 @@ bool PN532_Command(void)
|
|||||||
pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string
|
pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string
|
||||||
pn532_function = 2;
|
pn532_function = 2;
|
||||||
AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata);
|
AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata);
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}"));
|
||||||
ResponseAppend_P(PSTR(",\"PN532\":{\"COMMAND\":\"S\"}}"));
|
|
||||||
return serviced;
|
return serviced;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,8 +253,7 @@ void SPS30_Show(bool json) {
|
|||||||
|
|
||||||
void CmdClean(void) {
|
void CmdClean(void) {
|
||||||
sps30_cmd(SPS_CMD_CLEAN);
|
sps30_cmd(SPS_CMD_CLEAN);
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}"));
|
||||||
ResponseAppend_P(PSTR(",\"SPS30\":{\"CFAN\":\"true\"}}"));
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +106,7 @@ void RDM6300_ScanForTag() {
|
|||||||
memcpy(rdm_uid_str,&rdm_buffer[2],8);
|
memcpy(rdm_uid_str,&rdm_buffer[2],8);
|
||||||
rdm_uid_str[9]=0;
|
rdm_uid_str[9]=0;
|
||||||
|
|
||||||
Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
ResponseTime_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str);
|
||||||
ResponseAppend_P(PSTR(",\"RDM6300\":{\"UID\":\"%s\"}}"), rdm_uid_str);
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
/*
|
/*
|
||||||
char command[24];
|
char command[24];
|
||||||
|
@ -547,8 +547,7 @@ void ibeacon_mqtt(const char *mac,const char *rssi) {
|
|||||||
memcpy(s_rssi,rssi,4);
|
memcpy(s_rssi,rssi,4);
|
||||||
s_rssi[4]=0;
|
s_rssi[4]=0;
|
||||||
int16_t n_rssi=atoi(s_rssi);
|
int16_t n_rssi=atoi(s_rssi);
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"" D_CMND_IBEACON "_%s\":{\"RSSI\":%d}}"),s_mac,n_rssi);
|
||||||
ResponseAppend_P(PSTR(",\"" D_CMND_IBEACON "_%s\":{\"RSSI\":%d}}"),s_mac,n_rssi);
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,6 +140,11 @@ struct METER_DESC {
|
|||||||
uint16_t flag;
|
uint16_t flag;
|
||||||
int32_t params;
|
int32_t params;
|
||||||
char prefix[8];
|
char prefix[8];
|
||||||
|
int8_t trxpin;
|
||||||
|
uint8_t tsecs;
|
||||||
|
char *txmem;
|
||||||
|
uint8_t index;
|
||||||
|
uint8_t max_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
// meter list , enter new meters here
|
// meter list , enter new meters here
|
||||||
@ -167,7 +172,7 @@ struct METER_DESC {
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'o',0,SML_BAUDRATE,"OBIS"}};
|
[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}};
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
"1,1-0:1.8.0*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
||||||
"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|"
|
"1,1-0:2.8.0*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|"
|
||||||
@ -185,7 +190,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'o',0,SML_BAUDRATE,"OBIS"}};
|
[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}};
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
||||||
"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|"
|
"1,1-0:2.8.1*255(@1," D_TPWROUT ",KWh," DJ_TPWROUT ",4|"
|
||||||
@ -199,7 +204,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'s',0,SML_BAUDRATE,"SML"}};
|
[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}};
|
||||||
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
//0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff
|
//0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff
|
||||||
@ -218,7 +223,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'s',0,SML_BAUDRATE,"SML"}};
|
[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}};
|
||||||
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
||||||
// verbrauch total
|
// verbrauch total
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
@ -236,7 +241,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'s',0,SML_BAUDRATE,"SML"}};
|
[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}};
|
||||||
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
||||||
// verbrauch total
|
// verbrauch total
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
@ -252,7 +257,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'s',0,SML_BAUDRATE,"strom"}};
|
[0]={3,'s',0,SML_BAUDRATE,"strom",-1,1,0}};
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
//0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff
|
//0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff
|
||||||
"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
||||||
@ -275,7 +280,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'s',0,SML_BAUDRATE,"SML"}};
|
[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}};
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
//0x77,0x07,0x01,0x00,0x01,0x08,0x01,0xff
|
//0x77,0x07,0x01,0x00,0x01,0x08,0x01,0xff
|
||||||
"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
"1,77070100010800ff@1000," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
||||||
@ -291,9 +296,9 @@ const uint8_t meter[]=
|
|||||||
#define METERS_USED 3
|
#define METERS_USED 3
|
||||||
|
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'o',0,SML_BAUDRATE,"OBIS"}, // harware serial RX pin
|
[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, // harware serial RX pin
|
||||||
[1]={14,'s',0,SML_BAUDRATE,"SML"}, // GPIO14 software serial
|
[1]={14,'s',0,SML_BAUDRATE,"SML",-1,1,0}, // GPIO14 software serial
|
||||||
[2]={4,'o',0,SML_BAUDRATE,"OBIS2"}}; // GPIO4 software serial
|
[2]={4,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; // GPIO4 software serial
|
||||||
|
|
||||||
// 3 Zähler definiert
|
// 3 Zähler definiert
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
@ -320,8 +325,8 @@ const uint8_t meter[]=
|
|||||||
#define METERS_USED 2
|
#define METERS_USED 2
|
||||||
|
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'o',0,SML_BAUDRATE,"OBIS1"}, // harware serial RX pin
|
[0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, // harware serial RX pin
|
||||||
[1]={14,'o',0,SML_BAUDRATE,"OBIS2"}}; // GPIO14 software serial
|
[1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0}}; // GPIO14 software serial
|
||||||
|
|
||||||
// 2 Zähler definiert
|
// 2 Zähler definiert
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
@ -342,9 +347,9 @@ const uint8_t meter[]=
|
|||||||
#define METERS_USED 3
|
#define METERS_USED 3
|
||||||
|
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'o',0,SML_BAUDRATE,"OBIS1"}, // harware serial RX pin
|
[0]={3,'o',0,SML_BAUDRATE,"OBIS1",-1,1,0}, // harware serial RX pin
|
||||||
[1]={14,'o',0,SML_BAUDRATE,"OBIS2"},
|
[1]={14,'o',0,SML_BAUDRATE,"OBIS2",-1,1,0},
|
||||||
[2]={1,'o',0,SML_BAUDRATE,"OBIS3"}};
|
[2]={1,'o',0,SML_BAUDRATE,"OBIS3",-1,1,0}};
|
||||||
|
|
||||||
// 3 Zähler definiert
|
// 3 Zähler definiert
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
@ -372,7 +377,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'o',0,SML_BAUDRATE,"OBIS"}};
|
[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}};
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
"1,1-0:1.8.1*255(@1," D_TPWRIN ",KWh," DJ_TPWRIN ",4|"
|
||||||
"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|"
|
"1,=d 1 10 @1," D_TPWRCURR ",W," DJ_TPWRCURR ",0|"
|
||||||
@ -385,7 +390,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 1
|
#define METERS_USED 1
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'s',0,SML_BAUDRATE,"SML"}};
|
[0]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}};
|
||||||
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
// 2 Richtungszähler EHZ SML 8 bit 9600 baud, binär
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
//0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff
|
//0x77,0x07,0x01,0x00,0x01,0x08,0x00,0xff
|
||||||
@ -407,7 +412,7 @@ const uint8_t meter[]=
|
|||||||
#undef METERS_USED
|
#undef METERS_USED
|
||||||
#define METERS_USED 3
|
#define METERS_USED 3
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={3,'o',0,SML_BAUDRATE,"OBIS"}, // harware serial RX pin
|
[0]={3,'o',0,SML_BAUDRATE,"OBIS",-1,1,0}, // harware serial RX pin
|
||||||
[1]={14,'c',0,50,"Gas"}, // GPIO14 gas counter
|
[1]={14,'c',0,50,"Gas"}, // GPIO14 gas counter
|
||||||
[2]={1,'c',0,10,"Wasser"}}; // water counter
|
[2]={1,'c',0,10,"Wasser"}}; // water counter
|
||||||
|
|
||||||
@ -430,9 +435,9 @@ const uint8_t meter[]=
|
|||||||
#define METERS_USED 3
|
#define METERS_USED 3
|
||||||
|
|
||||||
struct METER_DESC const meter_desc[METERS_USED]={
|
struct METER_DESC const meter_desc[METERS_USED]={
|
||||||
[0]={1,'c',0,10,"H20"}, // GPIO1 Wasser Zähler
|
[0]={1,'c',0,10,"H20",-1,1,0}, // GPIO1 Wasser Zähler
|
||||||
[1]={4,'c',0,50,"GAS"}, // GPIO4 gas Zähler
|
[1]={4,'c',0,50,"GAS",-1,1,0}, // GPIO4 gas Zähler
|
||||||
[2]={3,'s',0,SML_BAUDRATE,"SML"}}; // SML harware serial RX pin
|
[2]={3,'s',0,SML_BAUDRATE,"SML",-1,1,0}}; // SML harware serial RX pin
|
||||||
|
|
||||||
const uint8_t meter[]=
|
const uint8_t meter[]=
|
||||||
//----------------------------Wasserzähler--sensor53 c1------------------------------------
|
//----------------------------Wasserzähler--sensor53 c1------------------------------------
|
||||||
@ -516,7 +521,7 @@ char meter_id[MAX_METERS][METER_ID_SIZE];
|
|||||||
#define EBUS_SYNC 0xaa
|
#define EBUS_SYNC 0xaa
|
||||||
#define EBUS_ESC 0xa9
|
#define EBUS_ESC 0xa9
|
||||||
uint8_t ebus_pos;
|
uint8_t ebus_pos;
|
||||||
|
uint8_t mbus_pos;
|
||||||
|
|
||||||
#ifdef USE_MEDIAN_FILTER
|
#ifdef USE_MEDIAN_FILTER
|
||||||
// median filter, should be odd size
|
// median filter, should be odd size
|
||||||
@ -786,32 +791,20 @@ uint8_t dump2log=0;
|
|||||||
|
|
||||||
bool Serial_available() {
|
bool Serial_available() {
|
||||||
uint8_t num=dump2log&7;
|
uint8_t num=dump2log&7;
|
||||||
if (num<1 || num>meters_used) return Serial.available();
|
if (num<1 || num>meters_used) num=1;
|
||||||
if (num==1) {
|
return meter_ss[num-1]->available();
|
||||||
return Serial.available();
|
|
||||||
} else {
|
|
||||||
return meter_ss[num-1]->available();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Serial_read() {
|
uint8_t Serial_read() {
|
||||||
uint8_t num=dump2log&7;
|
uint8_t num=dump2log&7;
|
||||||
if (num<1 || num>meters_used) return Serial.read();
|
if (num<1 || num>meters_used) num=1;
|
||||||
if (num==1) {
|
return meter_ss[num-1]->read();
|
||||||
return Serial.read();
|
|
||||||
} else {
|
|
||||||
return meter_ss[num-1]->read();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Serial_peek() {
|
uint8_t Serial_peek() {
|
||||||
uint8_t num=dump2log&7;
|
uint8_t num=dump2log&7;
|
||||||
if (num<1 || num>meters_used) return Serial.peek();
|
if (num<1 || num>meters_used) num=1;
|
||||||
if (num==1) {
|
return meter_ss[num-1]->peek();
|
||||||
return Serial.peek();
|
|
||||||
} else {
|
|
||||||
return meter_ss[num-1]->peek();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dump2log(void) {
|
void Dump2log(void) {
|
||||||
@ -1154,15 +1147,13 @@ uint8_t ebus_CalculateCRC( uint8_t *Data, uint16_t DataLen ) {
|
|||||||
|
|
||||||
void sml_shift_in(uint32_t meters,uint32_t shard) {
|
void sml_shift_in(uint32_t meters,uint32_t shard) {
|
||||||
uint32_t count;
|
uint32_t count;
|
||||||
if (meter_desc_p[meters].type!='e') {
|
if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m') {
|
||||||
// shift in
|
// shift in
|
||||||
for (count=0; count<SML_BSIZ-1; count++) {
|
for (count=0; count<SML_BSIZ-1; count++) {
|
||||||
smltbuf[meters][count]=smltbuf[meters][count+1];
|
smltbuf[meters][count]=smltbuf[meters][count+1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint8_t iob;
|
uint8_t iob=(uint8_t)meter_ss[meters]->read();
|
||||||
if (shard) iob=(uint8_t)Serial.read();
|
|
||||||
else iob=(uint8_t)meter_ss[meters]->read();
|
|
||||||
|
|
||||||
if (meter_desc_p[meters].type=='o') {
|
if (meter_desc_p[meters].type=='o') {
|
||||||
smltbuf[meters][SML_BSIZ-1]=iob&0x7f;
|
smltbuf[meters][SML_BSIZ-1]=iob&0x7f;
|
||||||
@ -1170,6 +1161,13 @@ void sml_shift_in(uint32_t meters,uint32_t shard) {
|
|||||||
smltbuf[meters][SML_BSIZ-1]=iob;
|
smltbuf[meters][SML_BSIZ-1]=iob;
|
||||||
} else if (meter_desc_p[meters].type=='r') {
|
} else if (meter_desc_p[meters].type=='r') {
|
||||||
smltbuf[meters][SML_BSIZ-1]=iob;
|
smltbuf[meters][SML_BSIZ-1]=iob;
|
||||||
|
} else if (meter_desc_p[meters].type=='m') {
|
||||||
|
smltbuf[meters][mbus_pos] = iob;
|
||||||
|
mbus_pos++;
|
||||||
|
if (mbus_pos>=9) {
|
||||||
|
SML_Decode(meters);
|
||||||
|
mbus_pos=0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (iob==EBUS_SYNC) {
|
if (iob==EBUS_SYNC) {
|
||||||
// should be end of telegramm
|
// should be end of telegramm
|
||||||
@ -1200,7 +1198,7 @@ void sml_shift_in(uint32_t meters,uint32_t shard) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb_counter++;
|
sb_counter++;
|
||||||
if (meter_desc_p[meters].type!='e') SML_Decode(meters);
|
if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m') SML_Decode(meters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1211,14 +1209,8 @@ uint32_t meters;
|
|||||||
for (meters=0; meters<meters_used; meters++) {
|
for (meters=0; meters<meters_used; meters++) {
|
||||||
if (meter_desc_p[meters].type!='c') {
|
if (meter_desc_p[meters].type!='c') {
|
||||||
// poll for serial input
|
// poll for serial input
|
||||||
if (meter_desc_p[meters].srcpin==3) {
|
while (meter_ss[meters]->available()) {
|
||||||
while (Serial.available()) {
|
sml_shift_in(meters,0);
|
||||||
sml_shift_in(meters,1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
while (meter_ss[meters]->available()) {
|
|
||||||
sml_shift_in(meters,0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1348,7 +1340,8 @@ void SML_Decode(uint8_t index) {
|
|||||||
} else {
|
} else {
|
||||||
// compare value
|
// compare value
|
||||||
uint8_t found=1;
|
uint8_t found=1;
|
||||||
int32_t ebus_dval=99;
|
uint32_t ebus_dval=99;
|
||||||
|
float mbus_dval=99;
|
||||||
while (*mp!='@') {
|
while (*mp!='@') {
|
||||||
if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') {
|
if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') {
|
||||||
if (*mp++!=*cp++) {
|
if (*mp++!=*cp++) {
|
||||||
@ -1363,7 +1356,7 @@ void SML_Decode(uint8_t index) {
|
|||||||
found=0;
|
found=0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ebus or raw
|
// ebus mbus or raw
|
||||||
// XXHHHHSSUU
|
// XXHHHHSSUU
|
||||||
if (*mp=='x' && *(mp+1)=='x') {
|
if (*mp=='x' && *(mp+1)=='x') {
|
||||||
//ignore
|
//ignore
|
||||||
@ -1379,7 +1372,7 @@ void SML_Decode(uint8_t index) {
|
|||||||
ebus_dval=val;
|
ebus_dval=val;
|
||||||
mp+=2;
|
mp+=2;
|
||||||
}
|
}
|
||||||
else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='s' && *(mp+3)=='s'){
|
else if (*mp=='s' && *(mp+1)=='s' && *(mp+2)=='s' && *(mp+3)=='s') {
|
||||||
int16_t val = *cp|(*(cp+1)<<8);
|
int16_t val = *cp|(*(cp+1)<<8);
|
||||||
ebus_dval=val;
|
ebus_dval=val;
|
||||||
mp+=4;
|
mp+=4;
|
||||||
@ -1389,7 +1382,15 @@ void SML_Decode(uint8_t index) {
|
|||||||
int8_t val = *cp++;
|
int8_t val = *cp++;
|
||||||
ebus_dval=val;
|
ebus_dval=val;
|
||||||
mp+=2;
|
mp+=2;
|
||||||
} else {
|
}
|
||||||
|
else if (*mp=='f' && *(mp+1)=='f' && *(mp+2)=='f' && *(mp+3)=='f' && *(mp+4)=='f' && *(mp+5)=='f' && *(mp+6)=='f' && *(mp+7)=='f') {
|
||||||
|
uint32_t val= (*(cp+0)<<24)|(*(cp+1)<<16)|(*(cp+2)<<8)|(*(cp+3)<<0);
|
||||||
|
float *fp=(float*)&val;
|
||||||
|
mbus_dval=*fp;
|
||||||
|
mp+=8;
|
||||||
|
cp+=4;
|
||||||
|
}
|
||||||
|
else {
|
||||||
uint8_t val = hexnibble(*mp++) << 4;
|
uint8_t val = hexnibble(*mp++) << 4;
|
||||||
val |= hexnibble(*mp++);
|
val |= hexnibble(*mp++);
|
||||||
if (val!=*cp++) {
|
if (val!=*cp++) {
|
||||||
@ -1418,7 +1419,7 @@ void SML_Decode(uint8_t index) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
double dval;
|
double dval;
|
||||||
if (meter_desc_p[mindex].type!='e' && meter_desc_p[mindex].type!='r') {
|
if (meter_desc_p[mindex].type!='e' && meter_desc_p[mindex].type!='r' && meter_desc_p[mindex].type!='m') {
|
||||||
// get numeric values
|
// get numeric values
|
||||||
if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') {
|
if (meter_desc_p[mindex].type=='o' || meter_desc_p[mindex].type=='c') {
|
||||||
dval=xCharToDouble((char*)cp);
|
dval=xCharToDouble((char*)cp);
|
||||||
@ -1426,7 +1427,7 @@ void SML_Decode(uint8_t index) {
|
|||||||
dval=sml_getvalue(cp,mindex);
|
dval=sml_getvalue(cp,mindex);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ebus
|
// ebus or mbus
|
||||||
if (*mp=='b') {
|
if (*mp=='b') {
|
||||||
mp++;
|
mp++;
|
||||||
uint8_t shift=*mp&7;
|
uint8_t shift=*mp&7;
|
||||||
@ -1434,7 +1435,23 @@ void SML_Decode(uint8_t index) {
|
|||||||
ebus_dval&=1;
|
ebus_dval&=1;
|
||||||
mp+=2;
|
mp+=2;
|
||||||
}
|
}
|
||||||
dval=ebus_dval;
|
if (*mp=='i') {
|
||||||
|
// mbus index
|
||||||
|
mp++;
|
||||||
|
uint8_t mb_index=strtol((char*)mp,(char**)&mp,10);
|
||||||
|
if (mb_index!=meter_desc_p[mindex].index) {
|
||||||
|
goto nextsect;
|
||||||
|
}
|
||||||
|
uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7);
|
||||||
|
if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect;
|
||||||
|
if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect;
|
||||||
|
dval=mbus_dval;
|
||||||
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
|
||||||
|
mp++;
|
||||||
|
} else {
|
||||||
|
dval=ebus_dval;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef USE_MEDIAN_FILTER
|
#ifdef USE_MEDIAN_FILTER
|
||||||
meter_vars[vindex]=median(&sml_mf[vindex],dval);
|
meter_vars[vindex]=median(&sml_mf[vindex],dval);
|
||||||
@ -1488,8 +1505,7 @@ void SML_Immediate_MQTT(const char *mp,uint8_t index,uint8_t mindex) {
|
|||||||
if (dp&0x10) {
|
if (dp&0x10) {
|
||||||
// immediate mqtt
|
// immediate mqtt
|
||||||
dtostrfd(meter_vars[index],dp&0xf,tpowstr);
|
dtostrfd(meter_vars[index],dp&0xf,tpowstr);
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"%s\":{\"%s\":%s}}"),meter_desc_p[mindex].prefix,jname,tpowstr);
|
||||||
ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%s}}"),meter_desc_p[mindex].prefix,jname,tpowstr);
|
|
||||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1723,6 +1739,14 @@ void SML_Init(void) {
|
|||||||
|
|
||||||
|
|
||||||
#ifdef USE_SCRIPT
|
#ifdef USE_SCRIPT
|
||||||
|
|
||||||
|
for (uint32_t cnt=0;cnt<MAX_METERS;cnt++) {
|
||||||
|
if (script_meter_desc[cnt].txmem) {
|
||||||
|
free(script_meter_desc[cnt].txmem);
|
||||||
|
script_meter_desc[cnt].txmem=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t meter_script=Run_Scripter(">M",-2,0);
|
uint8_t meter_script=Run_Scripter(">M",-2,0);
|
||||||
if (meter_script==99) {
|
if (meter_script==99) {
|
||||||
// use script definition
|
// use script definition
|
||||||
@ -1782,13 +1806,42 @@ void SML_Init(void) {
|
|||||||
lp++;
|
lp++;
|
||||||
script_meter_desc[index].prefix[7]=0;
|
script_meter_desc[index].prefix[7]=0;
|
||||||
for (uint32_t cnt=0; cnt<8; cnt++) {
|
for (uint32_t cnt=0; cnt<8; cnt++) {
|
||||||
if (*lp==SCRIPT_EOL) {
|
if (*lp==SCRIPT_EOL || *lp==',') {
|
||||||
script_meter_desc[index].prefix[cnt]=0;
|
script_meter_desc[index].prefix[cnt]=0;
|
||||||
lp--;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
script_meter_desc[index].prefix[cnt]=*lp++;
|
script_meter_desc[index].prefix[cnt]=*lp++;
|
||||||
}
|
}
|
||||||
|
if (*lp==',') {
|
||||||
|
lp++;
|
||||||
|
script_meter_desc[index].trxpin=strtol(lp,&lp,10);
|
||||||
|
if (*lp!=',') goto next_line;
|
||||||
|
lp++;
|
||||||
|
script_meter_desc[index].tsecs=strtol(lp,&lp,10);
|
||||||
|
if (*lp==',') {
|
||||||
|
lp++;
|
||||||
|
char txbuff[256];
|
||||||
|
uint32_t txlen=0,tx_entries=1;
|
||||||
|
for (uint32_t cnt=0; cnt<sizeof(txbuff); cnt++) {
|
||||||
|
if (*lp==SCRIPT_EOL) {
|
||||||
|
txbuff[cnt]=0;
|
||||||
|
txlen=cnt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*lp==',') tx_entries++;
|
||||||
|
txbuff[cnt]=*lp++;
|
||||||
|
}
|
||||||
|
if (txlen) {
|
||||||
|
script_meter_desc[index].txmem=(char*)calloc(txlen+2,1);
|
||||||
|
if (script_meter_desc[index].txmem) {
|
||||||
|
strcpy(script_meter_desc[index].txmem,txbuff);
|
||||||
|
}
|
||||||
|
script_meter_desc[index].index=0;
|
||||||
|
script_meter_desc[index].max_index=tx_entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*lp==SCRIPT_EOL) lp--;
|
||||||
goto next_line;
|
goto next_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1862,19 +1915,20 @@ next_line:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// serial input, init
|
// serial input, init
|
||||||
if (meter_desc_p[meters].srcpin==3) {
|
|
||||||
ClaimSerial();
|
|
||||||
SetSerialBaudrate(meter_desc_p[meters].params);
|
|
||||||
} else {
|
|
||||||
#ifdef SPECIAL_SS
|
#ifdef SPECIAL_SS
|
||||||
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,-1,0,1);
|
if (meter_desc_p[meters].type=='m') {
|
||||||
|
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1);
|
||||||
|
} else {
|
||||||
|
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,1);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,-1);
|
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1);
|
||||||
#endif
|
#endif
|
||||||
if (meter_ss[meters]->begin(meter_desc_p[meters].params)) {
|
if (meter_ss[meters]->begin(meter_desc_p[meters].params)) {
|
||||||
meter_ss[meters]->flush();
|
meter_ss[meters]->flush();
|
||||||
}
|
}
|
||||||
}
|
if (meter_ss[meters]->hardwareSerial()) { ClaimSerial(); }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1958,25 +2012,102 @@ uint32_t ctime=millis();
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SML_SEND_SEQ
|
#ifdef USE_SCRIPT
|
||||||
#define SML_SEQ_PERIOD 5
|
char *SML_Get_Sequence(char *cp,uint32_t index) {
|
||||||
uint8_t sml_seq_cnt;
|
if (!index) return cp;
|
||||||
void SendSeq(void) {
|
uint32_t cindex=0;
|
||||||
sml_seq_cnt++;
|
while (cp) {
|
||||||
if (sml_seq_cnt>SML_SEQ_PERIOD) {
|
cp=strchr(cp,',');
|
||||||
sml_seq_cnt=0;
|
if (cp) {
|
||||||
// send sequence every N Seconds
|
cp++;
|
||||||
uint8_t sequence[]={0x2F,0x3F,0x21,0x0D,0x0A,0};
|
cindex++;
|
||||||
uint8_t *ucp=sequence;
|
if (cindex==index) {
|
||||||
while (*ucp) {
|
return cp;
|
||||||
uint8_t iob=*ucp++;
|
}
|
||||||
// for no parity disable next line
|
|
||||||
iob|=(CalcEvenParity(iob)<<7);
|
|
||||||
Serial.write(iob);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t sml_250ms_cnt;
|
||||||
|
|
||||||
|
|
||||||
|
void SML_Check_Send(void) {
|
||||||
|
sml_250ms_cnt++;
|
||||||
|
for (uint32_t cnt=0; cnt<meters_used; cnt++) {
|
||||||
|
if (script_meter_desc[cnt].trxpin>=0 && script_meter_desc[cnt].txmem) {
|
||||||
|
if ((sml_250ms_cnt%script_meter_desc[cnt].tsecs)==0) {
|
||||||
|
if (script_meter_desc[cnt].max_index>1) {
|
||||||
|
script_meter_desc[cnt].index++;
|
||||||
|
if (script_meter_desc[cnt].index>=script_meter_desc[cnt].max_index) {
|
||||||
|
script_meter_desc[cnt].index=0;
|
||||||
|
}
|
||||||
|
char *cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index);
|
||||||
|
SML_Send_Seq(cnt,cp);
|
||||||
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),cp);
|
||||||
|
} else {
|
||||||
|
SML_Send_Seq(cnt,script_meter_desc[cnt].txmem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t sml_hexnibble(char chr) {
|
||||||
|
uint8_t rVal = 0;
|
||||||
|
if (isdigit(chr)) {
|
||||||
|
rVal = chr - '0';
|
||||||
|
} else {
|
||||||
|
if (chr >= 'A' && chr <= 'F') rVal = chr + 10 - 'A';
|
||||||
|
if (chr >= 'a' && chr <= 'f') rVal = chr + 10 - 'a';
|
||||||
|
}
|
||||||
|
return rVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send sequence every N Seconds
|
||||||
|
void SML_Send_Seq(uint32_t meter,char *seq) {
|
||||||
|
uint8_t sbuff[32];
|
||||||
|
uint8_t *ucp=sbuff,slen;
|
||||||
|
char *cp=seq;
|
||||||
|
while (*cp) {
|
||||||
|
if (!*cp || !*(cp+1)) break;
|
||||||
|
if (*cp==',') break;
|
||||||
|
uint8_t iob=(sml_hexnibble(*cp) << 4) | sml_hexnibble(*(cp+1));
|
||||||
|
cp+=2;
|
||||||
|
*ucp++=iob;
|
||||||
|
slen++;
|
||||||
|
if (slen>=sizeof(sbuff)) break;
|
||||||
|
}
|
||||||
|
if (script_meter_desc[meter].type=='m') {
|
||||||
|
*ucp++=0;
|
||||||
|
*ucp++=2;
|
||||||
|
// append crc
|
||||||
|
uint16_t crc = MBUS_calculateCRC(sbuff,6);
|
||||||
|
*ucp++=lowByte(crc);
|
||||||
|
*ucp++=highByte(crc);
|
||||||
|
slen+=4;
|
||||||
|
}
|
||||||
|
meter_ss[meter]->write(sbuff,slen);
|
||||||
|
}
|
||||||
|
#endif // USE_SCRIPT
|
||||||
|
|
||||||
|
uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num) {
|
||||||
|
uint16_t crc, flag;
|
||||||
|
crc = 0xFFFF;
|
||||||
|
for (uint32_t i = 0; i < num; i++) {
|
||||||
|
crc ^= frame[i];
|
||||||
|
for (uint32_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// for odd parity init with 1
|
// for odd parity init with 1
|
||||||
uint8_t CalcEvenParity(uint8_t data) {
|
uint8_t CalcEvenParity(uint8_t data) {
|
||||||
uint8_t parity=0;
|
uint8_t parity=0;
|
||||||
@ -1987,7 +2118,7 @@ uint8_t parity=0;
|
|||||||
}
|
}
|
||||||
return parity;
|
return parity;
|
||||||
}
|
}
|
||||||
#endif
|
*/
|
||||||
|
|
||||||
|
|
||||||
// dump to log shows serial data on console
|
// dump to log shows serial data on console
|
||||||
@ -2004,8 +2135,7 @@ bool XSNS_53_cmd(void) {
|
|||||||
// set dump mode
|
// set dump mode
|
||||||
cp++;
|
cp++;
|
||||||
dump2log=atoi(cp);
|
dump2log=atoi(cp);
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log);
|
||||||
ResponseAppend_P(PSTR(",\"SML\":{\"CMD\":\"dump: %d\"}}"),dump2log);
|
|
||||||
} else if (*cp=='c') {
|
} else if (*cp=='c') {
|
||||||
// set ounter
|
// set ounter
|
||||||
cp++;
|
cp++;
|
||||||
@ -2025,12 +2155,10 @@ bool XSNS_53_cmd(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"counter%d: %d\"}}"),index,RtcSettings.pulse_counter[index-1]);
|
||||||
ResponseAppend_P(PSTR(",\"SML\":{\"CMD\":\"counter%d: %d\"}}"),index,RtcSettings.pulse_counter[index-1]);
|
|
||||||
} else if (*cp=='r') {
|
} else if (*cp=='r') {
|
||||||
// restart
|
// restart
|
||||||
ResponseBeginTime();
|
ResponseTime_P(PSTR(",\"SML\":{\"CMD\":\"restart\"}}"));
|
||||||
ResponseAppend_P(PSTR(",\"SML\":{\"CMD\":\"restart\"}}"));
|
|
||||||
SML_CounterSaveState();
|
SML_CounterSaveState();
|
||||||
SML_Init();
|
SML_Init();
|
||||||
} else {
|
} else {
|
||||||
@ -2053,6 +2181,7 @@ void SML_CounterSaveState(void) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
@ -2070,11 +2199,11 @@ bool Xsns53(byte function) {
|
|||||||
if (dump2log) Dump2log();
|
if (dump2log) Dump2log();
|
||||||
else SML_Poll();
|
else SML_Poll();
|
||||||
break;
|
break;
|
||||||
#ifdef SML_SEND_SEQ
|
#ifdef USE_SCRIPT
|
||||||
case FUNC_EVERY_SECOND:
|
case FUNC_EVERY_250_MSECOND:
|
||||||
SendSeq();
|
SML_Check_Send();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif // USE_SCRIPT
|
||||||
case FUNC_JSON_APPEND:
|
case FUNC_JSON_APPEND:
|
||||||
SML_Show(1);
|
SML_Show(1);
|
||||||
break;
|
break;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
VER = '2.3.0032'
|
VER = '2.3.0033'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
decode-config.py - Backup/Restore Sonoff-Tasmota configuration data
|
decode-config.py - Backup/Restore Sonoff-Tasmota configuration data
|
||||||
@ -984,7 +984,22 @@ Setting_6_6_0_9.update ({
|
|||||||
'sbaudrate': ('<H', 0x77A, (None, None, ('Serial', '"SBaudrate {}".format($)')), ('$ * 1200','$ / 1200') ),
|
'sbaudrate': ('<H', 0x77A, (None, None, ('Serial', '"SBaudrate {}".format($)')), ('$ * 1200','$ / 1200') ),
|
||||||
})
|
})
|
||||||
# ======================================================================
|
# ======================================================================
|
||||||
|
Setting_6_6_0_10 = copy.deepcopy(Setting_6_6_0_9)
|
||||||
|
Setting_6_6_0_10.update ({
|
||||||
|
'cfg_timestamp': ('<L', 0xFF8, (None, None, (INTERNAL, None)) ),
|
||||||
|
'cfg_crc32': ('<L', 0xFFC, (None, None, (INTERNAL, None)), '"0x{:08x}".format($)' ),
|
||||||
|
'tuya_fnid_map': ({
|
||||||
|
'fnid': ('B', 0xE00, (None, None, ('Management', '"TuyaMCU {},{}".format($,@["tuya_fnid_map"][#-1]["dpid"]) if ($!=0 or @["tuya_fnid_map"][#-1]["dpid"]!=0) else None')) ),
|
||||||
|
'dpid': ('B', 0xE01, (None, None, ('Management', None)) ),
|
||||||
|
}, 0xE00, ([16], None, ('Management', None)), (None, None) ),
|
||||||
|
})
|
||||||
|
Setting_6_6_0_10['flag2'][0].update ({
|
||||||
|
'time_format': ('<L', (0x5BC,2, 4), (None, None, ('Management', '"Time {}".format($+1)')) ),
|
||||||
|
})
|
||||||
|
Setting_6_6_0_10['flag3'][0].pop('tuya_show_dimmer',None)
|
||||||
|
# ======================================================================
|
||||||
Settings = [
|
Settings = [
|
||||||
|
(0x606000A,0x1000, Setting_6_6_0_10),
|
||||||
(0x6060009,0x1000, Setting_6_6_0_9),
|
(0x6060009,0x1000, Setting_6_6_0_9),
|
||||||
(0x6060008,0x1000, Setting_6_6_0_8),
|
(0x6060008,0x1000, Setting_6_6_0_8),
|
||||||
(0x6060007,0x1000, Setting_6_6_0_7),
|
(0x6060007,0x1000, Setting_6_6_0_7),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user