Generic Pelion Device Management example for various Renesas-based boards. Add camera function.
Base software : https://os.mbed.com/teams/Renesas/code/pelion-example-common/
This example is known to work great on the following platforms:
- Renesas GR-LCYHEE over Wi-Fi and using SD card.
Example functionality
This example showcases the following device functionality:
- On user button click, increment Pelion LWM2M button resource.
- Allow the user to change the state of the board LED from Pelion LWM2M led_state resource and PUT request.
- On user button click, update Pelion LWM2M camera_img resource.
Camera image resource
- "5000/0/1", "camera_img", GET : Get the last saved camera image
- "5000/0/3", "camera_action", POST : Save camera image
Revision 4:8c3ca488d38c, committed 2019-02-14
- Comitter:
- dkato
- Date:
- Thu Feb 14 08:23:41 2019 +0000
- Parent:
- 3:c8de11b0ce7c
- Commit message:
- Add camera function
Changed in this revision
--- a/drivers/network/esp32-driver.lib Wed Dec 26 12:33:36 2018 +0900 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -https://github.com/d-kato/esp32-driver/#fd159f64c1e2394d9c9add7403b48ee965342dc0 \ No newline at end of file
--- a/main.cpp Wed Dec 26 12:33:36 2018 +0900 +++ b/main.cpp Thu Feb 14 08:23:41 2019 +0000 @@ -20,6 +20,30 @@ #include "mbed.h" #include "simple-mbed-cloud-client.h" #include "FATFileSystem.h" +#include "EasyAttach_CameraAndLCD.h" +#include "dcache-control.h" +#include "JPEG_Converter.h" + +/**** User Selection *********/ +#define VIDEO_PIXEL_HW (320u) /* QVGA */ +#define VIDEO_PIXEL_VW (240u) /* QVGA */ +#define JPEG_ENCODE_QUALITY (75) /* JPEG encode quality (min:1, max:75 (Considering the size of JpegBuffer, about 75 is the upper limit.)) */ +/*****************************/ + +#define DATA_SIZE_PER_PIC (2u) +#define FRAME_BUFFER_STRIDE (((VIDEO_PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u) +#define FRAME_BUFFER_HEIGHT (VIDEO_PIXEL_VW) + +#if defined(__ICCARM__) +#pragma data_alignment=32 +static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]; +#pragma data_alignment=32 +static uint8_t JpegBuffer[1024 * 32]; +#else +static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((aligned(32))); +static uint8_t JpegBuffer[1024 * 32]__attribute((aligned(32))); +#endif +static DisplayBase Display; // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads) // 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 @@ -37,12 +61,62 @@ MbedCloudClientResource *button_res; MbedCloudClientResource *pattern_res; +Thread jpegTask(osPriorityNormal, 1024 * 4); + +void save_camera_image_req(void) { + jpegTask.flags_set(1); +} + +void jpeg_task(MbedCloudClientResource *resource) { + M2MResource *m2m_camera_img_res = resource->get_m2m_resource(); + JPEG_Converter Jcu; + JPEG_Converter::bitmap_buff_info_t buff_info; + JPEG_Converter::encode_options_t encode_opt; + size_t encode_size; + + // Camera start + EasyAttach_Init(Display); + Display.Video_Write_Setting( + DisplayBase::VIDEO_INPUT_CHANNEL_0, + DisplayBase::COL_SYS_NTSC_358, + (void *)user_frame_buffer0, + FRAME_BUFFER_STRIDE, + DisplayBase::VIDEO_FORMAT_YCBCR422, + DisplayBase::WR_RD_WRSWA_32_16BIT, + VIDEO_PIXEL_VW, + VIDEO_PIXEL_HW + ); + EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0); + + // Jpeg setting + buff_info.width = VIDEO_PIXEL_HW; + buff_info.height = VIDEO_PIXEL_VW; + buff_info.format = JPEG_Converter::WR_RD_YCbCr422; + buff_info.buffer_address = (void *)user_frame_buffer0; + encode_opt.encode_buff_size = sizeof(JpegBuffer); + encode_opt.input_swapsetting = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT; + Jcu.SetQuality(JPEG_ENCODE_QUALITY); + + while (true) { + ThisThread::flags_wait_all(1); + dcache_invalid(JpegBuffer, sizeof(JpegBuffer)); + if (Jcu.encode(&buff_info, JpegBuffer, &encode_size, &encode_opt) == JPEG_Converter::JPEG_CONV_OK) { + m2m_camera_img_res->set_value(JpegBuffer, encode_size); + printf("Camera image update: %dbyte\n", encode_size); + } else { + printf("Jpeg convert error\n"); + } + } +} + void button_press() { int v = button_res->get_value_int() + 1; button_res->set_value(v); printf("User button clicked %d times\n", v); + + save_camera_image_req(); } /** @@ -84,6 +158,12 @@ } } +void camera_action_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) { + printf("POST received. Going to camera action\n"); + + save_camera_image_req(); +} + /** * Notification callback handler * @param resource The resource that triggered the callback @@ -93,6 +173,10 @@ printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status); } +void camera_img_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) { + printf("Camera image notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status); +} + /** * Registration callback handler * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal) @@ -139,6 +223,16 @@ blink_res->methods(M2MMethod::POST); blink_res->attach_post_callback(blink_callback); + MbedCloudClientResource *camera_img_res = client.create_resource("5000/0/1", "camera_img"); + camera_img_res->set_value(0); + camera_img_res->methods(M2MMethod::GET); + camera_img_res->observable(true); + camera_img_res->attach_notification_callback(camera_img_callback); + + MbedCloudClientResource *camera_action_res = client.create_resource("5000/0/3", "camera_action"); + camera_action_res->methods(M2MMethod::POST); + camera_action_res->attach_post_callback(camera_action_callback); + printf("Initialized Pelion Client. Registering...\n"); // Callback that fires when registering is complete @@ -154,6 +248,9 @@ // thread context instead of ISR context, which allows safely updating the cloud resource btn.fall(eventQueue.event(&button_press)); + // Start jpeg task + jpegTask.start(callback(jpeg_task, camera_img_res)); + // You can easily run the eventQueue in a separate thread if required eventQueue.dispatch_forever(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-gr-libs.lib Thu Feb 14 08:23:41 2019 +0000 @@ -0,0 +1,1 @@ +https://github.com/d-kato/mbed-gr-libs/#4c7f9d76507a6e1c52a04866e1a2dce6b5323e67
--- a/mbed_app.json Wed Dec 26 12:33:36 2018 +0900 +++ b/mbed_app.json Thu Feb 14 08:23:41 2019 +0000 @@ -9,6 +9,16 @@ "MBEDTLS_USER_CONFIG_FILE=\"mbedTLSConfig_mbedOS.h\"", "PAL_DTLS_PEER_MIN_TIMEOUT=5000" ], + "config": { + "camera":{ + "help": "0:disable 1:enable", + "value": "1" + }, + "camera-type":{ + "help": "Please see EasyAttach_CameraAndLCD/README.md", + "value": null + } + }, "target_overrides": { "*": { "platform.stdio-baud-rate" : 115200, @@ -18,8 +28,8 @@ "update-client.storage-locations" : "1", "mbed-trace.enable" : null, "nsapi.default-wifi-security" : "WPA_WPA2", - "nsapi.default-wifi-ssid" : "\"SSID\"", - "nsapi.default-wifi-password" : "\"PASSWORD\"" + "nsapi.default-wifi-ssid" : "\"iPhone DK\"", + "nsapi.default-wifi-password" : "\"eolith4467\"" }, "RZ_A1H": { "target.features_add" : ["BOOTLOADER"],