/* Copyright (C) 2021 Fredrik Öhrström This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ // Utility to relay serial port SND_NR telegrams using mosquitto pub. #define DEBUG 0 #define HOMEDIR "/home/yourdir" #define _GNU_SOURCE #include #include #include #include #include #include #include #include typedef unsigned char uchar; typedef uchar bool; #define true 1 #define false 0 int open_serial(const char *tty, int baud_rate) { int rc = 0; speed_t speed = 0; struct termios tios; //int DTR_flag = TIOCM_DTR; int fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) { usleep(1000*1000); fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) goto err; } switch (baud_rate) { case 300: speed = B300; break; case 600: speed = B600; break; case 1200: speed = B1200; break; case 2400: speed = B2400; break; case 4800: speed = B4800; break; case 9600: speed = B9600; break; case 19200: speed = B19200; break; case 38400: speed = B38400; break; case 57600: speed = B57600; break; case 115200: speed = B115200;break; default: goto err; } memset(&tios, 0, sizeof(tios)); rc = cfsetispeed(&tios, speed); if (rc < 0) goto err; rc = cfsetospeed(&tios, speed); if (rc < 0) goto err; // CREAD=Enable receive CLOCAL=Ignore any Carrier Detect signal. tios.c_cflag |= (CREAD | CLOCAL); tios.c_cflag &= ~CSIZE; tios.c_cflag |= CS8; tios.c_cflag &=~ CSTOPB; // Disable parity bit. tios.c_cflag &=~ PARENB; tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); tios.c_iflag &= ~INPCK; tios.c_iflag &= ~(IXON | IXOFF | IXANY); tios.c_oflag &=~ OPOST; tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = 0; rc = tcsetattr(fd, TCSANOW, &tios); if (rc < 0) goto err; // This code can toggle DTR... maybe necessary // for the pl2303 usb2serial driver/device. //rc = ioctl(fd, TIOCMBIC, &DTR_flag); //if (rc != 0) goto err; return fd; err: if (fd > 0) { close(fd); fd = -1; } return fd; } void manufacturerFlag(uchar lo, uchar hi, uchar *mfct) { int m_field = (hi*256)+lo; mfct[0] = (m_field/1024)%32+64; mfct[1] = (m_field/32)%32+64; mfct[2] = (m_field)%32+64; } bool find_telegram(uchar *buf, size_t *len) { size_t l = *len; if (*len < 10) return false; size_t tl = buf[0]; if (buf[1] != 0x44) return false; if (tl+1 > l) return false; size_t hl = 2*(tl+1)+1; uchar hex[hl]; for (size_t i=0; i= sizeof(buf)) { // Oups, a lot of random data fills up the buffer with no telegrams! len = 0; count_to_clear = 0; if (DEBUG) fprintf(stderr, "overflow clear\n"); } if (DEBUG) fprintf(stderr, "Reading..."); ssize_t n = read(fd, buf+len, sizeof(buf)-len); if (n <= 0) { if (errno == EBADF) { fprintf(stderr, "Could not read from serial port.\n"); break; } sleep(1); count_to_clear++; if (count_to_clear >= 2) { // After 2 seconds of no traffic, we clear the buffer. // Any existing telegrams should have been found already. len = 0; count_to_clear = 0; if (DEBUG) fprintf(stderr, "timeout clear\n"); } else { if (DEBUG) fprintf(stderr, "no data.\n"); } continue; } len+=n; if (DEBUG) fprintf(stderr, "received data, buffer len %zu\n", len); bool ok = find_telegram(buf, &len); if (!ok) { if (DEBUG) fprintf(stderr, "No telegram found in data."); } } close(fd); }