Differences

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

Link to this comparison view

sdk:scripts:serial-udp-server [2015/05/05 17:04] (current)
Line 1: Line 1:
 +====== SDK Script serial-udp-server.are ======
 +<code c serial-udp-server.are>​
 +/* DESC: This script reads messages coming from the serial port and forwards them via UDP to a remote host (and vice versa).
 + * Copyright (C) 2013 NetModule AG, Switzerland
 + */
 +
 +DEV = "​SERIAL1";​
 +
 +REMOTE_HOST = argv[1];
 +REMOTE_PORT = (int) argv[2];
 +LOCAL_PORT = (int) argv[3];
 +MAX_PACKET_SIZE = (int) argv[4]; ​       /* bytes */
 +POLL_TIMEOUT = (int) argv[5]; ​          /* seconds */
 +LATENCY = (int) argv[6]; ​               /* seconds */
 +
 +void usage()
 +{
 +    printf("​usage:​ serial-udp-server.are <​remote-host>​ <​remote-port>​ <​local-port>​ <​max-packet-size>​ <​poll-timeout>​ <​latency>​\n"​);​
 +    exit(1);
 +}
 +
 +int jiffy()
 +{
 +    sys = sysinfo();
 +    u = struct_get(sys,​ "​uptime"​);​
 +
 +    if (is_void(u) || u < 1) {
 +        return 0;
 +    } else {
 +        return u;
 +    }
 +}
 +
 +/* check arguments */
 +if (strlen(argv[1]) == 0) {
 +    nb_syslog("​ERROR:​ no remote host specified"​);​
 +    usage();
 +}
 +if (strlen(argv[2]) == 0) {
 +    nb_syslog("​ERROR:​ no remote port specified"​);​
 +    usage();
 +}
 +if (strlen(argv[3]) == 0) {
 +    nb_syslog("​ERROR:​ no local port specified"​);​
 +    usage();
 +}
 +if (strlen(argv[4]) == 0) {
 +    MAX_PACKET_SIZE = 1380;
 +}
 +if (strlen(argv[5]) == 0 || POLL_TIMEOUT < 1) {
 +    POLL_TIMEOUT = 1;
 +}
 +if (strlen(argv[6]) == 0 || LATENCY < 1) {
 +    LATENCY = 2;
 +}
 +
 +/* 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,​ 115200, 8, 1, 0, 0);
 +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);
 +}
 +
 +/* open UDP socket */
 +sock = socket(AF_INET,​ SOCK_DGRAM, IPPROTO_UDP);​
 +if (sock < 0) {
 +    nb_syslog("​ERROR:​ unable to open socket"​);​
 +    exit(1);
 +}
 +
 +/* bind socket to 1st LAN interface */
 +addr = nb_ifc_address("​LAN1"​);​
 +rc = bind(sock, REMOTE_PORT,​ addr);
 +if (rc == -1) {
 +    nb_syslog("​ERROR:​ unable to bind to port %d\n", REMOTE_PORT);​
 +    exit(1);
 +}
 +
 +nb_syslog("​Listening for messages (local %d, remote %s:​%d)",​ LOCAL_PORT, REMOTE_HOST,​ REMOTE_PORT);​
 +
 +fds = mkarray(sock,​ fd);
 +last = jiffy();
 +buffer = "";​
 +
 +while (1) {
 +    rc = select(fds, POLL_TIMEOUT);​
 +    if (rc == -1) {
 +        nb_syslog("​ERROR:​ select failed"​);​
 +        close(fd);
 +        exit(1);
 +    } 
 +
 +    if (rc == fd) {
 +        /* received something from serial device */
 +        data = read(fd, 4096);
 +        if (data) {
 +            buffer = strcat(buffer,​ data);
 +        }
 +    } else if (rc == sock) {
 +        /* received something from UDP */
 +        data = recvfrom(sock);​
 +        if (data) {
 +            len = strlen(data);​
 +            if (len > 0) {
 +                /* write to serial device */
 +                if (len > MAX_PACKET_SIZE) len = MAX_PACKET_SIZE;​
 +                write(fd, data, len);
 +            }
 +        }
 +    }
 +
 +    /* check serial buffer and send message */
 +    len = strlen(buffer);​
 +    if (len == 0) continue;
 +
 +    now = jiffy();
 +    elapsed = now - last;
 +
 +    if (len < MAX_PACKET_SIZE && elapsed < LATENCY) continue;
 +
 +    if (len <= MAX_PACKET_SIZE) {
 +        msg = buffer;
 +        msglen = len;
 +        buffer = "";​
 +    } else {
 +        msg = substr(buffer,​ 0, MAX_PACKET_SIZE);​
 +        msglen = MAX_PACKET_SIZE;​
 +        buffer = substr(buffer,​ MAX_PACKET_SIZE);​
 +    }
 +
 +    /* send UDP packet */
 +    sendbufto(sock,​ msg, msglen, REMOTE_HOST,​ REMOTE_PORT);​
 +    last = now;
 +}
 +
 +close(sock);​
 +close(fd);
 +
 +exit(0);
 +
 +</​code>​