@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.
@@ -0,0 +1,122 @@
1
+ // SPDX-FileCopyrightText: 2025 Contributors to the CitrineOS Project
2
+ //
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ import { OCPP2_0_1 } from '@citrineos/base';
5
+ import { VariableAttribute } from '@citrineos/data';
6
+ export class DeviceModelService {
7
+ _deviceModelRepository;
8
+ constructor(deviceModelRepository) {
9
+ this._deviceModelRepository = deviceModelRepository;
10
+ }
11
+ /**
12
+ * Fetches the ItemsPerMessageSetVariables attribute from the device model.
13
+ * Returns null if no such attribute exists.
14
+ * It is possible for there to be multiple ItemsPerMessageSetVariables attributes if component instances or evses
15
+ * are associated with alternate options. That structure is not supported by this logic, and that
16
+ * structure is a violation of Part 2 - Specification of OCPP 2.0.1.
17
+ * In that case, the first attribute will be returned.
18
+ * @param tenantId
19
+ * @param stationId Charging station identifier.
20
+ * @returns ItemsPerMessageSetVariables as a number or null if no such attribute exists.
21
+ */
22
+ async getItemsPerMessageSetVariablesByStationId(tenantId, stationId) {
23
+ const itemsPerMessageSetVariablesAttributes = await this._deviceModelRepository.readAllByQuerystring(tenantId, {
24
+ tenantId: tenantId,
25
+ stationId: stationId,
26
+ component_name: 'DeviceDataCtrlr',
27
+ variable_name: 'ItemsPerMessage',
28
+ variable_instance: 'SetVariables',
29
+ type: OCPP2_0_1.AttributeEnumType.Actual,
30
+ });
31
+ if (itemsPerMessageSetVariablesAttributes.length === 0) {
32
+ return null;
33
+ }
34
+ else {
35
+ // It is possible for itemsPerMessageSetVariablesAttributes.length > 1 if component instances or evses
36
+ // are associated with alternate options. That structure is not supported by this logic, and that
37
+ // structure is a violation of Part 2 - Specification of OCPP 2.0.1.
38
+ return Number(itemsPerMessageSetVariablesAttributes[0].value);
39
+ }
40
+ }
41
+ /**
42
+ * Fetches the ItemsPerMessageGetVariables attribute from the device model.
43
+ * Returns null if no such attribute exists.
44
+ * It is possible for there to be multiple ItemsPerMessageGetVariables attributes if component instances or evses
45
+ * are associated with alternate options. That structure is not supported by this logic, and that
46
+ * structure is a violation of Part 2 - Specification of OCPP 2.0.1.
47
+ * In that case, the first attribute will be returned.
48
+ * @param tenantId
49
+ * @param stationId Charging station identifier.
50
+ * @returns ItemsPerMessageGetVariables as a number or null if no such attribute exists.
51
+ */
52
+ async getItemsPerMessageGetVariablesByStationId(tenantId, stationId) {
53
+ const itemsPerMessageGetVariablesAttributes = await this._deviceModelRepository.readAllByQuerystring(tenantId, {
54
+ tenantId: tenantId,
55
+ stationId: stationId,
56
+ component_name: 'DeviceDataCtrlr',
57
+ variable_name: 'ItemsPerMessage',
58
+ variable_instance: 'GetVariables',
59
+ type: OCPP2_0_1.AttributeEnumType.Actual,
60
+ });
61
+ if (itemsPerMessageGetVariablesAttributes.length === 0) {
62
+ return null;
63
+ }
64
+ else {
65
+ // It is possible for itemsPerMessageGetVariablesAttributes.length > 1 if component instances or evses
66
+ // are associated with alternate options. That structure is not supported by this logic, and that
67
+ // structure is a violation of Part 2 - Specification of OCPP 2.0.1.
68
+ return Number(itemsPerMessageGetVariablesAttributes[0].value);
69
+ }
70
+ }
71
+ async updateDeviceModel(chargingStation, tenantId, stationId, timestamp) {
72
+ const attributes = [
73
+ {
74
+ component: 'ChargingStation',
75
+ variable: 'Model',
76
+ value: chargingStation.model,
77
+ },
78
+ {
79
+ component: 'ChargingStation',
80
+ variable: 'VendorName',
81
+ value: chargingStation.vendorName,
82
+ },
83
+ {
84
+ component: 'Controller',
85
+ variable: 'FirmwareVersion',
86
+ value: chargingStation.firmwareVersion,
87
+ },
88
+ {
89
+ component: 'ChargingStation',
90
+ variable: 'SerialNumber',
91
+ value: chargingStation.serialNumber,
92
+ },
93
+ {
94
+ component: 'DataLink',
95
+ variable: 'IMSI',
96
+ value: chargingStation.modem?.imsi,
97
+ },
98
+ {
99
+ component: 'DataLink',
100
+ variable: 'ICCID',
101
+ value: chargingStation.modem?.iccid,
102
+ },
103
+ ];
104
+ const promises = attributes
105
+ .filter((attr) => attr.value !== undefined)
106
+ .map((attr) => this._deviceModelRepository.createOrUpdateDeviceModelByStationId(tenantId, {
107
+ component: { name: attr.component },
108
+ variable: { name: attr.variable },
109
+ variableAttribute: [
110
+ {
111
+ type: OCPP2_0_1.AttributeEnumType.Actual,
112
+ value: attr.value,
113
+ mutability: OCPP2_0_1.MutabilityEnumType.ReadOnly,
114
+ persistent: true,
115
+ constant: true,
116
+ },
117
+ ],
118
+ }, stationId, timestamp));
119
+ await Promise.all(promises);
120
+ }
121
+ }
122
+ //# sourceMappingURL=DeviceModelService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeviceModelService.js","sourceRoot":"","sources":["../../src/module/DeviceModelService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Interface for the Configuration module.
3
+ */
4
+ export interface IConfigurationModuleApi {
5
+ }
@@ -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,110 @@
1
+ import type { BootstrapConfig, CallAction, HandlerProperties, ICache, IMessage, IMessageHandler, IMessageSender, SystemConfig } from '@citrineos/base';
2
+ import { AbstractModule, OCPP1_6, OCPP2_0_1, OCPPValidator } from '@citrineos/base';
3
+ import type { IBootRepository, IChangeConfigurationRepository, IDeviceModelRepository, ILocationRepository, IMessageInfoRepository, IOCPPMessageRepository, ITenantRepository } from '@citrineos/data';
4
+ import { IdGenerator } from '@citrineos/util';
5
+ import type { ILogObj } from 'tslog';
6
+ import { Logger } from 'tslog';
7
+ import { BootNotificationService } from './BootNotificationService.js';
8
+ import { DeviceModelService } from './DeviceModelService.js';
9
+ /**
10
+ * Component that handles Configuration related messages.
11
+ */
12
+ export declare class ConfigurationModule extends AbstractModule {
13
+ _deviceModelService: DeviceModelService;
14
+ _requests: CallAction[];
15
+ _responses: CallAction[];
16
+ protected _bootService: BootNotificationService;
17
+ private _idGenerator;
18
+ /**
19
+ * This is the constructor function that initializes the {@link ConfigurationModule}.
20
+ *
21
+ * @param {BootstrapConfig & SystemConfig} config - The `config` contains configuration settings for the module.
22
+ *
23
+ * @param {ICache} [cache] - The cache instance which is shared among the modules & Central System to pass information such as blacklisted actions or boot status.
24
+ *
25
+ * @param {IMessageSender} [sender] - The `sender` parameter is an optional parameter that represents an instance of the {@link IMessageSender} interface.
26
+ * 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.
27
+ *
28
+ * @param {IMessageHandler} [handler] - The `handler` parameter is an optional parameter that represents an instance of the {@link IMessageHandler} interface.
29
+ * 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.
30
+ *
31
+ * @param {Logger<ILogObj>} [logger] - The `logger` parameter is an optional parameter that represents an instance of {@link Logger<ILogObj>}.
32
+ * It is used to propagate system-wide logger settings and will serve as the parent logger for any subcomponent logging. If no `logger` is provided, a default {@link Logger<ILogObj>} instance is created and used.
33
+ *
34
+ * @param {IBootRepository} [bootRepository] - An optional parameter of type {@link IBootRepository} which represents a repository for accessing and manipulating authorization data.
35
+ * If no `bootRepository` is provided, a default {@link SequelizeBootRepository} instance is created and used.
36
+ *
37
+ * @param {IDeviceModelRepository} [deviceModelRepository] - An optional parameter of type {@link IDeviceModelRepository} which represents a repository for accessing and manipulating variable data.
38
+ * If no `deviceModelRepository` is provided, a default {@link sequelize:deviceModelRepository} instance is created and used.
39
+ *
40
+ * @param {IMessageInfoRepository} [messageInfoRepository] - An optional parameter of type {@link messageInfoRepository} which
41
+ * represents a repository for accessing and manipulating message info data. If no `messageInfoRepository` is provided, a default
42
+ * {@link SequelizeMessageInfoRepository} instance is created and used.
43
+ *
44
+ * @param {ILocationRepository} [locationRepository] - An optional parameter of type {@link locationRepository} which
45
+ * represents a repository for accessing and manipulating location data. If no `locationRepository` is provided, a default
46
+ * {@link SequelizeLocationRepository} instance is created and used.
47
+ *
48
+ * @param {IChangeConfigurationRepository} [changeConfigurationRepository] - An optional parameter of type {@link IChangeConfigurationRepository} which
49
+ * represents a repository for accessing and manipulating change configuration data. If no `changeConfigurationRepository` is provided, a default
50
+ * {@link SequelizeChangeConfigurationRepository} instance is created and used.
51
+ *
52
+ * @param {IOCPPMessageRepository} [ocppMessageRepository] - An optional parameter of type {@link IOCPPMessageRepository} which
53
+ * represents a repository for accessing and manipulating call message data. If no `ocppMessageRepository` is provided, a default
54
+ * {@link SequelizeOCPPMessageRepository} instance is created and used.
55
+ *
56
+ * @param {IdGenerator} [idGenerator] - An optional parameter of type {@link IdGenerator} which
57
+ * represents a generator for ids.
58
+ *
59
+ *If no `deviceModelRepository` is provided, a default {@link sequelize:messageInfoRepository} instance is created and used.
60
+ */
61
+ constructor(config: BootstrapConfig & SystemConfig, cache: ICache, sender?: IMessageSender, handler?: IMessageHandler, logger?: Logger<ILogObj>, ocppValidator?: OCPPValidator, bootRepository?: IBootRepository, deviceModelRepository?: IDeviceModelRepository, messageInfoRepository?: IMessageInfoRepository, locationRepository?: ILocationRepository, changeConfigurationRepository?: IChangeConfigurationRepository, ocppMessageRepository?: IOCPPMessageRepository, idGenerator?: IdGenerator, tenantRepository?: ITenantRepository);
62
+ protected _tenantRepository: ITenantRepository;
63
+ get tenantRepository(): ITenantRepository;
64
+ protected _bootRepository: IBootRepository;
65
+ get bootRepository(): IBootRepository;
66
+ protected _deviceModelRepository: IDeviceModelRepository;
67
+ get deviceModelRepository(): IDeviceModelRepository;
68
+ protected _messageInfoRepository: IMessageInfoRepository;
69
+ get messageInfoRepository(): IMessageInfoRepository;
70
+ protected _locationRepository: ILocationRepository;
71
+ get locationRepository(): ILocationRepository;
72
+ protected _changeConfigurationRepository: IChangeConfigurationRepository;
73
+ get changeConfigurationRepository(): IChangeConfigurationRepository;
74
+ protected _ocppMessageRepository: IOCPPMessageRepository;
75
+ get ocppMessageRepository(): IOCPPMessageRepository;
76
+ /**
77
+ * Handle OCPP 2.0.1 requests
78
+ */
79
+ protected _handleBootNotification(message: IMessage<OCPP2_0_1.BootNotificationRequest>, props?: HandlerProperties): Promise<void>;
80
+ protected _handleHeartbeat(message: IMessage<OCPP2_0_1.HeartbeatRequest>, props?: HandlerProperties): Promise<void>;
81
+ protected _handleNotifyDisplayMessages(message: IMessage<OCPP2_0_1.NotifyDisplayMessagesRequest>, props?: HandlerProperties): Promise<void>;
82
+ protected _handleFirmwareStatusNotification(message: IMessage<OCPP2_0_1.FirmwareStatusNotificationRequest>, props?: HandlerProperties): Promise<void>;
83
+ protected _handleDataTransfer(message: IMessage<OCPP2_0_1.DataTransferRequest>, props?: HandlerProperties): Promise<void>;
84
+ /**
85
+ * Handle OCPP 2.0.1 responses
86
+ */
87
+ protected _handleChangeAvailability(message: IMessage<OCPP2_0_1.ChangeAvailabilityResponse>, props?: HandlerProperties): void;
88
+ protected _handleSetNetworkProfile(message: IMessage<OCPP2_0_1.SetNetworkProfileResponse>, props?: HandlerProperties): Promise<void>;
89
+ protected _handleGetDisplayMessages(message: IMessage<OCPP2_0_1.GetDisplayMessagesResponse>, props?: HandlerProperties): void;
90
+ protected _handleSetDisplayMessage(message: IMessage<OCPP2_0_1.SetDisplayMessageResponse>, props?: HandlerProperties): Promise<void>;
91
+ protected _handlePublishFirmware(message: IMessage<OCPP2_0_1.PublishFirmwareResponse>, props?: HandlerProperties): void;
92
+ protected _handleUnpublishFirmware(message: IMessage<OCPP2_0_1.UnpublishFirmwareResponse>, props?: HandlerProperties): void;
93
+ protected _handleUpdateFirmware(message: IMessage<OCPP2_0_1.UpdateFirmwareResponse>, props?: HandlerProperties): void;
94
+ protected _handleReset(message: IMessage<OCPP2_0_1.ResetResponse>, props?: HandlerProperties): void;
95
+ protected _handleTriggerMessage(message: IMessage<OCPP2_0_1.TriggerMessageResponse>, props?: HandlerProperties): void;
96
+ protected _handleClearDisplayMessage(message: IMessage<OCPP2_0_1.ClearDisplayMessageResponse>, props?: HandlerProperties): Promise<void>;
97
+ /**
98
+ * Handle OCPP 1.6 requests
99
+ */
100
+ protected _handle16Heartbeat(message: IMessage<OCPP1_6.HeartbeatRequest>, props?: HandlerProperties): Promise<void>;
101
+ protected _handleOcpp16BootNotification(message: IMessage<OCPP1_6.BootNotificationRequest>, props?: HandlerProperties): Promise<void>;
102
+ /**
103
+ * Handle OCPP 1.6 response
104
+ */
105
+ protected _handleOcpp16GetConfiguration(message: IMessage<OCPP1_6.GetConfigurationResponse>, props?: HandlerProperties): Promise<void>;
106
+ protected _handleOcpp16ChangeConfiguration(message: IMessage<OCPP1_6.ChangeConfigurationResponse>, props?: HandlerProperties): Promise<void>;
107
+ protected _handleOcpp16TriggerMessage(message: IMessage<OCPP1_6.TriggerMessageResponse>, props?: HandlerProperties): void;
108
+ protected _handle16Reset(message: IMessage<OCPP1_6.ResetResponse>, props?: HandlerProperties): void;
109
+ protected _handleOcpp16ChangeAvailability(message: IMessage<OCPP1_6.ChangeAvailabilityResponse>, props?: HandlerProperties): void;
110
+ }