- :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
   `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),  
-  `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)  
-  }
-
 ###### Start Charging Station
 
 - Request:  
   `responsesFailed`: failed responses payload array (optional)  
   }
 
-###### Status Notification
+###### OCPP commands trigger
 
-- 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  
-  }
+The request PDU is the same as 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)  
-  }
+`PDU`: {  
+ `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),  
+ ...`payload`  
+ }
 
-###### Heartbeat
+Examples:
 
-- Request:  
-  `ProcedureName`: 'Heartbeat'  
-  `PDU`: {  
-  `hashIds`: charging station unique identifier strings array (optional, default: all charging stations),  
-  }
+- **Start Transaction**
 
-- 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)  
-  }
+  - 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
 
 
--- /dev/null
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "id": "urn:OCPP:1.6:2019:12:DataTransferRequest",
+  "title": "DataTransferRequest",
+  "type": "object",
+  "properties": {
+    "vendorId": {
+      "type": "string",
+      "maxLength": 255
+    },
+    "messageId": {
+      "type": "string",
+      "maxLength": 50
+    },
+    "data": {
+      "type": "string"
+    }
+  },
+  "additionalProperties": false,
+  "required": ["vendorId"]
+}
 
--- /dev/null
+{
+  "$schema": "http://json-schema.org/draft-04/schema#",
+  "id": "urn:OCPP:1.6:2019:12:DataTransferResponse",
+  "title": "DataTransferResponse",
+  "type": "object",
+  "properties": {
+    "status": {
+      "type": "string",
+      "additionalProperties": false,
+      "enum": ["Accepted", "Rejected", "UnknownMessageId", "UnknownVendorId"]
+    },
+    "data": {
+      "type": "string"
+    }
+  },
+  "additionalProperties": false,
+  "required": ["status"]
+}
 
 import { StandardParametersKey } from '../types/ocpp/Configuration';
 import {
   type BootNotificationRequest,
+  type DataTransferRequest,
   type HeartbeatRequest,
   type MeterValuesRequest,
   RequestCommand,
 } from '../types/ocpp/Requests';
 import {
   type BootNotificationResponse,
+  type DataTransferResponse,
+  DataTransferStatus,
   type HeartbeatResponse,
   type MeterValuesResponse,
   RegistrationStatus,
   | BootNotificationResponse
   | StatusNotificationResponse
   | HeartbeatResponse
-  | MeterValuesResponse;
+  | MeterValuesResponse
+  | DataTransferResponse;
 
 type CommandHandler = (
   requestPayload?: BroadcastChannelRequestPayload
           });
         },
       ],
+      [
+        BroadcastChannelProcedureName.DATA_TRANSFER,
+        async (requestPayload?: BroadcastChannelRequestPayload) =>
+          this.chargingStation.ocppRequestService.requestHandler<
+            DataTransferRequest,
+            DataTransferResponse
+          >(this.chargingStation, RequestCommand.DATA_TRANSFER, requestPayload),
+      ],
     ]);
     this.chargingStation = chargingStation;
     this.onmessage = this.requestHandler.bind(this) as (message: MessageEvent) => void;
           return ResponseStatus.SUCCESS;
         }
         return ResponseStatus.FAILURE;
+      case BroadcastChannelProcedureName.DATA_TRANSFER:
+        if (commandResponse?.status === DataTransferStatus.ACCEPTED) {
+          return ResponseStatus.SUCCESS;
+        }
+        return ResponseStatus.FAILURE;
       case BroadcastChannelProcedureName.STATUS_NOTIFICATION:
       case BroadcastChannelProcedureName.METER_VALUES:
         if (Utils.isEmptyObject(commandResponse) === true) {
 
 import {
   DiagnosticsStatusNotificationRequest,
   OCPP16BootNotificationRequest,
+  OCPP16DataTransferRequest,
   OCPP16HeartbeatRequest,
   OCPP16RequestCommand,
   OCPP16StatusNotificationRequest,
           )
         ) as JSONSchemaType<OCPP16StopTransactionRequest>,
       ],
+      [
+        OCPP16RequestCommand.DATA_TRANSFER,
+        JSON.parse(
+          fs.readFileSync(
+            path.resolve(
+              path.dirname(fileURLToPath(import.meta.url)),
+              '../../../assets/json-schemas/ocpp/1.6/DataTransfer.json'
+            ),
+            'utf8'
+          )
+        ) as JSONSchemaType<OCPP16DataTransferRequest>,
+      ],
     ]);
     this.buildRequestPayload.bind(this);
     this.validatePayload.bind(this);
             ),
           }),
         } as unknown as Request;
+      case OCPP16RequestCommand.DATA_TRANSFER:
+        return commandParams as unknown as Request;
       default:
         // OCPPError usage here is debatable: it's an error in the OCPP stack but not targeted to sendError().
         throw new OCPPError(
 
 import {
   DiagnosticsStatusNotificationResponse,
   OCPP16BootNotificationResponse,
+  OCPP16DataTransferResponse,
   OCPP16HeartbeatResponse,
   OCPP16RegistrationStatus,
   OCPP16StatusNotificationResponse,
       [OCPP16RequestCommand.STATUS_NOTIFICATION, this.emptyResponseHandler.bind(this)],
       [OCPP16RequestCommand.METER_VALUES, this.emptyResponseHandler.bind(this)],
       [OCPP16RequestCommand.DIAGNOSTICS_STATUS_NOTIFICATION, this.emptyResponseHandler.bind(this)],
+      [OCPP16RequestCommand.DATA_TRANSFER, this.emptyResponseHandler.bind(this)],
     ]);
     this.jsonSchemas = new Map<OCPP16RequestCommand, JSONSchemaType<JsonObject>>([
       [
           )
         ) as JSONSchemaType<DiagnosticsStatusNotificationResponse>,
       ],
+      [
+        OCPP16RequestCommand.DATA_TRANSFER,
+        JSON.parse(
+          fs.readFileSync(
+            path.resolve(
+              path.dirname(fileURLToPath(import.meta.url)),
+              '../../../assets/json-schemas/ocpp/1.6/DataTransferResponse.json'
+            ),
+            'utf8'
+          )
+        ) as JSONSchemaType<OCPP16DataTransferResponse>,
+      ],
     ]);
     this.validatePayload.bind(this);
   }
 
     [ProcedureName.STATUS_NOTIFICATION]: BroadcastChannelProcedureName.STATUS_NOTIFICATION,
     [ProcedureName.HEARTBEAT]: BroadcastChannelProcedureName.HEARTBEAT,
     [ProcedureName.METER_VALUES]: BroadcastChannelProcedureName.METER_VALUES,
+    [ProcedureName.DATA_TRANSFER]: BroadcastChannelProcedureName.DATA_TRANSFER,
   };
 
   protected readonly requestHandlers: Map<ProcedureName, ProtocolRequestHandler>;
 
   STATUS_NOTIFICATION = 'statusNotification',
   HEARTBEAT = 'heartbeat',
   METER_VALUES = 'meterValues',
+  DATA_TRANSFER = 'dataTransfer',
 }
 
 export interface RequestPayload extends JsonObject {
 
   STATUS_NOTIFICATION = 'statusNotification',
   HEARTBEAT = 'heartbeat',
   METER_VALUES = 'meterValues',
+  DATA_TRANSFER = 'dataTransfer',
 }
 
 export interface BroadcastChannelRequestPayload extends RequestPayload {
 
   STOP_TRANSACTION = 'StopTransaction',
   METER_VALUES = 'MeterValues',
   DIAGNOSTICS_STATUS_NOTIFICATION = 'DiagnosticsStatusNotification',
+  DATA_TRANSFER = 'DataTransfer',
 }
 
 export type OCPP16HeartbeatRequest = EmptyObject;
   requestedMessage: OCPP16MessageTrigger;
   connectorId?: number;
 }
+
+export interface OCPP16DataTransferRequest extends JsonObject {
+  vendorId: string;
+  messageId?: string;
+  data?: string;
+}
 
 export interface OCPP16TriggerMessageResponse extends JsonObject {
   status: OCPP16TriggerMessageStatus;
 }
+
+export enum OCPP16DataTransferStatus {
+  ACCEPTED = 'Accepted',
+  REJECTED = 'Rejected',
+  UNKNOWN_MESSAGE_ID = 'UnknownMessageId',
+  UNKNOWN_VENDOR_ID = 'UnknownVendorId',
+}
+
+export interface OCPP16DataTransferResponse extends JsonObject {
+  status: OCPP16DataTransferStatus;
+  data?: string;
+}
 
 import {
   OCPP16AvailabilityType,
   OCPP16BootNotificationRequest,
+  OCPP16DataTransferRequest,
   OCPP16HeartbeatRequest,
   OCPP16IncomingRequestCommand,
   OCPP16MessageTrigger,
 
 export type MeterValuesRequest = OCPP16MeterValuesRequest;
 
+export type DataTransferRequest = OCPP16DataTransferRequest;
+
 export type IncomingRequestHandler = (
   chargingStation: ChargingStation,
   commandPayload: JsonType
 
   OCPP16ChargingProfileStatus,
   OCPP16ClearChargingProfileStatus,
   OCPP16ConfigurationStatus,
+  OCPP16DataTransferResponse,
+  OCPP16DataTransferStatus,
   OCPP16HeartbeatResponse,
   OCPP16RegistrationStatus,
   OCPP16StatusNotificationResponse,
 
 export type MeterValuesResponse = OCPP16MeterValuesResponse;
 
+export type DataTransferResponse = OCPP16DataTransferResponse;
+
 export enum DefaultStatus {
   ACCEPTED = 'Accepted',
   REJECTED = 'Rejected',
 export const TriggerMessageStatus = {
   ...OCPP16TriggerMessageStatus,
 };
+
+export type DataTransferStatus = OCPP16DataTransferStatus;
+
+export const DataTransferStatus = {
+  ...OCPP16DataTransferStatus,
+};