From 76f28fefb972d9f8b149cd583c2ff9c1f60fe69c Mon Sep 17 00:00:00 2001 From: Valerio De Benedetto Date: Thu, 2 Jun 2022 11:10:42 +0200 Subject: [PATCH] Updated examples --- examples/client-tcp.c | 16 ++-- examples/platform.h | 167 ++++++++++++++++++++++++------------------ examples/server-tcp.c | 21 +++--- 3 files changed, 112 insertions(+), 92 deletions(-) diff --git a/examples/client-tcp.c b/examples/client-tcp.c index 377edea..0f24cb5 100644 --- a/examples/client-tcp.c +++ b/examples/client-tcp.c @@ -1,7 +1,3 @@ -#include "nanomodbus.h" -#include "platform.h" -#include - /* * This example application connects via TCP to a modbus server at the specified address and port, and sends some * modbus requests to it. @@ -9,9 +5,14 @@ * Since the platform for this example is linux, the platform arg is used to pass (to the linux TCP read/write * functions) a pointer to the file descriptor of our TCP connection * - * The platform functions are for Linux systems. */ +#include + +#include "nanomodbus.h" +#include "platform.h" + + int main(int argc, char* argv[]) { if (argc < 3) { fprintf(stderr, "Usage: client-tcp [address] [port]\n"); @@ -27,9 +28,8 @@ int main(int argc, char* argv[]) { nmbs_platform_conf platform_conf; platform_conf.transport = NMBS_TRANSPORT_TCP; - platform_conf.read_byte = read_byte_fd_linux; - platform_conf.write_byte = write_byte_fd_linux; - platform_conf.sleep = sleep_linux; + platform_conf.read = read_fd_linux; + platform_conf.write = write_fd_linux; platform_conf.arg = conn; // Passing our TCP connection handle to the read/write functions // Create the modbus client diff --git a/examples/platform.h b/examples/platform.h index e461ac1..13b5f4b 100644 --- a/examples/platform.h +++ b/examples/platform.h @@ -1,86 +1,20 @@ -#include "nanomodbus.h" -#include #include -#include -#include #include #include #include #include + +#include +#include +#include #include #include #include - -// Read/write/sleep platform functions - -int read_byte_fd_linux(uint8_t* b, int32_t timeout_ms, void* arg) { - int fd = *(int*) arg; - - fd_set rfds; - FD_ZERO(&rfds); - FD_SET(fd, &rfds); - - struct timeval* tv_p = NULL; - struct timeval tv; - if (timeout_ms >= 0) { - tv_p = &tv; - tv.tv_sec = timeout_ms / 1000; - tv.tv_usec = (timeout_ms % 1000) * 1000; - } - - int ret = select(fd + 1, &rfds, NULL, NULL, tv_p); - if (ret == 0) { - return 0; - } - else if (ret == 1) { - ssize_t r = read(fd, b, 1); - if (r != 1) - return -1; - else { - return 1; - } - } - else - return -1; -} +#include "nanomodbus.h" -int write_byte_fd_linux(uint8_t b, int32_t timeout_ms, void* arg) { - int fd = *(int*) arg; - - fd_set wfds; - FD_ZERO(&wfds); - FD_SET(fd, &wfds); - - struct timeval* tv_p = NULL; - struct timeval tv; - if (timeout_ms >= 0) { - tv_p = &tv; - tv.tv_sec = timeout_ms / 1000; - tv.tv_usec = (timeout_ms % 1000) * 1000; - } - - int ret = select(fd + 1, NULL, &wfds, NULL, tv_p); - if (ret == 0) { - return 0; - } - else if (ret == 1) { - ssize_t r = write(fd, &b, 1); - if (r != 1) - return -1; - else { - return 1; - } - } - else - return -1; -} - - -void sleep_linux(uint32_t milliseconds, void* arg) { - usleep(milliseconds * 1000); -} +#define UNUSED_PARAM(x) ((x) = (x)) // Connection management @@ -125,6 +59,7 @@ int client_read_fd = -1; fd_set client_connections; void close_server_on_exit(int sig) { + UNUSED_PARAM(sig); if (server_fd != -1) close(server_fd); } @@ -208,7 +143,7 @@ void* server_poll() { } FD_SET(client, &client_connections); - printf("Accepted connection from %s\n", inet_ntoa(client_addr.sin_addr)); + printf("Accepted connection %d from %s\n", client, inet_ntoa(client_addr.sin_addr)); } else { client_read_fd = i; @@ -223,9 +158,95 @@ void* server_poll() { void disconnect(void* conn) { int fd = *(int*) conn; close(fd); + printf("Closed connection %d\n", fd); } void close_server() { close(server_fd); + printf("Server closed\n"); +} + + +// Read/write/sleep platform functions + +int read_fd_linux(uint8_t* buf, uint32_t count, int32_t timeout_ms, void* arg) { + int fd = *(int*) arg; + + int32_t total = 0; + while (total != (int32_t) count) { + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + struct timeval* tv_p = NULL; + struct timeval tv; + if (timeout_ms >= 0) { + tv_p = &tv; + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + } + + int ret = select(fd + 1, &rfds, NULL, NULL, tv_p); + if (ret == 0) { + return total; + } + else if (ret == 1) { + ssize_t r = read(fd, buf + total, 1); + if (r == 0) { + disconnect(arg); + return -1; + } + else if (r < 0) + return -1; + else { + total += (int32_t) r; + } + } + else + return -1; + } + + return total; +} + + +int32_t write_fd_linux(const uint8_t* buf, uint32_t count, int32_t timeout_ms, void* arg) { + int fd = *(int*) arg; + + int32_t total = 0; + while (total != (int32_t) count) { + fd_set wfds; + FD_ZERO(&wfds); + FD_SET(fd, &wfds); + + struct timeval* tv_p = NULL; + struct timeval tv; + if (timeout_ms >= 0) { + tv_p = &tv; + tv.tv_sec = timeout_ms / 1000; + tv.tv_usec = (timeout_ms % 1000) * 1000; + } + + int ret = select(fd + 1, NULL, &wfds, NULL, tv_p); + if (ret == 0) { + return 0; + } + else if (ret == 1) { + ssize_t w = write(fd, buf + total, count); + if (w == 0) { + disconnect(arg); + return -1; + } + else if (w <= 0) + return -1; + else { + total += (int32_t) w; + } + } + else + return -1; + } + + return total; } diff --git a/examples/server-tcp.c b/examples/server-tcp.c index 1f5a551..a554d6e 100644 --- a/examples/server-tcp.c +++ b/examples/server-tcp.c @@ -1,7 +1,3 @@ -#include "nanomodbus.h" -#include "platform.h" -#include - /* * This example application sets up a TCP server at the specified address and port, and polls from modbus requests * from more than one modbus client (more specifically from maximum 1024 clients, since it uses select()) @@ -12,12 +8,16 @@ * FC 15 (0x0F) Write Multiple Coils * FC 16 (0x10) Write Multiple registers * -* Since the platform for this example is linux, the platform arg is used to pass (to the linux TCP read/write -* functions) a pointer to the file descriptor of the current read client connection + * Since the platform for this example is linux, the platform arg is used to pass (to the linux TCP read/write + * functions) a pointer to the file descriptor of the current read client connection * - * The platform functions are for Linux systems. */ +#include + +#include "nanomodbus.h" +#include "platform.h" + // The data model of this sever will support coils addresses 0 to 100 and registers addresses from 0 to 32 #define COILS_ADDR_MAX 100 @@ -93,9 +93,8 @@ int main(int argc, char* argv[]) { nmbs_platform_conf platform_conf = {0}; platform_conf.transport = NMBS_TRANSPORT_TCP; - platform_conf.read_byte = read_byte_fd_linux; - platform_conf.write_byte = write_byte_fd_linux; - platform_conf.sleep = sleep_linux; + platform_conf.read = read_fd_linux; + platform_conf.write = write_fd_linux; platform_conf.arg = NULL; // We will set the arg (socket fd) later // These functions are defined in server.h @@ -130,7 +129,7 @@ int main(int argc, char* argv[]) { err = nmbs_server_poll(&nmbs); if (err != NMBS_ERROR_NONE) { - fprintf(stderr, "Error on modbus connection - %s\n", nmbs_strerror(err)); + printf("Error on modbus connection - %s\n", nmbs_strerror(err)); // In a more complete example, we would handle this error by checking its nmbs_error value } }