From d8bbdb504a6a6f3d74d27da4792c3e36269ff4df Mon Sep 17 00:00:00 2001 From: proddy Date: Wed, 23 Sep 2020 19:27:45 +0200 Subject: [PATCH] option to set how booleans are rendered - #509 --- CHANGELOG.md | 8 +++-- .../src/project/EMSESPSettingsController.tsx | 14 +++++++++ interface/src/project/EMSESPtypes.ts | 1 + lib_standalone/ESP8266React.h | 1 + src/EMSESPSettingsService.cpp | 7 +++-- src/EMSESPSettingsService.h | 2 ++ src/emsdevice.h | 1 + src/helpers.cpp | 31 ++++++++++++++----- src/helpers.h | 23 +++++++++++--- src/system.cpp | 17 ++++++++-- src/system.h | 1 + 11 files changed, 84 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96e270fa4..1a5fc13ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [2.1] ### Added -- boiler heatingactivated, automatic select parameter telegrams for write -- boiler wWType parameter, in Console and MQTT +- boiler `heatingactivated`, automatic select parameter telegrams for write +- boiler `wWType` parameter, in Console and MQTT - support for uploading compressed firmware binaries in web UI - setting to manually override the MQTT retain flag -- New API via HTTP REST API. See https://emsesp.github.io/docs/#/API +- New API via HTTP REST API to read and set values. See https://emsesp.github.io/docs/#/API - `show commands` command +- exporting of system settings using the `system info` command in Web and Console. Added link into the Web's Settings page. +- setting to change how booleans are rendered in MQTT (on/off, true/false, 1/0) ### Fixed - fix wwontime readback diff --git a/interface/src/project/EMSESPSettingsController.tsx b/interface/src/project/EMSESPSettingsController.tsx index f8be4938a..b633ff984 100644 --- a/interface/src/project/EMSESPSettingsController.tsx +++ b/interface/src/project/EMSESPSettingsController.tsx @@ -14,6 +14,8 @@ import { EMSESPSettings } from './EMSESPtypes'; export const EMSESP_SETTINGS_ENDPOINT = ENDPOINT_ROOT + "emsespSettings"; +export const WebAPISystemInfo = window.location.origin + "/api?device=system&cmd=info"; + type EMSESPSettingsControllerProps = RestControllerProps; class EMSESPSettingsController extends Component { @@ -49,6 +51,7 @@ function EMSESPSettingsControllerForm(props: EMSESPSettingsControllerFormProps) Customize EMS-ESP by modifying the default settings here. Refer to the {'Documentation'} for descriptions of each setting. +

You can also {'export'}  all the system settings to make a backup.



@@ -194,6 +197,17 @@ function EMSESPSettingsControllerForm(props: EMSESPSettingsControllerFormProps) } label="Enable WEB API (for write commands)" /> + + on/off + true/false + 1/0 +

