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"],