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:

https://os.mbed.com/media/cache/platforms/GR-LYCHEE_and_cam.png.250x250_q85.png

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

Files at this revision

API Documentation at this revision

Comitter:
dkato
Date:
Thu Feb 14 08:23:41 2019 +0000
Parent:
3:c8de11b0ce7c
Commit message:
Add camera function

Changed in this revision

drivers/network/esp32-driver.lib Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-gr-libs.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
--- 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"],