Browse Source

LightControl Service Interfaces is under testing.

Trishia 4 years ago
parent
commit
15c27e0175

+ 25 - 0
app/sampledata/LightControlServiceData

@@ -0,0 +1,25 @@
+
+// retrieveAllDevices()
+[{"n":"Light Switch", "rt":["oic.d.light"], "sn":"2b32e152-3756-4fb6-b3f2-d8db7aafe39f", "state":"on-line"}]
+
+[{"n":"Light Switch", "rt":["oic.d.light"], "sn":"2b32e152-3756-4fb6-b3f2-d8db7aafe39f", "state":"on-line"},
+{"n":"Television","rt":["oic.d.tv"], "sn":"2cd8e585-ef21-4fd1-7958-6ca7e54adcce","state":"off-line"}]
+
+// retrieveAllResources()
+[{"n":"Light Switch", "uri":"/light", "rt":["oic.r.switch.binary"], "if":"RW"},
+{"n":"Dimming Control","uri":"/dimming","rt":["oic.r.light.dimming"], "if":"RW"},
+{"n":"Energy Consumption", "uri":"/EnergyConsumptionResURI", "rt": ["oic.r.energy.consumption"], "if":"S"},
+{"n":"Color Temperature", "uri":"/ColourTemperatureResURI", "rt": ["oic.r.colour.colourtemperature"], "if":"A"}]
+
+// doGetResourceProperties(in String device_uuid, in String resource_uri)
+{"n":"Light Switch", "value":true}
+{"n":"Dimming Control","dimmingSetting":100,"range":100,"step":10}
+{"n":"Energy Consumption","power":200.1,"energy":3500.4}
+{"n":"Color Temperature", "ct":457, "range":1000, "step":1}
+
+// doPostResourceProperties(in String device_uuid, in String resource_uri, in String prop_data)
+Param : prop_data = { "power" : true, "level" : 100 } or { "value" : true } or { "dimmingSetting" : 50}
+
+
+// void onResultReceived(int result_code, String result_data)
+{"tid":"3481704581734918", "sn":"15ba3c25-8cdd-41f8-6f9e-fe49105dce0a", "uri":"/light", "res_type":"POST", "res_data":{"n":"Light Switch","value":false}}

+ 5 - 2
app/src/main/AndroidManifest.xml

@@ -34,8 +34,11 @@
             </intent-filter>
         </activity>
 
-        <service android:name=".BridgeService"
-            android:exported="true"/>
+        <service android:name=".BridgeService" android:exported="true">
+            <intent-filter>
+              <action android:name="org.iotivity.bridge.homeserver.BRIDGE_SERVICE" />
+            </intent-filter>
+        </service>
 
         <receiver android:name=".AlarmReceiver" />
 

+ 13 - 0
app/src/main/aidl/com/icontrols/service/control/ILightControlService.aidl

@@ -1,8 +1,21 @@
 package com.icontrols.service.control;
 
