mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-25 11:46:31 +00:00
Merge pull request #16538 from gemu2015/sml_update
add kamstrup, fix mbus u32
This commit is contained in:
commit
9c7e536618
@ -53,6 +53,8 @@
|
|||||||
#define TMSBSIZ 256
|
#define TMSBSIZ 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MODBUS_DEBUG
|
||||||
|
|
||||||
// addresses a bug in meter DWS74
|
// addresses a bug in meter DWS74
|
||||||
//#define DWS74_BUG
|
//#define DWS74_BUG
|
||||||
|
|
||||||
@ -1609,16 +1611,16 @@ void sml_empty_receiver(uint32_t meters) {
|
|||||||
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;
|
||||||
#ifndef SML_OBIS_LINE
|
#ifndef SML_OBIS_LINE
|
||||||
if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R' && meter_desc_p[meters].type!='v') {
|
if (meter_desc_p[meters].type != 'e' && meter_desc_p[meters].type != 'k' && meter_desc_p[meters].type != 'm' && meter_desc_p[meters].type != 'M' && meter_desc_p[meters].type != 'p' && meter_desc_p[meters].type != 'R' && meter_desc_p[meters].type != 'v') {
|
||||||
#else
|
#else
|
||||||
if (meter_desc_p[meters].type!='o' && meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R' && meter_desc_p[meters].type!='v') {
|
if (meter_desc_p[meters].type!= 'o' && meter_desc_p[meters].type != 'e' && meter_desc_p[meters].type != 'k' && meter_desc_p[meters].type != 'm' && meter_desc_p[meters].type != 'M' && meter_desc_p[meters].type != 'p' && meter_desc_p[meters].type != 'R' && meter_desc_p[meters].type != 'v') {
|
||||||
#endif
|
#endif
|
||||||
// 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)meter_ss[meters]->read();
|
uint8_t iob = (uint8_t)meter_ss[meters]->read();
|
||||||
|
|
||||||
if (meter_desc_p[meters].type == 'o') {
|
if (meter_desc_p[meters].type == 'o') {
|
||||||
#ifndef SML_OBIS_LINE
|
#ifndef SML_OBIS_LINE
|
||||||
@ -1639,37 +1641,73 @@ 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' || meter_desc_p[meters].type=='M') {
|
} else if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M' || meter_desc_p[meters].type=='k') {
|
||||||
|
|
||||||
|
if (meter_desc_p[meters].type=='k') {
|
||||||
|
// Kamstrup
|
||||||
|
if (iob == 0x40) {
|
||||||
|
meter_spos[meters] = 0;
|
||||||
|
} else if (iob == 0x0d) {
|
||||||
|
uint16_t crc = KS_calculateCRC(&smltbuf[meters][0], meter_spos[meters]);
|
||||||
|
if (!crc) {
|
||||||
|
uint8_t *ucp = &smltbuf[meters][0];
|
||||||
|
for (uint16_t cnt = 0; cnt < meter_spos[meters]; cnt++) {
|
||||||
|
uint8_t iob = smltbuf[meters][cnt];
|
||||||
|
if (iob == 0x1b) {
|
||||||
|
*ucp++ = smltbuf[meters][cnt + 1] ^ 0xff;
|
||||||
|
cnt++;
|
||||||
|
} else {
|
||||||
|
*ucp++ = iob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SML_Decode(meters);
|
||||||
|
}
|
||||||
|
sml_empty_receiver(meters);
|
||||||
|
meter_spos[meters] = 0;
|
||||||
|
} else {
|
||||||
smltbuf[meters][meter_spos[meters]] = iob;
|
smltbuf[meters][meter_spos[meters]] = iob;
|
||||||
meter_spos[meters]++;
|
meter_spos[meters]++;
|
||||||
if (meter_spos[meters]>=SML_BSIZ) {
|
if (meter_spos[meters] >= SML_BSIZ) {
|
||||||
meter_spos[meters]=0;
|
meter_spos[meters] = 0;
|
||||||
}
|
}
|
||||||
if (meter_spos[meters]>=8) {
|
}
|
||||||
uint32_t mlen=smltbuf[meters][2]+5;
|
} else {
|
||||||
if (mlen>SML_BSIZ) mlen=SML_BSIZ;
|
smltbuf[meters][meter_spos[meters]] = iob;
|
||||||
if (meter_spos[meters]>=mlen) {
|
meter_spos[meters]++;
|
||||||
|
if (meter_spos[meters] >= SML_BSIZ) {
|
||||||
|
meter_spos[meters] = 0;
|
||||||
|
}
|
||||||
|
// modbus
|
||||||
|
if (meter_spos[meters] >= 8) {
|
||||||
|
uint32_t mlen = smltbuf[meters][2] + 5;
|
||||||
|
if (mlen > SML_BSIZ) mlen = SML_BSIZ;
|
||||||
|
if (meter_spos[meters] >= mlen) {
|
||||||
|
#ifdef MODBUS_DEBUG
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("receive index >> %d"),meter_desc_p[meters].index);
|
||||||
|
Hexdump(smltbuf[meters], 10);
|
||||||
|
#endif
|
||||||
SML_Decode(meters);
|
SML_Decode(meters);
|
||||||
sml_empty_receiver(meters);
|
sml_empty_receiver(meters);
|
||||||
meter_spos[meters]=0;
|
meter_spos[meters] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (meter_desc_p[meters].type=='p') {
|
}
|
||||||
|
} else if (meter_desc_p[meters].type == 'p') {
|
||||||
smltbuf[meters][meter_spos[meters]] = iob;
|
smltbuf[meters][meter_spos[meters]] = iob;
|
||||||
meter_spos[meters]++;
|
meter_spos[meters]++;
|
||||||
if (meter_spos[meters]>=7) {
|
if (meter_spos[meters] >= 7) {
|
||||||
SML_Decode(meters);
|
SML_Decode(meters);
|
||||||
sml_empty_receiver(meters);
|
sml_empty_receiver(meters);
|
||||||
meter_spos[meters]=0;
|
meter_spos[meters] = 0;
|
||||||
}
|
}
|
||||||
} else if (meter_desc_p[meters].type=='R') {
|
} else if (meter_desc_p[meters].type == 'R') {
|
||||||
smltbuf[meters][meter_spos[meters]] = iob;
|
smltbuf[meters][meter_spos[meters]] = iob;
|
||||||
meter_spos[meters]++;
|
meter_spos[meters]++;
|
||||||
if (meter_spos[meters]>=SML_BSIZ) {
|
if (meter_spos[meters] >= SML_BSIZ) {
|
||||||
meter_spos[meters]=0;
|
meter_spos[meters] = 0;
|
||||||
}
|
}
|
||||||
} else if (meter_desc_p[meters].type=='v') {
|
} else if (meter_desc_p[meters].type == 'v') {
|
||||||
if (iob==EBUS_SYNC) {
|
if (iob == EBUS_SYNC) {
|
||||||
sb_counter = 0;
|
sb_counter = 0;
|
||||||
SML_Decode(meters);
|
SML_Decode(meters);
|
||||||
smltbuf[meters][0] = iob;
|
smltbuf[meters][0] = iob;
|
||||||
@ -1682,15 +1720,15 @@ void sml_shift_in(uint32_t meters,uint32_t shard) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (iob==EBUS_SYNC) {
|
if (iob == EBUS_SYNC) {
|
||||||
// should be end of telegramm
|
// should be end of telegramm
|
||||||
// QQ,ZZ,PB,SB,NN ..... CRC, ACK SYNC
|
// QQ,ZZ,PB,SB,NN ..... CRC, ACK SYNC
|
||||||
if (meter_spos[meters]>4+5) {
|
if (meter_spos[meters] > 4 + 5) {
|
||||||
// get telegramm lenght
|
// get telegramm lenght
|
||||||
uint16_t tlen=smltbuf[meters][4]+5;
|
uint16_t tlen = smltbuf[meters][4] + 5;
|
||||||
// test crc
|
// test crc
|
||||||
if (smltbuf[meters][tlen]=ebus_CalculateCRC(smltbuf[meters],tlen)) {
|
if (smltbuf[meters][tlen] = ebus_CalculateCRC(smltbuf[meters], tlen)) {
|
||||||
ebus_esc(smltbuf[meters],tlen);
|
ebus_esc(smltbuf[meters], tlen);
|
||||||
SML_Decode(meters);
|
SML_Decode(meters);
|
||||||
} else {
|
} else {
|
||||||
// crc error
|
// crc error
|
||||||
@ -1702,15 +1740,15 @@ void sml_shift_in(uint32_t meters,uint32_t shard) {
|
|||||||
}
|
}
|
||||||
smltbuf[meters][meter_spos[meters]] = iob;
|
smltbuf[meters][meter_spos[meters]] = iob;
|
||||||
meter_spos[meters]++;
|
meter_spos[meters]++;
|
||||||
if (meter_spos[meters]>=SML_BSIZ) {
|
if (meter_spos[meters] >= SML_BSIZ) {
|
||||||
meter_spos[meters]=0;
|
meter_spos[meters] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb_counter++;
|
sb_counter++;
|
||||||
#ifndef SML_OBIS_LINE
|
#ifndef SML_OBIS_LINE
|
||||||
if (meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R' && meter_desc_p[meters].type!='v') SML_Decode(meters);
|
if (meter_desc_p[meters].type != 'e' && meter_desc_p[meters].type != 'm' && meter_desc_p[meters].type != 'M' && meter_desc_p[meters].type != 'k' && meter_desc_p[meters].type != 'p' && meter_desc_p[meters].type != 'R' && meter_desc_p[meters].type != 'v') SML_Decode(meters);
|
||||||
#else
|
#else
|
||||||
if (meter_desc_p[meters].type!='o' && meter_desc_p[meters].type!='e' && meter_desc_p[meters].type!='m' && meter_desc_p[meters].type!='M' && meter_desc_p[meters].type!='p' && meter_desc_p[meters].type!='R' && meter_desc_p[meters].type!='v') SML_Decode(meters);
|
if (meter_desc_p[meters].type != 'o' && meter_desc_p[meters].type != 'e' && meter_desc_p[meters].type != 'm' && meter_desc_p[meters].type != 'M' && meter_desc_p[meters].type != 'k' && meter_desc_p[meters].type != 'p' && meter_desc_p[meters].type != 'R' && meter_desc_p[meters].type != 'v') SML_Decode(meters);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1723,7 +1761,7 @@ uint32_t 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;
|
if (!meter_ss[meters]) continue;
|
||||||
if (ser_act_LED_pin!=255 && (ser_act_meter_num==0 || ser_act_meter_num-1==meters)) {
|
if (ser_act_LED_pin != 255 && (ser_act_meter_num == 0 || ser_act_meter_num - 1 == meters)) {
|
||||||
digitalWrite(ser_act_LED_pin, meter_ss[meters]->available() && !digitalRead(ser_act_LED_pin)); // Invert LED, if queue is continuously full
|
digitalWrite(ser_act_LED_pin, meter_ss[meters]->available() && !digitalRead(ser_act_LED_pin)); // Invert LED, if queue is continuously full
|
||||||
}
|
}
|
||||||
while (meter_ss[meters]->available()) {
|
while (meter_ss[meters]->available()) {
|
||||||
@ -1944,7 +1982,7 @@ void SML_Decode(uint8_t index) {
|
|||||||
// compare value
|
// compare value
|
||||||
uint8_t found = 1;
|
uint8_t found = 1;
|
||||||
double ebus_dval = 99;
|
double ebus_dval = 99;
|
||||||
float mbus_dval = 99;
|
double 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++) {
|
||||||
@ -2083,6 +2121,28 @@ void SML_Decode(uint8_t index) {
|
|||||||
mbus_dval = (float)((cp[0]<<8) | cp[1]);
|
mbus_dval = (float)((cp[0]<<8) | cp[1]);
|
||||||
mp += 4;
|
mp += 4;
|
||||||
cp += 2;
|
cp += 2;
|
||||||
|
} else if (!strncmp(mp, "kstr", 4)) {
|
||||||
|
mp += 4;
|
||||||
|
// decode the mantissa
|
||||||
|
uint32_t x = 0;
|
||||||
|
for (uint16_t i = 0; i < cp[5]; i++) {
|
||||||
|
x <<= 8;
|
||||||
|
x |= cp[i + 7];
|
||||||
|
}
|
||||||
|
// decode the exponent
|
||||||
|
int32_t i = cp[6] & 0x3f;
|
||||||
|
if (cp[6] & 0x40) {
|
||||||
|
i = -i;
|
||||||
|
};
|
||||||
|
//float ifl = pow(10, i);
|
||||||
|
float ifl = 1;
|
||||||
|
for (uint16_t x = 1; x <= i; ++x) {
|
||||||
|
ifl *= 10;
|
||||||
|
}
|
||||||
|
if (cp[6] & 0x80) {
|
||||||
|
ifl = -ifl;
|
||||||
|
}
|
||||||
|
mbus_dval = (double )(x * ifl);
|
||||||
} else if (!strncmp(mp, "bcd", 3)) {
|
} else if (!strncmp(mp, "bcd", 3)) {
|
||||||
mp += 3;
|
mp += 3;
|
||||||
uint8_t digits = strtol((char*)mp, (char**)&mp, 10);
|
uint8_t digits = strtol((char*)mp, (char**)&mp, 10);
|
||||||
@ -2229,7 +2289,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' && meter_desc_p[mindex].type!='m' && meter_desc_p[mindex].type!='M' && meter_desc_p[mindex].type!='p' && meter_desc_p[mindex].type!='v') {
|
if (meter_desc_p[mindex].type!='e' && meter_desc_p[mindex].type!='r' && meter_desc_p[mindex].type!='m' && meter_desc_p[mindex].type!='M' && meter_desc_p[mindex].type!='k' && meter_desc_p[mindex].type!='p' && meter_desc_p[mindex].type!='v') {
|
||||||
// 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') {
|
||||||
if (*mp == '(') {
|
if (*mp == '(') {
|
||||||
@ -2262,47 +2322,53 @@ void SML_Decode(uint8_t index) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ebus pzem vbus or mbus or raw
|
// ebus pzem vbus or mbus or raw
|
||||||
if (*mp=='b') {
|
if (*mp == 'b') {
|
||||||
mp++;
|
mp++;
|
||||||
uint8_t shift = *mp&7;
|
uint8_t shift = *mp&7;
|
||||||
ebus_dval = (uint32_t)ebus_dval>>shift;
|
ebus_dval = (uint32_t)ebus_dval>>shift;
|
||||||
ebus_dval = (uint32_t)ebus_dval&1;
|
ebus_dval = (uint32_t)ebus_dval&1;
|
||||||
mp+=2;
|
mp+=2;
|
||||||
}
|
}
|
||||||
if (*mp=='i') {
|
if (*mp == 'i') {
|
||||||
// mbus index
|
// mbus index
|
||||||
mp++;
|
mp++;
|
||||||
uint8_t mb_index=strtol((char*)mp,(char**)&mp,10);
|
uint8_t mb_index = strtol((char*)mp, (char**)&mp, 10);
|
||||||
if (mb_index!=meter_desc_p[mindex].index) {
|
if (mb_index != meter_desc_p[mindex].index) {
|
||||||
goto nextsect;
|
goto nextsect;
|
||||||
}
|
}
|
||||||
uint16_t pos = smltbuf[mindex][2]+3;
|
if (meter_desc_p[mindex].type == 'k') {
|
||||||
if (pos>32) pos=32;
|
// crc is already checked, get float value
|
||||||
uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0],pos,0xFFFF);
|
dval = mbus_dval;
|
||||||
if (lowByte(crc)!=smltbuf[mindex][pos]) goto nextsect;
|
|
||||||
if (highByte(crc)!=smltbuf[mindex][pos+1]) goto nextsect;
|
|
||||||
dval=mbus_dval;
|
|
||||||
//AddLog(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
|
|
||||||
mp++;
|
mp++;
|
||||||
} else {
|
} else {
|
||||||
if (meter_desc_p[mindex].type=='p') {
|
uint16_t pos = smltbuf[mindex][2] + 3;
|
||||||
uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6);
|
if (pos > 32) pos = 32;
|
||||||
if (crc!=smltbuf[mindex][6]) goto nextsect;
|
uint16_t crc = MBUS_calculateCRC(&smltbuf[mindex][0], pos, 0xFFFF);
|
||||||
dval=mbus_dval;
|
if (lowByte(crc) != smltbuf[mindex][pos]) goto nextsect;
|
||||||
|
if (highByte(crc) != smltbuf[mindex][pos + 1]) goto nextsect;
|
||||||
|
dval = mbus_dval;
|
||||||
|
//AddLog(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
|
||||||
|
mp++;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dval=ebus_dval;
|
if (meter_desc_p[mindex].type == 'p') {
|
||||||
|
uint8_t crc = SML_PzemCrc(&smltbuf[mindex][0],6);
|
||||||
|
if (crc != smltbuf[mindex][6]) goto nextsect;
|
||||||
|
dval = mbus_dval;
|
||||||
|
} else {
|
||||||
|
dval = ebus_dval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef USE_SML_MEDIAN_FILTER
|
#ifdef USE_SML_MEDIAN_FILTER
|
||||||
if (meter_desc_p[mindex].flag&16) {
|
if (meter_desc_p[mindex].flag & 16) {
|
||||||
meter_vars[vindex]=sml_median(&sml_mf[vindex],dval);
|
meter_vars[vindex] = sml_median(&sml_mf[vindex], dval);
|
||||||
} else {
|
} else {
|
||||||
meter_vars[vindex]=dval;
|
meter_vars[vindex] = dval;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
meter_vars[vindex]=dval;
|
meter_vars[vindex] = dval;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//AddLog(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
|
//AddLog(LOG_LEVEL_INFO, PSTR(">> %s"),mp);
|
||||||
@ -2356,11 +2422,11 @@ void SML_Immediate_MQTT(const char *mp,uint8_t index,uint8_t mindex) {
|
|||||||
jname[count]=*cp++;
|
jname[count]=*cp++;
|
||||||
}
|
}
|
||||||
cp++;
|
cp++;
|
||||||
uint8_t dp=atoi(cp);
|
uint8_t dp = atoi(cp);
|
||||||
if (dp&0x10) {
|
if (dp & 0x10) {
|
||||||
// immediate mqtt
|
// immediate mqtt
|
||||||
dtostrfd(meter_vars[index],dp&0xf,tpowstr);
|
dtostrfd(meter_vars[index], dp & 0xf, tpowstr);
|
||||||
ResponseTime_P(PSTR(",\"%s\":{\"%s\":%s}}"),meter_desc_p[mindex].prefix,jname,tpowstr);
|
ResponseTime_P(PSTR(",\"%s\":{\"%s\":%s}}"), meter_desc_p[mindex].prefix, jname, tpowstr);
|
||||||
MqttPublishTeleSensor();
|
MqttPublishTeleSensor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2383,22 +2449,22 @@ void SML_Show(boolean json) {
|
|||||||
|
|
||||||
if (!meters_used) return;
|
if (!meters_used) return;
|
||||||
|
|
||||||
int8_t lastmind=((*mp)&7)-1;
|
int8_t lastmind = ((*mp) & 7) - 1;
|
||||||
if (lastmind<0 || lastmind>=meters_used) lastmind=0;
|
if (lastmind < 0 || lastmind >= meters_used) lastmind = 0;
|
||||||
while (mp != NULL) {
|
while (mp != NULL) {
|
||||||
if (*mp==0) break;
|
if (*mp == 0) break;
|
||||||
// setup sections
|
// setup sections
|
||||||
mindex=((*mp)&7)-1;
|
mindex = ((*mp) & 7) - 1;
|
||||||
|
|
||||||
if (mindex<0 || mindex>=meters_used) mindex=0;
|
if (mindex < 0 || mindex >= meters_used) mindex = 0;
|
||||||
if (meter_desc_p[mindex].prefix[0]=='*' && meter_desc_p[mindex].prefix[1]==0) {
|
if (meter_desc_p[mindex].prefix[0] == '*' && meter_desc_p[mindex].prefix[1] == 0) {
|
||||||
nojson = 1;
|
nojson = 1;
|
||||||
} else {
|
} else {
|
||||||
nojson = 0;
|
nojson = 0;
|
||||||
}
|
}
|
||||||
mp+=2;
|
mp += 2;
|
||||||
if (*mp=='=' && *(mp+1)=='h') {
|
if (*mp == '=' && *(mp+1) == 'h') {
|
||||||
mp+=2;
|
mp += 2;
|
||||||
// html tag
|
// html tag
|
||||||
if (json) {
|
if (json) {
|
||||||
mp = strchr(mp, '|');
|
mp = strchr(mp, '|');
|
||||||
@ -2407,49 +2473,49 @@ void SML_Show(boolean json) {
|
|||||||
}
|
}
|
||||||
// web ui export
|
// web ui export
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
for (i=0;i<sizeof(tpowstr)-2;i++) {
|
for (i = 0; i < sizeof(tpowstr) - 2; i++) {
|
||||||
if (*mp=='|' || *mp==0) break;
|
if (*mp == '|' || *mp == 0) break;
|
||||||
tpowstr[i]=*mp++;
|
tpowstr[i] = *mp++;
|
||||||
}
|
}
|
||||||
tpowstr[i]=0;
|
tpowstr[i] = 0;
|
||||||
// export html
|
// export html
|
||||||
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s{e}", b_mqtt_data,tpowstr);
|
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s{s}%s{e}", b_mqtt_data,tpowstr);
|
||||||
WSContentSend_PD(PSTR("{s}%s{e}"),tpowstr);
|
WSContentSend_PD(PSTR("{s}%s{e}"), tpowstr);
|
||||||
// rewind, to ensure strchr
|
// rewind, to ensure strchr
|
||||||
mp--;
|
mp--;
|
||||||
mp = strchr(mp, '|');
|
mp = strchr(mp, '|');
|
||||||
if (mp) mp++;
|
if (mp) mp++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*mp=='=' && *(mp+1)=='s') {
|
if (*mp == '=' && *(mp + 1) == 's') {
|
||||||
mp = strchr(mp, '|');
|
mp = strchr(mp, '|');
|
||||||
if (mp) mp++;
|
if (mp) mp++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// skip compare section
|
// skip compare section
|
||||||
cp=strchr(mp,'@');
|
cp=strchr(mp, '@');
|
||||||
if (cp) {
|
if (cp) {
|
||||||
cp++;
|
cp++;
|
||||||
tststr:
|
tststr:
|
||||||
if (*cp=='#') {
|
if (*cp == '#') {
|
||||||
// meter id
|
// meter id
|
||||||
if (*(cp + 1) == 'x') {
|
if (*(cp + 1) == 'x') {
|
||||||
// convert hex to asci
|
// convert hex to asci
|
||||||
sml_hex_asci(mindex, tpowstr);
|
sml_hex_asci(mindex, tpowstr);
|
||||||
} else {
|
} else {
|
||||||
sprintf(tpowstr,"\"%s\"",&meter_id[mindex][0]);
|
sprintf(tpowstr,"\"%s\"", &meter_id[mindex][0]);
|
||||||
}
|
}
|
||||||
mid=1;
|
mid = 1;
|
||||||
} else if (*cp=='(') {
|
} else if (*cp == '(') {
|
||||||
if (meter_desc_p[mindex].type=='o') {
|
if (meter_desc_p[mindex].type == 'o') {
|
||||||
cp++;
|
cp++;
|
||||||
strtol((char*)cp,(char**)&cp, 10);
|
strtol((char*)cp,(char**)&cp, 10);
|
||||||
cp++;
|
cp++;
|
||||||
goto tststr;
|
goto tststr;
|
||||||
} else {
|
} else {
|
||||||
mid=0;
|
mid = 0;
|
||||||
}
|
}
|
||||||
} else if (*cp=='b') {
|
} else if (*cp == 'b') {
|
||||||
// bit value
|
// bit value
|
||||||
#ifdef SML_BIT_TEXT
|
#ifdef SML_BIT_TEXT
|
||||||
sprintf_P(tpowstr, PSTR("\"%s\""), (uint8_t)meter_vars[index]?D_ON:D_OFF);
|
sprintf_P(tpowstr, PSTR("\"%s\""), (uint8_t)meter_vars[index]?D_ON:D_OFF);
|
||||||
@ -2459,41 +2525,41 @@ void SML_Show(boolean json) {
|
|||||||
mid = 0;
|
mid = 0;
|
||||||
}
|
}
|
||||||
// skip scaling
|
// skip scaling
|
||||||
cp=strchr(cp,',');
|
cp = strchr(cp, ',');
|
||||||
if (cp) {
|
if (cp) {
|
||||||
// this is the name in web UI
|
// this is the name in web UI
|
||||||
cp++;
|
cp++;
|
||||||
for (count=0;count<sizeof(name);count++) {
|
for (count = 0; count < sizeof(name); count++) {
|
||||||
if (*cp==',') {
|
if (*cp == ',') {
|
||||||
name[count]=0;
|
name[count] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
name[count]=*cp++;
|
name[count] = *cp++;
|
||||||
}
|
}
|
||||||
cp++;
|
cp++;
|
||||||
|
|
||||||
for (count=0;count<sizeof(unit);count++) {
|
for (count = 0; count < sizeof(unit); count++) {
|
||||||
if (*cp==',') {
|
if (*cp == ',') {
|
||||||
unit[count]=0;
|
unit[count] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
unit[count]=*cp++;
|
unit[count] = *cp++;
|
||||||
}
|
}
|
||||||
cp++;
|
cp++;
|
||||||
|
|
||||||
for (count=0;count<sizeof(jname);count++) {
|
for (count = 0; count < sizeof(jname); count++) {
|
||||||
if (*cp==',') {
|
if (*cp == ',') {
|
||||||
jname[count]=0;
|
jname[count] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
jname[count]=*cp++;
|
jname[count] = *cp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
cp++;
|
cp++;
|
||||||
|
|
||||||
if (!mid) {
|
if (!mid) {
|
||||||
uint8_t dp=atoi(cp)&0xf;
|
uint8_t dp = atoi(cp) & 0xf;
|
||||||
dtostrfd(meter_vars[index],dp,tpowstr);
|
dtostrfd(meter_vars[index], dp, tpowstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json) {
|
if (json) {
|
||||||
@ -2502,14 +2568,14 @@ void SML_Show(boolean json) {
|
|||||||
//AddLog(LOG_LEVEL_INFO, PSTR("not yet valid line %d"), index);
|
//AddLog(LOG_LEVEL_INFO, PSTR("not yet valid line %d"), index);
|
||||||
//}
|
//}
|
||||||
// json export
|
// json export
|
||||||
if (index==0) {
|
if (index == 0) {
|
||||||
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s,\"%s\":{\"%s\":%s", b_mqtt_data,meter_desc_p[mindex].prefix,jname,tpowstr);
|
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s,\"%s\":{\"%s\":%s", b_mqtt_data,meter_desc_p[mindex].prefix,jname,tpowstr);
|
||||||
if (!nojson) {
|
if (!nojson) {
|
||||||
ResponseAppend_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (lastmind!=mindex) {
|
if (lastmind != mindex) {
|
||||||
// meter changed, close mqtt
|
// meter changed, close mqtt
|
||||||
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s}", b_mqtt_data);
|
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s}", b_mqtt_data);
|
||||||
if (!nojson) {
|
if (!nojson) {
|
||||||
@ -2518,13 +2584,13 @@ void SML_Show(boolean json) {
|
|||||||
// and open new
|
// and open new
|
||||||
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s,\"%s\":{\"%s\":%s", b_mqtt_data,meter_desc_p[mindex].prefix,jname,tpowstr);
|
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s,\"%s\":{\"%s\":%s", b_mqtt_data,meter_desc_p[mindex].prefix,jname,tpowstr);
|
||||||
if (!nojson) {
|
if (!nojson) {
|
||||||
ResponseAppend_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);
|
||||||
}
|
}
|
||||||
lastmind=mindex;
|
lastmind = mindex;
|
||||||
} else {
|
} else {
|
||||||
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s,\"%s\":%s", b_mqtt_data,jname,tpowstr);
|
//snprintf_P(b_mqtt_data, sizeof(b_mqtt_data), "%s,\"%s\":%s", b_mqtt_data,jname,tpowstr);
|
||||||
if (!nojson) {
|
if (!nojson) {
|
||||||
ResponseAppend_P(PSTR(",\"%s\":%s"),jname,tpowstr);
|
ResponseAppend_P(PSTR(",\"%s\":%s"), jname, tpowstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2532,11 +2598,11 @@ 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);
|
||||||
if (strcmp(name,"*")) 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (index<SML_MAX_VARS-1) {
|
if (index < SML_MAX_VARS - 1) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
// next section
|
// next section
|
||||||
@ -2631,8 +2697,8 @@ uint32_t debounce_time;
|
|||||||
|
|
||||||
uint32_t SML_getlinelen(char *lp) {
|
uint32_t SML_getlinelen(char *lp) {
|
||||||
uint32_t cnt;
|
uint32_t cnt;
|
||||||
for (cnt=0; cnt<SML_SRCBSIZE-1; cnt++) {
|
for (cnt = 0; cnt < SML_SRCBSIZE - 1; cnt++) {
|
||||||
if (lp[cnt]==SCRIPT_EOL) {
|
if (lp[cnt] == SCRIPT_EOL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2640,27 +2706,27 @@ uint32_t cnt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SML_getscriptsize(char *lp) {
|
uint32_t SML_getscriptsize(char *lp) {
|
||||||
uint32_t mlen=0;
|
uint32_t mlen = 0;
|
||||||
char dstbuf[SML_SRCBSIZE*2];
|
char dstbuf[SML_SRCBSIZE * 2];
|
||||||
while (1) {
|
while (1) {
|
||||||
Replace_Cmd_Vars(lp,1,dstbuf,sizeof(dstbuf));
|
Replace_Cmd_Vars(lp, 1, dstbuf, sizeof(dstbuf));
|
||||||
lp+=SML_getlinelen(lp)+1;
|
lp += SML_getlinelen(lp) + 1;
|
||||||
uint32_t slen=strlen(dstbuf);
|
uint32_t slen = strlen(dstbuf);
|
||||||
//AddLog(LOG_LEVEL_INFO, PSTR("%d - %s"),slen,dstbuf);
|
//AddLog(LOG_LEVEL_INFO, PSTR("%d - %s"),slen,dstbuf);
|
||||||
mlen+=slen+1;
|
mlen += slen + 1;
|
||||||
if (*lp=='#') break;
|
if (*lp == '#') break;
|
||||||
if (*lp=='>') break;
|
if (*lp == '>') break;
|
||||||
if (*lp==0) break;
|
if (*lp == 0) break;
|
||||||
}
|
}
|
||||||
//AddLog(LOG_LEVEL_INFO, PSTR("len=%d"),mlen);
|
//AddLog(LOG_LEVEL_INFO, PSTR("len=%d"),mlen);
|
||||||
return mlen+32;
|
return mlen + 32;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
uint32_t SML_getscriptsize(char *lp) {
|
uint32_t SML_getscriptsize(char *lp) {
|
||||||
uint32_t mlen=0;
|
uint32_t mlen = 0;
|
||||||
for (uint32_t cnt=0;cnt<METER_DEF_SIZE-1;cnt++) {
|
for (uint32_t cnt = 0; cnt < METER_DEF_SIZE - 1; cnt++) {
|
||||||
if (lp[cnt]=='\n' && lp[cnt+1]=='#') {
|
if (lp[cnt] == '\n' && lp[cnt + 1] == '#') {
|
||||||
mlen=cnt+3;
|
mlen = cnt + 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2711,19 +2777,19 @@ void SML_GetSpecOpt(char *cp, uint32_t mnum) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void SML_Init(void) {
|
void SML_Init(void) {
|
||||||
meters_used=METERS_USED;
|
meters_used = METERS_USED;
|
||||||
meter_desc_p=meter_desc;
|
meter_desc_p = meter_desc;
|
||||||
meter_p=meter;
|
meter_p = meter;
|
||||||
|
|
||||||
sml_desc_cnt=0;
|
sml_desc_cnt = 0;
|
||||||
|
|
||||||
for (uint32_t cnt=0;cnt<SML_MAX_VARS;cnt++) {
|
for (uint32_t cnt = 0; cnt < SML_MAX_VARS; cnt++) {
|
||||||
meter_vars[cnt]=0;
|
meter_vars[cnt] = 0;
|
||||||
dvalid[cnt]=0;
|
dvalid[cnt] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t cnt=0;cnt<MAX_METERS;cnt++) {
|
for (uint32_t cnt = 0; cnt < MAX_METERS; cnt++) {
|
||||||
meter_spos[cnt]=0;
|
meter_spos[cnt] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SML_SPECOPT
|
#ifdef USE_SML_SPECOPT
|
||||||
@ -2735,24 +2801,24 @@ void SML_Init(void) {
|
|||||||
|
|
||||||
#ifdef USE_SCRIPT
|
#ifdef USE_SCRIPT
|
||||||
|
|
||||||
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;
|
script_meter_desc[cnt].trxpin = -1;
|
||||||
|
|
||||||
if (meter_ss[cnt]) {
|
if (meter_ss[cnt]) {
|
||||||
delete meter_ss[cnt];
|
delete meter_ss[cnt];
|
||||||
meter_ss[cnt]=NULL;
|
meter_ss[cnt] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitRead(Settings->rule_enabled, 0)) {
|
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
|
||||||
if (script_meter) free(script_meter);
|
if (script_meter) free(script_meter);
|
||||||
script_meter = 0;
|
script_meter = 0;
|
||||||
@ -2781,23 +2847,23 @@ void SML_Init(void) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!*lp || *lp == '#' || *lp == '>') {
|
if (!*lp || *lp == '#' || *lp == '>') {
|
||||||
if (*(tp-1) == '|') *(tp-1) = 0;
|
if (*(tp - 1) == '|') *(tp - 1) = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*lp == '+') {
|
if (*lp == '+') {
|
||||||
// add descriptor +1,1,c,0,10,H20
|
// add descriptor +1,1,c,0,10,H20
|
||||||
//toLogEOL(">>",lp);
|
//toLogEOL(">>",lp);
|
||||||
lp++;
|
lp++;
|
||||||
index = *lp&7;
|
index = *lp & 7;
|
||||||
lp += 2;
|
lp += 2;
|
||||||
if (index < 1 || index > meters_used) {
|
if (index < 1 || index > meters_used) {
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("illegal meter number!"));
|
AddLog(LOG_LEVEL_INFO, PSTR("illegal meter number!"));
|
||||||
goto next_line;
|
goto next_line;
|
||||||
}
|
}
|
||||||
index--;
|
index--;
|
||||||
srcpin = strtol(lp,&lp,10);
|
srcpin = strtol(lp, &lp, 10);
|
||||||
if (Gpio_used(abs(srcpin))) {
|
if (Gpio_used(abs(srcpin))) {
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for RX in meter number %d"),abs(srcpin),index+1);
|
AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for RX in meter number %d"), abs(srcpin), index + 1);
|
||||||
dddef_exit:
|
dddef_exit:
|
||||||
if (script_meter) free(script_meter);
|
if (script_meter) free(script_meter);
|
||||||
script_meter = 0;
|
script_meter = 0;
|
||||||
@ -2852,7 +2918,7 @@ dddef_exit:
|
|||||||
lp++;
|
lp++;
|
||||||
script_meter_desc[index].trxpin = strtol(lp, &lp, 10);
|
script_meter_desc[index].trxpin = strtol(lp, &lp, 10);
|
||||||
if (Gpio_used(script_meter_desc[index].trxpin)) {
|
if (Gpio_used(script_meter_desc[index].trxpin)) {
|
||||||
AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for TX in meter number %d"),script_meter_desc[index].trxpin,index+1);
|
AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for TX in meter number %d"), script_meter_desc[index].trxpin, index + 1);
|
||||||
goto dddef_exit;
|
goto dddef_exit;
|
||||||
}
|
}
|
||||||
if (*lp != ',') goto next_line;
|
if (*lp != ',') goto next_line;
|
||||||
@ -3016,7 +3082,7 @@ dddef_exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
next_line:
|
next_line:
|
||||||
if (*lp==SCRIPT_EOL) {
|
if (*lp == SCRIPT_EOL) {
|
||||||
lp++;
|
lp++;
|
||||||
} else {
|
} else {
|
||||||
lp = strchr(lp, SCRIPT_EOL);
|
lp = strchr(lp, SCRIPT_EOL);
|
||||||
@ -3024,16 +3090,16 @@ next_line:
|
|||||||
lp++;
|
lp++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*tp=0;
|
*tp = 0;
|
||||||
meter_desc_p=script_meter_desc;
|
meter_desc_p = script_meter_desc;
|
||||||
meter_p=script_meter;
|
meter_p = script_meter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
init10:
|
init10:
|
||||||
typedef void (*function)();
|
typedef void (*function)();
|
||||||
uint8_t cindex=0;
|
uint8_t cindex = 0;
|
||||||
// preloud counters
|
// preloud counters
|
||||||
for (byte i = 0; i < MAX_COUNTERS; i++) {
|
for (byte i = 0; i < MAX_COUNTERS; i++) {
|
||||||
RtcSettings.pulse_counter[i] = Settings->pulse_counter[i];
|
RtcSettings.pulse_counter[i] = Settings->pulse_counter[i];
|
||||||
@ -3078,7 +3144,7 @@ init10:
|
|||||||
} else {
|
} else {
|
||||||
// serial input, init
|
// serial input, init
|
||||||
#ifdef SPECIAL_SS
|
#ifdef SPECIAL_SS
|
||||||
if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M' || meter_desc_p[meters].type=='p' || meter_desc_p[meters].type=='R' || meter_desc_p[meters].type=='v') {
|
if (meter_desc_p[meters].type=='m' || meter_desc_p[meters].type=='M' || meter_desc_p[meters].type=='k' || meter_desc_p[meters].type=='p' || meter_desc_p[meters].type=='R' || meter_desc_p[meters].type=='v') {
|
||||||
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,0,TMSBSIZ);
|
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,0,TMSBSIZ);
|
||||||
} else {
|
} else {
|
||||||
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,1,TMSBSIZ);
|
meter_ss[meters] = new TasmotaSerial(meter_desc_p[meters].srcpin,meter_desc_p[meters].trxpin,1,1,TMSBSIZ);
|
||||||
@ -3198,7 +3264,7 @@ uint32_t SML_SetBaud(uint32_t meter, uint32_t br) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SML_Status(uint32_t meter) {
|
uint32_t SML_Status(uint32_t meter) {
|
||||||
if (meter<1 || meter>meters_used) return 0;
|
if (meter < 1 || meter > meters_used) return 0;
|
||||||
meter--;
|
meter--;
|
||||||
#if defined(ED300L) || defined(AS2020) || defined(DTZ541) || defined(USE_SML_SPECOPT)
|
#if defined(ED300L) || defined(AS2020) || defined(DTZ541) || defined(USE_SML_SPECOPT)
|
||||||
return sml_status[meter];
|
return sml_status[meter];
|
||||||
@ -3210,20 +3276,20 @@ uint32_t SML_Status(uint32_t meter) {
|
|||||||
|
|
||||||
|
|
||||||
uint32_t SML_Write(uint32_t meter,char *hstr) {
|
uint32_t SML_Write(uint32_t meter,char *hstr) {
|
||||||
if (meter<1 || meter>meters_used) return 0;
|
if (meter < 1 || meter > meters_used) return 0;
|
||||||
meter--;
|
meter--;
|
||||||
if (!meter_ss[meter]) return 0;
|
if (!meter_ss[meter]) return 0;
|
||||||
SML_Send_Seq(meter,hstr);
|
SML_Send_Seq(meter, hstr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t SML_Read(int32_t meter,char *str, uint32_t slen) {
|
uint32_t SML_Read(int32_t meter,char *str, uint32_t slen) {
|
||||||
uint8_t hflg=0;
|
uint8_t hflg = 0;
|
||||||
if (meter<0) {
|
if (meter < 0) {
|
||||||
meter=abs(meter);
|
meter = abs(meter);
|
||||||
hflg=1;
|
hflg = 1;
|
||||||
}
|
}
|
||||||
if (meter<1 || meter>meters_used) return 0;
|
if (meter < 1 || meter > meters_used) return 0;
|
||||||
meter--;
|
meter--;
|
||||||
if (!meter_ss[meter]) return 0;
|
if (!meter_ss[meter]) return 0;
|
||||||
|
|
||||||
@ -3231,26 +3297,26 @@ uint8_t hflg=0;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
smltbuf[meter][meter_spos[meter]]=0;
|
smltbuf[meter][meter_spos[meter]] = 0;
|
||||||
|
|
||||||
if (!hflg) {
|
if (!hflg) {
|
||||||
strlcpy(str,(char*)&smltbuf[meter][0],slen);
|
strlcpy(str, (char*)&smltbuf[meter][0], slen);
|
||||||
} else {
|
} else {
|
||||||
uint32_t index=0;
|
uint32_t index = 0;
|
||||||
for (uint32_t cnt=0; cnt<meter_spos[meter]; cnt++) {
|
for (uint32_t cnt = 0; cnt < meter_spos[meter]; cnt++) {
|
||||||
sprintf(str,"%02x",smltbuf[meter][cnt]);
|
sprintf(str,"%02x", smltbuf[meter][cnt]);
|
||||||
str+=2;
|
str += 2;
|
||||||
index+=2;
|
index += 2;
|
||||||
if (index>=slen-2) break;
|
if (index >= slen - 2) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
meter_spos[meter]=0;
|
meter_spos[meter] = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SML_GetVal(uint32_t index) {
|
float SML_GetVal(uint32_t index) {
|
||||||
if (index < 1 || index > SML_MAX_VARS) { index = 1;}
|
if (index < 1 || index > SML_MAX_VARS) { index = 1;}
|
||||||
return meter_vars[index-1];
|
return meter_vars[index - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
char *SML_GetSVal(uint32_t index) {
|
char *SML_GetSVal(uint32_t index) {
|
||||||
@ -3357,13 +3423,13 @@ uint32_t ctime = millis();
|
|||||||
#ifdef USE_SCRIPT
|
#ifdef USE_SCRIPT
|
||||||
char *SML_Get_Sequence(char *cp,uint32_t index) {
|
char *SML_Get_Sequence(char *cp,uint32_t index) {
|
||||||
if (!index) return cp;
|
if (!index) return cp;
|
||||||
uint32_t cindex=0;
|
uint32_t cindex = 0;
|
||||||
while (cp) {
|
while (cp) {
|
||||||
cp=strchr(cp,',');
|
cp = strchr(cp, ',');
|
||||||
if (cp) {
|
if (cp) {
|
||||||
cp++;
|
cp++;
|
||||||
cindex++;
|
cindex++;
|
||||||
if (cindex==index) {
|
if (cindex == index) {
|
||||||
return cp;
|
return cp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3385,13 +3451,13 @@ void SML_Check_Send(void) {
|
|||||||
script_meter_desc[cnt].script_str = 0;
|
script_meter_desc[cnt].script_str = 0;
|
||||||
} else {
|
} else {
|
||||||
//AddLog(LOG_LEVEL_INFO, PSTR("100 ms>> 2"),cp);
|
//AddLog(LOG_LEVEL_INFO, PSTR("100 ms>> 2"),cp);
|
||||||
if (script_meter_desc[cnt].max_index>1) {
|
if (script_meter_desc[cnt].max_index > 1) {
|
||||||
script_meter_desc[cnt].index++;
|
script_meter_desc[cnt].index++;
|
||||||
if (script_meter_desc[cnt].index >= script_meter_desc[cnt].max_index) {
|
if (script_meter_desc[cnt].index >= script_meter_desc[cnt].max_index) {
|
||||||
script_meter_desc[cnt].index = 0;
|
script_meter_desc[cnt].index = 0;
|
||||||
sml_desc_cnt++;
|
sml_desc_cnt++;
|
||||||
}
|
}
|
||||||
cp=SML_Get_Sequence(script_meter_desc[cnt].txmem,script_meter_desc[cnt].index);
|
cp = SML_Get_Sequence(script_meter_desc[cnt].txmem, script_meter_desc[cnt].index);
|
||||||
//SML_Send_Seq(cnt,cp);
|
//SML_Send_Seq(cnt,cp);
|
||||||
} else {
|
} else {
|
||||||
cp = script_meter_desc[cnt].txmem;
|
cp = script_meter_desc[cnt].txmem;
|
||||||
@ -3461,7 +3527,37 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
|
|||||||
slen++;
|
slen++;
|
||||||
if (slen >= sizeof(sbuff)-6) break; // leave space for checksum
|
if (slen >= sizeof(sbuff)-6) break; // leave space for checksum
|
||||||
}
|
}
|
||||||
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' || script_meter_desc[meter].type == 'k') {
|
||||||
|
if (script_meter_desc[meter].type == 'k') {
|
||||||
|
// kamstrup, append crc, cr
|
||||||
|
*ucp++ = 0;
|
||||||
|
*ucp++ = 0;
|
||||||
|
slen += 2;
|
||||||
|
uint16_t crc = KS_calculateCRC(sbuff, slen);
|
||||||
|
ucp -= 2;
|
||||||
|
*ucp++ = highByte(crc);
|
||||||
|
*ucp++ = lowByte(crc);
|
||||||
|
|
||||||
|
// now check for escapes
|
||||||
|
uint8_t ksbuff[24];
|
||||||
|
ucp = ksbuff;
|
||||||
|
*ucp++ = 0x80;
|
||||||
|
uint8_t klen = 1;
|
||||||
|
for (uint16_t cnt = 0; cnt < slen; cnt++) {
|
||||||
|
uint8_t iob = sbuff[cnt];
|
||||||
|
if ((iob == 0x80) || (iob == 0x40) || (iob == 0x0d) || (iob == 0x06) || (iob == 0x1b)) {
|
||||||
|
*ucp++ = 0x1b;
|
||||||
|
*ucp++ = iob ^= 0xff;
|
||||||
|
klen += 2;
|
||||||
|
} else {
|
||||||
|
*ucp++ = iob;
|
||||||
|
klen++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*ucp++ = 0xd;
|
||||||
|
slen = klen + 1;
|
||||||
|
memcpy(sbuff, ksbuff, slen);
|
||||||
|
} else {
|
||||||
if (!rflg) {
|
if (!rflg) {
|
||||||
*ucp++ = 0;
|
*ucp++ = 0;
|
||||||
*ucp++ = 2;
|
*ucp++ = 2;
|
||||||
@ -3473,6 +3569,8 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
|
|||||||
*ucp++ = highByte(crc);
|
*ucp++ = highByte(crc);
|
||||||
slen += 2;
|
slen += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if (script_meter_desc[meter].type == 'o') {
|
if (script_meter_desc[meter].type == 'o') {
|
||||||
for (uint32_t cnt = 0; cnt < slen; cnt++) {
|
for (uint32_t cnt = 0; cnt < slen; cnt++) {
|
||||||
sbuff[cnt] |= (CalcEvenParity(sbuff[cnt]) << 7);
|
sbuff[cnt] |= (CalcEvenParity(sbuff[cnt]) << 7);
|
||||||
@ -3487,18 +3585,28 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
|
|||||||
*ucp++ = SML_PzemCrc(sbuff, 6);
|
*ucp++ = SML_PzemCrc(sbuff, 6);
|
||||||
slen += 6;
|
slen += 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meter_ss[meter]->flush();
|
||||||
meter_ss[meter]->write(sbuff, slen);
|
meter_ss[meter]->write(sbuff, slen);
|
||||||
if (dump2log) {
|
if (dump2log) {
|
||||||
#ifdef SML_DUMP_OUT_ALL
|
#ifdef SML_DUMP_OUT_ALL
|
||||||
Hexdump(sbuff, slen);
|
Hexdump(sbuff, slen);
|
||||||
#else
|
#else
|
||||||
uint8_t type = meter_desc_p[(dump2log&7) - 1].type;
|
uint8_t type = meter_desc_p[(dump2log&7) - 1].type;
|
||||||
if (type == 'm' || type == 'M') {
|
if (type == 'm' || type == 'M' || type == 'k') {
|
||||||
Hexdump(sbuff, slen);
|
Hexdump(sbuff, slen);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODBUS_DEBUG
|
||||||
|
uint8_t type = script_meter_desc[meter].type;
|
||||||
|
if (!dump2log && (type == 'm' || type == 'M' || type == 'k')) {
|
||||||
|
AddLog(LOG_LEVEL_INFO, PSTR("transmit index >> %d"),meter_desc_p[meter].index);
|
||||||
|
Hexdump(sbuff, slen);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif // USE_SCRIPT
|
#endif // USE_SCRIPT
|
||||||
|
|
||||||
@ -3520,6 +3628,27 @@ uint16_t MBUS_calculateCRC(uint8_t *frame, uint8_t num, uint16_t start) {
|
|||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t KS_calculateCRC(const uint8_t *frame, uint8_t num) {
|
||||||
|
uint32_t crc = 0;
|
||||||
|
for (uint32_t i = 0; i < num; i++) {
|
||||||
|
uint8_t mask = 0x80;
|
||||||
|
uint8_t iob = frame[i];
|
||||||
|
while (mask) {
|
||||||
|
crc <<= 1;
|
||||||
|
if (iob & mask) {
|
||||||
|
crc |= 1;
|
||||||
|
}
|
||||||
|
mask >>= 1;
|
||||||
|
if (crc & 0x10000) {
|
||||||
|
crc &= 0xffff;
|
||||||
|
crc ^= 0x1021;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) {
|
uint8_t SML_PzemCrc(uint8_t *data, uint8_t len) {
|
||||||
uint16_t crc = 0;
|
uint16_t crc = 0;
|
||||||
for (uint32_t i = 0; i < len; i++) crc += *data++;
|
for (uint32_t i = 0; i < len; i++) crc += *data++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user