Daiki Kato / Mbed OS pelion-example-camera
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 #if defined(__ICCARM__)
00038 #pragma data_alignment=32
00039 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT];
00040 #pragma data_alignment=32
00041 static uint8_t JpegBuffer[1024 * 32];
00042 #else
00043 static uint8_t user_frame_buffer0[FRAME_BUFFER_STRIDE * FRAME_BUFFER_HEIGHT]__attribute((aligned(32)));
00044 static uint8_t JpegBuffer[1024 * 32]__attribute((aligned(32)));
00045 #endif
00046 static DisplayBase Display;
00047 
00048 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
00049 // 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
00050 EventQueue eventQueue;
00051 
00052 // Default block device
00053 BlockDevice *bd = BlockDevice::get_default_instance();
00054 FATFileSystem fs("fs");
00055 
00056 // Default network interface object
00057 NetworkInterface *net = NetworkInterface::get_default_instance();
00058 
00059 InterruptIn btn(USER_BUTTON0);
00060 // Declaring pointers for access to Pelion Device Management Client resources outside of main()
00061 MbedCloudClientResource *button_res;
00062 MbedCloudClientResource *pattern_res;
00063 
00064 Thread jpegTask(osPriorityNormal, 1024 * 4);
00065 
00066 void save_camera_image_req(void) {
00067     jpegTask.flags_set(1);
00068 }
00069 
00070 void jpeg_task(MbedCloudClientResource *resource) {
00071     M2MResource *m2m_camera_img_res = resource->get_m2m_resource();
00072     JPEG_Converter Jcu;
00073     JPEG_Converter::bitmap_buff_info_t buff_info;
00074     JPEG_Converter::encode_options_t   encode_opt;
00075     size_t encode_size;
00076 
00077     // Camera start
00078     EasyAttach_Init(Display);
00079     Display.Video_Write_Setting(
00080         DisplayBase::VIDEO_INPUT_CHANNEL_0,
00081         DisplayBase::COL_SYS_NTSC_358,
00082         (void *)user_frame_buffer0,
00083         FRAME_BUFFER_STRIDE,
00084         DisplayBase::VIDEO_FORMAT_YCBCR422,
00085         DisplayBase::WR_RD_WRSWA_32_16BIT,
00086         VIDEO_PIXEL_VW,
00087         VIDEO_PIXEL_HW
00088     );
00089     EasyAttach_CameraStart(Display, DisplayBase::VIDEO_INPUT_CHANNEL_0);
00090 
00091     // Jpeg setting
00092     buff_info.width              = VIDEO_PIXEL_HW;
00093     buff_info.height             = VIDEO_PIXEL_VW;
00094     buff_info.format             = JPEG_Converter::WR_RD_YCbCr422;
00095     buff_info.buffer_address     = (void *)user_frame_buffer0;
00096     encode_opt.encode_buff_size  = sizeof(JpegBuffer);
00097     encode_opt.input_swapsetting = JPEG_Converter::WR_RD_WRSWA_32_16_8BIT;
00098     Jcu.SetQuality(JPEG_ENCODE_QUALITY);
00099 
00100     while (true) {
00101         ThisThread::flags_wait_all(1);
00102         dcache_invalid(JpegBuffer, sizeof(JpegBuffer));
00103         if (Jcu.encode(&buff_info, JpegBuffer, &encode_size, &encode_opt) == JPEG_Converter::JPEG_CONV_OK) {
00104             m2m_camera_img_res->set_value(JpegBuffer, encode_size);
00105             printf("Camera image update: %dbyte\n", encode_size);
00106         } else {
00107             printf("Jpeg convert error\n");
00108         }
00109     }
00110 }
00111 
00112 void button_press() {
00113     int v = button_res->get_value_int() + 1;
00114 
00115     button_res->set_value(v);
00116 
00117     printf("User button clicked %d times\n", v);    
00118 
00119     save_camera_image_req();
00120 }
00121 
00122 /**
00123  * PUT handler
00124  * @param resource The resource that triggered the callback
00125  * @param newValue Updated value for the resource
00126  */
00127 void pattern_updated(MbedCloudClientResource *resource, m2m::String newValue) {
00128     printf("PUT received, new value: %s\n", newValue.c_str());
00129 }
00130 
00131 /**
00132  * POST handler
00133  * @param resource The resource that triggered the callback
00134  * @param buffer If a body was passed to the POST function, this contains the data.
00135  *               Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
00136  * @param size Size of the body
00137  */
00138 void blink_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
00139     printf("POST received. Going to blink LED pattern: %s\n", pattern_res->get_value().c_str());
00140 
00141     static DigitalOut augmentedLed(LED1); // LED that is used for blinking the pattern
00142 
00143     // Parse the pattern string, and toggle the LED in that pattern
00144     string s = std::string(pattern_res->get_value().c_str());
00145     size_t i = 0;
00146     size_t pos = s.find(':');
00147     while (pos != string::npos) {
00148         wait_ms(atoi(s.substr(i, pos - i).c_str()));
00149         augmentedLed = !augmentedLed;
00150 
00151         i = ++pos;
00152         pos = s.find(':', pos);
00153 
00154         if (pos == string::npos) {
00155             wait_ms(atoi(s.substr(i, s.length()).c_str()));
00156             augmentedLed = !augmentedLed;
00157         }
00158     }
00159 }
00160 
00161 void camera_action_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
00162     printf("POST received. Going to camera action\n");
00163 
00164     save_camera_image_req();
00165 }
00166 
00167 /**
00168  * Notification callback handler
00169  * @param resource The resource that triggered the callback
00170  * @param status The delivery status of the notification
00171  */
00172 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
00173     printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
00174 }
00175 
00176 void camera_img_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
00177     printf("Camera image notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
00178 }
00179 
00180 /**
00181  * Registration callback handler
00182  * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
00183  */
00184 void registered(const ConnectorClientEndpointInfo *endpoint) {
00185     printf("Connected to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
00186 }
00187 
00188 int main(void) {
00189     printf("Starting Simple Pelion Device Management Client example\n");
00190     printf("Connecting to the network...\n");
00191 
00192     // Connect to the internet (DHCP is expected to be on)
00193     nsapi_error_t status = net->connect();
00194 
00195     if (status != NSAPI_ERROR_OK) {
00196         printf("Connecting to the network failed %d!\n", status);
00197         return -1;
00198     }
00199 
00200     printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
00201 
00202     // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
00203     SimpleMbedCloudClient client(net, bd, &fs);
00204     int client_status = client.init();
00205     if (client_status != 0) {
00206         printf("Pelion Client initialization failed (%d)\n", client_status);
00207         return -1;
00208     }
00209 
00210     // Creating resources, which can be written or read from the cloud
00211     button_res = client.create_resource("3200/0/5501", "button_count");
00212     button_res->set_value(0);
00213     button_res->methods(M2MMethod::GET);
00214     button_res->observable(true);
00215     button_res->attach_notification_callback(button_callback);
00216 
00217     pattern_res = client.create_resource("3201/0/5853", "blink_pattern");
00218     pattern_res->set_value("500:500:500:500:500:500:500:500");
00219     pattern_res->methods(M2MMethod::GET | M2MMethod::PUT);
00220     pattern_res->attach_put_callback(pattern_updated);
00221 
00222     MbedCloudClientResource *blink_res = client.create_resource("3201/0/5850", "blink_action");
00223     blink_res->methods(M2MMethod::POST);
00224     blink_res->attach_post_callback(blink_callback);
00225 
00226     MbedCloudClientResource *camera_img_res = client.create_resource("5000/0/1", "camera_img");
00227     camera_img_res->set_value(0);
00228     camera_img_res->methods(M2MMethod::GET);
00229     camera_img_res->observable(true);
00230     camera_img_res->attach_notification_callback(camera_img_callback);
00231 
00232     MbedCloudClientResource *camera_action_res = client.create_resource("5000/0/3", "camera_action");
00233     camera_action_res->methods(M2MMethod::POST);
00234     camera_action_res->attach_post_callback(camera_action_callback);
00235 
00236     printf("Initialized Pelion Client. Registering...\n");
00237 
00238     // Callback that fires when registering is complete
00239     client.on_registered(&registered);
00240 
00241     // Register with Pelion Device Management
00242     client.register_and_connect();
00243 
00244     // Setup the button
00245     btn.mode(PullUp);
00246 
00247     // The button fall handler is placed in the event queue so it will run in
00248     // thread context instead of ISR context, which allows safely updating the cloud resource
00249     btn.fall(eventQueue.event(&button_press));
00250 
00251     // Start jpeg task
00252     jpegTask.start(callback(jpeg_task, camera_img_res));
00253 
00254     // You can easily run the eventQueue in a separate thread if required
00255     eventQueue.dispatch_forever();
00256 }
00257 #endif