295 lines
9.4 KiB
Markdown
295 lines
9.4 KiB
Markdown
# POE Sensor - Modbus to MQTT Bridge Service
|
|
|
|
A robust Python service that reads temperature, humidity, and CO2 data from multiple Modbus TCP sensors and publishes the data to an MQTT broker with comprehensive monitoring and alerting capabilities.
|
|
|
|
## 📁 Project Structure
|
|
|
|
```
|
|
POE-sensor/
|
|
├── config.py # Configuration constants and sensor definitions
|
|
├── sensor_bridge.py # Core logic for Modbus and MQTT operations
|
|
├── sensor_tracker.py # Sensor status tracking and alerting system
|
|
├── health_check.py # HTTP health check server (optional monitoring)
|
|
├── main.py # Entry point and application lifecycle management
|
|
├── requirements.txt # Python dependencies
|
|
├── poe-sensor.nomad # Nomad deployment configuration
|
|
└── README.md # This documentation
|
|
```
|
|
|
|
## 🚀 Quick Start
|
|
|
|
### 1. Install Dependencies
|
|
```bash
|
|
pip install -r requirements.txt
|
|
```
|
|
|
|
### 2. Configure Settings
|
|
Edit `config.py` to match your environment:
|
|
```python
|
|
# Modbus sensor configuration
|
|
MODBUS_HOSTS = [
|
|
{"ip": "10.84.60.31", "location": "Warehouse-B", "type": "temperature_humidity"},
|
|
{"ip": "10.84.60.37", "location": "Office", "type": "cwt_co2"},
|
|
# Add more sensors as needed
|
|
]
|
|
|
|
# MQTT configuration
|
|
MQTT_BROKER = "mqtt.service.mesh"
|
|
MQTT_USERNAME = "relay"
|
|
MQTT_PASSWORD = "your_password"
|
|
```
|
|
|
|
### 3. Run the Service
|
|
```bash
|
|
python main.py
|
|
```
|
|
|
|
## 📊 Features
|
|
|
|
### Core Functionality
|
|
- **Multi-Sensor Support**: Handles both temperature/humidity and CO2 sensors
|
|
- **Modbus TCP Client**: Reads data from multiple Modbus holding registers
|
|
- **MQTT Publisher**: Publishes sensor data to structured MQTT topics
|
|
- **Data Processing**: Converts raw sensor values to calibrated readings
|
|
- **Error Handling**: Robust error handling and retry mechanisms
|
|
- **Resource Management**: Automatic connection cleanup and garbage collection
|
|
|
|
### Monitoring & Alerting
|
|
- **Real-time Sensor Tracking**: Individual sensor health monitoring
|
|
- **Automatic Alerting**: MQTT alerts for sensor failures and recovery
|
|
- **Health Check API**: Optional HTTP endpoints for system monitoring
|
|
- **Comprehensive Logging**: Detailed logging for debugging and monitoring
|
|
- **Status Reporting**: Real-time sensor status via MQTT topics
|
|
|
|
### Production Ready
|
|
- **Nomad Deployment**: Ready-to-deploy Nomad job configuration
|
|
- **Docker Support**: Containerized deployment with dependency management
|
|
- **Environment Configuration**: Environment variable support for flexible deployment
|
|
- **Graceful Shutdown**: Proper cleanup and signal handling
|
|
|
|
## 📈 Data Format & Topics
|
|
|
|
### MQTT Topic Structure
|
|
The service uses a flat topic structure for each location:
|
|
|
|
```
|
|
Location/{location}/Time # Timestamp
|
|
Location/{location}/Status # "online" or "offline"
|
|
Location/{location}/Temperature # Temperature value
|
|
Location/{location}/Humidity # Humidity value
|
|
Location/{location}/CO2 # CO2 sensors only
|
|
Location/{location}/alerts # Alert messages
|
|
```
|
|
|
|
> **Note:** The `CO2` topic is only published for sensors that support CO2 measurement.
|
|
|
|
### Example Topics
|
|
```
|
|
Location/Warehouse-B/Time → "2024-01-15 10:30:25"
|
|
Location/Warehouse-B/Status → "online"
|
|
Location/Warehouse-B/Temperature → "23.5"
|
|
Location/Warehouse-B/Humidity → "65.2"
|
|
|
|
Location/Office/Time → "2024-01-15 10:30:25"
|
|
Location/Office/Status → "online"
|
|
Location/Office/Temperature → "24.1"
|
|
Location/Office/Humidity → "58.3"
|
|
Location/Office/CO2 → "420"
|
|
```
|
|
|
|
### Alert Format
|
|
```json
|
|
{
|
|
"alert_type": "sensor_failure",
|
|
"timestamp": "2024-01-15T10:30:25Z",
|
|
"sensor_id": "10.84.60.31_Warehouse-B",
|
|
"sensor_ip": "10.84.60.31",
|
|
"sensor_location": "Warehouse-B",
|
|
"sensor_type": "temperature_humidity",
|
|
"consecutive_failures": 3,
|
|
"last_error": "Connection timeout",
|
|
"severity": "critical"
|
|
}
|
|
```
|
|
|
|
## 🔧 Configuration
|
|
|
|
### Sensor Configuration
|
|
Add sensors to the `MODBUS_HOSTS` list in `config.py`:
|
|
|
|
```python
|
|
MODBUS_HOSTS = [
|
|
# Temperature/Humidity sensors
|
|
{"ip": "10.84.60.31", "location": "Warehouse-B", "type": "temperature_humidity"},
|
|
{"ip": "10.84.60.32", "location": "Warehouse-C", "type": "temperature_humidity"},
|
|
|
|
# CO2 sensors (CWT series)
|
|
{"ip": "10.84.60.37", "location": "Office", "type": "cwt_co2"},
|
|
]
|
|
```
|
|
|
|
### Environment Variables
|
|
The service supports environment variable configuration:
|
|
|
|
| Variable | Description | Default |
|
|
|----------|-------------|---------|
|
|
| `MQTT_BROKER` | MQTT broker address | "mqtt.service.mesh" |
|
|
| `MQTT_PORT` | MQTT broker port | 1883 |
|
|
| `MQTT_USERNAME` | MQTT username | "relay" |
|
|
| `MQTT_PASSWORD` | MQTT password | - |
|
|
| `PUBLISH_INTERVAL` | Data publish interval (seconds) | 10 |
|
|
| `HEALTH_CHECK_ENABLED` | Enable HTTP health server | true |
|
|
| `HEALTH_CHECK_PORT` | Health server port | 8080 |
|
|
| `ALERTING_ENABLED` | Enable MQTT alerts | true |
|
|
| `SENSOR_TIMEOUT_THRESHOLD` | Failures before alert | 3 |
|
|
| `RECOVERY_CONFIRMATION_COUNT` | Successes to confirm recovery | 2 |
|
|
| `TIMEZONE_OFFSET` | Timezone offset from UTC (hours) | 7 (GMT+7) |
|
|
|
|
## 🏥 Health Check & Monitoring
|
|
|
|
### Optional Health Check Server
|
|
The service includes an optional HTTP health check server for monitoring:
|
|
|
|
- **http://localhost:8080/health** - Basic service health status
|
|
- **http://localhost:8080/sensors** - Detailed sensor status information
|
|
|
|
### Health Response Example
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"timestamp": "2024-01-15T10:30:25Z",
|
|
"service": "poe-sensor",
|
|
"version": "1.0.0",
|
|
"sensors_total": 7,
|
|
"sensors_online": 6,
|
|
"sensors_health": 85.7
|
|
}
|
|
```
|
|
|
|
### Sensor Status Response
|
|
```json
|
|
{
|
|
"timestamp": "2024-01-15T10:30:25Z",
|
|
"total_sensors": 7,
|
|
"online_sensors": 6,
|
|
"offline_sensors": 1,
|
|
"sensors": {
|
|
"10.84.60.31_Warehouse-B": {
|
|
"ip": "10.84.60.31",
|
|
"location": "Warehouse-B",
|
|
"type": "temperature_humidity",
|
|
"status": "online",
|
|
"last_success": "2024-01-15T10:29:45Z",
|
|
"uptime_percentage": 98.5
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## 🚀 Production Deployment
|
|
|
|
### Nomad Deployment
|
|
The service is designed for production deployment using HashiCorp Nomad:
|
|
|
|
```bash
|
|
# Deploy to Nomad cluster
|
|
nomad job run poe-sensor.nomad
|
|
|
|
# Check deployment status
|
|
nomad job status poe-sensor
|
|
|
|
# View logs
|
|
nomad alloc logs <allocation_id>
|
|
```
|
|
|
|
### Key Deployment Features
|
|
- **No Health Check Dependencies**: Service is considered healthy when running
|
|
- **Fast Deployment**: Minimal startup time requirements
|
|
- **Auto-restart**: Automatic restart on application crashes
|
|
- **Resource Limits**: Configured CPU and memory limits
|
|
- **Log Management**: Automatic log rotation and retention
|
|
|
|
### Docker Configuration
|
|
The Nomad job uses a pre-configured Docker image with:
|
|
- Python 3.x runtime
|
|
- Required system dependencies
|
|
- Automatic dependency installation
|
|
- Git-based source code deployment
|
|
|
|
## 📡 Sensor Support
|
|
|
|
### Temperature/Humidity Sensors
|
|
- **Register 0**: Temperature (formula: (125 - (-40)) * raw / 1650 - 40)
|
|
- **Register 1**: Humidity (formula: raw * 100 / 1000)
|
|
- **Output**: Temperature in °C, Humidity in %RH
|
|
|
|
### CWT CO2 Sensors
|
|
- **Register 0**: Humidity (0.1%RH resolution)
|
|
- **Register 1**: Temperature (0.1°C resolution, 2's complement)
|
|
- **Register 2**: CO2 (1ppm resolution)
|
|
- **Output**: Temperature in °C, Humidity in %RH, CO2 in ppm
|
|
|
|
## 🔧 Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **Sensor Connection Failures**
|
|
- Check network connectivity to sensor IPs
|
|
- Verify Modbus port (default: 505) is accessible
|
|
- Check sensor power and network configuration
|
|
|
|
2. **MQTT Connection Issues**
|
|
- Verify MQTT broker address and credentials
|
|
- Check network connectivity to MQTT broker
|
|
- Review MQTT broker logs for connection attempts
|
|
|
|
3. **Health Check Not Responding**
|
|
- Health check server is optional and non-blocking
|
|
- Service will continue running even if health server fails
|
|
- Check port 8080 availability if health check is needed
|
|
|
|
### Log Analysis
|
|
Monitor logs for key indicators:
|
|
- **Connection status**: Modbus and MQTT connection messages
|
|
- **Data reading**: Successful sensor data retrieval
|
|
- **Publishing status**: MQTT message publication confirmation
|
|
- **Error conditions**: Connection failures and retry attempts
|
|
- **Sensor health**: Failure/recovery notifications
|
|
|
|
### Performance Monitoring
|
|
- **Cycle completion**: Monitor sensor processing cycles
|
|
- **Memory usage**: Automatic garbage collection logs
|
|
- **Alert frequency**: Sensor failure and recovery alerts
|
|
- **Uptime percentage**: Individual sensor reliability metrics
|
|
|
|
## 🤝 Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
3. Make your changes with proper testing
|
|
4. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
5. Push to the branch (`git push origin feature/amazing-feature`)
|
|
6. Open a Pull Request
|
|
|
|
### Development Guidelines
|
|
- Follow Python PEP 8 style guidelines
|
|
- Add comprehensive logging for new features
|
|
- Test with multiple sensor types
|
|
- Update documentation for configuration changes
|
|
- Ensure backward compatibility when possible
|
|
|
|
## 📝 License
|
|
|
|
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
|
|
## 🆘 Support
|
|
|
|
For issues and questions:
|
|
1. Check the troubleshooting section above
|
|
2. Review application logs for error details
|
|
3. Verify network connectivity and sensor configuration
|
|
4. Create an issue in the project repository with:
|
|
- Detailed error description
|
|
- Relevant log excerpts
|
|
- Environment configuration
|
|
- Steps to reproduce the issue |