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 2016-2019 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 #ifndef MBED_TEST_MODE 00019 #include "mbed.h" 00020 #include "kv_config.h" 00021 #include "mbed-cloud-client/MbedCloudClient.h" // Required for new MbedCloudClient() 00022 #include "factory_configurator_client.h" // Required for fcc_* functions and FCC_* defines 00023 #include "m2mresource.h" // Required for M2MResource 00024 00025 #include "mbed-trace/mbed_trace.h" // Required for mbed_trace_* 00026 00027 // Camera setting 00028 #include "EasyAttach_CameraAndLCD.h" 00029 #include "dcache-control.h" 00030 #include "JPEG_Converter.h" 00031 /**** User Selection *********/ 00032 #define VIDEO_PIXEL_HW (320u) /* QVGA */ 00033 #define VIDEO_PIXEL_VW (240u) /* QVGA */ 00034 #define JPEG_ENCODE_QUALITY (75) /* JPEG encode quality (min:1, max:75 (Considering the size of JpegBuffer, about 75 is the upper limit.)) */ 00035 /*****************************/ 00036 #define DATA_SIZE_PER_PIC (2u) 00037 #define FRAME_BUFFER_STRIDE (((VIDEO_PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u) 00038 #define FRAME_BUFFER_HEIGHT (VIDEO_PIXEL_VW) 00039 00040 uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((aligned(32))); 00041 uint8_t JpegBuffer[1024 * 32]__attribute((aligned(32))); 00042 DisplayBase Display; 00043 JPEG_Converter Jcu; 00044 // End camera setting 00045 00046 const int LED_ON = MBED_CONF_APP_LED_ON; 00047 const int LED_OFF = (!(MBED_CONF_APP_LED_ON)); 00048 00049 // Pointers to the resources that will be created in main_application(). 00050 static MbedCloudClient *cloud_client; 00051 static bool cloud_client_running = true; 00052 static NetworkInterface *network = NULL; 00053 00054 // Fake entropy needed for non-TRNG boards. Suitable only for demo devices. 00055 const uint8_t MBED_CLOUD_DEV_ENTROPY[] = { 0xf6, 0xd6, 0xc0, 0x09, 0x9e, 0x6e, 0xf2, 0x37, 0xdc, 0x29, 0x88, 0xf1, 0x57, 0x32, 0x7d, 0xde, 0xac, 0xb3, 0x99, 0x8c, 0xb9, 0x11, 0x35, 0x18, 0xeb, 0x48, 0x29, 0x03, 0x6a, 0x94, 0x6d, 0xe8, 0x40, 0xc0, 0x28, 0xcc, 0xe4, 0x04, 0xc3, 0x1f, 0x4b, 0xc2, 0xe0, 0x68, 0xa0, 0x93, 0xe6, 0x3a }; 00056 00057 static M2MResource* m2m_get_res; 00058 static M2MResource* m2m_put_res; 00059 static M2MResource* m2m_post_res; 00060 static M2MResource* m2m_deregister_res; 00061 00062 // Additional resources for camera 00063 static M2MResource* m2m_camera_capture_res; 00064 00065 // Camera functions 00066 bool take_photo(uint8_t *photo_data, uint32_t *photo_data_len) { 00067 JPEG_Converter::bitmap_buff_info_t buff_info; 00068 JPEG_Converter::encode_options_t encode_opt; 00069 00070 if ((photo_data == NULL) || (photo_data_len == NULL)) { 00071 return false; 00072 } 00073 00074 // Jpeg setting 00075 buff_info.width = VIDEO_PIXEL_HW; 00076 buff_info.height = VIDEO_PIXEL_VW; 00077 buff_info.format = JPEG_Converter::WR_RD_YCbCr422; 00078 buff_info.buffer_address = (void *)user_frame_buffer0; 00079 encode_opt.encode_buff_size = *photo_data_len; 00080 encode_opt.input_swapsetting = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT; 00081 00082 dcache_invalid(photo_data, *photo_data_len); 00083 JPEG_Converter::jpeg_conv_error_t err = Jcu.encode(&buff_info, photo_data, (size_t *)photo_data_len, &encode_opt); 00084 if(err != JPEG_Converter::JPEG_CONV_OK) 00085 { 00086 return false; 00087 } 00088 return true; 00089 } 00090 00091 bool take_and_send_photo() { 00092 // Send photo data on button click 00093 uint32_t photo_data_len = sizeof(JpegBuffer); 00094 bool result = take_photo(JpegBuffer, &photo_data_len); 00095 if (result) { 00096 m2m_camera_capture_res->set_value((const uint8_t *)JpegBuffer, photo_data_len); 00097 } 00098 00099 return result; 00100 } 00101 00102 /* 00103 * Monitor the network connection. If the network is disconnected, LED4 on the board lights. 00104 */ 00105 void monitor() { 00106 static DigitalOut led(LED4, LED_OFF); 00107 nsapi_connection_status status = network->get_connection_status(); 00108 if(status != NSAPI_STATUS_GLOBAL_UP) { 00109 led = LED_ON; 00110 printf("Network is disconnected. Status = %d.\n", status); 00111 } else { 00112 led = LED_OFF; 00113 } 00114 } 00115 00116 00117 void print_client_ids(void) 00118 { 00119 printf("Account ID: %s\n", cloud_client->endpoint_info()->account_id.c_str()); 00120 printf("Endpoint name: %s\n", cloud_client->endpoint_info()->internal_endpoint_name.c_str()); 00121 printf("Device Id: %s\n\n", cloud_client->endpoint_info()->endpoint_name.c_str()); 00122 } 00123 00124 void button_press() { 00125 m2m_get_res->set_value(m2m_get_res->get_value_int() + 1); 00126 printf("User button clicked %d times\n", m2m_get_res->get_value_int()); 00127 00128 if(!take_and_send_photo()) { 00129 printf("Failed to send photo."); 00130 } 00131 } 00132 00133 void put_update(const char* /*object_name*/) 00134 { 00135 printf("Camera shutter triggered. %d\n", (int)m2m_put_res->get_value_int()); 00136 00137 if(!take_and_send_photo()) { 00138 printf("Failed to send photo."); 00139 } 00140 } 00141 00142 void execute_post(void* /*arguments*/) 00143 { 00144 printf("POST executed\n"); 00145 } 00146 00147 void deregister_client(void) 00148 { 00149 printf("Unregistering and disconnecting from the network.\n"); 00150 cloud_client->close(); 00151 } 00152 00153 void deregister(void* /*arguments*/) 00154 { 00155 printf("POST deregister executed\n"); 00156 m2m_deregister_res->send_delayed_post_response(); 00157 00158 deregister_client(); 00159 } 00160 00161 void client_registered(void) 00162 { 00163 printf("Client registered.\n"); 00164 print_client_ids(); 00165 // Turn on LED1 when device is registered. 00166 DigitalOut led(LED1, LED_ON); 00167 } 00168 00169 void client_unregistered(void) 00170 { 00171 printf("Client unregistered.\n"); 00172 (void) network->disconnect(); 00173 cloud_client_running = false; 00174 // Turn off LED1 when device is registered. 00175 DigitalOut led(LED1, LED_OFF); 00176 } 00177 00178 void client_error(int err) 00179 { 00180 printf("client_error(%d) -> %s\n", err, cloud_client->error_description()); 00181 } 00182 00183 void update_progress(uint32_t progress, uint32_t total) 00184 { 00185 uint8_t percent = (uint8_t)((uint64_t)progress * 100 / total); 00186 printf("Update progress = %" PRIu8 "%%\n", percent); 00187 } 00188 00189 int main(void) 00190 { 00191 int status; 00192 00193 status = mbed_trace_init(); 00194 if (status != 0) { 00195 printf("mbed_trace_init() failed with %d\n", status); 00196 return -1; 00197 } 00198 00199 // Mount default kvstore 00200 printf("Application ready\n"); 00201 status = kv_init_storage_config(); 00202 if (status != MBED_SUCCESS) { 00203 printf("kv_init_storage_config() - failed, status %d\n", status); 00204 return -1; 00205 } 00206 00207 // Connect with NetworkInterface 00208 printf("Connect to network\n"); 00209 network = NetworkInterface::get_default_instance(); 00210 if (network == NULL) { 00211 printf("Failed to get default NetworkInterface\n"); 00212 return -1; 00213 } 00214 status = network->connect(); 00215 if (status != NSAPI_ERROR_OK) { 00216 printf("NetworkInterface failed to connect with %d\n", status); 00217 // Turn on LED2 when the network initialization failed. 00218 DigitalOut led(LED2, LED_ON); 00219 return -1; 00220 } 00221 00222 printf("Network initialized, connected with IP %s\n\n", network->get_ip_address()); 00223 00224 // Run developer flow 00225 printf("Start developer flow\n"); 00226 status = fcc_init(); 00227 if (status != FCC_STATUS_SUCCESS) { 00228 printf("fcc_init() failed with %d\n", status); 00229 // Turn on LED3 when Pelion Client initialization failed. 00230 DigitalOut led(LED3, LED_ON); 00231 return -1; 00232 } 00233 00234 // Inject hardcoded entropy for the device. Suitable only for demo devices. 00235 (void) fcc_entropy_set(MBED_CLOUD_DEV_ENTROPY, sizeof(MBED_CLOUD_DEV_ENTROPY)); 00236 status = fcc_developer_flow(); 00237 if (status != FCC_STATUS_SUCCESS && status != FCC_STATUS_KCM_FILE_EXIST_ERROR && status != FCC_STATUS_CA_ERROR) { 00238 printf("fcc_developer_flow() failed with %d\n", status); 00239 // Turn on LED3 when Pelion Client initialization failed. 00240 DigitalOut led(LED3, LED_ON); 00241 return -1; 00242 } 00243 00244 printf("Create resources\n"); 00245 M2MObjectList m2m_obj_list; 00246 00247 // GET resource 3200/0/5501 00248 m2m_get_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3200, 0, 5501, M2MResourceInstance::INTEGER, M2MBase::GET_ALLOWED); 00249 if (m2m_get_res->set_value(0) != true) { 00250 printf("m2m_get_res->set_value() failed\n"); 00251 return -1; 00252 } 00253 00254 // PUT resource 3201/0/5853 (camera trigger resource) 00255 m2m_put_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3201, 0, 5853, M2MResourceInstance::INTEGER, M2MBase::GET_PUT_ALLOWED); 00256 if (m2m_put_res->set_value(0) != true) { 00257 printf("m2m_led_res->set_value() failed\n"); 00258 return -1; 00259 } 00260 if (m2m_put_res->set_value_updated_function(put_update) != true) { 00261 printf("m2m_put_res->set_value_updated_function() failed\n"); 00262 return -1; 00263 } 00264 00265 // POST resource 3201/0/5850 00266 m2m_post_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3201, 0, 5850, M2MResourceInstance::INTEGER, M2MBase::POST_ALLOWED); 00267 if (m2m_post_res->set_execute_function(execute_post) != true) { 00268 printf("m2m_post_res->set_execute_function() failed\n"); 00269 return -1; 00270 } 00271 00272 // POST resource 5000/0/1 to trigger deregister. 00273 m2m_deregister_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 5000, 0, 1, M2MResourceInstance::INTEGER, M2MBase::POST_ALLOWED); 00274 00275 // Use delayed response 00276 m2m_deregister_res->set_delayed_response(true); 00277 00278 if (m2m_deregister_res->set_execute_function(deregister) != true) { 00279 printf("m2m_post_res->set_execute_function() failed\n"); 00280 return -1; 00281 } 00282 00283 // Camera capture resource 3200/0/4014 00284 m2m_camera_capture_res = M2MInterfaceFactory::create_resource(m2m_obj_list, 3200, 0, 4014, M2MResourceInstance::STRING, M2MBase::GET_ALLOWED); 00285 if(m2m_camera_capture_res->set_value(0) != true) { 00286 printf("m2m_camera_capture_res->set_value() failed.\n"); 00287 return -1; 00288 } 00289 00290 // Camera start 00291 EasyAttach_Init(Display); 00292 Display.Video_Write_Setting( 00293 DisplayBase::VIDEO_INPUT_CHANNEL_0, 00294 DisplayBase::COL_SYS_NTSC_358, 00295 (void *)user_frame_buffer0, 00296 FRAME_BUFFER_STRIDE, 00297 DisplayBase::VIDEO_FORMAT_YCBCR422, 00298 DisplayBase::WR_RD_WRSWA_32_16BIT, 00299 VIDEO_PIXEL_VW, 00300 VIDEO_PIXEL_HW 00301 ); 00302 EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0); 00303 00304 // Jpeg setting 00305 Jcu.SetQuality(JPEG_ENCODE_QUALITY); 00306 00307 00308 printf("Register Pelion Device Management Client\n\n"); 00309 cloud_client = new MbedCloudClient(client_registered, client_unregistered, client_error, NULL, update_progress); 00310 cloud_client->add_objects(m2m_obj_list); 00311 cloud_client->setup(network); // cloud_client->setup(NULL); -- https://jira.arm.com/browse/IOTCLT-3114 00312 00313 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads) 00314 // This is great because things such as network operations are illegal in ISR, so updating a resource in a button's fall() function is not allowed 00315 EventQueue eventQueue; 00316 Thread t; 00317 // Start the event queue 00318 t.start(callback(&eventQueue, &EventQueue::dispatch_forever)); 00319 00320 // Setup the button 00321 InterruptIn btn(USER_BUTTON0); 00322 btn.mode(PullUp); 00323 00324 // The button fall handler is placed in the event queue so it will run in 00325 // thread context instead of ISR context, which allows safely updating the cloud resource 00326 btn.fall(eventQueue.event(&button_press)); 00327 00328 // Monitor the network connection periodically. 00329 Ticker ticker; 00330 ticker.attach(eventQueue.event(&monitor), 5.0); // second param is period in seconds 00331 00332 while(cloud_client_running) { 00333 int in_char = getchar(); 00334 if (in_char == 'i') { 00335 print_client_ids(); // When 'i' is pressed, print endpoint info 00336 continue; 00337 } else if (in_char == 'r') { 00338 (void) fcc_storage_delete(); // When 'r' is pressed, erase storage and reboot the board. 00339 printf("Storage erased, rebooting the device.\n\n"); 00340 wait_us(1000000); 00341 NVIC_SystemReset(); 00342 } else if (in_char > 0 && in_char != 0x03) { // Ctrl+C is 0x03 in Mbed OS and Linux returns negative number 00343 button_press(); // Simulate button press 00344 continue; 00345 } 00346 deregister_client(); 00347 break; 00348 } 00349 return 0; 00350 } 00351 00352 #endif /* MBED_TEST_MODE */
Generated on Sat Jul 16 2022 09:47:17 by
1.7.2