SDK Script modbus-tcp-rtu-gateway.are

modbus-tcp-rtu-gateway.are
/* 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);