This repository contains my implementation of the PhotoVoltaic (PV) simulator challenge. It contains two services:
- one that mocks a meter by sending random consumption values between 0 and 9000 W through a RabbiMQ broker,
- one that mocks a PV service by consuming messages from one meter, generating a random PV power value, adding the two, and writing the result in a file.
You can find the details of this challenge in the PV Simulator Challenge.pdf
file.
- A running RabbitMQ server
- please refer to the documentation to know how to install and run one
- Python 3.8 or later
- Pip package installer
- you can use any other package installer at your own risk
The repository contains two main scripts to launch the two services:
demo_meter.py
to run the meter service,demo_pv_service.py
to run the PV service.
In two different terminals, you will have to execute these scripts. You can add the -h
or --help
option to get more information regarding these scripts' usage.
Below, we detail a bit more about the procedure.
Before executing any script, you should run an instance of RabbitMQ as described in their documentation.
Warning: The current implementation does not support any credentials for the connection to the broker. Please be sure that the script will be able to connect to the broker with only its IP address (or hostname) and the port.
When the instance runs without any error, you can report the configuration in a .ini
file.
The configuration file should contain a broker
section as follows:
[broker]
host = <HOST_NAME or IP>
port = <PORT>
If not provided, the default values are localhost
for the host and 5672 for the port.
This implementation is based on only one external library: pika v.1.1.0, one client implementation of the RabbitMQ broker.
You can install it manually or using the requirements.txt
file: pip install -r requirements.txt
.
(If you look at the requirements.txt
file, you will see another dependency.
This dependency is only used in the test suite.)
You can start the meter service by executing the demo_meter.py
script.
It has three options:
-h
or--help
to print the usage,-conf
or--configuration-file
to define the broker configuration file's path. The default value isbroker.ini
,-nb
or--nb-meter
to define the number of meters to mock. Default value is 1. If the value is negative or 0, we silently choose the default value.
In the logs printed in the console, you will see the id of the meters created as follows (here for 3 meters):
INFO:root:Meter created: ['Meter_0', 'Meter_1', 'Meter_2']
.
RabbitMQ is configured with the default exchange.
We use the meter ids as routing keys.
The PV service needs to know the meter ids to start consuming the channel of the meter it is interested in.
The meter ids are on the form: Meter_<COUNT>
, with count starting at 0 and being increased at every meter creation.
You can stop the service at any time with Ctrl-C
.
Warning: RabbitMQ channels are destroyed when the script ends. If you stop it before executing the PV service, the PV service will not consume the messages.
You can start the PV service by executing the demo_pv_service.py
script.
It has two options:
-h
or--help
to print the usage,-conf
or--configuration-file
to define the broker configuration file's path. The default value isbroker.ini
,-ids
or--meter-ids
to define the channel to consume. It expects a space-separated list of IDs with at least one element.
The service will then instantiate as many PV services as meter ids: a PV service consumes messages of exactly one meter.
A CSV file will then be created for each meter with the following name: <METER_ID>-<YEAR>-<MONTH>-<DAY>.csv
.
If it already exists, the result of the PV service will be appended to the file.
Warning: if the file already exists, we do not check if the CSV headers correspond to the data we put.
The CSV file contains five columns:
meter_id
: the ID of the metertime_s
: EPOCH in seconds, timestamps at which the meter has read its valuemeter_power_value_w
: power value measured by the meter, in Wattpv_power_value_kw
: power value of the PV service, in kilo-Wattsum_meter_pv_w
: sum of the two power values in Watt
Disclaimer: we assume that the measurement of the meter and PV service are perfectly synchronous. It is why the final timestamp is the one of the meter. That is, of course, a simplification of a real case.
You can stop the service at any time with Ctrl-C
.
We use the unittest test engine for this project.
It only requires one additional library: parameterized v0.8.1.
You can install it manually or using the requirements.txt
file: pip install -r requirements.txt
.
To execute the test suite, simply run the following command from the root directory: python -m unittest
.
pv_simulator
: package that contains the whole implementation of the challengebroker.py
: module that implements the connection to the RabbitMQ brokermeter.py
: module that implements the mock of the meter serviceout.py
: module that handles the writing into a filepv_service.py
: module that implements the mock of the PV service
tests
: package that contains the test suite