juham.simulation

Description

This package contains general purpose simulation classes for testing automation scenarios in an environments where actual sensor data cannot be accessed.

class juham.simulation.EnergyMeterSimulator(name='em', interval=0)[source]

Bases: RThread

Simulator energy meter sensor. Spawns a thread to simulate Shelly PM mqtt messages

classmethod app_name(name)

Set application name

Parameters:

name (str) – application name

classmethod classattrs_from_dict(attributes)

Set class attributes from a dictionary.

classmethod classattrs_to_dict()

Convert class attributes to a dictionary.

classmethod configure_args(args)

Register startup arguments to be parsed.

Parameters:

parser (argparse.ArgumentParser) – parser to add the startup arguments.

Return type:

None

copy()

Create and return a copy of the current object.

This method serializes the current object to a dictionary using the to_dict method, creates a new instance of the object’s class, and populates it with the serialized data using the from_dict method.

This method uses class identifier based instantiation (see factory method pattern) to create a new instance of the object, and ‘to_dict’ and ‘from_dict’ methods to initialize object’s state.

Return type:

MasterPiece

Returns:

A new instance of the object’s class with the same state as the original object.

Example:

clone_of_john = john.copy()
database_class_id: str = 'JInflux'
database_client: Optional[JDatabase | None]
debug(msg, details='')

Logs the given debug message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

deserialize_from_json(f)

Load attributes from the given JSON file.

disconnect()

Request the asynchronous acquisition thread to stop after it has finished its current job. This method does not wait for the thread to stop. See shutdown().

elapsed_seconds_in_day(ts_utc)

Fetch the elapsed seconds since the be given time stamp ‘ts_utc’.

Returns:

elapsed second today

Return type:

float

elapsed_seconds_in_hour(ts_utc)

Given timestamp in UTC, Compute elapsed seconds within an hour

Parameters:

ts (float) – seconds since UTC epoch

Returns:

_description_

Return type:

float

epoc2utc(epoch)

Converts the given epoch time to UTC time string. All time coordinates are represented in UTC time. This allows the time coordinate to be mapped to any local time representation without ambiguity.

Parameters:
  • epoch (float) – timestamp in UTC time

  • rc (str) – time string describing date, time and time zone e.g 2024-07-08T12:10:22Z

Returns:

UTC time

error(msg, details='')

Logs the given error message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

event_topic = 'juham/event'
classmethod find_class(class_id)

Given class identifier find the registered class. If no class with the give identifier exists return None.

Parameters:

class_id (int) – class identifier

Returns:

class or null if not registered

Return type:

obj (obj)

from_dict(data)[source]

Update instance attributes from a dictionary.

classmethod get_app_name()

Get application name

Returns:

application name

Return type:

name (str)

classmethod get_class_id()

Return the class id of the class. Each class has an unique identifier that can be used for instantiating the class via Object.instantiate() method.

Parameters:

cls (class) – class

Return type:

str

Returns:

id (int) unique class identifier through which the class can be instantiated by factory method pattern.

classmethod get_json_file()

Generate the JSON file name based on the class name.

The file is created into users home folder.

classmethod get_registered_classes()

Get the dictionary holding the registered class identifiers and the corresponding classes.

Returns:

dictionary of class identifier - class pairs

Return type:

dict

classmethod has_class_method_directly(method_name)

Check if the method is in the class’s own dictionary

Return type:

bool

info(msg, details='')

Logs the given information message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

Example:

obj = new Base('test')
obj.info('Message arrived', str(msg))
init_database(name)

Instantiates the configured time series database object.

Issues a warning if the database_class_id has not been configured, in which case the object will not have the time series recording feature.

This method is called internally and typically there is no need to call it from the application code.

Return type:

None

init_mqtt(name)

Instantiates the configured MQTT object for networking.

This method is called internally and typically there is no need to call it from the application code.

Issues a warning if the pubsub_class_id has not been configured, even though objects without a capability to communicate are rather crippled.

