no way to compare when less than two revisions

Differences

This shows you the differences between two versions of the page.


sdk:serial-point-to-multipoint [2015/05/06 12:49] (current) – created - external edit 127.0.0.1
Line 1: Line 1:
 +====== Serial Point to Multipoint ======
 +This script reads messages coming from the local serial port and forwards them via TCP to a all remote host (and vice versa).
 +The local port can be the physical RS-232 (SERIAL1) or a virtual one using a USB adapter (SERIAL2).
 +<code c serial-point-to-multipoint.are>
 +// DESC: This script reads messages coming from the serial port and forwards them via TCP to a all remote host (and vice versa).
 +// Copyright (C) 2014 NetModule AG
 +//  usage: usage: serial-tcp-broadcast.are <remote-ip-1>  <remote-ip-2> .... <remote-ip-n>"
 +//  Version: 2.0
 +//
 +/* Options to configure by user*/
 +/* Serial Baud Rate 9600, 19200, 38400, 57600, 115200 */
 +SER_SPEED=115200;
 +/*  number of data bits (5, 6, 7, 8) */
 +SER_DATABIT=8;
 +/*  number of stop bits (1, 2) */
 +SER_STOPBIT=1;
 +/* parity (0=no parity, 1=odd parity, 2=even parity) */
 +SER_PARITY=0;
 +/*  flow control (0=none, 1=xon/xoff, 2=hardware) */
 +SER_FLOW=0;
 +/*  name of the Serial Interface (Only changed if your device has more then one serial Interface (NB3710) */
 +DEV = "SERIAL1";
 +
 +/* TCP Options */
 +/* If the script try to connect to a tcp slave, how many retries should it make */
 +RETRY = 3;
 +/* The pause in seconds between the retries*/
 +RETRY_INTERVAL = 3;
 +/* How many seconds should the script wait to run a new set of retries after the client got lost, or the retries were not sucessfull */
 +RECOVER_INTERVAL = 120;
 +
 +
 +//################################################################
 +//################################################################
 +//################################################################
 +/* Only changed things below this line if you know what you are doing */
 +//################################################################
 +//################################################################
 +//################################################################
 +POLL_TIMEOUT = 10;            /* seconds */
 +REMOTE_PORT =2000;  /* port of the remote serial slaves 2000 is default on NB Products */ 
 +
 +
 +
 +template slave 
 +{
 +    hostname = "";
 +    fd = -1;
 +    state = "down";
 +    downSince = 0; 
 +
 +
 +    void slave(string remotehost) 
 +    { 
 +        nb_syslog("creating slave %s",remotehost);
 +        if ( strlen(remotehost) > 0 ) {
 +            this.hostname=remotehost;
 +        } else {
 +            nb_syslog("No Hostname defined slave could not be created");
 +        }
 +    }
 +
 +    int jiffy()
 +    {
 +        sys = sysinfo();
 +        u = struct_get(sys, "uptime");
 +
 +        if (is_void(u) || u < 1) {
 +            return 0;
 +        } else {
 +            return u;
 +        }
 +    } 
 +
 +    int connect() {
 +        nb_syslog("Connecting to %s", this.hostname);
 +        /* open TCP socket */
 +        sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 +        setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,1);
 +        setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,1);
 +        setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,5);
 +        setsockopt(sock, SOL_TCP, TCP_KEEPCNT,5);
 +
 +        if (sock < 0) {
 +            nb_syslog("ERROR: unable to open socket");
 +        }
 +        for ( i = 0; i < RETRY; i++) {
 +            if (connect(sock, this.hostname, REMOTE_PORT) < 0){
 +                nb_syslog("Could not connect to %s (port %d)", this.hostname, REMOTE_PORT);
 +                nb_syslog("Retry connect, trial #%i, waiting %s sec", i, RETRY_INTERVAL);
 +                sleep(RETRY_INTERVAL);
 +            } else {
 +                nb_syslog("TCP connection is opened - remote server %s:%d", this.hostname, REMOTE_PORT);
 +                this.fd=sock;
 +                this.state="up";
 +                return 0;
 +            }
 +        }
 +        nb_syslog("Max retries reached, giving up TCP connection to %s",this.hostname);  
 +        this.downSince=this.jiffy();
 +        this.state="down";
 +        close(this.fd);
 +        return -1;
 +    }
 +
 +    int disconnect() {
 +        close(this.fd);
 +        this.fd=-1;
 +        this.state="down";
 +        this.downSince=this.jiffy();
 +        nb_syslog("Host %s disconnected", this.hostname);  
 +        return 0;
 +    }
 +
 +
 +} // of template slave
 +
 +void usage()
 +{
 +    nb_syslog("usage: serial-tcp-broadcast.are <remote-ip-1>  <remote-ip-2> .... <remote-ip-n>");
 +    exit(1);
 +}
 +
 +
 +
 +int start_serial() {
 +
 +    /* check serial port config */
 +    status = nb_config_get("serial.0.status");
 +    if (status != "2") {
 +        nb_syslog("Serial port is not enabled for us");
 +        exit(1);
 +    }
 +
 +    /* set attributes */
 +    rc = nb_serial_setattr(DEV, SER_SPEED, SER_DATABIT, SER_STOPBIT, SER_PARITY, SER_FLOW);
 +    if (rc != 0) {
 +        nb_syslog("ERROR: unable to set serial attributes (rc %d)", rc);
 +        exit(1);
 +    }
 +
 +    /* open serial port */
 +    fd = nb_serial_open(DEV);
 +    if (fd < 0) {
 +        nb_syslog("Unable to open serial device (%s)", DEV);
 +        exit(1);
 +    }
 +
 +    return fd;
 +}
 +
 +int stop_serial() {
 +
 +close(fd);
 +return 0; 
 +}
 +
 +
 +
 +
 +// ###################################################
 +// ###################################################
 +// ########Begining of Program########################
 +// ###################################################
 +// ###################################################
 +// ###################################################
 +
 +/* check arguments */
 +if (strlen(argv[1]) == 0) {
 +    nb_syslog("ERROR: no remote host specified");
 +    usage();
 +}
 +
 +/* create slave host list and set  */
 +
 +
 +nb_syslog("creating slaves");
 +for (i=1; i < argc; i++) {
 +    slaves[i-1] = new slave(argv[i]);
 +}
 +// connect to slave
 +//for ( i=0; i < length(slaves); i++) {
 +for ( i=0; i < length(slaves); i++) {
 +     nb_syslog("connect to slave %i",i);
 +    rc = slaves[i].connect();
 +    if (rc < 0) {
 +    nb_syslog("could not create socket %s", slaves[i].hostname);   
 +    }
 +}
 +
 +nb_syslog("starting serial");
 +serial_fd = start_serial();
 +
 +
 +
 +// Creating tcp fd array for select()
 +fds=mkarray();
 +tcp_fds=mkarray();
 +j=0;
 +for ( i=0; i < length(slaves); i++) {
 +     if (slaves[i].state == "up") {
 +     tcp_fds[j]=slaves[i].fd;
 +     j++;   
 +    }
 +}
 +fds=array_merge(serial_fd, tcp_fds);
 +
 +
 +while (1) {
 +    buffer = "";
 +    rc = select(fds, POLL_TIMEOUT);
 +    if (rc == -1) {
 +        nb_syslog("ERROR: select failed");
 +    } else if (rc == serial_fd) {
 +        /* received something from serial device */
 +        data = read(serial_fd, 4096);
 +        if (data) {
 +            serialbuffer = strcat(serialbuffer, data);
 +            nb_syslog("data on serial port: %s",serialBuffer);
 +        }
 +    } else if (rc != 0 && array_search(tcp_fds, rc) != NULL) {
 +        /* received something from TCP */
 +        data = recv(rc);
 +        len=strlen(data);
 +        if ( len > 0) {
 +                /* write to serial device */
 +                write(serial_fd, data, len);
 +
 +        } else if(len == 0) {
 +            //nb_syslog("tcp connection is gone lets set the slave correctly");
 +            for ( i=0; i < length(slaves); i++) {
 +                if (rc == slaves[i].fd) {
 +                /* lets put the socket on disable */
 +                    slaves[i].disconnect();   
 +                }
 +            }
 +
 +        }
 +     }
 +
 +
 +    /* check serial buffer and send message */
 +    len = strlen(serialbuffer);
 +    // we have data for the slaves lets sent it
 +    msg = serialbuffer;
 +    msglen = len;
 +    serialbuffer = "";
 +
 +    /* send TCP packet to every socket */
 +    if (len > 0) {
 +        for ( i=0; i < length(slaves); i++) {
 +            if (slaves[i].state == "up" ) {
 +                sent = send(slaves[i].fd, msg);
 +                if (sent == -1) {
 +                    nb_syslog("failed sending to host: %s fd: %i",slaves[i].hostname,slaves[i].fd);
 +                    /* lets put the socket on disable */
 +                    slaves[i].disconnect();   
 +                }
 +            }
 +        }
 +    }
 +    /* check if we have a error on the soocket */
 +    for ( i=0; i < length(slaves); i++) {
 +        if (slaves[i].state == "up" ) {
 +            sockop=getsockopt(slaves[i].fd, SOL_SOCKET, 4);
 +            if (sockop != 0) {
 +               nb_syslog("Error No %i on slave %s, Set Slave offline and try reconnect again", sockop, slaves[i].hostname);
 +               slaves[i].disconnect();
 +            }
 +        }
 +    }
 +
 +
 +    // reconnect to lost slaves    
 +    for ( i=0; i < length(slaves); i++) {
 +        if (slaves[i].state == "down" ) {
 +            if ( (slaves[i].downSince + RECOVER_INTERVAL) < slaves[i].jiffy() ) {
 +              slaves[i].connect();
 +            }
 +        }
 +    }
 +
 +    // recreate online fds
 +    fds=mkarray();
 +    tcp_fds=mkarray();
 +    j=0;
 +    for ( i=0; i < length(slaves); i++) {
 +         if (slaves[i].state == "up") {
 +             tcp_fds[j]=slaves[i].fd;
 +             j++;
 +        }
 +    }
 +    fds=array_merge(serial_fd, tcp_fds);
 +        
 +}
 +
 +
 +exit(0);
 +</code>
 +