/* DESC: This script implements a Modbus TCP RTU gateway * Copyright (C) 2015-2016 NetModule AG, Switzerland */ DEVIDX = 0; DEV = sprintf("SERIAL%d", (DEVIDX + 1)); TCP_PORT = 1502; DEBUG = 0; /* check serial port config */ st = nb_config_get(sprintf("serial.%d.status", DEVIDX)); if (st != "2") { nb_syslog("%s is not enabled for us", DEV); exit(1); } /* set attributes */ ret = nb_serial_setattr(DEV, 115200, 8, 1, 0, 0); if (ret != 0) { nb_syslog("Could not set serial attributes: %d", ret); exit(1); } /* open serial port */ serial_fd = nb_serial_open(DEV); if (serial_fd < 0) { nb_syslog("Unable to open %s", DEV); exit(1); } /* register serial_fd as modbus RTU */ if (nb_modbus_register(serial_fd, MODBUS_TYPE_RTU) != 0) { close(serial_fd); nb_syslog("Unable to register as modbus RTU (%s)", nb_modbus_last_error()); exit(1); } sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock < 0) { close(serial_fd); nb_syslog("Unable to open TCP socket"); exit(1); } ret = bind(sock, TCP_PORT, ""); if (ret == -1) { printf("Unable to bind TCP socket to port %d", TCP_PORT); close(serial_fd); close(sock); exit(1); } ret = listen(sock, 1); if (ret == -1) { nb_syslog("Unable to listen on TCP socket: %d", ret); close(serial_fd); close(sock); exit(1); } if (DEBUG == 1) { nb_modbus_set_debug(serial_fd, true); } printf("Listening for connections on port %d\n", TCP_PORT); tcp_client = -1; registered = 0; while (1) { if (tcp_client == -1) { tcp_client = accept(sock); if (tcp_client < 0) { nb_syslog("Unable to accept new connection"); sleep(1); continue; } else { if (DEBUG == 1) { nb_modbus_set_debug(tcp_client, true); } } } /* register client as modbus TCP */ if (registered == 0) { if (nb_modbus_register(tcp_client, MODBUS_TYPE_TCP)) { nb_syslog("Unable to register client (%s)", nb_modbus_last_error()); close(tcp_client); continue; } registered = 1; } /* wait for a modbus TCP request */ request = nb_modbus_receive(tcp_client); if (is_void(request)) { nb_syslog("Unable to receive modbus request (%s)", nb_modbus_last_error()); nb_modbus_unregister(tcp_client); close(tcp_client); tcp_client = -1; registered = 0; nb_syslog("Disconnected client"); } else { /* extract payload and forward it to RTU */ payload = nb_modbus_extract_payload(tcp_client, request); if (is_void(payload)) { nb_syslog("Unable to extract payload (%s)", nb_modbus_last_error()); } else { /* Modbus TCP - RTU must set the slave id */ ret = nb_modbus_set_slave (serial_fd, payload[0]); if (ret > 0) { nb_syslog("Unable to set modbus slave id"); break; } response = nb_modbus_send_raw(serial_fd, payload); if (is_void(response)) { nb_syslog("Unable to send modbus response (%s)", nb_modbus_last_error()); } else { /* extract payload and send response to modbus tcp */ payload = nb_modbus_extract_payload(serial_fd, response); if (is_void(payload)) { nb_syslog("Unable to extract payload (%s)", nb_modbus_last_error()); } else { nb_modbus_reply_raw_response(tcp_client, request, payload); } } } } } if (tcp_client > -1) { if (registered) { nb_modbus_unregister(tcp_client); } close(tcp_client); } nb_modbus_unregister(serial_fd); close(serial_fd); exit(0);