[IotCon] Added implementation of findResource().
authorPiotr Kosko <p.kosko@samsung.com>
Tue, 9 Feb 2016 13:28:57 +0000 (14:28 +0100)
committerPiotr Kosko <p.kosko@samsung.com>
Tue, 16 Feb 2016 08:32:47 +0000 (09:32 +0100)
[Feature] Added findResource of Client interface.

[Verification] Code compiles.
  Code below works and successCallback is called two times:
  var server = tizen.iotcon.getServer();
  var dict = {
    resourceInterfaces : ["DEFAULT", "LINK"],
    isObservable : true,
    isDiscoverable : true
  };
  server.createResource("/a/door2", ["core.door"], dict);

  var dict = {
    resourceInterfaces : ["DEFAULT", "LINK"],
    isObservable : true,
    isDiscoverable : true
  };
  server.createResource("/a/door3", ["core.door"], dict);

  var client = tizen.iotcon.getClient();
  client.findResource(null, "core.door", "ALL",
      function(v){console.log("success for address: " + v.hostAddress + " and uri: " + v.uriPath)},
      function(e){console.log("error " + JSON.stringify(e))},false);

Change-Id: I1b7c5fb102ba0e440651b392c0cdeabf85713e43
Signed-off-by: Piotr Kosko <p.kosko@samsung.com>
src/iotcon/iotcon_api.js
src/iotcon/iotcon_instance.cc
src/iotcon/iotcon_instance.h
src/iotcon/iotcon_utils.cc
src/iotcon/iotcon_utils.h

index f51d3695eff8409eff3a2ac90a7295665ee3bf28..1275ffb7575668893071594d02a1aacc64f856dc 100644 (file)
@@ -555,7 +555,12 @@ function RemoteResource(data) {
         var callArgs = {};
         callArgs.id = this[kIdKey];
         var result = native.callSync('IotconRemoteResource_getCachedRepresentation', callArgs);
-        return createRepresentation(native.getResultObject(result));
+        if (native.isSuccess(result)) {
+          return createRepresentation(native.getResultObject(result));
+        }
+        // TODO check what should be returned
+        console.log("returning empty Object");
+        return {};
       }.bind(this),
       set: function() {},
       enumerable: true
