mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
a8
This commit is contained in:
@@ -41,7 +41,7 @@ Note: Version 2.0 is not backward compatible with v1.0. The File system structur
|
||||
common commands available in all contexts:
|
||||
exit
|
||||
help
|
||||
log [level] [trace ID] [raw]
|
||||
log [level] [raw] [trace ID]
|
||||
su
|
||||
|
||||
(top level)
|
||||
@@ -124,8 +124,9 @@ thermostat
|
||||
### **Known issues, bugs and improvements currently working on**
|
||||
|
||||
```
|
||||
TODO ESP32 - when saving SPIFFS the UART stop and restart() functions need to flush queue to avoid miss fires
|
||||
TODO network issues with ESP8266 - can take a while to get an IP address. DNS issue?
|
||||
TODO figure out why sometimes telnet on ESP32 (and sometimes ESP8266) has slow response times. After a manual reset it seems to fix itself. Perhaps the telnet service needs to start after the wifi is up & running.
|
||||
TODO Get the ESP32 UART code working.
|
||||
TODO sometimes with tx_mode 0 there are a few CRC errors due to collision when waiting for a BRK signal.
|
||||
TODO console auto-complete with 'set' command in the system context is not showing all commands, only the hostname.
|
||||
```
|
||||
|
||||
@@ -26,15 +26,25 @@ uint64_t get_uptime_ms() {
|
||||
static uint32_t high_millis = 0;
|
||||
static uint32_t low_millis = 0;
|
||||
|
||||
uint32_t now_millis = ::millis();
|
||||
|
||||
if (now_millis < low_millis) {
|
||||
if (get_uptime() < low_millis) {
|
||||
high_millis++;
|
||||
}
|
||||
|
||||
low_millis = now_millis;
|
||||
low_millis = get_uptime();
|
||||
|
||||
return ((uint64_t)high_millis << 32) | low_millis;
|
||||
}
|
||||
|
||||
// added by proddy
|
||||
|
||||
static uint32_t now_millis; // added by proddy
|
||||
|
||||
void set_uptime() {
|
||||
now_millis = ::millis();
|
||||
}
|
||||
|
||||
uint32_t get_uptime() {
|
||||
return now_millis;
|
||||
}
|
||||
|
||||
} // namespace uuid
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
namespace uuid {
|
||||
|
||||
void loop() {
|
||||
set_uptime(); // added by proddy
|
||||
get_uptime_ms();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,9 @@ void loop();
|
||||
*/
|
||||
uint64_t get_uptime_ms();
|
||||
|
||||
uint32_t get_uptime(); // added by proddy
|
||||
void set_uptime();
|
||||
|
||||
} // namespace uuid
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@ extra_configs = pio_local.ini
|
||||
|
||||
;debug_flags = -DDEBUG_ESP_PORT=Serial -DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_TLS_MEM
|
||||
debug_flags =
|
||||
-D EMSESP_DEBUG
|
||||
; -D EMSESP_DEBUG
|
||||
; -D EMSESP_SAFE_MODE
|
||||
; -D ENABLE_CORS -D CORS_ORIGIN=\"http://localhost:3000\"
|
||||
|
||||
@@ -69,7 +69,7 @@ upload_protocol = espota
|
||||
upload_flags =
|
||||
--port=8266
|
||||
--auth=neo
|
||||
upload_port = ems-esp32.local
|
||||
upload_port = ems-esp.local
|
||||
|
||||
[env:esp8266]
|
||||
build_type = release
|
||||
|
||||
@@ -221,7 +221,7 @@ void Console::load_standard_commands(unsigned int context) {
|
||||
context,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(log)},
|
||||
flash_string_vector{F_(log_level_optional), F_(traceid_optional), F_(raw_optional)},
|
||||
flash_string_vector{F_(log_level_optional), F_(trace_format_optional), F_(traceid_optional)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint16_t watch_id;
|
||||
if (!arguments.empty()) {
|
||||
@@ -238,16 +238,17 @@ void Console::load_standard_commands(unsigned int context) {
|
||||
if (level == uuid::log::Level::TRACE) {
|
||||
watch_id = LOG_TRACE_WATCH_NONE; // no watch ID set
|
||||
if (arguments.size() > 1) {
|
||||
watch_id = Helpers::hextoint(arguments[1].c_str()); // get the watch ID
|
||||
}
|
||||
// next argument is raw or full
|
||||
if (arguments[1] == read_flash_string(F_(raw))) {
|
||||
emsesp::EMSESP::trace_raw(true);
|
||||
} else if (arguments[1] == read_flash_string(F_(full))) {
|
||||
emsesp::EMSESP::trace_raw(false);
|
||||
}
|
||||
|
||||
emsesp::EMSESP::trace_watch_id(watch_id);
|
||||
|
||||
// see if we have a "raw"
|
||||
if ((arguments.size() == 3) && (arguments[2] == read_flash_string(F_(raw)))) {
|
||||
emsesp::EMSESP::trace_raw(true);
|
||||
} else {
|
||||
emsesp::EMSESP::trace_raw(false);
|
||||
// get the watch_id if its set
|
||||
if (arguments.size() == 3) {
|
||||
emsesp::EMSESP::trace_watch_id(Helpers::hextoint(arguments[2].c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ MAKE_PSTR_WORD(restart)
|
||||
MAKE_PSTR_WORD(reconnect)
|
||||
MAKE_PSTR_WORD(format)
|
||||
MAKE_PSTR_WORD(raw)
|
||||
MAKE_PSTR_WORD(full)
|
||||
|
||||
// context menus
|
||||
MAKE_PSTR_WORD(mqtt)
|
||||
@@ -102,8 +103,8 @@ MAKE_PSTR(n_mandatory, "<n>")
|
||||
MAKE_PSTR(n_optional, "[n]")
|
||||
MAKE_PSTR(traceid_optional, "[trace ID]")
|
||||
MAKE_PSTR(trace_raw_fmt, "Displaying raw bytes = %s")
|
||||
MAKE_PSTR(raw_optional, "[raw]")
|
||||
MAKE_PSTR(bool_mandatory, "<on | off>")
|
||||
MAKE_PSTR(trace_format_optional, "[full|raw]")
|
||||
MAKE_PSTR(bool_mandatory, "<on|off>")
|
||||
MAKE_PSTR(typeid_mandatory, "<type ID>")
|
||||
MAKE_PSTR(deviceid_mandatory, "<device ID>")
|
||||
MAKE_PSTR(deviceid_optional, "[device ID]")
|
||||
|
||||
@@ -333,7 +333,7 @@ void EMSESP::process_UBADevices(std::shared_ptr<const Telegram> telegram) {
|
||||
// if we haven't already detected this device, request it's version details, unless its us (EMS-ESP)
|
||||
// when the version info is received, it will automagically add the device
|
||||
if ((device_id != ems_bus_id) && !(EMSESP::device_exists(device_id))) {
|
||||
LOG_INFO(F("New EMS device detected with ID 0x%02X. Requesting version information."), device_id);
|
||||
LOG_DEBUG(F("New EMS device detected with ID 0x%02X. Requesting version information."), device_id);
|
||||
send_read_request(EMSdevice::EMS_TYPE_VERSION, device_id);
|
||||
}
|
||||
}
|
||||
@@ -619,7 +619,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
// check for poll to us, if so send top message from Tx queue immediately and quit
|
||||
// if ht3 poll must be ems_bus_id else if Buderus poll must be (ems_bus_id | 0x80)
|
||||
if ((first_value ^ 0x80 ^ rxservice_.ems_mask()) == txservice_.ems_bus_id()) {
|
||||
EMSbus::last_bus_activity(millis()); // set the flag indication the EMS bus is active
|
||||
EMSbus::last_bus_activity(uuid::get_uptime()); // set the flag indication the EMS bus is active
|
||||
txservice_.send();
|
||||
}
|
||||
return;
|
||||
@@ -695,17 +695,17 @@ void EMSESP::console_commands(Shell & shell, unsigned int context) {
|
||||
flash_string_vector{F_(n_mandatory)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint8_t tx_mode = (arguments[0]).at(0) - '0';
|
||||
if ((tx_mode > 0) && (tx_mode <= 3)) {
|
||||
if ((tx_mode > 0) && (tx_mode <= 4)) {
|
||||
Settings settings;
|
||||
settings.ems_tx_mode(tx_mode);
|
||||
settings.commit();
|
||||
shell.printfln(F_(tx_mode_fmt), settings.ems_tx_mode());
|
||||
} else {
|
||||
shell.println(F("Must be 1 for EMS generic, 2 for EMS+ or 3 for HT3"));
|
||||
shell.println(F("Must be 1 for EMS generic, 2 for EMS+, 3 for HT3, 4 for experimental"));
|
||||
}
|
||||
},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> const std::vector<std::string> {
|
||||
return std::vector<std::string>{read_flash_string(F("1")), read_flash_string(F("2")), read_flash_string(F("3"))};
|
||||
return std::vector<std::string>{read_flash_string(F("1")), read_flash_string(F("2")), read_flash_string(F("3")), read_flash_string(F("4"))};
|
||||
});
|
||||
|
||||
EMSESPShell::commands->add_command(
|
||||
@@ -808,19 +808,20 @@ void EMSESP::start() {
|
||||
|
||||
// loop de loop
|
||||
void EMSESP::loop() {
|
||||
// network returns false if an OTA is being carried out.
|
||||
// network returns false if an OTA is being carried out
|
||||
// so we disable all services when an OTA is happening
|
||||
if (network_.loop()) {
|
||||
console_.loop(); // telnet/serial console
|
||||
system_.loop(); // does LED and checks system health, and syslog service
|
||||
mqtt_.loop(); // starts mqtt, and sends out anything in the queue
|
||||
rxservice_.loop(); // process what ever is in the rx queue
|
||||
txservice_.loop(); // check that the Tx is all ok
|
||||
shower_.loop(); // check for shower on/off
|
||||
sensors_.loop(); // this will also send out via MQTT
|
||||
|
||||
// force a query on the EMS devices to fetch latest data
|
||||
uint32_t currentMillis = millis();
|
||||
if ((currentMillis - last_fetch_ > EMS_FETCH_FREQUENCY)) {
|
||||
last_fetch_ = currentMillis;
|
||||
// force a query on the EMS devices to fetch latest data at a set interval (1 min)
|
||||
if ((uuid::get_uptime() - last_fetch_ > EMS_FETCH_FREQUENCY)) {
|
||||
last_fetch_ = uuid::get_uptime();
|
||||
fetch_device_values();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "boiler.h"
|
||||
#include "shower.h"
|
||||
|
||||
#define LOG_TRACE_WATCH_NONE 0 // no watch set
|
||||
#define LOG_TRACE_WATCH_NONE 0 // no watch set
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
|
||||
14
src/mqtt.cpp
14
src/mqtt.cpp
@@ -142,7 +142,7 @@ void Mqtt::setup() {
|
||||
#endif
|
||||
|
||||
mqtt_connecting_ = false;
|
||||
mqtt_last_connection_ = millis();
|
||||
mqtt_last_connection_ = uuid::get_uptime();
|
||||
mqtt_reconnect_delay_ = Mqtt::MQTT_RECONNECT_DELAY_MIN;
|
||||
|
||||
LOG_DEBUG(F("Configuring MQTT service..."));
|
||||
@@ -177,7 +177,7 @@ void Mqtt::init() {
|
||||
}
|
||||
|
||||
// Reset reconnection delay
|
||||
mqtt_last_connection_ = millis();
|
||||
mqtt_last_connection_ = uuid::get_uptime();
|
||||
mqtt_connecting_ = false;
|
||||
mqtt_start_ = false; // will force a new start()
|
||||
});
|
||||
@@ -236,7 +236,7 @@ void Mqtt::loop() {
|
||||
}
|
||||
|
||||
// send out heartbeat
|
||||
uint32_t currentMillis = millis();
|
||||
uint32_t currentMillis = uuid::get_uptime();
|
||||
if ((currentMillis - last_heartbeat_ > MQTT_HEARTBEAT_INTERVAL)) {
|
||||
last_heartbeat_ = currentMillis;
|
||||
send_heartbeat();
|
||||
@@ -258,7 +258,7 @@ void Mqtt::loop() {
|
||||
}
|
||||
|
||||
// We need to reconnect. Check when was the last time we tried this
|
||||
if (mqtt_last_connection_ && (millis() - mqtt_last_connection_ < mqtt_reconnect_delay_)) {
|
||||
if (mqtt_last_connection_ && (uuid::get_uptime() - mqtt_last_connection_ < mqtt_reconnect_delay_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -394,7 +394,9 @@ void Mqtt::on_publish(uint16_t packetId) {
|
||||
}
|
||||
|
||||
if (mqtt_message.packet_id_ == packetId) {
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("Acknowledged PID %d. Removing from queue"), packetId);
|
||||
#endif
|
||||
} else {
|
||||
LOG_DEBUG(F("Mismatch, expecting PID %d, got %d"), mqtt_message.packet_id_, packetId);
|
||||
mqtt_publish_fails_++; // increment error count
|
||||
@@ -436,7 +438,7 @@ void Mqtt::send_start_topic() {
|
||||
// MQTT onConnect - when a connect is established
|
||||
void Mqtt::on_connect() {
|
||||
mqtt_reconnect_delay_ = Mqtt::MQTT_RECONNECT_DELAY_MIN;
|
||||
mqtt_last_connection_ = millis();
|
||||
mqtt_last_connection_ = uuid::get_uptime();
|
||||
mqtt_connecting_ = false;
|
||||
LOG_INFO(F("MQTT connected"));
|
||||
}
|
||||
@@ -600,7 +602,9 @@ void Mqtt::process_queue() {
|
||||
// but add the packet_id so we can check it later
|
||||
if (mqtt_qos_ != 0) {
|
||||
mqtt_messages_.front().packet_id_ = packet_id;
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("Setting packetID for ACK to %d"), packet_id);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,8 +54,10 @@ void Sensors::start() {
|
||||
|
||||
void Sensors::loop() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
uint32_t time_now = uuid::get_uptime();
|
||||
|
||||
if (state_ == State::IDLE) {
|
||||
if (millis() - last_activity_ >= READ_INTERVAL_MS) {
|
||||
if (time_now - last_activity_ >= READ_INTERVAL_MS) {
|
||||
// LOG_DEBUG(F("Read sensor temperature")); // uncomment for debug
|
||||
if (bus_.reset()) {
|
||||
bus_.skip();
|
||||
@@ -67,7 +69,7 @@ void Sensors::loop() {
|
||||
// LOG_ERROR(F("Bus reset failed")); // uncomment for debug
|
||||
devices_.clear(); // remove all know devices incase we have a disconnect
|
||||
}
|
||||
last_activity_ = millis();
|
||||
last_activity_ = time_now;
|
||||
}
|
||||
} else if (state_ == State::READING) {
|
||||
if (temperature_convert_complete()) {
|
||||
@@ -76,18 +78,18 @@ void Sensors::loop() {
|
||||
found_.clear();
|
||||
|
||||
state_ = State::SCANNING;
|
||||
last_activity_ = millis();
|
||||
} else if (millis() - last_activity_ > READ_TIMEOUT_MS) {
|
||||
last_activity_ = time_now;
|
||||
} else if (time_now - last_activity_ > READ_TIMEOUT_MS) {
|
||||
LOG_ERROR(F("Sensor read timeout"));
|
||||
|
||||
state_ = State::IDLE;
|
||||
last_activity_ = millis();
|
||||
last_activity_ = time_now;
|
||||
}
|
||||
} else if (state_ == State::SCANNING) {
|
||||
if (millis() - last_activity_ > SCAN_TIMEOUT_MS) {
|
||||
if (time_now - last_activity_ > SCAN_TIMEOUT_MS) {
|
||||
LOG_ERROR(F("Sensor scan timeout"));
|
||||
state_ = State::IDLE;
|
||||
last_activity_ = millis();
|
||||
last_activity_ = time_now;
|
||||
} else {
|
||||
uint8_t addr[ADDR_LEN] = {0};
|
||||
|
||||
@@ -125,7 +127,7 @@ void Sensors::loop() {
|
||||
found_.clear();
|
||||
// LOG_DEBUG(F("Found %zu sensor(s). Adding them."), devices_.size()); // uncomment for debug
|
||||
state_ = State::IDLE;
|
||||
last_activity_ = millis();
|
||||
last_activity_ = time_now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,8 +100,8 @@ class Sensors {
|
||||
bool temperature_convert_complete();
|
||||
float get_temperature_c(const uint8_t addr[]);
|
||||
|
||||
uint32_t last_activity_ = millis();
|
||||
uint32_t last_publish_ = millis();
|
||||
uint32_t last_activity_ = uuid::get_uptime();
|
||||
uint32_t last_publish_ = uuid::get_uptime();
|
||||
State state_ = State::IDLE;
|
||||
std::vector<Device> found_;
|
||||
std::vector<Device> devices_;
|
||||
|
||||
@@ -36,7 +36,8 @@ void Shower::loop() {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t time_now = millis();
|
||||
uint32_t time_now = uuid::get_uptime();
|
||||
|
||||
// if already in cold mode, ignore all this logic until we're out of the cold blast
|
||||
if (!doing_cold_shot_) {
|
||||
// is the hot water running?
|
||||
|
||||
@@ -246,9 +246,8 @@ void System::set_led_speed(uint32_t speed) {
|
||||
void System::system_check() {
|
||||
static uint32_t last_system_check_ = 0;
|
||||
|
||||
uint32_t currentMillis = millis();
|
||||
if (!last_system_check_ || ((uint32_t)(currentMillis - last_system_check_) >= SYSTEM_CHECK_FREQUENCY)) {
|
||||
last_system_check_ = currentMillis;
|
||||
if (!last_system_check_ || ((uint32_t)(uuid::get_uptime() - last_system_check_) >= SYSTEM_CHECK_FREQUENCY)) {
|
||||
last_system_check_ = uuid::get_uptime();
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if ((WiFi.status() != WL_CONNECTED) || safe_mode()) {
|
||||
@@ -262,6 +261,7 @@ void System::system_check() {
|
||||
if (!EMSbus::bus_connected()) {
|
||||
system_healthy_ = false;
|
||||
set_led_speed(LED_WARNING_BLINK); // flash every 1/2 second from now on
|
||||
LOG_ERROR(F("No connection to the EMS bus!"));
|
||||
} else {
|
||||
// if it was unhealthy but now we're better, make sure the LED is solid again cos we've been healed
|
||||
if (!system_healthy_) {
|
||||
@@ -278,9 +278,8 @@ void System::system_check() {
|
||||
void System::led_monitor() {
|
||||
static uint32_t led_last_blink_ = 0;
|
||||
|
||||
uint32_t currentMillis = millis();
|
||||
if (!led_last_blink_ || (uint32_t)(currentMillis - led_last_blink_) >= led_flash_speed_) {
|
||||
led_last_blink_ = currentMillis;
|
||||
if (!led_last_blink_ || (uint32_t)(uuid::get_uptime() - led_last_blink_) >= led_flash_speed_) {
|
||||
led_last_blink_ = uuid::get_uptime();
|
||||
|
||||
// if bus_not_connected or network not connected, start flashing
|
||||
if (!system_healthy_) {
|
||||
|
||||
@@ -74,9 +74,9 @@ class System {
|
||||
static uuid::syslog::SyslogService syslog_;
|
||||
#endif
|
||||
|
||||
static constexpr uint32_t SYSTEM_CHECK_FREQUENCY = 5000; // check every 5 seconds
|
||||
static constexpr uint32_t LED_WARNING_BLINK = 1000; // pulse to show no connection
|
||||
static constexpr uint32_t LED_WARNING_BLINK_FAST = 100; // flash quickly for boot up sequence or safe-mode
|
||||
static constexpr uint32_t SYSTEM_CHECK_FREQUENCY = 10000; // check every 10 seconds
|
||||
static constexpr uint32_t LED_WARNING_BLINK = 1000; // pulse to show no connection, 1 sec
|
||||
static constexpr uint32_t LED_WARNING_BLINK_FAST = 100; // flash quickly for boot up sequence or safe-mode
|
||||
|
||||
// internal LED
|
||||
#if defined(ESP8266)
|
||||
|
||||
@@ -200,9 +200,10 @@ void RxService::flush_rx_queue() {
|
||||
rx_telegram_id_ = 0;
|
||||
}
|
||||
|
||||
// start and initialize the Rx incoming buffer. Not currently used.
|
||||
// start and initialize the Rx incoming buffer
|
||||
void RxService::start() {
|
||||
// LOG_DEBUG(F("RxStart"));
|
||||
// function not currently used
|
||||
}
|
||||
|
||||
// Rx loop, run as many times as you can
|
||||
@@ -210,11 +211,10 @@ void RxService::start() {
|
||||
void RxService::loop() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// give rx some breathing space
|
||||
uint32_t time_now = millis();
|
||||
if ((time_now - last_rx_check_) < RX_LOOP_WAIT) {
|
||||
if ((uuid::get_uptime() - last_rx_check_) < RX_LOOP_WAIT) {
|
||||
return;
|
||||
}
|
||||
last_rx_check_ = time_now;
|
||||
last_rx_check_ = uuid::get_uptime();
|
||||
#endif
|
||||
|
||||
while (!rx_telegrams_.empty()) {
|
||||
@@ -235,6 +235,7 @@ void RxService::loop() {
|
||||
|
||||
// add a new rx telegram object
|
||||
// data is the whole telegram, assuming last byte holds the CRC
|
||||
// length includes the CRC
|
||||
// for EMS+ the type_id has the value + 256. We look for these type of telegrams with F7, F9 and FF in 3rd byte
|
||||
void RxService::add(uint8_t * data, uint8_t length) {
|
||||
// validate the CRC
|
||||
@@ -263,7 +264,7 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
||||
uint8_t dest = data[1] & 0x7F; // strip MSB, don't care if its read or write for processing
|
||||
uint8_t offset = data[3]; // offset is always 4th byte
|
||||
|
||||
uint16_t type_id; // this could be 2 bytes for ems+
|
||||
uint16_t type_id = 0; // this could be 2 bytes for ems+
|
||||
uint8_t * message_data;
|
||||
uint8_t message_length;
|
||||
|
||||
@@ -274,15 +275,21 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
||||
message_data = data + 4; // message block starts at 5th byte
|
||||
message_length = length - 5; // remove 4 bytes header plus CRC
|
||||
} else {
|
||||
// EMS 2.0
|
||||
// EMS 2.0 / EMS+
|
||||
if (data[2] == 0xFF) {
|
||||
type_id = (data[4] << 8) + data[5] + 256;
|
||||
message_data = data + 6; // message block starts at 7th position
|
||||
|
||||
// check for empty data
|
||||
// special broadcast telegrams on ems+ have no data values, some even don't have a type ID
|
||||
if (length <= 7) {
|
||||
message_length = 0; // special broadcast on ems+ have no data values
|
||||
message_data = data; // bogus pointer, will not be used
|
||||
message_length = 0;
|
||||
if (length <= 5) {
|
||||
type_id = 0; // has also an empty type_id
|
||||
} else {
|
||||
type_id = (data[4] << 8) + data[5] + 256;
|
||||
}
|
||||
} else {
|
||||
message_length = length - 7; // remove 6 byte header plus CRC
|
||||
message_data = data + 6; // message block starts at 7th position
|
||||
}
|
||||
} else {
|
||||
// its F9 or F7
|
||||
@@ -297,20 +304,28 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have a type_id, exit
|
||||
if (type_id == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// create the telegram
|
||||
auto telegram = std::make_shared<Telegram>(Telegram::Operation::RX, src, dest, type_id, offset, message_data, message_length);
|
||||
|
||||
// check if queue is full
|
||||
if (rx_telegrams_.size() >= maximum_rx_telegrams_) {
|
||||
if (rx_telegrams_.size() >= MAX_RX_TELEGRAMS) {
|
||||
// rx_telegrams_overflow_ = true;
|
||||
rx_telegrams_.pop_front();
|
||||
}
|
||||
|
||||
// add to queue, with timestamp
|
||||
// add to queue
|
||||
LOG_DEBUG(F("New Rx [#%d] telegram, length %d"), rx_telegram_id_, message_length);
|
||||
rx_telegrams_.emplace_back(rx_telegram_id_++, std::move(telegram));
|
||||
}
|
||||
|
||||
//
|
||||
// Tx CODE here
|
||||
//
|
||||
|
||||
TxService::QueuedTxTelegram::QueuedTxTelegram(uint16_t id, std::shared_ptr<Telegram> && telegram)
|
||||
: id_(id)
|
||||
@@ -325,8 +340,6 @@ void TxService::flush_tx_queue() {
|
||||
|
||||
// start and initialize Tx
|
||||
void TxService::start() {
|
||||
// LOG_DEBUG(F("TxStart()"));
|
||||
|
||||
// grab the bus ID
|
||||
Settings settings;
|
||||
ems_bus_id(settings.ems_bus_id());
|
||||
@@ -336,6 +349,19 @@ void TxService::start() {
|
||||
read_request(EMSdevice::EMS_TYPE_UBADevices, EMSdevice::EMS_DEVICE_ID_BOILER);
|
||||
}
|
||||
|
||||
// Tx loop
|
||||
// here we check if the Tx is not full and report an error
|
||||
void TxService::loop() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if ((uuid::get_uptime() - last_tx_check_) > TX_LOOP_WAIT) {
|
||||
last_tx_check_ = uuid::get_uptime();
|
||||
if ((tx_telegrams_.size() >= MAX_TX_TELEGRAMS - 1) && (EMSbus::bus_connected())) {
|
||||
LOG_ERROR(F("Tx buffer full. Looks like Tx is not working?"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// sends a 1 byte poll which is our own device ID
|
||||
void TxService::send_poll() {
|
||||
EMSuart::send_poll(ems_bus_id() ^ ems_mask());
|
||||
@@ -352,9 +378,8 @@ void TxService::send() {
|
||||
|
||||
// if there's nothing in the queue to send
|
||||
// optionally, send back a poll and quit
|
||||
// for now I've disabled the poll
|
||||
if (tx_telegrams_.empty()) {
|
||||
// send_poll();
|
||||
// send_poll(); // TODO commented out poll for now. should add back when stable.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -482,7 +507,7 @@ void TxService::add(const uint8_t operation, const uint8_t dest, const uint16_t
|
||||
LOG_DEBUG(F("New Tx [#%d] telegram, length %d"), tx_telegram_id_, message_length);
|
||||
|
||||
// if the queue is full, make room but removing the last one
|
||||
if (tx_telegrams_.size() >= maximum_tx_telegrams_) {
|
||||
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
|
||||
tx_telegrams_.pop_front();
|
||||
}
|
||||
|
||||
@@ -508,7 +533,7 @@ void TxService::add(uint8_t * data, const uint8_t length) {
|
||||
auto telegram = std::make_shared<Telegram>(Telegram::Operation::TX_RAW, src, dest, type_id, offset, message_data, message_length);
|
||||
|
||||
// if the queue is full, make room but removing the last one
|
||||
if (tx_telegrams_.size() >= maximum_tx_telegrams_) {
|
||||
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
|
||||
tx_telegrams_.pop_front();
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ class EMSbus {
|
||||
|
||||
static bool bus_connected() {
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if ((millis() - last_bus_activity_) > EMS_BUS_TIMEOUT) {
|
||||
if ((uuid::get_uptime() - last_bus_activity_) > EMS_BUS_TIMEOUT) {
|
||||
bus_connected_ = false;
|
||||
}
|
||||
return bus_connected_;
|
||||
@@ -202,8 +202,6 @@ class RxService : public EMSbus {
|
||||
static constexpr uint32_t RX_LOOP_WAIT = 800; // delay in processing Rx queue
|
||||
uint32_t last_rx_check_ = 0;
|
||||
|
||||
size_t maximum_rx_telegrams_ = MAX_RX_TELEGRAMS;
|
||||
|
||||
// std::atomic<bool> rx_telegrams_overflow_{false};
|
||||
uint8_t rx_telegram_id_ = 0; // queue counter
|
||||
|
||||
@@ -224,6 +222,7 @@ class TxService : public EMSbus {
|
||||
~TxService() = default;
|
||||
|
||||
void start();
|
||||
void loop();
|
||||
void send();
|
||||
|
||||
void add(const uint8_t operation, const uint8_t dest, const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length);
|
||||
@@ -292,8 +291,10 @@ class TxService : public EMSbus {
|
||||
private:
|
||||
static constexpr uint8_t MAXIMUM_TX_RETRIES = 3;
|
||||
|
||||
size_t maximum_tx_telegrams_ = MAX_TX_TELEGRAMS;
|
||||
uint8_t tx_telegram_id_ = 0; // queue counter
|
||||
uint8_t tx_telegram_id_ = 0; // queue counter
|
||||
|
||||
static constexpr uint32_t TX_LOOP_WAIT = 10000; // when to check if Tx is up and running (10 sec)
|
||||
uint32_t last_tx_check_ = 0;
|
||||
|
||||
std::deque<QueuedTxTelegram> tx_telegrams_;
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
emsdevices.push_back(EMSFactory::add(EMSdevice::DeviceType::BOILER, EMSdevice::EMS_DEVICE_ID_BOILER, 0, "", "My Boiler", 0, 0));
|
||||
|
||||
// A fake response - UBADevices(0x07)
|
||||
uint8_t t0[] = {0x08, 0x00, 0x07, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47};
|
||||
rxservice_.add(t0, sizeof(t0));
|
||||
uint8_t t[] = {0x08, 0x00, 0x07, 0x00, 0x0B, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47};
|
||||
rxservice_.add(t, sizeof(t));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -28,8 +28,8 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
rxservice_.loop();
|
||||
|
||||
// simulate getting version information back from an unknown device
|
||||
uint8_t u1[] = {0x09, 0x0B, 0x02, 0x00, 0x59, 0x01, 0x02, 0x56};
|
||||
rxservice_.add(u1, sizeof(u1));
|
||||
uint8_t t[] = {0x09, 0x0B, 0x02, 0x00, 0x59, 0x01, 0x02, 0x56};
|
||||
rxservice_.add(t, sizeof(t));
|
||||
rxservice_.loop();
|
||||
|
||||
return;
|
||||
@@ -63,9 +63,9 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
|
||||
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
|
||||
// B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
|
||||
uint8_t s1[] = {0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
|
||||
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x89};
|
||||
rxservice_.add(s1, sizeof(s1));
|
||||
uint8_t t[] = {0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
|
||||
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x89};
|
||||
rxservice_.add(t, sizeof(t));
|
||||
rxservice_.loop();
|
||||
|
||||
shell.loop_all();
|
||||
@@ -84,9 +84,9 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
|
||||
// RCPLUSStatusMessage_HC1(0x01A5)
|
||||
// 98 00 FF 00 01 A5 00 CF 21 2E 00 00 2E 24 03 25 03 03 01 03 25 00 C8 00 00 11 01 03
|
||||
uint8_t c1[] = {0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24, 0x03,
|
||||
0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03, 0x13};
|
||||
rxservice_.add(c1, sizeof(c1));
|
||||
uint8_t t[] = {0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24, 0x03,
|
||||
0x25, 0x03, 0x03, 0x01, 0x03, 0x25, 0x00, 0xC8, 0x00, 0x00, 0x11, 0x01, 0x03, 0x13};
|
||||
rxservice_.add(t, sizeof(t));
|
||||
rxservice_.loop();
|
||||
|
||||
shell.loop_all();
|
||||
@@ -231,7 +231,7 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
|
||||
// simulate sending a read request
|
||||
// uint8_t t16[] = {0x44, 0x45, 0x46, 0x47}; // Me -> Thermostat, (0x91), telegram: 0B 17 91 05 44 45 46 47 (#data=4)
|
||||
//txservice_.add(Telegram::Operation::TX_RAW, 0x17, 0x91, 0x05, t16, sizeof(t16));
|
||||
// txservice_.add(Telegram::Operation::TX_RAW, 0x17, 0x91, 0x05, t16, sizeof(t16));
|
||||
send_read_request(0x91, 0x17);
|
||||
// txservice_.show_tx_queue();
|
||||
|
||||
@@ -240,19 +240,19 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
incoming_telegram(poll, 1);
|
||||
|
||||
// incoming Rx
|
||||
uint8_t t17[] = {0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A};
|
||||
incoming_telegram(t17, sizeof(t17));
|
||||
uint8_t t1[] = {0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3A};
|
||||
incoming_telegram(t1, sizeof(t1));
|
||||
rxservice_.loop();
|
||||
|
||||
// Simulate adding a Poll - should send retry
|
||||
incoming_telegram(poll, 1);
|
||||
|
||||
show_emsbus(shell);
|
||||
uint8_t t18[] = {0x21, 0x22};
|
||||
send_write_request(0x91, 0x17, 0x00, t18, sizeof(t18), 0);
|
||||
uint8_t t2[] = {0x21, 0x22};
|
||||
send_write_request(0x91, 0x17, 0x00, t2, sizeof(t2), 0);
|
||||
show_emsbus(shell);
|
||||
|
||||
incoming_telegram(t17, sizeof(t17));
|
||||
incoming_telegram(t1, sizeof(t1));
|
||||
|
||||
txservice_.flush_tx_queue();
|
||||
|
||||
@@ -324,9 +324,17 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
|
||||
if (command == "rx2") {
|
||||
// incoming Rx
|
||||
uint8_t t71[] = {0x1B, 0x5B, 0xFD, 0x2D, 0x9E, 0x3A, 0xB6, 0xE5, 0x02, 0x20, 0x33, 0x30, 0x32, 0x3A, 0x20, 0x5B, 0x73,
|
||||
0xFF, 0xFF, 0xCB, 0xDF, 0xB7, 0xA7, 0xB5, 0x67, 0x77, 0x77, 0xE4, 0xFF, 0xFD, 0x77, 0xFF, 0xD1};
|
||||
incoming_telegram(t71, sizeof(t71));
|
||||
uint8_t t[] = {0x1B, 0x5B, 0xFD, 0x2D, 0x9E, 0x3A, 0xB6, 0xE5, 0x02, 0x20, 0x33, 0x30, 0x32, 0x3A, 0x20, 0x5B, 0x73,
|
||||
0xFF, 0xFF, 0xCB, 0xDF, 0xB7, 0xA7, 0xB5, 0x67, 0x77, 0x77, 0xE4, 0xFF, 0xFD, 0x77, 0xFF, 0xD1};
|
||||
incoming_telegram(t, sizeof(t));
|
||||
return;
|
||||
}
|
||||
|
||||
// https://github.com/proddy/EMS-ESP/issues/380#issuecomment-633663007
|
||||
if (command == "rx3") {
|
||||
// incoming Rx
|
||||
uint8_t t[] = {0x21, 0x0B, 0xFF, 0x00, 0xDA};
|
||||
incoming_telegram(t, sizeof(t));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -341,8 +349,8 @@ void EMSESP::run_test(uuid::console::Shell & shell, const std::string & command)
|
||||
|
||||
// testing the UART tx command, without a queue
|
||||
if (command == "tx2") {
|
||||
uint8_t tx[] = {0x0B, 0x88, 0x18, 0x00, 0x20, 0xD4}; // including CRC
|
||||
EMSuart::transmit(tx, sizeof(tx));
|
||||
uint8_t t[] = {0x0B, 0x88, 0x18, 0x00, 0x20, 0xD4}; // including CRC
|
||||
EMSuart::transmit(t, sizeof(t));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,9 @@ EMSuart::EMSRxBuf_t * pEMSRxBuf;
|
||||
EMSuart::EMSRxBuf_t * paEMSRxBuf[EMS_MAXBUFFERS];
|
||||
uint8_t emsRxBufIdx = 0;
|
||||
|
||||
uint8_t phantomBreak = 0;
|
||||
uint8_t tx_mode_ = EMS_TXMODE_DEFAULT;
|
||||
|
||||
// Main interrupt handler
|
||||
// Important: must not use ICACHE_FLASH_ATTR
|
||||
void ICACHE_RAM_ATTR EMSuart::emsuart_rx_intr_handler(void * para) {
|
||||
@@ -64,6 +67,12 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_recvTask(os_event_t * events) {
|
||||
uint8_t length = pCurrent->length; // number of bytes including the BRK at the end
|
||||
pCurrent->length = 0;
|
||||
|
||||
// LEGACY CODE
|
||||
if (phantomBreak) {
|
||||
phantomBreak = 0;
|
||||
length--; // remove phantom break from Rx buffer
|
||||
}
|
||||
|
||||
// it's a poll or status code, single byte and ok to send on, then quit
|
||||
if (length == 2) {
|
||||
EMSESP::incoming_telegram((uint8_t *)pCurrent->buffer, 1);
|
||||
@@ -81,6 +90,8 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_recvTask(os_event_t * events) {
|
||||
* init UART0 driver
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR EMSuart::start(uint8_t tx_mode) {
|
||||
tx_mode_ = tx_mode;
|
||||
|
||||
// allocate and preset EMS Receive buffers
|
||||
for (int i = 0; i < EMS_MAXBUFFERS; i++) {
|
||||
EMSRxBuf_t * p = (EMSRxBuf_t *)malloc(sizeof(EMSRxBuf_t));
|
||||
@@ -139,16 +150,163 @@ void EMSuart::send_poll(uint8_t data) {
|
||||
* buf contains the CRC and len is #bytes including the CRC
|
||||
*/
|
||||
EMSUART_STATUS ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
if (len) {
|
||||
if (len == 0) {
|
||||
return EMS_TX_STATUS_OK; // nothing to send
|
||||
}
|
||||
|
||||
// new code from Michael. See https://github.com/proddy/EMS-ESP/issues/380
|
||||
if (tx_mode_ == EMS_TXMODE_NEW) {
|
||||
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK> bit
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
USF(EMSUART_UART) = buf[i];
|
||||
}
|
||||
USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK> at the end
|
||||
|
||||
return EMS_TX_STATUS_OK;
|
||||
}
|
||||
return EMS_TX_STATUS_OK;
|
||||
|
||||
// EMS+ https://github.com/proddy/EMS-ESP/issues/23#
|
||||
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // With extra tx delay for EMS+
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
USF(EMSUART_UART) = buf[i];
|
||||
delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070
|
||||
}
|
||||
tx_brk(); // send <BRK>
|
||||
return EMS_TX_STATUS_OK;
|
||||
}
|
||||
|
||||
// Junkers logic by @philrich
|
||||
if (tx_mode_ == EMS_TXMODE_HT3) {
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
USF(EMSUART_UART) = buf[i];
|
||||
|
||||
// just to be safe wait for tx fifo empty (still needed?)
|
||||
while (((USS(EMSUART_UART) >> USTXC) & 0xff))
|
||||
;
|
||||
|
||||
// wait until bits are sent on wire
|
||||
delayMicroseconds(EMSUART_TX_WAIT_BYTE - EMSUART_TX_LAG + EMSUART_TX_WAIT_GAP); // 1760
|
||||
}
|
||||
tx_brk(); // send <BRK>
|
||||
return EMS_TX_STATUS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Logic for tx_mode of 0 (EMS_TXMODE_DEFAULT)
|
||||
* based on code from https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
|
||||
*
|
||||
* Logic:
|
||||
* we emit the whole telegram, with Rx interrupt disabled, collecting busmaster response in FIFO.
|
||||
* after sending the last char we poll the Rx status until either
|
||||
* - size(Rx FIFO) == size(Tx-Telegram)
|
||||
* - <BRK> is detected
|
||||
* At end of receive we re-enable Rx-INT and send a Tx-BRK in loopback mode.
|
||||
*
|
||||
* EMS-Bus error handling
|
||||
* 1. Busmaster stops echoing on Tx w/o permission
|
||||
* 2. Busmaster cancel telegram by sending a BRK
|
||||
*
|
||||
* Case 1. is handled by a watchdog counter which is reset on each
|
||||
* Tx attempt. The timeout should be 20x EMSUART_BIT_TIME plus
|
||||
* some smart guess for processing time on targeted EMS device.
|
||||
* We set Status to EMS_TX_WTD_TIMEOUT and return
|
||||
*
|
||||
* Case 2. is handled via a BRK chk during transmission.
|
||||
* We set Status to EMS_TX_BRK_DETECT and return
|
||||
*
|
||||
*/
|
||||
|
||||
EMSUART_STATUS result = EMS_TX_STATUS_OK;
|
||||
|
||||
// disable rx interrupt
|
||||
// clear Rx status register, resetting the Rx FIFO and flush it
|
||||
ETS_UART_INTR_DISABLE();
|
||||
USC0(EMSUART_UART) |= (1 << UCRXRST);
|
||||
emsuart_flush_fifos();
|
||||
|
||||
// send the bytes along the serial line
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
uint16_t wdc = EMS_TX_TO_COUNT; // 1760
|
||||
volatile uint8_t _usrxc = (USS(EMSUART_UART) >> USRXC) & 0xFF;
|
||||
USF(EMSUART_UART) = buf[i]; // send each Tx byte
|
||||
// wait for echo from the busmaster
|
||||
while (((USS(EMSUART_UART) >> USRXC) & 0xFF) == _usrxc) {
|
||||
delayMicroseconds(EMSUART_BUSY_WAIT); // burn CPU cycles...
|
||||
if (--wdc == 0) {
|
||||
ETS_UART_INTR_ENABLE();
|
||||
return EMS_TX_WTD_TIMEOUT;
|
||||
}
|
||||
if (USIR(EMSUART_UART) & (1 << UIBD)) {
|
||||
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
|
||||
ETS_UART_INTR_ENABLE();
|
||||
return 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) {
|
||||
// neither bus collision nor timeout - send terminating BRK signal
|
||||
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_BIT_TIME);
|
||||
}
|
||||
|
||||
USC0(EMSUART_UART) &= ~((1 << UCBRK) | (1 << UCLBE)); // disable loopback & clear <BRK>
|
||||
USIC(EMSUART_UART) = (1 << UIBD); // clear BRK detect IRQ
|
||||
phantomBreak = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ETS_UART_INTR_ENABLE(); // open up the FIFO again to start receiving
|
||||
|
||||
return result; // send the Tx status back
|
||||
}
|
||||
|
||||
/*
|
||||
* flush everything left over in buffer, this clears both rx and tx FIFOs
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR EMSuart::emsuart_flush_fifos() {
|
||||
uint32_t tmp = ((1 << UCRXRST) | (1 << UCTXRST)); // bit mask
|
||||
USC0(EMSUART_UART) |= (tmp); // set bits
|
||||
USC0(EMSUART_UART) &= ~(tmp); // clear bits
|
||||
}
|
||||
|
||||
/*
|
||||
* 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))
|
||||
;
|
||||
|
||||
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);
|
||||
USC0(EMSUART_UART) |= (tmp); // set bit
|
||||
|
||||
if (tx_mode_ == EMS_TX_WTD_TIMEOUT) { // EMS+ mode
|
||||
delayMicroseconds(EMSUART_TX_BRK_WAIT);
|
||||
} else if (tx_mode_ == EMS_TXMODE_HT3) { // junkers mode
|
||||
delayMicroseconds(EMSUART_TX_WAIT_BRK - EMSUART_TX_LAG); // 1144 (11 Bits)
|
||||
}
|
||||
|
||||
USC0(EMSUART_UART) &= ~(tmp); // clear bit
|
||||
}
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
|
||||
@@ -31,11 +31,23 @@
|
||||
#define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra 2 for BRKs
|
||||
|
||||
#define EMSUART_recvTaskPrio 1 // 0, 1 or 2. 0 being the lowest
|
||||
#define EMSUART_recvTaskQueueLen 10 // number of queued'd Rx triggers
|
||||
#define EMSUART_recvTaskQueueLen 10 // number of queued Rx triggers
|
||||
|
||||
#define EMS_TXMODE_DEFAULT 1
|
||||
#define EMS_TXMODE_EMSPLUS 2
|
||||
#define EMS_TXMODE_HT3 3
|
||||
#define EMS_TXMODE_NEW 4 // for michael
|
||||
|
||||
// LEGACY
|
||||
#define EMSUART_BIT_TIME 104 // bit time @9600 baud
|
||||
#define EMSUART_TX_BRK_WAIT 2070 // the BRK from Boiler master is roughly 1.039ms, so accounting for hardware lag using around 2078 (for half-duplex) - 8 (lag)
|
||||
#define EMSUART_TX_WAIT_BYTE (EMSUART_BIT_TIME * 10) // Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit)
|
||||
#define EMSUART_TX_WAIT_BRK (EMSUART_BIT_TIME * 11) // Time to send a BRK Signal (11 Bit)
|
||||
#define EMSUART_TX_WAIT_GAP (EMSUART_BIT_TIME * 7) // Gap between to Bytes
|
||||
#define EMSUART_TX_LAG 8
|
||||
#define EMSUART_BUSY_WAIT (EMSUART_BIT_TIME / 8)
|
||||
#define EMS_TX_TO_CHARS (2 + 20)
|
||||
#define EMS_TX_TO_COUNT ((EMS_TX_TO_CHARS)*10 * 8)
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
@@ -64,6 +76,9 @@ class EMSuart {
|
||||
private:
|
||||
static void ICACHE_RAM_ATTR emsuart_rx_intr_handler(void * para);
|
||||
static void ICACHE_FLASH_ATTR emsuart_recvTask(os_event_t * events);
|
||||
|
||||
static void ICACHE_FLASH_ATTR emsuart_flush_fifos();
|
||||
static void ICACHE_FLASH_ATTR tx_brk();
|
||||
};
|
||||
|
||||
} // namespace emsesp
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "2.0.0a7"
|
||||
#define EMSESP_APP_VERSION "2.0.0a8"
|
||||
|
||||
Reference in New Issue
Block a user