From: Martin Mares Date: Fri, 28 Feb 2020 15:47:34 +0000 (+0100) Subject: BSB: Proper daemon name X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=94104045c47be3c2e8aa11417fdcdf049557b06b;p=home-hw.git BSB: Proper daemon name --- diff --git a/bsb/daemon/Makefile b/bsb/daemon/Makefile index 9f2ce2b..b602b51 100644 --- a/bsb/daemon/Makefile +++ b/bsb/daemon/Makefile @@ -27,7 +27,10 @@ UCW_LDFLAGS := $(shell $(PC) --libs libucw) CFLAGS=$(USB_CFLAGS) $(UCW_CFLAGS) -std=gnu1x -O2 -Wall -Wextra -Wno-parentheses LDFLAGS=$(USB_LDFLAGS) $(UCW_LDFLAGS) -lmosquitto -all: burrow-bsb bsb-monitor +all: burrow-bsbd bsb-monitor -# burrow-bsb: burrow-bsb.c ../firmware/interface.h +# burrow-bsbd: burrow-bsbd.c ../firmware/interface.h # bsb-monitor: bsb-monitor.c ../firmware/interface.h + +upload: + rsync -av burrow-bsbd bsb-monitor micac:/root/burrow/ diff --git a/bsb/daemon/burrow-bsb.c b/bsb/daemon/burrow-bsb.c deleted file mode 100644 index 6b83a5f..0000000 --- a/bsb/daemon/burrow-bsb.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Boiler System Bus Interface Daemon - * - * (c) 2020 Martin Mares - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -typedef unsigned char byte; -typedef uint32_t u32; -typedef unsigned int uint; - -#include "../firmware/interface.h" - -/*** MQTT ***/ - -static struct mosquitto *mosq; -static bool mqtt_connected; - -static void mqtt_publish(const char *topic, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - - if (mqtt_connected) { - char m[256]; - int l = vsnprintf(m, sizeof(m), fmt, args); - int err = mosquitto_publish(mosq, NULL, topic, l, m, 0, true); - if (err != MOSQ_ERR_SUCCESS) - msg(L_ERROR, "Mosquitto: Publish failed, error=%d", err); - } - - 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/bsb", "ok"); - mqtt_connected = true; - } else if (mqtt_connected) { - msg(L_DEBUG, "MQTT: Connection lost"); - mqtt_connected = false; - } -} - -static void mqtt_log_callback(struct mosquitto *mosq UNUSED, void *obj UNUSED, int level, const char *message) -{ - msg(L_DEBUG, "MQTT(%d): %s", level, message); -} - -static void mqtt_init(void) -{ - mosquitto_lib_init(); - - mosq = mosquitto_new("bsbd", 1, NULL); - if (!mosq) - die("Mosquitto: Initialization failed"); - - mosquitto_connect_callback_set(mosq, mqtt_conn_callback); - mosquitto_log_callback_set(mosq, mqtt_log_callback); - - if (mosquitto_will_set(mosq, "status/bsb", 4, "dead", 0, true) != MOSQ_ERR_SUCCESS) - die("Mosquitto: Unable to set will"); - - if (mosquitto_connect_async(mosq, "127.0.0.1", 1883, 60) != MOSQ_ERR_SUCCESS) - die("Mosquitto: Unable to connect"); - - if (mosquitto_loop_start(mosq)) - die("Mosquitto: Cannot start service thread"); -} - -/*** USB ***/ - -static struct libusb_context *usb_ctxt; -static struct libusb_device_handle *devh; - -static void usb_error(const char *msg, ...) -{ - va_list args; - va_start(args, msg); - ucw_vmsg(L_ERROR, msg, args); - fputc('\n', stderr); - va_end(args); - - if (devh) { - libusb_close(devh); - devh = NULL; - } -} - -static void open_device(void) -{ - int err; - libusb_device **devlist; - ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist); - if (devn < 0) - die("Cannot enumerate USB devices: error %d", (int) devn); - - for (ssize_t i=0; i= 4) { - uint temp = get_u16_be(p); - uint press = get_u16_be(p + 2); - mqtt_publish("burrow/heating/outside-temp", "%.2f", temp / 64.); - mqtt_publish("burrow/heating/water-pressure", "%.1f", press / 10.); - } - break; - case 0x05000229: - // AGU.2 status - if (len >= 2) { - uint temp = get_u16_be(p); - mqtt_publish("burrow/heating/circuit1/mix-temp", "%.2f", temp / 64.); - } - break; - case 0x05040227: - // AGU.2 control - if (len >= 2) { - uint m = get_u16_be(p); - mqtt_publish("burrow/heating/circuit1/mix-valve", "%u", m); - } - break; - case 0x3d2d0215: - // Room 1 status - if (len >= 2) { - uint temp = get_u16_be(p); - mqtt_publish("burrow/heating/circuit1/room-temp", "%.2f", temp / 64.); - } - break; - case 0x3e2e0215: - // Room 2 status - if (len >= 2) { - uint temp = get_u16_be(p); - mqtt_publish("burrow/heating/circuit2/room-temp", "%.2f", temp / 64.); - } - break; - } -} - -static void process_answer(byte *p, uint len) -{ - if (len < 4) - return; - - u32 addr = get_u32_be(p); - p += 4; - len -= 4; - - switch (addr) { - } -} - -static void process_frame(time_t t, byte *pkt, uint len) -{ - if (!len) { - msg(L_ERROR, "Received empty frame"); - return; - } - - byte status = *pkt++; - len--; - - if (!len) { - msg(L_ERROR, "Frame transmit status: %u", status); - return; - } - - if (len < 6) { - msg(L_ERROR, "Received truncated frame"); - return; - } - - char hex[3*len + 1]; - mem_to_hex(hex, pkt, len, ' '); - mqtt_publish("bsb/frame", "%s", hex, t); - - msg(L_DEBUG, "<< %s", hex); - - byte *params = pkt + BF_PARAMS; - uint param_len = len - BF_PARAMS - 2; // 2 for CRC - - switch (pkt[BF_OP]) { - case BSB_OP_INFO: - process_info(params, param_len); - break; - case BSB_OP_ANSWER: - process_answer(params, param_len); - break; - } -} - -static int use_daemon; -static int use_debug; - -static struct opt_section options = { - OPT_ITEMS { - OPT_HELP("A daemon for controlling the air conditioning controller 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); - - mqtt_init(); - init_usb(); - - time_t now = time(NULL); - time_t last_stats = 0; - // time_t last_query = now; - int err, received; - byte resp[64]; - - for (;;) { - if (!devh) { - msg(L_INFO, "Waiting for device to appear..."); - while (!devh) { - sleep(5); - open_device(); - } - } - - now = time(NULL); - if (last_stats + 60 < now) { - if ((received = libusb_control_transfer(devh, 0xc0, 0x00, 0, 0, resp, sizeof(resp), 1000)) < 0) { - usb_error("Receive failed: error %d", received); - continue; - } - - process_stats(now, resp, received); - last_stats = now; - } - -#if 0 - if (last_query + 10 < now) { - byte pkt[] = { 0xdc, 0xc2, 0x00, 0x0b, 0x06, 0x3d, 0x2e, 0x11, 0x25, 0x00, 0x00 }; - if (err = libusb_bulk_transfer(devh, 0x01, pkt, sizeof(pkt), &received, 2000)) { - usb_error("Send failed: error %d", err); - continue; - } else { - // msg(L_DEBUG"Send OK: %d bytes", received); - } - last_query = now; - } -#endif - - if (err = libusb_interrupt_transfer(devh, 0x82, resp, 64, &received, 1000)) { - if (err != LIBUSB_ERROR_TIMEOUT) - usb_error("Receive failed: error %d", err); - continue; - } - - process_frame(now, resp, received); - } -} diff --git a/bsb/daemon/burrow-bsbd.c b/bsb/daemon/burrow-bsbd.c new file mode 100644 index 0000000..6b83a5f --- /dev/null +++ b/bsb/daemon/burrow-bsbd.c @@ -0,0 +1,349 @@ +/* + * Boiler System Bus Interface Daemon + * + * (c) 2020 Martin Mares + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +typedef unsigned char byte; +typedef uint32_t u32; +typedef unsigned int uint; + +#include "../firmware/interface.h" + +/*** MQTT ***/ + +static struct mosquitto *mosq; +static bool mqtt_connected; + +static void mqtt_publish(const char *topic, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + if (mqtt_connected) { + char m[256]; + int l = vsnprintf(m, sizeof(m), fmt, args); + int err = mosquitto_publish(mosq, NULL, topic, l, m, 0, true); + if (err != MOSQ_ERR_SUCCESS) + msg(L_ERROR, "Mosquitto: Publish failed, error=%d", err); + } + + 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/bsb", "ok"); + mqtt_connected = true; + } else if (mqtt_connected) { + msg(L_DEBUG, "MQTT: Connection lost"); + mqtt_connected = false; + } +} + +static void mqtt_log_callback(struct mosquitto *mosq UNUSED, void *obj UNUSED, int level, const char *message) +{ + msg(L_DEBUG, "MQTT(%d): %s", level, message); +} + +static void mqtt_init(void) +{ + mosquitto_lib_init(); + + mosq = mosquitto_new("bsbd", 1, NULL); + if (!mosq) + die("Mosquitto: Initialization failed"); + + mosquitto_connect_callback_set(mosq, mqtt_conn_callback); + mosquitto_log_callback_set(mosq, mqtt_log_callback); + + if (mosquitto_will_set(mosq, "status/bsb", 4, "dead", 0, true) != MOSQ_ERR_SUCCESS) + die("Mosquitto: Unable to set will"); + + if (mosquitto_connect_async(mosq, "127.0.0.1", 1883, 60) != MOSQ_ERR_SUCCESS) + die("Mosquitto: Unable to connect"); + + if (mosquitto_loop_start(mosq)) + die("Mosquitto: Cannot start service thread"); +} + +/*** USB ***/ + +static struct libusb_context *usb_ctxt; +static struct libusb_device_handle *devh; + +static void usb_error(const char *msg, ...) +{ + va_list args; + va_start(args, msg); + ucw_vmsg(L_ERROR, msg, args); + fputc('\n', stderr); + va_end(args); + + if (devh) { + libusb_close(devh); + devh = NULL; + } +} + +static void open_device(void) +{ + int err; + libusb_device **devlist; + ssize_t devn = libusb_get_device_list(usb_ctxt, &devlist); + if (devn < 0) + die("Cannot enumerate USB devices: error %d", (int) devn); + + for (ssize_t i=0; i= 4) { + uint temp = get_u16_be(p); + uint press = get_u16_be(p + 2); + mqtt_publish("burrow/heating/outside-temp", "%.2f", temp / 64.); + mqtt_publish("burrow/heating/water-pressure", "%.1f", press / 10.); + } + break; + case 0x05000229: + // AGU.2 status + if (len >= 2) { + uint temp = get_u16_be(p); + mqtt_publish("burrow/heating/circuit1/mix-temp", "%.2f", temp / 64.); + } + break; + case 0x05040227: + // AGU.2 control + if (len >= 2) { + uint m = get_u16_be(p); + mqtt_publish("burrow/heating/circuit1/mix-valve", "%u", m); + } + break; + case 0x3d2d0215: + // Room 1 status + if (len >= 2) { + uint temp = get_u16_be(p); + mqtt_publish("burrow/heating/circuit1/room-temp", "%.2f", temp / 64.); + } + break; + case 0x3e2e0215: + // Room 2 status + if (len >= 2) { + uint temp = get_u16_be(p); + mqtt_publish("burrow/heating/circuit2/room-temp", "%.2f", temp / 64.); + } + break; + } +} + +static void process_answer(byte *p, uint len) +{ + if (len < 4) + return; + + u32 addr = get_u32_be(p); + p += 4; + len -= 4; + + switch (addr) { + } +} + +static void process_frame(time_t t, byte *pkt, uint len) +{ + if (!len) { + msg(L_ERROR, "Received empty frame"); + return; + } + + byte status = *pkt++; + len--; + + if (!len) { + msg(L_ERROR, "Frame transmit status: %u", status); + return; + } + + if (len < 6) { + msg(L_ERROR, "Received truncated frame"); + return; + } + + char hex[3*len + 1]; + mem_to_hex(hex, pkt, len, ' '); + mqtt_publish("bsb/frame", "%s", hex, t); + + msg(L_DEBUG, "<< %s", hex); + + byte *params = pkt + BF_PARAMS; + uint param_len = len - BF_PARAMS - 2; // 2 for CRC + + switch (pkt[BF_OP]) { + case BSB_OP_INFO: + process_info(params, param_len); + break; + case BSB_OP_ANSWER: + process_answer(params, param_len); + break; + } +} + +static int use_daemon; +static int use_debug; + +static struct opt_section options = { + OPT_ITEMS { + OPT_HELP("A daemon for controlling the air conditioning controller 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); + + mqtt_init(); + init_usb(); + + time_t now = time(NULL); + time_t last_stats = 0; + // time_t last_query = now; + int err, received; + byte resp[64]; + + for (;;) { + if (!devh) { + msg(L_INFO, "Waiting for device to appear..."); + while (!devh) { + sleep(5); + open_device(); + } + } + + now = time(NULL); + if (last_stats + 60 < now) { + if ((received = libusb_control_transfer(devh, 0xc0, 0x00, 0, 0, resp, sizeof(resp), 1000)) < 0) { + usb_error("Receive failed: error %d", received); + continue; + } + + process_stats(now, resp, received); + last_stats = now; + } + +#if 0 + if (last_query + 10 < now) { + byte pkt[] = { 0xdc, 0xc2, 0x00, 0x0b, 0x06, 0x3d, 0x2e, 0x11, 0x25, 0x00, 0x00 }; + if (err = libusb_bulk_transfer(devh, 0x01, pkt, sizeof(pkt), &received, 2000)) { + usb_error("Send failed: error %d", err); + continue; + } else { + // msg(L_DEBUG"Send OK: %d bytes", received); + } + last_query = now; + } +#endif + + if (err = libusb_interrupt_transfer(devh, 0x82, resp, 64, &received, 1000)) { + if (err != LIBUSB_ERROR_TIMEOUT) + usb_error("Receive failed: error %d", err); + continue; + } + + process_frame(now, resp, received); + } +}