Mercurial > louis > mq > lightsd
changeset 236:acd38691efab
wip
author | Louis Opter <kalessin@kalessin.fr> |
---|---|
date | Sun, 09 Aug 2015 03:25:17 -0700 |
parents | 28a09a3edd41 |
children | fec9ee97f40f |
files | fallback_on_device_addr_when_label.patch implement_some_metadata_packet_types.h series use_jq_when_avalaible.patch |
diffstat | 4 files changed, 674 insertions(+), 54 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/fallback_on_device_addr_when_label.patch Sun Aug 09 03:25:17 2015 -0700 @@ -0,0 +1,16 @@ +# HG changeset patch +# Parent f31af55210fe791d198fc5a25525dc994ad3be3b +Return the bulb address in get_light_state if a bulb label is empty + +diff --git a/core/proto.c b/core/proto.c +--- a/core/proto.c ++++ b/core/proto.c +@@ -222,7 +222,7 @@ + buf, sizeof(buf), state_fmt, + h, s, b, bulb->state.kelvin, + bulb->state.power == LGTD_LIFX_POWER_ON ? "true" : "false", +- bulb->state.label ++ bulb->state.label[0] ? bulb->state.label : lgtd_addrtoa(bulb->addr) + ); + if (written >= (int)sizeof(buf)) { + lgtd_warnx(
--- a/implement_some_metadata_packet_types.h Sat Aug 08 19:41:56 2015 -0700 +++ b/implement_some_metadata_packet_types.h Sun Aug 09 03:25:17 2015 -0700 @@ -6,40 +6,196 @@ - WiFi state & firmware info; - device/runtime info. +diff --git a/core/lightsd.h b/core/lightsd.h +--- a/core/lightsd.h ++++ b/core/lightsd.h +@@ -24,10 +24,33 @@ + #define LGTD_ABS(v) ((v) >= 0 ? (v) : (v) * -1) + #define LGTD_MIN(a, b) ((a) < (b) ? (a) : (b)) + #define LGTD_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +-#define LGTD_MSECS_TO_TIMEVAL(v) { \ ++#define LGTD_MSECS_TO_TIMEVAL(v) { \ + .tv_sec = (v) / 1000, \ + .tv_usec = ((v) % 1000) * 1000 \ + } ++#define LGTD_NSECS_TO_USECS(v) ((v) / (unsigned int)10E6) ++#define LGTD_NSECS_TO_SECS(v) ((v) / (unsigned int)10E9) ++#define LGTD_SECS_TO_NSECS(v) ((v) * (unsigned int)10E9) ++#define LGTD_TM_TO_ISOTIME(tm, sbuf, bufsz, usec) do { \ ++ /* '2015-01-02T10:13:16.132222+00:00' */ \ ++ if ((usec)) { \ ++ snprintf( \ ++ (sbuf), (bufsz), "%d-%02d-%02dT%02d:%02d:%02d.%jd%c%02ld:%02ld", \ ++ 1900 + (tm)->tm_year, 1 + (tm)->tm_mon, (tm)->tm_mday, \ ++ (tm)->tm_hour, (tm)->tm_min, (tm)->tm_sec, (intmax_t)usec, \ ++ (tm)->tm_gmtoff >= 0 ? '+' : '-', /* %+02ld doesn't work */ \ ++ LGTD_ABS((tm)->tm_gmtoff / 60 / 60), (tm)->tm_gmtoff % (60 * 60) \ ++ ); \ ++ } else { \ ++ snprintf( \ ++ (sbuf), (bufsz), "%d-%02d-%02dT%02d:%02d:%02d%c%02ld:%02ld", \ ++ 1900 + (tm)->tm_year, 1 + (tm)->tm_mon, (tm)->tm_mday, \ ++ (tm)->tm_hour, (tm)->tm_min, (tm)->tm_sec, \ ++ (tm)->tm_gmtoff >= 0 ? '+' : '-', /* %+02ld doesn't work */ \ ++ LGTD_ABS((tm)->tm_gmtoff / 60 / 60), (tm)->tm_gmtoff % (60 * 60) \ ++ ); \ ++ } \ ++} while (0) + + enum lgtd_verbosity { + LGTD_DEBUG = 0, +@@ -51,6 +74,11 @@ + void lgtd_sockaddrtoa(const struct sockaddr_storage *, char *buf, int buflen); + short lgtd_sockaddrport(const struct sockaddr_storage *); + ++void lgtd_print_duration(uint64_t, char *, int); ++#define LGTD_PRINT_DURATION(secs, arr) do { \ ++ lgtd_print_duration((secs), (arr), sizeof((arr))); \ ++} while (0) ++ + void _lgtd_err(void (*)(int, const char *, ...), int, const char *, ...) + __attribute__((format(printf, 3, 4))); + #define lgtd_err(eval, fmt, ...) _lgtd_err(err, (eval), (fmt), ##__VA_ARGS__); +diff --git a/core/log.c b/core/log.c +--- a/core/log.c ++++ b/core/log.c +@@ -52,14 +52,7 @@ + if (!localtime_r(&now.tv_sec, &tm_now)) { + goto error; + } +- // '2015-01-02T10:13:16.132222+00:00' +- snprintf( +- strbuf, bufsz, "%d-%02d-%02dT%02d:%02d:%02d.%jd%c%02ld:%02ld", +- 1900 + tm_now.tm_year, 1 + tm_now.tm_mon, tm_now.tm_mday, +- tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec, +- (intmax_t)now.tv_usec, tm_now.tm_gmtoff >= 0 ? '+' : '-', // %+02ld doesn't work +- LGTD_ABS(tm_now.tm_gmtoff / 60 / 60), tm_now.tm_gmtoff % (60 * 60) +- ); ++ LGTD_TM_TO_ISOTIME(&tm_now, strbuf, bufsz, now.tv_usec); + return; + error: + strbuf[0] = '\0'; +@@ -110,6 +103,26 @@ + } + + void ++lgtd_print_duration(uint64_t secs, char *buf, int bufsz) ++{ ++ assert(buf); ++ assert(bufsz > 0); ++ ++ int days = secs / (60 * 60 * 24); ++ int minutes = secs / 60; ++ int hours = minutes / 60; ++ hours = hours % 24; ++ minutes = minutes % 60; ++ ++ int i = 0; ++ if (days) { ++ int n = snprintf(buf, bufsz, "%d days ", days); ++ i = LGTD_MIN(i + n, bufsz); ++ } ++ snprintf(&buf[i], bufsz - i, "%02d:%02d", hours, minutes); ++} ++ ++void + _lgtd_err(void (*errfn)(int, const char *, ...), + int eval, + const char *fmt, +diff --git a/lifx/bulb.c b/lifx/bulb.c +--- a/lifx/bulb.c ++++ b/lifx/bulb.c +@@ -154,3 +154,69 @@ + + bulb->state.tags = tags; + } ++ ++void ++lgtd_lifx_bulb_set_mcu_state(struct lgtd_lifx_bulb *bulb, ++ const struct lgtd_lifx_ip_state *state, ++ lgtd_time_mono_t received_at) ++{ ++ assert(bulb); ++ assert(state); ++ ++ bulb->last_mcu_state_at = received_at; ++ memcpy(&bulb->mcu_state, state, sizeof(bulb->mcu_state)); ++} ++ ++void ++lgtd_lifx_bulb_set_mcu_firmware_info(struct lgtd_lifx_bulb *bulb, ++ const struct lgtd_lifx_ip_firmware_info *info) ++{ ++ assert(bulb); ++ assert(info); ++ ++ memcpy(&bulb->mcu_fw_info, info, sizeof(bulb->mcu_fw_info)); ++} ++ ++void ++lgtd_lifx_bulb_set_wifi_state(struct lgtd_lifx_bulb *bulb, ++ const struct lgtd_lifx_ip_state *state, ++ lgtd_time_mono_t received_at) ++{ ++ assert(bulb); ++ assert(state); ++ ++ bulb->last_wifi_state_at = received_at; ++ memcpy(&bulb->wifi_state, state, sizeof(bulb->wifi_state)); ++} ++ ++void ++lgtd_lifx_bulb_set_wifi_firmware_info(struct lgtd_lifx_bulb *bulb, ++ const struct lgtd_lifx_ip_firmware_info *info) ++{ ++ assert(bulb); ++ assert(info); ++ ++ memcpy(&bulb->wifi_fw_info, info, sizeof(bulb->wifi_fw_info)); ++} ++ ++void ++lgtd_lifx_bulb_set_product_info(struct lgtd_lifx_bulb *bulb, ++ const struct lgtd_lifx_product_info *info) ++{ ++ assert(bulb); ++ assert(info); ++ ++ memcpy(&bulb->product_info, info, sizeof(bulb->product_info)); ++} ++ ++void ++lgtd_lifx_bulb_set_runtime_info(struct lgtd_lifx_bulb *bulb, ++ const struct lgtd_lifx_runtime_info *info, ++ lgtd_time_mono_t received_at) ++{ ++ assert(bulb); ++ assert(info); ++ ++ bulb->last_runtime_info_at = received_at; ++ memcpy(&bulb->runtime_info, info, sizeof(bulb->runtime_info)); ++} diff --git a/lifx/bulb.h b/lifx/bulb.h --- a/lifx/bulb.h +++ b/lifx/bulb.h -@@ -30,17 +30,61 @@ +@@ -30,17 +30,51 @@ char label[LGTD_LIFX_LABEL_SIZE]; uint64_t tags; }; + -+struct lgtd_lifx_mcu_state { ++struct lgtd_lifx_ip_state { + float signal_strength; // mW + uint32_t tx_bytes; + uint32_t rx_bytes; -+ uint16_t reserverd; // Temperature? -+}; -+ -+struct lgtd_lifx_wifi_state { // same as mcu_state -+ float signal_strength; -+ uint32_t tx_bytes; -+ uint32_t rx_bytes; -+ uint16_t reserverd; ++ uint16_t reserved; // Temperature? +}; + -+struct lgtd_lifx_mcu_firmware_info { ++struct lgtd_lifx_ip_firmware_info { + uint64_t built_at; // ns since epoch + uint64_t installed_at; // ns since epoch + uint32_t version; +}; + -+struct lgtd_lifx_wifi_firmware_info { // same as mcu_firmware_info -+ uint64_t built_at; -+ uint64_t installed_at; -+ uint32_t version; -+}; -+ +struct lgtd_lifx_product_info { + uint32_t vendor_id; + uint32_t product_id; @@ -65,24 +221,316 @@ + RB_ENTRY(lgtd_lifx_bulb) link; + SLIST_ENTRY(lgtd_lifx_bulb) link_by_gw; + lgtd_time_mono_t last_light_state_at; ++ lgtd_time_mono_t last_mcu_state_at; ++ lgtd_time_mono_t last_wifi_state_at; ++ lgtd_time_mono_t last_runtime_info_at; + lgtd_time_mono_t dirty_at; + uint16_t expected_power_on; + uint8_t addr[LGTD_LIFX_ADDR_LENGTH]; + struct lgtd_lifx_gateway *gw; + struct lgtd_lifx_light_state state; -+ struct lgtd_lifx_mcu_state mcu_state; -+ struct lgtd_lifx_wifi_state wifi_state; -+ struct lgtd_lifx_mcu_firmware_info mcu_fw_info; -+ struct lgtd_lifx_wifi_firmware_info wifi_fw_info; ++ struct lgtd_lifx_ip_state mcu_state; ++ struct lgtd_lifx_ip_state wifi_state; ++ struct lgtd_lifx_ip_firmware_info mcu_fw_info; ++ struct lgtd_lifx_ip_firmware_info wifi_fw_info; + struct lgtd_lifx_product_info product_info; + struct lgtd_lifx_runtime_info runtime_info; }; RB_HEAD(lgtd_lifx_bulb_map, lgtd_lifx_bulb); SLIST_HEAD(lgtd_lifx_bulb_list, lgtd_lifx_bulb); +@@ -69,3 +103,19 @@ + lgtd_time_mono_t); + void lgtd_lifx_bulb_set_power_state(struct lgtd_lifx_bulb *, uint16_t); + void lgtd_lifx_bulb_set_tags(struct lgtd_lifx_bulb *, uint64_t); ++ ++void lgtd_lifx_bulb_set_mcu_state(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_ip_state *, ++ lgtd_time_mono_t); ++void lgtd_lifx_bulb_set_mcu_firmware_info(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_ip_firmware_info *); ++void lgtd_lifx_bulb_set_wifi_state(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_ip_state *, ++ lgtd_time_mono_t); ++void lgtd_lifx_bulb_set_wifi_firmware_info(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_ip_firmware_info *); ++void lgtd_lifx_bulb_set_product_info(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_product_info *); ++void lgtd_lifx_bulb_set_runtime_info(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_runtime_info *, ++ lgtd_time_mono_t); +diff --git a/lifx/gateway.c b/lifx/gateway.c +--- a/lifx/gateway.c ++++ b/lifx/gateway.c +@@ -489,12 +489,8 @@ + (uintmax_t)pkt->tags + ); + +- struct lgtd_lifx_bulb *b = lgtd_lifx_gateway_get_or_open_bulb( +- gw, hdr->target.device_addr +- ); +- if (!b) { +- return; +- } ++ struct lgtd_lifx_bulb *b; ++ LGTD_LIFX_GATEWAY_GET_BULB_OR_RETURN(b, gw, hdr->target.device_addr); + + assert(sizeof(*pkt) == sizeof(b->state)); + lgtd_lifx_bulb_set_light_state( +@@ -559,14 +555,9 @@ + gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr), pkt->power + ); + +- struct lgtd_lifx_bulb *b = lgtd_lifx_gateway_get_or_open_bulb( +- gw, hdr->target.device_addr ++ LGTD_LIFX_GATEWAY_SET_BULB_ATTR( ++ gw, hdr->target.device_addr, lgtd_lifx_bulb_set_power_state, pkt->power + ); +- if (!b) { +- return; +- } +- +- lgtd_lifx_bulb_set_power_state(b, pkt->power); + } + + int +@@ -673,9 +664,10 @@ + } + } + +-void lgtd_lifx_gateway_handle_tags(struct lgtd_lifx_gateway *gw, +- const struct lgtd_lifx_packet_header *hdr, +- const struct lgtd_lifx_packet_tags *pkt) ++void ++lgtd_lifx_gateway_handle_tags(struct lgtd_lifx_gateway *gw, ++ const struct lgtd_lifx_packet_header *hdr, ++ const struct lgtd_lifx_packet_tags *pkt) + { + assert(gw && hdr && pkt); + +@@ -685,12 +677,8 @@ + (uintmax_t)pkt->tags + ); + +- struct lgtd_lifx_bulb *b = lgtd_lifx_gateway_get_or_open_bulb( +- gw, hdr->target.device_addr +- ); +- if (!b) { +- return; +- } ++ struct lgtd_lifx_bulb *b; ++ LGTD_LIFX_GATEWAY_GET_BULB_OR_RETURN(b, gw, hdr->target.device_addr); + + int tag_id; + LGTD_LIFX_WIRE_FOREACH_TAG_ID(tag_id, pkt->tags) { +@@ -707,3 +695,142 @@ + + lgtd_lifx_bulb_set_tags(b, pkt->tags); + } ++ ++void ++lgtd_lifx_gateway_handle_ip_state(struct lgtd_lifx_gateway *gw, ++ const struct lgtd_lifx_packet_header *hdr, ++ const struct lgtd_lifx_packet_ip_state *pkt) ++{ ++ assert(gw && hdr && pkt); ++ ++ const char *type; ++ void (*bulb_fn)(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_ip_state *, ++ lgtd_time_mono_t); ++ ++ switch (hdr->packet_type) { ++ case LGTD_LIFX_MESH_INFO: ++ type = "MCU_STATE"; ++ bulb_fn = lgtd_lifx_bulb_set_mcu_state; ++ break; ++ case LGTD_LIFX_WIFI_INFO: ++ type = "WIFI_STATE"; ++ bulb_fn = lgtd_lifx_bulb_set_wifi_state; ++ break; ++ default: ++ lgtd_info("invalid ip state packet_type %#hx", hdr->packet_type); ++#ifndef NDEBUG ++ abort(); ++#endif ++ return; ++ } ++ ++ lgtd_debug( ++ "%s <-- [%s]:%hu - %s " ++ "signal_strength=%f, rx_bytes=%u, tx_bytes=%u, reserved=%hu", ++ type, gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr), ++ pkt->signal_strength, pkt->rx_bytes, pkt->tx_bytes, pkt->reserved ++ ); ++ ++ LGTD_LIFX_GATEWAY_SET_BULB_ATTR_WITH_RECV_AT( ++ gw, ++ hdr->target.device_addr, ++ bulb_fn, ++ (const struct lgtd_lifx_ip_state *)pkt ++ ); ++} ++ ++void ++lgtd_lifx_gateway_handle_ip_firmware_info(struct lgtd_lifx_gateway *gw, ++ const struct lgtd_lifx_packet_header *hdr, ++ const struct lgtd_lifx_packet_ip_firmware_info *pkt) ++{ ++ assert(gw && hdr && pkt); ++ ++ const char *type; ++ void (*bulb_fn)(struct lgtd_lifx_bulb *, ++ const struct lgtd_lifx_ip_firmware_info *); ++ ++ switch (hdr->packet_type) { ++ case LGTD_LIFX_MESH_FIRMWARE: ++ type = "MCU_FIRMWARE_INFO"; ++ bulb_fn = lgtd_lifx_bulb_set_mcu_firmware_info; ++ break; ++ case LGTD_LIFX_WIFI_FIRMWARE_STATE: ++ type = "WIFI_FIRMWARE_INFO"; ++ bulb_fn = lgtd_lifx_bulb_set_wifi_firmware_info; ++ break; ++ default: ++ lgtd_info("invalid ip firmware packet_type %#hx", hdr->packet_type); ++#ifndef NDEBUG ++ abort(); ++#endif ++ return; ++ } ++ ++ char built_at[64], installed_at[64]; ++ LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->built_at, built_at); ++ LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->installed_at, installed_at); ++ ++ lgtd_debug( ++ "%s <-- [%s]:%hu - %s " ++ "built_at=%s, installed_at=%s, version=%u", ++ type, gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr), ++ built_at, installed_at, pkt->version ++ ); ++ ++ LGTD_LIFX_GATEWAY_SET_BULB_ATTR( ++ gw, ++ hdr->target.device_addr, ++ bulb_fn, ++ (const struct lgtd_lifx_ip_firmware_info *)pkt ++ ); ++} ++ ++void ++lgtd_lifx_gateway_handle_product_info(struct lgtd_lifx_gateway *gw, ++ const struct lgtd_lifx_packet_header *hdr, ++ const struct lgtd_lifx_packet_product_info *pkt) ++{ ++ assert(gw && hdr && pkt); ++ ++ lgtd_debug( ++ "PRODUCT_INFO <-- [%s]:%hu - %s " ++ "vendor_id=%#x, product_id=%#x, version=%u", ++ gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr), ++ pkt->vendor_id, pkt->product_id, pkt->version ++ ); ++ ++ LGTD_LIFX_GATEWAY_SET_BULB_ATTR( ++ gw, ++ hdr->target.device_addr, ++ lgtd_lifx_bulb_set_product_info, ++ (const struct lgtd_lifx_product_info *)pkt ++ ); ++} ++ ++void ++lgtd_lifx_gateway_handle_runtime_info(struct lgtd_lifx_gateway *gw, ++ const struct lgtd_lifx_packet_header *hdr, ++ const struct lgtd_lifx_packet_runtime_info *pkt) ++{ ++ assert(gw && hdr && pkt); ++ ++ char device_time[64], uptime[64], downtime[64]; ++ LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(pkt->time, device_time); ++ LGTD_PRINT_DURATION(LGTD_NSECS_TO_SECS(pkt->uptime), uptime); ++ LGTD_PRINT_DURATION(LGTD_NSECS_TO_SECS(pkt->downtime), downtime); ++ ++ lgtd_debug( ++ "PRODUCT_INFO <-- [%s]:%hu - %s time=%s, uptime=%s, downtime=%s", ++ gw->ip_addr, gw->port, lgtd_addrtoa(hdr->target.device_addr), ++ device_time, uptime, downtime ++ ); ++ ++ LGTD_LIFX_GATEWAY_SET_BULB_ATTR_WITH_RECV_AT( ++ gw, ++ hdr->target.device_addr, ++ lgtd_lifx_bulb_set_runtime_info, ++ (const struct lgtd_lifx_runtime_info *)pkt ++ ); ++} +diff --git a/lifx/gateway.h b/lifx/gateway.h +--- a/lifx/gateway.h ++++ b/lifx/gateway.h +@@ -36,6 +36,12 @@ + struct lgtd_lifx_gateway { + LIST_ENTRY(lgtd_lifx_gateway) link; + struct lgtd_lifx_bulb_list bulbs; ++#define LGTD_LIFX_GATEWAY_GET_BULB_OR_RETURN(b, gw, bulb_addr) do { \ ++ (b) = lgtd_lifx_gateway_get_or_open_bulb((gw), (bulb_addr)); \ ++ if (!(b)) { \ ++ return; \ ++ } \ ++} while (0) + // Multiple gateways can share the same site (that happens when bulbs are + // far away enough that ZigBee can't be used). Moreover the SET_PAN_GATEWAY + // packet doesn't include the device address in the header (i.e: site and +@@ -77,6 +83,18 @@ + + extern struct lgtd_lifx_gateway_list lgtd_lifx_gateways; + ++#define LGTD_LIFX_GATEWAY_SET_BULB_ATTR(gw, bulb_addr, bulb_fn, payload) do { \ ++ struct lgtd_lifx_bulb *b; \ ++ LGTD_LIFX_GATEWAY_GET_BULB_OR_RETURN(b, gw, bulb_addr); \ ++ (bulb_fn)(b, (payload)); \ ++} while (0) ++ ++#define LGTD_LIFX_GATEWAY_SET_BULB_ATTR_WITH_RECV_AT(gw, bulb_addr, bulb_fn, payload) do { \ ++ struct lgtd_lifx_bulb *b; \ ++ LGTD_LIFX_GATEWAY_GET_BULB_OR_RETURN(b, gw, bulb_addr); \ ++ (bulb_fn)(b, (payload), (gw)->last_pkt_at); \ ++} while (0) ++ + struct lgtd_lifx_gateway *lgtd_lifx_gateway_get(const struct sockaddr_storage *); + struct lgtd_lifx_gateway *lgtd_lifx_gateway_open(const struct sockaddr_storage *, + ev_socklen_t, +@@ -119,3 +137,15 @@ + void lgtd_lifx_gateway_handle_tags(struct lgtd_lifx_gateway *, + const struct lgtd_lifx_packet_header *, + const struct lgtd_lifx_packet_tags *); ++void lgtd_lifx_gateway_handle_ip_state(struct lgtd_lifx_gateway *, ++ const struct lgtd_lifx_packet_header *, ++ const struct lgtd_lifx_packet_ip_state *); ++void lgtd_lifx_gateway_handle_ip_firmware_info(struct lgtd_lifx_gateway *, ++ const struct lgtd_lifx_packet_header *, ++ const struct lgtd_lifx_packet_ip_firmware_info *); ++void lgtd_lifx_gateway_handle_product_info(struct lgtd_lifx_gateway *, ++ const struct lgtd_lifx_packet_header *, ++ const struct lgtd_lifx_packet_product_info *); ++void lgtd_lifx_gateway_handle_runtime_info(struct lgtd_lifx_gateway *, ++ const struct lgtd_lifx_packet_header *, ++ const struct lgtd_lifx_packet_runtime_info *); diff --git a/lifx/wire_proto.c b/lifx/wire_proto.c --- a/lifx/wire_proto.c +++ b/lifx/wire_proto.c -@@ -74,12 +74,32 @@ +@@ -24,8 +24,10 @@ + #include <stdarg.h> + #include <stdbool.h> + #include <stdint.h> ++#include <stdio.h> + #include <stdlib.h> + #include <string.h> ++#include <time.h> + + #include <event2/util.h> + +@@ -74,12 +76,32 @@ (void)pkt; } @@ -116,7 +564,7 @@ ((void (*)(struct lgtd_lifx_gateway *, \ const struct lgtd_lifx_packet_header *, \ const void *))(x)) -@@ -90,6 +110,10 @@ +@@ -90,6 +112,10 @@ #define REQUEST_ONLY \ .decode = lgtd_lifx_wire_null_packet_encoder_decoder, \ .handle = lgtd_lifx_wire_null_packet_handler @@ -127,7 +575,7 @@ static struct lgtd_lifx_packet_info packet_table[] = { // Gateway packets: -@@ -187,6 +211,211 @@ +@@ -187,6 +213,211 @@ .size = sizeof(struct lgtd_lifx_packet_tags), .decode = DECODER(lgtd_lifx_wire_decode_tags), .handle = HANDLER(lgtd_lifx_gateway_handle_tags) @@ -142,9 +590,9 @@ + RESPONSE_ONLY, + .name = "MESH_INFO", + .type = LGTD_LIFX_MESH_INFO, -+ .size = sizeof(struct lgtd_lifx_packet_mcu_state), -+ .decode = DECODER(lgtd_lifx_wire_decode_uc_state), -+ .handle = HANDLER(lgtd_lifx_gateway_handle_mcu_state) ++ .size = sizeof(struct lgtd_lifx_packet_ip_state), ++ .decode = DECODER(lgtd_lifx_wire_decode_ip_state), ++ .handle = HANDLER(lgtd_lifx_gateway_handle_ip_state) + }, + { + REQUEST_ONLY, @@ -156,9 +604,9 @@ + RESPONSE_ONLY, + .name = "MESH_FIRMWARE", + .type = LGTD_LIFX_MESH_FIRMWARE, -+ .size = sizeof(struct lgtd_lifx_packet_mcu_firmware_info), -+ .decode = DECODER(lgtd_lifx_decode_firmware_info), -+ .handle = HANDLER(lgtd_lifx_gateway_handle_mcu_firmware_info) ++ .size = sizeof(struct lgtd_lifx_packet_ip_firmware_info), ++ .decode = DECODER(lgtd_lifx_wire_decode_ip_firmware_info), ++ .handle = HANDLER(lgtd_lifx_gateway_handle_ip_firmware_info) + }, + { + REQUEST_ONLY, @@ -170,9 +618,9 @@ + RESPONSE_ONLY, + .name = "WIFI_INFO", + .type = LGTD_LIFX_WIFI_INFO, -+ .size = sizeof(struct lgtd_lifx_packet_wifi_state), -+ .decode = DECODER(lgtd_lifx_wire_decode_uc_state), -+ .handle = HANDLER(lgtd_lifx_gateway_handle_wifi_state) ++ .size = sizeof(struct lgtd_lifx_packet_ip_state), ++ .decode = DECODER(lgtd_lifx_wire_decode_ip_state), ++ .handle = HANDLER(lgtd_lifx_gateway_handle_ip_state) + }, + { + REQUEST_ONLY, @@ -184,9 +632,9 @@ + RESPONSE_ONLY, + .name = "WIFI_FIRMWARE_STATE", + .type = LGTD_LIFX_WIFI_FIRMWARE_STATE, -+ .size = sizeof(struct lgtd_lifx_packet_wifi_firmware_info), -+ .decode = DECODER(lgtd_lifx_wire_decode_firmware_info), -+ .handle = HANDLER(lgtd_lifx_gateway_handle_wifi_firmware_info) ++ .size = sizeof(struct lgtd_lifx_packet_ip_firmware_info), ++ .decode = DECODER(lgtd_lifx_wire_decode_ip_firmware_info), ++ .handle = HANDLER(lgtd_lifx_gateway_handle_ip_firmware_info) + }, + { + REQUEST_ONLY, @@ -216,7 +664,7 @@ + .decode = DECODER(lgtd_lifx_wire_decode_runtime_info), + .handle = HANDLER(lgtd_lifx_gateway_handle_runtime_info) + }, -+ // Unimplemented packets ++ // Unimplemented but "known" packets + { + UNIMPLEMENTED, + .name = "GET_TIME", @@ -339,34 +787,109 @@ } }; +@@ -234,6 +465,24 @@ + return LGTD_LIFX_WAVEFORM_INVALID; + } + ++void ++lgtd_lifx_wire_print_nsec_timestamp(uint64_t nsec_ts, char *buf, int bufsz) ++{ ++ assert(buf); ++ assert(bufsz > 0); ++ ++ time_t ts = LGTD_NSECS_TO_SECS(nsec_ts); ++ ++ struct tm tm_utc; ++ if (gmtime_r(&ts, &tm_utc)) { ++ int64_t usecs = LGTD_NSECS_TO_USECS(nsec_ts - LGTD_SECS_TO_NSECS(ts)); ++ LGTD_TM_TO_ISOTIME(&tm_utc, buf, bufsz, usecs); ++ return; ++ } ++ ++ buf[0] = '\0'; ++} ++ + static void + lgtd_lifx_wire_encode_header(struct lgtd_lifx_packet_header *hdr, int flags) + { +@@ -423,3 +672,44 @@ + + pkt->tags = le64toh(pkt->tags); + } ++ ++void ++lgtd_lifx_wire_decode_ip_state(struct lgtd_lifx_packet_ip_state *pkt) ++{ ++ assert(pkt); ++ ++ pkt->signal_strength = lgtd_lifx_wire_lefloattoh(pkt->signal_strength); ++ pkt->tx_bytes = le32toh(pkt->tx_bytes); ++ pkt->rx_bytes = le32toh(pkt->rx_bytes); ++ pkt->reserved = le16toh(pkt->reserved); ++} ++ ++void ++lgtd_lifx_wire_decode_ip_firmware_info(struct lgtd_lifx_packet_ip_firmware_info *pkt) ++{ ++ assert(pkt); ++ ++ pkt->built_at = le64toh(pkt->built_at); ++ pkt->installed_at = le64toh(pkt->installed_at); ++ pkt->version = le32toh(pkt->version); ++} ++ ++void ++lgtd_lifx_wire_decode_product_info(struct lgtd_lifx_packet_product_info *pkt) ++{ ++ assert(pkt); ++ ++ pkt->vendor_id = le32toh(pkt->vendor_id); ++ pkt->product_id = le32toh(pkt->product_id); ++ pkt->version = le32toh(pkt->version); ++} ++ ++void ++lgtd_lifx_wire_decode_runtime_info(struct lgtd_lifx_packet_runtime_info *pkt) ++{ ++ assert(pkt); ++ ++ pkt->time = le64toh(pkt->time); ++ pkt->uptime = le64toh(pkt->uptime); ++ pkt->downtime = le64toh(pkt->downtime); ++} diff --git a/lifx/wire_proto.h b/lifx/wire_proto.h --- a/lifx/wire_proto.h +++ b/lifx/wire_proto.h -@@ -249,6 +249,43 @@ +@@ -28,7 +28,7 @@ + static inline floatle_t + lgtd_lifx_wire_htolefloat(float f) + { +- union { float f; uint32_t i; } u = { .f = f }; ++ union { float f; uint32_t i; } u = { .f = f }; + htole32(u.i); + return u.f; + } +@@ -36,7 +36,7 @@ + static inline floatle_t + lgtd_lifx_wire_lefloattoh(float f) + { +- union { float f; uint32_t i; } u = { .f = f }; ++ union { float f; uint32_t i; } u = { .f = f }; + le32toh(u.i); + return u.f; + } +@@ -249,6 +249,30 @@ char label[LGTD_LIFX_LABEL_SIZE]; }; -+struct lgtd_lifx_packet_mcu_state { ++struct lgtd_lifx_packet_ip_state { + floatle_t signal_strength; + uint32le_t tx_bytes; + uint32le_t rx_bytes; -+ uint16le_t reserverd; ++ uint16le_t reserved; +}; + -+struct lgtd_lifx_packet_wifi_state { -+ floatle_t signal_strength; -+ uint32le_t tx_bytes; -+ uint32le_t rx_bytes; -+ uint16le_t reserverd; -+}; -+ -+struct lgtd_lifx_packet_mcu_firmware_info { -+ uint64le_t built_at; -+ uint64le_t installed_at; -+ uint32le_t version; -+}; -+ -+struct lgtd_lifx_packet_wifi_firmware_info { ++struct lgtd_lifx_packet_ip_firmware_info { + uint64le_t built_at; + uint64le_t installed_at; + uint32le_t version; @@ -386,3 +909,25 @@ #pragma pack(pop) enum lgtd_lifx_header_flags { +@@ -330,8 +354,11 @@ + (tag_id_varname) != -1; \ + (tag_id_varname) = lgtd_lifx_wire_next_tag_id((tag_id_varname), (tags))) + +- + enum lgtd_lifx_waveform_type lgtd_lifx_wire_waveform_string_id_to_type(const char *, int); ++void lgtd_lifx_wire_print_nsec_timestamp(uint64_t, char *, int); ++#define LGTD_LIFX_WIRE_PRINT_NSEC_TIMESTAMP(ts, arr) do { \ ++ lgtd_lifx_wire_print_nsec_timestamp((ts), (arr), sizeof((arr))); \ ++} while (0) + + const struct lgtd_lifx_packet_info *lgtd_lifx_wire_get_packet_info(enum lgtd_lifx_packet_type); + void lgtd_lifx_wire_load_packet_info_map(void); +@@ -356,3 +383,8 @@ + void lgtd_lifx_wire_decode_tags(struct lgtd_lifx_packet_tags *); + void lgtd_lifx_wire_encode_tag_labels(struct lgtd_lifx_packet_tag_labels *); + void lgtd_lifx_wire_decode_tag_labels(struct lgtd_lifx_packet_tag_labels *); ++ ++void lgtd_lifx_wire_decode_ip_state(struct lgtd_lifx_packet_ip_state *); ++void lgtd_lifx_wire_decode_ip_firmware_info(struct lgtd_lifx_packet_ip_firmware_info *); ++void lgtd_lifx_wire_decode_product_info(struct lgtd_lifx_packet_product_info *); ++void lgtd_lifx_wire_decode_runtime_info(struct lgtd_lifx_packet_runtime_info *);
--- a/series Sat Aug 08 19:41:56 2015 -0700 +++ b/series Sun Aug 09 03:25:17 2015 -0700 @@ -1,1 +1,3 @@ implement_some_metadata_packet_types.h +fallback_on_device_addr_when_label.patch +use_jq_when_avalaible.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/use_jq_when_avalaible.patch Sun Aug 09 03:25:17 2015 -0700 @@ -0,0 +1,57 @@ +# HG changeset patch +# Parent dfe2227266b4be40a52a4e2cfa88b0e9e8c47523 +Use jq when available in lightsc.sh + +diff --git a/examples/lightsc.sh b/examples/lightsc.sh +--- a/examples/lightsc.sh ++++ b/examples/lightsc.sh +@@ -24,7 +24,7 @@ + # tags and labels into double quotes '"likethis"'. Also keep in mind + # that the pipe is write-only you cannot read any result back. + +-_b64e() { ++_lightsc_b64e() { + if type base64 >/dev/null 2>&1 ; then + base64 + elif type b64encode >/dev/null 2>&1 ; then +@@ -35,14 +35,22 @@ + fi + } + +-_gen_request_id() { ++_lightsc_gen_request_id() { + if type dd >/dev/null 2>&1 ; then +- printf '"%s"' `dd if=/dev/urandom bs=8 count=1 2>&- | _b64e` ++ printf '"%s"' `dd if=/dev/urandom bs=8 count=1 2>&- | _lightsc_b64e` + else + echo null + fi + } + ++_lightsc_jq() { ++ if type jq >/dev/null 2>&1 ; then ++ jq . ++ else ++ cat ++ fi ++} ++ + lightsc() { + if [ $# -lt 2 ] ; then + echo >&2 "Usage: $0 METHOD PARAMS ..." +@@ -61,12 +69,13 @@ + params=$params,$target + done + +- tee $pipe <<EOF ++ tee $pipe <<EOF | + { + "jsonrpc": "2.0", + "method": "$method", + "params": [$params], +- "id": `_gen_request_id` ++ "id": `_lightsc_gen_request_id` + } + EOF ++_lightsc_jq + }