Open napperley opened 4 years ago
I had the same issue recently.
Below is a Hello World Modbus TCP server.
Hope this helps.
I have the following in my main() function.
//Start Modbus slave/server thread pthread_t thread_id; pthread_create(&thread_id, NULL, modbus_main, NULL);
/*
Hello World: Modbus slave function. Address node 3, data in registers 40001, 40002, and 40003
/*
void modbus_main(void x) {
int i;
int server_socket = -1;
modbus_t *ctx;
ctx = modbus_new_tcp(NULL, 502);
// modbus_set_debug(ctx, TRUE);
int header_length = modbus_get_header_length(ctx);
server_socket = modbus_tcp_listen(ctx, 2); //Listen to max two connection
//This next line will block program execution until there is a connection made
modbus_tcp_accept(ctx, &server_socket);
modbus_mapping_t *mb_map, *mb_mapping[100]; //Array of pointers for each device
//this sets up 500 holding registers starting at 40001
mb_map = modbus_mapping_new(0, 0, 500, 0);
mb_mapping[1] = mb_map;
if (mb_mapping[1] == NULL) {
fprintf(stderr, "Failed to allocate the mapping: %s\n",
modbus_strerror(errno));
modbus_free(ctx);
return;
}
for (;;) {
uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
int rc;
do {
rc = modbus_receive(ctx, query);
/* Filtered queries return 0 */
} while (rc == 0);
/* The connection is not closed on errors which require on reply such as
bad CRC in RTU.
*/
if (rc == -1 && errno != EMBBADCRC) {
/* Quit */
break; //the loop
}
//Set up some dummy data
mb_mapping[1]->tab_registers[0] = rand() % 1000;
mb_mapping[1]->tab_registers[1] = rand() % 100;
mb_mapping[1]->tab_registers[2] = 333;
//See here for a description of the query
//http://www.simplymodbus.ca/FC03.htm
printf("Node=%d function=%d num registers=%d start addr=%d\n", query[header_length - 1], query[header_length], MODBUS_GET_INT16_FROM_INT8(query, header_length + 3), MODBUS_GET_INT16_FROM_INT8(query, header_length + 1) + 40001);
//query[6] = modbus node address
//query[7] = modbus function
if (query[6] != 3) { //If the node is NOT correct
modbus_reply_exception(ctx, query, MODBUS_EXCEPTION_GATEWAY_TARGET);
continue;
} else {
/* Return data */
/* rc is the query size */
modbus_reply(ctx, query, rc, mb_mapping[1]);
}
}
printf("Quit the loop: %s\n", modbus_strerror(errno));
if (server_socket != -1) {
close(server_socket);
}
modbus_mapping_free(mb_mapping[1]);
modbus_close(ctx);
modbus_free(ctx);
}
From: Nick Apperley notifications@github.com Sent: Wednesday, April 8, 2020 10:42 PM To: stephane/libmodbus libmodbus@noreply.github.com Cc: Subscribed subscribed@noreply.github.com Subject: [stephane/libmodbus] Missing Modbus TCP Server Sample (#530)
Although there is a C source file https://github.com/stephane/libmodbus/blob/master/tests/unit-test-server.c showing how to do a Modbus server it covers far too much (it is too complex), and lacks focus on a specific area. To make matters worse the source file isn't extensively documented (especially on memory management, and how to send a response back to the client with register data set in the response), and lacks proper code structure (all logic is done in a enormous sized main function).
The libmodbus library would greatly benefit from having a small Modbus TCP server sample that only focuses on a single area, and shows the minimum required to get a Modbus TCP server implemented.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/stephane/libmodbus/issues/530 , or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFDSAKLM6IJW6CVTBQER43RLUYXLANCNFSM4MEMNACQ . https://github.com/notifications/beacon/AAFDSAJVOLP543N3PSR2XQDRLUYXLA5CNFSM4MEMNAC2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4I4VGNUQ.gif
That example doesn't work. An error message appears after sending the reply on the server side:
Illegal data address 0x9C44 in read_input_registers
0x9c44 is simply not in range of the registers setup in @watsocd 's example, so it's behaving exactly as expected. They setup 500 holding registers, and no input registers.
Code comment at the top: Hello World: Modbus slave function. Address node 3, data in registers 40001, 40002, and 40003
Of course no/limited error checking. IT IS a Hello World minimal example for holding (40000) registers.
Caution: this demo server code only serve for one client.
If you want the server serving for multi clients at the same time.
You should see bandwidth-server-many-up.c in tests dir.
or you can try this https://github.com/alongL/modbusServer
The code above gives me segmentation fault during runtime. So does the random-test-server when i access the mb_mapping->tab_registers[0] to print or to assign some value to it. Without accessing the mb_mapping->tab_registers[index] it runs fine. As a sever i want to assign some values in the tab_registers array. Any kind of help is greatly appreciated.
I am running it in rhel 7 with libmodbus-3.1.10 installed.
Although there is a C source file showing how to do a Modbus server it covers far too much (it is too complex), and lacks focus on a specific area. To make matters worse the source file isn't extensively documented (especially on memory management, and how to send a response back to the client with register data set in the response), and lacks proper code structure (all logic is done in a enormous sized main function).
The libmodbus library would greatly benefit from having a small Modbus TCP server sample that only focuses on a single area, and shows the minimum required to get a Modbus TCP server implemented.