UNPKG

@citrineos/configuration

Version:

The configuration module for OCPP v2.0.1. This module is not intended to be used directly, but rather as a dependency for other modules.

206 lines 10.3 kB
// SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project // // SPDX-License-Identifier: Apache-2.0 var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 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; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import { Logger } from 'tslog'; import { ConfigurationModule } from './module.js'; 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'; import { Boot, ChargingStationKeyQuerySchema, ChargingStationNetworkProfile, Component, NetworkProfileDeleteQuerySchema, NetworkProfileQuerySchema, ServerNetworkProfile, SetNetworkProfile, UpdateChargingStationPasswordQuerySchema, Variable, VariableAttribute, } from '@citrineos/data'; import { Op } from 'sequelize'; import { generatePassword, isValidPassword } from '@citrineos/util'; import { v4 as uuidv4 } from 'uuid'; /** * Server API for the Configuration component. */ export class ConfigurationDataApi extends AbstractModuleApi { /** * Constructor for the class. * * @param {ConfigurationModule} ConfigurationComponent - The Configuration component. * @param {FastifyInstance} server - The server instance. * @param {Logger<ILogObj>} [logger] - Optional logger instance. */ constructor(ConfigurationComponent, server, logger) { super(ConfigurationComponent, server, null, logger); } putBootConfig(request) { return this._module.bootRepository.createOrUpdateByKey(request.query.tenantId, request.body, request.query.stationId); } getBootConfig(request) { return this._module.bootRepository.readByKey(request.query.tenantId, request.query.stationId); } deleteBootConfig(request) { return this._module.bootRepository.deleteByKey(request.query.tenantId, request.query.stationId); } async updatePassword(request) { const stationId = request.body.stationId; const tenantId = request.query.tenantId; this._logger.debug(`Updating password for ${stationId} station in tenant ${tenantId}`); if (request.body.setOnCharger && !request.body.password) { return { success: false, payload: 'Password is required when setOnCharger is true', }; } if (request.body.password && !isValidPassword(request.body.password)) { return { success: false, payload: 'Invalid password' }; } const password = request.body.password || generatePassword(); if (!request.body.setOnCharger) { try { await this.updatePasswordOnStation(password, stationId, tenantId, request.query.callbackUrl); } catch (error) { this._logger.warn(`Failed updating password on ${stationId} station`, error); return { success: false, payload: `Failed updating password on ${stationId} station`, }; } } const variableAttributes = await this.updatePasswordForStation(password, tenantId, stationId); this._logger.debug(`Successfully updated password for ${stationId} station`); return { success: true, payload: `Updated ${variableAttributes.length} attributes`, }; } async getNetworkProfiles(request) { return ChargingStationNetworkProfile.findAll({ where: { stationId: request.query.stationId, tenantId: request.query.tenantId }, include: [SetNetworkProfile, ServerNetworkProfile], }); } async deleteNetworkProfiles(request) { const destroyedRows = await ChargingStationNetworkProfile.destroy({ where: { stationId: request.query.stationId, tenantId: request.query.tenantId, configurationSlot: { [Op.in]: request.query.configurationSlot, }, }, }); return { success: true, payload: `${destroyedRows} rows successfully destroyed`, }; } /** * Overrides superclass method to generate the URL path based on the input {@link Namespace} * and the module's endpoint prefix configuration. * * @param {Namespace} input - The input {@link Namespace}. * @return {string} - The generated URL path. */ _toDataPath(input) { const endpointPrefix = this._module.config.modules.configuration.endpointPrefix; return super._toDataPath(input, endpointPrefix); } async updatePasswordOnStation(password, stationId, tenantId, callbackUrl) { const correlationId = uuidv4(); const cacheCallbackPromise = this._module.cache.onChange(correlationId, this._module.config.maxCachingSeconds, stationId); const messageConfirmation = await this._module.sendCall(stationId, tenantId, OCPPVersion.OCPP2_0_1, OCPP2_0_1_CallAction.SetVariables, { setVariableData: [ { variable: { name: 'BasicAuthPassword' }, attributeValue: password, attributeType: OCPP2_0_1.AttributeEnumType.Actual, component: { name: 'SecurityCtrlr' }, }, ], }, callbackUrl, correlationId); if (!messageConfirmation.success) { throw new Error(`Failed sending request to ${stationId} station for updating password`); } const responseJsonString = await cacheCallbackPromise; if (!responseJsonString) { throw new Error(`${stationId} station did not respond in time for updating password`); } const setVariablesResponse = JSON.parse(responseJsonString); const passwordUpdated = setVariablesResponse.setVariableResult.every((result) => result.attributeStatus === OCPP2_0_1.SetVariableStatusEnumType.Accepted); if (!passwordUpdated) { throw new Error(`Failure updating password on ${stationId} station`); } } async updatePasswordForStation(password, tenantId, stationId) { const timestamp = new Date().toISOString(); const variableAttributes = await this._module.deviceModelRepository.createOrUpdateDeviceModelByStationId(tenantId, { component: { name: 'SecurityCtrlr', }, variable: { name: 'BasicAuthPassword', }, variableAttribute: [ { type: OCPP2_0_1.AttributeEnumType.Actual, value: password, mutability: OCPP2_0_1.MutabilityEnumType.WriteOnly, }, ], variableCharacteristics: { dataType: OCPP2_0_1.DataEnumType.passwordString, supportsMonitoring: false, }, }, stationId, timestamp); for (let variableAttribute of variableAttributes) { variableAttribute = await variableAttribute.reload({ include: [Variable, Component], }); await this._module.deviceModelRepository.updateResultByStationId(tenantId, { attributeType: variableAttribute.type, attributeStatus: OCPP2_0_1.SetVariableStatusEnumType.Accepted, attributeStatusInfo: { reasonCode: 'SetOnCharger' }, component: variableAttribute.component, variable: variableAttribute.variable, }, stationId, timestamp); } return variableAttributes; } } __decorate([ AsDataEndpoint(Namespace.BootConfig, HttpMethod.Put, ChargingStationKeyQuerySchema, BootConfigSchema), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], ConfigurationDataApi.prototype, "putBootConfig", null); __decorate([ AsDataEndpoint(Namespace.BootConfig, HttpMethod.Get, ChargingStationKeyQuerySchema), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], ConfigurationDataApi.prototype, "getBootConfig", null); __decorate([ AsDataEndpoint(Namespace.BootConfig, HttpMethod.Delete, ChargingStationKeyQuerySchema), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], ConfigurationDataApi.prototype, "deleteBootConfig", null); __decorate([ AsDataEndpoint(OCPP2_0_1_Namespace.PasswordType, HttpMethod.Post, UpdateChargingStationPasswordQuerySchema, UpdateChargingStationPasswordSchema), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], ConfigurationDataApi.prototype, "updatePassword", null); __decorate([ AsDataEndpoint(OCPP2_0_1_Namespace.ServerNetworkProfile, HttpMethod.Get, NetworkProfileQuerySchema), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], ConfigurationDataApi.prototype, "getNetworkProfiles", null); __decorate([ AsDataEndpoint(OCPP2_0_1_Namespace.ServerNetworkProfile, HttpMethod.Delete, NetworkProfileDeleteQuerySchema), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Promise) ], ConfigurationDataApi.prototype, "deleteNetworkProfiles", null); //# sourceMappingURL=DataApi.js.map