Return type:

None

initialize()

Initialize time series database and mqtt networking for use. This method must be called after the object name has been set .

Return type:

None

classmethod initialize_class(load_class_attrs=True)

Initialize the class for instantiation. Initializes the class identifier. Initialize public class attributes from the class-specific configuration files, unless disabled with the load_class_attrs parameter. Call the register() method of the class to let each class do custom initializations. Set up atexit callback to generate class-specific initialization files if they don’t exist already.

Parameters:

load_class_attrs (bool, optional) – If true, then attempts to initialize class attributes from the class-specific configuration files. Defaults to True.

Returns:

Returns true if the class was initialized. False implies the class is already initialized, in which case the method call has no effect.

Return type:

bool

classmethod instantiate(class_id)

Create an instance of the class corresponding to the given class identifier. This method implements the factory method pattern, which is essential for a plugin architecture.

Parameters:

class_id (int) – Identifier of the class to instantiate.

Returns:

An instance of the class corresponding to the given class identifier.

Return type:

obj

classmethod instantiate_with_param(class_id, param)

Given class identifier and one constructor argument create the corresponding object.

Parameters:
  • class_id (str) – class identifier

  • param (Any) – class specific constructor parameter

Returns:

instance of the given class.

Return type:

obj

classmethod is_abstract()

Check whether the class is abstract or real. Override in the derived sub-classes. The default is False.

Return type:

bool

Returns:

True (bool) if abstract

is_time_between(begin_time, end_time, check_time=None)

Check if the given time is within the given time line. All timestamps must be in UTC time.

Parameters:
  • begin_time (timestamp) – beginning of the timeline

  • end_time (timestamp) – end of the timeline

  • check_time (timestamp) – time to be checked

Returns:

True if within the timeline

Return type:

rc (bool)

classmethod load_from_json()

Load class attributes from a JSON file.

log_message(type, msg, details='')

Publish the given log message to the MQTT ‘log’ topic.

This method constructs a log message with a timestamp, class type, source name, message, and optional details. It then publishes this message to the ‘log’ topic using the MQTT protocol.

Parameters:
  • type (str) – str The classification or type of the log message (e.g., ‘Error’, ‘Info’).

  • msg – str The main log message to be published.

  • details – str, optional Additional details about the log message (default is an empty string).

Return type:

None

Returns:

None

Raises:

Exception – If there is an issue with the MQTT client while publishing the message.

Example:

# publish info message to the Juham's 'log' topic
self.log_message("Info", f"Some cool message {some_stuff}", str(dict))
mqtt_class_id: str = 'JPaho2'
mqtt_client: Optional[JMqtt | None]
mqtt_host: str = 'localhost'
mqtt_port: int = 1883
mqtt_root_topic: str = 'juham'
on_connect(client, userdata, flags, rc)

Notification on connect.

This method is called whenever the MQTT broker is connected. For more information on this method consult MQTT documentation available in many public sources.

Parameters:
  • client (obj) – MQTT client

  • userdata (Any) – application specific data

  • flags (int) – Consult MQTT

  • rc (int) – See MQTT docs

Return type:

None

on_disconnect(client, userdata, rc=0)

Notification on disconnect.

This method is called whenever the MQTT broker is disconnected. For more information on this method consult MQTT documentation available in many public sources.

Parameters:
  • client (obj) – MQTT client

  • userdata (Any) – application specific data

  • rc (int) – See MQTT docs

Return type:

None

on_event(em)

Notification event callback e.g info or warning.

Parameters:

em (dictionary) – dictionary describing the event

Return type:

None

on_message(client, userdata, msg)[source]

The standared MQTT callback for arriving messages.

Parameters:
  • client (object) – mqtt client

  • userdata (Any) – any user specific data

  • msg (object) – MQTT message

on_sensor(em)[source]

Handle data coming from the energy meter.

Simply log the event to indicate the presense of simulated device. :type em: dict :param em: data from the sensor :type em: dict

