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
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ on:
paths:
- "apps/**"
- "lib/**"
- "tedge-zephyr/**"
- "sysbuild/**"
- "west.yml"
- "release/**"
Expand Down
63 changes: 0 additions & 63 deletions .github/workflows/tedge-zephyr.yml

This file was deleted.

4 changes: 2 additions & 2 deletions .github/workflows/wifi-provisioner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ jobs:
image: zephyrprojectrtos/zephyr-build:latest
options: --user root
env:
# See tedge-zephyr.yml: the image registers the SDK for its non-root
# user only, and this job runs as root.
# The image registers the SDK for its non-root user only, and this
# job runs as root.
ZEPHYR_SDK_INSTALL_DIR: /opt/toolchains
steps:
- uses: actions/checkout@v4
Expand Down
14 changes: 7 additions & 7 deletions DEVICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ upload and the heap still in dram1 missed by 1.3 KB.
192 KB dram0 and no PSRAM. The client fits beside **Modbus** or with **no
protocol** (`apps/tedge-agent`), at the ota level plus remote access; not
beside SNMP or OPC-UA at any level. Measured on the rpi5 WROOM
(3c:71:bf:10:c2:e4) with `lib/common/tedge-boards/esp32-devkitc.conf`:
(3c:71:bf:10:c2:e4) with `tiny-edge/ports/zephyr/profiles/boards/esp32-devkitc.conf`:
8 KB TLS records, a 56 KB mbedTLS heap in internal RAM, 10 network
connections. Each image was flashed `--app-only`, run against
thin-edge-io.eu-latest and the board restored from a full flash backup
Expand Down Expand Up @@ -238,7 +238,7 @@ Telemetry was published throughout, but the test tenant had no mapping for

### Shell diagnostics measured (2026-09-22)

`lib/common/tedge-boards/extras/shell-diagnostics.conf` adds the cloud shell
`tiny-edge/ports/zephyr/profiles/extras/shell-diagnostics.conf` adds the cloud shell
command (allow-list: `kernel uptime`, `kernel version`, `net iface`,
`net conn`, `wifi status`, `tedge params list`, `tedge diag`, and since
2026-10-06 `tedge identify`; `help` lists them, one per line). It costs about 16 KB of internal RAM.
Expand Down Expand Up @@ -434,7 +434,7 @@ CONFIG_NET_BUF_TX_COUNT=64
Without them a session paints one screen, freezes, and the device drops off
the cloud and reconnects. The failure is **burst depth, not bandwidth** —
the same image streams 1 MB happily. See
`tedge-zephyr/docs/debugging-against-real-devices.md`.
`tiny-edge/ports/zephyr/docs/debugging-against-real-devices.md`.

## Known board quirks

Expand All @@ -451,8 +451,8 @@ the same image streams 1 MB happily. See
## Rebuilding one

```sh
OVR="/ws/app/tedge-zephyr/profiles/<full|ota>.conf;\
/ws/app/lib/common/tedge-boards/<device>.conf;\
OVR="/ws/modules/lib/tiny-edge/ports/zephyr/profiles/<full|ota>.conf;\
/ws/modules/lib/tiny-edge/ports/zephyr/profiles/boards/<device>.conf;\
/ws/app/overlay-wifi-credentials.conf;/ws/app/tedge.local.conf"

docker exec -w /ws/app -e ZEPHYR_SDK_INSTALL_DIR=$SDK zephyr-dev \
Expand All @@ -462,8 +462,8 @@ docker exec -w /ws/app -e ZEPHYR_SDK_INSTALL_DIR=$SDK zephyr-dev \
ESPTOOL=~/flashenv/bin/esptool ./scripts/flash.sh build-x --port <port> --app-only
```

