Specific Pelion ready example using features of Seeed Wio boards including cellular and SD Card

Dependencies:   WS2812 PixelArray

Fork of simple-mbed-cloud-example-wio_3g by Toyomasa Watarai

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:
Seeed Wio 3G and Seeed Wio LTE-M1/NB1(BG96) over cellular and using SD card.

https://os.mbed.com/media/cache/platforms/Wio_3G.png.250x250_q85.png

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.

Instructions to use this program with mbed CLI

1. Import the application into your desktop:

mbed import https://os.mbed.com/teams/Seeed/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 APN name, username and password in the mbed_app.json.

            "nsapi.default-cellular-plmn"      : "\"00000\"",
            "nsapi.default-cellular-sim-pin"   : "\"0000\"",
            "nsapi.default-cellular-apn"       : "\"apn\"",
            "nsapi.default-cellular-username"  : "\"username\"",
            "nsapi.default-cellular-password"  : "\"password\""

Information

For the Wio LTE-M1/NB1(BG96) target, PLMN (Public land mobile network) should be specified to get quick connection to the network. This is usually found first 5 digit from your SIM card IMSI (International Mobile Subscriber Identity) number. e.g. 44052

4. Compile and program:

mbed compile -t <toolchain> -m WIO_3G

(supported toolchains : GCC_ARM / ARM / IAR)

Troubleshooting

  • Make sure the fields nsapi.default-cellular-sim-pin, nsapi.default-cellular-apn, nsapi.default-cellular-username and nsapi.default-cellular-password from the mbed_app.json file are filled in correctly. The correct values should appear in the user manual in the details of the SIM card.
  • Enable trace flag to have access to debug information "mbed-trace.enable": true.
  • Try both TCP and UDP socket types.
  • Try both "lwip.ppp-enabled": true and "lwip.ppp-enabled": false.
  • The modem and network may only support IPv6 in which case "lwip.ipv6-enabled": true shall be defined.
  • The SIM and modem must have compatible cellular technology (3G, 4G, NB-IoT, ...) supported and cellular network available.
Committer:
Osamu Koizumi
Date:
Thu Apr 18 13:13:04 2019 +0900
Revision:
2:aadfd874279d
Parent:
1:ddb04b438959
Child:
3:6f3b402196cc
Pelion Ready support

Who changed what in which revision?

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