added error callback listener in FindResource for Android
[platform/upstream/iotivity.git] / android / examples / simplebase / src / main / java / org / iotivity / base / examples / MessageFragment.java
1 /*
2  * ******************************************************************
3  *
4  * Copyright 2016 Samsung Electronics All Rights Reserved.
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
23 package org.iotivity.base.examples;
24
25 import android.app.Activity;
26 import android.app.AlertDialog;
27 import android.app.Fragment;
28 import android.content.Context;
29 import android.content.DialogInterface;
30 import android.content.Intent;
31 import android.nfc.NfcAdapter;
32 import android.os.Bundle;
33 import android.util.Log;
34 import android.view.LayoutInflater;
35 import android.view.View;
36 import android.view.ViewGroup;
37 import android.widget.Button;
38 import android.widget.CompoundButton;
39 import android.widget.EditText;
40 import android.widget.LinearLayout;
41 import android.widget.TextView;
42 import android.widget.Toast;
43 import android.widget.ToggleButton;
44
45 import org.iotivity.base.EntityHandlerResult;
46 import org.iotivity.base.ModeType;
47 import org.iotivity.base.OcConnectivityType;
48 import org.iotivity.base.OcException;
49 import org.iotivity.base.OcHeaderOption;
50 import org.iotivity.base.OcPlatform;
51 import org.iotivity.base.OcRepresentation;
52 import org.iotivity.base.OcResource;
53 import org.iotivity.base.OcResourceHandle;
54 import org.iotivity.base.OcResourceRequest;
55 import org.iotivity.base.OcResourceResponse;
56 import org.iotivity.base.PlatformConfig;
57 import org.iotivity.base.QualityOfService;
58 import org.iotivity.base.ServiceType;
59 import org.iotivity.ca.CaEdrInterface;
60 import org.iotivity.ca.CaIpInterface;
61 import org.iotivity.ca.CaLeClientInterface;
62
63 import java.io.PrintWriter;
64 import java.io.StringWriter;
65 import java.util.ArrayList;
66 import java.util.EnumSet;
67 import java.util.HashMap;
68 import java.util.List;
69 import java.util.Map;
70
71 /**
72  * This class is for messaging between the server and the client.
73  * It can handle message manually.
74  */
75 public class MessageFragment extends Fragment implements OcResource.OnGetListener,
76                                                          OcResource.OnPutListener {
77
78     private static final String TAG          = "OIC_SIMPLE_MESSAGE";
79     private final String        EOL          = System.getProperties().getProperty("line.separator");
80     private final double        MILLI_PER_SEC = 1000.0;
81
82     private Activity            mActivity;
83     private Context             mContext;
84
85     OcPlatform.EntityHandler    mEntityHandler;
86     private OcResourceHandle    mResourceHandle;
87     private OcResource          mFoundResource;
88
89     private QualityOfService    mQos         = QualityOfService.LOW;
90
91     private LinearLayout        mServerLayout;
92     private LinearLayout        mClientLayout;
93     private TextView            mResourceText;
94     private TextView            mActionLog;
95     private TextView            mResultLog;
96     private ToggleButton        mQosToggle;
97     private Button              mRegisterButton;
98     private Button              mGetButton;
99     private Button              mPutButton;
100     private Button              mLargeButton;
101     private Button              mDiscoverIPButton;
102     private Button              mDiscoverBTButton;
103     private Button              mDiscoverLEButton;
104     private Button              mDiscoverTCPButton;
105     private Button              mDiscoverNFCButton;
106
107     private String              mLargeData;
108     private boolean             mState;
109     private long                mStartTime;
110     private long                mEndTime;
111
112     @Override
113     public void onCreate(Bundle savedInstanceState) {
114         super.onCreate(savedInstanceState);
115
116         mActivity = getActivity();
117         mContext = mActivity.getBaseContext();
118     }
119
120     View.OnClickListener getButtonListener() {
121         return new View.OnClickListener() {
122             @Override
123             public void onClick(View view) {
124                 if (mFoundResource != null) {
125                     mStartTime = System.currentTimeMillis();
126                     sendGetToFoundResource(Common.STATE_GET);
127                 } else {
128                     Common.showToast(mContext, "Please discovery first");
129                     Log.e(TAG, "get() : resource is null");
130                 }
131             }
132         };
133     }
134
135     View.OnClickListener putButtonListener() {
136         return new View.OnClickListener() {
137             @Override
138             public void onClick(View view) {
139                 if (mFoundResource != null) {
140                     mStartTime = System.currentTimeMillis();
141                     sendPutToFoundResource();
142                 } else {
143                     Common.showToast(mContext, "Please discovery first");
144                     Log.e(TAG, "put() : resource is null");
145                 }
146             }
147         };
148     }
149
150     View.OnClickListener getLargeListener() {
151         return new View.OnClickListener() {
152             @Override
153             public void onClick(View view) {
154                 if (mFoundResource != null) {
155                     mStartTime = System.currentTimeMillis();
156                     sendGetToFoundResource(Common.LARGE_GET);
157                 } else {
158                     Common.showToast(mContext, "Please discovery first");
159                     Log.e(TAG, "large() : resource is null");
160                 }
161             }
162         };
163     }
164
165     View.OnClickListener discoverButtonListener(
166             final OcConnectivityType connectivityType) {
167         return new View.OnClickListener() {
168             @Override
169             public void onClick(View view) {
170                 initOcPlatform(ModeType.CLIENT);
171                 mFoundResource = null;
172
173                 if (OcConnectivityType.CT_ADAPTER_TCP == connectivityType) {
174                     showTCPInput();
175                 } else {
176                     try {
177                         Log.i(TAG, "discoverButtonListener");
178                         OcPlatform.findResource("",
179                                                 OcPlatform.WELL_KNOWN_QUERY,
180                                                 EnumSet.of(connectivityType),
181                                                 resourceFoundListener, mQos);
182
183                         mActivity.runOnUiThread(new Runnable() {
184                             @Override
185                             public void run() {
186                                 mActionLog.setText("[Action Log]" + EOL);
187                                 mActionLog.append("Find resource()" + EOL);
188                                 mActionLog.append("Connectivity : " + connectivityType + EOL);
189
190                                 mResultLog.setText("[Result Log]" + EOL);
191                                 mResultLog.append("Start Time : ");
192                                 mResultLog.append(Common.getDateCurrentTimeZone() + EOL);
193                                 mStartTime = System.currentTimeMillis();
194                             }
195                         });
196                     } catch (OcException e) {
197                         e.printStackTrace();
198                     }
199                 }
200                 mServerLayout.setVisibility(View.GONE);
201             }
202         };
203     }
204
205     void makeTCPResource(String address) {
206
207         List<String> resourceTypeList = new ArrayList<String>();
208         List<String> resourceInterfaceList = new ArrayList<String>();
209         resourceInterfaceList.add(Common.RESOURCE_INTERFACE);
210         resourceTypeList.add(Common.RESOURCE_TYPE);
211         try {
212             mFoundResource = OcPlatform.constructResourceObject(address,
213                     Common.RESOURCE_URI,
214                     EnumSet.of(OcConnectivityType.CT_ADAPTER_TCP), false,
215                     resourceTypeList, resourceInterfaceList);
216
217             mActionLog.setText("[Action Log]" + EOL);
218             mActionLog.append("Found resource()" + EOL);
219             mActionLog.append("Connectivity : " + OcConnectivityType.CT_ADAPTER_TCP + EOL);
220             mActionLog.append(mFoundResource.getHost() + Common.RESOURCE_URI);
221
222             mResultLog.setText("[Result Log]" + EOL);
223
224         } catch (OcException e) {
225             e.printStackTrace();
226         }
227     }
228
229     void sendGetToFoundResource(String command) {
230         try {
231             Log.i(TAG, "sendGetToFoundResource");
232
233             Map<String, String> queryParameters = new HashMap<String, String>();
234             queryParameters.put(Common.GET_COMMAND, command);
235
236             mFoundResource.get(queryParameters, this, mQos);
237
238             mActionLog.setText("[Action Log]" + EOL + "Send get()"+ EOL + "To : ");
239             mActionLog.append(mFoundResource.getHost() + mFoundResource.getUri() + EOL);
240         } catch (OcException e) {
241             e.printStackTrace();
242         }
243     }
244
245     void sendPutToFoundResource() {
246         try {
247             Log.i(TAG, "sendPutToFoundResource");
248
249             OcRepresentation rep = new OcRepresentation();
250             rep.setValue(Common.STATE_KEY, !mState);
251
252             Map<String, String> queryParams = new HashMap<>();
253
254             mFoundResource.put(rep, queryParams, this);
255             mActionLog.setText("[Action Log]" + EOL);
256             mActionLog.append("Send put()" + EOL + "To : ");
257             mActionLog.append(mFoundResource.getHost() + mFoundResource.getUri() + EOL);
258         } catch (OcException e) {
259             e.printStackTrace();
260         }
261     }
262
263     OcPlatform.OnResourceFoundListener resourceFoundListener =
264                                            new OcPlatform.OnResourceFoundListener() {
265         @Override
266         public void onResourceFound(OcResource ocResource) {
267             synchronized (mActivity) {
268                 final String resourceUri = ocResource.getUri();
269                 Log.i(TAG, "onResourceFound : " + ocResource.getUri());
270
271                 if (resourceUri.contains(Common.RESOURCE_URI)) {
272                     mFoundResource = ocResource;
273                     mActivity.runOnUiThread(new Runnable() {
274                         @Override
275                         public void run() {
276                             mEndTime = System.currentTimeMillis();
277                             double flightTime = (double) (mEndTime - mStartTime) / MILLI_PER_SEC;
278                             mResultLog.append("Discovery Time : ");
279                             mResultLog.append(String.format("%.3f", flightTime) + "sec" + EOL);
280                             mActionLog.append(mFoundResource.getHost() + resourceUri + EOL);
281                         }
282                     });
283                 }
284             }
285         }
286
287         @Override
288         public void onFindResourceFailed(Throwable throwable, String uri) {
289             synchronized (mActivity) {
290                 Log.i(TAG, "findResource request has failed");
291                 Log.e(TAG, throwable.toString());
292             }
293         }
294     };
295
296     @Override
297     public void onGetCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
298         String repUri = ocRepresentation.getUri();
299         Log.i(TAG, "onGetCompleted : " + repUri);
300
301         try {
302             final String command = ocRepresentation.getValue(Common.GET_COMMAND);
303
304             if (command == null || command.isEmpty()) {
305                 Log.e(TAG, "Get command is null");
306                 return;
307             } else if (command.equals(Common.STATE_GET)) {
308                 mState = ocRepresentation.getValue(Common.STATE_KEY);
309                 mLargeData = "";
310             } else if (command.equals(Common.LARGE_GET)) {
311                 mLargeData = ocRepresentation.getValue(Common.LARGE_KEY);
312             }
313         } catch (OcException e) {
314             e.printStackTrace();
315         }
316
317         mActivity.runOnUiThread(new Runnable() {
318             @Override
319             public void run() {
320                 mEndTime = System.currentTimeMillis();
321                 double flightTime = (double) (mEndTime - mStartTime) / MILLI_PER_SEC;
322
323                 if (mLargeData == null || mLargeData.isEmpty()) {
324                     mResultLog.append(EOL + "Get Light State : " + mState + EOL);
325                 } else {
326                     mResultLog.append(EOL + "Payload Size : " + mLargeData.length() + EOL);
327                 }
328
329                 mResultLog.append("Get Time : " + String.format("%.3f", flightTime) + "sec" + EOL);
330             }
331         });
332     }
333
334     @Override
335     public void onGetFailed(Throwable throwable) {
336         Log.e(TAG, "Get failed");
337     }
338
339     @Override
340     public void onPutCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
341         String repUri = ocRepresentation.getUri();
342         Log.i(TAG, "onPutCompleted : " + repUri);
343
344         try {
345             mState = ocRepresentation.getValue(Common.STATE_KEY);
346         } catch (OcException e) {
347             e.printStackTrace();
348         }
349
350         mActivity.runOnUiThread(new Runnable() {
351             @Override
352             public void run() {
353                 mEndTime = System.currentTimeMillis();
354                 double flightTime = (double) (mEndTime - mStartTime) / MILLI_PER_SEC;
355                 mResultLog.append(EOL + "Set Light State : " + !mState + EOL + "Put Time : ");
356                 mResultLog.append(String.format("%.3f", flightTime) + "sec" + EOL);
357             }
358         });
359     }
360
361     @Override
362     public void onPutFailed(Throwable throwable) {
363         Log.e(TAG, "Put failed");
364     }
365
366     // ******************************************************************************
367     // End of the OCF Client specific code
368     // ******************************************************************************
369
370     private void createResource() {
371         mEntityHandler = new OcPlatform.EntityHandler() {
372             @Override
373             public EntityHandlerResult handleEntity(
374                     OcResourceRequest ocResourceRequest) {
375                 return mEntityHandler(ocResourceRequest);
376             }
377         };
378
379         try {
380             mResourceHandle = OcPlatform.registerResource(Common.RESOURCE_URI,
381                                  Common.RESOURCE_TYPE, Common.RESOURCE_INTERFACE,
382                                  mEntityHandler, Common.RESOURCE_PROPERTIES);
383
384         } catch (OcException e) {
385             String errString = "Error : " + e.getErrorCode().toString();
386             Log.e(TAG, errString);
387             StringWriter sw = new StringWriter();
388             e.printStackTrace(new PrintWriter(sw));
389             String exceptionAsString = sw.toString();
390             Log.e(TAG, exceptionAsString);
391             mResourceText.setText(errString);
392         }
393
394         StringBuilder sb = new StringBuilder();
395         for (int i = 0; i < Common.DATA_SIZE; i++) {
396             sb.append('j');
397         }
398         mLargeData = sb.toString();
399
400         sb.setLength(0);
401         sb.append("URI :   " + Common.RESOURCE_URI + EOL);
402         sb.append("Type :   " + Common.RESOURCE_TYPE + EOL);
403         sb.append("Interface :   " + Common.RESOURCE_INTERFACE + EOL);
404         sb.append("Properties :   " + Common.RESOURCE_PROPERTIES.toString() + EOL);
405         mResourceText.setText(sb.toString());
406         mActionLog.setText("");
407         mResultLog.setText("Created resource" + EOL);
408     }
409
410     protected EntityHandlerResult mEntityHandler(OcResourceRequest ocResourceRequest) {
411         EntityHandlerResult result = EntityHandlerResult.ERROR;
412         final StringBuilder sb = new StringBuilder();
413         switch (ocResourceRequest.getRequestType()) {
414             case GET:
415                 sb.append("Type :   GET");
416                 if (sendGetResponse(ocResourceRequest)) {
417                     result = EntityHandlerResult.OK;
418                 }
419                 break;
420             case PUT:
421                 sb.append("Type :   PUT");
422                 if (sendPutResponse(ocResourceRequest)) {
423                     result = EntityHandlerResult.OK;
424                 }
425                 break;
426             case DELETE:
427                 sb.append("Type :   DELETE");
428                 break;
429             case POST:
430                 sb.append("Type :   POST");
431                 break;
432             default:
433                 break;
434         }
435         sb.append(EOL + "Light State :   " + mState);
436         sb.append(EOL + "Time :   " + Common.getDateCurrentTimeZone());
437         if (result == EntityHandlerResult.ERROR) {
438             sb.append(EOL + "!! Error occurred during sending the response !!");
439         }
440
441         mActivity.runOnUiThread(new Runnable() {
442             @Override
443             public void run() {
444                 mResultLog.setText(sb.toString());
445             }
446         });
447
448         return result;
449     }
450
451     private boolean sendGetResponse(OcResourceRequest ocResourceRequest) {
452         mActivity.runOnUiThread(new Runnable() {
453             @Override
454             public void run() {
455                 Common.showToast(mContext, "received get command, send response");
456             }
457         });
458
459         Map<String, String> queryParameters = ocResourceRequest.getQueryParameters();
460         final String command = queryParameters.get(Common.GET_COMMAND);
461
462         if (command == null
463                 || (!command.equals(Common.STATE_GET) && !command.equals(Common.LARGE_GET))) {
464             return false;
465         }
466
467         OcRepresentation rep = new OcRepresentation();
468         try {
469             rep.setValue(Common.GET_COMMAND, command);
470             if (command.equals(Common.STATE_GET)) {
471                 rep.setValue(Common.STATE_KEY, mState);
472             } else if (command.equals(Common.LARGE_GET)) {
473                 rep.setValue(Common.LARGE_KEY, mLargeData);
474             }
475         } catch (OcException e) {
476             e.printStackTrace();
477         }
478
479         OcResourceResponse response = new OcResourceResponse();
480
481         response.setRequestHandle(ocResourceRequest.getRequestHandle());
482         response.setResourceHandle(ocResourceRequest.getResourceHandle());
483         response.setResourceRepresentation(rep);
484         try {
485             OcPlatform.sendResponse(response);
486             return true;
487         } catch (OcException e) {
488             e.printStackTrace();
489             return false;
490         }
491     }
492
493     private boolean sendPutResponse(OcResourceRequest ocResourceRequest) {
494         mActivity.runOnUiThread(new Runnable() {
495             @Override
496             public void run() {
497                 Common.showToast(mContext, "received put command, send response");
498             }
499         });
500
501         try {
502             OcRepresentation rep = ocResourceRequest.getResourceRepresentation();
503             if (rep.hasAttribute(Common.STATE_KEY)) {
504                 mState = rep.getValue(Common.STATE_KEY);
505             }
506         } catch (OcException e) {
507             e.printStackTrace();
508         }
509
510         OcResourceResponse response = new OcResourceResponse();
511         OcRepresentation rep = new OcRepresentation();
512
513         response.setRequestHandle(ocResourceRequest.getRequestHandle());
514         response.setResourceHandle(ocResourceRequest.getResourceHandle());
515         response.setResourceRepresentation(rep);
516         try {
517             OcPlatform.sendResponse(response);
518             return true;
519         } catch (OcException e) {
520             e.printStackTrace();
521             return false;
522         }
523     }
524
525     // ******************************************************************************
526     // End of the OCF Server specific code
527     // ******************************************************************************
528
529     private void initOcPlatform(ModeType type) {
530         PlatformConfig cfg = new PlatformConfig(mActivity, mContext,
531                                                 ServiceType.IN_PROC,
532                                                 type,
533                                                 Common.IP_ADDRESS,
534                                                 Common.IP_PORT,
535                                                 mQos);
536         OcPlatform.Configure(cfg);
537     }
538
539     @Override
540     public View onCreateView(LayoutInflater inflater, ViewGroup container,
541             Bundle savedInstanceState) {
542         View rootView = inflater.inflate(R.layout.fragment_message, container, false);
543
544         mServerLayout = (LinearLayout) rootView.findViewById(R.id.server_layout);
545         mClientLayout = (LinearLayout) rootView.findViewById(R.id.client_layout);
546
547         mResourceText = (TextView) rootView.findViewById(R.id.resource_view);
548         mActionLog = (TextView) rootView.findViewById(R.id.action_log_view);
549         mResultLog = (TextView) rootView.findViewById(R.id.result_log_view);
550
551         mDiscoverIPButton = (Button) rootView.findViewById(R.id.ip_button);
552         mDiscoverBTButton = (Button) rootView.findViewById(R.id.bt_button);
553         mDiscoverLEButton = (Button) rootView.findViewById(R.id.le_button);
554         mDiscoverTCPButton = (Button) rootView.findViewById(R.id.tcp_button);
555         mDiscoverNFCButton = (Button) rootView.findViewById(R.id.nfc_button);
556
557         mRegisterButton = (Button) rootView.findViewById(R.id.register_button);
558         mGetButton = (Button) rootView.findViewById(R.id.get_button);
559         mPutButton = (Button) rootView.findViewById(R.id.put_button);
560         mLargeButton = (Button) rootView.findViewById(R.id.large_button);
561
562         mQosToggle = (ToggleButton) rootView.findViewById(R.id.qos_toggle_button);
563
564         mDiscoverIPButton.setOnClickListener(
565                 discoverButtonListener(OcConnectivityType.CT_ADAPTER_IP));
566         mDiscoverBTButton.setOnClickListener(
567                 discoverButtonListener(OcConnectivityType.CT_ADAPTER_RFCOMM_BTEDR));
568         mDiscoverLEButton.setOnClickListener(
569                 discoverButtonListener(OcConnectivityType.CT_ADAPTER_GATT_BTLE));
570         mDiscoverTCPButton.setOnClickListener(
571                 discoverButtonListener(OcConnectivityType.CT_ADAPTER_TCP));
572         mDiscoverNFCButton.setOnClickListener(
573                 discoverButtonListener(OcConnectivityType.CT_ADAPTER_NFC));
574
575         mRegisterButton.setOnClickListener(new View.OnClickListener() {
576             @Override
577             public void onClick(View view) {
578                 if (mResourceHandle == null) {
579                     initOcPlatform(ModeType.SERVER);
580                     createResource();
581                     mClientLayout.setVisibility(View.GONE);
582                 } else {
583                     Common.showToast(mContext, "Already created resource");
584                 }
585             }
586         });
587         mGetButton.setOnClickListener(getButtonListener());
588         mPutButton.setOnClickListener(putButtonListener());
589         mLargeButton.setOnClickListener(getLargeListener());
590
591         mQosToggle
592                 .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
593                     @Override
594                     public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
595                         if (b) {
596                             mQos = QualityOfService.HIGH;
597                         } else {
598                             mQos = QualityOfService.LOW;
599                         }
600                     }
601                 });
602
603         return rootView;
604     }
605
606     private void showTCPInput() {
607
608         LayoutInflater layoutInflater = LayoutInflater.from(mContext);
609         View inputView = layoutInflater.inflate(R.layout.tcp_input, null);
610         AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mActivity);
611         alertDialogBuilder.setView(inputView);
612
613         final EditText editText = (EditText) inputView.getRootView().findViewById(R.id.ipText);
614         editText.setText(Common.TCP_ADDRESS);
615         alertDialogBuilder
616                 .setCancelable(false)
617                 .setPositiveButton("OK", new DialogInterface.OnClickListener() {
618                     public void onClick(DialogInterface dialog, int id) {
619                         if (editText.getText().length() != 0) {
620                             Common.TCP_ADDRESS = editText.getText().toString();
621
622                             StringBuilder sb = new StringBuilder();
623                             sb.append(Common.COAP_TCP);
624                             sb.append(Common.TCP_ADDRESS);
625                             sb.append(Common.TCP_PORT);
626                             makeTCPResource(sb.toString());
627                         }
628                     }
629                 })
630                 .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
631                     public void onClick(DialogInterface dialog, int id) {
632                         dialog.cancel();
633                     }
634                 });
635
636         AlertDialog alert = alertDialogBuilder.create();
637         alert.show();
638     }
639
640     @Override
641     public void onResume() {
642         super.onResume();
643     }
644
645     @Override
646     public void onDestroy() {
647         super.onDestroy();
648     }
649 }