[Iotcon] Added set/unset StateChangeListener
authorPiotr Kosko <p.kosko@samsung.com>
Wed, 17 Feb 2016 10:29:56 +0000 (11:29 +0100)
committerPiotr Kosko <p.kosko@samsung.com>
Thu, 18 Feb 2016 14:22:37 +0000 (15:22 +0100)
[Verification] Code compiles, adding/removing listener works in chrome console,
  listener calls not checked.

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

index dab068b17fe65666525923e7aaeaf422e93b063d..2647cabf27f8f14564a1ddf49eb8794feeb1d9d1 100644 (file)
@@ -518,26 +518,22 @@ Response.prototype.send = function() {
   }
 };
 
-function RemoteResponse(request) {
-  validator.isConstructorCall(this, tizen.RemoteResponse);
+function RemoteResponse(data) {
+  if (data.representation) {
+    data.representation = createRepresentation(data.representation);
+  } else {
+    data.representation = null;
+  }
 
-  Object.defineProperties(this, {
-    result: {
-      value: null,
-      writable: false,
-      enumerable: true
-    },
-    representation: {
-      value: null,
-      writable: false,
-      enumerable: true
-    },
-    options: {
-      value: null,
-      writable: false,
-      enumerable: true
+  if (data.options) {
+    var options = [];
+    for (var i = 0; i < data.options.length; ++i) {
+      options.push(new IotconOption(data.options[i].id, data.options[i].data));
     }
-  });
+    data.options = options;
+  }
+
+  decorateWithData(data, this);
 }
 
 function State(key, state) {
@@ -768,11 +764,6 @@ RemoteResource.prototype.setStateChangeListener = function() {
   }, {
     name: 'successCallback',
     type: types.FUNCTION
-  }, {
-    name: 'errorCallback',
-    type: types.FUNCTION,
-    optional: true,
-    nullable: true
   }]);
 
   var callArgs = prepareResourceInfo(this);
@@ -781,12 +772,9 @@ RemoteResource.prototype.setStateChangeListener = function() {
   var that = this;
 
   var listener = function(result) {
-    if (native.isFailure(result)) {
-      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
-    } else {
-      updateWithInternalData(native.getResultObject(result), that);
-      args.successCallback(that);
-    }
+    //TODO check what should be updated
+    //updateWithInternalData(result, that);
+    args.successCallback(new RemoteResponse(result.data));
   };
 
   var result = native.callSync('IotconRemoteResource_setStateChangeListener', callArgs);
@@ -794,6 +782,7 @@ RemoteResource.prototype.setStateChangeListener = function() {
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
+    manageId(this, native.getResultObject(result));
     stateChangeListener.addListener(this[kIdKey], listener);
   }
 };
@@ -806,6 +795,7 @@ RemoteResource.prototype.unsetStateChangeListener = function() {
   if (native.isFailure(result)) {
     throw native.getErrorObject(result);
   } else {
+    manageId(this, native.getResultObject(result));
     stateChangeListener.removeListener(this[kIdKey]);
   }
 };
index be20d1e3d6007cfe46b16b4f24150e49f8bca7eb..d8c1a6afb2815e106e94d04e0a7e9d7e5d2d81f4 100644 (file)
@@ -45,6 +45,8 @@ const common::ListenerToken kFindResourceListenerToken{"FindResourceListener"};
 const common::ListenerToken kPresenceEventListenerToken{"PresenceEventListener"};
 const common::ListenerToken kRemoteResourceConnectionChangeListener
                                 {"RemoteResourceConnectionChangeListener"};
+const common::ListenerToken kRemoteResourceStateChangeListener
+                                {"RemoteResourceStateChangeListener"};
 
 const std::string kObserverIds = "observerIds";
 const std::string kQos = "qos";
@@ -535,14 +537,77 @@ common::TizenResult IotconInstance::RemoteResourceMethodDelete(const picojson::o
   return common::UnknownError("Not implemented");
 }
 
+static void ObserveCallback(iotcon_remote_resource_h resource, iotcon_error_e err,
+                            int sequence_number, iotcon_response_h response, void *user_data) {
+  ScopeLogger();
+  FoundRemoteInfo* ptr = static_cast<FoundRemoteInfo*>(user_data);
+  if (ptr->observe_listener) {
+    picojson::value json_result = picojson::value(picojson::object());
+
+    auto result = IotconUtils::ResponseToJson(response, &json_result.get<picojson::object>());
+    if (result) {
+      ptr->observe_listener(common::TizenSuccess(), json_result);
+    } else {
+      LoggerD("Ignoring callback");
+    }
+  }
+}
+
 common::TizenResult IotconInstance::RemoteResourceSetStateChangeListener(const picojson::object& args) {
   ScopeLogger();
-  return common::UnknownError("Not implemented");
+  CHECK_EXIST(args, kQuery);
+  CHECK_EXIST(args, kObservePolicy);
+  FoundRemoteInfoPtr ptr;
+  auto result = IotconUtils::RemoteResourceFromJson(args, &ptr);
+  if (!result) {
+    LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
+  }
+
+  iotcon_query_h query = nullptr;
+  auto query_obj = args.find(kQuery)->second.get<picojson::object>();
+  result = IotconUtils::QueryFromJson(query_obj, &query);
+  if (!result){
+    return result;
+  }
+  SCOPE_EXIT {
+    iotcon_query_destroy(query);
+  };
+
+  iotcon_observe_policy_e observe_policy = IotconUtils::ToObservePolicy(
+      args.find(kObservePolicy)->second.get<std::string>().c_str());
+
+  ptr->observe_listener = [this, ptr](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>(ptr->id)}));
+    obj.insert(std::make_pair("data", v));
+
+    Post(kRemoteResourceStateChangeListener, common::TizenSuccess{response});
+  };
+
+  result = IotconUtils::ConvertIotconError(
+      iotcon_remote_resource_observe_register(ptr->handle, observe_policy, query,
+                                              ObserveCallback, ptr.get()));
+  if (!result) {
+    return result;
+  }
+  return common::TizenSuccess{IotconClientManager::GetInstance().StoreRemoteResource(ptr)};
 }
 
 common::TizenResult IotconInstance::RemoteResourceUnsetStateChangeListener(const picojson::object& args) {
   ScopeLogger();
-  return common::UnknownError("Not implemented");
+  FoundRemoteInfoPtr ptr;
+  auto result = IotconUtils::RemoteResourceFromJson(args, &ptr);
+  if (!result) {
+    LogAndReturnTizenError(result, ("Failed to create remote resource handle"));
+  }
+  result = IotconUtils::ConvertIotconError(iotcon_remote_resource_observe_deregister(ptr->handle));
+  if (!result) {
+    return result;
+  }
+  ptr->observe_listener = nullptr;
+  return common::TizenSuccess{IotconClientManager::GetInstance().RemoveRemoteResource(ptr)};
 }
 
 static void RepresentationChangedCallback(iotcon_remote_resource_h resource,
index 60e05fcdff3ef49dac99d4674b698ab185a0f226..d44e8a15be3bdce26b4f9c7267e55f6ce989076f 100644 (file)
@@ -86,6 +86,11 @@ namespace {
   X(IOTCON_RESPONSE_FORBIDDEN, "FORBIDDEN") \
   XD(IOTCON_RESPONSE_ERROR, "unknown")
 
+#define IOTCON_OBSERVE_POLICY_E \
+  X(IOTCON_OBSERVE_IGNORE_OUT_OF_ORDER, "IGNORE_OUT_OF_ORDER") \
+  X(IOTCON_OBSERVE_ACCEPT_OUT_OF_ORDER, "ACCEPT_OUT_OF_ORDER") \
+  XD(IOTCON_OBSERVE_ACCEPT_OUT_OF_ORDER, "unknown")
+
 }  // namespace
 
 const std::string kIsDiscoverable = "isDiscoverable";
@@ -104,6 +109,7 @@ const std::string kKeepId = "keepId";
 const std::string kDeviceId = "deviceId";
 const std::string kHostAddress = "hostAddress";
 const std::string kConnectivityType = "connectivityType";
+const std::string kObservePolicy = "observePolicy";
 
 const std::string kRepresentation = "representation";
 const std::string kRepresentations = "representations";
@@ -1021,6 +1027,118 @@ common::TizenResult IotconUtils::QueryToJson(iotcon_query_h query,
   return TizenSuccess();
 }
 
+common::TizenResult IotconUtils::QueryFromJson(const picojson::object& source, iotcon_query_h* res) {
+  ScopeLogger();
+  iotcon_query_h query = nullptr;
+  auto result = ConvertIotconError(iotcon_query_create(&query));
+  if (!result) {
+    LogAndReturnTizenError(result, ("iotcon_query_create() failed"));
+  }
+  std::unique_ptr<std::remove_pointer<iotcon_query_h>::type, void(*)(iotcon_query_h)>
+  query_ptr(query, &iotcon_query_destroy); // automatically release the memory
+  {
+    // resourceType
+    auto it = source.find(kResourceType);
+    if (source.end() != it && it->second.is<std::string>()) {
+      const char* resource_type = it->second.get<std::string>().c_str();
+      auto result = ConvertIotconError(iotcon_query_set_resource_type(query, resource_type));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_query_set_resource_type() failed"));
+      }
+    }
+  }
+
+  {
+    // resourceInterface
+    auto it = source.find(kResourceInterface);
+    if (source.end() != it && it->second.is<std::string>()) {
+      iotcon_interface_e interface = ToInterface(it->second.get<std::string>());
+      auto result = ConvertIotconError(iotcon_query_set_interface(query, interface));
+      if (!result) {
+        LogAndReturnTizenError(result, ("iotcon_query_set_interface() failed"));
+      }
+    }
+  }
+
+  {
+    // filter
+    auto it = source.find(kFilter);
+    if (source.end() != it) {
+      const auto& filter = IotconUtils::GetArg(source, kFilter);
+      if (filter.is<picojson::object>()) {
+        const auto& filter_obj = filter.get<picojson::object>();
+        for (const auto it : filter_obj) {
+          if (it.second.is<std::string>()){
+            const std::string& key = it.first;
+            const std::string& value = it.second.get<std::string>();
+            LoggerD("key: %s  ----  value: %s", key.c_str(), value.c_str());
+
+            auto result = ConvertIotconError(iotcon_query_add(query, key.c_str(), value.c_str()));
+            if (!result) {
+              LogAndReturnTizenError(result, ("iotcon_query_add() failed"));
+            }
+          }
+        }
+      }
+    }
+  }
+
+  *res = query_ptr.release();
+  return TizenSuccess();
+}
+
+common::TizenResult IotconUtils::ResponseToJson(iotcon_response_h handle,
+                                                picojson::object* res) {
+  ScopeLogger();
+
+  {
+    // ResponseResult result
+    iotcon_response_result_e response = IOTCON_RESPONSE_ERROR;
+    auto result = ConvertIotconError(iotcon_response_get_result(handle, &response));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_response_get_result() failed"));
+    }
+    std::string result_str = FromResponseResultType(response);
+    res->insert(std::make_pair(kResultType, picojson::value{result_str}));
+  }
+
+  {
+    // Representation representation
+    iotcon_representation_h repr = nullptr;
+    auto result = ConvertIotconError(iotcon_response_get_representation(handle, &repr));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_response_get_representation() failed"));
+    }
+    picojson::value repr_json{picojson::object{}};
+    result = RepresentationToJson(repr, &repr_json.get<picojson::object>());
+    if (!result) {
+      LogAndReturnTizenError(result, ("RepresentationToJson() failed"));
+    }
+    res->insert(std::make_pair(kRepresentation, repr_json));
+  }
+
+  {
+    // IotconOption[]? options
+    iotcon_options_h options = nullptr;
+    auto result = ConvertIotconError(iotcon_response_get_options(handle, &options));
+    if (!result) {
+      LogAndReturnTizenError(result, ("iotcon_response_get_options() failed"));
+    }
+    if (options) {
+      picojson::value opt_json{picojson::array{}};
+      result = OptionsToJson(options, &opt_json.get<picojson::array>());
+      if (!result) {
+        LogAndReturnTizenError(result, ("OptionsToJson() failed"));
+      }
+      res->insert(std::make_pair(kOptions, opt_json));
+    } else {
+      res->insert(std::make_pair(kOptions, picojson::value{}));
+    }
+  }
+
+  return TizenSuccess();
+}
+
 common::TizenResult IotconUtils::RepresentationFromResource(const ResourceInfoPtr& resource,
                                                             const picojson::value& states,
                                                             iotcon_representation_h* out) {
@@ -1873,6 +1991,14 @@ std::string IotconUtils::FromPresenceTriggerType(iotcon_presence_trigger_e e) {
   }
 }
 
