chore: housekeeping

This commit is contained in:
2024-11-12 00:55:52 +06:00
parent 5f9c966602
commit 48943ba71f
32 changed files with 715 additions and 854 deletions

View File

@@ -3,52 +3,48 @@
#include <stdint.h>
// Debug flags
// debug flags
#define DEBUG_MODE 1
// Device Bus Types
typedef enum { BUS_RS485, BUS_ONEWIRE } bus_type_t;
// Device Type Definitions
// device type definitions
typedef enum {
DEVICE_RELAY = 1,
DEVICE_SOIL_SENSOR = 2,
DEVICE_THERMOMETER = 3
} device_type_t;
// Node Configuration
// node configuration
typedef struct {
const char* id; // Unique identifier for the node
const char* name; // Human readable name
const char* location; // Optional location description
uint8_t mac[6]; // MAC address
} node_config_t;
// RS485 Device Configuration
// RS485 device configuration
typedef struct {
uint8_t slave_id; // Modbus slave ID
device_type_t type; // Type of device
const char* name; // Device name (used in MQTT topics)
} rs485_device_t;
// Network Configuration
// Network configuration
#define MQTT_SERVER_IP {192, 168, 102, 100}
#define MQTT_PORT 1883
// MQTT Configuration
// MQTT configuration
#define MQTT_KEEP_ALIVE_INTERVAL 60
#define MQTT_TX_BUFFER_SIZE 128
#define MQTT_RX_BUFFER_SIZE 128
#define MQTT_COMMAND_TIMEOUT_MS 1000
// Node Specific Configuration
static const node_config_t NODE_CONFIG = {
.id = "ch32-node1", .name = "CH32 Node 1", .location = "somewhere"};
// node config declaration
extern node_config_t NODE_CONFIG;
// RS485 Devices Configuration
// RS485 devices configuration
#define RS485_DEVICE_COUNT 1
static const rs485_device_t RS485_DEVICES[RS485_DEVICE_COUNT] = {
{.slave_id = 0x01, .type = DEVICE_RELAY, .name = "relay-1"}};
// {.slave_id = 0x02, .type = DEVICE_SOIL_SENSOR, .name = "soil-monitor-1"}};
// RS485 devices declaration
extern const rs485_device_t RS485_DEVICES[RS485_DEVICE_COUNT];
#endif // CONFIG_H

View File

@@ -1,19 +0,0 @@
#ifndef DHCP_H
#define DHCP_H
#include <stdint.h>
typedef enum {
DHCP_STATE_INIT,
DHCP_STATE_DISCOVER,
DHCP_STATE_REQUEST,
DHCP_STATE_LEASED,
DHCP_STATE_RENEW,
DHCP_STATE_RELEASE
} dhcp_state_t;
void dhcp_init(void);
void dhcp_process(void);
uint8_t dhcp_get_state(void);
#endif

View File

@@ -13,7 +13,7 @@ typedef enum {
} led_state_t;
// Initialize GPIO
void init_gpio(void);
void gpio_init(void);
// LED status handling
void led_status_set(led_state_t state);

56
include/modbus.h Normal file
View File

@@ -0,0 +1,56 @@
#ifndef MODBUS_H
#define MODBUS_H
#include <MQTT/MQTTClient.h>
#include <stdbool.h>
#include <stdint.h>
#include "config.h"
// Function codes
#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03
#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
// Modbus protocol exception codes
#define MODBUS_ERROR_NONE 0x00
#define MODBUS_ERROR_ILLEGAL_FUNCTION 0x01
#define MODBUS_ERROR_ILLEGAL_ADDRESS 0x02
#define MODBUS_ERROR_ILLEGAL_VALUE 0x03
#define MODBUS_ERROR_DEVICE_FAILURE 0x04
#define MODBUS_ERROR_ACKNOWLEDGE 0x05
#define MODBUS_ERROR_DEVICE_BUSY 0x06
#define MODBUS_ERROR_MEMORY_PARITY 0x08
#define MODBUS_ERROR_TIMEOUT 0x0B // No response received
#define MODBUS_ERROR_CRC 0x0C // CRC check failed
// Frame length
#define MB_MIN_LEN 4
#define MB_CRC_LEN 2
#define MB_WREG_LEN 8
#define MB_MAX_BUFFER 32
// States for the Modbus protocol state machine
typedef enum {
MODBUS_IDLE, // Ready to send new request
MODBUS_WAITING_RESPONSE, // Request sent, waiting for slave response
MODBUS_PROCESS_RESPONSE // Response received, processing data
} modbus_state_t;
// Callback function type for handling received Modbus register values
typedef void (*modbus_value_cb)(uint8_t device_idx, const char* property,
uint16_t value);
// Initialize the Modbus protocol handler with callback for received values
void modbus_handler_init(modbus_value_cb value_callback);
void modbus_handler_process(void);
// Send a Modbus read or write request to a slave device
// Returns true if request was queued successfully
bool modbus_handler_send_request(uint8_t device_idx, const char* property,
bool is_write, uint16_t value);
// Publish a Modbus register value to MQTT broker
// Formats topic as device_name/property
void modbus_publish_value(MQTTClient* client, const char* device_name,
const char* property, uint16_t value);
#endif // MODBUS_H

