Modbus TCP v1

This commit is contained in:
2026-06-11 15:44:27 -05:00
parent 70cd36c934
commit b18ac04bf8
48 changed files with 14508 additions and 16204 deletions

View File

@@ -240,22 +240,6 @@ static uint8_t data_type_reg_span(modbus_data_type_t data_type)
}
}
static bool db_has_duplicate_name(const modbus_db_t *db, const char *name)
{
size_t i;
if (db == NULL || name == NULL)
return false;
for (i = 0; i < db->count; i++)
{
if (strcmp(db->points[i].name, name) == 0)
return true;
}
return false;
}
static bool db_has_duplicate_type_offset(const modbus_db_t *db,
modbus_point_type_t type,
uint16_t offset)
@@ -428,17 +412,10 @@ static bool append_helper_points(modbus_db_t *db, const modbus_point_t *base_pt)
helper.bit_value = 0U;
helper.reg_value = 0U;
snprintf(helper.name,
sizeof(helper.name),
"%.25s__w%u",
base_pt->name,
(unsigned)(i + 1U));
if (db->count >= MODBUS_MAX_POINTS)
return false;
if (db_has_duplicate_name(db, helper.name))
return false;
if (db_has_duplicate_type_offset(db, helper.type, helper.offset))
return false;
@@ -498,12 +475,6 @@ static bool parse_csv_line(const char *line_in, modbus_point_t *pt)
if (!normalize_address(pt->type, pt->raw_address, &pt->offset))
return false;
if (fields[2][0] == '\0')
return false;
strncpy(pt->name, fields[2], sizeof(pt->name) - 1U);
pt->name[sizeof(pt->name) - 1U] = '\0';
pt->data_type = parse_data_type(fields[3]);
if (pt->data_type == MB_DATA_INVALID)
return false;
@@ -624,9 +595,6 @@ static bool parse_csv_line(const char *line_in, modbus_point_t *pt)
}
}
strncpy(pt->notes, fields[7], sizeof(pt->notes) - 1U);
pt->notes[sizeof(pt->notes) - 1U] = '\0';
return true;
}
@@ -745,22 +713,13 @@ bool modbus_points_load(modbus_db_t *db, const char *filename)
return false;
}
if (db_has_duplicate_name(db, pt.name))
{
printf("CSV ERROR line %u: duplicate name '%s'\n",
(unsigned)line_num,
pt.name);
fclose(fp);
return false;
}
if (db_has_duplicate_type_offset(db, pt.type, pt.offset))
{
printf("CSV ERROR line %u: duplicate Modbus address for name '%s' raw=%lu offset=%u\n",
printf("CSV ERROR line %u: duplicate Modbus address raw=%lu offset=%u\n",
(unsigned)line_num,
pt.name,
(unsigned long)pt.raw_address,
(unsigned)pt.offset);
fclose(fp);
return false;
}
@@ -771,9 +730,8 @@ bool modbus_points_load(modbus_db_t *db, const char *filename)
pt.pics_offset,
pt.pics_reg_span))
{
printf("CSV ERROR line %u: overlapping PICS range for name '%s' pics_raw=%lu pics_offset=%u span=%u\n",
printf("CSV ERROR line %u: overlapping PICS range pics_raw=%lu pics_offset=%u span=%u\n",
(unsigned)line_num,
pt.name,
(unsigned long)pt.pics_raw_address,
(unsigned)pt.pics_offset,
(unsigned)pt.pics_reg_span);
@@ -785,9 +743,8 @@ bool modbus_points_load(modbus_db_t *db, const char *filename)
if (!append_helper_points(db, &pt))
{
printf("CSV ERROR line %u: failed to append helper points for '%s'\n",
(unsigned)line_num,
pt.name);
printf("CSV ERROR line %u: failed to append helper points\n",
(unsigned)line_num);
fclose(fp);
return false;
}
@@ -797,21 +754,6 @@ bool modbus_points_load(modbus_db_t *db, const char *filename)
return true;
}
const modbus_point_t *modbus_points_find_by_name(const modbus_db_t *db, const char *name)
{
size_t i;
if (db == NULL || name == NULL)
return NULL;
for (i = 0; i < db->count; i++)
{
if (strcmp(db->points[i].name, name) == 0)
return &db->points[i];
}
return NULL;
}
const modbus_point_t *modbus_points_find_by_type_offset(const modbus_db_t *db,
modbus_point_type_t type,

View File

@@ -7,9 +7,22 @@
#include "modbus_memory.h"
#define MODBUS_MAX_POINTS 130
#define MODBUS_MAX_NAME_LEN 32
#define MODBUS_MAX_NOTES_LEN 64
#define MODBUS_MAX_POINTS 80 /* Max point entries per device, including helper registers */
/*
Modbus Data Type
- bool = 1 register
- uint16 = 1 register
- uint32 = 2 registers
- float = 2 registers
Example: If max is set to 2, you can have this combination:
- 2 bool Data_Type
- 2 uint16 Data_Type
- 1 uint32 Data_Type
- 1 float Data_Type
*/
#define MODBUS_MAX_CSV_LINE_LEN 256
typedef enum
@@ -24,20 +37,20 @@ typedef enum
typedef enum
{
MB_DATA_BOOL = 0,
MB_DATA_UINT16,
MB_DATA_UINT32,
MB_DATA_FLOAT,
MB_DATA_DOUBLE,
MB_DATA_UINT16, /* 1 Register*/
MB_DATA_UINT32, /* 2 Registers */
MB_DATA_FLOAT, /* 2 Registers */
MB_DATA_DOUBLE, /* 4 Registers */
MB_DATA_INVALID
} modbus_data_type_t;
typedef enum
{
PICS_DATA_NONE = 0,
PICS_DATA_BOOLEAN,
PICS_DATA_INTEGER, /* PICS Integer = 32-bit */
PICS_DATA_FLOAT, /* PICS Float = 64-bit double */
PICS_DATA_STRING,
PICS_DATA_BOOLEAN, /* PICS Boolean = 1 bit ; uses 1 Register */
PICS_DATA_INTEGER, /* PICS Integer = 32-bit ; uses 2 Registers*/
PICS_DATA_FLOAT, /* PICS Float = 64-bit double ; uses 4 registers */
PICS_DATA_STRING, /* This is ignored, just brought in incase users usees it, ESP32 will ignore it*/
PICS_DATA_INVALID
} pics_data_type_t;
@@ -47,7 +60,6 @@ typedef struct modbus_point
uint32_t raw_address;
uint16_t offset;
char name[MODBUS_MAX_NAME_LEN];
modbus_data_type_t data_type;
uint8_t reg_span;
@@ -67,7 +79,6 @@ typedef struct modbus_point
uint16_t pics_words[4];
char notes[MODBUS_MAX_NOTES_LEN];
uint8_t bit_value;
uint16_t reg_value;
@@ -87,9 +98,6 @@ void modbus_points_reset(modbus_db_t *db);
bool modbus_points_load(modbus_db_t *db, const char *filename);
/* Lookup helpers */
const modbus_point_t *modbus_points_find_by_name(const modbus_db_t *db,
const char *name);
const modbus_point_t *modbus_points_find_by_type_offset(const modbus_db_t *db,
modbus_point_type_t type,
uint16_t offset);