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