summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile26
-rw-r--r--email.c51
-rw-r--r--net_rx.c23
-rw-r--r--rx.c170
-rw-r--r--serial_rx.c26
-rw-r--r--sia.c1
-rw-r--r--util.c66
-rw-r--r--util.h2
8 files changed, 290 insertions, 75 deletions
diff --git a/Makefile b/Makefile
index b55dec5..99f1d77 100644
--- a/Makefile
+++ b/Makefile
@@ -3,12 +3,15 @@ PKG_CONFIG=pkg-config
CURSES_CFLAGS=$(shell ${PKG_CONNFIG} --cflags ncursesw)
CURSES_LIBS=$(shell ${PKG_CONFIG} --libs ncursesw)
-#OPENWRT_BASE=/root/projects/openwrt/gl-inet-mt300n-v2/master-d20f4fc
-#TOOLCHAIN=${OPENWRT_BASE}/staging_dir/toolchain-mipsel_24kc_gcc-7.3.0_musl
-#CC=${TOOLCHAIN}/bin/mipsel-openwrt-linux-musl-gcc
-#STAGING_DIR=${OPENWRT_BASE}/staging_dir/target-mipsel_24kc_musl
-#export STAGING_DIR
-#CFLAGS=-I${STAGING_DIR}/include -I${TOOLS_DIR}/include
+ifeq (${STAGING_DIR},)
+ OPENWRT_BASE=/root/projects/openwrt/gl-inet-mt300n-v2/master-d20f4fc
+ TOOLCHAIN=${OPENWRT_BASE}/staging_dir/toolchain-mipsel_24kc_gcc-7.3.0_musl
+ CC=${TOOLCHAIN}/bin/mipsel-openwrt-linux-musl-gcc
+ STAGING_DIR:=${OPENWRT_BASE}/staging_dir/target-mipsel_24kc_musl
+ export STAGING_DIR
+ CFLAGS=-I${STAGING_DIR}/include -I${TOOLS_DIR}/include
+ LDFLAGS=
+endif
PROGS=net_rx net_arm serial_rx serial_arm serial_keypad net_keypad #test_email
@@ -20,9 +23,9 @@ install: ${PROGS}
mkdir -p ${DESTDIR}/${PREFIX}/bin
for i in ${PROGS}; do install -m 755 $$i ${DESTDIR}/${PREFIX}/bin/$$i; done
-net_rx:util.o sia.o net_rx.o rx.o email.o
-net_arm:util.o sia.o net_arm.o arm.o
-serial_rx:util.o sia.o serial_rx.o rx.o email.o
+net_rx:util.o sia.o net_rx.o rx.o email.o mqtt.o
+net_arm:util.o sia.o net_arm.o arm.o
+serial_rx:util.o sia.o serial_rx.o rx.o email.o mqtt.o
serial_arm:util.o sia.o serial_arm.o arm.o
test_email:test_email.o email.o
@@ -37,3 +40,8 @@ tidy:
clean:
/bin/rm -f *.o
+
+deploy:
+ rsync net_rx galaxy:/usr/bin/net_rx
+ ssh galaxy killall net_rx
+ ssh galaxy killall sleep
diff --git a/email.c b/email.c
index 0ee47ff..7374c34 100644
--- a/email.c
+++ b/email.c
@@ -8,60 +8,11 @@
#include <sys/wait.h>
+#include "util.h"
#include "email.h"
-static int daemonish (int nochdir, int noclose)
-{
- pid_t pid;
- int status;
-
- if (!nochdir && chdir ("/"))
- return -1;
-
- if (!noclose) {
- int fd, failed = 0;
-
- if ((fd = open ("/dev/null", O_RDWR)) < 0) return -1;
-
- if (dup2 (fd, 0) < 0 || dup2 (fd, 1) < 0 || dup2 (fd, 2) < 0)
- failed++;
-
- if (fd > 2) close (fd);
-
- if (failed) return -1;
- }
-
- switch ((pid = fork())) {
- case 0:
- break;
-
- case -1:
- return -1;
-
- default:
- waitpid (pid, &status, 0);
- return 1;;
- }
-
- if (setsid() < 0) return -1;
-
- switch (fork()) {
- case 0:
- break;
-
- case -1:
- return -1;
-
- default:
- _exit (0);
- }
-
- return 0;
-}
-
-
static void write_complete (int fd, const void *_buf, size_t len)
{
ssize_t writ;
diff --git a/net_rx.c b/net_rx.c
index 15e181b..7bcc01e 100644
--- a/net_rx.c
+++ b/net_rx.c
@@ -10,13 +10,14 @@
#include "util.h"
#include "sia.h"
-extern int new_block (int fd, SIA_Block *b, int log, const char *email);
+extern int new_block (int fd, SIA_Block *b, int log, const char *email, const char *state_file, const char *mqtt_host);
extern void periodic_task (void);
+extern void dump_state (const char *);
static int usage (const char *name)
{
fprintf (stderr, "Usage:\n");
- fprintf (stderr, "%s [ -l ] [ -p listen_port ] [ -m email address]\n\n", name);
+ fprintf (stderr, "%s [ -l ] [ -p listen_port ] [ -e email address] [ -s state_file ] [ -m mqtt_host ]\n\n", name);
fprintf (stderr, "listen_port defaults to 10002\n");
return 1;
@@ -39,9 +40,11 @@ int main (int argc, char *argv[])
unsigned ptr = 0;
const char *email = NULL;
+ const char *state_file = NULL;
+ const char *mqtt_host = NULL;
- while ((opt = getopt (argc, argv, "p:lm:")) != -1) {
+ while ((opt = getopt (argc, argv, "p:le:s:m:")) != -1) {
switch (opt) {
case 'p':
port = atoi (optarg);
@@ -51,10 +54,18 @@ int main (int argc, char *argv[])
log++;
break;
- case 'm':
+ case 'e':
email = optarg;
break;
+ case 's':
+ state_file = optarg;
+ break;
+
+ case 'm':
+ mqtt_host = optarg;
+ break;
+
default: /* '?' */
return usage (argv[0]);
}
@@ -72,6 +83,8 @@ int main (int argc, char *argv[])
set_blocking (fd);
+ if (state_file)
+ dump_state (state_file);
// Epically budget TCP server
@@ -123,7 +136,7 @@ int main (int argc, char *argv[])
break;
default: /*Valid block */
- new_block (afd, &b, log, email);
+ new_block (afd, &b, log, email, state_file, mqtt_host);
ptr = 0;
break;
}
diff --git a/rx.c b/rx.c
index 427dcd3..7f39d6d 100644
--- a/rx.c
+++ b/rx.c
@@ -6,33 +6,191 @@
#include "sia.h"
#include "email.h"
+#include "mqtt.h"
+#include "util.h"
-static void msg (char *account, char *event, char *ascii, int log, const char *email)
+
+typedef struct thing_struct {
+ struct thing_struct *next;
+ char *msg;
+ unsigned seq;
+} Thing;
+
+static Thing *thing_list = NULL;
+
+void dump_state (const char *file)
+{
+ Thing *thing;
+ FILE *f;
+ char fn[1024];
+
+ strcpy (fn, file);
+ strcat (fn, ".next");
+
+ f = fopen (fn, "w");
+
+ if (!f) return;
+
+ for (thing = thing_list; thing; thing = thing->next) {
+ fprintf (f, "%d ", thing->seq);
+ fputs (thing->msg, f);
+ fputc ('\n', f);
+ }
+
+ fclose (f);
+
+ rename (fn, file);
+}
+
+
+static void maintain_state (const char *msg, const char *state_file)
+{
+ Thing *thing;
+
+
+ switch (*msg) {
+ case '+':
+ case '-':
+ break;
+
+ default:
+ return;
+ }
+
+
+ for (thing = thing_list; thing; thing = thing->next) {
+
+ if (!strcmp (&msg[1], &thing->msg[1])) {
+ strcpy (thing->msg, msg);
+ dump_state (state_file);
+ return;
+ }
+ }
+
+ thing = malloc (sizeof (Thing));
+ thing->next = thing_list;
+ thing->msg = strdup (msg);
+ thing->seq = 1;
+
+ thing_list = thing;
+
+ dump_state (state_file);
+}
+
+
+
+static void send_mqtt (const char *msg, const char *host)
+{
+ char value[1024];
+ char topic[1024];
+ char prefix[] = "stat/alarm/";
+ const char *rptr;
+ char *wptr;
+ int retain = 0;
+
+
+ if (!host) return;
+
+
+ switch (*msg) {
+ case '+':
+ case '-':
+ retain = 1;
+ break;
+ }
+
+
+
+ for (rptr = msg, wptr = value; (*rptr) && ((*rptr) != ' '); rptr++, wptr++)
+ *wptr = *rptr;
+
+ if (!*rptr) return;
+
+ *wptr = 0;
+
+ while (*rptr == ' ') rptr++;
+
+ strcpy (topic, prefix);
+
+ wptr = topic + (sizeof (prefix) - 1);
+
+ if (!*rptr)
+ strcpy (wptr, value + 1);
+
+ else {
+ for (; *rptr; rptr++, wptr++) {
+ if (local_isalnum (*rptr))
+ *wptr = *rptr;
+
+ else
+ *wptr = '_';
+ }
+
+ *wptr = 0;
+ }
+
+ mqtt (host, topic, value, retain);
+
+#if 0
+ /* JMM and an ugly hack */
+
+ if (!strcmp (topic, "stat/alarm/Rain_Sensor")) {
+ if (value[0] == '+')
+ mqtt (host, "cmnd/vent/POWER1", "0", 0);
+
+ else if (value[0] == '-')
+ mqtt (host, "cmnd/vent/POWER1", "1", 0);
+ }
+
+#endif
+}
+
+static void msg (char *account, char *event, char *ascii, int log, const char *email, const char *state_file, const char *mqtt_host)
{
char body[256];
char subject[256];
+ if (state_file)
+ maintain_state (ascii, state_file);
+
+ if (strstr (ascii, "FULL SET"))
+ send_mqtt ("+ARMED SYSTEM", mqtt_host);
+
+ else if (strstr (ascii, "UNSET"))
+ send_mqtt ("-ARMED SYSTEM", mqtt_host);
+
+ else
+ send_mqtt (ascii, mqtt_host);
+
snprintf (body, sizeof (body) - 1, "%s %64s %s", account, event, ascii);
body[sizeof (body) - 1] = 0;
if (log)
syslog (LOG_WARNING, "SIA: %s", body);
- printf ("%s\n", body);
if (!email) return;
if (strstr (body, "HEARTBT")) return;
+ if (strstr (body, "Valid")) return;
+
+ if (strstr (body, "Rejct")) return;
+
+ if (strstr (body, "CUSTOM")) return;
+
+ if (strstr (body, "LOG")) return;
+
+
snprintf (subject, sizeof (subject) - 1, "Galaxy SIA: %s", ascii);
send_email (email, subject, body);
}
-int new_block (int fd, SIA_Block *b, int log, const char *email)
+int new_block (int fd, SIA_Block *b, int log, const char *email, const char *state_file, const char *mqtt_host)
{
static int have_ascii_messages = 0; /*SIA level 3 doesn't have ascii, SIA level 4 does */
@@ -56,7 +214,7 @@ int new_block (int fd, SIA_Block *b, int log, const char *email)
memcpy (event, b->data, len);
event[len] = 0;
- if (!have_ascii_messages) msg (account, event, "", log, email);
+ if (!have_ascii_messages) msg (account, event, "", log, email, state_file, mqtt_host);
break;
@@ -65,7 +223,7 @@ int new_block (int fd, SIA_Block *b, int log, const char *email)
memcpy (ascii, b->data, len);
ascii[len] = 0;
- msg (account, event, ascii, log, email);
+ msg (account, event, ascii, log, email, state_file, mqtt_host);
break;
}
@@ -77,3 +235,5 @@ void periodic_task (void)
}
+
+
diff --git a/serial_rx.c b/serial_rx.c
index 6165a01..340420b 100644
--- a/serial_rx.c
+++ b/serial_rx.c
@@ -9,14 +9,15 @@
#include "sia.h"
-extern int new_block (int fd, SIA_Block *b, int log, const char *email);
+extern int new_block (int fd, SIA_Block *b, int log, const char *email, const char *state_file, const char *mqtt_host);
+extern void dump_state (const char *);
//extern void periodic_task(void);
static int usage (const char *name)
{
fprintf (stderr, "Usage:\n");
- fprintf (stderr, "%s [ -l ] [ -b baud ] -p serial_device [ -m email address ]\n\n", name);
+ fprintf (stderr, "%s [ -l ] [ -b baud ] -p serial_device [ -e email address ] [ -s state_file ] [ -m mqtt_host ]\n\n", name);
fprintf (stderr, "baud defaults to 9600\n");
return 1;
@@ -32,13 +33,15 @@ int main (int argc, char *argv[])
SIA_Block b;
ssize_t red;
int log = 0;
- const char *email = NULL;
unsigned char buf[SIA_MAX_BLOCK_LENGTH];
unsigned ptr = 0;
+ const char *email = NULL;
+ const char *state_file = NULL;
+ const char *mqtt_host = NULL;
- while ((opt = getopt (argc, argv, "p:b:lm:")) != -1) {
+ while ((opt = getopt (argc, argv, "p:b:le:s:m:")) != -1) {
switch (opt) {
case 'p':
port = optarg;
@@ -48,10 +51,18 @@ int main (int argc, char *argv[])
baud = atoi (optarg);
break;
- case 'm':
+ case 'e':
email = optarg;
break;
+ case 's':
+ state_file = optarg;
+ break;
+
+ case 'm':
+ mqtt_host = optarg;
+ break;
+
case 'l':
log++;
break;
@@ -73,6 +84,9 @@ int main (int argc, char *argv[])
set_blocking (fd);
+ if (state_file)
+ dump_state (state_file);
+
for (;;) {
red = read (fd, &buf[ptr], 1);
@@ -95,7 +109,7 @@ int main (int argc, char *argv[])
break;
default: /*Valid block */
- new_block (fd, &b, log, email);
+ new_block (fd, &b, log, email, state_file, mqtt_host);
ptr = 0;
break;
}
diff --git a/sia.c b/sia.c
index 3c47c8b..6047117 100644
--- a/sia.c
+++ b/sia.c
@@ -228,6 +228,7 @@ int sia_login (int fd, SIA_Block *b)
{
const char *pin = "543210"; //JMM: Oh yes! and there's no way to change it from the panel, you need the £3k bit of software to do that
+
b->reverse_channel = 0;
b->request_ack = 1;
b->function = SIA_FN_REMOTE_LOGIN;
diff --git a/util.c b/util.c
index 21c1eb9..052b382 100644
--- a/util.c
+++ b/util.c
@@ -8,6 +8,7 @@
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
+#include <sys/wait.h>
@@ -296,6 +297,7 @@ int open_tcp_client (const char *host, unsigned port)
if (fd < 0) return -1;
+
sin.sin_port = htons (port);
if (connect (fd, (struct sockaddr *)&sin, sizeof (sin))) {
@@ -339,3 +341,67 @@ int open_tcp_server (unsigned port)
+int daemonish (int nochdir, int noclose)
+{
+ pid_t pid;
+ int status;
+
+ if (!nochdir && chdir ("/"))
+ return -1;
+
+ if (!noclose) {
+ int fd, failed = 0;
+
+ if ((fd = open ("/dev/null", O_RDWR)) < 0) return -1;
+
+ if (dup2 (fd, 0) < 0 || dup2 (fd, 1) < 0 || dup2 (fd, 2) < 0)
+ failed++;
+
+ if (fd > 2) close (fd);
+
+ if (failed) return -1;
+ }
+
+ switch ((pid = fork())) {
+ case 0:
+ break;
+
+ case -1:
+ return -1;
+
+ default:
+ waitpid (pid, &status, 0);
+ return 1;;
+ }
+
+ if (setsid() < 0) return -1;
+
+ switch (fork()) {
+ case 0:
+ break;
+
+ case -1:
+ return -1;
+
+ default:
+ _exit (0);
+ }
+
+ return 0;
+}
+
+
+int local_isalnum (char c)
+{
+ if ((c >= '0') && (c <= '9')) return 1;
+
+ if ((c >= 'A') && (c <= 'Z')) return 1;
+
+ if ((c >= 'a') && (c <= 'z')) return 1;
+
+ return 0;
+}
+
+
+
+
diff --git a/util.h b/util.h
index 55f6e38..aadab9c 100644
--- a/util.h
+++ b/util.h
@@ -10,5 +10,7 @@ extern int fd_drain (int fd);
extern int open_tty (const char *path, int baud);
extern int open_tcp_client (const char *host, unsigned port);
extern int open_tcp_server (unsigned port);
+extern int daemonish (int nochdir, int noclose);
+extern int local_isalnum (char c);
#endif /* _util_h_ */