const char* duid;
const char* policy;
const char* appname;
+ const char* parentUuid;
CallbackState callbackState;
} NM_NotificationData;
/**
* @brief NM_deleteApp sends application uninstall request to specified device
- * @param ctx [in] handle to context
- * @param dev_id [in] device id
- * @param app_name [in] application name to delete
+ * @param ctx [in] handle to context
+ * @param dev_id [in] device id
+ * @param parentUuid [in] id of the parent device
+ * @param app_name [in] application name to delete
* @return error code
*/
-NM_ErrorCode NM_deleteApp(NM_hContext ctx, const char* dev_id, const char* app_name);
+NM_ErrorCode NM_deleteApp(NM_hContext ctx, const char* dev_id, const char* parentUuid, const char* app_name);
/**
* @brief subscribeNotifications subscribes to secure server notifications.
#include "securitycontext.h"
#include "ctrl_app_support.h"
#include "registration_mq.h"
+#include "device_control.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
return EC_OK;
}
-NM_ErrorCode NM_deleteApp(NM_hContext ctx, const char* dev_id, const char* app_name)
+NM_ErrorCode NM_deleteApp(NM_hContext ctx, const char* dev_id, const char* parentUuid, const char* app_name)
{
FN_VISIT
- if (ctx == nullptr || dev_id == nullptr || app_name == nullptr) return EC_NULL_POINTER;
+ if (ctx == nullptr || dev_id == nullptr || app_name == nullptr || parentUuid == nullptr) return EC_NULL_POINTER;
+
+ NM_ErrorCode result = EC_OK;
try
{
- IoTDevice::deleteApp(dev_id, ctx->instance, app_name);
+ DeviceControl control(ctx->instance->host(), dev_id, ctx->instance);
+ result = control.deleteApp(app_name, parentUuid);
}
catch(NMexception& e)
{
LOG_E(TAG, "Delete applicatio error: %s, error code %d", e.what(), e.errorCode());
- return static_cast<NM_ErrorCode>(e.errorCode());
+ result = static_cast<NM_ErrorCode>(e.errorCode());
}
catch (std::exception& e)
{
LOG_E(TAG, "Delete applicatio error: %s", e.what());
- return EC_INTERNAL_ERROR;
+ result = EC_INTERNAL_ERROR;
}
- return EC_OK;
+ return result;
}
void NM_freeCharBuffer(char* buffer)
string duid = rep.getValueToString("duid");
string policy = rep.getValueToString("policy");
string appname = rep.getValueToString("appname");
+ string parentUuid = rep.getValueToString("parentUuid");
NM_NotificationType type = NM_NotificationType(stoi_secure(stype, NT_Undefined));
int pid = stoi_secure(spid, -1);
int time = stoi_secure(stime);
duid.c_str(),
policy.c_str(),
appname.c_str(),
+ parentUuid.c_str(),
callbackState
};
{
FN_VISIT
auto it = getIoTDevice(uuid);
- auto route = it->getRouting();
OCRepresentation repr;
repr.setValue("policy", policy);
- repr.setValue("route", route);
repr.setValue("duid", uuid);
- LOG_D(TAG, "Save policy for: %s with route %s", uuid.c_str(), route.c_str());
+ LOG_D(TAG, "Save policy for: %s", uuid.c_str());
iotivity->getMqHandler()->publish(POLICY_TOPIC, repr);
}
--- /dev/null
+#ifndef DEVICE_CONTROL_H
+#define DEVICE_CONTROL_H
+
+#include <OCApi.h>
+#include "iotivity.h"
+#include "nmlib.h"
+
+namespace NetworkManager
+{
+
+class DeviceControl
+{
+public:
+
+ /**
+ * @brief Type of the device control resource
+ */
+ static const std::string CTRL_RESOURCE_TYPE;
+
+ /**
+ * @brief Constructor
+ * @param host [in] host where resorce located
+ * @param duid [in] device id which expose resource
+ * @param iotivity [in] pointer to iotivity entity
+ */
+ DeviceControl(const std::string& host, const std::string& duid, IoTivity* iotivity);
+
+ /**
+ * @brief Sends application delete erquest
+ * @param app_name [in] name of the application to delete
+ * @param duid [in] id of the device for which command is sending
+ * @return error code
+ */
+ NM_ErrorCode deleteApp(const std::string& app_name, const std::string& duid);
+
+ /**
+ * @brief Sends unpair request to device
+ * @return error code
+ */
+ NM_ErrorCode unOwn();
+
+private:
+
+ NM_ErrorCode sendCommand(const OC::OCRepresentation& representation);
+
+ OC::OCResource::Ptr m_resource;
+ IoTivity* m_iotivity;
+};
+
+} // namespace NetworkManager
+
+#endif // DEVICE_CONTROL_H
namespace NetworkManager
{
-class IotRequestHandler
+/**
+ * @brief The IotResource class provides abstraction of IoTivity resource model
+ */
+class IotResourceServer
{
public:
+
+ IotResourceServer(const std::string& uri, const std::string& type);
+
+ IotResourceServer(const std::string& uri, const std::string& type, const std::vector<std::string>& interfaces);
+
+ /**
+ * @brief entityHandler - resource users request handler (called by OCF)
+ * @param request [in] request for resource
+ * @return error code or OC_EH_OK
+ */
+ OCEntityHandlerResult entityHandler(std::shared_ptr<OC::OCResourceRequest> request);
+
/**
* @brief OCResource GET method handler
* @param representation [in] request body
return OC_EH_BAD_REQ;
}
- virtual OCResourceHandle getHandle() = 0;
-
- virtual ~IotRequestHandler() {}
-};
-
-
-/**
- * @brief The IotResource class provides abstraction of IoTivity resource model
- */
-class IotResourceServer
-{
-public:
-
- IotResourceServer(IotRequestHandler* request_handler, const std::string& uri, const std::string& type);
-
- IotResourceServer(IotRequestHandler* request_handler, const std::string& uri, const std::string& type, const std::vector<std::string>& interfaces);
-
- /**
- * @brief entityHandler - resource users request handler (called by OCF)
- * @param request [in] request for resource
- * @return error code or OC_EH_OK
- */
- OCEntityHandlerResult entityHandler(std::shared_ptr<OC::OCResourceRequest> request);
-
/**
* @brief getHandle - retruns handle used for publishing of the resource on resource directory
* @return handle
private:
OCResourceHandle m_handle;
- IotRequestHandler* m_request_handler;
};
} // namespace NetworkManager
{
}
- /**
- * @brief deleteApp performes app uninstallation on remote device
- * @param duid [in] id of the device where application should be removed
- * @param iotivity [in] pointer to the IoTivity instance
- * @param app_name [in] application name
- */
- static void deleteApp(const std::string& duid, IoTivity* iotivity, const std::string& app_name);
-
- // deleteApp: implemented in iotdevice_inpl.cpp
};
typedef std::shared_ptr<IoTDevice> IoTDevicePtr;
--- /dev/null
+#include "device_control.h"
+#include "device_commands.h"
+#include "nmexceptions.h"
+#include "resource_callbacks.h"
+#include "logging.h"
+#include "network_manager_tag.h"
+
+namespace PH = std::placeholders;
+
+namespace NetworkManager
+{
+
+const std::string DeviceControl::CTRL_RESOURCE_TYPE = "device.control";
+
+DeviceControl::DeviceControl(const std::string& host, const std::string& duid, IoTivity* iotivity)
+{
+ m_resource = iotivity->findResource(host, CTRL_RESOURCE_TYPE, OC_RSRVD_WELL_KNOWN_URI, duid);
+}
+
+NM_ErrorCode DeviceControl::deleteApp(const std::string& app_name, const std::string& duid)
+{
+ if(!m_resource)
+ {
+ return EC_ITEM_NOT_FOUND;
+ }
+
+ OC::OCRepresentation request;
+ request.setValue("command", int(DeviceCommands::UNINSTALL));
+ request.setValue("name", app_name);
+ request.setValue("duid", duid);
+
+ return sendCommand(request);
+}
+
+NM_ErrorCode DeviceControl::unOwn()
+{
+ if(!m_resource)
+ {
+ return EC_ITEM_NOT_FOUND;
+ }
+
+ OC::OCRepresentation request;
+ request.setValue("command", int(DeviceCommands::UNOWN));
+ return sendCommand(request);
+}
+
+NM_ErrorCode DeviceControl::sendCommand(const OC::OCRepresentation& representation)
+{
+ NetworkManager::PostResourceCallback::Sptr callback = std::make_shared<NetworkManager::PostResourceCallback>();
+ auto result = m_resource->post(representation, QueryParamsMap{}, bind_callback(callback, PH::_1, PH::_2, PH::_3));
+
+ NM_ErrorCode error = EC_OK;
+
+ if (OC_STACK_OK != result)
+ {
+ LOG_E(TAG, "Post to control resource request failed with code: %d", result);
+ error = result == OC_STACK_UNAUTHORIZED_REQ? EC_UNAUTHORIZED : EC_IOTIVITY_ERROR;
+ }
+ else if (!callback->wait())
+ {
+ LOG_E(TAG, "Post to control resource error - callback not called");
+ error = EC_NO_CONNECTION;
+ }
+
+ return error;
+}
+
+}
namespace NetworkManager
{
-IotResourceServer::IotResourceServer(IotRequestHandler* request_handler, const std::string& uri, const std::string& type)
- : IotResourceServer(request_handler, uri, type, {OC::DEFAULT_INTERFACE})
+IotResourceServer::IotResourceServer(const std::string& uri, const std::string& type)
+ : IotResourceServer(uri, type, {OC::DEFAULT_INTERFACE})
{
}
-IotResourceServer::IotResourceServer(IotRequestHandler* request_handler, const std::string& uri, const std::string& type, const std::vector<std::string>& interfaces)
- : m_handle(nullptr), m_request_handler(request_handler)
+IotResourceServer::IotResourceServer(const std::string& uri, const std::string& type, const std::vector<std::string>& interfaces)
+ : m_handle(nullptr)
{
- if (uri.empty() || type.empty() || interfaces.size() == 0 || request_handler == nullptr)
+ if (uri.empty() || type.empty() || interfaces.size() == 0)
{
throw IoTInternalError("Register resource failed due to bad parameters", EC_BAD_PARAMETER);
}
{
OCEntityHandlerResult res = OC_EH_ERROR;
- if (request && m_request_handler != nullptr)
+ if (request)
{
std::string method = request->getRequestType();
int requestFlag = request->getRequestHandlerFlag();
{
if (method == "GET")
{
- res = m_request_handler->getHandler(representation, params, response_body);
+ res = getHandler(representation, params, response_body);
}
else if (method == "POST")
{
- res = m_request_handler->postHandler(representation, params, response_body);
+ res = postHandler(representation, params, response_body);
}
else if (method == "PUT")
{
- res = m_request_handler->putHandler(representation, params, response_body);
+ res = putHandler(representation, params, response_body);
}
else if (method == "DELETE")
{
- res = m_request_handler->deleteHandler(representation, params, response_body);
+ res = deleteHandler(representation, params, response_body);
}
}
if (requestFlag & OC::RequestHandlerFlag::ObserverFlag)
{
const OC::ObservationInfo& observationInfo = request->getObservationInfo();
- res = m_request_handler->observHandler(representation, params, observationInfo);
+ res = observHandler(representation, params, observationInfo);
}
response->setResponseResult(res);
#include <functional>
#include "resource_callbacks.h"
#include "iotutils.h"
-#include "device_commands.h"
+#include "device_control.h"
#include "EasySetup.hpp"
#include "ESRichCommon.h"
const std::string dev_info_uri{"/oic/d"};
const std::string dev_type_resource{"oic.d."};
const std::string dev_type_uri{"/oic/res?rt=oic.wk.d"};
-const std::string CTRL_RESOURCE_TYPE = "device.control";
void esErrorGuard(ESResult error)
{
}
}
-void sendCommand(OCResource::Ptr ctrl, const OC::OCRepresentation& representation)
-{
- NetworkManager::PostResourceCallback::Sptr callback = std::make_shared<NetworkManager::PostResourceCallback>();
- auto result = ctrl->post(representation, QueryParamsMap{}, bind_callback(callback, PH::_1, PH::_2, PH::_3));
-
- if (OC_STACK_OK != result)
- {
- throw NetworkManager::IoTInternalError("Post of \"unown\" request failed with code: ", result);
- }
-
- if (!callback->wait())
- {
- throw NetworkManager::IoTInternalError("Post of \"unown\" request error - callback not called", EC_UNAUTHORIZED);
- }
-}
-
}
namespace NetworkManager
{
-/**
- * @brief Implementation of static method IoTDevice::deleteApp
- * @param duid [in] id of the device where application should be removed
- * @param iotivity [in] pointer to the IoTivity instance
- * @param app_name [in] application name
- */
-void IoTDevice::deleteApp(const std::string& duid, IoTivity* iotivity, const std::string& app_name)
-{
- OC::OCResource::Ptr ctrl_resource = iotivity->findResource(iotivity->host(), CTRL_RESOURCE_TYPE, OC_RSRVD_WELL_KNOWN_URI, duid);
-
- if(!ctrl_resource)
- {
- throw IoTInternalError("Device not found", EC_ITEM_NOT_FOUND);
- }
-
- OC::OCRepresentation request;
- request.setValue("command", int(DeviceCommands::UNINSTALL));
- request.setValue("name", std::string{app_name});
- sendCommand(ctrl_resource, request);
-}
-
IoTDevice_impl::IoTDevice_impl(std::shared_ptr<OCResource> device_resource, bool connected)
: dev(device_resource), name("unknown"), model("unknown"), type("unknown"), uuid(""), spec_ver("unknown"),
online(connected), cloud_accessibility(false)
{
}
-OCResource::Ptr IoTDevice_impl::getControlResource()
+void IoTDevice_impl::unOwnDevice()
{
- if(host.empty())
+ if (host.empty())
{
- throw IoTInternalError("host is empty", EC_NOT_INITIALIZED);
+ throw IoTInternalError("Device not active", EC_ITEM_NOT_FOUND);
}
- auto iotinst = IoTivity::getInstance();
- OCResource::Ptr ctrl_resource = iotinst->findResource(host, CTRL_RESOURCE_TYPE);
-
- if(!ctrl_resource)
- {
- throw IoTInternalError("Control resource not found", EC_GENERIC_ERROR);
- }
-
- return ctrl_resource;
-}
-
-void IoTDevice_impl::unOwnDevice()
-{
- auto ctrl_resource = getControlResource();
- OCRepresentation request;
- request.setValue("command", int(DeviceCommands::UNOWN));
- sendCommand(ctrl_resource, request);
+ DeviceControl control(host, uuid, IoTivity::getInstance());
+ control.unOwn();
}
void IoTDevice_impl::setCloudProperties(const std::string& host, const std::string& provider, const std::string& token)
OC::OCRepresentation rpr;
rpr.setValue("duid", duid);
rpr.setValue("uuid", uuid);
- rpr.setValue("route", (parent.empty() ? duid : parent));
+ rpr.setValue("parentUuid", parent);
rpr.setValue("name", name);
rpr.setValue("model", model);
rpr.setValue("type", type);
rpr.setValue("report", makeReport(m_device_id, "smack", 0, report));
rpr.setValue("duid", m_device_id);
- if (m_mode == WorkingMode::Hub)
- {
- m_proxy_thread->addAction(std::async(std::launch::deferred, &ReportHandler::pass, m_report_handler, rpr, OC::QueryParamsMap{}));
- }
- else
- {
- m_report_handler->pass(rpr, OC::QueryParamsMap{});
- }
+ m_report_handler->pass(rpr, OC::QueryParamsMap{});
}
} // namespace NMD
#include "device_commands.h"
#include "application_service.h"
#include "logging.h"
+#include "device_control.h"
#define TAG "nmdaemon"
bool CommandHandler::uninstallCommand(const OC::OCRepresentation& command)
{
std::string name = command.getValue<std::string>("name");
+ std::string duid = command.getValue<std::string>("duid");
LOG_D(TAG, "Request to uninstall \"%s\"", name.c_str());
if (name.empty()) return false;
- return (0 == ApplicationService::uninstall(name));
+ bool result = false;
+
+ if (duid == m_iotivity->getDeviceID())
+ {
+ result = 0 == ApplicationService::uninstall(name);
+ }
+ else
+ {
+ if ((result = m_hub->isOwned(duid)))
+ {
+ NetworkManager::IoTivity* iot = m_iotivity;
+ auto deleter = [duid, iot, name]
+ {
+ NetworkManager::DeviceControl control("", duid, iot);
+ control.deleteApp(name, duid);
+ };
+
+ m_proxy_thread->addAction(std::async(std::launch::deferred, deleter));
+ }
+ }
+
+ return result;
}
bool CommandHandler::unOwnCommand(const OC::OCRepresentation& command)
namespace NMD
{
ControlResource::ControlResource(ICommandHandler* handler)
- : m_resource(this, CTRL_RESOURCE_URI, CTRL_RESOURCE_TYPE)
+ : NetworkManager::IotResourceServer(CTRL_RESOURCE_URI, CTRL_RESOURCE_TYPE)
, m_handler(handler)
{
assert(nullptr != handler);
OCEntityHandlerResult ControlResource::postHandler(const OC::OCRepresentation& representation, const OC::QueryParamsMap& /*params*/, OC::OCRepresentation& /*response_body*/)
{
+ LOG_D(TAG, "ControlResource::postHandler < IN");
return m_handler->process(representation) ? OC_EH_OK : OC_EH_BAD_REQ;
}
namespace NMD
{
-class ControlResource : public NetworkManager::IotRequestHandler //IotResource
+class ControlResource : public NetworkManager::IotResourceServer //IotResource
{
public:
/**
OCEntityHandlerResult postHandler(const OC::OCRepresentation& representation, const OC::QueryParamsMap& params, OC::OCRepresentation& response_body) override;
- OCResourceHandle getHandle() override
- {
- m_resource.getHandle();
- }
private:
ICommandHandler* m_handler;
- NetworkManager::IotResourceServer m_resource;
};
} // namespace NMD
else if(requestType == "POST")
{
const auto& rep = request->getResourceRepresentation();
- QueryParamsMap qp{{"did", did}, {"route", hub_did}, {"agent", agent_id}};
+ QueryParamsMap qp{{"did", did}, {"agent", agent_id}};
if (bool(proxy))
{
std::shared_ptr<ProxyThread> proxy_thread,
const std::string& _devices_file_path_name
)
- : m_resource(this, HUB_RESOURCE_URI, HUB_RESORCE_TYPE)
+ : NetworkManager::IotResourceServer(HUB_RESOURCE_URI, HUB_RESORCE_TYPE)
, m_devices_file_path_name(_devices_file_path_name)
, m_iotivity(iotivity)
, m_proxy_thread(proxy_thread)
}
}
+bool HubResource::isOwned(const std::string& duid)
+{
+ std::unique_lock<std::mutex> lock(m_mutex);
+ return m_owned_devices.find(duid) != m_owned_devices.cend();
+}
+
OCEntityHandlerResult HubResource::getHandler(const OCRepresentation& /*request_body*/, const OC::QueryParamsMap& params, OCRepresentation& response_body)
{
OCEntityHandlerResult res = OC_EH_BAD_REQ;
}
response_body.setValue("devices", dev_list);
+
+ res = OC_EH_OK;
}
return res;
if (device)
{
device->setWiFiProperties(m_iotivity->getDeviceID(), "Iotivity_PWD");
- RegistrationMQ::reg(m_iotivity->getMqHandler(), device->getUUID(), m_iotivity->getCloudAuthId(), device->getName(), device->getModel(), device->getType());
+ RegistrationMQ::reg(
+ m_iotivity->getMqHandler(),
+ device->getUUID(),
+ m_iotivity->getCloudAuthId(),
+ device->getName(),
+ device->getModel(),
+ device->getType(),
+ m_iotivity->getDeviceID()
+ );
ok = true;
}
namespace NMD
{
-class HubResource : public NetworkManager::IotRequestHandler /*NetworkManager::IotResource*/
+class HubResource : public NetworkManager::IotResourceServer
{
public:
void unownAll();
/**
+ * @brief Check that device with specified device id is owned by this hub.
+ * @param duid [in] device id.
+ * @return true if device owned by this hub.
+ */
+ bool isOwned(const std::string& duid);
+
+ /**
* @brief Set enabled state of the hub. If set to false the hub sends empty device list
* on response to "get device list" requests even if devices are found.
*/
* @brief Returns state of the hub.
* @return true if enabled and false otherwise.
*/
- bool isEnabled()
+ bool isEnabled() const
{
return m_enabled;
}
OCEntityHandlerResult postHandler(const OC::OCRepresentation& representation, const OC::QueryParamsMap& params, OC::OCRepresentation& response_body) override;
- OCResourceHandle getHandle() override
- {
- m_resource.getHandle();
- }
-
private:
/**
static const int m_find_devices_interval = 10;
static const int m_own_devices_interval = 10;
- NetworkManager::IotResourceServer m_resource;
std::string m_devices_file_path_name;
NetworkManager::IoTivity* m_iotivity;
std::shared_ptr<ProxyThread> m_proxy_thread;
{
std::string policy = rep.getValue<std::string>("policy");
std::string did = rep.getValue<std::string>("duid");
- std::string route = rep.getValue<std::string>("route");
+ std::string parentUuid = rep.getValue<std::string>("parentUuid");
LOG_D(TAG, "[Recieved Policy for %s]\n%s\n", did.c_str(), policy.c_str());
const std::string& device_id = NetworkManager::IoTivity::getInstance()->getDeviceID();
if (did == device_id)
{
iot::core::PolicyEnforce::GetInstance().ParsePolicy(policy);
}
- else if (callback && route == device_id)
+ else if (callback && parentUuid == device_id)
{
callback(head_options, rep, ecode, seq_number);
}
}
msg.setValue("duid", duid);
- it = params.find("hub_did");
-
- if (it != params.end())
- {
- msg.setValue("route", it->second);
- }
- else
- {
- msg.setValue("route", duid);
- }
it = params.find("agent");
OC::OCRepresentation representation1;
representation1.setValue("duid", DUID);
representation1.setValue("uuid", UUID);
- representation1.setValue("route", DUID);
+ representation1.setValue("parentUuid", DUID);
representation1.setValue("name", NAME);
representation1.setValue("model", MODEL);
representation1.setValue("type", TYPE);
OC::OCRepresentation representation2;
representation2.setValue("duid", DUID);
representation2.setValue("uuid", UUID);
- representation2.setValue("route", PARENT);
+ representation2.setValue("parentUuid", PARENT);
representation2.setValue("name", NAME);
representation2.setValue("model", MODEL);
representation2.setValue("type", TYPE);