liblightify
lightify-util.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 
10  * Redistributions of source code must retain the above copyright
11  notice, this list of conditions and the following disclaimer.
12 
13  * Redistributions in binary form must reproduce the above copyright
14  notice, this list of conditions and the following disclaimer in the
15  documentation and/or other materials provided with the distribution.
16 
17  * Neither the name of the author nor the
18  names of its contributors may be used to endorse or promote products
19  derived from this software without specific prior written permission.
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
25  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <netdb.h>
36 #include <string.h>
37 
39 #include <unistd.h>
40 
41 #include <fcntl.h>
42 
43 #include <getopt.h>
44 #include <time.h>
45 
46 #include <errno.h>
47 
48 
49 /* Flag set by ‘--verbose’. */
50 static int verbose_flag;
51 
52 static struct option long_options[] = {
53 /* These options set a flag. */
54 { "verbose", no_argument, &verbose_flag, 1 },
55 { "brief", no_argument, &verbose_flag, 0 },
56 /* These options don’t set a flag.
57  We distinguish them by their indices. */
58 { "cct", required_argument, 0, 'c' },
59 { "rgbw", required_argument, 0, 'r' },
60 { "level", required_argument, 0, 'l' },
61 { "name", required_argument, 0, 'n' },
62 { "host", required_argument, 0, 'h' },
63 { "port", required_argument, 0, 'p' },
64 { "on", required_argument, 0, '0' },
65 { "off", required_argument, 0, '1' },
66 { "time", required_argument, 0, 't' },
67 { "list-nodes", no_argument, 0, 'd' },
68 { "wait", required_argument, 0, 'w' },
69 { "list-groups", no_argument, 0, 2},
70 { "group", required_argument, 0, 'g' },
71 { 0, 0, 0, 0 }
72 };
73 /* getopt_long stores the option index here. */
74 
75 // commands data
76 int command_cct = 0;
78 
79 int command_r = 0;
80 int command_r_r = 0;
81 int command_r_g = 0;
82 int command_r_b = 0;
83 int command_r_w = 0;
84 
85 int command_l = 0;
87 
88 //int name = 0;
89 
90 char *name_data = NULL;
91 
92 char *group_data = NULL;
93 
94 char *host_data = NULL;
95 
96 int port = 4000;
97 
99 
100 int gonnected = 0;
101 
102 int sockfd;
103 
104 void usage(char *argv[]) {
105  printf("Usage: %s [OPTIONS] \n", argv[0]);
106  printf(" --host,-h <host> Hostname or IP\n");
107  printf(" [--verbose] Verbose mode\n");
108  printf(" [--list-nodes,-d] Dump info about lamps\n");
109  printf(" [--list-groups] Show all known groups\n");
110  printf(" [--wait,-w <value>] Wait for value/10 seconds\n");
111  printf(" [--time,-t <value>] Set fading time in 1/10 seconds\n");
112  printf(" [--name,-n <value>] Name of the lamp to be manipulated\n");
113  printf(" [--group,-g <value>] Name of the lamp to be manipulated\n");
114  printf(" [--port,-p <port>] Port, default 4000\n");
115  printf(" [--on,-0] Turn lamp on\n");
116  printf(" [--off,-1] Turn lamp off\n");
117  printf(" [--level,-l <value>] Set intensity level. Range 0 to 100\n");
118  printf(" [--cct,-c <value>] CCT to be set.\n");
119  printf(" [--rgbw,-r <value>] Set color. Give color as r,g,b,w. Color values from 0 to 255\n");
120  printf("\n Host must be given before any command. Commands on and off can broadcast to all lamps if name is not given before.\n");
121 }
122 
123 struct lightify_node* find_node_per_name(struct lightify_ctx *ctx, const char *name) {
124  if (!name) return NULL;
125  struct lightify_node *node = NULL;
126  while ((node = lightify_node_get_next(ctx, node))) {
127  if (0 == strcmp(name, lightify_node_get_name(node))) {
128  return node;
129  }
130  }
131  fprintf(stderr, "ERROR: Node %s not found\n", name);
132  return NULL;
133 }
134 
135 struct lightify_group* find_grp_per_name(struct lightify_ctx *ctx, const char *name) {
136  if (!name) return NULL;
137  struct lightify_group *group = NULL;
138  while( (group = lightify_group_get_next(ctx, group))) {
139  if (0 == strcmp(name, lightify_group_get_name(group))) {
140  return group;
141  }
142  }
143  fprintf(stderr, "ERROR: Group %s not found\n", name);
144  return NULL;
145 }
146 
147 
148 void command_set_0_1(struct lightify_ctx *ctx, int command_on) {
149  struct lightify_node *node = find_node_per_name(ctx,name_data);;
150  struct lightify_group *grp = find_grp_per_name(ctx,group_data);
151  char *type, *name;
152 
153  command_on = command_on > 0 ? 1 : 0;
154  if (!name_data && !group_data) {
155  type = "Broadcast"; name = "";
156  lightify_node_request_onoff(ctx, NULL, command_on);
157  } else if (node) {
158  type = "Node"; name = name_data;
159  lightify_node_request_onoff(ctx, node, command_on);
160  } else if (grp) {
161  type = "Group"; name = group_data;
162  lightify_group_request_onoff(ctx,grp,command_on);
163  } else {
164  return;
165  }
166 
167  if (verbose_flag) {
168  printf("%s %s switch %s\n", type, name , command_on ? "on" : "off");
169  }
170 }
171 
173  struct lightify_node *node = find_node_per_name(ctx,name_data);;
174  struct lightify_group *grp = find_grp_per_name(ctx,group_data);
175  char *type, *name;
176 
177  if(node) {
178  type = "Node"; name = name_data;
180  } else if (grp) {
181  type = "Group"; name = group_data;
183  } else {
184  return;
185  }
186 
187  if (verbose_flag) {
188  printf("%s %s cct %dK in time %d\n", type, name, command_cct_data, fadetime );
189  }
190 }
191 
193  struct lightify_node *node = find_node_per_name(ctx,name_data);
194  struct lightify_group *grp = find_grp_per_name(ctx,group_data);
195  char *type, *name;
196 
197  if(node) {
198  type ="Node"; name = name_data;
201  } else if (grp) {
202  type ="Group"; name = group_data;
205  } else {
206  return;
207  }
208 
209  if (verbose_flag) {
210  printf("%s %s rgbw %d,%d,%d,%d in time %d\n", type, name, command_r_r,
212  }
213 }
214 
216  struct lightify_node *node = find_node_per_name(ctx,name_data);
217  struct lightify_group *grp = find_grp_per_name(ctx,group_data);
218  char *type, *name;
219 
220  if(node) {
221  type ="Node"; name = name_data;
223  } else if (grp) {
224  type ="Group"; name = group_data;
226  } else {
227  return;
228  }
229 
230  if (verbose_flag) {
231  printf("%s %s brightness %d in time %d\n", type, name, command_l_data, fadetime);
232  }
233 }
234 
236  /* Create a socket point */
237  int err;
238  struct sockaddr_in serv_addr;
239  struct hostent *server;
240 
241  sockfd = socket(AF_INET, SOCK_STREAM, 0);
242 
243  if (sockfd < 0) {
244  perror("ERROR opening socket");
245  exit(1);
246  }
247  server = gethostbyname(host_data);
248 
249  if (server == NULL) {
250  fprintf(stderr, "ERROR, no such host\n");
251  exit(1);
252  }
253 
254  bzero((char *) &serv_addr, sizeof(serv_addr));
255  serv_addr.sin_family = AF_INET;
256  bcopy((char *) server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
257  serv_addr.sin_port = htons(port);
258 
259  /* Now connect to the server */
260  if (connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) < 0) {
261  perror("ERROR connecting");
262  exit(1);
263  }
264 
265  err = lightify_skt_setfd(ctx, sockfd);
266  if (err < 0) {
267  fprintf(stderr, "Could not set fd\n");
268  exit(1);
269  }
270 
271  gonnected = 1;
272 
273  // scan nodes
274  err = lightify_node_request_scan(ctx);
275  if (err < 0) {
276  fprintf(stderr,
277  "Error during node scan -- lets see if we've got partial data\n");
278  }
279 
280  // scan groups
281  err = lightify_group_request_scan(ctx);
282  if (err < 0) {
283  fprintf(stderr,
284  "Error during group scan -- lets see if we've got partial group data\n");
285  }
286 }
287 
288 
289 const char *decode_online_state(int state) {
290  switch (state) {
291  case LIGHTIFY_OFFLINE:
292  return "offline";
293  case LIGHTIFY_ONLINE:
294  return "online";
295  default:
296  return "unknown";
297  }
298 }
299 
300 const char *decode_lamptype(int type) {
301  switch (type) {
302  case LIGHTIFY_ONOFF_PLUG:
303  return "oo-plug";
305  return "dim";
307  return "color";
309  return "ext-col";
310  case LIGHTIFY_CCT_LIGHT:
311  return "cct";
312 
313  default:
314  return "unknown";
315  }
316 }
317 
318 const char *decode_onoff_sate(int state) {
319  if (state < 0) return "err";
320  switch (state) {
321  case 0:
322  return "off";
323  case 1:
324  return "on";
325  default:
326  return "???";
327  }
328 }
329 
330 void dump_nodes_state(struct lightify_ctx *ctx) {
331  int count=0;
332  // Let's create a short table...
333  // 1234567890123456 1234567812345678
334  printf("|------------------|------------------|---------|--------|---------|-----|-----|------|-----|-----|-----|-----|---|\n");
335  printf("| Name | MAC | type | group | online | 0/1 | dim | CCT | Red | Grn | Blu | Wht | s |\n");
336  printf("|------------------|------------------|---------|--------|---------|-----|-----|------|-----|-----|-----|-----|---|\n");
337  struct lightify_node *node = NULL;
338 
339  while (( node = lightify_node_get_next(ctx, node))) {
340  count++;
341  printf("| %-16s |" , lightify_node_get_name(node));
342  printf(" %016llx |" , lightify_node_get_nodeadr(node));
343  printf(" %-7s |", decode_lamptype(lightify_node_get_lamptype(node)));
344  printf(" 0x%04x |", lightify_node_get_grpadr(node));
345  printf(" %-7s |", decode_online_state(lightify_node_get_onlinestate(node)));
346  printf(" %-3s |", decode_onoff_sate(lightify_node_is_on(node)));
347  printf(" %-3d |", lightify_node_get_brightness(node));
348  printf(" %-4d |", lightify_node_get_cct(node));
349  printf(" %-3d |", lightify_node_get_red(node));
350  printf(" %-3d |", lightify_node_get_green(node));
351  printf(" %-3d |", lightify_node_get_blue(node));
352  printf(" %-3d |", lightify_node_get_white(node));
353  printf(" %c |\n", lightify_node_is_stale(node) ? '*' :' ');
354  }
355 
356  if (!count) {
357  printf("no nodes found\n");
358  }
359  printf("|------------------|------------------|---------|--------|---------|-----|-----|------|-----|-----|-----|-----|---|\n");
360 }
361 
362 void dump_groups(struct lightify_ctx *ctx) {
363 
364  struct lightify_group *group = NULL;
365  printf("|------------------|----|--------|----------------\n");
366  printf("| Group Name | id | mask | Group members\n");
367  printf("|------------------|----|--------|----------------\n");
368  while ((group = lightify_group_get_next(ctx,group))) {
369  printf("| %-16s | %-2d | 0x%04x |", lightify_group_get_name(group), lightify_group_get_id(group), 1 << (lightify_group_get_id(group)-1));
370  struct lightify_node *node = NULL;
371  while(node = lightify_group_get_next_node(group, node)) printf(" %s", lightify_node_get_name(node));
372  printf("\n");
373  }
374  printf("|------------------|----|--------|----------------\n");
375 }
376 
377 
378 
379 int main(int argc, char *argv[]) {
380  int option_index = 0;
381 
382  int c, err;
383  int n;
384 
385  struct lightify_ctx *ctx;
386 
387  err = lightify_new(&ctx, NULL );
388  if (err < 0) {
389  fprintf(stderr, "Cannot allocate library context\n");
390  exit(1);
391  }
392 
393 
394  while (1) {
395  c = getopt_long(argc, argv, "dc:r:l:n:h:p:01t:w:g:", long_options,
396  &option_index);
397  if (c == -1)
398  break;
399 
400  switch (c) {
401 
402  case '0':
403  if (!host_data) { usage(argv); exit(1); }
404  if (!gonnected) setup_connection(ctx);
405  command_set_0_1(ctx,0);
406  break;
407 
408  case '1':
409  if (!host_data) { usage(argv); exit(1); }
410  if (!gonnected) setup_connection(ctx);
411  command_set_0_1(ctx,1);
412  break;
413 
414  case 'c':
415  if (!host_data || (!name_data && !group_data) ) {
416  usage(argv);
417  exit(1);
418  }
419  if (!gonnected) setup_connection(ctx);
420  command_cct = 1;
421  command_cct_data = strtol(optarg, NULL, 10);
422  command_set_cct(ctx);
423  break;
424 
425  case 'r':
426  if (!host_data || (!name_data && !group_data)) {
427  usage(argv);
428  exit(1);
429  }
430  if (!gonnected) setup_connection(ctx);
431  command_r = 1;
432  sscanf(optarg, "%d,%d,%d,%d", &command_r_r, &command_r_g,
434  command_set_rgbw(ctx);
435  break;
436 
437  case 'l':
438  if (!host_data || (!name_data && !group_data)) {
439  usage(argv);
440  exit(1);
441  }
442  if (!gonnected) setup_connection(ctx);
443  command_l = 1;
444  command_l_data = strtol(optarg, NULL, 10);
445  command_set_lvl(ctx);
446  break;
447 
448  case 'n':
449  name_data = optarg;
450  group_data = NULL;
451  break;
452 
453  case 'h':
454  host_data = optarg;
455  break;
456 
457  case 'p':
458  port = strtol(optarg, NULL, 10);
459  break;
460 
461  case 't':
462  fadetime = strtol(optarg, NULL, 10);
463  break;
464 
465  case 'd': {
466  if (!host_data) {
467  usage(argv);
468  exit(1);
469  }
470  if (!gonnected) setup_connection(ctx);
471  dump_nodes_state(ctx);
472  break;
473  }
474 
475  case 'w': {
476  int tme = strtol(optarg, NULL, 10);
477  struct timespec ts;
478  ts.tv_sec = tme / 10;
479  ts.tv_nsec = (tme % 10 ) * 100 * 1000 * 1000;
480  while (1) {
481  if (0 == nanosleep(&ts,&ts)) break;
482  if (errno != EINTR) break;
483  }
484  }
485  break;
486 
487  case 2: {
488  if (!gonnected) setup_connection(ctx);
489  dump_groups(ctx);
490  break;
491  }
492 
493  case 'g': {
494  if (!gonnected) setup_connection(ctx);
495  group_data = optarg;
496  name_data = NULL;
497  break;
498  }
499 
500  case 0:
501  break;
502  case 1:
503  break;
504 
505  default:
506  //printf("unknown option %c %d", c, c);
507  usage(argv);
508  exit(1);
509  }
510  }
511 
512  return 0;
513 }
char * name
Definition: node.c:61
#define err(ctx, arg...)
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
void command_set_lvl(struct lightify_ctx *ctx)
int main(int argc, char *argv[])
int lightify_skt_setfd(struct lightify_ctx *ctx, int socket)
Definition: socket.c:206
void usage(char *argv[])
struct lightify_node * find_node_per_name(struct lightify_ctx *ctx, const char *name)
LIGHTIFY_EXPORT int lightify_node_request_scan(struct lightify_ctx *ctx)
Definition: context.c:486
const char * lightify_node_get_name(struct lightify_node *node)
Definition: node.c:164
LIGHTIFY_EXPORT int lightify_group_request_onoff(struct lightify_ctx *ctx, struct lightify_group *group, int onoff)
Definition: context.c:1073
int command_l_data
Definition: lightify-util.c:86
LIGHTIFY_EXPORT int lightify_node_request_onoff(struct lightify_ctx *ctx, struct lightify_node *node, int onoff)
Definition: context.c:852
int lightify_node_get_brightness(struct lightify_node *node)
Definition: node.c:274
LIGHTIFY_EXPORT int lightify_group_request_scan(struct lightify_ctx *ctx)
Definition: context.c:977
int command_r
Definition: lightify-util.c:79
uint64_t lightify_node_get_nodeadr(struct lightify_node *node)
Definition: node.c:175
int lightify_node_is_stale(struct lightify_node *node)
Definition: node.c:302
int command_cct_data
Definition: lightify-util.c:77
LIGHTIFY_EXPORT struct lightify_group * lightify_group_get_next(struct lightify_ctx *ctx, struct lightify_group *current)
Definition: groups.c:134
void command_set_rgbw(struct lightify_ctx *ctx)
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
int lightify_node_is_on(struct lightify_node *node)
Definition: node.c:286
int gonnected
LIGHTIFY_EXPORT int lightify_group_get_id(struct lightify_group *grp)
Definition: groups.c:128
int fadetime
Definition: lightify-util.c:98
int command_cct
Definition: lightify-util.c:76
struct lightify_group * find_grp_per_name(struct lightify_ctx *ctx, const char *name)
int command_r_w
Definition: lightify-util.c:83
LIGHTIFY_EXPORT struct lightify_node * lightify_node_get_next(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:385
struct lightify_ctx * ctx
Definition: groups.c:47
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
uint16_t lightify_node_get_grpadr(struct lightify_node *node)
Definition: node.c:197
int command_r_r
Definition: lightify-util.c:80
int port
Definition: lightify-util.c:96
char * host_data
Definition: lightify-util.c:94
void dump_groups(struct lightify_ctx *ctx)
int lightify_node_get_red(struct lightify_node *node)
Definition: node.c:219
LIGHTIFY_EXPORT struct lightify_node * lightify_group_get_next_node(struct lightify_group *grp, struct lightify_node *lastnode)
Definition: groups.c:147
void command_set_0_1(struct lightify_ctx *ctx, int command_on)
int sockfd
int lightify_node_get_cct(struct lightify_node *node)
Definition: node.c:263
const char * decode_lamptype(int type)
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
int lightify_node_get_white(struct lightify_node *node)
Definition: node.c:252
char * group_data
Definition: lightify-util.c:92
int command_r_b
Definition: lightify-util.c:82
int command_l
Definition: lightify-util.c:85
LIGHTIFY_EXPORT int lightify_new(struct lightify_ctx **ctx, void *reserved)
Definition: context.c:428
const char * decode_online_state(int state)
void command_set_cct(struct lightify_ctx *ctx)
void setup_connection(struct lightify_ctx *ctx)
enum lightify_node_type lightify_node_get_lamptype(struct lightify_node *node)
Definition: node.c:208
int command_r_g
Definition: lightify-util.c:81
int lightify_node_get_onlinestate(struct lightify_node *node)
Definition: node.c:297
int lightify_node_get_green(struct lightify_node *node)
Definition: node.c:241
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
char * name
Definition: groups.c:57
int lightify_node_get_blue(struct lightify_node *node)
Definition: node.c:230
void dump_nodes_state(struct lightify_ctx *ctx)
struct lightify_ctx * ctx
Definition: node.c:46
LIGHTIFY_EXPORT const char * lightify_group_get_name(struct lightify_group *grp)
Definition: groups.c:117
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
char * name_data
Definition: lightify-util.c:90
const char * decode_onoff_sate(int state)