This is a mbed Client sample where ZXing is incorporated, and works on GR-PEACH and GR-LYCHEE.

Dependencies:   DisplayApp AsciiFont

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002  * Copyright (c) 2015, 2016 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 "mbed-trace/mbed_trace.h"
00017 #include "mbed.h"
00018 #include "zxing_main.h"
00019 
00020 // Network interaction must be performed outside of interrupt context
00021 osThreadId mainThread;
00022 
00023 #define NO_CONNECT         (-1)
00024 
00025 #if MBED_CONF_APP_NETWORK_INTERFACE == NO_CONNECT
00026 
00027 static void callback_zxing(char * addr, int size) {
00028     printf("%s\r\n", addr);
00029 }
00030 
00031 // Entry point to the program
00032 int main() {
00033     // Keep track of the main thread
00034     mainThread = osThreadGetId();
00035     printf("no connect\n");
00036     mbed_trace_init();
00037     zxing_init(&callback_zxing);
00038 
00039     while (1) {
00040         zxing_loop();
00041         Thread::wait(5);
00042     }
00043 }
00044 
00045 #else // MBED_CONF_APP_NETWORK_INTERFACE != NO_CONNECT
00046 
00047 #define __STDC_FORMAT_MACROS
00048 #include <inttypes.h>
00049 #include <string>
00050 #include <sstream>
00051 #include <vector>
00052 #include "mbed-trace/mbed_trace.h"
00053 #include "mbedtls/entropy_poll.h"
00054 
00055 #include "security.h"
00056 
00057 #include "mbed.h"
00058 
00059 // easy-connect compliancy, it has 2 sets of wifi pins we have only one
00060 #define MBED_CONF_APP_ESP8266_TX MBED_CONF_APP_WIFI_TX
00061 #define MBED_CONF_APP_ESP8266_RX MBED_CONF_APP_WIFI_RX
00062 #include "easy-connect/easy-connect.h"
00063 
00064 // Should be defined after easy-connect.h
00065 #include "simpleclient.h"
00066 
00067 #ifdef TARGET_STM
00068 #define RED_LED     (LED3)
00069 #define GREEN_LED   (LED1)
00070 #define BLUE_LED    (LED2)
00071 #define LED_ON      (1)
00072 #elif TARGET_RZ_A1H
00073 #define RED_LED     (LED1)
00074 #define GREEN_LED   (LED2)
00075 #define BLUE_LED    (LED3)
00076 #define USER_LED    (LED4)
00077 #define LED_ON      (1)
00078 #elif TARGET_GR_LYCHEE
00079 #define GREEN_LED   (LED1)
00080 #define YELLOW_LED  (LED2)
00081 #define ORANGE_LED  (LED3)
00082 #define RED_LED     (LED4)
00083 #define LED_ON      (1)
00084 #else
00085 #define RED_LED     (LED1)
00086 #define GREEN_LED   (LED2)
00087 #define BLUE_LED    (LED3)
00088 #define LED_ON      (0)
00089 #endif
00090 #define LED_OFF (!LED_ON)
00091 
00092 #define BLINK_SIGNAL 0x1
00093 
00094 // Status indication
00095 DigitalOut red_led(RED_LED);
00096 DigitalOut green_led(GREEN_LED);
00097 #ifdef TARGET_RZ_A1H
00098 DigitalOut blue_led(BLUE_LED);
00099 DigitalOut user_led(USER_LED);
00100 #elif TARGET_GR_LYCHEE
00101 DigitalOut yellow_led(YELLOW_LED);
00102 DigitalOut orange_led(ORANGE_LED);
00103 #else
00104 DigitalOut blue_led(BLUE_LED);
00105 #endif
00106 
00107 Ticker status_ticker;
00108 void blinky() {
00109 #ifdef TARGET_RZ_A1H
00110     user_led = !user_led;
00111 #else
00112     green_led = !green_led;
00113 #endif
00114 }
00115 
00116 // These are example resource values for the Device Object
00117 struct MbedClientDevice device = {
00118     "Manufacturer_String",      // Manufacturer
00119     "Type_String",              // Type
00120     "ModelNumber_String",       // ModelNumber
00121     "SerialNumber_String"       // SerialNumber
00122 };
00123 
00124 // Instantiate the class which implements LWM2M Client API (from simpleclient.h)
00125 MbedClient mbed_client(device);
00126 
00127 // Set up a button interrupt for user interaction
00128 #ifdef MBED_CONF_APP_BUTTON1
00129     InterruptIn counter_btn(MBED_CONF_APP_BUTTON1);
00130 #endif
00131 
00132 
00133 /**
00134  * User interaction handler / simulator. Sets up physical button handler and a ticker
00135  * for regular updates for the resources.
00136  *
00137  * MBED_CONF_APP_BUTTON1 is mapped to actual button pin the mbed_app.json file, where you need to
00138  * specify board-specific value or leave it undefined if the board does not have buttons.
00139  */
00140 class InteractionProvider {
00141 
00142 public:
00143     InteractionProvider(Semaphore& updates_sem) : updates(updates_sem) {
00144 
00145         timer_ticked = false;
00146         clicked = false;
00147 
00148         // Set up handler function for the interaction button, if available
00149 
00150 #ifdef MBED_CONF_APP_BUTTON1
00151         counter_btn.fall(this, &InteractionProvider::counter_button_handler);
00152 #endif
00153 
00154         // Use the counter button handler to send an update of endpoint resource values
00155         // to connector every 15 seconds periodically.
00156         timer.attach(this, &InteractionProvider::timer_handler, 15.0);
00157     }
00158 
00159     // flags for interaction, these are read from outside interrupt context
00160     volatile bool timer_ticked;
00161     volatile bool clicked;
00162 
00163 
00164 private:
00165 
00166     void timer_handler() {
00167         timer_ticked = true;
00168         updates.release();
00169     }
00170 
00171     void counter_button_handler() {
00172         clicked = true;
00173         updates.release();
00174     }
00175 
00176     // time-based event source for regular resource updates
00177     Ticker timer;
00178 
00179     // Network interaction must be performed outside of interrupt context
00180     Semaphore& updates;
00181 
00182 };
00183 
00184 /*
00185  * Arguments for running "blink" in it's own thread.
00186  */
00187 class BlinkArgs {
00188 public:
00189     BlinkArgs() {
00190         clear();
00191     }
00192     void clear() {
00193         position = 0;
00194         blink_pattern.clear();
00195     }
00196     uint16_t position;
00197     std::vector<uint32_t> blink_pattern;
00198 };
00199 
00200 /*
00201  * The Led contains one property (pattern) and a function (blink).
00202  * When the function blink is executed, the pattern is read, and the LED
00203  * will blink based on the pattern.
00204  */
00205 class LedResource {
00206 public:
00207     LedResource() {
00208         // create ObjectID with metadata tag of '3201', which is 'digital output'
00209 //        blinky_thread.start(callback(this, &LedResource::do_blink));
00210         led_object = M2MInterfaceFactory::create_object("3201");
00211         M2MObjectInstance* led_inst = led_object->create_object_instance();
00212 
00213         // 5855 = Multi-state output
00214         M2MResource* color_res = led_inst->create_dynamic_resource("5855", "Color",
00215             M2MResourceInstance::STRING, false);
00216         // read and write
00217         color_res->set_operation(M2MBase::GET_PUT_ALLOWED);
00218         // set red as initial color
00219         color_res->set_value((const uint8_t*)"red", 3);
00220         
00221         // 5853 = Multi-state output
00222         M2MResource* pattern_res = led_inst->create_dynamic_resource("5853", "Pattern",
00223             M2MResourceInstance::STRING, false);
00224         // read and write
00225         pattern_res->set_operation(M2MBase::GET_PUT_ALLOWED);
00226         // set initial pattern (toggle every 200ms. 7 toggles in total)
00227         pattern_res->set_value((const uint8_t*)"500:500:500:500:500:500:500", 27);
00228 
00229         // there's not really an execute LWM2M ID that matches... hmm...
00230         M2MResource* led_res = led_inst->create_dynamic_resource("5850", "Blink",
00231             M2MResourceInstance::OPAQUE, false);
00232         // we allow executing a function here...
00233         led_res->set_operation(M2MBase::POST_ALLOWED);
00234         // when a POST comes in, we want to execute the led_execute_callback
00235         led_res->set_execute_function(execute_callback(this, &LedResource::blink));
00236 
00237     }
00238 
00239     M2MObject* get_object() {
00240         return led_object;
00241     }
00242 
00243     void blink(void *argument) {
00244         // read the value of 'Pattern'
00245         M2MObjectInstance* inst = led_object->object_instance();
00246         M2MResource* res = inst->resource("5853");
00247         // read the value of 'Color'
00248         M2MObjectInstance* instC = led_object->object_instance();
00249         M2MResource* resC = instC->resource("5855");
00250 
00251         // values in mbed Client are all buffers, and we need a vector of int's
00252         uint8_t* buffIn = NULL;
00253         uint32_t sizeIn;
00254         res->get_value(buffIn, sizeIn);
00255 
00256         uint8_t* cbuffIn = NULL;
00257         uint32_t csizeIn;
00258         resC->get_value(cbuffIn, csizeIn);
00259 
00260         // turn the buffer into a string, and initialize a vector<int> on the heap
00261         std::string s((char*)buffIn, sizeIn);
00262         std::vector<uint32_t>* v = new std::vector<uint32_t>;
00263 
00264         printf("led_execute_callback pattern=%s\n", s.c_str());
00265 
00266         // our pattern is something like 500:200:500, so parse that
00267         std::size_t found = s.find_first_of(":");
00268         while (found!=std::string::npos) {
00269             v->push_back(atoi((const char*)s.substr(0,found).c_str()));
00270             s = s.substr(found+1);
00271             found=s.find_first_of(":");
00272             if(found == std::string::npos) {
00273                 v->push_back(atoi((const char*)s.c_str()));
00274             }
00275         }
00276         int position = 0;
00277         while (1) {
00278             do_blink(cbuffIn);
00279             if (position >= v->size()) {
00280                 break;
00281             }
00282             // how long do we need to wait before the next blink?
00283             Thread::wait(v->at(position));
00284             position++;
00285         }
00286         free(buffIn);
00287         free(cbuffIn);
00288         delete v;
00289     }
00290 
00291 private:
00292     M2MObject* led_object;
00293     void do_blink(uint8_t* color) {
00294 
00295 #if defined(TARGET_RZ_A1H)
00296         if (!strcmp((char *)color, "red")) {
00297             // blink the LED in red color
00298             red_led = !red_led;
00299         }
00300         else if (!strcmp((char *)color, "green")) {
00301             // blink in green color
00302             green_led = !green_led;
00303         }
00304         else if (!strcmp((char *)color, "blue")) {
00305             // blink in blue color
00306             blue_led = !blue_led;
00307         }
00308         else if (!strcmp((char *)color, "cyan")) {
00309             // blink in cyan color
00310             green_led = !green_led;
00311             blue_led  = !blue_led;
00312         }
00313         else if (!strcmp((char *)color, "yellow")) {
00314             // blink in yellow color
00315             red_led   = !red_led;
00316             green_led = !green_led;
00317         }
00318         else if (!strcmp((char *)color, "magenta")) {
00319             // blink in magenta color
00320             red_led  = !red_led;
00321             blue_led = !blue_led;
00322         }            
00323         else if (!strcmp((char *)color, "white")) {
00324             // blink in white color
00325             red_led   = !red_led;
00326             green_led = !green_led;
00327             blue_led  = !blue_led;
00328         }
00329         else {
00330             // no operation
00331         }
00332 #elif defined(TARGET_GR_LYCHEE)
00333         if (!strcmp((char *)color, "green")) {
00334             // blink the LED1(green color)
00335             green_led = !green_led;
00336         }
00337         else if (!strcmp((char *)color, "yellow")) {
00338             // blink the LED2(yellow color)
00339             yellow_led = !yellow_led;
00340         }
00341         else if (!strcmp((char *)color, "orange")) {
00342             // blink the LED3(orange color)
00343             orange_led = !orange_led;
00344         }
00345         else if (!strcmp((char *)color, "red")) {
00346             // blink the LED4(red color)
00347             red_led = !red_led;
00348         }
00349         else {
00350             // no operation
00351         }
00352 #endif
00353     }
00354 };
00355 
00356 /*
00357  * The button contains one property (click count).
00358  * When `handle_button_click` is executed, the counter updates.
00359  */
00360 class ButtonResource {
00361 public:
00362     ButtonResource(): counter(0) {
00363         // create ObjectID with metadata tag of '3200', which is 'digital input'
00364         btn_object = M2MInterfaceFactory::create_object("3200");
00365         M2MObjectInstance* btn_inst = btn_object->create_object_instance();
00366         // create resource with ID '5501', which is digital input counter
00367         M2MResource* btn_res = btn_inst->create_dynamic_resource("5501", "Button",
00368             M2MResourceInstance::INTEGER, true /* observable */);
00369         // we can read this value
00370         btn_res->set_operation(M2MBase::GET_ALLOWED);
00371         // set initial value (all values in mbed Client are buffers)
00372         // to be able to read this data easily in the Connector console, we'll use a string
00373         btn_res->set_value((uint8_t*)"0", 1);
00374     }
00375 
00376     ~ButtonResource() {
00377     }
00378 
00379     M2MObject* get_object() {
00380         return btn_object;
00381     }
00382 
00383     /*
00384      * When you press the button, we read the current value of the click counter
00385      * from mbed Device Connector, then up the value with one.
00386      */
00387     void handle_button_click() {
00388         if (mbed_client.register_successful()) {
00389             M2MObjectInstance* inst = btn_object->object_instance();
00390             M2MResource* res = inst->resource("5501");
00391 
00392             // up counter
00393             counter++;
00394             printf("handle_button_click, new value of counter is %d\n", counter);
00395             // serialize the value of counter as a string, and tell connector
00396             char buffer[20];
00397             int size = sprintf(buffer,"%d",counter);
00398             res->set_value((uint8_t*)buffer, size);
00399         } else {
00400             printf("simulate button_click, device not registered\n");
00401         }
00402     }
00403 
00404 private:
00405     M2MObject* btn_object;
00406     uint16_t counter;
00407 };
00408 
00409 /*
00410  * The timer contains one property: counter.
00411  * When `handle_timer_tick` is executed, the counter updates.
00412  */
00413 class TimerResource {
00414 public:
00415     TimerResource(): counter(0) {
00416         // create ObjectID with metadata tag of '3200', which is 'digital input'
00417         btn_object = M2MInterfaceFactory::create_object("3200");
00418         M2MObjectInstance* btn_inst = btn_object->create_object_instance();
00419         // create resource with ID '5502', which is digital input counter
00420         M2MResource* btn_res = btn_inst->create_dynamic_resource("5502", "Timer",
00421             M2MResourceInstance::INTEGER, true /* observable */);
00422         // we can read this value
00423         btn_res->set_operation(M2MBase::GET_ALLOWED);
00424         // set initial value (all values in mbed Client are buffers)
00425         // to be able to read this data easily in the Connector console, we'll use a string
00426         btn_res->set_value((uint8_t*)"0", 1);
00427     }
00428 
00429     ~TimerResource() {
00430     }
00431 
00432     M2MObject* get_object() {
00433         return btn_object;
00434     }
00435 
00436     /*
00437      * When the timer ticks, we read the current value of the click counter
00438      * from mbed Device Connector, then up the value with one.l
00439      */
00440     void handle_timer_tick() {
00441         if (mbed_client.register_successful()) {
00442             M2MObjectInstance* inst = btn_object->object_instance();
00443             M2MResource* res = inst->resource("5502");
00444 
00445             // up counter
00446             counter++;
00447             printf("handle_timer_click, new value of counter is %d\n", counter);
00448             // serialize the value of counter as a string, and tell connector
00449             char buffer[20];
00450             int size = sprintf(buffer,"%d",counter);
00451             res->set_value((uint8_t*)buffer, size);
00452         } else {
00453             printf("handle_timer_tick, device not registered\n");
00454         }
00455     }
00456 
00457 private:
00458     M2MObject* btn_object;
00459     uint16_t counter;
00460 };
00461 
00462 
00463 
00464 class BigPayloadResource {
00465 public:
00466     BigPayloadResource() {
00467         big_payload = M2MInterfaceFactory::create_object("1000");
00468         M2MObjectInstance* payload_inst = big_payload->create_object_instance();
00469         M2MResource* payload_res = payload_inst->create_dynamic_resource("1", "BigData",
00470             M2MResourceInstance::STRING, true /* observable */);
00471         payload_res->set_operation(M2MBase::GET_PUT_ALLOWED);
00472         payload_res->set_value((uint8_t*)"0", 1);
00473         payload_res->set_incoming_block_message_callback(
00474                     incoming_block_message_callback(this, &BigPayloadResource::block_message_received));
00475         payload_res->set_outgoing_block_message_callback(
00476                     outgoing_block_message_callback(this, &BigPayloadResource::block_message_requested));
00477     }
00478 
00479     M2MObject* get_object() {
00480         return big_payload;
00481     }
00482 
00483     void block_message_received(M2MBlockMessage *argument) {
00484         if (argument) {
00485             if (M2MBlockMessage::ErrorNone == argument->error_code()) {
00486                 if (argument->is_last_block()) {
00487                     printf("Last block received\n");
00488                 }
00489                 printf("Block number: %d\n", argument->block_number());
00490                 // First block received
00491                 if (argument->block_number() == 0) {
00492                     // Store block
00493                 // More blocks coming
00494                 } else {
00495                     // Store blocks
00496                 }
00497             } else {
00498                 printf("Error when receiving block message!  - EntityTooLarge\n");
00499             }
00500 //            printf("Total message size: %" PRIu32 "\n", argument->total_message_size());
00501             printf("Total message size: %PRIu32\n", argument->total_message_size());
00502         }
00503     }
00504 
00505     void block_message_requested(const String& resource, uint8_t *&/*data*/, uint32_t &/*len*/) {
00506         printf("GET request received for resource: %s\n", resource.c_str());
00507         // Copy data and length to coap response
00508     }
00509 
00510 private:
00511     M2MObject*  big_payload;
00512 };
00513 
00514 /*
00515  * The Zxing contains a function (send string).
00516  * When `handle_string_send` is executed, the string after decoding is sent.
00517  */
00518 class ZxingResource {
00519 public:
00520     ZxingResource() {
00521         // create ObjectID with metadata tag of '3202', which is 'send string'
00522         zxing_object = M2MInterfaceFactory::create_object("3202");
00523         M2MObjectInstance* zxing_inst = zxing_object->create_object_instance();
00524         // create resource with ID '5700', which is 'send string'
00525         M2MResource* zxing_res = zxing_inst->create_dynamic_resource("5700", "zxing",
00526             M2MResourceInstance::STRING, true);
00527         // we can read this value
00528         zxing_res->set_operation(M2MBase::GET_ALLOWED);
00529         // set initial value (all values in mbed Client are buffers)
00530         // to be able to read this data easily in the Connector console, we'll use a string
00531         zxing_res->set_value((uint8_t*)"0", 1);
00532     }
00533 
00534     ~ZxingResource() {
00535     }
00536 
00537     M2MObject* get_object() {
00538         return zxing_object;
00539     }
00540 
00541     /*
00542      * When you success the decode process of barcode, we send the string after decoding to mbed Device Connector.
00543      */
00544     void handle_string_send(char * addr, int size) {
00545         if (mbed_client.register_successful()) {
00546             M2MObjectInstance* inst = zxing_object->object_instance();
00547             M2MResource* res = inst->resource("5700");
00548 
00549             printf("%s\r\n", addr);
00550 
00551             // tell the string to connector
00552             res->set_value((uint8_t *)addr, size);
00553         } else {
00554             printf("handle_string_send, device not registered\n");
00555         }
00556     }
00557 
00558 private:
00559     M2MObject* zxing_object;
00560 };
00561 
00562 ZxingResource zxing_resource;
00563 
00564 static void callback_zxing(char * addr, int size) {
00565     zxing_resource.handle_string_send(addr, size);
00566 }
00567 
00568 
00569 // debug printf function
00570 void trace_printer(const char* str) {
00571     printf("%s\r\n", str);
00572 }
00573 
00574 // Entry point to the program
00575 int main() {
00576 
00577     unsigned int seed;
00578     size_t len;
00579 
00580 #ifdef MBEDTLS_ENTROPY_HARDWARE_ALT
00581     // Used to randomize source port
00582     mbedtls_hardware_poll(NULL, (unsigned char *) &seed, sizeof seed, &len);
00583 
00584 #elif defined MBEDTLS_TEST_NULL_ENTROPY
00585 
00586 #warning "mbedTLS security feature is disabled. Connection will not be secure !! Implement proper hardware entropy for your selected hardware."
00587     // Used to randomize source port
00588     mbedtls_null_entropy_poll( NULL,(unsigned char *) &seed, sizeof seed, &len);
00589 
00590 #else
00591 
00592 #error "This hardware does not have entropy, endpoint will not register to Connector.\
00593 You need to enable NULL ENTROPY for your application, but if this configuration change is made then no security is offered by mbed TLS.\
00594 Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app.json macros to register your endpoint."
00595 
00596 #endif
00597 
00598     srand(seed);
00599     red_led = LED_OFF;
00600 #ifdef TARGET_GR_LYCHEE
00601     orange_led = LED_OFF;
00602 #else
00603     blue_led = LED_OFF;
00604 #endif
00605 
00606     status_ticker.attach_us(blinky, 250000);
00607     // Keep track of the main thread
00608     osThreadId mainThread = osThreadGetId();
00609 
00610     printf("\nStarting mbed Client example\n");
00611 
00612     mbed_trace_init();
00613     mbed_trace_print_function_set(trace_printer);
00614     mbed_trace_config_set(TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN);
00615 
00616 #if defined(TARGET_RZ_A1H) && (MBED_CONF_APP_NETWORK_INTERFACE == WIFI_BP3595)
00617     DigitalOut usb1en(P3_8);
00618     usb1en = 1;
00619     Thread::wait(5);
00620     usb1en = 0;
00621     Thread::wait(5);
00622 #endif
00623 
00624     NetworkInterface* network = easy_connect(true);
00625     if(network == NULL) {
00626         printf("\nConnection to Network Failed - exiting application...\n");
00627         return -1;
00628     }
00629 
00630     // we create our button, timer and LED resources
00631     ButtonResource button_resource;
00632     LedResource led_resource;
00633     BigPayloadResource big_payload_resource;
00634     TimerResource timer_resource;
00635 
00636     // Network interaction must be performed outside of interrupt context
00637     Semaphore updates(0);
00638 
00639     InteractionProvider interaction_provider(updates);
00640 
00641 
00642     // Create endpoint interface to manage register and unregister
00643     mbed_client.create_interface(MBED_SERVER_ADDRESS, network);
00644 
00645     // Create Objects of varying types, see simpleclient.h for more details on implementation.
00646     M2MSecurity* register_object = mbed_client.create_register_object(); // server object specifying connector info
00647     M2MDevice*   device_object   = mbed_client.create_device_object();   // device resources object
00648 
00649     // Create list of Objects to register
00650     M2MObjectList object_list;
00651 
00652     // Add objects to list
00653     object_list.push_back(device_object);
00654     object_list.push_back(button_resource.get_object());
00655     object_list.push_back(led_resource.get_object());
00656     object_list.push_back(big_payload_resource.get_object());
00657     object_list.push_back(timer_resource.get_object());
00658     object_list.push_back(zxing_resource.get_object());
00659 
00660     // Set endpoint registration object
00661     mbed_client.set_register_object(register_object);
00662 
00663     // Register with mbed Device Connector
00664     mbed_client.test_register(register_object, object_list);
00665     volatile bool registered = true;
00666 
00667 #if defined(TARGET_RZ_A1H) || defined(TARGET_GR_LYCHEE)
00668     zxing_init(&callback_zxing);
00669 
00670     Timer update_timer;
00671     update_timer.reset();
00672     update_timer.start();
00673 
00674     while (true) {
00675         if (zxing_loop() == 0) {
00676             update_timer.reset();
00677         } else if (update_timer.read() >= 25) {
00678             mbed_client.test_update_register();
00679             update_timer.reset();
00680         } else {
00681             // do nothing
00682         }
00683         Thread::wait(5);
00684     }
00685 #else
00686     while (true) {
00687         updates.wait(25000);
00688         if(registered) {
00689             if(!interaction_provider.clicked) {
00690                 mbed_client.test_update_register();
00691             }
00692         }else {
00693             break;
00694         }
00695         if(interaction_provider.clicked) {
00696             interaction_provider.clicked = false;
00697             button_resource.handle_button_click();
00698         }
00699         if(interaction_provider.timer_ticked) {
00700             interaction_provider.timer_ticked = false;
00701             timer_resource.handle_timer_tick();
00702         }
00703     }
00704 #endif
00705 
00706     mbed_client.test_unregister();
00707     status_ticker.detach();
00708 }
00709 
00710 #endif // MBED_CONF_APP_NETWORK_INTERFACE != NO_CONNECT
00711 
00712