+std::string IotconUtils::FromResponseResultType(iotcon_response_result_e e) {
+  ScopeLogger();
+
+  switch (e) {
+    IOTCON_RESPONSE_RESULT_E
+  }
+}
+
 #undef X
 #undef XD
 
@@ -1899,6 +2025,12 @@ iotcon_connectivity_type_e IotconUtils::ToConnectivityType(const std::string& e)
   IOTCON_CONNECTIVITY_TYPE_E
 }
 
+iotcon_observe_policy_e IotconUtils::ToObservePolicy(const std::string& e) {
+  ScopeLogger();
+
+  IOTCON_OBSERVE_POLICY_E
+}
+
 iotcon_response_result_e IotconUtils::ToResponseResult(const std::string& e) {
   IOTCON_RESPONSE_RESULT_E
 }
index 280b11e4758ad5743833c3f6c3f60632aaa90b41..21dbc5b02caa03add244127a446f1503d5c6a5fb 100644 (file)
@@ -58,6 +58,8 @@ extern const std::string kConnectivityType;
 extern const std::string kResourceType;
 extern const std::string kRepresentation;
 extern const std::string kOptions;
+extern const std::string kQuery;
+extern const std::string kObservePolicy;
 
 class ResourceInfo;
 class PresenceEvent;
