Commit 9bce5175 authored by Jihun Ha's avatar Jihun Ha Committed by Uze Choi

[IOT-1824] Add an API to request a WiFi Connection to Enrollee

This API would be helpful to Enrollee when it destroys its Soft AP network
and tries to connect an WiFi AP with given WiFi information from Mediator

oic.r.easysetup resource
 + "connect" or "cn" property
    - type: array of integer(enum)
    - e.g., "cn" : [ 1 ] or ''cn" : [ 2 ] or "cn" : [ 1, 2 ]  // 1 : WiFi, 2 : BLE , 3 : other transport to be added in a future

Change-Id: I476c95696c8df243e83232cedc27852c875b2dbe
Signed-off-by: default avatarJihun Ha <jihun.ha@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/17061Tested-by: default avatarjenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: default avatarHeewon Park <h_w.park@samsung.com>
Reviewed-by: default avatarUze Choi <uzchoi@samsung.com>
parent 3216cb4e
......@@ -64,6 +64,7 @@ extern "C"
#define OC_RSRVD_ES_MODELNUMBER "mnmo"
#define OC_RSRVD_ES_LOCATION "loc"
#define OC_RSRVD_ES_HREF "href"
#define OC_RSRVD_ES_CONNECT "cn"
/**
* Easysetup defined resoruce types and uris.
......@@ -137,6 +138,15 @@ typedef enum
OAUTH_TOKENTYPE_MAC
} OAUTH_TOKENTYPE;
/**
* @brief A target configuration type to be connected (or executed)
*/
typedef enum
{
ES_CONNECT_WIFI = 0x01, /**< WiFi Conf resource **/
ES_CONNECT_COAPCLOUD = 0x02 /**< Coap Cloud Conf resource **/
} ES_CONNECT_TYPE;
/**
* @brief A result of Easy Setup
*/
......
......@@ -972,6 +972,39 @@ namespace OIC
ESResult m_result;
};
/**
* Status object for connect API. This object is given to application
* when a response for 'Connect' request from Enrollee is arrived.
*/
class ConnectRequestStatus
{
public:
/**
* Constructor
*/
ConnectRequestStatus(ESResult result) :
m_result(result)
{
}
/**
* Get a result of Connect request
*
* @return ::ES_OK\n
* ::ES_COMMUNICATION_ERROR\n
* ::ES_ERROR\n
*
* @see ESResult
*/
ESResult getESResult()
{
return m_result;
}
private:
ESResult m_result;
};
class ESOwnershipTransferData
{
public:
......@@ -1059,6 +1092,12 @@ namespace OIC
*/
typedef function< void(shared_ptr< CloudPropProvisioningStatus >) > CloudPropProvStatusCb;
/**
* Callback function definition for providing 'Connect' request status
*/
typedef function< void(shared_ptr< ConnectRequestStatus >) > ConnectRequestStatusCb;
/**
* Callback function definition for providing Enrollee security provisioning status
*/
......
......@@ -161,6 +161,17 @@ namespace OIC
const CloudProp& cloudProp,
const CloudPropProvStatusCb callback);
/**
* Notify an Enrollee to Connect WiFi/Cloud
*
* @param connectTypes Target configurations to be connected. E.g. WiFi and coap cloud server
* @param callback will give the result if the connect request succeeds or fails
*
* @see ES_CONNECT_TYPE
* @see ConnectRequestStatusCb
*/
void requestToConnect(const std::vector<ES_CONNECT_TYPE> &connectTypes, const ConnectRequestStatusCb callback);
private:
RemoteEnrollee(const std::shared_ptr< OC::OCResource > resource);
......@@ -185,6 +196,10 @@ namespace OIC
const std::shared_ptr< CloudPropProvisioningStatus > status,
std::weak_ptr<RemoteEnrollee> this_ptr);
static void onConnectRequestStatusHandlerCallback(
const std::shared_ptr< ConnectRequestStatus > status,
std::weak_ptr<RemoteEnrollee> this_ptr);
static void onSecurityStatusHandlerCallback(
const std::shared_ptr< SecProvisioningStatus > status,
std::weak_ptr<RemoteEnrollee> this_ptr);
......@@ -204,6 +219,8 @@ namespace OIC
(const std::shared_ptr< DevicePropProvisioningStatus > status) const;
void cloudPropProvisioningStatusHandler
(const std::shared_ptr< CloudPropProvisioningStatus > status) const;
void connectRequestStatusHandler(
const std::shared_ptr< ConnectRequestStatus > status) const;
void securityStatusHandler
(const std::shared_ptr< SecProvisioningStatus > status) const;
ESOwnershipTransferData securityStatusWithOptionHandler
......@@ -230,6 +247,7 @@ namespace OIC
SecProvisioningDbPathCb m_secProvisioningDbPathCb;
DevicePropProvStatusCb m_devicePropProvStatusCb;
CloudPropProvStatusCb m_cloudPropProvStatusCb;
ConnectRequestStatusCb m_connectRequestStatusCb;
friend class EasySetup;
};
......
......@@ -36,6 +36,10 @@ namespace OIC
EnrolleeResource::EnrolleeResource(std::shared_ptr< OC::OCResource > resource)
{
m_ocResource = resource;
m_getStatusCb = nullptr;
m_getConfigurationStatusCb = nullptr;
m_devicePropProvStatusCb = nullptr;
m_connectRequestStatusCb = nullptr;
}
void EnrolleeResource::onEnrolleeResourceSafetyCB(const HeaderOptions& headerOptions,
......@@ -157,6 +161,41 @@ namespace OIC
}
}
void EnrolleeResource::onConnectRequestResponse(const HeaderOptions& /*headerOptions*/,
const OCRepresentation& /*rep*/, const int eCode)
{
OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "onConnectRequestResponse : eCode = %d",
eCode);
if (eCode > OCStackResult::OC_STACK_RESOURCE_CHANGED)
{
ESResult result = ESResult::ES_ERROR;
OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
"onConnectRequestResponse : onConnectRequestResponse is failed ");
if(eCode == OCStackResult::OC_STACK_COMM_ERROR)
{
OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
"can't receive any response from Enrollee by a timeout threshold.");
result = ESResult::ES_COMMUNICATION_ERROR;
}
std::shared_ptr< ConnectRequestStatus > connectRequestStatus = std::make_shared<
ConnectRequestStatus >(result);
m_connectRequestStatusCb(connectRequestStatus);
return;
}
OIC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
"onConnectRequestResponse : Provisioning is success. ");
std::shared_ptr< ConnectRequestStatus > connectRequestStatus = std::make_shared<
ConnectRequestStatus >(ESResult::ES_OK);
m_connectRequestStatusCb(connectRequestStatus);
}
void EnrolleeResource::registerGetStatusCallback(
const GetStatusCb callback)
{
......@@ -175,6 +214,12 @@ namespace OIC
m_devicePropProvStatusCb = callback;
}
void EnrolleeResource::registerConnectRequestStatusCallback(
const ConnectRequestStatusCb callback)
{
m_connectRequestStatusCb = callback;
}
void EnrolleeResource::getStatus()
{
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getStatus IN");
......@@ -277,5 +322,38 @@ namespace OIC
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "provisionProperties OUT");
}
void EnrolleeResource::requestToConnect(const std::vector<ES_CONNECT_TYPE> &connectTypes)
{
OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "requestToConnect IN");
if (m_ocResource == nullptr)
{
throw ESBadRequestException("Resource is not initialized");
}
OC::QueryParamsMap query;
OC::OCRepresentation requestRepresentation;
std::vector<int> connectTypes_int;
connectTypes_int.clear();
for(auto it : connectTypes)
{
connectTypes_int.push_back(static_cast<int>(it));
}
requestRepresentation.setValue<std::vector<int>>(OC_RSRVD_ES_CONNECT, connectTypes_int);
ESEnrolleeResourceCb cb = std::bind(&EnrolleeResource::onEnrolleeResourceSafetyCB,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
static_cast<ESEnrolleeResourceCb>(
std::bind(&EnrolleeResource::onConnectRequestResponse, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)),
shared_from_this());
m_ocResource->post(OC_RSRVD_ES_RES_TYPE_EASYSETUP, OC_RSRVD_INTERFACE_DEFAULT,
requestRepresentation, QueryParamsMap(), cb, OC::QualityOfService::HighQos);
OIC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "requestToConnect OUT");
}
}
}
......@@ -59,11 +59,13 @@ namespace OIC
const GetConfigurationStatusCb callback);
void registerDevicePropProvStatusCallback(
const DevicePropProvStatusCb callback);
void registerConnectRequestStatusCallback(
const ConnectRequestStatusCb callback);
void getConfiguration();
void getStatus();
void provisionProperties(const DeviceProp& deviceProp);
void requestToConnect(const std::vector<ES_CONNECT_TYPE> &connectTypes);
private:
std::shared_ptr< OC::OCResource > m_ocResource;
......@@ -71,6 +73,7 @@ namespace OIC
GetStatusCb m_getStatusCb;
GetConfigurationStatusCb m_getConfigurationStatusCb;
DevicePropProvStatusCb m_devicePropProvStatusCb;
ConnectRequestStatusCb m_connectRequestStatusCb;
private:
static void onEnrolleeResourceSafetyCB(const HeaderOptions& headerOptions,
......@@ -89,6 +92,9 @@ namespace OIC
void onProvisioningResponse(const HeaderOptions& headerOptions,
const OCRepresentation& rep,
const int eCode);
void onConnectRequestResponse(const HeaderOptions& headerOptions,
const OCRepresentation& rep,
const int eCode);
};
}
}
......
......@@ -49,6 +49,7 @@ namespace OIC
m_secProvisioningDbPathCb = nullptr;
m_devicePropProvStatusCb = nullptr;
m_cloudPropProvStatusCb = nullptr;
m_connectRequestStatusCb = nullptr;
m_deviceId = resource->sid();
}
......@@ -204,6 +205,29 @@ namespace OIC
OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "cloudPropProvisioningStatusHandler OUT");
}
void RemoteEnrollee::onConnectRequestStatusHandlerCallback(
const std::shared_ptr< ConnectRequestStatus > status,
std::weak_ptr<RemoteEnrollee> this_ptr)
{
OIC_LOG_V(DEBUG,ES_REMOTE_ENROLLEE_TAG,"onConnectRequestStatusHandlerCallback");
std::shared_ptr<RemoteEnrollee> Ptr = this_ptr.lock();
if(Ptr)
{
Ptr->connectRequestStatusHandler(status);
}
}
void RemoteEnrollee::connectRequestStatusHandler(
const std::shared_ptr< ConnectRequestStatus > status) const
{
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connectRequestStatusHandler IN");
OIC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_TAG, "RequestConnectStatus = %d", status->getESResult());
m_connectRequestStatusCb(status);
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connectRequestStatusHandler OUT");
}
void RemoteEnrollee::onDiscoveredCallback(const std::shared_ptr<OC::OCResource> resource,
std::weak_ptr<RemoteEnrollee> this_ptr)
{
......@@ -626,6 +650,28 @@ namespace OIC
OIC_LOG(INFO, ES_REMOTE_ENROLLEE_TAG, "provisionCloudProperties OUT");
}
void RemoteEnrollee::requestToConnect(const std::vector<ES_CONNECT_TYPE> &connectTypes, const ConnectRequestStatusCb callback)
{
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connect IN");
if(!callback)
{
throw ESInvalidParameterException("Callback is empty");
}
m_connectRequestStatusCb = callback;
ConnectRequestStatusCb connectRequestStatusCb = std::bind(
&RemoteEnrollee::onConnectRequestStatusHandlerCallback,
std::placeholders::_1,
shared_from_this());
m_enrolleeResource->registerConnectRequestStatusCallback(connectRequestStatusCb);
m_enrolleeResource->requestToConnect(connectTypes);
OIC_LOG(DEBUG, ES_REMOTE_ENROLLEE_TAG, "connect OUT");
}
}
}
......
......@@ -255,6 +255,41 @@ void provisionDeviceProperty()
}
}
void connectRequestStatusCallback(std::shared_ptr< ConnectRequestStatus > requestStatus)
{
if(requestStatus->getESResult() != ES_OK)
{
cout << "Request to connection is failed." << endl;
return;
}
else
{
cout << "Request to connection is success." << endl;
}
}
void requestToConnect()
{
if(!remoteEnrollee)
{
std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
return;
}
try
{
std::vector<ES_CONNECT_TYPE> types;
types.push_back(ES_CONNECT_WIFI);
types.push_back(ES_CONNECT_COAPCLOUD);
remoteEnrollee->requestToConnect(types, connectRequestStatusCallback);
}
catch (OCException &e)
{
std::cout << "Exception during provisionDeviceProperties call" << e.reason();
return;
}
}
void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
{
switch (provStatus->getESResult())
......@@ -360,9 +395,9 @@ void foundResource(std::shared_ptr<OC::OCResource> resource)
void discoveryEnrolleeResource()
{
try
{
std::ostringstream requestURI;
try
{
std::ostringstream requestURI;
requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << OC_RSRVD_ES_RES_TYPE_EASYSETUP;
OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
......@@ -370,20 +405,21 @@ void discoveryEnrolleeResource()
std::unique_lock<std::mutex> lck(g_discoverymtx);
g_cond.wait_for(lck, std::chrono::seconds(5));
}
catch (OCException &e)
{
std::cout << "Exception in discoveryEnrolleeResource: "<<e.what();
}
catch (OCException &e)
{
std::cout << "Exception in discoveryEnrolleeResource: "<<e.what();
}
}
void DisplayMenu()
{
constexpr int DISCOVERY_ENROLLEE = 1;
constexpr int DISCOVERY_ENROLLEE = 1;
constexpr int PROVISION_SECURITY = 2;
constexpr int GET_STATUS = 3;
constexpr int GET_CONFIGURATION = 4;
constexpr int PROVISION_DEVICE_PROPERTY = 5;
constexpr int PROVISION_CLOUD_PROPERTY = 6;
constexpr int REQUEST_TO_CONNECT = 6;
constexpr int PROVISION_CLOUD_PROPERTY = 7;
std::cout << "========================================================\n";
std::cout << DISCOVERY_ENROLLEE << ". Discovery Enrollee Resource \n";
......@@ -391,6 +427,7 @@ void DisplayMenu()
std::cout << GET_STATUS << ". Get Status from Enrollee \n";
std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee \n";
std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
std::cout << REQUEST_TO_CONNECT << ". Request to Connect \n";
std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property \n";
std::cout << "========================================================\n";
......@@ -413,6 +450,9 @@ void DisplayMenu()
case PROVISION_DEVICE_PROPERTY:
provisionDeviceProperty();
break;
case REQUEST_TO_CONNECT:
requestToConnect();
break;
case PROVISION_CLOUD_PROPERTY:
provisionCloudProperty();
break;
......
......@@ -252,6 +252,41 @@ void provisionDeviceProperty()
}
}
void connectRequestStatusCallback(std::shared_ptr< ConnectRequestStatus > requestStatus)
{
if(requestStatus->getESResult() != ES_OK)
{
cout << "Request to connection is failed." << endl;
return;
}
else
{
cout << "Request to connection is success." << endl;
}
}
void requestToConnect()
{
if(!remoteEnrollee)
{
std::cout << "RemoteEnrollee is null, retry Discovery EnrolleeResource." << endl;
return;
}
try
{
std::vector<ES_CONNECT_TYPE> types;
types.push_back(ES_CONNECT_WIFI);
types.push_back(ES_CONNECT_COAPCLOUD);
remoteEnrollee->requestToConnect(types, connectRequestStatusCallback);
}
catch (OCException &e)
{
std::cout << "Exception during provisionDeviceProperties call" << e.reason();
return;
}
}
void cloudProvisioningStatusCallback(std::shared_ptr< CloudPropProvisioningStatus > provStatus)
{
switch (provStatus->getESResult())
......@@ -357,9 +392,9 @@ void foundResource(std::shared_ptr<OC::OCResource> resource)
void discoveryEnrolleeResource()
{
try
{
std::ostringstream requestURI;
try
{
std::ostringstream requestURI;
requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=" << OC_RSRVD_ES_RES_TYPE_EASYSETUP;
OCPlatform::findResource("", requestURI.str(), CT_DEFAULT, &foundResource);
std::cout<< "Finding Resource... " <<std::endl;
......@@ -375,12 +410,13 @@ void discoveryEnrolleeResource()
void DisplayMenu()
{
constexpr int DISCOVERY_ENROLLEE = 1;
constexpr int DISCOVERY_ENROLLEE = 1;
constexpr int PROVISION_SECURITY = 2;
constexpr int GET_STATUS = 3;
constexpr int GET_CONFIGURATION = 4;
constexpr int PROVISION_DEVICE_PROPERTY = 5;
constexpr int PROVISION_CLOUD_PROPERTY = 6;
constexpr int REQUEST_TO_CONNECT = 6;
constexpr int PROVISION_CLOUD_PROPERTY = 7;
std::cout << "========================================================\n";
std::cout << DISCOVERY_ENROLLEE << ". Discovery Enrollee Resource \n";
......@@ -388,6 +424,7 @@ void DisplayMenu()
std::cout << GET_STATUS << ". Get Status from Enrollee \n";
std::cout << GET_CONFIGURATION << ". Get Configuration from Enrollee \n";
std::cout << PROVISION_DEVICE_PROPERTY << ". Provision Device Property\n";
std::cout << REQUEST_TO_CONNECT << ". Request to Connect \n";
std::cout << PROVISION_CLOUD_PROPERTY << ". Provision Cloud Property \n";
std::cout << "========================================================\n";
......@@ -410,6 +447,9 @@ void DisplayMenu()
case PROVISION_DEVICE_PROPERTY:
provisionDeviceProperty();
break;
case REQUEST_TO_CONNECT:
requestToConnect();
break;
case PROVISION_CLOUD_PROPERTY:
provisionCloudProperty();
break;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment