From 8f6dc93a7ab3034c3ae04363cca4f923f154ffcb Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Wed, 17 Feb 2016 11:29:56 +0100 Subject: [PATCH] [Iotcon] Added set/unset StateChangeListener [Verification] Code compiles, adding/removing listener works in chrome console, listener calls not checked. Change-Id: I9f91f2a48355b8fa52ff4fe527039b7f770d48c7 Signed-off-by: Piotr Kosko --- src/iotcon/iotcon_api.js | 48 +++++-------- src/iotcon/iotcon_instance.cc | 69 +++++++++++++++++- src/iotcon/iotcon_utils.cc | 132 ++++++++++++++++++++++++++++++++++ src/iotcon/iotcon_utils.h | 8 +++ 4 files changed, 226 insertions(+), 31 deletions(-) diff --git a/src/iotcon/iotcon_api.js b/src/iotcon/iotcon_api.js index dab068b1..2647cabf 100644 --- a/src/iotcon/iotcon_api.js +++ b/src/iotcon/iotcon_api.js @@ -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]); } }; diff --git a/src/iotcon/iotcon_instance.cc b/src/iotcon/iotcon_instance.cc index be20d1e3..d8c1a6af 100644 --- a/src/iotcon/iotcon_instance.cc +++ b/src/iotcon/iotcon_instance.cc @@ -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(user_data); + if (ptr->observe_listener) { + picojson::value json_result = picojson::value(picojson::object()); + + auto result = IotconUtils::ResponseToJson(response, &json_result.get()); + 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(); + 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().c_str()); + + ptr->observe_listener = [this, ptr](const common::TizenResult& res, const picojson::value& v) { + picojson::value response{picojson::object{}}; + auto& obj = response.get(); + + obj.insert(std::make_pair(kId, picojson::value{static_cast(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, diff --git a/src/iotcon/iotcon_utils.cc b/src/iotcon/iotcon_utils.cc index 60e05fcd..d44e8a15 100644 --- a/src/iotcon/iotcon_utils.cc +++ b/src/iotcon/iotcon_utils.cc @@ -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::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()) { + const char* resource_type = it->second.get().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()) { + iotcon_interface_e interface = ToInterface(it->second.get()); + 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()) { + const auto& filter_obj = filter.get(); + for (const auto it : filter_obj) { + if (it.second.is()){ + const std::string& key = it.first; + const std::string& value = it.second.get(); + 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()); + 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()); + 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 } diff --git a/src/iotcon/iotcon_utils.h b/src/iotcon/iotcon_utils.h index 280b11e4..21dbc5b0 100644 --- a/src/iotcon/iotcon_utils.h +++ b/src/iotcon/iotcon_utils.h @@ -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); }; -- 2.34.1