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
