@zetra/citrineos-configuration 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 +34 -0
- package/dist/module/1.6/MessageApi.js +190 -0
- package/dist/module/1.6/MessageApi.js.map +1 -0
- package/dist/module/2.0.1/MessageApi.d.ts +38 -0
- package/dist/module/2.0.1/MessageApi.js +183 -0
- package/dist/module/2.0.1/MessageApi.js.map +1 -0
- package/dist/module/BootNotificationService.d.ts +57 -0
- package/dist/module/BootNotificationService.js +248 -0
- package/dist/module/BootNotificationService.js.map +1 -0
- package/dist/module/DataApi.d.ts +52 -0
- package/dist/module/DataApi.js +206 -0
- package/dist/module/DataApi.js.map +1 -0
- package/dist/module/DeviceModelService.d.ts +30 -0
- package/dist/module/DeviceModelService.js +122 -0
- package/dist/module/DeviceModelService.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 +110 -0
- package/dist/module/module.js +733 -0
- package/dist/module/module.js.map +1 -0
- package/package.json +25 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { Boot, OCPP1_6_Mapper, OCPP2_0_1_Mapper } from '@citrineos/data';
|
|
2
|
+
import { BOOT_STATUS, OCPP1_6, OCPP1_6_CALL_SCHEMA_MAP, OCPP1_6_CallAction, OCPP2_0_1, OCPP2_0_1_CALL_SCHEMA_MAP, OCPP2_0_1_CallAction, } from '@citrineos/base';
|
|
3
|
+
import { Logger } from 'tslog';
|
|
4
|
+
export class BootNotificationService {
|
|
5
|
+
_bootRepository;
|
|
6
|
+
_cache;
|
|
7
|
+
_logger;
|
|
8
|
+
_config;
|
|
9
|
+
constructor(bootRepository, cache, config, logger) {
|
|
10
|
+
this._bootRepository = bootRepository;
|
|
11
|
+
this._cache = cache;
|
|
12
|
+
this._config = config;
|
|
13
|
+
this._logger = logger
|
|
14
|
+
? logger.getSubLogger({ name: this.constructor.name })
|
|
15
|
+
: new Logger({ name: this.constructor.name });
|
|
16
|
+
}
|
|
17
|
+
determineBootStatus(bootConfig) {
|
|
18
|
+
let bootStatus = bootConfig
|
|
19
|
+
? OCPP2_0_1_Mapper.BootMapper.toRegistrationStatusEnumType(bootConfig.status)
|
|
20
|
+
: this._config.ocpp2_0_1.unknownChargerStatus;
|
|
21
|
+
if (bootStatus === OCPP2_0_1.RegistrationStatusEnumType.Pending) {
|
|
22
|
+
let needToGetBaseReport = this._config.ocpp2_0_1.getBaseReportOnPending;
|
|
23
|
+
let needToSetVariables = false;
|
|
24
|
+
if (bootConfig) {
|
|
25
|
+
if (bootConfig.getBaseReportOnPending !== undefined &&
|
|
26
|
+
bootConfig.getBaseReportOnPending !== null) {
|
|
27
|
+
needToGetBaseReport = bootConfig.getBaseReportOnPending;
|
|
28
|
+
}
|
|
29
|
+
if (bootConfig.pendingBootSetVariables && bootConfig.pendingBootSetVariables.length > 0) {
|
|
30
|
+
needToSetVariables = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (!needToGetBaseReport && !needToSetVariables && this._config.ocpp2_0_1.autoAccept) {
|
|
34
|
+
bootStatus = OCPP2_0_1.RegistrationStatusEnumType.Accepted;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return bootStatus;
|
|
38
|
+
}
|
|
39
|
+
async createBootNotificationResponse(tenantId, stationId) {
|
|
40
|
+
// Unknown chargers, chargers without a BootConfig, will use SystemConfig.unknownChargerStatus for status.
|
|
41
|
+
const bootConfig = await this._bootRepository.readByKey(tenantId, stationId);
|
|
42
|
+
const bootStatus = this.determineBootStatus(bootConfig);
|
|
43
|
+
// When any BootConfig field is not set, the corresponding field on the SystemConfig will be used.
|
|
44
|
+
return {
|
|
45
|
+
currentTime: new Date().toISOString(),
|
|
46
|
+
status: bootStatus,
|
|
47
|
+
statusInfo: OCPP2_0_1_Mapper.BootMapper.toStatusInfo(bootConfig?.statusInfo),
|
|
48
|
+
interval: bootStatus === OCPP2_0_1.RegistrationStatusEnumType.Accepted
|
|
49
|
+
? bootConfig?.heartbeatInterval || this._config.heartbeatInterval
|
|
50
|
+
: bootConfig?.bootRetryInterval || this._config.bootRetryInterval,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async updateBootConfig(bootNotificationResponse, tenantId, stationId) {
|
|
54
|
+
let bootConfigDbEntity = await this._bootRepository.readByKey(tenantId, stationId);
|
|
55
|
+
if (!bootConfigDbEntity) {
|
|
56
|
+
const unknownChargerBootConfig = {
|
|
57
|
+
status: bootNotificationResponse.status,
|
|
58
|
+
statusInfo: bootNotificationResponse.statusInfo,
|
|
59
|
+
};
|
|
60
|
+
bootConfigDbEntity = await this._bootRepository.createOrUpdateByKey(tenantId, unknownChargerBootConfig, stationId);
|
|
61
|
+
}
|
|
62
|
+
if (!bootConfigDbEntity) {
|
|
63
|
+
throw new Error('Unable to create/update BootConfig...');
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
bootConfigDbEntity.lastBootTime = bootNotificationResponse.currentTime;
|
|
67
|
+
await bootConfigDbEntity.save();
|
|
68
|
+
}
|
|
69
|
+
return bootConfigDbEntity;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Determines whether to blacklist or whitelist charger actions based on its boot status.
|
|
73
|
+
*
|
|
74
|
+
* If the new boot is accepted and the charger actions were previously blacklisted, then whitelist the charger actions.
|
|
75
|
+
* If the new boot is not accepted and charger actions were previously whitelisted, then blacklist the charger actions.
|
|
76
|
+
*
|
|
77
|
+
* @param stationId
|
|
78
|
+
* @param cachedBootStatus
|
|
79
|
+
* @param bootNotificationResponseStatus
|
|
80
|
+
*/
|
|
81
|
+
async cacheChargerActionsPermissions(stationId, cachedBootStatus, bootNotificationResponseStatus) {
|
|
82
|
+
// New boot status is Accepted and cachedBootStatus exists (meaning there was a previous Rejected or Pending boot)
|
|
83
|
+
if (bootNotificationResponseStatus === OCPP2_0_1.RegistrationStatusEnumType.Accepted) {
|
|
84
|
+
if (cachedBootStatus) {
|
|
85
|
+
// Undo blacklisting of charger-originated actions
|
|
86
|
+
const promises = Array.from(OCPP2_0_1_CALL_SCHEMA_MAP).map(async ([action]) => {
|
|
87
|
+
if (action !== OCPP2_0_1_CallAction.BootNotification) {
|
|
88
|
+
return this._cache.remove(action, stationId);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
await Promise.all(promises);
|
|
92
|
+
// Remove cached boot status
|
|
93
|
+
await this._cache.remove(BOOT_STATUS, stationId);
|
|
94
|
+
this._logger.debug('Cached boot status removed: ', cachedBootStatus);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (!cachedBootStatus) {
|
|
98
|
+
// Status is not Accepted; i.e. Status is Rejected or Pending.
|
|
99
|
+
// Cached boot status for charger did not exist; i.e. this is the first BootNotificationResponse to be Rejected or Pending.
|
|
100
|
+
// Blacklist all charger-originated actions except BootNotification
|
|
101
|
+
// GetReport messages will need to un-blacklist NotifyReport
|
|
102
|
+
// TriggerMessage will need to un-blacklist the message it triggers
|
|
103
|
+
const promises = Array.from(OCPP2_0_1_CALL_SCHEMA_MAP).map(async ([action]) => {
|
|
104
|
+
if (action !== OCPP2_0_1_CallAction.BootNotification) {
|
|
105
|
+
return this._cache.set(action, 'blacklisted', stationId);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
await Promise.all(promises);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
async createGetBaseReportRequest(stationId, maxCachingSeconds) {
|
|
112
|
+
// OCTT tool does not meet B07.FR.04; instead always sends requestId === 0
|
|
113
|
+
// Commenting out this line, using requestId === 0 until fixed (10/26/2023)
|
|
114
|
+
// const requestId = Math.floor(Math.random() * ConfigurationModule.GET_BASE_REPORT_REQUEST_ID_MAX);
|
|
115
|
+
const requestId = 0;
|
|
116
|
+
await this._cache.set(requestId.toString(), 'ongoing', stationId, maxCachingSeconds);
|
|
117
|
+
return {
|
|
118
|
+
requestId: requestId,
|
|
119
|
+
reportBase: OCPP2_0_1.ReportBaseEnumType.FullInventory,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Based on the GetBaseReportMessageConfirmation, checks the cache to ensure GetBaseReport truly succeeded.
|
|
124
|
+
* If GetBaseReport did not succeed, this method will throw. Otherwise, it will finish without throwing.
|
|
125
|
+
*
|
|
126
|
+
* @param stationId
|
|
127
|
+
* @param requestId
|
|
128
|
+
* @param getBaseReportMessageConfirmation
|
|
129
|
+
* @param maxCachingSeconds
|
|
130
|
+
*/
|
|
131
|
+
async confirmGetBaseReportSuccess(stationId, requestId, getBaseReportMessageConfirmation, maxCachingSeconds) {
|
|
132
|
+
if (getBaseReportMessageConfirmation.success) {
|
|
133
|
+
this._logger.debug(`GetBaseReport successfully sent to charger: ${getBaseReportMessageConfirmation}`);
|
|
134
|
+
// Wait for GetBaseReport to complete
|
|
135
|
+
let getBaseReportCacheValue = await this._cache.onChange(requestId, maxCachingSeconds, stationId);
|
|
136
|
+
while (getBaseReportCacheValue === 'ongoing') {
|
|
137
|
+
getBaseReportCacheValue = await this._cache.onChange(requestId, maxCachingSeconds, stationId);
|
|
138
|
+
}
|
|
139
|
+
if (getBaseReportCacheValue === 'complete') {
|
|
140
|
+
this._logger.debug('GetBaseReport process successful.'); // All NotifyReports have been processed
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
throw new Error('GetBaseReport process failed--message timed out without a response.');
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
throw new Error(`GetBaseReport failed: ${JSON.stringify(getBaseReportMessageConfirmation)}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Methods for OCPP 1.6
|
|
152
|
+
*/
|
|
153
|
+
determineOcpp16BootStatus(bootConfig) {
|
|
154
|
+
let bootStatus = bootConfig
|
|
155
|
+
? OCPP1_6_Mapper.BootMapper.toRegistrationStatusEnumType(bootConfig.status)
|
|
156
|
+
: this._config.ocpp1_6.unknownChargerStatus;
|
|
157
|
+
if (bootStatus === OCPP1_6.BootNotificationResponseStatus.Pending) {
|
|
158
|
+
let needToGetConfigurations = true;
|
|
159
|
+
let needToChangeConfigurations = true;
|
|
160
|
+
if (bootConfig) {
|
|
161
|
+
if (bootConfig.getConfigurationsOnPending !== undefined &&
|
|
162
|
+
bootConfig.getConfigurationsOnPending !== null) {
|
|
163
|
+
needToGetConfigurations = bootConfig.getConfigurationsOnPending;
|
|
164
|
+
}
|
|
165
|
+
if (bootConfig.changeConfigurationsOnPending !== undefined &&
|
|
166
|
+
bootConfig.changeConfigurationsOnPending !== null) {
|
|
167
|
+
needToChangeConfigurations = bootConfig.changeConfigurationsOnPending;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (!needToGetConfigurations && !needToChangeConfigurations) {
|
|
171
|
+
bootStatus = OCPP1_6.BootNotificationResponseStatus.Accepted;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return bootStatus;
|
|
175
|
+
}
|
|
176
|
+
async createOcpp16BootNotificationResponse(tenantId, stationId) {
|
|
177
|
+
const boot = await this._bootRepository.readByKey(tenantId, stationId);
|
|
178
|
+
const status = this.determineOcpp16BootStatus(boot);
|
|
179
|
+
return {
|
|
180
|
+
currentTime: new Date().toISOString(),
|
|
181
|
+
status,
|
|
182
|
+
interval: status === OCPP1_6.BootNotificationResponseStatus.Accepted
|
|
183
|
+
? boot?.heartbeatInterval || this._config.heartbeatInterval
|
|
184
|
+
: boot?.bootRetryInterval || this._config.bootRetryInterval,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Determines whether to blacklist or whitelist charger actions based on its boot status.
|
|
189
|
+
*
|
|
190
|
+
* If the new boot is accepted and the charger actions were previously blacklisted, then whitelist the charger actions.
|
|
191
|
+
* If the new boot is not accepted and charger actions were previously whitelisted, then blacklist the charger actions.
|
|
192
|
+
*
|
|
193
|
+
* @param stationId
|
|
194
|
+
* @param cachedBootStatus
|
|
195
|
+
* @param bootNotificationResponseStatus
|
|
196
|
+
*/
|
|
197
|
+
async cacheOcpp16ChargerActionsPermissions(stationId, cachedBootStatus, bootNotificationResponseStatus) {
|
|
198
|
+
// New boot status is Accepted and cachedBootStatus exists (meaning there was a previous Rejected or Pending boot)
|
|
199
|
+
if (bootNotificationResponseStatus === OCPP1_6.BootNotificationResponseStatus.Accepted) {
|
|
200
|
+
if (cachedBootStatus) {
|
|
201
|
+
// Undo blacklisting of charger-originated actions
|
|
202
|
+
const promises = Array.from(OCPP1_6_CALL_SCHEMA_MAP).map(async ([action]) => {
|
|
203
|
+
if (action !== OCPP1_6_CallAction.BootNotification) {
|
|
204
|
+
return this._cache.remove(action, stationId);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
await Promise.all(promises);
|
|
208
|
+
// Remove cached boot status
|
|
209
|
+
await this._cache.remove(BOOT_STATUS, stationId);
|
|
210
|
+
this._logger.debug(`Cached boot status ${cachedBootStatus} removed for station ${stationId}.`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else if (!cachedBootStatus) {
|
|
214
|
+
// Status is not Accepted; i.e. Status is Rejected or Pending.
|
|
215
|
+
// Cached boot status for charger did not exist; i.e. this is the first BootNotificationResponse to be Rejected or Pending.
|
|
216
|
+
// Blacklist all charger-originated actions except BootNotification
|
|
217
|
+
// ChangeConfiguration, GetConfiguration and TriggerMessage will need to un-blacklist the message it triggers
|
|
218
|
+
const promises = Array.from(OCPP1_6_CALL_SCHEMA_MAP).map(async ([action]) => {
|
|
219
|
+
if (action !== OCPP1_6_CallAction.BootNotification) {
|
|
220
|
+
return this._cache.set(action, 'blacklisted', stationId);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
await Promise.all(promises);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
async updateOcpp16BootConfig(response, tenantId, stationId) {
|
|
227
|
+
const heartbeatInterval = response.status === OCPP1_6.BootNotificationResponseStatus.Accepted
|
|
228
|
+
? response.interval
|
|
229
|
+
: undefined;
|
|
230
|
+
const bootRetryInterval = response.status !== OCPP1_6.BootNotificationResponseStatus.Accepted
|
|
231
|
+
? response.interval
|
|
232
|
+
: undefined;
|
|
233
|
+
const unknownChargerBootConfig = {
|
|
234
|
+
status: response.status,
|
|
235
|
+
heartbeatInterval,
|
|
236
|
+
bootRetryInterval,
|
|
237
|
+
};
|
|
238
|
+
let bootConfigDbEntity = await this._bootRepository.createOrUpdateByKey(tenantId, unknownChargerBootConfig, stationId);
|
|
239
|
+
if (bootConfigDbEntity) {
|
|
240
|
+
bootConfigDbEntity = await this._bootRepository.updateLastBootTimeByKey(tenantId, response.currentTime, stationId);
|
|
241
|
+
}
|
|
242
|
+
if (!bootConfigDbEntity) {
|
|
243
|
+
throw new Error('Unable to create/update BootConfig...');
|
|
244
|
+
}
|
|
245
|
+
return bootConfigDbEntity;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=BootNotificationService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BootNotificationService.js","sourceRoot":"","sources":["../../src/module/BootNotificationService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { FastifyInstance, FastifyRequest } from 'fastify';
|
|
2
|
+
import type { ILogObj } from 'tslog';
|
|
3
|
+
import { Logger } from 'tslog';
|
|
4
|
+
import type { IConfigurationModuleApi } from './interface.js';
|
|
5
|
+
import { ConfigurationModule } from './module.js';
|
|
6
|
+
import type { BootConfig, IMessageConfirmation, UpdateChargingStationPasswordRequest } from '@citrineos/base';
|
|
7
|
+
import { AbstractModuleApi, Namespace, OCPP1_6_Namespace, OCPP2_0_1, OCPP2_0_1_Namespace } from '@citrineos/base';
|
|
8
|
+
import type { ChargingStationKeyQuerystring, NetworkProfileDeleteQuerystring, NetworkProfileQuerystring, UpdateChargingStationPasswordQueryString } from '@citrineos/data';
|
|
9
|
+
import { Boot, ChargingStationNetworkProfile } from '@citrineos/data';
|
|
10
|
+
/**
|
|
11
|
+
* Server API for the Configuration component.
|
|
12
|
+
*/
|
|
13
|
+
export declare class ConfigurationDataApi extends AbstractModuleApi<ConfigurationModule> implements IConfigurationModuleApi {
|
|
14
|
+
/**
|
|
15
|
+
* Constructor for the class.
|
|
16
|
+
*
|
|
17
|
+
* @param {ConfigurationModule} ConfigurationComponent - The Configuration component.
|
|
18
|
+
* @param {FastifyInstance} server - The server instance.
|
|
19
|
+
* @param {Logger<ILogObj>} [logger] - Optional logger instance.
|
|
20
|
+
*/
|
|
21
|
+
constructor(ConfigurationComponent: ConfigurationModule, server: FastifyInstance, logger?: Logger<ILogObj>);
|
|
22
|
+
putBootConfig(request: FastifyRequest<{
|
|
23
|
+
Body: OCPP2_0_1.BootNotificationResponse;
|
|
24
|
+
Querystring: ChargingStationKeyQuerystring;
|
|
25
|
+
}>): Promise<BootConfig | undefined>;
|
|
26
|
+
getBootConfig(request: FastifyRequest<{
|
|
27
|
+
Querystring: ChargingStationKeyQuerystring;
|
|
28
|
+
}>): Promise<Boot | undefined>;
|
|
29
|
+
deleteBootConfig(request: FastifyRequest<{
|
|
30
|
+
Querystring: ChargingStationKeyQuerystring;
|
|
31
|
+
}>): Promise<Boot | undefined>;
|
|
32
|
+
updatePassword(request: FastifyRequest<{
|
|
33
|
+
Body: UpdateChargingStationPasswordRequest;
|
|
34
|
+
Querystring: UpdateChargingStationPasswordQueryString;
|
|
35
|
+
}>): Promise<IMessageConfirmation>;
|
|
36
|
+
getNetworkProfiles(request: FastifyRequest<{
|
|
37
|
+
Querystring: NetworkProfileQuerystring;
|
|
38
|
+
}>): Promise<ChargingStationNetworkProfile[]>;
|
|
39
|
+
deleteNetworkProfiles(request: FastifyRequest<{
|
|
40
|
+
Querystring: NetworkProfileDeleteQuerystring;
|
|
41
|
+
}>): Promise<IMessageConfirmation>;
|
|
42
|
+
/**
|
|
43
|
+
* Overrides superclass method to generate the URL path based on the input {@link Namespace}
|
|
44
|
+
* and the module's endpoint prefix configuration.
|
|
45
|
+
*
|
|
46
|
+
* @param {Namespace} input - The input {@link Namespace}.
|
|
47
|
+
* @return {string} - The generated URL path.
|
|
48
|
+
*/
|
|
49
|
+
protected _toDataPath(input: OCPP2_0_1_Namespace | OCPP1_6_Namespace | Namespace): string;
|
|
50
|
+
private updatePasswordOnStation;
|
|
51
|
+
private updatePasswordForStation;
|
|
52
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
5
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
6
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
7
|
+
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;
|
|
8
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
9
|
+
};
|
|
10
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
11
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
12
|
+
};
|
|
13
|
+
import { Logger } from 'tslog';
|
|
14
|
+
import { ConfigurationModule } from './module.js';
|
|
15
|
+
import { AbstractModuleApi, AsDataEndpoint, BootConfigSchema, HttpMethod, Namespace, OCPP1_6_Namespace, OCPP2_0_1, OCPP2_0_1_CallAction, OCPP2_0_1_Namespace, OCPPVersion, UpdateChargingStationPasswordSchema, } from '@citrineos/base';
|
|
16
|
+
import { Boot, ChargingStationKeyQuerySchema, ChargingStationNetworkProfile, Component, NetworkProfileDeleteQuerySchema, NetworkProfileQuerySchema, ServerNetworkProfile, SetNetworkProfile, UpdateChargingStationPasswordQuerySchema, Variable, VariableAttribute, } from '@citrineos/data';
|
|
17
|
+
import { Op } from 'sequelize';
|
|
18
|
+
import { generatePassword, isValidPassword } from '@citrineos/util';
|
|
19
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
20
|
+
/**
|
|
21
|
+
* Server API for the Configuration component.
|
|
22
|
+
*/
|
|
23
|
+
export class ConfigurationDataApi extends AbstractModuleApi {
|
|
24
|
+
/**
|
|
25
|
+
* Constructor for the class.
|
|
26
|
+
*
|
|
27
|
+
* @param {ConfigurationModule} ConfigurationComponent - The Configuration component.
|
|
28
|
+
* @param {FastifyInstance} server - The server instance.
|
|
29
|
+
* @param {Logger<ILogObj>} [logger] - Optional logger instance.
|
|
30
|
+
*/
|
|
31
|
+
constructor(ConfigurationComponent, server, logger) {
|
|
32
|
+
super(ConfigurationComponent, server, null, logger);
|
|
33
|
+
}
|
|
34
|
+
putBootConfig(request) {
|
|
35
|
+
return this._module.bootRepository.createOrUpdateByKey(request.query.tenantId, request.body, request.query.stationId);
|
|
36
|
+
}
|
|
37
|
+
getBootConfig(request) {
|
|
38
|
+
return this._module.bootRepository.readByKey(request.query.tenantId, request.query.stationId);
|
|
39
|
+
}
|
|
40
|
+
deleteBootConfig(request) {
|
|
41
|
+
return this._module.bootRepository.deleteByKey(request.query.tenantId, request.query.stationId);
|
|
42
|
+
}
|
|
43
|
+
async updatePassword(request) {
|
|
44
|
+
const stationId = request.body.stationId;
|
|
45
|
+
const tenantId = request.query.tenantId;
|
|
46
|
+
this._logger.debug(`Updating password for ${stationId} station in tenant ${tenantId}`);
|
|
47
|
+
if (request.body.setOnCharger && !request.body.password) {
|
|
48
|
+
return {
|
|
49
|
+
success: false,
|
|
50
|
+
payload: 'Password is required when setOnCharger is true',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (request.body.password && !isValidPassword(request.body.password)) {
|
|
54
|
+
return { success: false, payload: 'Invalid password' };
|
|
55
|
+
}
|
|
56
|
+
const password = request.body.password || generatePassword();
|
|
57
|
+
if (!request.body.setOnCharger) {
|
|
58
|
+
try {
|
|
59
|
+
await this.updatePasswordOnStation(password, stationId, tenantId, request.query.callbackUrl);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
this._logger.warn(`Failed updating password on ${stationId} station`, error);
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
payload: `Failed updating password on ${stationId} station`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const variableAttributes = await this.updatePasswordForStation(password, tenantId, stationId);
|
|
70
|
+
this._logger.debug(`Successfully updated password for ${stationId} station`);
|
|
71
|
+
return {
|
|
72
|
+
success: true,
|
|
73
|
+
payload: `Updated ${variableAttributes.length} attributes`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async getNetworkProfiles(request) {
|
|
77
|
+
return ChargingStationNetworkProfile.findAll({
|
|
78
|
+
where: { stationId: request.query.stationId, tenantId: request.query.tenantId },
|
|
79
|
+
include: [SetNetworkProfile, ServerNetworkProfile],
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
async deleteNetworkProfiles(request) {
|
|
83
|
+
const destroyedRows = await ChargingStationNetworkProfile.destroy({
|
|
84
|
+
where: {
|
|
85
|
+
stationId: request.query.stationId,
|
|
86
|
+
tenantId: request.query.tenantId,
|
|
87
|
+
configurationSlot: {
|
|
88
|
+
[Op.in]: request.query.configurationSlot,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
return {
|
|
93
|
+
success: true,
|
|
94
|
+
payload: `${destroyedRows} rows successfully destroyed`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Overrides superclass method to generate the URL path based on the input {@link Namespace}
|
|
99
|
+
* and the module's endpoint prefix configuration.
|
|
100
|
+
*
|
|
101
|
+
* @param {Namespace} input - The input {@link Namespace}.
|
|
102
|
+
* @return {string} - The generated URL path.
|
|
103
|
+
*/
|
|
104
|
+
_toDataPath(input) {
|
|
105
|
+
const endpointPrefix = this._module.config.modules.configuration.endpointPrefix;
|
|
106
|
+
return super._toDataPath(input, endpointPrefix);
|
|
107
|
+
}
|
|
108
|
+
async updatePasswordOnStation(password, stationId, tenantId, callbackUrl) {
|
|
109
|
+
const correlationId = uuidv4();
|
|
110
|
+
const cacheCallbackPromise = this._module.cache.onChange(correlationId, this._module.config.maxCachingSeconds, stationId);
|
|
111
|
+
const messageConfirmation = await this._module.sendCall(stationId, tenantId, OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.SetVariables, {
|
|
112
|
+
setVariableData: [
|
|
113
|
+
{
|
|
114
|
+
variable: { name: 'BasicAuthPassword' },
|
|
115
|
+
attributeValue: password,
|
|
116
|
+
attributeType: OCPP2_0_1.AttributeEnumType.Actual,
|
|
117
|
+
component: { name: 'SecurityCtrlr' },
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
}, callbackUrl, correlationId);
|
|
121
|
+
if (!messageConfirmation.success) {
|
|
122
|
+
throw new Error(`Failed sending request to ${stationId} station for updating password`);
|
|
123
|
+
}
|
|
124
|
+
const responseJsonString = await cacheCallbackPromise;
|
|
125
|
+
if (!responseJsonString) {
|
|
126
|
+
throw new Error(`${stationId} station did not respond in time for updating password`);
|
|
127
|
+
}
|
|
128
|
+
const setVariablesResponse = JSON.parse(responseJsonString);
|
|
129
|
+
const passwordUpdated = setVariablesResponse.setVariableResult.every((result) => result.attributeStatus === OCPP2_0_1.SetVariableStatusEnumType.Accepted);
|
|
130
|
+
if (!passwordUpdated) {
|
|
131
|
+
throw new Error(`Failure updating password on ${stationId} station`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async updatePasswordForStation(password, tenantId, stationId) {
|
|
135
|
+
const timestamp = new Date().toISOString();
|
|
136
|
+
const variableAttributes = await this._module.deviceModelRepository.createOrUpdateDeviceModelByStationId(tenantId, {
|
|
137
|
+
component: {
|
|
138
|
+
name: 'SecurityCtrlr',
|
|
139
|
+
},
|
|
140
|
+
variable: {
|
|
141
|
+
name: 'BasicAuthPassword',
|
|
142
|
+
},
|
|
143
|
+
variableAttribute: [
|
|
144
|
+
{
|
|
145
|
+
type: OCPP2_0_1.AttributeEnumType.Actual,
|
|
146
|
+
value: password,
|
|
147
|
+
mutability: OCPP2_0_1.MutabilityEnumType.WriteOnly,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
variableCharacteristics: {
|
|
151
|
+
dataType: OCPP2_0_1.DataEnumType.passwordString,
|
|
152
|
+
supportsMonitoring: false,
|
|
153
|
+
},
|
|
154
|
+
}, stationId, timestamp);
|
|
155
|
+
for (let variableAttribute of variableAttributes) {
|
|
156
|
+
variableAttribute = await variableAttribute.reload({
|
|
157
|
+
include: [Variable, Component],
|
|
158
|
+
});
|
|
159
|
+
await this._module.deviceModelRepository.updateResultByStationId(tenantId, {
|
|
160
|
+
attributeType: variableAttribute.type,
|
|
161
|
+
attributeStatus: OCPP2_0_1.SetVariableStatusEnumType.Accepted,
|
|
162
|
+
attributeStatusInfo: { reasonCode: 'SetOnCharger' },
|
|
163
|
+
component: variableAttribute.component,
|
|
164
|
+
variable: variableAttribute.variable,
|
|
165
|
+
}, stationId, timestamp);
|
|
166
|
+
}
|
|
167
|
+
return variableAttributes;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
__decorate([
|
|
171
|
+
AsDataEndpoint(Namespace.BootConfig, HttpMethod.Put, ChargingStationKeyQuerySchema, BootConfigSchema),
|
|
172
|
+
__metadata("design:type", Function),
|
|
173
|
+
__metadata("design:paramtypes", [Object]),
|
|
174
|
+
__metadata("design:returntype", Promise)
|
|
175
|
+
], ConfigurationDataApi.prototype, "putBootConfig", null);
|
|
176
|
+
__decorate([
|
|
177
|
+
AsDataEndpoint(Namespace.BootConfig, HttpMethod.Get, ChargingStationKeyQuerySchema),
|
|
178
|
+
__metadata("design:type", Function),
|
|
179
|
+
__metadata("design:paramtypes", [Object]),
|
|
180
|
+
__metadata("design:returntype", Promise)
|
|
181
|
+
], ConfigurationDataApi.prototype, "getBootConfig", null);
|
|
182
|
+
__decorate([
|
|
183
|
+
AsDataEndpoint(Namespace.BootConfig, HttpMethod.Delete, ChargingStationKeyQuerySchema),
|
|
184
|
+
__metadata("design:type", Function),
|
|
185
|
+
__metadata("design:paramtypes", [Object]),
|
|
186
|
+
__metadata("design:returntype", Promise)
|
|
187
|
+
], ConfigurationDataApi.prototype, "deleteBootConfig", null);
|
|
188
|
+
__decorate([
|
|
189
|
+
AsDataEndpoint(OCPP2_0_1_Namespace.PasswordType, HttpMethod.Post, UpdateChargingStationPasswordQuerySchema, UpdateChargingStationPasswordSchema),
|
|
190
|
+
__metadata("design:type", Function),
|
|
191
|
+
__metadata("design:paramtypes", [Object]),
|
|
192
|
+
__metadata("design:returntype", Promise)
|
|
193
|
+
], ConfigurationDataApi.prototype, "updatePassword", null);
|
|
194
|
+
__decorate([
|
|
195
|
+
AsDataEndpoint(OCPP2_0_1_Namespace.ServerNetworkProfile, HttpMethod.Get, NetworkProfileQuerySchema),
|
|
196
|
+
__metadata("design:type", Function),
|
|
197
|
+
__metadata("design:paramtypes", [Object]),
|
|
198
|
+
__metadata("design:returntype", Promise)
|
|
199
|
+
], ConfigurationDataApi.prototype, "getNetworkProfiles", null);
|
|
200
|
+
__decorate([
|
|
201
|
+
AsDataEndpoint(OCPP2_0_1_Namespace.ServerNetworkProfile, HttpMethod.Delete, NetworkProfileDeleteQuerySchema),
|
|
202
|
+
__metadata("design:type", Function),
|
|
203
|
+
__metadata("design:paramtypes", [Object]),
|
|
204
|
+
__metadata("design:returntype", Promise)
|
|
205
|
+
], ConfigurationDataApi.prototype, "deleteNetworkProfiles", null);
|
|
206
|
+
//# 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,30 @@
|
|
|
1
|
+
import type { IDeviceModelRepository } from '@citrineos/data';
|
|
2
|
+
export declare class DeviceModelService {
|
|
3
|
+
protected _deviceModelRepository: IDeviceModelRepository;
|
|
4
|
+
constructor(deviceModelRepository: IDeviceModelRepository);
|
|
5
|
+
/**
|
|
6
|
+
* Fetches the ItemsPerMessageSetVariables attribute from the device model.
|
|
7
|
+
* Returns null if no such attribute exists.
|
|
8
|
+
* It is possible for there to be multiple ItemsPerMessageSetVariables attributes if component instances or evses
|
|
9
|
+
* are associated with alternate options. That structure is not supported by this logic, and that
|
|
10
|
+
* structure is a violation of Part 2 - Specification of OCPP 2.0.1.
|
|
11
|
+
* In that case, the first attribute will be returned.
|
|
12
|
+
* @param tenantId
|
|
13
|
+
* @param stationId Charging station identifier.
|
|
14
|
+
* @returns ItemsPerMessageSetVariables as a number or null if no such attribute exists.
|
|
15
|
+
*/
|
|
16
|
+
getItemsPerMessageSetVariablesByStationId(tenantId: number, stationId: string): Promise<number | null>;
|
|
17
|
+
/**
|
|
18
|
+
* Fetches the ItemsPerMessageGetVariables attribute from the device model.
|
|
19
|
+
* Returns null if no such attribute exists.
|
|
20
|
+
* It is possible for there to be multiple ItemsPerMessageGetVariables attributes if component instances or evses
|
|
21
|
+
* are associated with alternate options. That structure is not supported by this logic, and that
|
|
22
|
+
* structure is a violation of Part 2 - Specification of OCPP 2.0.1.
|
|
23
|
+
* In that case, the first attribute will be returned.
|
|
24
|
+
* @param tenantId
|
|
25
|
+
* @param stationId Charging station identifier.
|
|
26
|
+
* @returns ItemsPerMessageGetVariables as a number or null if no such attribute exists.
|
|
27
|
+
*/
|
|
28
|
+
getItemsPerMessageGetVariablesByStationId(tenantId: number, stationId: string): Promise<number | null>;
|
|
29
|
+
updateDeviceModel(chargingStation: any, tenantId: number, stationId: string, timestamp: string): Promise<void>;
|
|
30
|
+
}
|