diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md index 2fe8fac75..4bb5447ad 100644 --- a/tasmota/CHANGELOG.md +++ b/tasmota/CHANGELOG.md @@ -1,5 +1,9 @@ ## Unreleased (development) +### 7.1.2.2 20191206 + +- Add command ``SerialConfig 0..23`` or ``SerialConfig 8N1`` to select Serial Config (#7108) + ### 7.1.2.1 20191206 - Add rule var ``%topic%`` (#5522) diff --git a/tasmota/i18n.h b/tasmota/i18n.h index 5de4b7a1d..dfa998474 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -285,6 +285,7 @@ #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_BAUDRATE "Baudrate" +#define D_CMND_SERIALCONFIG "SerialConfig" #define D_CMND_TEMPLATE "Template" #define D_JSON_NAME "NAME" #define D_JSON_GPIO "GPIO" diff --git a/tasmota/settings.h b/tasmota/settings.h index 554711cad..f464a24cb 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -269,9 +269,7 @@ struct SYSCFG { uint8_t free_1d6[10]; // 1D6 SysBitfield4 flag4; // 1E0 - - uint8_t free_1e4; // 1E4 - + uint8_t serial_config; // 1E4 uint8_t wifi_output_power; // 1E5 uint8_t shutter_accuracy; // 1E6 uint8_t mqttlog_level; // 1E7 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 9ca979b45..f6113be46 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -156,6 +156,23 @@ const char kWebColors[] PROGMEM = COLOR_BUTTON_TEXT "|" COLOR_BUTTON "|" COLOR_BUTTON_HOVER "|" COLOR_BUTTON_RESET "|" COLOR_BUTTON_RESET_HOVER "|" COLOR_BUTTON_SAVE "|" COLOR_BUTTON_SAVE_HOVER "|" COLOR_TIMER_TAB_TEXT "|" COLOR_TIMER_TAB_BACKGROUND "|" COLOR_TITLE_TEXT; +enum TasmotaSerialConfig { + TS_SERIAL_5N1, TS_SERIAL_6N1, TS_SERIAL_7N1, TS_SERIAL_8N1, + TS_SERIAL_5N2, TS_SERIAL_6N2, TS_SERIAL_7N2, TS_SERIAL_8N2, + TS_SERIAL_5E1, TS_SERIAL_6E1, TS_SERIAL_7E1, TS_SERIAL_8E1, + TS_SERIAL_5E2, TS_SERIAL_6E2, TS_SERIAL_7E2, TS_SERIAL_8E2, + TS_SERIAL_5O1, TS_SERIAL_6O1, TS_SERIAL_7O1, TS_SERIAL_8O1, + TS_SERIAL_5O2, TS_SERIAL_6O2, TS_SERIAL_7O2, TS_SERIAL_8O2 }; + +const uint8_t kTasmotaSerialConfig[] PROGMEM = { + SERIAL_5N1, SERIAL_6N1, SERIAL_7N1, SERIAL_8N1, + SERIAL_5N2, SERIAL_6N2, SERIAL_7N2, SERIAL_8N2, + SERIAL_5E1, SERIAL_6E1, SERIAL_7E1, SERIAL_8E1, + SERIAL_5E2, SERIAL_6E2, SERIAL_7E2, SERIAL_8E2, + SERIAL_5O1, SERIAL_6O1, SERIAL_7O1, SERIAL_8O1, + SERIAL_5O2, SERIAL_6O2, SERIAL_7O2, SERIAL_8O2 +}; + /*********************************************************************************************\ * RTC memory \*********************************************************************************************/ @@ -670,6 +687,7 @@ void SettingsDefaultSet2(void) // for (uint32_t i = 1; i < MAX_PULSETIMERS; i++) { Settings.pulse_timer[i] = 0; } // Serial + Settings.serial_config = TS_SERIAL_8N1; Settings.baudrate = APP_BAUDRATE / 300; Settings.sbaudrate = SOFT_BAUDRATE / 300; Settings.serial_delimiter = 0xff; @@ -1155,6 +1173,9 @@ void SettingsDelta(void) if (Settings.version < 0x07000004) { Settings.wifi_output_power = 170; } + if (Settings.version < 0x07010202) { + Settings.serial_config = TS_SERIAL_8N1; + } Settings.version = VERSION; SettingsSave(1); diff --git a/tasmota/support.ino b/tasmota/support.ino index 8ce7f2840..f44d14eb7 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -737,19 +737,50 @@ int GetStateNumber(char *state_text) return state_number; } +String GetSerialConfig(void) +{ + // Settings.serial_config layout + // b000000xx - 5, 6, 7 or 8 data bits + // b00000x00 - 1 or 2 stop bits + // b000xx000 - None, Even or Odd parity + + const char kParity[] = "NEOI"; + + char config[4]; + config[0] = '5' + (Settings.serial_config & 0x3); + config[1] = kParity[(Settings.serial_config >> 3) & 0x3]; + config[2] = '1' + ((Settings.serial_config >> 2) & 0x1); + config[3] = '\0'; + return String(config); +} + +void SetSerialBegin(uint32_t baudrate) +{ + if (seriallog_level) { + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Set Serial to %s %d bit/s"), GetSerialConfig().c_str(), baudrate); + delay(100); + } + Serial.flush(); + Serial.begin(baudrate, (SerialConfig)pgm_read_byte(kTasmotaSerialConfig + Settings.serial_config)); + delay(10); + Serial.println(); +} + +void SetSerialConfig(uint32_t serial_config) +{ + if (serial_config == Settings.serial_config) { return; } + if (serial_config > TS_SERIAL_8O2) { return; } + + Settings.serial_config = serial_config; + SetSerialBegin(Serial.baudRate()); +} + void SetSerialBaudrate(int baudrate) { Settings.baudrate = baudrate / 300; - if (Serial.baudRate() != baudrate) { - if (seriallog_level) { - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_SET_BAUDRATE_TO " %d"), baudrate); - } - delay(100); - Serial.flush(); - Serial.begin(baudrate, serial_config); - delay(10); - Serial.println(); - } + if (Serial.baudRate() == baudrate) { return; } + + SetSerialBegin(baudrate); } void ClaimSerial(void) diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index fe8640045..070409566 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -23,7 +23,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_SETOPTION "|" D_CMND_TEMPERATURE_RESOLUTION "|" D_CMND_HUMIDITY_RESOLUTION "|" D_CMND_PRESSURE_RESOLUTION "|" D_CMND_POWER_RESOLUTION "|" D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|" D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|" - D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" + D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" @@ -38,7 +38,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSetoption, &CmndTemperatureResolution, &CmndHumidityResolution, &CmndPressureResolution, &CmndPowerResolution, &CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution, &CmndModule, &CmndModules, &CmndGpio, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange, - &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, + &CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, @@ -1082,6 +1082,48 @@ void CmndBaudrate(void) ResponseCmndNumber(Settings.baudrate * 300); } +void CmndSerialConfig(void) +{ + // See TasmotaSerialConfig for possible options + // SerialConfig 0..23 where 3 equals 8N1 + // SerialConfig 8N1 + + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.data_len < 3) { // Use 0..23 as serial config option + if ((XdrvMailbox.payload >= TS_SERIAL_5N1) && (XdrvMailbox.payload <= TS_SERIAL_8O2)) { + SetSerialConfig(XdrvMailbox.payload); + } + } + else if ((XdrvMailbox.payload >= 5) && (XdrvMailbox.payload <= 8)) { + uint8_t serial_config = XdrvMailbox.payload -5; // Data bits 5, 6, 7 or 8, No parity and 1 stop bit + + bool valid = true; + char parity = (XdrvMailbox.data[1] & 0xdf); + if ('E' == parity) { + serial_config += 0x08; // Even parity + } + else if ('O' == parity) { + serial_config += 0x10; // Odd parity + } + else if ('N' != parity) { + valid = false; + } + + if ('2' == XdrvMailbox.data[2]) { + serial_config += 0x04; // Stop bits 2 + } + else if ('1' != XdrvMailbox.data[2]) { + valid = false; + } + + if (valid) { + SetSerialConfig(serial_config); + } + } + } + ResponseCmndChar(GetSerialConfig().c_str()); +} + void CmndSerialSend(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 5)) { diff --git a/tasmota/support_rtc.ino b/tasmota/support_rtc.ino index ffb7239a6..27ef66ec7 100644 --- a/tasmota/support_rtc.ino +++ b/tasmota/support_rtc.ino @@ -379,7 +379,9 @@ void RtcSecond(void) Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle } uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id - if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || (Rtc.ntp_sync_minute == uptime_minute))) || ntp_force_sync ) ) { + if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || // Never synced + (Rtc.ntp_sync_minute == uptime_minute))) || // Re-sync every hour + ntp_force_sync ) ) { // Forced sync Rtc.ntp_time = sntp_get_current_timestamp(); if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on) ntp_force_sync = false; diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index e10dfdb63..5cf0a430f 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -74,8 +74,6 @@ const char kCodeImage[] PROGMEM = "tasmota|minimal|sensors|knx|basic|display|ir" * Global variables \*********************************************************************************************/ -SerialConfig serial_config = SERIAL_8N1; // Serial interface configuration 8 data bits, No parity, 1 stop bit - WiFiUDP PortUdp; // UDP Syslog and Alexa unsigned long feature_drv1; // Compiled driver feature map diff --git a/tasmota/tasmota_version.h b/tasmota/tasmota_version.h index 7b2207950..929924840 100644 --- a/tasmota/tasmota_version.h +++ b/tasmota/tasmota_version.h @@ -20,6 +20,6 @@ #ifndef _TASMOTA_VERSION_H_ #define _TASMOTA_VERSION_H_ -const uint32_t VERSION = 0x07010201; +const uint32_t VERSION = 0x07010202; #endif // _TASMOTA_VERSION_H_ diff --git a/tasmota/xnrg_02_cse7766.ino b/tasmota/xnrg_02_cse7766.ino index 339d4fee2..d52ee9ca3 100644 --- a/tasmota/xnrg_02_cse7766.ino +++ b/tasmota/xnrg_02_cse7766.ino @@ -211,7 +211,7 @@ void CseDrvInit(void) { if ((3 == pin[GPIO_CSE7766_RX]) && (1 == pin[GPIO_CSE7766_TX])) { // As it uses 8E1 currently only hardware serial is supported baudrate = 4800; - serial_config = SERIAL_8E1; + Settings.serial_config = TS_SERIAL_8E1; if (0 == Settings.param[P_CSE7766_INVALID_POWER]) { Settings.param[P_CSE7766_INVALID_POWER] = CSE_MAX_INVALID_POWER; // SetOption39 1..255 }