Pelion test

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2018 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 
00020 #include "mbed.h"
00021 #include "simple-mbed-cloud-client.h"
00022 #include "FATFileSystem.h"
00023 #include "EasyAttach_CameraAndLCD.h"
00024 #include "dcache-control.h"
00025 #include "JPEG_Converter.h"
00026 
00027 /**** User Selection *********/
00028 #define VIDEO_PIXEL_HW         (320u)  /* QVGA */
00029 #define VIDEO_PIXEL_VW         (240u)  /* QVGA */
00030 #define JPEG_ENCODE_QUALITY    (75)    /* JPEG encode quality (min:1, max:75 (Considering the size of JpegBuffer, about 75 is the upper limit.)) */
00031 /*****************************/
00032 
00033 #define DATA_SIZE_PER_PIC      (2u)
00034 #define FRAME_BUFFER_STRIDE    (((VIDEO_PIXEL_HW * DATA_SIZE_PER_PIC) + 31u) & ~31u)
00035 #define FRAME_BUFFER_HEIGHT    (VIDEO_PIXEL_VW)
00036 
00037 uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((aligned(32)));
00038 uint8_t JpegBuffer[1024 * 32]__attribute((aligned(32)));
00039 DisplayBase Display;
00040 JPEG_Converter Jcu;
00041 
00042 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
00043 // 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
00044 EventQueue eventQueue;
00045 
00046 // Default block device
00047 BlockDevice *bd = BlockDevice::get_default_instance();
00048 FATFileSystem fs("fs");
00049 
00050 // Default network interface object
00051 NetworkInterface *net = NetworkInterface::get_default_instance();
00052 
00053 InterruptIn btn(USER_BUTTON0);
00054 // Declaring pointers for access to Pelion Device Management Client resources outside of main()
00055 MbedCloudClientResource *button_res;
00056 MbedCloudClientResource *pattern_res;
00057 MbedCloudClientResource *res_camera_capture;
00058 
00059 bool take_photo(uint8_t *photo_data, uint32_t *photo_data_len) {
00060     JPEG_Converter::bitmap_buff_info_t buff_info;
00061     JPEG_Converter::encode_options_t   encode_opt;
00062 
00063     if ((photo_data == NULL) || (photo_data_len == NULL)) {
00064         return false;
00065     }
00066 
00067     // Jpeg setting
00068     buff_info.width              = VIDEO_PIXEL_HW;
00069     buff_info.height             = VIDEO_PIXEL_VW;
00070     buff_info.format             = JPEG_Converter::WR_RD_YCbCr422;
00071     buff_info.buffer_address     = (void *)user_frame_buffer0;
00072     encode_opt.encode_buff_size  = *photo_data_len;
00073     encode_opt.input_swapsetting = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT;
00074 
00075     dcache_invalid(photo_data, *photo_data_len);
00076     if (Jcu.encode(&buff_info, photo_data, photo_data_len, &encode_opt) != JPEG_Converter::JPEG_CONV_OK) {
00077         return false;
00078     }
00079 
00080     return true;
00081 }
00082 
00083 void button_press() {
00084     int v = button_res->get_value_int() + 1;
00085 
00086     button_res->set_value(v);
00087 
00088     printf("User button clicked %d times\n", v);
00089 
00090     // Send photo data on button click
00091     M2MResource* m2m_res = res_camera_capture->get_m2m_resource();
00092     uint32_t photo_data_len = sizeof(JpegBuffer);
00093     if (take_photo(JpegBuffer, &photo_data_len) != false) {
00094         m2m_res->set_value((const uint8_t *)JpegBuffer, photo_data_len);
00095     }
00096 }
00097 
00098 void res_camera_capture_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status)
00099 {
00100     printf("camera notification, status: %s (%d)\n", 
00101         MbedCloudClientResource::delivery_status_to_string(status), status);
00102 }
00103 
00104 /**
00105  * PUT handler
00106  * @param resource The resource that triggered the callback
00107  * @param newValue Updated value for the resource
00108  */
00109 void pattern_updated(MbedCloudClientResource *resource, m2m::String newValue) {
00110     printf("PUT received, new value: %s\n", newValue.c_str());
00111 }
00112 
00113 /**
00114  * POST handler
00115  * @param resource The resource that triggered the callback
00116  * @param buffer If a body was passed to the POST function, this contains the data.
00117  *               Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
00118  * @param size Size of the body
00119  */
00120 void camera_trigger_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
00121     printf("POST received. Camera takes a picture.", pattern_res->get_value().c_str());
00122     M2MResource* m2m_res = res_camera_capture->get_m2m_resource();
00123     uint32_t photo_data_len = sizeof(JpegBuffer);
00124     if (take_photo(JpegBuffer, &photo_data_len) != false) {
00125         m2m_res->set_value((const uint8_t *)JpegBuffer, photo_data_len);
00126     }
00127 }
00128 
00129 /**
00130  * Notification callback handler
00131  * @param resource The resource that triggered the callback
00132  * @param status The delivery status of the notification
00133  */
00134 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
00135     printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
00136 }
00137 
00138 /**
00139  * Registration callback handler
00140  * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
00141  */
00142 void registered(const ConnectorClientEndpointInfo *endpoint) {
00143     printf("Connected to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
00144     // Once registered, send default photo.
00145     M2MResource* m2m_res = res_camera_capture->get_m2m_resource();
00146     uint32_t photo_data_len = sizeof(JpegBuffer);
00147     if (take_photo(JpegBuffer, &photo_data_len) != false) {
00148         m2m_res->set_value((const uint8_t *)JpegBuffer, photo_data_len);
00149     }
00150 }
00151 
00152 int main(void) {
00153     printf("Starting Simple Pelion Device Management Client example\n");
00154     printf("Connecting to the network...\n");
00155 
00156     // Connect to the internet (DHCP is expected to be on)
00157     nsapi_error_t status = net->connect();
00158 
00159     if (status != NSAPI_ERROR_OK) {
00160         printf("Connecting to the network failed %d!\n", status);
00161         return -1;
00162     }
00163 
00164     printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
00165 
00166     // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
00167     SimpleMbedCloudClient client(net, bd, &fs);
00168     int client_status = client.init();
00169     if (client_status != 0) {
00170         printf("Pelion Client initialization failed (%d)\n", client_status);
00171         return -1;
00172     }
00173 
00174     // Creating resources, which can be written or read from the cloud
00175     button_res = client.create_resource("3200/0/5501", "button_count");
00176     button_res->set_value(0);
00177     button_res->methods(M2MMethod::GET);
00178     button_res->observable(true);
00179     button_res->attach_notification_callback(button_callback);
00180 
00181     pattern_res = client.create_resource("3201/0/5853", "blink_pattern");
00182     pattern_res->set_value("500:500:500:500:500:500:500:500");
00183     pattern_res->methods(M2MMethod::GET | M2MMethod::PUT);
00184     pattern_res->attach_put_callback(pattern_updated);
00185 
00186     res_camera_capture = client.create_resource("3200/0/4014", "CameraCapture");
00187     res_camera_capture->set_value(0);
00188     res_camera_capture->methods(M2MMethod::GET);
00189     res_camera_capture->observable(true);
00190     res_camera_capture->attach_notification_callback(res_camera_capture_callback);
00191 
00192     MbedCloudClientResource *blink_res = client.create_resource("3201/0/5850", "blink_action");
00193     blink_res->methods(M2MMethod::POST);
00194     blink_res->attach_post_callback(camera_trigger_callback);
00195 
00196     printf("Initialized Pelion Client. Registering...\n");
00197 
00198     // Camera start
00199     EasyAttach_Init(Display);
00200     Display.Video_Write_Setting(
00201         DisplayBase::VIDEO_INPUT_CHANNEL_0,
00202         DisplayBase::COL_SYS_NTSC_358,
00203         (void *)user_frame_buffer0,
00204         FRAME_BUFFER_STRIDE,
00205         DisplayBase::VIDEO_FORMAT_YCBCR422,
00206         DisplayBase::WR_RD_WRSWA_32_16BIT,
00207         VIDEO_PIXEL_VW,
00208         VIDEO_PIXEL_HW
00209     );
00210     EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0);
00211 
00212     // Jpeg setting
00213     Jcu.SetQuality(JPEG_ENCODE_QUALITY);
00214 
00215     // Callback that fires when registering is complete
00216     client.on_registered(&registered);
00217 
00218     // Register with Pelion Device Management
00219     client.register_and_connect();
00220 
00221     // Setup the button
00222     btn.mode(PullUp);
00223 
00224     // The button fall handler is placed in the event queue so it will run in
00225     // thread context instead of ISR context, which allows safely updating the cloud resource
00226     btn.fall(eventQueue.event(&button_press));
00227 
00228     // You can easily run the eventQueue in a separate thread if required
00229     eventQueue.dispatch_forever();
00230 }
00231 #endif