Remove deprecated files and configurations, including .env, Dockerfile, docker-compose.yml, and client-schedule.py. Update README.md to reflect new architecture and features, enhancing clarity on system capabilities and workflows. Adjust values.yaml for image tag and replica count, and improve code documentation across various modules for better maintainability.
118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
import random
|
|
from datetime import datetime, timezone
|
|
from typing import Any
|
|
import json
|
|
from kafka import KafkaProducer
|
|
from temporalio import activity
|
|
|
|
from sientia_do.notifications.handlers import CoreNotificationHandler as NotificationHandler
|
|
from sientia_do.temporal.activities.base import BaseActivity
|
|
from sientia_do.observability.logger import Logger
|
|
|
|
|
|
class Faker(BaseActivity):
|
|
"""
|
|
Synthetic data generation for testing and development.
|
|
|
|
This class generates realistic industrial sensor data for testing purposes.
|
|
It provides:
|
|
- Configurable sensor tag simulation
|
|
- Realistic data value generation
|
|
- Kafka integration for data publishing
|
|
- Comprehensive error handling and logging
|
|
|
|
The class is designed for development, testing, and demonstration of
|
|
data processing pipelines without requiring real industrial data sources.
|
|
"""
|
|
|
|
def __init__(self, bootstrap_servers: str, logger: Logger,
|
|
notification_handler: NotificationHandler):
|
|
"""
|
|
Initialize the Faker class with Kafka producer and sensor configuration.
|
|
|
|
Args:
|
|
bootstrap_servers (str): Kafka bootstrap servers configuration
|
|
logger (Logger): Logger instance for operation logging
|
|
notification_handler (NotificationHandler): Handler for system notifications
|
|
"""
|
|
self.producer = KafkaProducer(
|
|
bootstrap_servers=bootstrap_servers,
|
|
value_serializer=lambda v: json.dumps(v).encode('utf-8')
|
|
)
|
|
|
|
# Predefined lists for tag and name
|
|
self.tags = {
|
|
'ns=1;i=1001': 'Temperature Sensor',
|
|
'ns=1;i=1002': 'Vibration Meter',
|
|
'ns=1;i=1003': 'Pressure Gauge',
|
|
'ns=1;i=1004': 'Flow Meter',
|
|
'ns=1;i=1005': 'Voltage Sensor',
|
|
'ns=1;i=1006': 'Current Sensor'
|
|
}
|
|
|
|
BaseActivity.__init__(self, logger, notification_handler)
|
|
|
|
@activity.defn(name="generate_and_send_data")
|
|
async def generate_and_send_data(self, input_data: dict[str, Any]) -> None:
|
|
"""
|
|
Generate synthetic sensor data and publish to Kafka topic.
|
|
|
|
This activity creates realistic industrial sensor readings and publishes
|
|
them to the specified Kafka topic. The data includes sensor tags, names,
|
|
timestamps, and values with configurable message counts.
|
|
|
|
Args:
|
|
input_data (dict[str, Any]): Activity input parameters.
|
|
Required fields:
|
|
- topic (str): Kafka topic name for data publication
|
|
- metadata (dict[str, Any], optional): Workflow execution metadata
|
|
- num_messages (int, optional): Number of messages to generate.
|
|
Defaults to random count between 1 and available sensor tags
|
|
|
|
Returns:
|
|
None: This activity publishes data but doesn't return results
|
|
|
|
Raises:
|
|
ValueError: If topic is not specified
|
|
Exception: If data generation or Kafka publishing fails
|
|
"""
|
|
metadata = input_data['metadata']
|
|
topic = input_data.get('topic')
|
|
num_messages = input_data.get(
|
|
'num_messages', random.randint(1, len(self.tags))) # NOSONAR
|
|
|
|
if not topic:
|
|
raise ValueError("Topic must be specified in input_data")
|
|
|
|
self.info(
|
|
f"Generating {num_messages} messages for topic {topic}",
|
|
metadata=metadata
|
|
)
|
|
|
|
for _ in range(num_messages):
|
|
# Select random tag and name
|
|
tag = random.choice(list(self.tags.keys())) # NOSONAR
|
|
name = self.tags[tag]
|
|
|
|
# Generate random value between 0 and 100
|
|
if random.random() < 0.1: # NOSONAR
|
|
value = None
|
|
else:
|
|
value = round(random.uniform(0, 100), 2)
|
|
|
|
# Create data dictionary
|
|
data = {
|
|
'tag': tag,
|
|
'name': name,
|
|
'timestamp': datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S'),
|
|
'value': value
|
|
}
|
|
|
|
# Send to Kafka
|
|
self.producer.send(topic, value=data)
|
|
|
|
# Ensure all messages are sent
|
|
self.producer.flush()
|
|
|
|
self.info("Success", metadata=metadata)
|