context.c
Go to the documentation of this file.
/*
liblightify -- library to control OSRAM's LIGHTIFY
Copyright (c) 2015, Tobias Frost <tobi@coldtobi.de>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "liblightify-private.h"
#include "context.h"
#include "log.h"
#include "node.h"
#include "groups.h"
#include "socket.h"
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
enum msg_header {
HEADER_LEN_LSB,
HEADER_LEN_MSB,
HEADER_FLAGS,
HEADER_CMD,
HEADER_REQ_ID_B0,
HEADER_REQ_ID_B1,
HEADER_REQ_ID_B2,
HEADER_REQ_ID_B3,
HEADER_PAYLOAD_START
};
enum msg_0x13_query {
QUERY_0x13_REQTYPE = HEADER_PAYLOAD_START,
QUERY_0x13_SIZE
};
enum msg_0x13_answer {
ANSWER_0x13_UNKNOWN1 = HEADER_PAYLOAD_START,
ANSWER_0x13_NODESCNT_LSB,
ANSWER_0x13_NODESCNT_MSB,
ANSWER_0x13_SIZE
};
enum msg_0x13_answer_node {
ANSWER_0x13_NODE_ADR16_LSB,
ANSWER_0x13_NODE_ADR16_MSB,
ANSWER_0x13_NODE_ADR64_B0,
ANSWER_0x13_NODE_ADR64_B1,
ANSWER_0x13_NODE_ADR64_B2,
ANSWER_0x13_NODE_ADR64_B3,
ANSWER_0x13_NODE_ADR64_B4,
ANSWER_0x13_NODE_ADR64_B5,
ANSWER_0x13_NODE_ADR64_B6,
ANSWER_0x13_NODE_ADR64_B7,
ANSWER_0x13_NODE_NODETYPE,
ANSWER_0x13_UNKNOWN2,
ANSWER_0x13_UNKNOWN3,
ANSWER_0x13_UNKNOWN4,
ANSWER_0x13_UNKNOWN5,
ANSWER_0x13_NODE_ONLINE_STATE,
ANSWER_0x13_NODE_GRP_MEMBER_LSB,
ANSWER_0x13_NODE_GRP_MEMBER_MSB,
ANSWER_0x13_NODE_ONOFF_STATE,
ANSWER_0x13_NODE_DIM_LEVEL,
ANSWER_0x13_NODE_CCT_LSB,
ANSWER_0x13_NODE_CCT_MSB,
ANSWER_0x13_NODE_R,
ANSWER_0x13_NODE_G,
ANSWER_0x13_NODE_B,
ANSWER_0x13_NODE_W,
ANSWER_0x13_NODE_NAME_START,
ANSWER_0x13_NODE_LENGTH = 42
};
enum msg_0x31_query {
QUERY_0x31_NODEADR64_B0 = HEADER_PAYLOAD_START,
QUERY_0x31_NODEADR64_B1,
QUERY_0x31_NODEADR64_B2,
QUERY_0x31_NODEADR64_B3,
QUERY_0x31_NODEADR64_B4,
QUERY_0x31_NODEADR64_B5,
QUERY_0x31_NODEADR64_B6,
QUERY_0x31_NODEADR64_B7,
QUERY_0x31_LEVEL,
QUERY_0x31_FADETIME_LSB,
QUERY_0x31_FADETIME_MSB,
QUERY_0x31_SIZE
};
enum msg_0x31_answer {
ANSWER_0x31_STATE = HEADER_PAYLOAD_START,
ANSWER_0x31_UNKNOWN1,
ANSWER_0x31_UNKNOWN2,
ANSWER_0x31_NODEADR64_B0,
ANSWER_0x31_NODEADR64_B1,
ANSWER_0x31_NODEADR64_B2,
ANSWER_0x31_NODEADR64_B3,
ANSWER_0x31_NODEADR64_B4,
ANSWER_0x31_NODEADR64_B5,
ANSWER_0x31_NODEADR64_B6,
ANSWER_0x31_NODEADR64_B7,
ANSWER_0x31_UNKNOWN3,
ANSWER_0x31_SIZE
};
enum msg_0x32_query {
QUERY_0x32_NODEADR64_B0 = HEADER_PAYLOAD_START,
QUERY_0x32_NODEADR64_B1,
QUERY_0x32_NODEADR64_B2,
QUERY_0x32_NODEADR64_B3,
QUERY_0x32_NODEADR64_B4,
QUERY_0x32_NODEADR64_B5,
QUERY_0x32_NODEADR64_B6,
QUERY_0x32_NODEADR64_B7,
QUERY_0x32_ONOFF,
QUERY_0x32_SIZE
};
enum msg_0x32_answer {
ANSWER_0x32_STATE = HEADER_PAYLOAD_START,
ANSWER_0x32_RESERVED_LSB,
ANSWER_0x32_RESERVED_MSB,
ANSWER_0x32_NODEADR64_B0,
ANSWER_0x32_NODEADR64_B1,
ANSWER_0x32_NODEADR64_B2,
ANSWER_0x32_NODEADR64_B3,
ANSWER_0x32_NODEADR64_B4,
ANSWER_0x32_NODEADR64_B5,
ANSWER_0x32_NODEADR64_B6,
ANSWER_0x32_NODEADR64_B7,
ANSWER_0x32_UNKNOWN1,
ANSWER_0x32_SIZE
};
enum msg_0x33_query {
QUERY_0x33_NODEADR64_B0 = HEADER_PAYLOAD_START,
QUERY_0x33_NODEADR64_B1,
QUERY_0x33_NODEADR64_B2,
QUERY_0x33_NODEADR64_B3,
QUERY_0x33_NODEADR64_B4,
QUERY_0x33_NODEADR64_B5,
QUERY_0x33_NODEADR64_B6,
QUERY_0x33_NODEADR64_B7,
QUERY_0x33_CCT_LSB,
QUERY_0x33_CCT_MSB,
QUERY_0x33_FADETIME_LSB,
QUERY_0x33_FADETIME_MSB,
QUERY_0x33_SIZE
};
enum msg_0x33_answer {
ANSWER_0x33_STATE = HEADER_PAYLOAD_START,
ANSWER_0x33_RESERVED_LSB,
ANSWER_0x33_RESERVED_MSB,
ANSWER_0x33_NODEADR64_B0,
ANSWER_0x33_NODEADR64_B1,
ANSWER_0x33_NODEADR64_B2,
ANSWER_0x33_NODEADR64_B3,
ANSWER_0x33_NODEADR64_B4,
ANSWER_0x33_NODEADR64_B5,
ANSWER_0x33_NODEADR64_B6,
ANSWER_0x33_NODEADR64_B7,
ANSWER_0x33_UNKNOWN1,
ANSWER_0x33_SIZE
};
enum msg_0x36_query {
QUERY_0x36_NODEADR64_B0 = HEADER_PAYLOAD_START,
QUERY_0x36_NODEADR64_B1,
QUERY_0x36_NODEADR64_B2,
QUERY_0x36_NODEADR64_B3,
QUERY_0x36_NODEADR64_B4,
QUERY_0x36_NODEADR64_B5,
QUERY_0x36_NODEADR64_B6,
QUERY_0x36_NODEADR64_B7,
QUERY_0x36_R,
QUERY_0x36_G,
QUERY_0x36_B,
QUERY_0x36_W,
QUERY_0x36_FADETIME_LSB,
QUERY_0x36_FADETIME_MSB,
QUERY_0x36_SIZE
};
enum msg_0x36_answer {
ANSWER_0x36_STATE = HEADER_PAYLOAD_START,
ANSWER_0x36_RESERVED_LSB,
ANSWER_0x36_RESERVED_MSB,
ANSWER_0x36_NODEADR64_B0,
ANSWER_0x36_NODEADR64_B1,
ANSWER_0x36_NODEADR64_B2,
ANSWER_0x36_NODEADR64_B3,
ANSWER_0x36_NODEADR64_B4,
ANSWER_0x36_NODEADR64_B5,
ANSWER_0x36_NODEADR64_B6,
ANSWER_0x36_NODEADR64_B7,
ANSWER_0x36_UNKNOWN1,
ANSWER_0x36_SIZE
};
enum msg_0x68_query {
QUERY_0x68_NODEADR64_B0 = HEADER_PAYLOAD_START,
QUERY_0x68_NODEADR64_B1,
QUERY_0x68_NODEADR64_B2,
QUERY_0x68_NODEADR64_B3,
QUERY_0x68_NODEADR64_B4,
QUERY_0x68_NODEADR64_B5,
QUERY_0x68_NODEADR64_B6,
QUERY_0x68_NODEADR64_B7,
QUERY_0x68_SIZE
};
enum msg_0x68_answer {
ANSWER_0x68_STATE = HEADER_PAYLOAD_START,
ANSWER_0x68_NONODES_LSB,
ANSWER_0x68_NONODES_MSB,
ANSWER_0x68_NODEADR64_B0,
ANSWER_0x68_NODEADR64_B1,
ANSWER_0x68_NODEADR64_B2,
ANSWER_0x68_NODEADR64_B3,
ANSWER_0x68_NODEADR64_B4,
ANSWER_0x68_NODEADR64_B5,
ANSWER_0x68_NODEADR64_B6,
ANSWER_0x68_NODEADR64_B7,
ANSWER_0x68_UNKNOWN1,
ANSWER_0x68_ONLINESTATE,
ANSWER_0x68_ONOFF,
ANSWER_0x68_DIM_LEVEL,
ANSWER_0x68_CCT_LSB,
ANSWER_0x68_CCT_MSB,
ANSWER_0x68_R,
ANSWER_0x68_G,
ANSWER_0x68_B,
ANSWER_0x68_W,
ANSWER_0x68_SIZE
};
enum msg_0x1e_query {
QUERY_0x1e = HEADER_PAYLOAD_START,
QUERY_0x1e_SIZE
};
enum msg_0x1e_answer {
ANSWER_0x1e_STATE = HEADER_PAYLOAD_START,
ANSWER_0x1e_NUMGROUPS,
ANSWER_0x1e_HDR_UNKNOWN_ZERO,
ANSWER_0x1e_SIZE
};
enum msg_0x1e_answerpergroup {
ANSWER_0x1e_GRP_ID,
ANSWER_0x1e_GRP_UNKNOWN_ZERO,
ANSWER_0x1e_GRP_NAME,
ANSWER_0x1e_GRP_LENGHT= ANSWER_0x1e_GRP_NAME+16
};
// 0 seems success, non-zero error.
static int decode_status(unsigned char code) {
switch (code) {
// success
case 0x00: return 0;
case 0x15: return ENODEV;
default: return EIO;
}
}
LIGHTIFY_EXPORT struct lightify_node *lightify_node_get_from_mac(struct lightify_ctx *ctx, uint64_t mac) {
if (!ctx) return NULL;
struct lightify_node *ret = ctx->nodes;
while(ret) {
if (lightify_node_get_nodeadr(ret) == mac) return ret;
ret = lightify_node_get_nextnode(ret);
}
return NULL;
}
static uint64_t uint64_from_msg(uint8_t *msg) {
uint64_t tmp;
tmp = msg[7]; tmp <<=8;
tmp |= msg[6]; tmp <<=8;
tmp |= msg[5]; tmp <<=8;
tmp |= msg[4]; tmp <<=8;
tmp |= msg[3]; tmp <<=8;
tmp |= msg[2]; tmp <<=8;
tmp |= msg[1]; tmp <<=8;
tmp |= msg[0];
return tmp;
}
static void msg_from_uint64(unsigned char *pmsg, uint64_t mac) {
*pmsg++ = mac & 0xff;
*pmsg++ = mac >> 8 & 0xff;
*pmsg++ = mac >> 16 & 0xff;
*pmsg++ = mac >> 24 & 0xff;
*pmsg++ = mac >> 32 & 0xff;
*pmsg++ = mac >> 40 & 0xff;
*pmsg++ = mac >> 48 & 0xff;
*pmsg++ = mac >> 56 & 0xff;
}
static uint16_t uint16_from_msg(uint8_t *msg) {
uint16_t tmp;
tmp = msg[0] | (msg[1]<<8);
return tmp;
}
static void fill_telegram_header(unsigned char *msg, unsigned int len, unsigned long token, unsigned char flags, unsigned char command)
{
len-=2;
msg[HEADER_LEN_LSB] = len & 0xff;
msg[HEADER_LEN_MSB] = len >> 8;
msg[HEADER_FLAGS] = flags;
msg[HEADER_CMD] = command;
msg[HEADER_REQ_ID_B0] = token & 0xff;
msg[HEADER_REQ_ID_B1] = token >> 8 & 0xff;
msg[HEADER_REQ_ID_B2] = token >> 16 & 0xff;
msg[HEADER_REQ_ID_B3] = token >> 24 & 0xff;
}
static int check_header_response(unsigned char *msg, unsigned long token,
unsigned char cmd) {
unsigned long token2;
/* check the header if plausible */
/* check if the token we've supplied is also the returned one. */
token2 = msg[HEADER_REQ_ID_B0] | (msg[HEADER_REQ_ID_B1] << 8U) |
(msg[HEADER_REQ_ID_B1] << 16U) | (msg[HEADER_REQ_ID_B1] << 24U);
if (token != token2) return -EPROTO;
if (msg[HEADER_CMD] != cmd) return -EPROTO;
return 0;
}
LIGHTIFY_EXPORT struct lightify_node* lightify_node_get_next(struct lightify_ctx *ctx,
struct lightify_node *node ) {
if(!ctx) return NULL;
if(node) return lightify_node_get_nextnode(node);
return ctx->nodes;
}
LIGHTIFY_EXPORT struct lightify_node* lightify_node_get_previous(struct lightify_ctx *ctx,
struct lightify_node *node )
{
if(!ctx) return NULL;
return lightify_node_get_prevnode(node);
}
LIGHTIFY_EXPORT void *lightify_get_userdata(struct lightify_ctx *ctx)
{
if (!ctx) return NULL;
return ctx->userdata;
}
LIGHTIFY_EXPORT int lightify_set_userdata(struct lightify_ctx *ctx, void *userdata)
{
if (!ctx) return -EINVAL;
ctx->userdata = userdata;
return 0;
}
LIGHTIFY_EXPORT int lightify_set_socket_fn(struct lightify_ctx *ctx,
write_to_socket_fn fpw, read_from_socket_fn fpr) {
if (!ctx) return -EINVAL;
if (!fpw || !fpr) {;
ctx->socket_read_fn = read_from_socket;
ctx->socket_write_fn = write_to_socket;
return 0;
}
ctx->socket_read_fn = fpr;
ctx->socket_write_fn = fpw;
return 0;
}
LIGHTIFY_EXPORT int lightify_new(struct lightify_ctx **ctx, void *reserved)
{
struct lightify_ctx *c;
c = calloc(1, sizeof(struct lightify_ctx));
if (!c) return -ENOMEM;
c->log_fn = log_stderr;
c->log_priority = LOG_ERR;
#ifdef HAVE_SECURE_GETENV
/* environment overwrites config */
const char *env;
env = secure_getenv("lightify_LOG");
if (env != NULL)
lightify_set_log_priority(c, log_priority(env));
#endif
info(c, "ctx %p created\n", c);
dbg(c, "log_priority=%d\n", c->log_priority);
*ctx = c;
c->socket = -1;
c->iotimeout.tv_sec=1;
c->socket_read_fn = read_from_socket;
c->socket_write_fn = write_to_socket;
return 0;
}
static void free_all_nodes(struct lightify_ctx *ctx) {
if (!ctx) return;
while(ctx->nodes) {
dbg(ctx, "freeing node %p.\n", ctx->nodes);
lightify_node_remove(ctx->nodes);
}
}
static void free_all_groups(struct lightify_ctx *ctx) {
if (!ctx) return;
while(ctx->groups) {
dbg(ctx, "freeing group %p.\n", ctx->nodes);
lightify_group_remove(ctx->groups);
}
}
LIGHTIFY_EXPORT int lightify_free(struct lightify_ctx *ctx) {
if (!ctx) return -EINVAL;
free_all_nodes(ctx);
free_all_groups(ctx);
dbg(ctx, "context %p freed.\n", ctx);
free(ctx);
return 0;
}
LIGHTIFY_EXPORT int lightify_node_request_scan(struct lightify_ctx *ctx) {
int ret;
int n,m;
int no_of_nodes;
long token;
if (!ctx) return -EINVAL;
/* if using standard I/O functions, fd must be valid. If the user overrode those function,
we won't care */
if (ctx->socket_read_fn == read_from_socket
&& ctx->socket_write_fn == write_to_socket && ctx->socket < 0) {
return -EBADF;
}
/* remove old node information */
free_all_nodes(ctx);
token = ++ctx->cnt;
/* to avoid problems with packing, we need to use a char array.
* to assist we'll have this fine enum */
uint8_t msg[42];
/* 0x13 command to get all node's informations. */
fill_telegram_header(msg, QUERY_0x13_SIZE, token, 0x00, 0x13);
msg[QUERY_0x13_REQTYPE] = 0x01;
n = ctx->socket_write_fn(ctx, msg, QUERY_0x13_SIZE);
if ( n < 0 ) {
info(ctx,"socket_write_fn error %d\n", n);
return n;
}
if ( n != QUERY_0x13_SIZE) {
info(ctx,"short write %d!=%d\n", QUERY_0x13_SIZE, n);
return -EIO;
}
/* read the header */
n = ctx->socket_read_fn(ctx, msg, ANSWER_0x13_SIZE);
if (n < 0) {
info(ctx,"socket_read_fn error %d\n", n);
return n;
}
if (n != ANSWER_0x13_SIZE) {
info(ctx,"short read %d!=%d\n", ANSWER_0x13_SIZE, n);
return -EIO;
}
/* check the header if plausible */
/* check if the token we've supplied is also the returned one. */
n = check_header_response(msg, token, 0x13);
if ( n < 0 ) {
info(ctx,"Invalid response (header)\n");
return n;
}
/* check if the message length is as expected */
no_of_nodes = msg[ANSWER_0x13_NODESCNT_LSB] | (msg[ANSWER_0x13_NODESCNT_MSB] <<8);
m = msg[HEADER_LEN_LSB] | (msg[HEADER_LEN_MSB] << 8);
/*info(ctx, "0x13: received %d bytes\n",m);*/
if ( no_of_nodes * ANSWER_0x13_NODE_LENGTH + ANSWER_0x13_SIZE - 2 != m) {
info(ctx, "Reponse len unexpected for %d nodes: %d!=%d.\n", no_of_nodes,
no_of_nodes * ANSWER_0x13_NODE_LENGTH + ANSWER_0x13_SIZE - 2, m);
return -EPROTO;
}
if (msg[HEADER_PAYLOAD_START]) {
info(ctx, "strange byte at PAYLOAD_START: %d\n", msg[HEADER_PAYLOAD_START]);
}
ret = 0;
/* read each node..*/
while(no_of_nodes--) {
uint64_t tmp64;
struct lightify_node *node = NULL;
n = ctx->socket_read_fn(ctx, msg, ANSWER_0x13_NODE_LENGTH);
if (n< 0) return n;
if (ANSWER_0x13_NODE_LENGTH != n ) {
info(ctx,"read node info: short read %d!=%d\n", ANSWER_0x13_NODE_LENGTH, n);
return -EIO;
}
n = lightify_node_new(ctx, &node);
if (n < 0) {
info(ctx, "create node error %d", n);
return n;
}
tmp64 = uint64_from_msg(&msg[ANSWER_0x13_NODE_ADR64_B0]);
lightify_node_set_nodeadr(node, tmp64);
lightify_node_set_zoneadr(node, uint16_from_msg(&msg[ANSWER_0x13_NODE_ADR16_LSB]));
lightify_node_set_grpadr(node, uint16_from_msg(&msg[ANSWER_0x13_NODE_GRP_MEMBER_LSB]));
lightify_node_set_name(node, (char*) &msg[ANSWER_0x13_NODE_NAME_START]);
info(ctx, "new node: %s\n", lightify_node_get_name(node));
n = msg[ANSWER_0x13_NODE_NODETYPE];
switch (n) {
case 0x00 : // Plug
lightify_node_set_lamptype(node, LIGHTIFY_ONOFF_PLUG);
break;
case 0x02 : // CCT light
lightify_node_set_lamptype(node, LIGHTIFY_CCT_LIGHT);
break;
case 0x04 : // dimable
lightify_node_set_lamptype(node, LIGHTIFY_DIMABLE_LIGHT);
break;
case 0x08 : // RGB
lightify_node_set_lamptype(node, LIGHTIFY_COLOUR_LIGHT);
break;
case 0x0a : // CCT, RGB
lightify_node_set_lamptype(node, LIGHTIFY_EXT_COLOUR_LIGHT);
break;
default: // maybe the missing dimmer plug or on/off light.
lightify_node_set_lamptype(node, LIGHTIFY_UNKNOWNTYPE | n );
dbg(ctx, "unknown type %x for lamp %s. PLEASE REPORT A BUG AGAINST liblightify. \n",n, lightify_node_get_name(node));
break;
}
dbg(ctx, "xtra-data: %x -- %x %x %x %x\n", msg[ANSWER_0x13_UNKNOWN1],
msg[ANSWER_0x13_UNKNOWN2],msg[ANSWER_0x13_UNKNOWN3],
msg[ANSWER_0x13_UNKNOWN4],msg[ANSWER_0x13_UNKNOWN5]);
lightify_node_set_red(node, msg[ANSWER_0x13_NODE_R]);
lightify_node_set_green(node, msg[ANSWER_0x13_NODE_G]);
lightify_node_set_blue(node, msg[ANSWER_0x13_NODE_B]);
lightify_node_set_white(node, msg[ANSWER_0x13_NODE_W]);
lightify_node_set_cct(node, uint16_from_msg(&msg[ANSWER_0x13_NODE_CCT_LSB]));
lightify_node_set_onoff(node, msg[ANSWER_0x13_NODE_ONOFF_STATE] != 0);
lightify_node_set_online_status(node, msg[ANSWER_0x13_NODE_ONLINE_STATE]);
lightify_node_set_brightness(node,msg[ANSWER_0x13_NODE_DIM_LEVEL]);
lightify_node_set_stale(node, 0);
ret++;
}
return ret;
}
static int lightify_request_set_onoff(struct lightify_ctx *ctx, uint64_t adr, int isgroup, int onoff) {
unsigned char msg[32];
int n;
if (!ctx) return -EINVAL;
/* normalize to boolean -- int are 16bits...*/
onoff = (onoff != 0);
isgroup = (isgroup) ? 2 : 0;
long token = ++ctx->cnt;
fill_telegram_header(msg, QUERY_0x32_SIZE, token, isgroup, 0x32);
msg_from_uint64(&msg[QUERY_0x32_NODEADR64_B0], adr);
msg[QUERY_0x32_ONOFF] = onoff;
n = ctx->socket_write_fn(ctx,msg, QUERY_0x32_SIZE);
if ( n < 0 ) {
info(ctx,"socket_write_fn error %d\n", n);
return n;
}
if ( n != QUERY_0x32_SIZE) {
info(ctx,"short write %d!=%d\n", QUERY_0x32_SIZE, n);
return -EIO;
}
/* read the header */
n = ctx->socket_read_fn(ctx, msg, ANSWER_0x32_SIZE);
if (n < 0) {
info(ctx,"socket_read_fn error %d\n", n);
return n;
}
if (n != ANSWER_0x32_SIZE) {
info(ctx,"short read %d!=%d\n", ANSWER_0x32_SIZE, n);
int i = 0;
while(n--) {
info(ctx, " %d => %x\n ",i, msg[i]);
i++;
}
info(ctx, "\n");
return -EIO;
}
/* check the header if plausible */
n = check_header_response(msg, token, 0x32);
if ( n < 0 ) {
info(ctx,"Invalid response (header)\n");
return n;
}
/* check if the node address was echoed properly */
uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x32_NODEADR64_B0]);
if (adr != adr2) {
info(ctx, "unexected node mac / group adr %llx!=%llx", adr, adr2 );
return -EPROTO;
}
n = -decode_status(msg[ANSWER_0x32_STATE]);
if (n) {
info(ctx, "state %d indicates error.\n", n);
}
return n;
}
static int lightify_request_set_cct(struct lightify_ctx *ctx, uint64_t adr, int isgroup, unsigned int cct, unsigned int fadetime) {
unsigned char msg[32];
int n;
if (!ctx) return -EINVAL;
long token = ++ctx->cnt;
isgroup = (isgroup) ? 2 : 0;
fill_telegram_header(msg, QUERY_0x33_SIZE, token, isgroup, 0x33);
msg_from_uint64(&msg[QUERY_0x33_NODEADR64_B0], adr);
msg[QUERY_0x33_CCT_LSB] = cct & 0xff;
msg[QUERY_0x33_CCT_MSB] = (cct >> 8 ) & 0xff;
msg[QUERY_0x33_FADETIME_LSB] = fadetime & 0xff;
msg[QUERY_0x33_FADETIME_MSB] = (fadetime >> 8 ) & 0xff;
n = ctx->socket_write_fn(ctx,msg, QUERY_0x33_SIZE);
if ( n < 0 ) {
info(ctx,"socket_write_fn error %d\n", n);
return n;
}
if ( n != QUERY_0x33_SIZE) {
info(ctx,"short write %d!=%d\n", QUERY_0x33_SIZE, n);
return -EIO;
}
/* read the header */
n = ctx->socket_read_fn(ctx, msg, ANSWER_0x33_SIZE);
if (n < 0) {
info(ctx,"socket_read_fn error %d\n", n);
return n;
}
if (n != ANSWER_0x33_SIZE) {
info(ctx,"short read %d!=%d\n", ANSWER_0x33_SIZE, n);
return -EIO;
}
/* check the header if plausible */
n = check_header_response(msg, token, 0x33);
if ( n < 0 ) {
info(ctx,"Invalid response (header)\n");
return n;
}
/* check if the node address was echoed properly */
uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x33_NODEADR64_B0]);
if (adr != adr2) {
info(ctx, "unexected node mac / group adr %llx!=%llx", adr, adr2 );
return -EPROTO;
}
n = -decode_status(msg[ANSWER_0x33_STATE]);
return n;
}
static int lightify_request_set_rgbw(struct lightify_ctx *ctx, uint64_t adr,
int isgroup, unsigned int r, unsigned int g,
unsigned int b,unsigned int w,unsigned int fadetime) {
unsigned char msg[32];
int n;
if (!ctx) return -EINVAL;
/* does not support broadcast. */
long token = ++ctx->cnt;
isgroup = (isgroup) ? 2 : 0;
fill_telegram_header(msg, QUERY_0x36_SIZE, token, isgroup, 0x36);
msg_from_uint64(&msg[QUERY_0x36_NODEADR64_B0], adr);
msg[QUERY_0x36_R] = r & 0xff;
msg[QUERY_0x36_G] = g & 0xff;
msg[QUERY_0x36_B] = b & 0xff;
msg[QUERY_0x36_W] = w & 0xff;
msg[QUERY_0x36_FADETIME_LSB] = fadetime & 0xff;
msg[QUERY_0x36_FADETIME_MSB] = (fadetime >> 8 ) & 0xff;
n = ctx->socket_write_fn(ctx,msg, QUERY_0x36_SIZE);
if ( n < 0 ) {
info(ctx,"socket_write_fn error %d\n", n);
return n;
}
if ( n != QUERY_0x36_SIZE) {
info(ctx,"short write %d!=%d\n", QUERY_0x36_SIZE, n);
return -EIO;
}
/* read the header */
n = ctx->socket_read_fn(ctx, msg, ANSWER_0x36_SIZE);
if (n != ANSWER_0x36_SIZE) {
info(ctx,"short read %d!=%d\n", ANSWER_0x36_SIZE, n);
return -EIO;
}
/* check the header if plausible */
n = check_header_response(msg, token, 0x36);
if ( n < 0 ) {
info(ctx,"Invalid response (header)\n");
return n;
}
/* check if the node address was echoed properly */
uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x33_NODEADR64_B0]);
if (adr != adr2) {
info(ctx, "unexected node mac / group adr %llx!=%llx", adr, adr2 );
return -EPROTO;
}
n = -decode_status(msg[ANSWER_0x36_STATE]);
return n;
}
static int lightify_request_set_brightness(struct lightify_ctx *ctx, uint64_t adr,
int isgroup, unsigned int level, unsigned int fadetime) {
unsigned char msg[32];
int n;
if (!ctx) return -EINVAL;
long token = ++ctx->cnt;
isgroup = (isgroup) ? 2 : 0;
fill_telegram_header(msg, QUERY_0x31_SIZE, token, isgroup, 0x31);
msg_from_uint64(&msg[QUERY_0x31_NODEADR64_B0], adr);
msg[QUERY_0x31_LEVEL] = level & 0xff;
msg[QUERY_0x31_FADETIME_LSB] = fadetime & 0xff;
msg[QUERY_0x31_FADETIME_MSB] = (fadetime >> 8 ) & 0xff;
n = ctx->socket_write_fn(ctx,msg, QUERY_0x31_SIZE);
if ( n < 0 ) {
info(ctx,"socket_write_fn error %d\n", n);
return n;
}
if ( n != QUERY_0x31_SIZE) {
info(ctx,"short write %d!=%d\n", QUERY_0x31_SIZE, n);
return -EIO;
}
/* read the header */
n = ctx->socket_read_fn(ctx,msg,ANSWER_0x31_SIZE);
if (n < 0) {
info(ctx,"socket_read_fn error %d\n", n);
return n;
}
if (n != ANSWER_0x31_SIZE) {
info(ctx,"short read %d!=%d\n", ANSWER_0x31_SIZE, n);
return -EIO;
}
n = check_header_response(msg, token, 0x31);
if ( n < 0 ) {
info(ctx,"Invalid response (header)\n");
return n;
}
/* check if the node address was echoed properly */
uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x33_NODEADR64_B0]);
if (adr != adr2) {
info(ctx, "unexected node mac / group adr %llx!=%llx", adr, adr2 );
return -EPROTO;
}
n = -decode_status(msg[ANSWER_0x31_STATE]);
dbg(ctx, "unknown-bytes: %x %x %x\n", msg[ANSWER_0x31_UNKNOWN1],msg[ANSWER_0x31_UNKNOWN2],msg[ANSWER_0x31_UNKNOWN3]);
return n;
}
/* Node control */
LIGHTIFY_EXPORT int lightify_node_request_onoff(struct lightify_ctx *ctx, struct lightify_node *node, int onoff) {
if (!ctx) return -EINVAL;
uint64_t adr = -1;
if (node) adr = lightify_node_get_nodeadr(node);
onoff = (onoff != 0);
int ret = lightify_request_set_onoff(ctx, adr, 0, onoff);
if (node) {
lightify_node_set_onoff(node,onoff);
if (ret<0) {
lightify_node_set_stale(node,1);
}
} else {
node = NULL;
while((node = lightify_node_get_next(ctx, node))) {
lightify_node_set_onoff(node,onoff);
if (ret<0) {
lightify_node_set_stale(node,1);
}
}
}
return ret;
}
LIGHTIFY_EXPORT int lightify_node_request_cct(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int cct, unsigned int fadetime) {
if (!ctx || !node ) return -EINVAL;
uint64_t adr = lightify_node_get_nodeadr(node);
int ret = lightify_request_set_cct(ctx, adr, 0 , cct, fadetime);
lightify_node_set_cct(node, cct);
if (ret<0) {
lightify_node_set_stale(node,1);
}
return ret;
}
LIGHTIFY_EXPORT int lightify_node_request_rgbw(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int r, unsigned int g, unsigned int b,unsigned int w,unsigned int fadetime)
{
if (!ctx || !node ) return -EINVAL;
uint64_t adr = lightify_node_get_nodeadr(node);
int ret = lightify_request_set_rgbw(ctx, adr, 0, r, g ,b ,w ,fadetime);
lightify_node_set_red(node, r);
lightify_node_set_green(node, g);
lightify_node_set_blue(node, b);
lightify_node_set_white(node, w);
if (ret<0) {
lightify_node_set_stale(node,1);
}
return ret;
}
LIGHTIFY_EXPORT int lightify_node_request_brightness(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int level, unsigned int fadetime) {
if (!ctx || !node ) return -EINVAL;
uint64_t adr = lightify_node_get_nodeadr(node);
int ret = lightify_request_set_brightness(ctx, adr, 0, level, fadetime);
lightify_node_set_brightness(node, level);
lightify_node_set_onoff(node, level!=0);
if (ret<0) {
lightify_node_set_stale(node,1);
}
return ret;
}
LIGHTIFY_EXPORT int lightify_node_request_update(struct lightify_ctx *ctx,
struct lightify_node *node) {
unsigned char msg[32];
int n;
if (!ctx) return -EINVAL;
if (!node)return -EINVAL;
uint64_t node_adr = lightify_node_get_nodeadr(node);
long token = ++ctx->cnt;
fill_telegram_header(msg, QUERY_0x68_SIZE, token, 0x00, 0x68);
msg_from_uint64(&msg[QUERY_0x68_NODEADR64_B0], node_adr);
n = ctx->socket_write_fn(ctx,msg, QUERY_0x68_SIZE);
if ( n < 0 ) {
info(ctx,"socket_write_fn error %d\n", n);
return n;
}
if ( n != QUERY_0x68_SIZE) {
info(ctx,"short write %d!=%d\n", QUERY_0x68_SIZE, n);
return -EIO;
}
/* read the header */
n = ctx->socket_read_fn(ctx,msg,ANSWER_0x68_SIZE);
if (n < 0) {
info(ctx,"socket_read_fn error %d\n", n);
return n;
}
if (n != ANSWER_0x68_SIZE) {
info(ctx,"short read %d!=%d\n", ANSWER_0x68_SIZE, n);
return -EIO;
}
n = check_header_response(msg, token, 0x68);
if ( n < 0 ) {
info(ctx,"Invalid response (header)\n");
return n;
}
/* check if the node adress was echoed properly */
if (node_adr != uint64_from_msg(&msg[ANSWER_0x68_NODEADR64_B0])) return -EPROTO;
/* update node information */
lightify_node_set_online_status(node,msg[ANSWER_0x68_ONLINESTATE]);
lightify_node_set_onoff(node,msg[ANSWER_0x68_ONOFF] != 0 );
lightify_node_set_brightness(node,msg[ANSWER_0x68_DIM_LEVEL]);
n = msg[ANSWER_0x68_CCT_LSB] | msg[ANSWER_0x68_CCT_MSB] << 8;
lightify_node_set_cct(node,n);
lightify_node_set_red(node,msg[ANSWER_0x68_R]);
lightify_node_set_green(node,msg[ANSWER_0x68_G]);
lightify_node_set_blue(node,msg[ANSWER_0x68_B]);
lightify_node_set_white(node,msg[ANSWER_0x68_W]);
n = -decode_status(msg[ANSWER_0x68_STATE]);
lightify_node_set_stale(node, (n!=0));
return n;
}
LIGHTIFY_EXPORT int lightify_group_request_scan(struct lightify_ctx *ctx) {
int n,m;
int no_of_grps;
long token;
int ret;
if (!ctx) return -EINVAL;
/* if using standard I/O functions, fd must be valid. If the user overrode those function,
we won't care */
if (ctx->socket_read_fn == read_from_socket &&
ctx->socket_write_fn == write_to_socket && ctx->socket < 0) {
return -EBADF;
}
/* remove old group information */
free_all_groups(ctx);
token = ++ctx->cnt;
/* to avoid problems with packing, we need to use a char array.
* to assist we'll have this fine enum */
uint8_t msg[ANSWER_0x1e_GRP_LENGHT];
/* 0x1e command to get all groups. */
fill_telegram_header(msg, QUERY_0x1e_SIZE, token, 0x00, 0x1e);
n = ctx->socket_write_fn(ctx, msg, QUERY_0x1e_SIZE);
if ( n < 0 ) {
info(ctx,"socket_write_fn error %d\n", n);
return n;
}
if ( n != QUERY_0x1e_SIZE) {
info(ctx,"short write %d!=%d\n", QUERY_0x1e_SIZE, n);
return -EIO;
}
/* read the header */
n = ctx->socket_read_fn(ctx, msg, ANSWER_0x1e_SIZE);
if (n < 0) {
info(ctx,"socket_read_fn error %d\n", n);
return n;
}
if (n != ANSWER_0x1e_SIZE) {
info(ctx,"short read %d!=%d\n", ANSWER_0x1e_SIZE, n);
return -EIO;
}
/* check the header if plausible */
/* check if the token we've supplied is also the returned one. */
n = check_header_response(msg, token, 0x1e);
if ( n < 0 ) {
info(ctx,"Invalid response (header)\n");
return n;
}
/* check if the message length is as expected */
no_of_grps = msg[ANSWER_0x1e_NUMGROUPS];
m = msg[HEADER_LEN_LSB] | (msg[HEADER_LEN_MSB] << 8);
info(ctx, "0x1e: received %d bytes\n",m);
if ( no_of_grps * ANSWER_0x1e_GRP_LENGHT + ANSWER_0x1e_SIZE - 2 != m) {
info(ctx, "Reponse len unexpected for %d groups: %d!=%d.\n", no_of_grps,
no_of_grps * ANSWER_0x1e_GRP_LENGHT + ANSWER_0x1e_SIZE - 2, m);
return -EPROTO;
}
if (msg[HEADER_PAYLOAD_START]) {
info(ctx, "strange byte at PAYLOAD_START: %d\n", msg[HEADER_PAYLOAD_START]);
}
ret = 0;
/* read each node..*/
while(no_of_grps--) {
struct lightify_group *group = NULL;
n = ctx->socket_read_fn(ctx, msg, ANSWER_0x1e_GRP_LENGHT);
if (n< 0) return n;
if (ANSWER_0x1e_GRP_LENGHT != n ) {
info(ctx,"read group info: short read %d!=%d\n", ANSWER_0x1e_GRP_LENGHT, n);
return -EIO;
}
n = lightify_group_new(ctx,&group);
if (n < 0) {
info(ctx, "create group error %d", n);
return n;
}
lightify_group_set_id(group, msg[ANSWER_0x1e_GRP_ID]);
lightify_group_set_name(group, &msg[ANSWER_0x1e_GRP_NAME]);
ret++;
}
return ret;
}
/* Group control */
LIGHTIFY_EXPORT int lightify_group_request_onoff(struct lightify_ctx *ctx, struct lightify_group *group, int onoff) {
if (!ctx || !group) return -EINVAL;
onoff = (onoff != 0);
int ret = lightify_request_set_onoff(ctx, lightify_group_get_id(group), 1, onoff);
struct lightify_node *node = NULL;
while ( (node = lightify_group_get_next_node(group,node))) {
lightify_node_set_onoff(node, onoff);
if (ret < 0 ) lightify_node_set_stale(node, 1);
}
return ret;
}
LIGHTIFY_EXPORT int lightify_group_request_cct(struct lightify_ctx *ctx, struct lightify_group *group, unsigned int cct, unsigned int fadetime) {
if (!ctx || !group) return -EINVAL;
int ret = lightify_request_set_cct(ctx, lightify_group_get_id(group), 1, cct, fadetime);
struct lightify_node *node = NULL;
while ( (node = lightify_group_get_next_node(group,node))) {
lightify_node_set_cct(node, cct);
if (ret < 0 ) lightify_node_set_stale(node, 1);
}
return ret;
}
LIGHTIFY_EXPORT int lightify_group_request_rgbw(struct lightify_ctx *ctx,
struct lightify_group *group, unsigned int r, unsigned int g,
unsigned int b,unsigned int w,unsigned int fadetime) {
if (!ctx || !group) return -EINVAL;
int ret = lightify_request_set_rgbw(ctx, lightify_group_get_id(group), 1, r, g, b, w , fadetime);
struct lightify_node *node = NULL;
while ( (node = lightify_group_get_next_node(group,node))) {
lightify_node_set_red(node, r);
lightify_node_set_green(node, g);
lightify_node_set_blue(node, b);
lightify_node_set_white(node, w);
if (ret < 0 ) lightify_node_set_stale(node, 1);
}
return ret;
}
LIGHTIFY_EXPORT int lightify_group_request_brightness(struct lightify_ctx *ctx,
struct lightify_group *group, unsigned int level, unsigned int fadetime) {
if (!ctx || !group) return -EINVAL;
int ret = lightify_request_set_brightness(ctx, lightify_group_get_id(group), 1, level , fadetime);
struct lightify_node *node = NULL;
while ( (node = lightify_group_get_next_node(group,node))) {
lightify_node_set_brightness(node, level);
lightify_node_set_onoff(node, level!=0);
if (ret < 0 ) lightify_node_set_stale(node, 1);
}
return ret;
}
ANSWER_0x13_UNKNOWN2
Definition: context.c:78
lightify_node_new
int lightify_node_new(struct lightify_ctx *ctx, struct lightify_node **newnode)
Definition: node.c:80
ANSWER_0x33_NODEADR64_B6
Definition: context.c:183
QUERY_0x33_CCT_LSB
Definition: context.c:166
ANSWER_0x13_NODE_ADR64_B0
Definition: context.c:69
lightify_node_request_rgbw
LIGHTIFY_EXPORT int lightify_node_request_rgbw(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int r, unsigned int g, unsigned int b, unsigned int w, unsigned int fadetime)
Definition: context.c:889
ANSWER_0x32_NODEADR64_B0
Definition: context.c:145
ANSWER_0x33_NODEADR64_B2
Definition: context.c:179
ANSWER_0x13_UNKNOWN4
Definition: context.c:80
ANSWER_0x32_NODEADR64_B4
Definition: context.c:149
HEADER_REQ_ID_B1
Definition: context.c:48
msg_0x36_answer
msg_0x36_answer
Definition: context.c:208
ANSWER_0x1e_STATE
Definition: context.c:267
QUERY_0x31_FADETIME_LSB
Definition: context.c:107
ANSWER_0x1e_GRP_ID
Definition: context.c:274
ANSWER_0x13_NODE_ADR16_MSB
Definition: context.c:68
ANSWER_0x36_NODEADR64_B5
Definition: context.c:217
HEADER_LEN_MSB
Definition: context.c:44
QUERY_0x68_NODEADR64_B6
Definition: context.c:231
QUERY_0x32_NODEADR64_B3
Definition: context.c:132
QUERY_0x36_NODEADR64_B3
Definition: context.c:194
ANSWER_0x13_UNKNOWN1
Definition: context.c:60
ANSWER_0x31_NODEADR64_B7
Definition: context.c:123
ANSWER_0x13_NODESCNT_LSB
Definition: context.c:61
node.h
QUERY_0x13_REQTYPE
Definition: context.c:55
context.h
lightify_free
LIGHTIFY_EXPORT int lightify_free(struct lightify_ctx *ctx)
Definition: context.c:475
HEADER_REQ_ID_B3
Definition: context.c:50
lightify_node_set_grpadr
int lightify_node_set_grpadr(struct lightify_node *node, uint16_t adr)
Definition: node.c:191
lightify_node_set_onoff
int lightify_node_set_onoff(struct lightify_node *node, uint8_t on)
Definition: node.c:280
ANSWER_0x13_NODE_ONLINE_STATE
Definition: context.c:82
ANSWER_0x36_NODEADR64_B7
Definition: context.c:219
ANSWER_0x13_NODE_DIM_LEVEL
Definition: context.c:86
ANSWER_0x13_NODE_ADR64_B4
Definition: context.c:73
lightify_node_request_scan
LIGHTIFY_EXPORT int lightify_node_request_scan(struct lightify_ctx *ctx)
Definition: context.c:486
info
#define info(ctx, arg...)
ANSWER_0x68_SIZE
Definition: context.c:258
msg_header
msg_header
Definition: context.c:42
read_from_socket_fn
int(* read_from_socket_fn)(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: liblightify.h:167
QUERY_0x68_NODEADR64_B5
Definition: context.c:230
ANSWER_0x13_NODE_ADR64_B5
Definition: context.c:74
lightify_node_get_name
const char * lightify_node_get_name(struct lightify_node *node)
Definition: node.c:164
ANSWER_0x13_NODE_NAME_START
Definition: context.c:93
QUERY_0x36_NODEADR64_B4
Definition: context.c:195
HEADER_REQ_ID_B2
Definition: context.c:49
QUERY_0x68_NODEADR64_B2
Definition: context.c:227
ANSWER_0x68_NODEADR64_B6
Definition: context.c:246
ANSWER_0x36_RESERVED_MSB
Definition: context.c:211
LIGHTIFY_UNKNOWNTYPE
Definition: liblightify.h:111
ANSWER_0x36_NODEADR64_B2
Definition: context.c:214
QUERY_0x33_CCT_MSB
Definition: context.c:167
lightify_group_request_onoff
LIGHTIFY_EXPORT int lightify_group_request_onoff(struct lightify_ctx *ctx, struct lightify_group *group, int onoff)
Definition: context.c:1073
ANSWER_0x31_NODEADR64_B4
Definition: context.c:120
ANSWER_0x68_NODEADR64_B5
Definition: context.c:245
QUERY_0x32_NODEADR64_B7
Definition: context.c:136
QUERY_0x36_NODEADR64_B0
Definition: context.c:191
lightify_node_request_onoff
LIGHTIFY_EXPORT int lightify_node_request_onoff(struct lightify_ctx *ctx, struct lightify_node *node, int onoff)
Definition: context.c:852
ANSWER_0x31_STATE
Definition: context.c:113
ANSWER_0x1e_GRP_UNKNOWN_ZERO
Definition: context.c:275
ANSWER_0x32_UNKNOWN1
Definition: context.c:153
lightify_node_remove
int lightify_node_remove(struct lightify_node *node)
Definition: node.c:117
ANSWER_0x13_NODE_ADR64_B3
Definition: context.c:72
msg_0x68_answer
msg_0x68_answer
Definition: context.c:236
lightify_set_log_priority
int lightify_set_log_priority(struct lightify_ctx *ctx, int priority)
Definition: log.c:105
ANSWER_0x68_R
Definition: context.c:254
lightify_group_request_scan
LIGHTIFY_EXPORT int lightify_group_request_scan(struct lightify_ctx *ctx)
Definition: context.c:977
QUERY_0x33_NODEADR64_B3
Definition: context.c:161
ANSWER_0x32_NODEADR64_B2
Definition: context.c:147
ANSWER_0x13_NODE_ADR64_B7
Definition: context.c:76
QUERY_0x32_NODEADR64_B6
Definition: context.c:135
write_to_socket
int write_to_socket(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: socket.c:47
lightify_ctx::socket_read_fn
int(* socket_read_fn)(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Function pointer to the I/O handling – read from.
Definition: context.h:69
lightify_ctx::nodes
struct lightify_node * nodes
Definition: context.h:85
ANSWER_0x32_NODEADR64_B7
Definition: context.c:152
lightify_node_set_brightness
int lightify_node_set_brightness(struct lightify_node *node, int brightness)
Definition: node.c:268
msg_0x1e_answer
msg_0x1e_answer
Definition: context.c:266
QUERY_0x36_G
Definition: context.c:200
ANSWER_0x33_RESERVED_LSB
Definition: context.c:175
ANSWER_0x68_NODEADR64_B4
Definition: context.c:244
lightify_node_get_nodeadr
uint64_t lightify_node_get_nodeadr(struct lightify_node *node)
Definition: node.c:175
lightify_node_get_prevnode
struct lightify_node * lightify_node_get_prevnode(struct lightify_node *node)
Definition: node.c:145
lightify_get_userdata
LIGHTIFY_EXPORT void * lightify_get_userdata(struct lightify_ctx *ctx)
Definition: context.c:400
ANSWER_0x31_NODEADR64_B3
Definition: context.c:119
ANSWER_0x13_NODE_ADR64_B6
Definition: context.c:75
lightify_ctx
Definition: context.h:63
QUERY_0x36_R
Definition: context.c:199
ANSWER_0x68_DIM_LEVEL
Definition: context.c:251
QUERY_0x31_FADETIME_MSB
Definition: context.c:108
lightify_group_request_cct
LIGHTIFY_EXPORT int lightify_group_request_cct(struct lightify_ctx *ctx, struct lightify_group *group, unsigned int cct, unsigned int fadetime)
Definition: context.c:1087
ANSWER_0x33_NODEADR64_B4
Definition: context.c:181
LIGHTIFY_DIMABLE_LIGHT
Definition: liblightify.h:107
lightify_group_get_id
LIGHTIFY_EXPORT int lightify_group_get_id(struct lightify_group *grp)
Definition: groups.c:128
fadetime
int fadetime
Definition: lightify-util.c:98
LIGHTIFY_COLOUR_LIGHT
Definition: liblightify.h:108
lightify_node_set_stale
int lightify_node_set_stale(struct lightify_node *node, int stale)
Definition: node.c:307
QUERY_0x68_SIZE
Definition: context.c:233
ANSWER_0x68_CCT_LSB
Definition: context.c:252
ANSWER_0x36_NODEADR64_B0
Definition: context.c:212
lightify_set_socket_fn
LIGHTIFY_EXPORT int lightify_set_socket_fn(struct lightify_ctx *ctx, write_to_socket_fn fpw, read_from_socket_fn fpr)
Definition: context.c:413
QUERY_0x36_NODEADR64_B5
Definition: context.c:196
QUERY_0x31_NODEADR64_B6
Definition: context.c:104
ANSWER_0x68_B
Definition: context.c:256
ANSWER_0x13_NODE_ADR16_LSB
Definition: context.c:67
ANSWER_0x68_UNKNOWN1
Definition: context.c:248
lightify_ctx::userdata
void * userdata
Function pointer to the I/O handling – write to.
Definition: context.h:77
msg_0x33_answer
msg_0x33_answer
Definition: context.c:173
QUERY_0x36_SIZE
Definition: context.c:205
QUERY_0x33_NODEADR64_B2
Definition: context.c:160
lightify_node_set_zoneadr
int lightify_node_set_zoneadr(struct lightify_node *node, uint16_t adr)
Definition: node.c:180
QUERY_0x31_NODEADR64_B7
Definition: context.c:105
ANSWER_0x13_NODE_ADR64_B2
Definition: context.c:71
HEADER_CMD
Definition: context.c:46
ANSWER_0x36_NODEADR64_B1
Definition: context.c:213
lightify_node_get_next
LIGHTIFY_EXPORT struct lightify_node * lightify_node_get_next(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:385
liblightify-private.h
dbg
#define dbg(ctx, arg...)
ANSWER_0x13_NODE_ONOFF_STATE
Definition: context.c:85
write_to_socket_fn
int(* write_to_socket_fn)(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: liblightify.h:149
lightify_node_set_lamptype
int lightify_node_set_lamptype(struct lightify_node *node, enum lightify_node_type type)
Definition: node.c:202
lightify_group
Definition: groups.c:46
lightify_node_set_cct
int lightify_node_set_cct(struct lightify_node *node, int cct)
Definition: node.c:257
lightify_ctx::iotimeout
struct timeval iotimeout
Definition: context.h:94
ANSWER_0x32_SIZE
Definition: context.c:154
lightify_ctx::socket_write_fn
int(* socket_write_fn)(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Function pointer to the I/O handling – read from.
Definition: context.h:72
LIGHTIFY_EXPORT
#define LIGHTIFY_EXPORT
ANSWER_0x31_UNKNOWN1
Definition: context.c:114
ANSWER_0x33_SIZE
Definition: context.c:186
lightify_group_request_brightness
LIGHTIFY_EXPORT int lightify_group_request_brightness(struct lightify_ctx *ctx, struct lightify_group *group, unsigned int level, unsigned int fadetime)
Definition: context.c:1118
QUERY_0x36_NODEADR64_B2
Definition: context.c:193
lightify_node_set_blue
int lightify_node_set_blue(struct lightify_node *node, int blue)
Definition: node.c:224
ANSWER_0x33_NODEADR64_B7
Definition: context.c:184
ANSWER_0x32_NODEADR64_B3
Definition: context.c:148
QUERY_0x33_NODEADR64_B7
Definition: context.c:165
msg_0x13_answer_node
msg_0x13_answer_node
Definition: context.c:66
ANSWER_0x1e_SIZE
Definition: context.c:270
ANSWER_0x13_NODESCNT_MSB
Definition: context.c:62
lightify_node_set_red
int lightify_node_set_red(struct lightify_node *node, int red)
Definition: node.c:213
ANSWER_0x68_NONODES_LSB
Definition: context.c:238
ANSWER_0x68_NODEADR64_B1
Definition: context.c:241
LIGHTIFY_CCT_LIGHT
Definition: liblightify.h:110
QUERY_0x33_FADETIME_LSB
Definition: context.c:168
QUERY_0x68_NODEADR64_B1
Definition: context.c:226
ANSWER_0x68_W
Definition: context.c:257
ANSWER_0x13_NODE_GRP_MEMBER_MSB
Definition: context.c:84
QUERY_0x31_NODEADR64_B0
Definition: context.c:98
QUERY_0x36_FADETIME_LSB
Definition: context.c:203
QUERY_0x36_FADETIME_MSB
Definition: context.c:204
ANSWER_0x31_NODEADR64_B2
Definition: context.c:118
ANSWER_0x13_NODE_CCT_LSB
Definition: context.c:87
ANSWER_0x33_NODEADR64_B5
Definition: context.c:182
ANSWER_0x32_NODEADR64_B1
Definition: context.c:146
ANSWER_0x1e_NUMGROUPS
Definition: context.c:268
QUERY_0x31_NODEADR64_B3
Definition: context.c:101
lightify_group_get_next_node
LIGHTIFY_EXPORT struct lightify_node * lightify_group_get_next_node(struct lightify_group *grp, struct lightify_node *lastnode)
Definition: groups.c:147
ANSWER_0x13_NODE_GRP_MEMBER_LSB
Definition: context.c:83
ANSWER_0x68_NODEADR64_B0
Definition: context.c:240
QUERY_0x68_NODEADR64_B7
Definition: context.c:232
ANSWER_0x31_NODEADR64_B0
Definition: context.c:116
ANSWER_0x13_NODE_W
Definition: context.c:92
QUERY_0x31_NODEADR64_B4
Definition: context.c:102
lightify_node_set_green
int lightify_node_set_green(struct lightify_node *node, int green)
Definition: node.c:235
lightify_node_set_online_status
int lightify_node_set_online_status(struct lightify_node *node, uint8_t state)
Definition: node.c:291
ANSWER_0x36_STATE
Definition: context.c:209
ANSWER_0x1e_HDR_UNKNOWN_ZERO
Definition: context.c:269
lightify_ctx::log_priority
int log_priority
Definition: context.h:79
ANSWER_0x13_NODE_G
Definition: context.c:90
ANSWER_0x32_RESERVED_LSB
Definition: context.c:143
ANSWER_0x13_NODE_LENGTH
Definition: context.c:94
ANSWER_0x13_UNKNOWN3
Definition: context.c:79
ANSWER_0x13_NODE_CCT_MSB
Definition: context.c:88
msg_0x33_query
msg_0x33_query
Definition: context.c:157
ANSWER_0x32_RESERVED_MSB
Definition: context.c:144
HEADER_FLAGS
Definition: context.c:45
ANSWER_0x13_UNKNOWN5
Definition: context.c:81
HEADER_REQ_ID_B0
Definition: context.c:47
QUERY_0x1e
Definition: context.c:262
ANSWER_0x68_STATE
Definition: context.c:237
QUERY_0x68_NODEADR64_B0
Definition: context.c:225
QUERY_0x36_NODEADR64_B6
Definition: context.c:197
lightify_node_request_brightness
LIGHTIFY_EXPORT int lightify_node_request_brightness(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int level, unsigned int fadetime)
Definition: context.c:905
QUERY_0x33_NODEADR64_B0
Definition: context.c:158
lightify_set_userdata
LIGHTIFY_EXPORT int lightify_set_userdata(struct lightify_ctx *ctx, void *userdata)
Definition: context.c:406
msg_0x13_answer
msg_0x13_answer
Definition: context.c:59
msg_0x32_query
msg_0x32_query
Definition: context.c:128
QUERY_0x32_ONOFF
Definition: context.c:137
groups.h
QUERY_0x31_LEVEL
Definition: context.c:106
ANSWER_0x36_SIZE
Definition: context.c:221
QUERY_0x68_NODEADR64_B3
Definition: context.c:228
ANSWER_0x33_NODEADR64_B0
Definition: context.c:177
QUERY_0x32_NODEADR64_B5
Definition: context.c:134
ANSWER_0x68_ONLINESTATE
Definition: context.c:249
HEADER_LEN_LSB
Definition: context.c:43
ANSWER_0x31_SIZE
Definition: context.c:125
lightify_node_get_previous
LIGHTIFY_EXPORT struct lightify_node * lightify_node_get_previous(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:393
LIGHTIFY_EXT_COLOUR_LIGHT
Definition: liblightify.h:109
QUERY_0x31_NODEADR64_B5
Definition: context.c:103
ANSWER_0x13_NODE_NODETYPE
Definition: context.c:77
ANSWER_0x33_STATE
Definition: context.c:174
QUERY_0x1e_SIZE
Definition: context.c:263
msg_0x31_query
msg_0x31_query
Definition: context.c:97
lightify_group_set_id
int lightify_group_set_id(struct lightify_group *grp, int id)
Definition: groups.c:122
lightify_ctx::log_fn
void(* log_fn)(struct lightify_ctx *ctx, int priority, const char *file, int line, const char *fn, const char *format, va_list args)
Definition: context.h:65
ANSWER_0x13_NODE_R
Definition: context.c:89
msg_0x36_query
msg_0x36_query
Definition: context.c:190
msg_0x68_query
msg_0x68_query
Definition: context.c:224
ANSWER_0x68_NONODES_MSB
Definition: context.c:239
QUERY_0x31_SIZE
Definition: context.c:109
QUERY_0x32_NODEADR64_B2
Definition: context.c:131
QUERY_0x68_NODEADR64_B4
Definition: context.c:229
lightify_new
LIGHTIFY_EXPORT int lightify_new(struct lightify_ctx **ctx, void *reserved)
Definition: context.c:428
lightify_node
Definition: node.c:43
read_from_socket
int read_from_socket(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: socket.c:123
msg_0x1e_answerpergroup
msg_0x1e_answerpergroup
Definition: context.c:273
lightify_node_set_nodeadr
int lightify_node_set_nodeadr(struct lightify_node *node, uint64_t adr)
Definition: node.c:169
msg_0x13_query
msg_0x13_query
Definition: context.c:54
ANSWER_0x13_NODE_ADR64_B1
Definition: context.c:70
ANSWER_0x36_UNKNOWN1
Definition: context.c:220
ANSWER_0x33_NODEADR64_B1
Definition: context.c:178
QUERY_0x33_NODEADR64_B6
Definition: context.c:164
lightify_group_new
int lightify_group_new(struct lightify_ctx *ctx, struct lightify_group **newgroup)
Definition: groups.c:60
lightify_node_get_nextnode
struct lightify_node * lightify_node_get_nextnode(struct lightify_node *node)
Definition: node.c:140
ANSWER_0x32_STATE
Definition: context.c:142
lightify_node_get_from_mac
LIGHTIFY_EXPORT struct lightify_node * lightify_node_get_from_mac(struct lightify_ctx *ctx, uint64_t mac)
Definition: context.c:297
msg_0x32_answer
msg_0x32_answer
Definition: context.c:141
ANSWER_0x13_SIZE
Definition: context.c:63
ANSWER_0x1e_GRP_LENGHT
Definition: context.c:277
ANSWER_0x68_NODEADR64_B2
Definition: context.c:242
QUERY_0x31_NODEADR64_B2
Definition: context.c:100
QUERY_0x33_FADETIME_MSB
Definition: context.c:169
ANSWER_0x68_ONOFF
Definition: context.c:250
log_priority
int log_priority(const char *priority)
Definition: log.c:62
lightify_node_request_update
LIGHTIFY_EXPORT int lightify_node_request_update(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:919
ANSWER_0x31_NODEADR64_B1
Definition: context.c:117
lightify_group_remove
int lightify_group_remove(struct lightify_group *grp)
Definition: groups.c:84
QUERY_0x33_NODEADR64_B5
Definition: context.c:163
ANSWER_0x68_G
Definition: context.c:255
ANSWER_0x33_NODEADR64_B3
Definition: context.c:180
ANSWER_0x33_RESERVED_MSB
Definition: context.c:176
QUERY_0x36_NODEADR64_B1
Definition: context.c:192
ANSWER_0x31_NODEADR64_B6
Definition: context.c:122
QUERY_0x32_NODEADR64_B1
Definition: context.c:130
ANSWER_0x68_NODEADR64_B7
Definition: context.c:247
QUERY_0x36_B
Definition: context.c:201
ANSWER_0x68_NODEADR64_B3
Definition: context.c:243
QUERY_0x32_NODEADR64_B4
Definition: context.c:133
ANSWER_0x36_NODEADR64_B6
Definition: context.c:218
ANSWER_0x31_UNKNOWN2
Definition: context.c:115
ANSWER_0x68_CCT_MSB
Definition: context.c:253
lightify_node_request_cct
LIGHTIFY_EXPORT int lightify_node_request_cct(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int cct, unsigned int fadetime)
Definition: context.c:877
LIGHTIFY_ONOFF_PLUG
Definition: liblightify.h:106
ANSWER_0x33_UNKNOWN1
Definition: context.c:185
msg_0x1e_query
msg_0x1e_query
Definition: context.c:261
QUERY_0x36_W
Definition: context.c:202
lightify_ctx::cnt
long cnt
Definition: context.h:91
QUERY_0x32_SIZE
Definition: context.c:138
log.h
ANSWER_0x36_NODEADR64_B4
Definition: context.c:216
QUERY_0x33_NODEADR64_B1
Definition: context.c:159
socket.h
QUERY_0x33_SIZE
Definition: context.c:170
log_stderr
void log_stderr(struct lightify_ctx *ctx, int priority, const char *file, int line, const char *fn, const char *format, va_list args)
Definition: log.c:54
lightify_node::ctx
struct lightify_ctx * ctx
Definition: node.c:46
msg_0x31_answer
msg_0x31_answer
Definition: context.c:112
lightify_group_request_rgbw
LIGHTIFY_EXPORT int lightify_group_request_rgbw(struct lightify_ctx *ctx, struct lightify_group *group, unsigned int r, unsigned int g, unsigned int b, unsigned int w, unsigned int fadetime)
Definition: context.c:1100
ANSWER_0x36_RESERVED_LSB
Definition: context.c:210
lightify_node_set_white
int lightify_node_set_white(struct lightify_node *node, int white)
Definition: node.c:246
ANSWER_0x32_NODEADR64_B6
Definition: context.c:151
lightify_node_set_name
int lightify_node_set_name(struct lightify_node *node, char *name)
Definition: node.c:151
ANSWER_0x32_NODEADR64_B5
Definition: context.c:150
lightify_group_set_name
int lightify_group_set_name(struct lightify_group *grp, const unsigned char *name)
Definition: groups.c:104
HEADER_PAYLOAD_START
Definition: context.c:51
QUERY_0x31_NODEADR64_B1
Definition: context.c:99
QUERY_0x13_SIZE
Definition: context.c:56
lightify_node::cct
int cct
Definition: node.c:67
ANSWER_0x13_NODE_B
Definition: context.c:91
QUERY_0x36_NODEADR64_B7
Definition: context.c:198
ANSWER_0x1e_GRP_NAME
Definition: context.c:276
QUERY_0x33_NODEADR64_B4
Definition: context.c:162
QUERY_0x32_NODEADR64_B0
Definition: context.c:129
ANSWER_0x31_NODEADR64_B5
Definition: context.c:121
lightify_ctx::groups
struct lightify_group * groups
Definition: context.h:88
ANSWER_0x31_UNKNOWN3
Definition: context.c:124
ANSWER_0x36_NODEADR64_B3
Definition: context.c:215
lightify_ctx::socket
int socket
Definition: context.h:82