@@ -115,6 +117,7 @@ struct FoundRemoteInfo {
   short ref_count; // counter for registered listeners for this handle
   //TODO add listeners for each type
   common::PostCallback connection_listener;
+  common::PostCallback observe_listener;
   FoundRemoteInfo() :
     id(0), handle(nullptr), ref_count(1) {} //initialize with 1 (struct is created, so it
                                             //mean that some listener would be created)
@@ -162,6 +165,9 @@ class IotconUtils {
                                            picojson::array* out);
   static common::TizenResult QueryToJson(iotcon_query_h query,
                                          picojson::object* out);
+  static common::TizenResult QueryFromJson(const picojson::object& source, iotcon_query_h* res);
+  static common::TizenResult ResponseToJson(iotcon_response_h handle,
+                                            picojson::object* res);
   static common::TizenResult PresenceResponseToJson(iotcon_presence_response_h presence,
                                                 picojson::object* out);
   static common::TizenResult ExtractFromPresenceEvent(const PresenceEventPtr& pointer,
@@ -201,9 +207,11 @@ class IotconUtils {
   static std::string FromInterface(iotcon_interface_e e);
   static std::string FromPresenceResponseResultType(iotcon_presence_result_e e);
   static std::string FromPresenceTriggerType(iotcon_presence_trigger_e e);
+  static std::string FromResponseResultType(iotcon_response_result_e e);
 
   static iotcon_interface_e ToInterface(const std::string& e);
   static iotcon_connectivity_type_e ToConnectivityType(const std::string& e);
+  static iotcon_observe_policy_e ToObservePolicy(const std::string& e);
   static iotcon_qos_e ToQos(const std::string& e);
   static iotcon_response_result_e ToResponseResult(const std::string& e);
 };