+import com.icontrols.service.control.ILightControlServiceCallback ;
 
 interface ILightControlService {
 
+    /**
+     * Often you want to allow a service to call back to its clients.
+     * This shows how to do so, by registering a callback interface with
+     * the service.
+     */
+    void registerLightControlServiceCallback(ILightControlServiceCallback cb);
+
+    /**
+     * Remove a previously registered activity callback interface.
+     */
+    void unregisterLightControlServiceCallback(ILightControlServiceCallback cb);
+
     /**
      * retrieve all Bridged device list in Light Control Service
      * @return devices list data with json array format as String

+ 1 - 1
app/src/main/aidl/com/icontrols/service/control/ILightControlServiceCallback.aidl

@@ -12,7 +12,7 @@ interface ILightControlServiceCallback {
     * This is notifying async result for requests such as GET, POST, OBSERVE
     * @param result_code 0-OK, 1-FAIL, 2-ERROR
     * @param result_data json format as string (eg.
-    * {"id":"3481704581734918",                                     // Transaction ID
+    * {"tid":"3481704581734918",                                     // Transaction ID
     * "sn":"15ba3c25-8cdd-41f8-6f9e-fe49105dce0a",                  // Device UUID
     * "uri":"/light",                                               // Resource URI
     * "res_type":"GET",                                             // Response Type

+ 1 - 0
app/src/main/java/org/iotivity/bridge/homeserver/BridgeServer.java

@@ -245,6 +245,7 @@ public class BridgeServer {
         }
 
     }
+    
 
     public void removeLightVirtualOCFDevice(int vod_index) {
 

+ 12 - 8
app/src/main/java/org/iotivity/bridge/homeserver/BridgeServerActivity.java

@@ -7,6 +7,7 @@ import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.net.Uri;
 import android.os.Bundle;
 
 import android.os.IBinder;
@@ -29,6 +30,9 @@ import android.widget.SimpleAdapter;
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.icontrols.service.control.ILightControlService;
+import com.icontrols.service.control.ILightControlServiceCallback;
+
 import org.iotivity.OCCoreRes;
 import org.iotivity.OCEndpoint;
 import org.iotivity.OCQos;
@@ -81,7 +85,6 @@ public class BridgeServerActivity extends AppCompatActivity {
     public BridgeService getBridgeService() {
         return bridgeService ;
     }
-
     public BridgeServer getBridgeServer() {
         return bridgeServer ;
     }
@@ -101,15 +104,17 @@ public class BridgeServerActivity extends AppCompatActivity {
             Intent intent = new Intent( BridgeServerActivity.this, BridgeService.class );
             startService(intent);
 
-            // Local Bind Service
+            // Local Service Bind
             localConn = new LocalServiceConnection();
             bindService(intent, localConn, Context.BIND_AUTO_CREATE);
 
-            // Remote Bind Service
-            Intent mBindIntent = new Intent(BridgeServerActivity.this, BridgeService.class);
-            mBindIntent.setAction(IBridgeService.class.getName());
+            // Bridge Service Remote Bind
             remoteConn = new RemoteServiceConnection();
-            bindService(mBindIntent, remoteConn, Context.BIND_AUTO_CREATE);
+            Intent rIntent = new Intent();
+            rIntent.setClassName("org.iotivity.bridge.homeserver", "org.iotivity.bridge.homeserver.BridgeService");
+            rIntent.setAction(IBridgeService.class.getName());
+            bindService(rIntent, remoteConn, Context.BIND_AUTO_CREATE);
+
         }
     }
 
@@ -179,7 +184,7 @@ public class BridgeServerActivity extends AppCompatActivity {
                     remoteBinder.registerActivityCallback(aCallback);
                     remoteBinder.registerBridgeServiceCallback(sCallback);
                 } catch (RemoteException ex) {
-                    Log.e(TAG, "Unregister Callback", ex);
+                    Log.e(TAG, "Register Callbacks", 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)
@@ -264,7 +269,6 @@ public class BridgeServerActivity extends AppCompatActivity {
                         }
                         deviceArrayAdapter.setNotifyOnChange(true);
                     }
-
                     deviceArrayAdapter.notifyDataSetChanged();
                 }
             });

+ 253 - 0
app/src/main/java/org/iotivity/bridge/homeserver/BridgeService.java

@@ -7,8 +7,10 @@ import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
@@ -20,8 +22,12 @@ import android.os.RemoteException;
 import android.support.annotation.Nullable;
 import android.support.v4.app.NotificationCompat;
 import android.util.Log;
+import android.widget.Toast;
 
 
+import com.icontrols.service.control.ILightControlService;
+import com.icontrols.service.control.ILightControlServiceCallback;
+
 import org.iotivity.OCCoreRes;
 import org.iotivity.OCQos;
 import org.iotivity.OCUuid;
@@ -40,6 +46,7 @@ import org.iotivity.oc.OcUtils;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.json.JSONTokener;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -64,6 +71,7 @@ public class BridgeService extends IntentService {
     public static final int MSG_STRING = 2;
     public static final int MSG_LINE = 3;
     public static final int MSG_DEVICE_DISCOVERED = 4 ;
+    public static final int MSG_LIGHT_RESULT = 5 ;
 
     // IBridgeService RESULT TYPEs
     public enum ResultType {
@@ -101,6 +109,8 @@ public class BridgeService extends IntentService {
         bridgeServer = new BridgeServer(this);
 
         scheduledTaskInit();
+
+        bindLightServiceForTest();
     }
 
     /*
@@ -113,6 +123,8 @@ public class BridgeService extends IntentService {
         Log.d(TAG, "onBind() action = " + intent.getAction());
         if (IBridgeService.class.getName().equals(intent.getAction())) {
             return rBinder; // return Remote Binder
+        } else if (ILightControlService.class.getName().equals(intent.getAction())) {
+            return lightBinder; // return Remote Binder
         }
         return lBinder; // return Local Binder
     }
@@ -281,6 +293,243 @@ public class BridgeService extends IntentService {
         }
     };
 
+    private ILightControlService lightControlBinder = null ;        // Light Control Service Binder for test
+    private void bindLightServiceForTest() {
+
+        // 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.setAction(ILightControlService.class.getName());
+        bindService(lIntent, lightConn, Context.BIND_AUTO_CREATE);
+    }
+
+    class LightControlServiceConnection implements ServiceConnection {
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+
+            Log.d(TAG, "onServiceConnected ComponentName=" + name + ", IBinder=" + service.toString());
+            if (service instanceof ILightControlService.Stub) {
+
+                lightControlBinder = ILightControlService.Stub.asInterface(service);
+
+                try {
+                    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 obj = array.getJSONObject(index);
+                            Iterator<String> it = obj.keys();
+                            String n = null, sn = null, rt = null, state = null ;
+
+                            while (it.hasNext()) {
+                                String key = it.next();
+                                Object value = obj.get(key);
+                                if (key.equals("n") && value instanceof String) {
+                                    n = (String)value;
+                                    Log.d(TAG, "Light Control : n = " + n);
+                                } else if (key.equals("sn") && value instanceof String) {
+                                    sn = (String)value;
+                                    Log.d(TAG, "Light Control : sn = " + sn);
+                                } else if (key.equals("rt") && value instanceof JSONArray) {
+                                    rt = ((JSONArray)value).toString();
+                                    Log.d(TAG, "Light Control : rt = " + rt);
+                                } else if (key.equals("state") && value instanceof String) {
+                                    state = (String)value;
+                                    Log.d(TAG, "Light Control : state = " + state);
+                                }
+                            }
+
+                            String resources = lightControlBinder.retrieveAllResources(sn);
+                            Log.d(TAG, "Light Control retrieveAllResources() : " + resources);
+                            if(resources!=null) {
+                                JSONArray aArr = new JSONArray(resources);
+                                for (int loop = 0 ; loop < aArr.length(); loop++) {
+                                    JSONObject ob = aArr.getJSONObject(loop);
+                                    Iterator<String> keys = ob.keys();
+                                    String rName = null, rUri = null, rRT = null, rIF = null ;
+
+                                    while (keys.hasNext()) {
+                                        String rKey = keys.next();
+                                        Object rValue = ob.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) {
+                                            rRT = ((JSONArray)rValue).toString();
+                                            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);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+
+                        //Log.d(TAG, "Light Control doGetResourceProperties() : "+lightControlBinder.doGetResourceProperties("2b32e152-3756-4fb6-b3f2-d8db7aafe39f", "/light"));
+                        //Log.d(TAG, "Light Control doGetResourceProperties() : "+lightControlBinder.doGetResourceProperties("2b32e152-3756-4fb6-b3f2-d8db7aafe39f", "/dimming"));
+                        //Log.d(TAG, "Light Control doPostResourceProperties() : "+lightControlBinder.doPostResourceProperties("2b32e152-3756-4fb6-b3f2-d8db7aafe39f", "/light", null));
+                        //Log.d(TAG, "Light Control doPostResourceProperties() : "+lightControlBinder.doPostResourceProperties("2b32e152-3756-4fb6-b3f2-d8db7aafe39f", "/dimming", null));
+
+                    }
+                } 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.
+                }
+
+                msg( "Light Control Remote Service Connected");
+                printLine();
+
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+
+            //lightControlBinder.unregisterLightControlServiceCallback(lightCallback);
+            lightControlBinder = null;
+            msg("Light Control Remote Service Disconnected");
+            printLine();
+        }
+    }
+
+    private ILightControlServiceCallback lightCallback = new ILightControlServiceCallback.Stub() {
+        /**
+         * This is called by the light control remote service regularly to tell us about
+         * new values.  Note that IPC calls are dispatched through a thread
+         * pool running in each process, so the code executing here will
+         * NOT be running in our main thread like most other things -- so,
+         * to update the UI, we need to use a Handler to hop over there.
+         */
+
+        @Override
+        public void onResultReceived(int result_code, String result_data) throws RemoteException {
+            msg("result_code="+result_code + ", result_data="+result_data );
+            printLine();
+        }
+    };
+
+    /**
+     * The IBridgeService is defined through IDL
+     */
+    private final ILightControlServiceImpl lightBinder = new ILightControlServiceImpl() ;
+    class ILightControlServiceImpl extends ILightControlService.Stub {
+
+        final RemoteCallbackList<ILightControlServiceCallback> callbacks
+                = new RemoteCallbackList<ILightControlServiceCallback>();
+
+        @Override
+        public void registerLightControlServiceCallback(ILightControlServiceCallback cb) throws RemoteException {
+            if (cb != null) callbacks.register(cb);
+
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_STRING, "Light Control Client Callback was registered."));
+            mHandler.sendEmptyMessage(MSG_LINE);
+        }
+
+        @Override
+        public void unregisterLightControlServiceCallback(ILightControlServiceCallback cb) throws RemoteException {
+            if (cb != null) callbacks.unregister(cb);
+        }
+
+        @Override
+        public String retrieveAllDevices() throws RemoteException {
+            return "[{\"n\":\"Light Switch\", \"rt\":[\"oic.d.light\"], \"sn\":\"2b32e152-3756-4fb6-b3f2-d8db7aafe39f\", \"state\":\"on-line\"}]";
+        }
+
+        @Override
+        public String retrieveAllResources(String device_uuid) throws RemoteException {
+            if("2b32e152-3756-4fb6-b3f2-d8db7aafe39f".equalsIgnoreCase(device_uuid)) {
+                return "[{\"n\":\"Light Switch\", \"uri\":\"/light\", \"rt\":[\"oic.r.switch.binary\"], \"if\":\"RW\"},\n" +
+                        "{\"n\":\"Dimming Control\",\"uri\":\"/dimming\",\"rt\":[\"oic.r.light.dimming\"], \"if\":\"RW\"},\n" +
+                        "{\"n\":\"Energy Consumption\", \"uri\":\"/EnergyConsumptionResURI\", \"rt\": [\"oic.r.energy.consumption\"], \"if\":\"S\"},\n" +
+                        "{\"n\":\"Color Temperature\", \"uri\":\"/ColourTemperatureResURI\", \"rt\": [\"oic.r.colour.colourtemperature\"], \"if\":\"A\"}]";
+            }
+            return null ;
+        }
+
+        @Override
+        public String doGetResourceProperties(String device_uuid, String resource_uri) throws RemoteException {
+            if("2b32e152-3756-4fb6-b3f2-d8db7aafe39f".equalsIgnoreCase(device_uuid)) {
+                    if("/light".equalsIgnoreCase(resource_uri)) {
+                        return "{\"n\":\"Light Switch\", \"value\":true}" ;
+                    } else if("/dimming".equalsIgnoreCase(resource_uri)) {
+                        return "{\"n\":\"Dimming Control\",\"dimmingSetting\":100,\"range\":100,\"step\":10}";
+                    } else if("/EnergyConsumptionResURI".equalsIgnoreCase(resource_uri)) {
+                        return "{\"n\":\"Energy Consumption\",\"power\":200.1,\"energy\":3500.4}" ;
+                    } else if("/ColourTemperatureResURI".equalsIgnoreCase(resource_uri)) {
+                        return "{\"n\":\"Color Temperature\", \"ct\":457, \"range\":1000, \"step\":1}" ;
+                    }
+            }
+            return null;
+        }
+
+        @Override
+        public boolean doPostResourceProperties(String device_uuid, String resource_uri, String prop_data) throws RemoteException {
+            if("2b32e152-3756-4fb6-b3f2-d8db7aafe39f".equalsIgnoreCase(device_uuid)) {
+                if("/light".equalsIgnoreCase(resource_uri)) {
+                    String res_data = makeResultData(device_uuid, resource_uri, "{\"n\":\"Light Switch\", \"value\":true}");
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_LIGHT_RESULT, ResultType.OK.ordinal(), 0, res_data));
+                    return true ;
+                } else if("/dimming".equalsIgnoreCase(resource_uri)) {
+                    String res_data = makeResultData(device_uuid, resource_uri, "{\"n\":\"Dimming Control\",\"dimmingSetting\":100,\"range\":100,\"step\":10}");
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_LIGHT_RESULT, ResultType.OK.ordinal(), 0, res_data));
+                    return true ;
+                } else if("/EnergyConsumptionResURI".equalsIgnoreCase(resource_uri)) {
+                    String res_data = makeResultData(device_uuid, resource_uri, "{\"n\":\"Energy Consumption\",\"power\":200.1,\"energy\":3500.4}") ;
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_LIGHT_RESULT, ResultType.OK.ordinal(), 0, res_data));
+                    return true ;
+                } else if("/ColourTemperatureResURI".equalsIgnoreCase(resource_uri)) {
+                    String res_data = makeResultData(device_uuid, resource_uri,  "{\"n\":\"Color Temperature\", \"ct\":457, \"range\":1000, \"step\":1}") ;
+                    mHandler.sendMessage(mHandler.obtainMessage(MSG_LIGHT_RESULT, ResultType.OK.ordinal(), 0, res_data));
+                    return true ;
+                }
+            }
+            return false;
+        }
+
+        private String makeResultData(String device_uuid, String uri, String data) {
+            String res = "{\"tid\":\""+Utils.generateRandomID()+"\", " +
+                    "\"sn\":\""+device_uuid+"\", " +
+                    "\"uri\":\""+uri+"\", " +
+                    "\"res_type\":\"POST\", " +
+                    "\"res_data\":"+data+"}";
+            return res ;
+        }
+
+        public void killCallbacks() {
+            callbacks.kill();
+        }
+
+        public void broadcastResultToClients(int result_code, String result_data) {
+            // Broadcast to all clients the new value.
+            final int count = callbacks.beginBroadcast();
+            Log.i(TAG, "LigthControlServiceClientCallback count=" + count);
+            for (int index=0; index<count; index++) {
+                try {
+                    callbacks.getBroadcastItem(index).onResultReceived(result_code, result_data);
+                } catch (RemoteException e) {
+                    // The RemoteCallbackList will take care of removing
+                    // the dead object for us.
+                    Log.e(TAG, "onReceiveResult() RemoteException :", e);
+                }
+            }
+            callbacks.finishBroadcast();
+        }
+    };
+
     public void msg(String msg) {
         mHandler.sendMessage(mHandler.obtainMessage(MSG_STRING, msg));
     }