View File

@@ -1,17 +0,0 @@
#ifndef MODBUS_HANDLER_H
#define MODBUS_HANDLER_H
#include <stdint.h>
#include "config.h"
#include "modbus_master.h"
typedef void (*modbus_value_cb)(uint8_t device_idx, const char* property,
uint16_t value);
void modbus_handler_init(modbus_context_t* ctx, modbus_value_cb value_callback);
void modbus_handler_process(void);
bool modbus_handler_send_request(uint8_t device_idx, const char* property,
uint8_t is_write, uint16_t value);
#endif

View File

@@ -1,57 +0,0 @@
#ifndef __MODBUS_MASTER_H
#define __MODBUS_MASTER_H
#include <stdint.h>
#include <stdbool.h>
// Function codes
#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03
#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
// Error codes
#define MODBUS_ERROR_NONE 0x00
#define MODBUS_ERROR_FUNCTION 0x01
#define MODBUS_ERROR_ADDRESS 0x02
#define MODBUS_ERROR_VALUE 0x03
#define MODBUS_ERROR_TIMEOUT 0x04
// Frame length
#define MB_MIN_LEN 4
#define MB_CRC_LEN 2
#define MB_WREG_LEN 8
#define MB_MAX_BUFFER 32
// State machine states
typedef enum {
MODBUS_IDLE,
MODBUS_WAITING_RESPONSE,
MODBUS_PROCESS_RESPONSE
} modbus_state_t;
// Modbus context structure
typedef struct {
modbus_state_t state;
uint32_t last_send_time;
uint32_t response_timeout;
uint8_t buffer[MB_MAX_BUFFER];
uint16_t rx_len;
uint16_t current_bit;
uint16_t last_value;
void (*on_response)(uint8_t* buf, uint16_t len,
uint16_t value); // Response callback
void (*on_error)(uint8_t error_code); // Error callback
} modbus_context_t;
uint16_t modbus_create_request(uint8_t* req, uint8_t slave_addr,
uint8_t function, uint16_t address,
uint16_t value);
uint8_t modbus_process_response(uint8_t* buf, uint16_t len, uint16_t* value);
void modbus_init(modbus_context_t* ctx,
void (*response_callback)(uint8_t*, uint16_t, uint16_t),
void (*error_callback)(uint8_t));
void modbus_set_timeout(modbus_context_t* ctx, uint32_t timeout_ms);
void modbus_process(modbus_context_t* ctx);
bool modbus_send_request(modbus_context_t* ctx, uint8_t slave_addr,
uint8_t function, uint16_t address, uint16_t value);
#endif // __MODBUS_MASTER_H

View File

