p4n4 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.
- p4n4-0.1.0/.gitignore +44 -0
- p4n4-0.1.0/LICENSE +21 -0
- p4n4-0.1.0/PKG-INFO +633 -0
- p4n4-0.1.0/README.md +601 -0
- p4n4-0.1.0/p4n4/__init__.py +1 -0
- p4n4-0.1.0/p4n4/cli.py +53 -0
- p4n4-0.1.0/p4n4/commands/__init__.py +1 -0
- p4n4-0.1.0/p4n4/commands/add.py +18 -0
- p4n4-0.1.0/p4n4/commands/ei.py +23 -0
- p4n4-0.1.0/p4n4/commands/init.py +269 -0
- p4n4-0.1.0/p4n4/commands/lifecycle.py +126 -0
- p4n4-0.1.0/p4n4/commands/remove.py +18 -0
- p4n4-0.1.0/p4n4/commands/secret.py +80 -0
- p4n4-0.1.0/p4n4/commands/template.py +29 -0
- p4n4-0.1.0/p4n4/commands/upgrade.py +14 -0
- p4n4-0.1.0/p4n4/commands/validate.py +116 -0
- p4n4-0.1.0/p4n4/scaffold/__init__.py +1 -0
- p4n4-0.1.0/p4n4/sources.py +13 -0
- p4n4-0.1.0/p4n4/sources.yaml +3 -0
- p4n4-0.1.0/p4n4/utils/__init__.py +4 -0
- p4n4-0.1.0/p4n4/utils/compose.py +69 -0
- p4n4-0.1.0/p4n4/utils/env.py +40 -0
- p4n4-0.1.0/p4n4/utils/manifest.py +37 -0
- p4n4-0.1.0/pyproject.toml +62 -0
- p4n4-0.1.0/tests/__init__.py +0 -0
- p4n4-0.1.0/tests/conftest.py +18 -0
- p4n4-0.1.0/tests/test_cli.py +313 -0
p4n4-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.pyo
|
|
5
|
+
*.pyd
|
|
6
|
+
*.so
|
|
7
|
+
*.egg
|
|
8
|
+
*.egg-info/
|
|
9
|
+
dist/
|
|
10
|
+
build/
|
|
11
|
+
.eggs/
|
|
12
|
+
wheels/
|
|
13
|
+
|
|
14
|
+
# Virtual environments
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
|
|
19
|
+
# Testing
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
coverage.xml
|
|
23
|
+
htmlcov/
|
|
24
|
+
|
|
25
|
+
# Ruff / linters
|
|
26
|
+
.ruff_cache/
|
|
27
|
+
|
|
28
|
+
# Distribution / packaging
|
|
29
|
+
*.whl
|
|
30
|
+
*.tar.gz
|
|
31
|
+
MANIFEST
|
|
32
|
+
|
|
33
|
+
# Environment files
|
|
34
|
+
.env
|
|
35
|
+
.env.*
|
|
36
|
+
!.env.example
|
|
37
|
+
|
|
38
|
+
# Editor / OS
|
|
39
|
+
.DS_Store
|
|
40
|
+
Thumbs.db
|
|
41
|
+
.idea/
|
|
42
|
+
.vscode/
|
|
43
|
+
*.swp
|
|
44
|
+
*.swo
|
p4n4-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RAISGA
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
p4n4-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: p4n4
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI tool for bootstrapping and managing P4N4 projects
|
|
5
|
+
Project-URL: Homepage, https://github.com/raisga/p4n4-cli
|
|
6
|
+
Project-URL: Documentation, https://github.com/raisga/p4n4-docs
|
|
7
|
+
Project-URL: Issues, https://github.com/raisga/p4n4-cli/issues
|
|
8
|
+
Author-email: RAISGA <jraleman@raisga.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,docker,edge-ai,iot,scaffolding
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: jinja2>=3
|
|
23
|
+
Requires-Dist: pyyaml>=6
|
|
24
|
+
Requires-Dist: questionary>=2
|
|
25
|
+
Requires-Dist: rich>=13
|
|
26
|
+
Requires-Dist: typer[all]>=0.12
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# p4n4-cli
|
|
34
|
+
|
|
35
|
+
> Command-line tool for bootstrapping and managing **P4N4** projects — Platform for Nexus Neural Network Nodes.
|
|
36
|
+
|
|
37
|
+
`p4n4` scaffolds, configures, and orchestrates the P4N4 stack: the **MING** IoT services, Edge Impulse inference, and the Gen AI layer. It wraps `docker compose` with project-aware defaults and a guided setup flow.
|
|
38
|
+
|
|
39
|
+
Part of the [p4n4](https://github.com/raisga/p4n4) platform — an EdgeAI + GenAI integration platform for IoT deployments.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Table of Contents
|
|
44
|
+
|
|
45
|
+
- [Overview](#overview)
|
|
46
|
+
- [Repository Map](#repository-map)
|
|
47
|
+
- [Prerequisites](#prerequisites)
|
|
48
|
+
- [Installation](#installation)
|
|
49
|
+
- [Local Development](#local-development)
|
|
50
|
+
- [Quick Start](#quick-start)
|
|
51
|
+
- [Project Structure](#project-structure)
|
|
52
|
+
- [Commands](#commands)
|
|
53
|
+
- [p4n4 init](#p4n4-init)
|
|
54
|
+
- [p4n4 up](#p4n4-up)
|
|
55
|
+
- [p4n4 down](#p4n4-down)
|
|
56
|
+
- [p4n4 status](#p4n4-status)
|
|
57
|
+
- [p4n4 logs](#p4n4-logs)
|
|
58
|
+
- [p4n4 secret](#p4n4-secret)
|
|
59
|
+
- [p4n4 validate](#p4n4-validate)
|
|
60
|
+
- [p4n4 add](#p4n4-add)
|
|
61
|
+
- [p4n4 remove](#p4n4-remove)
|
|
62
|
+
- [p4n4 upgrade](#p4n4-upgrade)
|
|
63
|
+
- [p4n4 ei](#p4n4-ei)
|
|
64
|
+
- [p4n4 template](#p4n4-template)
|
|
65
|
+
- [Layers](#layers)
|
|
66
|
+
- [Configuration Reference](#configuration-reference)
|
|
67
|
+
- [Default Ports](#default-ports)
|
|
68
|
+
- [Source Repos](#source-repos)
|
|
69
|
+
- [Resources](#resources)
|
|
70
|
+
- [License](#license)
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Overview
|
|
75
|
+
|
|
76
|
+
P4N4 is a unified developer platform for IoT and Edge AI. It combines the **MING stack** (Mosquitto, InfluxDB, Node-RED, Grafana), **Edge Impulse** on-device ML inference, and a **Gen AI layer** (n8n, Letta, Ollama) into a single composable system.
|
|
77
|
+
|
|
78
|
+
`p4n4-cli` manages the full lifecycle — init, run, inspect, and tear down — from your terminal. Stack files are always fetched from the canonical source repos at init time, so projects are never pinned to a snapshot bundled inside the CLI.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Repository Map
|
|
83
|
+
|
|
84
|
+
| Repository | Description |
|
|
85
|
+
|------------|-------------|
|
|
86
|
+
| **[p4n4](https://github.com/raisga/p4n4)** | Umbrella repo — architecture, ADRs, cross-cutting docs |
|
|
87
|
+
| [p4n4-iot](https://github.com/raisga/p4n4-iot) | IoT stack: Mosquitto · InfluxDB · Node-RED · Grafana |
|
|
88
|
+
| [p4n4-ai](https://github.com/raisga/p4n4-ai) | GenAI stack: Ollama · Letta · n8n |
|
|
89
|
+
| [p4n4-edge](https://github.com/raisga/p4n4-edge) | Edge Impulse inference stack |
|
|
90
|
+
| [p4n4-api](https://github.com/raisga/p4n4-api) | Rust REST API gateway (port 8000) |
|
|
91
|
+
| [p4n4-lib](https://github.com/raisga/p4n4-lib) | Shared Rust library (`pip install p4n4lib` for Python bindings) |
|
|
92
|
+
| **[p4n4-cli](https://github.com/raisga/p4n4-cli)** | This repo — Python CLI (`pip install p4n4`) |
|
|
93
|
+
| [p4n4-templates](https://github.com/raisga/p4n4-templates) | Community template registry |
|
|
94
|
+
| [p4n4-docs](https://github.com/raisga/p4n4-docs) | Full technical documentation site |
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Prerequisites
|
|
99
|
+
|
|
100
|
+
- **Python** 3.11+
|
|
101
|
+
- **Git** (required by `p4n4 init` to clone stack repos)
|
|
102
|
+
- **Docker** v24+ (with Compose v2)
|
|
103
|
+
- **pipx** (recommended for isolated installation)
|
|
104
|
+
- At least **4 GB RAM** available to Docker (8 GB recommended when running Ollama)
|
|
105
|
+
|
|
106
|
+
Install `pipx` if you don't have it:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# macOS
|
|
110
|
+
brew install pipx && pipx ensurepath
|
|
111
|
+
|
|
112
|
+
# Linux / WSL
|
|
113
|
+
python3 -m pip install --user pipx && python3 -m pipx ensurepath
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Installation
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pipx install p4n4
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Or with plain pip:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
pip install p4n4
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Verify:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
p4n4 --version
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Upgrade / uninstall:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pipx upgrade p4n4
|
|
140
|
+
pipx uninstall p4n4
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Local Development
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# 1. Clone the repo
|
|
149
|
+
git clone https://github.com/raisga/p4n4-cli.git
|
|
150
|
+
cd p4n4-cli
|
|
151
|
+
|
|
152
|
+
# 2. Create the virtual environment
|
|
153
|
+
uv venv
|
|
154
|
+
source .venv/bin/activate
|
|
155
|
+
|
|
156
|
+
# 3. Install in editable mode with dev extras
|
|
157
|
+
uv pip install -e ".[dev]"
|
|
158
|
+
|
|
159
|
+
# 4. Verify
|
|
160
|
+
p4n4 --help
|
|
161
|
+
|
|
162
|
+
# 5. Run tests
|
|
163
|
+
pytest tests/ -v
|
|
164
|
+
|
|
165
|
+
# 6. Lint
|
|
166
|
+
ruff check .
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Quick Start
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Scaffold a new IoT project (fetches latest files from p4n4-iot)
|
|
175
|
+
p4n4 init my-project
|
|
176
|
+
cd my-project
|
|
177
|
+
|
|
178
|
+
# Validate the generated config
|
|
179
|
+
p4n4 validate
|
|
180
|
+
|
|
181
|
+
# Start the MING stack
|
|
182
|
+
p4n4 up
|
|
183
|
+
|
|
184
|
+
# Check service health
|
|
185
|
+
p4n4 status
|
|
186
|
+
|
|
187
|
+
# Tail logs from a specific service
|
|
188
|
+
p4n4 logs grafana
|
|
189
|
+
|
|
190
|
+
# Stop the stack
|
|
191
|
+
p4n4 down
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Scaffold a GenAI project instead:**
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
p4n4 init my-ai-project --layer ai
|
|
198
|
+
cd my-ai-project
|
|
199
|
+
p4n4 up
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Scaffold with all layers:**
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
p4n4 init my-full-project --layer all
|
|
206
|
+
cd my-full-project
|
|
207
|
+
p4n4 up
|
|
208
|
+
p4n4 up --ai
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**No internet access?** Point `--source-iot` / `--source-ai` at local checkouts:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
p4n4 init my-project --source-iot ../p4n4-iot
|
|
215
|
+
p4n4 init my-ai-project --layer ai --source-ai ../p4n4-ai
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Once the IoT stack is up:
|
|
219
|
+
|
|
220
|
+
| Service | URL |
|
|
221
|
+
|----------|-----------------------|
|
|
222
|
+
| Grafana | http://localhost:3000 |
|
|
223
|
+
| Node-RED | http://localhost:1880 |
|
|
224
|
+
| InfluxDB | http://localhost:8086 |
|
|
225
|
+
|
|
226
|
+
Once the AI stack is up:
|
|
227
|
+
|
|
228
|
+
| Service | URL |
|
|
229
|
+
|---------|------------------------|
|
|
230
|
+
| n8n | http://localhost:5678 |
|
|
231
|
+
| Letta | http://localhost:8283 |
|
|
232
|
+
| Ollama | http://localhost:11434 |
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## Project Structure
|
|
237
|
+
|
|
238
|
+
After `p4n4 init`, the project directory contains files sourced from the relevant stack repo(s). Stack files are never modified by the CLI after scaffolding.
|
|
239
|
+
|
|
240
|
+
**IoT layer (`--layer iot`, the default):**
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
my-project/
|
|
244
|
+
├── .p4n4.json # Manifest (project name, active layers, schema version)
|
|
245
|
+
├── .env # Credentials and config (auto-generated secrets)
|
|
246
|
+
├── docker-compose.yml # Stack orchestration (sourced from p4n4-iot)
|
|
247
|
+
├── config/
|
|
248
|
+
│ ├── mosquitto/
|
|
249
|
+
│ │ ├── mosquitto.conf # MQTT broker config
|
|
250
|
+
│ │ ├── passwd.example # Auth template for production hardening
|
|
251
|
+
│ │ └── acl.example # ACL template
|
|
252
|
+
│ ├── node-red/
|
|
253
|
+
│ │ ├── settings.js # Node-RED runtime settings
|
|
254
|
+
│ │ └── flows.json # MQTT → InfluxDB pipeline
|
|
255
|
+
│ └── grafana/
|
|
256
|
+
│ └── provisioning/
|
|
257
|
+
│ ├── datasources/
|
|
258
|
+
│ │ └── datasources.yml # Pre-configured InfluxDB datasources (5 buckets)
|
|
259
|
+
│ └── dashboards/
|
|
260
|
+
│ ├── dashboards.yml
|
|
261
|
+
│ └── json/
|
|
262
|
+
│ └── iot-overview.json
|
|
263
|
+
└── scripts/
|
|
264
|
+
├── init-buckets.sh # Creates additional InfluxDB buckets on first run
|
|
265
|
+
├── init-sandbox.sh
|
|
266
|
+
└── selector.sh
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**AI layer (`--layer ai`):**
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
my-ai-project/
|
|
273
|
+
├── .p4n4.json # Manifest
|
|
274
|
+
├── .env # Credentials and config (auto-generated secrets)
|
|
275
|
+
├── docker-compose.yml # Stack orchestration (sourced from p4n4-ai)
|
|
276
|
+
├── config/
|
|
277
|
+
│ ├── letta/
|
|
278
|
+
│ │ └── letta.conf # Letta agent server config
|
|
279
|
+
│ ├── n8n/
|
|
280
|
+
│ │ └── workflows/ # Pre-built n8n workflow definitions
|
|
281
|
+
│ │ ├── alert-enrichment.json
|
|
282
|
+
│ │ ├── device-onboarding.json
|
|
283
|
+
│ │ ├── incident-escalation.json
|
|
284
|
+
│ │ └── scheduled-digest.json
|
|
285
|
+
│ └── ollama/ # Ollama model storage (populated at runtime)
|
|
286
|
+
└── scripts/
|
|
287
|
+
├── pull-models.sh # Pull default Ollama models
|
|
288
|
+
└── selector.sh
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Commands
|
|
294
|
+
|
|
295
|
+
### `p4n4 init`
|
|
296
|
+
|
|
297
|
+
Scaffold a new P4N4 project. Clones the canonical stack repo(s) at init time so the project always starts from the latest source.
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
p4n4 init <project-name> [options]
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
| Flag | Description | Default |
|
|
304
|
+
|------|-------------|---------|
|
|
305
|
+
| `--layer <name>` | Layers to enable: `iot`, `ai`, `edge`, `all`, or comma-separated | `iot` |
|
|
306
|
+
| `--no-interactive` | Skip the wizard and use generated defaults | — |
|
|
307
|
+
| `--source-iot <path>` | Local p4n4-iot checkout (skips git clone; useful offline) | — |
|
|
308
|
+
| `--source-ai <path>` | Local p4n4-ai checkout (skips git clone; useful offline) | — |
|
|
309
|
+
|
|
310
|
+
The interactive wizard prompts for InfluxDB org, timezone, and admin passwords. When the `ai` layer is active it also prompts for Letta, n8n, and n8n encryption key values. All secrets default to randomly generated values if left blank.
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
# IoT stack, interactive wizard (default)
|
|
314
|
+
p4n4 init sensor-network
|
|
315
|
+
|
|
316
|
+
# GenAI stack, non-interactive
|
|
317
|
+
p4n4 init my-ai-project --layer ai --no-interactive
|
|
318
|
+
|
|
319
|
+
# All layers enabled
|
|
320
|
+
p4n4 init my-full-project --layer all
|
|
321
|
+
|
|
322
|
+
# From local checkouts (no network required)
|
|
323
|
+
p4n4 init sensor-network --source-iot ../p4n4-iot --no-interactive
|
|
324
|
+
p4n4 init my-ai-project --layer ai --source-ai ../p4n4-ai --no-interactive
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
### `p4n4 up`
|
|
330
|
+
|
|
331
|
+
Start the project stack (`docker compose up -d`).
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
p4n4 up [options]
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
| Flag | Description |
|
|
338
|
+
|------|-------------|
|
|
339
|
+
| `--ai` | Start Gen AI services only |
|
|
340
|
+
| `--edge` | Start Edge AI services only |
|
|
341
|
+
| `--build` | Rebuild images before starting |
|
|
342
|
+
| `--pull` | Pull the latest images before starting |
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
p4n4 up
|
|
346
|
+
p4n4 up --pull
|
|
347
|
+
p4n4 up --ai
|
|
348
|
+
p4n4 up --edge
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### `p4n4 down`
|
|
354
|
+
|
|
355
|
+
Stop all running services.
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
p4n4 down [options]
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
| Flag | Description |
|
|
362
|
+
|------|-------------|
|
|
363
|
+
| `--volumes` | Also remove persistent data volumes _(destructive — prompts for confirmation)_ |
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
p4n4 down
|
|
367
|
+
|
|
368
|
+
# Full teardown — deletes all stored data
|
|
369
|
+
p4n4 down --volumes
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
### `p4n4 status`
|
|
375
|
+
|
|
376
|
+
Print a service status table.
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
p4n4 status
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
Stack status — my-project
|
|
384
|
+
┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
|
|
385
|
+
┃ Service ┃ Status ┃ Health ┃ Ports ┃
|
|
386
|
+
┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
|
|
387
|
+
│ mqtt │ running │ healthy │ 1883→1883/tcp │
|
|
388
|
+
│ influxdb │ running │ healthy │ 8086→8086/tcp │
|
|
389
|
+
│ node-red │ running │ healthy │ 1880→1880/tcp │
|
|
390
|
+
│ grafana │ running │ healthy │ 3000→3000/tcp │
|
|
391
|
+
└───────────┴─────────┴─────────┴───────────────────────┘
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
### `p4n4 logs`
|
|
397
|
+
|
|
398
|
+
Stream logs from all services or a specific one.
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
p4n4 logs [service] [options]
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
| Flag | Description | Default |
|
|
405
|
+
|------|-------------|---------|
|
|
406
|
+
| `--tail <n>` | Lines from end of existing logs | `100` |
|
|
407
|
+
| `--no-follow` | Print once and exit | — |
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
p4n4 logs
|
|
411
|
+
p4n4 logs node-red
|
|
412
|
+
p4n4 logs influxdb --tail 50 --no-follow
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
### `p4n4 secret`
|
|
418
|
+
|
|
419
|
+
Rotate secrets in `.env` with new randomly generated values. Prompts for confirmation before writing. Rotates whichever of the following keys are present:
|
|
420
|
+
|
|
421
|
+
- **IoT layer:** `INFLUXDB_PASSWORD`, `INFLUXDB_TOKEN`, `GRAFANA_PASSWORD`
|
|
422
|
+
- **AI layer:** `LETTA_SERVER_PASSWORD`, `N8N_BASIC_AUTH_PASSWORD`, `N8N_ENCRYPTION_KEY`
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
p4n4 secret
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Run `p4n4 down && p4n4 up` after rotating secrets to apply them.
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
### `p4n4 validate`
|
|
433
|
+
|
|
434
|
+
Check that `.p4n4.json`, `.env`, and all required config files are present and valid for the active layers.
|
|
435
|
+
|
|
436
|
+
```bash
|
|
437
|
+
p4n4 validate
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
---
|
|
441
|
+
|
|
442
|
+
### `p4n4 add`
|
|
443
|
+
|
|
444
|
+
Add a layer or service to an existing project.
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
p4n4 add <component>
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
> Not yet implemented.
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
|
|
454
|
+
### `p4n4 remove`
|
|
455
|
+
|
|
456
|
+
Remove a layer or service from an existing project.
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
p4n4 remove <component>
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
> Not yet implemented.
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### `p4n4 upgrade`
|
|
467
|
+
|
|
468
|
+
Pull the latest Docker images for all active services.
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
p4n4 upgrade
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
> Not yet implemented.
|
|
475
|
+
|
|
476
|
+
---
|
|
477
|
+
|
|
478
|
+
### `p4n4 ei`
|
|
479
|
+
|
|
480
|
+
Manage Edge Impulse model deployment and inference.
|
|
481
|
+
|
|
482
|
+
```bash
|
|
483
|
+
p4n4 ei deploy
|
|
484
|
+
p4n4 ei run
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
| Subcommand | Description |
|
|
488
|
+
|------------|-------------|
|
|
489
|
+
| `deploy` | Deploy a trained Edge Impulse model to the edge device |
|
|
490
|
+
| `run` | Run inference and publish results over MQTT |
|
|
491
|
+
|
|
492
|
+
> Not yet implemented.
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
### `p4n4 template`
|
|
497
|
+
|
|
498
|
+
Browse and apply community project templates.
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
p4n4 template search [query]
|
|
502
|
+
p4n4 template apply <name>
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
> Not yet implemented.
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
509
|
+
## Layers
|
|
510
|
+
|
|
511
|
+
P4N4 is organized into three composable layers.
|
|
512
|
+
|
|
513
|
+
### IoT — MING Stack
|
|
514
|
+
|
|
515
|
+
| Service | Role |
|
|
516
|
+
|---------|------|
|
|
517
|
+
| **Mosquitto** | MQTT broker — central message bus |
|
|
518
|
+
| **InfluxDB** | Time-series database (5 pre-configured buckets) |
|
|
519
|
+
| **Node-RED** | Flow engine for MQTT routing and pipeline logic |
|
|
520
|
+
| **Grafana** | Real-time dashboarding and alerting |
|
|
521
|
+
|
|
522
|
+
### Edge
|
|
523
|
+
|
|
524
|
+
| Service | Role |
|
|
525
|
+
|---------|------|
|
|
526
|
+
| **Edge Impulse** | On-device ML inference; publishes results over MQTT |
|
|
527
|
+
|
|
528
|
+
### Gen AI
|
|
529
|
+
|
|
530
|
+
| Service | Role |
|
|
531
|
+
|---------|------|
|
|
532
|
+
| **n8n** | Workflow automation bridging IoT and AI layers |
|
|
533
|
+
| **Letta** | Stateful AI agent framework with long-term memory |
|
|
534
|
+
| **Ollama** | Local LLM runtime for open-weight models |
|
|
535
|
+
|
|
536
|
+
All three stacks communicate over a shared `p4n4-net` Docker bridge network owned by `p4n4-iot`. The CLI handles network creation and stack ordering automatically.
|
|
537
|
+
|
|
538
|
+
---
|
|
539
|
+
|
|
540
|
+
## Configuration Reference
|
|
541
|
+
|
|
542
|
+
`.env` is generated by `p4n4 init` with random secrets. Use `p4n4 secret` to rotate credentials at any time.
|
|
543
|
+
|
|
544
|
+
**IoT layer:**
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
TZ=UTC
|
|
548
|
+
|
|
549
|
+
# InfluxDB
|
|
550
|
+
INFLUXDB_USERNAME=admin
|
|
551
|
+
INFLUXDB_PASSWORD=<generated>
|
|
552
|
+
INFLUXDB_ORG=ming
|
|
553
|
+
INFLUXDB_TOKEN=<generated>
|
|
554
|
+
INFLUXDB_BUCKET=raw_telemetry
|
|
555
|
+
INFLUXDB_BUCKET_PROCESSED=processed_metrics
|
|
556
|
+
INFLUXDB_BUCKET_AI_EVENTS=ai_events
|
|
557
|
+
INFLUXDB_BUCKET_HEALTH=system_health
|
|
558
|
+
INFLUXDB_SANDBOX_BUCKET=sandbox
|
|
559
|
+
INFLUXDB_SANDBOX_RETENTION=30d
|
|
560
|
+
|
|
561
|
+
# Grafana
|
|
562
|
+
GRAFANA_USER=admin
|
|
563
|
+
GRAFANA_PASSWORD=<generated>
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
**AI layer:**
|
|
567
|
+
|
|
568
|
+
```bash
|
|
569
|
+
# Letta
|
|
570
|
+
LETTA_SERVER_PASSWORD=<generated>
|
|
571
|
+
|
|
572
|
+
# n8n
|
|
573
|
+
N8N_BASIC_AUTH_USER=admin
|
|
574
|
+
N8N_BASIC_AUTH_PASSWORD=<generated>
|
|
575
|
+
N8N_ENCRYPTION_KEY=<generated> # 32+ characters
|
|
576
|
+
N8N_HOST=localhost
|
|
577
|
+
|
|
578
|
+
# Shared InfluxDB (must match p4n4-iot values when used alongside it)
|
|
579
|
+
INFLUXDB_TOKEN=<generated>
|
|
580
|
+
INFLUXDB_ORG=ming
|
|
581
|
+
INFLUXDB_BUCKET=raw_telemetry
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## Default Ports
|
|
587
|
+
|
|
588
|
+
| Service | Port | Stack |
|
|
589
|
+
|----------------------|-----------------------------------|-------|
|
|
590
|
+
| MQTT (Mosquitto) | `1883` (MQTT), `9001` (WebSocket) | iot |
|
|
591
|
+
| InfluxDB | `8086` | iot |
|
|
592
|
+
| Node-RED | `1880` | iot |
|
|
593
|
+
| Grafana | `3000` | iot |
|
|
594
|
+
| n8n | `5678` | ai |
|
|
595
|
+
| Letta | `8283` | ai |
|
|
596
|
+
| Ollama | `11434` | ai |
|
|
597
|
+
| Edge Impulse Runner | `8080` (health endpoint) | edge |
|
|
598
|
+
| **p4n4 REST API** | **`8000`** | **api** |
|
|
599
|
+
|
|
600
|
+
---
|
|
601
|
+
|
|
602
|
+
## Source Repos
|
|
603
|
+
|
|
604
|
+
Stack files are fetched from these repos at `p4n4 init` time. URLs are defined in [`p4n4/sources.yaml`](p4n4/sources.yaml) and can be overridden per-layer via `--source-iot` / `--source-ai`, or by editing the file to point at a fork or mirror.
|
|
605
|
+
|
|
606
|
+
| Layer | Repo |
|
|
607
|
+
|-----------|------|
|
|
608
|
+
| IoT | https://github.com/raisga/p4n4-iot |
|
|
609
|
+
| AI | https://github.com/raisga/p4n4-ai |
|
|
610
|
+
| Edge | https://github.com/raisga/p4n4-edge |
|
|
611
|
+
| Templates | https://github.com/raisga/p4n4-templates |
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## Resources
|
|
616
|
+
|
|
617
|
+
- [p4n4.com](https://p4n4.com) — Platform overview
|
|
618
|
+
- [Full documentation](https://raisga.github.io/p4n4-docs) — MkDocs reference site
|
|
619
|
+
- [p4n4-iot](https://github.com/raisga/p4n4-iot) — MING stack source
|
|
620
|
+
- [p4n4-ai](https://github.com/raisga/p4n4-ai) — GenAI stack source
|
|
621
|
+
- [p4n4-edge](https://github.com/raisga/p4n4-edge) — Edge AI stack source
|
|
622
|
+
- [p4n4-templates](https://github.com/raisga/p4n4-templates) — Community template registry
|
|
623
|
+
- [MING Stack Tutorial](https://github.com/ArthurKretzer/tutorial-p4n4-stack) — IIoT data stack tutorial (XIV SBESC, 2024)
|
|
624
|
+
- [MING Stack with Edge Impulse](https://www.edgeimpulse.com/blog/accelerate-edge-ai-application-development-with-the-p4n4-stack-edge-impulse/) — Integration guide
|
|
625
|
+
- [Edge Impulse Linux SDK (Python)](https://github.com/edgeimpulse/linux-sdk-python)
|
|
626
|
+
- [Eclipse Mosquitto](https://mosquitto.org/) · [InfluxDB](https://docs.influxdata.com/) · [Node-RED](https://nodered.org/docs/) · [Grafana](https://grafana.com/docs/)
|
|
627
|
+
- [Ollama](https://github.com/ollama/ollama) · [Letta](https://docs.letta.com/) · [n8n](https://docs.n8n.io/)
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## License
|
|
632
|
+
|
|
633
|
+
This project is licensed under the [MIT License](LICENSE).
|