Mbed OS Device Connector client pushing environmental sensor data via 6LowPan.

Dependencies:   X_NUCLEO_IKS01A2

Fork of mbed-os-example-client-Sensors_6LowPan by Nicola Capovilla

The application is derived from the official mbedOS client example (link) and has been tested using a X-NUCLEO-IDS01A4 SubGHz 6LowPan connectivity board and a X-NUCLEO-IKS01A2 (default) or a X-NUCLEO-IKS01A1 motion and environmental sensors expansion board connected to a ST NUCLEO-F429ZI platform.
The following steps should be performed to make the application work:

  • Register and login into ARM mbed Connector.
  • Replace the default and empty security.h file with the one associated with your account and provided by the Connector (Security Credentials menu).
  • In order to use X-NUCLEO-IKS01A1 instead of default X-NUCLEO-IKS01A2 comment out the IKS01A2 macro definition in main.cpp file.
  • Choose NUCLEO-F429ZI as a target either from online compiler or from CLI, compile and flash.
  • Setup and connect a NUCLEO-F429ZI + X-NUCLEO-IDS01A4 6LowPan border router as explained here
  • Open a serial terminal (params 115200N1) and wait that the client is connected to the mbed Connector via the border router.
  • As soon as the client is connected it will start acquiring and pushing the environmental (pressure, temperature and humidity) data to the cloud.

Note: environmental data are expressed using IPSO representation based on OMA LWM2M standard.

Files at this revision

API Documentation at this revision

Comitter:
nikapov
Date:
Thu Jan 25 18:00:04 2018 +0100
Commit message:
First release.

Changed in this revision

