https://github.com/rossonet/waldot
TinkerPop Gremlin backend OPC UA
https://github.com/rossonet/waldot
gremlin milo opc opc-ua opcua rules-engine tinkerpop
Last synced: about 1 month ago
JSON representation
TinkerPop Gremlin backend OPC UA
- Host: GitHub
- URL: https://github.com/rossonet/waldot
- Owner: rossonet
- License: apache-2.0
- Created: 2024-03-21T18:59:31.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2026-03-28T17:54:05.000Z (2 months ago)
- Last Synced: 2026-03-28T18:23:49.333Z (2 months ago)
- Topics: gremlin, milo, opc, opc-ua, opcua, rules-engine, tinkerpop
- Language: Java
- Homepage:
- Size: 41 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# WaldOT
**A Digital Twin Engine Bridging OPC UA and Apache TinkerPop Graphs**
[](https://github.com/rossonet/waldot)
WaldOT is an innovative open-source project that seamlessly integrates industrial automation (OT - Operational Technology) with modern data analysis through graph databases. Built on [Apache TinkerPop](https://tinkerpop.apache.org/gremlin.html) and [Eclipse Milo OPC UA](https://projects.eclipse.org/projects/iot.milo), it transforms OPC UA address spaces into queryable, reactive graph structures.
## Why WaldOT?
### Unified OT/IT Data Model
Traditional industrial systems expose data through OPC UA - a powerful but hierarchical protocol. WaldOT revolutionizes this by representing the entire OPC UA address space as a **living graph database**, where:
- **OPC UA Objects** become **TinkerPop Vertices**
- **OPC UA References** become **Graph Edges**
- **OPC UA Variables** become **Vertex Properties**
- Changes propagate in real-time in both directions
This enables industrial engineers and data scientists to work with the same data using their preferred tools: OPC UA clients for configuration, Gremlin queries for analysis.
### Powerful Graph Queries with TinkerPop
WaldOT unlocks the full potential of **Apache TinkerPop's Gremlin query language** for industrial data. Instead of navigating rigid hierarchies, you can traverse complex relationships with expressive queries:
```groovy
// Find all motors in alarm state connected to Line 1
g.V().has('name', 'Line1')
.out('contains')
.has('type', 'motor')
.has('status', 'alarm')
.values('name')
// Calculate average temperature across all sensors in a zone
g.V().has('zone', 'production')
.has('type', 'temperature_sensor')
.values('value')
.mean()
// Find correlation patterns between equipment failures
g.V().has('event', 'failure')
.as('failed')
.in('connectedTo')
.where(out('causedBy').as('failed'))
.path()
```
These queries run **directly on the OPC UA server**, without external databases or ETL pipelines.
### Reactive Rules Engine
WaldOT includes a sophisticated **rules engine** that enables edge computing logic without external systems. Define rules using simple IF-THEN patterns with full access to graph traversal:
**Example: Temperature Monitoring**
```javascript
// Condition: Check if any sensor exceeds threshold
g.V().has('type', 'sensor')
.has('temperature', gt(80))
.hasNext()
// Action: Create alarm and notify
alarmTemp = g.V().has('type','sensor').has('temperature',gt(80)).values('temperature').next();
graph.addVertex('type', 'alarm', 'temperature', alarmTemp, 'timestamp', System.currentTimeMillis());
log.error('High temperature alert: ' + alarmTemp + '°C');
```
Rules can:
- **Query the graph** using Gremlin in conditions
- **Modify the graph** creating/updating vertices in actions
- **React to events** with configurable hysteresis (debouncing)
- **Execute in parallel** with priority-based scheduling
- **Integrate with external systems** via HTTP, message buses, etc.
### Edge-First Architecture
WaldOT is designed to run **on-device** - directly on RTUs (Remote Terminal Units), industrial PCs, or edge gateways:
- **Low latency**: No cloud round-trips for rule evaluation
- **Offline capable**: Operates without internet connectivity
- **Bandwidth efficient**: Only sends aggregated/filtered data upstream
- **Secure**: Data processing happens within the OT network perimeter
### Standards-Based & Extensible
Built on proven open standards:
- **OPC UA** for industrial connectivity (Eclipse Milo)
- **Apache TinkerPop 3.x** for graph operations
- **Gremlin** for query language
- **JEXL** for rule expressions
- **Plugin architecture** for custom extensions
## Quick Start
### Docker
```bash
docker pull rossonet/waldot:latest
docker run -p 4840:4840 -p 8182:8182 -p 8080:8080 rossonet/waldot
```
Access:
- **OPC UA Server**: `opc.tcp://localhost:4840`
- **Gremlin Console**: `ws://localhost:8182/gremlin`
- **REST API**: `http://localhost:8080/api`
### Build from Source
```bash
git clone https://github.com/rossonet/waldot.git
cd waldot
./gradlew clean build
java -jar waldot-app/build/libs/waldot-app-*.jar
```
### Maven/Gradle Dependency
```xml
net.rossonet.waldot
waldot-api
0.6.1
```
```gradle
// Gradle
implementation 'net.rossonet.waldot:waldot-api:0.6.1'
```
## Use Cases
### 1. Predictive Maintenance
Query historical patterns and correlations:
```groovy
// Find equipment that failed within 24h after temperature spike
g.V().has('type', 'equipment')
.where(
out('hasEvent').has('type', 'failure').as('failure')
.V().has('type', 'temperature_sensor')
.has('value', gt(90))
.has('timestamp', within(failure.timestamp - 86400000, failure.timestamp))
)
```
### 2. Energy Optimization
Aggregate and analyze consumption:
```groovy
// Total energy consumption per production line
g.V().has('type', 'production_line')
.group()
.by('name')
.by(out('contains').values('energy_kwh').sum())
```
### 3. Quality Control
Trace product genealogy:
```groovy
// Find all batches that used a specific raw material lot
g.V().has('lot_number', 'LOT12345')
.in('usedIn')
.in('producedBy')
.values('batch_id')
```
### 4. Real-Time Alerting
React to complex conditions:
```javascript
// Rule: Detect anomalous pump behavior
// Condition:
g.V().has('id', 'pump1').next().property('vibration').value() > threshold &&
g.V().has('id', 'pump1').next().property('flow').value() < minFlow
// Action:
graph.addVertex('type', 'maintenance_request', 'equipment', 'pump1', 'priority', 'high');
// Send notification via REST/MQTT/etc.
```
## Resources
### Documentation
- [Agent Documentation](AGENT.md) - Developer guide for AI agents and contributors
- [Architecture Overview](docs/) - Detailed technical documentation
### Links
- **Docker Images**: [DockerHub - WaldOT](https://hub.docker.com/r/rossonet/waldot) | [Zenoh Router](https://hub.docker.com/r/rossonet/zenohd)
- **Maven Central**: [WaldOT Artifacts](https://central.sonatype.com/search?q=net.rossonet.waldot)
- **GitHub Repository**: [rossonet/waldot](https://github.com/rossonet/waldot)
## Example: Complete Digital Twin Application
Here's a minimal example showing WaldOT's key features:
```java
// 1. Initialize WaldOT graph
WaldotGraph graph = OpcFactory.getOpcGraph("file:///tmp/waldot.db", new LoggerHistoryStrategy());
// 2. Create industrial equipment model
Vertex productionLine = graph.addVertex(
"id", "line1",
"type", "production_line",
"name", "Assembly Line 1"
);
Vertex motor1 = graph.addVertex(
"id", "motor1",
"type", "motor",
"rpm", 1500,
"temperature", 45.5,
"status", "running"
);
Vertex sensor1 = graph.addVertex(
"id", "temp_sensor_1",
"type", "temperature_sensor",
"value", 45.5,
"unit", "celsius"
);
// 3. Create relationships
productionLine.addEdge("contains", motor1);
motor1.addEdge("monitors", sensor1);
// 4. Define reactive rule
Vertex rule = graph.addVertex(
"id", "overheat_rule",
"type", "rule",
"name", "Motor Overheat Detection",
"condition", "g.V().has('id','temp_sensor_1').next().property('value').value() > 75",
"action", """
temp = g.V().has('id','temp_sensor_1').next().property('value').value();
log.warn('Motor overheating detected: ' + temp + '°C');
g.V().has('id','motor1').next().property('status', 'alarm');
graph.addVertex('type','alert','equipment','motor1','temperature',temp,'timestamp',System.currentTimeMillis());
""",
"hysteresis", 5000 // 5 second debounce
);
// 5. Create compute manager
Vertex compute = graph.addVertex(
"id", "compute_manager",
"type", "compute",
"threads", 2
);
// 6. Wire rule execution
sensor1.addEdge("fire", rule); // Trigger on sensor change
compute.addEdge("execute", rule, "priority", 100); // Execution priority
// 7. Now the system is live! Query from Gremlin or OPC UA client
// Gremlin query:
graph.traversal()
.V().has('type', 'motor')
.has('status', 'alarm')
.values('name')
.toList();
// OPC UA: Browse to opc.tcp://localhost:4840 and navigate the address space
```
## Advanced Features
### TinkerPop Graph Algorithms
WaldOT supports TinkerPop's graph algorithms for industrial analytics:
```groovy
// Shortest path between equipment
g.V().has('name', 'Pump1')
.repeat(out().simplePath())
.until(has('name', 'Tank5'))
.path()
.by('name')
// PageRank to find most connected equipment
g.V().pageRank().by('rank').values('rank').order().desc()
// Community detection for grouping related assets
g.V().connectedComponent().by('component').group().by('component')
```
### Extensibility via Plugins
Create custom vertex types and behaviors:
```java
@WaldotPlugin
public class MyIndustrialPlugin implements PluginListener {
@Override
public void initialize(WaldotNamespace namespace) {
// Register custom "Conveyor" vertex type in OPC UA
createConveyorTypeNode(namespace);
}
@Override
public WaldotVertex createVertex(NodeId typeNodeId, ...) {
return new ConveyorVertex(...); // Custom logic
}
}
```
### Integration Capabilities
- **REST API**: HTTP endpoints for external systems
- **Gremlin Server**: WebSocket protocol (port 8182)
- **OPC UA Client**: Connect to other OPC UA servers
- **Message Bus**: Zenoh pub/sub connector for edge-to-cloud
- **JDBC**: Export graph data to SQL databases
- **GraphQL**: Query via GraphQL over HTTP
## Performance & Scalability
- **Edge-optimized**: Runs on devices with 1GB+ RAM
- **Virtual threads**: Java 21 for massive concurrency
- **Persistent storage**: RocksDB backend for large graphs
- **Streaming**: Process millions of data points without memory issues
- **Distributed**: Cluster support via TinkerPop providers (Neo4j, JanusGraph, etc.)
## Development Tools
[](https://gitpod.io/#https://github.com/rossonet/waldot)
[](https://app.codacy.com/gh/rossonet/waldot/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
### CI/CD Status
[](https://github.com/rossonet/waldot/actions/workflows/test-branch-with-gradle.yml)
[](https://github.com/rossonet/waldot/actions/workflows/build-shadowjar-app.yml)
[](https://github.com/rossonet/waldot/actions/workflows/publish-to-docker-hub.yml)
[](https://github.com/rossonet/waldot/actions/workflows/publish-to-maven.yml)
## Contributing
We welcome contributions! Whether you're:
- Adding new plugins
- Improving documentation
- Reporting bugs
- Suggesting features
Please see [AGENT.md](AGENT.md) for development guidelines.
**Key contribution areas**:
- Additional storage connectors (Neo4j, JanusGraph, etc.)
- Rule engine extensions (SQL-like DSL, visual editor)
- Dashboard integrations (Grafana, real-time graph visualization)
- Protocol bridges (MQTT, Modbus, BACnet)
- AI/ML model integration
## References
- [Apache TinkerPop Documentation](https://tinkerpop.apache.org/docs/current/dev/provider/)
- [OPC UA Address Space Specification](https://reference.opcfoundation.org/Core/Part3/v104/docs/4)
- [Eclipse Milo GitHub](https://github.com/eclipse/milo)
- [Gremlin Query Language](https://tinkerpop.apache.org/docs/current/reference/#graph-traversal-steps)
## License
WaldOT is released under the **Apache License 2.0**.
See [LICENSE](LICENSE) file for details.
## Project Sponsor
[](https://www.rossonet.net)
---
**Ready to bridge your OT and IT worlds? Get started with WaldOT today!**