This project implements a backend service for collecting, storing, and managing time-series data from ESP32 devices simulating current sensors. It uses Spring Boot with TimescaleDB (PostgreSQL extension) for efficient storage and querying of time-series data.
- Spring Boot 3.2.1
- Java 17
- TimescaleDB (PostgreSQL extension)
- MQTT for IoT communication
- Gradle for build management
- Java 17+
- PostgreSQL with TimescaleDB extension
- MQTT Broker (running on specified IP)
- Gradle 8.x
# For Arch Linux
sudo pacman -S timescaledb
sudo nano /var/lib/postgres/data/postgresql.conf
shared_preload_libraries = 'timescaledb'
sudo systemctl restart postgresql
-- Connect to PostgreSQL
sudo -u postgres psql
-- Create database
CREATE DATABASE livewire;
-- Connect to database
\c livewire
-- Enable TimescaleDB
CREATE EXTENSION IF NOT EXISTS timescaledb;
-- Create the hypertable
CREATE TABLE device_readings (
device_id TEXT NOT NULL,
device_name TEXT,
current_rms DOUBLE PRECISION,
min_current DOUBLE PRECISION,
max_current DOUBLE PRECISION,
timestamp TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
id BIGSERIAL,
PRIMARY KEY (id, timestamp)
);
-- Convert to hypertable
SELECT create_hypertable('device_readings', 'timestamp');
Create or update src/main/resources/application.properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/livewire spring.datasource.username=postgres spring.datasource.password=postgres spring.jpa.hibernate.ddl-auto=update
mqtt.broker=tcp://192.168.1.14:1883
mqtt.client-id=spring-boot-client
mqtt.topics=livewire/sensor/current/#
server.port=8081
logging.level.org.livewire=DEBUG
Livewire/
├── README.md
├── build.gradle.kts
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── org/
│ │ │ └── livewire/
│ │ │ ├── config/
│ │ │ │ ├── JacksonConfig.java
│ │ │ │ ├── MqttConfig.java
│ │ │ │ ├── MqttHealthIndicator.java
│ │ │ │ └── MqttProperties.java
│ │ │ ├── controller/
│ │ │ │ └── SensorController.java
│ │ │ ├── dto/
│ │ │ │ └── SensorReadingDTO.java
│ │ │ ├── entity/
│ │ │ │ └── DeviceReading.java
│ │ │ ├── repository/
│ │ │ │ └── DeviceReadingRepository.java
│ │ │ ├── service/
│ │ │ │ └── MqttMessageHandler.java
│ │ │ └── LivewireApplication.java
│ │ └── resources/
│ │ └── application.properties
│ └── test/
│ ├── java/
│ │ └── org/
│ │ └── livewire/
│ │ ├── controller/
│ │ │ └── SensorControllerTest.java
│ │ ├── repository/
│ │ │ └── DeviceReadingRepositoryIntegrationTest.java
│ │ └── service/
│ │ └── MqttMessageHandlerTest.java
│ └── resources/
└── .gitignore
http://localhost:8081/api/data?page=0&size=10
Returns paginated data for all devices.
http://localhost:8081/api/latest
Returns the most recent reading from each device.
http://localhost:8081/api/devices
Returns a list of all device IDs in the system.
http://localhost:8081/api/device/{deviceId}?page=0&size=10
Returns paginated readings for a specific device.
{
"device_id": "device1",
"device_name": "Living Room",
"timestamp": 1734456562,
"current_RMS": 3.95,
"min_current": 3,
"max_current": 4
}
# Build the project
./gradlew build
# Run the application
./gradlew bootRun
Monitor MQTT messages:
mosquitto_sub -h 192.168.1.14 -t "livewire/sensor/current/#" -v
Monitor application health:
http://localhost:8081/actuator/health
- Database Connection Issues
- Verify PostgreSQL is running: systemctl status postgresql
- Check database credentials in application.properties
- Ensure TimescaleDB extension is enabled
- MQTT Connection Issues
- Verify MQTT broker address and port.
- Check MQTT broker is running.
- Verify topic subscription format.
- Port Already in Use
- Change server.port in application.properties.
- Check for other applications using port 8081.
- Fork the project
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Merge Request
This project is licensed under the MIT License - see the LICENSE file for details.
Raphael Fernandes