Syslog diff --git a/interface/src/project/EMSESPtypes.ts b/interface/src/project/EMSESPtypes.ts index 861ff81fa..f3d58086c 100644 --- a/interface/src/project/EMSESPtypes.ts +++ b/interface/src/project/EMSESPtypes.ts @@ -14,6 +14,7 @@ export interface EMSESPSettings { led_gpio: number; hide_led: boolean; api_enabled: boolean; + bool_format: number; } export enum busConnectionStatus { diff --git a/lib_standalone/ESP8266React.h b/lib_standalone/ESP8266React.h index 36e2e6851..d990bdeaa 100644 --- a/lib_standalone/ESP8266React.h +++ b/lib_standalone/ESP8266React.h @@ -44,6 +44,7 @@ class DummySettings { uint16_t publish_time_mixing; uint16_t publish_time_other; uint16_t publish_time_sensor; + uint8_t bool_format; static void read(DummySettings & settings, JsonObject & root){}; static void read(DummySettings & settings){}; diff --git a/src/EMSESPSettingsService.cpp b/src/EMSESPSettingsService.cpp index 7541fdb32..ae6ed3248 100644 --- a/src/EMSESPSettingsService.cpp +++ b/src/EMSESPSettingsService.cpp @@ -43,6 +43,7 @@ void EMSESPSettings::read(EMSESPSettings & settings, JsonObject & root) { root["led_gpio"] = settings.led_gpio; root["hide_led"] = settings.hide_led; root["api_enabled"] = settings.api_enabled; + root["bool_format"] = settings.bool_format; } StateUpdateResult EMSESPSettings::update(JsonObject & root, EMSESPSettings & settings) { @@ -61,6 +62,7 @@ StateUpdateResult EMSESPSettings::update(JsonObject & root, EMSESPSettings & set settings.led_gpio = root["led_gpio"] | EMSESP_DEFAULT_LED_GPIO; settings.hide_led = root["hide_led"] | EMSESP_DEFAULT_HIDE_LED; settings.api_enabled = root["api_enabled"] | EMSESP_DEFAULT_API_ENABLED; + settings.bool_format = root["bool_format"] | EMSESP_DEFAULT_BOOL_FORMAT; return StateUpdateResult::CHANGED; } @@ -69,11 +71,10 @@ StateUpdateResult EMSESPSettings::update(JsonObject & root, EMSESPSettings & set // either via the Web UI or via the Console void EMSESPSettingsService::onUpdate() { EMSESP::shower_.start(); - // EMSESP::system_.syslog_init(); // changing SysLog will require a restart - EMSESP::init_tx(); - System::set_led(); Sensor sensor_; // Dallas sensors sensor_.start(); + + System::init(); } void EMSESPSettingsService::begin() { diff --git a/src/EMSESPSettingsService.h b/src/EMSESPSettingsService.h index 7be982e6c..9a104024b 100644 --- a/src/EMSESPSettingsService.h +++ b/src/EMSESPSettingsService.h @@ -36,6 +36,7 @@ #define EMSESP_DEFAULT_HIDE_LED false #define EMSESP_DEFAULT_DALLAS_PARASITE false #define EMSESP_DEFAULT_API_ENABLED true +#define EMSESP_DEFAULT_BOOL_FORMAT 1 // on/off // Default GPIO PIN definitions #if defined(ESP8266) @@ -77,6 +78,7 @@ class EMSESPSettings { uint8_t led_gpio; bool hide_led; bool api_enabled; + uint8_t bool_format; static void read(EMSESPSettings & settings, JsonObject & root); static StateUpdateResult update(JsonObject & root, EMSESPSettings & settings); diff --git a/src/emsdevice.h b/src/emsdevice.h index e5bd45cd5..a97af672a 100644 --- a/src/emsdevice.h +++ b/src/emsdevice.h @@ -156,6 +156,7 @@ class EMSdevice { // format: // for ints its 0=no division, 255=handle as boolean, other divide by the value given and render with a decimal point // for floats its the precision in number of decimal places from 0 to 8 + // for bools its EMS_VALUE_BOOL (0xFF) template static void print_value(uuid::console::Shell & shell, uint8_t padding, diff --git a/src/helpers.cpp b/src/helpers.cpp index 529098bbb..e0731bf90 100644 --- a/src/helpers.cpp +++ b/src/helpers.cpp @@ -20,6 +20,8 @@ namespace emsesp { +uint8_t Helpers::bool_format_ = 1; // on/off + // like itoa but for hex, and quicker char * Helpers::hextoa(char * result, const uint8_t value) { char * p = result; @@ -120,17 +122,28 @@ char * Helpers::smallitoa(char * result, const uint16_t value) { return result; } +// work out how to display booleans +void Helpers::render_boolean(char * result, bool value) { + if (bool_format() == 1) { + strlcpy(result, value ? "on" : "off", 5); + } else if (bool_format() == 2) { + strlcpy(result, value ? "true" : "false", 7); + } else { + strlcpy(result, value ? "1" : "0", 2); + } +} + // convert unsigned int (single byte) to text value and returns it -// format: 255=boolean, 0=no formatting, otherwise divide by format +// format: 255(0xFF)=boolean, 0=no formatting, otherwise divide by format char * Helpers::render_value(char * result, uint8_t value, uint8_t format) { // special check if its a boolean if (format == EMS_VALUE_BOOL) { if (value == EMS_VALUE_BOOL_OFF) { - strlcpy(result, "off", 5); + render_boolean(result, false); } else if (value == EMS_VALUE_BOOL_NOTSET) { return nullptr; } else { - strlcpy(result, "on", 5); // assume on. could have value 0x01 or 0xFF + render_boolean(result, true); // assume on. could have value 0x01 or 0xFF } return result; } @@ -169,9 +182,11 @@ char * Helpers::render_value(char * result, const float value, const uint8_t for char * ret = result; long whole = (long)value; Helpers::itoa(result, whole, 10); + while (*result != '\0') { result++; } + *result++ = '.'; long decimal = abs((long)((value - whole) * p[format])); itoa(result, decimal, 10); @@ -329,27 +344,27 @@ bool Helpers::check_abs(const int32_t i) { } // for booleans, use isBool true (EMS_VALUE_BOOL) -bool Helpers::hasValue(const uint8_t &v, const uint8_t isBool) { +bool Helpers::hasValue(const uint8_t & v, const uint8_t isBool) { if (isBool == EMS_VALUE_BOOL) { return (v != EMS_VALUE_BOOL_NOTSET); } return (v != EMS_VALUE_UINT_NOTSET); } -bool Helpers::hasValue(const int8_t &v) { +bool Helpers::hasValue(const int8_t & v) { return (v != EMS_VALUE_INT_NOTSET); } // for short these are typically 0x8300, 0x7D00 and sometimes 0x8000 -bool Helpers::hasValue(const int16_t &v) { +bool Helpers::hasValue(const int16_t & v) { return (abs(v) < EMS_VALUE_USHORT_NOTSET); } -bool Helpers::hasValue(const uint16_t &v) { +bool Helpers::hasValue(const uint16_t & v) { return (v < EMS_VALUE_USHORT_NOTSET); } -bool Helpers::hasValue(const uint32_t &v) { +bool Helpers::hasValue(const uint32_t & v) { return (v != EMS_VALUE_ULONG_NOTSET); } diff --git a/src/helpers.h b/src/helpers.h index 3f32f1b21..ee526becc 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -38,6 +38,8 @@ class Helpers { static char * render_value(char * result, const uint32_t value, const uint8_t format); static char * render_value(char * result, const int16_t value, const uint8_t format); + static void render_boolean(char * result, bool value); + static char * smallitoa(char * result, const uint8_t value); static char * smallitoa(char * result, const uint16_t value); static char * itoa(char * result, int16_t value, const uint8_t base = 10); @@ -46,15 +48,23 @@ class Helpers { static bool check_abs(const int32_t i); static double round2(double value); + static void bool_format(uint8_t bool_format) { + bool_format_ = bool_format; + } + + static uint8_t bool_format() { + return bool_format_; + } + #ifdef EMSESP_STANDALONE static char * ultostr(char * ptr, uint32_t value, const uint8_t base); #endif - static bool hasValue(const uint8_t &v, const uint8_t isBool = 0); - static bool hasValue(const int8_t &v); - static bool hasValue(const int16_t &v); - static bool hasValue(const uint16_t &v); - static bool hasValue(const uint32_t &v); + static bool hasValue(const uint8_t & v, const uint8_t isBool = 0); + static bool hasValue(const int8_t & v); + static bool hasValue(const int16_t & v); + static bool hasValue(const uint16_t & v); + static bool hasValue(const uint32_t & v); static std::string toLower(std::string const & s); @@ -62,6 +72,9 @@ class Helpers { static bool value2float(const char * v, float & value); static bool value2bool(const char * v, bool & value); static bool value2string(const char * v, std::string & value); + + private: + static uint8_t bool_format_; }; } // namespace emsesp diff --git a/src/system.cpp b/src/system.cpp index 3ec036244..1f651084a 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -152,9 +152,6 @@ void System::start() { EMSESP::esp8266React.getWiFiSettingsService()->read( [&](WiFiSettings & wifiSettings) { LOG_INFO(F("System %s booted (EMS-ESP version %s)"), wifiSettings.hostname.c_str(), EMSESP_APP_VERSION); }); - syslog_init(); // init SysLog - set_led(); // init LED - // these commands respond to the topic "system" and take a payload like {cmd:"", data:"", id:""} EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) { Command::add(EMSdevice::DeviceType::SYSTEM, settings.ems_bus_id, F("pin"), System::command_pin); @@ -162,6 +159,18 @@ void System::start() { Command::add_with_json(EMSdevice::DeviceType::SYSTEM, F("info"), System::command_info); }); + syslog_init(); // init SysLog + + init(); +} + +// init stuff. This is called when settings are changed in the web +void System::init() { + set_led(); // init LED + + // set the boolean format used for rendering booleans + EMSESP::emsespSettingsService.read([&](EMSESPSettings & settings) { Helpers::bool_format(settings.bool_format); }); + EMSESP::init_tx(); // start UART } @@ -897,6 +906,8 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp node["dallas_parasite"] = settings.dallas_parasite; node["led_gpio"] = settings.led_gpio; node["hide_led"] = settings.hide_led; + node["api_enabled"] = settings.api_enabled; + node["bool_format"] = settings.bool_format; }); #endif diff --git a/src/system.h b/src/system.h index e23931512..991f70deb 100644 --- a/src/system.h +++ b/src/system.h @@ -57,6 +57,7 @@ class System { static bool upload_status(); static void show_mem(const char * note); static void set_led(); + static void init(); bool check_upgrade(); void syslog_init();