A comprehensive Redis database integration module for Inductive Automation's Ignition platform, providing seamless Redis connectivity across Gateway, Designer, and Client scopes.
- Multi-Scope Support: Full Redis functionality in Gateway, Designer, and Vision Client scopes
- Connection Management: Robust connection pooling with health monitoring and automatic retry logic
- Designer Tools: Redis Browser, CLI, and Profiler for development and debugging
- Expression Functions: Native Redis functions for use in property bindings and expression tags
- Scripting Functions: Complete
system.redis.*scripting API for all scopes - Web API: RESTful endpoints for external Redis operations
- Real-time Monitoring: Live connection status and metrics tracking
- Production Safety: Gateway comm mode protection prevents accidental cache modifications
- String Operations:
GET,SET,SET NX,DELETE,EXISTS,KEYSwith TTL support - Hash Operations:
HGET,HSET,HGETALL - Sorted Set Operations:
ZADD,ZREM,ZRANGEwith score management - Type Preservation: Automatic serialization with native type preservation (Integer, Double, Boolean, Lists, Maps)
- Batch Operations: Pipeline multiple operations for improved performance
- Key Management: Pattern matching and bulk operations
- Connection Pooling: Configurable Jedis connection pools with health checks
- Retry Logic: Exponential backoff retry with configurable limits
- Error Handling: Comprehensive error reporting with Python-compatible exceptions
- Security: Role-based access control integration
- Monitoring: Built-in connection health and performance metrics
- Ignition: Version 8.1.44 or higher
- Java: JDK 17+
- Redis: Version 3.0+ (tested with Redis 6.x and 7.x)
- Gradle: 8.7+ (included via wrapper)
# Clone the repository
git clone <repository-url>
cd redis-driver
# Build the module
./gradlew build
# The module file will be created at:
# build/distributions/Redis-Driver.modl# Clean build with tests
./gradlew clean build
# Build and deploy to local gateway (configure hostGateway in gradle.properties)
./gradlew deployModlredis-driver/
├── common/ # Shared interfaces and utilities
│ └── src/main/java/dev/bwdesigngroup/redis/common/
│ ├── api/ # RPC interfaces and DTOs
│ │ ├── BatchOperation.java # Batch operation data structure
│ │ └── RedisScriptInterface.java
│ ├── exception/ # Exception handling
│ │ ├── RedisException.java
│ │ └── RedisExceptionHandler.java
│ ├── scripting/ # Script module base classes
│ │ ├── AbstractRedisScriptModule.java
│ │ └── RedisRPCScriptModule.java
│ └── util/ # Utilities and constants
│ ├── RedisConstants.java
│ ├── RedisResultWrapper.java
│ └── RedisUtils.java
├── gateway/ # Gateway scope implementation
│ └── src/main/java/dev/bwdesigngroup/redis/gateway/
│ ├── connection/ # Connection management
│ │ ├── RedisConnectionConfig.java
│ │ ├── RedisConnectionManager.java
│ │ └── RedisConnector.java
│ ├── persistence/ # Database records
│ │ └── RedisConnectionRecord.java
│ ├── scripting/ # Script implementations
│ │ ├── RedisGatewayScriptModule.java
│ │ └── expressions/ # Expression functions
│ │ ├── RedisExpressionFunction.java
│ │ └── RedisExpressionProvider.java
│ ├── service/ # Business logic services
│ │ ├── RedisConnectionService.java
│ │ └── RedisOperationService.java
│ ├── web/ # REST API routes
│ │ ├── BaseRouteHandler.java
│ │ ├── RedisApiRoutes.java
│ │ ├── RedisConnectionRoutes.java
│ │ ├── RedisExtensionPage.java
│ │ └── RedisStatusRoutes.java
│ ├── RedisDriverGatewayHook.java
│ └── RedisExtensionPointType.java
├── designer/ # Designer scope implementation
│ └── src/main/java/dev/bwdesigngroup/redis/designer/
│ └── RedisDriverDesignerHook.java
├── client/ # Vision Client scope implementation
│ └── src/main/java/dev/bwdesigngroup/redis/client/
│ └── RedisDriverClientHook.java
├── docs/ # Module documentation
├── scripts/ # Build and deployment scripts
└── build.gradle.kts # Root build configuration
- Build or Download: Build the module from source or download a release
- Install Module: In the Ignition Gateway, go to Config → Modules → Install or Upgrade a Module
- Upload File: Select the
Redis-Driver.modlfile - Restart Gateway: The gateway will restart automatically to load the module
- Navigate to Config → Redis → Connections
- Click Create new Redis Connection...
- Configure connection settings:
- Connection Name: Unique identifier for the connection
- Enabled: Enable/disable the connection
- Host: Redis server hostname or IP address
- Port: Redis server port (default: 6379)
- Password: Redis AUTH password (optional)
- Database: Redis database number (default: 0)
- Max Pool Size: Maximum connections in pool (default: 8)
- Max Idle: Maximum idle connections (default: 8)
- Min Idle: Minimum idle connections (default: 0)
- Timeout: Connection timeout in milliseconds (default: 2000)
Connection Name: ProductionCache
Host: redis.company.com
Port: 6379
Password: ************
Database: 0
Max Pool Size: 20
Max Idle: 10
Min Idle: 2
Timeout: 5000
The module provides three powerful tools accessible from the Designer's Tools menu:
Access: Tools → Redis → Browser
A visual interface for exploring and managing Redis data:
- Key Explorer: Browse keys with pattern filtering and pagination
- Type Detection: Automatic detection and display of key types (string, hash, list, set, zset)
- TTL Display: View time-to-live for keys with expiration
- Value Editor: View and edit key values with type-specific editors
- Auto-refresh: Optional auto-refresh for monitoring live data
- Bulk Operations: Optimized for large datasets (10,000+ keys)
- Production Safety: Destructive operations blocked in read-only mode
Performance: Uses Redis pipelining to load thousands of keys instantly (single bulk RPC call vs. thousands of individual calls).
Access: Tools → Redis → CLI
An interactive command-line interface for Redis:
- Direct Commands: Execute any Redis command directly
- Command History: Navigate previous commands with up/down arrows
- Syntax Support: Full Redis command syntax including multi-word commands
- Response Display: Formatted responses with type information
- Production Safety: Destructive commands (SET, DEL, FLUSHDB, etc.) blocked in read-only mode
Example Commands:
GET user:123
SET cache:temp "value" EX 60
HGETALL config:database
ZADD leaderboard 100 "player1"
KEYS session:*
Access: Tools → Redis → Profiler
Performance monitoring and metrics:
- Connection Status: Live connection state for all configured connections
- Pool Metrics: Active/idle connection counts and utilization
- Health Monitoring: Last health check timestamps
- Error Tracking: Connection errors and retry attempts
- Diagnostics: Detailed connection information
All Designer tools respect the Gateway communication mode:
- Read-Write Mode: Full access to all operations
- Read-Only Mode: Blocks SET, DEL, HSET, ZADD, EXPIRE, FLUSHDB, and other destructive commands
- Disconnected Mode: All operations blocked
This prevents accidental modifications to production caches when developers are connected in read-only mode. The Designer toolbar shows the current comm mode.
Use Redis data directly in property bindings and expression tags:
// Get a string value
redisGet('ProductionCache', 'machine:line1:status')
// Check if key exists with conditional logic
if(redisExists('SessionStore', 'user:' + {Session.userId}),
'Logged In',
'Guest')
// Get typed values with automatic conversion
redisGetInt('Counters', 'production:total') + 1
redisGetDouble('Metrics', 'efficiency:line1') * 100
redisGetBoolean('Flags', 'maintenance:enabled')
// Hash operations
redisHGet('Configuration', 'database', 'host')
// Utility functions
redisKeyCount('Cache', 'session:*')
redisConnectionTest('ProductionCache')Access full Redis functionality in Gateway, Designer, and Client scripts:
# Import not needed - system.redis is automatically available
# String operations with native type support
system.redis.set('ProductionCache', 'machine:line1:temp', 75.2) # Stores as native Double
temperature = system.redis.get('ProductionCache', 'machine:line1:temp') # Returns 75.2 as Double
# Set with TTL options
system.redis.set('Cache', 'temp:data', 'value', ttlSeconds=300) # 5 minute TTL
system.redis.set('Cache', 'session', data, ttlMillis=3600000) # 1 hour TTL
system.redis.set('Cache', 'event', info, expirationDate=futureDate)
# Delete operations
system.redis.delete('ProductionCache', 'old:key')
deleted_count = system.redis.delete('Cache', 'key1', 'key2', 'key3') # Multiple keys
# Check existence
if system.redis.exists('SessionStore', 'user:12345'):
print("User session active")
# Pattern matching
session_keys = system.redis.keys('SessionStore', 'user:*')
print("Active sessions:", len(session_keys))# Set single field
system.redis.hset('Configuration', 'database', 'host', 'db.company.com')
# Set multiple fields at once
system.redis.hset('Configuration', 'database', {
'host': 'db.company.com',
'port': 5432,
'username': 'app_user',
'ssl': True
})
# Get hash values
db_host = system.redis.hget('Configuration', 'database', 'host')
db_config = system.redis.hgetAll('Configuration', 'database')
print("Database config:", db_config) # Returns dict with native types preserved# Native types are automatically preserved
system.redis.set('Counters', 'production:total', 12345) # Stored as Integer
count = system.redis.get('Counters', 'production:total') # Returns Integer 12345
system.redis.set('Metrics', 'efficiency', 85.7) # Stored as Double
efficiency = system.redis.get('Metrics', 'efficiency') # Returns Double 85.7
system.redis.set('Flags', 'maintenance', True) # Stored as Boolean
maintenance_mode = system.redis.get('Flags', 'maintenance') # Returns Boolean True
# Complex types (lists, dicts) are automatically serialized
machine_data = {
'id': 'LINE-001',
'status': 'running',
'temperature': 72.5,
'speed': 1200,
'errors': [],
'maintenance_due': False
}
system.redis.set('Machines', 'line1:data', machine_data)
retrieved_data = system.redis.get('Machines', 'line1:data') # Returns dict with types preserved# Create batch operations for pipeline execution
op1 = system.redis.createBatchOperation('op1', 'set').key('machine:1:status').value('running')
op2 = system.redis.createBatchOperation('op2', 'set').key('machine:1:temp').value(72.5)
op3 = system.redis.createBatchOperation('op3', 'get').key('machine:1:speed')
op4 = system.redis.createBatchOperation('op4', 'hget').key('config').field('timeout')
op5 = system.redis.createBatchOperation('op5', 'exists').key('machine:1:error')
# Execute batch
results = system.redis.batch('ProductionCache', [op1, op2, op3, op4, op5])
# Access results by operation ID
print("Speed:", results['op3']) # Retrieved value
print("Config timeout:", results['op4']) # Hash field value
print("Has error:", results['op5']) # Boolean exists result# List available connections
connections = system.redis.getConnectionNames()
print("Available Redis connections:", connections)
# Test connection health
if system.redis.testConnection('ProductionCache'):
print("Redis connection is healthy")
else:
print("Redis connection failed")
# Get TTL information
ttl = system.redis.getTTL('Cache', 'session:12345')
if ttl == -1:
print("Key has no expiration")
elif ttl == -2:
print("Key does not exist")
else:
print("Key expires in %d milliseconds" % ttl)# All operations throw Python-compatible exceptions
try:
value = system.redis.get('InvalidConnection', 'key')
except KeyError as e:
print("Connection not found:", e)
except ValueError as e:
print("Invalid parameter:", e)
except IOError as e:
print("Connection error:", e)
except RuntimeError as e:
print("Operation failed:", e)# Use batch operations for multiple related operations
operations = []
for i in range(100):
op = system.redis.createBatchOperation('op%s' % i, 'set')
op.key('sensor:%s:value' % i).value(readSensorValue(i))
operations.append(op)
# Single network round-trip for all operations
system.redis.batch('SensorCache', operations)
# vs multiple round-trips (slower)
for i in range(100):
system.redis.set('SensorCache', 'sensor:%s:value' % i, readSensorValue(i))The module provides REST endpoints for external integrations:
All API endpoints require appropriate Ignition Gateway permissions:
- Development Mode: Unrestricted access (set
redis.dev.mode=true) - Production Mode: Requires Config section permissions
# Set a value with optional TTL
POST /main/system/redis/api/set
Content-Type: application/json
{
"connection": "ProductionCache",
"key": "machine:1:status",
"value": "running",
"ttlSeconds": 300 # Optional
}
# Get a value (preserves original type)
GET /main/system/redis/api/get/ProductionCache/machine:1:status
# Delete a key
DELETE /main/system/redis/api/delete/ProductionCache/machine:1:status
# Check existence
GET /main/system/redis/api/exists/ProductionCache/machine:1:status
# Get keys with pattern
GET /main/system/redis/api/keys/ProductionCache?pattern=machine:*# Set hash field
POST /main/system/redis/api/hset
Content-Type: application/json
{
"connection": "ProductionCache",
"key": "machine:1",
"field": "status",
"value": "running"
}
# Get hash field
GET /main/system/redis/api/hget/ProductionCache/machine:1/status
# Get all hash fields
GET /main/system/redis/api/hgetall/ProductionCache/machine:1# Test connection
GET /main/system/redis/api/test/ProductionCache
# Get TTL for a key
GET /main/system/redis/api/ttl/ProductionCache/session:12345
# Get connection diagnostics
GET /main/system/redis/api/connections/ProductionCache/diagnostics
# List all connections with status
GET /main/system/redis/api/connectionsMonitor connection health in the Gateway web interface:
- Config → Redis → Connections: View all connections with status
- Status → System → Redis: Real-time connection monitoring via REST API
- Connected: ✅ Connection active and healthy
- Connecting: 🔄 Connection in progress
- Failed: ❌ Connection failed (with error details)
- Disabled: ⏸️ Connection disabled in configuration
- Disconnected: ⚪ Connection not established
Each connection displays:
- Active Connections: Currently in use
- Idle Connections: Available in pool
- Pool Utilization: Active+Idle/Max format
- Retry Attempts: Failed connection retry count
- Last Health Check: Timestamp of last verification
# Get detailed connection information
GET /main/system/redis/status/connections
# Response includes:
{
"count": 2,
"connections": [
{
"name": "ProductionCache",
"host": "redis.company.com",
"port": 6379,
"database": 0,
"enabled": true,
"connectionState": "CONNECTED",
"activeConnections": 3,
"idleConnections": 5,
"maxTotal": 20,
"retryAttempts": 0,
"lastHealthCheck": "2024-01-21T10:30:15Z"
}
]
}- Firewall Rules: Ensure Redis ports (default 6379) are properly secured
- VPN/Private Networks: Use secure networks for Redis communication
- SSL/TLS: Configure Redis with SSL for encrypted connections (requires Redis 6+)
- Redis AUTH: Always use password authentication in production
- Database Isolation: Use separate Redis databases for different applications
- Connection Limits: Configure appropriate pool sizes to prevent resource exhaustion
- Role-Based Access: API endpoints respect Ignition's role-based security
- Gateway Permissions: Requires Config section access for administrative operations
- Script Restrictions: Client/Designer operations use secure RPC to Gateway
Symptom: "Connection 'ProductionCache' not found or not available"
Solutions:
1. Verify connection exists in Gateway config
2. Check connection is enabled
3. Verify Redis server is running and accessible
4. Check network connectivity and firewall rules
5. Validate password if using AUTH
Symptom: "Could not get a resource from the pool"
Solutions:
1. Increase Max Pool Size in connection settings
2. Check for connection leaks in custom scripts
3. Monitor connection usage patterns
4. Consider connection timeout adjustments
Symptom: "Value 'xyz' at key 'abc' cannot be converted to Integer"
Solutions:
1. Verify the stored value type matches expected type
2. Use system.redis.get() for automatic type detection
3. Handle type conversion errors in scripts
4. Check data source for consistency
Enable detailed logging by setting system property:
-Dredis.dev.mode=trueThis enables:
- Unrestricted API access (development only)
- Detailed connection logging
- Enhanced error messages
Check Ignition Gateway logs for Redis-related entries:
Location: {ignition}/logs/wrapper.log
Filter: "Redis" or "dev.bwdesigngroup.redis"
# Run all tests
./gradlew test
# Run specific test class
./gradlew test --tests "*RedisConnectionManagerTest"
# Generate test reports
./gradlew test jacocoTestReport# Requires running Redis instance
export REDIS_HOST=localhost
export REDIS_PORT=6379
./gradlew integrationTest- Performance: Bulk key operations using Redis pipelining for Designer Redis Browser
- Performance: Reduced 2000+ RPC calls to single bulk operation when loading keys
- Security: Gateway communication mode protection for destructive operations
- Security: Prevents accidental production cache modifications in read-only mode
- UX: Sorted set operations (
zadd,zrem,zrange) with pipeline support - UX: SET NX (if-not-exists) support with
ifNotExistsparameter - Developer Tools: Redis Browser with type detection and TTL display
- Developer Tools: Redis CLI panel with command history
- Developer Tools: Redis Profiler for performance monitoring
- Logging: Reduced verbosity of routine operations (moved to debug level)
- Versioning: Automatic version detection from git tags
- Initial releases
- Multi-scope Redis connectivity (Gateway, Designer, Client)
- Expression and scripting functions with native type preservation
- REST API endpoints
- Connection pooling with automatic retry
- Batch operations support
- TTL/expiration support
- Comprehensive error handling with Python-compatible exceptions
- Hash operations (
hget,hset,hgetAll) - Key management with pattern matching
- Clone Repository:
git clone <repository-url> - Import IDE: Import as Gradle project in IntelliJ IDEA or Eclipse
- Configure Environment: Set up local Redis instance for testing
- Build Module: Run
./gradlew buildto verify setup
- Java: Follow Google Java Style Guide
- Package Structure: Maintain organized package hierarchy
- Documentation: Comprehensive JavaDoc for public APIs
- Testing: Minimum 80% code coverage for new features
- Logging: Use SLF4J with appropriate log levels
- Feature Branch: Create feature branch from
main - Implementation: Implement feature with tests
- Documentation: Update README and JavaDoc as needed
- Testing: Verify all tests pass
- Pull Request: Submit PR with detailed description
This project is licensed under the Apache License 2.0.
- Module Documentation: This README
- API Documentation: JavaDoc available in source code
- Ignition SDK: Inductive Automation SDK Documentation
- Redis Documentation: Redis Official Documentation
- Ignition Forums: Inductive Automation Forums
- Issue Tracking: Use GitHub Issues for bug reports and feature requests
For commercial support, training, or custom development:
- Email: support@bwdesigngroup.dev
- Website: bwdesigngroup.dev