Add Home Assistant controls over MQTT
Upgrade ArduinoHA from 1.3.0 to 2.1.0 and rewrite mqtt.ino for it. The clock now shows up in Home Assistant (discovery prefix "homeassistant") with: - switches Tubes (blank the display, runtime only) and Auto dim - numbers Day/Night brightness - light Backlight (on/off, brightness, RGB mapped to the colour wheel) - select LED effect, button Cathode protect - sensors Light (LDR) and WiFi signal, plus the upstream sensors when the clock has them; master-clock subscriptions are kept Settings changed from HA are saved to EEPROM 3 s after the last change. Fixes the unbounded memcpy in the MQTT message handler. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0d3e878051
commit
9a7061383c
108 files changed
+11482
-6567
No files matched your search
@@ -0,0 +1,214 @@
|
||||
#include "HANumeric.h"
|
||||
|
||||
const uint8_t HANumeric::MaxDigitsNb = 19;
|
||||
|
||||
HANumeric HANumeric::fromStr(const uint8_t* buffer, const uint16_t length)
|
||||
{
|
||||
if (length == 0) {
|
||||
return HANumeric();
|
||||
}
|
||||
|
||||
const uint8_t* firstCh = &buffer[0];
|
||||
int64_t out = 0;
|
||||
bool isSigned = false;
|
||||
|
||||
if (*firstCh == '-') {
|
||||
isSigned = true;
|
||||
firstCh++;
|
||||
}
|
||||
|
||||
uint8_t digitsNb = isSigned ? length - 1 : length;
|
||||
if (digitsNb > MaxDigitsNb) {
|
||||
return HANumeric();
|
||||
}
|
||||
|
||||
uint64_t base = 1;
|
||||
const uint8_t* ptr = &buffer[length - 1];
|
||||
|
||||
while (ptr >= firstCh) {
|
||||
uint8_t digit = *ptr - '0';
|
||||
if (digit > 9) {
|
||||
return HANumeric();
|
||||
}
|
||||
|
||||
out += digit * base;
|
||||
ptr--;
|
||||
base *= 10;
|
||||
}
|
||||
|
||||
return HANumeric(isSigned ? out * -1 : out);
|
||||
}
|
||||
|
||||
HANumeric::HANumeric():
|
||||
_isSet(false),
|
||||
_value(0),
|
||||
_precision(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HANumeric::HANumeric(const float value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * static_cast<float>(getPrecisionBase());
|
||||
}
|
||||
|
||||
HANumeric::HANumeric(const int8_t value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * static_cast<int32_t>(getPrecisionBase());
|
||||
}
|
||||
|
||||
HANumeric::HANumeric(const int16_t value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * static_cast<int32_t>(getPrecisionBase());
|
||||
}
|
||||
|
||||
HANumeric::HANumeric(const int32_t value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * static_cast<int32_t>(getPrecisionBase());
|
||||
}
|
||||
|
||||
HANumeric::HANumeric(const uint8_t value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * getPrecisionBase();
|
||||
}
|
||||
|
||||
HANumeric::HANumeric(const uint16_t value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * getPrecisionBase();
|
||||
}
|
||||
|
||||
HANumeric::HANumeric(const uint32_t value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * getPrecisionBase();
|
||||
}
|
||||
|
||||
#ifdef ARDUINOHA_INT_OVERLOAD
|
||||
HANumeric::HANumeric(const int value, const uint8_t precision):
|
||||
_isSet(true),
|
||||
_precision(precision)
|
||||
{
|
||||
_value = value * static_cast<int>(getPrecisionBase());
|
||||
}
|
||||
#endif
|
||||
|
||||
HANumeric::HANumeric(const int64_t value):
|
||||
_isSet(true),
|
||||
_value(value),
|
||||
_precision(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t HANumeric::getPrecisionBase() const
|
||||
{
|
||||
// using pow() increases the flash size by ~2KB
|
||||
switch (_precision) {
|
||||
case 1:
|
||||
return 10;
|
||||
|
||||
case 2:
|
||||
return 100;
|
||||
|
||||
case 3:
|
||||
return 1000;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t HANumeric::calculateSize() const
|
||||
{
|
||||
if (!_isSet) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t value = _value;
|
||||
const bool isSigned = value < 0;
|
||||
|
||||
if (isSigned) {
|
||||
value *= -1;
|
||||
}
|
||||
|
||||
uint8_t digitsNb = 1;
|
||||
while (value > 9) {
|
||||
value /= 10;
|
||||
digitsNb++;
|
||||
}
|
||||
|
||||
if (isSigned) {
|
||||
digitsNb++; // sign
|
||||
}
|
||||
|
||||
if (_precision > 0) {
|
||||
if (value == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// one digit + dot + decimal digits (+ sign)
|
||||
const uint8_t minValue = isSigned ? _precision + 3 : _precision + 2;
|
||||
return digitsNb >= minValue ? digitsNb + 1 : minValue;
|
||||
}
|
||||
|
||||
return digitsNb;
|
||||
}
|
||||
|
||||
uint16_t HANumeric::toStr(char* dst) const
|
||||
{
|
||||
char* prefixCh = &dst[0];
|
||||
if (!_isSet || _value == 0) {
|
||||
*prefixCh = '0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
int64_t value = _value;
|
||||
const uint8_t numberLength = calculateSize();
|
||||
if (value < 0) {
|
||||
value *= -1;
|
||||
*prefixCh = '-';
|
||||
prefixCh++;
|
||||
}
|
||||
|
||||
if (_precision > 0) {
|
||||
uint8_t i = _precision;
|
||||
char* dotPtr = prefixCh + 1;
|
||||
do {
|
||||
*prefixCh = '0';
|
||||
prefixCh++;
|
||||
} while(i-- > 0);
|
||||
|
||||
*dotPtr = '.';
|
||||
}
|
||||
|
||||
char* ch = &dst[numberLength - 1];
|
||||
char* lastCh = ch;
|
||||
char* dotPos = _precision > 0 ? &dst[numberLength - 1 - _precision] : nullptr;
|
||||
|
||||
while (value != 0) {
|
||||
if (ch == dotPos) {
|
||||
*dotPos = '.';
|
||||
ch--;
|
||||
continue;
|
||||
}
|
||||
|
||||
*ch = (value % 10) + '0';
|
||||
value /= 10;
|
||||
ch--;
|
||||
}
|
||||
|
||||
return lastCh - &dst[0] + 1;
|
||||
}
|
||||
Reference in new issue
Block a user