liblightify
liblightify++.hpp
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 
40 #ifndef SRC_LIBLIGHTIFY___LIGHTIFY___HPP_
41 #define SRC_LIBLIGHTIFY___LIGHTIFY___HPP_
42 
43 
45 #include <string.h>
46 
47 #include <netdb.h>
48 #include <unistd.h>
49 #include <errno.h>
50 #include <sys/socket.h>
51 #include <netinet/in.h>
52 #include <netinet/ip.h>
53 
55 #undef LIGHTIFY_ALLOW_THROW
56 #ifdef LIGHTIFY_ALLOW_THROW
57 #include <stdexcept>
58 #endif
59 
61  friend class Lightify;
62 protected:
64  struct lightify_node *node) {
65  _ctx = ctx;
66  _node = node;
67  }
68 
69 public:
70  // NOTE: Getters of node information will generally access cached data.
71  // An update from the actual node data has to be explicitly requested.
72  // An exception is the Name: It can only be queried with a scan.
73 
75  const char *GetName(void) const {
76  return lightify_node_get_name(_node);
77  }
78 
80  unsigned long long GetMAC(void) const {
81  return lightify_node_get_nodeadr(_node);
82  }
83 
85  unsigned int GetZoneAdr(void) const{
86  return lightify_node_get_zoneadr(_node);
87  }
88 
90  unsigned int GetGroup(void) const{
91  return lightify_node_get_grpadr(_node);
92  }
93 
96  return lightify_node_get_lamptype(_node);
97  }
98 
100  int GetRed(void) const {
101  return lightify_node_get_red(_node);
102  }
103 
105  int GetBlue(void) const {
106  return lightify_node_get_blue(_node);
107  }
108 
110  int GetGreen(void) const {
111  return lightify_node_get_green(_node);
112  }
113 
115  int GetWhite(void) const {
116  return lightify_node_get_white(_node);
117  }
118 
120  int GetCCT(void) const {
121  return lightify_node_get_cct(_node);
122  }
123 
125  int GetBrightness(void) const {
126  return lightify_node_get_brightness(_node);
127  }
128 
130  int IsOn(void) const {
131  return lightify_node_is_on(_node);
132  }
133 
135  int GetOnlineState(void) const {
136  return lightify_node_get_onlinestate(_node);
137  }
138 
142  int IsStale(void) const {
143  return lightify_node_is_stale(_node);
144  }
145 
146  /* The setter functions actually talk with the nodes.
147  * After setting the values are *not* verified from the hardware,
148  * only the cache will be updated.
149  *
150  * */
151 
153  int TurnOnOff(bool onoff) {
154  return lightify_node_request_onoff(_ctx, _node, onoff);
155  }
156 
164  int SetCCT(int cct, int time) {
165  return lightify_node_request_cct(_ctx, _node, cct, time);
166  }
167 
182  int SetRGBW(int red, int green, int blue, int white, int time) {
183  return lightify_node_request_rgbw(_ctx,_node, red, green, blue, white, time);
184  }
185 
193  int SetBrightness(int level, int time) {
194  return lightify_node_request_brightness(_ctx, _node, level, time);
195  }
196 
205  int UpdateNodeInfo(void) {
206  return lightify_node_request_update(_ctx, _node);
207  }
208 
209 
210 private:
211  Lightify_Node(const Lightify_Node &other) {
212  // No copies!
213  }
214 
215 private:
216  struct lightify_node *_node;
217  struct lightify_ctx *_ctx;
218 };
219 
221  friend class Lightify;
222 protected:
224  struct lightify_group *group) {
225  _ctx = ctx;
226  _group = group;
227  }
228 
229 public:
230  int GetId() {
231  return lightify_group_get_id(_group);
232  }
233 
234  const char *GetName() {
235  return lightify_group_get_name(_group);
236  }
237 
239  int TurnOnOff(bool onoff) {
240  return lightify_group_request_onoff(_ctx, _group, onoff);
241  }
242 
250  int SetCCT(int cct, int time) {
251  return lightify_group_request_cct(_ctx, _group, cct, time);
252  }
253 
268  int SetRGBW(int red, int green, int blue, int white, int time) {
269  return lightify_group_request_rgbw(_ctx,_group, red, green, blue, white, time);
270  }
271 
279  int SetBrightness(int level, int time) {
280  return lightify_group_request_brightness(_ctx, _group, level, time);
281  }
282 
283 
284 private:
285  Lightify_Group(const Lightify_Group &) {
286  // No copies!
287  // Just to avoid warnings..
288  _ctx = NULL; _group = NULL;
289  }
290 
291 
292 
293 private:
294  struct lightify_group *_group;
295  struct lightify_ctx *_ctx;
296 };
297 
304 class Lightify {
305 public:
308  Lightify(const char *host, unsigned int port=4000) {
309  _host = 0;
310  if (host) {
311  _host = strdup(host);
312  }
313  _port = port;
314  _sockfd = -1;
315  _ctx = NULL;
316  _nodesmap = NULL;
317  _groupsmap = NULL;
318  _no_nodes = 0;
319  _no_groups = 0;
320 
321  int err = lightify_new(&_ctx, NULL);
322 #ifdef LIGHTIFY_ALLOW_THROW
323  if (err < 0 || !_ctx) {
324  throw std::bad_alloc;
325  }
326 #endif
327  }
328 
329  virtual ~Lightify() {
330  if (_ctx) lightify_free(_ctx);
331  if (_host) free(_host);
332  if (_sockfd != -1) close(_sockfd);
333  _free_nodemap();
334  _free_groupmap();
335  }
336 
339  int Open(void) {
340 
341  if (_sockfd > 0) {
342  int e = Close();
343  if (e < 0) return e;
344  }
345 
346  int err;
347  struct sockaddr_in serv_addr;
348  struct hostent *server;
349 
350  _sockfd = socket(AF_INET, SOCK_STREAM, 0);
351 
352  if (_sockfd < 0) {
353  err = _sockfd;
354  _sockfd = -1;
355  return err;
356  }
357 
358  // FIXME gethostbyname is depreciated.
359  server = gethostbyname(_host);
360  if (server == NULL) {
361  // no such host
362  err = h_errno;
363  if (err >= 0) err = -EHOSTUNREACH;
364  goto err_out;
365  }
366 
367  memset((char *) &serv_addr, 0, sizeof(serv_addr));
368  serv_addr.sin_family = AF_INET;
369  memcpy((char *) &serv_addr.sin_addr.s_addr, (char *) server->h_addr,
370  server->h_length);
371  serv_addr.sin_port = htons(_port);
372 
373  /* Now connect to the server */
374  err = connect(_sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));
375  if (err < 0) {
376  err = -errno;
377  goto err_out;
378  }
379 
380  err = lightify_skt_setfd(_ctx, _sockfd);
381  if (err < 0) {
382  goto err_out;
383  }
384 
385  return 0;
386 
387 err_out:
388  if (_sockfd > 0) Close();
389  return err;
390 
391  }
392 
394  int Close(void) {
395  int i = 20;
396  if (_sockfd == -1) return -EBADF;
398  int local_socketfd = _sockfd;
399  _sockfd = -1;
400  /* Retry interrupted system calls, but with capped iteration count.*/
401  while (--i && 0 != close(local_socketfd)) {
402  if (errno != EINTR) return errno;
403  }
404  if (!i) return -EINTR;
405  return 0;
406  }
407 
410  int ScanNodes(void) {
411 
412  int err;
413  if (_sockfd == -1) return -EBADF;
414  _free_nodemap();
416  if (err < 0) return err;
417 
418  struct lean_nodemap *last_inserted = NULL;
419  struct lightify_node *node = NULL;
420  while(node = lightify_node_get_next(_ctx,node)) {
421  struct lean_nodemap *nm = new lean_nodemap();
422  if (!nm) return -ENOMEM;
423  nm->next = 0;
424  nm->node = new Lightify_Node(_ctx,node);
425  if (!nm->node) {
426  delete nm;
427  return -ENOMEM;
428  }
429 
430  if (!last_inserted) {
431  _nodesmap = nm;
432  } else {
433  last_inserted->next = nm;
434  }
435  last_inserted = nm;
436  _no_nodes ++;
437  }
438  return _no_nodes;
439 
440  }
441 
448  int ScanGroups(void) {
449  int err;
450  if (_sockfd == -1) return -EBADF;
451  _free_groupmap();
453  if (err < 0) return err;
454 
455  struct lean_groupmap *last_inserted = NULL;
456  struct lightify_group *group = NULL;
457  while ( (group = lightify_group_get_next(_ctx, group))) {
458  struct lean_groupmap *gm = new lean_groupmap();
459  if (!gm) return -ENOMEM;
460  gm->next = NULL;
461  gm-> group = new Lightify_Group(_ctx, group);
462  if (!gm->group) {
463  delete gm;
464  return -ENOMEM;
465  }
466 
467  if (!last_inserted) {
468  _groupsmap = gm;
469  } else {
470  last_inserted->next = gm;
471  }
472  last_inserted = gm;
473  _no_groups++;
474  }
475  return _no_groups;
476  }
477 
483  struct lightify_ctx *GetCtx(void) {
484  return _ctx;
485  }
486 
488  int TurnAllOnOff(bool onoff)
489  {
490  return lightify_node_request_onoff(_ctx,NULL,onoff);
491  }
492 
494  Lightify_Node *GetNode(long long mac) {
495  struct lean_nodemap *nm = _nodesmap;
496  while(nm) {
497  if (nm->node->GetMAC() == mac) return nm->node;
498  nm = nm->next;
499  }
500  return NULL;
501  }
502 
508  Lightify_Node* GetNodeAtPosX(int x) const {
509  if (x >= _no_nodes) return NULL;
510  struct lean_nodemap *nm = _nodesmap;
511  while(nm && x--) nm = nm->next;
512  return (nm ? nm->node : NULL);
513  }
514 
520  Lightify_Group* GetGroupAtPosX(int pos) const {
521  if (pos >= _no_groups) return NULL;
522  struct lean_groupmap *gm = _groupsmap;
523  while(pos--) gm = gm->next;
524  return gm->group;
525  }
526 
529  const struct lightify_ctx *GetLightifyContext(void) const {
530  return _ctx;
531  }
532 
538  int IsOpen(void) const
539  {
540  return (_sockfd > 0);
541  }
542 
552  int SetHostname(const char *host, unsigned int port=4000) {
553  if (!host) return -EINVAL;
554  if (port > 0xFFFFUL) return -EINVAL;
555 
556  if (_host) free(_host);
557  _host = strdup(host);
558  if (!_host) return -ENOMEM;
559  return 0;
560  }
561 
562 
563  int GetNodesCount(void) {
564  return _no_nodes;
565  }
566 
567  int GetGroupsCount(void) {
568  return _no_groups;
569  }
570 
571 
572 private:
573  void _free_nodemap(void) {
574  struct lean_nodemap *nmtmp, *nm = _nodesmap;
575  while (nm) {
576  nmtmp = nm->next;
577  delete nm->node;
578  delete nm;
579  nm = nmtmp;
580  }
581  _nodesmap = NULL;
582  _no_nodes = 0;
583  }
584 
585  void _free_groupmap(void) {
586  struct lean_groupmap *gmtmp, *gm = _groupsmap;
587  while (gm) {
588  gmtmp = gm->next;
589  delete gm->group;
590  delete gm;
591  gm = gmtmp;
592  }
593  _groupsmap = NULL;
594  _no_groups = 0;
595  }
596 
597  struct lightify_ctx *_ctx;
598  char *_host;
599  unsigned int _port;
600  int _sockfd;
601 
602  // this is to avoid avoid STL...
603  struct lean_nodemap {
604  struct lean_nodemap *next;
605  Lightify_Node *node;
606  };
607 
608  struct lean_groupmap {
609  struct lean_groupmap *next;
610  Lightify_Group *group;
611  };
612 
613  struct lean_nodemap *_nodesmap;
614  struct lean_groupmap *_groupsmap;
615 
616  int _no_nodes;
617  int _no_groups;
618 };
619 
620 
621 #endif /* SRC_LIBLIGHTIFY___LIGHTIFY___HPP_ */
Lightify_Group * GetGroupAtPosX(int pos) const
#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:959
unsigned long long GetMAC(void) const
int UpdateNodeInfo(void)
int lightify_skt_setfd(struct lightify_ctx *ctx, int socket)
Definition: socket.c:204
LIGHTIFY_EXPORT int lightify_free(struct lightify_ctx *ctx)
Definition: context.c:494
int GetOnlineState(void) const
LIGHTIFY_EXPORT int lightify_node_request_scan(struct lightify_ctx *ctx)
Definition: context.c:505
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:1178
unsigned int GetGroup(void) const
LIGHTIFY_EXPORT int lightify_node_request_onoff(struct lightify_ctx *ctx, struct lightify_node *node, int onoff)
Definition: context.c:922
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:1082
Lightify_Node * GetNode(long long mac)
const struct lightify_ctx * GetLightifyContext(void) const
int GetGroupsCount(void)
Lightify_Group(struct lightify_ctx *ctx, struct lightify_group *group)
const char * GetName(void) const
uint64_t lightify_node_get_nodeadr(struct lightify_node *node)
Definition: node.c:175
int SetCCT(int cct, int time)
int lightify_node_is_stale(struct lightify_node *node)
Definition: node.c:302
LIGHTIFY_EXPORT struct lightify_group * lightify_group_get_next(struct lightify_ctx *ctx, struct lightify_group *current)
Definition: groups.c:134
int Open(void)
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
int lightify_node_is_on(struct lightify_node *node)
Definition: node.c:286
int IsOpen(void) const
LIGHTIFY_EXPORT int lightify_group_get_id(struct lightify_group *grp)
Definition: groups.c:128
int IsOn(void) const
int GetCCT(void) const
struct lightify_ctx * _ctx
Definition: test-lightify.c:40
int GetNodesCount(void)
int ScanNodes(void)
int GetGreen(void) const
Lightify_Node(struct lightify_ctx *ctx, struct lightify_node *node)
int Close(void)
LIGHTIFY_EXPORT struct lightify_node * lightify_node_get_next(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:402
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
int IsStale(void) const
Lightify(const char *host, unsigned int port=4000)
uint16_t lightify_node_get_grpadr(struct lightify_node *node)
Definition: node.c:197
int port
Definition: lightify-util.c:97
int TurnOnOff(bool onoff)
int ScanGroups(void)
int lightify_node_get_red(struct lightify_node *node)
Definition: node.c:219
int SetBrightness(int level, int time)
struct lightify_ctx * GetCtx(void)
int lightify_node_get_cct(struct lightify_node *node)
Definition: node.c:263
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
int GetWhite(void) const
int lightify_node_get_white(struct lightify_node *node)
Definition: node.c:252
lightify_node_type
Definition: liblightify.h:105
int GetRed(void) const
int SetCCT(int cct, int time)
Lightify_Node * GetNodeAtPosX(int x) const
int SetRGBW(int red, int green, int blue, int white, int time)
Enable the use of exception within this wrapper.
int GetBrightness(void) const
LIGHTIFY_EXPORT int lightify_new(struct lightify_ctx **ctx, void *reserved)
Definition: context.c:445
int TurnOnOff(bool onoff)
enum lightify_node_type lightify_node_get_lamptype(struct lightify_node *node)
Definition: node.c:208
int lightify_node_get_onlinestate(struct lightify_node *node)
Definition: node.c:297
LIGHTIFY_EXPORT int lightify_node_request_update(struct lightify_ctx *ctx, struct lightify_node *node)
Definition: context.c:987
int SetHostname(const char *host, unsigned int port=4000)
int lightify_node_get_green(struct lightify_node *node)
Definition: node.c:241
int TurnAllOnOff(bool onoff)
unsigned int GetZoneAdr(void) const
const char * GetName()
lightify_node_type GetLampType(void) const
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
int lightify_node_get_blue(struct lightify_node *node)
Definition: node.c:230
int SetRGBW(int red, int green, int blue, int white, int time)
virtual ~Lightify()
LIGHTIFY_EXPORT const char * lightify_group_get_name(struct lightify_group *grp)
Definition: groups.c:117
int SetBrightness(int level, int time)
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
uint16_t lightify_node_get_zoneadr(struct lightify_node *node)
Definition: node.c:186
int GetBlue(void) const