@zetra/citrineos-ocpprouter 1.8.3-fork.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ export { AdminApi } from './module/DataApi.js';
2
+ export type { IAdminApi } from './module/interface.js';
3
+ export { MessageRouterImpl } from './module/router.js';
4
+ export { WebhookDispatcher } from './module/webhook.dispatcher.js';
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ export { AdminApi } from './module/DataApi.js';
5
+ export { MessageRouterImpl } from './module/router.js';
6
+ export { WebhookDispatcher } from './module/webhook.dispatcher.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,88 @@
1
+ import type { BootstrapConfig, IMessageRouter, INetworkConnection, SystemConfig, WebsocketServerConfig } from '@citrineos/base';
2
+ import { AbstractModuleApi, Namespace, OCPP1_6_Namespace, OCPP2_0_1_Namespace } from '@citrineos/base';
3
+ import type { ChargingStationKeyQuerystring, ConnectionDeleteQuerystring, IServerNetworkProfileRepository, ISubscriptionRepository, ModelKeyQuerystring, TenantQueryString, WebsocketDeleteQuerystring, WebsocketGetQuerystring, WebsocketMappingQuerystring } from '@citrineos/data';
4
+ import { Subscription } from '@citrineos/data';
5
+ import type { FastifyInstance, FastifyRequest } from 'fastify';
6
+ import type { ILogObj } from 'tslog';
7
+ import { Logger } from 'tslog';
8
+ import type { IAdminApi } from './interface.js';
9
+ /**
10
+ * Admin API for the OcppRouter.
11
+ */
12
+ export declare class AdminApi extends AbstractModuleApi<IMessageRouter> implements IAdminApi {
13
+ private _networkConnection;
14
+ private _subscriptionRepository;
15
+ private _serverNetworkProfileRepository;
16
+ /**
17
+ * Constructs a new instance of the class.
18
+ *
19
+ * @param {IMessageRouter} ocppRouter - The OcppRouter module.
20
+ * @param {INetworkConnection} networkConnection - The network connection instance.
21
+ * @param {FastifyInstance} server - The Fastify server instance.
22
+ * @param {BootstrapConfig & SystemConfig} config - The configuration instance.
23
+ * @param {Logger<ILogObj>} [logger] - The logger instance.
24
+ * @param {ISubscriptionRepository} [subscriptionRepository] - The subscription repository instance.
25
+ * @param {IServerNetworkProfileRepository} [serverNetworkProfileRepository] - The server network profile repository instance.
26
+ */
27
+ constructor(ocppRouter: IMessageRouter, networkConnection: INetworkConnection, server: FastifyInstance, config: BootstrapConfig & SystemConfig, logger?: Logger<ILogObj>, subscriptionRepository?: ISubscriptionRepository, serverNetworkProfileRepository?: IServerNetworkProfileRepository);
28
+ /**
29
+ * Creates a {@link Subscription}.
30
+ * Will always create a new entity and return its id.
31
+ *
32
+ * @param {FastifyRequest<{ Body: Subscription }>} request - The request object, containing the body which is parsed as a {@link Subscription}.
33
+ * @return {Promise<number>} The id of the created subscription.
34
+ */
35
+ postSubscription(request: FastifyRequest<{
36
+ Body: Subscription;
37
+ Querystring: TenantQueryString;
38
+ }>): Promise<number>;
39
+ getSubscriptionsByChargingStation(request: FastifyRequest<{
40
+ Querystring: ChargingStationKeyQuerystring;
41
+ }>): Promise<Subscription[]>;
42
+ deleteSubscriptionById(request: FastifyRequest<{
43
+ Querystring: ModelKeyQuerystring;
44
+ }>): Promise<boolean>;
45
+ getWebsocketConfigurations(request: FastifyRequest<{
46
+ Querystring: WebsocketGetQuerystring;
47
+ }>): Promise<WebsocketServerConfig[] | WebsocketServerConfig>;
48
+ createWebsocketConfiguration(request: FastifyRequest<{
49
+ Body: WebsocketServerConfig;
50
+ }>): Promise<WebsocketServerConfig>;
51
+ /**
52
+ * Adds or updates a mapping from a path segment to a tenant for a specific websocket server.
53
+ */
54
+ putWebsocketMapping(request: FastifyRequest<{
55
+ Body: {
56
+ path: string;
57
+ tenantId: number;
58
+ };
59
+ Querystring: WebsocketMappingQuerystring;
60
+ }>): Promise<WebsocketServerConfig>;
61
+ /**
62
+ * Removes a mapping for a specific path OR all mappings for a specific tenant from a websocket server.
63
+ */
64
+ deleteWebsocketMapping(request: FastifyRequest<{
65
+ Querystring: WebsocketMappingQuerystring & {
66
+ path?: string;
67
+ tenantId?: number;
68
+ };
69
+ }>): Promise<WebsocketServerConfig>;
70
+ /**
71
+ * Helper to validate internal system calls
72
+ */
73
+ private _validateSystemToken;
74
+ deleteWebsocketConfiguration(request: FastifyRequest<{
75
+ Querystring: WebsocketDeleteQuerystring;
76
+ }>): Promise<void>;
77
+ deleteWebsocketConnection(request: FastifyRequest<{
78
+ Querystring: ConnectionDeleteQuerystring;
79
+ }>): Promise<void>;
80
+ /**
81
+ * Overrides superclass method to generate the URL path based on the input {@link Namespace}
82
+ * and the module's endpoint prefix configuration.
83
+ *
84
+ * @param {Namespace} input - The input {@link Namespace}.
85
+ * @return {string} - The generated URL path.
86
+ */
87
+ protected _toDataPath(input: OCPP2_0_1_Namespace | OCPP1_6_Namespace | Namespace): string;
88
+ }
@@ -0,0 +1,248 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { AbstractModuleApi, AsDataEndpoint, BadRequestError, ConfigStoreFactory, DEFAULT_TENANT_ID, HttpMethod, Namespace, NotFoundError, OCPP1_6_Namespace, OCPP2_0_1_Namespace, UnauthorizedError, } from '@citrineos/base';
11
+ import { ChargingStationKeyQuerySchema, ConnectionDeleteQuerySchema, CreateSubscriptionSchema, ModelKeyQuerystringSchema, sequelize, Subscription, TenantQuerySchema, WebsocketDeleteQuerySchema, WebsocketGetQuerySchema, WebsocketRequestSchema, WebsocketMappingQuerySchema, WebsocketMappingRequestSchema, } from '@citrineos/data';
12
+ import { Logger } from 'tslog';
13
+ /**
14
+ * Admin API for the OcppRouter.
15
+ */
16
+ export class AdminApi extends AbstractModuleApi {
17
+ _networkConnection;
18
+ _subscriptionRepository;
19
+ _serverNetworkProfileRepository;
20
+ /**
21
+ * Constructs a new instance of the class.
22
+ *
23
+ * @param {IMessageRouter} ocppRouter - The OcppRouter module.
24
+ * @param {INetworkConnection} networkConnection - The network connection instance.
25
+ * @param {FastifyInstance} server - The Fastify server instance.
26
+ * @param {BootstrapConfig & SystemConfig} config - The configuration instance.
27
+ * @param {Logger<ILogObj>} [logger] - The logger instance.
28
+ * @param {ISubscriptionRepository} [subscriptionRepository] - The subscription repository instance.
29
+ * @param {IServerNetworkProfileRepository} [serverNetworkProfileRepository] - The server network profile repository instance.
30
+ */
31
+ constructor(ocppRouter, networkConnection, server, config, logger, subscriptionRepository, serverNetworkProfileRepository) {
32
+ super(ocppRouter, server, null, logger);
33
+ this._networkConnection = networkConnection;
34
+ this._subscriptionRepository =
35
+ subscriptionRepository || new sequelize.SequelizeSubscriptionRepository(config, this._logger);
36
+ this._serverNetworkProfileRepository =
37
+ serverNetworkProfileRepository ||
38
+ new sequelize.SequelizeServerNetworkProfileRepository(config, this._logger);
39
+ }
40
+ // N.B.: When adding subscriptions, chargers may be connected to a different instance of Citrine.
41
+ // If this is the case, new subscriptions will not take effect until the charger reconnects.
42
+ /**
43
+ * Creates a {@link Subscription}.
44
+ * Will always create a new entity and return its id.
45
+ *
46
+ * @param {FastifyRequest<{ Body: Subscription }>} request - The request object, containing the body which is parsed as a {@link Subscription}.
47
+ * @return {Promise<number>} The id of the created subscription.
48
+ */
49
+ async postSubscription(request) {
50
+ const tenantId = request.query.tenantId;
51
+ request.body.tenantId = tenantId;
52
+ if (!request.body.onClose &&
53
+ !request.body.onConnect &&
54
+ !request.body.onMessage &&
55
+ !request.body.sentMessage) {
56
+ throw new BadRequestError('Must specify at least one of onConnect, onClose, onMessage, sentMessage to true.');
57
+ }
58
+ return this._subscriptionRepository
59
+ .create(tenantId, request.body)
60
+ .then((subscription) => subscription?.id);
61
+ }
62
+ async getSubscriptionsByChargingStation(request) {
63
+ return this._subscriptionRepository.readAllByStationId(request.query.tenantId, request.query.stationId);
64
+ }
65
+ async deleteSubscriptionById(request) {
66
+ const tenantId = request.query.tenantId ?? DEFAULT_TENANT_ID;
67
+ return this._subscriptionRepository
68
+ .deleteByKey(tenantId, request.query.id.toString())
69
+ .then(() => true);
70
+ }
71
+ async getWebsocketConfigurations(request) {
72
+ if (request.query.id) {
73
+ const websocketConfig = this._module.config.util.networkConnection.websocketServers.find((ws) => ws.id === request.query.id);
74
+ if (!websocketConfig) {
75
+ throw new NotFoundError(`Could not find websocket configuration with id ${request.query.id}`);
76
+ }
77
+ else {
78
+ return websocketConfig;
79
+ }
80
+ }
81
+ else {
82
+ // TODO when available (coming soon in a separate feature), filter by tenantId if the tenantId query param exists
83
+ return this._module.config.util.networkConnection.websocketServers;
84
+ }
85
+ }
86
+ async createWebsocketConfiguration(request) {
87
+ const existingConfig = this._module.config.util.networkConnection.websocketServers.find((ws) => ws.id === request.body.id);
88
+ if (existingConfig) {
89
+ throw new BadRequestError(`Websocket configuration with id ${request.body.id} already exists.`);
90
+ }
91
+ else {
92
+ this._module.config.util.networkConnection.websocketServers.push(request.body);
93
+ await ConfigStoreFactory.getInstance().saveConfig(this._module.config);
94
+ return request.body;
95
+ }
96
+ }
97
+ /**
98
+ * Adds or updates a mapping from a path segment to a tenant for a specific websocket server.
99
+ */
100
+ async putWebsocketMapping(request) {
101
+ this._validateSystemToken(request);
102
+ const serverId = request.query.id;
103
+ const { path, tenantId } = request.body;
104
+ const websocketConfig = this._module.config.util.networkConnection.websocketServers.find((ws) => ws.id === serverId);
105
+ if (!websocketConfig) {
106
+ throw new NotFoundError(`Websocket configuration with id ${serverId} not found`);
107
+ }
108
+ if (!websocketConfig.tenantPathMapping) {
109
+ websocketConfig.tenantPathMapping = {};
110
+ }
111
+ if (websocketConfig.tenantPathMapping[path] !== undefined &&
112
+ websocketConfig.tenantPathMapping[path] !== tenantId) {
113
+ throw new BadRequestError(`Path ${path} is already mapped to tenant ${websocketConfig.tenantPathMapping[path]}`);
114
+ }
115
+ websocketConfig.tenantPathMapping[path] = tenantId;
116
+ websocketConfig.dynamicTenantResolution = true;
117
+ await ConfigStoreFactory.getInstance().saveConfig(this._module.config);
118
+ await this._serverNetworkProfileRepository.upsertServerNetworkProfile(websocketConfig, this._module.config.maxCallLengthSeconds);
119
+ return websocketConfig;
120
+ }
121
+ /**
122
+ * Removes a mapping for a specific path OR all mappings for a specific tenant from a websocket server.
123
+ */
124
+ async deleteWebsocketMapping(request) {
125
+ this._validateSystemToken(request);
126
+ const serverId = request.query.id;
127
+ const path = request.query.path;
128
+ const tenantId = request.query.tenantId;
129
+ if (!path && !tenantId) {
130
+ throw new BadRequestError('Either path or tenantId is required to delete a mapping');
131
+ }
132
+ const websocketConfig = this._module.config.util.networkConnection.websocketServers.find((ws) => ws.id === serverId);
133
+ if (!websocketConfig) {
134
+ throw new NotFoundError(`Websocket configuration with id ${serverId} not found`);
135
+ }
136
+ if (websocketConfig.tenantPathMapping) {
137
+ let changed = false;
138
+ if (path && websocketConfig.tenantPathMapping[path] !== undefined) {
139
+ delete websocketConfig.tenantPathMapping[path];
140
+ changed = true;
141
+ }
142
+ else if (tenantId) {
143
+ const tenantIdNum = Number(tenantId);
144
+ for (const [key, value] of Object.entries(websocketConfig.tenantPathMapping)) {
145
+ if (value === tenantIdNum) {
146
+ delete websocketConfig.tenantPathMapping[key];
147
+ changed = true;
148
+ }
149
+ }
150
+ }
151
+ if (changed) {
152
+ await ConfigStoreFactory.getInstance().saveConfig(this._module.config);
153
+ await this._serverNetworkProfileRepository.upsertServerNetworkProfile(websocketConfig, this._module.config.maxCallLengthSeconds);
154
+ }
155
+ }
156
+ return websocketConfig;
157
+ }
158
+ /**
159
+ * Helper to validate internal system calls
160
+ */
161
+ _validateSystemToken(request) {
162
+ const systemToken = this._module.config.centralSystem.systemApiToken;
163
+ if (!systemToken) {
164
+ return;
165
+ }
166
+ const providedToken = request.headers['x-system-token'];
167
+ if (providedToken !== systemToken) {
168
+ throw new UnauthorizedError('Invalid or missing system API token');
169
+ }
170
+ }
171
+ async deleteWebsocketConfiguration(request) {
172
+ const existingConfigIndex = this._module.config.util.networkConnection.websocketServers.findIndex((ws) => ws.id === request.query.id);
173
+ if (existingConfigIndex) {
174
+ this._module.config.util.networkConnection.websocketServers.splice(existingConfigIndex, 1);
175
+ await ConfigStoreFactory.getInstance().saveConfig(this._module.config);
176
+ }
177
+ }
178
+ // Forcibly disconnect a websocket connection by station id and tenant id and mark the station as offline
179
+ async deleteWebsocketConnection(request) {
180
+ await this._networkConnection.disconnect(request.query.tenantId, request.query.stationId);
181
+ }
182
+ /**
183
+ * Overrides superclass method to generate the URL path based on the input {@link Namespace}
184
+ * and the module's endpoint prefix configuration.
185
+ *
186
+ * @param {Namespace} input - The input {@link Namespace}.
187
+ * @return {string} - The generated URL path.
188
+ */
189
+ _toDataPath(input) {
190
+ const endpointPrefix = '/ocpprouter';
191
+ return super._toDataPath(input, endpointPrefix);
192
+ }
193
+ }
194
+ __decorate([
195
+ AsDataEndpoint(OCPP2_0_1_Namespace.Subscription, HttpMethod.Post, TenantQuerySchema, CreateSubscriptionSchema),
196
+ __metadata("design:type", Function),
197
+ __metadata("design:paramtypes", [Object]),
198
+ __metadata("design:returntype", Promise)
199
+ ], AdminApi.prototype, "postSubscription", null);
200
+ __decorate([
201
+ AsDataEndpoint(OCPP2_0_1_Namespace.Subscription, HttpMethod.Get, ChargingStationKeyQuerySchema),
202
+ __metadata("design:type", Function),
203
+ __metadata("design:paramtypes", [Object]),
204
+ __metadata("design:returntype", Promise)
205
+ ], AdminApi.prototype, "getSubscriptionsByChargingStation", null);
206
+ __decorate([
207
+ AsDataEndpoint(OCPP2_0_1_Namespace.Subscription, HttpMethod.Delete, ModelKeyQuerystringSchema),
208
+ __metadata("design:type", Function),
209
+ __metadata("design:paramtypes", [Object]),
210
+ __metadata("design:returntype", Promise)
211
+ ], AdminApi.prototype, "deleteSubscriptionById", null);
212
+ __decorate([
213
+ AsDataEndpoint(Namespace.Websocket, HttpMethod.Get, WebsocketGetQuerySchema),
214
+ __metadata("design:type", Function),
215
+ __metadata("design:paramtypes", [Object]),
216
+ __metadata("design:returntype", Promise)
217
+ ], AdminApi.prototype, "getWebsocketConfigurations", null);
218
+ __decorate([
219
+ AsDataEndpoint(Namespace.Websocket, HttpMethod.Post, undefined, WebsocketRequestSchema),
220
+ __metadata("design:type", Function),
221
+ __metadata("design:paramtypes", [Object]),
222
+ __metadata("design:returntype", Promise)
223
+ ], AdminApi.prototype, "createWebsocketConfiguration", null);
224
+ __decorate([
225
+ AsDataEndpoint(Namespace.WebsocketMapping, HttpMethod.Put, WebsocketMappingQuerySchema, WebsocketMappingRequestSchema),
226
+ __metadata("design:type", Function),
227
+ __metadata("design:paramtypes", [Object]),
228
+ __metadata("design:returntype", Promise)
229
+ ], AdminApi.prototype, "putWebsocketMapping", null);
230
+ __decorate([
231
+ AsDataEndpoint(Namespace.WebsocketMapping, HttpMethod.Delete, WebsocketMappingQuerySchema),
232
+ __metadata("design:type", Function),
233
+ __metadata("design:paramtypes", [Object]),
234
+ __metadata("design:returntype", Promise)
235
+ ], AdminApi.prototype, "deleteWebsocketMapping", null);
236
+ __decorate([
237
+ AsDataEndpoint(Namespace.Websocket, HttpMethod.Delete, WebsocketDeleteQuerySchema),
238
+ __metadata("design:type", Function),
239
+ __metadata("design:paramtypes", [Object]),
240
+ __metadata("design:returntype", Promise)
241
+ ], AdminApi.prototype, "deleteWebsocketConfiguration", null);
242
+ __decorate([
243
+ AsDataEndpoint(Namespace.Connection, HttpMethod.Delete, ConnectionDeleteQuerySchema),
244
+ __metadata("design:type", Function),
245
+ __metadata("design:paramtypes", [Object]),
246
+ __metadata("design:returntype", Promise)
247
+ ], AdminApi.prototype, "deleteWebsocketConnection", null);
248
+ //# sourceMappingURL=DataApi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataApi.js","sourceRoot":"","sources":["../../src/module/DataApi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * TODO: add actual interface
3
+ * Interface for the admin api.
4
+ */
5
+ export interface IAdminApi {
6
+ }
@@ -0,0 +1,5 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ export {};
5
+ //# sourceMappingURL=interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interface.js","sourceRoot":"","sources":["../../src/module/interface.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,EAAE;AACF,sCAAsC"}
@@ -0,0 +1,140 @@
1
+ import type { BootstrapConfig, Call, CallAction, CallError, CallResult, CircuitBreakerOptions, CircuitBreakerState, ICache, IMessageConfirmation, IMessageHandler, IMessageRouter, IMessageSender, OcppRequest, OcppResponse, OCPPVersionType, SystemConfig } from '@citrineos/base';
2
+ import { AbstractMessageRouter, CircuitBreaker, MessageOrigin, OcppError, OCPPValidator, OCPPVersion } from '@citrineos/base';
3
+ import type { ILocationRepository } from '@citrineos/data';
4
+ import type { ILogObj } from 'tslog';
5
+ import { Logger } from 'tslog';
6
+ import { WebhookDispatcher } from './webhook.dispatcher.js';
7
+ /**
8
+ * Implementation of the ocpp router
9
+ */
10
+ export declare class MessageRouterImpl extends AbstractMessageRouter implements IMessageRouter {
11
+ /**
12
+ * Fields
13
+ */
14
+ private _webhookDispatcher;
15
+ protected _cache: ICache;
16
+ protected _sender: IMessageSender;
17
+ protected _handler: IMessageHandler;
18
+ protected _networkHook: (identifier: string, message: string) => Promise<void>;
19
+ protected _locationRepository: ILocationRepository;
20
+ protected _circuitBreaker: CircuitBreaker;
21
+ protected _reconnectInterval?: NodeJS.Timeout;
22
+ protected static readonly DEFAULT_MAX_RECONNECT_DELAY = 30;
23
+ protected _maxReconnectDelay: number;
24
+ protected _failingReconnectDelay: number;
25
+ private readonly _oidcTokenProvider?;
26
+ /**
27
+ * Constructor for the class.
28
+ *
29
+ * @param {BootstrapConfig & SystemConfig} config - the system configuration
30
+ * @param {ICache} cache - the cache object
31
+ * @param {IMessageSender} [sender] - the message sender
32
+ * @param {IMessageHandler} [handler] - the message handler
33
+ * @param {WebhookDispatcher} [dispatcher] - the webhook dispatcher
34
+ * @param {Function} networkHook - the network hook needed to send messages to chargers
35
+ * @param {ILocationRepository} [locationRepository] - An optional parameter of type {@link ILocationRepository} which
36
+ * represents a repository for accessing and manipulating variable data.
37
+ * If no `locationRepository` is provided, a default {@link locationRepository} instance is created and used.
38
+ * @param {Logger<ILogObj>} [logger] - the logger object (optional)
39
+ * @param {OCPPValidator} [ocppValidator] - the OCPPValidator instance, for message validation (optional)
40
+ * @param {CircuitBreakerOptions} [circuitBreakerOptions] - options to configure the circuit breaker
41
+ */
42
+ constructor(config: BootstrapConfig & SystemConfig, cache: ICache, sender: IMessageSender, handler: IMessageHandler, dispatcher: WebhookDispatcher, networkHook: (identifier: string, message: string) => Promise<void>, logger?: Logger<ILogObj>, ocppValidator?: OCPPValidator, locationRepository?: ILocationRepository, circuitBreakerOptions?: CircuitBreakerOptions);
43
+ doesChargingStationExistByStationId(tenantId: number, stationId: string): Promise<boolean>;
44
+ registerConnection(tenantId: number, stationId: string, protocol: OCPPVersion): Promise<boolean>;
45
+ deregisterConnection(tenantId: number, stationId: string): Promise<boolean>;
46
+ onMessage(identifier: string, message: string, timestamp: Date, protocol: OCPPVersionType): Promise<boolean>;
47
+ /**
48
+ * Sends a Call message to a charging station with given identifier.
49
+ *
50
+ * @param {string} stationId - The identifier of the station.
51
+ * @param {number} tenantId - The identifier of the tenant.
52
+ * @param {OCPPVersionType} protocol The OCPP protocol version of the message.
53
+ * @param {CallAction} action - The action to be called.
54
+ * @param {OcppRequest} payload - The payload of the call.
55
+ * @param {string} correlationId - The correlation ID of the message.
56
+ * @param {MessageOrigin} _origin - The origin of the message.
57
+ * @return {Promise<boolean>} A promise that resolves to a boolean indicating if the call was sent successfully.
58
+ */
59
+ sendCall(stationId: string, tenantId: number, protocol: OCPPVersionType, action: CallAction, payload: OcppRequest, correlationId?: string, _origin?: MessageOrigin): Promise<IMessageConfirmation>;
60
+ /**
61
+ * Sends the CallResult to a charging station with given identifier.
62
+ *
63
+ * @param {string} correlationId - The correlation ID of the message.
64
+ * @param {string} stationId - The identifier of the charging station.
65
+ * @param {number} tenantId - The identifier of the tenant.
66
+ * @param {OCPPVersionType} protocol The OCPP protocol version of the message.
67
+ * @param {CallAction} action - The action to be called.
68
+ * @param {OcppRequest} payload - The payload of the call.
69
+ * @param {MessageOrigin} _origin - The origin of the message.
70
+ * @return {Promise<boolean>} A promise that resolves to true if the call result was sent successfully, or false otherwise.
71
+ */
72
+ sendCallResult(correlationId: string, stationId: string, tenantId: number, protocol: OCPPVersionType, action: CallAction, payload: OcppResponse, _origin?: MessageOrigin): Promise<IMessageConfirmation>;
73
+ /**
74
+ * Sends a CallError message to a charging station with given identifier.
75
+ *
76
+ * @param {string} correlationId - The correlation ID of the message.
77
+ * @param {string} stationId - The identifier of the charging station.
78
+ * @param {number} tenantId - The identifier of the tenant.
79
+ * @param {OCPPVersionType} protocol The OCPP protocol version of the message.
80
+ * @param {CallAction} _action - The action to be called.
81
+ * @param {OcppError} error - The error of the call.
82
+ * @param {MessageOrigin} _origin - The origin of the message.
83
+ * @return {Promise<boolean>} - A promise that resolves to true if the message was sent successfully.
84
+ */
85
+ sendCallError(correlationId: string, stationId: string, tenantId: number, protocol: OCPPVersionType, action: CallAction, error: OcppError, _origin?: MessageOrigin | undefined): Promise<IMessageConfirmation>;
86
+ shutdown(): Promise<void>;
87
+ /**
88
+ * Private Methods
89
+ */
90
+ /**
91
+ * Handles an incoming Call message from a client connection.
92
+ *
93
+ * @param {string} identifier - The client identifier.
94
+ * @param {Call} message - The Call message received.
95
+ * @param {Date} timestamp Time at which the message was received from the charger.
96
+ * @param {string} protocol The OCPP protocol version of the message
97
+ * @return {void}
98
+ */
99
+ _onCall(identifier: string, message: Call, timestamp: Date, protocol: OCPPVersionType): Promise<void>;
100
+ /**
101
+ * Handles a CallResult made by the client.
102
+ *
103
+ * @param {string} identifier - The client identifier that made the call.
104
+ * @param {CallResult} message - The OCPP CallResult message.
105
+ * @param {Date} timestamp Time at which the message was received from the charger.
106
+ * @param {OCPPVersionType} protocol The OCPP protocol version of the message
107
+ */
108
+ _onCallResult(identifier: string, message: CallResult, timestamp: Date, protocol: OCPPVersionType): Promise<void>;
109
+ /**
110
+ * Handles the CallError that may have occured during a Call exchange.
111
+ *
112
+ * @param {string} identifier - The client identifier.
113
+ * @param {CallError} message - The error message.
114
+ * @param {Date} timestamp Time at which the message was received from the charger.
115
+ * @param {OCPPVersionType} protocol The OCPP protocol version of the message
116
+ */
117
+ _onCallError(identifier: string, message: CallError, timestamp: Date, protocol: OCPPVersionType): Promise<void>;
118
+ /**
119
+ * Determine if the given action for identifier is allowed.
120
+ *
121
+ * @param {CallAction} action - The action to be checked.
122
+ * @param {string} identifier - The identifier to be checked.
123
+ * @return {Promise<boolean>} A promise that resolves to a boolean indicating if the action and identifier are allowed.
124
+ */
125
+ private _onCallIsAllowed;
126
+ private _sendMessage;
127
+ private _sendCallIsAllowed;
128
+ private _routeCall;
129
+ private _routeCallResult;
130
+ private _routeCallError;
131
+ private emitMessage;
132
+ private _handleMessageApiCallback;
133
+ protected handleCircuitBreakerStateChange(state: CircuitBreakerState, reason?: string): void;
134
+ private _attemptExponentialReconnect;
135
+ protected onCircuitBreakerClosed(reason?: string): void;
136
+ protected onCircuitBreakerOpen(): void;
137
+ protected onBrokerDisconnect(reason?: string): void;
138
+ protected onBrokerReconnect(): void;
139
+ private getActionFromIncompletelyParsedRpcMessage;
140
+ }