Skip to content

Commit

Permalink
Merge pull request #64 from debevv/create_api
Browse files Browse the repository at this point in the history
New *_create() APIs
  • Loading branch information
debevv authored Sep 20, 2024
2 parents 67bd7b2 + 8db45ad commit 0dffd91
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 65 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# nanoMODBUS - A compact MODBUS RTU/TCP C library for embedded/microcontrollers

**If you found this library useful, buy me a coffee on** [<img src='https://storage.ko-fi.com/cdn/brandasset/logo_white_stroke.png' width='80'>](https://ko-fi.com/B0B2LK779)
**If you found this library useful, buy me a coffee on
** [<img src='https://storage.ko-fi.com/cdn/brandasset/logo_white_stroke.png' width='80'>](https://ko-fi.com/B0B2LK779)

nanoMODBUS is a small C library that implements the Modbus protocol. It is especially useful in embedded and
resource-constrained systems like microcontrollers.
Expand Down Expand Up @@ -52,6 +53,7 @@ int main(int argc, char* argv[]) {

// my_transport_read() and my_transport_write() are implemented by the user
nmbs_platform_conf platform_conf;
nmbs_platform_conf_create(&platform_conf);
platform_conf.transport = NMBS_TRANSPORT_TCP;
platform_conf.read = my_transport_read;
platform_conf.write = my_transport_write;
Expand Down
1 change: 1 addition & 0 deletions examples/arduino/client-rtu/client-rtu.ino
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void setup() {

void loop() {
nmbs_platform_conf platform_conf;
nmbs_platform_conf_create(&platform_conf);
platform_conf.transport = NMBS_TRANSPORT_RTU;
platform_conf.read = read_serial;
platform_conf.write = write_serial;
Expand Down
4 changes: 3 additions & 1 deletion examples/arduino/server-rtu/server-rtu.ino
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,14 @@ void setup() {

void loop() {
nmbs_platform_conf platform_conf;
nmbs_platform_conf_create(&platform_conf);
platform_conf.transport = NMBS_TRANSPORT_RTU;
platform_conf.read = read_serial;
platform_conf.write = write_serial;
platform_conf.arg = NULL;

nmbs_callbacks callbacks = {0};
nmbs_callbacks callbacks;
nmbs_callbacks_create(&callbacks);
callbacks.read_coils = handle_read_coils;
callbacks.write_multiple_coils = handle_write_multiple_coils;
callbacks.read_holding_registers = handler_read_holding_registers;
Expand Down
1 change: 1 addition & 0 deletions examples/linux/client-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ int main(int argc, char* argv[]) {
}

nmbs_platform_conf platform_conf;
nmbs_platform_conf_create(&platform_conf);
platform_conf.transport = NMBS_TRANSPORT_TCP;
platform_conf.read = read_fd_linux;
platform_conf.write = write_fd_linux;
Expand Down
6 changes: 4 additions & 2 deletions examples/linux/server-tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,15 @@ int main(int argc, char* argv[]) {
return 1;
}

nmbs_platform_conf platform_conf = {0};
nmbs_platform_conf platform_conf;
nmbs_platform_conf_create(&platform_conf);
platform_conf.transport = NMBS_TRANSPORT_TCP;
platform_conf.read = read_fd_linux;
platform_conf.write = write_fd_linux;
platform_conf.arg = NULL; // We will set the arg (socket fd) later

nmbs_callbacks callbacks = {0};
nmbs_callbacks callbacks;
nmbs_callbacks_create(&callbacks);
callbacks.read_coils = handle_read_coils;
callbacks.write_multiple_coils = handle_write_multiple_coils;
callbacks.read_holding_registers = handler_read_holding_registers;
Expand Down
1 change: 1 addition & 0 deletions examples/win32/modbus_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ void onError(nmbs_error err) {
void ReadRegister(uint16_t reg) {

nmbs_platform_conf platform_conf;
nmbs_platform_conf_create(&platform_conf);
platform_conf.transport = NMBS_TRANSPORT_RTU;
platform_conf.read = read_serial;
platform_conf.write = write_serial;
Expand Down
28 changes: 24 additions & 4 deletions nanomodbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <stdint.h>
#include <string.h>

#define NMBS_UNUSED_PARAM(x) ((x) = (x))

#ifdef NMBS_DEBUG
#include <stdio.h>
#define NMBS_DEBUG_PRINT(...) printf(__VA_ARGS__)
Expand Down Expand Up @@ -178,7 +180,7 @@ nmbs_error nmbs_create(nmbs_t* nmbs, const nmbs_platform_conf* platform_conf) {
nmbs->byte_timeout_ms = -1;
nmbs->read_timeout_ms = -1;

if (!platform_conf)
if (!platform_conf || platform_conf->initialized != 0xFFFFDEBE)
return NMBS_ERROR_INVALID_ARGUMENT;

if (platform_conf->transport != NMBS_TRANSPORT_RTU && platform_conf->transport != NMBS_TRANSPORT_TCP)
Expand All @@ -203,6 +205,14 @@ void nmbs_set_byte_timeout(nmbs_t* nmbs, int32_t timeout_ms) {
}


void nmbs_platform_conf_create(nmbs_platform_conf* platform_conf) {
memset(platform_conf, 0, sizeof(nmbs_platform_conf));
platform_conf->crc_calc = nmbs_crc_calc;
// Workaround for older user code not calling nmbs_platform_conf_create()
platform_conf->initialized = 0xFFFFDEBE;
}


void nmbs_set_destination_rtu_address(nmbs_t* nmbs, uint8_t address) {
nmbs->dest_address_rtu = address;
}
Expand All @@ -213,7 +223,8 @@ void nmbs_set_platform_arg(nmbs_t* nmbs, void* arg) {
}


uint16_t nmbs_crc_calc(const uint8_t* data, uint32_t length) {
uint16_t nmbs_crc_calc(const uint8_t* data, uint32_t length, void* arg) {
NMBS_UNUSED_PARAM(arg);
uint16_t crc = 0xFFFF;
for (uint32_t i = 0; i < length; i++) {
crc ^= (uint16_t) data[i];
Expand Down Expand Up @@ -270,7 +281,7 @@ static nmbs_error recv_msg_footer(nmbs_t* nmbs) {
NMBS_DEBUG_PRINT("\n");

if (nmbs->platform.transport == NMBS_TRANSPORT_RTU) {
uint16_t crc = nmbs_crc_calc(nmbs->msg.buf, nmbs->msg.buf_idx);
uint16_t crc = nmbs->platform.crc_calc(nmbs->msg.buf, nmbs->msg.buf_idx, nmbs->platform.arg);

nmbs_error err = recv(nmbs, 2);
if (err != NMBS_ERROR_NONE)
Expand Down Expand Up @@ -381,7 +392,7 @@ static nmbs_error send_msg(nmbs_t* nmbs) {
NMBS_DEBUG_PRINT("\n");

if (nmbs->platform.transport == NMBS_TRANSPORT_RTU) {
uint16_t crc = nmbs_crc_calc(nmbs->msg.buf, nmbs->msg.buf_idx);
uint16_t crc = nmbs->platform.crc_calc(nmbs->msg.buf, nmbs->msg.buf_idx, nmbs->platform.arg);
put_2(nmbs, crc);
}

Expand Down Expand Up @@ -1839,11 +1850,20 @@ static nmbs_error handle_req_fc(nmbs_t* nmbs) {
}


void nmbs_callbacks_create(nmbs_callbacks* callbacks) {
memset(callbacks, 0, sizeof(nmbs_callbacks));
callbacks->initialized = 0xFFFFDEBE;
}


nmbs_error nmbs_server_create(nmbs_t* nmbs, uint8_t address_rtu, const nmbs_platform_conf* platform_conf,
const nmbs_callbacks* callbacks) {
if (platform_conf->transport == NMBS_TRANSPORT_RTU && address_rtu == 0)
return NMBS_ERROR_INVALID_ARGUMENT;

if (!callbacks || callbacks->initialized != 0xFFFFDEBE)
return NMBS_ERROR_INVALID_ARGUMENT;

nmbs_error ret = nmbs_create(nmbs, platform_conf);
if (ret != NMBS_ERROR_NONE)
return ret;
Expand Down
22 changes: 19 additions & 3 deletions nanomodbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ typedef enum nmbs_transport {
* A return value between `0` and `count - 1` will be treated as if a timeout occurred on the transport side. All other
* values will be treated as transport errors.
*
* Additionally, an optional crc_calc() function can be defined to override the default nanoMODBUS CRC calculation function.
*
* These methods accept a pointer to arbitrary user-data, which is the arg member of this struct.
* After the creation of an instance it can be changed with nmbs_set_platform_arg().
*/
Expand All @@ -148,7 +150,10 @@ typedef struct nmbs_platform_conf {
void* arg); /*!< Bytes read transport function pointer */
int32_t (*write)(const uint8_t* buf, uint16_t count, int32_t byte_timeout_ms,
void* arg); /*!< Bytes write transport function pointer */
void* arg; /*!< User data, will be passed to functions above */
uint16_t (*crc_calc)(const uint8_t* data, uint32_t length,
void* arg); /*!< CRC calculation function pointer. Optional */
void* arg; /*!< User data, will be passed to functions above */
uint32_t initialized; /*!< Reserved, workaround for older user code not calling nmbs_platform_conf_create() */
} nmbs_platform_conf;


Expand Down Expand Up @@ -216,7 +221,8 @@ typedef struct nmbs_callbacks {
#endif
#endif

void* arg; // User data, will be passed to functions above
void* arg; // User data, will be passed to functions above
uint32_t initialized; // Reserved, workaround for older user code not calling nmbs_callbacks_create()
} nmbs_callbacks;


Expand Down Expand Up @@ -268,13 +274,23 @@ void nmbs_set_read_timeout(nmbs_t* nmbs, int32_t timeout_ms);
*/
void nmbs_set_byte_timeout(nmbs_t* nmbs, int32_t timeout_ms);

/** Create a new nmbs_platform_conf struct.
* @param platform_conf pointer to the nmbs_platform_conf instance
*/
void nmbs_platform_conf_create(nmbs_platform_conf* platform_conf);

/** Set the pointer to user data argument passed to platform functions.
* @param nmbs pointer to the nmbs_t instance
* @param arg user data argument
*/
void nmbs_set_platform_arg(nmbs_t* nmbs, void* arg);

#ifndef NMBS_SERVER_DISABLED
/** Create a new nmbs_callbacks struct.
* @param callbacks pointer to the nmbs_callbacks instance
*/
void nmbs_callbacks_create(nmbs_callbacks* callbacks);

/** Create a new Modbus server.
* @param nmbs pointer to the nmbs_t instance where the client will be created.
* @param address_rtu RTU address of this server. Can be 0 if transport is not RTU.
Expand Down Expand Up @@ -510,7 +526,7 @@ nmbs_error nmbs_receive_raw_pdu_response(nmbs_t* nmbs, uint8_t* data_out, uint8_
* @param data Data
* @param length Length of the data
*/
uint16_t nmbs_crc_calc(const uint8_t* data, uint32_t length);
uint16_t nmbs_crc_calc(const uint8_t* data, uint32_t length, void* arg);

#ifndef NMBS_STRERROR_DISABLED
/** Convert a nmbs_error to string
Expand Down
14 changes: 8 additions & 6 deletions tests/client_disabled.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,15 @@ int main(int argc, char* argv[]) {

nmbs_t nmbs;

nmbs_platform_conf platform_conf_empty = {
.transport = NMBS_TRANSPORT_TCP,
.read = read_empty,
.write = write_empty,
};

nmbs_callbacks callbacks_empty = {0};
nmbs_platform_conf platform_conf_empty;
nmbs_platform_conf_create(&platform_conf_empty);
platform_conf_empty.transport = NMBS_TRANSPORT_TCP;
platform_conf_empty.read = read_empty;
platform_conf_empty.write = write_empty;

nmbs_callbacks callbacks_empty;
nmbs_callbacks_create(&callbacks_empty);

nmbs_error err = nmbs_server_create(&nmbs, 1, &platform_conf_empty, &callbacks_empty);
if (err != 0)
Expand Down
5 changes: 4 additions & 1 deletion tests/multi_server_rtu.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "nanomodbus.h"
Expand Down Expand Up @@ -100,6 +101,7 @@ int main(int argc, char* argv[]) {
UNUSED_PARAM(argv);

nmbs_platform_conf c_conf;
nmbs_platform_conf_create(&c_conf);
c_conf.arg = wire;
c_conf.transport = NMBS_TRANSPORT_RTU;
c_conf.read = read_wire;
Expand All @@ -122,7 +124,8 @@ int main(int argc, char* argv[]) {
nmbs_set_read_timeout(&client, 5000);
nmbs_set_byte_timeout(&client, 100);

nmbs_callbacks callbacks = {0};
nmbs_callbacks callbacks;
nmbs_callbacks_create(&callbacks);
callbacks.read_coils = read_coils;

err = nmbs_server_create(&server1, 33, &s1_conf, &callbacks);
Expand Down
Loading

0 comments on commit 0dffd91

Please sign in to comment.