@@ -5,7 +5,7 @@
#include <stdbool.h>
#include "ch32v003fun.h"
#include "w5500.h"
#include "network.h"
#define MAX_PAYLOAD_LENGTH 256
@@ -17,6 +17,7 @@ typedef struct {
int qos;
} ch32_mqtt_options_t;
// MQTT state
typedef struct {
Network network;
MQTTClient client;
@@ -28,16 +29,18 @@ typedef struct {
bool discovery_published;
} mqtt_state_t;
// List of connected MQTT nodes
extern char nodes_list[MAX_PAYLOAD_LENGTH];
void mqtt_init(mqtt_state_t* state);
void mqtt_process(mqtt_state_t* state);
// Callback for handling incoming MQTT messages
void message_arrived(MessageData* md);
void publish_value(MQTTClient* client, const char* device_name,
const char* property, uint16_t value);
// Publish a retained message to an MQTT topic
void publish_retained(MQTTClient* client, const char* topic,
const char* payload);
// Publish a QoS 0 message to a MQTT topic
void publish_message(MQTTClient* client, const char* payload,
const char* topic);
#endif
#endif // MQTT_HANDLER_H

27
include/network.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef NETWORK_H
#define NETWORK_H
#include <MQTT/MQTTClient.h>
#include <stdint.h>
// Definitions for socket indexes
#define DHCP_SOCKET 0
#define DNS_SOCKET 1
#define TCP_SOCKET 2
typedef enum {
DHCP_STATE_INIT,
DHCP_STATE_DISCOVER,
DHCP_STATE_REQUEST,
DHCP_STATE_LEASED,
DHCP_STATE_RENEW,
DHCP_STATE_RELEASE
} dhcp_state_t;
// Initializes the W5500 chip
void configure_network(void);
void network_init(void);
void dhcp_process(void);
uint8_t dhcp_get_state(void);
#endif // NETWORK_H

View File

@@ -1,11 +0,0 @@
#ifndef RS485_H
#define RS485_H
#include <stdint.h>
void rs485_init(int uart_brr);
void rs485_send(uint8_t *buf, uint16_t len);
uint8_t rs485_available(void);
uint8_t rs485_read(void);
#endif // RS485_H

View File

@@ -12,7 +12,7 @@ typedef enum {
} transfer_state_t;
// SPI DMA initialization function
void init_spidma(void);
void spidma_init(void);
// SPI DMA buffer read
void spidma_read_buffer(uint8_t *buf, uint16_t len);

View File

@@ -1,11 +0,0 @@
#ifndef SYSTEM_INIT_H
#define SYSTEM_INIT_H
#include <stdbool.h>
#define W5500_INIT_DELAY_MS 55
void init_system(void);
bool wait_for_dhcp(void);
#endif

View File

@@ -10,6 +10,6 @@
// ms counter incremented by SysTick
extern volatile uint32_t systick_millis;
void init_systick(void);
void systick_init(void);
#endif // SYSTICK_H

View File

@@ -3,20 +3,29 @@
#include <stdint.h>
// RS485 baud rate
#define UART1_BAUD_RATE 9600
#define UART2_BAUD_RATE 115200
// Macro definitions
#define APB1_CLOCK (FUNCONF_SYSTEM_CORE_CLOCK / 2) // APB1 is divided by 2
// APB1 bus clock is half the system core clock
#define APB1_CLOCK (FUNCONF_SYSTEM_CORE_CLOCK / 2)
// USART2
#define UART_BRR_APB1 (((APB1_CLOCK) + (UART_BAUD_RATE / 2)) / (UART_BAUD_RATE))
// USART1
// Calculate baud rate divisors
// Adds BAUD_RATE/2 for rounding to nearest integer
#define UART_BRR_APB1 \
(((APB1_CLOCK) + (UART2_BAUD_RATE / 2)) / (UART2_BAUD_RATE))
#define UART_BRR_APB2 \
(((FUNCONF_SYSTEM_CORE_CLOCK) + (UART1_BAUD_RATE / 2)) / (UART1_BAUD_RATE))
// Function prototypes
void init_uart(int uart_brr);
// UART2
void uart2_init(int uart_brr);
// RS485 functions
void rs485_init(int uart_brr);
void rs485_send(uint8_t *buf, uint16_t len);
uint8_t rs485_available(void);
uint8_t rs485_read(void);
#endif // UART_H

51
include/utils.h Normal file
View File

@@ -0,0 +1,51 @@
#ifndef UTILS_H
#define UTILS_H
#include <stdint.h>
/**
* @brief Combines two bytes into a 16-bit word
* @param hi High byte
* @param lo Low byte
* @return Combined 16-bit word
*/
static inline uint16_t to_word(uint8_t hi, uint8_t lo) {
return (hi << 8) | lo;
}
/**
* @brief Splits a 16-bit word into two bytes
* @param val Value to split
* @param hi Pointer to store high byte
* @param lo Pointer to store low byte
*/
static inline void to_bytes(uint16_t val, uint8_t* hi, uint8_t* lo) {
*hi = (val >> 8) & 0xFF;
*lo = val & 0xFF;
}
/**
* @brief Parses a decimal number from a string
* @param str String to parse
* @return Parsed decimal number
*/
static inline uint8_t parse_decimal(const char* str) {
uint8_t num = 0;
while (*str >= '0' && *str <= '9') {
num = num * 10 + (*str - '0');
str++;
}
return num;
}
/**
* @brief Extracts the node number from an ID string
* @param id ID string to extract from
* @return Extracted node number
*/
static inline uint8_t parse_node_number(const char* id) {
const char* last_dash = strrchr(id, '-');
return last_dash ? parse_decimal(last_dash + 1) : 0;
}
#endif // UTILS_H

View File

@@ -1,20 +0,0 @@
#ifndef W5500_H
#define W5500_H
#include <MQTT/MQTTClient.h>
#include <stdint.h>
// Definitions for socket indexes
#define DHCP_SOCKET 0
#define DNS_SOCKET 1
#define TCP_SOCKET 2
extern volatile int ip_assigned;
// Initializes the W5500 chip
void configure_network(void);
// resolves a domain name
// void resolve_domain_name(const char* domain_name);
#endif // W5500_H