Add Firmware update sample
authorMinji Park <minjii.park@samsung.com>
Mon, 3 Apr 2017 04:15:00 +0000 (13:15 +0900)
committerJee Hyeok Kim <jihyeok13.kim@samsung.com>
Fri, 7 Apr 2017 03:45:20 +0000 (03:45 +0000)
Change-Id: I4c3609551932f7d80996074060dc71d199475841
Signed-off-by: Jee Hyeok Kim <jihyeok13.kim@samsung.com>
Signed-off-by: Minji Park <minjii.park@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/18475
Tested-by: jenkins-iotivity <jenkins@iotivity.org>
cloud/samples/client/airconditioner/aircon_controlee.cpp
cloud/samples/client/airconditioner/aircon_controller.cpp

index 9f9f566..04d3046 100644 (file)
@@ -6,6 +6,7 @@
 #include <vector>
 #include <string>
 #include <unistd.h>
+#include <mutex>
 
 #include "ocstack.h"
 #include "ocpayload.h"
@@ -14,6 +15,8 @@
 #include <OCApi.h>
 #include <OCPlatform.h>
 
+#include <pthread.h>
+
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
 #include "ocprovisioningmanager.h"
 #include "mbedtls/ssl_ciphersuites.h"
@@ -430,6 +433,208 @@ class AirConditionerResource : public Resource // oic.d.airconditioner
         }
 };
 
