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