initial commit

This commit is contained in:
Thies Lennart Alff 2025-02-20 17:13:51 +01:00
commit 058bc70b84
Signed by: lennartalff
GPG key ID: 4EC67D34D594104D
8 changed files with 343 additions and 0 deletions

View file

@ -0,0 +1,7 @@
#pragma once
#include "protocol.h"
#include "hydrolink_msg_ack.h"
#include "hydrolink_msg_set_cmd.h"
#include "hydrolink_msg_set_response.h"
#include "hydrolink_msg_get_cmd.h"
#include "hydrolink_msg_get_response.h"

View file

@ -0,0 +1,20 @@
#pragma once
typedef enum CMD_ID {
CMD_ID_SWITCH = 1, /// Command for getting/setting the state of a switch
CMD_ID_CMD_ID_PWM = 2, /// Command for getting/setting the value of a PWM channel
CMD_ID_ENUM_END = 3
}CMD_ID;
#pragma once
typedef enum CMD_RESULT {
CMD_RESULT_SUCCESS = 1, ///
CMD_RESULT_FAILED = 2, ///
CMD_RESULT_CMD_UKNOWN = 3, /// The received command was unknown or unhandled.
CMD_RESULT_ENUM_END = 4
}CMD_RESULT;
#pragma once
typedef enum ACK {
ACK_ACK = 1, ///
ACK_NACK = 2, ///
ACK_ENUM_END = 3
}ACK;

View file

@ -0,0 +1,25 @@
#pragma once
#include "protocol.h"
#define HYDROLINK_MSG_ID_ACK 1
#define HYDROLINK_MSG_ID_ACK_LEN 1
#define HYDROLINK_MSG_ID_1_LEN 1
#define HYDROLINK_MSG_ID_ACK_CRC_EXTRA 73
typedef struct hydrolink_msg_ack_t_s {
uint8_t ack; ///
} hydrolink_msg_ack_t;
void hydrolink_ack_msg_encode(uint8_t src_id, uint8_t dst_id, const hydrolink_msg_ack_t *msg, hydrolink_msg_t *packet) {
packet->id = HYDROLINK_MSG_ID_ACK;
packet->src_id = src_id;
packet->dst_id = dst_id;
packet->length = HYDROLINK_MSG_ID_1_LEN + HYDROLINK_NON_PAYLOAD_LEN;
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 0, msg->ack);
}
static inline uint8_t hydrolink_msg_ack_get_ack(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 0);
}
static inline void hydrolink_msgack_decode(const hydrolink_msg_t *packet, hydrolink_msg_ack_t *ack) {
ack->ack = hydrolink_msg_ack_get_ack(packet);
}

View file

@ -0,0 +1,31 @@
#pragma once
#include "protocol.h"
#define HYDROLINK_MSG_ID_GET_CMD 4
#define HYDROLINK_MSG_ID_GET_CMD_LEN 2
#define HYDROLINK_MSG_ID_4_LEN 2
#define HYDROLINK_MSG_ID_GET_CMD_CRC_EXTRA 38
typedef struct hydrolink_msg_get_cmd_t_s {
uint8_t index; ///
uint8_t cmd_id; ///
} hydrolink_msg_get_cmd_t;
void hydrolink_get_cmd_msg_encode(uint8_t src_id, uint8_t dst_id, const hydrolink_msg_get_cmd_t *msg, hydrolink_msg_t *packet) {
packet->id = HYDROLINK_MSG_ID_GET_CMD;
packet->src_id = src_id;
packet->dst_id = dst_id;
packet->length = HYDROLINK_MSG_ID_4_LEN + HYDROLINK_NON_PAYLOAD_LEN;
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 0, msg->index);
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 1, msg->cmd_id);
}
static inline uint8_t hydrolink_msg_get_cmd_get_index(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 0);
}
static inline uint8_t hydrolink_msg_get_cmd_get_cmd_id(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 1);
}
static inline void hydrolink_msgget_cmd_decode(const hydrolink_msg_t *packet, hydrolink_msg_get_cmd_t *get_cmd) {
get_cmd->index = hydrolink_msg_get_cmd_get_index(packet);
get_cmd->cmd_id = hydrolink_msg_get_cmd_get_cmd_id(packet);
}

