liblightify
context.c
Go to the documentation of this file.
1 /*
2  liblightify -- library to control OSRAM's LIGHTIFY
3 
4 Copyright (c) 2015, Tobias Frost <tobi@coldtobi.de>
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11  * Redistributions in binary form must reproduce the above copyright
12  notice, this list of conditions and the following disclaimer in the
13  documentation and/or other materials provided with the distribution.
14  * Neither the name of the author nor the
15  names of its contributors may be used to endorse or promote products
16  derived from this software without specific prior written permission.
17 
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29 
30 #include "liblightify-private.h"
31 #include "context.h"
32 #include "log.h"
33 #include "node.h"
34 #include "groups.h"
35 
36 #include "socket.h"
37 
38 #include <errno.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 
42 /* For KFreeBSD, which has no ENODATA .. map it to EIO */
43 #ifndef ENODATA
44 #define ENODATA EIO
45 #endif
46 
47 
48 enum msg_header {
58 };
59 
63 };
64 
70 };
71 
109 };
110 
124 };
125 
140 };
141 
153 };
154 
169 };
170 
185 };
186 
201 };
202 
203 
220 };
221 
236 };
237 
248 };
249 
276 };
277 
281 };
282 
288 };
289 
295 };
296 
297 
298 // 0 seems success, non-zero error.
299 static int decode_status(unsigned char code) {
300  switch (code) {
301  // success
302  case 0x00: return 0;
303  case 0x15: return ENODEV;
304  default: return EIO;
305  }
306 }
307 
315  if (!ctx) return NULL;
316 
317  struct lightify_node *ret = ctx->nodes;
318  while(ret) {
319  if (lightify_node_get_nodeadr(ret) == mac) return ret;
320  ret = lightify_node_get_nextnode(ret);
321  }
322  return NULL;
323 }
324 
330 static uint64_t uint64_from_msg(uint8_t *msg) {
331  uint64_t tmp;
332  tmp = msg[7]; tmp <<=8;
333  tmp |= msg[6]; tmp <<=8;
334  tmp |= msg[5]; tmp <<=8;
335  tmp |= msg[4]; tmp <<=8;
336  tmp |= msg[3]; tmp <<=8;
337  tmp |= msg[2]; tmp <<=8;
338  tmp |= msg[1]; tmp <<=8;
339  tmp |= msg[0];
340  return tmp;
341 }
342 
343 static void msg_from_uint64(unsigned char *pmsg, uint64_t mac) {
344  *pmsg++ = mac & 0xff;
345  *pmsg++ = mac >> 8 & 0xff;
346  *pmsg++ = mac >> 16 & 0xff;
347  *pmsg++ = mac >> 24 & 0xff;
348  *pmsg++ = mac >> 32 & 0xff;
349  *pmsg++ = mac >> 40 & 0xff;
350  *pmsg++ = mac >> 48 & 0xff;
351  *pmsg++ = mac >> 56 & 0xff;
352 }
353 
359 static uint16_t uint16_from_msg(uint8_t *msg) {
360  uint16_t tmp;
361  tmp = msg[0] | (msg[1]<<8);
362  return tmp;
363 }
364 
365 
375 static void fill_telegram_header(unsigned char *msg, unsigned int len, uint32_t token, unsigned char flags, unsigned char command)
376 {
377  len-=2;
378  msg[HEADER_LEN_LSB] = len & 0xff;
379  msg[HEADER_LEN_MSB] = len >> 8;
380  msg[HEADER_FLAGS] = flags;
381  msg[HEADER_CMD] = command;
382  msg[HEADER_REQ_ID_B0] = token & 0xff;
383  msg[HEADER_REQ_ID_B1] = token >> 8 & 0xff;
384  msg[HEADER_REQ_ID_B2] = token >> 16 & 0xff;
385  msg[HEADER_REQ_ID_B3] = token >> 24 & 0xff;
386 }
387 
388 
389 static int check_header_response(unsigned char *msg, uint32_t token,
390  unsigned char cmd) {
391 
392  uint32_t token2;
393  /* check the header if plausible */
394  /* check if the token we've supplied is also the returned one. */
395  token2 = msg[HEADER_REQ_ID_B0] | (msg[HEADER_REQ_ID_B1] << 8U) |
396  (msg[HEADER_REQ_ID_B1] << 16U) | (msg[HEADER_REQ_ID_B1] << 24U);
397  if (token != token2) return -EPROTO;
398  if (msg[HEADER_CMD] != cmd) return -EPROTO;
399  return 0;
400 }
401 
403  struct lightify_node *node ) {
404 
405  if(!ctx) return NULL;
406  if(node) return lightify_node_get_nextnode(node);
407  return ctx->nodes;
408 }
409 
411  struct lightify_node *node )
412 {
413  if(!ctx) return NULL;
414  return lightify_node_get_prevnode(node);
415 }
416 
418 {
419  if (!ctx) return NULL;
420  return ctx->userdata;
421 }
422 
424 {
425  if (!ctx) return -EINVAL;
426  ctx->userdata = userdata;
427  return 0;
428 }
429 
432 
433  if (!ctx) return -EINVAL;
434  if (!fpw || !fpr) {;
437  return 0;
438  }
439 
440  ctx->socket_read_fn = fpr;
441  ctx->socket_write_fn = fpw;
442  return 0;
443 }
444 
445 LIGHTIFY_EXPORT int lightify_new(struct lightify_ctx **ctx, void *reserved)
446 {
447  struct lightify_ctx *c;
448 
449  c = calloc(1, sizeof(struct lightify_ctx));
450  if (!c) return -ENOMEM;
451 
452  c->log_fn = log_stderr;
453  c->log_priority = LOG_ERR;
454 
455 #ifdef HAVE_SECURE_GETENV
456  /* environment overwrites config */
457  const char *env;
458  env = secure_getenv("lightify_LOG");
459  if (env != NULL)
461 #endif
462 
463  info(c, "ctx %p created\n", c);
464  dbg(c, "log_priority=%d\n", c->log_priority);
465  *ctx = c;
466 
467  c->socket = -1;
468  c->iotimeout.tv_sec=1;
469 
472 
473  c->gw_protocol_version = -1;
474 
475  return 0;
476 }
477 
478 static void free_all_nodes(struct lightify_ctx *ctx) {
479  if (!ctx) return;
480  while(ctx->nodes) {
481  dbg(ctx, "freeing node %p.\n", ctx->nodes);
483  }
484 }
485 
486 static void free_all_groups(struct lightify_ctx *ctx) {
487  if (!ctx) return;
488  while(ctx->groups) {
489  dbg(ctx, "freeing group %p.\n", ctx->groups);
491  }
492 }
493 
495  if (!ctx) return -EINVAL;
496 
497  free_all_nodes(ctx);
498  free_all_groups(ctx);
499 
500  dbg(ctx, "context %p freed.\n", ctx);
501  free(ctx);
502  return 0;
503 }
504 
506  int ret;
507  int n,m;
508  int no_of_nodes;
509  int read_size = 0;
510  uint32_t token;
511 
512  if (!ctx) return -EINVAL;
513 
514  /* if using standard I/O functions, fd must be valid. If the user overrode those function,
515  we won't care */
516  if (ctx->socket_read_fn == read_from_socket
517  && ctx->socket_write_fn == write_to_socket && ctx->socket < 0) {
518  return -EBADF;
519  }
520 
521  /* remove old node information */
522  free_all_nodes(ctx);
523 
524  token = ++ctx->cnt;
525 
526  /* to avoid problems with packing, we need to use a char array.
527  * to assist we'll have this fine enum */
528  uint8_t msg[ANSWER_0x13_NODE_LENGTH+2];
529 
530  /* 0x13 command to get all node's informations. */
531  fill_telegram_header(msg, QUERY_0x13_SIZE, token, 0x00, 0x13);
532  msg[QUERY_0x13_REQTYPE] = 0x01;
533 
534  n = ctx->socket_write_fn(ctx, msg, QUERY_0x13_SIZE);
535  if ( n < 0 ) {
536  info(ctx,"socket_write_fn error %d\n", n);
537  return n;
538  }
539  if ( n != QUERY_0x13_SIZE) {
540  info(ctx,"short write %d!=%d\n", QUERY_0x13_SIZE, n);
541  return -EIO;
542  }
543 
544  /* read the header */
545  n = ctx->socket_read_fn(ctx, msg, ANSWER_0x13_SIZE);
546  if (n < 0) {
547  info(ctx,"socket_read_fn error %d\n", n);
548  return n;
549  }
550  if (n != ANSWER_0x13_SIZE) {
551  info(ctx,"short read %d!=%d\n", ANSWER_0x13_SIZE, n);
552  return -EIO;
553  }
554 
555  /* check the header if plausible */
556  /* check if the token we've supplied is also the returned one. */
557  n = check_header_response(msg, token, 0x13);
558  if ( n < 0 ) {
559  info(ctx,"Invalid response (header)\n");
560  return n;
561  }
562 
563  /* check if the message length is as expected */
564  no_of_nodes = msg[ANSWER_0x13_NODESCNT_LSB] | (msg[ANSWER_0x13_NODESCNT_MSB] <<8);
565 
566  if (!no_of_nodes) return 0;
567 
568  m = msg[HEADER_LEN_LSB] | (msg[HEADER_LEN_MSB] << 8);
569  /*info(ctx, "0x13: received %d bytes\n",m);*/
570 
571  m -= ANSWER_0x13_SIZE - 2 ;
572  if (m == ANSWER_0x13_NODE_LENGTH * no_of_nodes) {
574  read_size = ANSWER_0x13_NODE_LENGTH;
575  dbg(ctx, "0x13: Dec-15 GW protocol\n");
576 
577  } else if (m == ANSWER_0x13_UNKNOWN6 * no_of_nodes ){
579  read_size = ANSWER_0x13_UNKNOWN6;
580  dbg(ctx, "0x13: Old GW protocol\n");
581  } else {
582  info(ctx, "Response len unexpected for %d nodes: %d.\n", no_of_nodes, m);
583  return -EPROTO;
584  }
585 
586  if (msg[HEADER_PAYLOAD_START]) {
587  info(ctx, "strange byte at PAYLOAD_START: %d\n", msg[HEADER_PAYLOAD_START]);
588  }
589 
590  ret = 0;
591  /* read each node..*/
592  while(no_of_nodes--) {
593  uint64_t tmp64;
594  struct lightify_node *node = NULL;
595  n = ctx->socket_read_fn(ctx, msg, read_size);
596  if (n< 0) return n;
597  if (read_size != n ) {
598  info(ctx,"read node info: short read %d!=%d\n", read_size, n);
599  return -EIO;
600  }
601 
602  n = lightify_node_new(ctx, &node);
603  if (n < 0) {
604  info(ctx, "create node error %d", n);
605  return n;
606  }
607  tmp64 = uint64_from_msg(&msg[ANSWER_0x13_NODE_ADR64_B0]);
608  lightify_node_set_nodeadr(node, tmp64);
609 
610  lightify_node_set_zoneadr(node, uint16_from_msg(&msg[ANSWER_0x13_NODE_ADR16_LSB]));
611  lightify_node_set_grpadr(node, uint16_from_msg(&msg[ANSWER_0x13_NODE_GRP_MEMBER_LSB]));
612 
614  info(ctx, "new node: %s\n", lightify_node_get_name(node));
615 
616  n = msg[ANSWER_0x13_NODE_NODETYPE];
617 
619  switch (n) {
620  case 0x00 : /* Plug */
622  break;
623  case 0x02 : /* CCT light */
625  break;
626  case 0x04 : /* dimable */
628  break;
629  case 0x08 : /* RGB */
631  break;
632  case 0x0a : /* CCT, RGB */
634  break;
635  default: /* maybe the missing dimmer plug or on/off light. */
637  dbg(ctx, "unknown type %x for lamp %s. PLEASE REPORT A BUG AGAINST liblightify.\n",n, lightify_node_get_name(node));
638  break;
639  }
640  } else {
641  /* new gateway firmware (Dec 2015) returns different values.
642  * remap to avoid API Bump. */
643  switch (n) {
644  case 0x10 : // Plug
646  break;
647  case 0x00 : // CCT light
648  case 0x02 : // reported by user as CCT light as well.
650  break;
651  case 0x04 : // dimable
653  break;
654  case 0x08 : // RGB
656  break;
657  case 0x0a : // CCT, RGB
659  break;
660  case 0x41: /* 4-Way-Switch */
662  break;
663  default: // maybe the missing dimmer plug or on/off light.
665  dbg(ctx, "unknown type %x for lamp %s. PLEASE REPORT A BUG AGAINST liblightify.\n",n, lightify_node_get_name(node));
666  break;
667  }
668  }
669 
670  dbg(ctx, "xtra-data: %x -- %x %x %x %x\n", msg[ANSWER_0x13_UNKNOWN1],
673 
675  dbg(ctx, "xtra-data-new-prot: %x %x %x %x %x %x %x %x\n", msg[ANSWER_0x13_UNKNOWN6],
679  msg[ANSWER_0x13_UNKNOWN13]);
680  }
681 
686  lightify_node_set_cct(node, uint16_from_msg(&msg[ANSWER_0x13_NODE_CCT_LSB]));
690  lightify_node_set_stale(node, 0);
691  ret++;
692  }
693  return ret;
694 }
695 
696 static int lightify_request_set_onoff(struct lightify_ctx *ctx, uint64_t adr, int isgroup, int onoff) {
697  unsigned char msg[32];
698  int n;
699  if (!ctx) return -EINVAL;
700 
701  /* normalize to boolean -- int are 16bits...*/
702  onoff = (onoff != 0);
703  isgroup = (isgroup) ? 2 : 0;
704 
705  uint32_t token = ++ctx->cnt;
706  fill_telegram_header(msg, QUERY_0x32_SIZE, token, isgroup, 0x32);
707 
708  msg_from_uint64(&msg[QUERY_0x32_NODEADR64_B0], adr);
709  msg[QUERY_0x32_ONOFF] = onoff;
710 
712  if ( n < 0 ) {
713  info(ctx,"socket_write_fn error %d\n", n);
714  return n;
715  }
716  if ( n != QUERY_0x32_SIZE) {
717  info(ctx,"short write %d!=%d\n", QUERY_0x32_SIZE, n);
718  return -EIO;
719  }
720 
721  /* read the header */
723  if (n < 0) {
724  info(ctx,"socket_read_fn error %d\n", n);
725  return n;
726  }
727  if (n != ANSWER_0x32_SIZE) {
728  info(ctx,"short read %d!=%d\n", ANSWER_0x32_SIZE, n);
729  int i = 0;
730  while(n--) {
731  info(ctx, " %d => %x\n ",i, msg[i]);
732  i++;
733  }
734  info(ctx, "\n");
735  return -EIO;
736  }
737 
738  /* check the header if plausible */
739  n = check_header_response(msg, token, 0x32);
740  if ( n < 0 ) {
741  info(ctx,"Invalid response (header)\n");
742  return n;
743  }
744 
745  /* check if the node address was echoed properly */
746  uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x32_NODEADR64_B0]);
747  if (adr != adr2) {
748  info(ctx, "unexpected node mac / group adr %llx!=%llx", adr, adr2 );
749  return -EPROTO;
750  }
751 
752  n = -decode_status(msg[ANSWER_0x32_STATE]);
753  if (n) {
754  info(ctx, "state %d indicates error.\n", n);
755  }
756  return n;
757 }
758 
759 static int lightify_request_set_cct(struct lightify_ctx *ctx, uint64_t adr, int isgroup, unsigned int cct, unsigned int fadetime) {
760  unsigned char msg[32];
761  int n;
762  if (!ctx) return -EINVAL;
763 
764  uint32_t token = ++ctx->cnt;
765  isgroup = (isgroup) ? 2 : 0;
766  fill_telegram_header(msg, QUERY_0x33_SIZE, token, isgroup, 0x33);
767  msg_from_uint64(&msg[QUERY_0x33_NODEADR64_B0], adr);
768  msg[QUERY_0x33_CCT_LSB] = cct & 0xff;
769  msg[QUERY_0x33_CCT_MSB] = (cct >> 8 ) & 0xff;
770  msg[QUERY_0x33_FADETIME_LSB] = fadetime & 0xff;
771  msg[QUERY_0x33_FADETIME_MSB] = (fadetime >> 8 ) & 0xff;
772 
774  if ( n < 0 ) {
775  info(ctx,"socket_write_fn error %d\n", n);
776  return n;
777  }
778  if ( n != QUERY_0x33_SIZE) {
779  info(ctx,"short write %d!=%d\n", QUERY_0x33_SIZE, n);
780  return -EIO;
781  }
782 
783  /* read the header */
785  if (n < 0) {
786  info(ctx,"socket_read_fn error %d\n", n);
787  return n;
788  }
789  if (n != ANSWER_0x33_SIZE) {
790  info(ctx,"short read %d!=%d\n", ANSWER_0x33_SIZE, n);
791  return -EIO;
792  }
793 
794  /* check the header if plausible */
795  n = check_header_response(msg, token, 0x33);
796  if ( n < 0 ) {
797  info(ctx,"Invalid response (header)\n");
798  return n;
799  }
800 
801  /* check if the node address was echoed properly */
802  uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x33_NODEADR64_B0]);
803  if (adr != adr2) {
804  info(ctx, "unexpected node mac / group adr %llx!=%llx", adr, adr2 );
805  return -EPROTO;
806  }
807 
808  n = -decode_status(msg[ANSWER_0x33_STATE]);
809  return n;
810 }
811 
812 static int lightify_request_set_rgbw(struct lightify_ctx *ctx, uint64_t adr,
813  int isgroup, unsigned int r, unsigned int g,
814  unsigned int b,unsigned int w,unsigned int fadetime) {
815  unsigned char msg[32];
816  int n;
817  if (!ctx) return -EINVAL;
818  /* does not support broadcast. */
819 
820  uint32_t token = ++ctx->cnt;
821  isgroup = (isgroup) ? 2 : 0;
822  fill_telegram_header(msg, QUERY_0x36_SIZE, token, isgroup, 0x36);
823  msg_from_uint64(&msg[QUERY_0x36_NODEADR64_B0], adr);
824  msg[QUERY_0x36_R] = r & 0xff;
825  msg[QUERY_0x36_G] = g & 0xff;
826  msg[QUERY_0x36_B] = b & 0xff;
827  msg[QUERY_0x36_W] = w & 0xff;
828  msg[QUERY_0x36_FADETIME_LSB] = fadetime & 0xff;
829  msg[QUERY_0x36_FADETIME_MSB] = (fadetime >> 8 ) & 0xff;
830 
832  if ( n < 0 ) {
833  info(ctx,"socket_write_fn error %d\n", n);
834  return n;
835  }
836  if ( n != QUERY_0x36_SIZE) {
837  info(ctx,"short write %d!=%d\n", QUERY_0x36_SIZE, n);
838  return -EIO;
839  }
840 
841  /* read the header */
843  if (n != ANSWER_0x36_SIZE) {
844  info(ctx,"short read %d!=%d\n", ANSWER_0x36_SIZE, n);
845  return -EIO;
846  }
847 
848  /* check the header if plausible */
849  n = check_header_response(msg, token, 0x36);
850  if ( n < 0 ) {
851  info(ctx,"Invalid response (header)\n");
852  return n;
853  }
854 
855  /* check if the node address was echoed properly */
856  uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x33_NODEADR64_B0]);
857  if (adr != adr2) {
858  info(ctx, "unexpected node mac / group adr %llx!=%llx", adr, adr2 );
859  return -EPROTO;
860  }
861 
862  n = -decode_status(msg[ANSWER_0x36_STATE]);
863  return n;
864 }
865 
866 static int lightify_request_set_brightness(struct lightify_ctx *ctx, uint64_t adr,
867  int isgroup, unsigned int level, unsigned int fadetime) {
868  unsigned char msg[32];
869  int n;
870  if (!ctx) return -EINVAL;
871 
872  uint32_t token = ++ctx->cnt;
873  isgroup = (isgroup) ? 2 : 0;
874 
875  fill_telegram_header(msg, QUERY_0x31_SIZE, token, isgroup, 0x31);
876  msg_from_uint64(&msg[QUERY_0x31_NODEADR64_B0], adr);
877 
878  msg[QUERY_0x31_LEVEL] = level & 0xff;
879  msg[QUERY_0x31_FADETIME_LSB] = fadetime & 0xff;
880  msg[QUERY_0x31_FADETIME_MSB] = (fadetime >> 8 ) & 0xff;
881 
883  if ( n < 0 ) {
884  info(ctx,"socket_write_fn error %d\n", n);
885  return n;
886  }
887  if ( n != QUERY_0x31_SIZE) {
888  info(ctx,"short write %d!=%d\n", QUERY_0x31_SIZE, n);
889  return -EIO;
890  }
891 
892  /* read the header */
894  if (n < 0) {
895  info(ctx,"socket_read_fn error %d\n", n);
896  return n;
897  }
898  if (n != ANSWER_0x31_SIZE) {
899  info(ctx,"short read %d!=%d\n", ANSWER_0x31_SIZE, n);
900  return -EIO;
901  }
902 
903  n = check_header_response(msg, token, 0x31);
904  if ( n < 0 ) {
905  info(ctx,"Invalid response (header)\n");
906  return n;
907  }
908 
909  /* check if the node address was echoed properly */
910  uint64_t adr2 = uint64_from_msg(&msg[ANSWER_0x33_NODEADR64_B0]);
911  if (adr != adr2) {
912  info(ctx, "unexpected node mac / group adr %llx!=%llx", adr, adr2 );
913  return -EPROTO;
914  }
915 
916  n = -decode_status(msg[ANSWER_0x31_STATE]);
917  dbg(ctx, "unknown-bytes: %x %x %x\n", msg[ANSWER_0x31_UNKNOWN1],msg[ANSWER_0x31_UNKNOWN2],msg[ANSWER_0x31_UNKNOWN3]);
918  return n;
919 }
920 
921 /* Node control */
923  if (!ctx) return -EINVAL;
924  uint64_t adr = -1;
925  if (node) adr = lightify_node_get_nodeadr(node);
926 
927  onoff = (onoff != 0);
928  int ret = lightify_request_set_onoff(ctx, adr, 0, onoff);
929 
930  if (node) {
931  lightify_node_set_onoff(node,onoff);
932  if (ret<0) {
933  lightify_node_set_stale(node,1);
934  }
935  } else {
936  node = NULL;
937  while((node = lightify_node_get_next(ctx, node))) {
938  lightify_node_set_onoff(node,onoff);
939  if (ret<0) {
940  lightify_node_set_stale(node,1);
941  }
942  }
943  }
944  return ret;
945 }
946 
947 LIGHTIFY_EXPORT int lightify_node_request_cct(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int cct, unsigned int fadetime) {
948  if (!ctx || !node ) return -EINVAL;
949  uint64_t adr = lightify_node_get_nodeadr(node);
950  int ret = lightify_request_set_cct(ctx, adr, 0 , cct, fadetime);
951 
952  lightify_node_set_cct(node, cct);
953  if (ret<0) {
954  lightify_node_set_stale(node,1);
955  }
956  return ret;
957 }
958 
959 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)
960 {
961  if (!ctx || !node ) return -EINVAL;
962  uint64_t adr = lightify_node_get_nodeadr(node);
963  int ret = lightify_request_set_rgbw(ctx, adr, 0, r, g ,b ,w ,fadetime);
964 
965  lightify_node_set_red(node, r);
966  lightify_node_set_green(node, g);
967  lightify_node_set_blue(node, b);
968  lightify_node_set_white(node, w);
969  if (ret<0) {
970  lightify_node_set_stale(node,1);
971  }
972  return ret;
973 }
974 
975 LIGHTIFY_EXPORT int lightify_node_request_brightness(struct lightify_ctx *ctx, struct lightify_node *node, unsigned int level, unsigned int fadetime) {
976  if (!ctx || !node ) return -EINVAL;
977  uint64_t adr = lightify_node_get_nodeadr(node);
978  int ret = lightify_request_set_brightness(ctx, adr, 0, level, fadetime);
979  lightify_node_set_brightness(node, level);
980  lightify_node_set_onoff(node, level!=0);
981  if (ret<0) {
982  lightify_node_set_stale(node,1);
983  }
984  return ret;
985 }
986 
988  struct lightify_node *node) {
989 
990  unsigned char msg[ANSWER_0x68_SIZE+2];
991  int n;
992  int read_size;
993 
994  if (!ctx) return -EINVAL;
995  if (!node)return -EINVAL;
996 
997  uint64_t node_adr = lightify_node_get_nodeadr(node);
998  uint32_t token = ++ctx->cnt;
999  fill_telegram_header(msg, QUERY_0x68_SIZE, token, 0x00, 0x68);
1000  msg_from_uint64(&msg[QUERY_0x68_NODEADR64_B0], node_adr);
1001 
1003  if ( n < 0 ) {
1004  info(ctx,"socket_write_fn error %d\n", n);
1005  return n;
1006  }
1007  if ( n != QUERY_0x68_SIZE) {
1008  info(ctx,"short write %d!=%d\n", QUERY_0x68_SIZE, n);
1009  return -EIO;
1010  }
1011 
1012  /* read the header incl. no of nodes and the byte that seems to be the status */
1014  if (n < 0) {
1015  info(ctx,"socket_read_fn error %d\n", n);
1016  return n;
1017  }
1018  if (n != ANSWER_0x68_ONLINESTATE) {
1019  info(ctx,"header short read %d!=%d\n", ANSWER_0x68_ONLINESTATE, n);
1020  return -EIO;
1021  }
1022 
1023  n = check_header_response(msg, token, 0x68);
1024  if ( n < 0 ) {
1025  info(ctx,"Invalid response (header)\n");
1026  return n;
1027  }
1028 
1029  /* no of nodes must be 1*/
1030  n = msg[ANSWER_0x68_NONODES_MSB] <<8U | msg[ANSWER_0x68_NONODES_LSB];
1031  if (n != 1) {
1032  dbg_proto(ctx, "Node count expected 1 but is %u\n", (unsigned int)n);
1033  return -EPROTO;
1034  }
1035 
1036  /* check if the node address was echoed properly */
1037  if (node_adr != uint64_from_msg(&msg[ANSWER_0x68_NODEADR64_B0])) {
1038  dbg_proto(ctx, "Node address not matching! %lx != %lx\n",
1039  node_adr, uint64_from_msg(&msg[ANSWER_0x68_NODEADR64_B0]));
1040  return -EPROTO;
1041  }
1042 
1043  if (msg[ANSWER_0x68_REQUEST_STATUS] != 0) {
1044  /* node did not answer or some other error occurred (?) */
1045  dbg_proto(ctx, "Node Status not equal 0 but %u\n",msg[ANSWER_0x68_REQUEST_STATUS]);
1046  lightify_node_set_stale(node, 1);
1047  return -ENODATA;
1048  }
1049 
1052  } else {
1054  }
1055 
1056  n = ctx->socket_read_fn(ctx,&msg[ANSWER_0x68_ONLINESTATE],read_size);
1057  if (n < 0) {
1058  info(ctx,"socket_read_fn error %d\n", n);
1059  return n;
1060  }
1061  if (n != read_size) {
1062  info(ctx,"body short read %d!=%d\n", read_size, n);
1063  return -EIO;
1064  }
1065 
1066  /* update node information */
1068  lightify_node_set_onoff(node,msg[ANSWER_0x68_ONOFF] != 0 );
1070  n = msg[ANSWER_0x68_CCT_LSB] | msg[ANSWER_0x68_CCT_MSB] << 8;
1071  lightify_node_set_cct(node,n);
1076 
1077  n = -decode_status(msg[ANSWER_0x68_STATE]);
1078  lightify_node_set_stale(node, (n!=0));
1079  return n;
1080 }
1081 
1083  int n,m;
1084  int no_of_grps;
1085  uint32_t token;
1086  int ret;
1087 
1088  if (!ctx) return -EINVAL;
1089 
1090  /* if using standard I/O functions, fd must be valid. If the user overrode those function,
1091  we won't care */
1094  return -EBADF;
1095  }
1096 
1097  /* remove old group information */
1098  free_all_groups(ctx);
1099 
1100  token = ++ctx->cnt;
1101 
1102  /* to avoid problems with packing, we need to use a char array.
1103  * to assist we'll have this fine enum */
1104  uint8_t msg[ANSWER_0x1e_GRP_LENGHT];
1105 
1106  /* 0x1e command to get all groups. */
1107  fill_telegram_header(msg, QUERY_0x1e_SIZE, token, 0x00, 0x1e);
1108 
1109  n = ctx->socket_write_fn(ctx, msg, QUERY_0x1e_SIZE);
1110  if ( n < 0 ) {
1111  info(ctx,"socket_write_fn error %d\n", n);
1112  return n;
1113  }
1114  if ( n != QUERY_0x1e_SIZE) {
1115  info(ctx,"short write %d!=%d\n", QUERY_0x1e_SIZE, n);
1116  return -EIO;
1117  }
1118 
1119  /* read the header */
1120  n = ctx->socket_read_fn(ctx, msg, ANSWER_0x1e_SIZE);
1121  if (n < 0) {
1122  info(ctx,"socket_read_fn error %d\n", n);
1123  return n;
1124  }
1125  if (n != ANSWER_0x1e_SIZE) {
1126  info(ctx,"short read %d!=%d\n", ANSWER_0x1e_SIZE, n);
1127  return -EIO;
1128  }
1129 
1130  /* check the header if plausible */
1131  /* check if the token we've supplied is also the returned one. */
1132  n = check_header_response(msg, token, 0x1e);
1133  if ( n < 0 ) {
1134  info(ctx,"Invalid response (header)\n");
1135  return n;
1136  }
1137 
1138  /* check if the message length is as expected */
1139  no_of_grps = msg[ANSWER_0x1e_NUMGROUPS];
1140  m = msg[HEADER_LEN_LSB] | (msg[HEADER_LEN_MSB] << 8);
1141  info(ctx, "0x1e: received %d bytes\n",m);
1142  if ( no_of_grps * ANSWER_0x1e_GRP_LENGHT + ANSWER_0x1e_SIZE - 2 != m) {
1143  info(ctx, "Response len unexpected for %d groups: %d!=%d.\n", no_of_grps,
1144  no_of_grps * ANSWER_0x1e_GRP_LENGHT + ANSWER_0x1e_SIZE - 2, m);
1145  return -EPROTO;
1146  }
1147 
1148  if (msg[HEADER_PAYLOAD_START]) {
1149  info(ctx, "strange byte at PAYLOAD_START: %d\n", msg[HEADER_PAYLOAD_START]);
1150  }
1151 
1152  ret = 0;
1153  /* read each node..*/
1154  while(no_of_grps--) {
1155  struct lightify_group *group = NULL;
1157  if (n< 0) return n;
1158  if (ANSWER_0x1e_GRP_LENGHT != n ) {
1159  info(ctx,"read group info: short read %d!=%d\n", ANSWER_0x1e_GRP_LENGHT, n);
1160  return -EIO;
1161  }
1162 
1163  n = lightify_group_new(ctx,&group);
1164  if (n < 0) {
1165  info(ctx, "create group error %d", n);
1166  return n;
1167  }
1168 
1171  ret++;
1172  }
1173  return ret;
1174 }
1175 
1176 
1177 /* Group control */
1179  if (!ctx || !group) return -EINVAL;
1180 
1181  onoff = (onoff != 0);
1182  int ret = lightify_request_set_onoff(ctx, lightify_group_get_id(group), 1, onoff);
1183 
1184  struct lightify_node *node = NULL;
1185  while ( (node = lightify_group_get_next_node(group,node))) {
1186  lightify_node_set_onoff(node, onoff);
1187  if (ret < 0 ) lightify_node_set_stale(node, 1);
1188  }
1189  return ret;
1190 }
1191 
1192 LIGHTIFY_EXPORT int lightify_group_request_cct(struct lightify_ctx *ctx, struct lightify_group *group, unsigned int cct, unsigned int fadetime) {
1193  if (!ctx || !group) return -EINVAL;
1194 
1195  int ret = lightify_request_set_cct(ctx, lightify_group_get_id(group), 1, cct, fadetime);
1196 
1197  struct lightify_node *node = NULL;
1198  while ( (node = lightify_group_get_next_node(group,node))) {
1199  lightify_node_set_cct(node, cct);
1200  if (ret < 0 ) lightify_node_set_stale(node, 1);
1201  }
1202  return ret;
1203 }
1204 
1206  struct lightify_group *group, unsigned int r, unsigned int g,
1207  unsigned int b,unsigned int w,unsigned int fadetime) {
1208  if (!ctx || !group) return -EINVAL;
1209 
1210  int ret = lightify_request_set_rgbw(ctx, lightify_group_get_id(group), 1, r, g, b, w , fadetime);
1211 
1212  struct lightify_node *node = NULL;
1213  while ( (node = lightify_group_get_next_node(group,node))) {
1214  lightify_node_set_red(node, r);
1215  lightify_node_set_green(node, g);
1216  lightify_node_set_blue(node, b);
1217  lightify_node_set_white(node, w);
1218  if (ret < 0 ) lightify_node_set_stale(node, 1);
1219  }
1220  return ret;
1221 }
1222 
1224  struct lightify_group *group, unsigned int level, unsigned int fadetime) {
1225  if (!ctx || !group) return -EINVAL;
1226 
1227  int ret = lightify_request_set_brightness(ctx, lightify_group_get_id(group), 1, level , fadetime);
1228 
1229  struct lightify_node *node = NULL;
1230  while ( (node = lightify_group_get_next_node(group,node))) {
1231  lightify_node_set_brightness(node, level);
1232  lightify_node_set_onoff(node, level!=0);
1233  if (ret < 0 ) lightify_node_set_stale(node, 1);
1234  }
1235  return ret;
1236 }
ANSWER_0x13_NODE_ADR64_B0
@ ANSWER_0x13_NODE_ADR64_B0
Definition: context.c:75
ANSWER_0x32_NODEADR64_B0
@ ANSWER_0x32_NODEADR64_B0
Definition: context.c:159
ANSWER_0x33_NODEADR64_B2
@ ANSWER_0x33_NODEADR64_B2
Definition: context.c:193
ANSWER_0x31_UNKNOWN2
@ ANSWER_0x31_UNKNOWN2
Definition: context.c:129
QUERY_0x36_NODEADR64_B0
@ QUERY_0x36_NODEADR64_B0
Definition: context.c:205
ANSWER_0x32_NODEADR64_B4
@ ANSWER_0x32_NODEADR64_B4
Definition: context.c:163
HEADER_REQ_ID_B1
@ HEADER_REQ_ID_B1
Definition: context.c:54
lightify_node::cct
int cct
Definition: node.c:67
QUERY_0x36_W
@ QUERY_0x36_W
Definition: context.c:216
ANSWER_0x33_NODEADR64_B6
@ ANSWER_0x33_NODEADR64_B6
Definition: context.c:197
HEADER_REQ_ID_B2
@ HEADER_REQ_ID_B2
Definition: context.c:55
ANSWER_0x36_RESERVED_MSB
@ ANSWER_0x36_RESERVED_MSB
Definition: context.c:225
ANSWER_0x33_NODEADR64_B4
@ ANSWER_0x33_NODEADR64_B4
Definition: context.c:195
ANSWER_0x13_SIZE
@ ANSWER_0x13_SIZE
Definition: context.c:69
QUERY_0x33_NODEADR64_B3
@ QUERY_0x33_NODEADR64_B3
Definition: context.c:175
ANSWER_0x68_NODEADR64_B2
@ ANSWER_0x68_NODEADR64_B2
Definition: context.c:256
QUERY_0x33_FADETIME_MSB
@ QUERY_0x33_FADETIME_MSB
Definition: context.c:183
ANSWER_0x68_NODEADR64_B5
@ ANSWER_0x68_NODEADR64_B5
Definition: context.c:259
ANSWER_0x36_NODEADR64_B4
@ ANSWER_0x36_NODEADR64_B4
Definition: context.c:230
lightify_free
LIGHTIFY_EXPORT int lightify_free(struct lightify_ctx *ctx)
Definition: context.c:494
ANSWER_0x36_NODEADR64_B0
@ ANSWER_0x36_NODEADR64_B0
Definition: context.c:226
lightify_node_request_onoff
LIGHTIFY_EXPORT int lightify_node_request_onoff(struct lightify_ctx *ctx, struct lightify_node *node, int onoff)
Definition: context.c:922
ANSWER_0x32_UNKNOWN1
@ ANSWER_0x32_UNKNOWN1
Definition: context.c:167
QUERY_0x31_FADETIME_LSB
@ QUERY_0x31_FADETIME_LSB
Definition: context.c:121
info
#define info(ctx, arg...)
ANSWER_0x13_NODESCNT_LSB
@ ANSWER_0x13_NODESCNT_LSB
Definition: context.c:67
ANSWER_0x13_UNKNOWN7
@ ANSWER_0x13_UNKNOWN7
Definition: context.c:101
ANSWER_0x13_NODE_ADR16_LSB
@ ANSWER_0x13_NODE_ADR16_LSB
Definition: context.c:73
ANSWER_0x68_NODEADR64_B4
@ ANSWER_0x68_NODEADR64_B4
Definition: context.c:258
QUERY_0x32_NODEADR64_B0
@ QUERY_0x32_NODEADR64_B0
Definition: context.c:143
QUERY_0x68_NODEADR64_B5
@ QUERY_0x68_NODEADR64_B5
Definition: context.c:244
ANSWER_0x13_UNKNOWN6
@ ANSWER_0x13_UNKNOWN6
Definition: context.c:100
ANSWER_0x31_NODEADR64_B3
@ ANSWER_0x31_NODEADR64_B3
Definition: context.c:133
ANSWER_0x13_UNKNOWN2
@ ANSWER_0x13_UNKNOWN2
Definition: context.c:84
LIGHTIFY_ONOFF_PLUG
@ LIGHTIFY_ONOFF_PLUG
Definition: liblightify.h:106
QUERY_0x36_G
@ QUERY_0x36_G
Definition: context.c:214
ANSWER_0x13_NODE_ONOFF_STATE
@ ANSWER_0x13_NODE_ONOFF_STATE
Definition: context.c:91
ANSWER_0x36_NODEADR64_B2
@ ANSWER_0x36_NODEADR64_B2
Definition: context.c:228
log_priority
int log_priority(const char *priority)
Definition: log.c:62
ANSWER_0x68_SIZE
@ ANSWER_0x68_SIZE
Definition: context.c:275
GW_PROT_1512
#define GW_PROT_1512
Definition: context.h:52
lightify_node_set_cct
int lightify_node_set_cct(struct lightify_node *node, int cct)
Definition: node.c:257
LIGHTIFY_DIMABLE_LIGHT
@ LIGHTIFY_DIMABLE_LIGHT
Definition: liblightify.h:107
lightify_node_set_stale
int lightify_node_set_stale(struct lightify_node *node, int stale)
Definition: node.c:307
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_0x33_SIZE
@ ANSWER_0x33_SIZE
Definition: context.c:200
ANSWER_0x1e_GRP_UNKNOWN_ZERO
@ ANSWER_0x1e_GRP_UNKNOWN_ZERO
Definition: context.c:292
QUERY_0x68_NODEADR64_B2
@ QUERY_0x68_NODEADR64_B2
Definition: context.c:241
ANSWER_0x13_NODE_ADR64_B7
@ ANSWER_0x13_NODE_ADR64_B7
Definition: context.c:82
QUERY_0x68_NODEADR64_B6
@ QUERY_0x68_NODEADR64_B6
Definition: context.c:245
ANSWER_0x31_NODEADR64_B4
@ ANSWER_0x31_NODEADR64_B4
Definition: context.c:134
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:1223
ANSWER_0x13_UNKNOWN4
@ ANSWER_0x13_UNKNOWN4
Definition: context.c:86
ANSWER_0x31_STATE
@ ANSWER_0x31_STATE
Definition: context.c:127
lightify_node_request_scan
LIGHTIFY_EXPORT int lightify_node_request_scan(struct lightify_ctx *ctx)
Definition: context.c:505
msg_0x36_answer
msg_0x36_answer
Definition: context.c:222
ANSWER_0x13_UNKNOWN13
@ ANSWER_0x13_UNKNOWN13
Definition: context.c:107
ANSWER_0x1e_STATE
@ ANSWER_0x1e_STATE
Definition: context.c:284
lightify_group_request_scan
LIGHTIFY_EXPORT int lightify_group_request_scan(struct lightify_ctx *ctx)
Definition: context.c:1082
QUERY_0x33_NODEADR64_B2
@ QUERY_0x33_NODEADR64_B2
Definition: context.c:174
lightify_node_set_zoneadr
int lightify_node_set_zoneadr(struct lightify_node *node, uint16_t adr)
Definition: node.c:180
lightify_node_get_name
const char * lightify_node_get_name(struct lightify_node *node)
Definition: node.c:164
QUERY_0x31_NODEADR64_B7
@ QUERY_0x31_NODEADR64_B7
Definition: context.c:119
ANSWER_0x13_NODE_ADR64_B2
@ ANSWER_0x13_NODE_ADR64_B2
Definition: context.c:77
ANSWER_0x13_NODE_ADR64_B3
@ ANSWER_0x13_NODE_ADR64_B3
Definition: context.c:78
ANSWER_0x13_NODE_GRP_MEMBER_MSB
@ ANSWER_0x13_NODE_GRP_MEMBER_MSB
Definition: context.c:90
lightify_ctx::groups
struct lightify_group * groups
Definition: context.h:93
ANSWER_0x36_NODEADR64_B1
@ ANSWER_0x36_NODEADR64_B1
Definition: context.c:227
ANSWER_0x13_UNKNOWN10
@ ANSWER_0x13_UNKNOWN10
Definition: context.c:104
ANSWER_0x13_NODE_ONLINE_STATE
@ ANSWER_0x13_NODE_ONLINE_STATE
Definition: context.c:88
lightify_ctx::gw_protocol_version
int gw_protocol_version
Definition: context.h:102
ANSWER_0x13_UNKNOWN1
@ ANSWER_0x13_UNKNOWN1
Definition: context.c:66
lightify_group
Definition: groups.c:46
lightify_node_set_name
int lightify_node_set_name(struct lightify_node *node, char *name)
Definition: node.c:151
lightify_node_set_lamptype
int lightify_node_set_lamptype(struct lightify_node *node, enum lightify_node_type type)
Definition: node.c:202
QUERY_0x33_NODEADR64_B4
@ QUERY_0x33_NODEADR64_B4
Definition: context.c:176
ANSWER_0x31_UNKNOWN3
@ ANSWER_0x31_UNKNOWN3
Definition: context.c:138
read_from_socket_fn
int(* read_from_socket_fn)(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: liblightify.h:168
msg_0x68_answer
msg_0x68_answer
Definition: context.c:250
ANSWER_0x13_NODE_ADR64_B5
@ ANSWER_0x13_NODE_ADR64_B5
Definition: context.c:80
ANSWER_0x13_NODE_NAME_START
@ ANSWER_0x13_NODE_NAME_START
Definition: context.c:99
ANSWER_0x33_RESERVED_LSB
@ ANSWER_0x33_RESERVED_LSB
Definition: context.c:189
ANSWER_0x33_NODEADR64_B7
@ ANSWER_0x33_NODEADR64_B7
Definition: context.c:198
LIGHTIFY_EXPORT
#define LIGHTIFY_EXPORT
ANSWER_0x68_DIM_LEVEL
@ ANSWER_0x68_DIM_LEVEL
Definition: context.c:265
write_to_socket
int write_to_socket(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: socket.c:45
ANSWER_0x13_NODE_DIM_LEVEL
@ ANSWER_0x13_NODE_DIM_LEVEL
Definition: context.c:92
ANSWER_0x13_NODE_ADR64_B4
@ ANSWER_0x13_NODE_ADR64_B4
Definition: context.c:79
msg_0x1e_answer
msg_0x1e_answer
Definition: context.c:283
QUERY_0x32_NODEADR64_B7
@ QUERY_0x32_NODEADR64_B7
Definition: context.c:150
QUERY_0x68_SIZE
@ QUERY_0x68_SIZE
Definition: context.c:247
ANSWER_0x13_NODE_ADR64_B6
@ ANSWER_0x13_NODE_ADR64_B6
Definition: context.c:81
QUERY_0x31_FADETIME_MSB
@ QUERY_0x31_FADETIME_MSB
Definition: context.c:122
lightify_get_userdata
LIGHTIFY_EXPORT void * lightify_get_userdata(struct lightify_ctx *ctx)
Definition: context.c:417
QUERY_0x33_CCT_MSB
@ QUERY_0x33_CCT_MSB
Definition: context.c:181
lightify_set_log_priority
int lightify_set_log_priority(struct lightify_ctx *ctx, int priority)
Definition: log.c:105
ANSWER_0x68_NONODES_LSB
@ ANSWER_0x68_NONODES_LSB
Definition: context.c:252
ANSWER_0x68_NODEADR64_B1
@ ANSWER_0x68_NODEADR64_B1
Definition: context.c:255
QUERY_0x33_FADETIME_LSB
@ QUERY_0x33_FADETIME_LSB
Definition: context.c:182
QUERY_0x13_REQTYPE
@ QUERY_0x13_REQTYPE
Definition: context.c:61
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
lightify_node_get_nodeadr
uint64_t lightify_node_get_nodeadr(struct lightify_node *node)
Definition: node.c:175
QUERY_0x31_NODEADR64_B3
@ QUERY_0x31_NODEADR64_B3
Definition: context.c:115
fadetime
int fadetime
Definition: lightify-util.c:99
ANSWER_0x32_NODEADR64_B2
@ ANSWER_0x32_NODEADR64_B2
Definition: context.c:161
HEADER_REQ_ID_B3
@ HEADER_REQ_ID_B3
Definition: context.c:56
ANSWER_0x13_NODE_GRP_MEMBER_LSB
@ ANSWER_0x13_NODE_GRP_MEMBER_LSB
Definition: context.c:89
ANSWER_0x31_NODEADR64_B2
@ ANSWER_0x31_NODEADR64_B2
Definition: context.c:132
QUERY_0x32_NODEADR64_B6
@ QUERY_0x32_NODEADR64_B6
Definition: context.c:149
ANSWER_0x68_UNKNOWN2
@ ANSWER_0x68_UNKNOWN2
Definition: context.c:272
QUERY_0x33_NODEADR64_B0
@ QUERY_0x33_NODEADR64_B0
Definition: context.c:172
lightify_node_set_brightness
int lightify_node_set_brightness(struct lightify_node *node, int brightness)
Definition: node.c:268
ANSWER_0x32_SIZE
@ ANSWER_0x32_SIZE
Definition: context.c:168
lightify_node_get_previous
LIGHTIFY_EXPORT struct lightify_node * lightify_node_get_previous(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:410
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:430
lightify_node_new
int lightify_node_new(struct lightify_ctx *ctx, struct lightify_node **newnode)
Definition: node.c:80
lightify_node_set_grpadr
int lightify_node_set_grpadr(struct lightify_node *node, uint16_t adr)
Definition: node.c:191
QUERY_0x36_R
@ QUERY_0x36_R
Definition: context.c:213
lightify_ctx::iotimeout
struct timeval iotimeout
Definition: context.h:99
ANSWER_0x32_NODEADR64_B3
@ ANSWER_0x32_NODEADR64_B3
Definition: context.c:162
msg_0x33_answer
msg_0x33_answer
Definition: context.c:187
lightify_node::ctx
struct lightify_ctx * ctx
Definition: node.c:46
QUERY_0x33_NODEADR64_B7
@ QUERY_0x33_NODEADR64_B7
Definition: context.c:179
ANSWER_0x68_ONLINESTATE
@ ANSWER_0x68_ONLINESTATE
Definition: context.c:263
dbg
#define dbg(ctx, arg...)
ANSWER_0x68_CCT_LSB
@ ANSWER_0x68_CCT_LSB
Definition: context.c:266
ANSWER_0x13_NODESCNT_MSB
@ ANSWER_0x13_NODESCNT_MSB
Definition: context.c:68
QUERY_0x1e
@ QUERY_0x1e
Definition: context.c:279
QUERY_0x36_NODEADR64_B5
@ QUERY_0x36_NODEADR64_B5
Definition: context.c:210
ANSWER_0x68_W
@ ANSWER_0x68_W
Definition: context.c:271
ANSWER_0x68_R
@ ANSWER_0x68_R
Definition: context.c:268
QUERY_0x36_FADETIME_LSB
@ QUERY_0x36_FADETIME_LSB
Definition: context.c:217
QUERY_0x36_FADETIME_MSB
@ QUERY_0x36_FADETIME_MSB
Definition: context.c:218
ANSWER_0x68_STATE
@ ANSWER_0x68_STATE
Definition: context.c:251
ANSWER_0x1e_SIZE
@ ANSWER_0x1e_SIZE
Definition: context.c:287
QUERY_0x31_NODEADR64_B6
@ QUERY_0x31_NODEADR64_B6
Definition: context.c:118
node.h
LIGHTIFY_COLOUR_LIGHT
@ LIGHTIFY_COLOUR_LIGHT
Definition: liblightify.h:108
QUERY_0x32_NODEADR64_B2
@ QUERY_0x32_NODEADR64_B2
Definition: context.c:145
ANSWER_0x33_NODEADR64_B5
@ ANSWER_0x33_NODEADR64_B5
Definition: context.c:196
QUERY_0x36_SIZE
@ QUERY_0x36_SIZE
Definition: context.c:219
QUERY_0x68_NODEADR64_B1
@ QUERY_0x68_NODEADR64_B1
Definition: context.c:240
msg_0x13_answer_node
msg_0x13_answer_node
Definition: context.c:72
QUERY_0x68_NODEADR64_B0
@ QUERY_0x68_NODEADR64_B0
Definition: context.c:239
ANSWER_0x36_SIZE
@ ANSWER_0x36_SIZE
Definition: context.c:235
ANSWER_0x68_NODEADR64_B0
@ ANSWER_0x68_NODEADR64_B0
Definition: context.c:254
QUERY_0x68_NODEADR64_B7
@ QUERY_0x68_NODEADR64_B7
Definition: context.c:246
ANSWER_0x13_NODE_CCT_LSB
@ ANSWER_0x13_NODE_CCT_LSB
Definition: context.c:93
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:975
ANSWER_0x31_NODEADR64_B0
@ ANSWER_0x31_NODEADR64_B0
Definition: context.c:130
HEADER_CMD
@ HEADER_CMD
Definition: context.c:52
ANSWER_0x36_STATE
@ ANSWER_0x36_STATE
Definition: context.c:223
ANSWER_0x1e_HDR_UNKNOWN_ZERO
@ ANSWER_0x1e_HDR_UNKNOWN_ZERO
Definition: context.c:286
QUERY_0x31_LEVEL
@ QUERY_0x31_LEVEL
Definition: context.c:120
ANSWER_0x13_UNKNOWN12
@ ANSWER_0x13_UNKNOWN12
Definition: context.c:106
LIGHTIFY_4WAY_SWITCH
@ LIGHTIFY_4WAY_SWITCH
Definition: liblightify.h:111
ANSWER_0x31_NODEADR64_B1
@ ANSWER_0x31_NODEADR64_B1
Definition: context.c:131
lightify_group_remove
int lightify_group_remove(struct lightify_group *grp)
Definition: groups.c:84
QUERY_0x68_NODEADR64_B4
@ QUERY_0x68_NODEADR64_B4
Definition: context.c:243
QUERY_0x36_NODEADR64_B2
@ QUERY_0x36_NODEADR64_B2
Definition: context.c:207
QUERY_0x31_NODEADR64_B5
@ QUERY_0x31_NODEADR64_B5
Definition: context.c:117
HEADER_FLAGS
@ HEADER_FLAGS
Definition: context.c:51
lightify_node
Definition: node.c:43
QUERY_0x32_NODEADR64_B4
@ QUERY_0x32_NODEADR64_B4
Definition: context.c:147
QUERY_0x31_NODEADR64_B0
@ QUERY_0x31_NODEADR64_B0
Definition: context.c:112
ANSWER_0x32_RESERVED_LSB
@ ANSWER_0x32_RESERVED_LSB
Definition: context.c:157
ANSWER_0x68_B
@ ANSWER_0x68_B
Definition: context.c:270
lightify_node_set_nodeadr
int lightify_node_set_nodeadr(struct lightify_node *node, uint64_t adr)
Definition: node.c:169
ANSWER_0x32_RESERVED_MSB
@ ANSWER_0x32_RESERVED_MSB
Definition: context.c:158
ANSWER_0x68_UNKNOWN3
@ ANSWER_0x68_UNKNOWN3
Definition: context.c:273
LIGHTIFY_CCT_LIGHT
@ LIGHTIFY_CCT_LIGHT
Definition: liblightify.h:110
ANSWER_0x13_UNKNOWN5
@ ANSWER_0x13_UNKNOWN5
Definition: context.c:87
lightify_node_set_red
int lightify_node_set_red(struct lightify_node *node, int red)
Definition: node.c:213
lightify_node_get_nextnode
struct lightify_node * lightify_node_get_nextnode(struct lightify_node *node)
Definition: node.c:140
msg_0x33_query
msg_0x33_query
Definition: context.c:171
QUERY_0x36_NODEADR64_B6
@ QUERY_0x36_NODEADR64_B6
Definition: context.c:211
lightify_node_set_white
int lightify_node_set_white(struct lightify_node *node, int white)
Definition: node.c:246
lightify_ctx::socket
int socket
Definition: context.h:87
lightify_ctx
Definition: context.h:68
GW_PROT_OLD
#define GW_PROT_OLD
Definition: context.h:50
ANSWER_0x32_NODEADR64_B1
@ ANSWER_0x32_NODEADR64_B1
Definition: context.c:160
lightify_node_get_prevnode
struct lightify_node * lightify_node_get_prevnode(struct lightify_node *node)
Definition: node.c:145
ANSWER_0x1e_NUMGROUPS
@ ANSWER_0x1e_NUMGROUPS
Definition: context.c:285
HEADER_LEN_LSB
@ HEADER_LEN_LSB
Definition: context.c:49
ANSWER_0x33_RESERVED_MSB
@ ANSWER_0x33_RESERVED_MSB
Definition: context.c:190
ANSWER_0x31_UNKNOWN1
@ ANSWER_0x31_UNKNOWN1
Definition: context.c:128
QUERY_0x32_NODEADR64_B1
@ QUERY_0x32_NODEADR64_B1
Definition: context.c:144
QUERY_0x31_NODEADR64_B4
@ QUERY_0x31_NODEADR64_B4
Definition: context.c:116
lightify_new
LIGHTIFY_EXPORT int lightify_new(struct lightify_ctx **ctx, void *reserved)
Definition: context.c:445
lightify_node_get_next
LIGHTIFY_EXPORT struct lightify_node * lightify_node_get_next(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:402
ANSWER_0x13_NODE_NODETYPE
@ ANSWER_0x13_NODE_NODETYPE
Definition: context.c:83
ANSWER_0x68_UNKNOWN4
@ ANSWER_0x68_UNKNOWN4
Definition: context.c:274
ANSWER_0x68_NODEADR64_B3
@ ANSWER_0x68_NODEADR64_B3
Definition: context.c:257
QUERY_0x68_NODEADR64_B3
@ QUERY_0x68_NODEADR64_B3
Definition: context.c:242
log.h
msg_0x13_answer
msg_0x13_answer
Definition: context.c:65
msg_0x32_query
msg_0x32_query
Definition: context.c:142
ANSWER_0x13_NODE_LENGTH
@ ANSWER_0x13_NODE_LENGTH
Definition: context.c:108
lightify_ctx::cnt
uint32_t cnt
Definition: context.h:96
ANSWER_0x31_SIZE
@ ANSWER_0x31_SIZE
Definition: context.c:139
ANSWER_0x13_UNKNOWN3
@ ANSWER_0x13_UNKNOWN3
Definition: context.c:85
HEADER_PAYLOAD_START
@ HEADER_PAYLOAD_START
Definition: context.c:57
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:1192
lightify_ctx::userdata
void * userdata
Function pointer to the I/O handling – write to.
Definition: context.h:82
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:1205
ANSWER_0x33_STATE
@ ANSWER_0x33_STATE
Definition: context.c:188
ANSWER_0x13_UNKNOWN9
@ ANSWER_0x13_UNKNOWN9
Definition: context.c:103
HEADER_REQ_ID_B0
@ HEADER_REQ_ID_B0
Definition: context.c:53
lightify_group_get_id
LIGHTIFY_EXPORT int lightify_group_get_id(struct lightify_group *grp)
Definition: groups.c:128
QUERY_0x36_B
@ QUERY_0x36_B
Definition: context.c:215
lightify_node_set_onoff
int lightify_node_set_onoff(struct lightify_node *node, uint8_t on)
Definition: node.c:280
ANSWER_0x13_NODE_G
@ ANSWER_0x13_NODE_G
Definition: context.c:96
msg_0x32_answer
msg_0x32_answer
Definition: context.c:155
ANSWER_0x68_NONODES_MSB
@ ANSWER_0x68_NONODES_MSB
Definition: context.c:253
ANSWER_0x13_NODE_ADR64_B1
@ ANSWER_0x13_NODE_ADR64_B1
Definition: context.c:76
ANSWER_0x36_NODEADR64_B3
@ ANSWER_0x36_NODEADR64_B3
Definition: context.c:229
QUERY_0x33_NODEADR64_B1
@ QUERY_0x33_NODEADR64_B1
Definition: context.c:173
ANSWER_0x13_NODE_CCT_MSB
@ ANSWER_0x13_NODE_CCT_MSB
Definition: context.c:94
msg_0x31_query
msg_0x31_query
Definition: context.c:111
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_group_set_id
int lightify_group_set_id(struct lightify_group *grp, int id)
Definition: groups.c:122
msg_0x36_query
msg_0x36_query
Definition: context.c:204
QUERY_0x31_NODEADR64_B2
@ QUERY_0x31_NODEADR64_B2
Definition: context.c:114
ANSWER_0x13_UNKNOWN8
@ ANSWER_0x13_UNKNOWN8
Definition: context.c:102
lightify_group_request_onoff
LIGHTIFY_EXPORT int lightify_group_request_onoff(struct lightify_ctx *ctx, struct lightify_group *group, int onoff)
Definition: context.c:1178
lightify_ctx::nodes
struct lightify_node * nodes
Definition: context.h:90
read_from_socket
int read_from_socket(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: socket.c:121
ANSWER_0x68_REQUEST_STATUS
@ ANSWER_0x68_REQUEST_STATUS
Definition: context.c:262
QUERY_0x33_NODEADR64_B6
@ QUERY_0x33_NODEADR64_B6
Definition: context.c:178
ANSWER_0x32_NODEADR64_B5
@ ANSWER_0x32_NODEADR64_B5
Definition: context.c:164
ANSWER_0x32_STATE
@ ANSWER_0x32_STATE
Definition: context.c:156
socket.h
ANSWER_0x1e_GRP_ID
@ ANSWER_0x1e_GRP_ID
Definition: context.c:291
ANSWER_0x13_NODE_ADR16_MSB
@ ANSWER_0x13_NODE_ADR16_MSB
Definition: context.c:74
ANSWER_0x36_NODEADR64_B5
@ ANSWER_0x36_NODEADR64_B5
Definition: context.c:231
msg_0x1e_answerpergroup
msg_0x1e_answerpergroup
Definition: context.c:290
ANSWER_0x31_NODEADR64_B6
@ ANSWER_0x31_NODEADR64_B6
Definition: context.c:136
context.h
ANSWER_0x13_NODE_W
@ ANSWER_0x13_NODE_W
Definition: context.c:98
ENODATA
#define ENODATA
Definition: context.c:44
liblightify-private.h
lightify_set_userdata
LIGHTIFY_EXPORT int lightify_set_userdata(struct lightify_ctx *ctx, void *userdata)
Definition: context.c:423
HEADER_LEN_MSB
@ HEADER_LEN_MSB
Definition: context.c:50
lightify_node_set_blue
int lightify_node_set_blue(struct lightify_node *node, int blue)
Definition: node.c:224
lightify_group_new
int lightify_group_new(struct lightify_ctx *ctx, struct lightify_group **newgroup)
Definition: groups.c:60
ANSWER_0x1e_GRP_LENGHT
@ ANSWER_0x1e_GRP_LENGHT
Definition: context.c:294
msg_0x13_query
msg_0x13_query
Definition: context.c:60
ANSWER_0x36_RESERVED_LSB
@ ANSWER_0x36_RESERVED_LSB
Definition: context.c:224
QUERY_0x36_NODEADR64_B3
@ QUERY_0x36_NODEADR64_B3
Definition: context.c:208
groups.h
ANSWER_0x68_ONOFF
@ ANSWER_0x68_ONOFF
Definition: context.c:264
dbg_proto
#define dbg_proto(ctx, arg...)
lightify_group::ctx
struct lightify_ctx * ctx
Definition: groups.c:47
QUERY_0x31_SIZE
@ QUERY_0x31_SIZE
Definition: context.c:123
QUERY_0x36_NODEADR64_B1
@ QUERY_0x36_NODEADR64_B1
Definition: context.c:206
QUERY_0x31_NODEADR64_B1
@ QUERY_0x31_NODEADR64_B1
Definition: context.c:113
QUERY_0x13_SIZE
@ QUERY_0x13_SIZE
Definition: context.c:62
QUERY_0x1e_SIZE
@ QUERY_0x1e_SIZE
Definition: context.c:280
ANSWER_0x1e_GRP_NAME
@ ANSWER_0x1e_GRP_NAME
Definition: context.c:293
ANSWER_0x13_UNKNOWN11
@ ANSWER_0x13_UNKNOWN11
Definition: context.c:105
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:314
ANSWER_0x13_NODE_R
@ ANSWER_0x13_NODE_R
Definition: context.c:95
msg_0x68_query
msg_0x68_query
Definition: context.c:238
lightify_ctx::log_priority
int log_priority
Definition: context.h:84
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:74
ANSWER_0x33_NODEADR64_B1
@ ANSWER_0x33_NODEADR64_B1
Definition: context.c:192
write_to_socket_fn
int(* write_to_socket_fn)(struct lightify_ctx *ctx, unsigned char *msg, size_t size)
Definition: liblightify.h:150
ANSWER_0x33_UNKNOWN1
@ ANSWER_0x33_UNKNOWN1
Definition: context.c:199
QUERY_0x32_ONOFF
@ QUERY_0x32_ONOFF
Definition: context.c:151
lightify_node_remove
int lightify_node_remove(struct lightify_node *node)
Definition: node.c:117
LIGHTIFY_UNKNOWNTYPE
@ LIGHTIFY_UNKNOWNTYPE
Definition: liblightify.h:112
lightify_node_request_update
LIGHTIFY_EXPORT int lightify_node_request_update(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:987
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:959
ANSWER_0x36_UNKNOWN1
@ ANSWER_0x36_UNKNOWN1
Definition: context.c:234
ANSWER_0x33_NODEADR64_B0
@ ANSWER_0x33_NODEADR64_B0
Definition: context.c:191
QUERY_0x33_SIZE
@ QUERY_0x33_SIZE
Definition: context.c:184
msg_0x1e_query
msg_0x1e_query
Definition: context.c:278
QUERY_0x32_NODEADR64_B5
@ QUERY_0x32_NODEADR64_B5
Definition: context.c:148
ANSWER_0x31_NODEADR64_B7
@ ANSWER_0x31_NODEADR64_B7
Definition: context.c:137
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:70
QUERY_0x33_NODEADR64_B5
@ QUERY_0x33_NODEADR64_B5
Definition: context.c:177
ANSWER_0x68_G
@ ANSWER_0x68_G
Definition: context.c:269
ANSWER_0x33_NODEADR64_B3
@ ANSWER_0x33_NODEADR64_B3
Definition: context.c:194
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:77
LIGHTIFY_EXT_COLOUR_LIGHT
@ LIGHTIFY_EXT_COLOUR_LIGHT
Definition: liblightify.h:109
QUERY_0x32_NODEADR64_B3
@ QUERY_0x32_NODEADR64_B3
Definition: context.c:146
ANSWER_0x13_NODE_B
@ ANSWER_0x13_NODE_B
Definition: context.c:97
ANSWER_0x32_NODEADR64_B6
@ ANSWER_0x32_NODEADR64_B6
Definition: context.c:165
ANSWER_0x32_NODEADR64_B7
@ ANSWER_0x32_NODEADR64_B7
Definition: context.c:166
ANSWER_0x31_NODEADR64_B5
@ ANSWER_0x31_NODEADR64_B5
Definition: context.c:135
lightify_group_set_name
int lightify_group_set_name(struct lightify_group *grp, const unsigned char *name)
Definition: groups.c:104
msg_header
msg_header
Definition: context.c:48
ANSWER_0x36_NODEADR64_B6
@ ANSWER_0x36_NODEADR64_B6
Definition: context.c:232
msg_0x31_answer
msg_0x31_answer
Definition: context.c:126
ANSWER_0x68_CCT_MSB
@ ANSWER_0x68_CCT_MSB
Definition: context.c:267
ANSWER_0x68_NODEADR64_B7
@ ANSWER_0x68_NODEADR64_B7
Definition: context.c:261
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:947
QUERY_0x36_NODEADR64_B7
@ QUERY_0x36_NODEADR64_B7
Definition: context.c:212
QUERY_0x36_NODEADR64_B4
@ QUERY_0x36_NODEADR64_B4
Definition: context.c:209
ANSWER_0x68_NODEADR64_B6
@ ANSWER_0x68_NODEADR64_B6
Definition: context.c:260
ANSWER_0x36_NODEADR64_B7
@ ANSWER_0x36_NODEADR64_B7
Definition: context.c:233
QUERY_0x32_SIZE
@ QUERY_0x32_SIZE
Definition: context.c:152
QUERY_0x33_CCT_LSB
@ QUERY_0x33_CCT_LSB
Definition: context.c:180