Return type:

None

classmethod parse_args()

Parse registered startup arguments.

Parameters:

parser (argparse.ArgumentParser) – parser to add the startup arguments.

Return type:

None

classmethod parse_initial_args()

Parse application name and configuration name arguments. Note that argument parsing is two stage process. This method must be called at very early on to know where to load class initialization files. See register_args() method.

power: float = 1000.0
power_topic = 'juham/powerconsumption'
print(prefix='', is_last=True)

Print the name of the object, decorated with prefix consisting of ├─, └─, and │.

publish(topic, msg, qos=1, retain=True)

Publish the given message to the given MQTT topic. For more information consult MQTT.

Parameters:
  • topic (str) – topic

  • msg (str) – message to be published

  • qos (int, optional) – quality of service. Defaults to 1.

  • retain (bool, optional) – retain. Defaults to True.

quantize(quanta, value)

Quantize the given value.

Parameters:
  • quanta (float) – resolution for quantization

  • value (float) – value to be quantized

Returns:

quantized value

Return type:

(float)

Example:

hour_of_a_day = self.quantize(3600, epoch_seconds)
read(point)

Reads the given measurement from the database.

Parameters:

point – point with initialized time stamp.

Return type:

None

… note: NOT IMPLEMENTED YET

classmethod register()

Register the class.

Called immediately upon class initialization, right before the class attributes are loaded from the class specific configuration files.

Subclasses can extend this with custom register functionality:

class MyMasterPiece(MasterPiece):

    @classmethod
    def register(cls):
        super().register()  # Don't forget
        cls._custom_field = True
Return type:

None

classmethod register_args(parser)

Register startup arguments to be parsed.

Parameters:

parser (argparse.ArgumentParser) – parser to add the startup arguments.

Return type:

None

classmethod register_class(class_id, ctor)

Register the given class identifier for identifier based instantiation . This, factory method pattern, as it is called, decouples the actual implementation from the interface. For more information see instantiate() method.

Parameters:
  • class_id (str) – class identifier

  • ctor (function) – constructor

run()[source]

Initialize and start the asynchronous acquisition thread.

run_forever()

Starts the network loop and blocks the main thread, continuously running the loop to process MQTT messages.

The loop will run indefinitely unless the connection is lost or the program is terminated.

Return type:

None

classmethod save_to_json()

Create class configuration file, if the file does not exist yet.

serialize_to_json(f)

Serialize the object to given JSON file

classmethod set_log(l)

Set logger.

Parameters:

l (logger) – logger object

Return type:

None

shutdown()

Request the acquisition thread to stop, and wait for the thread to stop, then return.

subscribe(topic)

Subscribe to the given MQTT topic.

This method sets up the subscription to the specified MQTT topic and registers the on_message() method as the callback for incoming messages.

Parameters:

topic (str) – The MQTT topic to subscribe to.

Return type:

None

Example:

# configure
obj.subscribe('foo/bar')
timestamp()

Returns the current date-time in UTC.

Returns:

datetime in UTC.

Return type:

rc (datetime)

timestamp_hour(ts)

Returns the hour in 24h format in UTC.

Parameters:

ts (float) – timestamp

Returns:

current hour in UTC 0 …23

Return type:

rc (int)

timestampstr(ts)

Converts the given timestamp to human readable string of format ‘Y-m-d H:M:S’.

Parameters:

ts (timestamp) – time stamp to be converted

Returns:

human readable date-time string

Return type:

rc (string)

to_dict()[source]

Convert instance attributes to a dictionary.

update_interval: float = 10
warning(msg, details='')

Logs the given warning message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

workerThreadId = 'EnergyMeterSimulatorThread'
write(point)

Writes the given measurement to the database. In case of an error, it tries again until the maximum number of attempts is reached. If it is still unsuccessful, it gives up and passes the first encountered exception to the caller.

Parameters:

point – a measurement describing a time stamp and related attributes for one measurement.