View file

@ -0,0 +1,37 @@
#pragma once
#include "protocol.h"
#define HYDROLINK_MSG_ID_GET_RESPONSE 3
#define HYDROLINK_MSG_ID_GET_RESPONSE_LEN 6
#define HYDROLINK_MSG_ID_3_LEN 6
#define HYDROLINK_MSG_ID_GET_RESPONSE_CRC_EXTRA 28
typedef struct hydrolink_msg_get_response_t_s {
int32_t value; ///
uint8_t result; ///
uint8_t cmd_id; ///
} hydrolink_msg_get_response_t;
void hydrolink_get_response_msg_encode(uint8_t src_id, uint8_t dst_id, const hydrolink_msg_get_response_t *msg, hydrolink_msg_t *packet) {
packet->id = HYDROLINK_MSG_ID_GET_RESPONSE;
packet->src_id = src_id;
packet->dst_id = dst_id;
packet->length = HYDROLINK_MSG_ID_3_LEN + HYDROLINK_NON_PAYLOAD_LEN;
hydrolink_put_int32_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 0, msg->value);
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 4, msg->result);
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 5, msg->cmd_id);
}
static inline int32_t hydrolink_msg_get_response_get_value(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_int32_t(packet, 0);
}
static inline uint8_t hydrolink_msg_get_response_get_result(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 4);
}
static inline uint8_t hydrolink_msg_get_response_get_cmd_id(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 5);
}
static inline void hydrolink_msgget_response_decode(const hydrolink_msg_t *packet, hydrolink_msg_get_response_t *get_response) {
get_response->value = hydrolink_msg_get_response_get_value(packet);
get_response->result = hydrolink_msg_get_response_get_result(packet);
get_response->cmd_id = hydrolink_msg_get_response_get_cmd_id(packet);
}

View file

@ -0,0 +1,37 @@
#pragma once
#include "protocol.h"
#define HYDROLINK_MSG_ID_SET_CMD 2
#define HYDROLINK_MSG_ID_SET_CMD_LEN 6
#define HYDROLINK_MSG_ID_2_LEN 6
#define HYDROLINK_MSG_ID_SET_CMD_CRC_EXTRA 58
typedef struct hydrolink_msg_set_cmd_t_s {
int32_t value; ///
uint8_t index; ///
uint8_t cmd_id; /// Command defined as in CMD_ID enum.
} hydrolink_msg_set_cmd_t;
void hydrolink_set_cmd_msg_encode(uint8_t src_id, uint8_t dst_id, const hydrolink_msg_set_cmd_t *msg, hydrolink_msg_t *packet) {
packet->id = HYDROLINK_MSG_ID_SET_CMD;
packet->src_id = src_id;
packet->dst_id = dst_id;
packet->length = HYDROLINK_MSG_ID_2_LEN + HYDROLINK_NON_PAYLOAD_LEN;
hydrolink_put_int32_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 0, msg->value);
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 4, msg->index);
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 5, msg->cmd_id);
}
static inline int32_t hydrolink_msg_set_cmd_get_value(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_int32_t(packet, 0);
}
static inline uint8_t hydrolink_msg_set_cmd_get_index(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 4);
}
static inline uint8_t hydrolink_msg_set_cmd_get_cmd_id(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 5);
}
static inline void hydrolink_msgset_cmd_decode(const hydrolink_msg_t *packet, hydrolink_msg_set_cmd_t *set_cmd) {
set_cmd->value = hydrolink_msg_set_cmd_get_value(packet);
set_cmd->index = hydrolink_msg_set_cmd_get_index(packet);
set_cmd->cmd_id = hydrolink_msg_set_cmd_get_cmd_id(packet);
}

View file

