device-connect-server 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- device_connect_server-0.1.0/LICENSE +23 -0
- device_connect_server-0.1.0/PKG-INFO +30 -0
- device_connect_server-0.1.0/README.md +301 -0
- device_connect_server-0.1.0/device_connect_server/__init__.py +81 -0
- device_connect_server-0.1.0/device_connect_server/devctl/__init__.py +16 -0
- device_connect_server-0.1.0/device_connect_server/devctl/__main__.py +15 -0
- device_connect_server-0.1.0/device_connect_server/devctl/cli.py +638 -0
- device_connect_server-0.1.0/device_connect_server/device.py +3 -0
- device_connect_server-0.1.0/device_connect_server/drivers/__init__.py +40 -0
- device_connect_server-0.1.0/device_connect_server/drivers/base.py +2 -0
- device_connect_server-0.1.0/device_connect_server/drivers/capability_loader.py +850 -0
- device_connect_server-0.1.0/device_connect_server/drivers/decorators.py +2 -0
- device_connect_server-0.1.0/device_connect_server/errors.py +2 -0
- device_connect_server-0.1.0/device_connect_server/logging/__init__.py +42 -0
- device_connect_server-0.1.0/device_connect_server/logging/base.py +305 -0
- device_connect_server-0.1.0/device_connect_server/logging/mongo.py +160 -0
- device_connect_server-0.1.0/device_connect_server/messaging/__init__.py +3 -0
- device_connect_server-0.1.0/device_connect_server/messaging/base.py +2 -0
- device_connect_server-0.1.0/device_connect_server/messaging/config.py +2 -0
- device_connect_server-0.1.0/device_connect_server/messaging/exceptions.py +2 -0
- device_connect_server-0.1.0/device_connect_server/messaging/mqtt_adapter.py +2 -0
- device_connect_server-0.1.0/device_connect_server/messaging/nats_adapter.py +2 -0
- device_connect_server-0.1.0/device_connect_server/registry/__init__.py +18 -0
- device_connect_server-0.1.0/device_connect_server/registry/client.py +337 -0
- device_connect_server-0.1.0/device_connect_server/registry/service/__init__.py +1 -0
- device_connect_server-0.1.0/device_connect_server/registry/service/main.py +439 -0
- device_connect_server-0.1.0/device_connect_server/registry/service/registry.py +119 -0
- device_connect_server-0.1.0/device_connect_server/security/__init__.py +74 -0
- device_connect_server-0.1.0/device_connect_server/security/acl.py +303 -0
- device_connect_server-0.1.0/device_connect_server/security/commissioning.py +309 -0
- device_connect_server-0.1.0/device_connect_server/security/credentials.py +299 -0
- device_connect_server-0.1.0/device_connect_server/state/__init__.py +24 -0
- device_connect_server-0.1.0/device_connect_server/state/base.py +192 -0
- device_connect_server-0.1.0/device_connect_server/state/etcd_store.py +373 -0
- device_connect_server-0.1.0/device_connect_server/statectl/__init__.py +19 -0
- device_connect_server-0.1.0/device_connect_server/statectl/__main__.py +12 -0
- device_connect_server-0.1.0/device_connect_server/statectl/cli.py +439 -0
- device_connect_server-0.1.0/device_connect_server/telemetry/__init__.py +6 -0
- device_connect_server-0.1.0/device_connect_server/telemetry/config.py +2 -0
- device_connect_server-0.1.0/device_connect_server/telemetry/file_buffer_exporter.py +3 -0
- device_connect_server-0.1.0/device_connect_server/telemetry/metrics.py +2 -0
- device_connect_server-0.1.0/device_connect_server/telemetry/propagation.py +2 -0
- device_connect_server-0.1.0/device_connect_server/telemetry/tracer.py +2 -0
- device_connect_server-0.1.0/device_connect_server/types.py +2 -0
- device_connect_server-0.1.0/device_connect_server.egg-info/PKG-INFO +30 -0
- device_connect_server-0.1.0/device_connect_server.egg-info/SOURCES.txt +50 -0
- device_connect_server-0.1.0/device_connect_server.egg-info/dependency_links.txt +1 -0
- device_connect_server-0.1.0/device_connect_server.egg-info/entry_points.txt +3 -0
- device_connect_server-0.1.0/device_connect_server.egg-info/requires.txt +30 -0
- device_connect_server-0.1.0/device_connect_server.egg-info/top_level.txt +1 -0
- device_connect_server-0.1.0/pyproject.toml +45 -0
- device_connect_server-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Copyright 2024-2026 Arm Limited
|
|
2
|
+
PROPRIETARY AND CONFIDENTIAL
|
|
3
|
+
All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
This software and associated documentation files (the "Software") are the
|
|
6
|
+
proprietary and confidential property of Arm Limited. The Software is
|
|
7
|
+
provided under a separate Non-Disclosure Agreement (NDA) and may not be
|
|
8
|
+
used, copied, modified, merged, published, distributed, sublicensed, or
|
|
9
|
+
sold except as expressly permitted by that agreement.
|
|
10
|
+
|
|
11
|
+
Unauthorized copying, distribution, or use of this Software is strictly
|
|
12
|
+
prohibited and may result in civil and criminal penalties.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ARM
|
|
17
|
+
LIMITED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM
|
|
18
|
+
THE USE OF THE SOFTWARE.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
NOTE: This software is intended for future release under the Apache License,
|
|
23
|
+
Version 2.0. The open-source license will become effective upon public release.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: device-connect-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Device Connect — edge device runtime with Zenoh/NATS messaging, D2D communication, and IoT orchestration
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Requires-Dist: device-connect-sdk>=0.1.0
|
|
8
|
+
Provides-Extra: security
|
|
9
|
+
Requires-Dist: bcrypt>=4.0.0; extra == "security"
|
|
10
|
+
Requires-Dist: aiohttp>=3.9.0; extra == "security"
|
|
11
|
+
Requires-Dist: zeroconf>=0.131.0; extra == "security"
|
|
12
|
+
Requires-Dist: qrcode[pil]>=7.4.2; extra == "security"
|
|
13
|
+
Provides-Extra: telemetry
|
|
14
|
+
Requires-Dist: opentelemetry-api>=1.30.0; extra == "telemetry"
|
|
15
|
+
Requires-Dist: opentelemetry-sdk>=1.30.0; extra == "telemetry"
|
|
16
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.30.0; extra == "telemetry"
|
|
17
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.30.0; extra == "telemetry"
|
|
18
|
+
Provides-Extra: state
|
|
19
|
+
Requires-Dist: etcd3gw<3,>=2.4.0; extra == "state"
|
|
20
|
+
Provides-Extra: logging
|
|
21
|
+
Requires-Dist: pymongo; extra == "logging"
|
|
22
|
+
Provides-Extra: mqtt
|
|
23
|
+
Requires-Dist: aiomqtt; extra == "mqtt"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-timeout>=2.0; extra == "dev"
|
|
28
|
+
Provides-Extra: all
|
|
29
|
+
Requires-Dist: device-connect-server[dev,logging,mqtt,security,state,telemetry]; extra == "all"
|
|
30
|
+
Dynamic: license-file
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="../../logo.svg" alt="Device Connect" width="400">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# device-connect-server
|
|
6
|
+
|
|
7
|
+
Server-side runtime for the Device Connect framework. Extends [device-connect-sdk](../device-connect-sdk/) with device registry, security (commissioning, ACLs), distributed state, audit logging, and CLI tools.
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [Where This Fits](#where-this-fits)
|
|
12
|
+
- [Install](#install)
|
|
13
|
+
- [Quick Start](#quick-start)
|
|
14
|
+
- [CLI Tools](#cli-tools)
|
|
15
|
+
- [Device Commissioning Flow](#device-commissioning-flow)
|
|
16
|
+
- [Testing](#testing)
|
|
17
|
+
- [Contributing](#contributing)
|
|
18
|
+
|
|
19
|
+
## Where This Fits
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
device-connect-sdk device-connect-server device-connect-agent-tools
|
|
23
|
+
(Device Connect SDK) (server runtime — this) (agent SDK)
|
|
24
|
+
│ │ │
|
|
25
|
+
└──────────────── Mesh ─────────────────────────────┘
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- **device-connect-sdk** — runs on physical devices (Raspberry Pi, robots, cameras, sensors)
|
|
29
|
+
- **device-connect-server** — runs on servers. Adds registry, security, state, and CLIs
|
|
30
|
+
- **device-connect-agent-tools** — connects AI agents (Strands, LangChain, MCP) to the device mesh
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
> Not yet on PyPI. Install from Git:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python3 -m venv .venv
|
|
38
|
+
source .venv/bin/activate
|
|
39
|
+
pip install -e "../device-connect-sdk"
|
|
40
|
+
pip install -e ".[all]"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This pulls in `device-connect-sdk` automatically. Optional extras:
|
|
44
|
+
|
|
45
|
+
| Extra | Adds |
|
|
46
|
+
|-------|------|
|
|
47
|
+
| `[security]` | bcrypt, aiohttp, zeroconf, qrcode (commissioning + ACLs) |
|
|
48
|
+
| `[telemetry]` | OpenTelemetry SDK + OTLP exporters |
|
|
49
|
+
| `[state]` | etcd3gw (distributed state store) |
|
|
50
|
+
| `[logging]` | pymongo (audit logging to MongoDB) |
|
|
51
|
+
| `[mqtt]` | aiomqtt (MQTT messaging backend) |
|
|
52
|
+
| `[all]` | All of the above + dev tools |
|
|
53
|
+
|
|
54
|
+
> **Note:** Zenoh is now a core dependency of `device-connect-sdk` and is included automatically.
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
> **Prerequisites:** Complete the [Install](#install) steps first (venv active, packages installed). You also need Docker. For JWT auth you additionally need [nsc](https://github.com/nats-io/nsc) (`brew install nsc`).
|
|
59
|
+
|
|
60
|
+
### 1. Start infrastructure
|
|
61
|
+
|
|
62
|
+
Choose a deployment mode:
|
|
63
|
+
|
|
64
|
+
<details open>
|
|
65
|
+
<summary><b>Zenoh (dev mode, no auth)</b></summary>
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
docker compose -f infra/docker-compose-dev.yml up -d
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
</details>
|
|
72
|
+
|
|
73
|
+
<details>
|
|
74
|
+
<summary><b>Secure — Zenoh (TLS)</b></summary>
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# 1. Generate CA + Zenoh router + registry client certificates
|
|
78
|
+
./security_infra/generate_tls_certs.sh zenoh
|
|
79
|
+
|
|
80
|
+
# 2. Generate a client certificate for each device
|
|
81
|
+
./security_infra/generate_tls_certs.sh --client rng-001
|
|
82
|
+
|
|
83
|
+
# 3. Start infrastructure with TLS
|
|
84
|
+
docker compose -f infra/docker-compose.yml up -d
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
</details>
|
|
88
|
+
|
|
89
|
+
<details>
|
|
90
|
+
<summary><b>NATS (dev mode, no auth)</b></summary>
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
docker compose -f infra/docker-compose-nats-dev.yml up -d
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
</details>
|
|
97
|
+
|
|
98
|
+
<details>
|
|
99
|
+
<summary><b>Authenticated — NATS (JWT auth)</b></summary>
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# 1. Generate NATS JWT config
|
|
103
|
+
./security_infra/setup_jwt_auth.sh dev
|
|
104
|
+
|
|
105
|
+
# 2. Generate credentials for built-in roles (registry, devctl)
|
|
106
|
+
./security_infra/gen_creds.sh --all --force
|
|
107
|
+
|
|
108
|
+
# 3. Generate credentials for each device and agent
|
|
109
|
+
./security_infra/gen_creds.sh --user rng-001
|
|
110
|
+
./security_infra/gen_creds.sh --user my-agent
|
|
111
|
+
|
|
112
|
+
# 4. Start infrastructure with JWT auth
|
|
113
|
+
docker compose -f infra/docker-compose-nats.yml up -d
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
</details>
|
|
117
|
+
|
|
118
|
+
| Service | Port | Purpose |
|
|
119
|
+
|---------|------|---------|
|
|
120
|
+
| zenoh | 7447 | Zenoh messaging |
|
|
121
|
+
| nats / nats-jwt | 4222 | NATS messaging |
|
|
122
|
+
| etcd | 2379 | Distributed state store |
|
|
123
|
+
| device-registry-service | 8080 | Device registration and discovery |
|
|
124
|
+
|
|
125
|
+
### 2. Connect a simulated device
|
|
126
|
+
|
|
127
|
+
The number generator simulator connects to the messaging backend, registers itself with the device registry, and emits `number_generated` events every 5 seconds.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cd ../device-connect-sdk # sibling package in the monorepo
|
|
131
|
+
|
|
132
|
+
# Zenoh (dev mode, no auth)
|
|
133
|
+
DEVICE_CONNECT_ALLOW_INSECURE=true ZENOH_CONNECT=tcp/localhost:7447 \
|
|
134
|
+
python examples/number_generator/device_simulator.py
|
|
135
|
+
|
|
136
|
+
# Secure — Zenoh (TLS)
|
|
137
|
+
# ZENOH_CONNECT=tls/localhost:7447 \
|
|
138
|
+
# MESSAGING_TLS_CA_FILE=../device-connect-server/security_infra/ca.pem \
|
|
139
|
+
# MESSAGING_TLS_CERT_FILE=../device-connect-server/security_infra/rng-001-cert.pem \
|
|
140
|
+
# MESSAGING_TLS_KEY_FILE=../device-connect-server/security_infra/rng-001-key.pem \
|
|
141
|
+
# python examples/number_generator/device_simulator.py
|
|
142
|
+
|
|
143
|
+
# Insecure — NATS (no auth)
|
|
144
|
+
# DEVICE_CONNECT_ALLOW_INSECURE=true python examples/number_generator/device_simulator.py
|
|
145
|
+
|
|
146
|
+
# Authenticated — NATS (JWT auth)
|
|
147
|
+
# NATS_CREDENTIALS_FILE=~/.device-connect/credentials/rng-001.creds.json \
|
|
148
|
+
# NATS_URL=nats://localhost:4222 python examples/number_generator/device_simulator.py
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### 3. Verify the device registered
|
|
152
|
+
|
|
153
|
+
`devctl list` queries the registry service and returns all connected devices with their capabilities, identity, and status. `statectl` reads the same data directly from etcd.
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Zenoh (dev mode, no auth)
|
|
157
|
+
ZENOH_CONNECT=tcp/localhost:7447 devctl list
|
|
158
|
+
statectl --raw list /device-connect/default/devices/
|
|
159
|
+
|
|
160
|
+
# Secure — Zenoh (TLS)
|
|
161
|
+
# ZENOH_CONNECT=tls/localhost:7447 \
|
|
162
|
+
# MESSAGING_TLS_CA_FILE=security_infra/ca.pem \
|
|
163
|
+
# MESSAGING_TLS_CERT_FILE=security_infra/rng-001-cert.pem \
|
|
164
|
+
# MESSAGING_TLS_KEY_FILE=security_infra/rng-001-key.pem \
|
|
165
|
+
# devctl list
|
|
166
|
+
|
|
167
|
+
# Insecure — NATS (no auth)
|
|
168
|
+
# devctl list
|
|
169
|
+
|
|
170
|
+
# Authenticated — NATS (JWT auth)
|
|
171
|
+
# NATS_CREDENTIALS_FILE=~/.device-connect/credentials/devctl.creds.json \
|
|
172
|
+
# NATS_URL=nats://localhost:4222 devctl list
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### 4. Connect an AI agent
|
|
176
|
+
|
|
177
|
+
The Strands Agent subscribes to all device events on the mesh (`device-connect.default.*.event.>`), batches them over a time window, and sends them to Claude for analysis. Claude can call back into devices using `invoke_device()` and `get_device_status()` tools.
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
git clone https://github.com/arm/strands-device-connect-example.git
|
|
181
|
+
cd strands-device-connect-example
|
|
182
|
+
pip install -r requirements.txt
|
|
183
|
+
|
|
184
|
+
# Insecure — Zenoh (no auth)
|
|
185
|
+
ZENOH_CONNECT=tcp/localhost:7447 \
|
|
186
|
+
ANTHROPIC_API_KEY="sk-ant-..." python strands_agent.py
|
|
187
|
+
|
|
188
|
+
# Secure — Zenoh (TLS)
|
|
189
|
+
# ZENOH_CONNECT=tls/localhost:7447 \
|
|
190
|
+
# MESSAGING_TLS_CA_FILE=../device-connect-server/security_infra/ca.pem \
|
|
191
|
+
# MESSAGING_TLS_CERT_FILE=../device-connect-server/security_infra/my-agent-cert.pem \
|
|
192
|
+
# MESSAGING_TLS_KEY_FILE=../device-connect-server/security_infra/my-agent-key.pem \
|
|
193
|
+
# ANTHROPIC_API_KEY="sk-ant-..." python strands_agent.py
|
|
194
|
+
|
|
195
|
+
# Insecure — NATS (no auth)
|
|
196
|
+
# ANTHROPIC_API_KEY="sk-ant-..." python strands_agent.py
|
|
197
|
+
|
|
198
|
+
# Authenticated — NATS (JWT auth)
|
|
199
|
+
# ANTHROPIC_API_KEY="sk-ant-..." \
|
|
200
|
+
# NATS_CREDENTIALS_FILE=~/.device-connect/credentials/my-agent.creds.json \
|
|
201
|
+
# NATS_URL=nats://localhost:4222 python strands_agent.py
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
> Get an API key at [console.anthropic.com](https://console.anthropic.com/).
|
|
205
|
+
|
|
206
|
+
### 5. Tear down
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Insecure — Zenoh (no auth)
|
|
210
|
+
docker compose -f infra/docker-compose-dev.yml down
|
|
211
|
+
|
|
212
|
+
# Secure — Zenoh (TLS)
|
|
213
|
+
# docker compose -f infra/docker-compose.yml down
|
|
214
|
+
|
|
215
|
+
# Insecure — NATS (no auth)
|
|
216
|
+
# docker compose -f infra/docker-compose-nats-dev.yml down
|
|
217
|
+
|
|
218
|
+
# Authenticated — NATS (JWT auth)
|
|
219
|
+
# docker compose -f infra/docker-compose-nats.yml down
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
To clean up everything:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
rm -rf .venv
|
|
226
|
+
rm -rf ~/.device-connect/credentials
|
|
227
|
+
rm -rf security_infra/.nsc security_infra/nats-jwt-generated.conf
|
|
228
|
+
rm -f security_infra/*.pem security_infra/*.srl
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
See [device-connect-sdk — Credentials](../device-connect-sdk/README.md#credentials) for the credentials file format.
|
|
232
|
+
|
|
233
|
+
## CLI Tools
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Device control
|
|
237
|
+
devctl list # list registered devices
|
|
238
|
+
devctl list --compact # compact output
|
|
239
|
+
devctl register --id myDevice --keepalive # register a test device
|
|
240
|
+
devctl discover --timeout 5 # find uncommissioned devices (mDNS)
|
|
241
|
+
devctl commission cam-001 --pin 1234-5678 # commission a device
|
|
242
|
+
devctl interactive # REPL for device operations
|
|
243
|
+
|
|
244
|
+
# State management
|
|
245
|
+
statectl get experiments/EXP-001 # read a key
|
|
246
|
+
statectl list experiments/ # list keys under prefix
|
|
247
|
+
statectl set experiments/EXP-001 '{"status": "done"}' --ttl 3600
|
|
248
|
+
statectl delete experiments/EXP-001 # delete a key
|
|
249
|
+
statectl watch experiments/ --prefix # watch for changes
|
|
250
|
+
statectl locks # list held locks
|
|
251
|
+
statectl stats # key counts by namespace
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Device Commissioning Flow
|
|
255
|
+
|
|
256
|
+
New devices must be provisioned and commissioned before joining the mesh. The mechanism depends on your messaging backend:
|
|
257
|
+
|
|
258
|
+
- **Zenoh** — uses mTLS (mutual TLS). Each device gets a client certificate signed by the shared CA. Generate one with `./security_infra/generate_tls_certs.sh --client <device-id>`.
|
|
259
|
+
- **NATS** — uses JWT credentials. Each device gets a JWT + NKey pair. Generate one with `./security_infra/gen_creds.sh --user <device-id>`.
|
|
260
|
+
|
|
261
|
+
### NATS JWT commissioning (detailed)
|
|
262
|
+
|
|
263
|
+
Using `camera-001` as an example:
|
|
264
|
+
|
|
265
|
+
1. **Provision** (factory): generate an identity with NKey keypair + factory PIN
|
|
266
|
+
2. **Generate credentials** (admin): `./security_infra/gen_creds.sh --user camera-001`
|
|
267
|
+
3. **Commission** (admin): `devctl commission camera-001 --pin 1234-5678`
|
|
268
|
+
- Delivers credentials to the device's commissioning HTTP server
|
|
269
|
+
- Device saves credentials and connects to NATS
|
|
270
|
+
4. **Operate** (every boot): device loads credentials from disk, connects, registers, starts heartbeats
|
|
271
|
+
|
|
272
|
+
Each device becomes a user under the shared DEVICE-CONNECT account — all users in the same account can communicate over `device-connect.*` subjects:
|
|
273
|
+
|
|
274
|
+
```
|
|
275
|
+
Operator: dc-operator (trust root)
|
|
276
|
+
└─ Account: DEVICE-CONNECT (shared namespace)
|
|
277
|
+
├─ User: registry (registry service)
|
|
278
|
+
├─ User: devctl (CLI tools)
|
|
279
|
+
├─ User: orchestrator (server coordination)
|
|
280
|
+
├─ User: camera-001 (per-device, via --user)
|
|
281
|
+
└─ User: my-agent (AI agent, via --user)
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
See [device-connect-sdk — Credentials](../device-connect-sdk/README.md#credentials) for how devices consume credentials at runtime.
|
|
285
|
+
|
|
286
|
+
AI agents connecting via [device-connect-agent-tools](../device-connect-agent-tools/) also need their own credentials: `./security_infra/gen_creds.sh --user my-agent` (NATS) or `./security_infra/generate_tls_certs.sh --client my-agent` (Zenoh).
|
|
287
|
+
|
|
288
|
+
## Testing
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
python3 -m venv .venv
|
|
292
|
+
source .venv/bin/activate
|
|
293
|
+
pip install -e ".[all]"
|
|
294
|
+
pytest tests/ -v --timeout=30
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Unit tests run without external services. Integration tests are in [tests/](../../tests/).
|
|
298
|
+
|
|
299
|
+
## Contributing
|
|
300
|
+
|
|
301
|
+
We welcome contributions! Please open an [issue](https://github.com/arm/device-connect/issues) to report bugs or suggest features, or submit a [pull request](https://github.com/arm/device-connect/pulls) directly.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Device Connect - Edge device orchestration framework.
|
|
2
|
+
|
|
3
|
+
This package re-exports everything from device_connect_sdk (the lightweight
|
|
4
|
+
device SDK) and adds core extensions: registry, security, state, logging,
|
|
5
|
+
CapabilityLoader, devctl, and statectl.
|
|
6
|
+
|
|
7
|
+
Core Components:
|
|
8
|
+
- DeviceRuntime: Runtime that hosts a DeviceDriver (handles messaging, registration, heartbeats)
|
|
9
|
+
- DeviceDriver: Abstract base for device-specific logic
|
|
10
|
+
- DeviceCapabilities, DeviceIdentity, DeviceStatus: Type definitions
|
|
11
|
+
|
|
12
|
+
Submodules:
|
|
13
|
+
- device_connect_server.drivers: Device driver framework with decorators
|
|
14
|
+
- device_connect_server.messaging: Pluggable messaging (NATS, MQTT)
|
|
15
|
+
- device_connect_server.security: ACLs, commissioning, credentials
|
|
16
|
+
- device_connect_server.state: State store abstractions
|
|
17
|
+
- device_connect_server.registry: Registry client and service
|
|
18
|
+
- device_connect_server.telemetry: OpenTelemetry distributed tracing
|
|
19
|
+
- device_connect_server.logging: Audit logging framework
|
|
20
|
+
- device_connect_server.devctl: Device control CLI
|
|
21
|
+
- device_connect_server.statectl: State management CLI
|
|
22
|
+
|
|
23
|
+
Example:
|
|
24
|
+
from device_connect_server import DeviceRuntime
|
|
25
|
+
from device_connect_server.drivers import DeviceDriver, rpc
|
|
26
|
+
from device_connect_server.types import DeviceCapabilities
|
|
27
|
+
|
|
28
|
+
class CameraDriver(DeviceDriver):
|
|
29
|
+
device_type = "camera"
|
|
30
|
+
|
|
31
|
+
@rpc()
|
|
32
|
+
async def capture_image(self, resolution: str = "1080p") -> dict:
|
|
33
|
+
'''Capture an image.'''
|
|
34
|
+
return {"image_b64": "..."}
|
|
35
|
+
|
|
36
|
+
device = DeviceRuntime(
|
|
37
|
+
driver=CameraDriver(),
|
|
38
|
+
device_id="camera-001",
|
|
39
|
+
messaging_urls=["nats://localhost:4222"]
|
|
40
|
+
)
|
|
41
|
+
await device.run()
|
|
42
|
+
"""
|
|
43
|
+
# Re-export everything from device_connect_sdk
|
|
44
|
+
from device_connect_sdk import ( # noqa: F401
|
|
45
|
+
DeviceRuntime,
|
|
46
|
+
build_rpc_error,
|
|
47
|
+
build_rpc_response,
|
|
48
|
+
DeviceState,
|
|
49
|
+
DeviceCapabilities,
|
|
50
|
+
DeviceIdentity,
|
|
51
|
+
DeviceStatus,
|
|
52
|
+
FunctionDef,
|
|
53
|
+
EventDef,
|
|
54
|
+
DeviceConnectError,
|
|
55
|
+
DeviceError,
|
|
56
|
+
RegistrationError,
|
|
57
|
+
FunctionInvocationError,
|
|
58
|
+
ValidationError,
|
|
59
|
+
CommissioningError,
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
__all__ = [
|
|
63
|
+
# Device runtime
|
|
64
|
+
"DeviceRuntime",
|
|
65
|
+
"build_rpc_error",
|
|
66
|
+
"build_rpc_response",
|
|
67
|
+
# Types
|
|
68
|
+
"DeviceState",
|
|
69
|
+
"DeviceCapabilities",
|
|
70
|
+
"DeviceIdentity",
|
|
71
|
+
"DeviceStatus",
|
|
72
|
+
"FunctionDef",
|
|
73
|
+
"EventDef",
|
|
74
|
+
# Errors
|
|
75
|
+
"DeviceConnectError",
|
|
76
|
+
"DeviceError",
|
|
77
|
+
"RegistrationError",
|
|
78
|
+
"FunctionInvocationError",
|
|
79
|
+
"ValidationError",
|
|
80
|
+
"CommissioningError",
|
|
81
|
+
]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Device control CLI for Device Connect.
|
|
2
|
+
|
|
3
|
+
This module provides a command-line interface for interacting with
|
|
4
|
+
the device registry, commissioning devices, and performing device operations.
|
|
5
|
+
|
|
6
|
+
CLI Usage:
|
|
7
|
+
python -m device_connect_server.devctl list [--compact]
|
|
8
|
+
python -m device_connect_server.devctl register --id myDevice [--keepalive]
|
|
9
|
+
python -m device_connect_server.devctl discover [--timeout 5]
|
|
10
|
+
python -m device_connect_server.devctl commission <device_id> --pin 1234-5678
|
|
11
|
+
python -m device_connect_server.devctl interactive
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from device_connect_server.devctl.cli import main
|
|
15
|
+
|
|
16
|
+
__all__ = ["main"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Entry point for running devctl as a module.
|
|
2
|
+
|
|
3
|
+
Usage:
|
|
4
|
+
python -m device_connect_server.devctl list
|
|
5
|
+
python -m device_connect_server.devctl register --id myDevice
|
|
6
|
+
python -m device_connect_server.devctl discover
|
|
7
|
+
python -m device_connect_server.devctl commission <device_id> --pin 1234-5678
|
|
8
|
+
python -m device_connect_server.devctl interactive
|
|
9
|
+
python -m device_connect_server.devctl --help
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from device_connect_server.devctl.cli import main
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
main()
|