+class FirmwareResource : public Resource // x.samsung.firmware
+{
+    private:
+        string  m_currentversion;
+        int     m_state;    //0: Idle, 1: Downloading, 2: Downloaded, 3: Updating
+        int     m_result;   //0: Initial, 1: success, 2: not enough space, 3: out of ram, 4: connection lost, 5: invalid binary, 6: invalid uri, 7: update failed, 8: unsupport protocol
+        string  m_packageuri;
+        string  m_newversion;
+        int     m_updatemethod; //0: download immediatly, 1: user trigger download
+
+        bool    m_update;
+
+    public:
+        FirmwareResource(string uri, vector<string> rt, vector<string> itf)
+            : Resource(uri, rt, itf)
+        {
+            m_currentversion = "My Custom Binary Version 0";
+            m_state = 0;
+            m_result = 0;
+            m_packageuri = "";
+            m_newversion = "";
+            m_updatemethod = 0;
+
+            m_representation.setValue<string>("currentversion", m_currentversion);
+            m_representation.setValue<int>("state", m_state);
+            m_representation.setValue<int>("result", m_result);
+
+            m_representation.setValue<string>("packageuri", m_packageuri);
+            m_representation.setValue<string>("newversion", m_newversion);
+            m_representation.setValue<int>("updatemethod", m_updatemethod);
+        }
+
+        void onUpdateFirmware()
+        {
+            cout << "***Starting firmware update***" << endl;
+
+            sleep(1);
+            cout << "***Downloading image...***" << endl;
+
+            //Downloading, Initial
+            m_representation.setValue<int>("state", 1);
+            m_representation.setValue<int>("result", 0);
+            propagate();
+
+            sleep(5);
+            cout << "***Image downloaded, checking...***" << endl;
+
+            //Downloaded
+            m_representation.setValue<int>("state", 2);
+            propagate();
+
+            sleep(1);
+            cout << "***Updating image...***" << endl;
+
+            //Updating
+            m_representation.setValue<int>("state", 3);
+            propagate();
+
+            sleep(5);
+
+            //Idle, success
+            m_representation.setValue<int>("state", 0);
+            m_representation.setValue<int>("result", 1);
+
+            m_newversion = m_representation.getValue<string>("newversion");
+            m_currentversion = m_representation.getValue<string>("currentversion");
+
+            cout << "***Update completed from " << m_currentversion << " to " << m_newversion << "***" << endl;
+
+            m_representation.setValue<string>("currentversion", m_newversion);
+            m_representation.setValue<string>("newversion", "");
+            m_representation.setValue<string>("packageuri", "");
+            propagate();
+
+            sleep(2);
+            m_representation.setValue<int>("result", 0);
+            propagate();
+        }
+
+        static void *_worker(void *pArg)
+        {
+            FirmwareResource *pThread = (FirmwareResource *)pArg;
+            pThread->onUpdateFirmware();
+        }
+
+        void setFirmwareRepresentation(OCRepresentation &rep)
+        {
+            bool hasUpdates = false;
+
+            if (rep.getValue<string>("packageuri", m_packageuri))
+            {
+                cout << "\t\t\t\t" << "packageuri: " << m_packageuri << endl;
+                m_representation.setValue<string>("packageuri", m_packageuri);
+                hasUpdates = true;
+            }
+
+            if (rep.getValue<string>("newversion", m_newversion))
+            {
+                cout << "\t\t\t\t" << "newversion: " << m_newversion << endl;
+                m_representation.setValue<string>("newversion", m_newversion);
+                hasUpdates = true;
+            }
+
+            if (rep.getValue<int>("updatemethod", m_updatemethod))
+            {
+                cout << "\t\t\t\t" << "updatemethod: " << m_updatemethod << endl;
+                m_representation.setValue<int>("updatemethod", m_updatemethod);
+                hasUpdates = true;
+            }
+
+            if (rep.getValue<bool>("update", m_update))
+            {
+                cout << "\t\t\t\t" << "update: " << m_update << endl;
+                hasUpdates = true;
+
+                pthread_t hThread;
+                //Start temp thread to manage update simulator
+                pthread_create(&hThread, NULL, (void *(*)(void *))_worker, (void *)this);
+            }
+
+            if (hasUpdates)
+            {
+                propagate();
+            }
+        }
+
+        OCEntityHandlerResult entityHandler(shared_ptr<OCResourceRequest> request)
+        {
+            cout << "\tIn Server Firmware entity handler:\n";
+            OCEntityHandlerResult ehResult = OC_EH_ERROR;
+
+            if (request)
+            {
+                // Get the request type and request flag
+                string requestType = request->getRequestType();
+                int requestFlag = request->getRequestHandlerFlag();
+
+                if (requestFlag & RequestHandlerFlag::RequestFlag)
+                {
+                    cout << "\t\trequestFlag : Request\n";
+
+                    // If the request type is GET
+                    if (requestType == "GET")
+                    {
+                        cout << "\t\t\trequestType : GET\n";
+                        if (OC_STACK_OK == sendRepresentation(request))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
+                    }
+                    else if (requestType == "PUT")
+                    {
+                        cout << "\t\t\trequestType : PUT\n";
+                        // PUT requeist operations
+                    }
+                    else if (requestType == "POST")
+                    {
+                        cout << "\t\t\trequestType : POST\n";
+                        // POST request operations
+                        OCRepresentation    rep = request->getResourceRepresentation();
+                        setFirmwareRepresentation(rep);
+
+                        if (OC_STACK_OK == sendRepresentation(request))
+                        {
+                            ehResult = OC_EH_OK;
+                        }
+                    }
+                    else if (requestType == "DELETE")
+                    {
+                        cout << "\t\t\trequestType : DELETE\n";
+                        // DELETE request operations
+                    }
+                }
+
+                if (requestFlag & RequestHandlerFlag::ObserverFlag)
+                {
+                    cout << "\t\trequestFlag : Observer\n";
+
+                    ObservationInfo observationInfo = request->getObservationInfo();
+                    if (ObserveAction::ObserveRegister == observationInfo.action)
+                    {
+                        m_interestedObservers.push_back(observationInfo.obsId);
+                    }
+                    else if (ObserveAction::ObserveUnregister == observationInfo.action)
+                    {
+                        m_interestedObservers.erase(remove(
+                                                        m_interestedObservers.begin(),
+                                                        m_interestedObservers.end(),
+                                                        observationInfo.obsId),
+                                                    m_interestedObservers.end());
+                    }
+                }
+            }
+            else
+            {
+                cout << "Request invalid" << endl;
+            }
+
+            return ehResult;
+        }
+};
+
 condition_variable g_callbackLock;
 string             g_uid;
 string             g_accesstoken;
