From 38961d722d1e88207b6f28a20bfe1b86610f23c5 Mon Sep 17 00:00:00 2001 From: Dawid Chyrzynski Date: Sun, 6 Dec 2020 12:55:36 +0100 Subject: [PATCH] add support for units of measurement in the HASensor --- src/HAMqtt.cpp | 5 --- src/HAMqtt.h | 5 --- src/device-types/BaseDeviceType.cpp | 2 +- src/device-types/HASensor.cpp | 52 ++++++++++++++++++++++++----- src/device-types/HASensor.h | 9 +++++ 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/src/HAMqtt.cpp b/src/HAMqtt.cpp index 6944734..b905e5e 100644 --- a/src/HAMqtt.cpp +++ b/src/HAMqtt.cpp @@ -113,11 +113,6 @@ void HAMqtt::addDeviceType(BaseDeviceType* deviceType) } } -void HAMqtt::removeDeviceType(BaseDeviceType* deviceType) -{ - // todo: remove device from the list -} - bool HAMqtt::publish(const char* topic, const char* payload, bool retained) { if (!isConnected()) { diff --git a/src/HAMqtt.h b/src/HAMqtt.h index 2fcda77..9d6f0f9 100644 --- a/src/HAMqtt.h +++ b/src/HAMqtt.h @@ -73,11 +73,6 @@ public: */ void addDeviceType(BaseDeviceType* deviceType); - /** - * Removes device's type from the MQTT. - */ - void removeDeviceType(BaseDeviceType* deviceType); - /** * Publishes MQTT message with given topic and payload. * Message won't be published if connection with MQTT broker is not established. diff --git a/src/device-types/BaseDeviceType.cpp b/src/device-types/BaseDeviceType.cpp index 9aff833..5aadb1f 100644 --- a/src/device-types/BaseDeviceType.cpp +++ b/src/device-types/BaseDeviceType.cpp @@ -13,7 +13,7 @@ BaseDeviceType::BaseDeviceType(HAMqtt& mqtt) : BaseDeviceType::~BaseDeviceType() { - _mqtt.removeDeviceType(this); + } uint16_t BaseDeviceType::calculateTopicLength( diff --git a/src/device-types/HASensor.cpp b/src/device-types/HASensor.cpp index 067c330..2226416 100644 --- a/src/device-types/HASensor.cpp +++ b/src/device-types/HASensor.cpp @@ -1,5 +1,3 @@ -#ifndef NO_HA_SENSOR - #include "HASensor.h" #include "../ArduinoHADefines.h" #include "../HAMqtt.h" @@ -19,6 +17,7 @@ HASensor::HASensor( BaseDeviceType(mqtt), _name(name), _class(nullptr), + _units(nullptr), _valueType(HAUtils::determineValueType()), _currentValue(initialValue) { @@ -35,6 +34,7 @@ HASensor::HASensor( BaseDeviceType(mqtt), _name(name), _class(deviceClass), + _units(nullptr), _valueType(HAUtils::determineValueType()), _currentValue(initialValue) { @@ -66,6 +66,10 @@ bool HASensor::setValue(T value) return false; } + if (_currentValue == value) { + return true; + } + if (publishValue(value)) { _currentValue = value; return true; @@ -193,6 +197,11 @@ uint16_t HASensor::calculateSerializedLength( size += strlen(_class) + 13; // 13 - length of the JSON data for this field } + // units of measurement + if (_units != nullptr) { + size += strlen(_units) + 18; + } + // device size += strlen(serializedDevice) + 7; // 7 - length of the JSON data for this field @@ -282,6 +291,15 @@ bool HASensor::writeSerializedTrigger(const char* serializedDevice) const mqtt()->writePayload_P(QuotationSign); } + // units of measurement + if (_units != nullptr) { + static const char DataBefore[] PROGMEM = {",\"unit_of_meas\":\""}; + + mqtt()->writePayload_P(DataBefore); + mqtt()->writePayload(_units, strlen(_units)); + mqtt()->writePayload_P(QuotationSign); + } + { static const char Data[] PROGMEM = {"}"}; mqtt()->writePayload_P(Data); @@ -297,21 +315,40 @@ uint16_t HASensor::calculateValueLength() const return 0; } + uint16_t size = 0; + switch (_valueType) { case HAUtils::ValueTypeUint8: + size = 3; // from 0 to 255 + break; + case HAUtils::ValueTypeUint16: + size = 5; // from 0 to 65535 + break; + case HAUtils::ValueTypeUint32: + size = 10; // from 0 to 4294967295 + break; + case HAUtils::ValueTypeInt8: + size = 4; // from -128 to 127 + break; + case HAUtils::ValueTypeInt16: + size = 6; // from -32768 to 32767 + break; + case HAUtils::ValueTypeInt32: - return (HAUtils::getValueTypeLength(_valueType) * 3) + 1; // 3 digits per byte + null terminator + size = 11; // from -2147483648 to 2147483647 + break; case HAUtils::ValueTypeDouble: case HAUtils::ValueTypeFloat: - return (HAUtils::getValueTypeLength(_valueType) * 3) + 4; // 3 digits per byte + dot separator + 2 precision digits + null terminator + // 3 digits per byte + dot separator + 2 precision digits + return (HAUtils::getValueTypeLength(_valueType) * 3) + 3; } - return 0; + return (size > 0 ? (size + 1) : 0); } template @@ -328,15 +365,14 @@ bool HASensor::valueToStr(char* dst, T value) const case HAUtils::ValueTypeInt8: case HAUtils::ValueTypeInt16: case HAUtils::ValueTypeInt32: - sprintf(dst, "%d", value); + itoa(value, dst, 10); break; case HAUtils::ValueTypeDouble: + case HAUtils::ValueTypeFloat: dtostrf(value, 0, 2, dst); break; } return true; } - -#endif diff --git a/src/device-types/HASensor.h b/src/device-types/HASensor.h index 7969fef..5c721c2 100644 --- a/src/device-types/HASensor.h +++ b/src/device-types/HASensor.h @@ -61,6 +61,14 @@ public: inline T getValue() const { return _currentValue; } + /** + * Defines the units of measurement of the sensor, if any. + * + * @param units For example: °C, % + */ + inline void setUnitOfMeasurement(const char* units) + { _units = units; } + private: void publishConfig(); bool publishValue(T value); @@ -71,6 +79,7 @@ private: const char* _name; const char* _class; + const char* _units; HAUtils::ValueType _valueType; T _currentValue; };