Advantech / Mbed OS pelion-ready-example-nbiot-wise-1570
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 "LittleFileSystem.h"
00023 #include "mbed_shared_queues.h"
00024 
00025 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
00026 // 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
00027 EventQueue eventQueue;
00028 
00029 // Default block device
00030 BlockDevice *bd = BlockDevice::get_default_instance();
00031 LittleFileSystem fs("fs");
00032 StorageHelper sh(bd, &fs);
00033 
00034 // Default network interface object
00035 NetworkInterface *net = NetworkInterface::get_default_instance();
00036 
00037 // Declaring pointers for access to Pelion Device Management Client resources outside of main()
00038 MbedCloudClientResource *button_res;
00039 MbedCloudClientResource *pattern_res;
00040 
00041 // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
00042 SimpleMbedCloudClient *client;
00043 
00044 // shared EventQueue for scheduling client re-registration
00045 events::EventQueue      *_shared_queue = mbed::mbed_event_queue();
00046 
00047 // This function gets triggered by the timer. It's easy to replace it by an InterruptIn and fall() mode on a real button
00048 void fake_button_press() {
00049     int v = button_res->get_value_int() + 1;
00050 
00051     button_res->set_value(v);
00052 
00053     printf("Simulated button clicked %d times\n", v);
00054 }
00055 
00056 /**
00057  * PUT handler
00058  * @param resource The resource that triggered the callback
00059  * @param newValue Updated value for the resource
00060  */
00061 void pattern_updated(MbedCloudClientResource *resource, m2m::String newValue) {
00062     printf("PUT received, new value: %s\n", newValue.c_str());
00063 }
00064 
00065 /**
00066  * POST handler
00067  * @param resource The resource that triggered the callback
00068  * @param buffer If a body was passed to the POST function, this contains the data.
00069  *               Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
00070  * @param size Size of the body
00071  */
00072 void blink_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
00073     printf("POST received. Going to blink LED pattern: %s\n", pattern_res->get_value().c_str());
00074 
00075     static DigitalOut augmentedLed(LED1); // LED that is used for blinking the pattern
00076 
00077     // Parse the pattern string, and toggle the LED in that pattern
00078     string s = std::string(pattern_res->get_value().c_str());
00079     size_t i = 0;
00080     size_t pos = s.find(':');
00081     while (pos != string::npos) {
00082         wait_ms(atoi(s.substr(i, pos - i).c_str()));
00083         augmentedLed = !augmentedLed;
00084 
00085         i = ++pos;
00086         pos = s.find(':', pos);
00087 
00088         if (pos == string::npos) {
00089             wait_ms(atoi(s.substr(i, s.length()).c_str()));
00090             augmentedLed = !augmentedLed;
00091         }
00092     }
00093 }
00094 
00095 /**
00096  * Notification callback handler
00097  * @param resource The resource that triggered the callback
00098  * @param status The delivery status of the notification
00099  */
00100 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
00101     printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
00102 }
00103 
00104 #if defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP) || defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE)
00105 static bool register_update_called = false;
00106 /**
00107  * shared EventQueue callback handler for client re-registration
00108  */
00109 static void reregister_callback(void)
00110 {
00111     client->register_update();
00112 }
00113 #endif
00114 
00115 /**
00116  * Registration callback handler
00117  * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
00118  */
00119 void registered(const ConnectorClientEndpointInfo *endpoint) {
00120     printf("Connected to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
00121 
00122     /* When using UDP, start re-registration 30s after initial registration. Allows update campaign to start. */
00123     #if defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP) || defined(MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE)
00124     if(!register_update_called) {
00125         register_update_called = true;
00126         _shared_queue->call_in(30000, reregister_callback);
00127     }
00128     #endif
00129 }
00130 
00131 int main(void) {
00132     // Call StorageHelper to initialize FS for us
00133     sh.init();
00134 
00135     // Initialize client only after making sure FS is ready
00136     client = new SimpleMbedCloudClient(net, bd, &fs);
00137 
00138     printf("Starting Simple Pelion Device Management Client example\n");
00139     //Uncomment the following line to demonstrate update
00140     //printf("FW updated OTA\n");
00141     printf("Connecting to the network...\n");
00142 
00143     // Connect to the internet (DHCP is expected to be on)
00144     nsapi_error_t status = net->connect();
00145 
00146     if (status != NSAPI_ERROR_OK) {
00147         printf("Connecting to the network failed %d!\n", status);
00148         return -1;
00149     }
00150 
00151     printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
00152 
00153     // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
00154     int client_status = client->init();
00155     if (client_status != 0) {
00156         printf("Pelion Client initialization failed (%d)\n", client_status);
00157         return -1;
00158     }
00159 
00160     // Creating resources, which can be written or read from the cloud
00161     button_res = client->create_resource("3200/0/5501", "button_count");
00162     button_res->set_value(0);
00163     button_res->methods(M2MMethod::GET);
00164     button_res->observable(true);
00165     button_res->attach_notification_callback(button_callback);
00166 
00167     pattern_res = client->create_resource("3201/0/5853", "blink_pattern");
00168     pattern_res->set_value("500:500:500:500:500:500:500:500");
00169     pattern_res->methods(M2MMethod::GET | M2MMethod::PUT);
00170     pattern_res->attach_put_callback(pattern_updated);
00171 
00172     MbedCloudClientResource *blink_res = client->create_resource("3201/0/5850", "blink_action");
00173     blink_res->methods(M2MMethod::POST);
00174     blink_res->attach_post_callback(blink_callback);
00175 
00176     printf("Initialized Pelion Client. Registering...\n");
00177 
00178     // Callback that fires when registering is complete
00179     client->on_registered(&registered);
00180 
00181     // Register with Pelion Device Management
00182     client->register_and_connect();
00183 
00184     // Placeholder for callback to update local resource when GET comes.
00185     // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
00186     Ticker timer;
00187     timer.attach(eventQueue.event(&fake_button_press), 5.0);
00188 
00189     // You can easily run the eventQueue in a separate thread if required
00190     eventQueue.dispatch_forever();
00191 }
00192 #endif