Christos Vasilakis / Mbed OS pelion-example-common-DISCO_F413ZH
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 "LittleFileSystem.h"
00024 
00025 #include <string> 
00026 
00027 // Default network interface object. Don't forget to change the WiFi SSID/password in mbed_app.json if you're using WiFi.
00028 NetworkInterface *net = NetworkInterface::get_default_instance();
00029 
00030 // Default block device available on the target board
00031 BlockDevice *bd = BlockDevice::get_default_instance();
00032 
00033 #if COMPONENT_SD || COMPONENT_NUSD
00034 // Use FATFileSystem for SD card type blockdevices
00035 FATFileSystem fs("fs");
00036 #else
00037 // Use LittleFileSystem for non-SD block devices to enable wear leveling and other functions
00038 LittleFileSystem fs("fs");
00039 #endif
00040 
00041 // Default User button for GET example
00042 InterruptIn button(BUTTON1);
00043 // Default LED to use for PUT/POST example
00044 DigitalOut led(LED1, 0);
00045 
00046 // How often to fetch sensor data (in seconds)
00047 #define SENSORS_POLL_INTERVAL 3.0
00048 
00049 // Send all sensor data or just limited (useful for when running out of memory)
00050 #define SEND_ALL_SENSORS
00051 
00052 // Sensors related includes and initialization
00053 // Temperature reading from microcontroller
00054 AnalogIn adc_temp(ADC_TEMP);
00055 // Voltage reference reading from microcontroller
00056 AnalogIn adc_vref(ADC_VREF);
00057 
00058 // Declaring pointers for access to Pelion Device Management Client resources outside of main()
00059 MbedCloudClientResource *res_button;
00060 MbedCloudClientResource *res_pattern_led;
00061 MbedCloudClientResource *res_post;
00062 
00063 // Additional resources for sensor readings
00064 #ifdef SEND_ALL_SENSORS
00065 MbedCloudClientResource *res_temperature;
00066 MbedCloudClientResource *res_voltage;
00067 #endif /* SEND_ALL_SENSORS */
00068 
00069 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
00070 // 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
00071 EventQueue eventQueue;
00072 
00073 // When the device is registered, this variable will be used to access various useful information, like device ID etc.
00074 static const ConnectorClientEndpointInfo* endpointInfo;
00075 
00076 void pattern_updated(MbedCloudClientResource *resource, m2m::String newValue) {
00077     printf("PUT received, new value: %s\n", newValue.c_str());
00078 }
00079 
00080 void blink() {
00081     led = !led;
00082 }
00083 
00084 /**
00085  * POST handler
00086  * @param resource The resource that triggered the callback
00087  * @param buffer If a body was passed to the POST function, this contains the data.
00088  *               Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
00089  * @param size Size of the body
00090  */
00091 void blink_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
00092     printf("POST received. Going to blink LED pattern: %s\n", res_pattern_led->get_value().c_str());
00093 
00094     // Parse the pattern string, and toggle the LED in that pattern
00095     string s = string(res_pattern_led->get_value().c_str());
00096     size_t i = 0;
00097     size_t pos = s.find(':');
00098     int total_len = 0;
00099     while (pos != string::npos) {
00100         int len = atoi(s.substr(i, pos - i).c_str());
00101 
00102         mbed_event_queue()->call_in(total_len + len, &blink);
00103 
00104         total_len += len;
00105         i = ++pos;
00106         pos = s.find(':', pos);
00107     }
00108 }
00109 
00110 /**
00111  * Notification callback handler
00112  * @param resource The resource that triggered the callback
00113  * @param status The delivery status of the notification
00114  */
00115 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
00116     printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
00117 }
00118 
00119 /**
00120  * Button handler
00121  * This function will be triggered either by a physical button press or by a ticker every 5 seconds (see below)
00122  */
00123 void button_press() {
00124     int v = res_button->get_value_int() + 1;
00125     res_button->set_value(v);
00126     printf("Button clicked %d times\n", v);
00127 }
00128 
00129 /**
00130  * Update sensors and report their values.
00131  * This function is called periodically.
00132  */
00133 void sensors_update() {
00134     float temp = adc_temp.read()*100;
00135     float vref = adc_vref.read();
00136     printf("ADC temp:  %6.4f C,  vref: %6.4f %%\r\n", temp, vref);
00137     if (endpointInfo) {
00138         res_temperature->set_value(temp);
00139         res_voltage->set_value(vref);
00140     }
00141 }
00142 
00143 /**
00144  * Registration callback handler
00145  * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
00146  * When the device is registered, this variable will be used to access various useful information, like device ID etc.
00147  */
00148 void registered(const ConnectorClientEndpointInfo *endpoint) {
00149     printf("Registered to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
00150     endpointInfo = endpoint;
00151 }
00152 
00153 int main(void) {
00154     printf("\nStarting Simple Pelion Device Management Client example\n");
00155 
00156     int storage_status = fs.mount(bd);
00157     if (storage_status != 0) {
00158         printf("Storage mounting failed.\n");
00159     }
00160     // If the User button is pressed ons start, then format storage.
00161     bool btn_pressed = (button.read() == MBED_CONF_APP_BUTTON_PRESSED_STATE);
00162     if (btn_pressed) {
00163         printf("User button is pushed on start...\n");
00164     }
00165 
00166     if (storage_status || btn_pressed) {
00167         printf("Formatting the storage...\n");
00168         int storage_status = StorageHelper::format(&fs, bd);
00169         if (storage_status != 0) {
00170             printf("ERROR: Failed to reformat the storage (%d).\n", storage_status);
00171         }
00172     } else {
00173         printf("You can hold the user button during boot to format the storage and change the device identity.\n");
00174     }
00175 
00176     // Connect to the Internet (DHCP is expected to be on)
00177     printf("Connecting to the network using the default network interface...\n");
00178     net = NetworkInterface::get_default_instance();
00179 
00180     nsapi_error_t net_status = NSAPI_ERROR_NO_CONNECTION;
00181     while ((net_status = net->connect()) != NSAPI_ERROR_OK) {
00182         printf("Unable to connect to network (%d). Retrying...\n", net_status);
00183     }
00184 
00185     printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
00186 
00187     printf("Initializing Pelion Device Management Client...\n");
00188 
00189     // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
00190     SimpleMbedCloudClient client(net, bd, &fs);
00191     int client_status = client.init();
00192     if (client_status != 0) {
00193         printf("Pelion Client initialization failed (%d)\n", client_status);
00194         return -1;
00195     }
00196 
00197     // Creating resources, which can be written or read from the cloud
00198     res_button = client.create_resource("3200/0/5501", "Button Count");
00199     res_button->set_value(0);
00200     res_button->methods(M2MMethod::GET);
00201     res_button->observable(true);
00202     res_button->attach_notification_callback(button_callback);
00203 
00204     res_pattern_led = client.create_resource("3201/0/5853", "LED Pattern");
00205     //res_pattern_led->set_value("500:500:500:500:500:500:500:500");
00206     res_pattern_led->set_value("100:100:100:100:100:100:100:100");
00207     res_pattern_led->methods(M2MMethod::GET | M2MMethod::PUT);
00208     res_pattern_led->attach_put_callback(pattern_updated);
00209 
00210     res_post = client.create_resource("3201/0/5850", "Blink Action");
00211     res_post->methods(M2MMethod::POST);
00212     res_post->attach_post_callback(eventQueue.event(&blink_callback));
00213 
00214     // Sensor resources
00215     res_temperature = client.create_resource("3303/0/5700", "Temperature (C)");
00216     res_temperature->set_value(0);
00217     res_temperature->methods(M2MMethod::GET);
00218     res_temperature->observable(true);
00219 
00220     res_voltage = client.create_resource("3316/0/5700", "Voltage");
00221     res_voltage->set_value(0);
00222     res_voltage->methods(M2MMethod::GET);
00223     res_voltage->observable(true);
00224 
00225     printf("Initialized Pelion Device Management Client. Registering...\n");
00226 
00227     // Callback that fires when registering is complete
00228     client.on_registered(&registered);
00229 
00230     // Register with Pelion DM
00231     client.register_and_connect();
00232 
00233     // The button fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
00234     button.fall(eventQueue.event(&button_press));
00235     printf("Press the user button to increment the LwM2M resource value...\n");
00236 
00237     // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
00238     Ticker timer;
00239     timer.attach(eventQueue.event(&sensors_update), SENSORS_POLL_INTERVAL);
00240 
00241     // You can easily run the eventQueue in a separate thread if required
00242     eventQueue.dispatch_forever();
00243 }
00244 
00245 #endif /* MBED_TEST_MODE */