@@ -509,7 +714,7 @@ int saveTrustCert(void)
     OCStackResult res = OC_STACK_ERROR;
     uint16_t g_credId = 0;
 
-    cout << "Save Trust Cert. Chain into Cred of SVR" <<endl;
+    cout << "Save Trust Cert. Chain into Cred of SVR" << endl;
 
     ByteArray trustCertChainArray = {0, 0};
 
@@ -531,15 +736,16 @@ int saveTrustCert(void)
             rewind(fp);
             if (fsize != fread(trustCertChainArray.data, 1, fsize, fp))
             {
-                 cout << "Certiface not read completely" << endl;
+                cout << "Certiface not read completely" << endl;
             }
             fclose(fp);
         }
     }
 
-    res = OCSaveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len, OIC_ENCODING_PEM,&g_credId);
+    res = OCSaveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len, OIC_ENCODING_PEM,
+                               &g_credId);
 
-    if(OC_STACK_OK != res)
+    if (OC_STACK_OK != res)
     {
         cout << "OCSaveTrustCertChainBin API error" << endl;
         return res;
@@ -554,7 +760,7 @@ static FILE *client_open(const char *path, const char *mode)
 {
     if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
     {
-               return fopen("./aircon_controlee.dat", mode);
+        return fopen("./aircon_controlee.dat", mode);
     }
     else
     {
@@ -629,37 +835,37 @@ int main(int argc, char *argv[])
 
     OCStackResult result = OC_STACK_ERROR;
 
-       g_host = "coap+tcp://";
+    g_host = "coap+tcp://";
 
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-       g_host = "coaps+tcp://";
+    g_host = "coaps+tcp://";
 #endif
 
 
-       g_host += argv[1];
+    g_host += argv[1];
 
-       OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(g_host,
-               CT_ADAPTER_TCP);
+    OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(g_host,
+                                       CT_ADAPTER_TCP);
 
 
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-       cout << "Security Mode" << endl;
-       if (CA_STATUS_OK != saveTrustCert())
-       {
-               cout << "saveTrustCert returned an error" << endl;
-       }
-
-       uint16_t cipher = MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256;
-       if (CA_STATUS_OK != CASelectCipherSuite(cipher, CA_ADAPTER_TCP))
-       {
-               cout << "CASelectCipherSuite returned an error" << endl;
-       }
+    cout << "Security Mode" << endl;
+    if (CA_STATUS_OK != saveTrustCert())
+    {
+        cout << "saveTrustCert returned an error" << endl;
+    }
+
+    uint16_t cipher = MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256;
+    if (CA_STATUS_OK != CASelectCipherSuite(cipher, CA_ADAPTER_TCP))
+    {
+        cout << "CASelectCipherSuite returned an error" << endl;
+    }
 #endif
 
     mutex blocker;
     unique_lock<mutex> lock(blocker);
 
-       if (strlen(argv[2]) > 35)
+    if (strlen(argv[2]) > 35)
     {
         accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB);
         g_callbackLock.wait(lock);
@@ -680,6 +886,8 @@ int main(int argc, char *argv[])
 
     TemperatureResource     temperature("/temperature/0", { "oic.r.temperature" }, { DEFAULT_INTERFACE });
 
+    FirmwareResource     firmware("/firmware", { "x.samsung.firmware" }, { DEFAULT_INTERFACE });
+
     string uri = airConditioner.getResourceUri();
     string rt = airConditioner.getResourceType()[0];
     string itf = airConditioner.getInterfaces()[0];
@@ -750,6 +958,25 @@ int main(int argc, char *argv[])
         exit(EXIT_FAILURE);
     }
 
+
+    uri = firmware.getResourceUri();
+    rt = firmware.getResourceType()[0];
+    itf = firmware.getInterfaces()[0];
+
+    result = OCPlatform::registerResource(firmware.m_handle,
+                                          uri,
+                                          rt,
+                                          itf,
+                                          bind(&FirmwareResource::entityHandler
+                                                  , &firmware, placeholders::_1),
+                                          OC_OBSERVABLE);
+
+    if (result != OC_STACK_OK)
+    {
+        exit(EXIT_FAILURE);
+    }
+
+
     result = airConditioner.addChildResource(&binarySwitch);
 
     if (result != OC_STACK_OK)
@@ -775,15 +1002,16 @@ int main(int argc, char *argv[])
 
     ResourceHandles resourceHandles;
 
-       result = RDClient::Instance().publishResourceToRD(g_host, OCConnectivityType::CT_ADAPTER_TCP,
+    result = RDClient::Instance().publishResourceToRD(g_host, OCConnectivityType::CT_ADAPTER_TCP,
              resourceHandles,
              &onPublish);
 
     cout << " result: " << result << " Waiting Publish default resource response from cloud" << endl;
 
     resourceHandles.push_back(airConditioner.m_handle);
+    resourceHandles.push_back(firmware.m_handle);
 
-       result = RDClient::Instance().publishResourceToRD(g_host, OCConnectivityType::CT_ADAPTER_TCP,
+    result = RDClient::Instance().publishResourceToRD(g_host, OCConnectivityType::CT_ADAPTER_TCP,
              resourceHandles,
              &onPublish);
 
index 9a95510..2235b44 100644 (file)
@@ -30,6 +30,8 @@ string         g_accesstoken;
 string              g_host;
 OC::OCResource::Ptr g_binaryswitchResource = nullptr;
 
+OC::OCResource::Ptr g_firmwareResource = nullptr;
+
 void printRepresentation(OCRepresentation rep)
 {
     for (auto itr = rep.begin(); itr != rep.end(); ++itr)
@@ -174,6 +176,22 @@ void turnOnOffSwitch(bool toTurn)
                                  &onPost);
 }
 
+void updateFirmware()
+{
+    if (g_firmwareResource == nullptr)
+    {
+        cout << "Firmware update not found" << endl;
+        return;
+    }
+
+    OCRepresentation firmwareUpdate;
+    firmwareUpdate.setValue<bool>("update", true);
+
+    QueryParamsMap      query;
+    g_binaryswitchResource->post("x.samsung.firmware", DEFAULT_INTERFACE, firmwareUpdate, query,
+                                 &onPost);
+}
+
 void getCollectionResource(const HeaderOptions &,
                            const OCRepresentation &rep, const int ecode)
 {
@@ -200,6 +218,18 @@ void getCollectionResource(const HeaderOptions &,
             QueryParamsMap      query;
             g_binaryswitchResource->observe(ObserveType::Observe, query, &onObserve);
         }
+
+        if (it->getResourceTypes().at(0).compare("x.samsung.firmware") == 0)
+        {
+            cout << "Observing " << it->getUri() << endl;
+            g_firmwareResource = OCPlatform::constructResourceObject(g_host,
+                                 it->getUri(),
+                                 static_cast<OCConnectivityType>(CT_ADAPTER_TCP | CT_IP_USE_V4), true,
+            { string("x.samsung.firmware") }, { string(DEFAULT_INTERFACE) });
+
+            QueryParamsMap      query;
+            g_firmwareResource->observe(ObserveType::Observe, query, &onObserve);
+        }
     }
 }
 
@@ -279,7 +309,7 @@ int saveTrustCert(void)
     OCStackResult res = OC_STACK_ERROR;
     uint16_t g_credId = 0;
 
-    cout << "Save Trust Cert. Chain into Cred of SVR" <<endl;
+    cout << "Save Trust Cert. Chain into Cred of SVR" << endl;
 
     ByteArray trustCertChainArray = {0, 0};
 
@@ -301,15 +331,16 @@ int saveTrustCert(void)
             rewind(fp);
             if (fsize != fread(trustCertChainArray.data, 1, fsize, fp))
             {
-                 cout << "Certiface not read completely" << endl;
+                cout << "Certiface not read completely" << endl;
             }
             fclose(fp);
         }
     }
 
