# OCPP2 Mock Server
This project includes an Open Charge Point Protocol (OCPP) version 2.0.1 mock server implemented in Python.
-https://github.com/mobilityhouse/ocpp/blob/master/ocpp/v201/enums.py
## Prerequisites
This project requires Python 3.7+ and [poetry](https://python-poetry.org/) to install the required packages:
-```shell
-pip install poetry
-```
-
-then
-
```shell
poetry install
```
poetry run task server
```
-or
+The server will start listening for connections on port 9000.
+
+## Running the server with command sending
+
+You can also specify a command and a period duration with the --request and --period options respectively when running the server. The server will then send your chosen command to the connected client every period seconds.
+
+### GetBaseReport Command
+
+To run the server and send a GetBaseReport command every 5 seconds, use:
```shell
poetry run task server --request GetBaseReport --period 5
```
-The server will start listening for connections on port 9000.
+=======
+
+### ClearCache Command
+
+To run the server and send a ClearCache command every 5 seconds, use:
+
+```shell
+poetry run task server --request ClearCache --period 5
+```
+
+Please be mindful that these commands were examples according to the provided scenario, the available commands and their syntax might vary depending on the ocpp version and the implemented functionalities on your server.
## Overview of the Server Scripts
return ocpp.v201.call_result.MeterValues()
@on(Action.GetBaseReport)
- async def on_get_base_report(
- self, request_id: int, report_base: ReportBaseType, **kwargs
- ):
- logging.info("Received GetBaseReport")
+ async def on_get_base_report(self, request_id: int, report_base: ReportBaseType, **kwargs):
+ logging.info("Received %s", Action.GetBaseReport)
return ocpp.v201.call_result.GetBaseReport(status="Accepted")
# Request handlers to emit OCPP messages.
# If period is not None, send command repeatedly with period interval
if period:
- while True:
- if command_name == "GetBaseReport":
- logging.info("GetBaseReport parser working")
- await cp.send_get_base_report()
+ async def send_command_repeatedly():
+ while True:
+ command_name = await charge_point.receive_command()
+ try:
+ match command_name:
+ case 'ClearCache':
+ logging.info("ClearCache parser working")
+ await charge_point.send_clear_cache()
+ case 'GetBaseReport':
+ logging.info("GetBaseReport parser working")
+ await charge_point.send_get_base_report()
+ case _:
+ logging.warning(f"Unsupported command {command_name}")
+ except Exception as e:
+ logging.exception(f"Failure while processing command {command_name}")
+ finally:
+ await asyncio.sleep(period)
+
+ timer = RepeatTimer(period, send_command_repeatedly)
+ await timer.start()
+ await timer.wait_closed() # Wait for timer to finish before exiting
- await asyncio.sleep(period)
else:
if command_name == "GetBaseReport":
await cp.send_get_base_report()
charge_point_id = path.strip("/")
cp = ChargePoint(charge_point_id, websocket)
- # Check if request argument is specified
- if args.request:
- asyncio.create_task(
- send_ocpp_command(cp, args.request, args.delay, args.period)
- )
-
- # Start the ChargePoint instance to listen for incoming messages.
- await cp.start()
-
ChargePoints.add(cp)
try:
await cp.start()
+ # Check if request argument is specified
+ if args.request:
+ asyncio.create_task(send_ocpp_command(cp, args.request, args.delay, args.period))
+
except ConnectionClosed:
logging.info("ChargePoint %s closed connection", cp.id)
ChargePoints.remove(cp)