Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 #define __STDC_FORMAT_MACROS 00017 #include <inttypes.h> 00018 #include <string> 00019 #include <sstream> 00020 #include <vector> 00021 #include "mbed-trace/mbed_trace.h" 00022 #include "mbedtls/entropy_poll.h" 00023 00024 #include "security.h" 00025 00026 #include "mbed.h" 00027 00028 // easy-connect compliancy, it has 2 sets of wifi pins we have only one 00029 #define MBED_CONF_APP_ESP8266_TX MBED_CONF_APP_WIFI_TX 00030 #define MBED_CONF_APP_ESP8266_RX MBED_CONF_APP_WIFI_RX 00031 #include "easy-connect/easy-connect.h" 00032 00033 // Should be defined after easy-connect.h 00034 #include "simpleclient.h" 00035 00036 #ifdef TARGET_STM 00037 #define RED_LED (LED3) 00038 #define GREEN_LED (LED1) 00039 #define BLUE_LED (LED2) 00040 #define LED_ON (1) 00041 #else // !TARGET_STM 00042 #define RED_LED (LED1) 00043 #define GREEN_LED (LED2) 00044 #define BLUE_LED (LED3) 00045 #define LED_ON (0) 00046 #endif // !TARGET_STM 00047 #define LED_OFF (!LED_ON) 00048 00049 #define BLINK_SIGNAL 0x1 00050 00051 // Status indication 00052 DigitalOut red_led(RED_LED); 00053 DigitalOut green_led(GREEN_LED); 00054 DigitalOut blue_led(BLUE_LED); 00055 00056 Ticker status_ticker; 00057 void blinky() { 00058 green_led = !green_led; 00059 } 00060 00061 // These are example resource values for the Device Object 00062 struct MbedClientDevice device = { 00063 "Manufacturer_String", // Manufacturer 00064 "Type_String", // Type 00065 "ModelNumber_String", // ModelNumber 00066 "SerialNumber_String" // SerialNumber 00067 }; 00068 00069 // Instantiate the class which implements LWM2M Client API (from simpleclient.h) 00070 MbedClient mbed_client(device); 00071 00072 // Set up a button interrupt for user interaction 00073 #ifdef MBED_CONF_APP_BUTTON1 00074 InterruptIn counter_btn(MBED_CONF_APP_BUTTON1); 00075 #endif 00076 00077 00078 /** 00079 * User interaction handler / simulator. Sets up physical button handler and a ticker 00080 * for regular updates for the resources. 00081 * 00082 * MBED_CONF_APP_BUTTON1 is mapped to actual button pin the mbed_app.json file, where you need to 00083 * specify board-specific value or leave it undefined if the board does not have buttons. 00084 */ 00085 class InteractionProvider { 00086 00087 public: 00088 InteractionProvider(Semaphore& updates_sem) : updates(updates_sem) { 00089 00090 timer_ticked = false; 00091 clicked = false; 00092 00093 // Set up handler function for the interaction button, if available 00094 00095 #ifdef MBED_CONF_APP_BUTTON1 00096 counter_btn.fall(this, &InteractionProvider::counter_button_handler); 00097 #endif 00098 00099 // Use the counter button handler to send an update of endpoint resource values 00100 // to connector every 15 seconds periodically. 00101 timer.attach(this, &InteractionProvider::timer_handler, 15.0); 00102 } 00103 00104 // flags for interaction, these are read from outside interrupt context 00105 volatile bool timer_ticked; 00106 volatile bool clicked; 00107 00108 00109 private: 00110 00111 void timer_handler() { 00112 timer_ticked = true; 00113 updates.release(); 00114 } 00115 00116 void counter_button_handler() { 00117 clicked = true; 00118 updates.release(); 00119 } 00120 00121 // time-based event source for regular resource updates 00122 Ticker timer; 00123 00124 // Network interaction must be performed outside of interrupt context 00125 Semaphore& updates; 00126 00127 }; 00128 00129 /* 00130 * Arguments for running "blink" in it's own thread. 00131 */ 00132 class BlinkArgs { 00133 public: 00134 BlinkArgs() { 00135 clear(); 00136 } 00137 void clear() { 00138 position = 0; 00139 blink_pattern.clear(); 00140 } 00141 uint16_t position; 00142 std::vector<uint32_t> blink_pattern; 00143 }; 00144 00145 /* 00146 * The Led contains one property (pattern) and a function (blink). 00147 * When the function blink is executed, the pattern is read, and the LED 00148 * will blink based on the pattern. 00149 */ 00150 class LedResource { 00151 public: 00152 LedResource() { 00153 // create ObjectID with metadata tag of '3201', which is 'digital output' 00154 blinky_thread.start(callback(this, &LedResource::do_blink)); 00155 led_object = M2MInterfaceFactory::create_object("3201"); 00156 M2MObjectInstance* led_inst = led_object->create_object_instance(); 00157 00158 // 5853 = Multi-state output 00159 M2MResource* pattern_res = led_inst->create_dynamic_resource("5853", "Pattern", 00160 M2MResourceInstance::STRING, false); 00161 // read and write 00162 pattern_res->set_operation(M2MBase::GET_PUT_ALLOWED); 00163 // set initial pattern (toggle every 200ms. 7 toggles in total) 00164 pattern_res->set_value((const uint8_t*)"500:500:500:500:500:500:500", 27); 00165 00166 // there's not really an execute LWM2M ID that matches... hmm... 00167 M2MResource* led_res = led_inst->create_dynamic_resource("5850", "Blink", 00168 M2MResourceInstance::OPAQUE, false); 00169 // we allow executing a function here... 00170 led_res->set_operation(M2MBase::POST_ALLOWED); 00171 // when a POST comes in, we want to execute the led_execute_callback 00172 led_res->set_execute_function(execute_callback(this, &LedResource::blink)); 00173 // Completion of execute function can take a time, that's why delayed response is used 00174 led_res->set_delayed_response(true); 00175 blink_args = new BlinkArgs(); 00176 } 00177 00178 ~LedResource() { 00179 delete blink_args; 00180 } 00181 00182 M2MObject* get_object() { 00183 return led_object; 00184 } 00185 00186 void blink(void *argument) { 00187 // read the value of 'Pattern' 00188 status_ticker.detach(); 00189 green_led = LED_OFF; 00190 00191 M2MObjectInstance* inst = led_object->object_instance(); 00192 M2MResource* res = inst->resource("5853"); 00193 // Clear previous blink data 00194 blink_args->clear(); 00195 00196 // values in mbed Client are all buffers, and we need a vector of int's 00197 uint8_t* buffIn = NULL; 00198 uint32_t sizeIn; 00199 res->get_value(buffIn, sizeIn); 00200 00201 // turn the buffer into a string, and initialize a vector<int> on the heap 00202 std::string s((char*)buffIn, sizeIn); 00203 free(buffIn); 00204 printf("led_execute_callback pattern=%s\n", s.c_str()); 00205 00206 // our pattern is something like 500:200:500, so parse that 00207 std::size_t found = s.find_first_of(":"); 00208 while (found!=std::string::npos) { 00209 blink_args->blink_pattern.push_back(atoi((const char*)s.substr(0,found).c_str())); 00210 s = s.substr(found+1); 00211 found=s.find_first_of(":"); 00212 if(found == std::string::npos) { 00213 blink_args->blink_pattern.push_back(atoi((const char*)s.c_str())); 00214 } 00215 } 00216 // check if POST contains payload 00217 if (argument) { 00218 M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument; 00219 String object_name = param->get_argument_object_name(); 00220 uint16_t object_instance_id = param->get_argument_object_instance_id(); 00221 String resource_name = param->get_argument_resource_name(); 00222 int payload_length = param->get_argument_value_length(); 00223 const uint8_t* payload = param->get_argument_value(); 00224 printf("Resource: %s/%d/%s executed\n", object_name.c_str(), object_instance_id, resource_name.c_str()); 00225 printf("Payload: %.*s\n", payload_length, payload); 00226 } 00227 // do_blink is called with the vector, and starting at -1 00228 blinky_thread.signal_set(BLINK_SIGNAL); 00229 } 00230 00231 private: 00232 M2MObject* led_object; 00233 Thread blinky_thread; 00234 BlinkArgs *blink_args; 00235 void do_blink() { 00236 for(;;) { 00237 blinky_thread.signal_wait(BLINK_SIGNAL); 00238 for (;;) { 00239 // blink the LED 00240 red_led = !red_led; 00241 // up the position, if we reached the end of the vector 00242 if (blink_args->position >= blink_args->blink_pattern.size()) { 00243 // send delayed response after blink is done 00244 M2MObjectInstance* inst = led_object->object_instance(); 00245 M2MResource* led_res = inst->resource("5850"); 00246 led_res->send_delayed_post_response(); 00247 red_led = LED_OFF; 00248 status_ticker.attach_us(blinky, 250000); 00249 break; 00250 } 00251 // Wait requested time, then continue prosessing the blink pattern from next position. 00252 Thread::wait(blink_args->blink_pattern.at(blink_args->position)); 00253 blink_args->position++; 00254 } 00255 } 00256 } 00257 }; 00258 00259 /* 00260 * The button contains one property (click count). 00261 * When `handle_button_click` is executed, the counter updates. 00262 */ 00263 class ButtonResource { 00264 public: 00265 ButtonResource(): counter(0) { 00266 // create ObjectID with metadata tag of '3200', which is 'digital input' 00267 btn_object = M2MInterfaceFactory::create_object("3200"); 00268 M2MObjectInstance* btn_inst = btn_object->create_object_instance(); 00269 // create resource with ID '5501', which is digital input counter 00270 M2MResource* btn_res = btn_inst->create_dynamic_resource("5501", "Button", 00271 M2MResourceInstance::INTEGER, true /* observable */); 00272 // we can read this value 00273 btn_res->set_operation(M2MBase::GET_ALLOWED); 00274 // set initial value (all values in mbed Client are buffers) 00275 // to be able to read this data easily in the Connector console, we'll use a string 00276 btn_res->set_value((uint8_t*)"0", 1); 00277 } 00278 00279 ~ButtonResource() { 00280 } 00281 00282 M2MObject* get_object() { 00283 return btn_object; 00284 } 00285 00286 /* 00287 * When you press the button, we read the current value of the click counter 00288 * from mbed Device Connector, then up the value with one. 00289 */ 00290 void handle_button_click() { 00291 if (mbed_client.register_successful()) { 00292 M2MObjectInstance* inst = btn_object->object_instance(); 00293 M2MResource* res = inst->resource("5501"); 00294 00295 // up counter 00296 counter++; 00297 printf("handle_button_click, new value of counter is %d\n", counter); 00298 // serialize the value of counter as a string, and tell connector 00299 char buffer[20]; 00300 int size = sprintf(buffer,"%d",counter); 00301 res->set_value((uint8_t*)buffer, size); 00302 } else { 00303 printf("simulate button_click, device not registered\n"); 00304 } 00305 } 00306 00307 private: 00308 M2MObject* btn_object; 00309 uint16_t counter; 00310 }; 00311 00312 /* 00313 * The timer contains one property: counter. 00314 * When `handle_timer_tick` is executed, the counter updates. 00315 */ 00316 class TimerResource { 00317 public: 00318 TimerResource(): counter(0) { 00319 // create ObjectID with metadata tag of '3200', which is 'digital input' 00320 btn_object = M2MInterfaceFactory::create_object("3200"); 00321 M2MObjectInstance* btn_inst = btn_object->create_object_instance(); 00322 // create resource with ID '5502', which is digital input counter 00323 M2MResource* btn_res = btn_inst->create_dynamic_resource("5502", "Timer", 00324 M2MResourceInstance::INTEGER, true /* observable */); 00325 // we can read this value 00326 btn_res->set_operation(M2MBase::GET_ALLOWED); 00327 // set initial value (all values in mbed Client are buffers) 00328 // to be able to read this data easily in the Connector console, we'll use a string 00329 btn_res->set_value((uint8_t*)"0", 1); 00330 } 00331 00332 ~TimerResource() { 00333 } 00334 00335 M2MObject* get_object() { 00336 return btn_object; 00337 } 00338 00339 /* 00340 * When the timer ticks, we read the current value of the click counter 00341 * from mbed Device Connector, then up the value with one.l 00342 */ 00343 void handle_timer_tick() { 00344 if (mbed_client.register_successful()) { 00345 M2MObjectInstance* inst = btn_object->object_instance(); 00346 M2MResource* res = inst->resource("5502"); 00347 00348 // up counter 00349 counter++; 00350 printf("handle_timer_click, new value of counter is %d\n", counter); 00351 // serialize the value of counter as a string, and tell connector 00352 char buffer[20]; 00353 int size = sprintf(buffer,"%d",counter); 00354 res->set_value((uint8_t*)buffer, size); 00355 } else { 00356 printf("handle_timer_tick, device not registered\n"); 00357 } 00358 } 00359 00360 private: 00361 M2MObject* btn_object; 00362 uint16_t counter; 00363 }; 00364 00365 00366 00367 class BigPayloadResource { 00368 public: 00369 BigPayloadResource() { 00370 big_payload = M2MInterfaceFactory::create_object("1000"); 00371 M2MObjectInstance* payload_inst = big_payload->create_object_instance(); 00372 M2MResource* payload_res = payload_inst->create_dynamic_resource("1", "BigData", 00373 M2MResourceInstance::STRING, true /* observable */); 00374 payload_res->set_operation(M2MBase::GET_PUT_ALLOWED); 00375 payload_res->set_value((uint8_t*)"0", 1); 00376 payload_res->set_incoming_block_message_callback( 00377 incoming_block_message_callback(this, &BigPayloadResource::block_message_received)); 00378 payload_res->set_outgoing_block_message_callback( 00379 outgoing_block_message_callback(this, &BigPayloadResource::block_message_requested)); 00380 } 00381 00382 M2MObject* get_object() { 00383 return big_payload; 00384 } 00385 00386 void block_message_received(M2MBlockMessage *argument) { 00387 if (argument) { 00388 if (M2MBlockMessage::ErrorNone == argument->error_code()) { 00389 if (argument->is_last_block()) { 00390 printf("Last block received\n"); 00391 } 00392 printf("Block number: %d\n", argument->block_number()); 00393 // First block received 00394 if (argument->block_number() == 0) { 00395 // Store block 00396 // More blocks coming 00397 } else { 00398 // Store blocks 00399 } 00400 } else { 00401 printf("Error when receiving block message! - EntityTooLarge\n"); 00402 } 00403 printf("Total message size: %" PRIu32 "\n", argument->total_message_size()); 00404 } 00405 } 00406 00407 void block_message_requested(const String& resource, uint8_t *&/*data*/, uint32_t &/*len*/) { 00408 printf("GET request received for resource: %s\n", resource.c_str()); 00409 // Copy data and length to coap response 00410 } 00411 00412 private: 00413 M2MObject* big_payload; 00414 }; 00415 00416 00417 00418 00419 // debug printf function 00420 void trace_printer(const char* str) { 00421 printf("%s\r\n", str); 00422 } 00423 00424 // Entry point to the program 00425 int main() { 00426 00427 unsigned int seed; 00428 size_t len; 00429 00430 #ifdef MBEDTLS_ENTROPY_HARDWARE_ALT 00431 // Used to randomize source port 00432 mbedtls_hardware_poll(NULL, (unsigned char *) &seed, sizeof seed, &len); 00433 00434 #elif defined MBEDTLS_TEST_NULL_ENTROPY 00435 00436 #warning "mbedTLS security feature is disabled. Connection will not be secure !! Implement proper hardware entropy for your selected hardware." 00437 // Used to randomize source port 00438 mbedtls_null_entropy_poll( NULL,(unsigned char *) &seed, sizeof seed, &len); 00439 00440 #else 00441 00442 #error "This hardware does not have entropy, endpoint will not register to Connector.\ 00443 You need to enable NULL ENTROPY for your application, but if this configuration change is made then no security is offered by mbed TLS.\ 00444 Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app.json macros to register your endpoint." 00445 00446 #endif 00447 00448 srand(seed); 00449 red_led = LED_OFF; 00450 blue_led = LED_OFF; 00451 00452 status_ticker.attach_us(blinky, 250000); 00453 // Keep track of the main thread 00454 osThreadId mainThread = osThreadGetId(); 00455 00456 printf("\nStarting mbed Client example\n"); 00457 00458 mbed_trace_init(); 00459 mbed_trace_print_function_set(trace_printer); 00460 mbed_trace_config_set(TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN); 00461 00462 NetworkInterface* network = easy_connect(true); 00463 if(network == NULL) { 00464 printf("\nConnection to Network Failed - exiting application...\n"); 00465 return -1; 00466 } 00467 00468 // we create our button, timer and LED resources 00469 ButtonResource button_resource; 00470 LedResource led_resource; 00471 BigPayloadResource big_payload_resource; 00472 TimerResource timer_resource; 00473 00474 // Network interaction must be performed outside of interrupt context 00475 Semaphore updates(0); 00476 00477 InteractionProvider interaction_provider(updates); 00478 00479 00480 // Create endpoint interface to manage register and unregister 00481 mbed_client.create_interface(MBED_SERVER_ADDRESS, network); 00482 00483 // Create Objects of varying types, see simpleclient.h for more details on implementation. 00484 M2MSecurity* register_object = mbed_client.create_register_object(); // server object specifying connector info 00485 M2MDevice* device_object = mbed_client.create_device_object(); // device resources object 00486 00487 // Create list of Objects to register 00488 M2MObjectList object_list; 00489 00490 // Add objects to list 00491 object_list.push_back(device_object); 00492 object_list.push_back(button_resource.get_object()); 00493 object_list.push_back(led_resource.get_object()); 00494 object_list.push_back(big_payload_resource.get_object()); 00495 object_list.push_back(timer_resource.get_object()); 00496 00497 // Set endpoint registration object 00498 mbed_client.set_register_object(register_object); 00499 00500 // Register with mbed Device Connector 00501 mbed_client.test_register(register_object, object_list); 00502 volatile bool registered = true; 00503 00504 while (true) { 00505 updates.wait(25000); 00506 if(registered) { 00507 if(!interaction_provider.clicked) { 00508 mbed_client.test_update_register(); 00509 } 00510 }else { 00511 break; 00512 } 00513 if(interaction_provider.clicked) { 00514 interaction_provider.clicked = false; 00515 button_resource.handle_button_click(); 00516 } 00517 if(interaction_provider.timer_ticked) { 00518 interaction_provider.timer_ticked = false; 00519 timer_resource.handle_timer_tick(); 00520 } 00521 } 00522 00523 mbed_client.test_unregister(); 00524 status_ticker.detach(); 00525 }
Generated on Tue Jul 12 2022 15:06:45 by
1.7.2
Wiznet Wi-Fi WizFi310