Temp. fix for the IOT-826
[platform/upstream/iotivity.git] / android / examples / simpleclient / src / main / java / org / iotivity / base / examples / SimpleClient.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.app.Activity;
25 import android.content.Context;
26 import android.os.Bundle;
27 import android.text.method.ScrollingMovementMethod;
28 import android.util.Log;
29 import android.view.View;
30 import android.widget.Button;
31 import android.widget.ScrollView;
32 import android.widget.TextView;
33
34 import org.iotivity.base.ErrorCode;
35 import org.iotivity.base.ModeType;
36 import org.iotivity.base.ObserveType;
37 import org.iotivity.base.OcConnectivityType;
38 import org.iotivity.base.OcException;
39 import org.iotivity.base.OcHeaderOption;
40 import org.iotivity.base.OcPlatform;
41 import org.iotivity.base.OcRepresentation;
42 import org.iotivity.base.OcResource;
43 import org.iotivity.base.OcResourceIdentifier;
44 import org.iotivity.base.PlatformConfig;
45 import org.iotivity.base.QualityOfService;
46 import org.iotivity.base.ServiceType;
47
48 import java.util.EnumSet;
49 import java.util.HashMap;
50 import java.util.List;
51 import java.util.Map;
52
53 /**
54  * SimpleClient
55  * <p/>
56  * SimpleClient is a sample client app which should be started after the simpleServer is started.
57  * It finds resources advertised by the server and calls different operations on it (GET, PUT,
58  * POST, DELETE and OBSERVE).
59  */
60 public class SimpleClient extends Activity implements
61         OcPlatform.OnResourceFoundListener,
62         OcResource.OnGetListener,
63         OcResource.OnPutListener,
64         OcResource.OnPostListener,
65         OcResource.OnObserveListener {
66
67     private Map<OcResourceIdentifier, OcResource> mFoundResources = new HashMap<>();
68     private OcResource mFoundLightResource = null;
69     //local representation of a server's light resource
70     private Light mLight = new Light();
71
72     /**
73      * A local method to configure and initialize platform, and then search for the light resources.
74      */
75     private void startSimpleClient() {
76         Context context = this;
77
78         PlatformConfig platformConfig = new PlatformConfig(
79                 context,
80                 ServiceType.IN_PROC,
81                 ModeType.CLIENT,
82                 "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
83                 0,         // Uses randomly available port
84                 QualityOfService.LOW
85         );
86
87         msg("Configuring platform.");
88         OcPlatform.Configure(platformConfig);
89
90         try {
91             msg("Finding all resources of type \"core.light\".");
92             String requestUri = OcPlatform.WELL_KNOWN_QUERY + "?rt=core.light";
93             OcPlatform.findResource("",
94                     requestUri,
95                     EnumSet.of(OcConnectivityType.CT_DEFAULT),
96                     this
97             );
98             sleep(1);
99
100             /*Find resource is done twice so that we discover the original resources a second time.
101             These resources will have the same uniqueidentifier (yet be different objects),
102             so that we can verify/show the duplicate-checking code in foundResource(above);
103              */
104             msg("Finding all resources of type \"core.light\" for the second time");
105             OcPlatform.findResource("",
106                     requestUri,
107                     EnumSet.of(OcConnectivityType.CT_DEFAULT),
108                     this
109             );
110
111         } catch (OcException e) {
112             Log.e(TAG, e.toString());
113             msg("Failed to invoke find resource API");
114         }
115
116         printLine();
117     }
118
119     /**
120      * An event handler to be executed whenever a "findResource" request completes successfully
121      *
122      * @param ocResource found resource
123      */
124     @Override
125     public synchronized void onResourceFound(OcResource ocResource) {
126         if (null == ocResource) {
127             msg("Found resource is invalid");
128             return;
129         }
130
131         if (mFoundResources.containsKey(ocResource.getUniqueIdentifier())) {
132             msg("Found a previously seen resource again!");
133         } else {
134             msg("Found resource for the first time on server with ID: " + ocResource.getServerId());
135             mFoundResources.put(ocResource.getUniqueIdentifier(), ocResource);
136         }
137
138         if (null != mFoundLightResource) {
139             msg("Found another resource, ignoring");
140             return;
141         }
142         // Get the resource URI
143         String resourceUri = ocResource.getUri();
144         // Get the resource host address
145         String hostAddress = ocResource.getHost();
146         msg("\tURI of the resource: " + resourceUri);
147         msg("\tHost address of the resource: " + hostAddress);
148         // Get the resource types
149         msg("\tList of resource types: ");
150         for (String resourceType : ocResource.getResourceTypes()) {
151             msg("\t\t" + resourceType);
152         }
153         msg("\tList of resource interfaces:");
154         for (String resourceInterface : ocResource.getResourceInterfaces()) {
155             msg("\t\t" + resourceInterface);
156         }
157         msg("\tList of resource connectivity types:");
158         for (OcConnectivityType connectivityType : ocResource.getConnectivityTypeSet()) {
159             msg("\t\t" + connectivityType);
160         }
161         printLine();
162
163         //In this example we are only interested in the light resources
164         if (resourceUri.equals("/a/light")) {
165             //Assign resource reference to a global variable to keep it from being
166             //destroyed by the GC when it is out of scope.
167             mFoundLightResource = ocResource;
168
169             // Call a local method which will internally invoke "get" API on the foundLightResource
170             getLightResourceRepresentation();
171         }
172     }
173
174     /**
175      * Local method to get representation of a found light resource
176      */
177     private void getLightResourceRepresentation() {
178         msg("Getting Light Representation...");
179
180         Map<String, String> queryParams = new HashMap<>();
181         try {
182             // Invoke resource's "get" API with a OcResource.OnGetListener event
183             // listener implementation
184             sleep(1);
185             mFoundLightResource.get(queryParams, this);
186         } catch (OcException e) {
187             Log.e(TAG, e.toString());
188             msg("Error occurred while invoking \"get\" API");
189         }
190     }
191
192     /**
193      * An event handler to be executed whenever a "get" request completes successfully
194      *
195      * @param list             list of the header options
196      * @param ocRepresentation representation of a resource
197      */
198     @Override
199     public synchronized void onGetCompleted(List<OcHeaderOption> list,
200                                             OcRepresentation ocRepresentation) {
201         msg("GET request was successful");
202         msg("Resource URI: " + ocRepresentation.getUri());
203
204         try {
205             //Read attribute values into local representation of a light
206             mLight.setOcRepresentation(ocRepresentation);
207         } catch (OcException e) {
208             Log.e(TAG, e.toString());
209             msg("Failed to read the attributes of a light resource");
210         }
211         msg("Light attributes: ");
212         msg(mLight.toString());
213         printLine();
214
215         //Call a local method which will internally invoke put API on the foundLightResource
216         putLightRepresentation();
217     }
218
219     /**
220      * An event handler to be executed whenever a "get" request fails
221      *
222      * @param throwable exception
223      */
224     @Override
225     public synchronized void onGetFailed(Throwable throwable) {
226         if (throwable instanceof OcException) {
227             OcException ocEx = (OcException) throwable;
228             Log.e(TAG, ocEx.toString());
229             ErrorCode errCode = ocEx.getErrorCode();
230             //do something based on errorCode
231             msg("Error code: " + errCode);
232         }
233         msg("Failed to get representation of a found light resource");
234     }
235
236     /**
237      * Local method to put a different state for this light resource
238      */
239     private void putLightRepresentation() {
240         //set new values
241         mLight.setState(true);
242         mLight.setPower(15);
243
244         msg("Putting light representation...");
245         OcRepresentation representation = null;
246         try {
247             representation = mLight.getOcRepresentation();
248         } catch (OcException e) {
249             Log.e(TAG, e.toString());
250             msg("Failed to get OcRepresentation from a light");
251         }
252
253         Map<String, String> queryParams = new HashMap<>();
254
255         try {
256             sleep(1);
257             // Invoke resource's "put" API with a new representation, query parameters and
258             // OcResource.OnPutListener event listener implementation
259             mFoundLightResource.put(representation, queryParams, this);
260         } catch (OcException e) {
261             Log.e(TAG, e.toString());
262             msg("Error occurred while invoking \"put\" API");
263         }
264     }
265
266     /**
267      * An event handler to be executed whenever a "put" request completes successfully
268      *
269      * @param list             list of the header options
270      * @param ocRepresentation representation of a resource
271      */
272     @Override
273     public synchronized void onPutCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
274         msg("PUT request was successful");
275         try {
276             mLight.setOcRepresentation(ocRepresentation);
277         } catch (OcException e) {
278             Log.e(TAG, e.toString());
279             msg("Failed to create Light representation");
280         }
281         msg("Light attributes: ");
282         msg(mLight.toString());
283         printLine();
284
285         //Call a local method which will internally invoke post API on the foundLightResource
286         postLightRepresentation();
287     }
288
289     /**
290      * An event handler to be executed whenever a "put" request fails
291      *
292      * @param throwable exception
293      */
294     @Override
295     public synchronized void onPutFailed(Throwable throwable) {
296         if (throwable instanceof OcException) {
297             OcException ocEx = (OcException) throwable;
298             Log.e(TAG, ocEx.toString());
299             ErrorCode errCode = ocEx.getErrorCode();
300             //do something based on errorCode
301             msg("Error code: " + errCode);
302         }
303         msg("Failed to \"put\" a new representation");
304     }
305
306     /**
307      * Local method to post a different state for this light resource
308      */
309     private void postLightRepresentation() {
310         //set new values
311         mLight.setState(false);
312         mLight.setPower(105);
313
314         msg("Posting light representation...");
315         OcRepresentation representation = null;
316         try {
317             representation = mLight.getOcRepresentation();
318         } catch (OcException e) {
319             Log.e(TAG, e.toString());
320             msg("Failed to get OcRepresentation from a light");
321         }
322
323         Map<String, String> queryParams = new HashMap<>();
324         try {
325             sleep(1);
326             // Invoke resource's "post" API with a new representation, query parameters and
327             // OcResource.OnPostListener event listener implementation
328             mFoundLightResource.post(representation, queryParams, this);
329         } catch (OcException e) {
330             Log.e(TAG, e.toString());
331             msg("Error occurred while invoking \"post\" API");
332         }
333     }
334
335     /**
336      * An event handler to be executed whenever a "post" request completes successfully
337      *
338      * @param list             list of the header options
339      * @param ocRepresentation representation of a resource
340      */
341     @Override
342     public synchronized void onPostCompleted(List<OcHeaderOption> list,
343                                              OcRepresentation ocRepresentation) {
344         msg("POST request was successful");
345         try {
346             if (ocRepresentation.hasAttribute(OcResource.CREATED_URI_KEY)) {
347                 msg("\tUri of the created resource: " +
348                         ocRepresentation.getValue(OcResource.CREATED_URI_KEY));
349             } else {
350                 mLight.setOcRepresentation(ocRepresentation);
351                 msg(mLight.toString());
352             }
353         } catch (OcException e) {
354             Log.e(TAG, e.toString());
355         }
356
357         //setting new values
358         mLight.setState(true);
359         mLight.setPower(55);
360         msg("Posting again light representation...");
361         OcRepresentation representation2 = null;
362         try {
363             representation2 = mLight.getOcRepresentation();
364         } catch (OcException e) {
365             Log.e(TAG, e.toString());
366             msg("Failed to get OcRepresentation from a light");
367         }
368
369         Map<String, String> queryParams = new HashMap<>();
370         try {
371             // Invoke resource's "post" API with a new representation, query parameters and
372             // OcResource.OnPostListener event listener implementation
373             mFoundLightResource.post(representation2, queryParams, onPostListener2);
374         } catch (OcException e) {
375             Log.e(TAG, e.toString());
376             msg("Error occurred while invoking \"post\" API");
377         }
378     }
379
380     /**
381      * An event handler to be executed whenever a "post" request fails
382      *
383      * @param throwable exception
384      */
385     @Override
386     public synchronized void onPostFailed(Throwable throwable) {
387         if (throwable instanceof OcException) {
388             OcException ocEx = (OcException) throwable;
389             Log.e(TAG, ocEx.toString());
390             ErrorCode errCode = ocEx.getErrorCode();
391             //do something based on errorCode
392             msg("Error code: " + errCode);
393         }
394         msg("Failed to \"post\" a new representation");
395     }
396
397     /**
398      * Declare and implement a second OcResource.OnPostListener
399      */
400     OcResource.OnPostListener onPostListener2 = new OcResource.OnPostListener() {
401         /**
402          * An event handler to be executed whenever a "post" request completes successfully
403          * @param list             list of the header options
404          * @param ocRepresentation representation of a resource
405          */
406         @Override
407         public synchronized void onPostCompleted(List<OcHeaderOption> list,
408                                                  OcRepresentation ocRepresentation) {
409             msg("Second POST request was successful");
410             try {
411                 if (ocRepresentation.hasAttribute(OcResource.CREATED_URI_KEY)) {
412                     msg("\tUri of the created resource: " +
413                             ocRepresentation.getValue(OcResource.CREATED_URI_KEY));
414                 } else {
415                     mLight.setOcRepresentation(ocRepresentation);
416                     msg(mLight.toString());
417                 }
418             } catch (OcException e) {
419                 Log.e(TAG, e.toString());
420             }
421
422             //Call a local method which will internally invoke observe API on the foundLightResource
423             observeFoundLightResource();
424         }
425
426         /**
427          * An event handler to be executed whenever a "post" request fails
428          *
429          * @param throwable exception
430          */
431         @Override
432         public synchronized void onPostFailed(Throwable throwable) {
433             if (throwable instanceof OcException) {
434                 OcException ocEx = (OcException) throwable;
435                 Log.e(TAG, ocEx.toString());
436                 ErrorCode errCode = ocEx.getErrorCode();
437                 //do something based on errorCode
438                 msg("Error code: " + errCode);
439             }
440             msg("Failed to \"post\" a new representation");
441         }
442     };
443
444     /**
445      * Local method to start observing this light resource
446      */
447     private void observeFoundLightResource() {
448         try {
449             sleep(1);
450             // Invoke resource's "observe" API with a observe type, query parameters and
451             // OcResource.OnObserveListener event listener implementation
452             mFoundLightResource.observe(ObserveType.OBSERVE, new HashMap<String, String>(), this);
453         } catch (OcException e) {
454             Log.e(TAG, e.toString());
455             msg("Error occurred while invoking \"observe\" API");
456         }
457     }
458
459     // holds current number of observations
460     private static int mObserveCount = 0;
461
462     /**
463      * An event handler to be executed whenever a "post" request completes successfully
464      *
465      * @param list             list of the header options
466      * @param ocRepresentation representation of a resource
467      * @param sequenceNumber   sequence number
468      */
469     @Override
470     public synchronized void onObserveCompleted(List<OcHeaderOption> list,
471                                                 OcRepresentation ocRepresentation,
472                                                 int sequenceNumber) {
473         if (OcResource.OnObserveListener.REGISTER == sequenceNumber) {
474             msg("Observe registration action is successful:");
475         } else if (OcResource.OnObserveListener.DEREGISTER == sequenceNumber) {
476             msg("Observe De-registration action is successful");
477         } else if (OcResource.OnObserveListener.NO_OPTION == sequenceNumber) {
478             msg("Observe registration or de-registration action is failed");
479         }
480
481         msg("OBSERVE Result:");
482         msg("\tSequenceNumber:" + sequenceNumber);
483         try {
484             mLight.setOcRepresentation(ocRepresentation);
485         } catch (OcException e) {
486             Log.e(TAG, e.toString());
487             msg("Failed to get the attribute values");
488         }
489         msg(mLight.toString());
490
491         if ((++mObserveCount) == 11) {
492             msg("Cancelling Observe...");
493             try {
494                 mFoundLightResource.cancelObserve();
495             } catch (OcException e) {
496                 Log.e(TAG, e.toString());
497                 msg("Error occurred while invoking \"cancelObserve\" API");
498             }
499             msg("DONE");
500
501             //prepare for the next restart of the SimpleClient
502             resetGlobals();
503             enableStartButton();
504         }
505     }
506
507     /**
508      * An event handler to be executed whenever a "observe" request fails
509      *
510      * @param throwable exception
511      */
512     @Override
513     public synchronized void onObserveFailed(Throwable throwable) {
514         if (throwable instanceof OcException) {
515             OcException ocEx = (OcException) throwable;
516             Log.e(TAG, ocEx.toString());
517             ErrorCode errCode = ocEx.getErrorCode();
518             //do something based on errorCode
519             msg("Error code: " + errCode);
520         }
521         msg("Observation of the found light resource has failed");
522     }
523
524     //******************************************************************************
525     // End of the OIC specific code
526     //******************************************************************************
527
528     private final static String TAG = SimpleClient.class.getSimpleName();
529     private TextView mConsoleTextView;
530     private ScrollView mScrollView;
531
532     protected void onCreate(Bundle savedInstanceState) {
533         super.onCreate(savedInstanceState);
534         setContentView(R.layout.activity_simple_client);
535
536         mConsoleTextView = (TextView) findViewById(R.id.consoleTextView);
537         mConsoleTextView.setMovementMethod(new ScrollingMovementMethod());
538         mScrollView = (ScrollView) findViewById(R.id.scrollView);
539         mScrollView.fullScroll(View.FOCUS_DOWN);
540         final Button button = (Button) findViewById(R.id.button);
541
542         if (null == savedInstanceState) {
543             button.setOnClickListener(new View.OnClickListener() {
544                 @Override
545                 public void onClick(View v) {
546                     button.setText("Re-start");
547                     button.setEnabled(false);
548                     new Thread(new Runnable() {
549                         public void run() {
550                             startSimpleClient();
551                         }
552                     }).start();
553                 }
554             });
555         } else {
556             String consoleOutput = savedInstanceState.getString("consoleOutputString");
557             mConsoleTextView.setText(consoleOutput);
558         }
559     }
560
561     @Override
562     protected void onSaveInstanceState(Bundle outState) {
563         super.onSaveInstanceState(outState);
564         outState.putString("consoleOutputString", mConsoleTextView.getText().toString());
565     }
566
567     @Override
568     protected void onRestoreInstanceState(Bundle savedInstanceState) {
569         super.onRestoreInstanceState(savedInstanceState);
570
571         String consoleOutput = savedInstanceState.getString("consoleOutputString");
572         mConsoleTextView.setText(consoleOutput);
573     }
574
575     private void enableStartButton() {
576         runOnUiThread(new Runnable() {
577             public void run() {
578                 Button button = (Button) findViewById(R.id.button);
579                 button.setEnabled(true);
580             }
581         });
582     }
583
584     private void sleep(int seconds) {
585         try {
586             Thread.sleep(seconds * 1000);
587         } catch (InterruptedException e) {
588             e.printStackTrace();
589             Log.e(TAG, e.toString());
590         }
591     }
592
593     private void msg(final String text) {
594         runOnUiThread(new Runnable() {
595             public void run() {
596                 mConsoleTextView.append("\n");
597                 mConsoleTextView.append(text);
598                 mScrollView.fullScroll(View.FOCUS_DOWN);
599             }
600         });
601         Log.i(TAG, text);
602     }
603
604     private void printLine() {
605         msg("------------------------------------------------------------------------");
606     }
607
608     private synchronized void resetGlobals() {
609         mFoundLightResource = null;
610         mFoundResources.clear();
611         mLight = new Light();
612         mObserveCount = 0;
613     }
614 }