SkillAgentSearch skills...

VanneControl

IoT piston control system with Kotlin backend, MQTT broker, and cross-platform mobile app support (KMM). Control up to 8 pistons per device remotely via REST API and real-time WebSocket updates.

Install / Use

/learn @YassineKaibi/VanneControl
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

IoT Piston Control System

A production-ready self-hosted IoT platform for remotely controlling piston actuators via MQTT. Features comprehensive scheduling, admin management, and real-time monitoring capabilities.

Features

Core Functionality

  • Secure Authentication - JWT-based authentication with refresh tokens and BCrypt password hashing
  • REST API - Complete RESTful API for device management, user profiles, and system control
  • MQTT Communication - Real-time bidirectional device communication via Mosquitto broker with TLS support
  • WebSocket Support - Live status updates with JWT-authenticated WebSocket connections
  • Automated Scheduling - Cron-based scheduling system using Quartz for automated piston control

Administration & Management

  • Role-Based Access Control - User and admin roles with granular permissions
  • Web Admin Dashboard - Full-featured HTML admin panel with FreeMarker templates
  • Audit Logging - Comprehensive activity tracking for compliance and security
  • User Management - Admin tools for user creation, role assignment, and deletion
  • System Statistics - Real-time dashboard with user counts, device metrics, and activity logs

Infrastructure

  • Docker Compose - Complete containerized deployment with health checks
  • PostgreSQL Database - Robust data persistence with JSONB support and optimized indexes
  • Redis Caching - High-performance caching layer for improved response times
  • Nginx Reverse Proxy - SSL/TLS termination and load balancing
  • Mobile App Support - Native Android application (see separate README)

Architecture

┌─────────────────┐
│  Mobile/Web App │
└────────┬────────┘
         │ HTTPS/WSS
    ┌────▼─────┐
    │  Nginx   │ (Reverse Proxy)
    └────┬─────┘
         │
    ┌────▼─────┐
    │  Ktor    │ (Backend API)
    │ Backend  │
    └─┬──┬──┬──┘
      │  │  │
   ┌──▼──▼──▼────┐
   │ PostgreSQL  │
   │   Redis     │
   └─────────────┘
         │
    ┌────▼──────┐
    │ Mosquitto │ (MQTT Broker)
    └────┬──────┘
         │
    ┌────▼──────┐
    │   ESP32   │ (IoT Devices)
    │  Devices  │
    └───────────┘

System Components

Backend Server (backend/)

  • Ktor framework (Kotlin)
  • REST API + WebSocket endpoints
  • JWT authentication with role-based access
  • MQTT client integration
  • Quartz scheduler for automated tasks
  • FreeMarker templating for admin web UI

Database Layer (PostgreSQL)

  • User accounts & authentication
  • Device registry with ownership
  • Piston states & history (8 pistons per device)
  • Telemetry data with JSONB payloads
  • Schedules with cron expressions
  • Audit logs for admin actions

Message Broker (Mosquitto MQTT)

  • Device command/control messages
  • Real-time status updates
  • TLS encryption support
  • Binary protocol for ESP32 devices

Caching Layer (Redis)

  • Session storage
  • API response caching
  • Real-time data buffering

Reverse Proxy (Nginx)

  • SSL/TLS termination
  • Load balancing
  • Static content serving
  • WebSocket proxying

Quick Start

Prerequisites

  • Docker & Docker Compose
  • OpenSSL (for certificate generation)
  • Python 3.8+ (for device client/simulator)

Installation

  1. Clone the repository
git clone https://github.com/YassineKaibi/VanneControl.git
cd VanneControl
  1. Generate certificates
chmod +x generate-certs.sh
./generate-certs.sh
  1. Configure environment
cp .env.example .env
# Edit .env with your secure passwords
nano .env

Required environment variables:

POSTGRES_PASSWORD=your_secure_postgres_password
REDIS_PASSWORD=your_secure_redis_password
JWT_SECRET=your_jwt_secret_key
JWT_ISSUER=piston-control
JWT_AUDIENCE=piston-app
SESSION_ENCRYPT_KEY=your_32_char_session_encrypt_key
SESSION_SIGN_KEY=your_32_char_session_sign_key
  1. Start services
docker compose build
docker compose up -d
  1. Verify deployment
curl http://localhost:8080/health

Expected response:

{
  "status": "healthy",
  "timestamp": 1234567890
}

API Documentation

Authentication

Register User

POST /auth/register
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "SecurePass123!"
}

Response (201 Created):

{
  "user": {
    "id": "uuid",
    "email": "user@example.com",
    "role": "user"
  },
  "token": "eyJhbGc..."
}

Login

POST /auth/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "SecurePass123!"
}

Response (200 OK):

{
  "token": "eyJhbGc...",
  "refreshToken": "refresh_token_here"
}

Device Management

List Devices

GET /devices
Authorization: Bearer <token>

Get Device Details

GET /devices/{deviceId}
Authorization: Bearer <token>

Control Piston

POST /devices/{deviceId}/pistons/{pistonNumber}
Authorization: Bearer <token>
Content-Type: application/json

{
  "action": "activate"
}

Get Device Statistics

