Ram Gandikota / Mbed OS ABCD
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "sockets/UDPSocket.h"
00017 #include "EthernetInterface.h"
00018 #include "test_env.h"
00019 #include "mbed-client/m2minterfacefactory.h"
00020 #include "mbed-client/m2minterfaceobserver.h"
00021 #include "mbed-client/m2mdevice.h"
00022 #include "mbed-client/m2mobjectinstance.h"
00023 #include "mbed-client/m2minterface.h"
00024 #include "testconfig.h"
00025 
00026 // TODO: Remove when yotta supports init.
00027 #include "lwipv4_init.h"
00028 
00029 // Minar for event scheduling
00030 #include "minar/minar.h"
00031 
00032 using namespace mbed::util;
00033 const String &MANUFACTURER = "ARM";
00034 const String &TYPE = "type";
00035 
00036 static bool test_result = false;
00037 
00038 // Dynamic resource variables
00039 const String &DYNAMIC_RESOURCE_NAME = "Dynamic";
00040 const String &DYNAMIC_RESOURCE_TYPE = "DynamicType";
00041 const String &STATIC_RESOURCE_NAME = "Static";
00042 const String &STATIC_RESOURCE_TYPE = "StaticType";
00043 const uint8_t STATIC_VALUE[] = "Static value";
00044 
00045 //TODO: should this be configured in .json conf file, and communicated via host test to here?
00046 int CALLBACK_TIMEOUT = 5;
00047 int MINAR_DELAY = 10000;
00048 
00049 #define SUITE_TEST_INFO(test_name, info)        printf("Suite-%s: %s\n", test_name, info)
00050 #define SUITE_TEST_RESULT(test_name, result)    printf("Suite-%s: result %s\n", test_name, result ? "PASSED" : "FAILED")
00051 #define SUITE_RESULT(result)                    printf("Suite: result %s\n", result ? "success" : "failure")
00052 
00053 
00054 class MbedClient: public M2MInterfaceObserver {
00055 public:
00056     MbedClient(TestConfig *test_config){
00057         _interface = NULL;
00058         _register_security = NULL;
00059         _resource_object = NULL;
00060         _bootstrapped = false;
00061         _error = false;
00062         _registered = false;
00063         _unregistered = false;
00064         _registration_updated = false;
00065         _resource_value = 0;
00066         _object = NULL;
00067         _test_config = test_config;
00068     }
00069 
00070     virtual ~MbedClient() {
00071         if(_interface) {
00072             delete _interface;
00073         }
00074         if( _register_security){
00075             delete _register_security;
00076         }
00077     }
00078 
00079     bool create_interface() {
00080         bool success = false;
00081          // Creates M2MInterface using which endpoint can
00082          // setup its name, resource type, life time, connection mode,
00083          // Currently only LwIPv4 is supported.
00084          _interface = M2MInterfaceFactory::create_interface( *this,
00085                                                    _test_config->get_endpoint_name(),
00086                                                    _test_config->get_endpoint_type(),
00087                                                    _test_config->get_lifetime(),
00088                                                    _test_config->get_port(),
00089                                                    _test_config->get_domain(),
00090                                                    M2MInterface::UDP,
00091                                                    M2MInterface::LwIP_IPv4,
00092                                                    "");
00093          if (_interface) {
00094              success = true;
00095          }
00096 
00097          return success;
00098     }
00099 
00100     bool bootstrap_successful() {
00101         return _bootstrapped;
00102     }
00103 
00104     M2MSecurity* create_bootstrap_object() {
00105         // Creates bootstrap server object with Bootstrap server address and other parameters
00106         // required for client to connect to bootstrap server.
00107         M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::Bootstrap);
00108         if(security) {
00109             security->set_resource_value(M2MSecurity::M2MServerUri, _test_config->get_bootstrap_server());
00110             security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity);
00111         }
00112         return security;
00113     }
00114 
00115     void test_bootstrap(M2MSecurity *security) {
00116         if(_interface) {
00117              // Bootstrap function.
00118             _interface->bootstrap(security);
00119         }
00120     }
00121 
00122     bool register_successful() {
00123         return _registered;
00124     }
00125 
00126     bool unregister_successful() {
00127         return _unregistered;
00128     }
00129 
00130     bool update_register_successful() {
00131         return _registration_updated;
00132     }
00133 
00134     void check_result(const char* result) {
00135         if(_registered && _registration_updated && _unregistered) {
00136             SUITE_TEST_RESULT(result, true);
00137             test_result = true;
00138         } else {
00139            SUITE_TEST_RESULT(result, false);
00140            test_result = false;
00141         }
00142         minar::Scheduler::stop();
00143     }
00144 
00145     M2MSecurity* create_register_object() {
00146         // Creates server object with LWM2M server address and other parameters
00147         // required for client to connect to LWM2M server.
00148         M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
00149         if(security) {
00150             security->set_resource_value(M2MSecurity::M2MServerUri, _test_config->get_mds_server());
00151             //security->set_resource_value(M2MSecurity::M2MServerUri, "ds-test.dev.mbed.com");
00152             security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::NoSecurity);
00153         }
00154         return security;
00155     }
00156 
00157     void test_register(M2MObjectList object_list){
00158         if(_interface) {
00159             // Register function
00160             _interface->register_object(_register_security, object_list);
00161         }
00162     }
00163 
00164     void test_update_register(const uint32_t lifetime)
00165     {
00166         if(_interface && _register_security) {
00167             _interface->update_registration(_register_security,lifetime);
00168         }        
00169     }
00170 
00171     void test_unregister(){
00172         if(_interface) {
00173             // Unregister function
00174             _interface->unregister_object(NULL);
00175         }
00176     }
00177 
00178     void set_register_object(M2MSecurity *&register_object){
00179         if(_register_security) {
00180             delete _register_security;
00181             _register_security = NULL;
00182         }
00183         _register_security = register_object;
00184     }
00185 
00186     M2MDevice* create_device_object() {
00187         M2MDevice *device = M2MInterfaceFactory::create_device();
00188         if (device) {
00189             device->create_resource(M2MDevice::Manufacturer, MANUFACTURER);
00190             device->create_resource(M2MDevice::DeviceType, TYPE);
00191         }
00192         return device;
00193     }
00194 
00195     M2MObject* create_generic_object() {
00196         _object = M2MInterfaceFactory::create_object("Test");
00197         if(_object) {
00198             M2MObjectInstance* inst = _object->create_object_instance();
00199             if(inst) {
00200                     M2MResource* res = inst->create_dynamic_resource("D","ResourceTest",
00201                                                                      M2MResourceInstance::INTEGER,
00202                                                                      true);
00203                     char buffer[20];
00204                     int size = sprintf(buffer,"%d",_resource_value);
00205                     res->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
00206                     res->set_value((const uint8_t*)buffer,
00207                                    (const uint32_t)size);
00208                     _resource_value++;
00209 
00210                     inst->create_static_resource("S",
00211                                                  "ResourceTest",
00212                                                  M2MResourceInstance::STRING,
00213                                                  STATIC_VALUE,
00214                                                  sizeof(STATIC_VALUE)-1);
00215             }
00216         }
00217         return _object;
00218     }
00219 
00220     //Callback from mbed client stack when the bootstrap
00221     // is successful, it returns the mbed Device Server object
00222     // which will be used for registering the resources to
00223     // mbed Device server.
00224     void bootstrap_done(M2MSecurity *server_object){
00225         if(server_object) {
00226             _bootstrapped = true;
00227             _error = false;
00228         }
00229     }
00230 
00231     //Callback from mbed client stack when the registration
00232     // is successful, it returns the mbed Device Server object
00233     // to which the resources are registered and registered objects.
00234     void object_registered(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/){
00235         _registered = true;
00236     }
00237 
00238     //Callback from mbed client stack when the registration update
00239         // is successful, it returns the mbed Device Server object
00240         // to which the resources are registered and registered objects.
00241     void registration_updated(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/){
00242             _registration_updated = true;
00243         }
00244 
00245     //Callback from mbed client stack when the unregistration
00246     // is successful, it returns the mbed Device Server object
00247     // to which the resources were unregistered.
00248     void object_unregistered(M2MSecurity */*server_object*/){
00249         _unregistered = true;        
00250     }
00251 
00252     //Callback from mbed client stack if any value has changed
00253     // during PUT operation. Object and its type is passed in
00254     // the callback.
00255     void value_updated(M2MBase *base, M2MBase::BaseType type) {
00256         printf("\nValue updated of Object name %s and Type %d\n",
00257                base->name().c_str(), type);
00258     }
00259 
00260     //Callback from mbed client stack if any error is encountered
00261     // during any of the LWM2M operations. Error type is passed in
00262     // the callback.
00263     void error(M2MInterface::Error error){
00264         _error = true;
00265         printf("\nError occured %d\n", error);
00266     }
00267 
00268 private:
00269 
00270     M2MInterface        *_interface;
00271     M2MSecurity         *_register_security;
00272     M2MObject           *_resource_object;
00273     M2MObject           *_object;
00274     volatile bool       _bootstrapped;
00275     volatile bool       _error;
00276     volatile bool       _registered;
00277     volatile bool       _unregistered;
00278     volatile bool       _registration_updated;
00279     int                 _resource_value;
00280     TestConfig          *_test_config;
00281 };
00282 
00283 #define WAIT_CALLBACK(X, TIMEOUT)                                  \
00284 {int _timer = 0;\
00285 while ( 1 )       \
00286     {                                                     \
00287       _result &= (X);                                     \
00288       if (_result) {                                      \
00289           SUITE_TEST_INFO(_tn, "callback done");          \
00290           break;                                          \
00291       }                                                   \
00292       wait_ms(1000); _timer+=1;                           \
00293       if (_timer >= TIMEOUT) {                            \
00294           SUITE_TEST_INFO(_tn, "ERROR: callback timeout");\
00295           break;                                          \
00296       }                                                   \
00297     }}
00298 
00299 bool test_bootStrap(TestConfig *test_config) {
00300     bool _result = true;
00301     const char* _tn = "TC1_bootStrap";
00302 
00303     SUITE_TEST_INFO(_tn, "STARTED");
00304 
00305     // Instantiate the class which implements
00306     // mbed Client API
00307     MbedClient *mbed_client = new MbedClient(test_config);
00308 
00309     SUITE_TEST_INFO(_tn, "client done");
00310 
00311     // Create LWM2M Client API interface to manage bootstrap,
00312     // register and unregister
00313     _result &= mbed_client->create_interface();
00314 
00315     // Create LWM2M bootstrap object specifying bootstrap server
00316     // information.
00317     M2MSecurity* security_object = mbed_client->create_bootstrap_object();
00318 
00319     // Issue bootstrap command.
00320     mbed_client->test_bootstrap(security_object);
00321     SUITE_TEST_INFO(_tn, "bootstrap done");
00322 
00323     SUITE_TEST_INFO(_tn, "waiting bootstrap callback...");
00324     // Wait till the bootstrap callback is called successfully.
00325     // Callback comes in bootstrap_done()
00326     WAIT_CALLBACK(mbed_client->bootstrap_successful(), CALLBACK_TIMEOUT);
00327 
00328     // Delete security object created for bootstrapping
00329     if(security_object) {
00330         delete security_object;
00331     }
00332 
00333     if (mbed_client) {
00334         delete mbed_client;
00335     }
00336 
00337     SUITE_TEST_RESULT(_tn, _result);
00338     return _result;
00339 }
00340 
00341 void test_deviceObject(TestConfig *test_config) {
00342     const char* _tn = "TC2_deviceObject";
00343 
00344     SUITE_TEST_INFO(_tn, "STARTED");
00345 
00346     // Instantiate the class which implements
00347     // LWM2M Client API
00348     MbedClient mbed_client(test_config);// = new MbedClient(test_config);
00349 
00350     SUITE_TEST_INFO(_tn, "client done");
00351 
00352     // Create LWM2M Client API interface for M2M server
00353     mbed_client.create_interface();
00354 
00355     M2MSecurity *register_object = mbed_client.create_register_object();
00356 
00357     mbed_client.set_register_object(register_object);
00358 
00359     // Create LWM2M device object specifying device resources
00360     // as per OMA LWM2M specification.
00361     M2MDevice* device_object = mbed_client.create_device_object();
00362 
00363     // Add the device object that we want to register
00364     // into the list and pass the list for register API.
00365     M2MObjectList object_list;
00366     object_list.push_back(device_object);
00367 
00368     // Issue register command.
00369 
00370     FunctionPointer1<void, M2MObjectList> tr(&mbed_client, &MbedClient::test_register);
00371     minar::Scheduler::postCallback(tr.bind(object_list));
00372 
00373     // Issue update register command.
00374 
00375     uint32_t lifetime = 2222;
00376 
00377     FunctionPointer1<void, uint32_t> ur(&mbed_client, &MbedClient::test_update_register);
00378     minar::Scheduler::postCallback(ur.bind(lifetime)).delay(MINAR_DELAY);
00379 
00380     // Issue unregister command.
00381 
00382     FunctionPointer0<void> tur(&mbed_client, &MbedClient::test_unregister);
00383     minar::Scheduler::postCallback(tur.bind()).delay(MINAR_DELAY*2);
00384 
00385     FunctionPointer1<void, const char*> cus(&mbed_client, &MbedClient::check_result);
00386     minar::Scheduler::postCallback(cus.bind(_tn)).delay(MINAR_DELAY*3);
00387 
00388     minar::Scheduler::start();
00389 
00390     // Delete device object created for registering device
00391     // resources.
00392 
00393     if(device_object) {
00394         M2MDevice::delete_instance();
00395     }
00396 }
00397 
00398 bool test_resource(TestConfig *test_config) {
00399     bool _result = true;
00400     const char* _tn = "TC3_resource";
00401     SUITE_TEST_INFO(_tn, "STARTED");
00402 
00403     // Instantiate the class which implements LWM2M Client API
00404     MbedClient mbed_client(test_config);
00405     SUITE_TEST_INFO(_tn, "client done");
00406 
00407     // Create LWM2M Client API interface for M2M server
00408     _result &= mbed_client.create_interface();
00409 
00410     M2MSecurity *register_object = mbed_client.create_register_object();
00411 
00412     mbed_client.set_register_object(register_object);
00413 
00414     // Create LWM2M device object specifying device resources
00415     // as per OMA LWM2M specification.
00416     M2MDevice* device_object = mbed_client.create_device_object();
00417 
00418     // Create LWM2M generic object for resource
00419     M2MObject* resource_object = mbed_client.create_generic_object();
00420 
00421     // Add the device object that we want to register
00422     // into the list and pass the list for register API.
00423     M2MObjectList object_list;
00424     object_list.push_back(device_object);
00425     object_list.push_back(resource_object);
00426 
00427     // Issue register command.
00428 
00429     FunctionPointer1<void, M2MObjectList> tr(&mbed_client, &MbedClient::test_register);
00430     minar::Scheduler::postCallback(tr.bind(object_list));
00431 
00432     // Issue update register command.
00433 
00434     uint32_t lifetime = 2222;
00435 
00436     FunctionPointer1<void, uint32_t> ur(&mbed_client, &MbedClient::test_update_register);
00437     minar::Scheduler::postCallback(ur.bind(lifetime)).delay(MINAR_DELAY);
00438 
00439     // Issue unregister command.
00440 
00441     FunctionPointer0<void> tur(&mbed_client, &MbedClient::test_unregister);
00442     minar::Scheduler::postCallback(tur.bind()).delay(MINAR_DELAY*2);
00443 
00444     FunctionPointer1<void, const char*> cus(&mbed_client, &MbedClient::check_result);
00445     minar::Scheduler::postCallback(cus.bind(_tn)).delay(MINAR_DELAY*3);
00446 
00447     minar::Scheduler::start();
00448 
00449     // Delete device object created for registering device resources.
00450     if(device_object) {
00451         M2MDevice::delete_instance();
00452     }
00453 
00454     // Delete resource object for registering resources.
00455     if(resource_object) {
00456         delete resource_object;
00457     }
00458 }
00459 
00460 
00461 
00462 void app_start(int /*argc*/, char* /*argv*/[]) {
00463     DigitalOut _led = DigitalOut(LED3);
00464     _led = 1;
00465 
00466     MBED_HOSTTEST_TIMEOUT(40);
00467     MBED_HOSTTEST_SELECT(mbed_client_auto);
00468     MBED_HOSTTEST_DESCRIPTION(LWM2MClient Smoke Test);
00469     MBED_HOSTTEST_START("LWM2MClientSmokeTest");
00470 
00471     // This sets up the network interface configuration which will be used
00472     // by LWM2M Client API to communicate with mbed Device server.
00473     EthernetInterface eth;
00474     eth.init(); //Use DHCP
00475     eth.connect();
00476 
00477     lwipv4_socket_init();
00478 
00479     // Create test config object, and setup with unique MAC address
00480     TestConfig test_config;
00481     test_config.setup();
00482 
00483     _led = 0;
00484 
00485     // Bootstrap test is uncommented, until it will be supported.
00486     //result &= test_bootStrap(&test_config);
00487     test_deviceObject(&test_config);
00488     test_resource(&test_config);
00489 
00490     _led = 1;
00491 
00492     // Disconnect and teardown the network interface
00493     eth.disconnect();
00494 
00495     SUITE_RESULT(test_result);
00496 }
00497