@ -0,0 +1,31 @@
#pragma once
#include "protocol.h"
#define HYDROLINK_MSG_ID_SET_RESPONSE 3
#define HYDROLINK_MSG_ID_SET_RESPONSE_LEN 2
#define HYDROLINK_MSG_ID_3_LEN 2
#define HYDROLINK_MSG_ID_SET_RESPONSE_CRC_EXTRA 250
typedef struct hydrolink_msg_set_response_t_s {
uint8_t result; ///
uint8_t cmd_id; ///
} hydrolink_msg_set_response_t;
void hydrolink_set_response_msg_encode(uint8_t src_id, uint8_t dst_id, const hydrolink_msg_set_response_t *msg, hydrolink_msg_t *packet) {
packet->id = HYDROLINK_MSG_ID_SET_RESPONSE;
packet->src_id = src_id;
packet->dst_id = dst_id;
packet->length = HYDROLINK_MSG_ID_3_LEN + HYDROLINK_NON_PAYLOAD_LEN;
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 0, msg->result);
hydrolink_put_uint8_t(HYDROLINK_PAYLOAD_NON_CONST(packet), 1, msg->cmd_id);
}
static inline uint8_t hydrolink_msg_set_response_get_result(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 0);
}
static inline uint8_t hydrolink_msg_set_response_get_cmd_id(const hydrolink_msg_t *packet) {
return HYDROLINK_RETURN_uint8_t(packet, 1);
}
static inline void hydrolink_msgset_response_decode(const hydrolink_msg_t *packet, hydrolink_msg_set_response_t *set_response) {
set_response->result = hydrolink_msg_set_response_get_result(packet);
set_response->cmd_id = hydrolink_msg_set_response_get_cmd_id(packet);
}

View file

