diff options
-rw-r--r-- | cethcan/Makefile | 2 | ||||
-rw-r--r-- | cethcan/beanctr.c | 91 | ||||
-rw-r--r-- | cethcan/cethcan.h | 1 | ||||
-rw-r--r-- | cethcan/main.c | 9 |
4 files changed, 101 insertions, 2 deletions
diff --git a/cethcan/Makefile b/cethcan/Makefile index a61d256..5368ef0 100644 --- a/cethcan/Makefile +++ b/cethcan/Makefile @@ -3,7 +3,7 @@ love: cethcan PKGS="libevent jansson" -cethcan: main.o can.o ether.o light.o http.o socketcan.o +cethcan: main.o can.o ether.o light.o beanctr.o http.o socketcan.o gcc -g -o $@ `pkg-config --libs $(PKGS)` -lcrypto $^ clean: diff --git a/cethcan/beanctr.c b/cethcan/beanctr.c new file mode 100644 index 0000000..d381c79 --- /dev/null +++ b/cethcan/beanctr.c @@ -0,0 +1,91 @@ +#include "cethcan.h" + +struct bean { + struct can_user *u; + + char *name; + unsigned logical_addr; + + uint8_t raw; + json_t *vals[2]; + + time_t change, valid; +}; + +static void bean_json_handler(void *arg, json_t *json, enum json_subtype type) +{ + struct bean *b = arg; + json_t *bobj = json_object(); + + json_object_set_new(bobj, "klass", json_string("beancounter")); + json_object_set_new(bobj, "addr", json_integer(b->logical_addr)); + + json_object_set_new(bobj, "raw", json_integer(b->raw)); + json_object_set_new(bobj, "value", json_boolean(b->raw & 1)); + json_object_set_new(bobj, "text", json_incref(b->vals[b->raw & 1])); + if (type != JSON_LONGPOLL) + json_object_set_new(bobj, "ts", json_integer(b->valid)); + json_object_set_new(bobj, "tschg", json_integer(b->change)); + + json_object_set_new(json, b->name, bobj); +} + +static void bean_can_handler(void *arg, struct can_message *msg) +{ + struct bean *b = arg; + unsigned laddr; + uint8_t dval; + + if ((msg->daddr & CANA_PROTOCOL) != CANA_SENSOR) + return; + + laddr = msg->daddr & 0xfff; + if (b->logical_addr < laddr) + return; + if (b->logical_addr - laddr >= msg->dlc) + return; + dval = msg->bytes[b->logical_addr - laddr]; + + time(&b->valid); + if (dval != b->raw || b->change == 0) { + b->raw = dval; + time(&b->change); + lprintf("%s: set %02x", b->u->name, dval); + + json_bump_longpoll(); + } +} + +int bean_init_conf(json_t *config) +{ + struct bean *b; + json_t *vals; + + if (!json_is_object(config)) { + lprintf("light config must be an object/dictionary"); + return 1; + } + if (!json_is_integer(json_object_get(config, "addr"))) { + lprintf("light config must have an 'addr' key"); + return 1; + } + if (!json_is_string(json_object_get(config, "name"))) { + lprintf("light config must have a 'name' key"); + return 1; + } + vals = json_object_get(config, "values"); + if (!json_is_array(vals) || json_array_size(vals) != 2) { + lprintf("light config must have a 'values' array of len 2"); + return 1; + } + + b = calloc(sizeof(*b), 1); + b->name = strdup(json_string_value(json_object_get(config, "name"))); + b->logical_addr = json_integer_value(json_object_get(config, "addr")); + b->vals[0] = json_array_get(vals, 0); + b->vals[1] = json_array_get(vals, 1); + + b->u = can_register_alloc(b, bean_can_handler, "bean[%s]", b->name); + b->u->json = bean_json_handler; + return 0; +} diff --git a/cethcan/cethcan.h b/cethcan/cethcan.h index 4326429..4777f5f 100644 --- a/cethcan/cethcan.h +++ b/cethcan/cethcan.h @@ -80,6 +80,7 @@ extern void json_bump_longpoll(void); extern int socan_init(json_t *config); extern int ether_init(json_t *config); extern int light_init_conf(json_t *config); +extern int bean_init_conf(json_t *config); extern void http_init(void); #endif /* _CETHCAN_H */ diff --git a/cethcan/main.c b/cethcan/main.c index 5bdca0a..cc3522b 100644 --- a/cethcan/main.c +++ b/cethcan/main.c @@ -7,7 +7,7 @@ int main(int argc, char **argv) int optch = 0; const char *cfgfile = "cethcan.json"; json_error_t je; - json_t *config, *ethercfg, *lightcfg, *socancfg; + json_t *config, *ethercfg, *lightcfg, *beancfg, *socancfg; do { optch = getopt(argc, argv, "c:"); @@ -54,6 +54,13 @@ int main(int argc, char **argv) return 1; } + beancfg = json_object_get(config, "beans"); + for (size_t i = 0; i < json_array_size(beancfg); i++) { + json_t *c = json_array_get(beancfg, i); + if (bean_init_conf(c)) + return 1; + } + socancfg = json_object_get(config, "socketcan"); for (size_t i = 0; i < json_array_size(socancfg); i++) { json_t *c = json_array_get(socancfg, i); |