feat: initial KosmoConnect platform v0.1
Includes: - Backend services: ingestion (:8001), weather API (:8002), gateway (:8003), billing (:8004) with BTCPay integration - Shared asyncpg pool, TimescaleDB hypertable, Redis, Mosquitto MQTT - React frontend: Dashboard (MapLibre) and Messaging (chat UI) - Bridge daemon for Pi + Meshtastic (Serial/TCP T-Deck support) - Production Docker Compose, Nginx reverse proxy, ops scripts - DEPLOY.md with step-by-step deployment guide
This commit is contained in:
203
docs/api/openapi-draft.yaml
Normal file
203
docs/api/openapi-draft.yaml
Normal file
@@ -0,0 +1,203 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: KosmoConnect API
|
||||
description: Draft OpenAPI specification for the KosmoConnect platform.
|
||||
version: 0.1.0
|
||||
|
||||
paths:
|
||||
/api/v1/weather/latest:
|
||||
get:
|
||||
summary: Get latest readings from all nodes
|
||||
parameters:
|
||||
- name: node_id
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
required: false
|
||||
description: Filter by specific node ID
|
||||
responses:
|
||||
'200':
|
||||
description: Latest environmental readings
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/EnviroReading'
|
||||
|
||||
/api/v1/weather/history:
|
||||
get:
|
||||
summary: Get historical readings for a node
|
||||
parameters:
|
||||
- name: node_id
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: start
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
- name: end
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
- name: interval
|
||||
in: query
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
enum: [raw, 1h, 1d]
|
||||
responses:
|
||||
'200':
|
||||
description: Historical environmental data
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/EnviroReading'
|
||||
|
||||
/api/v1/messages:
|
||||
post:
|
||||
summary: Send a message to a mesh node
|
||||
security:
|
||||
- bearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/OutboundMessage'
|
||||
responses:
|
||||
'202':
|
||||
description: Message accepted and queued
|
||||
'403':
|
||||
description: Subscription does not allow messaging this node
|
||||
'429':
|
||||
description: Rate limit exceeded
|
||||
|
||||
/api/v1/messages/conversations:
|
||||
get:
|
||||
summary: Get user's message conversations
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: List of conversation summaries
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
node_id:
|
||||
type: string
|
||||
nickname:
|
||||
type: string
|
||||
latest_text:
|
||||
type: string
|
||||
latest_at:
|
||||
type: string
|
||||
format: date-time
|
||||
unread_count:
|
||||
type: integer
|
||||
|
||||
/api/v1/messages/conversations/{node_id}:
|
||||
get:
|
||||
summary: Get full conversation with a node
|
||||
security:
|
||||
- bearerAuth: []
|
||||
parameters:
|
||||
- name: node_id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: Message history
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
direction:
|
||||
type: string
|
||||
sender_node_id:
|
||||
type: string
|
||||
target_node_id:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
status:
|
||||
type: string
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
components:
|
||||
schemas:
|
||||
EnviroReading:
|
||||
type: object
|
||||
properties:
|
||||
node_id:
|
||||
type: string
|
||||
timestamp:
|
||||
type: string
|
||||
format: date-time
|
||||
temperature_c:
|
||||
type: number
|
||||
humidity_percent:
|
||||
type: number
|
||||
pressure_pa:
|
||||
type: number
|
||||
wind_speed_ms:
|
||||
type: number
|
||||
wind_direction:
|
||||
type: integer
|
||||
pm25_ugm3:
|
||||
type: number
|
||||
pm10_ugm3:
|
||||
type: number
|
||||
gas_resistance_kohm:
|
||||
type: number
|
||||
|
||||
OutboundMessage:
|
||||
type: object
|
||||
properties:
|
||||
target_node_id:
|
||||
type: string
|
||||
text:
|
||||
type: string
|
||||
maxLength: 200
|
||||
required:
|
||||
- target_node_id
|
||||
- text
|
||||
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
145
docs/architecture/data-flow.md
Normal file
145
docs/architecture/data-flow.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Data Flow
|
||||
|
||||
This document describes how environmental data moves from the sensor to the user's web browser, and how control/commands flow in the opposite direction.
|
||||
|
||||
## 1. Sensor Reading & Local Storage
|
||||
|
||||
**Frequency**: Every 60 seconds (configurable)
|
||||
**Actor**: Enviro-Node firmware
|
||||
|
||||
1. MCU wakes from deep sleep (or remains active if interval is short)
|
||||
2. Sensors are powered on, stabilized, and read
|
||||
3. Raw readings are calibrated and packaged into a compact binary format
|
||||
4. The packet is appended to a local ring buffer in SPI flash or SD card
|
||||
5. A "data ready" flag is set for the Meshtastic module
|
||||
|
||||
### Data Packet Structure (Enviro-Node Local)
|
||||
```c
|
||||
typedef struct {
|
||||
uint32_t timestamp_unix;
|
||||
int16_t temperature_c; // 0.01°C resolution
|
||||
uint16_t humidity_percent; // 0.01% resolution
|
||||
uint32_t pressure_pa;
|
||||
uint16_t wind_speed_ms; // 0.1 m/s resolution
|
||||
uint16_t wind_direction; // degrees
|
||||
uint16_t pm25_ugm3;
|
||||
uint16_t pm10_ugm3;
|
||||
uint16_t gas_resistance_kohm;
|
||||
uint8_t node_id[6]; // Meshtastic Node ID
|
||||
uint16_t crc16;
|
||||
} enviro_packet_t;
|
||||
```
|
||||
|
||||
## 2. Mesh Transmission
|
||||
|
||||
**Frequency**: Every 5-15 minutes (configurable, power-dependent)
|
||||
**Actor**: Meshtastic firmware + custom module
|
||||
|
||||
1. The custom module requests one or more packets from the local buffer
|
||||
2. Packets are encoded into a Meshtastic `DATA` payload on a dedicated environmental channel
|
||||
3. The packet is broadcast into the mesh with `want_ack = false` (fire-and-forget for efficiency)
|
||||
4. If an infrastructure node is within range (direct or multi-hop), it receives the packet
|
||||
5. If no ACK or route is available, the packet remains in the buffer for the next transmission window
|
||||
|
||||
### Channel Strategy
|
||||
- **Primary Channel**: Standard Meshtastic LongFast for relaying user messages
|
||||
- **Secondary Channel**: Custom `KOSMO_ENV` channel for environmental data (can use different frequency slot or SF to avoid congesting primary channel)
|
||||
|
||||
## 3. Bridge Ingestion
|
||||
|
||||
**Actor**: Infrastructure Node Bridge Daemon
|
||||
|
||||
1. The bridge daemon listens to Meshtastic packets via the serial/protobuf API
|
||||
2. It filters for packets on the `KOSMO_ENV` channel or with a specific portnum
|
||||
3. Valid environmental packets are decoded and wrapped in a JSON envelope:
|
||||
```json
|
||||
{
|
||||
"type": "enviro_reading",
|
||||
"node_id": "!a1b2c3d4",
|
||||
"received_at": "2026-04-12T09:15:00Z",
|
||||
"hop_count": 2,
|
||||
"payload": {
|
||||
"timestamp": 1744446900,
|
||||
"temperature_c": 18.50,
|
||||
"humidity_percent": 62.30,
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
4. The envelope is published to the cloud MQTT broker topic: `kosmo/ingest/enviro`
|
||||
|
||||
## 4. Cloud Ingestion
|
||||
|
||||
**Actor**: Backend Ingestion Service
|
||||
|
||||
1. The ingestion service subscribes to `kosmo/ingest/#`
|
||||
2. On receiving a message:
|
||||
- Validate JSON schema
|
||||
- Verify `node_id` is registered and active
|
||||
- Write raw payload to TimescaleDB hypertable `enviro_readings`
|
||||
- Update node `last_seen` timestamp in PostgreSQL
|
||||
- If the node has a backlog, trigger a "sync complete" notification (optional)
|
||||
|
||||
### Database Schema (Simplified)
|
||||
```sql
|
||||
-- TimescaleDB
|
||||
CREATE TABLE enviro_readings (
|
||||
time TIMESTAMPTZ NOT NULL,
|
||||
node_id TEXT NOT NULL,
|
||||
temperature_c DOUBLE PRECISION,
|
||||
humidity_percent DOUBLE PRECISION,
|
||||
pressure_pa DOUBLE PRECISION,
|
||||
wind_speed_ms DOUBLE PRECISION,
|
||||
wind_direction SMALLINT,
|
||||
pm25_ugm3 DOUBLE PRECISION,
|
||||
pm10_ugm3 DOUBLE PRECISION,
|
||||
gas_resistance_kohm DOUBLE PRECISION
|
||||
);
|
||||
SELECT create_hypertable('enviro_readings', by_range('time'));
|
||||
|
||||
-- PostgreSQL
|
||||
CREATE TABLE nodes (
|
||||
id UUID PRIMARY KEY,
|
||||
mesh_node_id TEXT UNIQUE NOT NULL,
|
||||
name TEXT,
|
||||
location GEOGRAPHY(POINT, 4326),
|
||||
hardware_revision TEXT,
|
||||
installed_at TIMESTAMPTZ,
|
||||
last_seen TIMESTAMPTZ,
|
||||
is_active BOOLEAN DEFAULT true
|
||||
);
|
||||
```
|
||||
|
||||
## 5. Web Dashboard Display
|
||||
|
||||
**Actor**: Web Dashboard (React)
|
||||
|
||||
1. User loads the dashboard
|
||||
2. Frontend queries `/api/v1/weather/latest` and `/api/v1/weather/history`
|
||||
3. API service fetches aggregated data from TimescaleDB
|
||||
4. Frontend renders:
|
||||
- Map markers with latest readings
|
||||
- Time-series charts (temperature, wind, etc.)
|
||||
- Node health indicators (battery, signal strength, last seen)
|
||||
|
||||
## 6. Command Flow (Web to Node)
|
||||
|
||||
For configuration updates or remote diagnostics:
|
||||
|
||||
1. Admin sends a command via web admin panel (e.g., "change reporting interval to 10 min")
|
||||
2. API validates admin permissions
|
||||
3. Command is queued in the message gateway for the specific node
|
||||
4. Infrastructure node picks up the command via MQTT
|
||||
5. Bridge daemon injects the command as a Meshtastic admin packet
|
||||
6. Enviro-node receives and applies the config update
|
||||
7. Acknowledgment (if requested) flows back through the same path
|
||||
|
||||
## Data Retention Policy
|
||||
|
||||
| Data Type | Storage Location | Retention |
|
||||
|-----------|-----------------|-----------|
|
||||
| Raw sensor readings | Enviro-Node flash | 30-90 days (ring buffer) |
|
||||
| Ingested readings | TimescaleDB | 2 years raw, then downsampled |
|
||||
| Downsampled aggregates | TimescaleDB | Indefinite |
|
||||
| Mesh messages | PostgreSQL | 90 days |
|
||||
| Audit logs | PostgreSQL | 1 year |
|
||||
188
docs/architecture/messaging-gateway.md
Normal file
188
docs/architecture/messaging-gateway.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Messaging Gateway Architecture
|
||||
|
||||
The Messaging Gateway is the bridge between the internet (web users) and the Meshtastic mesh. It is the primary monetization surface for the project.
|
||||
|
||||
## Business Rules
|
||||
|
||||
1. **The mesh is open**: Anyone with a Meshtastic device can join the Kosmo mesh and send/receive messages locally for free.
|
||||
2. **The gateway is gated**: Sending a message from the internet to the mesh requires an active subscription.
|
||||
3. **Authorization granularity**:
|
||||
- **Network-level**: Subscriber can send to any node reachable through the gateway.
|
||||
- **Node-level**: Subscriber can send only to specific whitelisted nodes (e.g., family members).
|
||||
- Future: **Group-level** access for organizations.
|
||||
|
||||
## Gateway Flow: Web → Mesh
|
||||
|
||||
```
|
||||
User (Web Browser)
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Web API │ <-- Validates JWT, checks subscription status
|
||||
│ /messages │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Billing │ <-- Confirms subscriber has active plan & quota remaining
|
||||
│ Service │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Message │ <-- Writes message to outbound queue (RabbitMQ / Redis)
|
||||
│ Gateway │ Topic: `mesh.outbound.{node_id}`
|
||||
└──────┬───────┘
|
||||
│ MQTT / TLS
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Infrastructure│ <-- Bridge daemon reads queue
|
||||
│ Node │
|
||||
└──────┬───────┘
|
||||
│ Serial / protobuf API
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Meshtastic │ <-- Broadcasts text message to target node ID
|
||||
│ Radio │
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
## Gateway Flow: Mesh → Web
|
||||
|
||||
Replies and inbound messages from the mesh to a subscriber:
|
||||
|
||||
```
|
||||
Meshtastic Radio (any node)
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Infrastructure│ <-- Receives mesh message
|
||||
│ Node │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Bridge │ <-- Publishes to `kosmo/mesh/inbound`
|
||||
│ Daemon │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Message │ <-- Matches sender node ID to subscriber inboxes
|
||||
│ Gateway │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Web API │ <-- Stores in user's inbox, sends push notification
|
||||
│ Inbox │
|
||||
└───────────────┘
|
||||
```
|
||||
|
||||
## Subscription Models
|
||||
|
||||
### Plan Tiers (Example)
|
||||
|
||||
| Tier | Price | Messages/Month | Scope | Features |
|
||||
|------|-------|----------------|-------|----------|
|
||||
| Free | $0 | 5 (inbound only) | Inbox | Receive replies, view weather |
|
||||
| Wanderer | $5/mo | 50 | Network | Send to any node |
|
||||
| Guardian | $12/mo | 500 | Node-level | Manage up to 5 linked nodes |
|
||||
| Sanctuary | $50/mo | Unlimited | Network + API | Bulk messaging, webhook access |
|
||||
|
||||
All paid plans are processed through the Church of Kosmo's self-hosted BTCPay Server at `pay.cqre.net`.
|
||||
|
||||
### Authorization Check
|
||||
|
||||
When a user attempts to send a message:
|
||||
|
||||
```python
|
||||
def can_send(user: User, target_node_id: str) -> bool:
|
||||
subscription = user.active_subscription()
|
||||
if not subscription or subscription.is_expired():
|
||||
return False
|
||||
|
||||
if subscription.plan == "network":
|
||||
return True
|
||||
|
||||
if subscription.plan == "node_level":
|
||||
return user.allowed_nodes.filter(mesh_node_id=target_node_id).exists()
|
||||
|
||||
return False
|
||||
```
|
||||
|
||||
## Message Queue Schema
|
||||
|
||||
### Outbound (Cloud → Mesh)
|
||||
```json
|
||||
{
|
||||
"message_id": "uuid-v4",
|
||||
"sender_user_id": "uuid-v4",
|
||||
"target_node_id": "!a1b2c3d4",
|
||||
"text": "Hello from the web!",
|
||||
"priority": "normal",
|
||||
"max_hops": 7,
|
||||
"want_ack": true,
|
||||
"created_at": "2026-04-12T09:20:00Z",
|
||||
"retry_count": 0
|
||||
}
|
||||
```
|
||||
|
||||
### Inbound (Mesh → Cloud)
|
||||
```json
|
||||
{
|
||||
"message_id": "uuid-v4",
|
||||
"source_node_id": "!a1b2c3d4",
|
||||
"gateway_node_id": "!gateway01",
|
||||
"text": "Reply from the woods",
|
||||
"hop_count": 3,
|
||||
"rssi": -90,
|
||||
"snr": 8.5,
|
||||
"received_at": "2026-04-12T09:25:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## Rate Limiting & Anti-Spam
|
||||
|
||||
- **Per-user**: Max 1 message per 10 seconds, burst of 5
|
||||
- **Per-subscription tier**: Enforced monthly quotas
|
||||
- **Per-target-node**: Max 10 web messages per hour (to prevent harassment)
|
||||
- **Content filtering**: Basic profanity/spam filter on the gateway
|
||||
- **Blocklist**: Users and nodes can block each other
|
||||
|
||||
## Delivery Tracking
|
||||
|
||||
The gateway tracks message state:
|
||||
|
||||
```
|
||||
PENDING -> QUEUED -> TRANSMITTED -> DELIVERED (ACK received)
|
||||
|
|
||||
+-> FAILED (max retries exceeded)
|
||||
```
|
||||
|
||||
Users see delivery status in the messaging UI:
|
||||
- Single checkmark: Queued
|
||||
- Double checkmark: Transmitted by gateway
|
||||
- Blue double checkmark: Delivered (ACK from target node)
|
||||
|
||||
## Billing Integration
|
||||
|
||||
The gateway relies on the **Billing Service** to enforce subscriptions. The billing service:
|
||||
- Creates invoices via BTCPay Server Greenfield API
|
||||
- Listens to BTCPay webhooks for payment confirmation
|
||||
- Manages subscription validity periods and quotas in PostgreSQL
|
||||
- Deactivates old subscriptions and resets quotas on successful payment
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Authentication**: JWT-based auth for web users, API keys for bridge daemons
|
||||
2. **Encryption**: Mesh messages are encrypted with the channel key. The bridge daemon does not decrypt content; it only forwards the encrypted payload.
|
||||
3. **Privacy**: The gateway logs message metadata (sender, recipient, timestamp, size) but does not log message content.
|
||||
4. **Node Impersonation**: Web messages are tagged with a special prefix or sender ID indicating they originated from the gateway, preventing spoofing of local mesh nodes.
|
||||
|
||||
## Fallback Behavior
|
||||
|
||||
If no infrastructure node is currently online:
|
||||
- Outbound messages remain queued for up to 24 hours
|
||||
- Users are notified that delivery is delayed
|
||||
- If the queue expires, the message is marked as failed and the user's quota is refunded
|
||||
123
docs/architecture/system-overview.md
Normal file
123
docs/architecture/system-overview.md
Normal file
@@ -0,0 +1,123 @@
|
||||
# System Architecture Overview
|
||||
|
||||
## High-Level Concept
|
||||
|
||||
KosmoConnect is a **three-tier system**:
|
||||
|
||||
1. **Edge Tier**: Solar-powered enviro-nodes running Meshtastic + custom sensor firmware
|
||||
2. **Bridge Tier**: Infrastructure nodes with internet backhaul (WiFi/Ethernet/Cellular)
|
||||
3. **Cloud Tier**: Central backend services and web frontends
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ CLOUD TIER │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ │
|
||||
│ │ Web API │ │ Ingestion │ │ Message │ │ Billing │ │
|
||||
│ │ (Fastify/ │ │ Service │ │ Gateway │ │ & Auth │ │
|
||||
│ │ Django) │ │ (TimescaleDB│ │ (RabbitMQ/ │ │ (Stripe) │ │
|
||||
│ │ │ │ + Redis) │ │ MQTT) │ │ │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬──────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ ┌──────▼─────────────────▼─────────────────▼─────────────────▼──────┐ │
|
||||
│ │ PostgreSQL │ │
|
||||
│ │ (Users, Nodes, Subscriptions) │ │
|
||||
│ └───────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
▲
|
||||
│ HTTPS / MQTT over TLS
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ BRIDGE TIER │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Infrastructure Node │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ │
|
||||
│ │ │ Meshtastic │ │ Bridge │ │ Backhaul (WiFi/Eth/ │ │ │
|
||||
│ │ │ Radio │◄─┤ Daemon │◄─┤ Cellular) │ │ │
|
||||
│ │ │ (SX1262) │ │ (Python) │ │ │ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ (Mains Powered) │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
▲
|
||||
│ LoRa / Mesh
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ EDGE TIER │
|
||||
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ Enviro-Node │ │
|
||||
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │
|
||||
│ │ │ BME280 │ │ Wind │ │ Air │ │ Meshtastic │ │ │
|
||||
│ │ │ (T/H/P) │ │ Sensor │ │ Quality │ │ Firmware │ │ │
|
||||
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ + Sensor Module │ │ │
|
||||
│ │ └─────────────┴─────────────┘ │ + Store/Forward │ │ │
|
||||
│ │ │ │ + Power Manager │ │ │
|
||||
│ │ ┌──────▼──────┐ └─────────┬─────────┘ │ │
|
||||
│ │ │ ESP32/ │ │ │ │
|
||||
│ │ │ nRF52840 │◄────────────────────────┘ │ │
|
||||
│ │ └──────┬──────┘ │ │
|
||||
│ │ │ │ │
|
||||
│ │ ┌──────▼──────┐ │ │
|
||||
│ │ │ Solar + │ │ │
|
||||
│ │ │ Battery │ │ │
|
||||
│ │ └─────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────────────────┘ │
|
||||
│ (Solar Powered) │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Core Principles
|
||||
|
||||
### 1. Open Mesh, Gated Gateway
|
||||
The Meshtastic mesh itself is open. Anyone with a compatible device can join, extend range, and benefit from the enviro-node relay infrastructure. However, access to the **web-to-mesh gateway** (sending messages from the internet to the mesh) is restricted to paying subscribers.
|
||||
|
||||
### 2. Store-and-Forward Data Offload
|
||||
Enviro-nodes collect data continuously but may not always have a direct route to an infrastructure node. Data is buffered in local flash/SD and transmitted when a route becomes available. The Meshtastic store-and-forward module may be leveraged or extended.
|
||||
|
||||
### 3. Separation of Concerns
|
||||
- **Meshtastic handles**: Mesh routing, encryption, device-to-device messaging, channel management
|
||||
- **Custom firmware handles**: Sensor reading, power management, data buffering, packet formatting
|
||||
- **Backend handles**: User auth, subscription billing, data persistence, web APIs, message queuing
|
||||
- **Bridge handles**: Protocol translation between Meshtastic protobufs and cloud MQTT/HTTPS
|
||||
|
||||
## Component Boundaries
|
||||
|
||||
### Enviro-Node (Edge)
|
||||
**Hardware**: Custom PCB based on ESP32-S3-WROOM-1 or nRF52840 + SX1262, sensor headers, solar charge controller, battery management.
|
||||
**Firmware**: Either a Meshtastic firmware fork with a custom sensor module, or a companion MCU architecture where Meshtastic runs on one chip and a sensor controller runs on another.
|
||||
|
||||
### Infrastructure Node (Bridge)
|
||||
**Hardware**: Meshtastic device (LILYGO T-Beam, RAK4631, or custom) with reliable internet backhaul.
|
||||
**Software**: A bridge daemon running alongside the Meshtastic firmware (via serial/API) that forwards environmental data to the cloud and injects outbound mesh messages from the cloud queue.
|
||||
|
||||
### Central Backend (Cloud)
|
||||
- **Ingestion Service**: Consumes MQTT from infrastructure nodes, validates, writes to TimescaleDB
|
||||
- **API Service**: REST/GraphQL API for weather data, node registry, health status
|
||||
- **Message Gateway**: Manages the queue of web-to-mesh messages, handles delivery confirmations, rate limiting
|
||||
- **Billing & Auth**: Stripe integration for subscriptions, OAuth2/JWT for user auth, node-level permission checks
|
||||
|
||||
### Web Frontend (Cloud)
|
||||
- **Dashboard**: Map-based weather visualization, node health, historical charts
|
||||
- **Messaging Client**: Compose messages to mesh nodes by node ID or alias, view replies
|
||||
- **Admin Panel**: Node onboarding, subscriber management, network diagnostics
|
||||
|
||||
## Technology Stack Recommendations
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|------------|
|
||||
| Enviro-Node MCU | ESP32-S3 (for power/performance) or nRF52840 (for efficiency) |
|
||||
| Radio | Semtech SX1262 (Meshtastic standard) |
|
||||
| Sensors | BME680 (T/H/P/Gas), SPS30 (PM), Davis anemometer (wind) |
|
||||
| Bridge Daemon | Python with `meshtastic` CLI library + `paho-mqtt` |
|
||||
| Backend Runtime | Python (FastAPI) or Node.js (NestJS) |
|
||||
| Database (Time-series) | TimescaleDB or InfluxDB |
|
||||
| Database (Relational) | PostgreSQL |
|
||||
| Message Queue | RabbitMQ or Redis Streams |
|
||||
| Frontend | React / Vue + MapLibre GL |
|
||||
| Infra | Docker, Terraform, Ansible |
|
||||
|
||||
## Scalability Considerations
|
||||
|
||||
- A single infrastructure node can serve a large mesh area, but dense networks benefit from multiple infrastructure nodes for redundancy.
|
||||
- Environmental data is small and infrequent (e.g., one packet every 5-15 minutes), so bandwidth is not a concern.
|
||||
- Web-to-mesh messaging is low bandwidth but requires delivery tracking and rate limiting to prevent spam.
|
||||
- The system should gracefully degrade if the cloud is unreachable; the mesh continues to function locally.
|
||||
151
docs/requirements/prd.md
Normal file
151
docs/requirements/prd.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Product Requirements Document
|
||||
|
||||
## Project Name
|
||||
KosmoConnect
|
||||
|
||||
## Steward
|
||||
Church of Kosmo Technology Division
|
||||
|
||||
## Mission Statement
|
||||
Build a resilient, solar-powered environmental monitoring network that doubles as an emergency communication backbone for the Church of Kosmo community and beyond. KosmoConnect is a technology project of the Church of Kosmo, developed in the open and operated as community infrastructure.
|
||||
|
||||
---
|
||||
|
||||
## Objective 1: Enviro-Node Network
|
||||
|
||||
### 1.1 Enviro-Node Hardware
|
||||
|
||||
**REQ-HW-001**: The enviro-node must be capable of year-round autonomous operation on solar power in temperate climates.
|
||||
|
||||
**REQ-HW-002**: The enviro-node must measure at minimum:
|
||||
- Air temperature
|
||||
- Relative humidity
|
||||
- Barometric pressure
|
||||
- Wind speed and direction
|
||||
|
||||
**REQ-HW-003**: The enviro-node should optionally support:
|
||||
- Particulate matter (PM2.5, PM10)
|
||||
- Volatile organic compounds / gas resistance
|
||||
- UV index
|
||||
- Rainfall
|
||||
|
||||
**REQ-HW-004**: The enviro-node enclosure must be IP65 rated or better.
|
||||
|
||||
**REQ-HW-005**: The enviro-node must operate in temperatures from -20°C to +50°C.
|
||||
|
||||
**REQ-HW-006**: The enviro-node must use a Meshtastic-compatible LoRa radio (SX1262 recommended).
|
||||
|
||||
**REQ-HW-007**: The enviro-node must buffer at least 30 days of 15-minute readings locally.
|
||||
|
||||
### 1.2 Enviro-Node Firmware
|
||||
|
||||
**REQ-FW-001**: The firmware must read sensors at a configurable interval (default: 60 seconds).
|
||||
|
||||
**REQ-FW-002**: The firmware must store readings in a resilient local ring buffer.
|
||||
|
||||
**REQ-FW-003**: The firmware must transmit accumulated readings over Meshtastic at a configurable interval (default: 15 minutes during daylight, 60 minutes at night).
|
||||
|
||||
**REQ-FW-004**: The firmware must implement power management to maximize battery life, including deep sleep between intervals.
|
||||
|
||||
**REQ-FW-005**: The firmware must act as a standard Meshtastic relay, forwarding messages for other mesh clients.
|
||||
|
||||
**REQ-FW-006**: The firmware must support remote configuration updates over the mesh (admin channel).
|
||||
|
||||
**REQ-FW-007**: The firmware must report its own health status (battery voltage, solar input voltage, free storage, temperature).
|
||||
|
||||
### 1.3 Infrastructure Nodes
|
||||
|
||||
**REQ-INF-001**: Infrastructure nodes must bridge the Meshtastic mesh to the internet.
|
||||
|
||||
**REQ-INF-002**: Infrastructure nodes must support at least one backhaul method: WiFi, Ethernet, or LTE.
|
||||
|
||||
**REQ-INF-003**: Infrastructure nodes must be mains-powered or have a large enough battery/solar setup for 99.9% uptime.
|
||||
|
||||
**REQ-INF-004**: Infrastructure nodes must forward environmental data packets to the cloud backend without decrypting content.
|
||||
|
||||
**REQ-INF-005**: Infrastructure nodes must inject outbound web-to-mesh messages into the mesh.
|
||||
|
||||
### 1.4 Central Weather Service
|
||||
|
||||
**REQ-WS-001**: The service must ingest environmental data from all registered nodes.
|
||||
|
||||
**REQ-WS-002**: The service must provide a public map showing current conditions at each node.
|
||||
|
||||
**REQ-WS-003**: The service must provide historical charts for each sensor type at each node.
|
||||
|
||||
**REQ-WS-004**: The service must display node health (online/offline, battery level, last seen).
|
||||
|
||||
**REQ-WS-005**: The service must expose a public API for reading weather data (rate-limited).
|
||||
|
||||
---
|
||||
|
||||
## Objective 2: Web-to-Mesh Gateway
|
||||
|
||||
### 2.1 User Subscription
|
||||
|
||||
**REQ-SUB-001**: Users must be able to create an account and subscribe to a paid plan via BTCPay Server (pay.cqre.net).
|
||||
|
||||
**REQ-SUB-002**: The system must support at least two authorization scopes:
|
||||
- **Network scope**: Send messages to any node on the mesh.
|
||||
- **Node scope**: Send messages only to specific whitelisted nodes.
|
||||
|
||||
**REQ-SUB-003**: Users must be able to link Meshtastic node IDs to their account for receiving replies.
|
||||
|
||||
**REQ-SUB-004**: The system must enforce monthly message quotas based on the subscription tier.
|
||||
|
||||
**REQ-SUB-005**: Users must receive email notifications for subscription events (payment received, renewal, expiration).
|
||||
|
||||
### 2.2 Web Messaging
|
||||
|
||||
**REQ-MSG-001**: Subscribers must be able to compose and send text messages to mesh nodes from a web browser.
|
||||
|
||||
**REQ-MSG-002**: The web UI must show delivery status (queued, transmitted, delivered, failed).
|
||||
|
||||
**REQ-MSG-003**: Subscribers must be able to receive replies from mesh nodes in their web inbox.
|
||||
|
||||
**REQ-MSG-004**: The system must support push notifications (browser or email) for incoming replies.
|
||||
|
||||
**REQ-MSG-005**: Messages must be rate-limited to prevent spam and network abuse.
|
||||
|
||||
**REQ-MSG-006**: Messages from the gateway must be clearly identified as originating from the internet to mesh users.
|
||||
|
||||
### 2.3 Admin & Operations
|
||||
|
||||
**REQ-ADM-001**: Admins must be able to register new enviro-nodes and infrastructure nodes.
|
||||
|
||||
**REQ-ADM-002**: Admins must be able to view system-wide metrics (nodes online, messages sent, data ingested).
|
||||
|
||||
**REQ-ADM-003**: Admins must be able to broadcast emergency alerts to all mesh nodes via the gateway.
|
||||
|
||||
**REQ-ADM-004**: The system must generate monthly reports on network health and subscription revenue.
|
||||
|
||||
---
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
**REQ-NF-001**: The mesh must remain functional for local communication even if the cloud backend is unreachable.
|
||||
|
||||
**REQ-NF-002**: All cloud communications must use TLS 1.3 or better.
|
||||
|
||||
**REQ-NF-003**: The backend must horizontally scale to support at least 1,000 active nodes and 10,000 subscribers.
|
||||
|
||||
**REQ-NF-004**: The enviro-node hardware designs and firmware must be open-source.
|
||||
|
||||
**REQ-NF-005**: The web-to-mesh gateway software must be open-source, but the hosted instance may be operated as a paid service.
|
||||
|
||||
**REQ-NF-006**: The system must comply with GDPR / CCPA for user data.
|
||||
|
||||
**REQ-NF-007**: The system must comply with local RF regulations (FCC, CE, etc.) for the intended deployment regions.
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
| Metric | Target |
|
||||
|--------|--------|
|
||||
| Enviro-node uptime (sunny season) | >95% |
|
||||
| Enviro-node uptime (winter) | >80% |
|
||||
| Data delivery success rate | >98% |
|
||||
| Web-to-mesh delivery time | <5 minutes (when infrastructure node is in range) |
|
||||
| Subscriber churn rate | <5% monthly |
|
||||
| Kit assembly time | <4 hours for a moderately technical user |
|
||||
150
docs/roadmap.md
Normal file
150
docs/roadmap.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# KosmoConnect Project Roadmap
|
||||
|
||||
*A technology project of the Church of Kosmo*
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Foundation & Alignment
|
||||
**Duration:** 2–3 months
|
||||
**Goal:** Validate the core concept, secure resources, and establish the legal/technical bedrock.
|
||||
|
||||
### Milestones
|
||||
| # | Deliverable | Success Criteria |
|
||||
|---|-------------|------------------|
|
||||
| 0.1 | **Project Charter Ratified** | Church of Kosmo leadership approves mission, budget, and open-source licensing strategy. |
|
||||
| 0.2 | **License Stack Finalized** | Decide whether to adopt KΛ 1.1-Draft or remain on KΛ 1.0 + AGPL-3.0 + CERN-OHL-S-2.0. |
|
||||
| 0.3 | **Reference Hardware Bench** | Procure 2× ESP32-S3 dev boards, 2× SX1262 modules, 2× LILYGO T-Beams, reference sensors. |
|
||||
| 0.4 | **Reference Sensor Validation** | Confirm BME680 and SPS30 accuracy against a calibrated weather station over 2 weeks. |
|
||||
| 0.5 | **Power Budget Proven** | Build a spreadsheet-validated, lab-measured power model proving 80+ days battery autonomy. |
|
||||
| 0.6 | **Repo & CI Operational** | All placeholder CI jobs replaced with real builds; contribution guidelines published. |
|
||||
|
||||
### Key Decisions
|
||||
- MCU: ESP32-S3 (confirmed) vs. nRF52840 (deferred to v2)
|
||||
- Backhaul: WiFi-first for infrastructure nodes; LTE as v1.5 upgrade
|
||||
- Cloud provider: Hetzner / DigitalOcean / AWS (to be selected)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Proof of Concept ("Genesis Node")
|
||||
**Duration:** 3–4 months
|
||||
**Goal:** One end-to-end enviro-node → bridge → cloud → dashboard chain working in a controlled environment.
|
||||
|
||||
### Milestones
|
||||
| # | Deliverable | Success Criteria |
|
||||
|---|-------------|------------------|
|
||||
| 1.1 | **Meshtastic Fork with Sensor Module** | Enviro-node firmware reads BME680 + SPS30 and injects a custom data packet into the mesh. |
|
||||
| 1.2 | **Local Data Buffer** | Ring buffer in SPI flash stores 7 days of readings and survives reboots. |
|
||||
| 1.3 | **Bridge Daemon v0.1** | Python daemon on Raspberry Pi forwards mesh packets to a local MQTT broker. |
|
||||
| 1.4 | **Ingestion Service v0.1** | FastAPI service consumes MQTT, writes to TimescaleDB, exposes `/latest` and `/history`. |
|
||||
| 1.5 | **Dashboard v0.1** | React app displays a single node on a map with live temperature, humidity, and pressure. |
|
||||
| 1.6 | **Genesis Node Deployed** | One prototype node + one bridge node installed on Church of Kosmo property, running 24/7 for 30 days. |
|
||||
|
||||
### Phase 1 Metrics
|
||||
- Data delivery success rate: >90%
|
||||
- Dashboard uptime: >95%
|
||||
- Mesh packet success (single hop): >95%
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Pilot Network ("Kosmo Constellation")
|
||||
**Duration:** 4–6 months
|
||||
**Goal:** Deploy 3–5 enviro-nodes in one geographic region with one or more infrastructure nodes. Onboard the first paying subscribers to the web-to-mesh gateway.
|
||||
|
||||
### Milestones
|
||||
| # | Deliverable | Success Criteria |
|
||||
|---|-------------|------------------|
|
||||
| 2.1 | **Enviro-Node PCB v1.0** | First fabricated PCB integrating MCU, radio, sensor headers, and power management. |
|
||||
| 2.2 | **Multi-Hop Data Offload** | Nodes 2+ hops from infrastructure successfully transmit buffered data via intermediate relays. |
|
||||
| 2.3 | **Gateway Service v0.1** | Subscribers can send web messages to any node; delivery status tracked (queued → transmitted). |
|
||||
| 2.4 | **Billing Integration** | Stripe subscription flow live; at least two plan tiers functional (Wanderer, Guardian). |
|
||||
| 2.5 | **Messaging Client v0.1** | Web inbox supports composing, receiving replies, and viewing delivery status. |
|
||||
| 2.6 | **Admin Panel v0.1** | Node registration, subscriber lookup, and emergency broadcast functional. |
|
||||
| 2.7 | **Pilot Deployment** | 3–5 nodes cover a local watershed or community area; 10–20 beta subscribers active. |
|
||||
|
||||
### Phase 2 Metrics
|
||||
- Enviro-node uptime (summer): >95%
|
||||
- Web-to-mesh delivery time: <10 minutes
|
||||
- Subscriber churn: <10% monthly (beta expectation)
|
||||
- Kit assembly time (internal test): <4 hours
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Production Network & Kits ("The Open Mesh")
|
||||
**Duration:** 6–9 months
|
||||
**Goal:** Scale to 20–50 nodes, launch the enviro-node kit for sale, and stabilize all services for production load.
|
||||
|
||||
### Milestones
|
||||
| # | Deliverable | Success Criteria |
|
||||
|---|-------------|------------------|
|
||||
| 3.1 | **Enviro-Node Kit v1.0** | Complete BOM, assembly manual, packaging, and first production run of 50 kits. |
|
||||
| 3.2 | **Certification (FCC / CE / ISED)** | Modular radio approval + EMC testing complete for intended markets. |
|
||||
| 3.3 | **Gateway Delivery ACKs** | Full delivery tracking including node-level ACKs (queued → transmitted → delivered). |
|
||||
| 3.4 | **Auto-Provisioning** | New kits can self-onboard to the network via QR code + smartphone app without manual admin intervention. |
|
||||
| 3.5 | **Horizontal Scaling** | Backend services run on 3+ hosts; database read replicas configured. |
|
||||
| 3.6 | **Community Infrastructure Nodes** | Documented process for volunteers to host bridge nodes; at least 3 community-hosted bridges online. |
|
||||
| 3.7 | **Production Launch** | 20–50 active enviro-nodes; 100+ paying subscribers; public weather dashboard live. |
|
||||
|
||||
### Phase 3 Metrics
|
||||
- Enviro-node uptime (annual avg): >90%
|
||||
- Data delivery success rate: >98%
|
||||
- Web-to-mesh delivery time: <5 minutes
|
||||
- Subscriber churn: <5% monthly
|
||||
- Gross margin on kits: >30% (to fund network expansion)
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Ecosystem & Resilience ("The Continuum")
|
||||
**Duration:** 12+ months (ongoing)
|
||||
**Goal:** KosmoConnect becomes a platform. Other communities fork the stack, build compatible nodes, and participate in the wider mesh ecosystem.
|
||||
|
||||
### Milestones
|
||||
| # | Deliverable | Success Criteria |
|
||||
|---|-------------|------------------|
|
||||
| 4.1 | **Public API & Webhooks** | Developers can query weather data and receive mesh events via webhooks (Sanctuary tier). |
|
||||
| 4.2 | **Mesh Federation** | Interoperability experiments with other Meshtastic community networks; shared routing where appropriate. |
|
||||
| 4.3 | **Enviro-Node v2.0** | nRF52840-based redesign with 50% lower sleep current and 50% smaller enclosure. |
|
||||
| 4.4 | **Mobile App** | Native iOS/Android app for messaging and node management (extends or replaces web client). |
|
||||
| 4.5 | **Disaster Response Integration** | Partnership with local emergency management to use the mesh for alert broadcasting during grid outages. |
|
||||
| 4.6 | **Open Continuum Archive** | All historical designs, firmware, and docs mirrored to IPFS or equivalent durable storage. |
|
||||
|
||||
### Phase 4 Metrics
|
||||
- Forks / derivative projects: >5 active
|
||||
- Nodes on the mesh (including non-Church-of-Kosmo builds): >200
|
||||
- Subscribers: >1,000
|
||||
- Uptime during a documented emergency event: Mesh remains locally functional for >72 hours without internet
|
||||
|
||||
---
|
||||
|
||||
## Continuous Workstreams
|
||||
|
||||
These activities run in parallel across all phases:
|
||||
|
||||
| Workstream | Activities |
|
||||
|------------|------------|
|
||||
| **Community** | Discord/forum moderation, kit build-along events, contributor onboarding |
|
||||
| **Documentation** | API docs, assembly guides, troubleshooting wikis, video tutorials |
|
||||
| **Legal & Compliance** | Privacy policy updates, RF compliance in new regions, trademark guidance |
|
||||
| **Finance** | Grant applications, kit pricing reviews, subscriber retention analysis |
|
||||
| **Security** | Penetration testing of gateway, firmware signing, supply-chain verification |
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Risk Mitigation
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|------------|
|
||||
| Solar power insufficient in winter | Oversize battery + panel in v1; aggressive sleep optimization in v2 |
|
||||
| Meshtastic protocol changes break custom module | Pin to stable releases; maintain a small upstream contribution relationship |
|
||||
| Regulatory certification costs exceed budget | Use pre-certified radio modules; start with one market (e.g., USA) |
|
||||
| Subscriber growth slower than expected | Double down on kit sales and community node sponsorships |
|
||||
| Cloud infrastructure fails during emergency | Multiple community-hosted bridges; mesh functions locally regardless |
|
||||
|
||||
---
|
||||
|
||||
## How to Read This Roadmap
|
||||
|
||||
- **Phases are sequential** but overlapping. For example, kit design (Phase 3) begins before Phase 2 ends.
|
||||
- **Milestones are negotiable.** If a technical discovery in Phase 1 invalidates the PCB approach, Phase 2 slips to accommodate the pivot.
|
||||
- **Metrics are targets, not guarantees.** They exist to focus effort and signal when to ask for help.
|
||||
|
||||
> *"Through openness, we preserve. Through preservation, we evolve. Through evolution, we return."*
|
||||
Reference in New Issue
Block a user