diff --git a/build_all.sh b/build_all.sh index c30fa28a2..a305461d4 100755 --- a/build_all.sh +++ b/build_all.sh @@ -11,6 +11,7 @@ mbed compile -m K64F -t $TOOL cp BUILD/K64F/$TOOL/mbed-os-example-client.bin k64f-$TOOL-eth-v4.bin mbed compile -m NUCLEO_F429ZI -t $TOOL cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-eth-v4.bin +cp configs/eth_odin_v4.json ./mbed_app.json mbed compile -m UBLOX_EVK_ODIN_W2 -t $TOOL cp ./BUILD/UBLOX_EVK_ODIN_W2/$TOOL/mbed-os-example-client.bin ublox-odin-$TOOL-eth-v4.bin @@ -21,6 +22,7 @@ mbed compile -m K64F -t $TOOL cp BUILD/K64F/$TOOL/mbed-os-example-client.bin k64f-$TOOL-eth-v6.bin mbed compile -m NUCLEO_F429ZI -t $TOOL cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-eth-v4.bin +cp configs/eth_odin_v6.json ./mbed_app.json mbed compile -m UBLOX_EVK_ODIN_W2 -t $TOOL cp ./BUILD/UBLOX_EVK_ODIN_W2/$TOOL/mbed-os-example-client.bin ublox-odin-$TOOL-eth-v6.bin diff --git a/configs/eth_odin_v4.json b/configs/eth_odin_v4.json new file mode 100644 index 000000000..d6ea74952 --- /dev/null +++ b/configs/eth_odin_v4.json @@ -0,0 +1,22 @@ +{ + "config": { + "network-interface":{ + "help": "Options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, MESH_LOWPAN_ND, MESH_THREAD", + "value": "ETHERNET" + } + }, + "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], + "target_overrides": { + "*": { + "target.features_add": ["LWIP", "COMMON_PAL"], + "platform.stdio-baud-rate": 115200, + "platform.stdio-convert-newlines": true, + "lwip.ipv4-enabled": true, + "lwip.ipv6-enabled": false, + "mbed-trace.enable": 0 + }, + "UBLOX_EVK_ODIN_W2": { + "target.device_has_remove": ["EMAC"] + } + } +} diff --git a/configs/eth_odin_v6.json b/configs/eth_odin_v6.json new file mode 100644 index 000000000..f45524517 --- /dev/null +++ b/configs/eth_odin_v6.json @@ -0,0 +1,22 @@ +{ + "config": { + "network-interface":{ + "help": "Options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, MESH_LOWPAN_ND, MESH_THREAD", + "value": "ETHERNET" + } + }, + "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], + "target_overrides": { + "*": { + "target.features_add": ["LWIP", "COMMON_PAL"], + "platform.stdio-baud-rate": 115200, + "platform.stdio-convert-newlines": true, + "lwip.ipv4-enabled": false, + "lwip.ipv6-enabled": true, + "mbed-trace.enable": 0 + }, + "UBLOX_EVK_ODIN_W2": { + "target.device_has_remove": ["EMAC"] + } + } +} diff --git a/configs/eth_v4.json b/configs/eth_v4.json index d6ea74952..36456891c 100644 --- a/configs/eth_v4.json +++ b/configs/eth_v4.json @@ -3,6 +3,10 @@ "network-interface":{ "help": "Options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, MESH_LOWPAN_ND, MESH_THREAD", "value": "ETHERNET" + }, + "button1": { + "help": "Use BUTTON1 from PinNames.h by default", + "value": "BUTTON1" } }, "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], diff --git a/configs/eth_v6.json b/configs/eth_v6.json index f45524517..b72a858cc 100644 --- a/configs/eth_v6.json +++ b/configs/eth_v6.json @@ -3,6 +3,10 @@ "network-interface":{ "help": "Options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, MESH_LOWPAN_ND, MESH_THREAD", "value": "ETHERNET" + }, + "button1": { + "help": "Use BUTTON1 from PinNames.h by default", + "value": "BUTTON1" } }, "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], diff --git a/configs/mesh_6lowpan.json b/configs/mesh_6lowpan.json index 46f49be1f..91fca0603 100644 --- a/configs/mesh_6lowpan.json +++ b/configs/mesh_6lowpan.json @@ -7,6 +7,10 @@ "mesh_radio_type": { "help": "options are ATMEL, MCR20", "value": "ATMEL" + }, + "button1": { + "help": "Use BUTTON1 from PinNames.h by default", + "value": "BUTTON1" } }, "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], diff --git a/configs/mesh_6lowpan_subg.json b/configs/mesh_6lowpan_subg.json index ff9ba3e7c..d5fff2b83 100644 --- a/configs/mesh_6lowpan_subg.json +++ b/configs/mesh_6lowpan_subg.json @@ -7,6 +7,10 @@ "mesh_radio_type": { "help": "options are ATMEL, MCR20, SPIRIT1", "value": "SPIRIT1" + }, + "button1": { + "help": "Use BUTTON1 from PinNames.h by default", + "value": "BUTTON1" } }, "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], diff --git a/configs/mesh_thread.json b/configs/mesh_thread.json index 9b31bc2ad..d46924642 100644 --- a/configs/mesh_thread.json +++ b/configs/mesh_thread.json @@ -7,6 +7,10 @@ "mesh_radio_type": { "help": "options are ATMEL, MCR20, EFR32", "value": "ATMEL" + }, + "button1": { + "help": "Use BUTTON1 from PinNames.h by default", + "value": "BUTTON1" } }, "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], diff --git a/configs/wifi_esp8266_v4.json b/configs/wifi_esp8266_v4.json index 7f3044d61..cd78ed5ae 100644 --- a/configs/wifi_esp8266_v4.json +++ b/configs/wifi_esp8266_v4.json @@ -19,6 +19,10 @@ "wifi-rx": { "help": "RX pin for serial connection to external device", "value": "D0" + }, + "button1": { + "help": "Use BUTTON1 from PinNames.h by default", + "value": "BUTTON1" } }, "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], diff --git a/configs/wifi_odin_v4.json b/configs/wifi_odin_v4.json index 83f056420..59fb4f708 100644 --- a/configs/wifi_odin_v4.json +++ b/configs/wifi_odin_v4.json @@ -19,6 +19,10 @@ "wifi-rx": { "help": "RX pin for serial connection to external device", "value": "D0" + }, + "button1": { + "help": "Use BUTTON1 from PinNames.h by default", + "value": "BUTTON1" } }, "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""], diff --git a/main.cpp b/main.cpp index fb9ee7c4c..b169b16cc 100644 --- a/main.cpp +++ b/main.cpp @@ -67,19 +67,63 @@ struct MbedClientDevice device = { // Instantiate the class which implements LWM2M Client API (from simpleclient.h) MbedClient mbed_client(device); +// Set up a button interrupt for user interaction +#ifdef MBED_CONF_APP_BUTTON1 + InterruptIn counter_btn(MBED_CONF_APP_BUTTON1); +#endif -// In case of K64F board , there is button resource available -// to change resource value and unregister -#ifdef TARGET_K64F -// Set up Hardware interrupt button. -InterruptIn obs_button(SW2); -InterruptIn unreg_button(SW3); -#else -//In non K64F boards , set up a timer to simulate updating resource, -// there is no functionality to unregister. -Ticker timer; + +/** + * 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. */ @@ -248,11 +292,7 @@ class ButtonResource { // up counter counter++; - #ifdef TARGET_K64F printf("handle_button_click, new value of counter is %d\n", counter); - #else - printf("simulate button_click, new value of counter is %d\n", counter); - #endif // serialize the value of counter as a string, and tell connector char buffer[20]; int size = sprintf(buffer,"%d",counter); @@ -267,6 +307,61 @@ class ButtonResource { 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() { @@ -316,21 +411,8 @@ class BigPayloadResource { M2MObject* big_payload; }; -// Network interaction must be performed outside of interrupt context -Semaphore updates(0); -volatile bool registered = false; -volatile bool clicked = false; -osThreadId mainThread; -void unregister() { - registered = false; - updates.release(); -} -void button_clicked() { - clicked = true; - updates.release(); -} // debug printf function void trace_printer(const char* str) { @@ -367,7 +449,7 @@ Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app status_ticker.attach_us(blinky, 250000); // Keep track of the main thread - mainThread = osThreadGetId(); + osThreadId mainThread = osThreadGetId(); printf("\nStarting mbed Client example\n"); @@ -381,23 +463,17 @@ Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app return -1; } - // we create our button and LED resources + // we create our button, timer and LED resources ButtonResource button_resource; LedResource led_resource; BigPayloadResource big_payload_resource; + TimerResource timer_resource; -#ifdef TARGET_K64F - // On press of SW3 button on K64F board, example application - // will call unregister API towards mbed Device Connector - //unreg_button.fall(&mbed_client,&MbedClient::test_unregister); - unreg_button.fall(&unregister); + // Network interaction must be performed outside of interrupt context + Semaphore updates(0); + + InteractionProvider interaction_provider(updates); - // Observation Button (SW2) press will send update of endpoint resource values to connector - obs_button.fall(&button_clicked); -#else - // Send update of endpoint resource values to connector every 15 seconds periodically - timer.attach(&button_clicked, 15.0); -#endif // Create endpoint interface to manage register and unregister mbed_client.create_interface(MBED_SERVER_ADDRESS, network); @@ -414,27 +490,32 @@ Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app 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()); // Set endpoint registration object mbed_client.set_register_object(register_object); // Register with mbed Device Connector mbed_client.test_register(register_object, object_list); - registered = true; + volatile bool registered = true; while (true) { updates.wait(25000); if(registered) { - if(!clicked) { + if(!interaction_provider.clicked) { mbed_client.test_update_register(); } }else { break; } - if(clicked) { - clicked = false; + 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(); + } } mbed_client.test_unregister();