[IOT-1824] Add an API to request a WiFi Connection to Enrollee
authorJihun Ha <jihun.ha@samsung.com>
Thu, 16 Feb 2017 09:32:32 +0000 (18:32 +0900)
committerUze Choi <uzchoi@samsung.com>
Fri, 17 Feb 2017 08:09:56 +0000 (08:09 +0000)
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: Jihun Ha <jihun.ha@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/17061
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
Reviewed-by: Heewon Park <h_w.park@samsung.com>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/easy-setup/inc/escommon.h
service/easy-setup/mediator/richsdk/inc/ESRichCommon.h
service/easy-setup/mediator/richsdk/inc/RemoteEnrollee.h
service/easy-setup/mediator/richsdk/src/EnrolleeResource.cpp
service/easy-setup/mediator/richsdk/src/EnrolleeResource.h
service/easy-setup/mediator/richsdk/src/RemoteEnrollee.cpp
service/easy-setup/sampleapp/mediator/linux/richsdk_sample/mediator.cpp
service/easy-setup/sampleapp/mediator/linux/richsdk_sample/submediator.cpp

index 20e4e43..2b66b7a 100755 (executable)
@@ -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.
@@ -138,6 +139,15 @@ typedef enum
 } 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
  */
 typedef enum
index 4c9a8f5..6fe0416 100755 (executable)
@@ -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:
@@ -1060,6 +1093,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
          */
         typedef function< void(shared_ptr<SecProvisioningStatus>) > SecurityProvStatusCb;
index 69ea0ae..76ce155 100755 (executable)
@@ -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;
         };
index 48750fb..a1e35e9 100755 (executable)
@@ -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");
+        }
     }
 }
index 803e802..f345a91 100755 (executable)
@@ -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);
         };
     }
 }
index 5bba4e5..d5ed06b 100755 (executable)
@@ -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");
+        }
     }
 }
 
index 7ecf8da..55513a8 100755 (executable)
@@ -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;
index d930acb..6bd699a 100755 (executable)
@@ -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;