mirror of https://github.com/arendst/Tasmota.git
Merge remote-tracking branch 'Tasmota/development' into development
This commit is contained in:
commit
ef6aad7c81
|
@ -75,6 +75,7 @@
|
||||||
| USE_DHT | - | - | x | x | x | x | x |
|
| USE_DHT | - | - | x | x | x | x | x |
|
||||||
| USE_MAX31855 | - | - | - | - | x | - | - |
|
| USE_MAX31855 | - | - | - | - | x | - | - |
|
||||||
| USE_MAX31865 | - | - | - | - | - | - | - |
|
| USE_MAX31865 | - | - | - | - | - | - | - |
|
||||||
|
| USE_THERMOSTAT | - | - | - | - | - | - | - |
|
||||||
| | | | | | | | |
|
| | | | | | | | |
|
||||||
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
|
| Feature or Sensor | minimal | lite | tasmota | knx | sensors | ir | display | Remarks
|
||||||
| USE_I2C | - | - | x | x | x | - | x |
|
| USE_I2C | - | - | x | x | x | - | x |
|
||||||
|
|
|
@ -54,4 +54,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
|
||||||
|
|
||||||
### Version 8.3.0.1
|
### Version 8.3.0.1
|
||||||
|
|
||||||
|
- Change KNX pow function to approximative pow saving 5k of code space
|
||||||
|
- Change Mutichannel Gas sensor pow function to approximative pow saving 5k of code space
|
||||||
|
- Change Quick Power Cycle detection from 4 to 7 power interrupts (#4066)
|
||||||
- Fix default state of ``SetOption73 0`` for button decoupling and send multi-press and hold MQTT messages
|
- Fix default state of ``SetOption73 0`` for button decoupling and send multi-press and hold MQTT messages
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
### 8.3.0.1 20200514
|
### 8.3.0.1 20200514
|
||||||
|
|
||||||
|
- Change KNX pow function to approximative pow saving 5k of code space
|
||||||
|
- Change Mutichannel Gas sensor pow function to approximative pow saving 5k of code space
|
||||||
|
- Change Quick Power Cycle detection from 4 to 7 power interrupts (#4066)
|
||||||
- Fix default state of ``SetOption73 0`` for button decoupling and send multi-press and hold MQTT messages
|
- Fix default state of ``SetOption73 0`` for button decoupling and send multi-press and hold MQTT messages
|
||||||
|
|
||||||
## Released
|
## Released
|
||||||
|
|
|
@ -357,9 +357,9 @@ void UpdateQuickPowerCycle(bool update)
|
||||||
#else // ESP32
|
#else // ESP32
|
||||||
QPCRead(&pc_register, sizeof(pc_register));
|
QPCRead(&pc_register, sizeof(pc_register));
|
||||||
#endif // ESP8266 - ESP32
|
#endif // ESP8266 - ESP32
|
||||||
if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) {
|
if (update && ((pc_register & 0xFFFFFF80) == 0xFFA55A80)) {
|
||||||
uint32_t counter = ((pc_register & 0xF) << 1) & 0xF;
|
uint32_t counter = ((pc_register & 0x7F) << 1) & 0x7F;
|
||||||
if (0 == counter) { // 4 power cycles in a row
|
if (0 == counter) { // 7 power cycles in a row
|
||||||
SettingsErase(3); // Quickly reset all settings including QuickPowerCycle flag
|
SettingsErase(3); // Quickly reset all settings including QuickPowerCycle flag
|
||||||
EspRestart(); // And restart
|
EspRestart(); // And restart
|
||||||
} else {
|
} else {
|
||||||
|
@ -372,8 +372,8 @@ void UpdateQuickPowerCycle(bool update)
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter);
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (pc_register != 0xFFA55ABF) {
|
else if (pc_register != 0xFFA55AFF) {
|
||||||
pc_register = 0xFFA55ABF;
|
pc_register = 0xFFA55AFF;
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
// Assume flash is default all ones and setting a bit to zero does not need an erase
|
// Assume flash is default all ones and setting a bit to zero does not need an erase
|
||||||
if (ESP.flashEraseSector(pc_location)) {
|
if (ESP.flashEraseSector(pc_location)) {
|
||||||
|
|
|
@ -1600,8 +1600,9 @@ void CmndTeleperiod(void)
|
||||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||||
Settings.tele_period = (1 == XdrvMailbox.payload) ? TELE_PERIOD : XdrvMailbox.payload;
|
Settings.tele_period = (1 == XdrvMailbox.payload) ? TELE_PERIOD : XdrvMailbox.payload;
|
||||||
if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; // Do not allow periods < 10 seconds
|
if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; // Do not allow periods < 10 seconds
|
||||||
tele_period = Settings.tele_period;
|
// tele_period = Settings.tele_period;
|
||||||
}
|
}
|
||||||
|
tele_period = Settings.tele_period; // Show teleperiod data also on empty command
|
||||||
ResponseCmndNumber(Settings.tele_period);
|
ResponseCmndNumber(Settings.tele_period);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -836,28 +836,44 @@ void LightStateClass::HsToRgb(uint16_t hue, uint8_t sat, uint8_t *r_r, uint8_t *
|
||||||
|
|
||||||
#define POW FastPrecisePowf
|
#define POW FastPrecisePowf
|
||||||
|
|
||||||
|
//
|
||||||
|
// Matrix 3x3 multiplied to a 3 vector, result in a 3 vector
|
||||||
|
//
|
||||||
|
void mat3x3(const float *mat33, const float *vec3, float *res3) {
|
||||||
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
|
const float * v = vec3;
|
||||||
|
*res3 = 0.0f;
|
||||||
|
for (uint32_t j = 0; j < 3; j++) {
|
||||||
|
*res3 += *mat33++ * *v++;
|
||||||
|
}
|
||||||
|
res3++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) {
|
void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x, float *r_y) {
|
||||||
float x = 0.31271f; // default medium white
|
float x = 0.31271f; // default medium white
|
||||||
float y = 0.32902f;
|
float y = 0.32902f;
|
||||||
|
|
||||||
if (i_r + i_b + i_g > 0) {
|
if (i_r + i_b + i_g > 0) {
|
||||||
float r = (float)i_r / 255.0f;
|
float rgb[3] = { (float)i_r, (float)i_g, (float)i_b };
|
||||||
float g = (float)i_g / 255.0f;
|
|
||||||
float b = (float)i_b / 255.0f;
|
|
||||||
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
|
// https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
|
||||||
// Gamma correction
|
// Gamma correction
|
||||||
r = (r > 0.04045f) ? POW((r + 0.055f) / (1.0f + 0.055f), 2.4f) : (r / 12.92f);
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
g = (g > 0.04045f) ? POW((g + 0.055f) / (1.0f + 0.055f), 2.4f) : (g / 12.92f);
|
rgb[i] = rgb[i] / 255.0f;
|
||||||
b = (b > 0.04045f) ? POW((b + 0.055f) / (1.0f + 0.055f), 2.4f) : (b / 12.92f);
|
rgb[i] = (rgb[i] > 0.04045f) ? POW((rgb[i] + 0.055f) / (1.0f + 0.055f), 2.4f) : (rgb[i] / 12.92f);
|
||||||
|
}
|
||||||
|
|
||||||
// conversion to X, Y, Z
|
// conversion to X, Y, Z
|
||||||
// Y is also the Luminance
|
// Y is also the Luminance
|
||||||
float X = r * 0.649926f + g * 0.103455f + b * 0.197109f;
|
float XYZ[3];
|
||||||
float Y = r * 0.234327f + g * 0.743075f + b * 0.022598f;
|
static const float XYZ_factors[] = { 0.649926f, 0.103455f, 0.197109f,
|
||||||
float Z = r * 0.000000f + g * 0.053077f + b * 1.035763f;
|
0.234327f, 0.743075f, 0.022598f,
|
||||||
|
0.000000f, 0.053077f, 1.035763f };
|
||||||
|
mat3x3(XYZ_factors, rgb, XYZ);
|
||||||
|
|
||||||
x = X / (X + Y + Z);
|
float XYZ_sum = XYZ[0] + XYZ[1] + XYZ[2];
|
||||||
y = Y / (X + Y + Z);
|
x = XYZ[0] / XYZ_sum;
|
||||||
|
y = XYZ[1] / XYZ_sum;
|
||||||
// we keep the raw gamut, one nice thing could be to convert to a narrower gamut
|
// we keep the raw gamut, one nice thing could be to convert to a narrower gamut
|
||||||
}
|
}
|
||||||
if (r_x) *r_x = x;
|
if (r_x) *r_x = x;
|
||||||
|
@ -866,36 +882,33 @@ void LightStateClass::RgbToXy(uint8_t i_r, uint8_t i_g, uint8_t i_b, float *r_x,
|
||||||
|
|
||||||
void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb)
|
void LightStateClass::XyToRgb(float x, float y, uint8_t *rr, uint8_t *rg, uint8_t *rb)
|
||||||
{
|
{
|
||||||
|
float XYZ[3], rgb[3];
|
||||||
x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x));
|
x = (x > 0.99f ? 0.99f : (x < 0.01f ? 0.01f : x));
|
||||||
y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y));
|
y = (y > 0.99f ? 0.99f : (y < 0.01f ? 0.01f : y));
|
||||||
float z = 1.0f - x - y;
|
float z = 1.0f - x - y;
|
||||||
//float Y = 1.0f;
|
XYZ[0] = x / y;
|
||||||
float X = x / y;
|
XYZ[1] = 1.0f;
|
||||||
float Z = z / y;
|
XYZ[2] = z / y;
|
||||||
// float r = X * 1.4628067f - 0.1840623f - Z * 0.2743606f;
|
|
||||||
// float g = -X * 0.5217933f + 1.4472381f + Z * 0.0677227f;
|
|
||||||
// float b = X * 0.0349342f - 0.0968930f + Z * 1.2884099f;
|
|
||||||
float r = X * 3.2406f - 1.5372f - Z * 0.4986f;
|
|
||||||
float g = -X * 0.9689f + 1.8758f + Z * 0.0415f;
|
|
||||||
float b = X * 0.0557f - 0.2040f + Z * 1.0570f;
|
|
||||||
float max = (r > g && r > b) ? r : (g > b) ? g : b;
|
|
||||||
r = r / max; // normalize to max == 1.0
|
|
||||||
g = g / max;
|
|
||||||
b = b / max;
|
|
||||||
r = (r <= 0.0031308f) ? 12.92f * r : 1.055f * POW(r, (1.0f / 2.4f)) - 0.055f;
|
|
||||||
g = (g <= 0.0031308f) ? 12.92f * g : 1.055f * POW(g, (1.0f / 2.4f)) - 0.055f;
|
|
||||||
b = (b <= 0.0031308f) ? 12.92f * b : 1.055f * POW(b, (1.0f / 2.4f)) - 0.055f;
|
|
||||||
//
|
|
||||||
// AddLog_P2(LOG_LEVEL_DEBUG_MORE, "XyToRgb XZ (%s %s) rgb (%s %s %s)",
|
|
||||||
// String(X,5).c_str(), String(Z,5).c_str(),
|
|
||||||
// String(r,5).c_str(), String(g,5).c_str(),String(b,5).c_str());
|
|
||||||
|
|
||||||
int32_t ir = r * 255.0f + 0.5f;
|
static const float rgb_factors[] = { 3.2406f, -1.5372f, -0.4986f,
|
||||||
int32_t ig = g * 255.0f + 0.5f;
|
-0.9689f, 1.8758f, 0.0415f,
|
||||||
int32_t ib = b * 255.0f + 0.5f;
|
0.0557f, -0.2040f, 1.0570f };
|
||||||
if (rr) { *rr = (ir > 255 ? 255: (ir < 0 ? 0 : ir)); }
|
mat3x3(rgb_factors, XYZ, rgb);
|
||||||
if (rg) { *rg = (ig > 255 ? 255: (ig < 0 ? 0 : ig)); }
|
float max = (rgb[0] > rgb[1] && rgb[0] > rgb[2]) ? rgb[0] : (rgb[1] > rgb[2]) ? rgb[1] : rgb[2];
|
||||||
if (rb) { *rb = (ib > 255 ? 255: (ib < 0 ? 0 : ib)); }
|
|
||||||
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
|
rgb[i] = rgb[i] / max; // normalize to max == 1.0
|
||||||
|
rgb[i] = (rgb[i] <= 0.0031308f) ? 12.92f * rgb[i] : 1.055f * POW(rgb[i], (1.0f / 2.4f)) - 0.055f; // gamma
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t irgb[3];
|
||||||
|
for (uint32_t i = 0; i < 3; i++) {
|
||||||
|
irgb[i] = rgb[i] * 255.0f + 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rr) { *rr = (irgb[0] > 255 ? 255: (irgb[0] < 0 ? 0 : irgb[0])); }
|
||||||
|
if (rg) { *rg = (irgb[1] > 255 ? 255: (irgb[1] < 0 ? 0 : irgb[1])); }
|
||||||
|
if (rb) { *rb = (irgb[2] > 255 ? 255: (irgb[2] < 0 ? 0 : irgb[2])); }
|
||||||
}
|
}
|
||||||
|
|
||||||
class LightControllerClass {
|
class LightControllerClass {
|
||||||
|
|
|
@ -641,13 +641,14 @@ char *script;
|
||||||
|
|
||||||
#ifdef USE_LIGHT
|
#ifdef USE_LIGHT
|
||||||
#ifdef USE_WS2812
|
#ifdef USE_WS2812
|
||||||
void ws2812_set_array(float *array ,uint8_t len) {
|
void ws2812_set_array(float *array ,uint32_t len, uint32_t offset) {
|
||||||
|
|
||||||
Ws2812ForceSuspend();
|
Ws2812ForceSuspend();
|
||||||
for (uint8_t cnt=0;cnt<len;cnt++) {
|
for (uint32_t cnt=0;cnt<len;cnt++) {
|
||||||
if (cnt>Settings.light_pixels) break;
|
uint32_t index=cnt+offset;
|
||||||
|
if (index>Settings.light_pixels) break;
|
||||||
uint32_t col=array[cnt];
|
uint32_t col=array[cnt];
|
||||||
Ws2812SetColor(cnt+1,col>>16,col>>8,col,0);
|
Ws2812SetColor(index+1,col>>16,col>>8,col,0);
|
||||||
}
|
}
|
||||||
Ws2812ForceUpdate();
|
Ws2812ForceUpdate();
|
||||||
}
|
}
|
||||||
|
@ -2444,7 +2445,7 @@ char *ForceStringVar(char *lp,char *dstr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace vars in cmd %var%
|
// replace vars in cmd %var%
|
||||||
void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) {
|
void Replace_Cmd_Vars(char *srcbuf,uint32_t srcsize, char *dstbuf,uint32_t dstsize) {
|
||||||
char *cp;
|
char *cp;
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
uint8_t vtype;
|
uint8_t vtype;
|
||||||
|
@ -2455,6 +2456,7 @@ void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) {
|
||||||
char string[SCRIPT_MAXSSIZE];
|
char string[SCRIPT_MAXSSIZE];
|
||||||
dstsize-=2;
|
dstsize-=2;
|
||||||
for (count=0;count<dstsize;count++) {
|
for (count=0;count<dstsize;count++) {
|
||||||
|
if (srcsize && (*cp==SCRIPT_EOL)) break;
|
||||||
if (*cp=='%') {
|
if (*cp=='%') {
|
||||||
cp++;
|
cp++;
|
||||||
if (*cp=='%') {
|
if (*cp=='%') {
|
||||||
|
@ -2869,7 +2871,11 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||||
lp=GetNumericResult(lp,OPER_EQU,&cv_inc,0);
|
lp=GetNumericResult(lp,OPER_EQU,&cv_inc,0);
|
||||||
//SCRIPT_SKIP_EOL
|
//SCRIPT_SKIP_EOL
|
||||||
cv_ptr=lp;
|
cv_ptr=lp;
|
||||||
floop=1;
|
if (*cv_count<cv_max) {
|
||||||
|
floop=1;
|
||||||
|
} else {
|
||||||
|
floop=2;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// error
|
// error
|
||||||
toLogEOL("for error",lp);
|
toLogEOL("for error",lp);
|
||||||
|
@ -2877,11 +2883,20 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||||
} else if (!strncmp(lp,"next",4) && floop>0) {
|
} else if (!strncmp(lp,"next",4) && floop>0) {
|
||||||
// for next loop
|
// for next loop
|
||||||
*cv_count+=cv_inc;
|
*cv_count+=cv_inc;
|
||||||
if (*cv_count<=cv_max) {
|
if (floop==1) {
|
||||||
lp=cv_ptr;
|
if (*cv_count<=cv_max) {
|
||||||
|
lp=cv_ptr;
|
||||||
|
} else {
|
||||||
|
lp+=4;
|
||||||
|
floop=0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
lp+=4;
|
if (*cv_count>=cv_max) {
|
||||||
floop=0;
|
lp=cv_ptr;
|
||||||
|
} else {
|
||||||
|
lp+=4;
|
||||||
|
floop=0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3010,6 +3025,12 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||||
lp+=7;
|
lp+=7;
|
||||||
lp=isvar(lp,&vtype,&ind,0,0,0);
|
lp=isvar(lp,&vtype,&ind,0,0,0);
|
||||||
if (vtype!=VAR_NV) {
|
if (vtype!=VAR_NV) {
|
||||||
|
SCRIPT_SKIP_SPACES
|
||||||
|
if (*lp!=')') {
|
||||||
|
lp=GetNumericResult(lp,OPER_EQU,&fvar,0);
|
||||||
|
} else {
|
||||||
|
fvar=0;
|
||||||
|
}
|
||||||
// found variable as result
|
// found variable as result
|
||||||
uint8_t index=glob_script_mem.type[ind.index].index;
|
uint8_t index=glob_script_mem.type[ind.index].index;
|
||||||
if ((vtype&STYPE)==0) {
|
if ((vtype&STYPE)==0) {
|
||||||
|
@ -3018,7 +3039,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||||
uint8_t len=0;
|
uint8_t len=0;
|
||||||
float *fa=Get_MFAddr(index,&len);
|
float *fa=Get_MFAddr(index,&len);
|
||||||
//Serial.printf(">> 2 %d\n",(uint32_t)*fa);
|
//Serial.printf(">> 2 %d\n",(uint32_t)*fa);
|
||||||
if (fa && len) ws2812_set_array(fa,len);
|
if (fa && len) ws2812_set_array(fa,len,fvar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3069,7 +3090,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
|
||||||
//AddLog_P(LOG_LEVEL_INFO, tmp);
|
//AddLog_P(LOG_LEVEL_INFO, tmp);
|
||||||
// replace vars in cmd
|
// replace vars in cmd
|
||||||
char *tmp=cmdmem+SCRIPT_CMDMEM/2;
|
char *tmp=cmdmem+SCRIPT_CMDMEM/2;
|
||||||
Replace_Cmd_Vars(cmd,tmp,SCRIPT_CMDMEM/2);
|
Replace_Cmd_Vars(cmd,0,tmp,SCRIPT_CMDMEM/2);
|
||||||
//toSLog(tmp);
|
//toSLog(tmp);
|
||||||
|
|
||||||
if (!strncmp(tmp,"print",5) || pflg) {
|
if (!strncmp(tmp,"print",5) || pflg) {
|
||||||
|
@ -4198,7 +4219,7 @@ void Script_Check_Hue(String *response) {
|
||||||
}
|
}
|
||||||
cp++;
|
cp++;
|
||||||
}
|
}
|
||||||
Replace_Cmd_Vars(line,tmp,sizeof(tmp));
|
Replace_Cmd_Vars(line,0,tmp,sizeof(tmp));
|
||||||
// check for hue defintions
|
// check for hue defintions
|
||||||
// NAME, TYPE , vars
|
// NAME, TYPE , vars
|
||||||
cp=tmp;
|
cp=tmp;
|
||||||
|
@ -5043,7 +5064,7 @@ void ScriptWebShow(char mc) {
|
||||||
WSContentSend_PD(SCRIPT_MSG_NUMINP,label,minstr,maxstr,stepstr,vstr,vname);
|
WSContentSend_PD(SCRIPT_MSG_NUMINP,label,minstr,maxstr,stepstr,vstr,vname);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Replace_Cmd_Vars(lin,tmp,sizeof(tmp));
|
Replace_Cmd_Vars(lin,0,tmp,sizeof(tmp));
|
||||||
if (optflg) {
|
if (optflg) {
|
||||||
WSContentSend_PD(PSTR("<div>%s</div>"),tmp);
|
WSContentSend_PD(PSTR("<div>%s</div>"),tmp);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5052,7 +5073,7 @@ void ScriptWebShow(char mc) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (*lin==mc) {
|
if (*lin==mc) {
|
||||||
Replace_Cmd_Vars(lin+1,tmp,sizeof(tmp));
|
Replace_Cmd_Vars(lin+1,0,tmp,sizeof(tmp));
|
||||||
WSContentSend_PD(PSTR("%s"),tmp);
|
WSContentSend_PD(PSTR("%s"),tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5097,7 +5118,7 @@ uint8_t msect=Run_Scripter(">m",-2,0);
|
||||||
}
|
}
|
||||||
cp++;
|
cp++;
|
||||||
}
|
}
|
||||||
Replace_Cmd_Vars(line,tmp,sizeof(tmp));
|
Replace_Cmd_Vars(line,0,tmp,sizeof(tmp));
|
||||||
//client->println(tmp);
|
//client->println(tmp);
|
||||||
func(tmp);
|
func(tmp);
|
||||||
}
|
}
|
||||||
|
@ -5142,7 +5163,7 @@ void ScriptJsonAppend(void) {
|
||||||
}
|
}
|
||||||
cp++;
|
cp++;
|
||||||
}
|
}
|
||||||
Replace_Cmd_Vars(line,tmp,sizeof(tmp));
|
Replace_Cmd_Vars(line,0,tmp,sizeof(tmp));
|
||||||
ResponseAppend_P(PSTR("%s"),tmp);
|
ResponseAppend_P(PSTR("%s"),tmp);
|
||||||
}
|
}
|
||||||
if (*lp==SCRIPT_EOL) {
|
if (*lp==SCRIPT_EOL) {
|
||||||
|
|
|
@ -306,6 +306,9 @@ void MCP230xx_CheckForInterrupt(void) {
|
||||||
ResponseTime_P(PSTR(",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"),
|
ResponseTime_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"));
|
||||||
|
if (Settings.flag3.hass_tele_on_power) { // SetOption59 - Send tele/%topic%/SENSOR in addition to stat/%topic%/RESULT
|
||||||
|
MqttPublishSensor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (int_event) {
|
if (int_event) {
|
||||||
char command[19]; // Theoretical max = 'event MCPINT_D16=1' so 18 + 1 (for the \n)
|
char command[19]; // Theoretical max = 'event MCPINT_D16=1' so 18 + 1 (for the \n)
|
||||||
|
|
|
@ -45,7 +45,9 @@
|
||||||
#include <TasmotaSerial.h>
|
#include <TasmotaSerial.h>
|
||||||
|
|
||||||
// use special no wait serial driver, should be always on
|
// use special no wait serial driver, should be always on
|
||||||
|
#ifndef ESP32
|
||||||
#define SPECIAL_SS
|
#define SPECIAL_SS
|
||||||
|
#endif
|
||||||
|
|
||||||
// addresses a bug in meter DWS74
|
// addresses a bug in meter DWS74
|
||||||
//#define DWS74_BUG
|
//#define DWS74_BUG
|
||||||
|
@ -440,7 +442,9 @@ const uint8_t meter[]=
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// max number of meters , may be adjusted
|
// max number of meters , may be adjusted
|
||||||
|
#ifndef MAX_METERS
|
||||||
#define MAX_METERS 5
|
#define MAX_METERS 5
|
||||||
|
#endif
|
||||||
double meter_vars[SML_MAX_VARS];
|
double meter_vars[SML_MAX_VARS];
|
||||||
// calulate deltas
|
// calulate deltas
|
||||||
#define MAX_DVARS MAX_METERS*2
|
#define MAX_DVARS MAX_METERS*2
|
||||||
|
@ -453,7 +457,11 @@ const uint8_t *meter_p;
|
||||||
uint8_t meter_spos[MAX_METERS];
|
uint8_t meter_spos[MAX_METERS];
|
||||||
|
|
||||||
// software serial pointers
|
// software serial pointers
|
||||||
|
#ifdef ESP32
|
||||||
|
HardwareSerial *meter_ss[MAX_METERS];
|
||||||
|
#else
|
||||||
TasmotaSerial *meter_ss[MAX_METERS];
|
TasmotaSerial *meter_ss[MAX_METERS];
|
||||||
|
#endif
|
||||||
|
|
||||||
// serial buffers, may be made larger depending on telegram lenght
|
// serial buffers, may be made larger depending on telegram lenght
|
||||||
#define SML_BSIZ 48
|
#define SML_BSIZ 48
|
||||||
|
@ -774,18 +782,21 @@ 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) num=1;
|
if (num<1 || num>meters_used) num=1;
|
||||||
|
if (!meter_ss[num-1]) return 0;
|
||||||
return meter_ss[num-1]->available();
|
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) num=1;
|
if (num<1 || num>meters_used) num=1;
|
||||||
|
if (!meter_ss[num-1]) return 0;
|
||||||
return meter_ss[num-1]->read();
|
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) num=1;
|
if (num<1 || num>meters_used) num=1;
|
||||||
|
if (!meter_ss[num-1]) return 0;
|
||||||
return meter_ss[num-1]->peek();
|
return meter_ss[num-1]->peek();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,7 +1197,8 @@ void sml_shift_in(uint32_t meters,uint32_t shard) {
|
||||||
} else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') {
|
} else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M') {
|
||||||
smltbuf[meters][meter_spos[meters]] = iob;
|
smltbuf[meters][meter_spos[meters]] = iob;
|
||||||
meter_spos[meters]++;
|
meter_spos[meters]++;
|
||||||
if (meter_spos[meters]>=9) {
|
uint32_t mlen=smltbuf[meters][2]+5;
|
||||||
|
if (meter_spos[meters]>=mlen) {
|
||||||
SML_Decode(meters);
|
SML_Decode(meters);
|
||||||
sml_empty_receiver(meters);
|
sml_empty_receiver(meters);
|
||||||
meter_spos[meters]=0;
|
meter_spos[meters]=0;
|
||||||
|
@ -1236,6 +1248,7 @@ 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_ss[meters]) continue;
|
||||||
while (meter_ss[meters]->available()) {
|
while (meter_ss[meters]->available()) {
|
||||||
sml_shift_in(meters,0);
|
sml_shift_in(meters,0);
|
||||||
}
|
}
|
||||||
|
@ -1530,9 +1543,10 @@ void SML_Decode(uint8_t index) {
|
||||||
if (mb_index!=meter_desc_p[mindex].index) {
|
if (mb_index!=meter_desc_p[mindex].index) {
|
||||||
goto nextsect;
|
goto nextsect;
|
||||||
}
|
}
|
||||||
uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],7);
|
uint16_t pos = smltbuf[mindex][2]+3;
|
||||||
if (lowByte(crc)!=smltbuf[mindex][7]) goto nextsect;
|
uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],pos);
|
||||||
if (highByte(crc)!=smltbuf[mindex][8]) goto nextsect;
|
if (lowByte(crc)!=smltbuf[mindex][pos]) goto nextsect;
|
||||||
|
if (highByte(crc)!=smltbuf[mindex][pos+1]) goto nextsect;
|
||||||
dval=mbus_dval;
|
dval=mbus_dval;
|
||||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
|
||||||
mp++;
|
mp++;
|
||||||
|
@ -1728,7 +1742,7 @@ void SML_Show(boolean json) {
|
||||||
} else {
|
} else {
|
||||||
// web ui export
|
// web ui export
|
||||||
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s %s: {m}%s %s{e}", b_mqtt_data,meter_desc[mindex].prefix,name,tpowstr,unit);
|
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s %s: {m}%s %s{e}", b_mqtt_data,meter_desc[mindex].prefix,name,tpowstr,unit);
|
||||||
WSContentSend_PD(PSTR("{s}%s %s: {m}%s %s{e}"),meter_desc_p[mindex].prefix,name,tpowstr,unit);
|
if (strcmp(name,"*")) WSContentSend_PD(PSTR("{s}%s %s: {m}%s %s{e}"),meter_desc_p[mindex].prefix,name,tpowstr,unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1830,6 +1844,52 @@ uint8_t *script_meter;
|
||||||
#define METER_DEF_SIZE 3000
|
#define METER_DEF_SIZE 3000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SML_REPLACE_VARS
|
||||||
|
|
||||||
|
#define SML_SRCBSIZE 256
|
||||||
|
|
||||||
|
uint32_t SML_getlinelen(char *lp) {
|
||||||
|
uint32_t cnt;
|
||||||
|
for (cnt=0; cnt<SML_SRCBSIZE-1; cnt++) {
|
||||||
|
if (lp[cnt]==SCRIPT_EOL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t SML_getscriptsize(char *lp) {
|
||||||
|
uint32_t mlen=0;
|
||||||
|
char dstbuf[SML_SRCBSIZE*2];
|
||||||
|
while (1) {
|
||||||
|
Replace_Cmd_Vars(lp,1,dstbuf,sizeof(dstbuf));
|
||||||
|
lp+=SML_getlinelen(lp)+1;
|
||||||
|
uint32_t slen=strlen(dstbuf);
|
||||||
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR("%d - %s"),slen,dstbuf);
|
||||||
|
mlen+=slen+1;
|
||||||
|
if (*lp=='#') break;
|
||||||
|
if (*lp=='>') break;
|
||||||
|
if (*lp==0) break;
|
||||||
|
}
|
||||||
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR("len=%d"),mlen);
|
||||||
|
return mlen+32;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint32_t SML_getscriptsize(char *lp) {
|
||||||
|
uint32_t mlen=0;
|
||||||
|
for (uint32_t cnt=0;cnt<METER_DEF_SIZE-1;cnt++) {
|
||||||
|
if (lp[cnt]=='\n' && lp[cnt+1]=='#') {
|
||||||
|
mlen=cnt+3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR("len=%d"),mlen);
|
||||||
|
return mlen;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Gpio_used(uint8_t gpiopin) {
|
bool Gpio_used(uint8_t gpiopin) {
|
||||||
/*
|
/*
|
||||||
for (uint16_t i=0;i<GPIO_SENSOR_END;i++) {
|
for (uint16_t i=0;i<GPIO_SENSOR_END;i++) {
|
||||||
|
@ -1865,10 +1925,19 @@ void SML_Init(void) {
|
||||||
for (uint32_t cnt=0;cnt<MAX_METERS;cnt++) {
|
for (uint32_t cnt=0;cnt<MAX_METERS;cnt++) {
|
||||||
if (script_meter_desc[cnt].txmem) {
|
if (script_meter_desc[cnt].txmem) {
|
||||||
free(script_meter_desc[cnt].txmem);
|
free(script_meter_desc[cnt].txmem);
|
||||||
script_meter_desc[cnt].txmem=0;
|
|
||||||
}
|
}
|
||||||
|
script_meter_desc[cnt].txmem=0;
|
||||||
|
script_meter_desc[cnt].trxpin=-1;
|
||||||
|
|
||||||
|
if (meter_ss[cnt]) {
|
||||||
|
delete meter_ss[cnt];
|
||||||
|
meter_ss[cnt]=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bitRead(Settings.rule_enabled, 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
|
||||||
|
@ -1886,13 +1955,7 @@ void SML_Init(void) {
|
||||||
lp+=2;
|
lp+=2;
|
||||||
meters_used=strtol(lp,0,10);
|
meters_used=strtol(lp,0,10);
|
||||||
section=1;
|
section=1;
|
||||||
uint32_t mlen=0;
|
uint32_t mlen=SML_getscriptsize(lp);
|
||||||
for (uint32_t cnt=0;cnt<METER_DEF_SIZE-1;cnt++) {
|
|
||||||
if (lp[cnt]=='\n' && lp[cnt+1]=='#') {
|
|
||||||
mlen=cnt+3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mlen==0) return; // missing end #
|
if (mlen==0) return; // missing end #
|
||||||
script_meter=(uint8_t*)calloc(mlen,1);
|
script_meter=(uint8_t*)calloc(mlen,1);
|
||||||
if (!script_meter) {
|
if (!script_meter) {
|
||||||
|
@ -1981,6 +2044,30 @@ dddef_exit:
|
||||||
goto next_line;
|
goto next_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SML_REPLACE_VARS
|
||||||
|
char dstbuf[SML_SRCBSIZE*2];
|
||||||
|
Replace_Cmd_Vars(lp,1,dstbuf,sizeof(dstbuf));
|
||||||
|
lp+=SML_getlinelen(lp);
|
||||||
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR("%s"),dstbuf);
|
||||||
|
char *lp1=dstbuf;
|
||||||
|
if (*lp1=='-' || isdigit(*lp1)) {
|
||||||
|
//toLogEOL(">>",lp);
|
||||||
|
// add meters line -1,1-0:1.8.0*255(@10000,H2OIN,cbm,COUNTER,4|
|
||||||
|
if (*lp1=='-') lp1++;
|
||||||
|
uint8_t mnum=strtol(lp1,0,10);
|
||||||
|
if (mnum<1 || mnum>meters_used) goto next_line;
|
||||||
|
while (1) {
|
||||||
|
if (*lp1==0) {
|
||||||
|
*tp++='|';
|
||||||
|
goto next_line;
|
||||||
|
}
|
||||||
|
*tp++=*lp1++;
|
||||||
|
index++;
|
||||||
|
if (index>=METER_DEF_SIZE) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
if (*lp=='-' || isdigit(*lp)) {
|
if (*lp=='-' || isdigit(*lp)) {
|
||||||
//toLogEOL(">>",lp);
|
//toLogEOL(">>",lp);
|
||||||
// add meters line -1,1-0:1.8.0*255(@10000,H2OIN,cbm,COUNTER,4|
|
// add meters line -1,1-0:1.8.0*255(@10000,H2OIN,cbm,COUNTER,4|
|
||||||
|
@ -1997,6 +2084,7 @@ dddef_exit:
|
||||||
if (index>=METER_DEF_SIZE) break;
|
if (index>=METER_DEF_SIZE) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2013,6 +2101,7 @@ next_line:
|
||||||
meter_desc_p=script_meter_desc;
|
meter_desc_p=script_meter_desc;
|
||||||
meter_p=script_meter;
|
meter_p=script_meter;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
init10:
|
init10:
|
||||||
|
@ -2024,6 +2113,7 @@ init10:
|
||||||
RtcSettings.pulse_counter[i]=Settings.pulse_counter[i];
|
RtcSettings.pulse_counter[i]=Settings.pulse_counter[i];
|
||||||
sml_counters[i].sml_cnt_last_ts=millis();
|
sml_counters[i].sml_cnt_last_ts=millis();
|
||||||
}
|
}
|
||||||
|
uint32_t uart_index=2;
|
||||||
for (uint8_t meters=0; meters<meters_used; meters++) {
|
for (uint8_t meters=0; meters<meters_used; meters++) {
|
||||||
if (meter_desc_p[meters].type=='c') {
|
if (meter_desc_p[meters].type=='c') {
|
||||||
if (meter_desc_p[meters].flag&2) {
|
if (meter_desc_p[meters].flag&2) {
|
||||||
|
@ -2058,9 +2148,23 @@ init10:
|
||||||
} else {
|
} else {
|
||||||
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,1);
|
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,1);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#ifdef ESP32
|
||||||
|
meter_ss[meters] = new HardwareSerial(uart_index);
|
||||||
|
uart_index--;
|
||||||
|
if (uart_index<0) uart_index=0;
|
||||||
#else
|
#else
|
||||||
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1);
|
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
if (meter_desc_p[meters].type=='M') {
|
||||||
|
meter_ss[meters]->begin(meter_desc_p[meters].params, SERIAL_8E1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin);
|
||||||
|
} else {
|
||||||
|
meter_ss[meters]->begin(meter_desc_p[meters].params,SERIAL_8N1,meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin);
|
||||||
|
}
|
||||||
|
#else
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
@ -2069,8 +2173,9 @@ init10:
|
||||||
Serial.begin(meter_desc_p[meters].params, SERIAL_8E1);
|
Serial.begin(meter_desc_p[meters].params, SERIAL_8E1);
|
||||||
}
|
}
|
||||||
ClaimSerial();
|
ClaimSerial();
|
||||||
|
//Serial.setRxBufferSize(512);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2262,6 +2367,11 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
|
||||||
uint8_t sbuff[32];
|
uint8_t sbuff[32];
|
||||||
uint8_t *ucp=sbuff,slen=0;
|
uint8_t *ucp=sbuff,slen=0;
|
||||||
char *cp=seq;
|
char *cp=seq;
|
||||||
|
uint8_t rflg = 0;
|
||||||
|
if (*cp=='r') {
|
||||||
|
rflg = 1;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
while (*cp) {
|
while (*cp) {
|
||||||
if (!*cp || !*(cp+1)) break;
|
if (!*cp || !*(cp+1)) break;
|
||||||
if (*cp==',') break;
|
if (*cp==',') break;
|
||||||
|
@ -2272,8 +2382,10 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
|
||||||
if (slen>=sizeof(sbuff)) break;
|
if (slen>=sizeof(sbuff)) break;
|
||||||
}
|
}
|
||||||
if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') {
|
if (script_meter_desc[meter].type=='m' || script_meter_desc[meter].type=='M') {
|
||||||
*ucp++=0;
|
if (!rflg) {
|
||||||
*ucp++=2;
|
*ucp++=0;
|
||||||
|
*ucp++=2;
|
||||||
|
}
|
||||||
// append crc
|
// append crc
|
||||||
uint16_t crc = MBUS_calculateCRC(sbuff,6);
|
uint16_t crc = MBUS_calculateCRC(sbuff,6);
|
||||||
*ucp++=lowByte(crc);
|
*ucp++=lowByte(crc);
|
||||||
|
@ -2412,14 +2524,18 @@ bool Xsns53(byte function) {
|
||||||
break;
|
break;
|
||||||
case FUNC_LOOP:
|
case FUNC_LOOP:
|
||||||
SML_Counter_Poll();
|
SML_Counter_Poll();
|
||||||
break;
|
|
||||||
case FUNC_EVERY_50_MSECOND:
|
|
||||||
if (dump2log) Dump2log();
|
if (dump2log) Dump2log();
|
||||||
else SML_Poll();
|
else SML_Poll();
|
||||||
break;
|
break;
|
||||||
|
// case FUNC_EVERY_50_MSECOND:
|
||||||
|
// if (dump2log) Dump2log();
|
||||||
|
// else SML_Poll();
|
||||||
|
// break;
|
||||||
#ifdef USE_SCRIPT
|
#ifdef USE_SCRIPT
|
||||||
case FUNC_EVERY_100_MSECOND:
|
case FUNC_EVERY_100_MSECOND:
|
||||||
SML_Check_Send();
|
if (bitRead(Settings.rule_enabled, 0)) {
|
||||||
|
SML_Check_Send();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
#endif // USE_SCRIPT
|
#endif // USE_SCRIPT
|
||||||
case FUNC_JSON_APPEND:
|
case FUNC_JSON_APPEND:
|
||||||
|
|
Loading…
Reference in New Issue