From: Piotr Kosko Date: Tue, 9 Feb 2016 13:28:57 +0000 (+0100) Subject: [IotCon] Added implementation of findResource(). X-Git-Tag: submit/tizen/20160222.104327^2~16 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=02d53eac78aab028b75326a49e855a70f185923e;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [IotCon] Added implementation of findResource(). [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 --- diff --git a/src/iotcon/iotcon_api.js b/src/iotcon/iotcon_api.js index f51d3695..1275ffb7 100644 --- a/src/iotcon/iotcon_api.js +++ b/src/iotcon/iotcon_api.js @@ -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); } }; diff --git a/src/iotcon/iotcon_instance.cc b/src/iotcon/iotcon_instance.cc index a0657183..6f2e9d15 100644 --- a/src/iotcon/iotcon_instance.cc +++ b/src/iotcon/iotcon_instance.cc @@ -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(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())); + 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()) { + host_address = const_cast(args.find(kHostAddress)->second.get().c_str()); + } + + CHECK_EXIST(args, kResourceType); + char* resource_type = nullptr; + if (args.find(kResourceType)->second.is()) { + resource_type = const_cast(args.find(kResourceType)->second.get().c_str()); + } + + CHECK_EXIST(args, kConnectivityType); + iotcon_connectivity_type_e connectivity_type = IotconUtils::ToConnectivityType( + args.find(kConnectivityType)->second.get()); + CHECK_EXIST(args, kIsSecure); + bool is_secure = args.find(kIsSecure)->second.get(); + + 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(); + + obj.insert(std::make_pair(kId, picojson::value{static_cast(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) { diff --git a/src/iotcon/iotcon_instance.h b/src/iotcon/iotcon_instance.h index abcc198a..0793370a 100644 --- a/src/iotcon/iotcon_instance.h +++ b/src/iotcon/iotcon_instance.h @@ -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, diff --git a/src/iotcon/iotcon_utils.cc b/src/iotcon/iotcon_utils.cc index 7b19dc89..2d6c192f 100644 --- a/src/iotcon/iotcon_utils.cc +++ b/src/iotcon/iotcon_utils.cc @@ -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()); + 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()); + 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(); diff --git a/src/iotcon/iotcon_utils.h b/src/iotcon/iotcon_utils.h index bfcfd747..fdbfc313 100644 --- a/src/iotcon/iotcon_utils.h +++ b/src/iotcon/iotcon_utils.h @@ -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 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);