2
0

12 کامیت‌ها 3c367a209c ... 2a31adf41f

نویسنده SHA1 پیام تاریخ
  Trishia 2a31adf41f Introspection data related to null character (0x00) same with pki data was solved and CT4.1.1 Bridge, VOD and VOD List behaviour was passed with CTT 2002.4.2 fully. 4 سال پیش
  Trishia 5a568c52b2 code cleansing. 4 سال پیش
  Trishia d654af1b44 Real Light Control Service's package and service name was applied. 4 سال پیش
  Trishia d1f0116e10 Start Light Switch and Light Control on boot up again 4 سال پیش
  Trishia d8a6f4bbf7 read files for pki certs and idd was modified to add 0x00 at the end of byte array. 4 سال پیش
  Trishia ffe70b4e48 Notifying to observers was deleted on doGetLightControlResources of scheduledTask, just only used in onResultReceived() of ILightControlServiceCallback. 4 سال پیش
  Trishia 2a4a07be24 Notifying changed resource to Observers for Bridged Client was added. 4 سال پیش
  Trishia e760217ef4 Remove VODs/Each VOD, Stop Service's functional logic was changed and minor update for stable source code. 4 سال پیش
  Trishia e2eb4faeba Option menu functions were modified for stable operation. 4 سال پیش
  Trishia ba3c8980ba VOD reset issue was solved via modifying oc_sec_ael_init(). 4 سال پیش
  Trishia 3f3d32c14e Option menu related to vod reset, vod add, vod remove, bridged client start/stop was added or modified. And ocfbridge branch 2020.09.29 was merged. 4 سال پیش
  Trishia 705a2ad894 LightControl Client Connection logic was modified. 4 سال پیش

+ 1 - 1
app/build.gradle

