This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is an IoT Energy Storage Management Platform (储能运营平台), originally based on RuoYi v3.9.0 but now stripped down to a standalone Spring Boot module focused on IoT device telemetry ingestion, MQTT messaging, time-series data storage, and vehicle/equipment tracking.
# Build the iot-platform module
mvn clean package -pl iot-platform -am -Dmaven.test.skip=true
# Run locally with .env
source .env && cd iot-platform/target && java -jar iot-platform.jar
# Or use the convenience script
./start.sh start
The application starts on port 8887. The executable JAR is iot-platform/target/iot-platform.jar.
This is now a single-module Spring Boot application (previously a multi-module RuoYi project).
iot-platform/
├── controller → REST API endpoints, Swagger config
├── service → Business logic: IoT data sync, MQTT consumers, TDengine ops
├── domain → Entity classes, DTOs, VO objects
├── mapper → MyBatis mapper interfaces + XML in resources/mapper/
├── mqtt → MQTT consumers (AbstractMqttConsumer base class)
├── task → Scheduled tasks (VehicleSyncTask, etc.)
├── config → Spring configuration classes
├── common → Shared constants (RedisKeys), utilities
└── datasource → Dynamic datasource configuration
data): System tables (users, roles, menus) + business tablescnc): Secondary data — configured in application-druid.yml47.104.204.180:3306@DataSource annotationTDengineServicejdbc:TAOS://localhost:6030/stableColumnCache)localhost:6379common/RedisKeys.java):
DSB:active:devices — Set of active IoT device keysDSB:<controllerId>:<metricName> — Hash storing device telemetryworkorder:coordinate:<controllerId> — GPS coordinates<controllerId>:<topicName> — MQTT topic metadataiot-platform/src/main/resources/application.yml — Main config (port 8887, Redis, MyBatis, Actuator)iot-platform/src/main/resources/application-druid.yml — Database connection (Druid pool, master/slave)iot-platform/src/main/resources/logback-spring.xml — Logging config with rolling.env — Environment variables (passwords, credentials) loaded by systemd or start.shAll sensitive credentials are externalized to .env:
MYSQL_USERNAME=root
MYSQL_PASSWORD="..."
REDIS_PASSWORD=
MQTT_USERNAME=...
MQTT_PASSWORD=...
TDENGINE_USERNAME=root
TDENGINE_PASSWORD=taosdata
DRUID_STAT_ENABLED=false
DRUID_USERNAME=ruoyi
DRUID_PASSWORD=...
Spring Boot config uses ${ENV_NAME:default} syntax for non-sensitive defaults only. MySQL and Druid passwords have no fallback defaults — missing env vars will cause startup failures.
MQTT Broker (47.104.204.180:1883)
↓ subscribes to "+/generics", "+/status", "+/fault"
MqttGenericConsumer / MqttStatusConsumer / MqttFaultConsumer
↓ parse JSON → ControllerData
├─→ Redis (DSB:active:devices, DSB:<id>:<metric> hashes)
├─→ MySQL (sys_controller, sys_device tables)
└─→ TDengine (time-series telemetry tables)
VehicleSyncTask (@Scheduled every 30s, Redis distributed lock)
↓ reads Redis DSB:* keys
├─→ syncs to sysrealtime (MySQL)
├─→ updates vehicle GPS in sys_car (MySQL)
├─→ updates sys_indicators KPIs (MySQL)
└─→ triggers external webhook (URL from `iot.mqtt.vehicle-trigger-url` config)
Two base classes handle MQTT connections:
AbstractMqttConsumer (single-topic consumers):
synchronized reconnect/disconnect@PreDestroyAbstractDynamicMqttConsumer (dynamic multi-topic consumers):
Implementations:
MqttGenericConsumer — General telemetry ingestion (single-topic)MqttStatusConsumer — Device status messages (single-topic)MqttFaultConsumer — Fault/alarm messages (single-topic)MqttDynamicConsumer — Dynamic topic subscription (extends AbstractDynamicMqttConsumer)MqttChargeStationConsumer — Charge station telemetry (extends AbstractDynamicMqttConsumer)Production deployment uses systemd on online180 (47.104.204.180).
# Deploy from local
cd deploy
./deploy.sh --build # Build and deploy
./deploy.sh --jar <path> # Deploy specific jar
# Server management
systemctl status iot-platform
systemctl restart iot-platform
journalctl -u iot-platform -f
See deploy/README.md for full deployment documentation.
Authorization)config/SecurityConfig.java^[a-zA-Z_][a-zA-Z0-9_]*$ in SysControllerService, SysFaultService, SysAlarmServiceAll controllers return AjaxResult:
{
"code": 200,
"msg": "操作成功",
"data": { ... }
}
Page queries use TableDataInfo:
{
"code": 200,
"msg": "查询成功",
"rows": [ ... ],
"total": 100
}
Spring Boot Actuator is enabled at /actuator/health:
curl http://localhost:8887/actuator/health
# {"status":"UP"}
src/main/resources/mapper/I prefix)ALLOWED_COLUMNS) and escapeValue()VehicleSyncTask uses Redis SET NX for per-method distributed locking (30s delay, 60s TTL)stableColumnCache capped at 1000 entries to prevent unbounded growthhttps://maven.aliyun.com/repository/public) configured in root pom.xml