Full-stack backend platform for managing connected smart lamps with secure APIs, MQTT-based device communication, telemetry ingestion, and OTA firmware delivery.
Overview Live frontend . Screenshots below
IoTServerApp is a Spring Boot backend for operating IoT-enabled smart lamps at scale. It combines secure user management, fleet-level device orchestration, real-time MQTT messaging, telemetry processing, and firmware lifecycle management in one platform.
This project demonstrates practical backend engineering across:
- secure authentication and authorization,
- event-driven device communication,
- binary device protocols with Protocol Buffers,
- cloud-backed OTA delivery,
- operational monitoring and scheduling,
- containerized local deployment.
For an IoT product, the backend is where reliability, security, and maintainability either hold together or fail. IoTServerApp addresses that by providing:
- Centralized device control for individual lamps and fleets
- Low-latency command delivery over MQTT
- Operational visibility through telemetry and alert tracking
- Secure access with JWT-based authentication
- Firmware rollout support through OTA update workflows
- Production-oriented deployment with Docker, PostgreSQL, and RabbitMQ
- Secure JWT authentication with access/refresh token flow
- User management and profile update endpoints
- Lamp registration and lifecycle management
- Fleet management for grouping and bulk operations
- Real-time lamp control via MQTT command topics
- Telemetry ingestion from device metrics topics
- Statistics endpoints for lamp, fleet, and user-level insights
- OTA firmware update workflow with S3-backed artifact delivery
- RabbitMQ-backed MQTT broker integration
- Swagger / OpenAPI documentation support
- RGB and white-channel control
- Photo white and photo color modes
- Preset-based lighting workflows
- Disco effects:
- Color cycle
- Strobe
- Pulse
- Circadian/daylight scheduling
- Adaptive brightness configuration
- Scheduled smart feature execution
- Protocol Buffers for compact device payloads
- Layered Spring architecture with controllers, services, repositories, DTOs, and entities
- Containerized local stack with PostgreSQL + RabbitMQ + backend
- Test support with JUnit 5, Spring test tooling, H2, and Testcontainers
| Category | Technologies |
|---|---|
| Language | Java 17 |
| Framework | Spring Boot 3.3.5 |
| Security | Spring Security, JWT, BCrypt |
| Data | Spring Data JPA, PostgreSQL, H2 |
| Messaging | RabbitMQ, MQTT, Spring Integration, Spring AMQP, Eclipse Paho |
| Serialization | Protocol Buffers |
| Cloud Storage | AWS S3 SDK |
| API Docs | SpringDoc OpenAPI / Swagger UI |
| Build Tool | Maven |
| Testing | JUnit 5, Testcontainers, Spring Security Test, Spring Rabbit Test |
| Deployment | Docker, Docker Compose |
The application follows a layered architecture pattern:
┌─────────────────────────────────────────────────────────────┐
│ Client Applications │
│ (Web UI, Mobile Apps, IoT Devices) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ REST API Layer │
│ (Controllers: Auth, User, Lamp, Fleet, OTA, Stats) │
└────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Service Layer │
│ (Business Logic: LampService, FleetService, OtaService) │
└────────────────────────┬────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Repository │ │ MQTT │ │ S3 │
│ Layer │ │ Service │ │ Storage │
└──────┬──────┘ └──────┬──────┘ └─────────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ PostgreSQL │ │ RabbitMQ │
│ Database │ │ MQTT Broker │
└─────────────┘ └─────────────┘
Client Apps / Admin UI
|
v
REST API (Spring Boot Controllers)
|
v
Service Layer
| | |
| | +--> OTA / S3 integration
| |
| +------------> MQTT / RabbitMQ messaging
|
+---------------------> JPA Repositories / PostgreSQL
IoT Devices
|
+--> publish metrics / alerts
+--> receive commands / OTA instructions
config/
controller/
dto/
entity/
repository/
scheduler/
security/
service/
resources/proto/
AuthControllerUserControllerLampControllerFleetControllerStatsControllerOtaControllerRabbitAuthController
LampServiceFleetServiceStatsServiceMqttServiceMqttListenerServiceOtaServiceRabbitMqListener
src/main/java/org/qualv13/iotbackend/
├── config/ # Spring, MQTT, RabbitMQ, S3, OpenAPI, web config
├── controller/ # REST endpoints
├── dto/ # Request/response DTOs
├── entity/ # JPA entities
├── enums/ # Alert levels and causes
├── repository/ # Spring Data repositories
├── scheduler/ # Scheduled smart/device tasks
├── security/ # JWT filter, JWT service, security config
├── service/ # Business logic and integrations
└── IoTServerAppApplication.java
src/main/resources/
├── application.yaml
├── application-test.yaml
├── application.properties
├── proto/iot_service.proto
└── static/index.html
- Java 17
- Maven 3.9+
- Docker and Docker Compose
- PostgreSQL 15
- RabbitMQ with MQTT enabled
The repository includes a multi-service setup for:
- PostgreSQL
- RabbitMQ management + MQTT
- Spring Boot backend
git clone https://github.com/qualv13/IoTServerApp.git
cd IoTServerApp
docker network create iot-net
docker compose up --build| Service | Port | Purpose |
|---|---|---|
| Backend | 40142 |
REST API |
| RabbitMQ Management | 40132 |
Broker admin UI |
| MQTT | 40131 |
Device MQTT traffic |
git clone https://github.com/qualv13/IoTServerApp.git
cd IoTServerApp
mvn spring-boot:runIf running locally without Docker, update datasource and MQTT settings to match your local services.
The verified runtime configuration includes:
spring:
datasource:
url: jdbc:postgresql://postgres:5432/iot_db
username: postgres
password: password
mqtt:
broker-url: tcp://rabbitmq-mqtt-kierzno:1883
username: iotproject
password: iotproject
jwt:
secret: <hex-secret>export SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/iot_db
export SPRING_DATASOURCE_USERNAME=postgres
export SPRING_DATASOURCE_PASSWORD=password
export MQTT_BROKER=tcp://localhost:1883
export MQTT_USERNAME=iotproject
export MQTT_PASSWORD=iotproject
export JWT_SECRET=your_jwt_secret_hereSecurity note: the repository contains development defaults. For any serious deployment, move secrets to environment variables or a secret manager.
curl -X POST http://localhost:40142/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "your-password"
}'curl http://localhost:40142/api/lamps \
-H "Authorization: Bearer <access-token>"The project uses Protocol Buffers for device communication. A simplified command intent looks like:
message LampCommand {
uint32 version = 1;
int64 ts = 2;
oneof command {
SetDirectSettingsCommand set_direct_settings_command = 5;
SetMode set_mode_command = 8;
DownloadOtaUpdateCommand download_ota_update_command = 10;
SetPresetCommand set_preset_command = 12;
}
}lamps/{lampId}/command
lamps/{lampId}/metrics
The verified config uses wildcard subscriptions:
lamps/+/command
lamps/+/metrics
The repository includes a protobuf contract at:
src/main/resources/proto/iot_service.proto
StatusReportAlertLampConfigLampCommand
- Set Wi-Fi parameters
- Blink LED
- Set direct RGB/white settings
- Set photo white settings
- Set photo color settings
- Change mode
- Reboot device
- Download OTA update
- Register lamp
- Set preset
- Acknowledge alerts
This is a strong design choice for IoT systems because it keeps payloads compact and explicit while preserving schema evolution options.
The project includes SpringDoc OpenAPI support.
| Area | Purpose |
|---|---|
| Auth | Login, token refresh, registration |
| Users | Profile and account operations |
| Lamps | Device CRUD and control |
| Fleets | Grouping and fleet-level operations |
| Stats | Metrics and analytics |
| OTA | Firmware release and update workflows |
mvn test9 tests run on every push, against H2 in memory with the MQTT client mocked out. No database, no broker and no credentials required, which is the point: a test that only passes on the machine it was written on is not a test.
| Class | Covers | Tests |
|---|---|---|
AuthControllerTest |
login, refresh, account deletion | 2 |
FleetControllerTest |
fleet creation and lamp assignment | 2 |
JwtServiceTest |
token issue and validation | 2 |
FleetServiceTest |
fleet service logic | 1 |
LampMetricRepositoryTest |
metric queries | 1 |
IoTServerAppApplicationTests |
the context starts | 1 |
Six more classes in src/test are commented out, and they are not
decoration: uncommented, they compile and run, they just do not pass yet.
| Class | Why it is parked |
|---|---|
LampControllerTest, LampControllerProtoTest, OtaControllerTest, UserControllerTest |
assertions written against older response shapes |
LampServiceTest |
LampService gained two constructor arguments (LampAlertRepository, MqttService) |
RabbitMqListenerTest |
one assertion drifted from the current listener |
StatsServiceTest |
getUserStats returns DetailedStatsDto now, with a different API |
MqttListenerServiceTest |
its subject, MqttListenerService, is itself commented out; the MQTT path moved to RabbitMqListener |
That is 7 failing assertions, not 7 broken features. Each one is a decision about what the endpoint should return today, which is why they are listed here instead of being quietly deleted.
docker build -t iotserverapp .docker network create iot-net
docker compose up -d --build- Replace default JWT secret
- Replace default database credentials
- Restrict CORS
- Secure RabbitMQ management access
- Use managed secret storage
- Add observability and structured logging
- Add CI/CD validation for tests and image builds
Contributions are welcome.
- Fork the repository
- Create a feature branch
- Make focused changes
- Add or update tests
- Open a pull request with implementation notes
- Keep commits small and reviewable
- Document API or protocol changes
- Include setup notes for infra-related changes
The current public README references MIT.
- GitHub profile: qualv13
- Repository: qualv13/IoTServerApp