Return type:

None

write_attempts = 3
class juham.simulation.RTracker(name='rtracker')[source]

Bases: RThread

A tracker automation object. Spawns async thread to generate geographic coordinates at specific rate, and writes them to time series database.

Parameters:

RThread (class) – super class

classmethod app_name(name)

Set application name

Parameters:

name (str) – application name

classmethod classattrs_from_dict(attributes)

Set class attributes from a dictionary.

classmethod classattrs_to_dict()

Convert class attributes to a dictionary.

classmethod configure_args(args)

Register startup arguments to be parsed.

Parameters:

parser (argparse.ArgumentParser) – parser to add the startup arguments.

Return type:

None

copy()

Create and return a copy of the current object.

This method serializes the current object to a dictionary using the to_dict method, creates a new instance of the object’s class, and populates it with the serialized data using the from_dict method.

This method uses class identifier based instantiation (see factory method pattern) to create a new instance of the object, and ‘to_dict’ and ‘from_dict’ methods to initialize object’s state.

Return type:

MasterPiece

Returns:

A new instance of the object’s class with the same state as the original object.

Example:

clone_of_john = john.copy()
database_class_id: str = 'JInflux'
database_client: Optional[JDatabase | None]
debug(msg, details='')

Logs the given debug message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

deserialize_from_json(f)

Load attributes from the given JSON file.

disconnect()

Request the asynchronous acquisition thread to stop after it has finished its current job. This method does not wait for the thread to stop. See shutdown().

elapsed_seconds_in_day(ts_utc)

Fetch the elapsed seconds since the be given time stamp ‘ts_utc’.

Returns:

elapsed second today

Return type:

float

elapsed_seconds_in_hour(ts_utc)

Given timestamp in UTC, Compute elapsed seconds within an hour

Parameters:

ts (float) – seconds since UTC epoch

Returns:

_description_

Return type:

float

epoc2utc(epoch)

Converts the given epoch time to UTC time string. All time coordinates are represented in UTC time. This allows the time coordinate to be mapped to any local time representation without ambiguity.

Parameters:
  • epoch (float) – timestamp in UTC time

  • rc (str) – time string describing date, time and time zone e.g 2024-07-08T12:10:22Z

Returns:

UTC time

error(msg, details='')

Logs the given error message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

event_topic = 'juham/event'
classmethod find_class(class_id)

Given class identifier find the registered class. If no class with the give identifier exists return None.

Parameters:

class_id (int) – class identifier

Returns:

class or null if not registered

Return type:

obj (obj)

from_dict(data)

Update instance attributes from a dictionary.

classmethod get_app_name()

Get application name

Returns:

application name

Return type:

name (str)

classmethod get_class_id()

Return the class id of the class. Each class has an unique identifier that can be used for instantiating the class via Object.instantiate() method.

Parameters:

cls (class) – class

Return type:

str

Returns:

id (int) unique class identifier through which the class can be instantiated by factory method pattern.

classmethod get_json_file()

Generate the JSON file name based on the class name.

The file is created into users home folder.

classmethod get_registered_classes()

Get the dictionary holding the registered class identifiers and the corresponding classes.

Returns:

dictionary of class identifier - class pairs

Return type:

dict

classmethod has_class_method_directly(method_name)

Check if the method is in the class’s own dictionary

Return type:

bool

info(msg, details='')

Logs the given information message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

Example:

obj = new Base('test')
obj.info('Message arrived', str(msg))
init_database(name)

Instantiates the configured time series database object.

Issues a warning if the database_class_id has not been configured, in which case the object will not have the time series recording feature.

This method is called internally and typically there is no need to call it from the application code.

Return type:

None

init_mqtt(name)

Instantiates the configured MQTT object for networking.

This method is called internally and typically there is no need to call it from the application code.

Issues a warning if the pubsub_class_id has not been configured, even though objects without a capability to communicate are rather crippled.

Return type:

None

initialize()