.gitignore Show annotated file Show diff for this revision Revisions of this file
Jenkinsfile Show annotated file Show diff for this revision Revisions of this file
LICENSE Show annotated file Show diff for this revision Revisions of this file
README.md Show annotated file Show diff for this revision Revisions of this file
X_NUCLEO_IKS01A2.lib Show annotated file Show diff for this revision Revisions of this file
apache-2.0.txt Show annotated file Show diff for this revision Revisions of this file
build_all.sh Show annotated file Show diff for this revision Revisions of this file
clicks.png Show annotated file Show diff for this revision Revisions of this file
easy-connect.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-client.lib Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed_app.json Show annotated file Show diff for this revision Revisions of this file
mbed_client_config.h Show annotated file Show diff for this revision Revisions of this file
mbedtls_mbed_client_config.h Show annotated file Show diff for this revision Revisions of this file
pal.lib Show annotated file Show diff for this revision Revisions of this file
security.h Show annotated file Show diff for this revision Revisions of this file
simpleclient.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 694e888fd1b5 .gitignore
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,34 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+yotta_modules/
+yotta_targets/
+build/
+.yotta.json
+source/security.h
diff -r 000000000000 -r 694e888fd1b5 Jenkinsfile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Jenkinsfile	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,124 @@
+properties ([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [
+  [$class: 'StringParameterDefinition', name: 'mbed_os_revision', defaultValue: 'latest', description: 'Revision of mbed-os to build. To access mbed-os PR use format "pull/PR number/head"']
+  ]]])
+
+try {
+  echo "Verifying build with mbed-os version ${mbed_os_revision}"
+  env.MBED_OS_REVISION = "${mbed_os_revision}"
+  if (mbed_os_revision.matches('pull/\\d+/head')) {
+    echo "Revision is a Pull Request"
+  }
+} catch (err) {
+  def mbed_os_revision = "latest"
+  echo "Verifying build with mbed-os version ${mbed_os_revision}"
+  env.MBED_OS_REVISION = "${mbed_os_revision}"
+}
+
+// List of targets to compile
+def targets = [
+  "K64F",
+  "NUCLEO_F429ZI",
+  "UBLOX_EVK_ODIN_W2"
+  ]
+
+// Map toolchains to compilers
+def toolchains = [
+  ARM: "armcc",
+  GCC_ARM: "arm-none-eabi-gcc",
+  IAR: "iar_arm"
+  ]
+
+def configurations = [
+  "def": ["ETH"],
+  "thd": ["ATMEL", "MCR20"],
+  "6lp": ["ATMEL", "MCR20"]
+  ]
+
+def connectiontypes = [
+  "ETH",
+  "ATMEL",
+  "MCR20"
+  ]
+
+def stepsForParallel = [:]
+
+// Jenkins pipeline does not support map.each, we need to use oldschool for loop
+for (int i = 0; i < targets.size(); i++) {
+  for(int j = 0; j < toolchains.size(); j++) {
+    for(int k = 0; k < configurations.size(); k++) {
+      for(int l = 0; l < connectiontypes.size(); l++) {
+
+        def target = targets.get(i)
+        def toolchain = toolchains.keySet().asList().get(j)
+        def compilerLabel = toolchains.get(toolchain)
+        def config = configurations.keySet().asList().get(k)
+        def allowed_configs = configurations.get(config)
+        def connectiontype = connectiontypes.get(l)
+
+        def stepName = "${target} ${toolchain} ${config} ${connectiontype}"
+        if(allowed_configs.contains(connectiontype)) {
+          stepsForParallel[stepName] = buildStep(target, compilerLabel, toolchain, config, connectiontype)
+        }
+      }
+    }
+  }
+}
+
+timestamps {
+  parallel stepsForParallel
+}
+
+def buildStep(target, compilerLabel, toolchain, configName, connectiontype) {
+  return {
+    stage ("${target}_${compilerLabel}_${configName}_${connectiontype}") {
+      node ("${compilerLabel}") {
+        deleteDir()
+        dir("mbed-os-example-client") {
+          checkout scm
+          def config_file = "mbed_app.json"
+
+          if ("${configName}" == "thd") {
+            config_file = "./configs/mesh_thread.json"
+            // Update Thread channel and PANID
+            execute("sed -i 's/\"mbed-mesh-api.thread-config-channel\": 22/\"mbed-mesh-api.thread-config-channel\": 18/' ${config_file}")
+            execute("sed -i 's/\"mbed-mesh-api.thread-config-panid\": \"0x0700\"/\"mbed-mesh-api.thread-config-panid\": \"0xBAAB\"/' ${config_file}")
+   
+          }
+
+          if ("${configName}" == "6lp") {
+            config_file = "./configs/mesh_6lowpan.json"
+
+            // Change channel for HW tests
+            execute ("sed -i 's/\"mbed-mesh-api.6lowpan-nd-channel\": 12/\"mbed-mesh-api.6lowpan-nd-channel\": 17/' ${config_file}")
+
+            //Use PANID filter
+            execute ("sed -i '/6lowpan-nd-channel\":/a \"mbed-mesh-api.6lowpan-nd-panid-filter\": \"0xABBA\",' ${config_file}")
+          }
+
+          if ("${connectiontype}" == "MCR20") {
+            // Replace default rf shield
+            execute ("sed -i 's/\"value\": \"ATMEL\"/\"value\": \"MCR20\"/' ${config_file}")
+          }
+
+          // Copy security.h to build
+          mbed.getSecurityFile()
+
+          // Set mbed-os to revision received as parameter
+          execute ("mbed deploy --protocol ssh")
+          dir("mbed-os") {
+            if (env.MBED_OS_REVISION.matches('pull/\\d+/head')) {
+                // Use mbed-os PR and switch to branch created
+                execute("git fetch origin ${env.MBED_OS_REVISION}:_PR_")
+                execute("git checkout _PR_")
+              } else {
+                execute ("git checkout ${env.MBED_OS_REVISION}")
+            }
+          }
+          execute ("mbed compile --build out/${target}_${toolchain}_${configName}_${connectiontype}/ -m ${target} -t ${toolchain} -c --app-config ${config_file}")
+        }
+        archive '**/mbed-os-example-client.bin'
+        step([$class: 'WsCleanup'])
+      }
+    }
+  }
+}
diff -r 000000000000 -r 694e888fd1b5 LICENSE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,2 @@
+Unless specifically indicated otherwise in a file, files are licensed
+under the Apache 2.0 license, as can be found in: apache-2.0.txt
\ No newline at end of file
diff -r 000000000000 -r 694e888fd1b5 README.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,395 @@
+# Getting started with mbed Client on mbed OS
+
+This is the mbed Client example for mbed OS (we also have one for [Linux](https://github.com/ARMmbed/mbed-client-linux-example)). It demonstrates how to register a device with mbed Device Connector, how to read and write values, and how to deregister. If you are unfamiliar with mbed Device Connector, we recommend that you read [the introduction to the data model](https://docs.mbed.com/docs/mbed-device-connector-web-interfaces/en/latest/#the-mbed-device-connector-data-model) first.
+
+## Required software
+
+* [ARM mbed account](https://developer.mbed.org/account/login/?next=/).
+* [mbed-cli](https://github.com/ARMmbed/mbed-cli) - to build the example programs. To learn how to build mbed OS applications with mbed-cli, see [the user guide](https://github.com/ARMmbed/mbed-cli/blob/master/README.md).
+* [Serial port monitor](https://developer.mbed.org/handbook/SerialPC#host-interface-and-terminal-applications).
+
+The application:
+
+* Connects to network with WiFi, Ethernet, 6LoWPAN ND or Thread connection.
+* Registers with mbed Device Connector.
+* Gives mbed Device Connector access to its resources (read and write).
+* Records the number of clicks on the device’s button and sends the number to mbed Device Connector.
+* Lets you control the blink pattern of the LED on the device (through mbed Device Connector).
+
+## Application setup
+
+To configure the example application:
+
+1. [Select network and board](#select-network-and-board)
+    * [Ethernet](#ethernet)
+    * [Mesh (6LoWPAN and Thread)](#mesh)
+    * [WiFi](#wifi)
+    * [Non listed boards](#non-listed-board-support)
+1. [Set the client credentials](#client-credentials).
+1. [Set up an IP address](#ip-address-setup). This step is optional.
+1. [Change the socket type](#changing-the-socket-type). This step is optional.
+
+### Select network and board
+
+This example supports following hardware-network combinations:
+
+### Ethernet
+
+#### Supported boards
+
+* K64F
+* NUCLEO_F429ZI
+* UBLOX_EVK_ODIN_W2 (use the supplied `configs/eth_v4.json`)
+
+For running the example application using Ethernet, you need:
+
+- An Ethernet cable.
+- An Ethernet connection to the internet.
+
+### Mesh
+
+There are example settings under the configs directory, which provide the easiest way to start with the applications. 
+The [mbed-mesh-api](https://github.com/ARMmbed/mbed-os/tree/master/features/nanostack/FEATURE_NANOSTACK/mbed-mesh-api/mbed_lib.json)
+defines the defaults settings for applications. The most relevant parameters are described in more detail in the following sections.
+
+#### Supported boards
+
+* K64F + NXP MCR20 15.4 shield (mesh `NANOSTACK_FULL` mode)
+* [NUCLEO_F429ZI](https://developer.mbed.org/platforms/ST-Nucleo-F429ZI/) + [X-NUCLEO-IDS01A4](https://github.com/ARMmbed/stm-spirit1-rf-driver) Spirit1 6LoWPAN expansion board (mesh `LOWPAN_ROUTER` mode)
+* NUCLEO_F429ZI + ATMEL AT233 15.4 shield (mesh `LOWPAN_ROUTER` mode)
+* [Supported combinations of board and shields](#supported-combinations-of-board-and-shields)
+
+First, you need to select the RF driver to be used by the 6LoWPAN/Thread stack. 
+
+This example supports these shields:
+
+* [AT86RF233/212B](https://github.com/ARMmbed/atmel-rf-driver)
+* [NXP-MCR20a](https://github.com/ARMmbed/mcr20a-rf-driver)
+* [X-NUCLEO-IDS01A4](https://github.com/ARMmbed/stm-spirit1-rf-driver) (*a.k.a.* Spirit1) radio shields. Check instructions for compilation [here](#compile-configuration-for-spirit1)
+
+To select the radio shield make sure that the `mbed_app.json` file points to the correct radio driver type:
+
+```json
+    "mesh_radio_type": {
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "ATMEL"
+        },
+```
+
+Then you need to enable ARM IPv6/6LoWPAN stack. Edit the `mbed_app.json` file to add `NANOSTACK` feature with the particular configuration of the stack:
+
+```
+"target.features_add": ["NANOSTACK", "LOWPAN_ROUTER", "COMMON_PAL"],
+```
+
+If your connection type is `MESH_THREAD` then you may want to use the `THREAD_ROUTER` configuration:
+
+```
+"target.features_add": ["NANOSTACK", "THREAD_ROUTER", "COMMON_PAL"],
+```
+
+Since 6LoWPAN ND and Thread use IPv6 for connectivity, you need to verify first that you have a working IPv6 connection. 
+To do that, ping the Connector IPv6 address `2607:f0d0:2601:52::20` from your network.
+
+#### Compile configuration for Spirit1
+
+<span class="notes">**Note:** In case you want to use the STM Spirit1 Sub-1 GHz RF expansion board (X-NUCLEO-IDS01A4), you also need to configure its MAC address in the `mbed_app.json` file, for example:</span>
+
+```json
+    "target_overrides": {
+        "*": {
+            "spirit1.mac-address": "{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}"
+        },
+    }
+```
+
+#### Channel settings
+
+The default 2.4GHz channel settings are already defined by the [mbed-mesh-api](https://github.com/ARMmbed/mbed-os/tree/master/features/nanostack/FEATURE_NANOSTACK/mbed-mesh-api) to match the Border Router settings. The application can override these settings by adding them to the `.json` file. For example:
+
+```json
+    "target_overrides": {
+        "*": {
+            "mbed-mesh-api.6lowpan-nd-channel-page": 0,
+            "mbed-mesh-api.6lowpan-nd-channel": 12,
+            "mbed-mesh-api.thread-config-channel-page": 0,
+            "mbed-mesh-api.thread-config-channel": 22
+        }
+    }
+```
+
+For sub-GHz shields ([Spirit1](https://github.com/ARMmbed/stm-spirit1-rf-driver) or AT86RF212B) use the following overrides, **6LoWPAN ND only**:
+
+```json
+"mbed-mesh-api.6lowpan-nd-channel-page": 2,
+"mbed-mesh-api.6lowpan-nd-channel": 1
+```
+
+For more information about the radio shields, see [the related documentation](docs/radio_module_identify.md). 
+ 
+=======
+#### Supported combinations of board and shields
+
+See Mesh-minimal's [Notes on different hardware](https://github.com/ARMmbed/mbed-os-example-mesh-minimal/blob/master/Hardware.md) for known combinations of development boards and RF shields that have been tested with mesh networking stack.
+
+#### Border router
+
+There are two options for border router.
+
+##### Nanostack-border-router
+
+You can configure and build the [nanostack-border-router](https://github.com/ARMmbed/nanostack-border-router) for the 6LoWPAN ND or Thread mode.
+
+#### Thread-specific settings
+
+With Thread, you can change the operating mode of the client from the default router mode to a sleepy end device by adding the following override to the `mbed_app.json` file:
+
+```json
+    "mbed-mesh-api.thread-device-type": "MESH_DEVICE_TYPE_THREAD_SLEEPY_END_DEVICE"
+```
+
+## WiFi
+
+#### Supported boards
+
+* UBLOX_EVK_ODIN_W2. Check instructions for compilation [here](#compile-configuration-for-odin-wifi).
+* K64F + GROVE SEEED shield using [ESP8266](https://en.wikipedia.org/wiki/ESP8266) WiFi module.
+* NUCLEO_F429ZI + GROVE SEEED shield using [ESP8266](https://en.wikipedia.org/wiki/ESP8266) WiFi module.
+
+To run this application using ESP8266 WiFi Interface, you need:
+
+1. An [ESP8266](https://en.wikipedia.org/wiki/ESP8266) WiFi module.
+1. Updated [Espressif Firmware](https://developer.mbed.org/teams/ESP8266/wiki/Firmware-Update).
+1. Mount the WiFi module onto [K64F Grove Shield v2](https://developer.mbed.org/platforms/FRDM-K64F/#supported-seeed-studio-grove-extension).
+1. Attach the shield on your board.
+1. In the `mbed_app.json` file, change:
+
+```json
+    "network-interface": {
+        "help": "options are ETHERNET,WIFI,MESH_LOWPAN_ND,MESH_THREAD.",
+        "value": "WIFI"
+    }
+```
+
+Provide your WiFi SSID and password here and leave `\"` in the beginning and end of your SSID and password (as shown in the example below). Otherwise, the example cannot pick up the SSID and password in correct format.
+
+```json
+    "wifi-ssid": {
+        "help": "WiFi SSID",
+        "value": "\"SSID\""
+    },
+    "wifi-password": {
+        "help": "WiFi Password",
+        "value": "\"Password\""
+    }
+```
+
+<span class="notes">**Note:** Some devices do not support the Grove Shield or use the primary UART for USB communication. On such devices, modify the `mbed_app.json` to use the serial pins connected to the ESP8266.</span>
+
+For example, NUCLEO_F401RE requires a different serial connection:
+
+```json
+    "wifi-tx": {
+        "help": "TX pin for serial connection to external device",
+        "value": "PA_11"
+    },
+    "wifi-rx": {
+        "help": "RX pin for serial connection to external device",
+        "value": "PA_12"
+    }
+```
+
+#### Compile configuration for ODIN WiFi
+
+To compile ODIN WiFi configuration, you need to tell mbed NOT to compile the related files. To do that, set up a `.mbedignore` file. An example file is available in the `configs` folder.     
+
+This should resolve the issue:
+
+```     
+cp configs/eth-wifi-mbedignore ./.mbedignore 
+```    
+ 
+### Non listed board support 
+
+Apart from the listed configurations, this example can work on other mbed OS supported hardware boards which support any of the given network interface including Ethernet, WiFi, Mesh (6LoWPAN) or Thread, provided the configuration fulfills condition that the target hardware has TLS entropy implemented for it. On devices where hardware entropy is not present, TLS is disabled by default. This would result in compile time failures or linking failures.
+
+To learn why entropy is required, read the [TLS Porting guide](https://docs.mbed.com/docs/mbed-os-handbook/en/5.2/advanced/tls_porting/).
+
+Also, the complete example configuration of mbed Client, the selected network interface and mbed OS components must fit into hardware's given memory size (Flash size and RAM size). 
+
+<span class="notes">**Note:** On non-K64F boards, there is no unregistration functionality and button presses are simulated through timer ticks incrementing every 15 seconds.</span>
+
+<span class="notes">**Note:** To see how different targets are built please see the supplied `build_all.sh script`.</span>
+
+
+### Client credentials
+
+To register the application with the mbed Device Connector service, you need to create and set the client side certificate.
+
+1. Go to [mbed Device Connector](https://connector.mbed.com) and log in with your mbed account.
+1. On mbed Device Connector, go to [My Devices > Security credentials](https://connector.mbed.com/#credentials) and click the **Get my device security credentials** to get new credentials for your device.
+1. Replace the contents in the `security.h` file of this project's folder with the content copied above.
+
+### IP address setup
+
+This example uses IPv4 to communicate with the [mbed Device Connector Server](https://api.connector.mbed.com) except for 6LoWPAN ND and Thread. However, you can easily change it to IPv6 by changing the `mbed_app.json` you make:
+
+```
+    "target_overrides": {
+        "*": {
+            "target.features_add": ["LWIP", "NANOSTACK", "COMMON_PAL"],
+            "lwip.ipv4-enabled": false,
+            "lwip.ipv6-enabled": true,
+            "mbed-trace.enable": 0
+        }
+```
+
+by modifying the `ipv4-enabled` or `ipv6-enabled` to `true/false`. Only one should be true.
+
+The example program should automatically get an IP address from the router when connected over Ethernet or WiFi.
+
+If your network does not have DHCP enabled, you have to manually assign a static IP address to the board. We recommend having DHCP enabled to make everything run smoothly.
+
+### Changing the socket type
+
+Your device can connect to mbed Device Connector via UDP or TCP binding mode. The default and only allowed value is UDP for Thread and 6LoWPAN. TCP is the default for other connections. The binding mode cannot be changed in 6LoWPAN ND or Thread mode.
+
+To change the binding mode:
+
+1. In the `simpleclient.h` file, find the parameter `SOCKET_MODE`. The default is `M2MInterface::UDP` for mesh and `M2MInterface::TCP` for others.
+1. To switch to UDP, change it to `M2MInterface::UDP`.
+1. Rebuild and flash the application.
+
+<span class="tips">**Tip:** The instructions in this document remain the same, irrespective of the socket mode you select.</span>
+
+Possible socket types per connection:
+
+| Network  interface                    | UDP   | TCP | 
+| ------------------------------|:-----:|:-----:|
+| Ethernet (IPv4)               |   X   |   X   | 
+| Ethernet (IPv6)               |   X   |       | 
+| Wifi (IPv4)                   |   X   |   X   |
+| Wifi (IPv6) - Not supported   |       |       |
+| 6LoWPAN/Thread (IPv6)         |   X   |       |
+
+## Building the example
+
+To build the example using mbed CLI:
+
+1. Open a command line tool and navigate to the project’s directory.
+
+2. Import this example:
+
+    ```
+    mbed import mbed-os-example-client
+    ```
+
+3. To build the application, select the hardware board and build the toolchain using the command:
+
+    (Specify the config file in the build command, for example for 6LoWPAN)
+
+    ```
+    mbed compile -m K64F -t GCC_ARM -c --app-config configs/6lowpan_Atmel_RF.json
+    ```
+    
+    If you are using either of the following configurations remember to copy .mbedignore as well:
+    
+    ``` 
+    configs/eth_*
+    configs/wifi_*
+    ```
+    
+    ```
+    cp configs/eth-wifi-mbedignore ./.mbedignore 
+    ```
+    
+    mbed CLI builds a binary file under the project’s `BUILD/` directory.
+
+4. Plug the Ethernet cable into the board if you are using Ethernet mode.
+
+5. If you are using 6LoWPAN ND or Thread mode, connect and power on the Border Router first.
+
+6. Plug the micro-USB cable into the **OpenSDA** port. The board is listed as a mass-storage device.
+
+7. Drag the binary `BUILD/K64F/GCC_ARM/mbed-os-example-client.bin` to the board to flash the application.
+
+8. The board is automatically programmed with the new binary. A flashing LED on it indicates that it is still working. When the LED stops blinking, the board is ready to work.
+
+9. Press the **Reset** button on the board to run the program.
+
+10. For verification, continue to the [Monitoring the application](#monitoring-the-application) chapter.
+
+**To build the example using the Online IDE:**
+
+Import this repository in the Online IDE and continue from step 3 onwards.
+
+## Monitoring the application
+
+The application prints debug messages over the serial port, so you can monitor its activity with a serial port monitor. The application uses baud rate 115200.
+
+<span class="notes">**Note:** Instructions to set this up are located [here](https://developer.mbed.org/handbook/SerialPC#host-interface-and-terminal-applications).</span>
+
+After connecting, you should see messages about connecting to mbed Device Connector:
+
+```
+Starting mbed Client example
+[EasyConnect] IPv4 mode
+[EasyConnect] Using Ethernet
+[EasyConnect] Connected to Network successfully
+[EasyConnect] IP address  192.168.8.110
+[EasyConnect] MAC address 5c:cf:7f:86:de:bf
+
+SOCKET_MODE : TCP
+
+Connecting to coap://api.connector.mbed.com:5684
+
+Registered object succesfully!
+```
+
+<span class="notes">**Note:** Device name is the endpoint name you will need later on when [testing the application](https://github.com/ARMmbed/mbed-os-example-client#testing-the-application).</span>
+
+When you press the **SW2** button on your board you should see messages about the value changes:
+
+```
+handle_button_click, new value of counter is 1
+```
+
+## Testing the application
+
+1. Flash the application.
+2. Verify that the registration succeeded. You should see `Registered object successfully!` printed to the serial port.
+3. On mbed Device Connector, go to [My devices > Connected devices](https://connector.mbed.com/#endpoints). Your device should be listed here.
+4. Press the **SW2** button on the device a number of times (make a note of how many times you did that).
+5. Go to [Device Connector > API Console](https://connector.mbed.com/#console).
+6. Click the **Endpoint directory lookups** drop down menu.
+    ![](/docs/img/ep_lookup.PNG) 
+7. In the menu, click **GET** next to **Endpoint's resource representation**. Select your _endpoint_ and _resource-path_. For example, the _endpoint_ is the identifier of your endpoint that can be found in the `security.h` file as `MBED_ENDPOINT_NAME`. Select `3200/0/5501`as a resource path and click **TEST API**. 
+8. The number of times you pressed **SW2** is shown.
+9. Press the **SW3** button to unregister from mbed Device Connector. You should see `Unregistered Object Successfully` printed to the serial port and the LED starts blinking. This will also stop your application. Press the **Reset** button to run the program again.
+
+<span class="notes">**Note:** On non-K64F boards, there is no unregistration functionality and button presses are simulated through timer ticks incrementing every 15 seconds.</span>
+
+![SW2 pressed five times, as shown by the API Console](clicks.png)
+
+<span class="tips">**Tip:** If you get an error, for example `Server Response: 410 (Gone)`, clear your browser's cache, log out, and log back in.</span>
+
+<span class="notes">**Note:** Only GET methods can be executed through [Device Connector > API Console](https://connector.mbed.com/#console). For other methods, check the [mbed Device Connector Quick Start](https://github.com/ARMmbed/mbed-connector-api-node-quickstart).
+
+### Application resources
+
+The application exposes three [resources](https://docs.mbed.com/docs/mbed-device-connector-web-interfaces/en/latest/#the-mbed-device-connector-data-model):
+
+1. `3200/0/5501`. Number of presses of **SW2** (GET).
+2. `3201/0/5850`. Blink function, blinks **LED1** when executed (POST).
+3. `3201/0/5853`. Blink pattern, used by the blink function to determine how to blink. In the format of `1000:500:1000:500:1000:500` (PUT).
+
+To learn how to get notifications when resource 1 changes, or how to use resources 2 and 3, read the [mbed Device Connector Quick Start](https://github.com/ARMmbed/mbed-connector-api-node-quickstart).
+
+## Known issues
+
+### mbed OS 5.4
+
+* [UBLOX_EVK_ODIN_W2]: This example is not compiling with IAR. See [#194](https://github.com/ARMmbed/mbed-os-example-client/issues/194)
+* [NUCLEO_F429ZI]: This example is not compiling with IAR. See [#194](https://github.com/ARMmbed/mbed-os-example-client/issues/194)
+
+Fix for those issues coming via; [mbed-os PR 3920] (https://github.com/ARMmbed/mbed-os/pull/3920)
diff -r 000000000000 -r 694e888fd1b5 X_NUCLEO_IKS01A2.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/X_NUCLEO_IKS01A2.lib	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/ST/code/X_NUCLEO_IKS01A2/#138a7a28bd21
diff -r 000000000000 -r 694e888fd1b5 apache-2.0.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/apache-2.0.txt	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,56 @@
+
+
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+    You must give any other recipients of the Work or Derivative Works a copy of this License; and
+    You must cause any modified files to carry prominent notices stating that You changed the files; and
+    You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+    If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
\ No newline at end of file
diff -r 000000000000 -r 694e888fd1b5 build_all.sh
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build_all.sh	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,61 @@
+#!/bin/bash  
+#
+set -e
+TOOL=GCC_ARM
+
+echo Compiling with $TOOL
+echo Ethernet v4
+cp configs/eth_v4.json ./mbed_app.json
+cp configs/eth-wifi-mbedignore ./.mbedignore
+mbed compile -m K64F -t $TOOL
+cp BUILD/K64F/$TOOL/mbed-os-example-client.bin k64f-$TOOL-eth-v4.bin
+mbed compile -m NUCLEO_F429ZI -t $TOOL
+cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-eth-v4.bin
+mbed compile -m UBLOX_EVK_ODIN_W2 -t $TOOL
+cp ./BUILD/UBLOX_EVK_ODIN_W2/$TOOL/mbed-os-example-client.bin ublox-odin-$TOOL-eth-v4.bin
+
+echo Ethernet v6
+cp configs/eth_v6.json ./mbed_app.json
+cp configs/eth-wifi-mbedignore ./.mbedignore
+mbed compile -m K64F -t $TOOL
+cp BUILD/K64F/$TOOL/mbed-os-example-client.bin k64f-$TOOL-eth-v6.bin
+mbed compile -m NUCLEO_F429ZI -t $TOOL
+cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-eth-v4.bin
+mbed compile -m UBLOX_EVK_ODIN_W2 -t $TOOL
+cp ./BUILD/UBLOX_EVK_ODIN_W2/$TOOL/mbed-os-example-client.bin ublox-odin-$TOOL-eth-v6.bin
+
+echo WIFI - ESP8266 
+cp configs/wifi_esp8266_v4.json ./mbed_app.json
+cp configs/eth-wifi-mbedignore ./.mbedignore
+mbed compile -m K64F -t $TOOL
+cp BUILD/K64F/$TOOL/mbed-os-example-client.bin k64f-$TOOL-esp-wifi-v4.bin
+mbed compile -m NUCLEO_F429ZI -t $TOOL
+cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-esp-wifi-v4.bin
+
+echo WIFI - ODIN for UBLOX_EVK_ODIN_W2
+cp configs/wifi_odin_v4.json ./mbed_app.json
+cp configs/eth-wifi-mbedignore ./.mbedignore
+mbed compile -m UBLOX_EVK_ODIN_W2 -t $TOOL
+cp ./BUILD/UBLOX_EVK_ODIN_W2/$TOOL/mbed-os-example-client.bin ublox-odin-$TOOL-wifi-v4.bin
+
+echo 6-Lowpan builds
+cp configs/mesh_6lowpan.json ./mbed_app.json
+cp configs/mesh-mbedignore ./.mbedignore
+mbed compile -m K64F -t $TOOL
+cp BUILD/K64F/$TOOL/mbed-os-example-client.bin k64f-$TOOL-6lowpan.bin
+mbed compile -m NUCLEO_F429ZI -t $TOOL
+cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-6lowpan.bin
+
+echo 6-Lowpan Sub-1 GHz builds
+cp configs/mesh_6lowpan_subg.json ./mbed_app.json
+cp configs/mesh-mbedignore ./.mbedignore
+mbed compile -m NUCLEO_F429ZI -t $TOOL
+cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-6lowpan-subg.bin
+
+echo Thread builds
+cp configs/mesh_thread.json ./mbed_app.json
+cp configs/mesh-mbedignore ./.mbedignore
+mbed compile -m K64F -t $TOOL
+cp BUILD/K64F/$TOOL/mbed-os-example-client.bin k64f-$TOOL-Thread.bin
+mbed compile -m NUCLEO_F429ZI -t $TOOL
+cp ./BUILD/NUCLEO_F429ZI/$TOOL/mbed-os-example-client.bin f429zi-$TOOL-Thread.bin
diff -r 000000000000 -r 694e888fd1b5 clicks.png
Binary file clicks.png has changed
diff -r 000000000000 -r 694e888fd1b5 easy-connect.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/easy-connect.lib	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/easy-connect/#bf821b0695ccada3620a6091503eb53a2a1ac3c8
diff -r 000000000000 -r 694e888fd1b5 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,634 @@
+/*
+ * Copyright (c) 2015, 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+ /* 
+  * Modified by STMicroelectronics to support X-NUCLEO-IKS01A1/2 environmental 
+  * sensors on top of Nucleo-F429ZI/Nucleo-L476RG.
+ */
+ 
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include "simpleclient.h"
+#include <string>
+#include <sstream>
+#include <vector>
+#include "mbed-trace/mbed_trace.h"
+#include "mbedtls/entropy_poll.h"
+
+#include "security.h"
+
+#include "mbed.h"
+
+// easy-connect compliancy, it has 2 sets of wifi pins we have only one
+#define MBED_CONF_APP_ESP8266_TX MBED_CONF_APP_WIFI_TX
+#define MBED_CONF_APP_ESP8266_RX MBED_CONF_APP_WIFI_RX
+#include "easy-connect/easy-connect.h"
+
+#ifdef TARGET_STM
+#define RED_LED (LED3)
+#define GREEN_LED (LED1)
+#define BLUE_LED (LED2)
+#define LED_ON (1)		     
+#else // !TARGET_STM
+#define RED_LED (LED1)
+#define GREEN_LED (LED2)
+#define BLUE_LED (LED3)			     
+#define LED_ON (0) 
+#endif // !TARGET_STM
+#define LED_OFF (!LED_ON)
+
+// Status indication
+DigitalOut red_led(RED_LED);
+DigitalOut green_led(GREEN_LED);
+DigitalOut blue_led(BLUE_LED);
+
+Ticker status_ticker;
+void blinky() {
+    green_led = !green_led;
+}
+
+// These are example resource values for the Device Object
+struct MbedClientDevice device = {
+    "Manufacturer_String",      // Manufacturer
+    "Type_String",              // Type
+    "ModelNumber_String",       // ModelNumber
+    "SerialNumber_String"       // SerialNumber
+};
+
+// Instantiate the class which implements LWM2M Client API (from simpleclient.h)
+MbedClient mbed_client(device);
+
+
+// In case of K64F board , there is button resource available
+// to change resource value and unregister
+#ifdef TARGET_K64F
+// Set up Hardware interrupt button.
+InterruptIn obs_button(SW2);
+InterruptIn unreg_button(SW3);
+#else
+//In non K64F boards , set up a timer to simulate updating resource,
+// there is no functionality to unregister.
+Ticker timer;
+#endif
+
+/*
+ * Arguments for running "blink" in it's own thread.
+ */
+class BlinkArgs {
+public:
+    BlinkArgs() {
+        clear();
+    }
+    void clear() {
+        position = 0;
+        blink_pattern.clear();
+    }
+    uint16_t position;
+    std::vector<uint32_t> blink_pattern;
+};
+
+/*
+ * The Led contains one property (pattern) and a function (blink).
+ * When the function blink is executed, the pattern is read, and the LED
+ * will blink based on the pattern.
+ */
+class LedResource {
+public:
+    LedResource() {
+        // create ObjectID with metadata tag of '3201', which is 'digital output'
+        led_object = M2MInterfaceFactory::create_object("3201");
+        M2MObjectInstance* led_inst = led_object->create_object_instance();
+
+        // 5853 = Multi-state output
+        M2MResource* pattern_res = led_inst->create_dynamic_resource("5853", "Pattern",
+            M2MResourceInstance::STRING, false);
+        // read and write
+        pattern_res->set_operation(M2MBase::GET_PUT_ALLOWED);
+        // set initial pattern (toggle every 200ms. 7 toggles in total)
+        pattern_res->set_value((const uint8_t*)"500:500:500:500:500:500:500", 27);
+
+        // there's not really an execute LWM2M ID that matches... hmm...
+        M2MResource* led_res = led_inst->create_dynamic_resource("5850", "Blink",
+            M2MResourceInstance::OPAQUE, false);
+        // we allow executing a function here...
+        led_res->set_operation(M2MBase::POST_ALLOWED);
+        // when a POST comes in, we want to execute the led_execute_callback
+        led_res->set_execute_function(execute_callback(this, &LedResource::blink));
+        // Completion of execute function can take a time, that's why delayed response is used
+        led_res->set_delayed_response(true);
+        blink_args = new BlinkArgs();
+
+        // betzw: Start blinky thread
+        blinky_thread.start(callback(this, &LedResource::do_blink)); // betzw - NOTE: threads can only be started once!
+    }
+
+    ~LedResource() {
+        delete blink_args;
+    }
+
+    M2MObject* get_object() {
+        return led_object;
+    }
+
+    void blink(void *argument) {
+        // read the value of 'Pattern'
+        status_ticker.detach();
+        green_led = LED_OFF;
+
+        M2MObjectInstance* inst = led_object->object_instance();
+        M2MResource* res = inst->resource("5853");
+        // Clear previous blink data
+        blink_args->clear();
+
+        // values in mbed Client are all buffers, and we need a vector of int's
+        uint8_t* buffIn = NULL;
+        uint32_t sizeIn;
+        res->get_value(buffIn, sizeIn);
+
+        // turn the buffer into a string, and initialize a vector<int> on the heap
+        std::string s((char*)buffIn, sizeIn);
+        free(buffIn);
+        printf("led_execute_callback pattern=%s\n", s.c_str());
+
+        // our pattern is something like 500:200:500, so parse that
+        std::size_t found = s.find_first_of(":");
+        while (found!=std::string::npos) {
+            blink_args->blink_pattern.push_back(atoi((const char*)s.substr(0,found).c_str()));
+            s = s.substr(found+1);
+            found=s.find_first_of(":");
+            if(found == std::string::npos) {
+                blink_args->blink_pattern.push_back(atoi((const char*)s.c_str()));
+            }
+        }
+        // check if POST contains payload
+        if (argument) {
+            M2MResource::M2MExecuteParameter* param = (M2MResource::M2MExecuteParameter*)argument;
+            String object_name = param->get_argument_object_name();
+            uint16_t object_instance_id = param->get_argument_object_instance_id();
+            String resource_name = param->get_argument_resource_name();
+            int payload_length = param->get_argument_value_length();
+            uint8_t* payload = param->get_argument_value();
+            printf("Resource: %s/%d/%s executed\n", object_name.c_str(), object_instance_id, resource_name.c_str());
+            printf("Payload: %.*s\n", payload_length, payload);
+        }
+        // do_blink is called with the vector, and starting at -1
+        // blinky_thread.start(callback(this, &LedResource::do_blink)); // betzw - NOTE: threads can only be started once!
+        blinky_thread.signal_set(1);
+    }
+
+private:
+    M2MObject* led_object;
+    Thread blinky_thread;
+    BlinkArgs *blink_args;
+    void do_blink() {
+    	blinky_thread.signal_wait(0);
+        for (;;) {
+            // blink the LED
+            red_led = !red_led;
+            // up the position, if we reached the end of the vector
+            if (blink_args->position >= blink_args->blink_pattern.size()) {
+                // send delayed response after blink is done
+                M2MObjectInstance* inst = led_object->object_instance();
+                M2MResource* led_res = inst->resource("5850");
+                led_res->send_delayed_post_response();
+                red_led = LED_OFF;
+                status_ticker.attach_us(blinky, 250000);
+                // betzw - WAS: return;
+                blinky_thread.signal_wait(0);
+                continue;
+            }
+            // Wait requested time, then continue processing the blink pattern from next position.
+            Thread::wait(blink_args->blink_pattern.at(blink_args->position));
+            blink_args->position++;
+        }
+    }
+};
+
+/*
+ * The button contains one property (click count).
+ * When `handle_button_click` is executed, the counter updates.
+ */
+class ButtonResource {
+public:
+    ButtonResource(): counter(0) {
+        // create ObjectID with metadata tag of '3200', which is 'digital input'
+        btn_object = M2MInterfaceFactory::create_object("3200");
+        M2MObjectInstance* btn_inst = btn_object->create_object_instance();
+        // create resource with ID '5501', which is digital input counter
+        M2MResource* btn_res = btn_inst->create_dynamic_resource("5501", "Button",
+            M2MResourceInstance::INTEGER, true /* observable */);
+        // we can read this value
+        btn_res->set_operation(M2MBase::GET_ALLOWED);
+        // set initial value (all values in mbed Client are buffers)
+        // to be able to read this data easily in the Connector console, we'll use a string
+        btn_res->set_value((uint8_t*)"0", 1);
+    }
+
+    ~ButtonResource() {
+    }
+
+    M2MObject* get_object() {
+        return btn_object;
+    }
+
+    /*
+     * When you press the button, we read the current value of the click counter
+     * from mbed Device Connector, then up the value with one.
+     */
+    void handle_button_click() {
+        if (mbed_client.register_successful()) {
+            M2MObjectInstance* inst = btn_object->object_instance();
+            M2MResource* res = inst->resource("5501");
+
+            // up counter
+            counter++;
+    #if defined(TARGET_K64F) || defined(TARGET_NUCLEO_F429ZI) || defined(TARGET_NUCLEO_L476RG)
+            printf("handle_button_click, new value of counter is %d\r\n", counter);
+    #else
+            printf("simulate button_click, new value of counter is %d\n", counter);
+    #endif
+            // serialize the value of counter as a string, and tell connector
+            char buffer[20];
+            int size = sprintf(buffer,"%d",counter);
+            res->set_value((uint8_t*)buffer, size);
+        } else {
+            printf("simulate button_click, device not registered\n");
+        }
+    }
+
+private:
+    M2MObject* btn_object;
+    uint16_t counter;
+};
+
+class BigPayloadResource {
+public:
+    BigPayloadResource() {
+        big_payload = M2MInterfaceFactory::create_object("1000");
+        M2MObjectInstance* payload_inst = big_payload->create_object_instance();
+        M2MResource* payload_res = payload_inst->create_dynamic_resource("1", "BigData",
+            M2MResourceInstance::STRING, true /* observable */);
+        payload_res->set_operation(M2MBase::GET_PUT_ALLOWED);
+        payload_res->set_value((uint8_t*)"0", 1);
+        payload_res->set_incoming_block_message_callback(
+                    incoming_block_message_callback(this, &BigPayloadResource::block_message_received));
+        payload_res->set_outgoing_block_message_callback(
+                    outgoing_block_message_callback(this, &BigPayloadResource::block_message_requested));
+    }
+
+    M2MObject* get_object() {
+        return big_payload;
+    }
+
+    void block_message_received(M2MBlockMessage *argument) {
+        if (argument) {
+            if (M2MBlockMessage::ErrorNone == argument->error_code()) {
+                if (argument->is_last_block()) {
+                    printf("Last block received\n");
+                }
+                printf("Block number: %d\n", argument->block_number());
+                // First block received
+                if (argument->block_number() == 0) {
+                    // Store block
+                // More blocks coming
+                } else {
+                    // Store blocks
+                }
+            } else {
+                printf("Error when receiving block message!  - EntityTooLarge\n");
+            }
+            printf("Total message size: %" PRIu32 "\n", argument->total_message_size());
+        }
+    }
+
+    void block_message_requested(const String& resource, uint8_t *&/*data*/, uint32_t &/*len*/) {
+        printf("GET request received for resource: %s\n", resource.c_str());
+        // Copy data and length to coap response
+    }
+
+private:
+    M2MObject*  big_payload;
+};
+
+/* STMicroelectronics IKS01A1/2 code  - BEGIN */
+
+#define IKS01A2  // comment out for IKS01A1
+
+#ifdef IKS01A2
+#define __ARCHDEP__TYPES  // fix to a typedef redefinition with LWIP stack
+typedef unsigned char u8_t;
+typedef unsigned short int u16_t;
+//typedef unsigned int u32_t;  // conflictiong definition
+typedef int i32_t;
+typedef short int i16_t;
+typedef signed char i8_t;
+#include "XNucleoIKS01A2.h"
+#else
+#include "XNucleoIKS01A1.h"
+#endif
+
+#define SENSOR_OK	0
+#define DEFAULT_ENV_POLLING_PERIOD_MS	5000   // default polling time 
+
+class EnvResource {
+public:
+	EnvResource() {
+#ifdef IKS01A2
+		p_mems_expansion_board = XNucleoIKS01A2::instance(IKS01A2_PIN_I2C_SDA,IKS01A2_PIN_I2C_SCL);
+#else
+		p_mems_expansion_board = XNucleoIKS01A1::instance(IKS01A1_PIN_I2C_SDA,IKS01A1_PIN_I2C_SCL);
+#endif
+		
+        temp_object = M2MInterfaceFactory::create_object("3303");
+        temp_inst = temp_object->create_object_instance();
+        temp_res = temp_inst->create_dynamic_resource("5700", "Temperature",
+            M2MResourceInstance::FLOAT, true);	// observable
+        // we can only read this value
+	    temp_res->set_operation(M2MBase::GET_ALLOWED);
+		temp_res->set_value((uint8_t*)"20.0", 4);
+		
+		hum_object = M2MInterfaceFactory::create_object("3304");
+        hum_inst = hum_object->create_object_instance();
+        hum_res = hum_inst->create_dynamic_resource("5700", "Humidity",
+            M2MResourceInstance::FLOAT, true);	// observable
+        // we can only read this value
+	    hum_res->set_operation(M2MBase::GET_ALLOWED);
+		hum_res->set_value((uint8_t*)"50.0", 4);
+		
+#ifdef IKS01A2 // need to explicitly enable the sensor with IKS01A2
+		HTS221Sensor *hum_temp = p_mems_expansion_board->ht_sensor;
+		hum_temp->enable();
+#endif
+		
+		press_object = M2MInterfaceFactory::create_object("3300");
+        press_inst = press_object->create_object_instance();
+        press_res = press_inst->create_dynamic_resource("5700", "Pressure",
+            M2MResourceInstance::FLOAT, true);	// observable
+        // we can only read this value
+	    press_res->set_operation(M2MBase::GET_ALLOWED);
+		press_res->set_value((uint8_t*)"5000", 4);
+
+#ifdef IKS01A2 // need to explicitly enable the sensor with IKS01A2
+		LPS22HBSensor *press_temp = p_mems_expansion_board->pt_sensor;
+		press_temp->enable();
+#endif
+		
+        timer_res = press_inst->create_dynamic_resource("5603", "PollingPeriodMs",  // one polling time for all env values, associated to humidity
+		    M2MResourceInstance::INTEGER, false);	// not observable
+        // we can read/wr this value
+	    timer_res->set_operation(M2MBase::GET_PUT_ALLOWED);
+        timer_res->set_value((uint8_t*)"1000",4); // default 1s polling
+		
+	}
+	
+	M2MObject* get_temp_object() {
+        return temp_object;
+	}
+	
+	M2MObject* get_hum_object() {
+        return hum_object;
+	}
+	
+	M2MObject* get_press_object() {
+        return press_object;
+	}
+	
+	int get_polling_period() {
+		return timer_res->get_value_int();
+	}
+
+	void update_resources() {
+	   float temp;
+	   float hum;
+	   float press;
+	   int err;
+	   
+		err = p_mems_expansion_board->ht_sensor->get_temperature(&temp);
+       if ( err != SENSOR_OK) {  
+			printf ("= * ERROR %d get_temperature\n\r", err);
+			temp = 20.0;
+			red_led = 1;
+		} else {
+			printf ("Temp C: %f\n\r", temp);
+			red_led = 0;
+		}
+		
+		err = p_mems_expansion_board->ht_sensor->get_humidity(&hum);
+        if ( err != SENSOR_OK) {  
+	       printf ("= * ERROR %d get_humidity\n\r", err);
+		   hum= 50.0;
+		   red_led = 1;
+		} else {
+		   printf ("Humidity %: %f\n\r", hum);
+		   red_led = 0;
+		}
+		
+		err = p_mems_expansion_board->pt_sensor->get_pressure(&press);
+        if ( err != SENSOR_OK) {  
+	      printf ("= * ERROR %d get_pressure\n\r", err);
+		  red_led = 1;
+	      return;
+        } else {
+	      printf ("Pressure mBar: %f\n\r", press); 
+		  red_led = 0;
+        }
+		
+        stringstream ss_temp;
+	    ss_temp << temp;
+        std::string stringified = ss_temp.str();
+        temp_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
+	  
+	    stringstream ss_hum;
+	    ss_hum << hum;
+        stringified = ss_hum.str();
+        hum_res->set_value((uint8_t*)stringified.c_str(), stringified.length());
+	  
+	    stringstream ss_press;
+	    ss_press << press;
+        stringified = ss_press.str();
+        press_res->set_value((uint8_t*)stringified.c_str(), stringified.length()); 
+    }
+	
+private:
+ 
+   M2MObject* temp_object;
+   M2MObjectInstance* temp_inst;
+   M2MResource* temp_res;
+   
+   M2MObject* hum_object;
+   M2MObjectInstance* hum_inst;
+   M2MResource* hum_res;
+   
+   M2MObject* press_object;
+   M2MObjectInstance* press_inst;
+   M2MResource* press_res;
+   
+   M2MResource* timer_res;
+	
+#ifdef IKS01A2
+   XNucleoIKS01A2 *p_mems_expansion_board;
+#else
+   XNucleoIKS01A1 *p_mems_expansion_board; 
+#endif
+
+};
+
+
+/* STMicroelectronics IKS01A1/2 code  - END */
+
+// Network interaction must be performed outside of interrupt context
+Semaphore updates(0);
+volatile bool registered = false;
+volatile bool clicked = false;
+osThreadId mainThread;
+
+void unregister() {
+    registered = false;
+	blue_led = 0;
+    updates.release();
+}
+
+void button_clicked() {
+    clicked = true;
+}
+
+// debug printf function
+void trace_printer(const char* str) {
+    printf("%s\r\n", str);
+}
+
+// Entry point to the program
+int main() {
+
+    unsigned int seed;
+    size_t len;
+
+#ifdef MBEDTLS_ENTROPY_HARDWARE_ALT
+    // Used to randomize source port
+    mbedtls_hardware_poll(NULL, (unsigned char *) &seed, sizeof seed, &len);
+
+#elif defined MBEDTLS_TEST_NULL_ENTROPY
+
+#warning "mbedTLS security feature is disabled. Connection will not be secure !! Implement proper hardware entropy for your selected hardware."
+    // Used to randomize source port
+    mbedtls_null_entropy_poll( NULL,(unsigned char *) &seed, sizeof seed, &len);
+
+#else
+
+#error "This hardware does not have entropy, endpoint will not register to Connector.\
+You need to enable NULL ENTROPY for your application, but if this configuration change is made then no security is offered by mbed TLS.\
+Add MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY in mbed_app.json macros to register your endpoint."
+
+#endif
+
+    srand(seed);
+    red_led = LED_OFF;
+    blue_led = LED_OFF;
+
+    status_ticker.attach_us(blinky, 250000);
+    // Keep track of the main thread
+    mainThread = osThreadGetId();
+
+    printf("\nStarting mbed Client example\n");
+
+    mbed_trace_init();
+    mbed_trace_print_function_set(trace_printer);
+    mbed_trace_config_set(TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN);
+
+    NetworkInterface* network = easy_connect(true);
+    if(network == NULL) {
+        printf("\nConnection to Network Failed - exiting application...\n");
+        return -1;
+    }
+
+    // we create our button and LED resources
+    ButtonResource button_resource;
+    LedResource led_resource;
+    BigPayloadResource big_payload_resource;
+	
+	// STMicroelectronics IKS01A1/2
+	EnvResource env_resource;
+
+	
+#ifdef TARGET_K64F
+    // On press of SW3 button on K64F board, example application
+    // will call unregister API towards mbed Device Connector
+    //unreg_button.fall(&mbed_client,&MbedClient::test_unregister);
+    unreg_button.fall(&unregister);
+
+    // Observation Button (SW2) press will send update of endpoint resource values to connector
+    obs_button.fall(&button_clicked);
+#elif defined(TARGET_NUCLEO_F429ZI) || defined (TARGET_NUCLEO_L476RG)
+    InterruptIn user_button(USER_BUTTON);
+	user_button.fall(&button_clicked);
+#else
+    // Send update of endpoint resource values to connector every 15 seconds periodically
+    timer.attach(&button_clicked, 15.0);
+#endif
+
+    // Create endpoint interface to manage register and unregister
+    mbed_client.create_interface(MBED_SERVER_ADDRESS, network);
+
+    // Create Objects of varying types, see simpleclient.h for more details on implementation.
+    M2MSecurity* register_object = mbed_client.create_register_object(); // server object specifying connector info
+    M2MDevice*   device_object   = mbed_client.create_device_object();   // device resources object
+
+    // Create list of Objects to register
+    M2MObjectList object_list;
+
+    // Add objects to list
+    object_list.push_back(device_object);
+    object_list.push_back(button_resource.get_object());
+    object_list.push_back(led_resource.get_object());
+    object_list.push_back(big_payload_resource.get_object());
+	
+	// STMicroelectronics IKS01A1/2
+	object_list.push_back(env_resource.get_temp_object());
+	object_list.push_back(env_resource.get_hum_object());
+	object_list.push_back(env_resource.get_press_object());
+	
+    // Set endpoint registration object
+    mbed_client.set_register_object(register_object);
+
+    // Register with mbed Device Connector
+    mbed_client.test_register(register_object, object_list);
+
+
+	// STMicroelectronics IKS01A1/2
+	// wait for registration before getting data
+	while (!mbed_client.register_successful())  {
+		Thread::wait(500);
+	}
+	registered = true;
+	blue_led = 1;
+	printf ("\r\nRegistered! Now getting sensor data\r\n\n");
+		
+    while (true) {
+           	  
+		int timer_val = env_resource.get_polling_period();
+		env_resource.update_resources();
+
+        if(clicked) {
+            clicked = false;
+            button_resource.handle_button_click();
+        }
+		Thread::wait(timer_val);
+    }
+
+    mbed_client.test_unregister();
+    status_ticker.detach();
+}
diff -r 000000000000 -r 694e888fd1b5 mbed-client.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-client.lib	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-client/#31e5ce203cc0f3e5c5e3fe5e01b396d7fe2ee8f9
diff -r 000000000000 -r 694e888fd1b5 mbed-os.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#6e0d01cd13e8aca7bf4d697c3699ec9225386881
diff -r 000000000000 -r 694e888fd1b5 mbed_app.json
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_app.json	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,26 @@
+{
+    "config": {
+        "network-interface":{
+            "help": "Options are ETHERNET, WIFI_ESP8266, WIFI_ODIN, MESH_LOWPAN_ND, MESH_THREAD",
+            "value": "MESH_LOWPAN_ND"
+        },
+        "mesh_radio_type": {
+            "help": "options are ATMEL, MCR20, SPIRIT1",
+            "value": "SPIRIT1"
+        }
+    },
+    "macros": ["MBEDTLS_USER_CONFIG_FILE=\"mbedtls_mbed_client_config.h\""],
+    "target_overrides": {
+        "*": {
+            "spirit1.mac-address": "{0x51, 0xc0, 0x7a, 0xca, 0x90, 0x71, 0x77, 0xa1}",
+            "target.features_add": ["NANOSTACK", "LOWPAN_ROUTER", "COMMON_PAL"],
+            "platform.stdio-baud-rate": 115200,
+            "platform.stdio-convert-newlines": true,
+            "mbed-mesh-api.6lowpan-nd-security-mode": "PSK",
+            "mbed-mesh-api.6lowpan-nd-channel-page": 2,
+            "mbed-mesh-api.6lowpan-nd-channel": 1,
+            "mbed-mesh-api.6lowpan-nd-channel-mask": "(1<<1)",
+            "mbed-trace.enable": 0
+        }
+    }
+}
diff -r 000000000000 -r 694e888fd1b5 mbed_client_config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_client_config.h	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef MBED_CLIENT_CONFIG_H
+#define MBED_CLIENT_CONFIG_H
+
+
+// Defines the number of times client should try re-connection towards
+// Server in case of connectivity loss , also defines the number of CoAP
+// re-transmission attempts.Default value is 3
+#define M2M_CLIENT_RECONNECTION_COUNT		3
+
+// Defines the interval (in seconds) in which client should try re-connection towards
+// Server in case of connectivity loss , also use the same interval for CoAP
+// re-transmission attempts. Default value is 5 seconds
+#define M2M_CLIENT_RECONNECTION_INTERVAL	5
+
+// Defines the keep-alive interval (in seconds) in which client should send keep alive
+// pings to server while connected through TCP mode. Default value is 300 seconds
+#define M2M_CLIENT_TCP_KEEPALIVE_TIME 		300
+
+// Defines the maximum CoAP messages that client can hold, maximum value is 6
+#define SN_COAP_DUPLICATION_MAX_MSGS_COUNT  2
+
+// Defines the size of blockwise CoAP messages that client can handle.
+// The values that can be defined uust be 2^x and x is at least 4.
+// Suitable values: 0, 16, 32, 64, 128, 256, 512 and 1024
+#define SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE  512
+
+// Many pure LWM2M servers doen't accept 'obs' text in registration message.
+// While using Client against such servers, this flag can be set to define to
+// disable client sending 'obs' text for observable resources.
+#undef COAP_DISABLE_OBS_FEATURE
+
+// Disable Bootstrap functionality in client in order to reduce code size, if bootstrap
+// functionality is not required.
+#undef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
+
+#endif // MBED_CLIENT_CONFIG_H
+
diff -r 000000000000 -r 694e888fd1b5 mbedtls_mbed_client_config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbedtls_mbed_client_config.h	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,111 @@
+/**
+ *  Minimal configuration for using mbedtls as part of mbed-client
+ *
+ *  NOTE! This is an optimized, minimal configuration for mbed Client.
+ *  We know it works with mbed Client but if you want to add more
+ *  services/communications to the application yourself - please ensure
+ *  you update this configuration accordingly. The default configuration
+ *  can be found from mbedTLS Github:
+ *
+ *  https://github.com/ARMmbed/mbedtls/blob/development/include/mbedtls/config.h
+ *
+ *
+ *  Copyright (C) 2006-2016, ARM Limited, All Rights Reserved
+ *  SPDX-License-Identifier: Apache-2.0
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"); you may
+ *  not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  This file is part of mbed TLS (https://tls.mbed.org)
+ */
+
+
+#ifndef MBEDTLS_CUSTOM_CONFIG_H
+#define MBEDTLS_CUSTOM_CONFIG_H
+
+/* System support */
+#define MBEDTLS_HAVE_ASM
+
+/* mbed TLS feature support */
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_NIST_OPTIM
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_PROTO_DTLS
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#define MBEDTLS_SSL_EXPORT_KEYS
+
+/* mbed TLS modules */
+#define MBEDTLS_AES_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_MD_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_SHA256_C
+#define MBEDTLS_SSL_COOKIE_C
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+
+// XXX mbedclient needs these: mbedtls_x509_crt_free, mbedtls_x509_crt_init, mbedtls_x509_crt_parse
+#define MBEDTLS_X509_USE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+
+// XXX: clean these up!!
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_GCM_C
+
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_X509_CRT_PARSE_C
+
+// Remove RSA, save 20KB at total
+#undef MBEDTLS_RSA_C
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+
+// Remove error messages, save 10KB of ROM
+#undef MBEDTLS_ERROR_C
+
+// Remove selftesting and save 11KB of ROM
+#undef MBEDTLS_SELF_TEST
+
+// Reduces ROM size by 30 kB
+#undef MBEDTLS_ERROR_STRERROR_DUMMY
+#undef MBEDTLS_VERSION_FEATURES
+#undef MBEDTLS_DEBUG_C
+
+// needed for parsing the certificates
+#define MBEDTLS_PEM_PARSE_C
+// dep of the previous
+#define MBEDTLS_BASE64_C
+
+// Reduce IO buffer to save RAM, default is 16KB
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 2048
+
+// define to save 8KB RAM at the expense of ROM
+#undef MBEDTLS_AES_ROM_TABLES
+
+// Save ROM and a few bytes of RAM by specifying our own ciphersuite list
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
+
+#include "mbedtls/check_config.h"
+
+#endif /* MBEDTLS_CUSTOM_CONFIG_H */
diff -r 000000000000 -r 694e888fd1b5 pal.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pal.lib	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/pal/#60ce64d5ec358b3cf8bb492b95c5da7dad9254ca
diff -r 000000000000 -r 694e888fd1b5 security.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/security.h	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __SECURITY_H__
+#define __SECURITY_H__
+ 
+#include <inttypes.h>
+ 
+#define MBED_DOMAIN "DOMAIN"
+#define MBED_ENDPOINT_NAME "ENDPOINT_NAME"
+ 
+const uint8_t SERVER_CERT[] = "-----BEGIN CERTIFICATE-----\r\n"
+"-----END CERTIFICATE-----\r\n";
+ 
+const uint8_t CERT[] = "-----BEGIN CERTIFICATE-----\r\n"
+"-----END CERTIFICATE-----\r\n";
+ 
+const uint8_t KEY[] = "-----BEGIN PRIVATE KEY-----\r\n"
+"-----END PRIVATE KEY-----\r\n";
+ 
+#endif //__SECURITY_H__
+ 
+#error "You need to get security.h credentials from connector.mbed.com and replace the content of this security.h file"
diff -r 000000000000 -r 694e888fd1b5 simpleclient.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simpleclient.h	Thu Jan 25 18:00:04 2018 +0100
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SIMPLECLIENT_H__
+#define __SIMPLECLIENT_H__
+
+#include "mbed-client/m2minterfacefactory.h"
+#include "mbed-client/m2mdevice.h"
+#include "mbed-client/m2minterfaceobserver.h"
+#include "mbed-client/m2minterface.h"
+#include "mbed-client/m2mobject.h"
+#include "mbed-client/m2mobjectinstance.h"
+#include "mbed-client/m2mresource.h"
+#include "mbed-client/m2mconfig.h"
+#include "mbed-client/m2mblockmessage.h"
+#include "security.h"
+#include "mbed.h"
+
+#define ETHERNET        1
+#define WIFI            2
+#define MESH_LOWPAN_ND  3
+#define MESH_THREAD     4
+#define ATMEL           5
+#define MCR20           6
+#define SPIRIT1         7
+#define EFR32           8
+
+#define STRINGIFY(s) #s
+
+// Check if using mesh networking, define helper
+#if MBED_CONF_APP_NETWORK_INTERFACE == MESH_LOWPAN_ND
+    #define MESH
+#elif MBED_CONF_APP_NETWORK_INTERFACE == MESH_THREAD
+    #define MESH
+#endif
+
+#if defined (MESH) || (MBED_CONF_LWIP_IPV6_ENABLED==true)
+    // Mesh is always IPV6 - also WiFi and ETH can be IPV6 if IPV6 is enabled
+    M2MInterface::NetworkStack NETWORK_STACK = M2MInterface::LwIP_IPv6;
+#else
+    // Everything else - we assume it's IPv4
+    M2MInterface::NetworkStack NETWORK_STACK = M2MInterface::LwIP_IPv4;
+#endif
+
+//Select binding mode: UDP or TCP -- note - Mesh networking is IPv6 UDP ONLY
+#ifdef MESH
+    M2MInterface::BindingMode SOCKET_MODE = M2MInterface::UDP;
+#else
+    // WiFi or Ethernet supports both - TCP by default to avoid
+    // NAT problems, but UDP will also work - IF you configure
+    // your network right.
+    M2MInterface::BindingMode SOCKET_MODE = M2MInterface::TCP;
+#endif
+
+
+// MBED_DOMAIN and MBED_ENDPOINT_NAME come
+// from the security.h file copied from connector.mbed.com
+
+struct MbedClientDevice {
+    const char* Manufacturer;
+    const char* Type;
+    const char* ModelNumber;
+    const char* SerialNumber;
+};
+
+/*
+* Wrapper for mbed client stack that handles all callbacks, error handling, and
+* other shenanigans to make the mbed client stack easier to use.
+*
+* The end user should only have to care about configuring the parameters at the
+* top of this file and making sure they add the security.h file correctly.
+* To add resources you can copy the _TODO__ function and add as many instances as
+* you want.
+*
+*/
+class MbedClient: public M2MInterfaceObserver {
+public:
+
+    // constructor for MbedClient object, initialize private variables
+    MbedClient(struct MbedClientDevice device) {
+        _interface = NULL;
+        _bootstrapped = false;
+        _error = false;
+        _registered = false;
+        _unregistered = false;
+        _register_security = NULL;
+        _value = 0;
+        _object = NULL;
+        _device = device;
+    }
+
+    // de-constructor for MbedClient object, you can ignore this
+    ~MbedClient() {
+        if(_interface) {
+            delete _interface;
+        }
+        if(_register_security){
+            delete _register_security;
+        }
+    }
+
+    // debug printf function
+    void trace_printer(const char* str) {
+        printf("\r\n%s\r\n", str);
+    }
+
+    /*
+    *  Creates M2MInterface using which endpoint can
+    *  setup its name, resource type, life time, connection mode,
+    *  Currently only LwIPv4 is supported.
+    */
+    void create_interface(const char *server_address,
+                          void *handler=NULL) {
+    // Randomizing listening port for Certificate mode connectivity
+    _server_address = server_address;
+    uint16_t port = 0; // Network interface will randomize with port 0
+
+    // create mDS interface object, this is the base object everything else attaches to
+    _interface = M2MInterfaceFactory::create_interface(*this,
+                                                      MBED_ENDPOINT_NAME,       // endpoint name string
+                                                      "test",                   // endpoint type string
+                                                      100,                      // lifetime
+                                                      port,                     // listen port
+                                                      MBED_DOMAIN,              // domain string
+                                                      SOCKET_MODE,              // binding mode
+                                                      NETWORK_STACK,            // network stack
+                                                      "");                      // context address string
+    const char *binding_mode = (SOCKET_MODE == M2MInterface::UDP) ? "UDP" : "TCP";
+    printf("\r\nSOCKET_MODE : %s\r\n", binding_mode);
+    printf("Connecting to %s\r\n", server_address);
+
+    if(_interface) {
+        _interface->set_platform_network_handler(handler);
+    }
+
+    }
+
+    /*
+    *  check private variable to see if the registration was sucessful or not
+    */
+    bool register_successful() {
+        return _registered;
+    }
+
+    /*
+    *  check private variable to see if un-registration was sucessful or not
+    */
+    bool unregister_successful() {
+        return _unregistered;
+    }
+
+    /*
+    *  Creates register server object with mbed device server address and other parameters
+    *  required for client to connect to mbed device server.
+    */
+    M2MSecurity* create_register_object() {
+        // create security object using the interface factory.
+        // this will generate a security ObjectID and ObjectInstance
+        M2MSecurity *security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer);
+
+        // make sure security ObjectID/ObjectInstance was created successfully
+        if(security) {
+            // Add ResourceID's and values to the security ObjectID/ObjectInstance
+            security->set_resource_value(M2MSecurity::M2MServerUri, _server_address);
+            security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate);
+            security->set_resource_value(M2MSecurity::ServerPublicKey, SERVER_CERT, sizeof(SERVER_CERT) - 1);
+            security->set_resource_value(M2MSecurity::PublicKey, CERT, sizeof(CERT) - 1);
+            security->set_resource_value(M2MSecurity::Secretkey, KEY, sizeof(KEY) - 1);
+        }
+        return security;
+    }
+
+    /*
+    * Creates device object which contains mandatory resources linked with
+    * device endpoint.
+    */
+    M2MDevice* create_device_object() {
+        // create device objectID/ObjectInstance
+        M2MDevice *device = M2MInterfaceFactory::create_device();
+        // make sure device object was created successfully
+        if(device) {
+            // add resourceID's to device objectID/ObjectInstance
+            device->create_resource(M2MDevice::Manufacturer, _device.Manufacturer);
+            device->create_resource(M2MDevice::DeviceType, _device.Type);
+            device->create_resource(M2MDevice::ModelNumber, _device.ModelNumber);
+            device->create_resource(M2MDevice::SerialNumber, _device.SerialNumber);
+        }
+        return device;
+    }
+
+    /*
+    * register an object
+    */
+    void test_register(M2MSecurity *register_object, M2MObjectList object_list){
+        if(_interface) {
+            // Register function
+            _interface->register_object(register_object, object_list);
+        }
+    }
+
+    /*
+    * unregister all objects
+    */
+    void test_unregister() {
+        if(_interface) {
+            // Unregister function
+            _interface->unregister_object(NULL); // NULL will unregister all objects
+        }
+    }
+
+    //Callback from mbed client stack when the bootstrap
+    // is successful, it returns the mbed Device Server object
+    // which will be used for registering the resources to
+    // mbed Device server.
+    void bootstrap_done(M2MSecurity *server_object){
+        if(server_object) {
+            _bootstrapped = true;
+            _error = false;
+            trace_printer("Bootstrapped");
+        }
+    }
+
+    //Callback from mbed client stack when the registration
+    // is successful, it returns the mbed Device Server object
+    // to which the resources are registered and registered objects.
+    void object_registered(M2MSecurity */*security_object*/, const M2MServer &/*server_object*/){
+        _registered = true;
+        _unregistered = false;
+        trace_printer("Registered object successfully!");
+    }
+
+    //Callback from mbed client stack when the unregistration
+    // is successful, it returns the mbed Device Server object
+    // to which the resources were unregistered.
+    void object_unregistered(M2MSecurity */*server_object*/){
+        trace_printer("Unregistered Object Successfully");
+        _unregistered = true;
+        _registered = false;
+    }
+
+    /*
+    * Callback from mbed client stack when registration is updated
+    */
+    void registration_updated(M2MSecurity */*security_object*/, const M2MServer & /*server_object*/){
+        /* The registration is updated automatically and frequently by the
+        *  mbed client stack. This print statement is turned off because it
+        *  tends to happen alot.
+        */
+        //trace_printer("\r\nRegistration Updated\r\n");
+    }
+
+    // Callback from mbed client stack if any error is encountered
+    // during any of the LWM2M operations. Error type is passed in
+    // the callback.
+    void error(M2MInterface::Error error){
+        _error = true;
+        switch(error){
+            case M2MInterface::AlreadyExists:
+                trace_printer("[ERROR:] M2MInterface::AlreadyExist");
+                break;
+            case M2MInterface::BootstrapFailed:
+                trace_printer("[ERROR:] M2MInterface::BootstrapFailed");
+                break;
+            case M2MInterface::InvalidParameters:
+                trace_printer("[ERROR:] M2MInterface::InvalidParameters");
+                break;
+            case M2MInterface::NotRegistered:
+                trace_printer("[ERROR:] M2MInterface::NotRegistered");
+                break;
+            case M2MInterface::Timeout:
+                trace_printer("[ERROR:] M2MInterface::Timeout");
+                break;
+            case M2MInterface::NetworkError:
+                trace_printer("[ERROR:] M2MInterface::NetworkError");
+                break;
+            case M2MInterface::ResponseParseFailed:
+                trace_printer("[ERROR:] M2MInterface::ResponseParseFailed");
+                break;
+            case M2MInterface::UnknownError:
+                trace_printer("[ERROR:] M2MInterface::UnknownError");
+                break;
+            case M2MInterface::MemoryFail:
+                trace_printer("[ERROR:] M2MInterface::MemoryFail");
+                break;
+            case M2MInterface::NotAllowed:
+                trace_printer("[ERROR:] M2MInterface::NotAllowed");
+                break;
+            case M2MInterface::SecureConnectionFailed:
+                trace_printer("[ERROR:] M2MInterface::SecureConnectionFailed");
+                break;
+            case M2MInterface::DnsResolvingFailed:
+                trace_printer("[ERROR:] M2MInterface::DnsResolvingFailed");
+                break;
+
+            default:
+                break;
+        }
+    }
+
+    /* Callback from mbed client stack if any value has changed
+    *  during PUT operation. Object and its type is passed in
+    *  the callback.
+    *  BaseType enum from m2mbase.h
+    *       Object = 0x0, Resource = 0x1, ObjectInstance = 0x2, ResourceInstance = 0x3
+    */
+    void value_updated(M2MBase *base, M2MBase::BaseType type) {
+        printf("\r\nPUT Request Received!");
+        printf("\r\nName :'%s', \r\nPath : '%s', \r\nType : '%d' (0 for Object, 1 for Resource), \r\nType : '%s'\r\n",
+               base->name(),
+               base->uri_path(),
+               type,
+               base->resource_type()
+               );
+    }
+
+    /*
+    * update the registration period
+    */
+    void test_update_register() {
+        if (_registered) {
+            _interface->update_registration(_register_security, 100);
+        }
+    }
+
+    /*
+    * manually configure the security object private variable
+    */
+   void set_register_object(M2MSecurity *register_object) {
+        if (_register_security == NULL) {
+            _register_security = register_object;
+        }
+    }
+
+private:
+
+    /*
+    *  Private variables used in class
+    */
+    M2MInterface    	     *_interface;
+    M2MSecurity              *_register_security;
+    M2MObject                *_object;
+    volatile bool            _bootstrapped;
+    volatile bool            _error;
+    volatile bool            _registered;
+    volatile bool            _unregistered;
+    int                      _value;
+    struct MbedClientDevice  _device;
+    String                   _server_address;
+};
+
+#endif // __SIMPLECLIENT_H__