Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ bundle, checking first that the board has the flash it was laid out for.
Verify downloads with `sha256sum -c SHA256SUMS`.

Then provision the device: [Improv](#provisioning-a-device) for
`standalone`, [lab-ztp-provisioner](#provisioning-wi-fi-and-cumulocity-with-lab-ztp-provisioner)
for `tedge-*`. The security notes there apply to prebuilt images too.
`standalone`, and for `tedge-*`
[tedge-onboard over USB](#setting-a-device-up-over-usb-with-tedge-onboard) or
[lab-ztp-provisioner](#provisioning-wi-fi-and-cumulocity-with-lab-ztp-provisioner). The security notes there apply to prebuilt images too.

> **Release images are signed with MCUboot's public development key** unless
> a release says otherwise (its notes and every `flash.json` state the key).
Expand Down Expand Up @@ -414,10 +415,30 @@ If you'd rather not bake credentials into the image, see the next section: on
the ESP32-C6, the ESP32-S3 boards and the ESP32-WROOM-32 a device can be given
its network over BLE after flashing.

## Setting a device up over USB with tedge-onboard

The `tedge-*` builds are set up from a computer by default. Plug the device
into a computer with a USB data cable and run
[`tedge-onboard`](https://github.com/thin-edge/tiny-edge/tree/main/tools/onboard)
there. It finds the device, gives it the computer's Wi-Fi network (the one
the device can see), registers it in Cumulocity through your go-c8y-cli
session, and waits until it is connected. Download it from the
[tiny-edge releases](https://github.com/thin-edge/tiny-edge/releases).

A `tedge-*` device with no Wi-Fi network waits for the tool: its status LED
shows the provisioning pattern (two short blinks, then a pause), and the log
says so. To provision it over BLE instead (Improv, or lab-ztp-provisioner),
**press the button 3 times within 2 seconds**: it reboots into the Wi-Fi
provisioner described below.

The Wi-Fi network the tool sends is tried before it is stored: if the device
cannot join it, the device keeps its previous network.

## Provisioning Wi-Fi over BLE

On boards with a BLE radio the device can join any network without a rebuild.
A device with no credentials boots into the **Wi-Fi provisioner**: it advertises
A `standalone` device with no credentials boots into the **Wi-Fi provisioner**
(a `tedge-*` device does after the button pattern above): it advertises
the [Improv Wi-Fi](https://www.improv-wifi.com/ble/) BLE service, a phone or
laptop sends it an SSID and password, and the device checks them by actually
joining the network, stores them, and reboots into the application.
Expand Down
11 changes: 9 additions & 2 deletions apps/modbus-server/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <zephyr/logging/log.h>

#include "net.h"
#include "prov_tedge.h"
#include "display.h"
#include "modbus_server.h"
#if defined(CONFIG_TEDGE)
Expand All @@ -37,8 +38,12 @@ int main(void)
return 0;
}

/* No Wi-Fi network yet: the client starts first (tedge-onboard gives
* the device one), and the rest waits for the network. */
bool onboarding = app_prov_tedge_start_unprovisioned(tedge_glue_start);

LOG_INF("Waiting for network...");
ret = app_net_wait_connected(K_SECONDS(60));
ret = app_net_wait_connected(onboarding ? K_FOREVER : K_SECONDS(60));
if (ret) {
LOG_ERR("Network did not come up in time (%d)", ret);
display_status_stage(DISPLAY_STAGE_ERROR);
Expand All @@ -55,7 +60,9 @@ int main(void)

#if defined(CONFIG_TEDGE)
/* Device management runs alongside the protocol server. */
(void)tedge_glue_start();
if (!onboarding) {
(void)tedge_glue_start();
}
#endif

return 0;
Expand Down
4 changes: 4 additions & 0 deletions apps/modbus-server/src/tedge_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "identity.h"
#if defined(CONFIG_APP_WIFI_CRED_STORE)
#include "prov_c8y.h"
#include "prov_tedge.h"
#endif
#include "status_led.h"

Expand Down Expand Up @@ -478,6 +479,9 @@ int tedge_glue_start(void)
LOG_ERR("tedge_init failed (%d)", rc);
return rc;
}
#if defined(CONFIG_APP_TEDGE_PROVISIONING)
(void)app_prov_tedge_init();
#endif
#if defined(CONFIG_APP_WIFI_CRED_STORE)
/* Tenant and one-time password from the ZTP provisioner, if it left
* any. The external ID already came through app_identity_device_id(). */
Expand Down
9 changes: 7 additions & 2 deletions apps/opcua-server/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <zephyr/logging/log.h>

#include "net.h"
#include "prov_tedge.h"
#include "display.h"

#if defined(CONFIG_APP_OPCUA_SERVER)
Expand Down Expand Up @@ -40,8 +41,12 @@ int main(void)
return 0;
}

/* No Wi-Fi network yet: the client starts first (tedge-onboard gives
* the device one), and the rest waits for the network. */
bool onboarding = app_prov_tedge_start_unprovisioned(tedge_glue_start);

LOG_INF("Waiting for network...");
ret = app_net_wait_connected(K_SECONDS(60));
ret = app_net_wait_connected(onboarding ? K_FOREVER : K_SECONDS(60));
if (ret) {
LOG_ERR("Network did not come up in time (%d)", ret);
display_status_stage(DISPLAY_STAGE_ERROR);
Expand All @@ -63,7 +68,7 @@ int main(void)

#if defined(CONFIG_TEDGE)
/* Device management runs alongside the protocol server. */
if (tedge_glue_start() == 0) {
if (onboarding || tedge_glue_start() == 0) {
#if defined(CONFIG_TEDGE_TELEMETRY)
tedge_glue_start_telemetry();
#endif
Expand Down
4 changes: 4 additions & 0 deletions apps/opcua-server/src/tedge_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "opcua_server.h"
#if defined(CONFIG_APP_WIFI_CRED_STORE)
#include "prov_c8y.h"
#include "prov_tedge.h"
#endif
#include "status_led.h"

Expand Down Expand Up @@ -149,6 +150,9 @@ int tedge_glue_start(void)
LOG_ERR("tedge_init failed (%d)", rc);
return rc;
}
#if defined(CONFIG_APP_TEDGE_PROVISIONING)
(void)app_prov_tedge_init();
#endif
#if defined(CONFIG_APP_WIFI_CRED_STORE)
/* Tenant and one-time password from the ZTP provisioner, if it left
* any. The external ID already came through app_identity_device_id(). */
Expand Down
9 changes: 7 additions & 2 deletions apps/snmp-agent/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <zephyr/logging/log.h>

#include "net.h"
#include "prov_tedge.h"
#include "display.h"
#include "snmp_agent.h"
#if defined(CONFIG_TEDGE)
Expand All @@ -38,8 +39,12 @@ int main(void)
return 0;
}

/* No Wi-Fi network yet: the client starts first (tedge-onboard gives
* the device one), and the rest waits for the network. */
bool onboarding = app_prov_tedge_start_unprovisioned(tedge_glue_start);

LOG_INF("Waiting for network...");
ret = app_net_wait_connected(K_SECONDS(60));
ret = app_net_wait_connected(onboarding ? K_FOREVER : K_SECONDS(60));
if (ret) {
LOG_ERR("Network did not come up in time (%d)", ret);
display_status_stage(DISPLAY_STAGE_ERROR);
Expand All @@ -56,7 +61,7 @@ int main(void)

#if defined(CONFIG_TEDGE)
/* Device management runs alongside the protocol agent. */
if (tedge_glue_start() == 0) {
if (onboarding || tedge_glue_start() == 0) {
#if defined(CONFIG_TEDGE_TELEMETRY)
tedge_glue_start_telemetry();
#endif
Expand Down
4 changes: 4 additions & 0 deletions apps/snmp-agent/src/tedge_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "identity.h"
#if defined(CONFIG_APP_WIFI_CRED_STORE)
#include "prov_c8y.h"
#include "prov_tedge.h"
#endif
#include "status_led.h"

Expand Down Expand Up @@ -125,6 +126,9 @@ int tedge_glue_start(void)
LOG_ERR("tedge_init failed (%d)", rc);
return rc;
}
#if defined(CONFIG_APP_TEDGE_PROVISIONING)
(void)app_prov_tedge_init();
#endif
#if defined(CONFIG_APP_WIFI_CRED_STORE)
/* Tenant and one-time password from the ZTP provisioner, if it left
* any. The external ID already came through app_identity_device_id(). */
Expand Down
9 changes: 7 additions & 2 deletions apps/tedge-agent/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <zephyr/logging/log.h>

#include "net.h"
#include "prov_tedge.h"
#include "display.h"
#include "tedge_glue.h"

Expand All @@ -37,15 +38,19 @@ int main(void)
return 0;
}

/* No Wi-Fi network yet: the client starts first (tedge-onboard gives
* the device one), and the rest waits for the network. */
bool onboarding = app_prov_tedge_start_unprovisioned(tedge_glue_start);

LOG_INF("Waiting for network...");
ret = app_net_wait_connected(K_SECONDS(60));
ret = app_net_wait_connected(onboarding ? K_FOREVER : K_SECONDS(60));
if (ret) {
LOG_ERR("Network did not come up in time (%d)", ret);
display_status_stage(DISPLAY_STAGE_ERROR);
return 0;
}

ret = tedge_glue_start();
ret = onboarding ? 0 : tedge_glue_start();
if (ret) {
LOG_ERR("Device management did not start (%d)", ret);
display_status_stage(DISPLAY_STAGE_ERROR);
Expand Down
4 changes: 4 additions & 0 deletions apps/tedge-agent/src/tedge_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "net.h"
#if defined(CONFIG_APP_WIFI_CRED_STORE)
#include "prov_c8y.h"
#include "prov_tedge.h"
#endif
#include "status_led.h"

Expand Down Expand Up @@ -179,6 +180,9 @@ int tedge_glue_start(void)
LOG_ERR("tedge_init failed (%d)", rc);
return rc;
}
#if defined(CONFIG_APP_TEDGE_PROVISIONING)
(void)app_prov_tedge_init();
#endif
#if defined(CONFIG_APP_WIFI_CRED_STORE)
/* Tenant and one-time password from the ZTP provisioner, if it left
* any. The external ID already came through app_identity_device_id(). */
Expand Down
1 change: 1 addition & 0 deletions lib/common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ zephyr_library_sources(status_led.c)
zephyr_library_sources_ifdef(CONFIG_APP_BOOT_REQUEST boot_request.c)
zephyr_library_sources_ifdef(CONFIG_APP_WIFI_CRED_STORE prov_identity.c prov_c8y.c)
zephyr_library_sources_ifdef(CONFIG_APP_PROV_HANDOFF prov_handoff.c)
zephyr_library_sources_ifdef(CONFIG_APP_TEDGE_PROVISIONING prov_tedge.c)

# Identify: `tedge identify` blinks the status LED, the sw0 identify pattern
# sends an event.
Expand Down
12 changes: 12 additions & 0 deletions lib/common/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,18 @@ config APP_BOOT_REQUEST
help
The boot request record in bootreq_partition (boot_request.h).

config APP_TEDGE_PROVISIONING
bool "Set the device up over USB with tedge-onboard"
default y
depends on TEDGE && APP_WIFI_CRED_STORE && !APP_WIFI_PROVISIONER
select TEDGE_PROVISIONING
help
tiny-edge's provisioning library on the console (Improv Serial):
tedge-onboard, run on a computer the device is plugged into, gives it
the Wi-Fi network and registers it in Cumulocity. A device without a
Wi-Fi network then waits for it, rather than starting the Wi-Fi
provisioner image (the button pattern still starts that).

config APP_PROV_HANDOFF
bool "Hand over to the Wi-Fi provisioner image"
default y if BOOTLOADER_MCUBOOT && $(dt_nodelabel_exists,prov_partition)
Expand Down
Loading
Loading