@@ -5,7 +5,7 @@ android {
     buildToolsVersion '29.0.2'
     defaultConfig {
         applicationId "org.iotivity.bridge.homeserver"
-        minSdkVersion 21
+        minSdkVersion 23
         targetSdkVersion 26
         versionCode 2
         versionName "1.0"

BIN
app/libs/iotivity-lite.jar


+ 0 - 4
app/src/main/AndroidManifest.xml

@@ -3,7 +3,6 @@
     package="org.iotivity.bridge.homeserver">
 
     <uses-feature android:name="android.hardware.nfc" />
-
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
@@ -15,7 +14,6 @@
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
     <uses-permission android:name="android.permission.NFC" />
-
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 
     <application
@@ -31,7 +29,6 @@
             android:screenOrientation="fullSensor">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
-
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
@@ -42,7 +39,6 @@
             </intent-filter>
         </service>
 
-        <!--<receiver android:name=".AlarmReceiver" />-->
         <receiver android:name=".BootCompletedReceiver" android:exported="false" android:enabled="true">
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />

+ 180 - 83
app/src/main/java/org/iotivity/bridge/homeserver/BridgeServer.java

@@ -35,12 +35,14 @@ import org.iotivity.oc.OcUtils;
 import org.iotivity.OCUuidUtil;
 import org.iotivity.OCUuid;
 import org.iotivity.OCVirtualDevice;
+import org.iotivity.oc.OcVirtualDevice;
 import org.json.JSONObject;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Properties;
 
 public class BridgeServer {
@@ -83,8 +85,8 @@ public class BridgeServer {
 
     public void initBridgeServer() {
 
-        this.addLightVirtualOCFServer(LIGHT_UUID, "Light Switch", "rs-485");
-        //this.addVirtualOCFClient(CLIENT_UUID, "Virtual OCF Client", "ocf");
+        this.addLightVirtualOCFServer(BridgeServer.LIGHT_UUID, "Light Switch", "ocf");
+        //this.addVirtualOCFClient(BridgeServer.CLIENT_UUID, "Virtual OCF Client", "ocf");
 
         this.loadPairwisedDeviceUUIDs();
     }
@@ -105,35 +107,122 @@ public class BridgeServer {
         //ocPlatform.systemInit(initHandler);
     }
 
-    public void resetVirtualOCFDevices() {
+    public void deleteVirtualOCFDevices() {
         int vod_count = OCBridge.getVirtualDeviceCount();
         Log.d(TAG, "Virtual OCF Device Count = [" + vod_count + "], Core Device Nums = ["+OCCoreRes.getNumDevices()+"] ");
 
         for (int index = 1; index <= vod_count; index++) {
             OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(index);
             if (vod != null) {
-                OCBridge.removeVirtualDevice(vod.getIndex());
-                OCBridge.deleteVirtualDevice(vod.getIndex()); //  Note :This includes OCMain.resetDevice(index);
+                OCBridge.removeVirtualDevice(vod.getIndex());  // Note : This removes vod in vods_list and shutdown connectivity
+                OCBridge.deleteVirtualDevice(vod.getIndex()); //  Note : This removes piid, core device, vod map at index and OCMain.resetDevice(index);
                 Log.d(TAG, "Virtual OCF Device [" + vod.getIndex() + "] was reset!");
             }
         }
+        //TODO : need to check Memory data
         bridge.clearVirtualOCFDeviceList();
+    }
 
-        /* // For test
-        if(OCCoreRes.getNumDevices() > 1) {
-            for (int index = 1; index <= OCCoreRes.getNumDevices(); index++) {
-                OCMain.resetDevice(index);
-                Log.d(TAG, "OCF Device [" + index + "] was reset!");
+    public void deleteVirtualOCFDevice(String device_sn) {
+        int vod_count = OCBridge.getVirtualDeviceCount();
+        Log.d(TAG, "Virtual OCF Device Count = [" + vod_count + "], Core Device Nums = ["+OCCoreRes.getNumDevices()+"] ");
+        for (int index = 1; index <= vod_count; index++) {
+            OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(index);
+            if (vod != null && OCUuidUtil.bytesToString(vod.getId()).equalsIgnoreCase(device_sn)) {
+                this.deleteVirtualOCFDevice((int)vod.getIndex());
+                Log.d(TAG, "Virtual OCF Device [" + vod.getIndex() + "] was deleted!");
             }
-        }*/
+        }
     }
 
-    public void resetVirtualOCFDevice(int vod_index) {
-        OCBridge.removeVirtualDevice(vod_index);
-        OCBridge.deleteVirtualDevice(vod_index); // Note : This includes OCMain.resetDevice(index);
+    public void deleteVirtualOCFDevice(int vod_index) {
+        OCBridge.removeVirtualDevice(vod_index);  // Note : This removes vod in vods_list and shutdown connectivity
+        OCBridge.deleteVirtualDevice(vod_index); //  Note : This removes piid, core device, vod map at index and OCMain.resetDevice(index);
+
+        //TODO : need to check Memory data
         bridge.removeVirtualOCFDevice(vod_index);
     }
 
+    public void removeVirtualOCFDevices() {
+
+        ArrayList<VirtualOCFDevice> vods = (ArrayList<VirtualOCFDevice>)bridge.getVirtualOCFDeviceList().clone();
+        for(VirtualOCFDevice vod : vods) {
+            this.removeVirtualOCFDevice(vod.getVODIndex());
+        }
+    }
+
+    public void removeVirtualOCFDevice(int vod_index) {
+
+        OCVirtualDevice vod_light = OCBridge.getVirtualDeviceInfo(vod_index);
+        if(vod_light != null) {
+            Log.d(TAG, "Virtual Server[" + vod_light.getIndex() + "] "
+                    + ", DeviceId = " + OCUuidUtil.bytesToString(vod_light.getId())
+                    + ", Econame = " + vod_light.getEconame() + ", Name = " + vod_light.getEconame()
+                    + " will be removed");
+
+            int ret = OCBridge.removeVirtualDevice(vod_index);
+            if (ret >=0) {
+                bridge.removeVirtualOCFDevice(vod_index);
+            }
+        }
+    }
+
+    public void resetVirtualOCFDevices() {
+
+        int dev_count = (int)OCCoreRes.getNumDevices();
+        Log.d(TAG, "VOD Nums = ["+OCBridge.getVirtualDeviceCount()+"], Core Res Nums = ["+OCCoreRes.getNumDevices()+"]");
+        for (int index = 1 ; index <= dev_count; index++) {
+            /*OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(index);
+            if(vod!=null) continue;
+            Log.d(TAG, "VODs Device [" + index + ", "+vod.getIndex()+", vod_id="+OCUuidUtil.bytesToString(vod.getId())+ "]");
+*/
+            OCDeviceInfo dev = OCCoreRes.getDeviceInfo(index);
+            if(dev != null) {
+                Log.d(TAG, "Core OCF Device [" + index +" piid="+OCUuidUtil.uuidToString(dev.getPiid())+ "]");
+                if(dev.getName() != null) {
+                    Log.d(TAG, "Core OCF Device [" + index + "] "+dev.getName()+" was reset!");
+                    this.resetDevice(index);
+                }
+            }
+        }
+    }
+
+    public void resetVirtualOCFDevice(OCUuid device_uuid) {
+        int dev_count = (int)OCCoreRes.getNumDevices();
+        Log.d(TAG, "Core Device Nums = ["+dev_count+"] ");
+        for (int index = 1; index <= dev_count; index++) {
+            OCDeviceInfo dev = OCCoreRes.getDeviceInfo(index);
+            if (dev != null && OCUuidUtil.isEqual(dev.getDi(),device_uuid)) {
+                this.resetDevice(index);
+                Log.d(TAG, "Core OCF Device [" + index + "] "+dev.getName()+" was reset!");
+            }
+        }
+    }
+
+    public void resetVirtualOCFDevice(String device_uuid) {
+        int dev_count = (int)OCCoreRes.getNumDevices();
+        Log.d(TAG, "Core Device Nums = ["+dev_count+"] ");
+        for (int index = 1; index <= dev_count; index++) {
+            OCDeviceInfo dev = OCCoreRes.getDeviceInfo(index);
+            if (dev != null && OCUuidUtil.uuidToString(dev.getDi()).equalsIgnoreCase(device_uuid)) {
+                this.resetDevice(index);
+                Log.d(TAG, "Core OCF Device [" + index + "] "+dev.getName()+" was reset!");
+            }
+        }
+    }
+
+    public void resetVirtualOCFDeviceByDevicePiid(String device_sn) {
+        int dev_count = (int)OCCoreRes.getNumDevices();
+        Log.d(TAG, "Core Device Nums = ["+dev_count+"] ");
+        for (int index = 1; index <= dev_count; index++) {
+            OCDeviceInfo dev = OCCoreRes.getDeviceInfo(index);
+            if (dev != null && OCUuidUtil.uuidToString(dev.getPiid()).equalsIgnoreCase(device_sn)) {
+                this.resetDevice(index);
+                Log.d(TAG, "Core OCF Device [" + index + "] "+dev.getName()+" was reset!");
+            }
+        }
+    }
+
     public void resetDevice(int device_index) {
 
         if(device_index < 0) return ;
@@ -141,31 +230,18 @@ public class BridgeServer {
         OCDeviceInfo info = OCCoreRes.getDeviceInfo(device_index);
         if(info == null) return ;
         if(device_index == Bridge.BRIDGE_INDEX) {
-            if (info != null) {
-                Log.d(TAG, "Bridge Server[" + Bridge.BRIDGE_INDEX + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
-                        + " will reset");
-            }
+            Log.d(TAG, "Bridge Server[" + Bridge.BRIDGE_INDEX + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
+                    + " will reset");
             this.resetBridgeServer();
 
         } else if(device_index > 0) {
             OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(device_index);
-            if (info != null) {
+            if (vod != null) {
                 Log.d(TAG, "Virtual OCF Server/Client[" + vod.getIndex() + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
-                        + ", echoname = " + vod.getEconame() + " will reset");
-            }
-            this.resetVirtualOCFDevice(device_index);
-        }
-    }
-
-    public void resetVirtualOCFDevice(String device_sn) {
-        int vod_count = OCBridge.getVirtualDeviceCount();
-        Log.d(TAG, "Virtual OCF Device Count = [" + vod_count + "], Core Device Nums = ["+OCCoreRes.getNumDevices()+"] ");
-        for (int index = 1; index <= vod_count; index++) {
-            OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(index);
-            if (vod != null && OCUuidUtil.bytesToString(vod.getId()).equalsIgnoreCase(device_sn)) {
-                this.resetVirtualOCFDevice((int)vod.getIndex());
-                Log.d(TAG, "Virtual OCF Device [" + vod.getIndex() + "] was reset!");
+                        + ", echoname = " + vod.getEconame() + ", name = "+info.getName()+" will be reset");
             }
+            //this.resetVirtualOCFDevice(device_index);
+            OCMain.resetDevice(device_index);
         }
     }
 
@@ -188,14 +264,14 @@ public class BridgeServer {
         }
     }*/
 
-    public String existVirtualOCFDevice(String virtual_di, String econame) {
+    public boolean existVirtualOCFDevice(String virtual_di, String econame) {
 
         for(VirtualOCFDevice vod : bridge.getVirtualOCFDeviceList()){
             if(vod.getVirtualDeviceId().equals(virtual_di) && vod.getEcoName().equals(econame)) {
-                return vod.getVirtualDeviceId();
+                return true ;
             }
         }
-        return null ;
+        return false ;
     }
 
     public VirtualOCFDevice addVirtualOCFDevice(String device_name, String virtual_di, String device_type, String eco_name) {
@@ -213,8 +289,8 @@ public class BridgeServer {
             OCVirtualDevice vod_info = OCBridge.getVirtualDeviceInfo(vod_index);
             Log.d(TAG, "VOD Info = " + vod_info);
             if (vod_info != null) {
-                Log.d(TAG, "Virtual Server[" + vod_info.getIndex() + "] "
-                        + " DeviceId = " + OCUuidUtil.bytesToString(vod_info.getId())
+                Log.d(TAG, "Virtual Server [" + vod_info.getIndex() + "] "
+                        + " Virtual Device Id = " + OCUuidUtil.bytesToString(vod_info.getId())
                         + ", Econame = " + vod_info.getEconame() + ", Name = " + dev_info.getName()
                         + " was added");
 
@@ -229,7 +305,7 @@ public class BridgeServer {
                 // set immutable device id for Platform Independent Identifier (piid)
                 OCMain.setImmutableDeviceIdentifier(vod_index, OCUuidUtil.stringToUuid(virtual_di));
                 Log.d(TAG, "Virtual Server [" + vod_info.getIndex() + "] "
-                        + ", Virtual Device Id = " + virtual_di
+                        + " Virtual Device Id = " + virtual_di
                         + ", Device Id = " + OCUuidUtil.uuidToString(dev_info.getDi())
                         + ", Device Piid = " + OCUuidUtil.uuidToString(dev_info.getPiid()));
 
@@ -261,6 +337,8 @@ public class BridgeServer {
         OCMain.resourceSetRequestHandler(resource, OCMethod.OC_POST, new PostRequestHandler(service, device));
         OCMain.resourceSetRequestHandler(resource, OCMethod.OC_PUT, new PutRequestHandler(service, device));
         OCMain.addResource(resource);
+
+        device.addOCResource(resource);
     }
 
     public void addLightVirtualOCFServer(String virtual_di, String devicename, String econame) {
@@ -279,8 +357,8 @@ public class BridgeServer {
             OCVirtualDevice vod_info = OCBridge.getVirtualDeviceInfo(vod_index);
             Log.d(TAG, "VOD Info = "+ vod_info);
             if(vod_info != null) {
-                Log.d(TAG, "Virtual Server[" + vod_info.getIndex() + "] "
-                        + " DeviceId = " + OCUuidUtil.bytesToString(vod_info.getId())
+                Log.d(TAG, "Virtual Server [" + vod_info.getIndex() + "] "
+                        + " Virtual Device Id = " + OCUuidUtil.bytesToString(vod_info.getId())
                         + ", Econame = " + vod_info.getEconame() + ", Name = " + dev_info.getName()
                         + " was added");
 
@@ -304,6 +382,7 @@ public class BridgeServer {
                 OCMain.resourceSetRequestHandler(res_light, OCMethod.OC_POST, new PostLightRequestHandler(service, light));
                 OCMain.resourceSetRequestHandler(res_light, OCMethod.OC_PUT, new PutLightRequestHandler(service, light));
                 OCMain.addResource(res_light);
+                vod.addOCResource(res_light);
 
                 // Add Dimming Resource
                 OCResource res_dimming = OCMain.newResource(devicename, "/dimming", (short) 1, (long) vod_index);
@@ -318,12 +397,12 @@ public class BridgeServer {
                 OCMain.resourceSetRequestHandler(res_dimming, OCMethod.OC_POST, new PostLightRequestHandler(service, light));
                 OCMain.resourceSetRequestHandler(res_dimming, OCMethod.OC_PUT, new PutLightRequestHandler(service, light));
                 OCMain.addResource(res_dimming);
-
+                vod.addOCResource(res_dimming);
 
                 // set immutable device id for Platform Independent Identifier (piid)
                 OCMain.setImmutableDeviceIdentifier(vod_index, OCUuidUtil.stringToUuid(virtual_di));
-                Log.d(TAG, "Virtual Server [" + vod_info.getIndex() + "] "
-                        + ", Virtual Device Id = " + virtual_di
+                Log.d(TAG, "Virtual Device [" + vod_info.getIndex() + "] "
+                        + " Virtual Device Id = " + virtual_di
                         + ", Device Id = " + OCUuidUtil.uuidToString(dev_info.getDi())
                         + ", Device Piid = " + OCUuidUtil.uuidToString(dev_info.getPiid()));
 
@@ -334,22 +413,6 @@ public class BridgeServer {
         }
     }
 
-    public void removeLightVirtualOCFDevice(int vod_index) {
-
-        OCVirtualDevice vod_light = OCBridge.getVirtualDeviceInfo(vod_index);
-        if(vod_light != null) {
-            Log.d(TAG, "Virtual Server[" + vod_light.getIndex() + "] "
-                    + ", DeviceId = " + OCUuidUtil.bytesToString(vod_light.getId())
-                    + ", Econame = " + vod_light.getEconame() + ", Name = " + vod_light.getEconame()
-                    + " will be removed");
-
-            int ret = OCBridge.removeVirtualDevice(vod_index);
-            if (ret >=0) {
-                bridge.removeVirtualOCFDevice(vod_index);
-            }
-        }
-    }
-
     public void addVirtualOCFClient(String device_uuid, String devicename, String econame) {
 
         // Add Virtual Device for Legarcy Client like such as zibee coodinater
@@ -362,8 +425,8 @@ public class BridgeServer {
             OCDeviceInfo dev_info = OCCoreRes.getDeviceInfo(vod_index);
             OCVirtualDevice vod_client = OCBridge.getVirtualDeviceInfo(vod_index);
             if(vod_client != null){
-                Log.d(TAG, "Virtual Client[" + vod_client.getIndex() + "] "
-                        + " DeviceId = " + OCUuidUtil.bytesToString(vod_client.getId())
+                Log.d(TAG, "Virtual Client [" + vod_client.getIndex() + "] "
+                        + " Virtual Device Id = " + OCUuidUtil.bytesToString(vod_client.getId())
                         + ", Econame = " + vod_client.getEconame() + ", Name = " + dev_info.getName()
                         + " was added");
 
@@ -373,6 +436,14 @@ public class BridgeServer {
                 vod.setDiscovered(true);
                 vod.setAddedToBridge(true);
                 bridge.addOrReplaceVirtualOCFDevice(vod);
+
+                // set immutable device id for Platform Independent Identifier (piid)
+                OCMain.setImmutableDeviceIdentifier(vod_index, uuid);
+                Log.d(TAG, "Virtual Device [" + vod_client.getIndex() + "] "
+                        + " Virtual Device Id = " + device_uuid
+                        + ", Device Id = " + OCUuidUtil.uuidToString(dev_info.getDi())
+                        + ", Device Piid = " + OCUuidUtil.uuidToString(dev_info.getPiid()));
+
             }
         }
 
@@ -411,24 +482,21 @@ public class BridgeServer {
         return null ;
     }
 
+    public boolean compareVirtualOCFDeviceProperties(String device_sn, String uri, String props) {
+        VirtualOCFDevice device = getVirtualOCFDevice(device_sn);
+        if(device != null) {
+            return device.compareProperties(uri, props);
+        }
+        return false ;
+    }
 
-    /*
-    private boolean checkExistVOD(String device_unique_id) {
-        String device_uuid = existVirtualOCFDevice(devicename, econame);
-        if (device_uuid == null) { // In case of no exist device
-            // generate new UUID
-            OCUuid new_uuid = OCUuidUtil.generateUuid();
-            device_uuid = OCUuidUtil.uuidToString(new_uuid);
-            Log.d(TAG, "Virtual Device : Name = " + devicename + ", DeviceId = " + device_uuid
-                    + ", echoname = " + econame + " will be added since it doesn't exist.");
-
-            return false ;
-        } else {
-            Log.d(TAG, "Virtual Device : Name = " + devicename + ", DeviceId = " + device_uuid
-                    + ", echoname = " + econame + " exists already.");
-            return true ;
+    public boolean existVirtualOCFDevice(String device_sn) {  // Virtual OCF ID (Serial Number or Piid)
+        VirtualOCFDevice device = getVirtualOCFDevice(device_sn);
+        if(device != null) {
+            return existVirtualOCFDevice(device.getVirtualDeviceId(), device.getEcoName());
         }
-    }*/
+        return false ;
+    }
 
     public void disconnectVirtualDevice(int vod_index) {
 
@@ -440,7 +508,7 @@ public class BridgeServer {
 
             OCDeviceInfo info = OCCoreRes.getDeviceInfo(vod_index);
             if(OCBridge.removeVirtualDevice(vod_index) == 0) {
-                Log.d(TAG, "Virtual OCF Server/Client[" + vod.getVODIndex() + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
+                Log.d(TAG, "Virtual OCF Server/Client [" + vod.getVODIndex() + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
                         + ", echoname = " + vod.getEcoName() + " was removed from the bridge");
             } else {
                 Log.d(TAG, "Failed to remove Virtual OCF Server/Client["+vod_index+"] "+info.getName()+" from the bridge");
@@ -448,9 +516,24 @@ public class BridgeServer {
         }
     }
 
-    public void discoveredOCFDevice(OcRemoteDevice remoteDevice) {
-        // TODO : check if discovered OCF Device has to add to the bridge as a Virtual OCF Device or not
+    public void disconnectAllVirtualDevices() {
+
+        for (VirtualOCFDevice vod : bridge.getVirtualOCFDeviceList()) {
+            Log.d(TAG, "disconnect All Virtual Devices.");
+            if (vod != null) {
+
+                vod.setDiscovered(false);
+                vod.setAddedToBridge(false);
 
+                OCDeviceInfo info = OCCoreRes.getDeviceInfo(vod.getVODIndex());
+                if (OCBridge.removeVirtualDevice(vod.getVODIndex()) == 0) {
+                    Log.d(TAG, "Virtual OCF Server/Client [" + vod.getVODIndex() + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
+                            + ", echoname = " + vod.getEcoName() + " was removed from the bridge");
+                } else {
+                    Log.d(TAG, "Failed to remove Virtual OCF Server/Client[" + vod.getVODIndex() + "] " + info.getName() + " from the bridge");
+                }
+            }
+        }
     }
 
     /* These APIs are related to online pairwised devices */
@@ -571,7 +654,7 @@ public class BridgeServer {
                 baos = new ByteArrayOutputStream();
                 int length = 0;
                 while ((length = is.read(buffer)) != -1) {
-                    Log.d(TAG, "bytes read = " + length);
+                    //Log.d(TAG, "bytes read = " + length);
                     baos.write(buffer, 0, length);
                 }
             } catch (IOException e) {
@@ -597,7 +680,21 @@ public class BridgeServer {
             Log.e(TAG, "Failed to read " + filepath);
         }
 
-        return ((baos != null) ? baos.toByteArray() : null);
+        if(baos!=null) {
+            Log.d(TAG, "bytes length = " + baos.toByteArray().length);
+            return baos.toByteArray() ;
+
+            /*int len = baos.toByteArray().length ;
+            if(baos.toByteArray()[len-1] != (byte)0x00 ) {
+                byte[] result = Arrays.copyOf(baos.toByteArray(), len + 1);
+                result[len] = (byte) 0x00;
+                Log.d(TAG, "bytes length = " + result.length);
+                return result;
+            } else {
+                return baos.toByteArray() ;
+            }*/
+        }
+        return null;
     }
 }
 

+ 328 - 29
app/src/main/java/org/iotivity/bridge/homeserver/BridgeServerActivity.java

@@ -34,7 +34,9 @@ import com.icontrols.service.control.ILightControlService;
 import com.icontrols.service.control.ILightControlServiceCallback;
 
 import org.iotivity.OCCoreRes;
+import org.iotivity.OCDeviceInfo;
 import org.iotivity.OCEndpoint;
+import org.iotivity.OCMain;
 import org.iotivity.OCQos;
 import org.iotivity.OCUuid;
 import org.iotivity.OCUuidUtil;
@@ -46,8 +48,10 @@ import org.iotivity.bridge.homeserver.handler.client.PostLightResponseHandler;
 import org.iotivity.bridge.homeserver.handler.client.ResourceDetailsHelper;
 import org.iotivity.bridge.homeserver.model.Bridge;
 import org.iotivity.bridge.homeserver.model.Light;
+import org.iotivity.bridge.homeserver.model.VirtualOCFDevice;
 import org.iotivity.bridge.homeserver.utils.Utils;
 import org.iotivity.oc.OcCborEncoder;
+import org.iotivity.oc.OcDevice;
 import org.iotivity.oc.OcRemoteDevice;
 import org.iotivity.oc.OcRemoteResource;
 import org.iotivity.oc.OcUtils;
@@ -68,8 +72,7 @@ public class BridgeServerActivity extends AppCompatActivity {
 
     private AdapterView.OnItemClickListener deviceItemClickListener;
     private ArrayAdapter<OcRemoteDevice> deviceArrayAdapter;
-
-    ArrayList<OcRemoteDevice> deviceList = new ArrayList<OcRemoteDevice>();
+    private ArrayList<OcRemoteDevice> deviceList = new ArrayList<OcRemoteDevice>();
     private final Object arrayAdapterSync = new Object();
 
     private TextView mConsoleTextView;
@@ -97,8 +100,6 @@ public class BridgeServerActivity extends AppCompatActivity {
         createContent();
 
         if (savedInstanceState == null) {
-            // start first time only
-            //bridgeServer = new BridgeServer(this);
 
             // start Service
             Intent intent = new Intent( BridgeServerActivity.this, BridgeService.class );
@@ -300,21 +301,6 @@ public class BridgeServerActivity extends AppCompatActivity {
         }
     };
 
-    /*private static final int BUMP_MSG = 1;
-
-    private Handler mHandler = new Handler() {
-        @Override public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case BUMP_MSG:
-                    msg("Received from service: " + msg.arg1);
-                    break;
-                default:
-                    super.handleMessage(msg);
-            }
-        }
-
-    };
-*/
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
         getMenuInflater().inflate(R.menu.actionbar_actions, menu) ;
@@ -334,7 +320,11 @@ public class BridgeServerActivity extends AppCompatActivity {
                 resetBridgeDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
-                        if(bridgeServer!=null) bridgeServer.resetBridgeServer();
+                        if(bridgeServer!=null) {
+                            bridgeServer.resetBridgeServer();
+                            Toast.makeText(BridgeServerActivity.this, getString(R.string.resetBridgeOkMessage)
+                                    , Toast.LENGTH_LONG).show();
+                        }
                     }
                 });
 
@@ -350,16 +340,19 @@ public class BridgeServerActivity extends AppCompatActivity {
             }
 
             case R.id.action_vods_reset:
-                // TODO : do some action like start Activity or show Dialog
                 {
                     AlertDialog.Builder resetVodsDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
-                    resetVodsDialogBuilder.setTitle(getString(R.string.resetVods));
-                    resetVodsDialogBuilder.setMessage(getString(R.string.resetVodsMessage));
+                    resetVodsDialogBuilder.setTitle(getString(R.string.resetVODs));
+                    resetVodsDialogBuilder.setMessage(getString(R.string.resetVODsMessage));
 
                     resetVodsDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
-                            if(bridgeServer!=null) bridgeServer.resetVirtualOCFDevices();
+                            if(bridgeServer!=null) {
+                                bridgeServer.resetVirtualOCFDevices();
+                                Toast.makeText(BridgeServerActivity.this, getString(R.string.resetVODsOkMessage)
+                                        , Toast.LENGTH_LONG).show();
+                            }
                         }
                     });
 
@@ -373,6 +366,303 @@ public class BridgeServerActivity extends AppCompatActivity {
                     resetVodsDialog.show();
                     return true;
             }
+            case R.id.action_vod_reset:
+            {
+                AlertDialog.Builder resetListDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                resetListDialogBuilder.setTitle(getString(R.string.selectDevice));
+                //resetListDialogBuilder.setMessage(getString(R.string.resetDeviceMessage));
+
+                final ArrayList<OCDeviceInfo> vodlist = new ArrayList<OCDeviceInfo>();
+                for(int index = 1 ; index < OCCoreRes.getNumDevices() ; index++) {
+                    OCDeviceInfo info = OCCoreRes.getDeviceInfo(index);
+                    if(info !=null && info.getName() != null) vodlist.add(info);
+                }
+
+                ListView deviceResetListView = new ListView(BridgeServerActivity.this);
+                final ArrayAdapter deviceArrayAdapter = new ArrayAdapter(BridgeServerActivity.this,
+                        android.R.layout.simple_list_item_1, android.R.id.text1, vodlist) {
+                    @Override
+                    public View getView(int position, View convertView, ViewGroup parent) {
+                        View view = super.getView(position, convertView, parent);
+                        TextView text1 = (TextView) view.findViewById(android.R.id.text1);
+
+                        OCDeviceInfo device = (OCDeviceInfo) this.getItem(position);
+                        if (device != null) {
+                            text1.setText(device.getName());
+                        }
+                        return view;
+                    }
+                };
+                deviceResetListView.setAdapter(deviceArrayAdapter);
+                deviceResetListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                    @Override
+                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                        // TODO :
+                        Log.d(TAG, "deviceResetListView position["+position+"] clicked!!");
+                        final OCDeviceInfo device = (OCDeviceInfo) deviceArrayAdapter.getItem(position);
+                        if(device == null) return ;
+
+                        AlertDialog.Builder resetBridgeDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                        resetBridgeDialogBuilder.setTitle(getString(R.string.resetDevice));
+                        resetBridgeDialogBuilder.setMessage(getString(R.string.resetDeviceMessage).replace("?", device.getName()));
+
+                        resetBridgeDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+
+                                bridgeServer.resetVirtualOCFDevice(device.getDi());
+                                Toast.makeText(BridgeServerActivity.this,
+                                        getString(R.string.resetDeviceOkMessage).replace("?", device.getName())
+                                        , Toast.LENGTH_LONG).show();
+                            }
+                        });
+
+                        resetBridgeDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                            }
+                        });
+
+                        Dialog resetbridgeDialog = resetBridgeDialogBuilder.create();
+                        resetbridgeDialog.show();
+
+                    }
+                });
+                resetListDialogBuilder.setView(deviceResetListView);
+                resetListDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        dialog.dismiss();
+                    }
+                });
+
+                final Dialog resetDialog = resetListDialogBuilder.create();
+                resetDialog.show();
+                return true;
+            }
+            case R.id.action_add_vos:
+            {
+                AlertDialog.Builder confirmBridgeDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                confirmBridgeDialogBuilder.setTitle(getString(R.string.addVOS));
+                confirmBridgeDialogBuilder.setMessage(getString(R.string.addVOSMessage));
+
+                confirmBridgeDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if(bridgeServer!=null) {
+                            bridgeServer.addLightVirtualOCFServer(BridgeServer.LIGHT_UUID, "Light Switch", "ocf");
+                            Toast.makeText(BridgeServerActivity.this, getString(R.string.addVOSOkMessage)
+                                    , Toast.LENGTH_LONG).show();
+                        }
+                    }
+                });
+
+                confirmBridgeDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                    }
+                });
+
+                Dialog confirmDialog = confirmBridgeDialogBuilder.create();
+                confirmDialog.show();
+                return true;
+            }
+            case R.id.action_add_voc:
+            {
+                AlertDialog.Builder confirmBridgeDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                confirmBridgeDialogBuilder.setTitle(getString(R.string.addVOC));
+                confirmBridgeDialogBuilder.setMessage(getString(R.string.addVOCMessage));
+
+                confirmBridgeDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if(bridgeServer!=null) {
+                            bridgeServer.addVirtualOCFClient(BridgeServer.CLIENT_UUID, "Virtual OCF Client", "ocf");
+                            Toast.makeText(BridgeServerActivity.this, getString(R.string.addVOCOkMessage)
+                                    , Toast.LENGTH_LONG).show();
+                        }
+                    }
+                });
+
+                confirmBridgeDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                    }
+                });
+
+                Dialog confirmDialog = confirmBridgeDialogBuilder.create();
+                confirmDialog.show();
+                return true;
+            }
+            case R.id.action_vods_remove:
+            {
+                AlertDialog.Builder removeVodsDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                removeVodsDialogBuilder.setTitle(getString(R.string.removeVODs));
+                removeVodsDialogBuilder.setMessage(getString(R.string.removeVODsMessage));
+
+                removeVodsDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if(bridgeServer!=null) {
+                            //bridgeServer.deleteVirtualOCFDevices();
+                            bridgeServer.removeVirtualOCFDevices();
+                            Toast.makeText(BridgeServerActivity.this, getString(R.string.removeVODsOkMessage)
+                                    , Toast.LENGTH_LONG).show();
+                        }
+                    }
+                });
+
+                removeVodsDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                    }
+                });
+
+                Dialog removeVodsDialog = removeVodsDialogBuilder.create();
+                removeVodsDialog.show();
+                return true;
+            }
+            case R.id.action_vod_remove:
+            {
+                AlertDialog.Builder removeListDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                removeListDialogBuilder.setTitle(getString(R.string.selectDevice));
+                //resetListDialogBuilder.setMessage(getString(R.string.resetDeviceMessage));
+
+                final ArrayList<VirtualOCFDevice> vodlist = (ArrayList<VirtualOCFDevice>)bridgeServer.getVirtualOCFDeviceList().clone();
+
+                ListView deviceRemoveListView = new ListView(BridgeServerActivity.this);
+                final ArrayAdapter deviceArrayAdapter = new ArrayAdapter(BridgeServerActivity.this,
+                        android.R.layout.simple_list_item_1, android.R.id.text1, vodlist) {
+                    @Override
+                    public View getView(int position, View convertView, ViewGroup parent) {
+                        View view = super.getView(position, convertView, parent);
+                        TextView text1 = (TextView) view.findViewById(android.R.id.text1);
+
+                        VirtualOCFDevice device = (VirtualOCFDevice) this.getItem(position);
+                        if (device != null) {
+                            OCDeviceInfo info = OCCoreRes.getDeviceInfo(device.getVODIndex());
+                            if(info !=null) text1.setText(info.getName());
+                        }
+                        return view;
+                    }
+                };
+                deviceRemoveListView.setAdapter(deviceArrayAdapter);
+                deviceRemoveListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                    @Override
+                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                        // TODO :
+                        Log.d(TAG, "deviceResetListView position["+position+"] clicked!!");
+                        final VirtualOCFDevice device = (VirtualOCFDevice) deviceArrayAdapter.getItem(position);
+                        if (device == null) return ;
+                        final OCDeviceInfo info = OCCoreRes.getDeviceInfo(device.getVODIndex());
+                        if (info == null) return ;
+
+                        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                        dialogBuilder.setTitle(getString(R.string.removeVOD));
+                        dialogBuilder.setMessage(getString(R.string.removeVODMessage).replace("?", info.getName()));
+
+                        dialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+
+                                final String device_name = info.getName();
+                                if(bridgeServer!=null) {
+                                    //bridgeServer.deleteVirtualOCFDevice(device.getVODIndex());
+                                    bridgeServer.removeVirtualOCFDevice(device.getVODIndex());
+                                    Toast.makeText(BridgeServerActivity.this,
+                                            getString(R.string.removeVODOkMessage).replace("?", device_name)
+                                            , Toast.LENGTH_LONG).show();
+                                }
+                            }
+                        });
+
+                        dialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                            }
+                        });
+
+                        Dialog dialog = dialogBuilder.create();
+                        dialog.show();
+
+                    }
+                });
+                removeListDialogBuilder.setView(deviceRemoveListView);
+                removeListDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        dialog.dismiss();
+                    }
+                });
+
+                final Dialog removeDialog = removeListDialogBuilder.create();
+                removeDialog.show();
+                return true;
+            }
+            case R.id.action_start_bridged_client:
+            {
+                AlertDialog.Builder confirmBridgeDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                confirmBridgeDialogBuilder.setTitle(getString(R.string.startBridgedClient));
+                confirmBridgeDialogBuilder.setMessage(getString(R.string.startBridgedClientMessage));
+
+                confirmBridgeDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if(bridgeService!=null) {
+                            bridgeService.bindLightControlService();
+                            bridgeService.startScheduledTaskForLightControl();
+                            Toast.makeText(BridgeServerActivity.this, getString(R.string.startBridgedClientOkMessage)
+                                    , Toast.LENGTH_LONG).show();
+                        }
+                    }
+                });
+
+                confirmBridgeDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                    }
+                });
+
+                Dialog confirmDialog = confirmBridgeDialogBuilder.create();
+                confirmDialog.show();
+                return true;
+            }
+            case R.id.action_stop_bridged_client:
+            {
+                AlertDialog.Builder confirmBridgeDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
+                confirmBridgeDialogBuilder.setTitle(getString(R.string.stopBridgedClient));
+                confirmBridgeDialogBuilder.setMessage(getString(R.string.stopBridgedClientMessage));
+
+                confirmBridgeDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        if(bridgeService != null ) {
+                            bridgeService.stopScheduledTaskForLightControl();
+                            if(bridgeServer != null ) {
+                                ArrayList<VirtualOCFDevice> vods = (ArrayList<VirtualOCFDevice>)bridgeServer.getVirtualOCFDeviceList().clone();
+                                for (VirtualOCFDevice vod : vods) {
+                                    if (vod.getEcoName().equalsIgnoreCase(BridgeService.LightControlServiceConnection.ECO_NAME)) {
+                                        bridgeServer.removeVirtualOCFDevice(vod.getVODIndex());
+                                    }
+                                }
+                            }
+                            bridgeService.unbindLightControlService();
+                            Toast.makeText(BridgeServerActivity.this, getString(R.string.stopBridgedClientOkMessage)
+                                    , Toast.LENGTH_LONG).show();
+                        }
+                    }
+                });
+
+                confirmBridgeDialogBuilder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                    }
+                });
+
+                Dialog confirmDialog = confirmBridgeDialogBuilder.create();
+                confirmDialog.show();
+                return true;
+            }
             case R.id.action_bridgeservice_stop : {
 
                 AlertDialog.Builder stopServiceDialogBuilder = new AlertDialog.Builder(BridgeServerActivity.this);
@@ -382,8 +672,12 @@ public class BridgeServerActivity extends AppCompatActivity {
                 stopServiceDialogBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
-                        // Stop Bridge Service
-                        stopBridgeService();
+                        // stop Bridge Service
+                        if(bridgeService!=null ) {
+                            //stopBridgeService();
+                            bridgeService.stopScheduledTaskForPairwised();
+                        }
+                        unbindBridgeService();
                     }
                 });
 
