diff options
-rw-r--r-- | cethcan/Makefile | 2 | ||||
-rw-r--r-- | cethcan/cethcan.h | 3 | ||||
-rw-r--r-- | cethcan/light.c | 69 | ||||
-rw-r--r-- | cethcan/main.c | 9 | ||||
-rw-r--r-- | cethcan/protocol.h | 24 |
5 files changed, 105 insertions, 2 deletions
diff --git a/cethcan/Makefile b/cethcan/Makefile index a81124c..f0d5d4b 100644 --- a/cethcan/Makefile +++ b/cethcan/Makefile @@ -3,7 +3,7 @@ love: cethcan PKGS="libevent jansson" -cethcan: main.o can.o ether.o +cethcan: main.o can.o ether.o light.o gcc -g -o $@ `pkg-config --libs $(PKGS)` $^ clean: diff --git a/cethcan/cethcan.h b/cethcan/cethcan.h index 477221e..292b5c9 100644 --- a/cethcan/cethcan.h +++ b/cethcan/cethcan.h @@ -23,6 +23,8 @@ #include <event2/event.h> #include <jansson.h> +#include "protocol.h" + #define lprintf(...) do { \ struct timeval tv; struct tm tm; char tvbuf[64]; \ gettimeofday(&tv, NULL); localtime_r(&tv.tv_sec, &tm); \ @@ -66,5 +68,6 @@ extern void can_broadcast(struct can_user *origin, struct can_message *msg); extern void can_init(void); extern int ether_init(json_t *config); +extern int light_init_conf(json_t *config); #endif /* _CETHCAN_H */ diff --git a/cethcan/light.c b/cethcan/light.c new file mode 100644 index 0000000..2bc6b2f --- /dev/null +++ b/cethcan/light.c @@ -0,0 +1,69 @@ +#include "cethcan.h" + +struct value { + uint8_t val; + time_t change, valid; +}; + +struct light { + struct can_user *u; + + char *name; + unsigned logical_addr; + + struct value set, actual; +}; + +static void light_can_handler(void *arg, struct can_message *msg) +{ + struct light *l = arg; + struct value *v = NULL; + unsigned laddr; + uint8_t dval; + + if ((msg->daddr & CANA_PROTOCOL) == CANA_LIGHT) + v = &l->set; + if ((msg->daddr & CANA_PROTOCOL) == CANA_SENSOR) + v = &l->actual; + if (!v) + return; + + laddr = msg->daddr & 0xfff; + if (l->logical_addr < laddr) + return; + if (l->logical_addr - laddr >= msg->dlc) + return; + dval = msg->bytes[l->logical_addr - laddr]; + + time(&v->valid); + if (dval != v->val || v->change == 0) { + v->val = dval; + time(&v->change); + lprintf("%s: set %02x", l->u->name, dval); + } +} + +int light_init_conf(json_t *config) +{ + struct light *l; + + 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; + } + + l = calloc(sizeof(*l), 1); + l->name = strdup(json_string_value(json_object_get(config, "name"))); + l->logical_addr = json_integer_value(json_object_get(config, "addr")); + + l->u = can_register_alloc(l, light_can_handler, "light[%s]", l->name); + return 0; +} diff --git a/cethcan/main.c b/cethcan/main.c index 6d79a9f..0794254 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; + json_t *config, *ethercfg, *lightcfg; do { optch = getopt(argc, argv, "c:"); @@ -47,6 +47,13 @@ int main(int argc, char **argv) return 1; } + lightcfg = json_object_get(config, "lights"); + for (size_t i = 0; i < json_array_size(lightcfg); i++) { + json_t *c = json_array_get(lightcfg, i); + if (light_init_conf(c)) + return 1; + } + event_base_loop(ev_base, 0); return 0; } diff --git a/cethcan/protocol.h b/cethcan/protocol.h new file mode 100644 index 0000000..34327d2 --- /dev/null +++ b/cethcan/protocol.h @@ -0,0 +1,24 @@ + /* addrs: SSSEEEEE + * 8 -> extended addr + * 14 -> unused + */ +#define CANA_TIME 0x10080000 +#define CANA_DISCOVERY 0x4c080000 +#define CANA_DISCOVERY_F(pg,dst) (CANA_DISCOVERY | (((uint32_t)(pg) & 0xf) << 12) | ((dst) & 0xfff)) +#define CANA_LIGHT 0xcc080000 +#define CANA_LIGHT_F(src,dst) (CANA_LIGHT | (((src) & 0x3f) << 12) | ((dst) & 0xfff)) +#define CANA_SENSOR 0xe6080000 +#define CANA_SENSOR_F(src) (CANA_SENSOR | ((src) & 0xfff)) +#define CANA_DEBUG 0xe7000000 + +#define CANA_PROTOCOL 0xffe80000 + +/* +#define can_rx_isext() (can_rx_addr.b[1] & 0x08) +#define can_rx_ext_rr() (can_rx_dlc & 0x40) +#define can_rx_len() (can_rx_dlc & 0x0f) + +#define can_rx_sublab_proto() ((can_rx_addr.b[0] << 8) | (can_rx_addr.b[1] & 0xe8)) +#define can_rx_sublab_addr() (((can_rx_addr.b[2] & 0x0f) << 8) | can_rx_addr.b[3]) +#define can_rx_sublab_disco_page() ((can_rx_addr.b[2] & 0xf0) >> 4) +*/ |