From b9ee03944f9575adb2e68b7b4fe263d67d5f9e58 Mon Sep 17 00:00:00 2001 From: carloslibardo Date: Wed, 18 Dec 2024 14:27:36 -0300 Subject: [PATCH] Feat: Implement websocketOptions as arg to CS connection (#58) Feat: Implement websocketOptions as arg to CS connection --- docs/modules/cp/index.ts.md | 2 +- src/cp/index.ts | 11 +- .../CentralSystemServiceSoap12.ts | 2 +- src/soap/connection.ts | 115 ++++++++++++------ src/ws/format.ts | 5 +- tsconfig.json | 16 +-- yarn.lock | 6 +- 7 files changed, 97 insertions(+), 60 deletions(-) diff --git a/docs/modules/cp/index.ts.md b/docs/modules/cp/index.ts.md index ec98c45..01d8a05 100644 --- a/docs/modules/cp/index.ts.md +++ b/docs/modules/cp/index.ts.md @@ -70,7 +70,7 @@ const chargePoint = new ChargePoint( **Signature** ```ts -async connect(): Promise>> +async connect(websocketOptions: WebsocketOptions): Promise>> ``` ### sendRequest (method) diff --git a/src/cp/index.ts b/src/cp/index.ts index b667ac6..cea6cc6 100644 --- a/src/cp/index.ts +++ b/src/cp/index.ts @@ -6,6 +6,9 @@ import { ChargePointAction, chargePointActions } from '../messages/cp'; import { EitherAsync, Left } from 'purify-ts'; import { OCPPRequestError, ValidationError } from '../errors'; import { OCPPVersion } from '../types'; +import * as http from 'http'; + +export type ConnectArgs = http.ClientRequestArgs & WebSocket.ClientOptions; export type CPSendRequestArgs, V extends OCPPVersion> = { ocppVersion: 'v1.6-json', @@ -45,6 +48,7 @@ export type CPSendRequestArgs, V extends OCPPVers * * @category Charge Point */ + export default class ChargePoint { private connection?: Connection>; @@ -54,9 +58,12 @@ export default class ChargePoint { private readonly csUrl: string ) { } - async connect(): Promise>> { + async connect(connectArgs?: ConnectArgs): Promise>> { const url = `${this.csUrl}/${this.id}`; - const socket = new WebSocket(url, SUPPORTED_PROTOCOLS); + const socket = new WebSocket(url, SUPPORTED_PROTOCOLS, { + auth: `${this.id}:${connectArgs?.auth}`, + ...connectArgs, + }); const connection = new Connection( socket, diff --git a/src/messages/soap/wsdl/CentralSystemService/CentralSystemServiceSoap12.ts b/src/messages/soap/wsdl/CentralSystemService/CentralSystemServiceSoap12.ts index d60bb5d..c12a0c0 100644 --- a/src/messages/soap/wsdl/CentralSystemService/CentralSystemServiceSoap12.ts +++ b/src/messages/soap/wsdl/CentralSystemService/CentralSystemServiceSoap12.ts @@ -133,7 +133,7 @@ export interface IBootNotificationInput { export interface IBootNotificationOutput { /** urn://Ocpp/Cs/2012/06/#RegistrationStatus(Accepted,Rejected) */ - status: "Accepted" | "Rejected" | 'Pending'; + status: "Accepted" | "Rejected" | "Pending"; /** urn://Ocpp/Cs/2012/06/#s:dateTime(undefined) */ currentTime: string; /** urn://Ocpp/Cs/2012/06/#s:int(undefined) */ diff --git a/src/soap/connection.ts b/src/soap/connection.ts index 8436f03..c4d500a 100644 --- a/src/soap/connection.ts +++ b/src/soap/connection.ts @@ -1,57 +1,92 @@ -import { ActionName, Request, Response } from '../messages'; -import { OCPPApplicationError, OCPPRequestError } from '../errors/index'; -import { validateMessageRequest } from '../messages/validation'; -import { EitherAsync, Left, Right } from 'purify-ts'; -import * as soap from 'soap'; -import * as path from 'path'; -import { chargePointActions } from '../messages/cp'; -import { soapCentralSystemActions } from '../messages/cs'; -import * as uuid from 'uuid'; +import { ActionName, Request, Response } from "../messages"; +import { OCPPApplicationError, OCPPRequestError } from "../errors/index"; +import { validateMessageRequest } from "../messages/validation"; +import { EitherAsync, Left, Right } from "purify-ts"; +import * as soap from "soap"; +import * as path from "path"; +import { chargePointActions } from "../messages/cp"; +import { soapCentralSystemActions } from "../messages/cs"; +import * as uuid from "uuid"; + +type SOAPResponse = [Error | null, any, any, any, any]; export default class SOAPConnection { - private respondedActions: ActionName<'v1.5-soap'>[]; + private respondedActions: ActionName<"v1.5-soap">[]; constructor( private readonly soapClient: soap.Client, - private readonly connectedTo: 'cp' | 'cs', + private readonly connectedTo: "cp" | "cs", private readonly chargePointId: string, - private readonly endpoint: string, + private readonly endpoint: string ) { - this.respondedActions = connectedTo === 'cp' ? soapCentralSystemActions : chargePointActions; + this.respondedActions = + connectedTo === "cp" ? soapCentralSystemActions : chargePointActions; } - static async connect(endpoint: string, connectedTo: 'cp' | 'cs', chargePointId: string): Promise { - const wsdlPath = path.resolve(__dirname, ( - connectedTo === 'cs' - ? '../messages/soap/ocpp_centralsystemservice_1.5_final.wsdl' - : '../messages/soap/ocpp_chargepointservice_1.5_final.wsdl' - )); - const soapClient = await soap.createClientAsync(wsdlPath, { endpoint, forceSoap12Headers: true }); + static async connect( + endpoint: string, + connectedTo: "cp" | "cs", + chargePointId: string + ): Promise { + const wsdlPath = path.resolve( + __dirname, + connectedTo === "cs" + ? "../messages/soap/ocpp_centralsystemservice_1.5_final.wsdl" + : "../messages/soap/ocpp_chargepointservice_1.5_final.wsdl" + ); + const soapClient = await soap.createClientAsync(wsdlPath, { + endpoint, + forceSoap12Headers: true, + }); return new SOAPConnection(soapClient, connectedTo, chargePointId, endpoint); } - public sendRequest>(action: T, { action: _, ocppVersion: __, ...payload }: Request): EitherAsync> { + public sendRequest>( + action: T, + { action: _, ocppVersion: __, ...payload }: Request + ): EitherAsync> { return EitherAsync.fromPromise(async () => { - const validateResult = validateMessageRequest(action, payload, this.respondedActions); + const validateResult = validateMessageRequest( + action, + payload, + this.respondedActions + ); if (validateResult.isLeft()) - return Left(new OCPPApplicationError(validateResult.extract().toString())) - - const xmlNs = this.connectedTo === 'cp' ? 'urn://Ocpp/Cp/2012/06/' : 'urn://Ocpp/Cs/2012/06/'; - this.soapClient.addSoapHeader({ chargeBoxIdentity: this.chargePointId }, '', 'ocpp', xmlNs); - this.soapClient.addSoapHeader({ - 'Action': '/' + action, - 'MessageID': uuid.v4(), - 'To': this.endpoint, - }, '', 'wsa5', 'http://www.w3.org/2005/08/addressing'); + return Left( + new OCPPApplicationError(validateResult.extract().toString()) + ); - const [err, result, _rawResponse, _soapHeader, _rawRequest] = await new Promise(resolve => { - const [serviceKey, portKey] = this.connectedTo === 'cp' - ? ['ChargePointService', 'ChargePointServiceSoap12'] - : ['CentralSystemService', 'CentralSystemServiceSoap12']; - this.soapClient[serviceKey][portKey][action](payload, (...args: any) => resolve(args)) + const xmlNs = + this.connectedTo === "cp" + ? "urn://Ocpp/Cp/2012/06/" + : "urn://Ocpp/Cs/2012/06/"; + this.soapClient.addSoapHeader( + { chargeBoxIdentity: this.chargePointId }, + "", + "ocpp", + xmlNs + ); + this.soapClient.addSoapHeader( + { + Action: "/" + action, + MessageID: uuid.v4(), + To: this.endpoint, + }, + "", + "wsa5", + "http://www.w3.org/2005/08/addressing" + ); + + const [err, result, _rawResponse, _soapHeader, _rawRequest] = await new Promise((resolve) => { + const [serviceKey, portKey] = + this.connectedTo === "cp" + ? ["ChargePointService", "ChargePointServiceSoap12"] + : ["CentralSystemService", "CentralSystemServiceSoap12"]; + this.soapClient[serviceKey][portKey][action](payload, (...args: any[]) => + resolve(args as SOAPResponse) + ); }); - if (err) - return Left(new OCPPRequestError(err.toString())) + if (err) return Left(new OCPPRequestError(err.toString())); return Right(result); - }) + }); } -} \ No newline at end of file +} diff --git a/src/ws/format.ts b/src/ws/format.ts index 85f2f23..860abd9 100644 --- a/src/ws/format.ts +++ b/src/ws/format.ts @@ -42,7 +42,10 @@ export const parseOCPPMessage = (raw: OCPPJRawMessage): Either