@zetra/citrineos-evdriver 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.
- package/dist/index.d.ts +5 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/module/1.6/MessageApi.d.ts +29 -0
- package/dist/module/1.6/MessageApi.js +79 -0
- package/dist/module/1.6/MessageApi.js.map +1 -0
- package/dist/module/2.0.1/MessageApi.d.ts +33 -0
- package/dist/module/2.0.1/MessageApi.js +246 -0
- package/dist/module/2.0.1/MessageApi.js.map +1 -0
- package/dist/module/DataApi.d.ts +29 -0
- package/dist/module/DataApi.js +53 -0
- package/dist/module/DataApi.js.map +1 -0
- package/dist/module/LocalAuthListService.d.ts +21 -0
- package/dist/module/LocalAuthListService.js +108 -0
- package/dist/module/LocalAuthListService.js.map +1 -0
- package/dist/module/interface.d.ts +5 -0
- package/dist/module/interface.js +5 -0
- package/dist/module/interface.js.map +1 -0
- package/dist/module/module.d.ts +127 -0
- package/dist/module/module.js +706 -0
- package/dist/module/module.js.map +1 -0
- package/package.json +25 -0
|
@@ -0,0 +1,706 @@
|
|
|
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 { AbstractModule, AsHandler, AuthorizationStatusEnum, ChargingLimitSourceEnum, ChargingStationSequenceTypeEnum, ErrorCode, EventGroup, MessageOrigin, OCPP1_6, OCPP1_6_CallAction, OCPP2_0_1, OCPP2_0_1_CallAction, OcppError, OCPPValidator, OCPPVersion, } from '@citrineos/base';
|
|
11
|
+
import { Authorization, OCPP1_6_Mapper, OCPP2_0_1_Mapper, sequelize, SequelizeChargingStationSequenceRepository, Tariff, VariableAttribute, } from '@citrineos/data';
|
|
12
|
+
import { CertificateAuthorityService, IdGenerator, RabbitMqReceiver, RabbitMqSender, RealTimeAuthorizer, validateIdToken, } from '@citrineos/util';
|
|
13
|
+
import { Logger } from 'tslog';
|
|
14
|
+
import { LocalAuthListService } from './LocalAuthListService.js';
|
|
15
|
+
/**
|
|
16
|
+
* Component that handles provisioning related messages.
|
|
17
|
+
*/
|
|
18
|
+
export class EVDriverModule extends AbstractModule {
|
|
19
|
+
/**
|
|
20
|
+
* Fields
|
|
21
|
+
*/
|
|
22
|
+
_requests = [];
|
|
23
|
+
_responses = [];
|
|
24
|
+
_tariffRepository;
|
|
25
|
+
_locationRepository;
|
|
26
|
+
_certificateAuthorityService;
|
|
27
|
+
_authorizers;
|
|
28
|
+
_idGenerator;
|
|
29
|
+
/**
|
|
30
|
+
* This is the constructor function that initializes the {@link EVDriverModule}.
|
|
31
|
+
*
|
|
32
|
+
* @param {BootstrapConfig & SystemConfig} config - The `config` contains configuration settings for the module.
|
|
33
|
+
*
|
|
34
|
+
* @param {ICache} [cache] - The cache instance which is shared among the modules & Central System to pass information such as blacklisted actions or boot status.
|
|
35
|
+
*
|
|
36
|
+
* @param {IMessageSender} [sender] - The `sender` parameter is an optional parameter that represents an instance of the {@link IMessageSender} interface.
|
|
37
|
+
* It is used to send messages from the central system to external systems or devices. If no `sender` is provided, a default {@link RabbitMqSender} instance is created and used.
|
|
38
|
+
*
|
|
39
|
+
* @param {IMessageHandler} [handler] - The `handler` parameter is an optional parameter that represents an instance of the {@link IMessageHandler} interface.
|
|
40
|
+
* It is used to handle incoming messages and dispatch them to the appropriate methods or functions. If no `handler` is provided, a default {@link RabbitMqReceiver} instance is created and used.
|
|
41
|
+
*
|
|
42
|
+
* @param {Logger<ILogObj>} [logger] - The `logger` parameter is an optional parameter that represents an instance of {@link Logger<ILogObj>}.
|
|
43
|
+
* It is used to propagate system wide logger settings and will serve as the parent logger for any sub-component logging. If no `logger` is provided, a default {@link Logger<ILogObj>} instance is created and used.
|
|
44
|
+
*
|
|
45
|
+
* @param {IAuthorizationRepository} [authorizeRepository] - An optional parameter of type {@link IAuthorizationRepository} which represents a repository for accessing and manipulating Authorization data.
|
|
46
|
+
* If no `authorizeRepository` is provided, a default {@link sequelize:AuthorizationRepository} instance is created and used.
|
|
47
|
+
*
|
|
48
|
+
* @param {ILocalAuthListRepository} [localAuthListRepository] - An optional parameter of type {@link ILocalAuthListRepository} which represents a repository for accessing and manipulating Local Authorization List data.
|
|
49
|
+
* If no `localAuthListRepository` is provided, a default {@link sequelize:localAuthListRepository} instance is created and used.
|
|
50
|
+
*
|
|
51
|
+
* @param {IDeviceModelRepository} [deviceModelRepository] - An optional parameter of type {@link IDeviceModelRepository} which represents a repository for accessing and manipulating variable data.
|
|
52
|
+
* If no `deviceModelRepository` is provided, a default {@link sequelize:deviceModelRepository} instance is
|
|
53
|
+
* created and used.
|
|
54
|
+
*
|
|
55
|
+
* @param {ITariffRepository} [tariffRepository] - An optional parameter of type {@link ITariffRepository} which
|
|
56
|
+
* represents a repository for accessing and manipulating variable data.
|
|
57
|
+
* If no `deviceModelRepository` is provided, a default {@link sequelize:tariffRepository} instance is
|
|
58
|
+
* created and used.
|
|
59
|
+
*
|
|
60
|
+
* @param {ITransactionEventRepository} [transactionEventRepository] - An optional parameter of type {@link ITransactionEventRepository}
|
|
61
|
+
* which represents a repository for accessing and manipulating transaction data.
|
|
62
|
+
* If no `transactionEventRepository` is provided, a default {@link sequelize:transactionEventRepository} instance is
|
|
63
|
+
* created and used.
|
|
64
|
+
*
|
|
65
|
+
* @param {IChargingProfileRepository} [chargingProfileRepository] - An optional parameter of type {@link IChargingProfileRepository}
|
|
66
|
+
* which represents a repository for accessing and manipulating charging profile data.
|
|
67
|
+
* If no `chargingProfileRepository` is provided, a default {@link sequelize:chargingProfileRepository} instance is created and used.
|
|
68
|
+
*
|
|
69
|
+
* @param {IReservationRepository} [reservationRepository] - An optional parameter of type {@link IReservationRepository}
|
|
70
|
+
* which represents a repository for accessing and manipulating reservation data.
|
|
71
|
+
* If no `reservationRepository` is provided, a default {@link sequelize:reservationRepository} instance is created and used.
|
|
72
|
+
*
|
|
73
|
+
* @param {IOCPPMessageRepository} [ocppMessageRepository] - An optional parameter of type {@link IOCPPMessageRepository}
|
|
74
|
+
* which represents a repository for accessing and manipulating ocppMessage data.
|
|
75
|
+
* If no `ocppMessageRepository` is provided, a default {@link sequelize:ocppMessageRepository} instance is created and used.
|
|
76
|
+
*
|
|
77
|
+
* @param {ILocationRepository} [locationRepository] - An optional parameter of type {@link ILocationRepository} which represents a repository for accessing and manipulating location and charging station data.
|
|
78
|
+
* If no `locationRepository` is provided, a default {@link sequelize:locationRepository} instance is
|
|
79
|
+
* created and used.
|
|
80
|
+
*
|
|
81
|
+
* @param {CertificateAuthorityService} [certificateAuthorityService] - An optional parameter of
|
|
82
|
+
* type {@link CertificateAuthorityService} which handles certificate authority operations.
|
|
83
|
+
*
|
|
84
|
+
* @param {IAuthorizer} [realTimeAuthorizer] - An optional parameter of type {@link IAuthorizer} which represents
|
|
85
|
+
* a real-time authorizer that can be used to authorize real-time requests.
|
|
86
|
+
*
|
|
87
|
+
* @param {IAuthorizer[]} [authorizers] - An optional parameter of type {@link IAuthorizer[]} which represents
|
|
88
|
+
* a list of authorizers that can be used to authorize requests.
|
|
89
|
+
*
|
|
90
|
+
* @param {IdGenerator} [idGenerator] - An optional parameter of type {@link IdGenerator} which generates
|
|
91
|
+
* unique identifiers.
|
|
92
|
+
*/
|
|
93
|
+
constructor(config, cache, sender, handler, logger, ocppValidator, authorizeRepository, localAuthListRepository, deviceModelRepository, tariffRepository, transactionEventRepository, chargingProfileRepository, reservationRepository, ocppMessageRepository, locationRepository, certificateAuthorityService, realTimeAuthorizer, authorizers, idGenerator) {
|
|
94
|
+
super(config, cache, handler || new RabbitMqReceiver(config, logger), sender || new RabbitMqSender(config, logger), EventGroup.EVDriver, logger, ocppValidator);
|
|
95
|
+
this._requests = config.modules.evdriver.requests;
|
|
96
|
+
this._responses = config.modules.evdriver.responses;
|
|
97
|
+
this._authorizeRepository =
|
|
98
|
+
authorizeRepository || new sequelize.SequelizeAuthorizationRepository(config, logger);
|
|
99
|
+
this._localAuthListRepository =
|
|
100
|
+
localAuthListRepository || new sequelize.SequelizeLocalAuthListRepository(config, logger);
|
|
101
|
+
this._deviceModelRepository =
|
|
102
|
+
deviceModelRepository || new sequelize.SequelizeDeviceModelRepository(config, logger);
|
|
103
|
+
this._tariffRepository =
|
|
104
|
+
tariffRepository || new sequelize.SequelizeTariffRepository(config, logger);
|
|
105
|
+
this._transactionEventRepository =
|
|
106
|
+
transactionEventRepository ||
|
|
107
|
+
new sequelize.SequelizeTransactionEventRepository(config, logger);
|
|
108
|
+
this._chargingProfileRepository =
|
|
109
|
+
chargingProfileRepository || new sequelize.SequelizeChargingProfileRepository(config, logger);
|
|
110
|
+
this._reservationRepository =
|
|
111
|
+
reservationRepository || new sequelize.SequelizeReservationRepository(config, logger);
|
|
112
|
+
this._ocppMessageRepository =
|
|
113
|
+
ocppMessageRepository || new sequelize.SequelizeOCPPMessageRepository(config, logger);
|
|
114
|
+
this._locationRepository =
|
|
115
|
+
locationRepository || new sequelize.SequelizeLocationRepository(config, logger);
|
|
116
|
+
this._certificateAuthorityService =
|
|
117
|
+
certificateAuthorityService || new CertificateAuthorityService(config, cache, logger);
|
|
118
|
+
this._localAuthListService = new LocalAuthListService(this._localAuthListRepository, this._deviceModelRepository);
|
|
119
|
+
const _realTimeAuthorizer = realTimeAuthorizer ||
|
|
120
|
+
new RealTimeAuthorizer(this._locationRepository, this.config, this._logger);
|
|
121
|
+
this._authorizers = [_realTimeAuthorizer, ...(authorizers || [])];
|
|
122
|
+
this._idGenerator =
|
|
123
|
+
idGenerator ||
|
|
124
|
+
new IdGenerator(new SequelizeChargingStationSequenceRepository(config, this._logger));
|
|
125
|
+
}
|
|
126
|
+
_authorizeRepository;
|
|
127
|
+
get authorizeRepository() {
|
|
128
|
+
return this._authorizeRepository;
|
|
129
|
+
}
|
|
130
|
+
_localAuthListRepository;
|
|
131
|
+
get localAuthListRepository() {
|
|
132
|
+
return this._localAuthListRepository;
|
|
133
|
+
}
|
|
134
|
+
_deviceModelRepository;
|
|
135
|
+
get deviceModelRepository() {
|
|
136
|
+
return this._deviceModelRepository;
|
|
137
|
+
}
|
|
138
|
+
_transactionEventRepository;
|
|
139
|
+
get transactionEventRepository() {
|
|
140
|
+
return this._transactionEventRepository;
|
|
141
|
+
}
|
|
142
|
+
_chargingProfileRepository;
|
|
143
|
+
get chargingProfileRepository() {
|
|
144
|
+
return this._chargingProfileRepository;
|
|
145
|
+
}
|
|
146
|
+
_reservationRepository;
|
|
147
|
+
get reservationRepository() {
|
|
148
|
+
return this._reservationRepository;
|
|
149
|
+
}
|
|
150
|
+
_ocppMessageRepository;
|
|
151
|
+
get ocppMessageRepository() {
|
|
152
|
+
return this._ocppMessageRepository;
|
|
153
|
+
}
|
|
154
|
+
_localAuthListService;
|
|
155
|
+
get localAuthListService() {
|
|
156
|
+
return this._localAuthListService;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Handle OCPP 2.0.1 requests
|
|
160
|
+
*/
|
|
161
|
+
async _handleAuthorize(message, props) {
|
|
162
|
+
this._logger.debug('Authorize received:', message, props);
|
|
163
|
+
const request = message.payload;
|
|
164
|
+
const context = message.context;
|
|
165
|
+
const response = {
|
|
166
|
+
idTokenInfo: {
|
|
167
|
+
status: OCPP2_0_1.AuthorizationStatusEnumType.Unknown,
|
|
168
|
+
// TODO determine how/if to set personalMessage
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
// Validate ID token format after AJV schema validation, checking if the token conforms to expected type e.g if type is ISO14443, the token should be a hex string of even length
|
|
172
|
+
const tokenValidation = validateIdToken(request.idToken.type, request.idToken.idToken);
|
|
173
|
+
if (!tokenValidation.isValid) {
|
|
174
|
+
this._logger.warn(`Invalid ID token format`, {
|
|
175
|
+
type: request.idToken.type,
|
|
176
|
+
token: request.idToken.idToken,
|
|
177
|
+
error: tokenValidation.errorMessage,
|
|
178
|
+
});
|
|
179
|
+
const messageId = message.context.correlationId;
|
|
180
|
+
const error = new OcppError(messageId, ErrorCode.PropertyConstraintViolation, tokenValidation.errorMessage || 'Invalid token value for specified type');
|
|
181
|
+
response.idTokenInfo.status = OCPP2_0_1.AuthorizationStatusEnumType.Invalid;
|
|
182
|
+
this._logger.error('Token validation failed:', tokenValidation.errorMessage);
|
|
183
|
+
await this.sendCallErrorWithMessage(message, error);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (message.payload.idToken.type === OCPP2_0_1.IdTokenEnumType.NoAuthorization) {
|
|
187
|
+
response.idTokenInfo.status = OCPP2_0_1.AuthorizationStatusEnumType.Accepted;
|
|
188
|
+
await this.sendCallResultWithMessage(message, response);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
// Validate Contract Certificates based on OCPP 2.0.1 Part 2 C07
|
|
192
|
+
if (request.iso15118CertificateHashData || request.certificate) {
|
|
193
|
+
// TODO - implement validation using cached OCSP data described in C07.FR.05
|
|
194
|
+
if (request.iso15118CertificateHashData && request.iso15118CertificateHashData.length > 0) {
|
|
195
|
+
response.certificateStatus =
|
|
196
|
+
await this._certificateAuthorityService.validateCertificateHashData(request.iso15118CertificateHashData);
|
|
197
|
+
}
|
|
198
|
+
// If Charging Station is not able to validate a contract certificate,
|
|
199
|
+
// it SHALL pass the contract certificate chain to the CSMS in certificate attribute (in PEM
|
|
200
|
+
// format) of AuthorizeRequest for validation by CSMS, see C07.FR.06
|
|
201
|
+
if (request.certificate) {
|
|
202
|
+
response.certificateStatus =
|
|
203
|
+
await this._certificateAuthorityService.validateCertificateChainPem(request.certificate);
|
|
204
|
+
}
|
|
205
|
+
if (response.certificateStatus !== OCPP2_0_1.AuthorizeCertificateStatusEnumType.Accepted) {
|
|
206
|
+
response.idTokenInfo.status = OCPP2_0_1.AuthorizationStatusEnumType.Invalid;
|
|
207
|
+
const messageConfirmation = await this.sendCallResultWithMessage(message, response);
|
|
208
|
+
this._logger.debug('Authorize response sent:', messageConfirmation);
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const authorization = await this._authorizeRepository.readOnlyOneByQuerystring(context.tenantId, {
|
|
213
|
+
idToken: request.idToken.idToken,
|
|
214
|
+
type: OCPP2_0_1_Mapper.AuthorizationMapper.fromIdTokenEnumType(request.idToken.type),
|
|
215
|
+
});
|
|
216
|
+
if (authorization) {
|
|
217
|
+
// Use flat fields directly instead of authorization.idTokenInfo
|
|
218
|
+
const idTokenInfo = OCPP2_0_1_Mapper.AuthorizationMapper.toIdTokenInfo(authorization);
|
|
219
|
+
if (idTokenInfo.status === OCPP2_0_1.AuthorizationStatusEnumType.Accepted) {
|
|
220
|
+
if (idTokenInfo.cacheExpiryDateTime &&
|
|
221
|
+
new Date() > new Date(idTokenInfo.cacheExpiryDateTime)) {
|
|
222
|
+
response.idTokenInfo = {
|
|
223
|
+
status: OCPP2_0_1.AuthorizationStatusEnumType.Invalid,
|
|
224
|
+
groupIdToken: idTokenInfo.groupIdToken,
|
|
225
|
+
// TODO determine how/if to set personalMessage
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// If charging station does not have values and evses associated with the component/variable pairs below,
|
|
230
|
+
// this logic will break. CSMS's aiming to use the allowedConnectorTypes or disallowedEvseIdPrefixes
|
|
231
|
+
// Authorization restrictions MUST provide these variable attributes as defined in Physical Component
|
|
232
|
+
// list of Part 2 - Appendices of OCPP 2.0.1
|
|
233
|
+
let evseIds = undefined;
|
|
234
|
+
if (authorization.allowedConnectorTypes &&
|
|
235
|
+
authorization.allowedConnectorTypes.length > 0) {
|
|
236
|
+
evseIds = new Set();
|
|
237
|
+
const connectorTypes = await this._deviceModelRepository.readAllByQuerystring(context.tenantId, {
|
|
238
|
+
tenantId: context.tenantId,
|
|
239
|
+
stationId: message.context.stationId,
|
|
240
|
+
component_name: 'Connector',
|
|
241
|
+
variable_name: 'ConnectorType',
|
|
242
|
+
type: OCPP2_0_1.AttributeEnumType.Actual,
|
|
243
|
+
});
|
|
244
|
+
for (const connectorType of connectorTypes) {
|
|
245
|
+
if (authorization.allowedConnectorTypes.indexOf(connectorType.value) > 0) {
|
|
246
|
+
evseIds.add(connectorType.evse?.id);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if (evseIds && evseIds.size === 0) {
|
|
251
|
+
response.idTokenInfo = {
|
|
252
|
+
status: OCPP2_0_1.AuthorizationStatusEnumType.NotAllowedTypeEVSE,
|
|
253
|
+
groupIdToken: idTokenInfo.groupIdToken,
|
|
254
|
+
// TODO determine how/if to set personalMessage
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
if (authorization.disallowedEvseIdPrefixes &&
|
|
259
|
+
authorization.disallowedEvseIdPrefixes.length > 0) {
|
|
260
|
+
evseIds = evseIds ? evseIds : new Set();
|
|
261
|
+
const evseIdAttributes = await this._deviceModelRepository.readAllByQuerystring(context.tenantId, {
|
|
262
|
+
tenantId: context.tenantId,
|
|
263
|
+
stationId: message.context.stationId,
|
|
264
|
+
component_name: 'EVSE',
|
|
265
|
+
variable_name: 'EvseId',
|
|
266
|
+
type: OCPP2_0_1.AttributeEnumType.Actual,
|
|
267
|
+
});
|
|
268
|
+
for (const evseIdAttribute of evseIdAttributes) {
|
|
269
|
+
const evseIdAllowed = authorization.disallowedEvseIdPrefixes.some((disallowedEvseId) => evseIdAttribute.value.startsWith(disallowedEvseId));
|
|
270
|
+
if (evseIdAllowed && !authorization.allowedConnectorTypes) {
|
|
271
|
+
evseIds.add(evseIdAttribute.evse?.id);
|
|
272
|
+
}
|
|
273
|
+
else if (!evseIdAllowed && authorization.allowedConnectorTypes) {
|
|
274
|
+
evseIds.delete(evseIdAttribute.evse?.id);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (evseIds && evseIds.size === 0) {
|
|
279
|
+
response.idTokenInfo = {
|
|
280
|
+
status: OCPP2_0_1.AuthorizationStatusEnumType.NotAtThisLocation,
|
|
281
|
+
groupIdToken: idTokenInfo.groupIdToken,
|
|
282
|
+
// TODO determine how/if to set personalMessage
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
// TODO: Determine how to check for NotAtThisTime
|
|
287
|
+
response.idTokenInfo = idTokenInfo;
|
|
288
|
+
const evseId = [...(evseIds ? evseIds.values() : [])];
|
|
289
|
+
if (evseId.length > 0) {
|
|
290
|
+
response.idTokenInfo.evseId = [evseId.pop(), ...evseId];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
for (const authorizer of this._authorizers) {
|
|
296
|
+
if (response.idTokenInfo.status !== OCPP2_0_1.AuthorizationStatusEnumType.Accepted) {
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
const result = await authorizer.authorize(authorization, context);
|
|
300
|
+
response.idTokenInfo.status =
|
|
301
|
+
OCPP2_0_1_Mapper.AuthorizationMapper.fromAuthorizationStatusEnumType(result);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
// Blocked, Expired, Invalid, NoCredit, Unknown
|
|
306
|
+
response.idTokenInfo = idTokenInfo;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
// Status is Unknown if no authorization found
|
|
311
|
+
response.idTokenInfo = {
|
|
312
|
+
status: OCPP2_0_1.AuthorizationStatusEnumType.Unknown,
|
|
313
|
+
// TODO determine how/if to set personalMessage
|
|
314
|
+
};
|
|
315
|
+
const messageConfirmation = await this.sendCallResultWithMessage(message, response);
|
|
316
|
+
this._logger.debug('Authorize response sent:', messageConfirmation);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (response.idTokenInfo.status === OCPP2_0_1.AuthorizationStatusEnumType.Accepted) {
|
|
320
|
+
const tariffAvailable = await this._deviceModelRepository.readAllByQuerystring(context.tenantId, {
|
|
321
|
+
tenantId: context.tenantId,
|
|
322
|
+
stationId: message.context.stationId,
|
|
323
|
+
component_name: 'TariffCostCtrlr',
|
|
324
|
+
variable_name: 'Available',
|
|
325
|
+
variable_instance: 'Tariff',
|
|
326
|
+
type: OCPP2_0_1.AttributeEnumType.Actual,
|
|
327
|
+
});
|
|
328
|
+
const displayMessageAvailable = await this._deviceModelRepository.readAllByQuerystring(context.tenantId, {
|
|
329
|
+
tenantId: context.tenantId,
|
|
330
|
+
stationId: message.context.stationId,
|
|
331
|
+
component_name: 'DisplayMessageCtrlr',
|
|
332
|
+
variable_name: 'Available',
|
|
333
|
+
type: OCPP2_0_1.AttributeEnumType.Actual,
|
|
334
|
+
});
|
|
335
|
+
// only send the tariff information if the Charging Station supports the tariff or DisplayMessage functionality
|
|
336
|
+
if ((tariffAvailable.length > 0 && Boolean(tariffAvailable[0].value)) ||
|
|
337
|
+
(displayMessageAvailable.length > 0 && Boolean(displayMessageAvailable[0].value))) {
|
|
338
|
+
// TODO: refactor the workaround below after tariff implementation is finalized.
|
|
339
|
+
const tariff = await this._tariffRepository.findByStationId(context.tenantId, message.context.stationId);
|
|
340
|
+
if (tariff) {
|
|
341
|
+
if (!response.idTokenInfo.personalMessage) {
|
|
342
|
+
response.idTokenInfo.personalMessage = {
|
|
343
|
+
format: OCPP2_0_1.MessageFormatEnumType.ASCII,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
response.idTokenInfo.personalMessage.content = `${tariff.pricePerKwh}/kWh`;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
const messageConfirmation = await this.sendCallResultWithMessage(message, response);
|
|
351
|
+
this._logger.debug('Authorize response sent:', messageConfirmation);
|
|
352
|
+
}
|
|
353
|
+
async _handleReservationStatusUpdate(message, props) {
|
|
354
|
+
this._logger.debug('ReservationStatusUpdateRequest received:', message, props);
|
|
355
|
+
try {
|
|
356
|
+
const status = message.payload
|
|
357
|
+
.reservationUpdateStatus;
|
|
358
|
+
const reservation = await this._reservationRepository.readOnlyOneByQuery(message.context.tenantId, {
|
|
359
|
+
where: {
|
|
360
|
+
tenantId: message.context.tenantId,
|
|
361
|
+
stationId: message.context.stationId,
|
|
362
|
+
id: message.payload.reservationId,
|
|
363
|
+
},
|
|
364
|
+
});
|
|
365
|
+
if (reservation) {
|
|
366
|
+
if (status === OCPP2_0_1.ReservationUpdateStatusEnumType.Expired ||
|
|
367
|
+
status === OCPP2_0_1.ReservationUpdateStatusEnumType.Removed) {
|
|
368
|
+
await this._reservationRepository.updateByKey(message.context.tenantId, {
|
|
369
|
+
isActive: false,
|
|
370
|
+
}, reservation.databaseId.toString());
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
throw new Error(`Reservation ${message.payload.reservationId} not found`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
catch (error) {
|
|
378
|
+
this._logger.error('Error reading reservation:', error);
|
|
379
|
+
}
|
|
380
|
+
// Create response
|
|
381
|
+
const response = {};
|
|
382
|
+
const messageConfirmation = await this.sendCallResultWithMessage(message, response);
|
|
383
|
+
this._logger.debug('ReservationStatusUpdate response sent: ', messageConfirmation);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Handle OCPP 2.0.1 responses
|
|
387
|
+
*/
|
|
388
|
+
async _handleRequestStartTransaction(message, props) {
|
|
389
|
+
this._logger.debug('RequestStartTransactionResponse received:', message, props);
|
|
390
|
+
if (message.payload.status === OCPP2_0_1.RequestStartStopStatusEnumType.Accepted) {
|
|
391
|
+
// Start transaction with charging profile succeeds,
|
|
392
|
+
// we need to update db entity with the latest data from charger
|
|
393
|
+
const stationId = message.context.stationId;
|
|
394
|
+
// 1. Clear all existing profiles: find existing active profiles and set them to isActive false
|
|
395
|
+
await this._chargingProfileRepository.updateAllByQuery(message.context.tenantId, {
|
|
396
|
+
isActive: false,
|
|
397
|
+
}, {
|
|
398
|
+
where: {
|
|
399
|
+
stationId: stationId,
|
|
400
|
+
isActive: true,
|
|
401
|
+
chargingLimitSource: OCPP2_0_1.ChargingLimitSourceEnumType.CSO,
|
|
402
|
+
chargingProfilePurpose: OCPP2_0_1.ChargingProfilePurposeEnumType.TxProfile,
|
|
403
|
+
},
|
|
404
|
+
returning: false,
|
|
405
|
+
});
|
|
406
|
+
// 2. Request charging profiles to get the latest data
|
|
407
|
+
await this.sendCall(stationId, message.context.tenantId, OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.GetChargingProfiles, {
|
|
408
|
+
requestId: await this._idGenerator.generateRequestId(message.context.tenantId, message.context.stationId, ChargingStationSequenceTypeEnum.getChargingProfiles),
|
|
409
|
+
chargingProfile: {
|
|
410
|
+
chargingProfilePurpose: OCPP2_0_1.ChargingProfilePurposeEnumType.TxProfile,
|
|
411
|
+
chargingLimitSource: [OCPP2_0_1.ChargingLimitSourceEnumType.CSO],
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
this._logger.error(`RequestStartTransaction failed: ${JSON.stringify(message.payload)}`);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
async _handleRequestStopTransaction(message, props) {
|
|
420
|
+
this._logger.debug('RequestStopTransactionResponse received:', message, props);
|
|
421
|
+
}
|
|
422
|
+
async _handleCancelReservation(message, props) {
|
|
423
|
+
this._logger.debug('CancelReservationResponse received:', message, props);
|
|
424
|
+
const request = await this._ocppMessageRepository.readOnlyOneByQuery(message.context.tenantId, {
|
|
425
|
+
where: {
|
|
426
|
+
tenantId: message.context.tenantId,
|
|
427
|
+
stationId: message.context.stationId,
|
|
428
|
+
correlationId: message.context.correlationId,
|
|
429
|
+
origin: MessageOrigin.ChargingStationManagementSystem,
|
|
430
|
+
},
|
|
431
|
+
});
|
|
432
|
+
if (request) {
|
|
433
|
+
await this._reservationRepository.updateByKey(message.context.tenantId, {
|
|
434
|
+
isActive: message.payload.status === OCPP2_0_1.CancelReservationStatusEnumType.Rejected,
|
|
435
|
+
}, request.message[3].reservationId);
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
this._logger.error(`Update reservation failed. ReservationId not found by CorrelationId ${message.context.correlationId}.`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
async _handleReserveNow(message, props) {
|
|
442
|
+
this._logger.debug('ReserveNowResponse received:', message, props);
|
|
443
|
+
const request = await this._ocppMessageRepository.readOnlyOneByQuery(message.context.tenantId, {
|
|
444
|
+
where: {
|
|
445
|
+
tenantId: message.context.tenantId,
|
|
446
|
+
stationId: message.context.stationId,
|
|
447
|
+
correlationId: message.context.correlationId,
|
|
448
|
+
origin: MessageOrigin.ChargingStationManagementSystem,
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
if (request) {
|
|
452
|
+
const status = message.payload.status;
|
|
453
|
+
await this._reservationRepository.updateByKey(message.context.tenantId, {
|
|
454
|
+
reserveStatus: status,
|
|
455
|
+
isActive: status === OCPP2_0_1.ReserveNowStatusEnumType.Accepted,
|
|
456
|
+
}, request.message[3].id);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
this._logger.error(`Update reservation failed. ReservationId not found by CorrelationId ${message.context.correlationId}.`);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
async _handleUnlockConnector(message, props) {
|
|
463
|
+
this._logger.debug('UnlockConnectorResponse received:', message, props);
|
|
464
|
+
}
|
|
465
|
+
async _handleClearCache(message, props) {
|
|
466
|
+
this._logger.debug('ClearCacheResponse received:', message, props);
|
|
467
|
+
}
|
|
468
|
+
async _handleSendLocalList(message, props) {
|
|
469
|
+
this._logger.debug('SendLocalListResponse received:', message, props);
|
|
470
|
+
const stationId = message.context.stationId;
|
|
471
|
+
const sendLocalListRequest = await this._localAuthListRepository.getSendLocalListRequestByStationIdAndCorrelationId(message.context.tenantId, stationId, message.context.correlationId);
|
|
472
|
+
if (!sendLocalListRequest) {
|
|
473
|
+
this._logger.error(`Unable to process SendLocalListResponse. SendLocalListRequest not found for StationId ${stationId} by CorrelationId ${message.context.correlationId}.`);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const sendLocalListResponse = message.payload;
|
|
477
|
+
switch (sendLocalListResponse.status) {
|
|
478
|
+
case OCPP2_0_1.SendLocalListStatusEnumType.Accepted:
|
|
479
|
+
await this._localAuthListRepository.createOrUpdateLocalListVersionFromStationIdAndSendLocalList(message.context.tenantId, stationId, sendLocalListRequest);
|
|
480
|
+
break;
|
|
481
|
+
case OCPP2_0_1.SendLocalListStatusEnumType.Failed:
|
|
482
|
+
// TODO: Surface alert for upstream handling
|
|
483
|
+
this._logger.error(`SendLocalListRequest failed for StationId ${stationId}: ${message.context.correlationId}, ${JSON.stringify(sendLocalListRequest)}.`);
|
|
484
|
+
break;
|
|
485
|
+
case OCPP2_0_1.SendLocalListStatusEnumType.VersionMismatch: {
|
|
486
|
+
this._logger.error(`SendLocalListRequest version mismatch for StationId ${stationId}: ${message.context.correlationId}, ${JSON.stringify(sendLocalListRequest)}.`);
|
|
487
|
+
this._logger.error(`Sending GetLocalListVersionRequest for StationId ${stationId} due to SendLocalListRequest version mismatch.`);
|
|
488
|
+
const messageConfirmation = await this.sendCall(stationId, message.context.tenantId, OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.GetLocalListVersion, {});
|
|
489
|
+
if (!messageConfirmation.success) {
|
|
490
|
+
this._logger.error(`Unable to send GetLocalListVersionRequest for StationId ${stationId} due to SendLocalListRequest version mismatch.`, messageConfirmation);
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
default:
|
|
495
|
+
this._logger.error(`Unknown SendLocalListStatusEnumType: ${sendLocalListResponse.status}.`);
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
async _handleGetLocalListVersion(message, props) {
|
|
500
|
+
this._logger.debug('GetLocalListVersionResponse received:', message, props);
|
|
501
|
+
await this._localAuthListRepository.validateOrReplaceLocalListVersionForStation(message.context.tenantId, message.payload.versionNumber, message.context.stationId);
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Handle OCPP 1.6 responses
|
|
505
|
+
*/
|
|
506
|
+
async _handleOcpp16RemoteStopTransaction(message, props) {
|
|
507
|
+
this._logger.debug('RemoteStopTransactionResponse received:', message, props);
|
|
508
|
+
}
|
|
509
|
+
async _handleOCPP16Authorize(message, props) {
|
|
510
|
+
this._logger.debug('OCPP 16 Authorize received: ', message, props);
|
|
511
|
+
const request = message.payload;
|
|
512
|
+
const context = message.context;
|
|
513
|
+
// Default response: Invalid
|
|
514
|
+
const response = {
|
|
515
|
+
idTagInfo: {
|
|
516
|
+
status: OCPP1_6.AuthorizeResponseStatus.Invalid,
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
try {
|
|
520
|
+
const authorizations = await this._authorizeRepository.readAllByQuerystring(context.tenantId, {
|
|
521
|
+
idToken: request.idTag,
|
|
522
|
+
});
|
|
523
|
+
if (!authorizations || authorizations.length === 0) {
|
|
524
|
+
this._logger.error(`No authorization found for idToken: ${request.idTag}`);
|
|
525
|
+
//below line is just to make it more explicit. Default status is already invalid.
|
|
526
|
+
response.idTagInfo.status = OCPP1_6.AuthorizeResponseStatus.Invalid;
|
|
527
|
+
await this.sendCallResultWithMessage(message, response);
|
|
528
|
+
this._logger.debug('Authorize response sent:', response);
|
|
529
|
+
return;
|
|
530
|
+
}
|
|
531
|
+
// If we find more than one token for an idTag it's too opinionated on how to define which one is valid.
|
|
532
|
+
// For now, we error out, and implementers should change this according to their needs.
|
|
533
|
+
if (authorizations.length > 1) {
|
|
534
|
+
this._logger.error(`Too many authorizations found for idToken: ${request.idTag}`);
|
|
535
|
+
response.idTagInfo.status = OCPP1_6.AuthorizeResponseStatus.Invalid;
|
|
536
|
+
await this.sendCallResultWithMessage(message, response);
|
|
537
|
+
this._logger.debug('Authorize response sent:', response);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const authorization = authorizations[0];
|
|
541
|
+
if (!authorization.status) {
|
|
542
|
+
response.idTagInfo.status = OCPP1_6.AuthorizeResponseStatus.Accepted;
|
|
543
|
+
}
|
|
544
|
+
else if (authorization.status === AuthorizationStatusEnum.Accepted) {
|
|
545
|
+
const cacheExpiryDateTime = authorization.cacheExpiryDateTime;
|
|
546
|
+
const groupAuthorizationId = authorization.groupAuthorizationId;
|
|
547
|
+
response.idTagInfo.expiryDate = cacheExpiryDateTime;
|
|
548
|
+
if (groupAuthorizationId) {
|
|
549
|
+
// Look up the referenced Authorization for parentIdTag
|
|
550
|
+
const parentAuth = await this._authorizeRepository.readOnlyOneByQuery(message.context.tenantId, { where: { id: groupAuthorizationId } });
|
|
551
|
+
if (parentAuth) {
|
|
552
|
+
response.idTagInfo.parentIdTag = parentAuth.idToken;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (cacheExpiryDateTime && new Date() > new Date(cacheExpiryDateTime)) {
|
|
556
|
+
response.idTagInfo.status = OCPP1_6.AuthorizeResponseStatus.Expired;
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
// Apply authorizers
|
|
560
|
+
let status = authorization.status;
|
|
561
|
+
for (const authorizer of this._authorizers) {
|
|
562
|
+
if (status !== AuthorizationStatusEnum.Accepted) {
|
|
563
|
+
break;
|
|
564
|
+
}
|
|
565
|
+
status = await authorizer.authorize(authorization, context);
|
|
566
|
+
}
|
|
567
|
+
response.idTagInfo.status = OCPP1_6_Mapper.AuthorizationMapper.toIdTagInfoStatus(status);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
catch (error) {
|
|
572
|
+
// Log any unexpected errors
|
|
573
|
+
this._logger.error(`Failed to retrieve authorization for idToken '${request.idTag}':`, error);
|
|
574
|
+
// response remains "Invalid" by default
|
|
575
|
+
}
|
|
576
|
+
await this.sendCallResultWithMessage(message, response).then((messageConfirmation) => {
|
|
577
|
+
this._logger.debug('Authorize response sent:', messageConfirmation);
|
|
578
|
+
});
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
async _handleRemoteStartTransaction(message, props) {
|
|
582
|
+
this._logger.debug('RemoteStartTransactionResponse received:', message, props);
|
|
583
|
+
const tenantId = message.context.tenantId;
|
|
584
|
+
const stationId = message.context.stationId;
|
|
585
|
+
if (message.payload.status === OCPP1_6.RemoteStartTransactionResponseStatus.Accepted) {
|
|
586
|
+
const originalMessage = await this._ocppMessageRepository.readOnlyOneByQuery(tenantId, {
|
|
587
|
+
where: {
|
|
588
|
+
tenantId: tenantId,
|
|
589
|
+
stationId: stationId,
|
|
590
|
+
correlationId: message.context.correlationId,
|
|
591
|
+
origin: MessageOrigin.ChargingStationManagementSystem,
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
if (originalMessage) {
|
|
595
|
+
const originalRequest = originalMessage.message[3];
|
|
596
|
+
if (originalRequest.chargingProfile) {
|
|
597
|
+
const mapped = OCPP1_6_Mapper.ChargingProfileMapper.fromRemoteStartChargingProfile(originalRequest.chargingProfile);
|
|
598
|
+
await this._chargingProfileRepository.createOrUpdateChargingProfile(tenantId, mapped, stationId, originalRequest.connectorId ?? null, ChargingLimitSourceEnum.CSO, true);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
this._logger.error(`OCPP 1.6 RemoteStartTransaction accepted but original request not found by CorrelationId ${message.context.correlationId}.`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
this._logger.error(`OCPP 1.6 RemoteStartTransaction rejected: ${JSON.stringify(message.payload)}`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
async _handleOcpp16ClearCache(message, props) {
|
|
610
|
+
this._logger.debug('ClearCacheResponse received:', message, props);
|
|
611
|
+
}
|
|
612
|
+
_updateAuthorizationFromDto(auth, dto) {
|
|
613
|
+
for (const key of Object.keys(dto)) {
|
|
614
|
+
const value = dto[key];
|
|
615
|
+
if (value !== undefined && value !== null) {
|
|
616
|
+
auth[key] = value;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return auth;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
__decorate([
|
|
623
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.Authorize),
|
|
624
|
+
__metadata("design:type", Function),
|
|
625
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
626
|
+
__metadata("design:returntype", Promise)
|
|
627
|
+
], EVDriverModule.prototype, "_handleAuthorize", null);
|
|
628
|
+
__decorate([
|
|
629
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.ReservationStatusUpdate),
|
|
630
|
+
__metadata("design:type", Function),
|
|
631
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
632
|
+
__metadata("design:returntype", Promise)
|
|
633
|
+
], EVDriverModule.prototype, "_handleReservationStatusUpdate", null);
|
|
634
|
+
__decorate([
|
|
635
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.RequestStartTransaction),
|
|
636
|
+
__metadata("design:type", Function),
|
|
637
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
638
|
+
__metadata("design:returntype", Promise)
|
|
639
|
+
], EVDriverModule.prototype, "_handleRequestStartTransaction", null);
|
|
640
|
+
__decorate([
|
|
641
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.RequestStopTransaction),
|
|
642
|
+
__metadata("design:type", Function),
|
|
643
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
644
|
+
__metadata("design:returntype", Promise)
|
|
645
|
+
], EVDriverModule.prototype, "_handleRequestStopTransaction", null);
|
|
646
|
+
__decorate([
|
|
647
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.CancelReservation),
|
|
648
|
+
__metadata("design:type", Function),
|
|
649
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
650
|
+
__metadata("design:returntype", Promise)
|
|
651
|
+
], EVDriverModule.prototype, "_handleCancelReservation", null);
|
|
652
|
+
__decorate([
|
|
653
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.ReserveNow),
|
|
654
|
+
__metadata("design:type", Function),
|
|
655
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
656
|
+
__metadata("design:returntype", Promise)
|
|
657
|
+
], EVDriverModule.prototype, "_handleReserveNow", null);
|
|
658
|
+
__decorate([
|
|
659
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.UnlockConnector),
|
|
660
|
+
__metadata("design:type", Function),
|
|
661
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
662
|
+
__metadata("design:returntype", Promise)
|
|
663
|
+
], EVDriverModule.prototype, "_handleUnlockConnector", null);
|
|
664
|
+
__decorate([
|
|
665
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.ClearCache),
|
|
666
|
+
__metadata("design:type", Function),
|
|
667
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
668
|
+
__metadata("design:returntype", Promise)
|
|
669
|
+
], EVDriverModule.prototype, "_handleClearCache", null);
|
|
670
|
+
__decorate([
|
|
671
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.SendLocalList),
|
|
672
|
+
__metadata("design:type", Function),
|
|
673
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
674
|
+
__metadata("design:returntype", Promise)
|
|
675
|
+
], EVDriverModule.prototype, "_handleSendLocalList", null);
|
|
676
|
+
__decorate([
|
|
677
|
+
AsHandler(OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.GetLocalListVersion),
|
|
678
|
+
__metadata("design:type", Function),
|
|
679
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
680
|
+
__metadata("design:returntype", Promise)
|
|
681
|
+
], EVDriverModule.prototype, "_handleGetLocalListVersion", null);
|
|
682
|
+
__decorate([
|
|
683
|
+
AsHandler(OCPPVersion.OCPP1_6, OCPP1_6_CallAction.RemoteStopTransaction),
|
|
684
|
+
__metadata("design:type", Function),
|
|
685
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
686
|
+
__metadata("design:returntype", Promise)
|
|
687
|
+
], EVDriverModule.prototype, "_handleOcpp16RemoteStopTransaction", null);
|
|
688
|
+
__decorate([
|
|
689
|
+
AsHandler(OCPPVersion.OCPP1_6, OCPP1_6_CallAction.Authorize),
|
|
690
|
+
__metadata("design:type", Function),
|
|
691
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
692
|
+
__metadata("design:returntype", Promise)
|
|
693
|
+
], EVDriverModule.prototype, "_handleOCPP16Authorize", null);
|
|
694
|
+
__decorate([
|
|
695
|
+
AsHandler(OCPPVersion.OCPP1_6, OCPP1_6_CallAction.RemoteStartTransaction),
|
|
696
|
+
__metadata("design:type", Function),
|
|
697
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
698
|
+
__metadata("design:returntype", Promise)
|
|
699
|
+
], EVDriverModule.prototype, "_handleRemoteStartTransaction", null);
|
|
700
|
+
__decorate([
|
|
701
|
+
AsHandler(OCPPVersion.OCPP1_6, OCPP1_6_CallAction.ClearCache),
|
|
702
|
+
__metadata("design:type", Function),
|
|
703
|
+
__metadata("design:paramtypes", [Object, Object]),
|
|
704
|
+
__metadata("design:returntype", Promise)
|
|
705
|
+
], EVDriverModule.prototype, "_handleOcpp16ClearCache", null);
|
|
706
|
+
//# sourceMappingURL=module.js.map
|