Source code for lories.connectors.virtual

# -*- coding: utf-8 -*-
"""
lories.connectors.virtual
~~~~~~~~~~~~~~~~~~~~~~~~~


"""

from __future__ import annotations

import random
from typing import Optional

import pandas as pd
import pytz as tz
from lories.connectors import Connector, ConnectorError, register_connector_type
from lories.core.configs import ConfigurationError
from lories.typing import Channel, Resource, Resources, Timestamp


# noinspection PyShadowingBuiltins
[docs] @register_connector_type("virtual", "random", "dummy") class VirtualConnector(Connector): VIRTUAL: str = "virtual" RANDOM: str = "random" _data: pd.Series def connect(self, resources: Resources) -> None: super().connect(resources) index = [] data = [] for resource in resources: index.append(resource.id) generator = resource.get("generator", default=None) if generator == VirtualConnector.RANDOM: for attr in ["min", "max"]: if attr not in resource: raise ConfigurationError(f"Invalid dummy channel '{resource.id}', missing attribute: {attr}") data.append(float(random.randrange(int(resource.min * 100), int(resource.max * 100))) / 100.0) elif generator is not None: raise ConfigurationError(f"Invalid dummy channel '{resource.id}' generator: {generator}") else: data.append(resource.get("default", default=None)) self._data = pd.Series(index=index, data=data) def read( self, resources: Resources, start: Optional[Timestamp] = None, end: Optional[Timestamp] = None, ) -> pd.DataFrame: for resource in resources: generator = resource.get("generator", default=VirtualConnector.VIRTUAL) if generator == VirtualConnector.RANDOM: self._read_random(resource) elif generator != VirtualConnector.VIRTUAL: raise ConnectorError(self, f"Trying to read dummy channel '{resource.id}' with generator: {generator}") return self._data.to_frame(pd.Timestamp.now(tz.UTC).floor(freq="s")).T def _read_random(self, resource: Resource) -> None: range = int(abs(resource.max - resource.min)) value = float(random.randrange(-range * 100, range * 100)) / 1000.0 + self._data[resource.id] if value < resource.min: value = resource.min if value > resource.max: value = resource.max self._data[resource.id] = value def write(self, data: pd.DataFrame) -> None: for id in data.columns: if id in self.channels: channel = self.channels[id] generator = channel.get("generator", default=VirtualConnector.VIRTUAL) if generator == VirtualConnector.VIRTUAL: self._write_virtual(data, channel) elif generator == VirtualConnector.RANDOM: self._write_random(data, channel) else: raise ConnectorError( self, f"Trying to write to dummy channel '{channel.id}' with generator: {generator}" ) def _write_virtual(self, data: pd.DataFrame, channel: Channel) -> None: self._data[channel.id] = data.at[data.index[-1], channel.id] def _write_random(self, data: pd.DataFrame, channel: Channel) -> None: value = data.at[data.index[-1], channel.id] if value < channel.min: value = channel.min if value > channel.max: value = channel.max self._data[channel.id] = value