This is a mbed Client sample where ZXing is incorporated, and works on GR-PEACH and GR-LYCHEE.
Dependencies: DisplayApp AsciiFont
Overview
This sample program shows how to use mbed Client together with ZXing which is an open-source, multi-format 1D/2D barcode image processing library. For more info on ZXing, please refer to https://github.com/zxing/zxing.
Required hardware
- GR-PEACH ( https://developer.mbed.org/platforms/Renesas-GR-PEACH/ )
- Audio Camera Shield ( https://developer.mbed.org/teams/Renesas/wiki/Audio_Camera-shield )
- LCD Shield ( https://developer.mbed.org/teams/Renesas/wiki/LCD-shield )
- Ethernet cable and connection to the internet
- Wireless Camera shieled (This is GR-PEACH' Wifi(ESP32) optional.)
- GR-LYCHEE ( https://developer.mbed.org/platforms/Renesas-GR-LYCHEE/ )
Application setup
- Select the connection type. For details, please refer to the following wiki:
https://os.mbed.com/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/wiki/Connection-type. - Set the client credentials. For details, please refer to the following wiki:
https://os.mbed.com/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/wiki/Client-credentials. - Change Ethernet settings. For details, please refer to the following wiki:
https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/wiki/Ethernet-settings. - Change Wifi settings. For details, please refer to the following wiki:
https://os.mbed.com/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/wiki/Wifi-settings. - Set up an IP address. (This step is optional.) For details, please refer to the following wiki:
https://os.mbed.com/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/wiki/IP-address-setup.
Building the example
To build this example:
- Import this example onto mbed Compiler.
- Configure the example in accordance with Application setup.
- Compile the example on mbed Compiler and download the resultant binary file.
- Plug the Ethernet cable into GR-PEACH or GR-LYCHEE if you are using Ethernet mode.
- Plug the micro-USB cable into the OpenSDA port which lies on the next to the RESET button.
- Copy the binary previously downloaded to your PC to GR-PEACH or GR-LYCHEE to flash this example. When the copy is successfully completed, the board is ready to work.
- Press the RESET button on the board to run the example.
- For verification, please refer to the following wiki:
https://developer.mbed.org/teams/Renesas/code/GR-PEACH_mbed-os-client-ZXingSample/wiki/Monitoring-the-application.
Application resources
This example exposes four resources listed below:
- 3202/0/5700. Decode result of barcode data input from camera (GET).
- 3201/0/5850. Blink function, blinks LED when executed (POST).
- 3201/0/5853. Blink pattern, used by the blink function to determine how to blink. In the format of 1000:500:1000:500:1000:500 (PUT).
- 3201/0/5855. Blink color, used by the blink function. Any of red, green, blue, cyan, yellow and magenta is acceptable if you are using GR-PEACH board (PUT).
- 3201/0/5855. Blink color, used by the blink function. Any of green, yellow, orange and red is acceptable if you are using GR-LYCHEE board (PUT).
For more info on how to get notifications when resource 1 changes, or how to use resource 2, 3 and 4, please look at
Import programGR-PEACH_mbed-connector-ZXingSample-node
Node.js based Web Application for mbed Device Connector specific to GR-PEACH_mbed-os-client-ZXingSample
Diff: main.cpp
- Revision:
- 6:ea24d9271ff1
- Parent:
- 2:6ec5c1c1d41c
- Child:
- 10:f7e8d2b608c3
diff -r 6b6540e303f2 -r ea24d9271ff1 main.cpp --- a/main.cpp Mon Apr 17 05:28:29 2017 +0000 +++ b/main.cpp Thu Dec 13 08:28:47 2018 +0000 @@ -45,17 +45,73 @@ #else // MBED_CONF_APP_NETWORK_INTERFACE != NO_CONNECT #define __STDC_FORMAT_MACROS +#include <inttypes.h> #include <string> #include <sstream> #include <vector> +#include "mbed-trace/mbed_trace.h" +#include "mbedtls/entropy_poll.h" + #include "security.h" -#include "simpleclient.h" -#include "mbedtls/entropy_poll.h" + +#include "mbed.h" // easy-connect compliancy, it has 2 sets of wifi pins we have only one #define MBED_CONF_APP_ESP8266_TX MBED_CONF_APP_WIFI_TX #define MBED_CONF_APP_ESP8266_RX MBED_CONF_APP_WIFI_RX -#include "easy-connect.h" +#include "easy-connect/easy-connect.h" + +// Should be defined after easy-connect.h +#include "simpleclient.h" + +#ifdef TARGET_STM +#define RED_LED (LED3) +#define GREEN_LED (LED1) +#define BLUE_LED (LED2) +#define LED_ON (1) +#elif TARGET_RZ_A1H +#define RED_LED (LED1) +#define GREEN_LED (LED2) +#define BLUE_LED (LED3) +#define USER_LED (LED4) +#define LED_ON (1) +#elif TARGET_GR_LYCHEE +#define GREEN_LED (LED1) +#define YELLOW_LED (LED2) +#define ORANGE_LED (LED3) +#define RED_LED (LED4) +#define LED_ON (1) +#else +#define RED_LED (LED1) +#define GREEN_LED (LED2) +#define BLUE_LED (LED3) +#define LED_ON (0) +#endif +#define LED_OFF (!LED_ON) + +#define BLINK_SIGNAL 0x1 + +// Status indication +DigitalOut red_led(RED_LED); +DigitalOut green_led(GREEN_LED); +#ifdef TARGET_RZ_A1H +DigitalOut blue_led(BLUE_LED); +DigitalOut user_led(USER_LED); +#elif TARGET_GR_LYCHEE +DigitalOut yellow_led(YELLOW_LED); +DigitalOut orange_led(ORANGE_LED); +#else +DigitalOut blue_led(BLUE_LED); +#endif + +Ticker status_ticker; +void blinky() { +#ifdef TARGET_RZ_A1H + user_led = !user_led; +#else + green_led = !green_led; +#endif +} // These are example resource values for the Device Object struct MbedClientDevice device = { @@ -68,10 +124,79 @@ // Instantiate the class which implements LWM2M Client API (from simpleclient.h) MbedClient mbed_client(device); -// LED Output -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); +// Set up a button interrupt for user interaction +#ifdef MBED_CONF_APP_BUTTON1 + InterruptIn counter_btn(MBED_CONF_APP_BUTTON1); +#endif + + +/** + * User interaction handler / simulator. Sets up physical button handler and a ticker + * for regular updates for the resources. + * + * MBED_CONF_APP_BUTTON1 is mapped to actual button pin the mbed_app.json file, where you need to + * specify board-specific value or leave it undefined if the board does not have buttons. + */ +class InteractionProvider { + +public: + InteractionProvider(Semaphore& updates_sem) : updates(updates_sem) { + + timer_ticked = false; + clicked = false; + + // Set up handler function for the interaction button, if available + +#ifdef MBED_CONF_APP_BUTTON1 + counter_btn.fall(this, &InteractionProvider::counter_button_handler); +#endif + + // Use the counter button handler to send an update of endpoint resource values + // to connector every 15 seconds periodically. + timer.attach(this, &InteractionProvider::timer_handler, 15.0); + } + + // flags for interaction, these are read from outside interrupt context + volatile bool timer_ticked; + volatile bool clicked; + + +private: + + void timer_handler() { + timer_ticked = true; + updates.release(); + } + + void counter_button_handler() { + clicked = true; + updates.release(); + } + + // time-based event source for regular resource updates + Ticker timer; + + // Network interaction must be performed outside of interrupt context + Semaphore& updates; + +}; + +/* + * Arguments for running "blink" in it's own thread. + */ +class BlinkArgs { +public: + BlinkArgs() { + clear(); + } + void clear() { + position = 0; + blink_pattern.clear(); + } + uint16_t position; + std::vector<uint32_t> blink_pattern; +}; + /* * The Led contains one property (pattern) and a function (blink). * When the function blink is executed, the pattern is read, and the LED @@ -81,6 +206,7 @@ public: LedResource() { // create ObjectID with metadata tag of '3201', which is 'digital output' +// blinky_thread.start(callback(this, &LedResource::do_blink)); led_object = M2MInterfaceFactory::create_object("3201"); M2MObjectInstance* led_inst = led_object->create_object_instance(); @@ -115,8 +241,6 @@ } void blink(void *argument) { - - // read the value of 'Pattern' M2MObjectInstance* inst = led_object->object_instance(); M2MResource* res = inst->resource("5853"); @@ -128,7 +252,7 @@ uint8_t* buffIn = NULL; uint32_t sizeIn; res->get_value(buffIn, sizeIn); - + uint8_t* cbuffIn = NULL; uint32_t csizeIn; resC->get_value(cbuffIn, csizeIn); @@ -137,12 +261,11 @@ std::string s((char*)buffIn, sizeIn); std::vector<uint32_t>* v = new std::vector<uint32_t>; - printf("led_execute_callback pattern=%s\r\n", s.c_str()); + printf("led_execute_callback pattern=%s\n", s.c_str()); // our pattern is something like 500:200:500, so parse that std::size_t found = s.find_first_of(":"); while (found!=std::string::npos) { - v->push_back(atoi((const char*)s.substr(0,found).c_str())); s = s.substr(found+1); found=s.find_first_of(":"); @@ -168,47 +291,227 @@ private: M2MObject* led_object; void do_blink(uint8_t* color) { - + +#if defined(TARGET_RZ_A1H) if (!strcmp((char *)color, "red")) { // blink the LED in red color - led1 = !led1; + red_led = !red_led; } else if (!strcmp((char *)color, "green")) { // blink in green color - led2 = !led2; + green_led = !green_led; } else if (!strcmp((char *)color, "blue")) { // blink in blue color - led3 = !led3; + blue_led = !blue_led; } else if (!strcmp((char *)color, "cyan")) { // blink in cyan color - led2 = !led2; - led3 = !led3; + green_led = !green_led; + blue_led = !blue_led; } else if (!strcmp((char *)color, "yellow")) { // blink in yellow color - led1 = !led1; - led2 = !led2; + red_led = !red_led; + green_led = !green_led; } else if (!strcmp((char *)color, "magenta")) { // blink in magenta color - led1 = !led1; - led3 = !led3; + red_led = !red_led; + blue_led = !blue_led; } else if (!strcmp((char *)color, "white")) { // blink in white color - led1 = !led1; - led2 = !led2; - led3 = !led3; + red_led = !red_led; + green_led = !green_led; + blue_led = !blue_led; + } + else { + // no operation + } +#elif defined(TARGET_GR_LYCHEE) + if (!strcmp((char *)color, "green")) { + // blink the LED1(green color) + green_led = !green_led; + } + else if (!strcmp((char *)color, "yellow")) { + // blink the LED2(yellow color) + yellow_led = !yellow_led; + } + else if (!strcmp((char *)color, "orange")) { + // blink the LED3(orange color) + orange_led = !orange_led; + } + else if (!strcmp((char *)color, "red")) { + // blink the LED4(red color) + red_led = !red_led; } else { // no operation } +#endif } }; /* + * The button contains one property (click count). + * When `handle_button_click` is executed, the counter updates. + */ +class ButtonResource { +public: + ButtonResource(): counter(0) { + // create ObjectID with metadata tag of '3200', which is 'digital input' + btn_object = M2MInterfaceFactory::create_object("3200"); + M2MObjectInstance* btn_inst = btn_object->create_object_instance(); + // create resource with ID '5501', which is digital input counter + M2MResource* btn_res = btn_inst->create_dynamic_resource("5501", "Button", + M2MResourceInstance::INTEGER, true /* observable */); + // we can read this value + btn_res->set_operation(M2MBase::GET_ALLOWED); + // set initial value (all values in mbed Client are buffers) + // to be able to read this data easily in the Connector console, we'll use a string + btn_res->set_value((uint8_t*)"0", 1); + } + + ~ButtonResource() { + } + + M2MObject* get_object() { + return btn_object; + } + + /* + * When you press the button, we read the current value of the click counter + * from mbed Device Connector, then up the value with one. + */ + void handle_button_click() { + if (mbed_client.register_successful()) { + M2MObjectInstance* inst = btn_object->object_instance(); + M2MResource* res = inst->resource("5501"); + + // up counter + counter++; + printf("handle_button_click, new value of counter is %d\n", counter); + // serialize the value of counter as a string, and tell connector + char buffer[20]; + int size = sprintf(buffer,"%d",counter); + res->set_value((uint8_t*)buffer, size); + } else { + printf("simulate button_click, device not registered\n"); + } + } + +private: + M2MObject* btn_object; + uint16_t counter; +}; + +/* + * The timer contains one property: counter. + * When `handle_timer_tick` is executed, the counter updates. + */ +class TimerResource { +public: + TimerResource(): counter(0) { + // create ObjectID with metadata tag of '3200', which is 'digital input' + btn_object = M2MInterfaceFactory::create_object("3200"); + M2MObjectInstance* btn_inst = btn_object->create_object_instance(); + // create resource with ID '5502', which is digital input counter + M2MResource* btn_res = btn_inst->create_dynamic_resource("5502", "Timer", + M2MResourceInstance::INTEGER, true /* observable */); + // we can read this value + btn_res->set_operation(M2MBase::GET_ALLOWED); + // set initial value (all values in mbed Client are buffers) + // to be able to read this data easily in the Connector console, we'll use a string + btn_res->set_value((uint8_t*)"0", 1); + } + + ~TimerResource() { + } + + M2MObject* get_object() { + return btn_object; + } + + /* + * When the timer ticks, we read the current value of the click counter + * from mbed Device Connector, then up the value with one.l + */ + void handle_timer_tick() { + if (mbed_client.register_successful()) { + M2MObjectInstance* inst = btn_object->object_instance(); + M2MResource* res = inst->resource("5502"); + + // up counter + counter++; + printf("handle_timer_click, new value of counter is %d\n", counter); + // serialize the value of counter as a string, and tell connector + char buffer[20]; + int size = sprintf(buffer,"%d",counter); + res->set_value((uint8_t*)buffer, size); + } else { + printf("handle_timer_tick, device not registered\n"); + } + } + +private: + M2MObject* btn_object; + uint16_t counter; +}; + + + +class BigPayloadResource { +public: + BigPayloadResource() { + big_payload = M2MInterfaceFactory::create_object("1000"); + M2MObjectInstance* payload_inst = big_payload->create_object_instance(); + M2MResource* payload_res = payload_inst->create_dynamic_resource("1", "BigData", + M2MResourceInstance::STRING, true /* observable */); + payload_res->set_operation(M2MBase::GET_PUT_ALLOWED); + payload_res->set_value((uint8_t*)"0", 1); + payload_res->set_incoming_block_message_callback( + incoming_block_message_callback(this, &BigPayloadResource::block_message_received)); + payload_res->set_outgoing_block_message_callback( + outgoing_block_message_callback(this, &BigPayloadResource::block_message_requested)); + } + + M2MObject* get_object() { + return big_payload; + } + + void block_message_received(M2MBlockMessage *argument) { + if (argument) { + if (M2MBlockMessage::ErrorNone == argument->error_code()) { + if (argument->is_last_block()) { + printf("Last block received\n"); + } + printf("Block number: %d\n", argument->block_number()); + // First block received + if (argument->block_number() == 0) { + // Store block + // More blocks coming + } else { + // Store blocks + } + } else { + printf("Error when receiving block message! - EntityTooLarge\n"); + } +// printf("Total message size: %" PRIu32 "\n", argument->total_message_size()); + printf("Total message size: %PRIu32\n", argument->total_message_size()); + } + } + + void block_message_requested(const String& resource, uint8_t *&/*data*/, uint32_t &/*len*/) { + printf("GET request received for resource: %s\n", resource.c_str()); + // Copy data and length to coap response + } + +private: + M2MObject* big_payload; +}; + +/* * The Zxing contains a function (send string). * When `handle_string_send` is executed, the string after decoding is sent. */ @@ -239,13 +542,17 @@ * When you success the decode process of barcode, we send the string after decoding to mbed Device Connector. */ void handle_string_send(char * addr, int size) { - M2MObjectInstance* inst = zxing_object->object_instance(); - M2MResource* res = inst->resource("5700"); + if (mbed_client.register_successful()) { + M2MObjectInstance* inst = zxing_object->object_instance(); + M2MResource* res = inst->resource("5700"); + + printf("%s\r\n", addr); - printf("%s\r\n", addr); - - // tell the string to connector - res->set_value((uint8_t *)addr, size); + // tell the string to connector + res->set_value((uint8_t *)addr, size); + } else { + printf("handle_string_send, device not registered\n"); + } } private: @@ -258,10 +565,10 @@ zxing_resource.handle_string_send(addr, size); } -static volatile bool registered; -void unregister() { - registered = false; +// debug printf function +void trace_printer(const char* str) { + printf("%s\r\n", str); } // Entry point to the program @@ -289,19 +596,24 @@ #endif srand(seed); - // Keep track of the main thread - mainThread = osThreadGetId(); - printf("\nStarting mbed Client example in "); - -#if defined (MESH) || (MBED_CONF_LWIP_IPV6_ENABLED==true) - printf("IPv6 mode\n"); + red_led = LED_OFF; +#ifdef TARGET_GR_LYCHEE + orange_led = LED_OFF; #else - printf("IPv4 mode\n"); + blue_led = LED_OFF; #endif - mbed_trace_init(); + status_ticker.attach_us(blinky, 250000); + // Keep track of the main thread + osThreadId mainThread = osThreadGetId(); + + printf("\nStarting mbed Client example\n"); -#if MBED_CONF_APP_NETWORK_INTERFACE == WIFI_BP3595 + mbed_trace_init(); + mbed_trace_print_function_set(trace_printer); + mbed_trace_config_set(TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN); + +#if defined(TARGET_RZ_A1H) && (MBED_CONF_APP_NETWORK_INTERFACE == WIFI_BP3595) DigitalOut usb1en(P3_8); usb1en = 1; Thread::wait(5); @@ -314,7 +626,18 @@ printf("\nConnection to Network Failed - exiting application...\n"); return -1; } + + // we create our button, timer and LED resources + ButtonResource button_resource; LedResource led_resource; + BigPayloadResource big_payload_resource; + TimerResource timer_resource; + + // Network interaction must be performed outside of interrupt context + Semaphore updates(0); + + InteractionProvider interaction_provider(updates); + // Create endpoint interface to manage register and unregister mbed_client.create_interface(MBED_SERVER_ADDRESS, network); @@ -328,7 +651,10 @@ // Add objects to list object_list.push_back(device_object); + object_list.push_back(button_resource.get_object()); object_list.push_back(led_resource.get_object()); + object_list.push_back(big_payload_resource.get_object()); + object_list.push_back(timer_resource.get_object()); object_list.push_back(zxing_resource.get_object()); // Set endpoint registration object @@ -336,18 +662,16 @@ // Register with mbed Device Connector mbed_client.test_register(register_object, object_list); + volatile bool registered = true; +#if defined(TARGET_RZ_A1H) || defined(TARGET_GR_LYCHEE) zxing_init(&callback_zxing); Timer update_timer; update_timer.reset(); update_timer.start(); - registered = true; - InterruptIn unreg_button(USER_BUTTON0); - unreg_button.fall(&unregister); - - while (registered) { + while (true) { if (zxing_loop() == 0) { update_timer.reset(); } else if (update_timer.read() >= 25) { @@ -358,10 +682,39 @@ } Thread::wait(5); } +#else + while (true) { + updates.wait(25000); + if(registered) { + if(!interaction_provider.clicked) { + mbed_client.test_update_register(); + } + }else { + break; + } + if(interaction_provider.clicked) { + interaction_provider.clicked = false; + button_resource.handle_button_click(); + } + if(interaction_provider.timer_ticked) { + interaction_provider.timer_ticked = false; + timer_resource.handle_timer_tick(); + } + } +#endif mbed_client.test_unregister(); + status_ticker.detach(); } +void mbed_mac_address(char *mac) { + mac[0] = 0x00; + mac[1] = 0x02; + mac[2] = 0xF7; + mac[3] = 0xF0; + mac[4] = 0x00; + mac[5] = 0x00; +} #endif // MBED_CONF_APP_NETWORK_INTERFACE != NO_CONNECT