@ -0,0 +1,155 @@
#pragma once
#include <stdint.h>
#define HYDROLINK_HEADER_LEN 4
#define HYDROLINK_CRC_LEN 2
#define HYDROLINK_NON_PAYLOAD_LEN (HYDROLINK_HEADER_LEN + HYDROLINK_CRC_LEN)
#define HYDROLINK_MAX_PAYLOAD_LEN 6
#define HYDROLINK_MAX_MSG_LEN (HYDROLINK_MAX_PAYLOAD_LEN + HYDROLINK_NON_PAYLOAD_LEN)
struct hydrolink_msg_s;
typedef struct hydrolink_msg_s hydrolink_msg_t;
struct hydrolink_msg_s {
uint8_t id;
uint8_t payload_length;
uint8_t dst_id;
uint8_t src_id;
uint8_t payload[HYDROLINK_MAX_PAYLOAD_LEN];
uint16_t crc;
};
#define HYDROLINK_PAYLOAD(msg) ((const char *)(&((msg)->payload[0])))
#define HYDROLINK_PAYLOAD_NON_CONST(msg) ((char *)(&((msg)->payload[0])))
#define hydrolink_put_float(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b)
#define hydrolink_put_double(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b)
#define hydrolink_put_char(buf, wire_offset, b) buf[wire_offset] = (char)b
#define hydrolink_put_int8_t(buf, wire_offset, b) buf[wire_offset] = (int8_t)b
#define hydrolink_put_uint8_t(buf, wire_offset, b) buf[wire_offset] = (uint8_t)b
#define hydrolink_put_int16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b)
#define hydrolink_put_uint16_t(buf, wire_offset, b) byte_swap_2(&buf[wire_offset], (const char *)&b)
#define hydrolink_put_int32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b)
#define hydrolink_put_uint32_t(buf, wire_offset, b) byte_swap_4(&buf[wire_offset], (const char *)&b)
#define hydrolink_put_int64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b)
#define hydrolink_put_uint64_t(buf, wire_offset, b) byte_swap_8(&buf[wire_offset], (const char *)&b)
inline void byte_swap_2(char *dst, const char *src) {
dst[0] = src[1];
dst[1] = src[0];
}
inline void byte_swap_4(char *dst, const char *src) {
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];
}
inline void byte_swap_8(char *dst, const char *src) {
dst[0] = src[7];
dst[1] = src[6];
dst[2] = src[5];
dst[3] = src[4];
dst[4] = src[3];
dst[5] = src[2];
dst[6] = src[1];
dst[7] = src[0];
}
#define HYDROLINK_MSG_RETURN_TYPE(TYPE, SIZE) \
static inline TYPE HYDROLINK_RETURN_## TYPE(const hydrolink_msg_t *msg, uint8_t offset) {\
TYPE ret; \
byte_swap_## SIZE((char*)&ret, &HYDROLINK_PAYLOAD(msg)[offset]); \
return ret; \
}
HYDROLINK_MSG_RETURN_TYPE(float, 4)
HYDROLINK_MSG_RETURN_TYPE(double, 8)
#define HYDROLINK_RETURN_char(msg, wire_offset) (char)HYDROLINK_PAYLOAD(msg)[wire_offset]
#define HYDROLINK_RETURN_int8_t(msg, wire_offset) (int8_t)HYDROLINK_PAYLOAD(msg)[wire_offset]
#define HYDROLINK_RETURN_uint8_t(msg, wire_offset) (uint8_t)HYDROLINK_PAYLOAD(msg)[wire_offset]
HYDROLINK_MSG_RETURN_TYPE(int16_t, 2)
HYDROLINK_MSG_RETURN_TYPE(uint16_t, 2)
HYDROLINK_MSG_RETURN_TYPE(int32_t, 4)
HYDROLINK_MSG_RETURN_TYPE(uint32_t, 4)
HYDROLINK_MSG_RETURN_TYPE(int64_t, 8)
HYDROLINK_MSG_RETURN_TYPE(uint64_t, 8)
inline void crc_xmodem_init(uint16_t *crc) { *crc = 0; }
inline void crc_xmodem_accumulate(uint8_t data, uint16_t *crc) {
*crc = *crc ^ ((uint16_t)data << 8);
for (uint8_t j = 0; j < 8; j++) {
if (*crc & 0x8000) {
*crc = (*crc << 1) ^ 0x1021;
} else {
*crc <<= 1;
}
}
}
inline uint16_t crc_xmodem_calculate(const uint8_t *data, uint8_t length) {
uint16_t crc;
crc_xmodem_init(&crc);
for (uint8_t i = 0; i < length; i++) {
crc_xmodem_accumulate(*data, &crc);
}
return crc;
}
void hydrolink_fill_header_and_crc(hydrolink_msg_t *msg, uint8_t msg_id, uint8_t payload_length, uint8_t dst_id, uint8_t src_id, uint8_t crc_extra) {
msg->id = msg_id;
msg->payload_length = payload_length;
msg->dst_id = dst_id;
msg->src_id = src_id;
uint16_t crc;
crc_xmodem_init(&crc);
for(int i = 0; i < msg->payload_length; ++i) {
crc_xmodem_accumulate(msg->payload[i], &crc);
}
crc_xmodem_accumulate(crc_extra, &crc);
msg->crc = crc;
}
uint8_t hydrolink_serialize_message(hydrolink_msg_t *msg, uint8_t *buffer) {
buffer[0] = msg->id;
buffer[1] = msg->payload_length;
buffer[2] = msg->dst_id;
buffer[3] = msg->src_id;
uint8_t *p = &buffer[4];
for(int i =0; i<msg->payload_length;++i) {
*p++ = msg->payload[i];
}
*p++ = (uint8_t)(msg->crc >> 8);
*p++ = (uint8_t)(msg->crc & 0xff);
return HYDROLINK_NON_PAYLOAD_LEN + msg->payload_length;
}
uint8_t hydrolink_deserialize_header(hydrolink_msg_t *msg, uint8_t *buffer, uint8_t buffer_length) {
if (buffer_length < HYDROLINK_NON_PAYLOAD_LEN) {
return 0;
}
msg->id = buffer[0];
msg->payload_length = buffer[1];
msg->dst_id = buffer[2];
msg->src_id = buffer[3];
msg->crc = buffer[buffer_length-1] | (((uint16_t)buffer[buffer_length-2]) << 8);
if (msg->payload_length + HYDROLINK_NON_PAYLOAD_LEN != buffer_length) {
return 0;
}
uint8_t *p = &buffer[HYDROLINK_HEADER_LEN];
for (int i = 0; i < msg->payload_length; ++i) {
msg->payload[i] = *p++;
}
return msg->payload_length + HYDROLINK_NON_PAYLOAD_LEN;
}