e9b1fb47d5b3f94494705e0804fbf03f4391e5f3
[platform/upstream/iotivity.git] / android / examples / simpleserver / src / main / java / org / iotivity / base / examples / Light.java
1 /*
2  * //******************************************************************
3  * //
4  * // Copyright 2015 Intel Corporation.
5  * //
6  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7  * //
8  * // Licensed under the Apache License, Version 2.0 (the "License");
9  * // you may not use this file except in compliance with the License.
10  * // You may obtain a copy of the License at
11  * //
12  * //      http://www.apache.org/licenses/LICENSE-2.0
13  * //
14  * // Unless required by applicable law or agreed to in writing, software
15  * // distributed under the License is distributed on an "AS IS" BASIS,
16  * // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * // See the License for the specific language governing permissions and
18  * // limitations under the License.
19  * //
20  * //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21  */
22 package org.iotivity.base.examples;
23
24 import android.content.Context;
25 import android.content.Intent;
26 import android.util.Log;
27
28 import org.iotivity.base.EntityHandlerResult;
29 import org.iotivity.base.ErrorCode;
30 import org.iotivity.base.ObservationInfo;
31 import org.iotivity.base.OcException;
32 import org.iotivity.base.OcPlatform;
33 import org.iotivity.base.OcRepresentation;
34 import org.iotivity.base.OcResource;
35 import org.iotivity.base.OcResourceHandle;
36 import org.iotivity.base.OcResourceRequest;
37 import org.iotivity.base.OcResourceResponse;
38 import org.iotivity.base.RequestHandlerFlag;
39 import org.iotivity.base.RequestType;
40 import org.iotivity.base.ResourceProperty;
41
42 import java.util.EnumSet;
43 import java.util.LinkedList;
44 import java.util.List;
45 import java.util.Map;
46
47 /**
48  * Light
49  * <p/>
50  * This class represents a light resource
51  */
52 public class Light implements OcPlatform.EntityHandler {
53     private static final String NAME_KEY = "name";
54     private static final String STATE_KEY = "state";
55     private static final String POWER_KEY = "power";
56
57     private String mResourceUri;                //resource URI
58     private String mResourceTypeName;           //resource type name.
59     private String mResourceInterface;          //resource interface.
60     private OcResourceHandle mResourceHandle;   //resource handle
61
62     private String mName;                       //light name
63     private boolean mState;                     //light state
64     private int mPower;                         //light power
65
66     public Light(String resourceUri, String name, boolean state, int power) {
67         mResourceUri = resourceUri;
68         mResourceTypeName = "core.light";
69         mResourceInterface = OcPlatform.DEFAULT_INTERFACE;
70         mResourceHandle = null; //this is set when resource is registered
71
72         mName = name;
73         mState = state;
74         mPower = power;
75     }
76
77     public synchronized void registerResource() throws OcException {
78         if (null == mResourceHandle) {
79             mResourceHandle = OcPlatform.registerResource(
80                     mResourceUri,
81                     mResourceTypeName,
82                     mResourceInterface,
83                     this,
84                     EnumSet.of(ResourceProperty.DISCOVERABLE, ResourceProperty.OBSERVABLE)
85             );
86         }
87     }
88
89     /**
90      * NOTE: This is just a sample implementation of entity handler. Entity handler can be
91      * implemented in several ways by the manufacturer.
92      *
93      * @param request
94      * @return
95      */
96     @Override
97     public synchronized EntityHandlerResult handleEntity(final OcResourceRequest request) {
98         EntityHandlerResult ehResult = EntityHandlerResult.ERROR;
99         if (null == request) {
100             msg("Server request is invalid");
101             return ehResult;
102         }
103         // Get the request flags
104         EnumSet<RequestHandlerFlag> requestFlags = request.getRequestHandlerFlagSet();
105         if (requestFlags.contains(RequestHandlerFlag.INIT)) {
106             msg("\t\tRequest Flag: Init");
107             ehResult = EntityHandlerResult.OK;
108         }
109         if (requestFlags.contains(RequestHandlerFlag.REQUEST)) {
110             msg("\t\tRequest Flag: Request");
111             ehResult = handleRequest(request);
112         }
113         if (requestFlags.contains(RequestHandlerFlag.OBSERVER)) {
114             msg("\t\tRequest Flag: Observer");
115             ehResult = handleObserver(request);
116         }
117         return ehResult;
118     }
119
120     private EntityHandlerResult handleRequest(OcResourceRequest request) {
121         EntityHandlerResult ehResult = EntityHandlerResult.ERROR;
122         // Check for query params (if any)
123         Map<String, String> queries = request.getQueryParameters();
124         if (!queries.isEmpty()) {
125             msg("Query processing is up to entityHandler");
126         } else {
127             msg("No query parameters in this request");
128         }
129
130         for (Map.Entry<String, String> entry : queries.entrySet()) {
131             msg("Query key: " + entry.getKey() + " value: " + entry.getValue());
132         }
133
134         //Get the request type
135         RequestType requestType = request.getRequestType();
136         switch (requestType) {
137             case GET:
138                 msg("\t\t\tRequest Type is GET");
139                 ehResult = handleGetRequest(request);
140                 break;
141             case PUT:
142                 msg("\t\t\tRequest Type is PUT");
143                 ehResult = handlePutRequest(request);
144                 break;
145             case POST:
146                 msg("\t\t\tRequest Type is POST");
147                 ehResult = handlePostRequest(request);
148                 break;
149             case DELETE:
150                 msg("\t\t\tRequest Type is DELETE");
151                 ehResult = handleDeleteRequest();
152                 break;
153         }
154         return ehResult;
155     }
156
157     private EntityHandlerResult handleGetRequest(final OcResourceRequest request) {
158         EntityHandlerResult ehResult;
159         OcResourceResponse response = new OcResourceResponse();
160         response.setRequestHandle(request.getRequestHandle());
161         response.setResourceHandle(request.getResourceHandle());
162
163         if (mIsSlowResponse) { // Slow response case
164             new Thread(new Runnable() {
165                 public void run() {
166                     handleSlowResponse(request);
167                 }
168             }).start();
169             ehResult = EntityHandlerResult.SLOW;
170         } else { // normal response case.
171             response.setErrorCode(SUCCESS);
172             response.setResponseResult(EntityHandlerResult.OK);
173             response.setResourceRepresentation(getOcRepresentation());
174             ehResult = sendResponse(response);
175         }
176         return ehResult;
177     }
178
179     private EntityHandlerResult handlePutRequest(OcResourceRequest request) {
180         OcResourceResponse response = new OcResourceResponse();
181         response.setRequestHandle(request.getRequestHandle());
182         response.setResourceHandle(request.getResourceHandle());
183
184         setOcRepresentation(request.getResourceRepresentation());
185         response.setResourceRepresentation(getOcRepresentation());
186         response.setResponseResult(EntityHandlerResult.OK);
187         response.setErrorCode(SUCCESS);
188         return sendResponse(response);
189     }
190
191     private static int sUriCounter = 1;
192     private EntityHandlerResult handlePostRequest(OcResourceRequest request) {
193         OcResourceResponse response = new OcResourceResponse();
194         response.setRequestHandle(request.getRequestHandle());
195         response.setResourceHandle(request.getResourceHandle());
196         String newUri = "/a/light" + (++sUriCounter);
197         if(null != mContext && mContext instanceof SimpleServer) {
198             ((SimpleServer) mContext).createNewLightResource(newUri, "John's light " + sUriCounter);
199         }
200         OcRepresentation rep_post = getOcRepresentation();
201         try {
202             rep_post.setValue(OcResource.CREATED_URI_KEY, newUri);
203         } catch (OcException e) {
204             Log.e(TAG, e.toString());
205         }
206         response.setResourceRepresentation(rep_post);
207         response.setErrorCode(SUCCESS);
208         response.setNewResourceUri(newUri);
209         response.setResponseResult(EntityHandlerResult.RESOURCE_CREATED);
210         return sendResponse(response);
211     }
212
213     private EntityHandlerResult handleDeleteRequest() {
214         try {
215             this.unregisterResource();
216             return EntityHandlerResult.RESOURCE_DELETED;
217         } catch (OcException e) {
218             Log.e(TAG, e.toString());
219             msg("Failed to unregister a light resource");
220             return EntityHandlerResult.ERROR;
221         }
222     }
223
224     private void handleSlowResponse(OcResourceRequest request) {
225         sleep(10);
226         msg("Sending slow response...");
227         OcResourceResponse response = new OcResourceResponse();
228         response.setRequestHandle(request.getRequestHandle());
229         response.setResourceHandle(request.getResourceHandle());
230
231         response.setErrorCode(SUCCESS);
232         response.setResponseResult(EntityHandlerResult.OK);
233         response.setResourceRepresentation(getOcRepresentation());
234         sendResponse(response);
235     }
236
237     private List<Byte> mObservationIds; //IDs of observes
238
239     private EntityHandlerResult handleObserver(final OcResourceRequest request) {
240         ObservationInfo observationInfo = request.getObservationInfo();
241         switch (observationInfo.getObserveAction()) {
242             case REGISTER:
243                 if (null == mObservationIds) {
244                     mObservationIds = new LinkedList<>();
245                 }
246                 mObservationIds.add(observationInfo.getOcObservationId());
247                 break;
248             case UNREGISTER:
249                 mObservationIds.remove((Byte)observationInfo.getOcObservationId());
250                 break;
251         }
252         // Observation happens on a different thread in notifyObservers method.
253         // If we have not created the thread already, we will create one here.
254         if (null == mObserverNotifier) {
255             mObserverNotifier = new Thread(new Runnable() {
256                 public void run() {
257                     notifyObservers(request);
258                 }
259             });
260             mObserverNotifier.start();
261         }
262         return EntityHandlerResult.OK;
263     }
264
265     private void notifyObservers(OcResourceRequest request) {
266         while (true) {
267             // increment current power value by 10 every 2 seconds
268             mPower += 10;
269             sleep(2);
270
271             msg("Notifying observers...");
272             msg(this.toString());
273             try {
274                 if (mIsListOfObservers) {
275                     OcResourceResponse response = new OcResourceResponse();
276                     response.setErrorCode(SUCCESS);
277                     response.setResourceRepresentation(getOcRepresentation());
278                     OcPlatform.notifyListOfObservers(
279                             mResourceHandle,
280                             mObservationIds,
281                             response);
282                 } else {
283                     OcPlatform.notifyAllObservers(mResourceHandle);
284                 }
285             } catch (OcException e) {
286                 ErrorCode errorCode = e.getErrorCode();
287                 if (ErrorCode.NO_OBSERVERS == errorCode) {
288                     msg("No more observers, stopping notifications");
289                 }
290                 return;
291             }
292         }
293     }
294
295     private EntityHandlerResult sendResponse(OcResourceResponse response) {
296         try {
297             OcPlatform.sendResponse(response);
298             return EntityHandlerResult.OK;
299         } catch (OcException e) {
300             Log.e(TAG, e.toString());
301             msg("Failed to send response");
302             return EntityHandlerResult.ERROR;
303         }
304     }
305
306     public synchronized void unregisterResource() throws OcException {
307         if (null != mResourceHandle) {
308             OcPlatform.unregisterResource(mResourceHandle);
309         }
310     }
311
312     public void setOcRepresentation(OcRepresentation rep) {
313         try {
314             if (rep.hasAttribute(NAME_KEY)) mName = rep.getValue(NAME_KEY);
315             if (rep.hasAttribute(STATE_KEY)) mState = rep.getValue(STATE_KEY);
316             if (rep.hasAttribute(POWER_KEY)) mPower = rep.getValue(POWER_KEY);
317         } catch (OcException e) {
318             Log.e(TAG, e.toString());
319             msg("Failed to get representation values");
320         }
321     }
322
323     public OcRepresentation getOcRepresentation() {
324         OcRepresentation rep = new OcRepresentation();
325         try {
326             rep.setValue(NAME_KEY, mName);
327             rep.setValue(STATE_KEY, mState);
328             rep.setValue(POWER_KEY, mPower);
329         } catch (OcException e) {
330             Log.e(TAG, e.toString());
331             msg("Failed to set representation values");
332         }
333         return rep;
334     }
335
336     //******************************************************************************
337     // End of the OIC specific code
338     //******************************************************************************
339
340     public void setSlowResponse(boolean isSlowResponse) {
341         mIsSlowResponse = isSlowResponse;
342     }
343
344     public void useListOfObservers(boolean isListOfObservers) {
345         mIsListOfObservers = isListOfObservers;
346     }
347
348     public void setContext(Context context) {
349         mContext = context;
350     }
351
352     @Override
353     public String toString() {
354         return "\t" + "URI" + ": " + mResourceUri +
355                 "\n\t" + NAME_KEY + ": " + mName +
356                 "\n\t" + STATE_KEY + ": " + mState +
357                 "\n\t" + POWER_KEY + ": " + mPower;
358     }
359
360     private void sleep(int seconds) {
361         try {
362             Thread.sleep(seconds * 1000);
363         } catch (InterruptedException e) {
364             e.printStackTrace();
365             Log.e(TAG, e.toString());
366         }
367     }
368
369     private void msg(String text) {
370         if (null != mContext) {
371             Intent intent = new Intent("org.iotivity.base.examples.simpleserver");
372             intent.putExtra("message", text);
373             mContext.sendBroadcast(intent);
374         }
375     }
376
377     private final static String TAG = Light.class.getSimpleName();
378     private final static int SUCCESS = 200;
379     private boolean mIsSlowResponse = false;
380     private boolean mIsListOfObservers = false;
381     private Thread mObserverNotifier;
382     private Context mContext;
383 }