Remove and expand macros.h
This commit is contained in:
@@ -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; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "macros.h"
|
||||
|
||||
#include "observable.h"
|
||||
#include "protocol.h"
|
||||
#include "ratgdo_state.h"
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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); }
|
||||
|
||||
Reference in New Issue
Block a user