1.. zephyr:code-sample:: updatehub-fota
2   :name: UpdateHub embedded Firmware Over-The-Air (FOTA) update
3   :relevant-api: updatehub
4
5   Perform Firmware Over-The-Air (FOTA) updates using UpdateHub.
6
7Overview
8********
9
10UpdateHub is an enterprise-grade solution which makes it simple to remotely
11update all your embedded devices.  It handles all aspects related to sending
12Firmware Over-the-Air (FOTA) updates with maximum security and efficiency,
13while you focus on adding value to your product.  It is possible to read more
14about at `docs.updatehub.io`_.
15
16This sample shows how to use UpdateHub in both a polling and manual update
17mode.
18
19Polling mode runs automatically on a predefined period, probing the server
20for updates and installing them without requiring user intervention.
21
22Manual mode requires the user to call the server probe and then, if there is
23an available update, also requires the user to decide if it is appropriate to
24update now or later.
25
26You can access the sample source code at
27:zephyr_file:`samples/subsys/mgmt/updatehub/src/main.c`.
28
29Caveats
30*******
31
32* The Zephyr port of ``UpdateHub`` was initially developed to run on a
33  :zephyr:board:`Freedom-K64F <frdm_k64f>` kit using the ethernet connectivity.  The
34  application should build and run for other platforms with same connectivity.
35
36* The sample provides overlay files to enable other technologies like WIFI,
37  802.15.4 or OpenThread.  These technologies depends on
38  hardware resources and the correspondent overlay was designed to be generic
39  instead full optimized.
40
41* It is important understand that some wireless technologies may require a
42  gateway or some sort of border router.  It is out of scope provide such
43  configuration in details.
44
45* The MCUboot bootloader is required for ``UpdateHub`` function properly.
46  Before chose a platform to test, make sure that SoC and board have support
47  to it.  UpdateHub currently uses two slots to perform the upgrade.  More
48  information about Device Firmware Upgrade subsystem and MCUboot can be found
49  in :ref:`mcuboot`.
50
51* ``UpdateHub`` acts like a service on Zephyr. It is heavily dependent on
52  Zephyr sub-systems and it uses CoAP over UDP.
53
54
55Building and Running
56********************
57
58The below steps describe how to build and run the ``UpdateHub`` sample in
59Zephyr.  Open a terminal ``terminal 1`` and navigate to your Zephyr project
60directory.  This allows to construct and run everything from a common place.
61
62.. code-block:: console
63
64    ls
65    bootloader  modules  tools  zephyr
66
67
68Step 1: Build/Flash MCUboot
69===========================
70
71The MCUboot can be built following the instructions in the :ref:`mcuboot`
72documentation page.  Flash the resulting image file using west on
73``terminal 1``.
74
75.. zephyr-app-commands::
76    :app: bootloader/mcuboot/boot/zephyr
77    :board: frdm_k64f
78    :build-dir: mcuboot-frdm_k64f
79    :goals: build flash
80
81
82Step 2: Start the UpdateHub Server
83==================================
84
85Step 2.1: UpdateHub-CE (Community Edition)
86------------------------------------------
87
88The Zephyr sample application is configured by default to use the UpdateHub-CE
89server edition.  This version implies you need run your own server.  The
90UpdateHub-CE is distributed as a docker container and can be on your local
91network or even installed on a service provider like Digital Ocean, Vultr etc.
92To start using the UpdateHub-CE simple execute the docker command with the
93following parameters on another terminal ``terminal 2``.
94
95.. code-block:: console
96
97    docker run -it -p 8080:8080 -p 5683:5683/udp --rm
98      updatehub/updatehub-ce:latest
99
100Step 2.2: UpdateHub Cloud
101-------------------------
102
103The UpdateHub Cloud is an enterprise-grade solution.  It provides almost same
104resources than UpdateHub-CE with the DTLS as main diferential.  For more
105details on how to use the UpdateHub Cloud please refer to the documentation on
106`updatehub.io`_.  The UpdateHub Cloud has the option to use CoAPS/DTLS or not.
107If you want to use the CoAPS/DTLS, simply add the ``overlay-dtls.conf`` when
108building the sample.  You can use the provided certificate for test this
109example or create your own.  The below procedure instruct how create a new
110certificate using openssl on a Linux machine on terminal ``terminal 2``.
111
112.. code-block:: console
113
114    openssl genrsa -out privkey.pem 512
115    openssl req -new -x509 -key privkey.pem -out servercert.pem
116
117The ``servercert`` and ``privkey`` files must be embedded in the application
118by ``certificates.h`` file.  The following procedure can be used to generated
119the required ``der`` files:
120
121.. code-block:: console
122
123    openssl x509 -in servercert.pem -outform DER -out servercert.der
124    openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in privkey.pem
125      -out privkey.der
126
127
128The ``der`` files should be placed on the sample source at certificates
129directory.
130
131.. note::
132
133    When using UpdateHub Cloud server it is necessary update your own
134    ``overlay-prj.conf`` with option :kconfig:option:`CONFIG_UPDATEHUB_CE` equal ``n``.
135
136
137Step 3: Configure UpdateHub Sample
138==================================
139
140The updatehub have several Kconfig options that are necessary configure to
141make it work or tune communication.
142
143Set :kconfig:option:`CONFIG_UPDATEHUB_CE` select between UpdateHub edition.  The ``y``
144value will select UpdateHub-CE otherwise ``n`` selects UpdateHub Cloud.
145
146Set :kconfig:option:`CONFIG_UPDATEHUB_SERVER` with your local IP address that runs the
147UpdateHub-CE server edition.  If your are using a service provider a DNS name
148is a valid option too.  This option is only valid when using UpdateHub-CE.
149
150Set :kconfig:option:`CONFIG_UPDATEHUB_POLL_INTERVAL` with the polling period of your
151preference, remembering that the limit is between 0 and 43200 minutes
152(30 days).  The default value is 1440 minutes (24h).
153
154Set :kconfig:option:`CONFIG_UPDATEHUB_PRODUCT_UID` with your product ID.  When using
155UpdateHub-CE the valid is available at ``overlay-prj.conf.example`` file.
156
157
158Step 4: Build UpdateHub App
159===========================
160
161In order to correctly build UpdateHub the overlay files must be use correctly.
162More information about overlay files in :ref:`important-build-vars`.
163
164.. note::
165    It is out of scope at this moment provide support for experimental
166    features.  However, the configuration and use is similar to the start
167    point indicated on the experimental network interface.
168
169Step 4.1: Build for Ethernet
170----------------------------
171
172The ethernet depends only from base configuration.
173
174.. zephyr-app-commands::
175    :zephyr-app: samples/subsys/mgmt/updatehub
176    :board: [ frdm_k64f | nucleo_f767zi ]
177    :build-dir: app
178    :gen-args: -DEXTRA_CONF_FILE=overlay-prj.conf
179    :goals: build
180    :compact:
181
182Step 4.2: Build for WiFi
183------------------------
184
185For WiFi, it needs add ``overlay-wifi.conf``.  Here a shield provides WiFi
186connectivity using, for instance, arduino headers.  See :ref:`module_esp_8266`
187for details.
188
189.. zephyr-app-commands::
190    :zephyr-app: samples/subsys/mgmt/updatehub
191    :board: [ frdm_k64f | nrf52840dk/nrf52840 | nucleo_f767zi ]
192    :build-dir: app
193    :gen-args: -DEXTRA_CONF_FILE="overlay-wifi.conf;overlay-prj.conf"
194    :shield: esp_8266_arduino
195    :goals: build
196    :compact:
197
198.. note::
199    The board disco_l475_iot1 is not supported.  The es-WIFI driver currently
200    doesn't support UDP.
201
202Step 4.3: Build for IEEE 802.15.4 [experimental]
203------------------------------------------------
204
205For IEEE 802.15.4 needs add ``overlay-802154.conf``.  This requires two nodes:
206one will be the host and the second one will be the device under test.  The
207validation needs a Linux kernel >= 4.9 with all 6loWPAN support. It is out of scope
208at this moment provide support since it is experimental.  The gateway was
209tested with both native linux driver and ``atusb``.
210
211.. zephyr-app-commands::
212    :zephyr-app: samples/subsys/mgmt/updatehub
213    :board: nrf52840dk/nrf52840
214    :build-dir: app
215    :gen-args: -DEXTRA_CONF_FILE="overlay-802154.conf;overlay-prj.conf"
216    :goals: build
217    :compact:
218
219.. zephyr-app-commands::
220    :zephyr-app: samples/subsys/mgmt/updatehub
221    :board: [ frdm_k64f | nucleo_f767zi ]
222    :build-dir: app
223    :gen-args: -DEXTRA_CONF_FILE="overlay-802154.conf;overlay-prj.conf"
224    :shield: atmel_rf2xx_arduino
225    :goals: build
226    :compact:
227
228Step 4.4: Build for OpenThread Network [experimental]
229-----------------------------------------------------
230
231The OpenThread requires the ``overlay-ot.conf``.  It requires two nodes:
232one will be the host NCP and the second one will be the device under test.  The
233validation needs a Linux kernel >= 4.9 with optional NAT-64 support.  The
234start point is try reproduce the `OpenThread Router`_. It is
235out of scope at this moment provide support since it is experimental.  The
236gateway was tested using two boards with OpenThread 1.1.1 on NCP mode.
237
238.. zephyr-app-commands::
239    :zephyr-app: samples/subsys/mgmt/updatehub
240    :board: nrf52840dk/nrf52840
241    :build-dir: app
242    :gen-args: -DEXTRA_CONF_FILE="overlay-ot.conf;overlay-prj.conf"
243    :goals: build
244    :compact:
245
246
247Step 5: Sign the app image
248==========================
249
250The app image is the application itself that will be on the board.  This app
251will connect to UpdateHub server and check for new images.  The image will be
252loaded on the board with version 1.0.0.  It is important check what file
253format you SoC tools uses.  In general, Zephyr can create images with binary
254(``.bin``) image format or Intel's (``.hex``) image format.
255
256The Zephyr provide the ``west`` tool that simplify the signing process.  Just
257call west with proper parameter values:
258
259.. code-block:: console
260
261  west sign -t imgtool -d build/app -- --version 1.0.0 --pad
262    --key bootloader/mcuboot/root-rsa-2048.pem
263
264  === image configuration:
265  partition offset: 131072 (0x20000)
266  partition size: 393216 (0x60000)
267  rom start offset: 512 (0x200)
268  === signing binaries
269  unsigned bin: <zephyrdir>/build/app/zephyr/zephyr.bin
270  signed bin:   <zephyrdir>/build/app/zephyr/zephyr.signed.bin
271
272
273Step 6: Flash the app image
274===========================
275
276.. code-block:: console
277
278    west flash -d build/app --bin-file build/app/zephyr/zephyr.signed.bin
279
280.. note:: Command variation to flash a ``hex`` file:
281    ``west flash -d build/app --hex-file build/app/zephyr/zephyr.signed.hex``
282
283At this point you can access a third terminal ``terminal 3`` to check if image
284is running.  Open the ``terminal 3`` and press reset on your board:
285
286.. code-block:: console
287
288    minicom -D /dev/ttyACM0
289
290
291Step 7: Signing the binary test image
292=====================================
293
294The test image needs different parameters to add the signature.  Pay attention
295to make sure you are creating the right signed image.  The test image will be
296created with version 2.0.0 in this tutorial:
297
298.. code-block:: console
299
300  west sign --no-hex --bin -B build/zephyr-2.0.0.bin -t imgtool -d build/app --
301    --version 2.0.0 --key bootloader/mcuboot/root-rsa-2048.pem
302
303  === image configuration:
304  partition offset: 131072 (0x20000)
305  partition size: 393216 (0x60000)
306  rom start offset: 512 (0x200)
307  === signing binaries
308  unsigned bin: <zephyrdir>/build/app/zephyr/zephyr.bin
309  signed bin:   build/zephyr-2.0.0.bin
310
311
312Step 8: Create a package with UpdateHub Utilities (uhu)
313=======================================================
314
315First, install UpdateHub Utilities (``uhu``) on your system, using:
316
317.. code-block:: console
318
319    pip3 install --user uhu
320
321After installing uhu you will need to set the ``product-uid``.  The value for
322UpdateHub-CE can be found at ``overlay-prj.conf.example`` file.  For UpdateHub
323Cloud, you need copy the value from the web interface.
324
325.. code-block:: console
326
327    uhu product use "e4d37cfe6ec48a2d069cc0bbb8b078677e9a0d8df3a027c4d8ea131130c4265f"
328
329Then, add the package and its mode (``zephyr``):
330
331.. code-block:: console
332
333    uhu package add build/zephyr-2.0.0.bin -m zephyr
334
335Then inform what ``version`` this image is:
336
337.. code-block:: console
338
339   uhu package version 2.0.0
340
341And finally you can build the package by running:
342
343.. code-block:: console
344
345    uhu package archive --output build/zephyr-2.0.0.pkg
346
347The remaining steps are dedicated to UpdateHub-CE.  If you are using UpdateHub
348Cloud you can find the proper procedure at `docs.updatehub.io`_.
349
350
351Step 9: Add the package to server
352=================================
353
354Now, add the package to the updatehub server.  Open your browser to the server
355URL, ``<your-ip-address>:8080``, and logging into the server using ``admin``
356as the login and password by default.  After logging in, click on the package
357menu, then ``UPLOAD PACKAGE``, and select the package built in step 8.
358
359
360Step 10: Register device on server
361==================================
362
363If you chose ``Manual``, register your device at updatehub server by using the
364terminal session where you are debugging the board ``terminal 3``. Type the
365following command:
366
367.. code-block:: console
368
369    updatehub run
370
371If everything is alright, it will print on the screen ``No update available``.
372
373For ``Polling`` mode, the system will automatically register your device after
374:kconfig:option:`CONFIG_UPDATEHUB_POLL_INTERVAL` minutes.  The ``updatehub run`` can
375be used to speed-up.
376
377.. note::
378    The message ``Could not receive data`` means that the application was not
379    able to reached the updatehub server for some reason.  The most common
380    cases are server down, missing network routes and forget to change the
381    content of ``overlay-prj.conf`` file.
382
383
384Step 11: Create a rollout
385=========================
386
387In the browser where the UpdateHub-CE is open, click on ``menu Rollout``
388and then ``CREATE ROLLOUT``.  Select the version of the package that you added
389in step 9.  With that, the update is published, and the server is ready to
390accept update requests.
391
392
393Step 12: Run the update
394=======================
395
396Back in the terminal session that you used for debugging the board, type the
397following command:
398
399.. code-block:: console
400
401    updatehub run
402
403And then wait.  The board will probe the server, check if there are any new
404updates, and then download the update package you've just created. If
405everything goes fine the message ``Image flashed successfully, you can reboot
406now`` will be printed on the terminal.  If you are using the ``Polling`` mode
407the board will reboot automatically and Step 13 can be skipped.
408
409
410Step 13: Reboot the system
411==========================
412
413In the terminal you used for debugging the board, type the following command:
414
415.. code-block:: console
416
417    kernel reboot cold
418
419Your board will reboot and then start with the new image.  After rebooting,
420the board will automatically ping the server again and the message ``No update
421available`` will be printed on the terminal.  You can check the newer version
422using the following command:
423
424.. code-block:: console
425
426    uart:~$ updatehub info
427    Unique device id: acbdef0123456789
428    Firmware Version: 2.0.0
429    Product uid: e4d37cfe6ec48a2d069cc0bbb8b078677e9a0d8df3a027c4d8ea131130c4265f
430    UpdateHub Server: <server ip/dns>
431    uart:~$
432
433Hardware
434********
435
436The below list of hardware have been used by UpdateHub team.
437
438
439.. csv-table::
440   :header: "ID", "Network Interface", "Shield / Device"
441   :widths: 5, 45, 50
442   :width: 800px
443
444   1, Ethernet, Native
445   2, WIFI, :ref:`ESP-8266 <module_esp_8266>`
446   3, "MODEM (PPP)", "SIMCOM 808"
447   4, "IEEE 802.15.4 (6loWPAN)", "Native,
448   :ref:`RF2XX <atmel_at86rf2xx_transceivers>`"
449   6, "OpenThread Network", Native
450
451.. csv-table::
452   :header: "Board", "Network Interface"
453   :widths: 50, 50
454   :width: 800px
455
456   :zephyr:board:`frdm_k64f`, "1, 2, 3, 4"
457   :ref:`nrf52840dk_nrf52840`, "2, 3, 4, 5, 6"
458   :zephyr:board:`nucleo_f767zi`, "1, 2, 3, 4"
459
460
461.. _updatehub.io: https://updatehub.io
462.. _docs.updatehub.io: https://docs.updatehub.io/
463.. _OpenThread Router: https://openthread.io/guides/border-router
464