]> mj.ucw.cz Git - home-hw.git/commitdiff
Clock: MQTT daemon
authorMartin Mares <mj@ucw.cz>
Tue, 14 Aug 2018 10:00:36 +0000 (12:00 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 14 Aug 2018 10:00:36 +0000 (12:00 +0200)
usb/host/Makefile
usb/host/burrow-clock.c [new file with mode: 0644]
usb/host/test.c

index a31dce131d6efbb2b7857072f8d0563f6fb6b2dd..aebb0d507ff667d5ef1ffc50763f72e9bfd5838f 100644 (file)
@@ -4,6 +4,12 @@ UCWLF:=$(shell PKG_CONFIG_PATH=$(LIBUCW)/lib/pkgconfig pkg-config --libs libucw)
 CFLAGS=-std=gnu99 -O2 -Wall -Wextra -Wno-parentheses $(UCWCF)
 LDLIBS=-lusb-1.0 $(UCWLF)
 
-all: test
+all: test burrow-clock
 
 test: test.c
+
+burrow-clock: burrow-clock.c
+burrow-clock: LDLIBS += -lmosquitto
+
+install: all
+       install burrow-clock /usr/local/sbin/
diff --git a/usb/host/burrow-clock.c b/usb/host/burrow-clock.c
new file mode 100644 (file)
index 0000000..62a1e8c
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ *     MJ's desktop clock daemon
+ *
+ *     (c) 2018 Martin Mares <mj@ucw.cz>
+ */
+
+#include <ucw/lib.h>
+#include <ucw/log.h>
+#include <ucw/opt.h>
+#include <ucw/unaligned.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <libusb-1.0/libusb.h>
+#include <mosquitto.h>
+
+static struct mosquitto *mosq;
+
+struct libusb_context *usb_ctxt;
+struct libusb_device_handle *devh;
+
+static libusb_device *find_device(void)
+{
+       libusb_device **devlist;
+       ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist);
+       if (devn < 0) {
+               fprintf(stderr, "Cannot enumerate USB devices: error %d\n", (int) devn);
+               exit(1);
+       }
+
+       for (ssize_t i=0; i<devn; i++) {
+               struct libusb_device_descriptor desc;
+               libusb_device *dev = devlist[i];
+               if (!libusb_get_device_descriptor(dev, &desc)) {
+                       if (desc.idVendor == 0x4242 && desc.idProduct == 0x0001) {
+                               msg(L_INFO, "Found device at usb%d.%d\n", libusb_get_bus_number(dev), libusb_get_device_address(dev));
+                               // FIXME: Free device list
+                               return dev;
+                       }
+               }
+       }
+
+       libusb_free_device_list(devlist, 1);
+       fprintf(stderr, "Device not found\n");
+       exit(1);
+}
+
+static void mqtt_publish(const char *topic, const char *fmt, ...)
+{
+       va_list args;
+       va_start(args, fmt);
+       char m[256];
+       int l = vsnprintf(m, sizeof(m), fmt, args);
+       if (mosquitto_publish(mosq, NULL, topic, l, m, 0, true) != MOSQ_ERR_SUCCESS)
+               msg(L_ERROR, "Mosquitto: publish failed");
+       va_end(args);
+}
+
+static void mqtt_conn_callback(struct mosquitto *mosq UNUSED, void *obj UNUSED, int status)
+{
+       if (!status) {
+               msg(L_DEBUG, "MQTT: Connection established");
+               mqtt_publish("status/clock", "ok");
+       }
+}
+
+static int use_daemon;
+static int use_debug;
+
+static struct opt_section options = {
+       OPT_ITEMS {
+               OPT_HELP("A daemon for controlling the solid state relay module via MQTT"),
+               OPT_HELP(""),
+               OPT_HELP("Options:"),
+               OPT_BOOL('d', "debug", use_debug, 0, "\tLog debugging messages"),
+               OPT_BOOL(0, "daemon", use_daemon, 0, "\tDaemonize"),
+               OPT_HELP_OPTION,
+               OPT_CONF_OPTIONS,
+               OPT_END
+       }
+};
+
+int main(int argc UNUSED, char **argv)
+{
+       log_init(argv[0]);
+       opt_parse(&options, argv+1);
+
+       if (use_daemon) {
+               struct log_stream *ls = log_new_syslog("daemon", LOG_PID);
+               log_set_default_stream(ls);
+       }
+       if (!use_debug)
+               log_default_stream()->levels &= ~(1U << L_DEBUG);
+
+       mosquitto_lib_init();
+       mosq = mosquitto_new("clock", 1, NULL);
+       if (!mosq)
+               die("Mosquitto: initialization failed");
+
+       mosquitto_connect_callback_set(mosq, mqtt_conn_callback);
+
+       if (mosquitto_will_set(mosq, "status/clock", 4, "dead", 0, true) != MOSQ_ERR_SUCCESS)
+               die("Mosquitto: unable to set will");
+
+       if (mosquitto_connect_async(mosq, "10.32.184.5", 1883, 60) != MOSQ_ERR_SUCCESS)
+               die("Mosquitto: connect failed");
+
+       if (mosquitto_loop_start(mosq))
+               die("Mosquitto: cannot start service thread");
+
+       int err;
+       if (err = libusb_init(&usb_ctxt))
+               die("Cannot initialize libusb: error %d", err);
+       libusb_set_debug(usb_ctxt, 3);
+
+       libusb_device *dev = find_device();
+
+       if (err = libusb_open(dev, &devh))
+               die("Cannot open device: error %d", err);
+       libusb_reset_device(devh);
+       if (err = libusb_claim_interface(devh, 0))
+               die("Cannot claim interface: error %d", err);
+
+       uint cnt = 0;
+       for (;;) {
+               time_t t = time(NULL);
+               struct tm *tm = localtime(&t);
+
+               unsigned char req[8] = {
+                       tm->tm_hour / 10,
+                       tm->tm_hour % 10,
+                       (tm->tm_sec % 2 ? 10 : 0xff),
+                       tm->tm_min / 10,
+                       tm->tm_min % 10,
+               };
+               int transferred;
+               if (err = libusb_bulk_transfer(devh, 0x01, req, 8, &transferred, 2000))
+                       die("Transfer failed: error %d", err);
+
+               unsigned char resp[64];
+               int received;
+               if (err = libusb_bulk_transfer(devh, 0x82, resp, 64, &received, 2000))
+                       die("Receive failed: error %d\n", err);
+               // printf("Received %d bytes\n", received);
+               if (received >= 12) {
+                       int temp = get_u32_be(resp);
+                       int press = get_u32_be(resp + 4);
+                       uint cycle = get_u32_be(resp + 8);
+                       msg(L_DEBUG, "Temperature %d ddegC, pressure %d Pa, cycle %u", temp, press, cycle);
+                       if (!(cnt % 10)) {
+                               mqtt_publish("burrow/temp/clock", "%.1f %llu", temp / 10., (long long) t);
+                               mqtt_publish("burrow/pressure/clock", "%d %llu", press, (long long) t);
+                       }
+               }
+
+               sleep(1);
+               cnt++;
+       }
+
+       return 0;
+}
index 2d94a98ec8c9e31cba8341c7a8149a7b8fcf5415..455d8e257e8a4a5529452f03dfa2864a8ee5025b 100644 (file)
@@ -79,13 +79,13 @@ int main(void)
       };
       int transferred;
       if (err = libusb_bulk_transfer(devh, 0x01, req, 8, &transferred, 2000))
-       die("Transfer failed: error %d\n", err);
+       die("Transfer failed: error %d", err);
       // printf("Transferred %d bytes\n", transferred);
 
       unsigned char resp[64];
       int received;
       if (err = libusb_bulk_transfer(devh, 0x82, resp, 64, &received, 2000))
-       die("Receive failed: error %d\n", err);
+       die("Receive failed: error %d", err);
       // printf("Received %d bytes\n", received);
       if (received >= 12)
        {