@@ -840,6 +845,9 @@ RemoteResource.prototype.unsetConnectionChangeListener = function() {
 function Client() {
 }
 
+var findResourceListener = createListener('FindResourceListener');
+var globalFindResourceId = 0;
+
 Client.prototype.findResource = function() {
   var args = validator.validateMethod(arguments, [{
     name: 'hostAddress',
@@ -861,12 +869,17 @@ Client.prototype.findResource = function() {
     type: types.FUNCTION,
     optional: true,
     nullable: true
+  }, {
+    name: 'isSecure',
+    type: types.BOOLEAN
   }]);
 
   var callArgs = {};
+  callArgs.id = ++globalFindResourceId;
   callArgs.hostAddress = args.hostAddress;
   callArgs.resourceType = args.resourceType;
   callArgs.connectivityType = args.connectivityType;
+  callArgs.isSecure = args.isSecure;
 
   var callback = function(result) {
     if (native.isFailure(result)) {
@@ -877,10 +890,11 @@ Client.prototype.findResource = function() {
     }
   };
 
-  var result = native.call('IotconClient_findResource', callArgs, callback);
-
+  var result = native.callSync('IotconClient_findResource', callArgs);
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
+  } else {
+    findResourceListener.addListener(callArgs.id, callback);
   }
 };
 
index a0657183b99ea97a627fcddc1031c89f6b85b0ec..6f2e9d153c3fa1a3dfc7ff81b44f20899bf81157 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "common/logger.h"
 #include "common/scope_exit.h"
+#include "common/tools.h"
 
 #include "iotcon/iotcon_utils.h"
 
@@ -55,6 +56,7 @@ const picojson::value& GetArg(const picojson::object& args, const std::string& n
 }
 
 const common::ListenerToken kResourceRequestListenerToken{"ResourceRequestListener"};
+const common::ListenerToken kFindResourceListenerToken{"FindResourceListener"};
 
 const std::string kObserverIds = "observerIds";
 const std::string kQos = "qos";
@@ -95,6 +97,7 @@ IotconInstance::IotconInstance() {
   REGISTER_SYNC("Iotcon_setTimeout", SetTimeout);
   REGISTER_SYNC("IotconServer_createResource", ServerCreateResource);
   REGISTER_SYNC("IotconServer_removeResource", ServerRemoveResource);
+  REGISTER_SYNC("IotconClient_findResource", ClientFindResource);
 
 #undef REGISTER_SYNC
 
@@ -105,7 +108,6 @@ IotconInstance::IotconInstance() {
   REGISTER_ASYNC("IotconRemoteResource_methodPut", RemoteResourceMethodPut);
   REGISTER_ASYNC("IotconRemoteResource_methodPost", RemoteResourceMethodPost);
   REGISTER_ASYNC("IotconRemoteResource_methodDelete", RemoteResourceMethodDelete);
-  REGISTER_ASYNC("IotconClient_findResource", ClientFindResource);
   REGISTER_ASYNC("IotconClient_getDeviceInfo", ClientGetDeviceInfo);
   REGISTER_ASYNC("IotconClient_getPlatformInfo", ClientGetPlatformInfo);
 
@@ -465,10 +467,88 @@ common::TizenResult IotconInstance::RemoteResourceUnsetConnectionChangeListener(
   return common::UnknownError("Not implemented");
 }
 
-common::TizenResult IotconInstance::ClientFindResource(const picojson::object& args,
-                                                       const common::AsyncToken& token) {
+void IotconInstance::ResourceFoundCallback(iotcon_remote_resource_h resource,
+                                           iotcon_error_e result, void *user_data) {
   ScopeLogger();
-  return common::UnknownError("Not implemented");
+  CallbackData* data = static_cast<CallbackData*>(user_data);
+  auto ret = IotconUtils::ConvertIotconError(result);
+  if (!ret) {
+    data->fun(ret, picojson::value{});
+    return;
+  }
+
+  picojson::value json_result = picojson::value(picojson::object());
+
+  ret = IotconUtils::RemoteResourceToJson(resource, &(json_result.get<picojson::object>()));
+  if (!ret) {
+    data->fun(ret, picojson::value{});
+    return;
+  }
+  data->fun(ret, json_result);
+}
+
+common::TizenResult IotconInstance::ClientFindResource(const picojson::object& args) {
+  ScopeLogger();
+
+  CHECK_EXIST(args, kHostAddress);
+  char* host_address = nullptr;
+  if (args.find(kHostAddress)->second.is<std::string>()) {
+    host_address = const_cast<char*>(args.find(kHostAddress)->second.get<std::string>().c_str());
+  }
+
+  CHECK_EXIST(args, kResourceType);
+  char* resource_type = nullptr;
+  if (args.find(kResourceType)->second.is<std::string>()) {
+    resource_type = const_cast<char*>(args.find(kResourceType)->second.get<std::string>().c_str());
+  }
+
+  CHECK_EXIST(args, kConnectivityType);
+  iotcon_connectivity_type_e connectivity_type = IotconUtils::ToConnectivityType(
+      args.find(kConnectivityType)->second.get<std::string>());
+  CHECK_EXIST(args, kIsSecure);
+  bool is_secure = args.find(kIsSecure)->second.get<bool>();
+
+  long long id = GetId(args);
+  auto response = [this, id](const common::TizenResult& res, const picojson::value& v) {
+    picojson::value response{picojson::object{}};
+    auto& obj = response.get<picojson::object>();
+
+    obj.insert(std::make_pair(kId, picojson::value{static_cast<double>(id)}));
+    if(res) {
+      common::tools::ReportSuccess(v, obj);
+    } else {
+      common::tools::ReportError(res, &obj);
+    }
+
+    Post(kFindResourceListenerToken, common::TizenSuccess{response});
+  };
+  CallbackData* data = new CallbackData{response};
+
+  LoggerD("Running find with:\nhost_address: %s,\nconnectivity_type: %d,\nresource_type: %s,\nis_secure: %d",
+          host_address, connectivity_type, resource_type, is_secure);
+  auto result = IotconUtils::ConvertIotconError(
+      iotcon_find_resource(host_address, connectivity_type, resource_type,
+                           is_secure, ResourceFoundCallback, data));
+  if (!result) {
+    delete data;
+    LogAndReturnTizenError(result);
+  } else {
+    int timeout = 60; //default value set much bigger than default value for iotcon = 30s
+    auto result = IotconUtils::ConvertIotconError(iotcon_get_timeout(&timeout));
+    if (!result) {
+      LoggerE("iotcon_get_timeout - function call failed, using default value %d", timeout);
+    } else {
+      timeout = timeout + 1; //add one extra second to prevent too fast delete
+    }
+    // adding listener to delete data, when find would be finished
+    std::thread([data, timeout]() {
+      std::this_thread::sleep_for(std::chrono::seconds(timeout));
+      LoggerD("Deleting resource find data: %p", data);
+      delete data;
+    }).detach();
+  }
+
+  return common::TizenSuccess();
 }
 
 common::TizenResult IotconInstance::ClientAddPresenceEventListener(const picojson::object& args) {
index abcc198a294d530df8dc5a465ee0d0e520022136..0793370a6d2a2547dda9baac9f1150859a8c58e7 100644 (file)
@@ -30,6 +30,8 @@ class IotconInstance : public common::TizenInstance {
   virtual ~IotconInstance();
  private:
   static void ConnectionChangedCallback(bool is_connected, void* user_data);
+  static void ResourceFoundCallback(iotcon_remote_resource_h resource,
+                                    iotcon_error_e result, void *user_data);
 
   common::TizenResult ResourceGetObserverIds(const picojson::object& args);
   common::TizenResult ResourceNotify(const picojson::object& args);
@@ -55,8 +57,7 @@ class IotconInstance : public common::TizenInstance {
   common::TizenResult RemoteResourceStopCaching(const picojson::object& args);
   common::TizenResult RemoteResourceSetConnectionChangeListener(const picojson::object& args);
   common::TizenResult RemoteResourceUnsetConnectionChangeListener(const picojson::object& args);
-  common::TizenResult ClientFindResource(const picojson::object& args,
-                                         const common::AsyncToken& token);
+  common::TizenResult ClientFindResource(const picojson::object& args);
   common::TizenResult ClientAddPresenceEventListener(const picojson::object& args);
   common::TizenResult ClientRemovePresenceEventListener(const picojson::object& args);
   common::TizenResult ClientGetDeviceInfo(const picojson::object& args,
index 7b19dc89102db1bd724e328513e37811e58a5c11..2d6c192f2787c41a9a2ea27134b6245baa622792 100644 (file)
@@ -80,9 +80,10 @@ const std::string kResourceChildren = "resources";
 const std::string kUriPath = "uriPath";
 const std::string kStates = "states";
 const std::string kId = "id";
-
+const std::string kDeviceId = "deviceId";
 const std::string kHostAddress = "hostAddress";
 const std::string kConnectivityType = "connectivityType";
+
 const std::string kRepresentation = "representation";
 const std::string kRepresentations = "representations";
 const std::string kRequestType = "type";
@@ -120,6 +121,22 @@ const std::string kDataModelVersion = "dataModelVersion";
 using common::TizenResult;
 using common::TizenSuccess;
 
+
+void IotconUtils::PropertiesToJson(int properties, picojson::object* res) {
+  bool value = properties & IOTCON_RESOURCE_OBSERVABLE;
+  res->insert(std::make_pair(kIsObservable, picojson::value(value)));
+  value = properties & IOTCON_RESOURCE_DISCOVERABLE;
+  res->insert(std::make_pair(kIsDiscoverable, picojson::value(value)));
+  value = properties & IOTCON_RESOURCE_ACTIVE;
+  res->insert(std::make_pair(kIsActive, picojson::value(value)));
+  value = properties & IOTCON_RESOURCE_SLOW;
+  res->insert(std::make_pair(kIsSlow, picojson::value(value)));
+  value = properties & IOTCON_RESOURCE_SECURE;
+  res->insert(std::make_pair(kIsSecure, picojson::value(value)));
+  value = properties & IOTCON_RESOURCE_EXPLICIT_DISCOVERABLE;
+  res->insert(std::make_pair(kIsExplicitDiscoverable, picojson::value(value)));
+}
+
 TizenResult IotconUtils::ArrayToInterfaces(const picojson::array& interfaces, int* res) {
   ScopeLogger();
 
@@ -246,18 +263,7 @@ TizenResult IotconUtils::ResourceToJson(ResourceInfoPtr pointer,
 
   res->insert(std::make_pair(kResourceInterfaces,
                              picojson::value(InterfacesToArray(ifaces))));
-  bool value = properties & IOTCON_RESOURCE_OBSERVABLE;
-  res->insert(std::make_pair(kIsObservable, picojson::value(value)));
-  value = properties & IOTCON_RESOURCE_DISCOVERABLE;
-  res->insert(std::make_pair(kIsDiscoverable, picojson::value(value)));
-  value = properties & IOTCON_RESOURCE_ACTIVE;
-  res->insert(std::make_pair(kIsActive, picojson::value(value)));
-  value = properties & IOTCON_RESOURCE_SLOW;
-  res->insert(std::make_pair(kIsSlow, picojson::value(value)));
-  value = properties & IOTCON_RESOURCE_SECURE;
-  res->insert(std::make_pair(kIsSecure, picojson::value(value)));
-  value = properties & IOTCON_RESOURCE_EXPLICIT_DISCOVERABLE;
-  res->insert(std::make_pair(kIsExplicitDiscoverable, picojson::value(value)));
+  IotconUtils::PropertiesToJson(properties, res);
 
   picojson::array children;
   for (const auto& child_resource : pointer->children) {
@@ -274,6 +280,116 @@ TizenResult IotconUtils::ResourceToJson(ResourceInfoPtr pointer,
   return TizenSuccess();
 }
 
+TizenResult IotconUtils::ExtractFromRemoteResource(RemoteResourceInfo* resource) {
+  ScopeLogger();
+
+  auto result = ConvertIotconError(
+      iotcon_remote_resource_get_uri_path(resource->resource, &resource->uri_path));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering uri path failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_connectivity_type(resource->resource, &resource->connectivity_type));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering connectivity type failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_host_address(resource->resource, &resource->host_address));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering host address failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_device_id(resource->resource, &resource->device_id));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering host address failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_types(resource->resource, &resource->types));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering types failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_interfaces(resource->resource, &resource->ifaces));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering interfaces failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_properties(resource->resource, &resource->properties));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering properties failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_options(resource->resource, &resource->options));
+  if (!result) {
+    LogAndReturnTizenError(result, ("Gathering options failed"));
+  }
+
+  result = ConvertIotconError(
+      iotcon_remote_resource_get_cached_representation(resource->resource, &resource->representation));
+  if (!result) {
+    LoggerD("Gathering cached representation failed");
+    //TODO check: native method returns error here, now ignoring fail instead of returning error
+    //LogAndReturnTizenError(result, ("Gathering cached representation failed"));
+  }
+
+  return TizenSuccess();
+}
+
+TizenResult IotconUtils::RemoteResourceToJson(iotcon_remote_resource_h handle,
+                                              picojson::object* res) {
+  ScopeLogger();
+
+  RemoteResourceInfo remote_res;
+  remote_res.resource = handle;
+  auto result = ExtractFromRemoteResource(&remote_res);
+  if (!result){
+    return result;
+  }
+  res->insert(std::make_pair(kUriPath, picojson::value(remote_res.uri_path)));
+  res->insert(std::make_pair(kConnectivityType, picojson::value(
+      FromConnectivityType(remote_res.connectivity_type))));
+  res->insert(std::make_pair(kHostAddress, picojson::value(remote_res.host_address)));
+  res->insert(std::make_pair(kDeviceId, picojson::value(remote_res.device_id)));
+
+  if (remote_res.types) {
+    picojson::array types;
+    iotcon_resource_types_foreach(remote_res.types, ResourceTypeIterator, &types);
+    res->insert(std::make_pair(kResourceTypes, picojson::value(types)));
+  }
+
+  res->insert(std::make_pair(kResourceInterfaces,
+                             picojson::value(InterfacesToArray(remote_res.ifaces))));
+
+  IotconUtils::PropertiesToJson(remote_res.properties, res);
+
+  if (remote_res.options) {
+    picojson::value opt_json{picojson::array{}};
+    result = OptionsToJson(remote_res.options, &opt_json.get<picojson::array>());
+    if (!result) {
+      LogAndReturnTizenError(result, ("OptionsToJson() failed"));
+    }
+    res->insert(std::make_pair(kOptions, opt_json));
+  }
+
+  if (remote_res.representation) {
+    picojson::value repr_json{picojson::object{}};
+    result = RepresentationToJson(remote_res.representation, &repr_json.get<picojson::object>());
+    if (!result) {
+      LogAndReturnTizenError(result, ("RepresentationToJson() failed"));
+    }
+    res->insert(std::make_pair(kRepresentation, repr_json));
+  }
+
+  return TizenSuccess();
+}
+
 common::TizenResult IotconUtils::RequestToJson(iotcon_request_h request,
                                                picojson::object* out) {
   ScopeLogger();
index bfcfd74777618844bd7080f617f164b9ec2a416a..fdbfc31338ee9519e8fea9e42c295e6de799f9c9 100644 (file)
@@ -45,8 +45,10 @@ extern const std::string kResourceChildren;
 extern const std::string kUriPath;
 extern const std::string kStates;
 extern const std::string kId;
+extern const std::string kDeviceId;
 extern const std::string kHostAddress;
 extern const std::string kConnectivityType;
+extern const std::string kResourceType;
 
 class ResourceInfo;
 typedef std::shared_ptr<ResourceInfo> ResourceInfoPtr;
@@ -71,8 +73,30 @@ struct ResourceInfo {
   }
 };
 
+struct RemoteResourceInfo {
+  iotcon_remote_resource_h resource;
+  char* uri_path;
+  iotcon_connectivity_type_e connectivity_type;
+  char* host_address;
+  char* device_id;
+  iotcon_resource_types_h types;
+  int ifaces;
+  int properties;  // to check if observable
+  iotcon_options_h options;
+  iotcon_representation_h representation;
+  RemoteResourceInfo() :
+    resource(nullptr), uri_path(nullptr),
+    connectivity_type(IOTCON_CONNECTIVITY_ALL), host_address(nullptr),
+    device_id(nullptr), types(nullptr), ifaces(0),
+    properties(0), options(nullptr), representation(nullptr) {}
+  ~RemoteResourceInfo() {
+    //according to native description, must not release any handles
+  }
+};
+
 class IotconUtils {
  public:
+  static void PropertiesToJson(int properties, picojson::object* res);
   static common::TizenResult ArrayToInterfaces(const picojson::array& interfaces, int* res);
   static picojson::array InterfacesToArray(int interfaces);
   static common::TizenResult ArrayToTypes(const picojson::array& types, iotcon_resource_types_h* res);
@@ -83,6 +107,9 @@ class IotconUtils {
                                                  int* properties);
   static common::TizenResult ResourceToJson(ResourceInfoPtr pointer,
                                             picojson::object* res);
+  static common::TizenResult ExtractFromRemoteResource(RemoteResourceInfo* resource);
+  static common::TizenResult RemoteResourceToJson(iotcon_remote_resource_h handle,
+                                                  picojson::object* res);
 
   static common::TizenResult RequestToJson(iotcon_request_h request,
                                            picojson::object* out);