Generic Pelion Device Management example for various U-blox-based boards.

Dependencies:   ublox-at-cellular-interface ublox-cellular-base

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:

For Odin-W2 please go to Repository link

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

UBLOX_C030_U201

UBLOX_C030_R412M

Example functionality

This example showcases the following device functionality:

  • On user button click, increment Pelion LWM2M button resource.
  • Allow the user to change the state of the board LED from Pelion LWM2M led_state resource and PUT request.
  • (currently disabled) Read ADC temperature and ADC vref, and report them as Pelion LWM2M resources.

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/ublox/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)

Committer:
screamer
Date:
Wed Feb 20 15:33:02 2019 +0000
Revision:
6:2fb5057c0e42
Parent:
3:3b2db67b206e
Child:
7:230af466efc4
Updated to Mbed OS 5.11.4 and SMCC 2.1.1.3

Who changed what in which revision?

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