commit
0dffd91e3d
@ -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.
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
28
nanomodbus.c
28
nanomodbus.c
@ -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__)
|
||||
@ -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)
|
||||
@ -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;
|
||||
}
|
||||
@ -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];
|
||||
@ -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)
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
22
nanomodbus.h
22
nanomodbus.h
@ -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().
|
||||
*/
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -268,6 +274,11 @@ 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
|
||||
@ -275,6 +286,11 @@ void nmbs_set_byte_timeout(nmbs_t* nmbs, int32_t timeout_ms);
|
||||
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.
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nanomodbus.h"
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
||||
@ -31,16 +31,16 @@ int32_t write_empty(const uint8_t* data, uint16_t count, int32_t timeout, void*
|
||||
|
||||
void test_server_create(nmbs_transport transport) {
|
||||
nmbs_t nmbs;
|
||||
nmbs_error err;
|
||||
|
||||
nmbs_platform_conf platform_conf_empty = {
|
||||
.transport = transport,
|
||||
.read = read_empty,
|
||||
.write = write_empty,
|
||||
};
|
||||
nmbs_error err = NMBS_ERROR_NONE;
|
||||
|
||||
nmbs_platform_conf platform_conf_empty;
|
||||
nmbs_platform_conf_create(&platform_conf_empty);
|
||||
platform_conf_empty.transport = transport;
|
||||
platform_conf_empty.read = read_empty;
|
||||
platform_conf_empty.write = write_empty;
|
||||
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
should("create a modbus server");
|
||||
reset(nmbs);
|
||||
@ -112,13 +112,15 @@ int32_t read_timeout_second(uint8_t* buf, uint16_t count, int32_t timeout, void*
|
||||
|
||||
void test_server_receive_base(nmbs_transport transport) {
|
||||
nmbs_t server;
|
||||
nmbs_error err;
|
||||
nmbs_error err = NMBS_ERROR_NONE;
|
||||
nmbs_platform_conf platform_conf;
|
||||
nmbs_callbacks callbacks_empty;
|
||||
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
should("honor read_timeout and return normally");
|
||||
reset(server);
|
||||
|
||||
nmbs_platform_conf_create(&platform_conf);
|
||||
platform_conf.transport = transport;
|
||||
platform_conf.read = read_timeout;
|
||||
platform_conf.write = write_empty;
|
||||
@ -204,7 +206,8 @@ nmbs_error read_discrete(uint16_t address, uint16_t quantity, nmbs_bitfield coil
|
||||
void test_fc1(nmbs_transport transport) {
|
||||
const uint8_t fc = 1;
|
||||
uint8_t raw_res[260];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -213,7 +216,11 @@ void test_fc1(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.read_coils = read_discrete});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_coils = read_discrete;
|
||||
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with quantity 0");
|
||||
@ -272,7 +279,8 @@ void test_fc1(nmbs_transport transport) {
|
||||
void test_fc2(nmbs_transport transport) {
|
||||
const uint8_t fc = 2;
|
||||
uint8_t raw_res[260];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -281,7 +289,10 @@ void test_fc2(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.read_discrete_inputs = read_discrete});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_discrete_inputs = read_discrete;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with quantity 0");
|
||||
@ -378,7 +389,8 @@ nmbs_error read_registers(uint16_t address, uint16_t quantity, uint16_t* registe
|
||||
void test_fc3(nmbs_transport transport) {
|
||||
const uint8_t fc = 3;
|
||||
uint8_t raw_res[260];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -387,7 +399,10 @@ void test_fc3(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.read_holding_registers = read_registers});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_holding_registers = read_registers;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with quantity 0");
|
||||
@ -434,7 +449,8 @@ void test_fc3(nmbs_transport transport) {
|
||||
void test_fc4(nmbs_transport transport) {
|
||||
const uint8_t fc = 4;
|
||||
uint8_t raw_res[260];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -443,7 +459,10 @@ void test_fc4(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.read_input_registers = read_registers});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_input_registers = read_registers;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with quantity 0");
|
||||
@ -516,7 +535,8 @@ nmbs_error write_coil(uint16_t address, bool value, uint8_t unit_id, void* arg)
|
||||
void test_fc5(nmbs_transport transport) {
|
||||
const uint8_t fc = 5;
|
||||
uint8_t raw_res[260];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -525,7 +545,10 @@ void test_fc5(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.write_single_coil = write_coil});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.write_single_coil = write_coil;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("return NMBS_EXCEPTION_ILLEGAL_DATA_VALUE when calling with value !0x0000 or 0xFF000");
|
||||
@ -588,7 +611,8 @@ nmbs_error write_register(uint16_t address, uint16_t value, uint8_t unit_id, voi
|
||||
void test_fc6(nmbs_transport transport) {
|
||||
const uint8_t fc = 6;
|
||||
uint8_t raw_res[260];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -597,7 +621,10 @@ void test_fc6(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.write_single_register = write_register});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.write_single_register = write_register;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("return NMBS_EXCEPTION_SERVER_DEVICE_FAILURE when server handler returns any non-exception error");
|
||||
@ -676,7 +703,8 @@ void test_fc15(nmbs_transport transport) {
|
||||
const uint8_t fc = 15;
|
||||
uint8_t raw_res[260];
|
||||
nmbs_bitfield bf = {0};
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -685,7 +713,10 @@ void test_fc15(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.write_multiple_coils = write_coils});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.write_multiple_coils = write_coils;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with quantity 0");
|
||||
@ -797,7 +828,8 @@ void test_fc16(nmbs_transport transport) {
|
||||
const uint8_t fc = 16;
|
||||
uint8_t raw_res[260];
|
||||
uint16_t registers[125];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -806,7 +838,10 @@ void test_fc16(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.write_multiple_registers = write_registers});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.write_multiple_registers = write_registers;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with quantity 0");
|
||||
@ -899,7 +934,8 @@ nmbs_error read_file(uint16_t file_number, uint16_t record_number, uint16_t* reg
|
||||
|
||||
void test_fc20(nmbs_transport transport) {
|
||||
uint16_t registers[128];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -908,7 +944,10 @@ void test_fc20(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.read_file_record = read_file});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_file_record = read_file;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with file_number 0");
|
||||
@ -978,7 +1017,8 @@ nmbs_error write_file(uint16_t file_number, uint16_t record_number, const uint16
|
||||
|
||||
void test_fc21(nmbs_transport transport) {
|
||||
uint16_t registers[128];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -987,7 +1027,10 @@ void test_fc21(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.write_file_record = write_file});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.write_file_record = write_file;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with file_number 0");
|
||||
@ -1024,7 +1067,8 @@ void test_fc21(nmbs_transport transport) {
|
||||
void test_fc23(nmbs_transport transport) {
|
||||
uint16_t registers[125];
|
||||
uint16_t registers_write[125];
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
@ -1034,8 +1078,11 @@ void test_fc23(nmbs_transport transport) {
|
||||
|
||||
stop_client_and_server();
|
||||
|
||||
start_client_and_server(transport, &(nmbs_callbacks){.read_holding_registers = read_registers,
|
||||
.write_multiple_registers = write_registers});
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_holding_registers = read_registers;
|
||||
callbacks.write_multiple_registers = write_registers;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with quantity 0");
|
||||
@ -1150,25 +1197,31 @@ void test_fc43_14(nmbs_transport transport) {
|
||||
buffers[i] = &mem[i * buf_size];
|
||||
}
|
||||
|
||||
nmbs_callbacks callbacks_empty = {0};
|
||||
nmbs_callbacks callbacks_empty;
|
||||
nmbs_callbacks_create(&callbacks_empty);
|
||||
start_client_and_server(transport, &callbacks_empty);
|
||||
|
||||
should("return NMBS_EXCEPTION_ILLEGAL_FUNCTION when callback is not registered server-side");
|
||||
expect(nmbs_read_device_identification(&CLIENT, 0x00, buffers[0], buf_size) == NMBS_EXCEPTION_ILLEGAL_FUNCTION);
|
||||
|
||||
stop_client_and_server();
|
||||
start_client_and_server(transport,
|
||||
&(nmbs_callbacks){.read_device_identification = read_device_identification,
|
||||
.read_device_identification_map = read_device_identification_map});
|
||||
|
||||
nmbs_callbacks callbacks;
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_device_identification = read_device_identification;
|
||||
callbacks.read_device_identification_map = read_device_identification_map;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("immediately return NMBS_ERROR_INVALID_ARGUMENT when calling with an invalid Object Id");
|
||||
expect(nmbs_read_device_identification(&CLIENT, 0x07, buffers[0], buf_size) == NMBS_ERROR_INVALID_ARGUMENT);
|
||||
|
||||
stop_client_and_server();
|
||||
start_client_and_server(
|
||||
transport, &(nmbs_callbacks){.read_device_identification = read_device_identification,
|
||||
.read_device_identification_map = read_device_identification_map_incomplete});
|
||||
|
||||
nmbs_callbacks_create(&callbacks);
|
||||
callbacks.read_device_identification = read_device_identification;
|
||||
callbacks.read_device_identification_map = read_device_identification_map_incomplete;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("return NMBS_ERROR_SERVER_DEVICE_FAILURE when not exposing Basic object IDs");
|
||||
@ -1176,9 +1229,10 @@ void test_fc43_14(nmbs_transport transport) {
|
||||
NMBS_EXCEPTION_SERVER_DEVICE_FAILURE);
|
||||
|
||||
stop_client_and_server();
|
||||
start_client_and_server(transport,
|
||||
&(nmbs_callbacks){.read_device_identification = read_device_identification,
|
||||
.read_device_identification_map = read_device_identification_map});
|
||||
|
||||
callbacks.read_device_identification = read_device_identification;
|
||||
callbacks.read_device_identification_map = read_device_identification_map;
|
||||
start_client_and_server(transport, &callbacks);
|
||||
nmbs_set_callbacks_arg(&SERVER, (void*) &callbacks_user_data);
|
||||
|
||||
should("return NMBS_EXCEPTION_ILLEGAL_FUNCTION with wrong MEI type");
|
||||
|
||||
@ -155,6 +155,7 @@ int32_t write_socket_client(const uint8_t* buf, uint16_t count, int32_t timeout_
|
||||
|
||||
nmbs_platform_conf nmbs_platform_conf_server;
|
||||
nmbs_platform_conf* platform_conf_socket_server(nmbs_transport transport) {
|
||||
nmbs_platform_conf_create(&nmbs_platform_conf_server);
|
||||
nmbs_platform_conf_server.transport = transport;
|
||||
nmbs_platform_conf_server.read = read_socket_server;
|
||||
nmbs_platform_conf_server.write = write_socket_server;
|
||||
@ -164,6 +165,7 @@ nmbs_platform_conf* platform_conf_socket_server(nmbs_transport transport) {
|
||||
|
||||
nmbs_platform_conf nmbs_platform_conf_client;
|
||||
nmbs_platform_conf* platform_conf_socket_client(nmbs_transport transport) {
|
||||
nmbs_platform_conf_create(&nmbs_platform_conf_client);
|
||||
nmbs_platform_conf_client.transport = transport;
|
||||
nmbs_platform_conf_client.read = read_socket_client;
|
||||
nmbs_platform_conf_client.write = write_socket_client;
|
||||
|
||||
@ -27,11 +27,11 @@ 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_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_error err = nmbs_client_create(&nmbs, &platform_conf_empty);
|
||||
if (err != 0)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user