The profile picks the features (`tedge-zephyr/profiles/`); the board file
(`lib/common/tedge-boards/`, one per device, whatever the app) sizes the TLS
The profile picks the features (`tiny-edge/ports/zephyr/profiles/`); the board file
(`tiny-edge/ports/zephyr/profiles/boards/`, one per device, whatever the app) sizes the TLS
heap, PSRAM, connections and network buffers, and goes after the profile so
its sizes win. The ESP32-CAM also needs
`-DEXTRA_DTC_OVERLAY_FILE=/ws/app/lib/common/dts/esp32cam-status-led.overlay`
Expand Down
39 changes: 24 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,10 @@ group to flash.
## First-time workspace setup

This repo is a Zephyr *workspace application* (T2 topology): it is the west
manifest repo, and `west update` fetches Zephyr + modules + open62541.
manifest repo, and `west update` fetches Zephyr + modules + open62541, and
the thin-edge.io client, [tiny-edge](https://github.com/thin-edge/tiny-edge),
into `/ws/modules/lib/tiny-edge`. West adds tiny-edge as a Zephyr module, so
the applications do not name it in their CMake files.

```sh
# Persistent build container with this repo mounted at /ws/app.
Expand All @@ -199,6 +202,12 @@ docker exec -w /ws zephyr-dev west blobs fetch hal_espressif
docker exec zephyr-dev bash -lc 'cd /ws/modules/crypto/mbedtls && git submodule update --init --recursive'
```

To change tiny-edge and an application together, work in the workspace's
clone (`/ws/modules/lib/tiny-edge`), or mount your own clone over it with
`-v /path/to/tiny-edge:/ws/modules/lib/tiny-edge` when you create the
container. `west.yml` pins tiny-edge to a release, so a change to the
client is released there first and then picked up here by moving the pin.

## Build & run on `native_sim`

```sh
Expand Down Expand Up @@ -610,8 +619,8 @@ has no room for both. Build the provisioner with `overlay-ztp.conf`, and leave
the Wi-Fi and tenant overlays out — the bundle supplies both:

```sh
OVR="/ws/app/tedge-zephyr/profiles/full.conf;\
/ws/app/lib/common/tedge-boards/esp32c6-devkitc.conf"
OVR="/ws/modules/lib/tiny-edge/ports/zephyr/profiles/full.conf;\
/ws/modules/lib/tiny-edge/ports/zephyr/profiles/boards/esp32c6-devkitc.conf"

docker exec -w /ws/app -e ZEPHYR_SDK_INSTALL_DIR=$SDK zephyr-dev \
west build --sysbuild -b esp32c6_devkitc/esp32c6/hpcore apps/modbus-server \
Expand Down Expand Up @@ -648,7 +657,7 @@ in PSA ITS, never exported); the relay forwards it, the server answers, the
relay writes the answer back. The device joins the Wi-Fi network first —
nothing is stored unless that works — then stores the Cumulocity data for the
application and reboots into it. The application hands the tenant and password
to `tedge-zephyr` (`tedge_set_c8y_url()`, `tedge_set_enroll_otp()`) and uses
to `tiny-edge` (`tedge_set_c8y_url()`, `tedge_set_enroll_otp()`) and uses
the external ID from the bundle as its identity from then on. A *pending*
answer (the operator has not approved the device yet) leaves it provisionable:
the relay simply asks again.
Expand Down Expand Up @@ -1080,7 +1089,7 @@ lib/frontend-template/ copy-me skeleton for a new protocol (CAN/...)
apps/opcua-server/ OPC-UA firmware: lib/common (env sim) + lib/opcua
apps/modbus-server/ Modbus TCP firmware: lib/common (pump sim) + lib/modbus
apps/snmp-agent/ SNMP agent firmware: lib/common (switch sim) + lib/snmp
apps/tedge-agent/ device-management agent: lib/common + tedge-zephyr, no protocol
apps/tedge-agent/ device-management agent: lib/common + tiny-edge, no protocol
├── boards/<board>.conf per-app board overlays (RAM/Wi-Fi tuning)
└── points.d/<proto>/*.toml point library: the app's address map for a
collector (see "Point libraries" below)
Expand Down Expand Up @@ -1226,7 +1235,7 @@ demo lively but a device left running noisy. Override per build:
`apps/tedge-agent` is the thin-edge.io client with **no industrial protocol**:
`lib/common` (Wi-Fi, stored or provisioned credentials, the provisioner
hand-off, identity, status LED, button, liveness watchdog) plus
`tedge-zephyr`. It is for a device whose job is to be managed from Cumulocity
`tiny-edge`. It is for a device whose job is to be managed from Cumulocity
and to give it **remote access to hosts on its LAN** (SSH, web UIs) — the
role the hand-built WROOM "remote-access enabler" played.

Expand All @@ -1237,20 +1246,20 @@ Remote access follows the client's Kconfig policy, which by default allows
hosts on the device's own LAN. It advertises no DNS-SD service; it answers to
`<hostname>.local` (`tedge-agent<mac>`).

Build it with a `tedge-zephyr` profile and the board's settings, like the
Build it with a `tiny-edge` profile and the board's settings, like the
`tedge` builds of the protocol apps, and with the lab-ztp-provisioner
provisioner so the tenant arrives at provisioning time:

```sh
docker exec -w /ws/app -e ZEPHYR_SDK_INSTALL_DIR=$SDK zephyr-dev \
west build --sysbuild -b esp32c6_devkitc/esp32c6/hpcore apps/tedge-agent \
--pristine -d build-agent -- \
"-DEXTRA_CONF_FILE=/ws/app/tedge-zephyr/profiles/full.conf;/ws/app/lib/common/tedge-boards/esp32c6-devkitc.conf" \
"-DEXTRA_CONF_FILE=/ws/modules/lib/tiny-edge/ports/zephyr/profiles/full.conf;/ws/modules/lib/tiny-edge/ports/zephyr/profiles/boards/esp32c6-devkitc.conf" \
-Dwifi-provisioner_EXTRA_CONF_FILE=/ws/app/apps/wifi-provisioner/overlay-ztp.conf
```

On an ESP32-WROOM-32 use `profiles/ota.conf`, `tedge-boards/esp32-devkitc.conf`
and `tedge-boards/extras/parameters.conf`. Remote access links there but
On an ESP32-WROOM-32 use `profiles/ota.conf`, `profiles/boards/esp32-devkitc.conf`
and `profiles/extras/parameters.conf`. Remote access links there but
does not work interactively: the board has room for about three Wi-Fi frames
of receive buffers, and an `htop` session over a tunnel fails (DEVICES.md).

Expand All @@ -1271,7 +1280,7 @@ tenant needs, ready to deploy.

Every payload is flat: `time` (UTC) and one number per series, two decimals,
**no units** (the tables below give them, for the mapping to add). The format
is the client's; see `tedge-zephyr/README.md`, "What the client publishes".
is the client's; see `tiny-edge/ports/zephyr/README.md`, "What the client publishes".

**`modbus-server`** — `te/device/<id>///m/pump`, every 30 s (the pump
simulation it also serves over Modbus; values are 0 or ambient until a client
Expand Down Expand Up @@ -1361,7 +1370,7 @@ c8y operations create --device <device> \
```

This needs an image with the cloud shell command, which today means the
images built with `lib/common/tedge-boards/extras/shell-diagnostics.conf`
images built with `tiny-edge/ports/zephyr/profiles/extras/shell-diagnostics.conf`
(the S3-DevKitC and QT Py modbus-server and tedge-agent full builds; see
DEVICES.md). That file puts `tedge identify` on the allow-list. On other
images the cloud has no shell, so only the button works. The same command
Expand Down Expand Up @@ -1499,8 +1508,8 @@ Things to know:
## Releasing

All applications share **one version**, kept in every `apps/*/VERSION`
(`tedge-zephyr/VERSION` is the module's own and moves only when the module
changes). [release-please](https://github.com/googleapis/release-please)
(tiny-edge has its own version, and `west.yml` pins the release the
applications are built with). [release-please](https://github.com/googleapis/release-please)
chooses the next one from the commit messages on `main`:

- **Pull requests are squash-merged**, and the PR title becomes the commit
Expand Down Expand Up @@ -1605,7 +1614,7 @@ fingerprint. Devices change keys only by a flash by cable.
**Adding a device or a build.** Its board needs a provisioner layout
(`lib/common/dts/layout-*.dtsi`, listed in `sysbuild/provisioning.cmake`) and
board files for each app. For a `tedge-*` build, also a board settings file in
[`lib/common/tedge-boards/`](lib/common/tedge-boards/README.md), and a run on
[`tiny-edge/ports/zephyr/profiles/boards/`](https://github.com/thin-edge/tiny-edge/blob/main/ports/zephyr/profiles/boards/README.md), and a run on
the board recorded in DEVICES.md — connection, telemetry, a firmware update
that confirms, a tunnel if remote access is in — which the manifest entry
names in `measured:`. `scripts/release/matrix.py` rejects an entry without
Expand Down
25 changes: 13 additions & 12 deletions SCOPE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Cumulocity are **not** involved in this primary phase.
protocol), serving device/sensor data to an external client.
- **Phase 2: Additional protocols / sources.**
Extend beyond OPC-UA to other industry protocols as source options.
- **Phase 3 (started 2026-09-19): tedge-zephyr, a device-management client.**
- **Phase 3 (started 2026-09-19): tiny-edge, a device-management client.**
A thin-edge.io client shipped as a **reusable Zephyr module** that any user's
Zephyr application can include. The OPC-UA, Modbus and SNMP apps here serve
as example user applications. It provides device-management features:
Expand Down Expand Up @@ -104,23 +104,24 @@ single-purpose devices (OPC-UA today; SNMP/Modbus/CAN as later Phase-2 apps):
`west build -b <board> apps/<protocol>`. Today: `apps/opcua-server` (OPC-UA,
env sim), `apps/modbus-server` (Modbus TCP on port 502, pump sim) and
`apps/snmp-agent` (SNMPv2c on UDP 161 + traps on 162, switch sim).
- `tedge-zephyr/` — (Phase 3) the thin-edge.io device-management client, a
standalone Zephyr module (`tedge`) for *any* Zephyr application. It never
depends on `lib/` or `apps/`, and it will move into its own repository. Apps
here opt in with `CONFIG_TEDGE` and keep their glue code in `apps/<app>/src/`.
- The thin-edge.io device-management client is not in this repository. It
is [tiny-edge](https://github.com/thin-edge/tiny-edge), a Zephyr module
(`tedge`) that `west.yml` pins to a release. Apps here opt in with
`CONFIG_TEDGE` and keep their glue code in `apps/<app>/src/`.

## Phase 3 roadmap: device management client

### A module for any application

The client lives in `tedge-zephyr/`, a self-contained Zephyr module named
`tedge`:
The client was developed here as `tedge-zephyr/` and now lives in its own
repository, [tiny-edge](https://github.com/thin-edge/tiny-edge), which is
also laid out for other RTOSes. It is a Zephyr module named `tedge`:

- **Namespaced:** the API is `tedge_*` and Kconfig is `CONFIG_TEDGE_*`.
- **Self-contained:** it depends only on Zephyr and MCUboot, and never on
this repo's `lib/`.
- **Portable:** it is laid out so it can move into its own repository and
west project later without changing its files.
- **Portable:** a west project of its own, with a portable core and one port
per RTOS (Zephyr first).
- **The host application owns** connectivity, identity, telemetry and the
watchdog.
- **The module owns** its threads, a bounded heap, its settings subtree
Expand Down Expand Up @@ -228,7 +229,7 @@ the strongest reason for the direct transport.
| Step | Change | Content |
|---|---|---|
| P0 | `c8y-direct-spikes` (done 2026-09-19: go) | TLS/MQTT Service cost, OTA into `slot1`, CA enrollment, remote-access tunnel to a LAN host, module skeleton, footprint table |
| P1 | `c8y-direct-core` (done 2026-09-20) | The `tedge-zephyr` module and public API; onboarding (CA and bootstrap), connection with reconnect and back-off, inventory, restart (full-system reset hook), availability, state on `te/` topics with reference Smart Functions; one protocol app and `samples/minimal` integrated |
| P1 | `c8y-direct-core` (done 2026-09-20) | The `tiny-edge` module and public API; onboarding (CA and bootstrap), connection with reconnect and back-off, inventory, restart (full-system reset hook), availability, state on `te/` topics with reference Smart Functions; one protocol app and `samples/minimal` integrated |
| P2 | `c8y-direct-remote-access` (done 2026-09-20) | **Remote access**: WSS bridge to LAN hosts and local services under the target policy, session cap, audit events, capacity as twin data |
| P3 | `c8y-direct-firmware-update` (done 2026-09-20) | Firmware update: confirmed only after the new image reaches Cumulocity and passes the app's checks; MCUboot rolls back otherwise |
| P4 | `c8y-direct-telemetry` (done 2026-09-20) | Telemetry (free-form, `te/`-shaped) and device-health measurements, buffered through an outage with the time each reading was taken |
Expand All @@ -237,7 +238,7 @@ the strongest reason for the direct transport.
| P7 | `c8y-direct-parameters` (done 2026-09-20) | Typed device parameters the cloud can see and change (Cumulocity Parameter Update, as thin-edge.io's parameter plugin does), not configuration files; the client declares a set for itself too, so a device is adjustable in the field whatever its application does |
| P8 | `gateway-transport` (proposed) | Gateway transport: a thin-edge.io child device with no TLS, no certificate and no cloud token, reusing the P1–P7 handlers |
| — | separate small change | Full-system reset in `lib/common` (`liveness.c`, `net.c`): a CPU reset hangs MCUboot on the C6 |
| — | — | Move `tedge-zephyr` into its own repository once the P1 API has settled |
| — | done 2026-11-03 | Move the client into its own repository: [tiny-edge](https://github.com/thin-edge/tiny-edge) |
| later | — | Device profiles, WROOM tuning, "software" via LLEXT or Wasm |

## Open questions
Expand All @@ -255,5 +256,5 @@ the strongest reason for the direct transport.
open problems P1–P13 there carry into `c8y-direct-core`, notably reconnect
after a network drop (P1), the C6 reset hang (P2) and key protection (P9).
- Phase 3: free-form telemetry is turned into measurements by Cumulocity
Smart Functions. Which reference functions tedge-zephyr ships, and how
Smart Functions. Which reference functions tiny-edge ships, and how
they're installed, is open (P12).
4 changes: 2 additions & 2 deletions apps/modbus-server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ cmake_minimum_required(VERSION 3.20.0)
list(APPEND ZEPHYR_EXTRA_MODULES
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/common
${CMAKE_CURRENT_SOURCE_DIR}/../../lib/modbus
# thin-edge.io device management; off unless CONFIG_TEDGE=y.
${CMAKE_CURRENT_SOURCE_DIR}/../../tedge-zephyr
)
# thin-edge.io device management (tiny-edge, off unless CONFIG_TEDGE=y) is a
# west project, so west adds it as a module; see west.yml.

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(modbus_server_firmware C)
Expand Down
4 changes: 2 additions & 2 deletions apps/modbus-server/src/tedge_glue.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: Apache-2.0
*
* The glue between this application and the tedge-zephyr client. It lives
* The glue between this application and the tiny-edge client. It lives
* here, not in the module: the module knows nothing about lib/common.
*
* It gives the client this device's identity, shows the registration URL
Expand Down Expand Up @@ -203,7 +203,7 @@ static int cmd_crash(const struct shell *sh, size_t argc, char **argv)
}
#endif

/* These hang off the client's own "tedge" root, which tedge-zephyr defines.
/* These hang off the client's own "tedge" root, which tiny-edge defines.
* An application that registered a root of the same name would give the
* device two of them, and the shell would only ever reach one. */
SHELL_SUBCMD_ADD((tedge), diag, NULL, "client state and TLS heap", cmd_diag,
Expand Down
Loading
Loading