mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 08:19:52 +03:00
merge with txmode2 branch
This commit is contained in:
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.9.0b2_web] 2019-08-11
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Merged with @susisstrolch's TxMode2 branch for improved support for sending EMS packages
|
||||||
|
|
||||||
## [1.9.0b1_web] 2019-08-02
|
## [1.9.0b1_web] 2019-08-02
|
||||||
|
|
||||||
### Breaking changes for first time use
|
### Breaking changes for first time use
|
||||||
|
|||||||
7862
doc/HT3-Bus_Telegramme.html
Normal file
7862
doc/HT3-Bus_Telegramme.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -210,6 +210,8 @@ void MyESP::_wifiCallback(justwifi_messages_t code, char * parameter) {
|
|||||||
// start OTA
|
// start OTA
|
||||||
ArduinoOTA.begin(); // moved to support esp32
|
ArduinoOTA.begin(); // moved to support esp32
|
||||||
myDebug_P(PSTR("[OTA] listening to %s.local:%u"), ArduinoOTA.getHostname().c_str(), OTA_PORT);
|
myDebug_P(PSTR("[OTA] listening to %s.local:%u"), ArduinoOTA.getHostname().c_str(), OTA_PORT);
|
||||||
|
// unconditionaly show the last reset reason
|
||||||
|
myDebug_P(PSTR("[SYSTEM] Last reset info: %s"), (char *)ESP.getResetInfo().c_str());
|
||||||
|
|
||||||
// MQTT Setup
|
// MQTT Setup
|
||||||
_mqtt_setup();
|
_mqtt_setup();
|
||||||
@@ -1111,9 +1113,10 @@ bool MyESP::_rtcmemStatus() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (reason) {
|
switch (reason) {
|
||||||
//case REASON_EXT_SYS_RST: // external system reset
|
//case REASON_EXT_SYS_RST: // external system reset
|
||||||
case REASON_WDT_RST: // hardware watch dog reset
|
case REASON_WDT_RST: // hardware watch dog reset
|
||||||
case REASON_DEFAULT_RST: // normal startup by power on
|
case REASON_DEFAULT_RST: // normal startup by power on
|
||||||
|
case REASON_SOFT_WDT_RST: // Software watchdog
|
||||||
readable = false;
|
readable = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -2565,7 +2568,7 @@ void MyESP::_bootupSequence() {
|
|||||||
|
|
||||||
if (isWifiConnected()) {
|
if (isWifiConnected()) {
|
||||||
_setSystemBootStatus(MYESP_BOOTSTATUS_BOOTED); // completed, reset flag
|
_setSystemBootStatus(MYESP_BOOTSTATUS_BOOTED); // completed, reset flag
|
||||||
digitalWrite(LED_BUILTIN, HIGH); // turn off LED
|
digitalWrite(LED_BUILTIN, HIGH); // turn off LED, 1=OFF with LED_BULLETIN
|
||||||
|
|
||||||
// write a log message if we're not using NTP, otherwise wait for the internet time to arrive
|
// write a log message if we're not using NTP, otherwise wait for the internet time to arrive
|
||||||
if (!_ntp_enabled) {
|
if (!_ntp_enabled) {
|
||||||
@@ -2617,13 +2620,15 @@ void MyESP::loop() {
|
|||||||
_systemCheckLoop();
|
_systemCheckLoop();
|
||||||
_heartbeatCheck();
|
_heartbeatCheck();
|
||||||
_bootupSequence(); // see if a reset was pressed during bootup
|
_bootupSequence(); // see if a reset was pressed during bootup
|
||||||
_telnetHandle(); // telnet
|
|
||||||
|
|
||||||
ESP.wdtFeed(); // TODO see if this helps with WDT resets
|
|
||||||
|
|
||||||
jw.loop(); // WiFi
|
jw.loop(); // WiFi
|
||||||
ArduinoOTA.handle(); // OTA
|
ArduinoOTA.handle(); // OTA
|
||||||
_mqttConnect(); // MQTT
|
|
||||||
|
ESP.wdtFeed(); // feed the watchdog...
|
||||||
|
_telnetHandle(); // telnet
|
||||||
|
ESP.wdtFeed(); // feed the watchdog...
|
||||||
|
|
||||||
|
_mqttConnect(); // MQTT
|
||||||
|
|
||||||
if (_timerequest) {
|
if (_timerequest) {
|
||||||
_timerequest = false;
|
_timerequest = false;
|
||||||
|
|||||||
@@ -135,20 +135,6 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row form-group">
|
|
||||||
<label class="col-xs-3">TX mode<i style="margin-left: 10px;" class="glyphicon glyphicon-info-sign"
|
|
||||||
aria-hidden="true" data-toggle="popover" data-trigger="hover" data-placement="right"
|
|
||||||
data-content="TX mode settings for various EMS brands"></i></label>
|
|
||||||
<span class="col-xs-9 col-md-5">
|
|
||||||
<select class="form-control input-sm" id="tx_mode">
|
|
||||||
<option selected="selected" value="0">0=EMS 1.0 (default)</option>
|
|
||||||
<option value="1">1=EMS+</option>
|
|
||||||
<option value="2">2=Generic (experimental!)</option>
|
|
||||||
<option value="3">3=Junkers</option>
|
|
||||||
</select>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-xs-9 col-md-8">
|
<div class="col-xs-9 col-md-8">
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ var custom_config = {
|
|||||||
"shower_timer": false,
|
"shower_timer": false,
|
||||||
"shower_alert": false,
|
"shower_alert": false,
|
||||||
"publish_time": 120,
|
"publish_time": 120,
|
||||||
"heating_circuit": 1,
|
"heating_circuit": 1
|
||||||
"tx_mode": 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,7 +23,6 @@ function listcustom() {
|
|||||||
document.getElementById("dallas_gpio").value = custom_config.settings.dallas_gpio;
|
document.getElementById("dallas_gpio").value = custom_config.settings.dallas_gpio;
|
||||||
document.getElementById("publish_time").value = custom_config.settings.publish_time;
|
document.getElementById("publish_time").value = custom_config.settings.publish_time;
|
||||||
document.getElementById("heating_circuit").value = custom_config.settings.heating_circuit;
|
document.getElementById("heating_circuit").value = custom_config.settings.heating_circuit;
|
||||||
document.getElementById("tx_mode").value = custom_config.settings.tx_mode;
|
|
||||||
|
|
||||||
if (custom_config.settings.led) {
|
if (custom_config.settings.led) {
|
||||||
$("input[name=\"led\"][value=\"1\"]").prop("checked", true);
|
$("input[name=\"led\"][value=\"1\"]").prop("checked", true);
|
||||||
@@ -74,7 +72,6 @@ function savecustom() {
|
|||||||
|
|
||||||
custom_config.settings.publish_time = parseInt(document.getElementById("publish_time").value);
|
custom_config.settings.publish_time = parseInt(document.getElementById("publish_time").value);
|
||||||
custom_config.settings.heating_circuit = parseInt(document.getElementById("heating_circuit").value);
|
custom_config.settings.heating_circuit = parseInt(document.getElementById("heating_circuit").value);
|
||||||
custom_config.settings.tx_mode = parseInt(document.getElementById("tx_mode").value);
|
|
||||||
|
|
||||||
custom_uncommited();
|
custom_uncommited();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ static const command_t project_cmds[] PROGMEM = {
|
|||||||
{true, "shower_alert <on | off>", "stop hot water to send 3 cold burst warnings after max shower time is exceeded"},
|
{true, "shower_alert <on | off>", "stop hot water to send 3 cold burst warnings after max shower time is exceeded"},
|
||||||
{true, "publish_time <seconds>", "set frequency for publishing data to MQTT (0=off)"},
|
{true, "publish_time <seconds>", "set frequency for publishing data to MQTT (0=off)"},
|
||||||
{true, "heating_circuit <1 | 2>", "set the main thermostat HC to work with (if using multiple heating circuits)"},
|
{true, "heating_circuit <1 | 2>", "set the main thermostat HC to work with (if using multiple heating circuits)"},
|
||||||
{true, "tx_mode <n>", "changes Tx logic. 0=ems 1.0, 1=ems+, 2=generic (experimental!), 3=HT3"},
|
|
||||||
|
|
||||||
{false, "info", "show current captured on the devices"},
|
{false, "info", "show current captured on the devices"},
|
||||||
{false, "log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
|
{false, "log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
|
||||||
@@ -417,6 +416,8 @@ void showInfo() {
|
|||||||
myDebug_P(PSTR(" System logging set to Thermostat only"));
|
myDebug_P(PSTR(" System logging set to Thermostat only"));
|
||||||
} else if (sysLog == EMS_SYS_LOGGING_SOLARMODULE) {
|
} else if (sysLog == EMS_SYS_LOGGING_SOLARMODULE) {
|
||||||
myDebug_P(PSTR(" System logging set to Solar Module only"));
|
myDebug_P(PSTR(" System logging set to Solar Module only"));
|
||||||
|
} else if (sysLog == EMS_SYS_LOGGING_JABBER) {
|
||||||
|
myDebug_P(PSTR(" System logging set to Jabber"));
|
||||||
} else {
|
} else {
|
||||||
myDebug_P(PSTR(" System logging set to None"));
|
myDebug_P(PSTR(" System logging set to None"));
|
||||||
}
|
}
|
||||||
@@ -1141,8 +1142,6 @@ bool LoadSaveCallback(MYESP_FSACTION action, JsonObject json) {
|
|||||||
EMSESP_Status.shower_alert = settings["shower_alert"];
|
EMSESP_Status.shower_alert = settings["shower_alert"];
|
||||||
EMSESP_Status.publish_time = settings["publish_time"] | DEFAULT_PUBLISHTIME;
|
EMSESP_Status.publish_time = settings["publish_time"] | DEFAULT_PUBLISHTIME;
|
||||||
|
|
||||||
ems_setTxMode(settings["tx_mode"]);
|
|
||||||
|
|
||||||
EMSESP_Status.listen_mode = settings["listen_mode"];
|
EMSESP_Status.listen_mode = settings["listen_mode"];
|
||||||
ems_setTxDisabled(EMSESP_Status.listen_mode);
|
ems_setTxDisabled(EMSESP_Status.listen_mode);
|
||||||
|
|
||||||
@@ -1164,7 +1163,6 @@ bool LoadSaveCallback(MYESP_FSACTION action, JsonObject json) {
|
|||||||
settings["shower_alert"] = EMSESP_Status.shower_alert;
|
settings["shower_alert"] = EMSESP_Status.shower_alert;
|
||||||
settings["publish_time"] = EMSESP_Status.publish_time;
|
settings["publish_time"] = EMSESP_Status.publish_time;
|
||||||
settings["heating_circuit"] = EMSESP_Status.heating_circuit;
|
settings["heating_circuit"] = EMSESP_Status.heating_circuit;
|
||||||
settings["tx_mode"] = ems_getTxMode();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1282,12 +1280,6 @@ bool SetListCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, co
|
|||||||
myDebug_P(PSTR("Error. Usage: set heating_circuit <1 | 2>"));
|
myDebug_P(PSTR("Error. Usage: set heating_circuit <1 | 2>"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tx delay/ tx mode
|
|
||||||
if (((strcmp(setting, "tx_mode") == 0) || (strcmp(setting, "tx_delay") == 0)) && (wc == 2)) {
|
|
||||||
ems_setTxMode(atoi(value));
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == MYESP_FSACTION_LIST) {
|
if (action == MYESP_FSACTION_LIST) {
|
||||||
@@ -1300,7 +1292,6 @@ bool SetListCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, co
|
|||||||
myDebug_P(PSTR(" shower_timer=%s"), EMSESP_Status.shower_timer ? "on" : "off");
|
myDebug_P(PSTR(" shower_timer=%s"), EMSESP_Status.shower_timer ? "on" : "off");
|
||||||
myDebug_P(PSTR(" shower_alert=%s"), EMSESP_Status.shower_alert ? "on" : "off");
|
myDebug_P(PSTR(" shower_alert=%s"), EMSESP_Status.shower_alert ? "on" : "off");
|
||||||
myDebug_P(PSTR(" publish_time=%d"), EMSESP_Status.publish_time);
|
myDebug_P(PSTR(" publish_time=%d"), EMSESP_Status.publish_time);
|
||||||
myDebug_P(PSTR(" tx_mode=%d"), ems_getTxMode());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
@@ -1437,6 +1428,9 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
|
|||||||
} else if (strcmp(second_cmd, "n") == 0) {
|
} else if (strcmp(second_cmd, "n") == 0) {
|
||||||
ems_setLogging(EMS_SYS_LOGGING_NONE);
|
ems_setLogging(EMS_SYS_LOGGING_NONE);
|
||||||
ok = true;
|
ok = true;
|
||||||
|
} else if (strcmp(second_cmd, "j") == 0) {
|
||||||
|
ems_setLogging(EMS_SYS_LOGGING_JABBER);
|
||||||
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
167
src/ems.cpp
167
src/ems.cpp
@@ -221,7 +221,7 @@ void ems_init() {
|
|||||||
EMS_Sys_Status.emsTxPkgs = 0;
|
EMS_Sys_Status.emsTxPkgs = 0;
|
||||||
EMS_Sys_Status.emxCrcErr = 0;
|
EMS_Sys_Status.emxCrcErr = 0;
|
||||||
EMS_Sys_Status.emsRxStatus = EMS_RX_STATUS_IDLE;
|
EMS_Sys_Status.emsRxStatus = EMS_RX_STATUS_IDLE;
|
||||||
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE;
|
EMS_Sys_Status.emsTxStatus = EMS_TX_REV_DETECT;
|
||||||
EMS_Sys_Status.emsRefreshed = false;
|
EMS_Sys_Status.emsRefreshed = false;
|
||||||
EMS_Sys_Status.emsPollEnabled = false; // start up with Poll disabled
|
EMS_Sys_Status.emsPollEnabled = false; // start up with Poll disabled
|
||||||
EMS_Sys_Status.emsBusConnected = false;
|
EMS_Sys_Status.emsBusConnected = false;
|
||||||
@@ -230,8 +230,8 @@ void ems_init() {
|
|||||||
EMS_Sys_Status.emsTxDisabled = false;
|
EMS_Sys_Status.emsTxDisabled = false;
|
||||||
EMS_Sys_Status.emsPollFrequency = 0;
|
EMS_Sys_Status.emsPollFrequency = 0;
|
||||||
EMS_Sys_Status.txRetryCount = 0;
|
EMS_Sys_Status.txRetryCount = 0;
|
||||||
EMS_Sys_Status.emsReverse = false;
|
EMS_Sys_Status.emsIDMask = 0x00;
|
||||||
EMS_Sys_Status.emsTxMode = 0;
|
EMS_Sys_Status.emsPollAck[0] = EMS_ID_ME;
|
||||||
|
|
||||||
// thermostat
|
// thermostat
|
||||||
EMS_Thermostat.setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET;
|
EMS_Thermostat.setpoint_roomTemp = EMS_VALUE_SHORT_NOTSET;
|
||||||
@@ -350,23 +350,6 @@ bool ems_getPoll() {
|
|||||||
return EMS_Sys_Status.emsPollEnabled;
|
return EMS_Sys_Status.emsPollEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ems_setTxMode(uint8_t mode) {
|
|
||||||
EMS_Sys_Status.emsTxMode = mode;
|
|
||||||
|
|
||||||
// special case for Junkers. If tx_mode is 3 then set the reverse poll flag
|
|
||||||
// https://github.com/proddy/EMS-ESP/issues/103#issuecomment-495945850
|
|
||||||
if (mode == 3) {
|
|
||||||
EMS_Sys_Status.emsReverse = true;
|
|
||||||
myDebug_P(PSTR("Forcing emsReverse for Junkers"));
|
|
||||||
} else {
|
|
||||||
EMS_Sys_Status.emsReverse = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t ems_getTxMode() {
|
|
||||||
return EMS_Sys_Status.emsTxMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ems_getEmsRefreshed() {
|
bool ems_getEmsRefreshed() {
|
||||||
return EMS_Sys_Status.emsRefreshed;
|
return EMS_Sys_Status.emsRefreshed;
|
||||||
}
|
}
|
||||||
@@ -434,7 +417,7 @@ _EMS_SYS_LOGGING ems_getLogging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ems_setLogging(_EMS_SYS_LOGGING loglevel) {
|
void ems_setLogging(_EMS_SYS_LOGGING loglevel) {
|
||||||
if (loglevel <= EMS_SYS_LOGGING_VERBOSE) {
|
if (loglevel <= EMS_SYS_LOGGING_JABBER) {
|
||||||
EMS_Sys_Status.emsLogging = loglevel;
|
EMS_Sys_Status.emsLogging = loglevel;
|
||||||
if (loglevel == EMS_SYS_LOGGING_NONE) {
|
if (loglevel == EMS_SYS_LOGGING_NONE) {
|
||||||
myDebug_P(PSTR("System Logging set to None"));
|
myDebug_P(PSTR("System Logging set to None"));
|
||||||
@@ -448,10 +431,19 @@ void ems_setLogging(_EMS_SYS_LOGGING loglevel) {
|
|||||||
myDebug_P(PSTR("System Logging set to Solar Module only"));
|
myDebug_P(PSTR("System Logging set to Solar Module only"));
|
||||||
} else if (loglevel == EMS_SYS_LOGGING_RAW) {
|
} else if (loglevel == EMS_SYS_LOGGING_RAW) {
|
||||||
myDebug_P(PSTR("System Logging set to Raw mode"));
|
myDebug_P(PSTR("System Logging set to Raw mode"));
|
||||||
|
} else if (loglevel == EMS_SYS_LOGGING_JABBER) {
|
||||||
|
myDebug_P(PSTR("System Logging set to Jabber mode"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* send a poll acknowledge
|
||||||
|
*/
|
||||||
|
void ems_tx_pollAck() {
|
||||||
|
emsuart_tx_buffer(&EMS_Sys_Status.emsPollAck[0], 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate CRC checksum using lookup table for speed
|
* Calculate CRC checksum using lookup table for speed
|
||||||
* len is length of all the data in bytes (including the header & CRC byte at end)
|
* len is length of all the data in bytes (including the header & CRC byte at end)
|
||||||
@@ -609,21 +601,26 @@ void _ems_sendTelegram() {
|
|||||||
_debugPrintTelegram("Sending raw: ", &EMS_RxTelegram, COLOR_CYAN, true);
|
_debugPrintTelegram("Sending raw: ", &EMS_RxTelegram, COLOR_CYAN, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
EMS_TxTelegram.data[EMS_TxTelegram.length - 1] = _crcCalculator(EMS_TxTelegram.data, EMS_TxTelegram.length); // add the CRC
|
EMS_TxTelegram.data[EMS_TxTelegram.length - 1] = _crcCalculator(EMS_TxTelegram.data, EMS_TxTelegram.length); // add the CRC
|
||||||
emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx
|
_EMS_TX_STATUS _txStatus = emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx
|
||||||
EMS_TxQueue.shift(); // and remove from queue
|
if (EMS_TX_BRK_DETECT == _txStatus || EMS_TX_WTD_TIMEOUT == _txStatus) {
|
||||||
|
// Tx Error!
|
||||||
|
myDebug_P(PSTR("** error sending buffer: %s"), _txStatus == EMS_TX_BRK_DETECT ? "BRK" : "WDTO");
|
||||||
|
// EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE;
|
||||||
|
}
|
||||||
|
EMS_TxQueue.shift(); // and remove from queue
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the header
|
// create the header
|
||||||
EMS_TxTelegram.data[0] = (EMS_Sys_Status.emsReverse) ? EMS_ID_ME | 0x80 : EMS_ID_ME; // src
|
EMS_TxTelegram.data[0] = EMS_ID_ME ^ EMS_Sys_Status.emsIDMask; // src
|
||||||
|
|
||||||
// dest
|
// dest
|
||||||
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) {
|
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) {
|
||||||
EMS_TxTelegram.data[1] = EMS_TxTelegram.dest;
|
EMS_TxTelegram.data[1] = EMS_TxTelegram.dest ^ EMS_Sys_Status.emsIDMask;
|
||||||
} else {
|
} else {
|
||||||
// for a READ or VALIDATE
|
// for a READ or VALIDATE
|
||||||
EMS_TxTelegram.data[1] = EMS_TxTelegram.dest | 0x80; // read has 8th bit set
|
EMS_TxTelegram.data[1] = (EMS_TxTelegram.dest ^ 0x80 ^ EMS_Sys_Status.emsIDMask); // read has 8th bit set
|
||||||
}
|
}
|
||||||
|
|
||||||
// complete the rest of the header depending on EMS or EMS+
|
// complete the rest of the header depending on EMS or EMS+
|
||||||
@@ -666,9 +663,15 @@ void _ems_sendTelegram() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send the telegram to the UART Tx
|
// send the telegram to the UART Tx
|
||||||
emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length);
|
_EMS_TX_STATUS _txStatus = emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx
|
||||||
|
if (EMS_TX_STATUS_OK == _txStatus || EMS_TX_STATUS_IDLE == _txStatus)
|
||||||
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_WAIT;
|
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_WAIT;
|
||||||
|
else {
|
||||||
|
// Tx Error!
|
||||||
|
// Tx Error!
|
||||||
|
myDebug_P(PSTR("** error sending buffer: %s"), _txStatus == EMS_TX_BRK_DETECT ? "BRK" : "WDTO");
|
||||||
|
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -715,6 +718,60 @@ void _createValidate() {
|
|||||||
EMS_TxQueue.unshift(new_EMS_TxTelegram); // add back to queue making it first to be picked up next (FIFO)
|
EMS_TxQueue.unshift(new_EMS_TxTelegram); // add back to queue making it first to be picked up next (FIFO)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dump a UART Tx or Rx buffer to console...
|
||||||
|
*/
|
||||||
|
void ems_dumpBuffer(const char * prefix, uint8_t * telegram, uint8_t length) {
|
||||||
|
uint32_t timestamp = millis();
|
||||||
|
static char output_str[200] = {0};
|
||||||
|
static char buffer[16] = {0};
|
||||||
|
|
||||||
|
if (EMS_Sys_Status.emsLogging != EMS_SYS_LOGGING_JABBER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
// we only care about known devices
|
||||||
|
if (length) {
|
||||||
|
uint8_t dev = telegram[0] & 0x7F;
|
||||||
|
if (!((dev == 0x04)||(dev == 0x08)||(dev == 0x09)||(dev == 0x0a)
|
||||||
|
||(dev == 0x01)||(dev == 0x0b)||(dev == 0x10)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
strlcpy(output_str, "(", sizeof(output_str));
|
||||||
|
strlcat(output_str, COLOR_CYAN, sizeof(output_str));
|
||||||
|
strlcat(output_str, _smallitoa((uint8_t)((timestamp / 3600000) % 24), buffer), sizeof(output_str));
|
||||||
|
strlcat(output_str, ":", sizeof(output_str));
|
||||||
|
strlcat(output_str, _smallitoa((uint8_t)((timestamp / 60000) % 60), buffer), sizeof(output_str));
|
||||||
|
strlcat(output_str, ":", sizeof(output_str));
|
||||||
|
strlcat(output_str, _smallitoa((uint8_t)((timestamp / 1000) % 60), buffer), sizeof(output_str));
|
||||||
|
strlcat(output_str, ".", sizeof(output_str));
|
||||||
|
strlcat(output_str, _smallitoa3(timestamp % 1000, buffer), sizeof(output_str));
|
||||||
|
strlcat(output_str, COLOR_RESET, sizeof(output_str));
|
||||||
|
strlcat(output_str, ") ", sizeof(output_str));
|
||||||
|
|
||||||
|
strlcat(output_str, COLOR_YELLOW, sizeof(output_str));
|
||||||
|
strlcat(output_str, prefix, sizeof(output_str));
|
||||||
|
|
||||||
|
// show some EMS_Sys_Status entries
|
||||||
|
strlcat(output_str, _hextoa(EMS_Sys_Status.emsRxStatus, buffer), sizeof(output_str));
|
||||||
|
strlcat(output_str, " ", sizeof(output_str));
|
||||||
|
strlcat(output_str, _hextoa(EMS_Sys_Status.emsTxStatus, buffer), sizeof(output_str));
|
||||||
|
strlcat(output_str, ": ", sizeof(output_str));
|
||||||
|
|
||||||
|
|
||||||
|
// print whole buffer, don't interpret any data
|
||||||
|
for (int i = 0; i < (length); i++) {
|
||||||
|
strlcat(output_str, _hextoa(telegram[i], buffer), sizeof(output_str));
|
||||||
|
strlcat(output_str, " ", sizeof(output_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
strlcat(output_str, COLOR_RESET, sizeof(output_str));
|
||||||
|
|
||||||
|
myDebug(output_str);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point triggered by an interrupt in emsuart.cpp
|
* Entry point triggered by an interrupt in emsuart.cpp
|
||||||
* length is the number of all the telegram bytes up to and including the CRC at the end
|
* length is the number of all the telegram bytes up to and including the CRC at the end
|
||||||
@@ -724,16 +781,28 @@ void _createValidate() {
|
|||||||
void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
|
void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
|
||||||
static uint32_t _last_emsPollFrequency = 0;
|
static uint32_t _last_emsPollFrequency = 0;
|
||||||
|
|
||||||
|
ems_dumpBuffer("ems_parseTelegram: ", telegram, length);
|
||||||
/*
|
/*
|
||||||
* check if we just received a single byte
|
* check if we just received a single byte
|
||||||
* it could well be a Poll request from the boiler for us, which will have a value of 0x8B (0x0B | 0x80)
|
* it could well be a Poll request from the boiler for us, which will have a value of 0x8B (0x0B | 0x80)
|
||||||
* or either a return code like 0x01 or 0x04 from the last Write command
|
* or either a return code like 0x01 or 0x04 from the last Write command
|
||||||
* Roger Wilco: we have different types here:
|
*/
|
||||||
* EMS_ID_ME && length == 1 && EMS_TX_STATUS_IDLE && EMS_RX_STATUS_IDLE: polling request
|
|
||||||
* EMS_ID_ME && length > 1 && EMS_TX_STATUS_IDLE && EMS_RX_STATUS_IDLE: direct telegram
|
/*
|
||||||
* (EMS_TX_SUCCESS || EMS_TX_ERROR) && EMS_TX_STATUS_WAIT: response, free the EMS bus
|
* Detect the EMS bus type - Buderus or Junkers - and set emsIDMask accordingly.
|
||||||
*
|
* we wait for the first valid telegram and look at the SourceID.
|
||||||
* In addition, it may happen that we where interrupted (f.e. by WIFI activity) and the
|
* If Bit 7 is set we have a Buderus, otherwise a Junkers
|
||||||
|
*/
|
||||||
|
if (EMS_Sys_Status.emsTxStatus == EMS_TX_REV_DETECT) {
|
||||||
|
if ((length >= 5) && (telegram[length - 1] == _crcCalculator(telegram, length))) {
|
||||||
|
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE;
|
||||||
|
EMS_Sys_Status.emsIDMask = telegram[0] & 0x80;
|
||||||
|
EMS_Sys_Status.emsPollAck[0] = EMS_ID_ME ^ EMS_Sys_Status.emsIDMask;
|
||||||
|
} else
|
||||||
|
return; // ignore the whole telegram Rx Telegram while in DETECT mode
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It may happen that we where interrupted (f.e. by WIFI activity) and the
|
||||||
* buffer isn't valid anymore, so we must not answer at all...
|
* buffer isn't valid anymore, so we must not answer at all...
|
||||||
*/
|
*/
|
||||||
if (EMS_Sys_Status.emsRxStatus != EMS_RX_STATUS_IDLE) {
|
if (EMS_Sys_Status.emsRxStatus != EMS_RX_STATUS_IDLE) {
|
||||||
@@ -747,8 +816,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
|
|||||||
uint8_t value = telegram[0]; // 1st byte of data package
|
uint8_t value = telegram[0]; // 1st byte of data package
|
||||||
|
|
||||||
// check first for a Poll for us
|
// check first for a Poll for us
|
||||||
// the poll has the MSB set - seems to work on both EMS and Junkers
|
if ((value ^ 0x80 ^ EMS_Sys_Status.emsIDMask) == EMS_ID_ME) {
|
||||||
if ((value & 0x7F) == EMS_ID_ME) {
|
|
||||||
EMS_Sys_Status.emsTxCapable = true;
|
EMS_Sys_Status.emsTxCapable = true;
|
||||||
uint32_t timenow_microsecs = micros();
|
uint32_t timenow_microsecs = micros();
|
||||||
EMS_Sys_Status.emsPollFrequency = (timenow_microsecs - _last_emsPollFrequency);
|
EMS_Sys_Status.emsPollFrequency = (timenow_microsecs - _last_emsPollFrequency);
|
||||||
@@ -761,7 +829,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
|
|||||||
} else {
|
} else {
|
||||||
// nothing to send so just send a poll acknowledgement back
|
// nothing to send so just send a poll acknowledgement back
|
||||||
if (EMS_Sys_Status.emsPollEnabled) {
|
if (EMS_Sys_Status.emsPollEnabled) {
|
||||||
emsuart_tx_poll();
|
ems_tx_pollAck();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_WAIT) {
|
} else if (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_WAIT) {
|
||||||
@@ -769,15 +837,15 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
|
|||||||
if (value == EMS_TX_SUCCESS) {
|
if (value == EMS_TX_SUCCESS) {
|
||||||
EMS_Sys_Status.emsTxPkgs++;
|
EMS_Sys_Status.emsTxPkgs++;
|
||||||
// got a success 01. Send a validate to check the value of the last write
|
// got a success 01. Send a validate to check the value of the last write
|
||||||
emsuart_tx_poll(); // send a poll to free the EMS bus
|
ems_tx_pollAck(); // send a poll to free the EMS bus
|
||||||
_createValidate(); // create a validate Tx request (if needed)
|
_createValidate(); // create a validate Tx request (if needed)
|
||||||
} else if (value == EMS_TX_ERROR) {
|
} else if (value == EMS_TX_ERROR) {
|
||||||
// last write failed (04), delete it from queue and dont bother to retry
|
// last write failed (04), delete it from queue and dont bother to retry
|
||||||
if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) {
|
if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) {
|
||||||
myDebug_P(PSTR("** Write command failed from host"));
|
myDebug_P(PSTR("** Write command failed from host"));
|
||||||
}
|
}
|
||||||
emsuart_tx_poll(); // send a poll to free the EMS bus
|
ems_tx_pollAck(); // send a poll to free the EMS bus
|
||||||
_removeTxQueue(); // remove from queue
|
_removeTxQueue(); // remove from queue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,7 +855,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
|
|||||||
// ignore anything that doesn't resemble a proper telegram package
|
// ignore anything that doesn't resemble a proper telegram package
|
||||||
// minimal is 5 bytes, excluding CRC at the end
|
// minimal is 5 bytes, excluding CRC at the end
|
||||||
if (length <= 4) {
|
if (length <= 4) {
|
||||||
//_debugPrintTelegram("Noisy data:", &EMS_RxTelegram COLOR_RED);
|
// _debugPrintTelegram("Noisy data:", &EMS_RxTelegram, COLOR_RED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -835,7 +903,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
|
|||||||
|
|
||||||
// if we are in raw logging mode then just print out the telegram as it is
|
// if we are in raw logging mode then just print out the telegram as it is
|
||||||
// but still continue to process it
|
// but still continue to process it
|
||||||
if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_RAW) {
|
if ((EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_RAW)) {
|
||||||
_debugPrintTelegram("", &EMS_RxTelegram, COLOR_WHITE, true);
|
_debugPrintTelegram("", &EMS_RxTelegram, COLOR_WHITE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1030,7 +1098,8 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) {
|
|||||||
|
|
||||||
// if its an echo of ourselves from the master UBA, ignore. This should never happen mind you
|
// if its an echo of ourselves from the master UBA, ignore. This should never happen mind you
|
||||||
if (EMS_RxTelegram->src == EMS_ID_ME) {
|
if (EMS_RxTelegram->src == EMS_ID_ME) {
|
||||||
// _debugPrintTelegram("echo:", EMS_RxTelegram, COLOR_WHITE);
|
if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_JABBER)
|
||||||
|
_debugPrintTelegram("echo:", EMS_RxTelegram, COLOR_WHITE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1138,10 +1207,9 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emsuart_tx_poll(); // send Acknowledgement back to free the EMS bus since we have the telegram
|
ems_tx_pollAck(); // send Acknowledgement back to free the EMS bus since we have the telegram
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if hot tap water or heating is active
|
* Check if hot tap water or heating is active
|
||||||
* using a quick hack for checking the heating. Selected Flow Temp >= 70
|
* using a quick hack for checking the heating. Selected Flow Temp >= 70
|
||||||
@@ -1677,7 +1745,8 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
|
|||||||
|
|
||||||
// check to see if its a Junkers Heatronic3, which has a different poll'ing logic
|
// check to see if its a Junkers Heatronic3, which has a different poll'ing logic
|
||||||
if (EMS_Boiler.product_id == EMS_PRODUCTID_HEATRONICS) {
|
if (EMS_Boiler.product_id == EMS_PRODUCTID_HEATRONICS) {
|
||||||
EMS_Sys_Status.emsReverse = true;
|
EMS_Sys_Status.emsIDMask = 0x80;
|
||||||
|
EMS_Sys_Status.emsPollAck[0] = EMS_ID_ME ^ EMS_Sys_Status.emsIDMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
ems_getBoilerValues(); // get Boiler values that we would usually have to wait for
|
ems_getBoilerValues(); // get Boiler values that we would usually have to wait for
|
||||||
@@ -1816,9 +1885,11 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
|
|||||||
* Do a read command for the version with the src having the MSB set
|
* Do a read command for the version with the src having the MSB set
|
||||||
*/
|
*/
|
||||||
void _ems_detectJunkers() {
|
void _ems_detectJunkers() {
|
||||||
|
#ifdef JUNKERS_DETECT
|
||||||
char s[30] = {0};
|
char s[30] = {0};
|
||||||
snprintf(s, sizeof(s), "%02X %02X %02X 00 %02X", (EMS_ID_ME | 0x80), (EMS_ID_BOILER | 0x080), EMS_TYPE_Version, EMS_MAX_TELEGRAM_LENGTH);
|
snprintf(s, sizeof(s), "%02X %02X %02X 00 %02X", (EMS_ID_ME | 0x80), (EMS_ID_BOILER | 0x080), EMS_TYPE_Version, EMS_MAX_TELEGRAM_LENGTH);
|
||||||
ems_sendRawTelegram(s);
|
ems_sendRawTelegram(s);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
58
src/ems.h
58
src/ems.h
@@ -30,39 +30,39 @@
|
|||||||
#define GPIO_H(mask) (GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, (mask)))
|
#define GPIO_H(mask) (GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, (mask)))
|
||||||
#define GPIO_L(mask) (GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, (mask)))
|
#define GPIO_L(mask) (GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, (mask)))
|
||||||
|
|
||||||
#define RX_PULSE(pulse) \
|
#define RX_PULSE(pulse) \
|
||||||
do { \
|
do { \
|
||||||
GPIO_H(RX_MARK_MASK); \
|
GPIO_H(RX_MARK_MASK); \
|
||||||
delayMicroseconds(pulse); \
|
delayMicroseconds(pulse); \
|
||||||
GPIO_L(RX_MARK_MASK); \
|
GPIO_L(RX_MARK_MASK); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define TX_PULSE(pulse) \
|
#define TX_PULSE(pulse) \
|
||||||
do { \
|
do { \
|
||||||
GPIO_H(TX_MARK_MASK); \
|
GPIO_H(TX_MARK_MASK); \
|
||||||
delayMicroseconds(pulse); \
|
delayMicroseconds(pulse); \
|
||||||
GPIO_L(TX_MARK_MASK); \
|
GPIO_L(TX_MARK_MASK); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define LA_PULSE(pulse) \
|
#define LA_PULSE(pulse) \
|
||||||
do { \
|
do { \
|
||||||
GPIO_H(MARKERS_MASK); \
|
GPIO_H(MARKERS_MASK); \
|
||||||
delayMicroseconds(pulse); \
|
delayMicroseconds(pulse); \
|
||||||
GPIO_L(MARKERS_MASK); \
|
GPIO_L(MARKERS_MASK); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define INIT_MARKERS(void) \
|
#define INIT_MARKERS(void) \
|
||||||
do { \
|
do { \
|
||||||
pinMode(RX_MARK_PIN, OUTPUT); \
|
pinMode(RX_MARK_PIN, OUTPUT); \
|
||||||
pinMode(TX_MARK_PIN, OUTPUT); \
|
pinMode(TX_MARK_PIN, OUTPUT); \
|
||||||
GPIO_L(MARKERS_MASK); \
|
GPIO_L(MARKERS_MASK); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define RX_PULSE(pulse) \
|
#define RX_PULSE(pulse) \
|
||||||
{}
|
{}
|
||||||
#define TX_PULSE(pulse) \
|
#define TX_PULSE(pulse) \
|
||||||
{}
|
{}
|
||||||
#define LA_PULSE(pulse) \
|
#define LA_PULSE(pulse) \
|
||||||
{}
|
{}
|
||||||
#define INIT_MARKERS(void) \
|
#define INIT_MARKERS(void) \
|
||||||
{}
|
{}
|
||||||
#define RX_MARK_MASK
|
#define RX_MARK_MASK
|
||||||
#define TX_MARK_MASK
|
#define TX_MARK_MASK
|
||||||
@@ -125,7 +125,8 @@ typedef enum {
|
|||||||
EMS_TX_STATUS_IDLE, // ready
|
EMS_TX_STATUS_IDLE, // ready
|
||||||
EMS_TX_STATUS_WAIT, // waiting for response from last Tx
|
EMS_TX_STATUS_WAIT, // waiting for response from last Tx
|
||||||
EMS_TX_WTD_TIMEOUT, // watchdog timeout during send
|
EMS_TX_WTD_TIMEOUT, // watchdog timeout during send
|
||||||
EMS_TX_BRK_DETECT // incoming BRK during Tx
|
EMS_TX_BRK_DETECT, // incoming BRK during Tx
|
||||||
|
EMS_TX_REV_DETECT // waiting to detect reverse bit
|
||||||
} _EMS_TX_STATUS;
|
} _EMS_TX_STATUS;
|
||||||
|
|
||||||
#define EMS_TX_SUCCESS 0x01 // EMS single byte after a Tx Write indicating a success
|
#define EMS_TX_SUCCESS 0x01 // EMS single byte after a Tx Write indicating a success
|
||||||
@@ -146,7 +147,8 @@ typedef enum {
|
|||||||
EMS_SYS_LOGGING_BASIC, // only basic read/write messages
|
EMS_SYS_LOGGING_BASIC, // only basic read/write messages
|
||||||
EMS_SYS_LOGGING_THERMOSTAT, // only telegrams sent from thermostat
|
EMS_SYS_LOGGING_THERMOSTAT, // only telegrams sent from thermostat
|
||||||
EMS_SYS_LOGGING_SOLARMODULE, // only telegrams sent from thermostat
|
EMS_SYS_LOGGING_SOLARMODULE, // only telegrams sent from thermostat
|
||||||
EMS_SYS_LOGGING_VERBOSE // everything
|
EMS_SYS_LOGGING_VERBOSE, // everything
|
||||||
|
EMS_SYS_LOGGING_JABBER // lots of debug output...
|
||||||
} _EMS_SYS_LOGGING;
|
} _EMS_SYS_LOGGING;
|
||||||
|
|
||||||
// status/counters since last power on
|
// status/counters since last power on
|
||||||
@@ -165,8 +167,9 @@ typedef struct {
|
|||||||
bool emsTxCapable; // able to send via Tx
|
bool emsTxCapable; // able to send via Tx
|
||||||
bool emsTxDisabled; // true to prevent all Tx
|
bool emsTxDisabled; // true to prevent all Tx
|
||||||
uint8_t txRetryCount; // # times the last Tx was re-sent
|
uint8_t txRetryCount; // # times the last Tx was re-sent
|
||||||
bool emsReverse; // if true, poll logic is reversed
|
|
||||||
uint8_t emsTxMode; // handles Tx logic
|
uint8_t emsTxMode; // handles Tx logic
|
||||||
|
uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80
|
||||||
|
uint8_t emsPollAck[1]; // acknowledge buffer
|
||||||
} _EMS_Sys_Status;
|
} _EMS_Sys_Status;
|
||||||
|
|
||||||
// The Tx send package
|
// The Tx send package
|
||||||
@@ -392,6 +395,7 @@ typedef struct {
|
|||||||
} _EMS_Type;
|
} _EMS_Type;
|
||||||
|
|
||||||
// function definitions
|
// function definitions
|
||||||
|
extern void ems_dumpBuffer(const char * prefix, uint8_t * telegram, uint8_t length);
|
||||||
extern void ems_parseTelegram(uint8_t * telegram, uint8_t len);
|
extern void ems_parseTelegram(uint8_t * telegram, uint8_t len);
|
||||||
void ems_init();
|
void ems_init();
|
||||||
void ems_doReadCommand(uint16_t type, uint8_t dest, bool forceRefresh = false);
|
void ems_doReadCommand(uint16_t type, uint8_t dest, bool forceRefresh = false);
|
||||||
|
|||||||
@@ -111,12 +111,12 @@
|
|||||||
#define EMS_OFFSET_RCPLUSStatusMessage_setpoint 3 // setpoint temp
|
#define EMS_OFFSET_RCPLUSStatusMessage_setpoint 3 // setpoint temp
|
||||||
#define EMS_OFFSET_RCPLUSStatusMessage_curr 0 // current temp
|
#define EMS_OFFSET_RCPLUSStatusMessage_curr 0 // current temp
|
||||||
#define EMS_OFFSET_RCPLUSGet_mode_day 10 // day/night mode
|
#define EMS_OFFSET_RCPLUSGet_mode_day 10 // day/night mode
|
||||||
#define EMS_OFFSET_RCPLUSSet_mode 0 // operation mode (Auto=xFF, Manual=x00)
|
#define EMS_OFFSET_RCPLUSSet_mode 0 // operation mode (Auto=xFF, Manual=x00)
|
||||||
#define EMS_OFFSET_RCPLUSStatusMessage_mode 0x0A // thermostat mode (auto, manual)
|
#define EMS_OFFSET_RCPLUSStatusMessage_mode 0x0A // thermostat mode (auto, manual)
|
||||||
#define EMS_OFFSET_RCPLUSSet_temp_comfort3 1 // comfort3 level
|
#define EMS_OFFSET_RCPLUSSet_temp_comfort3 1 // comfort3 level
|
||||||
#define EMS_OFFSET_RCPLUSSet_temp_comfort2 2 // comfort2 level
|
#define EMS_OFFSET_RCPLUSSet_temp_comfort2 2 // comfort2 level
|
||||||
#define EMS_OFFSET_RCPLUSSet_temp_comfort1 3 // comfort1 level
|
#define EMS_OFFSET_RCPLUSSet_temp_comfort1 3 // comfort1 level
|
||||||
#define EMS_OFFSET_RCPLUSSet_temp_eco 4 // eco level
|
#define EMS_OFFSET_RCPLUSSet_temp_eco 4 // eco level
|
||||||
|
|
||||||
// Junkers FR10, FW100 (EMS Plus)
|
// Junkers FR10, FW100 (EMS Plus)
|
||||||
#define EMS_TYPE_JunkersStatusMessage 0x6F // is an automatic thermostat broadcast giving us temps
|
#define EMS_TYPE_JunkersStatusMessage 0x6F // is an automatic thermostat broadcast giving us temps
|
||||||
|
|||||||
209
src/emsuart.cpp
209
src/emsuart.cpp
@@ -11,7 +11,8 @@
|
|||||||
|
|
||||||
_EMSRxBuf * pEMSRxBuf;
|
_EMSRxBuf * pEMSRxBuf;
|
||||||
_EMSRxBuf * paEMSRxBuf[EMS_MAXBUFFERS];
|
_EMSRxBuf * paEMSRxBuf[EMS_MAXBUFFERS];
|
||||||
uint8_t emsRxBufIdx = 0;
|
uint8_t emsRxBufIdx = 0;
|
||||||
|
uint8_t phantomBreak = 0;
|
||||||
|
|
||||||
os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue
|
os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue
|
||||||
|
|
||||||
@@ -21,7 +22,7 @@ os_event_t recvTaskQueue[EMSUART_recvTaskQueueLen]; // our Rx queue
|
|||||||
//
|
//
|
||||||
static void emsuart_rx_intr_handler(void * para) {
|
static void emsuart_rx_intr_handler(void * para) {
|
||||||
static uint8_t length;
|
static uint8_t length;
|
||||||
static uint8_t uart_buffer[EMS_MAXBUFFERSIZE];
|
static uint8_t uart_buffer[EMS_MAXBUFFERSIZE + 2];
|
||||||
|
|
||||||
// is a new buffer? if so init the thing for a new telegram
|
// is a new buffer? if so init the thing for a new telegram
|
||||||
if (EMS_Sys_Status.emsRxStatus == EMS_RX_STATUS_IDLE) {
|
if (EMS_Sys_Status.emsRxStatus == EMS_RX_STATUS_IDLE) {
|
||||||
@@ -32,7 +33,9 @@ static void emsuart_rx_intr_handler(void * para) {
|
|||||||
// fill IRQ buffer, by emptying Rx FIFO
|
// fill IRQ buffer, by emptying Rx FIFO
|
||||||
if (USIS(EMSUART_UART) & ((1 << UIFF) | (1 << UITO) | (1 << UIBD))) {
|
if (USIS(EMSUART_UART) & ((1 << UIFF) | (1 << UITO) | (1 << UIBD))) {
|
||||||
while ((USS(EMSUART_UART) >> USRXC) & 0xFF) {
|
while ((USS(EMSUART_UART) >> USRXC) & 0xFF) {
|
||||||
uart_buffer[length++] = USF(EMSUART_UART);
|
uint8_t rx = USF(EMSUART_UART);
|
||||||
|
if (length < EMS_MAXBUFFERSIZE)
|
||||||
|
uart_buffer[length++] = rx;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear Rx FIFO full and Rx FIFO timeout interrupts
|
// clear Rx FIFO full and Rx FIFO timeout interrupts
|
||||||
@@ -45,10 +48,11 @@ static void emsuart_rx_intr_handler(void * para) {
|
|||||||
ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them
|
ETS_UART_INTR_DISABLE(); // disable all interrupts and clear them
|
||||||
USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt
|
USIC(EMSUART_UART) = (1 << UIBD); // INT clear the BREAK detect interrupt
|
||||||
|
|
||||||
pEMSRxBuf->length = length;
|
pEMSRxBuf->length = (length > EMS_MAXBUFFERSIZE) ? EMS_MAXBUFFERSIZE : length;
|
||||||
os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, length); // copy data into transfer buffer, including the BRK 0x00 at the end
|
os_memcpy((void *)pEMSRxBuf->buffer, (void *)&uart_buffer, pEMSRxBuf->length); // copy data into transfer buffer, including the BRK 0x00 at the end
|
||||||
EMS_Sys_Status.emsRxStatus = EMS_RX_STATUS_IDLE; // set the status flag stating BRK has been received and we can start a new package
|
length = 0;
|
||||||
ETS_UART_INTR_ENABLE(); // re-enable UART interrupts
|
EMS_Sys_Status.emsRxStatus = EMS_RX_STATUS_IDLE; // set the status flag stating BRK has been received and we can start a new package
|
||||||
|
ETS_UART_INTR_ENABLE(); // re-enable UART interrupts
|
||||||
|
|
||||||
system_os_post(EMSUART_recvTaskPrio, 0, 0); // call emsuart_recvTask() at next opportunity
|
system_os_post(EMSUART_recvTaskPrio, 0, 0); // call emsuart_recvTask() at next opportunity
|
||||||
RX_PULSE(EMSUART_BIT_TIME / 2);
|
RX_PULSE(EMSUART_BIT_TIME / 2);
|
||||||
@@ -66,18 +70,21 @@ static void ICACHE_FLASH_ATTR emsuart_recvTask(os_event_t * events) {
|
|||||||
uint8_t length = pCurrent->length; // number of bytes including the BRK at the end
|
uint8_t length = pCurrent->length; // number of bytes including the BRK at the end
|
||||||
pCurrent->length = 0;
|
pCurrent->length = 0;
|
||||||
|
|
||||||
// validate and transmit the EMS buffer, excluding the BRK
|
if (phantomBreak) {
|
||||||
|
phantomBreak = 0;
|
||||||
|
length--; // remove phantom break from Rx buffer
|
||||||
|
}
|
||||||
|
|
||||||
if (length == 2) {
|
if (length == 2) {
|
||||||
RX_PULSE(20);
|
RX_PULSE(20);
|
||||||
// it's a poll or status code, single byte and ok to send on
|
// it's a poll or status code, single byte and ok to send on
|
||||||
ems_parseTelegram((uint8_t *)pCurrent->buffer, 1);
|
ems_parseTelegram((uint8_t *)pCurrent->buffer, 1);
|
||||||
} else if ((length > 4) && (length <= EMS_MAXBUFFERSIZE + 1) && (pCurrent->buffer[length - 2] != 0x00)) {
|
} else if ((length > 4) && (length <= EMS_MAXBUFFERSIZE + 1)) {
|
||||||
// ignore double BRK at the end, possibly from the Tx loopback
|
// ignore double BRK at the end, possibly from the Tx loopback
|
||||||
// also telegrams with no data value
|
// also telegrams with no data value
|
||||||
RX_PULSE(40);
|
RX_PULSE(40);
|
||||||
ems_parseTelegram((uint8_t *)pCurrent->buffer, length - 1); // transmit EMS buffer, excluding the BRK
|
ems_parseTelegram((uint8_t *)pCurrent->buffer, length - 1); // transmit EMS buffer, excluding the BRK
|
||||||
}
|
}
|
||||||
// memset(pCurrent->buffer, 0x00, EMS_MAXBUFFERSIZE); // wipe memory just to be safe
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -124,7 +131,7 @@ void ICACHE_FLASH_ATTR emsuart_init() {
|
|||||||
// change: we set UCFFT to 1 to get an immediate indicator about incoming traffic.
|
// change: we set UCFFT to 1 to get an immediate indicator about incoming traffic.
|
||||||
// Otherwise, we're only noticed by UCTOT or RxBRK!
|
// Otherwise, we're only noticed by UCTOT or RxBRK!
|
||||||
USC1(EMSUART_UART) = 0; // reset config first
|
USC1(EMSUART_UART) = 0; // reset config first
|
||||||
USC1(EMSUART_UART) = (0x01 << UCFFT) | (0x01 << UCTOT) | (1 << UCTOE); // enable interupts
|
USC1(EMSUART_UART) = (0x01 << UCFFT) | (0x01 << UCTOT) | (0 << UCTOE); // enable interupts
|
||||||
|
|
||||||
// set interrupts for triggers
|
// set interrupts for triggers
|
||||||
USIC(EMSUART_UART) = 0xFFFF; // clear all interupts
|
USIC(EMSUART_UART) = 0xFFFF; // clear all interupts
|
||||||
@@ -132,7 +139,8 @@ void ICACHE_FLASH_ATTR emsuart_init() {
|
|||||||
|
|
||||||
// enable rx break, fifo full and timeout.
|
// enable rx break, fifo full and timeout.
|
||||||
// but not frame error UIFR (because they are too frequent) or overflow UIOF because our buffer is only max 32 bytes
|
// but not frame error UIFR (because they are too frequent) or overflow UIOF because our buffer is only max 32 bytes
|
||||||
USIE(EMSUART_UART) = (1 << UIBD) | (1 << UIFF) | (1 << UITO);
|
// change: we don't care about Rx Timeout - it may lead to wrong readouts
|
||||||
|
USIE(EMSUART_UART) = (1 << UIBD) | (1 << UIFF) | (0 << UITO);
|
||||||
|
|
||||||
// set up interrupt callbacks for Rx
|
// set up interrupt callbacks for Rx
|
||||||
system_os_task(emsuart_recvTask, EMSUART_recvTaskPrio, recvTaskQueue, EMSUART_recvTaskQueueLen);
|
system_os_task(emsuart_recvTask, EMSUART_recvTaskPrio, recvTaskQueue, EMSUART_recvTaskQueueLen);
|
||||||
@@ -162,73 +170,15 @@ void ICACHE_FLASH_ATTR emsuart_start() {
|
|||||||
ETS_UART_INTR_ENABLE();
|
ETS_UART_INTR_ENABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Send a BRK signal
|
|
||||||
* Which is a 11-bit set of zero's (11 cycles)
|
|
||||||
*/
|
|
||||||
void ICACHE_FLASH_ATTR emsuart_tx_brk() {
|
|
||||||
uint32_t tmp;
|
|
||||||
|
|
||||||
// must make sure Tx FIFO is empty
|
|
||||||
while (((USS(EMSUART_UART) >> USTXC) & 0xFF) != 0)
|
|
||||||
;
|
|
||||||
|
|
||||||
tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask
|
|
||||||
USC0(EMSUART_UART) |= (tmp); // set bits
|
|
||||||
USC0(EMSUART_UART) &= ~(tmp); // clear bits
|
|
||||||
|
|
||||||
// To create a 11-bit <BRK> we set TXD_BRK bit so the break signal will
|
|
||||||
// automatically be sent when the tx fifo is empty
|
|
||||||
tmp = (1 << UCBRK);
|
|
||||||
GPIO_H(TX_MARK_MASK);
|
|
||||||
USC0(EMSUART_UART) |= (tmp); // set bit
|
|
||||||
|
|
||||||
if (EMS_Sys_Status.emsTxMode <= 1) { // classic mode and ems+ (0, 1)
|
|
||||||
delayMicroseconds(EMSUART_TX_BRK_WAIT);
|
|
||||||
} else if (EMS_Sys_Status.emsTxMode == 3) { // junkers mode
|
|
||||||
delayMicroseconds(EMSUART_TX_WAIT_BRK - EMSUART_TX_LAG); // 1144 (11 Bits)
|
|
||||||
}
|
|
||||||
|
|
||||||
USC0(EMSUART_UART) &= ~(tmp); // clear bit
|
|
||||||
GPIO_L(TX_MARK_MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send to Tx, ending with a <BRK>
|
* Send to Tx, ending with a <BRK>
|
||||||
*/
|
*/
|
||||||
_EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
|
_EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
|
||||||
_EMS_TX_STATUS result = EMS_TX_STATUS_OK;
|
_EMS_TX_STATUS result = EMS_TX_STATUS_OK;
|
||||||
|
ems_dumpBuffer("emsuart_tx_buffer: ", buf, len); // validate and transmit the EMS buffer, excluding the BRK
|
||||||
if (len) {
|
if (len) {
|
||||||
LA_PULSE(50);
|
LA_PULSE(50);
|
||||||
// temp code until we get mode 2 working without resets
|
/*
|
||||||
if (EMS_Sys_Status.emsTxMode == 0) { // classic mode logic
|
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
|
||||||
TX_PULSE(EMSUART_BIT_TIME / 4);
|
|
||||||
USF(EMSUART_UART) = buf[i];
|
|
||||||
}
|
|
||||||
emsuart_tx_brk(); // send <BRK>
|
|
||||||
} else if (EMS_Sys_Status.emsTxMode == 1) { // With extra tx delay for EMS+
|
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
|
||||||
TX_PULSE(EMSUART_BIT_TIME / 4);
|
|
||||||
USF(EMSUART_UART) = buf[i];
|
|
||||||
delayMicroseconds(EMSUART_TX_BRK_WAIT); // https://github.com/proddy/EMS-ESP/issues/23#
|
|
||||||
}
|
|
||||||
emsuart_tx_brk(); // send <BRK>
|
|
||||||
} else if (EMS_Sys_Status.emsTxMode == 3) { // Junkers logic by @philrich
|
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
|
||||||
TX_PULSE(EMSUART_BIT_TIME / 4);
|
|
||||||
USF(EMSUART_UART) = buf[i];
|
|
||||||
|
|
||||||
// just to be safe wait for tx fifo empty (needed?)
|
|
||||||
while (((USS(EMSUART_UART) >> USTXC) & 0xff) != 0)
|
|
||||||
;
|
|
||||||
|
|
||||||
// wait until bits are sent on wire
|
|
||||||
delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP);
|
|
||||||
}
|
|
||||||
emsuart_tx_brk(); // send <BRK>
|
|
||||||
} else if (EMS_Sys_Status.emsTxMode == 2) {
|
|
||||||
/*
|
|
||||||
*
|
*
|
||||||
* based on code from https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
|
* based on code from https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
|
||||||
* we emit the whole telegram, with Rx interrupt disabled, collecting busmaster response in FIFO.
|
* we emit the whole telegram, with Rx interrupt disabled, collecting busmaster response in FIFO.
|
||||||
@@ -253,76 +203,63 @@ _EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
|
|||||||
|
|
||||||
// shorter busy poll...
|
// shorter busy poll...
|
||||||
#define EMSUART_BUSY_WAIT (EMSUART_BIT_TIME / 8)
|
#define EMSUART_BUSY_WAIT (EMSUART_BIT_TIME / 8)
|
||||||
#define EMS_TX_TO_COUNT ((20 + 10000 / EMSUART_BIT_TIME) * 8)
|
#define EMS_TX_TO_CHARS (2 + 20)
|
||||||
uint16_t wdc = EMS_TX_TO_COUNT;
|
#define EMS_TX_TO_COUNT ((EMS_TX_TO_CHARS)*10 * 8)
|
||||||
|
uint16_t wdc = EMS_TX_TO_COUNT;
|
||||||
|
ETS_UART_INTR_DISABLE(); // disable rx interrupt
|
||||||
|
|
||||||
ETS_UART_INTR_DISABLE(); // disable rx interrupt
|
// clear Rx status register
|
||||||
|
USC0(EMSUART_UART) |= (1 << UCRXRST); // reset uart rx fifo
|
||||||
|
emsuart_flush_fifos();
|
||||||
|
|
||||||
// clear Rx status register
|
// throw out the telegram...
|
||||||
USC0(EMSUART_UART) |= (1 << UCRXRST); // reset uart rx fifo
|
for (uint8_t i = 0; i < len && result == EMS_TX_STATUS_OK;) {
|
||||||
emsuart_flush_fifos();
|
GPIO_H(TX_MARK_MASK);
|
||||||
|
|
||||||
// throw out the telegram...
|
wdc = EMS_TX_TO_COUNT;
|
||||||
for (uint8_t i = 0; i < len && result == EMS_TX_STATUS_OK;) {
|
volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF;
|
||||||
GPIO_H(TX_MARK_MASK);
|
USF(EMSUART_UART) = buf[i++]; // send each Tx byte
|
||||||
|
// wait for echo from busmaster
|
||||||
wdc = EMS_TX_TO_COUNT;
|
GPIO_L(TX_MARK_MASK);
|
||||||
volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF;
|
while (((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) {
|
||||||
USF(EMSUART_UART) = buf[i++]; // send each Tx byte
|
delayMicroseconds(EMSUART_BUSY_WAIT); // burn CPU cycles...
|
||||||
// wait for echo from busmaster
|
if (--wdc == 0) {
|
||||||
GPIO_L(TX_MARK_MASK);
|
EMS_Sys_Status.emsTxStatus = result = EMS_TX_WTD_TIMEOUT;
|
||||||
|
break;
|
||||||
while (((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) {
|
}
|
||||||
delayMicroseconds(EMSUART_BUSY_WAIT); // burn CPU cycles...
|
if (USIR(EMSUART_UART) & (1 << UIBD)) {
|
||||||
if (--wdc == 0) {
|
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
|
||||||
EMS_Sys_Status.emsTxStatus = result = EMS_TX_WTD_TIMEOUT;
|
EMS_Sys_Status.emsTxStatus = result = EMS_TX_BRK_DETECT;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (USIR(EMSUART_UART) & (1 << UIBD)) {
|
|
||||||
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
|
|
||||||
EMS_Sys_Status.emsTxStatus = result = EMS_TX_BRK_DETECT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// we got the whole telegram in the Rx buffer
|
|
||||||
// on Rx-BRK (bus collision), we simply enable Rx and leave it
|
|
||||||
// otherwise we send the final Tx-BRK in the loopback and re=enable Rx-INT.
|
|
||||||
// worst case, we'll see an additional Rx-BRK...
|
|
||||||
if (result != EMS_TX_STATUS_OK) {
|
|
||||||
LA_PULSE(200); // mark Tx error
|
|
||||||
} else {
|
|
||||||
// neither bus collision nor timeout - send terminating BRK signal
|
|
||||||
GPIO_H(TX_MARK_MASK);
|
|
||||||
if (!(USIS(EMSUART_UART) & (1 << UIBD))) {
|
|
||||||
// no bus collision - send terminating BRK signal
|
|
||||||
USC0(EMSUART_UART) |= (1 << UCLBE) | (1 << UCBRK); // enable loopback & set <BRK>
|
|
||||||
|
|
||||||
// wait until BRK detected...
|
|
||||||
while (!(USIR(EMSUART_UART) & (1 << UIBD))) {
|
|
||||||
delayMicroseconds(EMSUART_BUSY_WAIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear <BRK>
|
|
||||||
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
|
|
||||||
}
|
|
||||||
GPIO_L(TX_MARK_MASK);
|
|
||||||
}
|
|
||||||
ETS_UART_INTR_ENABLE(); // receive anything from FIFO...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// we got the whole telegram in the Rx buffer
|
||||||
|
// on Rx-BRK (bus collision), we simply enable Rx and leave it
|
||||||
|
// otherwise we send the final Tx-BRK in the loopback and re=enable Rx-INT.
|
||||||
|
// worst case, we'll see an additional Rx-BRK...
|
||||||
|
if (result != EMS_TX_STATUS_OK) {
|
||||||
|
LA_PULSE(200); // mark Tx error
|
||||||
|
} else {
|
||||||
|
// neither bus collision nor timeout - send terminating BRK signal
|
||||||
|
GPIO_H(TX_MARK_MASK);
|
||||||
|
if (!(USIS(EMSUART_UART) & (1 << UIBD))) {
|
||||||
|
// no bus collision - send terminating BRK signal
|
||||||
|
USC0(EMSUART_UART) |= (1 << UCLBE) | (1 << UCBRK); // enable loopback & set <BRK>
|
||||||
|
|
||||||
|
// wait until BRK detected...
|
||||||
|
while (!(USIR(EMSUART_UART) & (1 << UIBD))) {
|
||||||
|
// delayMicroseconds(EMSUART_BUSY_WAIT);
|
||||||
|
delayMicroseconds(EMSUART_BIT_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear <BRK>
|
||||||
|
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
|
||||||
|
phantomBreak = 1;
|
||||||
|
}
|
||||||
|
GPIO_L(TX_MARK_MASK);
|
||||||
|
}
|
||||||
|
ETS_UART_INTR_ENABLE(); // receive anything from FIFO...
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Send the Poll (our own ID) to Tx as a single byte and end with a <BRK>
|
|
||||||
*/
|
|
||||||
void ICACHE_FLASH_ATTR emsuart_tx_poll() {
|
|
||||||
static uint8_t buf[1];
|
|
||||||
if (EMS_Sys_Status.emsReverse) {
|
|
||||||
buf[0] = {EMS_ID_ME | 0x80};
|
|
||||||
} else {
|
|
||||||
buf[0] = {EMS_ID_ME};
|
|
||||||
}
|
|
||||||
emsuart_tx_buffer(buf, 1);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -36,4 +36,3 @@ void ICACHE_FLASH_ATTR emsuart_init();
|
|||||||
void ICACHE_FLASH_ATTR emsuart_stop();
|
void ICACHE_FLASH_ATTR emsuart_stop();
|
||||||
void ICACHE_FLASH_ATTR emsuart_start();
|
void ICACHE_FLASH_ATTR emsuart_start();
|
||||||
_EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len);
|
_EMS_TX_STATUS ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len);
|
||||||
void ICACHE_FLASH_ATTR emsuart_tx_poll();
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
#define APP_NAME "EMS-ESP"
|
#define APP_NAME "EMS-ESP"
|
||||||
#define APP_VERSION "1.9.0b1_web"
|
#define APP_VERSION "1.9.0b2_web"
|
||||||
#define APP_HOSTNAME "ems-esp"
|
#define APP_HOSTNAME "ems-esp"
|
||||||
#define APP_HELPURL "https://github.com/proddy/EMS-ESP/wiki"
|
#define APP_HELPURL "https://github.com/proddy/EMS-ESP/wiki"
|
||||||
#define APP_UPDATEURL "https://api.github.com/repos/proddy/EMS-ESP/releases/latest"
|
#define APP_UPDATEURL "https://api.github.com/repos/proddy/EMS-ESP/releases/latest"
|
||||||
|
|||||||
@@ -106,8 +106,7 @@ var custom_configfile = {
|
|||||||
"shower_timer": false,
|
"shower_timer": false,
|
||||||
"shower_alert": false,
|
"shower_alert": false,
|
||||||
"publish_time": 120,
|
"publish_time": 120,
|
||||||
"heating_circuit": 1,
|
"heating_circuit": 1
|
||||||
"tx_mode": 2
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user