mirror of https://github.com/arendst/Tasmota.git
modbus tcp, uart select (#18038)
This commit is contained in:
parent
29ae903f67
commit
c752610bb7
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue