TGM Expert provides comprehensive IoT sensor management including data ingestion, real-time monitoring, threshold-based alerting, and condition-based maintenance integration.
Table of Contents¶
Overview¶
Key Features¶
- Real-Time Data Ingestion - Ingest sensor readings via REST API
- Dual Storage - PostgreSQL and InfluxDB time-series storage
- Threshold-Based Alerting - Warning and critical thresholds
- Anomaly Detection - Statistical anomaly detection
- Condition-Based Maintenance - Auto-generate work orders from alerts
- Multi-Sensor Comparison - Compare data across sensors
Architecture¶
IoT Devices/Gateways
│
▼
REST API (/iot/readings)
│
├─────────────────────┐
▼ ▼
PostgreSQL InfluxDB
(Recent data) (Time-series)
│ │
└─────────┬───────────┘
▼
Alert Engine
│
▼
┌─────────┴─────────┐
▼ ▼
Notifications Work Orders
Sensors¶
Sensor Entity¶
{
"id": 1,
"name": "Bearing Temperature Sensor",
"description": "Monitors turbine bearing temperature",
"type": "TEMPERATURE",
"unit": "°C",
"externalId": "SENSOR-001-TEMP",
"component": {
"id": 100,
"name": "Main Bearing"
},
"isActive": true,
"minValue": "0",
"maxValue": "150",
"warningMin": 20,
"warningMax": 80,
"criticalMin": 10,
"criticalMax": 100,
"alertEnabled": true,
"autoWorkOrderEnabled": true,
"lastReadingValue": 65.5,
"lastReadingTime": "2026-02-01T10:30:00Z",
"influxMeasurement": "sensor_readings",
"influxField": "value"
}
Sensor Types¶
| Type | Description |
|---|---|
TEMPERATURE |
Temperature sensor (°C, °F) |
PRESSURE |
Pressure sensor (bar, psi) |
VIBRATION |
Vibration sensor (mm/s, g) |
FLOW |
Flow rate sensor (m³/h, L/min) |
LEVEL |
Level sensor (m, %) |
SPEED |
Speed/RPM sensor |
CURRENT |
Electrical current (A) |
VOLTAGE |
Electrical voltage (V) |
POWER |
Power sensor (kW, MW) |
HUMIDITY |
Humidity sensor (%) |
API Endpoints¶
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/sensors |
List sensors |
| GET | /api/sensors/{id} |
Get sensor |
| POST | /api/sensors |
Create sensor |
| PUT | /api/sensors/{id} |
Update sensor |
| DELETE | /api/sensors/{id} |
Delete sensor |
Create Sensor¶
curl -X POST https://api.tgm-expert.com/api/sensors \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Bearing Temperature",
"type": "TEMPERATURE",
"unit": "°C",
"externalId": "SENSOR-001-TEMP",
"componentId": 100,
"warningMin": 20,
"warningMax": 80,
"criticalMin": 10,
"criticalMax": 100,
"alertEnabled": true,
"autoWorkOrderEnabled": true
}'
Data Ingestion¶
Single Reading¶
curl -X POST https://api.tgm-expert.com/iot/readings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"sensorId": 1,
"value": 65.5,
"timestamp": "2026-02-01T10:30:00Z",
"metadata": {
"quality": "good",
"source": "plc-gateway"
}
}'
Or by external ID:
curl -X POST https://api.tgm-expert.com/iot/readings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"externalId": "SENSOR-001-TEMP",
"value": 65.5,
"timestamp": "2026-02-01T10:30:00Z"
}'
Bulk Ingestion¶
curl -X POST https://api.tgm-expert.com/iot/readings/bulk \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[
{"sensorId": 1, "value": 65.5, "timestamp": "2026-02-01T10:30:00Z"},
{"sensorId": 2, "value": 120.3, "timestamp": "2026-02-01T10:30:00Z"},
{"sensorId": 3, "value": 45.8, "timestamp": "2026-02-01T10:30:00Z"}
]'
Reading Response¶
{
"data": {
"id": 12345,
"sensor": {"id": 1, "name": "Bearing Temperature"},
"value": 65.5,
"readingTime": "2026-02-01T10:30:00Z",
"metadata": {
"quality": "good",
"source": "plc-gateway"
}
}
}
Querying Readings¶
# Get paginated readings
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/readings?page=0&size=50" \
-H "Authorization: Bearer $TOKEN"
# Get readings in time range
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/readings/range?startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z" \
-H "Authorization: Bearer $TOKEN"
# Get latest reading
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/readings/latest" \
-H "Authorization: Bearer $TOKEN"
Alerts & Thresholds¶
Threshold Configuration¶
Sensors can have warning and critical thresholds:
▲ Value
│
100│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ criticalMax
│ CRITICAL
80│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ warningMax
│ WARNING
│
│ NORMAL
│
20│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ warningMin
│ WARNING
10│ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ criticalMin
│ CRITICAL
└────────────────────────▶ Time
Alert Entity¶
{
"id": 1,
"sensor": {
"id": 1,
"name": "Bearing Temperature"
},
"type": "HIGH_VALUE",
"severity": "WARNING",
"status": "ACTIVE",
"message": "Value 85°C exceeds warning threshold 80°C",
"triggerValue": 85,
"thresholdValue": 80,
"triggeredAt": "2026-02-01T10:30:00Z",
"acknowledgedAt": null,
"acknowledgedBy": null,
"resolvedAt": null,
"resolutionNotes": null
}
Alert Severity¶
| Severity | Description |
|---|---|
INFO |
Informational alert |
WARNING |
Warning threshold exceeded |
CRITICAL |
Critical threshold exceeded |
EMERGENCY |
Escalated critical alert |
Alert Status¶
| Status | Description |
|---|---|
ACTIVE |
Alert is active |
ACKNOWLEDGED |
Alert acknowledged by operator |
ESCALATED |
Alert escalated to higher severity |
RESOLVED |
Alert resolved |
Alert Management¶
# Get active alerts
curl -X GET "https://api.tgm-expert.com/iot/alerts/active" \
-H "Authorization: Bearer $TOKEN"
# Get alerts by status
curl -X GET "https://api.tgm-expert.com/iot/alerts?status=ACTIVE&page=0&size=20" \
-H "Authorization: Bearer $TOKEN"
# Get sensor-specific alerts
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/alerts" \
-H "Authorization: Bearer $TOKEN"
Acknowledge Alert¶
curl -X POST "https://api.tgm-expert.com/iot/alerts/1/acknowledge" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"notes": "Investigating high temperature reading"
}'
Resolve Alert¶
curl -X POST "https://api.tgm-expert.com/iot/alerts/1/resolve" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"resolutionNotes": "Cooling system was temporarily offline. Issue resolved."
}'
Escalate Alert¶
curl -X POST "https://api.tgm-expert.com/iot/alerts/1/escalate" \
-H "Authorization: Bearer $TOKEN"
Time-Series Data¶
InfluxDB Integration¶
TGM Expert supports dual storage with InfluxDB for high-performance time-series queries.
# Check storage status
curl -X GET "https://api.tgm-expert.com/iot/status" \
-H "Authorization: Bearer $TOKEN"
Response:
{
"data": {
"influxdbAvailable": true,
"postgresqlAvailable": true,
"primaryStorage": "influxdb"
}
}
Time-Series Queries¶
# Get time-series data
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/timeseries?startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z&limit=1000" \
-H "Authorization: Bearer $TOKEN"
# Get downsampled data (for charts)
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/timeseries/downsampled?startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z&windowSize=1h" \
-H "Authorization: Bearer $TOKEN"
Window Sizes¶
| Window | Description |
|---|---|
1m |
1 minute aggregation |
5m |
5 minute aggregation |
15m |
15 minute aggregation |
1h |
1 hour aggregation |
6h |
6 hour aggregation |
1d |
1 day aggregation |
Multi-Sensor Comparison¶
curl -X GET "https://api.tgm-expert.com/iot/sensors/compare?sensorIds=1,2,3&startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z&windowSize=1h" \
-H "Authorization: Bearer $TOKEN"
Response:
{
"data": {
"1": [
{"time": "2026-02-01T00:00:00Z", "mean": 65.2, "min": 60.1, "max": 70.3},
{"time": "2026-02-01T01:00:00Z", "mean": 66.5, "min": 62.3, "max": 71.2}
],
"2": [
{"time": "2026-02-01T00:00:00Z", "mean": 120.5, "min": 115.2, "max": 125.8}
]
}
}
Analytics¶
Sensor Statistics¶
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/stats?startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z" \
-H "Authorization: Bearer $TOKEN"
Response:
{
"data": {
"count": 1440,
"mean": 65.5,
"min": 55.2,
"max": 78.3,
"stddev": 5.2,
"firstReading": "2026-02-01T00:00:30Z",
"lastReading": "2026-02-01T23:59:30Z"
}
}
Anomaly Detection¶
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/anomalies?startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z&stddevThreshold=2.0" \
-H "Authorization: Bearer $TOKEN"
Response:
{
"data": [
{
"timestamp": "2026-02-01T14:32:00Z",
"value": 95.5,
"mean": 65.5,
"stddev": 5.2,
"deviations": 5.77,
"isAnomaly": true
}
]
}
Data Rate Analysis¶
curl -X GET "https://api.tgm-expert.com/iot/sensors/1/datarate?startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z&windowSize=1h" \
-H "Authorization: Bearer $TOKEN"
Response:
{
"data": [
{"time": "2026-02-01T00:00:00Z", "count": 60, "rate": "1/min"},
{"time": "2026-02-01T01:00:00Z", "count": 58, "rate": "0.97/min"}
]
}
Component Readings¶
Get all sensor readings for a component:
curl -X GET "https://api.tgm-expert.com/iot/components/100/readings?startTime=2026-02-01T00:00:00Z&endTime=2026-02-01T23:59:59Z&limit=1000" \
-H "Authorization: Bearer $TOKEN"
Dashboard¶
IoT Dashboard¶
curl -X GET "https://api.tgm-expert.com/iot/dashboard?periodDays=30" \
-H "Authorization: Bearer $TOKEN"
Response:
{
"data": {
"totalSensors": 150,
"activeSensors": 145,
"inactiveSensors": 5,
"totalReadings": 1250000,
"readingsLast24h": 45000,
"activeAlerts": 3,
"alertsLast24h": 12,
"sensorsByType": {
"TEMPERATURE": 50,
"PRESSURE": 30,
"VIBRATION": 40,
"FLOW": 20,
"OTHER": 10
},
"alertsBySeverity": {
"WARNING": 2,
"CRITICAL": 1,
"EMERGENCY": 0
},
"topAlertingSensors": [
{"sensorId": 1, "name": "Bearing Temp", "alertCount": 5},
{"sensorId": 15, "name": "Oil Pressure", "alertCount": 3}
]
}
}
IoT API Endpoints Summary¶
| Method | Endpoint | Description |
|---|---|---|
| POST | /iot/readings |
Ingest single reading |
| POST | /iot/readings/bulk |
Bulk ingest readings |
| GET | /iot/sensors/{id}/readings |
Get paginated readings |
| GET | /iot/sensors/{id}/readings/range |
Get readings in time range |
| GET | /iot/sensors/{id}/readings/latest |
Get latest reading |
| GET | /iot/sensors/{id}/stats |
Get sensor statistics |
| GET | /iot/alerts |
Get alerts by status |
| GET | /iot/alerts/active |
Get active alerts |
| GET | /iot/sensors/{id}/alerts |
Get sensor alerts |
| POST | /iot/alerts/{id}/acknowledge |
Acknowledge alert |
| POST | /iot/alerts/{id}/resolve |
Resolve alert |
| POST | /iot/alerts/{id}/escalate |
Escalate alert |
| GET | /iot/dashboard |
Get IoT dashboard |
| GET | /iot/sensors/{id}/timeseries |
Get time-series data |
| GET | /iot/sensors/{id}/timeseries/downsampled |
Get downsampled data |
| GET | /iot/sensors/compare |
Compare multiple sensors |
| GET | /iot/sensors/{id}/anomalies |
Detect anomalies |
| GET | /iot/sensors/{id}/datarate |
Get data rate |
| GET | /iot/components/{id}/readings |
Get component readings |
| GET | /iot/status |
Get storage status |
Best Practices¶
1. Use Bulk Ingestion¶
For high-frequency sensors, batch readings together:
readings = []
for sensor_data in collected_data:
readings.append({
"externalId": sensor_data["id"],
"value": sensor_data["value"],
"timestamp": sensor_data["time"]
})
if len(readings) >= 100:
api.post("/iot/readings/bulk", readings)
readings = []
2. Set Appropriate Thresholds¶
Configure thresholds based on equipment specifications:
{
"warningMin": 20, // Below normal operating range
"warningMax": 80, // Above normal, needs attention
"criticalMin": 10, // Equipment at risk
"criticalMax": 100 // Immediate action required
}
3. Enable Auto Work Orders¶
For critical sensors, enable automatic work order creation:
{
"alertEnabled": true,
"autoWorkOrderEnabled": true
}
4. Use External IDs¶
Use stable external IDs for sensors to simplify integration:
{
"externalId": "PLC1-SENSOR-001-TEMP"
}
5. Include Metadata¶
Include quality and source information:
{
"value": 65.5,
"metadata": {
"quality": "good",
"source": "modbus-gateway",
"plcTimestamp": "2026-02-01T10:30:00.123Z"
}
}
Webhooks¶
IoT events trigger webhooks for integration:
| Event | Description |
|---|---|
sensor_reading.received |
New sensor reading ingested |
sensor_alert.created |
New alert triggered |
sensor_alert.acknowledged |
Alert acknowledged |
sensor_alert.resolved |
Alert resolved |
sensor_alert.escalated |
Alert escalated |
See Webhooks Documentation for setup details.