@@ -409,6 +703,7 @@ public class BridgeServerActivity extends AppCompatActivity {
                     public void onClick(DialogInterface dialog, int which) {
                         // kill Bridge Service
                         stopBridgeService();
+
                         Log.d(TAG, "System.exit() will be called");
                         System.runFinalizersOnExit(true);
                         System.exit(0);
@@ -559,9 +854,13 @@ public class BridgeServerActivity extends AppCompatActivity {
         discoverDevicesButton.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                deviceArrayAdapter.setNotifyOnChange(false);
-                deviceArrayAdapter.clear();
-                deviceArrayAdapter.setNotifyOnChange(true);
+
+                synchronized (arrayAdapterSync) {
+                    deviceArrayAdapter.setNotifyOnChange(false);
+                    deviceArrayAdapter.clear();
+                    deviceArrayAdapter.setNotifyOnChange(true);
+                }
+                deviceArrayAdapter.notifyDataSetChanged();
 
                 if(bridgeService!=null) {
                     bridgeService.clearPairwisedDevices();

+ 198 - 112
app/src/main/java/org/iotivity/bridge/homeserver/BridgeService.java

@@ -71,8 +71,6 @@ public class BridgeService extends IntentService {
     private final IBinder lBinder = new LocalServiceBinder();
     private BridgeServer bridgeServer = null ;
 
-    private ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
-
     // Message Handler MSG TYPEs
     public static final int MSG_RESULT = 1 ;
     public static final int MSG_STRING = 2;
@@ -99,8 +97,7 @@ public class BridgeService extends IntentService {
     public BridgeService() {
         super(BridgeService.class.getName());
     }
-
-    private BridgeService getService() {
+    public BridgeService getService() {
         return this ;
     }
     public BridgeServer getBridgeServer() {
@@ -110,15 +107,17 @@ public class BridgeService extends IntentService {
     @Override
     public void onCreate() {
         super.onCreate();
-
         Log.d(TAG, "onCreate()");
+
         // start first time only
         bridgeServer = new BridgeServer(this);
 
-        scheduledTaskInit();
+        // start Scheduled Tasks for pairwised devices
+        startScheduledTaskForPairwised();
 
-        // TODO : should remove this test function after connected to Light Control Service of Wallpad
-        bindLightServiceForTest();
+        // start Light Control Service Client and ScheduledTask
+        bindLightControlService();
+        startScheduledTaskForLightControl();
     }
 
     /*
@@ -301,20 +300,42 @@ public class BridgeService extends IntentService {
         }
     };
 
-    private ILightControlService lightControlBinder = null ;        // Light Control Service Binder for test
-    private void bindLightServiceForTest() {
+    private ILightControlService lightControlBinder = null ;        // Light Control Service Binder
+    private LightControlServiceConnection lightConn = new LightControlServiceConnection();
+    public void bindLightControlService() {
+
+        Log.d(TAG, "SecheduledTaskInit : bindLightControlService() called.");
 
         // Light Control Service Remote Bind
-        LightControlServiceConnection lightConn = new LightControlServiceConnection();
         Intent lIntent = new Intent();
-        lIntent.setClassName("org.iotivity.bridge.homeserver", "org.iotivity.bridge.homeserver.BridgeService");
+        //lIntent.setClassName("org.iotivity.bridge.homeserver", "org.iotivity.bridge.homeserver.BridgeService"); // self test for Light Control Service
+        lIntent.setClassName("kr.co.icontrols.ocfservice", "kr.co.icontrols.ocfservice.LightControlService");
         lIntent.setAction(ILightControlService.class.getName());
         bindService(lIntent, lightConn, Context.BIND_AUTO_CREATE);
+        Log.d(TAG, "bind Light Control Service with Remote Connection");
+    }
+
+    public void unbindLightControlService() {
+        // Light Control Service Remote Unbind
+        if (lightControlBinder != null) {
+            try {
+                lightControlBinder.unregisterLightControlServiceCallback(lightCallback);
+                Log.d(TAG, "unregister Light Control Service with Remote Client Callback");
+                if(lightConn!=null) unbindService(lightConn);
+                Log.d(TAG, "unbind Light Control Service with Remote Connection");
+            } catch (RemoteException ex) {
+                Log.e(TAG, "unregister Callback", ex);
+                // There is nothing special we need to do if the service
+                // has crashed.
+            }
+        }
     }
 
     class LightControlServiceConnection implements ServiceConnection {
 
         public static final String ECO_NAME = "rs-485" ;
+        public static final String ONLINE = "on-line" ;
+        public static final String OFFLINE = "off-line" ;
 
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
@@ -322,91 +343,14 @@ public class BridgeService extends IntentService {
             Log.d(TAG, "onServiceConnected ComponentName=" + name + ", IBinder=" + service.toString());
             if (service instanceof ILightControlService.Stub) {
 
-                lightControlBinder = ILightControlService.Stub.asInterface(service);
-
                 try {
+                    lightControlBinder = ILightControlService.Stub.asInterface(service);
                     lightControlBinder.registerLightControlServiceCallback(lightCallback);
 
-                    String devices = lightControlBinder.retrieveAllDevices();
-                    Log.d(TAG, "Light Control retrieveAllDevices() : "+ devices);
-                    if(devices != null) {
-                        JSONArray array = new JSONArray(devices);
-
-                        for (int index = 0 ; index < array.length(); index++) {
-                            JSONObject devs = array.getJSONObject(index);
-                            Iterator<String> it_devs = devs.keys();
-                            String n = null, sn = null, rt = null, state = null ;
-
-                            while (it_devs.hasNext()) {
-                                String key = it_devs.next();
-                                Object value = devs.get(key);
-                                if (key.equals("n") && value instanceof String) {
-                                    n = (String)value;
-                                    Log.d(TAG, "Light Device : n = " + n);
-                                } else if (key.equals("sn") && value instanceof String) {
-                                    sn = (String)value;
-                                    Log.d(TAG, "Light Device : sn = " + sn);
-                                } else if (key.equals("rt") && value instanceof JSONArray) {
-                                    Log.d(TAG, "Light Device : rt(org) = " + ((JSONArray)value).toString());
-                                    rt = ((JSONArray)value).getString(0);
-                                    Log.d(TAG, "Light Device : rt = " + rt);
-                                } else if (key.equals("state") && value instanceof String) {
-                                    state = (String)value;
-                                    Log.d(TAG, "Light Device : state = " + state);
-                                }
-                            }
-                            // add device on ocf platform
-                            VirtualOCFDevice device = bridgeServer.addVirtualOCFDevice(n, sn, rt, ECO_NAME);
-                            if(device==null) continue;
-
-                            String resources = lightControlBinder.retrieveAllResources(sn);
-                            Log.d(TAG, "Light Control retrieveAllResources() : " + resources);
-                            if(resources!=null) {
-                                JSONArray resArr = new JSONArray(resources);
-                                for (int loop = 0 ; loop < resArr.length(); loop++) {
-                                    JSONObject res = resArr.getJSONObject(loop);
-                                    Iterator<String> rKeys = res.keys();
-                                    String rName = null, rUri = null, rRT = null, rIF = null ;
-
-                                    while (rKeys.hasNext()) {
-                                        String rKey = rKeys.next();
-                                        Object rValue = res.get(rKey);
-                                        if (rKey.equals("n") && rValue instanceof String) {
-                                            rName = (String)rValue;
-                                            Log.d(TAG, "Light Resource : n = " + rName);
-                                        } else if (rKey.equals("uri") && rValue instanceof String) {
-                                            rUri = (String)rValue;
-                                            Log.d(TAG, "Light Resource : uri = " + rUri);
-                                        } else if (rKey.equals("rt") && rValue instanceof JSONArray) {
-                                            Log.d(TAG, "Light Resource : rt(org) = " + ((JSONArray)rValue).toString());
-                                            rRT = ((JSONArray)rValue).getString(0);
-                                            Log.d(TAG, "Light Resource : rt = " + rRT);
-                                        } else if (rKey.equals("if") && rValue instanceof String) {
-                                            rIF = (String)rValue;
-                                            Log.d(TAG, "Light Resource : if = " + rIF);
-                                        }
-                                    }
-                                    // add resource on the device
-                                    bridgeServer.addVirtualDeviceResource(device, rName, rUri, rRT, rIF);
-
-                                    // get resource properties
-                                    String properites = lightControlBinder.doGetResourceProperties(sn, rUri);
-                                    Log.d(TAG, "Light Control doGetResourceProperties("+sn+", "+rUri+") : " + properites);
-
-                                    JSONObject props = new JSONObject(properites);
-                                    Iterator<String> pKeys = props.keys();
-                                    while(pKeys.hasNext()) {
-                                        String pKey = pKeys.next();
-                                        Object pValue = props.get(pKey);
-                                        // update properties state
-                                        device.addProperty(rUri, pKey, pValue);
-                                    }
+                    // Discover All Light Control Devices
+                    discoverAllLightControlDevices();
 
-                                }
-                            }
-                        }
-                    }
-                } catch (RemoteException | JSONException ex) {
+                } catch (RemoteException ex) {
                     Log.e(TAG, "Register Callback", ex);
                     // In this case the service has crashed before we could even
                     // do anything with it; we can count on soon being
@@ -449,16 +393,20 @@ public class BridgeService extends IntentService {
                     String tid = obj.getString("tid");              // Transaction Id
                     String sn = obj.getString("sn");                // Serial Number (Virtual Device Id)
                     String uri = obj.getString("uri");              // Resource URI
-                    String res_type = obj.getString("res_type");    // GET, POST, PUT
+                    String res_type = obj.getString("res_type");    // GET, POST, PUT, OBSERVE
                     String res_data = obj.getString("res_data");    // Properties
 
                     // Update Properties of the resource from result
                     bridgeServer.addOrUpdateVirtualOCFDeviceProperties(sn, uri, res_data);
 
                     // TODO : need to check // notify to Observers for changed properties's value
-                    /*VirtualOCFDevice vod = bridgeServer.getVirtualOCFDevice(sn);
-                    OCResource ocResource = OCCoreRes.getResourceByUri(uri, vod.getVODIndex());
-                    OCMain.notifyObservers(ocResource);*/
+                    VirtualOCFDevice vod = bridgeServer.getVirtualOCFDevice(sn);
+                    if(vod != null) {
+                        OCResource ocResource = vod.getOCResource(uri);
+                        if(ocResource != null) {
+                            OCMain.notifyObservers(ocResource);
+                        }
+                    }
                 }
             } catch (JSONException e) {
                 Log.e(TAG, "Light Control Service Remote Error : ", e);
@@ -467,7 +415,7 @@ public class BridgeService extends IntentService {
     };
 
     /**
-     * The IBridgeService is defined through IDL
+     * The ILightControlService is defined through IDL
      */
     private final ILightControlServiceImpl lightBinder = new ILightControlServiceImpl() ;
     class ILightControlServiceImpl extends ILightControlService.Stub {
@@ -599,6 +547,114 @@ public class BridgeService extends IntentService {
         return null ;
     }
 
+    public void discoverAllLightControlDevices() {
+
+        Log.d(TAG, "SecheduledTaskInit : doRetrieveLightControlAllDevices() called.");
+        try {
+            String devices = lightControlBinder.retrieveAllDevices();
+            Log.d(TAG, "Light Control retrieveAllDevices() : "+ devices);
+            if(devices != null) {
+                JSONArray array = new JSONArray(devices);
+
+                for (int index = 0 ; index < array.length(); index++) {
+                    JSONObject devs = array.getJSONObject(index);
+                    Iterator<String> it_devs = devs.keys();
+                    String n = null, sn = null, rt = null, state = null ;
+
+                    while (it_devs.hasNext()) {
+                        String key = it_devs.next();
+                        Object value = devs.get(key);
+                        if (key.equals("n") && value instanceof String) {
+                            n = (String)value;
+                            Log.d(TAG, "Light Device : n = " + n);
+                        } else if (key.equals("sn") && value instanceof String) {
+                            sn = (String)value;
+                            Log.d(TAG, "Light Device : sn = " + sn);
+                        } else if (key.equals("rt") && value instanceof JSONArray) {
+                            Log.d(TAG, "Light Device : rt(org) = " + ((JSONArray)value).toString());
+                            rt = ((JSONArray)value).getString(0);
+                            Log.d(TAG, "Light Device : rt = " + rt);
+                        } else if (key.equals("state") && value instanceof String) {
+                            state = (String)value;
+                            Log.d(TAG, "Light Device : state = " + state);
+                        }
+                    }
+
+                    VirtualOCFDevice device = null ;
+                    if(bridgeServer.existVirtualOCFDevice(sn)) {  // exist Virtual OCF Device
+                        if(LightControlServiceConnection.OFFLINE.equalsIgnoreCase(state)) {
+                            device = bridgeServer.getVirtualOCFDevice(sn);
+                            bridgeServer.disconnectVirtualDevice(device.getVODIndex()); // TODO : neet do check this logic properly
+                            Log.d(TAG, "Light Device ("+n+") : state was changed to " + state + ", so existing VOD was diconnected.");
+                        }
+                    } else {
+
+                        if(LightControlServiceConnection.OFFLINE.equalsIgnoreCase(state)) {
+                            Log.d(TAG, "Light Device ("+n+") : state is " + state + ", so VOD will not be added.");
+                            continue;
+                        }
+
+                        // add device on ocf platform
+                        device = bridgeServer.addVirtualOCFDevice(n, sn, rt, LightControlServiceConnection.ECO_NAME);
+                        if(device==null) continue;
+
+                        String resources = lightControlBinder.retrieveAllResources(sn);
+                        Log.d(TAG, "Light Control retrieveAllResources() : " + resources);
+                        if(resources!=null) {
+                            JSONArray resArr = new JSONArray(resources);
+                            for (int loop = 0 ; loop < resArr.length(); loop++) {
+                                JSONObject res = resArr.getJSONObject(loop);
+                                Iterator<String> rKeys = res.keys();
+                                String rName = null, rUri = null, rRT = null, rIF = null ;
+
+                                while (rKeys.hasNext()) {
+                                    String rKey = rKeys.next();
+                                    Object rValue = res.get(rKey);
+                                    if (rKey.equals("n") && rValue instanceof String) {
+                                        rName = (String)rValue;
+                                        Log.d(TAG, "Light Resource : n = " + rName);
+                                    } else if (rKey.equals("uri") && rValue instanceof String) {
+                                        rUri = (String)rValue;
+                                        Log.d(TAG, "Light Resource : uri = " + rUri);
+                                    } else if (rKey.equals("rt") && rValue instanceof JSONArray) {
+                                        Log.d(TAG, "Light Resource : rt(org) = " + ((JSONArray)rValue).toString());
+                                        rRT = ((JSONArray)rValue).getString(0);
+                                        Log.d(TAG, "Light Resource : rt = " + rRT);
+                                    } else if (rKey.equals("if") && rValue instanceof String) {
+                                        rIF = (String)rValue;
+                                        Log.d(TAG, "Light Resource : if = " + rIF);
+                                    }
+                                }
+                                // add resource on the device
+                                bridgeServer.addVirtualDeviceResource(device, rName, rUri, rRT, rIF);
+
+                                // get resource properties
+                                String properites = lightControlBinder.doGetResourceProperties(sn, rUri);
+                                Log.d(TAG, "Light Control doGetResourceProperties("+sn+", "+rUri+") : " + properites);
+
+                                JSONObject props = new JSONObject(properites);
+                                Iterator<String> pKeys = props.keys();
+                                while(pKeys.hasNext()) {
+                                    String pKey = pKeys.next();
+                                    Object pValue = props.get(pKey);
+                                    // update properties state
+                                    device.addProperty(rUri, pKey, pValue);
+                                }
+
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (RemoteException | JSONException ex) {
+            Log.e(TAG, "Register Callback", ex);
+            // In this case the service has crashed before we could even
+            // do anything with it; we can count on soon being
+            // disconnected (and then reconnected if it can be restarted)
+            // so there is no need to do anything here.
+        }
+    }
+
     public void doGetLightControlResources() {
 
         Log.d(TAG, "SecheduledTaskInit : doGetLightControlResources() called.");
@@ -611,19 +667,21 @@ public class BridgeService extends IntentService {
                     for (OCFDevice.Resource resource : vod.getResources()) {
                         try {
                             // doGetProperties with Light Control Service
+                            String prev_props = bridgeServer.getVirtualOCFDeviceProperties(device_sn, resource.getResourceUri());
                             String properies = lightBinder.doGetResourceProperties(device_sn, resource.getResourceUri());
                             bridgeServer.addOrUpdateVirtualOCFDeviceProperties(device_sn, resource.getResourceUri(), properies);
 
+                            /*Log.d(TAG,"(1) prev_props : " +prev_props + ", cur_props : " +properies );
                             // TODO : need to check // notify to Observers for changed properties's value
-                            /*Log.d(TAG, "OCCoreRes.getResourceByUri() before : " + vod.getDeviceName() +
-                                    ", " +resource.getResourceUri()+", "+ vod.getVODIndex());
-                            //OCDeviceInfo info = OCCoreRes.getDeviceInfo(vod.getVODIndex());
-                            OCResource ocResource = OCCoreRes.getResourceByUri(resource.getResourceUri(), vod.getVODIndex());
-                            if(ocResource != null && ocResource.getNumObservers() > 0) {
-                                Log.d(TAG, "OCCoreRes.getResourceByUri() after : " + ocResource.getName() +
-                                        ", " +ocResource.getUri() +", "+ ocResource.getNumObservers());
-                                OCMain.notifyObservers(ocResource);
+                            if(!bridgeServer.compareVirtualOCFDeviceProperties(device_sn, resource.getResourceUri(), properies)) {
+                                Log.d(TAG,"(2) prev_props : " +prev_props + ", cur_props : " +properies );
+                                //bridgeServer.addOrUpdateVirtualOCFDeviceProperties(device_sn, resource.getResourceUri(), properies);
+                                OCResource ocResource = vod.getOCResource(resource.getResourceUri());
+                                if (ocResource != null) {
+                                    OCMain.notifyObservers(ocResource);
+                                }
                             }*/
+
                         } catch (RemoteException e) {
                             Log.e(TAG, "Light Control Service Remote Error : ", e);
                         }
@@ -713,6 +771,8 @@ public class BridgeService extends IntentService {
         // Unregister all callbacks.
         rBinder.killCallbacks();
 
+        Toast.makeText(getApplicationContext(), getString(R.string.killBridgeMessage), Toast.LENGTH_LONG).show();
+
         // Bridge Service and Application Process Kill
         // android.os.Process.killProcess(Process.myPid());
         // or below action
@@ -781,13 +841,18 @@ public class BridgeService extends IntentService {
         alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
     }
 
-    public void scheduledTaskInit () {
+
+    private ScheduledExecutorService executorPairwised = null ;
+    private ScheduledExecutorService executorLightControl = null;
+    public void startScheduledTaskForPairwised () {
 
         /* How to use ExecuterService like followings
          * executorService.schedule(Classname::someTask, delayInSeconds, TimeUnit.SECONDS);                 // once after a delay
          * executorService.scheduleAtFixedRate(Classname::someTask, 0, delayInSeconds, TimeUnit.SECONDS);   // at fixed time interval
          */
-        executorService.scheduleAtFixedRate(new Runnable() {
+        if(executorPairwised != null && executorPairwised.isShutdown() == false ) { executorPairwised.shutdown();}
+        executorPairwised = Executors.newSingleThreadScheduledExecutor();
+        executorPairwised.scheduleAtFixedRate(new Runnable() {
             @Override
             public void run() {
                 // load pair-wised device UUIDs from Bridge Credentials
@@ -805,17 +870,38 @@ public class BridgeService extends IntentService {
                     Log.d(TAG, "DeviceDiscovery ScheduledTask per 90sec was called.");
                 }
             }
-        }, 10, 90, TimeUnit.SECONDS); //90 sec interval after 10sec delay
+        }, 10, 90, TimeUnit.SECONDS); // 90 sec interval after 10sec delay
+    }
+
+    public void stopScheduledTaskForPairwised() {
+        if(executorPairwised!=null ) { executorPairwised.shutdown(); }
+    }
+
+    public void startScheduledTaskForLightControl () {
 
-        executorService.scheduleAtFixedRate(new Runnable() {
+        /* How to use ExecuterService like followings
+         * executorService.schedule(Classname::someTask, delayInSeconds, TimeUnit.SECONDS);                 // once after a delay
+         * executorService.scheduleAtFixedRate(Classname::someTask, 0, delayInSeconds, TimeUnit.SECONDS);   // at fixed time interval
+         */
+        if(executorLightControl != null && executorLightControl.isShutdown() == false ) { executorLightControl.shutdown();}
+        executorLightControl = Executors.newSingleThreadScheduledExecutor();
+        executorLightControl.scheduleAtFixedRate(new Runnable() {
             @Override
             public void run() {
                 // Getting Properites of Light Control Service for resource monitoring
-                Log.d(TAG, "LightControl Resources Retrieve ScheduledTask per 180sec was called.");
+                Log.d(TAG, "LightControl ScheduledTask per 180sec was called.");
+                if(lightControlBinder==null) {
+                    bindLightControlService();
+                }
+                discoverAllLightControlDevices();
                 doGetLightControlResources();
             }
-        }, 30, 180, TimeUnit.SECONDS); // 30sec interval after 30sec delay
+        }, 30, 180, TimeUnit.SECONDS); // 180sec interval after 30sec delay
+
+    }
 
+    public void stopScheduledTaskForLightControl() {
+        if(executorLightControl !=null) { executorLightControl.shutdown(); }
     }
 
     public void loadPairwisedDeviceUUIDs() {

+ 16 - 6
app/src/main/java/org/iotivity/bridge/homeserver/handler/BridgeInitHandler.java

@@ -21,6 +21,7 @@ import org.iotivity.oc.OcUtils;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
 
 public class BridgeInitHandler implements OCMainInitHandler {
 
@@ -43,11 +44,6 @@ public class BridgeInitHandler implements OCMainInitHandler {
         if (ret >= 0) {
             // Create the devices and add them to the platform
             ret = OCBridge.addBridgeDevice(bridge.getName(), "ocf.2.0.5", "ocf.res.1.3.0,ocf.sh.1.3.0");
-            /*, new OCAddDeviceHandler() {
-                        public void handler() {
-                            Log.d(TAG, "inside OcBridge.OCAddDeviceHandler.handler()");
-                        }
-                    });*/
         } else {
             Log.e(TAG, "Error in platformInit, return value = " + ret);
         }
@@ -118,6 +114,20 @@ public class BridgeInitHandler implements OCMainInitHandler {
             Log.e(TAG, "Failed to read " + filepath);
         }
 
-        return ((baos != null) ? baos.toByteArray() : null);
+        if(baos!=null) {
+            Log.d(TAG, "bytes length = " + baos.toByteArray().length);
+            return baos.toByteArray() ;
+
+            /*int len = baos.toByteArray().length ;
+            if(baos.toByteArray()[len-1] != (byte)0x00 ) {
+                byte[] result = Arrays.copyOf(baos.toByteArray(), len + 1);
+                result[len] = (byte) 0x00;
+                Log.d(TAG, "bytes length = " + result.length);
+                return result;
+            } else {
+                return baos.toByteArray() ;
+            }*/
+        }
+        return null;
     }
 }

+ 10 - 7
app/src/main/java/org/iotivity/bridge/homeserver/handler/FactoryPresetsHandler.java

@@ -13,6 +13,7 @@ import org.iotivity.bridge.homeserver.utils.Utils;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
 
 public class FactoryPresetsHandler implements OCFactoryPresetsHandler {
 
@@ -28,13 +29,8 @@ public class FactoryPresetsHandler implements OCFactoryPresetsHandler {
     public void handler(long deviceIndex) {
         Log.d(TAG, "inside the FactoryPresetsHandler, deviceIndex  = " + deviceIndex);
 
-        // TODO : when attempting to add an identity certificate chain, could not parse identity cert's private key
-
-        boolean isMfgCertSupport = true;
-        if (isMfgCertSupport && deviceIndex != 0)
-            return; // TODO : Only Bridge will use pki certs in this case
-
         setPKISecurityMfgCert(deviceIndex);
+
     }
 
     private void setPKISecurityMfgCert(long deviceIndex) {
@@ -146,6 +142,13 @@ public class FactoryPresetsHandler implements OCFactoryPresetsHandler {
             Log.e(TAG, "Failed to read " + filepath);
         }
 
-        return ((baos != null) ? baos.toByteArray() : null);
+        if(baos!=null) {
+            int len = baos.toByteArray().length ;
+            byte[] result = Arrays.copyOf(baos.toByteArray(), len + 1);
+            result[len] = (byte)0x00;
+            Log.d(TAG, "bytes length = " + result.length);
+            return result ;
+        }
+        return null;
     }
 }

+ 19 - 0
app/src/main/java/org/iotivity/bridge/homeserver/model/OCFDevice.java

@@ -161,4 +161,23 @@ public class OCFDevice {
         return null ;
     }
 
+    public boolean compareProperties(String resource_uri, String properties) {
+        Resource resource = getResource(resource_uri);
+        Properties cur_props = resource.getProperties();
+        try {
+            JSONObject props = new JSONObject(properties);
+            Iterator<String> keys = props.keys();
+            while(keys.hasNext()) {
+                String key = keys.next() ;
+                Object value = props.get(key);
+
+                if(cur_props.get(key) == null || !cur_props.get(key).equals(value)) {
+                    return false ;
+                }
+            }
+        } catch (JSONException e) {
+            Log.e(TAG, "JSON Error :", e);
+        }
+        return true ;
+    }
 }

+ 32 - 2
app/src/main/java/org/iotivity/bridge/homeserver/model/VirtualOCFDevice.java

@@ -1,5 +1,6 @@
 package org.iotivity.bridge.homeserver.model;
 
+import org.iotivity.OCResource;
 import org.iotivity.oc.OcCborException;
 import org.iotivity.oc.OcRepresentation;
 
@@ -18,8 +19,8 @@ public class VirtualOCFDevice extends OCFDevice {
 
     private boolean discovered ;
     private boolean added_to_bridge ;
-    private boolean isOwned ;
 
+    private ArrayList<OCResource> ocResources = new ArrayList<OCResource>() ;
 
     public VirtualOCFDevice(int vod_index, String name, String econame, String virtual_di, String type) {
         super(name, type);
@@ -73,8 +74,37 @@ public class VirtualOCFDevice extends OCFDevice {
         sb.append(", vod_id="+vod_id);
         sb.append(", isDiscoverd="+discovered);
         sb.append(", addedToBridge="+added_to_bridge);
-        sb.append(", isOwned="+isOwned);
 
         return sb.toString();
     }
+
+    public ArrayList<OCResource> getOCResources() {
+        return ocResources;
+    }
+
+    public OCResource getOCResource(String resource_uri) {
+        for(OCResource resource : ocResources) {
+            if (resource.getUri().equalsIgnoreCase(resource_uri)) {
+                return resource ;
+            }
+        }
+        return null ;
+    }
+
+    public void addOCResource(OCResource ocResource) {
+        ocResources.add(ocResource);
+    }
+
+    public void removeOCResource(int index) {
+
+        ocResources.remove(index);
+    }
+
+    public void removeOCResource(String uri) {
+        ArrayList<OCResource> resources1 = (ArrayList<OCResource>)ocResources.clone();
+        for(int loop = 0 ; loop < resources1.size() ; loop++) {
+            OCResource resource1 = resources1.get(loop);
+            if(resource1.getUri().equals(uri)) ocResources.remove(loop) ;
+        }
+    }
 }

BIN
app/src/main/jniLibs/arm64-v8a/libiotivity-lite-jni.so


BIN
app/src/main/jniLibs/armeabi-v7a/libiotivity-lite-jni.so


BIN
app/src/main/jniLibs/x86/libiotivity-lite-jni.so


BIN
app/src/main/jniLibs/x86_64/libiotivity-lite-jni.so


+ 34 - 1
app/src/main/res/menu/actionbar_actions.xml

@@ -10,7 +10,40 @@
 
         <item
             android:id="@+id/action_vods_reset"
-            android:title="@string/resetVods"
+            android:title="@string/resetVODs"
+            app:showAsAction="never"/>
+        <item
+            android:id="@+id/action_vod_reset"
+            android:title="@string/resetVOD"
+            app:showAsAction="never"/>
+
+        <item
+            android:id="@+id/action_add_vos"
+            android:title="@string/addVOS"
+            app:showAsAction="never"/>
+
+        <item
+            android:id="@+id/action_add_voc"
+            android:title="@string/addVOC"
+            app:showAsAction="never"/>
+
+        <item
+            android:id="@+id/action_vods_remove"
+            android:title="@string/removeVODs"
+            app:showAsAction="never"/>
+        <item
+            android:id="@+id/action_vod_remove"
+            android:title="@string/removeVOD"
+            app:showAsAction="never"/>
+
+        <item
+            android:id="@+id/action_start_bridged_client"
+            android:title="@string/startBridgedClient"
+            app:showAsAction="never"/>
+
+        <item
+            android:id="@+id/action_stop_bridged_client"
+            android:title="@string/stopBridgedClient"
             app:showAsAction="never"/>
 
         <item

+ 46 - 5
app/src/main/res/values/strings.xml

@@ -6,14 +6,55 @@
     <string name="discoverDevices">Discover Devices</string>
     <string name="discoveredResources">Discovered Resources</string>
     <string name="resetBridge">Reset Bridge</string>
-    <string name="resetBridgeMessage">Note: This Bridge including SVRs will be reset.</string>
+    <string name="resetBridgeMessage">Note: This Bridge will be reset so that device id will be changed to new one.</string>
+    <string name="resetBridgeOkMessage">Bridge platform was reset successfully.</string>
+
     <!--<string name="resetBridge">Reset </string>
     <string name="resetBridgeMessage">Note: This Client including SVRs will be reset.</string>-->
-    <string name="resetVods">Reset Vods</string>
-    <string name="resetVodsMessage">Note: All virtual OCF devices will be reset and clear VOD List So you should kill and restart Bridge Service.</string>
+    <string name="resetVODs">Reset VODs</string>
+    <string name="resetVODsMessage">Note: All Virtual OCF devices will be reset so that their device id will be changed to new one.</string>
+    <string name="resetVODsOkMessage">All Virtual OCF Devices was reset successfully.</string>
+
+    <string name="resetVOD">Reset Each VOD</string>
+    <string name="selectDevice">Select Device</string>
+    <string name="resetDevice">Reset Selected Device</string>
+    <string name="resetDeviceMessage">Note: Selected device - ? will be reset and their device id will be changed to new one.</string>
+    <string name="resetDeviceOkMessage">Selected device - ? was reset successfully.</string>
+
+    <string name="addVOS">Add Virtual OCF Server</string>
+    <string name="addVOSMessage">Note: Virtual OCF Server(Light Switch) will be added to operate CTT as a first VOD.</string>
+    <string name="addVOSOkMessage">Virtual OCF Server(Light Switch) was added successfully.</string>
+
+    <string name="addVOC">Add Virtual OCF Client</string>
+    <string name="addVOCMessage">Note: Virtual OCF Client will be added to operate CTT as a second VOD.</string>
+    <string name="addVOCOkMessage">Virtual OCF Client was added successfully.</string>
+
+    <string name="removeVOD">Remove Each VOD</string>
+    <string name="removeVODMessage">Note: Selected VOD - ? will be disconnected so this device will no longer be visible.</string>
+    <string name="removeVODOkMessage">Selected VOD - ? was disconnected successfully.</string>
+    <string name="removeVODs">Remove VODs</string>
+    <string name="removeVODsMessage">Note: All Virtual OCF Device will be disconnected and no longer be visible.</string>
+    <string name="removeVODsOkMessage">All Virtual OCF Devices was disconnected successfully.</string>
+
+    <string name="deleteVOD">Delete Each VOD</string>
+    <string name="deleteVODMessage">Note: Selected VOD - ? will be deleted so this device will no longer be doable.</string>
+    <string name="deleteVODOkMessage">Selected VOD - ? was deleted successfully.</string>
+    <string name="deleteVODs">Delete VODs</string>
+    <string name="deleteVODsMessage">Note: All Virtual OCF Device will be deleted and no longer be doable.</string>
+    <string name="deleteVODsOkMessage">All Virtual OCF Devices was deleted successfully.</string>
+
+    <string name="startBridgedClient">Connect Light Control</string>
+    <string name="startBridgedClientMessage">Note: Bridge Client will be connected to Light Control Service and then Virtual OCF Servers will be registered.</string>
+    <string name="startBridgedClientOkMessage">Bridge Client was connected successfully.</string>
+
+    <string name="stopBridgedClient">Disconnect Light Control</string>
+    <string name="stopBridgedClientMessage">Note: Bridge Client will be disconnected to Light Control Service and Virtual OCF Servers will be removed. </string>
+    <string name="stopBridgedClientOkMessage">Bridge Client was disconnected successfully.</string>
+
     <string name="stopBridgeService">Stop Bridge Service</string>
-    <string name="stopBridgeMessage">Note: Service Client Callbacks will be unbind and stop but Bridge Service will not be destroyed.</string>
+    <string name="stopBridgeMessage">Note: Scheduled Task in Bridge Service will be stop and All Activity Client will be unbind so Activity Client can not receive any notification.</string>
+
     <string name="killBridgeService">Kill Bridge Service</string>
-    <string name="killBridgeMessage">Note: Foregrounding Bridge Service and BridgeServer Activity will be killed.</string>
+    <string name="killBridgeMessage">Note: Bridge Service and Activity will be killed completely.</string>
 
 </resources>