mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 00:09:51 +03:00
Merge branch 'v2' of https://github.com/proddy/EMS-ESP into v2
This commit is contained in:
@@ -61,7 +61,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] [pretty | raw] [trace ID]
|
||||
log [level]
|
||||
su
|
||||
|
||||
(top root level)
|
||||
@@ -86,6 +86,7 @@ ems
|
||||
show devices
|
||||
show emsbus
|
||||
show values
|
||||
watch <on | off | raw> [ID]
|
||||
|
||||
mqtt
|
||||
publish
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace uuid {
|
||||
namespace log {
|
||||
|
||||
char format_level_char(Level level) {
|
||||
constexpr char log_level_chars[(int)Level::ALL - (int)Level::OFF + 1] = {' ', 'P', 'A', 'C', 'E', 'W', 'N', 'I', 'T', 'D', ' '}; // changed by proddy
|
||||
constexpr char log_level_chars[(int)Level::ALL - (int)Level::OFF + 1] = {' ', 'P', 'A', 'C', 'E', 'W', 'N', 'I', 'D', 'T', ' '};
|
||||
return log_level_chars[(int)level + 1];
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_of
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_warning),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_notice),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_info),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_trace), // switched by proddy
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_debug),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_trace),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_lowercase_all)};
|
||||
|
||||
const __FlashStringHelper * format_level_lowercase(Level level) {
|
||||
|
||||
@@ -47,8 +47,8 @@ PROGMEM = {reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_of
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_warning),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_notice),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_info),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_trace), // switched by proddy
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_debug),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_trace),
|
||||
reinterpret_cast<const __FlashStringHelper *>(pstr_level_uppercase_all)};
|
||||
|
||||
const __FlashStringHelper * format_level_uppercase(Level level) {
|
||||
|
||||
@@ -33,8 +33,8 @@ std::vector<Level> levels() {
|
||||
Level::WARNING,
|
||||
Level::NOTICE,
|
||||
Level::INFO,
|
||||
Level::DEBUG,
|
||||
Level::TRACE,
|
||||
Level::DEBUG, // switched by proddy
|
||||
Level::ALL};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ std::vector<std::string> levels_lowercase() {
|
||||
uuid::read_flash_string(format_level_lowercase(Level::WARNING)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::NOTICE)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::INFO)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::TRACE)), // switched by proddy
|
||||
uuid::read_flash_string(format_level_lowercase(Level::DEBUG)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::TRACE)),
|
||||
uuid::read_flash_string(format_level_lowercase(Level::ALL))};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ std::vector<std::string> levels_uppercase() {
|
||||
uuid::read_flash_string(format_level_uppercase(Level::WARNING)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::NOTICE)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::INFO)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::TRACE)), // switched by proddy
|
||||
uuid::read_flash_string(format_level_uppercase(Level::DEBUG)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::TRACE)),
|
||||
uuid::read_flash_string(format_level_uppercase(Level::ALL))};
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace uuid {
|
||||
namespace log {
|
||||
|
||||
/**
|
||||
* Severity level of log messages. Proddy switches trace & debug
|
||||
* Severity level of log messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@@ -84,8 +84,8 @@ enum Level : int8_t {
|
||||
WARNING, /*!< Warning conditions. @since 1.0.0 */
|
||||
NOTICE, /*!< Normal but significant conditions. @since 1.0.0 */
|
||||
INFO, /*!< Informational messages. @since 1.0.0 */
|
||||
TRACE, /*!< Trace messages. @since 1.0.0 */
|
||||
DEBUG, /*!< Debug-level messages. @since 1.0.0 */
|
||||
TRACE, /*!< Trace messages. @since 1.0.0 */
|
||||
ALL, /*!< Meta level representing all log messages. @since 1.0.0 */
|
||||
};
|
||||
|
||||
|
||||
@@ -225,9 +225,8 @@ void Console::load_standard_commands(unsigned int context) {
|
||||
context,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(log)},
|
||||
flash_string_vector{F_(log_level_optional), F_(trace_format_optional), F_(traceid_optional)},
|
||||
flash_string_vector{F_(log_level_optional)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
uint16_t watch_id;
|
||||
if (!arguments.empty()) {
|
||||
uuid::log::Level level;
|
||||
|
||||
@@ -237,41 +236,10 @@ void Console::load_standard_commands(unsigned int context) {
|
||||
shell.printfln(F_(invalid_log_level));
|
||||
return;
|
||||
}
|
||||
|
||||
// trace logic
|
||||
if (level == uuid::log::Level::TRACE || level == uuid::log::Level::DEBUG) {
|
||||
watch_id = LOG_TRACE_WATCH_NONE; // no watch ID set
|
||||
if (arguments.size() > 1) {
|
||||
// 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_(pretty))) {
|
||||
emsesp::EMSESP::trace_raw(false);
|
||||
} else {
|
||||
emsesp::EMSESP::trace_watch_id(Helpers::hextoint(arguments[1].c_str()));
|
||||
}
|
||||
|
||||
// get the watch_id if its set
|
||||
if (arguments.size() == 3) {
|
||||
emsesp::EMSESP::trace_watch_id(Helpers::hextoint(arguments[2].c_str()));
|
||||
}
|
||||
} else {
|
||||
// it was "log trace" so reset the watch id and switch back to pretty
|
||||
emsesp::EMSESP::trace_raw(false);
|
||||
emsesp::EMSESP::trace_watch_id(LOG_TRACE_WATCH_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print out logging settings
|
||||
shell.printfln(F_(log_level_fmt), uuid::log::format_level_uppercase(shell.log_level()));
|
||||
watch_id = emsesp::EMSESP::trace_watch_id();
|
||||
if (watch_id == LOG_TRACE_WATCH_NONE) {
|
||||
shell.printfln(F("Tracing all telegrams"));
|
||||
} else {
|
||||
shell.printfln(F("Tracing only telegrams that match a device ID or telegram type of 0x%02X"), watch_id);
|
||||
}
|
||||
shell.printfln(F_(trace_raw_fmt), emsesp::EMSESP::trace_raw() ? F("as raw bytes") : F("in decoded format"));
|
||||
},
|
||||
[](Shell & shell __attribute__((unused)), const std::vector<std::string> & arguments __attribute__((unused))) -> std::vector<std::string> {
|
||||
return uuid::log::levels_lowercase();
|
||||
|
||||
@@ -42,8 +42,8 @@ using uuid::log::Level;
|
||||
// clang-format off
|
||||
|
||||
#define LOG_DEBUG(...) if (logger_.enabled(Level::DEBUG)) {logger_.debug(__VA_ARGS__);}
|
||||
#define LOG_TRACE(...) if (logger_.enabled(Level::TRACE)) {logger_.trace(__VA_ARGS__);}
|
||||
#define LOG_INFO(...) logger_.info(__VA_ARGS__)
|
||||
#define LOG_TRACE(...) logger_.trace(__VA_ARGS__)
|
||||
#define LOG_NOTICE(...) logger_.notice(__VA_ARGS__)
|
||||
#define LOG_WARNING(...) logger_.warning(__VA_ARGS__)
|
||||
#define LOG_ERROR(...) logger_.err(__VA_ARGS__)
|
||||
@@ -90,7 +90,7 @@ MAKE_PSTR_WORD(restart)
|
||||
MAKE_PSTR_WORD(reconnect)
|
||||
MAKE_PSTR_WORD(format)
|
||||
MAKE_PSTR_WORD(raw)
|
||||
MAKE_PSTR_WORD(pretty)
|
||||
MAKE_PSTR_WORD(watch)
|
||||
|
||||
// context menus
|
||||
MAKE_PSTR_WORD(mqtt)
|
||||
@@ -102,9 +102,6 @@ MAKE_PSTR(degrees_mandatory, "<degrees>")
|
||||
MAKE_PSTR(asterisks, "********")
|
||||
MAKE_PSTR(n_mandatory, "<n>")
|
||||
MAKE_PSTR(n_optional, "[n]")
|
||||
MAKE_PSTR(traceid_optional, "[trace ID]")
|
||||
MAKE_PSTR(trace_raw_fmt, "Displaying telegrams %s")
|
||||
MAKE_PSTR(trace_format_optional, "[pretty | raw]")
|
||||
MAKE_PSTR(bool_mandatory, "<on | off>")
|
||||
MAKE_PSTR(typeid_mandatory, "<type ID>")
|
||||
MAKE_PSTR(deviceid_mandatory, "<device ID>")
|
||||
|
||||
@@ -98,6 +98,7 @@
|
||||
{207, DeviceType::CONTROLLER, F("Sense II/CS200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x10
|
||||
{209, DeviceType::CONTROLLER, F("ErP"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
{218, DeviceType::CONTROLLER, F("M200/RFM200"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x50
|
||||
{224, DeviceType::CONTROLLER, F("Bosch 9000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
{230, DeviceType::CONTROLLER, F("BC Base"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
{241, DeviceType::CONTROLLER, F("Condens 5000i"), DeviceFlags::EMS_DEVICE_FLAG_NONE}, // 0x09
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
||||
// the telegram handlers...
|
||||
register_telegram_type(0x10, F("UBAErrorMessage1"), false, std::bind(&Boiler::process_UBAErrorMessage, this, _1));
|
||||
register_telegram_type(0x11, F("UBAErrorMessage2"), false, std::bind(&Boiler::process_UBAErrorMessage, this, _1));
|
||||
register_telegram_type(0x12, F("UBAErrorMessage3"), false, std::bind(&Boiler::process_UBAErrorMessage, this, _1));
|
||||
register_telegram_type(0x18, F("UBAMonitorFast"), false, std::bind(&Boiler::process_UBAMonitorFast, this, _1));
|
||||
register_telegram_type(0x19, F("UBAMonitorSlow"), true, std::bind(&Boiler::process_UBAMonitorSlow, this, _1));
|
||||
register_telegram_type(0x34, F("UBAMonitorWW"), false, std::bind(&Boiler::process_UBAMonitorWW, this, _1));
|
||||
|
||||
@@ -32,6 +32,10 @@ MAKE_PSTR(tx_mode_fmt, "Tx mode = %d")
|
||||
MAKE_PSTR(bus_id_fmt, "Bus ID = %02X")
|
||||
MAKE_PSTR(read_only_fmt, "Read-only mode is %s")
|
||||
|
||||
MAKE_PSTR(watchid_optional, "[ID]")
|
||||
MAKE_PSTR(watch_format_mandatory, "<off | on | raw>")
|
||||
MAKE_PSTR(invalid_watch, "Invalid watch type")
|
||||
|
||||
MAKE_PSTR(logger_name, "emsesp")
|
||||
|
||||
namespace emsesp {
|
||||
@@ -56,8 +60,8 @@ Shower EMSESP::shower_; // Shower logic
|
||||
|
||||
// static/common variables
|
||||
uint8_t EMSESP::actual_master_thermostat_ = EMSESP_DEFAULT_MASTER_THERMOSTAT; // which thermostat leads when multiple found
|
||||
uint16_t EMSESP::trace_watch_id_ = LOG_TRACE_WATCH_NONE; // for when log is TRACE. 0 means no trace set
|
||||
bool EMSESP::trace_raw_ = false; // not showing raw when in trace logging
|
||||
uint16_t EMSESP::watch_id_ = WATCH_NONE; // for when log is TRACE. 0 means no trace set
|
||||
uint8_t EMSESP::watch_ = 0; // trace off
|
||||
bool EMSESP::tap_water_active_ = false; // for when Boiler states we having running warm water. used in Shower()
|
||||
bool EMSESP::ems_read_only_;
|
||||
uint32_t EMSESP::last_fetch_ = 0;
|
||||
@@ -97,12 +101,12 @@ uint8_t EMSESP::actual_master_thermostat() {
|
||||
}
|
||||
|
||||
// to watch both type IDs and device IDs
|
||||
void EMSESP::trace_watch_id(uint16_t trace_watch_id) {
|
||||
void EMSESP::watch_id(uint16_t watch_id) {
|
||||
// if it's a device ID, which is a single byte, remove the MSB so to support both Buderus and HT3 protocols
|
||||
if (trace_watch_id <= 0xFF) {
|
||||
trace_watch_id_ = (trace_watch_id & 0x7F);
|
||||
if (watch_id <= 0xFF) {
|
||||
watch_id_ = (watch_id & 0x7F);
|
||||
} else {
|
||||
trace_watch_id_ = trace_watch_id;
|
||||
watch_id_ = watch_id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,10 +393,9 @@ void EMSESP::process_version(std::shared_ptr<const Telegram> telegram) {
|
||||
// We also check for common telgram types, like the Version(0x02)
|
||||
// returns false if there are none found
|
||||
bool EMSESP::process_telegram(std::shared_ptr<const Telegram> telegram) {
|
||||
if ((logger_.enabled(Level::TRACE)) && !trace_raw()) {
|
||||
if ((trace_watch_id_ == LOG_TRACE_WATCH_NONE) || (telegram->src == trace_watch_id_) || (telegram->dest == trace_watch_id_)
|
||||
|| (telegram->type_id == trace_watch_id_)) {
|
||||
LOG_TRACE(pretty_telegram(telegram).c_str());
|
||||
if (watch() == 1) {
|
||||
if ((watch_id_ == WATCH_NONE) || (telegram->src == watch_id_) || (telegram->dest == watch_id_) || (telegram->type_id == watch_id_)) {
|
||||
LOG_INFO(pretty_telegram(telegram).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,9 +571,9 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
if (((first_value & 0x7F) == txservice_.ems_bus_id()) && (length > 1)) {
|
||||
// if we ask ourself at roomcontrol for version e.g. 0B 98 02 00 20
|
||||
Roomctrl::check((data[1] ^ 0x80 ^ rxservice_.ems_mask()), data);
|
||||
//#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("Echo: %s"), Helpers::data_to_hex(data, length).c_str());
|
||||
//#endif
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("[DEBUG] Echo: %s"), Helpers::data_to_hex(data, length).c_str());
|
||||
#endif
|
||||
return; // it's an echo
|
||||
}
|
||||
|
||||
@@ -613,7 +616,7 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
|
||||
// So re-send the last Tx and increment retry count
|
||||
uint8_t retries = txservice_.retry_tx(); // returns 0 if exceeded count
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("Last Tx operation failed. Retry #%d. Sent: %s, received: %s"),
|
||||
LOG_DEBUG(F("[DEBUG] Last Tx operation failed. Retry #%d. Sent: %s, received: %s"),
|
||||
retries,
|
||||
txservice_.last_tx_to_string().c_str(),
|
||||
Helpers::data_to_hex(data, length).c_str());
|
||||
@@ -725,7 +728,6 @@ void EMSESP::console_commands(Shell & shell, unsigned int context) {
|
||||
flash_string_vector{F_(set), F_(tx_mode)},
|
||||
flash_string_vector{F_(n_mandatory)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
// uint8_t tx_mode = (arguments[0]).at(0) - '0';
|
||||
uint8_t tx_mode = std::strtol(arguments[0].c_str(), nullptr, 10);
|
||||
if ((tx_mode > 0) && (tx_mode <= 30)) {
|
||||
Settings settings;
|
||||
@@ -824,6 +826,50 @@ void EMSESP::console_commands(Shell & shell, unsigned int context) {
|
||||
shell.printfln(F_(read_only_fmt), settings.ems_read_only() ? F_(on) : F_(off));
|
||||
});
|
||||
|
||||
|
||||
|
||||
EMSESPShell::commands->add_command(ShellContext::EMS,
|
||||
CommandFlags::USER,
|
||||
flash_string_vector{F_(watch)},
|
||||
flash_string_vector{F_(watch_format_mandatory), F_(watchid_optional)},
|
||||
[](Shell & shell, const std::vector<std::string> & arguments) {
|
||||
// get raw/pretty
|
||||
if (arguments[0] == read_flash_string(F_(raw))) {
|
||||
emsesp::EMSESP::watch(2); // raw
|
||||
} else if (arguments[0] == read_flash_string(F_(on))) {
|
||||
emsesp::EMSESP::watch(1); // on
|
||||
} else if (arguments[0] == read_flash_string(F_(off))) {
|
||||
emsesp::EMSESP::watch(0); // off
|
||||
} else {
|
||||
shell.printfln(F_(invalid_watch));
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t watch_id;
|
||||
if (arguments.size() == 2) {
|
||||
// get the watch_id if its set
|
||||
watch_id = Helpers::hextoint(arguments[1].c_str());
|
||||
} else {
|
||||
watch_id = WATCH_NONE;
|
||||
}
|
||||
|
||||
emsesp::EMSESP::watch_id(watch_id);
|
||||
|
||||
uint8_t watch = emsesp::EMSESP::watch();
|
||||
if (watch == 0) {
|
||||
shell.printfln(F("Watch is off"));
|
||||
} else if (watch == 1) {
|
||||
shell.printfln(F("Watching incoming telegrams, displayed in decoded format"));
|
||||
} else {
|
||||
shell.printfln(F("Watching incoming telegrams, displayed as raw bytes"));
|
||||
}
|
||||
|
||||
watch_id = emsesp::EMSESP::watch_id();
|
||||
if (watch_id != WATCH_NONE) {
|
||||
shell.printfln(F("Filtering only telegrams that match a device ID or telegram type of 0x%02X"), watch_id);
|
||||
}
|
||||
});
|
||||
|
||||
// enter the context
|
||||
Console::enter_custom_context(shell, context);
|
||||
}
|
||||
@@ -839,7 +885,6 @@ void EMSESP::start() {
|
||||
network_.start();
|
||||
console_.start();
|
||||
sensors_.start();
|
||||
rxservice_.start();
|
||||
txservice_.start();
|
||||
shower_.start();
|
||||
mqtt_.start();
|
||||
|
||||
20
src/emsesp.h
20
src/emsesp.h
@@ -46,7 +46,7 @@
|
||||
|
||||
#include "devices/boiler.h"
|
||||
|
||||
#define LOG_TRACE_WATCH_NONE 0 // no watch id set
|
||||
#define WATCH_NONE 0 // no watch id set
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
@@ -99,18 +99,18 @@ class EMSESP {
|
||||
return sensors_.devices();
|
||||
}
|
||||
|
||||
static void trace_watch_id(uint16_t id);
|
||||
static void watch_id(uint16_t id);
|
||||
|
||||
static uint16_t trace_watch_id() {
|
||||
return trace_watch_id_;
|
||||
static uint16_t watch_id() {
|
||||
return watch_id_;
|
||||
}
|
||||
|
||||
static void trace_raw(bool trace_raw) {
|
||||
trace_raw_ = trace_raw;
|
||||
static void watch(uint8_t watch) {
|
||||
watch_ = watch; // 0=off, 1=on, 2=raw
|
||||
}
|
||||
|
||||
static bool trace_raw() {
|
||||
return trace_raw_;
|
||||
static uint8_t watch() {
|
||||
return watch_; // 0=off, 1=on, 2=raw
|
||||
}
|
||||
|
||||
static bool tap_water_active() {
|
||||
@@ -166,8 +166,8 @@ class EMSESP {
|
||||
static std::vector<Device_record> device_library_;
|
||||
|
||||
static uint8_t actual_master_thermostat_;
|
||||
static uint16_t trace_watch_id_;
|
||||
static bool trace_raw_;
|
||||
static uint16_t watch_id_;
|
||||
static uint8_t watch_;
|
||||
static bool tap_water_active_;
|
||||
static bool ems_read_only_;
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ char * Helpers::render_value(char * result, uint8_t value, uint8_t format) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
static char s2[5] = {0};
|
||||
char s2[5] = {0};
|
||||
|
||||
switch (format) {
|
||||
case 2:
|
||||
@@ -226,7 +226,7 @@ char * Helpers::render_value(char * result, const uint32_t value, const uint8_t
|
||||
return (result);
|
||||
}
|
||||
|
||||
static char s[20] = {0};
|
||||
char s[20] = {0};
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
if (format <= 1) {
|
||||
|
||||
@@ -340,7 +340,7 @@ void Mqtt::on_message(char * topic, char * payload, size_t len) {
|
||||
strlcpy(message, payload, len + 1);
|
||||
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("Received %s => %s (length %d)"), topic, message, len);
|
||||
LOG_DEBUG(F("[DEBUG] Received %s => %s (length %d)"), topic, message, len);
|
||||
#endif
|
||||
|
||||
// strip out everything until the last /
|
||||
|
||||
@@ -29,12 +29,7 @@
|
||||
#include "telegram.h"
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include "uart/emsuart_esp8266.h"
|
||||
#include <RTCVars.h>
|
||||
#elif defined(ESP32)
|
||||
#include "uart/emsuart_esp32.h"
|
||||
#elif defined(EMSESP_STANDALONE)
|
||||
#include <emsuart_standalone.h>
|
||||
#endif
|
||||
|
||||
#ifndef EMSESP_STANDALONE
|
||||
|
||||
170
src/telegram.cpp
170
src/telegram.cpp
@@ -68,8 +68,8 @@ Telegram::Telegram(uint8_t operation, uint8_t src, uint8_t dest, uint16_t type_i
|
||||
, type_id(type_id)
|
||||
, offset(offset)
|
||||
, message_length(message_length) {
|
||||
// copy complete telegram data over
|
||||
for (uint8_t i = 0; i < message_length; i++) {
|
||||
// copy complete telegram data over, preventing buffer overflow
|
||||
for (uint8_t i = 0; ((i < message_length) && (i != EMS_MAX_TELEGRAM_MESSAGE_LENGTH - 1)); i++) {
|
||||
message_data[i] = data[i];
|
||||
}
|
||||
}
|
||||
@@ -211,36 +211,26 @@ void RxService::flush_rx_queue() {
|
||||
rx_telegram_id_ = 0;
|
||||
}
|
||||
|
||||
// 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
|
||||
// processes all telegrams on the queue. Assumes there are valid (i.e. CRC checked)
|
||||
void RxService::loop() {
|
||||
/*
|
||||
#ifndef EMSESP_STANDALONE
|
||||
// give rx some breathing space
|
||||
//if ((uuid::get_uptime() - last_rx_check_) < RX_LOOP_WAIT) {
|
||||
// return;
|
||||
//}
|
||||
//last_rx_check_ = uuid::get_uptime();
|
||||
give rx some breathing space if ((uuid::get_uptime() - last_rx_check_) < RX_LOOP_WAIT) {
|
||||
return;
|
||||
}
|
||||
last_rx_check_ = uuid::get_uptime();
|
||||
#endif
|
||||
*/
|
||||
|
||||
while (!rx_telegrams_.empty()) {
|
||||
auto telegram = rx_telegrams_.front().telegram_;
|
||||
|
||||
// rx_telegrams_overflow_ = false;
|
||||
|
||||
(void)EMSESP::process_telegram(telegram); // further process the telegram
|
||||
|
||||
increment_telegram_count(); // increase count
|
||||
|
||||
// remove it from the queue
|
||||
// if (!rx_telegrams_overflow_) {
|
||||
rx_telegrams_.pop_front();
|
||||
// }
|
||||
rx_telegrams_.pop_front(); // remove it from the queue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,10 +239,15 @@ void RxService::loop() {
|
||||
// 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) {
|
||||
if (length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// validate the CRC
|
||||
uint8_t crc = calculate_crc(data, length - 1);
|
||||
if (data[length - 1] != crc) {
|
||||
LOG_TRACE(F("Rx: %s %s(BAD, CRC %02X != %02X)%s"), Helpers::data_to_hex(data, length).c_str(), COLOR_RED, data[length - 1], crc, COLOR_RESET);
|
||||
|
||||
if ((data[length - 1] != crc) && (EMSESP::watch() != 0)) {
|
||||
LOG_ERROR(F("Rx: %s %s(BAD, CRC %02X != %02X)%s"), Helpers::data_to_hex(data, length).c_str(), COLOR_RED, data[length - 1], crc, COLOR_RESET);
|
||||
increment_telegram_error_count();
|
||||
return;
|
||||
}
|
||||
@@ -270,43 +265,36 @@ 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 = 0; // this could be 2 bytes for ems+
|
||||
uint8_t * message_data;
|
||||
uint8_t message_length;
|
||||
// set default values, which will be adjusted depending on the EMS1.0/2.0 logic below
|
||||
uint16_t type_id = 0;
|
||||
uint8_t * message_data = data;
|
||||
uint8_t message_length = length;
|
||||
|
||||
// work out depending on the type where the data message block starts
|
||||
if (data[2] < 0xF0 || length < 6) {
|
||||
// EMS 1.0
|
||||
type_id = data[2];
|
||||
message_data = data + 4; // message block starts at 5th byte
|
||||
message_length = length - 5; // remove 4 bytes header plus CRC
|
||||
message_data += 4; // message block starts at 5th byte
|
||||
message_length -= 5; // remove 4 bytes header plus CRC
|
||||
} else {
|
||||
// EMS 2.0 / EMS+
|
||||
if (data[2] == 0xFF) {
|
||||
// check for empty data
|
||||
// special broadcast telegrams on ems+ have no data values, some even don't have a type ID, e.g. "21 0B FF 00"
|
||||
if (length <= 7) {
|
||||
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;
|
||||
if (length > 8) {
|
||||
message_length -= 7; // remove 6 byte header plus CRC
|
||||
message_data += 6; // message block starts at 7th position
|
||||
}
|
||||
} else {
|
||||
type_id = (data[4] << 8) + data[5] + 256;
|
||||
message_length = length - 7; // remove 6 byte header plus CRC
|
||||
message_data = data + 6; // message block starts at 7th position
|
||||
if (length > 5) {
|
||||
type_id = (data[4] << 8) + data[5] + 256; // set type_id if there is one
|
||||
}
|
||||
} else {
|
||||
// its F9 or F7
|
||||
uint8_t shift = (data[4] != 0xFF) ? 1 : 0; // true (1) if 5th byte is not 0xFF, then telegram is 1 byte longer
|
||||
type_id = (data[5 + shift] << 8) + data[6 + shift] + 256;
|
||||
message_data = data + 6 + shift; // there is a special byte after the typeID which we ignore for now
|
||||
if (length <= (9 + shift)) {
|
||||
message_length = 0; // special broadcast on ems+ have no data values
|
||||
} else {
|
||||
message_length = length - (9 + shift);
|
||||
message_data += 6 + shift; // there is a special byte after the typeID which we ignore for now
|
||||
if (length > (9 + shift)) {
|
||||
message_length -= (9 + shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -316,26 +304,27 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we're in "trace" and "raw" print out actual telegram as bytes to the console
|
||||
if (EMSESP::watch() == 2) {
|
||||
uint16_t trace_watch_id = EMSESP::watch_id();
|
||||
if ((trace_watch_id == WATCH_NONE) || (src == trace_watch_id) || (dest == trace_watch_id) || (type_id == trace_watch_id)) {
|
||||
LOG_INFO(F("Rx: %s"), Helpers::data_to_hex(data, length).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("[DEBUG] New Rx [#%d] telegram, message length %d"), rx_telegram_id_, message_length);
|
||||
#endif
|
||||
|
||||
// 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 so remove top item to make space
|
||||
if (rx_telegrams_.size() >= MAX_RX_TELEGRAMS) {
|
||||
// rx_telegrams_overflow_ = true;
|
||||
rx_telegrams_.pop_front();
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// if we're in "trace" and "raw" print out actual telegram as bytes to the console
|
||||
if (logger_.enabled(Level::TRACE) && EMSESP::trace_raw()) {
|
||||
uint16_t trace_watch_id = EMSESP::trace_watch_id();
|
||||
if ((trace_watch_id == LOG_TRACE_WATCH_NONE) || (src == trace_watch_id) || (dest == trace_watch_id) || (type_id == trace_watch_id)) {
|
||||
LOG_TRACE(F("Rx: %s"), Helpers::data_to_hex(data, length).c_str());
|
||||
}
|
||||
}
|
||||
rx_telegrams_.emplace_back(rx_telegram_id_++, std::move(telegram)); // add to queue
|
||||
}
|
||||
|
||||
|
||||
@@ -380,7 +369,7 @@ void TxService::loop() {
|
||||
|
||||
// sends a 1 byte poll which is our own device ID
|
||||
void TxService::send_poll() {
|
||||
//LOG_TRACE(F("Ack %02X"),ems_bus_id() ^ ems_mask());
|
||||
//LOG_DEBUG(F("Ack %02X"),ems_bus_id() ^ ems_mask());
|
||||
EMSuart::send_poll(ems_bus_id() ^ ems_mask());
|
||||
}
|
||||
|
||||
@@ -477,23 +466,18 @@ void TxService::send_telegram(const QueuedTxTelegram & tx_telegram) {
|
||||
tx_telegram.id_,
|
||||
telegram->to_string(telegram_raw, length).c_str());
|
||||
|
||||
// if we're watching an ID, then always show the full telegram
|
||||
if ((logger_.enabled(Level::TRACE))
|
||||
&& ((telegram->src == EMSESP::trace_watch_id()) || (telegram->dest == EMSESP::trace_watch_id()) || (telegram->type_id == EMSESP::trace_watch_id()))) {
|
||||
logger_.trace(F("Sending %s Tx [#%d], telegram: %s"),
|
||||
(telegram->operation == Telegram::Operation::TX_WRITE) ? F("write") : F("read"),
|
||||
tx_telegram.id_,
|
||||
telegram->to_string(telegram_raw, length).c_str());
|
||||
}
|
||||
|
||||
// send the telegram to the UART Tx
|
||||
uint16_t status = EMSuart::transmit(telegram_raw, length);
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_TRACE(F("Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str());
|
||||
// if watching in 'raw' mode
|
||||
if (EMSESP::watch() == 2) {
|
||||
LOG_INFO(F("[DEBUG] Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status != EMS_TX_STATUS_OK) {
|
||||
if (status == EMS_TX_STATUS_ERR) {
|
||||
LOG_ERROR(F("Failed to transmit Tx via UART."));
|
||||
increment_telegram_fail_count(); // another Tx fail
|
||||
tx_waiting(false); // nothing send, tx not in wait state
|
||||
return;
|
||||
}
|
||||
@@ -514,11 +498,15 @@ void TxService::send_telegram(const uint8_t * data, const uint8_t length) {
|
||||
|
||||
LOG_DEBUG(F("Sending Raw telegram: %s (length=%d)"), Helpers::data_to_hex(telegram_raw, length).c_str(), length);
|
||||
|
||||
tx_waiting(false); // no post validation
|
||||
|
||||
// send the telegram to the UART Tx
|
||||
uint16_t status = EMSuart::transmit(telegram_raw, length);
|
||||
//LOG_TRACE(F("Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str());
|
||||
if (status != EMS_TX_STATUS_OK) {
|
||||
LOG_ERROR(F("Failed to transmit Tx via UART"));
|
||||
//LOG_DEBUG(F("Tx: %s"), Helpers::data_to_hex(telegram_raw, length).c_str());
|
||||
|
||||
if (status == EMS_TX_STATUS_ERR) {
|
||||
LOG_ERROR(F("Failed to transmit Tx via UART."));
|
||||
increment_telegram_fail_count(); // another Tx fail
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,7 +514,9 @@ void TxService::send_telegram(const uint8_t * data, const uint8_t length) {
|
||||
// given some details like the destination, type, offset and message block
|
||||
void TxService::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) {
|
||||
auto telegram = std::make_shared<Telegram>(operation, ems_bus_id(), dest, type_id, offset, message_data, message_length);
|
||||
LOG_DEBUG(F("New Tx [#%d] telegram, length %d"), tx_telegram_id_, message_length);
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("[DEBUG] New Tx [#%d] telegram, length %d"), tx_telegram_id_, message_length);
|
||||
#endif
|
||||
|
||||
// if the queue is full, make room but removing the last one
|
||||
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
|
||||
@@ -537,14 +527,17 @@ void TxService::add(const uint8_t operation, const uint8_t dest, const uint16_t
|
||||
}
|
||||
|
||||
// builds a Tx telegram and adds to queue, using only raw data
|
||||
// format is EMS 1.0 (src, dest, type_id, offset, data)
|
||||
// length is the length of the whole telegram data
|
||||
void TxService::add(uint8_t * data, const uint8_t length) {
|
||||
uint8_t message_length = length - 4;
|
||||
if (!message_length) {
|
||||
LOG_ERROR(F("Bad Tx telegram, too short (message length is %d)"), message_length);
|
||||
// front = true if adding to the front of queue, e.g. with an Tx retry. Default is false.
|
||||
void TxService::add(uint8_t * data, const uint8_t length, bool front) {
|
||||
if (length < 5) {
|
||||
LOG_ERROR(F("Tx telegram too short (telegram length is %d)"), length);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t message_length = length - 4;
|
||||
|
||||
// build header
|
||||
uint8_t src = data[0];
|
||||
uint8_t dest = data[1];
|
||||
@@ -559,8 +552,16 @@ void TxService::add(uint8_t * data, const uint8_t length) {
|
||||
tx_telegrams_.pop_front();
|
||||
}
|
||||
|
||||
LOG_DEBUG(F("New Tx [#%d] telegram, length %d"), tx_telegram_id_, message_length);
|
||||
#ifdef EMSESP_DEBUG
|
||||
LOG_DEBUG(F("[DEBUG] New Tx [#%d] telegram, length %d"), tx_telegram_id_, message_length);
|
||||
#endif
|
||||
|
||||
// add to either front or back of queue
|
||||
if (front) {
|
||||
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram));
|
||||
} else {
|
||||
tx_telegrams_.emplace_back(tx_telegram_id_++, std::move(telegram));
|
||||
}
|
||||
}
|
||||
|
||||
// send a Tx telegram to request data from an EMS device
|
||||
@@ -626,25 +627,8 @@ uint8_t TxService::retry_tx() {
|
||||
increment_telegram_fail_count(); // another Tx fail
|
||||
return 0;
|
||||
}
|
||||
// if the queue is full, throw away
|
||||
if (tx_telegrams_.size() >= MAX_TX_TELEGRAMS) {
|
||||
reset_retry_count(); // give up
|
||||
increment_telegram_fail_count(); // another Tx fail
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t message_length = telegram_last_length_ - 4;
|
||||
|
||||
// build header
|
||||
uint8_t src = telegram_last_[0];
|
||||
uint8_t dest = telegram_last_[1];
|
||||
uint8_t type_id = telegram_last_[2];
|
||||
uint8_t offset = telegram_last_[3];
|
||||
uint8_t * message_data = telegram_last_ + 4;
|
||||
|
||||
auto telegram = std::make_shared<Telegram>(Telegram::Operation::TX_RAW, src, dest, type_id, offset, message_data, message_length);
|
||||
|
||||
tx_telegrams_.emplace_front(tx_telegram_id_++, std::move(telegram));
|
||||
add(telegram_last_, telegram_last_length_, true); // add the last Tx telegram to the front of the tx queue, at the top
|
||||
|
||||
return retry_count_;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,15 @@
|
||||
#include <deque>
|
||||
#include <memory> // for unique ptrs
|
||||
#include <vector>
|
||||
// #include <atomic> // for overflow
|
||||
|
||||
// UART drivers
|
||||
#if defined(ESP8266)
|
||||
#include "uart/emsuart_esp8266.h"
|
||||
#elif defined(ESP32)
|
||||
#include "uart/emsuart_esp32.h"
|
||||
#elif defined(EMSESP_STANDALONE)
|
||||
#include <emsuart_standalone.h>
|
||||
#endif
|
||||
|
||||
#include <uuid/log.h>
|
||||
|
||||
@@ -43,8 +51,8 @@ static constexpr int16_t EMS_VALUE_SHORT_INVALID = 0x8000;
|
||||
static constexpr uint32_t EMS_VALUE_ULONG_NOTSET = 0xFFFFFFFF; // for 3-byte and 4-byte longs
|
||||
static constexpr uint32_t EMS_VALUE_ULONG_INVALID = 0x80000000;
|
||||
|
||||
static constexpr uint8_t EMS_MAX_TELEGRAM_LENGTH = 32; // max length of a telegram
|
||||
static constexpr uint8_t EMS_MAX_TELEGRAM_MESSAGE_LENGTH = EMS_MAX_TELEGRAM_LENGTH - 5; // max length of message block
|
||||
static constexpr uint8_t EMS_MAX_TELEGRAM_LENGTH = 32; // max length of a complete EMS telegram
|
||||
static constexpr uint8_t EMS_MAX_TELEGRAM_MESSAGE_LENGTH = 27; // max length of message block, assuming EMS1.0
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
@@ -170,7 +178,6 @@ class RxService : public EMSbus {
|
||||
RxService() = default;
|
||||
~RxService() = default;
|
||||
|
||||
void start();
|
||||
void loop();
|
||||
|
||||
void add(uint8_t * data, uint8_t length);
|
||||
@@ -210,7 +217,6 @@ class RxService : public EMSbus {
|
||||
static constexpr uint32_t RX_LOOP_WAIT = 800; // delay in processing Rx queue
|
||||
uint32_t last_rx_check_ = 0;
|
||||
|
||||
// std::atomic<bool> rx_telegrams_overflow_{false};
|
||||
uint8_t rx_telegram_id_ = 0; // queue counter
|
||||
|
||||
uint16_t telegram_count_ = 0; // # Rx received
|
||||
@@ -234,7 +240,7 @@ class TxService : public EMSbus {
|
||||
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);
|
||||
void add(uint8_t * data, const uint8_t length);
|
||||
void add(uint8_t * data, const uint8_t length, bool front = false);
|
||||
|
||||
void read_request(const uint16_t type_id, const uint8_t dest, const uint8_t offset = 0);
|
||||
|
||||
|
||||
@@ -122,7 +122,12 @@ void EMSuart::start(uint8_t tx_mode) {
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
};
|
||||
}
|
||||
if (tx_mode_ == 5) {
|
||||
EMS_UART.conf0.stop_bit_num = UART_STOP_BITS_1_5;
|
||||
} else {
|
||||
EMS_UART.conf0.stop_bit_num = UART_STOP_BITS_1;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(uart_param_config(EMSUART_UART, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(EMSUART_UART, EMSUART_TXPIN, EMSUART_RXPIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
@@ -161,7 +166,12 @@ void EMSuart::restart() {
|
||||
EMS_UART.int_ena.brk_det = 1; // activate only break
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = 0;
|
||||
};
|
||||
if (tx_mode_ == 5) {
|
||||
EMS_UART.conf0.stop_bit_num = UART_STOP_BITS_1_5;
|
||||
} else {
|
||||
EMS_UART.conf0.stop_bit_num = UART_STOP_BITS_1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sends a 1-byte poll, ending with a <BRK>
|
||||
@@ -186,7 +196,7 @@ void EMSuart::send_poll(uint8_t data) {
|
||||
*/
|
||||
uint16_t EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
if (len == 0 || len > 32) {
|
||||
return EMS_TX_STATUS_ERROR;
|
||||
return EMS_TX_STATUS_ERR;
|
||||
}
|
||||
if (tx_mode_ == EMS_TXMODE_NEW || tx_mode_ == 5) {
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
namespace emsesp {
|
||||
|
||||
#define EMS_TX_STATUS_OK 1
|
||||
#define EMS_TX_STATUS_ERROR 0
|
||||
#define EMS_TX_STATUS_ERR 0
|
||||
|
||||
class EMSuart {
|
||||
public:
|
||||
|
||||
@@ -35,6 +35,7 @@ uint8_t phantomBreak = 0;
|
||||
uint8_t tx_mode_ = 0xFF;
|
||||
bool drop_next_rx = true;
|
||||
uint32_t emsRxTime;
|
||||
// uint32_t emsTxTime = 0;
|
||||
uint8_t emsTxBuf[EMS_MAXBUFFERSIZE];
|
||||
uint8_t emsTxBufIdx;
|
||||
uint8_t emsTxBufLen;
|
||||
@@ -88,7 +89,10 @@ void ICACHE_FLASH_ATTR EMSuart::emsuart_recvTask(os_event_t * events) {
|
||||
phantomBreak = 0;
|
||||
length--; // remove phantom break from Rx buffer
|
||||
}
|
||||
|
||||
// if (emsTxTime > 0) {
|
||||
// LOG_INFO(F("tx duration: %d ms"), uuid::get_uptime() - emsTxTime);
|
||||
// emsTxTime = 0;
|
||||
// }
|
||||
// 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);
|
||||
@@ -124,7 +128,7 @@ void ICACHE_RAM_ATTR EMSuart::emsuart_tx_timer_intr_handler() {
|
||||
} else if (emsTxBufIdx == emsTxBufLen) {
|
||||
USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
|
||||
if (tx_mode_ > 5 || tx_mode_ < 11) {
|
||||
timer1_write(5 * EMSUART_TX_BIT_TIME * 11);
|
||||
timer1_write(5 * EMSUART_TX_BIT_TIME * 12);
|
||||
USIE(EMSUART_UART) &= ~(1 << UIBD); // disable break interrupt
|
||||
}
|
||||
} else if (USC0(EMSUART_UART) & (1 << UCBRK)) {
|
||||
@@ -259,9 +263,9 @@ void ICACHE_FLASH_ATTR EMSuart::tx_brk() {
|
||||
USC0(EMSUART_UART) |= (1 << UCBRK); // set bit
|
||||
|
||||
if (tx_mode_ == EMS_TXMODE_EMSPLUS) { // EMS+ mode
|
||||
delayMicroseconds(EMSUART_TX_BRK_WAIT); // 2070
|
||||
} else if (tx_mode_ == EMS_TXMODE_HT3) { // junkers mode
|
||||
delayMicroseconds(EMSUART_TX_BRK_WAIT_HT3); // 1144
|
||||
delayMicroseconds(EMSUART_TX_WAIT_PLUS); // 2070
|
||||
} else { // junkers and EMS1.0
|
||||
delayMicroseconds(EMSUART_TX_WAIT_BRK); // 1144
|
||||
}
|
||||
|
||||
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear BRK bit
|
||||
@@ -283,10 +287,17 @@ void EMSuart::send_poll(uint8_t data) {
|
||||
} else if (tx_mode_ >= EMS_TXMODE_NEW) { // hardware controlled modes
|
||||
USF(EMSUART_UART) = data;
|
||||
USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK> at the end
|
||||
} else { // software controlled modes
|
||||
// EMS1.0, EMS+ and HT3
|
||||
} else if (tx_mode_ == EMS_TXMODE_HT3) {
|
||||
USF(EMSUART_UART) = data;
|
||||
delayMicroseconds(EMSUART_TX_BRK_WAIT);
|
||||
delayMicroseconds(EMSUART_TX_WAIT_HT3);
|
||||
tx_brk(); // send <BRK>
|
||||
} else if (tx_mode_ == EMS_TXMODE_EMSPLUS) {
|
||||
USF(EMSUART_UART) = data;
|
||||
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
|
||||
tx_brk(); // send <BRK>
|
||||
} else { // EMS1.0
|
||||
USF(EMSUART_UART) = data;
|
||||
delayMicroseconds(EMSUART_TX_WAIT_BRK);
|
||||
tx_brk(); // send <BRK>
|
||||
}
|
||||
}
|
||||
@@ -303,6 +314,7 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
#ifdef EMSESP_DEBUG
|
||||
// LOG_INFO(F("[DEBUG] UART Response time: %d ms"), uuid::get_uptime() - emsRxTime);
|
||||
#endif
|
||||
// emsTxTime = uuid::get_uptime();
|
||||
// if ((uuid::get_uptime() - emsRxTime) > EMS_RX_TO_TX_TIMEOUT)) { // send allowed within 20 ms
|
||||
// return EMS_TX_STATUS_ERR;
|
||||
// }
|
||||
@@ -317,6 +329,8 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
emsTxBufIdx = 0;
|
||||
emsTxBufLen = len;
|
||||
USF(EMSUART_UART) = buf[0];
|
||||
// timer1_attachInterrupt(emsuart_tx_timer_intr_handler); // Add ISR Function
|
||||
// timer1_enable(TIM_DIV16, TIM_EDGE, TIM_SINGLE); // 5 MHz timer
|
||||
timer1_write(emsTxWait);
|
||||
return EMS_TX_STATUS_OK;
|
||||
}
|
||||
@@ -334,7 +348,7 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
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
|
||||
delayMicroseconds(EMSUART_TX_WAIT_PLUS); // 2070
|
||||
}
|
||||
tx_brk(); // send <BRK>
|
||||
return EMS_TX_STATUS_OK;
|
||||
@@ -350,7 +364,7 @@ uint16_t ICACHE_FLASH_ATTR EMSuart::transmit(uint8_t * buf, uint8_t len) {
|
||||
;
|
||||
|
||||
// wait until bits are sent on wire
|
||||
delayMicroseconds(EMSUART_TX_BRK_WAIT_HT3);
|
||||
delayMicroseconds(EMSUART_TX_WAIT_HT3);
|
||||
}
|
||||
tx_brk(); // send <BRK>
|
||||
return EMS_TX_STATUS_OK;
|
||||
|
||||
@@ -42,13 +42,16 @@
|
||||
|
||||
// LEGACY
|
||||
#define EMSUART_TX_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_BRK (EMSUART_TX_BIT_TIME * 11) // 1144
|
||||
|
||||
// EMS 1.0
|
||||
#define EMSUART_TX_BUSY_WAIT (EMSUART_TX_BIT_TIME / 8) // 13
|
||||
|
||||
// HT3/Junkers - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit). The -8 is for lag compensation.
|
||||
#define EMSUART_TX_BRK_WAIT_HT3 (EMSUART_TX_BIT_TIME * 11) - 8 // 1136
|
||||
// HT3/Junkers - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) plus 7 bit delay. The -8 is for lag compensation.
|
||||
#define EMSUART_TX_WAIT_HT3 (EMSUART_TX_BIT_TIME * 17) - 8 // 1760
|
||||
|
||||
// EMS+ - Time to send one Byte (8 Bits, 1 Start Bit, 1 Stop Bit) and delay of another Bytetime.
|
||||
#define EMSUART_TX_WAIT_PLUS 2070
|
||||
|
||||
namespace emsesp {
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "2.0.0a17"
|
||||
#define EMSESP_APP_VERSION "2.0.0a18"
|
||||
|
||||
Reference in New Issue
Block a user