Contiki 3.x
ipso-leds-control.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015, Yanzi Networks AB.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /**
32  * \addtogroup ipso-objects
33  * @{
34  *
35  */
36 
37 /**
38  * \file
39  * Implementation of OMA LWM2M / IPSO Light Control for LEDs
40  * \author
41  * Joakim Eriksson <joakime@sics.se>
42  * Niclas Finne <nfi@sics.se>
43  */
44 
45 #include "lwm2m-object.h"
46 #include "lwm2m-engine.h"
47 #include "er-coap-engine.h"
48 #include "dev/leds.h"
49 #include <stdint.h>
50 
51 #define DEBUG 0
52 #if DEBUG
53 #include <stdio.h>
54 #define PRINTF(...) printf(__VA_ARGS__)
55 #else
56 #define PRINTF(...)
57 #endif
58 
59 #if LEDS_ALL & LEDS_BLUE || LEDS_ALL & LEDS_RED || LEDS_ALL & LEDS_BLUE
60 #define LEDS_CONTROL_NUMBER (((LEDS_ALL & LEDS_BLUE) ? 1 : 0) + ((LEDS_ALL & LEDS_RED) ? 1 : 0) + ((LEDS_ALL & LEDS_GREEN) ? 1 : 0))
61 #else
62 #define LEDS_CONTROL_NUMBER 1
63 #endif
64 
65 struct led_state {
66  unsigned long last_on_time;
67  uint32_t total_on_time;
68  uint8_t is_on;
69  uint8_t led_value;
70 };
71 
72 static struct led_state states[LEDS_CONTROL_NUMBER];
73 static lwm2m_instance_t leds_control_instances[LEDS_CONTROL_NUMBER];
74 /*---------------------------------------------------------------------------*/
75 static int
76 read_state(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
77 {
78  uint8_t idx = ctx->object_instance_index;
79  if(idx >= LEDS_CONTROL_NUMBER) {
80  return 0;
81  }
82  return ctx->writer->write_boolean(ctx, outbuf, outsize,
83  states[idx].is_on ? 1 : 0);
84 }
85 /*---------------------------------------------------------------------------*/
86 static int
87 write_state(lwm2m_context_t *ctx, const uint8_t *inbuf, size_t insize,
88  uint8_t *outbuf, size_t outsize)
89 {
90  int value;
91  size_t len;
92 
93  uint8_t idx = ctx->object_instance_index;
94  if(idx >= LEDS_CONTROL_NUMBER) {
95  return 0;
96  }
97 
98  len = ctx->reader->read_boolean(ctx, inbuf, insize, &value);
99  if(len > 0) {
100  if(value) {
101  if(!states[idx].is_on) {
102  states[idx].is_on = 1;
103  states[idx].last_on_time = clock_seconds();
104 #if PLATFORM_HAS_LEDS
105  leds_on(states[idx].led_value);
106 #endif /* PLATFORM_HAS_LEDS */
107  }
108  } else if(states[idx].is_on) {
109  states[idx].total_on_time += clock_seconds() - states[idx].last_on_time;
110  states[idx].is_on = 0;
111 #if PLATFORM_HAS_LEDS
112  leds_off(states[idx].led_value);
113 #endif /* PLATFORM_HAS_LEDS */
114  }
115  } else {
116  PRINTF("IPSO leds control - ignored illegal write to on/off\n");
117  }
118  return len;
119 }
120 /*---------------------------------------------------------------------------*/
121 static char *
122 get_color(int value) {
123  switch(value) {
124  case LEDS_GREEN:
125  return "Green";
126  case LEDS_RED:
127  return "Red";
128  case LEDS_BLUE:
129  return "Blue";
130  }
131  return "None";
132 }
133 
134 static int
135 read_color(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
136 {
137  char *value;
138  uint8_t idx = ctx->object_instance_index;
139  if(idx >= LEDS_CONTROL_NUMBER) {
140  return 0;
141  }
142  value = get_color(states[idx].led_value);
143  return ctx->writer->write_string(ctx, outbuf, outsize,
144  value, strlen(value));
145 }
146 /*---------------------------------------------------------------------------*/
147 static int
148 read_on_time(lwm2m_context_t *ctx, uint8_t *outbuf, size_t outsize)
149 {
150  unsigned long now;
151  uint8_t idx = ctx->object_instance_index;
152  if(idx >= LEDS_CONTROL_NUMBER) {
153  return 0;
154  }
155 
156  if(states[idx].is_on) {
157  /* Update the on time */
158  now = clock_seconds();
159  states[idx].total_on_time += now - states[idx].last_on_time;
160  states[idx].last_on_time = now;
161  }
162  return ctx->writer->write_int(ctx, outbuf, outsize,
163  (int32_t)states[idx].total_on_time);
164 }
165 /*---------------------------------------------------------------------------*/
166 static int
167 write_on_time(lwm2m_context_t *ctx,
168  const uint8_t *inbuf, size_t insize,
169  uint8_t *outbuf, size_t outsize)
170 {
171  int32_t value;
172  size_t len;
173  uint8_t idx = ctx->object_instance_index;
174  if(idx >= LEDS_CONTROL_NUMBER) {
175  return 0;
176  }
177 
178  len = ctx->reader->read_int(ctx, inbuf, insize, &value);
179  if(len > 0 && value == 0) {
180  PRINTF("IPSO leds control - reset On Time\n");
181  states[idx].total_on_time = 0;
182  if(states[idx].is_on) {
183  states[idx].last_on_time = clock_seconds();
184  }
185  } else {
186  PRINTF("IPSO leds control - ignored illegal write to On Time\n");
187  }
188  return len;
189 }
190 /*---------------------------------------------------------------------------*/
191 LWM2M_RESOURCES(leds_control_resources,
192  LWM2M_RESOURCE_CALLBACK(5850, { read_state, write_state, NULL }),
193  LWM2M_RESOURCE_CALLBACK(5706, { read_color, NULL, NULL }),
194  LWM2M_RESOURCE_CALLBACK(5852, { read_on_time, write_on_time, NULL })
195  );
196 LWM2M_OBJECT(leds_control, 3311, leds_control_instances);
197 /*---------------------------------------------------------------------------*/
198 static int
199 bit_no(int bit)
200 {
201  int i;
202  for(i = 0; i < 8; i++) {
203  if(LEDS_ALL & (1 << i)) {
204  if(bit == 0) {
205  /* matching bit */
206  return 1 << i;
207  } else {
208  /* matching but used */
209  bit--;
210  }
211  }
212  }
213  return 0;
214 }
215 
216 void
217 ipso_leds_control_init(void)
218 {
219  lwm2m_instance_t template = LWM2M_INSTANCE(0, leds_control_resources);
220  int i;
221 
222  /* Initialize the instances */
223  for(i = 0; i < LEDS_CONTROL_NUMBER; i++) {
224  leds_control_instances[i] = template;
225  leds_control_instances[i].id = i;
226  states[i].led_value = bit_no(i);
227  }
228 
229  /* register this device and its handlers - the handlers automatically
230  sends in the object to handle */
231  lwm2m_engine_register_object(&leds_control);
232  PRINTF("IPSO leds control initialized with %u instances\n",
233  LEDS_CONTROL_NUMBER);
234 }
235 /*---------------------------------------------------------------------------*/
236 /** @} */
Header file for the Contiki OMA LWM2M object API
Header file for the Contiki OMA LWM2M engine
#define NULL
The null pointer.
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
Definition: clock.c:54
CoAP implementation for the REST Engine.