-    res = OCSaveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len, OIC_ENCODING_PEM,&g_credId);
+    res = OCSaveTrustCertChain(trustCertChainArray.data, trustCertChainArray.len, OIC_ENCODING_PEM,
+                               &g_credId);
 
-    if(OC_STACK_OK != res)
+    if (OC_STACK_OK != res)
     {
         cout << "OCSaveTrustCertChainBin API error" << endl;
         return res;
@@ -322,26 +353,26 @@ int saveTrustCert(void)
 
 static FILE *client_open(const char *path, const char *mode)
 {
-       if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
-       {
-               return fopen("./aircon_controller.dat", mode);
-       }
-       else
-       {
-               return fopen(path, mode);
-       }
+    if (0 == strcmp(path, OC_SECURITY_DB_DAT_FILE_NAME))
+    {
+        return fopen("./aircon_controller.dat", mode);
+    }
+    else
+    {
+        return fopen(path, mode);
+    }
 }
 
 int main(int argc, char *argv[])
 {
-       if (argc != 4)
-       {
-               cout << "Put \"[host-ipaddress:port] [authprovider] [authcode]\" for sign-up and sign-in and publish resources"
-                       << endl;
-               cout << "Put \"[host-ipaddress:port] [uid] [accessToken]\" for sign-in and publish resources" <<
-                       endl;
-               return 0;
-       }
+    if (argc != 4)
+    {
+        cout << "Put \"[host-ipaddress:port] [authprovider] [authcode]\" for sign-up and sign-in and publish resources"
+             << endl;
+        cout << "Put \"[host-ipaddress:port] [uid] [accessToken]\" for sign-in and publish resources" <<
+             endl;
+        return 0;
+    }
 
     OCPersistentStorage ps{ client_open, fread, fwrite, fclose, unlink };
 
@@ -359,10 +390,10 @@ int main(int argc, char *argv[])
 
     OCStackResult result = OC_STACK_ERROR;
 
-       g_host = "coap+tcp://";
+    g_host = "coap+tcp://";
 
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-       g_host = "coaps+tcp://";
+    g_host = "coaps+tcp://";
 #endif
 
 
@@ -373,24 +404,24 @@ int main(int argc, char *argv[])
 
 
 #if defined(__WITH_DTLS__) || defined(__WITH_TLS__)
-       cout << "Security Mode" << endl;
-       if (CA_STATUS_OK != saveTrustCert())
-       {
-               cout << "saveTrustCert returned an error" << endl;
-       }
-
-       uint16_t cipher = MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256;
-       if (CA_STATUS_OK != CASelectCipherSuite(cipher, CA_ADAPTER_TCP))
-       {
-               cout << "CASelectCipherSuite returned an error" << endl;
-       }
+    cout << "Security Mode" << endl;
+    if (CA_STATUS_OK != saveTrustCert())
+    {
+        cout << "saveTrustCert returned an error" << endl;
+    }
+
+    uint16_t cipher = MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256;
+    if (CA_STATUS_OK != CASelectCipherSuite(cipher, CA_ADAPTER_TCP))
+    {
+        cout << "CASelectCipherSuite returned an error" << endl;
+    }
 #endif
 
-       mutex blocker;
-       unique_lock<mutex> lock(blocker);
+    mutex blocker;
+    unique_lock<mutex> lock(blocker);
 
-       if (strlen(argv[2]) > 35)
-       {
+    if (strlen(argv[2]) > 35)
+    {
         accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB);
         g_callbackLock.wait(lock);
     }
@@ -444,6 +475,10 @@ int main(int argc, char *argv[])
                 turnOnOffSwitch(false);
                 break;
 
+            case 'f':
+                updateFirmware();
+                break;
+
             case 'q':
                 goto exit;
         }