nanoMODBUS/tests/multi_server_rtu.c
2023-05-16 16:38:04 +02:00

199 lines
4.8 KiB
C

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "nanomodbus.h"
#define WIRE_SIZE 1024
#define ITERATIONS 10
uint32_t run = 1;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
nmbs_t server1 = {0};
nmbs_t server2 = {0};
uint32_t index_w = 0;
uint32_t indices_r[3] = {0};
uint8_t wire[WIRE_SIZE];
int32_t read_wire(uint8_t* buf, uint16_t count, int32_t timeout_ms, void* arg) {
while (1) {
pthread_mutex_lock(&mutex);
uint32_t index = (uint32_t) arg;
uint32_t read = 0;
for (int i = 0; i < count; i++) {
if (indices_r[index] == index_w)
break;
indices_r[index] = (indices_r[index] + 1) % WIRE_SIZE;
buf[i] = wire[indices_r[index]];
read++;
}
pthread_mutex_unlock(&mutex);
if (read != 0)
return read;
if (timeout_ms != 0)
usleep(timeout_ms * 1000);
else
return 0;
timeout_ms = 0;
}
}
int32_t write_wire(const uint8_t* buf, uint16_t count, int32_t timeout_ms, void* arg) {
pthread_mutex_lock(&mutex);
uint32_t index = (uint32_t) arg;
uint32_t written = 0;
for (int i = 0; i < count; i++) {
index_w = (index_w + 1) % WIRE_SIZE;
indices_r[index] = index_w;
wire[index_w] = buf[i];
written++;
}
pthread_mutex_unlock(&mutex);
return written;
}
nmbs_error read_coils(uint16_t address, uint16_t quantity, nmbs_bitfield coils_out, void* arg) {
for (int i = 0; i < quantity; i++)
nmbs_bitfield_write(coils_out, address + i, 1);
return NMBS_ERROR_NONE;
}
void* poll_server1(void* arg) {
while (run) {
nmbs_server_poll(&server1);
}
}
void* poll_server2(void* arg) {
while (run) {
nmbs_server_poll(&server2);
}
}
int main(int argc, char* argv[]) {
nmbs_platform_conf c_conf;
c_conf.arg = wire;
c_conf.transport = NMBS_TRANSPORT_RTU;
c_conf.read = read_wire;
c_conf.write = write_wire;
c_conf.arg = 0;
nmbs_platform_conf s1_conf = c_conf;
s1_conf.arg = (void*) 1;
nmbs_platform_conf s2_conf = c_conf;
s2_conf.arg = (void*) 2;
nmbs_t client = {0};
nmbs_error err = nmbs_client_create(&client, &c_conf);
if (err != NMBS_ERROR_NONE) {
fprintf(stderr, "Error creating modbus client\n");
return 1;
}
nmbs_set_read_timeout(&client, 5000);
nmbs_set_byte_timeout(&client, 100);
nmbs_callbacks callbacks = {0};
callbacks.read_coils = read_coils;
err = nmbs_server_create(&server1, 33, &s1_conf, &callbacks);
if (err != NMBS_ERROR_NONE) {
fprintf(stderr, "Error creating modbus server 1\n");
return 1;
}
nmbs_set_read_timeout(&server1, 100);
nmbs_set_byte_timeout(&server1, 100);
err = nmbs_server_create(&server2, 99, &s2_conf, &callbacks);
if (err != NMBS_ERROR_NONE) {
fprintf(stderr, "Error creating modbus server 2\n");
return 1;
}
nmbs_set_read_timeout(&server2, 100);
nmbs_set_byte_timeout(&server2, 100);
pthread_t thread1, thread2;
int ret = pthread_create(&thread1, NULL, poll_server1, NULL);
if (ret != 0) {
fprintf(stderr, "Error creating thread 1\n");
return 1;
}
ret = pthread_create(&thread2, NULL, poll_server2, NULL);
if (ret != 0) {
fprintf(stderr, "Error creating thread 2\n");
return 1;
}
sleep(1);
nmbs_bitfield coils;
for (uint32_t c = 0; c < 10; c++) {
nmbs_bitfield_write(coils, c, rand() % 1);
}
nmbs_set_destination_rtu_address(&client, 33);
err = nmbs_write_multiple_coils(&client, 0, 10, coils);
if (err != NMBS_ERROR_NONE) {
fprintf(stderr, "Error writing coils to %d %s\n", 33, nmbs_strerror(err));
}
nmbs_bitfield coils_read;
err = nmbs_read_coils(&client, 0, 10, coils_read);
if (err != NMBS_ERROR_NONE) {
fprintf(stderr, "Error reading coils from %d %s\n", 33, nmbs_strerror(err));
}
if (memcmp(coils, coils, sizeof(nmbs_bitfield)) != 0) {
fprintf(stderr, "Coils mismatch from %d\n", 33);
}
for (uint32_t c = 0; c < 10; c++) {
nmbs_bitfield_write(coils, c, rand() % 1);
}
nmbs_set_destination_rtu_address(&client, 99);
err = nmbs_write_multiple_coils(&client, 0, 10, coils);
if (err != NMBS_ERROR_NONE) {
fprintf(stderr, "Error writing coils to %d %s\n", 99, nmbs_strerror(err));
}
err = nmbs_read_coils(&client, 0, 10, coils_read);
if (err != NMBS_ERROR_NONE) {
fprintf(stderr, "Error reading coils from %d %s\n", 99, nmbs_strerror(err));
}
if (memcmp(coils, coils, sizeof(nmbs_bitfield)) != 0) {
fprintf(stderr, "Coils mismatch from %d\n", 99);
}
sleep(5);
run = 0;
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}