Specific Pelion ready example using features of Uhuru RAVEN board including Wi-Fi and SPI flash

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:
Uhuru RAVEN over Wi-Fi and using onboard SPI flash.

/media/uploads/MACRUM/raven.jpg

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

Example functionality

This example showcases the following device functionality:

  • Allow the user to change the state of the board LED from Pelion LWM2M led_state resource and PUT request.

Use this example with Mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/Uhuru/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.9.x or above.

Set SSID and password in the mbed_app.json.

            "nsapi.default-wifi-ssid"                   : "\"SSID\"",
            "nsapi.default-wifi-password"               : "\"Password\""

4. Compile and program:

mbed compile -t <toolchain> -m UHURU_RAVEN

(supported toolchains : GCC_ARM / ARM / IAR)

5. You can connect on a virtual terminal/COM port to the platform using:

mbed sterm -b 115200

This should give you an output similar to:

[BOOT] INFO: init - verified SFDP Signature and version Successfully
[BOOT] DEBUG: Erase Type(A) 1 - Inst: 0xFFh, Size: 4096
[BOOT] INFO: Erase Type 1 - Inst: 0x20h, Size: 4096
[BOOT] DEBUG: Erase Type(A) 2 - Inst: 0xFFh, Size: 32768
[BOOT] INFO: Erase Type 2 - Inst: 0x52h, Size: 32768
[BOOT] DEBUG: Erase Type(A) 3 - Inst: 0xFFh, Size: 65536
[BOOT] INFO: Erase Type 3 - Inst: 0xD8h, Size: 65536
[BOOT] DEBUG: Erase Type(A) 4 - Inst: 0xFFh, Size: 1
[BOOT] INFO: Erase Type 4 - Inst: 0xFFh, Size: 1
[BOOT] Mbed Bootloader
[BOOT] ARM: 00000000000000000000
[BOOT] OEM: 00000000000000000000
[BOOT] Layout: 0 80091E0
[BOOT] Active firmware integrity check:
[BOOT] SHA256: DC87CF84F7064E58EF0FD011C1768ADFA4803BA1F6758808972680605CBB2C9B
[BOOT] Version: 1558427552
[BOOT] INFO Read - Inst: 0x3h
[BOOT] Slot 0 is empty
[BOOT] Active firmware up-to-date
[BOOT] Application's start address: 0x8010400
[BOOT] Application's jump address: 0x80108F9
[BOOT] Application's stack address: 0x20080000
[BOOT] Forwarding to application...
..¿<.
Starting Simple Pelion Device Management Client example
You can hold the user button during boot to format the storage and change the device identity.
Connecting to the network using the default network interface...
Connected to the network successfully. IP address: 192.168.11.20
Initializing Pelion Device Management Client...
Initialized Pelion Device Management Client. Registering...
Simulating button press every 5 seconds...
Registered to Pelion Device Management. Endpoint Name: 016ad986878400000000000100xxxxxx
Button clicked 1 times
Button clicked 2 times
Button clicked 3 times
Committer:
MACRUM
Date:
Tue May 21 17:19:38 2019 +0900
Revision:
0:16957896f9cd
initial commit

Who changed what in which revision?

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