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
Committer:
dkato
Date:
Thu Feb 14 08:23:41 2019 +0000
Revision:
4:8c3ca488d38c
Parent:
0:6d2053b84a92
Add camera function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MACRUM 0:6d2053b84a92 1 // ----------------------------------------------------------------------------
MACRUM 0:6d2053b84a92 2 // Copyright 2016-2018 ARM Ltd.
MACRUM 0:6d2053b84a92 3 //
MACRUM 0:6d2053b84a92 4 // SPDX-License-Identifier: Apache-2.0
MACRUM 0:6d2053b84a92 5 //
MACRUM 0:6d2053b84a92 6 // Licensed under the Apache License, Version 2.0 (the "License");
MACRUM 0:6d2053b84a92 7 // you may not use this file except in compliance with the License.
MACRUM 0:6d2053b84a92 8 // You may obtain a copy of the License at
MACRUM 0:6d2053b84a92 9 //
MACRUM 0:6d2053b84a92 10 // http://www.apache.org/licenses/LICENSE-2.0
MACRUM 0:6d2053b84a92 11 //
MACRUM 0:6d2053b84a92 12 // Unless required by applicable law or agreed to in writing, software
MACRUM 0:6d2053b84a92 13 // distributed under the License is distributed on an "AS IS" BASIS,
MACRUM 0:6d2053b84a92 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
MACRUM 0:6d2053b84a92 15 // See the License for the specific language governing permissions and
MACRUM 0:6d2053b84a92 16 // limitations under the License.
MACRUM 0:6d2053b84a92 17 // ----------------------------------------------------------------------------
MACRUM 0:6d2053b84a92 18 #ifndef MBED_TEST_MODE
MACRUM 0:6d2053b84a92 19
MACRUM 0:6d2053b84a92 20 #include "mbed.h"
MACRUM 0:6d2053b84a92 21 #include "simple-mbed-cloud-client.h"
MACRUM 0:6d2053b84a92 22 #include "FATFileSystem.h"
dkato 4:8c3ca488d38c 23 #include "EasyAttach_CameraAndLCD.h"
dkato 4:8c3ca488d38c 24 #include "dcache-control.h"
dkato 4:8c3ca488d38c 25 #include "JPEG_Converter.h"
dkato 4:8c3ca488d38c 26
dkato 4:8c3ca488d38c 27 /**** User Selection *********/
dkato 4:8c3ca488d38c 28 #define VIDEO_PIXEL_HW (320u) /* QVGA */
dkato 4:8c3ca488d38c 29 #define VIDEO_PIXEL_VW (240u) /* QVGA */
dkato 4:8c3ca488d38c 30 #define JPEG_ENCODE_QUALITY (75) /* JPEG encode quality (min:1, max:75 (Considering the size of JpegBuffer, about 75 is the upper limit.)) */
dkato 4:8c3ca488d38c 31 /*****************************/
dkato 4:8c3ca488d38c 32
dkato 4:8c3ca488d38c 33 #define DATA_SIZE_PER_PIC (2u)
dkato 4:8c3ca488d38c 34 #define FRAME_BUFFER_STRIDE (((VIDEO_PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u)
dkato 4:8c3ca488d38c 35 #define FRAME_BUFFER_HEIGHT (VIDEO_PIXEL_VW)
dkato 4:8c3ca488d38c 36
dkato 4:8c3ca488d38c 37 #if defined(__ICCARM__)
dkato 4:8c3ca488d38c 38 #pragma data_alignment=32
dkato 4:8c3ca488d38c 39 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT];
dkato 4:8c3ca488d38c 40 #pragma data_alignment=32
dkato 4:8c3ca488d38c 41 static uint8_t JpegBuffer[1024 * 32];
dkato 4:8c3ca488d38c 42 #else
dkato 4:8c3ca488d38c 43 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((aligned(32)));
dkato 4:8c3ca488d38c 44 static uint8_t JpegBuffer[1024 * 32]__attribute((aligned(32)));
dkato 4:8c3ca488d38c 45 #endif
dkato 4:8c3ca488d38c 46 static DisplayBase Display;
MACRUM 0:6d2053b84a92 47
MACRUM 0:6d2053b84a92 48 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
MACRUM 0:6d2053b84a92 49 // 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
MACRUM 0:6d2053b84a92 50 EventQueue eventQueue;
MACRUM 0:6d2053b84a92 51
MACRUM 0:6d2053b84a92 52 // Default block device
MACRUM 0:6d2053b84a92 53 BlockDevice *bd = BlockDevice::get_default_instance();
MACRUM 0:6d2053b84a92 54 FATFileSystem fs("fs");
MACRUM 0:6d2053b84a92 55
MACRUM 0:6d2053b84a92 56 // Default network interface object
MACRUM 0:6d2053b84a92 57 NetworkInterface *net = NetworkInterface::get_default_instance();
MACRUM 0:6d2053b84a92 58
MACRUM 0:6d2053b84a92 59 InterruptIn btn(USER_BUTTON0);
MACRUM 0:6d2053b84a92 60 // Declaring pointers for access to Pelion Device Management Client resources outside of main()
MACRUM 0:6d2053b84a92 61 MbedCloudClientResource *button_res;
MACRUM 0:6d2053b84a92 62 MbedCloudClientResource *pattern_res;
MACRUM 0:6d2053b84a92 63
dkato 4:8c3ca488d38c 64 Thread jpegTask(osPriorityNormal, 1024 * 4);
dkato 4:8c3ca488d38c 65
dkato 4:8c3ca488d38c 66 void save_camera_image_req(void) {
dkato 4:8c3ca488d38c 67 jpegTask.flags_set(1);
dkato 4:8c3ca488d38c 68 }
dkato 4:8c3ca488d38c 69
dkato 4:8c3ca488d38c 70 void jpeg_task(MbedCloudClientResource *resource) {
dkato 4:8c3ca488d38c 71 M2MResource *m2m_camera_img_res = resource->get_m2m_resource();
dkato 4:8c3ca488d38c 72 JPEG_Converter Jcu;
dkato 4:8c3ca488d38c 73 JPEG_Converter::bitmap_buff_info_t buff_info;
dkato 4:8c3ca488d38c 74 JPEG_Converter::encode_options_t encode_opt;
dkato 4:8c3ca488d38c 75 size_t encode_size;
dkato 4:8c3ca488d38c 76
dkato 4:8c3ca488d38c 77 // Camera start
dkato 4:8c3ca488d38c 78 EasyAttach_Init(Display);
dkato 4:8c3ca488d38c 79 Display.Video_Write_Setting(
dkato 4:8c3ca488d38c 80 DisplayBase::VIDEO_INPUT_CHANNEL_0,
dkato 4:8c3ca488d38c 81 DisplayBase::COL_SYS_NTSC_358,
dkato 4:8c3ca488d38c 82 (void *)user_frame_buffer0,
dkato 4:8c3ca488d38c 83 FRAME_BUFFER_STRIDE,
dkato 4:8c3ca488d38c 84 DisplayBase::VIDEO_FORMAT_YCBCR422,
dkato 4:8c3ca488d38c 85 DisplayBase::WR_RD_WRSWA_32_16BIT,
dkato 4:8c3ca488d38c 86 VIDEO_PIXEL_VW,
dkato 4:8c3ca488d38c 87 VIDEO_PIXEL_HW
dkato 4:8c3ca488d38c 88 );
dkato 4:8c3ca488d38c 89 EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0);
dkato 4:8c3ca488d38c 90
dkato 4:8c3ca488d38c 91 // Jpeg setting
dkato 4:8c3ca488d38c 92 buff_info.width = VIDEO_PIXEL_HW;
dkato 4:8c3ca488d38c 93 buff_info.height = VIDEO_PIXEL_VW;
dkato 4:8c3ca488d38c 94 buff_info.format = JPEG_Converter::WR_RD_YCbCr422;
dkato 4:8c3ca488d38c 95 buff_info.buffer_address = (void *)user_frame_buffer0;
dkato 4:8c3ca488d38c 96 encode_opt.encode_buff_size = sizeof(JpegBuffer);
dkato 4:8c3ca488d38c 97 encode_opt.input_swapsetting = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT;
dkato 4:8c3ca488d38c 98 Jcu.SetQuality(JPEG_ENCODE_QUALITY);
dkato 4:8c3ca488d38c 99
dkato 4:8c3ca488d38c 100 while (true) {
dkato 4:8c3ca488d38c 101 ThisThread::flags_wait_all(1);
dkato 4:8c3ca488d38c 102 dcache_invalid(JpegBuffer, sizeof(JpegBuffer));
dkato 4:8c3ca488d38c 103 if (Jcu.encode(&buff_info, JpegBuffer, &encode_size, &encode_opt) == JPEG_Converter::JPEG_CONV_OK) {
dkato 4:8c3ca488d38c 104 m2m_camera_img_res->set_value(JpegBuffer, encode_size);
dkato 4:8c3ca488d38c 105 printf("Camera image update: %dbyte\n", encode_size);
dkato 4:8c3ca488d38c 106 } else {
dkato 4:8c3ca488d38c 107 printf("Jpeg convert error\n");
dkato 4:8c3ca488d38c 108 }
dkato 4:8c3ca488d38c 109 }
dkato 4:8c3ca488d38c 110 }
dkato 4:8c3ca488d38c 111
MACRUM 0:6d2053b84a92 112 void button_press() {
MACRUM 0:6d2053b84a92 113 int v = button_res->get_value_int() + 1;
MACRUM 0:6d2053b84a92 114
MACRUM 0:6d2053b84a92 115 button_res->set_value(v);
MACRUM 0:6d2053b84a92 116
MACRUM 0:6d2053b84a92 117 printf("User button clicked %d times\n", v);
dkato 4:8c3ca488d38c 118
dkato 4:8c3ca488d38c 119 save_camera_image_req();
MACRUM 0:6d2053b84a92 120 }
MACRUM 0:6d2053b84a92 121
MACRUM 0:6d2053b84a92 122 /**
MACRUM 0:6d2053b84a92 123 * PUT handler
MACRUM 0:6d2053b84a92 124 * @param resource The resource that triggered the callback
MACRUM 0:6d2053b84a92 125 * @param newValue Updated value for the resource
MACRUM 0:6d2053b84a92 126 */
MACRUM 0:6d2053b84a92 127 void pattern_updated(MbedCloudClientResource *resource, m2m::String newValue) {
MACRUM 0:6d2053b84a92 128 printf("PUT received, new value: %s\n", newValue.c_str());
MACRUM 0:6d2053b84a92 129 }
MACRUM 0:6d2053b84a92 130
MACRUM 0:6d2053b84a92 131 /**
MACRUM 0:6d2053b84a92 132 * POST handler
MACRUM 0:6d2053b84a92 133 * @param resource The resource that triggered the callback
MACRUM 0:6d2053b84a92 134 * @param buffer If a body was passed to the POST function, this contains the data.
MACRUM 0:6d2053b84a92 135 * Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
MACRUM 0:6d2053b84a92 136 * @param size Size of the body
MACRUM 0:6d2053b84a92 137 */
MACRUM 0:6d2053b84a92 138 void blink_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
MACRUM 0:6d2053b84a92 139 printf("POST received. Going to blink LED pattern: %s\n", pattern_res->get_value().c_str());
MACRUM 0:6d2053b84a92 140
MACRUM 0:6d2053b84a92 141 static DigitalOut augmentedLed(LED1); // LED that is used for blinking the pattern
MACRUM 0:6d2053b84a92 142
MACRUM 0:6d2053b84a92 143 // Parse the pattern string, and toggle the LED in that pattern
MACRUM 0:6d2053b84a92 144 string s = std::string(pattern_res->get_value().c_str());
MACRUM 0:6d2053b84a92 145 size_t i = 0;
MACRUM 0:6d2053b84a92 146 size_t pos = s.find(':');
MACRUM 0:6d2053b84a92 147 while (pos != string::npos) {
MACRUM 0:6d2053b84a92 148 wait_ms(atoi(s.substr(i, pos - i).c_str()));
MACRUM 0:6d2053b84a92 149 augmentedLed = !augmentedLed;
MACRUM 0:6d2053b84a92 150
MACRUM 0:6d2053b84a92 151 i = ++pos;
MACRUM 0:6d2053b84a92 152 pos = s.find(':', pos);
MACRUM 0:6d2053b84a92 153
MACRUM 0:6d2053b84a92 154 if (pos == string::npos) {
MACRUM 0:6d2053b84a92 155 wait_ms(atoi(s.substr(i, s.length()).c_str()));
MACRUM 0:6d2053b84a92 156 augmentedLed = !augmentedLed;
MACRUM 0:6d2053b84a92 157 }
MACRUM 0:6d2053b84a92 158 }
MACRUM 0:6d2053b84a92 159 }
MACRUM 0:6d2053b84a92 160
dkato 4:8c3ca488d38c 161 void camera_action_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
dkato 4:8c3ca488d38c 162 printf("POST received. Going to camera action\n");
dkato 4:8c3ca488d38c 163
dkato 4:8c3ca488d38c 164 save_camera_image_req();
dkato 4:8c3ca488d38c 165 }
dkato 4:8c3ca488d38c 166
MACRUM 0:6d2053b84a92 167 /**
MACRUM 0:6d2053b84a92 168 * Notification callback handler
MACRUM 0:6d2053b84a92 169 * @param resource The resource that triggered the callback
MACRUM 0:6d2053b84a92 170 * @param status The delivery status of the notification
MACRUM 0:6d2053b84a92 171 */
MACRUM 0:6d2053b84a92 172 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
MACRUM 0:6d2053b84a92 173 printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
MACRUM 0:6d2053b84a92 174 }
MACRUM 0:6d2053b84a92 175
dkato 4:8c3ca488d38c 176 void camera_img_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
dkato 4:8c3ca488d38c 177 printf("Camera image notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
dkato 4:8c3ca488d38c 178 }
dkato 4:8c3ca488d38c 179
MACRUM 0:6d2053b84a92 180 /**
MACRUM 0:6d2053b84a92 181 * Registration callback handler
MACRUM 0:6d2053b84a92 182 * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
MACRUM 0:6d2053b84a92 183 */
MACRUM 0:6d2053b84a92 184 void registered(const ConnectorClientEndpointInfo *endpoint) {
MACRUM 0:6d2053b84a92 185 printf("Connected to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
MACRUM 0:6d2053b84a92 186 }
MACRUM 0:6d2053b84a92 187
MACRUM 0:6d2053b84a92 188 int main(void) {
MACRUM 0:6d2053b84a92 189 printf("Starting Simple Pelion Device Management Client example\n");
MACRUM 0:6d2053b84a92 190 printf("Connecting to the network...\n");
MACRUM 0:6d2053b84a92 191
MACRUM 0:6d2053b84a92 192 // Connect to the internet (DHCP is expected to be on)
MACRUM 0:6d2053b84a92 193 nsapi_error_t status = net->connect();
MACRUM 0:6d2053b84a92 194
MACRUM 0:6d2053b84a92 195 if (status != NSAPI_ERROR_OK) {
MACRUM 0:6d2053b84a92 196 printf("Connecting to the network failed %d!\n", status);
MACRUM 0:6d2053b84a92 197 return -1;
MACRUM 0:6d2053b84a92 198 }
MACRUM 0:6d2053b84a92 199
MACRUM 0:6d2053b84a92 200 printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
MACRUM 0:6d2053b84a92 201
MACRUM 0:6d2053b84a92 202 // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
MACRUM 0:6d2053b84a92 203 SimpleMbedCloudClient client(net, bd, &fs);
MACRUM 0:6d2053b84a92 204 int client_status = client.init();
MACRUM 0:6d2053b84a92 205 if (client_status != 0) {
MACRUM 0:6d2053b84a92 206 printf("Pelion Client initialization failed (%d)\n", client_status);
MACRUM 0:6d2053b84a92 207 return -1;
MACRUM 0:6d2053b84a92 208 }
MACRUM 0:6d2053b84a92 209
MACRUM 0:6d2053b84a92 210 // Creating resources, which can be written or read from the cloud
MACRUM 0:6d2053b84a92 211 button_res = client.create_resource("3200/0/5501", "button_count");
MACRUM 0:6d2053b84a92 212 button_res->set_value(0);
MACRUM 0:6d2053b84a92 213 button_res->methods(M2MMethod::GET);
MACRUM 0:6d2053b84a92 214 button_res->observable(true);
MACRUM 0:6d2053b84a92 215 button_res->attach_notification_callback(button_callback);
MACRUM 0:6d2053b84a92 216
MACRUM 0:6d2053b84a92 217 pattern_res = client.create_resource("3201/0/5853", "blink_pattern");
MACRUM 0:6d2053b84a92 218 pattern_res->set_value("500:500:500:500:500:500:500:500");
MACRUM 0:6d2053b84a92 219 pattern_res->methods(M2MMethod::GET | M2MMethod::PUT);
MACRUM 0:6d2053b84a92 220 pattern_res->attach_put_callback(pattern_updated);
MACRUM 0:6d2053b84a92 221
MACRUM 0:6d2053b84a92 222 MbedCloudClientResource *blink_res = client.create_resource("3201/0/5850", "blink_action");
MACRUM 0:6d2053b84a92 223 blink_res->methods(M2MMethod::POST);
MACRUM 0:6d2053b84a92 224 blink_res->attach_post_callback(blink_callback);
MACRUM 0:6d2053b84a92 225
dkato 4:8c3ca488d38c 226 MbedCloudClientResource *camera_img_res = client.create_resource("5000/0/1", "camera_img");
dkato 4:8c3ca488d38c 227 camera_img_res->set_value(0);
dkato 4:8c3ca488d38c 228 camera_img_res->methods(M2MMethod::GET);
dkato 4:8c3ca488d38c 229 camera_img_res->observable(true);
dkato 4:8c3ca488d38c 230 camera_img_res->attach_notification_callback(camera_img_callback);
dkato 4:8c3ca488d38c 231
dkato 4:8c3ca488d38c 232 MbedCloudClientResource *camera_action_res = client.create_resource("5000/0/3", "camera_action");
dkato 4:8c3ca488d38c 233 camera_action_res->methods(M2MMethod::POST);
dkato 4:8c3ca488d38c 234 camera_action_res->attach_post_callback(camera_action_callback);
dkato 4:8c3ca488d38c 235
MACRUM 0:6d2053b84a92 236 printf("Initialized Pelion Client. Registering...\n");
MACRUM 0:6d2053b84a92 237
MACRUM 0:6d2053b84a92 238 // Callback that fires when registering is complete
MACRUM 0:6d2053b84a92 239 client.on_registered(&registered);
MACRUM 0:6d2053b84a92 240
MACRUM 0:6d2053b84a92 241 // Register with Pelion Device Management
MACRUM 0:6d2053b84a92 242 client.register_and_connect();
MACRUM 0:6d2053b84a92 243
MACRUM 0:6d2053b84a92 244 // Setup the button
MACRUM 0:6d2053b84a92 245 btn.mode(PullUp);
MACRUM 0:6d2053b84a92 246
MACRUM 0:6d2053b84a92 247 // The button fall handler is placed in the event queue so it will run in
MACRUM 0:6d2053b84a92 248 // thread context instead of ISR context, which allows safely updating the cloud resource
MACRUM 0:6d2053b84a92 249 btn.fall(eventQueue.event(&button_press));
MACRUM 0:6d2053b84a92 250
dkato 4:8c3ca488d38c 251 // Start jpeg task
dkato 4:8c3ca488d38c 252 jpegTask.start(callback(jpeg_task, camera_img_res));
dkato 4:8c3ca488d38c 253
MACRUM 0:6d2053b84a92 254 // You can easily run the eventQueue in a separate thread if required
MACRUM 0:6d2053b84a92 255 eventQueue.dispatch_forever();
MACRUM 0:6d2053b84a92 256 }
MACRUM 0:6d2053b84a92 257 #endif