The simulator component is a Python-based application for generating anomalous data events for refrigerated shipping containers (also known as 'reefers'). This code is part of the Vaccine Cold Chain monitoring solution, and helps to control the test and the demonstration of the cold chain monitoring scenario or the anomaly detection use case.
This implementation illustrates the following technologies:
- Flask, with blueprint, flasgger.Swagger, prometheus metrics
- Kafka producer code using Confuent-python library
- Integration with Health for kubernetes deployment
- Sensor simulator using numpy, Pandas to generate tuples and simulated data
- Use of gnunicorn for serving the webapp in production
- Vuejs application connect to Server Side End point from another service
- Dynamic end point URL injection to the Vuejs via a REST end point (see
api/freezerURL.py) - Vuejs and gauge implemented with
- Docker-compose to run locally
- Use gitops and Kustomize for deployment. This is declared in a separate gitops repository under
appsfolder.
You can read more of the solution in this site.
The last updated detailed documentation of this component is under the Reefer Simulator IoT design chapter.
To build the local image use ./script/buildAll.sh which runs:
docker build -t ibmcase/vaccine-reefer-simulator .
docker push ibmcase/vaccine-reefer-simulatorThe build includes a user interface in Vuejs and the Flask app.
We have different modes to run the simulator locally depending of the target Kafka cluster.
The repository includes a sample docker-compose.yaml which you can use to run a single-node Kafka cluster on your local machine.
- To start Kafka locally, run
docker-compose up -d. This will start Kafka, Zookeeper, and the Reefer manager service, all connected via a Docker network on your machine, which you can find the name of by runningdocker network list.
We did not mount any folder to persist Kafka topics data, so each time you start this cluster you must create the telemetries topic with the command: ./scripts/createTopics.sh.
You can always validate the list of topics with the command: ./scripts/listTopics.sh
- For development purpose, you can start a docker image with a Python environment using the command:
./scripts/startPythonEnv.sh
# then in the container shell start the app
python app.pyAccess the OpenAPI doc at http://localhost:5000/apidocs.
- Use the following command to send 20 simulated temperatures
curl -X POST http://localhost:5000/control -d "{\"containerID\": \"C01\",\"nb_of_records\": 20,\"product_id\": \"P01\",\"simulation\": \"tempgrowth\"}"
The response is a string of tuples like:
[('C01', '2021-03-19 02:48:25', 'P01', -50.66101485, -50., 18.6447905, 3.65012681, 0, 1, 4, 21.75044215, 78.3859634, 40.7754046, 7.81047338, True, True, True, '37.8226902168957', '-122.324895', 0), ('C01', '2021-03-19 02:53:25', 'P01', -50.60219959, -50., 18.06471888, 2.27853715, 0, 1, 3, 21.38479556, 78.68539182, 40.37011913, 6.44987377, True, True, True, '37.8226902168957', '-122.324895', 0), ('C01', '2021-03-19 02:58:25', 'P01', -50.63849678, -50., 19.77104538, 2.79465754, 0, 1, 5, 19.55180659, 77.93256727, 41.7870542, 8.3963486, True, True, True, '37.8226902168957', '-122.324895', 0), ('C01', '2021-03-19 03:03:25', 'P01', -52.43289337, -50., 17.86306113, 1.80923096, 0, 1, 4, 18.95530879, 78.34202763, 39.11963127, 6.85136766, True, True, True, '37.8226902168957', '-122.324895', 0),...
Where the columns are:
[“container_id”, “measurement_time”, “product_id”,
“temperature”, “target_temperature”, “ambiant_temperature”,
“kilowatts”, “time_door_open”,
“content_type”, “defrost_cycle”,
“oxygen_level”, “nitrogen_level”, “humidity_level”, “carbon_dioxide_level”,
“fan_1”, “fan_2", “fan_3”, “latitude”, “longitude”, “maintenance_required”
- Verify the telemetries records are in the topic:
./scripts/verifyTelemetrieTopicContent.sh
The ui folder includes a Vuejs app which can be started by doing the following:
export VUE_APP_SERVER_URL=http://localhost:5000
# under ui folder
yarn serveThen point your web browser to http://localhost:4200/, you should get a list of existing containers and then once selecting one of them, you should see the simulator controller page:
See the demonstration script in this note.
It is possible to use the simulator as a standalone tool to create csv file. Here is an example on how to do that using python:
# Create normal records
python reefer_simulator_tool.py --stype norma --cid C01 --product_id covid-19 --records 1000 --file telemetries.csv
# Append errors on temperature (18% faulty records)
python reefer_simulator_tool.py --stype temperature --cid C01 --product_id covid-19 --records 700 --file telemetries.csv --append
# Append errors on co2sensor
python reefer_simulator_tool.py --stype co2sensor --cid C01 --product_id covid-19 --records 700 --file telemetries.csv --append
# append errors for o2sensor
python reefer_simulator_tool.py --stype o2sensor --cid C01 --product_id covid-19 --records 700 --file telemetries.csv --appendWe are using a separate gitops repository to manage the deploy of the application on OpenShift. See for example this lab to understand how the simulator is deployed.
Once deployed, you can access the Swagger-based REST API via the defined route and trigger the simulation controls.
- To determine the route, use the
oc get route vaccine-reefer-simulatorcommand and go to the URL specified in theHOST/PORTfield in your browser. - From there, drill down into the
POST /controlsection and click Try it out!. - Enter any of the following options for the fields pre-populated in the
controlbody:
- Container:
C01, C02, C03, C04 - Product:
P01, P02, P03, P04 - Simulation:
poweroff, temperature, tempgrowth, co2sensor, o2sensor, normal - Number of records: A positive integer
- Click Execute
- Verify the telemetries are created in the
telemetriestopic.
The test coverage for this project is not great yet.
cd ./scripts
./startPythonEnv.sh
root@1de81b16f940:/# python test/unit/TestSimulator.pyTo be able to run locally, you need a Kafka simple cluster. We have defined a docker compose for that, see previous section.
Use the web browser or a Postman to go to the URL: http://localhost:8080/control and do a POST. Here is an image of the open API UI:
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
We have improvement requests and bug reports via git issues in this project.

