+<!-- markdownlint-disable-file MD033 MD024 -->
+
# [e-mobility charging stations simulator](https://github.com/sap/e-mobility-charging-stations-simulator)
[![REUSE status](https://api.reuse.software/badge/github.com/SAP/e-mobility-charging-stations-simulator)](https://api.reuse.software/info/github.com/SAP/e-mobility-charging-stations-simulator)
## Summary
-Simple [node.js](https://nodejs.org/) software to simulate a set of charging stations based on the OCPP-J 1.6 protocol as part of SAP e-Mobility solution.
+Simple [node.js](https://nodejs.org/) software to simulate and scale a set of charging stations based on the OCPP-J 1.6 protocol as part of SAP e-Mobility solution.
## Prerequisites
brew install node@16
```
-### GNU/Linux:
+### GNU/Linux
- [NodeSource](https://github.com/nodesource/distributions) Node.js Binary Distributions for version >= 16.X
## Start Web UI
-See Web UI [README.md](src/ui/web/README.md) for more information.
+See Web UI [README.md](ui/web/README.md) for more information.
## Configuration files syntax
**src/assets/config.json**:
-| Key | Value(s) | Default Value | Value type | Description |
-| -------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| supervisionUrls | | [] | string \| string[] | string or array of global connection URIs to OCPP-J servers |
-| supervisionUrlDistribution | round-robin/random/sequential | round-robin | boolean | supervision urls distribution policy to simulated charging stations |
-| logStatisticsInterval | | 60 | integer | seconds between charging stations statistics output in the logs |
-| logConsole | true/false | false | boolean | output logs on the console |
-| logFormat | | simple | string | winston log format |
-| logRotate | true/false | true | boolean | enable daily log files rotation |
-| logMaxFiles | | 7 | integer | maximum number of log files to keep |
-| logLevel | emerg/alert/crit/error/warning/notice/info/debug | info | string | winston logging level |
-| logFile | | combined.log | string | log file relative path |
-| logErrorFile | | error.log | string | error log file relative path |
-| worker | | {<br />"processType": "workerSet",<br />"startDelay": 500,<br />"elementStartDelay": 0,<br />"elementsPerWorker": 1,<br />"poolMinSize": 4,<br />"poolMaxSize": 16,<br />"poolStrategy": "ROUND_ROBBIN"<br />} | {<br />processType: WorkerProcessType;<br />startDelay: number;<br />elementStartDelay: number;<br />elementsPerWorker: number;<br />poolMinSize: number;<br />poolMaxSize: number;<br />poolStrategy: WorkerChoiceStrategy;<br />} | Worker configuration section:<br />- processType: worker threads process type (workerSet/staticPool/dynamicPool)<br />- startDelay: milliseconds to wait at worker threads startup (only for workerSet threads process type)<br />- elementStartDelay: milliseconds to wait at charging station startup<br />- elementsPerWorker: number of charging stations per worker threads for the `workerSet` process type<br />- poolMinSize: worker threads pool minimum number of threads</br >- poolMaxSize: worker threads pool maximum number of threads<br />- poolStrategy: worker threads pool [poolifier](https://github.com/poolifier/poolifier) worker choice strategy |
-| uiServer | | {<br />"enabled": true,<br />"type": "ws",<br />"options": {<br />"host: "localhost",<br />"port": 8080<br />}<br />} | {<br />enabled: boolean;<br />type: ApplicationProtocol;<br />options: ServerOptions;<br />authentication: {<br />enabled: boolean;<br />type: AuthenticationType;<br />username: string;<br />password: string;<br />}<br />} | UI server configuration section |
-| performanceStorage | | {<br />"enabled": false,<br />"type": "jsonfile",<br />"file:///performanceRecords.json"<br />} | {<br />enabled: boolean;<br />type: string;<br />URI: string;<br />}<br />where type can be 'jsonfile' or 'mongodb' | performance storage configuration section |
-| stationTemplateUrls | | {}[] | {<br />file: string;<br />numberOfStations: number;<br />}[] | array of charging station configuration templates URIs configuration section (charging station configuration template file name and number of stations) |
-
-#### Worker process model:
+| Key | Value(s) | Default Value | Value type | Description |
+| -------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| supervisionUrls | | [] | string \| string[] | string or array of global connection URIs to OCPP-J servers |
+| supervisionUrlDistribution | round-robin/random/charging-station-affinity | charging-station-affinity | boolean | supervision urls distribution policy to simulated charging stations |
+| logStatisticsInterval | | 60 | integer | seconds between charging stations statistics output in the logs |
+| logConsole | true/false | false | boolean | output logs on the console |
+| logFormat | | simple | string | winston log format |
+| logRotate | true/false | true | boolean | enable daily log files rotation |
+| logMaxFiles | | 7 | integer | maximum number of log files to keep |
+| logLevel | emerg/alert/crit/error/warning/notice/info/debug | info | string | winston logging level |
+| logFile | | combined.log | string | log file relative path |
+| logErrorFile | | error.log | string | error log file relative path |
+| worker | | {<br />"processType": "workerSet",<br />"startDelay": 500,<br />"elementStartDelay": 0,<br />"elementsPerWorker": 1,<br />"poolMinSize": 4,<br />"poolMaxSize": 16,<br />"poolStrategy": "ROUND_ROBIN"<br />} | {<br />processType: WorkerProcessType;<br />startDelay: number;<br />elementStartDelay: number;<br />elementsPerWorker: number;<br />poolMinSize: number;<br />poolMaxSize: number;<br />poolStrategy: WorkerChoiceStrategy;<br />} | Worker configuration section:<br />- processType: worker threads process type (workerSet/staticPool/dynamicPool)<br />- startDelay: milliseconds to wait at worker threads startup (only for workerSet threads process type)<br />- elementStartDelay: milliseconds to wait at charging station startup<br />- elementsPerWorker: number of charging stations per worker threads for the `workerSet` process type<br />- poolMinSize: worker threads pool minimum number of threads</br >- poolMaxSize: worker threads pool maximum number of threads<br />- poolStrategy: worker threads pool [poolifier](https://github.com/poolifier/poolifier) worker choice strategy |
+| uiServer | | {<br />"enabled": true,<br />"type": "ws",<br />"options": {<br />"host": "localhost",<br />"port": 8080<br />}<br />} | {<br />enabled: boolean;<br />type: ApplicationProtocol;<br />options: ServerOptions;<br />authentication: {<br />enabled: boolean;<br />type: AuthenticationType;<br />username: string;<br />password: string;<br />}<br />} | UI server configuration section |
+| performanceStorage | | {<br />"enabled": false,<br />"type": "jsonfile",<br />"file:///performanceRecords.json"<br />} | {<br />enabled: boolean;<br />type: string;<br />URI: string;<br />}<br />where type can be 'jsonfile' or 'mongodb' | performance storage configuration section |
+| stationTemplateUrls | | {}[] | {<br />file: string;<br />numberOfStations: number;<br />}[] | array of charging station configuration templates URIs configuration section (charging station configuration template file name and number of stations) |
+
+#### Worker process model
- **workerSet**:
Worker set executing each a static number (elementsPerWorker) of simulated charging stations from the total
| mainVoltageMeterValues | true/false | true | boolean | include charging stations main voltage MeterValues on three phased charging stations |
| phaseLineToLineVoltageMeterValues | true/false | true | boolean | include charging stations line to line voltage MeterValues on three phased charging stations |
| customValueLimitationMeterValues | true/false | true | boolean | enable limitation on custom fluctuated value in MeterValues |
-| commandsSupport | | {<br />"incomingCommands": {},<br />"outgoingCommands": {}<br />} | {<br /> incomingCommands: Record<IncomingRequestCommand, boolean>;<br />outgoingCommands?: Record<RequestCommand, boolean>;<br />} | Configuration section for OCPP commands support. Empty section or subsections means all implemented commands are supported |
+| commandsSupport | | {<br />"incomingCommands": {},<br />"outgoingCommands": {}<br />} | {<br /> incomingCommands: Record<IncomingRequestCommand, boolean>;<br />outgoingCommands?: Record<RequestCommand, boolean>;<br />} | Configuration section for OCPP commands support. Empty section or subsections means all implemented OCPP commands are supported |
+| messageTriggerSupport | | {} | Record<MessageTrigger, boolean> | Configuration section for OCPP commands trigger support. Empty section means all implemented OCPP trigger commands are supported |
| Configuration | | | ChargingStationConfiguration | charging stations OCPP parameters configuration section |
| AutomaticTransactionGenerator | | | AutomaticTransactionGenerator | charging stations ATG configuration section |
| Connectors | | | Connectors | charging stations connectors configuration section |
#### AutomaticTransactionGenerator section
+Section type definition:
+
+```ts
+type AutomaticTransactionGeneratorConfiguration = {
+ enable: boolean;
+ minDuration: number;
+ maxDuration: number;
+ minDelayBetweenTwoTransactions: number;
+ maxDelayBetweenTwoTransactions: number;
+ probabilityOfStart: number;
+ stopAfterHours: number;
+ stopOnConnectionFailure: boolean;
+ requireAuthorize?: boolean;
+ idTagDistribution?: 'random' | 'round-robin' | 'connector-affinity';
+};
+```
+
+Section example:
+
```json
"AutomaticTransactionGenerator": {
"enable": false,
"probabilityOfStart": 1,
"stopAfterHours": 0.3,
"stopOnConnectionFailure": true,
- "requireAuthorize": true
+ "requireAuthorize": true,
+ "idTagDistribution": "random"
}
```
- :white_check_mark: ChangeAvailability
- :white_check_mark: ChangeConfiguration
- :white_check_mark: ClearCache
-- :x: DataTransfer
+- :white_check_mark: DataTransfer
- :white_check_mark: GetConfiguration
- :white_check_mark: Heartbeat
- :white_check_mark: MeterValues
### HTTP Protocol
-A Postman and [Insomnia](https://insomnia.rest/) requests collection, to learn how to use the HTTP protocol to pilot the simulator, is available in [src/assets](./src/assets/) directory.
+To learn how to use the HTTP protocol to pilot the simulator, an [Insomnia](https://insomnia.rest/) HTTP requests collection is available in [src/assets/ui-protocol](./src/assets/ui-protocol) directory.
### Websocket Protocol
`uuid`: String uniquely linking the response to the request
`PDU`: Response parameters to requested procedure
+An [Insomnia](https://insomnia.rest/) WebSocket requests collection is available in [src/assets/ui-protocol](./src/assets/ui-protocol) directory.
+
#### Version 0.0.1
Set the Websocket header _Sec-Websocket-Protocol_ to `ui0.0.1`.
`chargingStations`: ChargingStationData[]
}
-###### Start Transaction
-
-- Request:
- `ProcedureName`: 'startTransaction'
- `PDU`: {
- `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
- `connectorId`: connector id integer,
- `idTag`: RFID tag string
- }
-
-- Response:
- `PDU`: {
- `status`: 'success' | 'failure',
- `hashIdsSucceeded`: charging station unique identifier strings array,
- `hashIdsFailed`: charging station unique identifier strings array (optional)
- }
-
-###### Stop Transaction
-
-- Request:
- `ProcedureName`: 'stopTransaction'
- `PDU`: {
- `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
- `transactionId`: transaction id integer
- }
-
-- Response:
- `PDU`: {
- `status`: 'success' | 'failure',
- `hashIdsSucceeded`: charging station unique identifier strings array,
- `hashIdsFailed`: charging station unique identifier strings array (optional)
- }
-
###### Start Charging Station
- Request:
`status`: 'success' | 'failure',
`hashIdsSucceeded`: charging station unique identifier strings array,
`hashIdsFailed`: charging station unique identifier strings array (optional)
+ `responsesFailed`: failed responses payload array (optional)
}
###### Stop Charging Station
`PDU`: {
`status`: 'success' | 'failure',
`hashIdsSucceeded`: charging station unique identifier strings array,
- `hashIdsFailed`: charging station unique identifier strings array (optional)
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
}
###### Open Connection
`PDU`: {
`status`: 'success' | 'failure',
`hashIdsSucceeded`: charging station unique identifier strings array,
- `hashIdsFailed`: charging station unique identifier strings array (optional)
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
}
###### Close Connection
`PDU`: {
`status`: 'success' | 'failure',
`hashIdsSucceeded`: charging station unique identifier strings array,
- `hashIdsFailed`: charging station unique identifier strings array (optional)
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
}
###### Start Automatic Transaction Generator
`PDU`: {
`status`: 'success' | 'failure',
`hashIdsSucceeded`: charging station unique identifier strings array,
- `hashIdsFailed`: charging station unique identifier strings array (optional)
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
}
###### Stop Automatic Transaction Generator
`PDU`: {
`status`: 'success' | 'failure',
`hashIdsSucceeded`: charging station unique identifier strings array,
- `hashIdsFailed`: charging station unique identifier strings array (optional)
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
}
+###### OCPP commands trigger
+
+- Request:
+ `ProcedureName`: 'commandName' (the OCPP command name in camel case)
+ `PDU`: {
+ `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
+ ...`commandPayload`
+ } (the OCPP command payload with some optional fields added to target the simulated charging stations)
+
+- Response:
+ `PDU`: {
+ `status`: 'success' | 'failure',
+ `hashIdsSucceeded`: charging station unique identifier strings array,
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
+ }
+
+Examples:
+
+- **Start Transaction**
+
+ - Request:
+ `ProcedureName`: 'startTransaction'
+ `PDU`: {
+ `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
+ `connectorId`: connector id integer,
+ `idTag`: RFID tag string
+ }
+
+ - Response:
+ `PDU`: {
+ `status`: 'success' | 'failure',
+ `hashIdsSucceeded`: charging station unique identifier strings array,
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
+ }
+
+- **Stop Transaction**
+
+ - Request:
+ `ProcedureName`: 'stopTransaction'
+ `PDU`: {
+ `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
+ `transactionId`: transaction id integer
+ }
+
+ - Response:
+ `PDU`: {
+ `status`: 'success' | 'failure',
+ `hashIdsSucceeded`: charging station unique identifier strings array,
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
+ }
+
+- **Status Notification**
+
+ - Request:
+ `ProcedureName`: 'statusNotification'
+ `PDU`: {
+ `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
+ `connectorId`: connector id integer,
+ `errorCode`: connector error code,
+ `status`: connector status
+ }
+
+ - Response:
+ `PDU`: {
+ `status`: 'success' | 'failure',
+ `hashIdsSucceeded`: charging station unique identifier strings array,
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
+ }
+
+- **Heartbeat**
+
+ - Request:
+ `ProcedureName`: 'heartbeat'
+ `PDU`: {
+ `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),
+ }
+
+ - Response:
+ `PDU`: {
+ `status`: 'success' | 'failure',
+ `hashIdsSucceeded`: charging station unique identifier strings array,
+ `hashIdsFailed`: charging station unique identifier strings array (optional),
+ `responsesFailed`: failed responses payload array (optional)
+ }
+
## Support, Feedback, Contributing
This project is open to feature requests/suggestions, bug reports etc. via [GitHub issues](https://github.com/SAP/e-mobility-charging-stations-simulator/issues). Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our [Contribution Guidelines](CONTRIBUTING.md).