Initialize time series database and mqtt networking for use. This method must be called after the object name has been set .

Return type:

None

classmethod initialize_class(load_class_attrs=True)

Initialize the class for instantiation. Initializes the class identifier. Initialize public class attributes from the class-specific configuration files, unless disabled with the load_class_attrs parameter. Call the register() method of the class to let each class do custom initializations. Set up atexit callback to generate class-specific initialization files if they don’t exist already.

Parameters:

load_class_attrs (bool, optional) – If true, then attempts to initialize class attributes from the class-specific configuration files. Defaults to True.

Returns:

Returns true if the class was initialized. False implies the class is already initialized, in which case the method call has no effect.

Return type:

bool

classmethod instantiate(class_id)

Create an instance of the class corresponding to the given class identifier. This method implements the factory method pattern, which is essential for a plugin architecture.

Parameters:

class_id (int) – Identifier of the class to instantiate.

Returns:

An instance of the class corresponding to the given class identifier.

Return type:

obj

classmethod instantiate_with_param(class_id, param)

Given class identifier and one constructor argument create the corresponding object.

Parameters:
  • class_id (str) – class identifier

  • param (Any) – class specific constructor parameter

Returns:

instance of the given class.

Return type:

obj

classmethod is_abstract()

Check whether the class is abstract or real. Override in the derived sub-classes. The default is False.

Return type:

bool

Returns:

True (bool) if abstract

is_time_between(begin_time, end_time, check_time=None)

Check if the given time is within the given time line. All timestamps must be in UTC time.

Parameters:
  • begin_time (timestamp) – beginning of the timeline

  • end_time (timestamp) – end of the timeline

  • check_time (timestamp) – time to be checked

Returns:

True if within the timeline

Return type:

rc (bool)

lat = 60.968117
classmethod load_from_json()

Load class attributes from a JSON file.

log_message(type, msg, details='')

Publish the given log message to the MQTT ‘log’ topic.

This method constructs a log message with a timestamp, class type, source name, message, and optional details. It then publishes this message to the ‘log’ topic using the MQTT protocol.

Parameters:
  • type (str) – str The classification or type of the log message (e.g., ‘Error’, ‘Info’).

  • msg – str The main log message to be published.

  • details – str, optional Additional details about the log message (default is an empty string).

Return type:

None

Returns:

None

Raises:

Exception – If there is an issue with the MQTT client while publishing the message.

Example:

# publish info message to the Juham's 'log' topic
self.log_message("Info", f"Some cool message {some_stuff}", str(dict))
lon = 25.636786
mqtt_class_id: str = 'JPaho2'
mqtt_client: Optional[JMqtt | None]
mqtt_host: str = 'localhost'
mqtt_port: int = 1883
mqtt_root_topic: str = 'juham'
on_connect(client, userdata, flags, rc)[source]

Notification on connect.

This method is called whenever the MQTT broker is connected. For more information on this method consult MQTT documentation available in many public sources.

Parameters:
  • client (obj) – MQTT client

  • userdata (Any) – application specific data

  • flags (int) – Consult MQTT

  • rc (int) – See MQTT docs

on_disconnect(client, userdata, rc=0)

Notification on disconnect.

This method is called whenever the MQTT broker is disconnected. For more information on this method consult MQTT documentation available in many public sources.

Parameters:
  • client (obj) – MQTT client

  • userdata (Any) – application specific data

  • rc (int) – See MQTT docs

Return type:

None

on_event(em)

Notification event callback e.g info or warning.

Parameters:

em (dictionary) – dictionary describing the event

Return type:

None

on_message(client, userdata, msg)[source]

The standared MQTT callback for arriving messages.

Parameters:
  • client (object) – mqtt client

  • userdata (Any) – any user specific data

  • msg (object) – MQTT message

on_sensor(msg)[source]
classmethod parse_args()

Parse registered startup arguments.

Parameters:

parser (argparse.ArgumentParser) – parser to add the startup arguments.

