#ifndef SET_PROTOCOL_H #define SET_PROTOCOL_H #include #include #include #ifdef __cplusplus extern "C" { #endif #define SETP_VERSION 0x02U #define SETP_SOF0 0xA5U #define SETP_SOF1 0x5AU #define SETP_HEADER_SIZE 14U #define SETP_CRC_SIZE 4U #ifndef SETP_MAX_PAYLOAD #define SETP_MAX_PAYLOAD 512U #endif #define SETP_FRAME_MAX (SETP_HEADER_SIZE + SETP_MAX_PAYLOAD + SETP_CRC_SIZE) #define SETP_NODE_LOCAL 0x0000U #define SETP_NODE_BROADCAST 0xFFFFU #define SETP_DEVICE_INFO_SCHEMA_VERSION 1U #define SETP_DEVICE_INFO_FIXED_SIZE 25U #define SETP_DEVICE_MODEL_MAX 63U #define SETP_CAPABILITIES_SCHEMA_VERSION 1U #define SETP_CAPABILITIES_SIZE 20U /* Frame flags. Reserved bits must be transmitted as zero. */ #define SETP_FLAG_RESPONSE 0x01U #define SETP_FLAG_EVENT 0x02U #define SETP_FLAG_ERROR 0x04U #define SETP_FLAG_ACK_REQUIRED 0x08U #define SETP_FLAG_MORE 0x10U #define SETP_FLAG_PRIORITY 0x20U #define SETP_FLAG_KNOWN_MASK 0x3FU #define SETP_FLAG_RESERVED_MASK 0xC0U typedef enum { SETP_IFACE_NONE = 0, SETP_IFACE_RS232 = 1, SETP_IFACE_RS485 = 2, SETP_IFACE_CAN = 3, SETP_IFACE_USB_CDC = 4, SETP_IFACE_ETHERNET_TCP = 5, SETP_IFACE_ETHERNET_UDP = 6 } setp_iface_t; typedef enum { SETP_MSG_PING = 0x0001, SETP_MSG_DEVICE_INFO = 0x0002, SETP_MSG_CAPABILITIES = 0x0003, SETP_MSG_DIAGNOSTICS = 0x0008, SETP_MSG_READ = 0x0009, SETP_MSG_WRITE = 0x000A, SETP_MSG_LOG_READ = 0x0010, SETP_MSG_CATALOG = 0x0011, SETP_MSG_SUBSCRIBE = 0x0012, SETP_MSG_PUBLISH = 0x0013, SETP_MSG_UNSUBSCRIBE = 0x0014, SETP_MSG_FW_BEGIN = 0x0100, SETP_MSG_FW_DATA = 0x0101, SETP_MSG_FW_END = 0x0102, SETP_MSG_FW_ABORT = 0x0103, SETP_MSG_FW_STATUS = 0x0104, SETP_MSG_FW_ACTIVATE = 0x0105, SETP_MSG_DEVICE_BASE = 0x1000, SETP_MSG_DEVICE_LAST = 0x7FFF } setp_message_type_t; typedef enum { SETP_STATUS_OK = 0, SETP_STATUS_INVALID_ARGUMENT = 1, SETP_STATUS_INVALID_LENGTH = 2, SETP_STATUS_NOT_FOUND = 3, SETP_STATUS_ACCESS_DENIED = 4, SETP_STATUS_BUSY = 5, SETP_STATUS_NO_PROVIDER = 6, SETP_STATUS_INTERNAL = 7, SETP_STATUS_CRC = 8, SETP_STATUS_SEQUENCE = 9, SETP_STATUS_NO_SPACE = 10, SETP_STATUS_UNSUPPORTED = 11, SETP_STATUS_VERIFY_FAILED = 12, SETP_STATUS_AUTH_FAILED = 13, SETP_STATUS_TIMEOUT = 14, SETP_STATUS_WRONG_STATE = 15 } setp_status_t; /* CAPABILITIES feature_flags. */ #define SETP_FEATURE_READ (1UL << 0) #define SETP_FEATURE_WRITE (1UL << 1) #define SETP_FEATURE_CATALOG (1UL << 2) #define SETP_FEATURE_SUBSCRIBE (1UL << 3) #define SETP_FEATURE_LOG_READ (1UL << 4) #define SETP_FEATURE_FIRMWARE (1UL << 5) #define SETP_FEATURE_DIAGNOSTICS (1UL << 6) /* CAPABILITIES interface_mask; bit index equals setp_iface_t. */ #define SETP_IFACE_MASK(iface) (1UL << (uint32_t)(iface)) typedef struct { uint16_t schema_version; uint16_t device_class; uint32_t hardware_version; uint32_t firmware_version; uint32_t dictionary_version; uint64_t serial_number; uint8_t model_length; const uint8_t *model; } setp_device_info_t; typedef struct { uint16_t schema_version; uint16_t max_payload; uint32_t interface_mask; uint32_t feature_flags; uint16_t max_read_items; uint16_t max_write_items; uint16_t max_subscriptions; uint16_t max_publish_items; } setp_capabilities_t; typedef struct { uint8_t flags; uint16_t message_type; uint16_t source; uint16_t destination; uint16_t sequence; uint16_t payload_length; const uint8_t *payload; } setp_frame_t; typedef struct { uint32_t frames; uint32_t crc_errors; uint32_t version_errors; uint32_t length_errors; uint32_t flag_errors; uint32_t stray_bytes; uint32_t overflows; } setp_parser_stats_t; typedef struct { uint8_t buffer[SETP_FRAME_MAX]; uint16_t length; setp_parser_stats_t stats; } setp_parser_t; typedef void (*setp_frame_fn)(const setp_frame_t *frame, void *user); uint16_t setp_get_u16(const uint8_t *data); uint32_t setp_get_u32(const uint8_t *data); uint64_t setp_get_u64(const uint8_t *data); void setp_put_u16(uint8_t *data, uint16_t value); void setp_put_u32(uint8_t *data, uint32_t value); void setp_put_u64(uint8_t *data, uint64_t value); uint32_t setp_crc32(const uint8_t *data, size_t length); /** Encode one complete stream/UDP frame. Returns zero on invalid arguments. */ size_t setp_frame_encode(const setp_frame_t *frame, uint8_t *out, size_t capacity); /** Decode exactly one complete UDP/datagram frame; trailing bytes are rejected. */ bool setp_frame_decode_datagram(const uint8_t *data, size_t length, setp_frame_t *out); void setp_parser_init(setp_parser_t *parser); void setp_parser_reset(setp_parser_t *parser); /** Feed an arbitrary stream chunk. Returns the number of delivered frames. */ size_t setp_parser_feed(setp_parser_t *parser, const uint8_t *data, size_t length, setp_frame_fn callback, void *user); /** Encode the common two-byte status prefix used by every response. */ size_t setp_status_encode(uint16_t status, uint8_t *out, size_t capacity); /** Split a response payload into status and optional response body. */ bool setp_status_decode(const setp_frame_t *frame, uint16_t *status, const uint8_t **body, uint16_t *body_length); /** Encode/decode DEVICE_INFO response body (without the status prefix). */ size_t setp_device_info_encode(const setp_device_info_t *info, uint8_t *out, size_t capacity); bool setp_device_info_decode(const uint8_t *data, uint16_t length, setp_device_info_t *out); /** Encode/decode CAPABILITIES response body (without the status prefix). */ size_t setp_capabilities_encode(const setp_capabilities_t *capabilities, uint8_t *out, size_t capacity); bool setp_capabilities_decode(const uint8_t *data, uint16_t length, setp_capabilities_t *out); #ifdef __cplusplus } #endif #endif /* SET_PROTOCOL_H */