--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":simpleclientblescan" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="examples" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="android-gradle" name="Android-Gradle">
+ <configuration>
+ <option name="GRADLE_PROJECT_PATH" value=":simpleclientblescan" />
+ </configuration>
+ </facet>
+ <facet type="android" name="Android">
+ <configuration>
+ <option name="SELECTED_BUILD_VARIANT" value="debug" />
+ <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
+ <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
+ <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
+ <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
+ <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
+ <afterSyncTasks>
+ <task>generateDebugAndroidTestSources</task>
+ <task>generateDebugSources</task>
+ </afterSyncTasks>
+ <option name="ALLOW_USER_CONFIGURATION" value="false" />
+ <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
+ <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
+ <option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
+ <option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
+ <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
+ <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
+ <excludeFolder url="file://$MODULE_DIR$/build/reports" />
+ <excludeFolder url="file://$MODULE_DIR$/build/test-results" />
+ <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
+ </content>
+ <orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="library" exported="" name="iotivity-base-armeabi-release-" level="project" />
+ <orderEntry type="library" exported="" name="android-android-21" level="project" />
+ </component>
+</module>
--- /dev/null
+/*
+ *******************************************************************
+ *
+ * Copyright 2015 Intel Corporation.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ */
+package org.iotivity.base.examples;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.BroadcastReceiver;
+import android.content.IntentFilter;
+import android.nfc.NfcAdapter;
+import android.os.Bundle;
+import android.text.method.ScrollingMovementMethod;
+import android.util.Log;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.ScrollView;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.os.ParcelUuid;
+import android.os.Handler;
+import android.text.TextUtils;
+
+import org.iotivity.base.ErrorCode;
+import org.iotivity.base.ModeType;
+import org.iotivity.base.ObserveType;
+import org.iotivity.base.OcConnectivityType;
+import org.iotivity.base.OcException;
+import org.iotivity.base.OcHeaderOption;
+import org.iotivity.base.OcPlatform;
+import org.iotivity.base.OcRepresentation;
+import org.iotivity.base.OcResource;
+import org.iotivity.base.OcResourceIdentifier;
+import org.iotivity.base.PlatformConfig;
+import org.iotivity.base.QualityOfService;
+import org.iotivity.base.ServiceType;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+import java.nio.charset.Charset;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
+
+/**
+ * SimpleClientBleScan
+ * <p/>
+ * SimpleClientBleScan is a sample client app which should be started after the simpleServer is started.
+ * It finds resources advertised by the server and calls different operations on it (GET, PUT,
+ * POST, DELETE and OBSERVE).
+ */
+public class SimpleClientBleScan extends Activity implements
+ OcPlatform.OnResourceFoundListener,
+ OcResource.OnGetListener,
+ OcResource.OnPutListener,
+ OcResource.OnPostListener,
+ OcResource.OnObserveListener {
+
+ private Map<OcResourceIdentifier, OcResource> mFoundResources = new HashMap<>();
+ private OcResource mFoundLightResource = null;
+ //local representation of a server's light resource
+ private Light mLight = new Light();
+ //variables related observer
+ private int maxSequenceNumber = 0xFFFFFF;
+ private OcConnectivityType adapterFlag = OcConnectivityType.CT_ADAPTER_IP;
+ //flags related TCP transport test
+ private boolean isRequestFlag = false;
+ private boolean isTCPContained = false;
+
+ /**
+ * A local method to configure and initialize platform, and then search for the light resources.
+ */
+ private void startSimpleClientBleScan(OcConnectivityType type, String device_addr) {
+ Context context = this;
+ adapterFlag = type;
+
+ PlatformConfig platformConfig = new PlatformConfig(
+ this,
+ context,
+ ServiceType.IN_PROC,
+ ModeType.CLIENT,
+ "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
+ 0, // Uses randomly available port
+ QualityOfService.LOW
+ );
+ msg("Configuring platform.");
+ OcPlatform.Configure(platformConfig);
+
+ try {
+ msg("Finding all resources of type \"core.light\".");
+ msg("Setting Device address: " + device_addr);
+ String requestUri = OcPlatform.WELL_KNOWN_QUERY + "?rt=core.light";
+ OcPlatform.findResource(device_addr,
+ requestUri,
+ EnumSet.of(OcConnectivityType.CT_ADAPTER_GATT_BTLE),
+ this
+ );
+ sleep(1);
+
+ /*Find resource is done twice so that we discover the original resources a second time.
+ These resources will have the same uniqueidentifier (yet be different objects),
+ so that we can verify/show the duplicate-checking code in foundResource(above);
+ */
+ msg("Finding all resources of type \"core.light\" for the second time");
+ OcPlatform.findResource(device_addr,
+ requestUri,
+ EnumSet.of(OcConnectivityType.CT_ADAPTER_GATT_BTLE),
+ this
+ );
+
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Failed to invoke find resource API");
+ }
+
+ printLine();
+ }
+
+ /**
+ * An event handler to be executed whenever a "findResource" request completes successfully
+ *
+ * @param ocResource found resource
+ */
+ @Override
+ public synchronized void onResourceFound(OcResource ocResource) {
+ if (null == ocResource) {
+ msg("Found resource is invalid");
+ return;
+ }
+
+ if (mFoundResources.containsKey(ocResource.getUniqueIdentifier())) {
+ msg("Found a previously seen resource again!");
+ } else {
+ msg("Found resource for the first time on server with ID: " + ocResource.getServerId());
+ mFoundResources.put(ocResource.getUniqueIdentifier(), ocResource);
+ }
+
+ if (null != mFoundLightResource) {
+ if (ocResource.getUri().equals("/a/light")) {
+ if (ocResource.getConnectivityTypeSet().contains(OcConnectivityType.CT_ADAPTER_TCP)) {
+ msg("Found resource which has TCP transport");
+ if (isTCPContained == false)
+ {
+ isTCPContained = true;
+ return;
+ }
+ }
+ }
+ msg("Found another resource, ignoring");
+ return;
+
+ }
+ // Get the resource URI
+ String resourceUri = ocResource.getUri();
+ // Get the resource host address
+ String hostAddress = ocResource.getHost();
+ msg("\tURI of the resource: " + resourceUri);
+ msg("\tHost address of the resource: " + hostAddress);
+ // Get the resource types
+ msg("\tList of resource types: ");
+ for (String resourceType : ocResource.getResourceTypes()) {
+ msg("\t\t" + resourceType);
+ }
+ msg("\tList of resource interfaces:");
+ for (String resourceInterface : ocResource.getResourceInterfaces()) {
+ msg("\t\t" + resourceInterface);
+ }
+ msg("\tList of resource connectivity types:");
+ for (OcConnectivityType connectivityType : ocResource.getConnectivityTypeSet()) {
+ msg("\t\t" + connectivityType);
+ }
+ printLine();
+
+ //In this example we are only interested in the light resources
+ if (resourceUri.equals("/a/light")) {
+ //Assign resource reference to a global variable to keep it from being
+ //destroyed by the GC when it is out of scope.
+ if (OcConnectivityType.CT_ADAPTER_TCP == adapterFlag)
+ {
+ if (ocResource.getConnectivityTypeSet().contains(OcConnectivityType.CT_ADAPTER_TCP))
+ {
+ msg("set mFoundLightResource which has TCP transport");
+ mFoundLightResource = ocResource;
+ // Call a local method which will internally invoke "get" API
+ getLightResourceRepresentation();
+ return;
+ }
+ }
+ else
+ {
+ msg("set mFoundLightResource which has UDP transport");
+ mFoundLightResource = ocResource;
+ // Call a local method which will internally invoke "get" API on the foundLightResource
+ getLightResourceRepresentation();
+ }
+ }
+ }
+
+ @Override
+ public synchronized void onFindResourceFailed(Throwable throwable, String uri) {
+ msg("findResource request has failed");
+ Log.e(TAG, throwable.toString());
+ }
+
+ /**
+ * Local method to get representation of a found light resource
+ */
+ private void getLightResourceRepresentation() {
+ msg("Getting Light Representation...");
+
+ Map<String, String> queryParams = new HashMap<>();
+ try {
+ // Invoke resource's "get" API with a OcResource.OnGetListener event
+ // listener implementation
+ sleep(1);
+ mFoundLightResource.get(queryParams, this);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Error occurred while invoking \"get\" API");
+ }
+ }
+
+ /**
+ * An event handler to be executed whenever a "get" request completes successfully
+ *
+ * @param list list of the header options
+ * @param ocRepresentation representation of a resource
+ */
+ @Override
+ public synchronized void onGetCompleted(List<OcHeaderOption> list,
+ OcRepresentation ocRepresentation) {
+ msg("GET request was successful");
+ msg("Resource URI: " + ocRepresentation.getUri());
+
+ try {
+ //Read attribute values into local representation of a light
+ mLight.setOcRepresentation(ocRepresentation);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Failed to read the attributes of a light resource");
+ }
+ msg("Light attributes: ");
+ msg(mLight.toString());
+ printLine();
+
+ //Call a local method which will internally invoke put API on the foundLightResource
+ putLightRepresentation();
+ }
+
+ /**
+ * An event handler to be executed whenever a "get" request fails
+ *
+ * @param throwable exception
+ */
+ @Override
+ public synchronized void onGetFailed(Throwable throwable) {
+ if (throwable instanceof OcException) {
+ OcException ocEx = (OcException) throwable;
+ Log.e(TAG, ocEx.toString());
+ ErrorCode errCode = ocEx.getErrorCode();
+ //do something based on errorCode
+ msg("Error code: " + errCode);
+ }
+ msg("Failed to get representation of a found light resource");
+ }
+
+ /**
+ * Local method to put a different state for this light resource
+ */
+ private void putLightRepresentation() {
+ //set new values
+ mLight.setState(true);
+ mLight.setPower(15);
+
+ msg("Putting light representation...");
+ OcRepresentation representation = null;
+ try {
+ representation = mLight.getOcRepresentation();
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Failed to get OcRepresentation from a light");
+ }
+
+ Map<String, String> queryParams = new HashMap<>();
+
+ try {
+ sleep(1);
+ // Invoke resource's "put" API with a new representation, query parameters and
+ // OcResource.OnPutListener event listener implementation
+ mFoundLightResource.put(representation, queryParams, this);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Error occurred while invoking \"put\" API");
+ }
+ }
+
+ /**
+ * An event handler to be executed whenever a "put" request completes successfully
+ *
+ * @param list list of the header options
+ * @param ocRepresentation representation of a resource
+ */
+ @Override
+ public synchronized void onPutCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
+ msg("PUT request was successful");
+ try {
+ mLight.setOcRepresentation(ocRepresentation);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Failed to create Light representation");
+ }
+ msg("Light attributes: ");
+ msg(mLight.toString());
+ printLine();
+
+ //Call a local method which will internally invoke post API on the foundLightResource
+ postLightRepresentation();
+ }
+
+ /**
+ * An event handler to be executed whenever a "put" request fails
+ *
+ * @param throwable exception
+ */
+ @Override
+ public synchronized void onPutFailed(Throwable throwable) {
+ if (throwable instanceof OcException) {
+ OcException ocEx = (OcException) throwable;
+ Log.e(TAG, ocEx.toString());
+ ErrorCode errCode = ocEx.getErrorCode();
+ //do something based on errorCode
+ msg("Error code: " + errCode);
+ }
+ msg("Failed to \"put\" a new representation");
+ }
+
+ /**
+ * Local method to post a different state for this light resource
+ */
+ private void postLightRepresentation() {
+ //set new values
+ mLight.setState(false);
+ mLight.setPower(105);
+
+ msg("Posting light representation...");
+ OcRepresentation representation = null;
+ try {
+ representation = mLight.getOcRepresentation();
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Failed to get OcRepresentation from a light");
+ }
+
+ Map<String, String> queryParams = new HashMap<>();
+ try {
+ sleep(1);
+ // Invoke resource's "post" API with a new representation, query parameters and
+ // OcResource.OnPostListener event listener implementation
+ mFoundLightResource.post(representation, queryParams, this);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Error occurred while invoking \"post\" API");
+ }
+ }
+
+ /**
+ * An event handler to be executed whenever a "post" request completes successfully
+ *
+ * @param list list of the header options
+ * @param ocRepresentation representation of a resource
+ */
+ @Override
+ public synchronized void onPostCompleted(List<OcHeaderOption> list,
+ OcRepresentation ocRepresentation) {
+ msg("POST request was successful");
+ try {
+ if (ocRepresentation.hasAttribute(OcResource.CREATED_URI_KEY)) {
+ msg("\tUri of the created resource: " +
+ ocRepresentation.getValue(OcResource.CREATED_URI_KEY));
+ } else {
+ mLight.setOcRepresentation(ocRepresentation);
+ msg(mLight.toString());
+ }
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ }
+
+ //setting new values
+ mLight.setState(true);
+ mLight.setPower(55);
+ msg("Posting again light representation...");
+ OcRepresentation representation2 = null;
+ try {
+ representation2 = mLight.getOcRepresentation();
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Failed to get OcRepresentation from a light");
+ }
+
+ Map<String, String> queryParams = new HashMap<>();
+ try {
+ // Invoke resource's "post" API with a new representation, query parameters and
+ // OcResource.OnPostListener event listener implementation
+ mFoundLightResource.post(representation2, queryParams, onPostListener2);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Error occurred while invoking \"post\" API");
+ }
+ }
+
+ /**
+ * An event handler to be executed whenever a "post" request fails
+ *
+ * @param throwable exception
+ */
+ @Override
+ public synchronized void onPostFailed(Throwable throwable) {
+ if (throwable instanceof OcException) {
+ OcException ocEx = (OcException) throwable;
+ Log.e(TAG, ocEx.toString());
+ ErrorCode errCode = ocEx.getErrorCode();
+ //do something based on errorCode
+ msg("Error code: " + errCode);
+ }
+ msg("Failed to \"post\" a new representation");
+ }
+
+ /**
+ * Declare and implement a second OcResource.OnPostListener
+ */
+ OcResource.OnPostListener onPostListener2 = new OcResource.OnPostListener() {
+ /**
+ * An event handler to be executed whenever a "post" request completes successfully
+ * @param list list of the header options
+ * @param ocRepresentation representation of a resource
+ */
+ @Override
+ public synchronized void onPostCompleted(List<OcHeaderOption> list,
+ OcRepresentation ocRepresentation) {
+ msg("Second POST request was successful");
+ try {
+ if (ocRepresentation.hasAttribute(OcResource.CREATED_URI_KEY)) {
+ msg("\tUri of the created resource: " +
+ ocRepresentation.getValue(OcResource.CREATED_URI_KEY));
+ } else {
+ mLight.setOcRepresentation(ocRepresentation);
+ msg(mLight.toString());
+ }
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ }
+
+ //Call a local method which will internally invoke observe API on the foundLightResource
+ observeFoundLightResource();
+ }
+
+ /**
+ * An event handler to be executed whenever a "post" request fails
+ *
+ * @param throwable exception
+ */
+ @Override
+ public synchronized void onPostFailed(Throwable throwable) {
+ if (throwable instanceof OcException) {
+ OcException ocEx = (OcException) throwable;
+ Log.e(TAG, ocEx.toString());
+ ErrorCode errCode = ocEx.getErrorCode();
+ //do something based on errorCode
+ msg("Error code: " + errCode);
+ }
+ msg("Failed to \"post\" a new representation");
+ }
+ };
+
+ /**
+ * Local method to start observing this light resource
+ */
+ private void observeFoundLightResource() {
+ try {
+ sleep(1);
+ // Invoke resource's "observe" API with a observe type, query parameters and
+ // OcResource.OnObserveListener event listener implementation
+ mFoundLightResource.observe(ObserveType.OBSERVE, new HashMap<String, String>(), this);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Error occurred while invoking \"observe\" API");
+ }
+ }
+
+ // holds current number of observations
+ private static int mObserveCount = 0;
+
+ /**
+ * An event handler to be executed whenever a "post" request completes successfully
+ *
+ * @param list list of the header options
+ * @param ocRepresentation representation of a resource
+ * @param sequenceNumber sequence number
+ */
+ @Override
+ public synchronized void onObserveCompleted(List<OcHeaderOption> list,
+ OcRepresentation ocRepresentation,
+ int sequenceNumber) {
+
+ if (sequenceNumber != maxSequenceNumber + 1)
+ {
+ msg("OBSERVE Result:");
+ msg("\tSequenceNumber:" + sequenceNumber);
+ try {
+ mLight.setOcRepresentation(ocRepresentation);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Failed to get the attribute values");
+ }
+ msg(mLight.toString());
+
+ if ((++mObserveCount) == 11) {
+ msg("Cancelling Observe...");
+ try {
+ mFoundLightResource.cancelObserve(QualityOfService.HIGH);
+ } catch (OcException e) {
+ Log.e(TAG, e.toString());
+ msg("Error occurred while invoking \"cancelObserve\" API");
+ }
+
+ sleep(10);
+ resetGlobals();
+ if (true == isTCPContained && false == isRequestFlag)
+ {
+ msg("Start TCP test...");
+ //startSimpleClientBleScan(OcConnectivityType.CT_ADAPTER_TCP);
+ isRequestFlag = true;
+ return;
+ } else if (true == isRequestFlag)
+ {
+ msg("End TCP test...");
+ isRequestFlag = false;
+ }
+
+ msg("DONE");
+ //prepare for the next restart of the SimpleClientBleScan
+ //enableStartButton();
+ }
+ }
+ }
+
+ /**
+ * An event handler to be executed whenever a "observe" request fails
+ *
+ * @param throwable exception
+ */
+ @Override
+ public synchronized void onObserveFailed(Throwable throwable) {
+ if (throwable instanceof OcException) {
+ OcException ocEx = (OcException) throwable;
+ Log.e(TAG, ocEx.toString());
+ ErrorCode errCode = ocEx.getErrorCode();
+ //do something based on errorCode
+ msg("Error code: " + errCode);
+ }
+ msg("Observation of the found light resource has failed");
+ }
+
+ //******************************************************************************
+ // End of the OIC specific code
+ //******************************************************************************
+
+ private final static String TAG = SimpleClientBleScan.class.getSimpleName();
+ private TextView mConsoleTextView;
+ private ScrollView mScrollView;
+ private ArrayAdapter<String> mNewDevicesArrayAdapter;
+
+ private BluetoothLeScanner mBluetoothLeScanner;
+ private Handler mHandler = new Handler();
+
+ private ScanCallback mScanCallback = new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ Log.d(TAG, "Scan callback called");
+ super.onScanResult(callbackType, result);
+ if( result == null
+ || result.getDevice() == null)
+ {
+ return;
+ }
+
+ StringBuilder builder = new StringBuilder( result.getDevice().getAddress());
+
+ mNewDevicesArrayAdapter.add(result.getDevice().getName() + "\n" + result.getDevice().getAddress());
+ Log.d(TAG, builder.toString());
+ }
+
+ @Override
+ public void onBatchScanResults(List<ScanResult> results) {
+ msg("Batch Scan callback called");
+ super.onBatchScanResults(results);
+ }
+
+ @Override
+ public void onScanFailed(int errorCode) {
+ msg("Scan Failed !");
+ Log.e(TAG, "Discovery onScanFailed: " + errorCode );
+ super.onScanFailed(errorCode);
+ }
+ };
+
+ private void discover() {
+ msg("Discovery started");
+ Log.i(TAG, "Discover called");
+ List<ScanFilter> filters = new ArrayList<ScanFilter>();
+ ScanFilter filter = new ScanFilter.Builder().setServiceUuid(new ParcelUuid(UUID.fromString("ADE3D529-C784-4F63-A987-EB69F70EE816"))).build();
+ filters.add(filter);
+
+ ScanSettings settings = new ScanSettings.Builder()
+ .setScanMode( ScanSettings.SCAN_MODE_BALANCED)
+ .build();
+
+ mBluetoothLeScanner.startScan(mScanCallback);
+
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mBluetoothLeScanner.stopScan(mScanCallback);
+ msg("Scan Stopped");
+ Log.d(TAG, "Scan Stopped");
+ }
+ }, 10000);
+ }
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_simple_client);
+
+ mConsoleTextView = (TextView) findViewById(R.id.consoleTextView);
+ mConsoleTextView.setMovementMethod(new ScrollingMovementMethod());
+ mScrollView = (ScrollView) findViewById(R.id.scrollView);
+ mScrollView.fullScroll(View.FOCUS_DOWN);
+ final Button scan_button = (Button) findViewById(R.id.scan_button);
+ mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);
+
+ final ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
+ newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
+
+ mBluetoothLeScanner = BluetoothAdapter.getDefaultAdapter().getBluetoothLeScanner();
+
+ if (null == savedInstanceState) {
+ scan_button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ scan_button.setText("Scan Started");
+ scan_button.setEnabled(false);
+ new Thread(new Runnable() {
+ public void run() {
+ discover();
+ }
+ }).start();
+ }
+ });
+
+ newDevicesListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ String value = newDevicesListView.getItemAtPosition(position).toString();
+ String lines[] = value.split("\\r?\\n");
+ startSimpleClientBleScan(OcConnectivityType.CT_ADAPTER_IP, lines[1]);
+ }
+ });
+ } else {
+ String consoleOutput = savedInstanceState.getString("consoleOutputString");
+ mConsoleTextView.setText(consoleOutput);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString("consoleOutputString", mConsoleTextView.getText().toString());
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+
+ String consoleOutput = savedInstanceState.getString("consoleOutputString");
+ mConsoleTextView.setText(consoleOutput);
+ }
+
+ private void sleep(int seconds) {
+ try {
+ Thread.sleep(seconds * 1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ Log.e(TAG, e.toString());
+ }
+ }
+
+ private void msg(final String text) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ mConsoleTextView.append("\n");
+ mConsoleTextView.append(text);
+ mScrollView.fullScroll(View.FOCUS_DOWN);
+ }
+ });
+ Log.i(TAG, text);
+ }
+
+ private void printLine() {
+ msg("------------------------------------------------------------------------");
+ }
+
+ private synchronized void resetGlobals() {
+ mFoundLightResource = null;
+ mFoundResources.clear();
+ mLight = new Light();
+ mObserveCount = 0;
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ Log.d(TAG, "onNewIntent with changes sending broadcast IN ");
+
+ Intent i = new Intent();
+ i.setAction(intent.getAction());
+ i.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES,
+ intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES));
+ sendBroadcast(i);
+ Log.d(TAG, "Initialize Context again resetting");
+ }
+
+}