2 * MJ's desktop clock daemon
4 * (c) 2018 Martin Mares <mj@ucw.cz>
10 #include <ucw/unaligned.h>
19 #include <libusb-1.0/libusb.h>
20 #include <mosquitto.h>
22 static struct mosquitto *mosq;
24 struct libusb_context *usb_ctxt;
25 struct libusb_device_handle *devh;
27 static libusb_device *find_device(void)
29 libusb_device **devlist;
30 ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist);
32 fprintf(stderr, "Cannot enumerate USB devices: error %d\n", (int) devn);
36 for (ssize_t i=0; i<devn; i++) {
37 struct libusb_device_descriptor desc;
38 libusb_device *dev = devlist[i];
39 if (!libusb_get_device_descriptor(dev, &desc)) {
40 if (desc.idVendor == 0x4242 && desc.idProduct == 0x0001) {
41 msg(L_INFO, "Found device at usb%d.%d", libusb_get_bus_number(dev), libusb_get_device_address(dev));
42 // FIXME: Free device list
48 libusb_free_device_list(devlist, 1);
49 fprintf(stderr, "Device not found\n");
53 static void mqtt_publish(const char *topic, const char *fmt, ...)
58 int l = vsnprintf(m, sizeof(m), fmt, args);
59 if (mosquitto_publish(mosq, NULL, topic, l, m, 0, true) != MOSQ_ERR_SUCCESS)
60 msg(L_ERROR, "Mosquitto: publish failed");
64 static void mqtt_conn_callback(struct mosquitto *mosq UNUSED, void *obj UNUSED, int status)
67 msg(L_DEBUG, "MQTT: Connection established");
68 mqtt_publish("status/clock", "ok");
72 static int use_daemon;
75 static struct opt_section options = {
77 OPT_HELP("A daemon for controlling the solid state relay module via MQTT"),
80 OPT_BOOL('d', "debug", use_debug, 0, "\tLog debugging messages"),
81 OPT_BOOL(0, "daemon", use_daemon, 0, "\tDaemonize"),
88 int main(int argc UNUSED, char **argv)
91 opt_parse(&options, argv+1);
94 struct log_stream *ls = log_new_syslog("daemon", LOG_PID);
95 log_set_default_stream(ls);
98 log_default_stream()->levels &= ~(1U << L_DEBUG);
100 mosquitto_lib_init();
101 mosq = mosquitto_new("clock", 1, NULL);
103 die("Mosquitto: initialization failed");
105 mosquitto_connect_callback_set(mosq, mqtt_conn_callback);
107 if (mosquitto_will_set(mosq, "status/clock", 4, "dead", 0, true) != MOSQ_ERR_SUCCESS)
108 die("Mosquitto: unable to set will");
110 if (mosquitto_connect_async(mosq, "10.32.184.5", 1883, 60) != MOSQ_ERR_SUCCESS)
111 die("Mosquitto: connect failed");
113 if (mosquitto_loop_start(mosq))
114 die("Mosquitto: cannot start service thread");
117 if (err = libusb_init(&usb_ctxt))
118 die("Cannot initialize libusb: error %d", err);
120 libusb_device *dev = find_device();
122 if (err = libusb_open(dev, &devh))
123 die("Cannot open device: error %d", err);
124 libusb_reset_device(devh);
125 if (err = libusb_claim_interface(devh, 0))
126 die("Cannot claim interface: error %d", err);
130 time_t t = time(NULL);
131 struct tm *tm = localtime(&t);
133 unsigned char req[8] = {
136 (tm->tm_sec % 2 ? 10 : 0xff),
141 if (err = libusb_bulk_transfer(devh, 0x01, req, 8, &transferred, 2000))
142 die("Transfer failed: error %d", err);
144 unsigned char resp[64];
146 if (err = libusb_bulk_transfer(devh, 0x82, resp, 64, &received, 2000))
147 die("Receive failed: error %d", err);
148 // printf("Received %d bytes\n", received);
149 if (received >= 12) {
150 int temp = get_u32_be(resp);
151 int press = get_u32_be(resp + 4);
152 uint cycle = get_u32_be(resp + 8);
153 msg(L_DEBUG, "Temperature %d ddegC, pressure %d Pa, cycle %u", temp, press, cycle);
154 if (!(cnt % 10) && press) {
155 mqtt_publish("burrow/temp/clock", "%.1f %llu", temp / 10., (long long) t);
156 mqtt_publish("burrow/pressure/clock", "%d %llu", press, (long long) t);