@@ -309,6 +558,9 @@ public class BridgeService extends IntentService {
                 case MSG_RESULT: {
                     rBinder.broadcastResultToClients(msg.arg1, (String)msg.obj);
                 } break ;
+                case MSG_LIGHT_RESULT: {
+                    lightBinder.broadcastResultToClients(msg.arg1, (String)msg.obj);
+                } break ;
                 default:
                     super.handleMessage(msg);
             }
@@ -483,6 +735,7 @@ public class BridgeService extends IntentService {
     }
 
     public String getAllDiscoveredDevices() {
+
         if(bridgeServer!=null) {
             ArrayList<OcRemoteDevice> devices = bridgeServer.getPairwisedDevices();
             try {

+ 4 - 0
app/src/main/java/org/iotivity/bridge/homeserver/utils/Utils.java

@@ -22,11 +22,15 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.UUID;
 
 public class Utils {
 
     private static final String TAG = Utils.class.getSimpleName();
 
+    public static long generateRandomID() {
+        return UUID.randomUUID().getMostSignificantBits() & Long.MAX_VALUE;
+    }
     public static boolean containsList(String[] arr, String targetValue) {
         return Arrays.asList(arr).contains(targetValue);
     }

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

@@ -4,7 +4,7 @@
 
     <item
         android:id="@+id/action_bridge_reset"
-        android:title="Reset Client"
+        android:title="Reset Bridge"
         app:showAsAction="never"/>