Return type:

None

classmethod parse_initial_args()

Parse application name and configuration name arguments. Note that argument parsing is two stage process. This method must be called at very early on to know where to load class initialization files. See register_args() method.

print(prefix='', is_last=True)

Print the name of the object, decorated with prefix consisting of ├─, └─, and │.

publish(topic, msg, qos=1, retain=True)

Publish the given message to the given MQTT topic. For more information consult MQTT.

Parameters:
  • topic (str) – topic

  • msg (str) – message to be published

  • qos (int, optional) – quality of service. Defaults to 1.

  • retain (bool, optional) – retain. Defaults to True.

quantize(quanta, value)

Quantize the given value.

Parameters:
  • quanta (float) – resolution for quantization

  • value (float) – value to be quantized

Returns:

quantized value

Return type:

(float)

Example:

hour_of_a_day = self.quantize(3600, epoch_seconds)
rad = 3
read(point)

Reads the given measurement from the database.

Parameters:

point – point with initialized time stamp.

Return type:

None

… note: NOT IMPLEMENTED YET

classmethod register()

Register the class.

Called immediately upon class initialization, right before the class attributes are loaded from the class specific configuration files.

Subclasses can extend this with custom register functionality:

class MyMasterPiece(MasterPiece):

    @classmethod
    def register(cls):
        super().register()  # Don't forget
        cls._custom_field = True
Return type:

None

classmethod register_args(parser)

Register startup arguments to be parsed.

Parameters:

parser (argparse.ArgumentParser) – parser to add the startup arguments.

Return type:

None

classmethod register_class(class_id, ctor)

Register the given class identifier for identifier based instantiation . This, factory method pattern, as it is called, decouples the actual implementation from the interface. For more information see instantiate() method.

Parameters:
  • class_id (str) – class identifier

  • ctor (function) – constructor

run()[source]

Initialize and start the asynchronous acquisition thread.

run_forever()

Starts the network loop and blocks the main thread, continuously running the loop to process MQTT messages.

The loop will run indefinitely unless the connection is lost or the program is terminated.

Return type:

None

classmethod save_to_json()

Create class configuration file, if the file does not exist yet.

serialize_to_json(f)

Serialize the object to given JSON file

classmethod set_log(l)

Set logger.

Parameters:

l (logger) – logger object

Return type:

None

shutdown()

Request the acquisition thread to stop, and wait for the thread to stop, then return.

subscribe(topic)

Subscribe to the given MQTT topic.

This method sets up the subscription to the specified MQTT topic and registers the on_message() method as the callback for incoming messages.

Parameters:

topic (str) – The MQTT topic to subscribe to.

Return type:

None

Example:

# configure
obj.subscribe('foo/bar')
timestamp()

Returns the current date-time in UTC.

Returns:

datetime in UTC.

Return type:

rc (datetime)

timestamp_hour(ts)

Returns the hour in 24h format in UTC.

Parameters:

ts (float) – timestamp

Returns:

current hour in UTC 0 …23

Return type:

rc (int)

timestampstr(ts)

Converts the given timestamp to human readable string of format ‘Y-m-d H:M:S’.

Parameters:

ts (timestamp) – time stamp to be converted

Returns:

human readable date-time string

Return type:

rc (string)

to_dict()

Convert instance attributes to a dictionary.

topic = 'juham/tracks'
update_interval = 60
warning(msg, details='')

Logs the given warning message to the database after logging it using the BaseClass’s info() method.

Parameters:
  • msg (str) – The information message to be logged.

  • details (str) – Additional detailed information for the message to be logged

Return type:

None

workerThreadId = 'RTrackerThread'
write(point)

Writes the given measurement to the database. In case of an error, it tries again until the maximum number of attempts is reached. If it is still unsuccessful, it gives up and passes the first encountered exception to the caller.

Parameters:

point – a measurement describing a time stamp and related attributes for one measurement.

Return type:

None

write_attempts = 3