diff --git a/Makefile b/Makefile
index 01670d1..5824015 100644
--- a/Makefile
+++ b/Makefile
@@ -377,5 +377,8 @@ extract_fuzz_telegram_seeds:
@rm -f fuzz_testcases/telegrams/seed_*
@SEED=1; while read -r line; do echo "$${line}" | xxd -r -p - > "fuzz_testcases/telegrams/seed_$${SEED}"; SEED=$$((SEED + 1)); done < $(BUILD)/seeds; echo "Extracted $${SEED} seeds from simulations."
+relay: utils/relay.c
+ gcc -g utils/relay.c -o relay -O0 -ggdb -fsanitize=address -fno-omit-frame-pointer -fprofile-arcs -ftest-coverage
+
# Include dependency information generated by gcc in a previous compile.
include $(wildcard $(patsubst %.o,%.d,$(METER_OBJS)))
diff --git a/utils/relay.c b/utils/relay.c
new file mode 100644
index 0000000..e240a50
--- /dev/null
+++ b/utils/relay.c
@@ -0,0 +1,250 @@
+/*
+ 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);
+}