/*
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);
}