Generic Pelion Device Management example for various Nuvoton-based boards.

DEPRECATED

This example application is not maintained and not recommended. It uses an old version of Mbed OS, Pelion DM, and Arm toolchain. It doesn't work with Mbed Studio.

Please use: https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-pelion/

This example is known to work great on the following platforms:

Follow the Quick-Start instructions: https://cloud.mbed.com/quick-start

https://os.mbed.com/media/cache/platforms/NuMaker-IoT-M487_board_front_small.jpg.250x250_q85.jpghttps://os.mbed.com/media/cache/platforms/NuMaker-PFM-M487.png.170x170_q85.png https://os.mbed.com/media/cache/platforms/NuMaker-PFM-NUC472Small.png.170x170_q85.png

Example functionality

This example showcases the following device functionality:

  • On timer button increment, simulate Pelion LWM2M button resource change

Use this example with Mbed CLI


1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/Nuvoton/code/pelion-example-common
cd pelion-example-common


2. Install the CLOUD_SDK_API_KEY

mbed config -G CLOUD_SDK_API_KEY <PELION_DM_API_KEY>

For instructions on how to generate your API key, please see the documentation.

3. Initialize firmware credentials (done once per repository). You can use the following command:

mbed dm init -d "<your company name in Pelion DM>" --model-name "<product model identifier>" -q --force

If above command do not work for your Mbed CLI, please consider upgrading Mbed CLI to version 1.8.x or above.

4. Compile and program:

mbed compile -t <toolchain> -m <TARGET_BOARD>

(supported toolchains : GCC_ARM / ARM / IAR)

5. Copy the binary file pelion-example-common.bin to your mbed device.

Note

This platform and application is suitable for evaluation and initial development. For production purposes, we recommend to use a different variant with built-in security features

