Remove and expand macros.h

This commit is contained in:
2026-05-27 12:57:34 +00:00
parent 0bdb599afe
commit 05da21c4f3
4 changed files with 194 additions and 171 deletions
-129
View File
@@ -1,129 +0,0 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include "esphome/core/log.h"
#define PARENS ()
// Rescan macro tokens 256 times
#define EXPAND(...) EXPAND4(EXPAND4(EXPAND4(EXPAND4(__VA_ARGS__))))
#define EXPAND4(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__))))
#define EXPAND3(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__))))
#define EXPAND2(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__))))
#define EXPAND1(...) __VA_ARGS__
#define FOR_EACH(macro, name, ...) \
__VA_OPT__(EXPAND(FOR_EACH_HELPER(macro, name, __VA_ARGS__)))
#define FOR_EACH_HELPER(macro, name, a1, ...) \
macro(name, a1) \
__VA_OPT__(FOR_EACH_AGAIN PARENS(macro, name, __VA_ARGS__))
#define FOR_EACH_AGAIN() FOR_EACH_HELPER
#define ENUM_VARIANT0(name, val) name = val,
#define ENUM_VARIANT(name, tuple) ENUM_VARIANT0 tuple
#define TUPLE(x, y) x, y
#define LPAREN (
#define TO_STRING_IF0(type, name, val) \
if (_e == type::name) \
return #name;
#define TO_STRING_IF(type, tuple) TO_STRING_IF0 LPAREN type, TUPLE tuple)
#define FROM_INT_CASE0(type, name, val) \
case val: \
return type::name;
#define FROM_INT_CASE(type, tuple) FROM_INT_CASE0 LPAREN type, TUPLE tuple)
// String blob helpers for packed enum-to-string lookup tables
#define STR_BLOB_ENTRY0(type, name, val) #name "\0"
#define STR_BLOB_ENTRY(type, tuple) STR_BLOB_ENTRY0 LPAREN type, TUPLE tuple)
#define COUNT_ONE0(type, name, val) +1
#define COUNT_ONE(name, tuple) COUNT_ONE0 LPAREN name, TUPLE tuple)
namespace esphome::ratgdo {
namespace detail {
template <size_t N>
struct EnumStringOffsets {
uint8_t data[N];
};
template <size_t Count, size_t BlobSize>
constexpr EnumStringOffsets<Count> compute_enum_string_offsets(const char (&blob)[BlobSize])
{
EnumStringOffsets<Count> result { };
result.data[0] = 0;
size_t entry = 1;
for (size_t i = 0; i < BlobSize - 1 && entry < Count; ++i) {
if (blob[i] == '\0') {
result.data[entry++] = static_cast<uint8_t>(i + 1);
}
}
return result;
}
} // namespace detail
} // namespace esphome::ratgdo
// Platform-specific helpers for enum string return types
#define ENUM_STR_RET const char*
#define ENUM_STR_UNKNOWN "UNKNOWN"
#define ENUM_BLOB_ATTR
#define ENUM_BLOB_RETURN(blob, offset) (&(blob)[offset])
// ENUM: packed string blob with O(1) offset lookup (for contiguous 0-based enums with uint8_t type)
#define ENUM(name, type, ...) \
enum class name : type { \
FOR_EACH(ENUM_VARIANT, name, __VA_ARGS__) \
}; \
static_assert(sizeof(type) == 1, "ENUM() requires uint8_t type; use ENUM_SPARSE() for wider types"); \
inline ENUM_STR_RET \
name##_to_string(name _e) \
{ \
static constexpr size_t _n = (0 FOR_EACH(COUNT_ONE, name, __VA_ARGS__)); \
static const char _b[] ENUM_BLOB_ATTR = FOR_EACH(STR_BLOB_ENTRY, name, __VA_ARGS__); \
static_assert(sizeof(_b) <= 256, "ENUM() string blob exceeds 255 bytes; use shorter names"); \
static constexpr auto _o = ::esphome::ratgdo::detail::compute_enum_string_offsets<_n>( \
FOR_EACH(STR_BLOB_ENTRY, name, __VA_ARGS__)); \
auto _i = static_cast<uint8_t>(_e); \
if (_i >= _n) \
return ENUM_STR_UNKNOWN; \
return ENUM_BLOB_RETURN(_b, _o.data[_i]); \
} \
inline name \
to_##name(type _t, name _unknown) \
{ \
switch (_t) { \
FOR_EACH(FROM_INT_CASE, name, __VA_ARGS__) \
default: \
return _unknown; \
} \
}
// ENUM_SPARSE: if-chain lookup (for non-contiguous enum values, avoids CSWTCH)
#define ENUM_SPARSE(name, type, ...) \
enum class name : type { \
FOR_EACH(ENUM_VARIANT, name, __VA_ARGS__) \
}; \
inline ENUM_STR_RET \
name##_to_string(name _e) \
{ \
FOR_EACH(TO_STRING_IF, name, __VA_ARGS__) \
return ENUM_STR_UNKNOWN; \
} \
inline name \
to_##name(type _t, name _unknown) \
{ \
switch (_t) { \
FOR_EACH(FROM_INT_CASE, name, __VA_ARGS__) \
default: \
return _unknown; \
} \
}
+1 -1
View File
@@ -22,7 +22,7 @@
#include <utility>
#include "callbacks.h"
#include "macros.h"
#include "observable.h"
#include "protocol.h"
#include "ratgdo_state.h"
+157 -31
View File
@@ -13,50 +13,176 @@
#pragma once
#include "esphome/core/defines.h"
#include "macros.h"
#include <cstdint>
namespace esphome::ratgdo {
ENUM(DoorState, uint8_t,
(UNKNOWN, 0),
(OPEN, 1),
(CLOSED, 2),
(STOPPED, 3),
(OPENING, 4),
(CLOSING, 5))
enum class DoorState : uint8_t {
UNKNOWN = 0,
OPEN = 1,
CLOSED = 2,
STOPPED = 3,
OPENING = 4,
CLOSING = 5
};
inline const char* DoorState_to_string(DoorState e) {
switch (e) {
case DoorState::UNKNOWN: return "UNKNOWN";
case DoorState::OPEN: return "OPEN";
case DoorState::CLOSED: return "CLOSED";
case DoorState::STOPPED: return "STOPPED";
case DoorState::OPENING: return "OPENING";
case DoorState::CLOSING: return "CLOSING";
default: return "UNKNOWN";
}
}
inline DoorState to_DoorState(uint8_t t, DoorState unknown) {
switch (t) {
case static_cast<uint8_t>(DoorState::UNKNOWN): return DoorState::UNKNOWN;
case static_cast<uint8_t>(DoorState::OPEN): return DoorState::OPEN;
case static_cast<uint8_t>(DoorState::CLOSED): return DoorState::CLOSED;
case static_cast<uint8_t>(DoorState::STOPPED): return DoorState::STOPPED;
case static_cast<uint8_t>(DoorState::OPENING): return DoorState::OPENING;
case static_cast<uint8_t>(DoorState::CLOSING): return DoorState::CLOSING;
default: return unknown;
}
}
/// Enum for all states a the light can be in.
ENUM(LightState, uint8_t,
(OFF, 0),
(ON, 1),
(UNKNOWN, 2))
enum class LightState : uint8_t {
OFF = 0,
ON = 1,
UNKNOWN = 2
};
inline const char* LightState_to_string(LightState e) {
switch (e) {
case LightState::OFF: return "OFF";
case LightState::ON: return "ON";
case LightState::UNKNOWN: return "UNKNOWN";
default: return "UNKNOWN";
}
}
inline LightState to_LightState(uint8_t t, LightState unknown) {
switch (t) {
case static_cast<uint8_t>(LightState::OFF): return LightState::OFF;
case static_cast<uint8_t>(LightState::ON): return LightState::ON;
case static_cast<uint8_t>(LightState::UNKNOWN): return LightState::UNKNOWN;
default: return unknown;
}
}
LightState light_state_toggle(LightState state);
/// Enum for all states a the lock can be in.
ENUM(LockState, uint8_t,
(UNLOCKED, 0),
(LOCKED, 1),
(UNKNOWN, 2))
enum class LockState : uint8_t {
UNLOCKED = 0,
LOCKED = 1,
UNKNOWN = 2
};
inline const char* LockState_to_string(LockState e) {
switch (e) {
case LockState::UNLOCKED: return "UNLOCKED";
case LockState::LOCKED: return "LOCKED";
case LockState::UNKNOWN: return "UNKNOWN";
default: return "UNKNOWN";
}
}
inline LockState to_LockState(uint8_t t, LockState unknown) {
switch (t) {
case static_cast<uint8_t>(LockState::UNLOCKED): return LockState::UNLOCKED;
case static_cast<uint8_t>(LockState::LOCKED): return LockState::LOCKED;
case static_cast<uint8_t>(LockState::UNKNOWN): return LockState::UNKNOWN;
default: return unknown;
}
}
// actions
ENUM(LightAction, uint8_t,
(OFF, 0),
(ON, 1),
(TOGGLE, 2),
(UNKNOWN, 3))
enum class LightAction : uint8_t {
OFF = 0,
ON = 1,
TOGGLE = 2,
UNKNOWN = 3
};
ENUM(LockAction, uint8_t,
(UNLOCK, 0),
(LOCK, 1),
(UNKNOWN, 3))
inline const char* LightAction_to_string(LightAction e) {
switch (e) {
case LightAction::OFF: return "OFF";
case LightAction::ON: return "ON";
case LightAction::TOGGLE: return "TOGGLE";
case LightAction::UNKNOWN: return "UNKNOWN";
default: return "UNKNOWN";
}
}
ENUM(DoorAction, uint8_t,
(CLOSE, 0),
(OPEN, 1),
(TOGGLE, 2),
(STOP, 3),
(UNKNOWN, 4))
inline LightAction to_LightAction(uint8_t t, LightAction unknown) {
switch (t) {
case static_cast<uint8_t>(LightAction::OFF): return LightAction::OFF;
case static_cast<uint8_t>(LightAction::ON): return LightAction::ON;
case static_cast<uint8_t>(LightAction::TOGGLE): return LightAction::TOGGLE;
case static_cast<uint8_t>(LightAction::UNKNOWN): return LightAction::UNKNOWN;
default: return unknown;
}
}
enum class LockAction : uint8_t {
UNLOCK = 0,
LOCK = 1,
UNKNOWN = 3
};
inline const char* LockAction_to_string(LockAction e) {
switch (e) {
case LockAction::UNLOCK: return "UNLOCK";
case LockAction::LOCK: return "LOCK";
case LockAction::UNKNOWN: return "UNKNOWN";
default: return "UNKNOWN";
}
}
inline LockAction to_LockAction(uint8_t t, LockAction unknown) {
switch (t) {
case static_cast<uint8_t>(LockAction::UNLOCK): return LockAction::UNLOCK;
case static_cast<uint8_t>(LockAction::LOCK): return LockAction::LOCK;
case static_cast<uint8_t>(LockAction::UNKNOWN): return LockAction::UNKNOWN;
default: return unknown;
}
}
enum class DoorAction : uint8_t {
CLOSE = 0,
OPEN = 1,
TOGGLE = 2,
STOP = 3,
UNKNOWN = 4
};
inline const char* DoorAction_to_string(DoorAction e) {
switch (e) {
case DoorAction::CLOSE: return "CLOSE";
case DoorAction::OPEN: return "OPEN";
case DoorAction::TOGGLE: return "TOGGLE";
case DoorAction::STOP: return "STOP";
case DoorAction::UNKNOWN: return "UNKNOWN";
default: return "UNKNOWN";
}
}
inline DoorAction to_DoorAction(uint8_t t, DoorAction unknown) {
switch (t) {
case static_cast<uint8_t>(DoorAction::CLOSE): return DoorAction::CLOSE;
case static_cast<uint8_t>(DoorAction::OPEN): return DoorAction::OPEN;
case static_cast<uint8_t>(DoorAction::TOGGLE): return DoorAction::TOGGLE;
case static_cast<uint8_t>(DoorAction::STOP): return DoorAction::STOP;
case static_cast<uint8_t>(DoorAction::UNKNOWN): return DoorAction::UNKNOWN;
default: return unknown;
}
}
struct Openings {
uint16_t count;
+36 -10
View File
@@ -28,18 +28,44 @@ namespace secplus2 {
static const uint8_t PACKET_LENGTH = 19;
typedef uint8_t WirePacket[PACKET_LENGTH];
ENUM_SPARSE(CommandType, uint16_t,
(UNKNOWN, 0x000),
(GET_STATUS, 0x080),
(STATUS, 0x081),
enum class CommandType : uint16_t {
UNKNOWN = 0x000,
GET_STATUS = 0x080,
STATUS = 0x081,
LOCK = 0x18c,
DOOR_ACTION = 0x280,
LIGHT = 0x281,
GET_OPENINGS = 0x48b,
OPENINGS = 0x48c // openings = (byte1<<8)+byte2
};
(LOCK, 0x18c),
(DOOR_ACTION, 0x280),
(LIGHT, 0x281),
inline const char* CommandType_to_string(CommandType e) {
switch (e) {
case CommandType::UNKNOWN: return "UNKNOWN";
case CommandType::GET_STATUS: return "GET_STATUS";
case CommandType::STATUS: return "STATUS";
case CommandType::LOCK: return "LOCK";
case CommandType::DOOR_ACTION: return "DOOR_ACTION";
case CommandType::LIGHT: return "LIGHT";
case CommandType::GET_OPENINGS: return "GET_OPENINGS";
case CommandType::OPENINGS: return "OPENINGS";
default: return "UNKNOWN";
}
}
(GET_OPENINGS, 0x48b),
(OPENINGS, 0x48c), // openings = (byte1<<8)+byte2
)
inline CommandType to_CommandType(uint16_t t, CommandType unknown) {
switch (t) {
case static_cast<uint16_t>(CommandType::UNKNOWN): return CommandType::UNKNOWN;
case static_cast<uint16_t>(CommandType::GET_STATUS): return CommandType::GET_STATUS;
case static_cast<uint16_t>(CommandType::STATUS): return CommandType::STATUS;
case static_cast<uint16_t>(CommandType::LOCK): return CommandType::LOCK;
case static_cast<uint16_t>(CommandType::DOOR_ACTION): return CommandType::DOOR_ACTION;
case static_cast<uint16_t>(CommandType::LIGHT): return CommandType::LIGHT;
case static_cast<uint16_t>(CommandType::GET_OPENINGS): return CommandType::GET_OPENINGS;
case static_cast<uint16_t>(CommandType::OPENINGS): return CommandType::OPENINGS;
default: return unknown;
}
}
inline bool operator==(const uint16_t cmd_i, const CommandType& cmd_e) { return cmd_i == static_cast<uint16_t>(cmd_e); }
inline bool operator==(const CommandType& cmd_e, const uint16_t cmd_i) { return cmd_i == static_cast<uint16_t>(cmd_e); }