modbus tcp, uart select (#18038)

This commit is contained in:
gemu 2023-02-25 09:58:33 +01:00 committed by GitHub
parent 29ae903f67
commit c752610bb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 275 additions and 107 deletions

View File

@ -32,7 +32,6 @@
//#define DEBUG_CNT_LED1 2
//#define DEBUG_CNT_LED1 2
#include <TasmotaSerial.h>
@ -81,6 +80,16 @@
#define USE_SML_DECRYPT
#endif
#ifndef NO_USE_SML_TCP
// modbus over TCP
#define USE_SML_TCP
#endif
#ifndef NO_SML_OBIS_LINE
// obis in line mode
#define SML_OBIS_LINE
#endif
// median filter eliminates outliers, but uses much RAM and CPU cycles
// 672 bytes extra RAM with SML_MAX_VARS = 16
// default compile on, but must be enabled by descriptor flag 16
@ -132,6 +141,10 @@ needs USE_SML_AUTHKEY
synchronisation timout in milliseconds, after no serial data within this
time serial pointer is reset to zero
7:
on esp32 the uart index may be set, normally it is allocated from 2 down to 0 automatically
thus you can combine serial SML with serial script , berry or serial drivers.
*/
//#define MODBUS_DEBUG
@ -409,7 +422,8 @@ struct METER_DESC {
uint8_t so_bpos1;
uint8_t so_fcode2;
uint8_t so_bpos2;
#endif
#endif // USE_SML_SPECOPT
#ifdef ESP32
#ifndef USE_ESP32_SW_SERIAL
HardwareSerial *meter_ss;
@ -417,10 +431,12 @@ struct METER_DESC {
SML_ESP32_SERIAL *meter_ss;
#endif
#endif // ESP32
// software serial pointers
#ifdef ESP8266
TasmotaSerial *meter_ss;
#endif // ESP8266
#ifdef USE_SML_DECRYPT
bool use_crypt = false;
uint8_t last_iob;
@ -428,11 +444,26 @@ struct METER_DESC {
Han_Parser *hp;
#ifdef USE_SML_AUTHKEY
uint8_t auth[SML_CRYPT_SIZE];
#endif // USE_SML_AUTHKEY
#endif // USE_SML_DECRYPT
#ifdef USE_SML_TCP
IPAddress ip_addr;
#ifdef TCP_CLIENT_SECURE
WiFiClientSecure *client;
#else
WiFiClient *client;
#endif
#ifdef ESP32
int8_t uart_index;
#endif
#endif
};
#define TCP_MODE_FLG 0x7f
struct METER_DESC meter_desc[MAX_METERS];
@ -573,22 +604,37 @@ double sml_median(struct SML_MEDIAN_FILTER* mf, double in) {
uint16_t Serial_available() {
uint8_t num = sml_globs.dump2log & 7;
if (num < 1 || num > sml_globs.meters_used) num = 1;
if (!meter_desc[num - 1].meter_ss) return 0;
return meter_desc[num - 1].meter_ss->available();
num--;
if (meter_desc[num].srcpin != TCP_MODE_FLG) {
if (!meter_desc[num].meter_ss) return 0;
return meter_desc[num].meter_ss->available();
} else {
return meter_desc[num].client->available();
}
}
uint8_t Serial_read() {
uint8_t num = sml_globs.dump2log & 7;
if (num < 1 || num > sml_globs.meters_used) num = 1;
if (!meter_desc[num - 1].meter_ss) return 0;
return meter_desc[num - 1].meter_ss->read();
num--;
if (meter_desc[num].srcpin != TCP_MODE_FLG) {
if (!meter_desc[num].meter_ss) return 0;
return meter_desc[num].meter_ss->read();
} else {
return meter_desc[num].client->read();
}
}
uint8_t Serial_peek() {
uint8_t num = sml_globs.dump2log & 7;
if (num < 1 || num > sml_globs.meters_used) num = 1;
if (!meter_desc[num - 1].meter_ss) return 0;
return meter_desc[num - 1].meter_ss->peek();
num--;
if (meter_desc[num].srcpin != TCP_MODE_FLG) {
if (!meter_desc[num].meter_ss) return 0;
return meter_desc[num].meter_ss->peek();
} else {
return meter_desc[num].client->peek();
}
}
void sml_dump_start(char c) {
@ -599,7 +645,7 @@ void sml_dump_start(char c) {
#define SML_EBUS_SKIP_SYNC_DUMPS
uint8_t *hdlc_decode(struct METER_DESC *mp, uint16_t *size);
void dump2log(void) {
int16_t index = 0, hcnt = 0;
@ -1206,7 +1252,13 @@ void sml_shift_in(uint32_t meters, uint32_t shard) {
mp->sbuff[count] = mp->sbuff[count + 1];
}
}
uint8_t iob = (uint8_t)mp->meter_ss->read();
uint8_t iob;
if (mp->srcpin != TCP_MODE_FLG) {
iob = (uint8_t)mp->meter_ss->read();
} else {
iob = (uint8_t)mp->client->read();
}
switch (mp->type) {
case 'o':
@ -1289,6 +1341,20 @@ void sml_shift_in(uint32_t meters, uint32_t shard) {
if (mp->spos >= mp->sbsiz) {
mp->spos = 0;
}
if (mp->srcpin == TCP_MODE_FLG) {
// tcp read
if (mp->spos >= 6) {
uint8_t tlen = (mp->sbuff[4] << 8) | mp->sbuff[5];
if (mp->spos == 6 + tlen) {
mp->spos = 0;
SML_Decode(meters);
mp->client->flush();
//Hexdump(mp->sbuff + 6, 10);
}
}
break;
}
if (mp->spos >= 3) {
uint32_t mlen = mp->sbuff[2] + 5;
if (mlen > mp->sbsiz) mlen = mp->sbsiz;
@ -1369,23 +1435,24 @@ void SML_Poll(void) {
uint32_t meters;
for (meters = 0; meters < sml_globs.meters_used; meters++) {
if (sml_globs.mp[meters].type != 'c') {
// poll for serial input
if (!meter_desc[meters].meter_ss) continue;
if (sml_globs.ser_act_LED_pin != 255 && (sml_globs.ser_act_meter_num == 0 || sml_globs.ser_act_meter_num - 1 == meters)) {
digitalWrite(sml_globs.ser_act_LED_pin, meter_desc[meters].meter_ss->available() && !digitalRead(sml_globs.ser_act_LED_pin)); // Invert LED, if queue is continuously full
struct METER_DESC *mp = &meter_desc[meters];
if (mp->type != 'c') {
if (mp->srcpin != TCP_MODE_FLG) {
if (!mp->meter_ss) continue;
// poll for serial input
if (sml_globs.ser_act_LED_pin != 255 && (sml_globs.ser_act_meter_num == 0 || sml_globs.ser_act_meter_num - 1 == meters)) {
digitalWrite(sml_globs.ser_act_LED_pin, mp->meter_ss->available() && !digitalRead(sml_globs.ser_act_LED_pin)); // Invert LED, if queue is continuously full
}
while (mp->meter_ss->available()) {
sml_shift_in(meters, 0);
}
} else {
#ifdef USE_SML_TCP
while (mp->client->available()){
sml_shift_in(meters, 0);
}
#endif
}
while (meter_desc[meters].meter_ss->available()) {
sml_shift_in(meters, 0);
}
/*
if (meter_desc[meters].meter_ss->available()) {
sml_count++;
uint8_t iob = meter_desc[meters].meter_ss->read();
if (sml_count<5 || sml_count > 100) {
AddLog(LOG_LEVEL_INFO, PSTR(">> %02x - %d"),iob,sml_count);
}
}*/
}
}
}
@ -1656,6 +1723,11 @@ void SML_Decode(uint8_t index) {
double ebus_dval = 99;
double mbus_dval = 99;
while (*mp != '@') {
if (found == 0) {
// skip rest of decoder part
mp++;
continue;
}
if (sml_globs.mp[mindex].type == 'o' || sml_globs.mp[mindex].type == 'c') {
if (*mp++ != *cp++) {
found=0;
@ -2545,12 +2617,18 @@ struct METER_DESC *mp = &meter_desc[mnum];
mp->auth[cnt / 2] = (sml_hexnibble(cp[cnt]) << 4) | sml_hexnibble(cp[cnt + 1]);
}
break;
#endif // USE_SML_AUTHKEY
#endif // USE_SML_DECRYPT
case '6':
cp += 2;
mp->tout_ms = strtol(cp, &cp, 10);
break;
case '7':
cp += 2;
#ifdef ESP32
mp->uart_index = strtol(cp, &cp, 10);
#endif // ESP32
break;
#endif
#endif
}
return cp;
}
@ -2630,6 +2708,10 @@ void reset_sml_vars(uint16_t maxmeters) {
mp->lastms = millis();
mp->tout_ms = SML_STIMEOUT;
#ifdef ESP32
mp->uart_index = -1;
#endif
#ifdef USE_SML_DECRYPT
if (mp->use_crypt) {
if (mp->hp) {
@ -2707,8 +2789,13 @@ void SML_Init(void) {
uint32_t mlen;
uint16_t memory = 0;
#ifdef ESP32
uint32_t uart_index = SOC_UART_NUM - 1;
#endif
sml_globs.sml_send_blocks = 0;
lp = glob_script_mem.section_ptr;
struct METER_DESC *mmp;
while (lp) {
if (!section) {
if (*lp == '>' && *(lp + 1) == 'M') {
@ -2741,93 +2828,115 @@ void SML_Init(void) {
goto next_line;
}
index--;
srcpin = strtol(lp, &lp, 10);
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);
mmp = &meter_desc[index];
if (*lp == '[') {
// sign TCP mode
srcpin = TCP_MODE_FLG;
lp++;
char str[32];
uint8_t cnt;
for (cnt = 0; cnt < sizeof(str) - 1; cnt++) {
if (!*lp || *lp == '\n' || *lp == ']') {
break;
}
str[cnt] = *lp++;
}
str[cnt] = 0;
lp++;
#ifdef USE_SML_TCP
mmp->ip_addr.fromString(str);
#endif
} else {
srcpin = strtol(lp, &lp, 10);
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);
dddef_exit:
if (sml_globs.script_meter) free(sml_globs.script_meter);
sml_globs.script_meter = 0;
return;
if (sml_globs.script_meter) free(sml_globs.script_meter);
sml_globs.script_meter = 0;
return;
}
}
meter_desc[index].srcpin = srcpin;
mmp->srcpin = srcpin;
if (*lp != ',') goto next_line;
lp++;
meter_desc[index].type = *lp;
mmp->type = *lp;
lp++;
if (*lp != ',') {
switch (*lp) {
case 'N':
lp++;
meter_desc[index].sopt = 0x10 | (*lp & 3);
mmp->sopt = 0x10 | (*lp & 3);
lp++;
break;
case 'E':
lp++;
meter_desc[index].sopt = 0x20 | (*lp & 3);
mmp->sopt = 0x20 | (*lp & 3);
lp++;
break;
case 'O':
lp++;
meter_desc[index].sopt = 0x30 | (*lp & 3);
mmp->sopt = 0x30 | (*lp & 3);
lp++;
break;
default:
meter_desc[index].sopt = *lp&7;
mmp->sopt = *lp&7;
lp++;
}
} else {
meter_desc[index].sopt = 0;
mmp->sopt = 0;
}
lp++;
meter_desc[index].flag = strtol(lp, &lp, 10);
mmp->flag = strtol(lp, &lp, 10);
if (*lp != ',') goto next_line;
lp++;
meter_desc[index].params = strtol(lp, &lp, 10);
mmp->params = strtol(lp, &lp, 10);
if (*lp != ',') goto next_line;
lp++;
meter_desc[index].prefix[7] = 0;
mmp->prefix[7] = 0;
for (uint32_t cnt = 0; cnt < 8; cnt++) {
if (*lp == SCRIPT_EOL || *lp == ',') {
meter_desc[index].prefix[cnt] = 0;
mmp->prefix[cnt] = 0;
break;
}
meter_desc[index].prefix[cnt] = *lp++;
mmp->prefix[cnt] = *lp++;
}
if (*lp == ',') {
lp++;
// get TRX pin
meter_desc[index].trxpin = strtol(lp, &lp, 10);
if (Gpio_used(meter_desc[index].trxpin)) {
AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for TX in meter number %d"), meter_desc[index].trxpin, index + 1);
goto dddef_exit;
mmp->trxpin = strtol(lp, &lp, 10);
if (mmp->srcpin != TCP_MODE_FLG) {
if (Gpio_used(mmp->trxpin)) {
AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for TX in meter number %d"), meter_desc[index].trxpin, index + 1);
goto dddef_exit;
}
}
// optional transmit enable pin
if (*lp == '(') {
lp++;
if (*lp == 'i') {
lp++;
meter_desc[index].trx_en.trxenpol = 1;
mmp->trx_en.trxenpol = 1;
} else {
meter_desc[index].trx_en.trxenpol = 0;
mmp->trx_en.trxenpol = 0;
}
meter_desc[index].trx_en.trxenpin = strtol(lp, &lp, 10);
mmp->trx_en.trxenpin = strtol(lp, &lp, 10);
if (*lp != ')') {
goto dddef_exit;
}
lp++;
if (Gpio_used(meter_desc[index].trx_en.trxenpin)) {
if (Gpio_used(mmp->trx_en.trxenpin)) {
AddLog(LOG_LEVEL_INFO, PSTR("SML: Error: Duplicate GPIO %d defined. Not usable for TX enable in meter number %d"), meter_desc[index].trx_en.trxenpin, index + 1);
goto dddef_exit;
}
meter_desc[index].trx_en.trxen = 1;
pinMode(meter_desc[index].trx_en.trxenpin, OUTPUT);
digitalWrite(meter_desc[index].trx_en.trxenpin, meter_desc[index].trx_en.trxenpol);
mmp->trx_en.trxen = 1;
pinMode(mmp->trx_en.trxenpin, OUTPUT);
digitalWrite(mmp->trx_en.trxenpin, mmp->trx_en.trxenpol);
} else {
meter_desc[index].trx_en.trxen = 0;
mmp->trx_en.trxen = 0;
}
if (*lp != ',') goto next_line;
lp++;
meter_desc[index].tsecs = strtol(lp, &lp, 10);
mmp->tsecs = strtol(lp, &lp, 10);
if (*lp == ',') {
lp++;
// look ahead
@ -2851,9 +2960,9 @@ dddef_exit:
txlen++;
}
if (txlen) {
meter_desc[index].txmem = (char*)calloc(txlen + 2, 1);
mmp->txmem = (char*)calloc(txlen + 2, 1);
memory += txlen + 2;
if (meter_desc[index].txmem) {
if (mmp->txmem) {
// now copy send blocks
char *txp = lp;
uint16_t tind = 0;
@ -2861,14 +2970,14 @@ dddef_exit:
if (*txp == SCRIPT_EOL) {
txp++;
} else {
meter_desc[index].txmem[tind] = *txp++;
mmp->txmem[tind] = *txp++;
tind++;
}
}
}
//AddLog(LOG_LEVEL_INFO, PSTR(">>> %s - %d"), meter_desc[index].txmem, txlen);
meter_desc[index].index = 0;
meter_desc[index].max_index = tx_entries;
mmp->index = 0;
mmp->max_index = tx_entries;
sml_globs.sml_send_blocks++;
lp += txlen;
}
@ -2948,28 +3057,27 @@ next_line:
RtcSettings.pulse_counter[i] = Settings->pulse_counter[i];
sml_counters[i].sml_cnt_last_ts = millis();
}
#ifdef ESP32
uint32_t uart_index = SOC_UART_NUM - 1;
#endif
sml_counter_pinstate = 0;
for (uint8_t meters = 0; meters < sml_globs.meters_used; meters++) {
if (sml_globs.mp[meters].type == 'c') {
if (sml_globs.mp[meters].flag & 2) {
METER_DESC *mp = &meter_desc[meters];
if (mp->type == 'c') {
if (mp->flag & 2) {
} else {
// counters, set to input with pullup
if (sml_globs.mp[meters].flag & 1) {
pinMode(sml_globs.mp[meters].srcpin, INPUT_PULLUP);
if (mp->flag & 1) {
pinMode(mp->srcpin, INPUT_PULLUP);
} else {
pinMode(sml_globs.mp[meters].srcpin, INPUT);
pinMode(mp->srcpin, INPUT);
}
// check for irq mode
if (sml_globs.mp[meters].params <= 0) {
if (mp->params <= 0) {
// init irq mode
sml_counters[cindex].sml_cnt_old_state = meters;
sml_counters[cindex].sml_debounce = -sml_globs.mp[meters].params;
attachInterruptArg(sml_globs.mp[meters].srcpin, SML_CounterIsr, &sml_cnt_index[cindex], CHANGE);
if (digitalRead(sml_globs.mp[meters].srcpin) > 0) {
attachInterruptArg(mp->srcpin, SML_CounterIsr, &sml_cnt_index[cindex], CHANGE);
if (digitalRead(mp->srcpin) > 0) {
sml_counter_pinstate |= (1 << cindex);
}
sml_counters[cindex].sml_counter_ltime = millis();
@ -2981,86 +3089,108 @@ next_line:
}
} else {
// serial input, init
if (mp->srcpin == TCP_MODE_FLG) {
#ifdef USE_SML_TCP
// tcp mode
#ifdef TCP_CLIENT_SECURE
mp->client = new WiFiClientSecure;
//client(new BearSSL::WiFiClientSecure_light(1024,1024)) {
mp->client->setInsecure();
#else
mp->client = new WiFiClient;
#endif
int32_t err = mp->client->connect(mp->ip_addr, mp->params);
if (!err) {
AddLog(LOG_LEVEL_INFO, PSTR("SML: could not connect TCP to %s:%d"),mp->ip_addr.toString().c_str(), mp->params);
}
#endif
} else {
// serial mode
#ifdef ESP8266
#ifdef SPECIAL_SS
char type = sml_globs.mp[meters].type;
char type = mp->type;
if (type == 'm' || type == 'M' || type == 'k' || type == 'p' || type == 'R' || type == 'v') {
meter_desc[meters].meter_ss = new TasmotaSerial(sml_globs.mp[meters].srcpin,sml_globs.mp[meters].trxpin, 1, 0, meter_desc[meters].sibsiz);
mp->meter_ss = new TasmotaSerial(mp->srcpin, mp->trxpin, 1, 0, mp->sibsiz);
} else {
meter_desc[meters].meter_ss = new TasmotaSerial(sml_globs.mp[meters].srcpin,sml_globs.mp[meters].trxpin, 1, 1, meter_desc[meters].sibsiz);
mp->meter_ss = new TasmotaSerial(mp->srcpin, mp->trxpin, 1, 1, mp->sibsiz);
}
#else
meter_desc[meters].meter_ss = new TasmotaSerial(sml_globs.mp[meters].srcpin,sml_globs.mp[meters].trxpin, 1, 0, meter_desc[meters].sibsiz);
mp->meter_ss = new TasmotaSerial(mp->srcpin, mp->trxpin, 1, 0, mp->sibsiz);
#endif // SPECIAL_SS
#endif // ESP8266
#ifdef ESP32
// use hardware serial
if (mp->uart_index >= 0) {
uart_index = mp->uart_index;
}
AddLog(LOG_LEVEL_INFO, PSTR("SML: uart used: %d"),uart_index);
#ifdef USE_ESP32_SW_SERIAL
meter_desc[meters].meter_ss = new SML_ESP32_SERIAL(uart_index);
if (sml_globs.mp[meters].srcpin >= 0) {
mp->meter_ss = new SML_ESP32_SERIAL(uart_index);
if (mp->srcpin >= 0) {
if (uart_index == 0) { ClaimSerial(); }
uart_index--;
if (uart_index < 0) uart_index = 0;
}
#else
meter_desc[meters].meter_ss = new HardwareSerial(uart_index);
mp->meter_ss = new HardwareSerial(uart_index);
if (uart_index == 0) { ClaimSerial(); }
uart_index--;
if (uart_index < 0) uart_index = 0;
meter_desc[meters].meter_ss->setRxBufferSize(meter_desc[meters].sibsiz);
mp->meter_ss->setRxBufferSize(mp->sibsiz);
#endif // USE_ESP32_SW_SERIAL
#endif // ESP32
SerialConfig smode = SERIAL_8N1;
if (sml_globs.mp[meters].sopt & 0xf0) {
if (mp->sopt & 0xf0) {
// new serial config
switch (sml_globs.mp[meters].sopt >> 4) {
switch (mp->sopt >> 4) {
case 1:
if ((sml_globs.mp[meters].sopt & 1) == 1) smode = SERIAL_8N1;
if ((mp->sopt & 1) == 1) smode = SERIAL_8N1;
else smode = SERIAL_8N2;
break;
case 2:
if ((sml_globs.mp[meters].sopt & 1) == 1) smode = SERIAL_8E1;
if ((mp->sopt & 1) == 1) smode = SERIAL_8E1;
else smode = SERIAL_8E2;
break;
case 3:
if ((sml_globs.mp[meters].sopt & 1) == 1) smode = SERIAL_8O1;
if ((mp->sopt & 1) == 1) smode = SERIAL_8O1;
else smode = SERIAL_8O2;
break;
}
} else {
// deprecated serial config
if (sml_globs.mp[meters].sopt == 2) {
if (mp->sopt == 2) {
smode = SERIAL_8N2;
}
if (sml_globs.mp[meters].type=='M') {
if (mp->type=='M') {
smode = SERIAL_8E1;
if (sml_globs.mp[meters].sopt == 2) {
if (mp->sopt == 2) {
smode = SERIAL_8E2;
}
}
}
#ifdef ESP8266
if (meter_desc[meters].meter_ss->begin(sml_globs.mp[meters].params)) {
meter_desc[meters].meter_ss->flush();
if (mp->meter_ss->begin(mp->params)) {
mp->meter_ss->flush();
}
if (meter_desc[meters].meter_ss->hardwareSerial()) {
Serial.begin(sml_globs.mp[meters].params, smode);
if (mp->meter_ss->hardwareSerial()) {
Serial.begin(mp->params, smode);
ClaimSerial();
//Serial.setRxBufferSize(512);
}
#endif // ESP8266
#ifdef ESP32
meter_desc[meters].meter_ss->begin(sml_globs.mp[meters].params, smode, sml_globs.mp[meters].srcpin, sml_globs.mp[meters].trxpin);
mp->meter_ss->begin(mp->params, smode, mp->srcpin, mp->trxpin);
#ifdef USE_ESP32_SW_SERIAL
meter_desc[meters].meter_ss->setRxBufferSize(meter_desc[meters].sibsiz);
mp->meter_ss->setRxBufferSize(mp->sibsiz);
#endif
#endif // ESP32
}
}
}
@ -3439,8 +3569,43 @@ uint8_t sml_hexnibble(char chr) {
return rVal;
}
typedef struct {
uint16_t T_ID;
uint16_t P_ID;
uint16_t SIZE;
uint8_t U_ID;
uint8_t payload[8];
} MODBUS_TCP_HEADER;
uint16_t sml_swap(uint16_t in) {
return (in << 8) || in >> 8;
}
// send modbus TCP frame with payload
// given ip addr and port in baudrate
void sml_tcp_send(uint32_t meter, uint8_t *sbuff, uint16_t slen) {
MODBUS_TCP_HEADER tcph;
tcph.T_ID = sml_swap(0x1234);
tcph.P_ID = 0;
tcph.SIZE = sml_swap(6);
tcph.U_ID = *sbuff;
sbuff++;
for (uint8_t cnt = 0; cnt < slen - 3; cnt++) {
tcph.payload[cnt] = *sbuff++;
}
#ifdef USE_SML_TCP
// AddLog(LOG_LEVEL_INFO, PSTR("slen >> %d "),slen);
if (meter_desc[meter].client->connected()) {
meter_desc[meter].client->write((uint8_t*)&tcph, 7 + slen - 3);
}
#endif
}
// send sequence every N Seconds
void SML_Send_Seq(uint32_t meter,char *seq) {
void SML_Send_Seq(uint32_t meter, char *seq) {
uint8_t sbuff[48];
uint8_t *ucp = sbuff, slen = 0;
char *cp = seq;
@ -3517,16 +3682,19 @@ void SML_Send_Seq(uint32_t meter,char *seq) {
slen += 6;
}
if (meter_desc[meter].trx_en.trxen) {
digitalWrite(meter_desc[meter].trx_en.trxenpin, meter_desc[meter].trx_en.trxenpol ^ 1);
}
meter_desc[meter].meter_ss->flush();
meter_desc[meter].meter_ss->write(sbuff, slen);
if (meter_desc[meter].trx_en.trxen) {
// must wait for all data sent
if (meter_desc[meter].srcpin == TCP_MODE_FLG) {
sml_tcp_send(meter, sbuff, slen);
} else {
if (meter_desc[meter].trx_en.trxen) {
digitalWrite(meter_desc[meter].trx_en.trxenpin, meter_desc[meter].trx_en.trxenpol ^ 1);
}
meter_desc[meter].meter_ss->flush();
digitalWrite(meter_desc[meter].trx_en.trxenpin, meter_desc[meter].trx_en.trxenpol);
meter_desc[meter].meter_ss->write(sbuff, slen);
if (meter_desc[meter].trx_en.trxen) {
// must wait for all data sent
meter_desc[meter].meter_ss->flush();
digitalWrite(meter_desc[meter].trx_en.trxenpin, meter_desc[meter].trx_en.trxenpol);
}
}
if (sml_globs.dump2log) {