Committer:
cyliang
Date:
Tue Apr 16 10:53:01 2019 +0800
Revision:
2:f07ccb7164d3
Parent:
0:e0138281f21d
SMCC 2.2.1.2 migration for 3 NuMaker platforms

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sam Chu 0:e0138281f21d 1 // ----------------------------------------------------------------------------
Sam Chu 0:e0138281f21d 2 // Copyright 2016-2018 ARM Ltd.
Sam Chu 0:e0138281f21d 3 //
Sam Chu 0:e0138281f21d 4 // SPDX-License-Identifier: Apache-2.0
Sam Chu 0:e0138281f21d 5 //
Sam Chu 0:e0138281f21d 6 // Licensed under the Apache License, Version 2.0 (the "License");
Sam Chu 0:e0138281f21d 7 // you may not use this file except in compliance with the License.
Sam Chu 0:e0138281f21d 8 // You may obtain a copy of the License at
Sam Chu 0:e0138281f21d 9 //
Sam Chu 0:e0138281f21d 10 // http://www.apache.org/licenses/LICENSE-2.0
Sam Chu 0:e0138281f21d 11 //
Sam Chu 0:e0138281f21d 12 // Unless required by applicable law or agreed to in writing, software
Sam Chu 0:e0138281f21d 13 // distributed under the License is distributed on an "AS IS" BASIS,
Sam Chu 0:e0138281f21d 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Sam Chu 0:e0138281f21d 15 // See the License for the specific language governing permissions and
Sam Chu 0:e0138281f21d 16 // limitations under the License.
Sam Chu 0:e0138281f21d 17 // ----------------------------------------------------------------------------
Sam Chu 0:e0138281f21d 18 #ifndef MBED_TEST_MODE
Sam Chu 0:e0138281f21d 19
Sam Chu 0:e0138281f21d 20 #include "mbed.h"
Sam Chu 0:e0138281f21d 21 #include "simple-mbed-cloud-client.h"
Sam Chu 0:e0138281f21d 22 #include "FATFileSystem.h"
cyliang 2:f07ccb7164d3 23 #include "LittleFileSystem.h"
cyliang 2:f07ccb7164d3 24
cyliang 2:f07ccb7164d3 25 // Default network interface object. Don't forget to change the WiFi SSID/password in mbed_app.json if you're using WiFi.
cyliang 2:f07ccb7164d3 26 NetworkInterface *net = NetworkInterface::get_default_instance();
cyliang 2:f07ccb7164d3 27
cyliang 2:f07ccb7164d3 28 // Default block device available on the target board
cyliang 2:f07ccb7164d3 29 BlockDevice *bd = BlockDevice::get_default_instance();
cyliang 2:f07ccb7164d3 30
cyliang 2:f07ccb7164d3 31 #if COMPONENT_SD || COMPONENT_NUSD
cyliang 2:f07ccb7164d3 32 // Use FATFileSystem for SD card type blockdevices
cyliang 2:f07ccb7164d3 33 FATFileSystem fs("fs");
cyliang 2:f07ccb7164d3 34 #else
cyliang 2:f07ccb7164d3 35 // Use LittleFileSystem for non-SD block devices to enable wear leveling and other functions
cyliang 2:f07ccb7164d3 36 LittleFileSystem fs("fs");
cyliang 2:f07ccb7164d3 37 #endif
cyliang 2:f07ccb7164d3 38
cyliang 2:f07ccb7164d3 39 #if USE_BUTTON == 1
cyliang 2:f07ccb7164d3 40 InterruptIn button(SW2); //(BUTTON1);
cyliang 2:f07ccb7164d3 41 #endif /* USE_BUTTON */
cyliang 2:f07ccb7164d3 42
cyliang 2:f07ccb7164d3 43 // Default LED to use for PUT/POST example
cyliang 2:f07ccb7164d3 44 DigitalOut led(LED1, 0);
cyliang 2:f07ccb7164d3 45
cyliang 2:f07ccb7164d3 46 // Declaring pointers for access to Pelion Device Management Client resources outside of main()
cyliang 2:f07ccb7164d3 47 MbedCloudClientResource *button_res;
cyliang 2:f07ccb7164d3 48 MbedCloudClientResource *led_res;
cyliang 2:f07ccb7164d3 49 MbedCloudClientResource *post_res;
cyliang 2:f07ccb7164d3 50
Sam Chu 0:e0138281f21d 51 // An event queue is a very useful structure to debounce information between contexts (e.g. ISR and normal threads)
Sam Chu 0:e0138281f21d 52 // 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
Sam Chu 0:e0138281f21d 53 EventQueue eventQueue;
Sam Chu 0:e0138281f21d 54
cyliang 2:f07ccb7164d3 55 /**
cyliang 2:f07ccb7164d3 56 * PUT handler - sets the value of the built-in LED
cyliang 2:f07ccb7164d3 57 * @param resource The resource that triggered the callback
cyliang 2:f07ccb7164d3 58 * @param newValue Updated value for the resource
cyliang 2:f07ccb7164d3 59 */
cyliang 2:f07ccb7164d3 60 void put_callback(MbedCloudClientResource *resource, m2m::String newValue) {
cyliang 2:f07ccb7164d3 61 printf("PUT received. New value: %s\n", newValue.c_str());
cyliang 2:f07ccb7164d3 62 led = atoi(newValue.c_str());
Sam Chu 0:e0138281f21d 63 }
Sam Chu 0:e0138281f21d 64
Sam Chu 0:e0138281f21d 65 /**
cyliang 2:f07ccb7164d3 66 * POST handler - prints the content of the payload
Sam Chu 0:e0138281f21d 67 * @param resource The resource that triggered the callback
Sam Chu 0:e0138281f21d 68 * @param buffer If a body was passed to the POST function, this contains the data.
Sam Chu 0:e0138281f21d 69 * Note that the buffer is deallocated after leaving this function, so copy it if you need it longer.
Sam Chu 0:e0138281f21d 70 * @param size Size of the body
Sam Chu 0:e0138281f21d 71 */
cyliang 2:f07ccb7164d3 72 void post_callback(MbedCloudClientResource *resource, const uint8_t *buffer, uint16_t size) {
cyliang 2:f07ccb7164d3 73 printf("POST received (length %u). Payload: ", size);
cyliang 2:f07ccb7164d3 74 for (size_t ix = 0; ix < size; ix++) {
cyliang 2:f07ccb7164d3 75 printf("%02x ", buffer[ix]);
cyliang 2:f07ccb7164d3 76 }
cyliang 2:f07ccb7164d3 77 printf("\n");
cyliang 2:f07ccb7164d3 78 }
Sam Chu 0:e0138281f21d 79
cyliang 2:f07ccb7164d3 80 /**
cyliang 2:f07ccb7164d3 81 * Button handler
cyliang 2:f07ccb7164d3 82 * This function will be triggered either by a physical button press or by a ticker every 5 seconds (see below)
cyliang 2:f07ccb7164d3 83 */
cyliang 2:f07ccb7164d3 84 void button_press() {
cyliang 2:f07ccb7164d3 85 int v = button_res->get_value_int() + 1;
cyliang 2:f07ccb7164d3 86 button_res->set_value(v);
cyliang 2:f07ccb7164d3 87 printf("Button clicked %d times\n", v);
Sam Chu 0:e0138281f21d 88 }
Sam Chu 0:e0138281f21d 89
Sam Chu 0:e0138281f21d 90 /**
Sam Chu 0:e0138281f21d 91 * Notification callback handler
Sam Chu 0:e0138281f21d 92 * @param resource The resource that triggered the callback
Sam Chu 0:e0138281f21d 93 * @param status The delivery status of the notification
Sam Chu 0:e0138281f21d 94 */
Sam Chu 0:e0138281f21d 95 void button_callback(MbedCloudClientResource *resource, const NoticationDeliveryStatus status) {
Sam Chu 0:e0138281f21d 96 printf("Button notification, status %s (%d)\n", MbedCloudClientResource::delivery_status_to_string(status), status);
Sam Chu 0:e0138281f21d 97 }
Sam Chu 0:e0138281f21d 98
Sam Chu 0:e0138281f21d 99 /**
Sam Chu 0:e0138281f21d 100 * Registration callback handler
Sam Chu 0:e0138281f21d 101 * @param endpoint Information about the registered endpoint such as the name (so you can find it back in portal)
Sam Chu 0:e0138281f21d 102 */
Sam Chu 0:e0138281f21d 103 void registered(const ConnectorClientEndpointInfo *endpoint) {
cyliang 2:f07ccb7164d3 104 printf("Registered to Pelion Device Management. Endpoint Name: %s\n", endpoint->internal_endpoint_name.c_str());
Sam Chu 0:e0138281f21d 105 }
Sam Chu 0:e0138281f21d 106
Sam Chu 0:e0138281f21d 107 int main(void) {
cyliang 2:f07ccb7164d3 108 printf("\nStarting Simple Pelion Device Management Client example\n");
cyliang 2:f07ccb7164d3 109
cyliang 2:f07ccb7164d3 110 int storage_status = fs.mount(bd);
cyliang 2:f07ccb7164d3 111 if (storage_status != 0) {
cyliang 2:f07ccb7164d3 112 printf("Storage mounting failed.\n");
cyliang 2:f07ccb7164d3 113 }
cyliang 2:f07ccb7164d3 114
cyliang 2:f07ccb7164d3 115 #if USE_BUTTON == 1
cyliang 2:f07ccb7164d3 116 // If the User button is pressed ons start, then format storage.
cyliang 2:f07ccb7164d3 117 bool btn_pressed = (button.read() == MBED_CONF_APP_BUTTON_PRESSED_STATE);
cyliang 2:f07ccb7164d3 118 if (btn_pressed) {
cyliang 2:f07ccb7164d3 119 printf("User button is pushed on start...\n");
cyliang 2:f07ccb7164d3 120 }
cyliang 2:f07ccb7164d3 121 #else
cyliang 2:f07ccb7164d3 122 bool btn_pressed = FALSE;
cyliang 2:f07ccb7164d3 123 #endif /* USE_BUTTON */
Sam Chu 0:e0138281f21d 124
cyliang 2:f07ccb7164d3 125 if (storage_status || btn_pressed) {
cyliang 2:f07ccb7164d3 126 printf("Formatting the storage...\n");
cyliang 2:f07ccb7164d3 127 int storage_status = StorageHelper::format(&fs, bd);
cyliang 2:f07ccb7164d3 128 if (storage_status != 0) {
cyliang 2:f07ccb7164d3 129 printf("ERROR: Failed to reformat the storage (%d).\n", storage_status);
cyliang 2:f07ccb7164d3 130 }
cyliang 2:f07ccb7164d3 131 } else {
cyliang 2:f07ccb7164d3 132 printf("You can hold the user button during boot to format the storage and change the device identity.\n");
cyliang 2:f07ccb7164d3 133 }
Sam Chu 0:e0138281f21d 134
cyliang 2:f07ccb7164d3 135 // Connect to the Internet (DHCP is expected to be on)
cyliang 2:f07ccb7164d3 136 printf("Connecting to the network using the default network interface...\n");
cyliang 2:f07ccb7164d3 137 net = NetworkInterface::get_default_instance();
cyliang 2:f07ccb7164d3 138
cyliang 2:f07ccb7164d3 139 nsapi_error_t net_status = NSAPI_ERROR_NO_CONNECTION;
cyliang 2:f07ccb7164d3 140 while ((net_status = net->connect()) != NSAPI_ERROR_OK) {
cyliang 2:f07ccb7164d3 141 printf("Unable to connect to network (%d). Retrying...\n", net_status);
Sam Chu 0:e0138281f21d 142 }
Sam Chu 0:e0138281f21d 143
Sam Chu 0:e0138281f21d 144 printf("Connected to the network successfully. IP address: %s\n", net->get_ip_address());
Sam Chu 0:e0138281f21d 145
cyliang 2:f07ccb7164d3 146 printf("Initializing Pelion Device Management Client...\n");
cyliang 2:f07ccb7164d3 147
Sam Chu 0:e0138281f21d 148 // SimpleMbedCloudClient handles registering over LwM2M to Pelion Device Management
Sam Chu 0:e0138281f21d 149 SimpleMbedCloudClient client(net, bd, &fs);
Sam Chu 0:e0138281f21d 150 int client_status = client.init();
Sam Chu 0:e0138281f21d 151 if (client_status != 0) {
Sam Chu 0:e0138281f21d 152 printf("Pelion Client initialization failed (%d)\n", client_status);
Sam Chu 0:e0138281f21d 153 return -1;
Sam Chu 0:e0138281f21d 154 }
Sam Chu 0:e0138281f21d 155
Sam Chu 0:e0138281f21d 156 // Creating resources, which can be written or read from the cloud
Sam Chu 0:e0138281f21d 157 button_res = client.create_resource("3200/0/5501", "button_count");
Sam Chu 0:e0138281f21d 158 button_res->set_value(0);
Sam Chu 0:e0138281f21d 159 button_res->methods(M2MMethod::GET);
Sam Chu 0:e0138281f21d 160 button_res->observable(true);
Sam Chu 0:e0138281f21d 161 button_res->attach_notification_callback(button_callback);
Sam Chu 0:e0138281f21d 162
cyliang 2:f07ccb7164d3 163 led_res = client.create_resource("3201/0/5853", "led_state");
cyliang 2:f07ccb7164d3 164 led_res->set_value(led.read());
cyliang 2:f07ccb7164d3 165 led_res->methods(M2MMethod::GET | M2MMethod::PUT);
cyliang 2:f07ccb7164d3 166 led_res->attach_put_callback(put_callback);
Sam Chu 0:e0138281f21d 167
cyliang 2:f07ccb7164d3 168 post_res = client.create_resource("3300/0/5605", "execute_function");
cyliang 2:f07ccb7164d3 169 post_res->methods(M2MMethod::POST);
cyliang 2:f07ccb7164d3 170 post_res->attach_post_callback(post_callback);
Sam Chu 0:e0138281f21d 171
cyliang 2:f07ccb7164d3 172 printf("Initialized Pelion Device Management Client. Registering...\n");
Sam Chu 0:e0138281f21d 173
Sam Chu 0:e0138281f21d 174 // Callback that fires when registering is complete
Sam Chu 0:e0138281f21d 175 client.on_registered(&registered);
Sam Chu 0:e0138281f21d 176
cyliang 2:f07ccb7164d3 177 // Register with Pelion DM
Sam Chu 0:e0138281f21d 178 client.register_and_connect();
Sam Chu 0:e0138281f21d 179
cyliang 2:f07ccb7164d3 180 #if USE_BUTTON == 1
cyliang 2:f07ccb7164d3 181 // The button fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
cyliang 2:f07ccb7164d3 182 button.fall(eventQueue.event(&button_press));
cyliang 2:f07ccb7164d3 183 printf("Press the user button to increment the LwM2M resource value...\n");
cyliang 2:f07ccb7164d3 184 #else
Sam Chu 0:e0138281f21d 185 // The timer fires on an interrupt context, but debounces it to the eventqueue, so it's safe to do network operations
Sam Chu 0:e0138281f21d 186 Ticker timer;
cyliang 2:f07ccb7164d3 187 timer.attach(eventQueue.event(&button_press), 5.0);
cyliang 2:f07ccb7164d3 188 printf("Simulating button press every 5 seconds...\n");
cyliang 2:f07ccb7164d3 189 #endif /* USE_BUTTON */
Sam Chu 0:e0138281f21d 190
Sam Chu 0:e0138281f21d 191 // You can easily run the eventQueue in a separate thread if required
Sam Chu 0:e0138281f21d 192 eventQueue.dispatch_forever();
Sam Chu 0:e0138281f21d 193 }
cyliang 2:f07ccb7164d3 194
cyliang 2:f07ccb7164d3 195 #endif /* MBED_TEST_MODE */