GET /devices/{deviceId}/stats
Authorization: Bearer <token>

Schedule Management

Create Schedule

POST /schedules
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "Morning activation",
  "deviceId": "device-uuid",
  "pistonNumber": 1,
  "action": "ACTIVATE",
  "cronExpression": "0 0 8 * * ?",
  "enabled": true
}

Cron expression format: second minute hour day month day-of-week

List User Schedules

GET /schedules
Authorization: Bearer <token>

Get Schedule by ID

GET /schedules/{scheduleId}
Authorization: Bearer <token>

Update Schedule

PUT /schedules/{scheduleId}
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "Updated name",
  "cronExpression": "0 0 20 * * ?",
  "enabled": false
}

Delete Schedule

DELETE /schedules/{scheduleId}
Authorization: Bearer <token>

Get Schedules by Device

GET /schedules/device/{deviceId}
Authorization: Bearer <token>

User Profile

Get Profile

GET /user/profile
Authorization: Bearer <token>

Update Profile

PUT /user/profile
Authorization: Bearer <token>
Content-Type: application/json

{
  "firstName": "John",
  "lastName": "Doe",
  "phoneNumber": "+1234567890",
  "location": "New York"
}

Admin Endpoints

All admin endpoints require admin role.

List All Users

GET /admin/users?limit=50&offset=0
Authorization: Bearer <admin-token>

Get User by ID

GET /admin/users/{userId}
Authorization: Bearer <admin-token>

Update User Role

PATCH /admin/users/{userId}/role
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "role": "admin"
}

Delete User

DELETE /admin/users/{userId}
Authorization: Bearer <admin-token>

Get System Statistics

GET /admin/stats
Authorization: Bearer <admin-token>

Response:

{
  "totalUsers": 150,
  "totalAdmins": 5,
  "totalDevices": 75,
  "totalSchedules": 200,
  "recentAuditLogs": [...]
}

Get Audit Logs

GET /admin/audit-logs?limit=100&offset=0
Authorization: Bearer <admin-token>

Admin Web Dashboard

Access the web-based admin panel at:

http://localhost:8080/admin/login

Features:

  • User management interface
  • System statistics dashboard
  • Audit log viewer
  • Role assignment tools
  • Session-based authentication

WebSocket Connection

Connect to WebSocket

const ws = new WebSocket('ws://localhost:8080/ws?token=<jwt-token>');

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Device update:', data);
};

WebSocket message format:

{
  "deviceId": "uuid",
  "pistonNumber": 1,
  "state": "active",
  "timestamp": 1234567890
}

Security

Production Security Checklist

Environment Variables

  • Change all default passwords in .env
  • Use strong random values for JWT secrets
  • Generate unique session encryption keys

TLS/SSL

  • Enable HTTPS in Nginx configuration
  • Use valid SSL certificates (Let's Encrypt recommended)
  • Configure MQTT broker for TLS on port 8883

Database

  • Use strong PostgreSQL password
  • Restrict database network access
  • Enable SSL connections in production

Authentication

  • JWT tokens expire after configurable period
  • Refresh tokens for long-lived sessions
  • BCrypt password hashing with salt rounds

Admin Access

  • Create admin users manually via database
  • Use separate admin JWT authentication
  • All admin actions logged to audit_logs table

Network Security

  • Use Docker network isolation
  • Configure firewall rules
  • Limit exposed ports

Creating Admin User

  1. Register a normal user via /auth/register
  2. Promote to admin via database:
UPDATE users SET role = 'admin' WHERE email = 'admin@example.com';

Database Schema

Tables

users

  • id (UUID, PK)
  • email (TEXT, UNIQUE)
  • password_hash (TEXT)
  • role (TEXT: 'user' | 'admin')
  • first_name, last_name, phone_number, date_of_birth, location
  • avatar_url (TEXT)
  • preferences (JSONB)
  • created_at, updated_at (TIMESTAMP)

devices

  • id (UUID, PK)
  • name (TEXT)
  • owner_id (UUID, FK -> users)
  • mqtt_client_id (TEXT, UNIQUE)
  • status (TEXT: 'online' | 'offline')
  • created_at, updated_at (TIMESTAMP)

pistons

  • id (UUID, PK)
  • device_id (UUID, FK -> devices)
  • piston_number (INT: 1-8)
  • state (TEXT: 'active' | 'inactive')
  • last_triggered (TIMESTAMP)

telemetry

  • id (BIGSERIAL, PK)
  • device_id (UUID, FK -> devices)
  • piston_id (UUID, FK -> pistons)
  • event_type (TEXT: 'activated' | 'deactivated' | 'status_update')
  • payload (JSONB)
  • created_at (TIMESTAMP)

schedules

  • id (UUID, PK)
  • name (TEXT)
  • device_id (UUID, FK -> devices)
  • piston_number (INT: 1-8)
  • action (TEXT: 'ACTIVATE' | 'DEACTIVATE')
  • cron_expression (TEXT)
  • `en

Related Skills

View on GitHub
GitHub Stars5
CategoryCustomer
Updated1mo ago
Forks0

Languages

Kotlin

Security Score

85/100

Audited on Feb 2, 2026

No findings