UNPKG

@citrineos/reporting

Version:

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

282 lines 17 kB
"use strict"; // Copyright (c) 2023 S44, LLC // Copyright 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); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ReportingModule = void 0; const base_1 = require("@citrineos/base"); const data_1 = require("@citrineos/data"); const util_1 = require("@citrineos/util"); const services_1 = require("./services"); /** * Component that handles provisioning related messages. */ class ReportingModule extends base_1.AbstractModule { /** * Constructor */ /** * This is the constructor function that initializes the {@link ReportingModule}. * * @param {SystemConfig} config - The `config` contains configuration settings for the module. * * @param {ICache} [cache] - The cache instance which is shared among the modules & Central System to pass information such as blacklisted actions or boot status. * * @param {IMessageSender} [sender] - The `sender` parameter is an optional parameter that represents an instance of the {@link IMessageSender} interface. * 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. * * @param {IMessageHandler} [handler] - The `handler` parameter is an optional parameter that represents an instance of the {@link IMessageHandler} interface. * 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. * * @param {Logger<ILogObj>} [logger] - The `logger` parameter is an optional parameter that represents an instance of {@link Logger<ILogObj>}. * 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. * * @param {IDeviceModelRepository} [deviceModelRepository] - An optional parameter of type {@link IDeviceModelRepository} which represents a repository for accessing and manipulating variable data. * If no `deviceModelRepository` is provided, a default {@link sequelize:deviceModelRepository} instance is created and used. * * @param {ISecurityEventRepository} [securityEventRepository] - An optional parameter of type {@link ISecurityEventRepository} which represents a repository for accessing security event notification data. * * @param {IVariableMonitoringRepository} [variableMonitoringRepository] - An optional parameter of type {@link IVariableMonitoringRepository} which represents a repository for accessing and manipulating monitoring data. */ constructor(config, cache, sender, handler, logger, deviceModelRepository, securityEventRepository, variableMonitoringRepository) { super(config, cache, handler || new util_1.RabbitMqReceiver(config, logger), sender || new util_1.RabbitMqSender(config, logger), base_1.EventGroup.Reporting, logger); /** * Fields */ this._requests = [ base_1.OCPP2_0_1_CallAction.LogStatusNotification, base_1.OCPP2_0_1_CallAction.NotifyCustomerInformation, base_1.OCPP2_0_1_CallAction.NotifyReport, base_1.OCPP2_0_1_CallAction.SecurityEventNotification, base_1.OCPP2_0_1_CallAction.NotifyMonitoringReport, ]; this._responses = [ base_1.OCPP2_0_1_CallAction.CustomerInformation, base_1.OCPP2_0_1_CallAction.GetLog, base_1.OCPP2_0_1_CallAction.GetReport, base_1.OCPP2_0_1_CallAction.GetBaseReport, base_1.OCPP2_0_1_CallAction.GetMonitoringReport, ]; this._deviceModelRepository = deviceModelRepository || new data_1.sequelize.SequelizeDeviceModelRepository(config, this._logger); this._securityEventRepository = securityEventRepository || new data_1.sequelize.SequelizeSecurityEventRepository(config, this._logger); this._variableMonitoringRepository = variableMonitoringRepository || new data_1.sequelize.SequelizeVariableMonitoringRepository(config, this._logger); this._deviceModelService = new services_1.DeviceModelService(this._deviceModelRepository); } get deviceModelRepository() { return this._deviceModelRepository; } /** * Handle Requests */ _handleLogStatusNotification(message, props) { return __awaiter(this, void 0, void 0, function* () { this._logger.debug('LogStatusNotification received:', message, props); // TODO: LogStatusNotification is usually triggered. Ideally, it should be sent to the callbackUrl from the message api that sent the trigger message // Create response const response = {}; const messageConfirmation = yield this.sendCallResultWithMessage(message, response); this._logger.debug('LogStatusNotification response sent: ', messageConfirmation); }); } _handleNotifyCustomerInformation(message, props) { return __awaiter(this, void 0, void 0, function* () { this._logger.debug('NotifyCustomerInformation request received:', message, props); // Create response const response = {}; const messageConfirmation = yield this.sendCallResultWithMessage(message, response); this._logger.debug('NotifyCustomerInformation response sent: ', messageConfirmation); }); } _handleNotifyMonitoringReport(message, props) { return __awaiter(this, void 0, void 0, function* () { this._logger.debug('NotifyMonitoringReport request received:', message, props); for (const monitorType of message.payload.monitor ? message.payload.monitor : []) { const stationId = message.context.stationId; const [component, variable] = yield this._deviceModelRepository.findOrCreateEvseAndComponentAndVariable(monitorType.component, monitorType.variable); yield this._variableMonitoringRepository.createOrUpdateByMonitoringDataTypeAndStationId(monitorType, component ? component.id : null, variable ? variable.id : null, stationId); } // Create response const response = {}; const messageConfirmation = yield this.sendCallResultWithMessage(message, response); this._logger.debug('NotifyMonitoringReport response sent: ', messageConfirmation); }); } _handleNotifyReport(message, props) { return __awaiter(this, void 0, void 0, function* () { this._logger.info('NotifyReport received:', message, props); const timestamp = message.payload.generatedAt; for (const reportDataType of message.payload.reportData ? message.payload.reportData : []) { // To keep consistency with VariableAttributeType defined in OCPP 2.0.1: // mutability: Default is ReadWrite when omitted. // if it is not present, we set it to ReadWrite for (const variableAttr of reportDataType.variableAttribute) { if (!variableAttr.mutability) { variableAttr.mutability = base_1.OCPP2_0_1.MutabilityEnumType.ReadWrite; } } const variableAttributes = yield this._deviceModelRepository.createOrUpdateDeviceModelByStationId(reportDataType, message.context.stationId, timestamp); for (const variableAttribute of variableAttributes) { // Reload is necessary because in createOrUpdateDeviceModelByStationId does not do eager loading yield variableAttribute.reload({ include: [data_1.Component, data_1.Variable], }); yield this._deviceModelRepository.updateResultByStationId({ attributeType: variableAttribute.type, attributeStatus: base_1.OCPP2_0_1.SetVariableStatusEnumType.Accepted, attributeStatusInfo: { reasonCode: message.action }, component: variableAttribute.component, variable: variableAttribute.variable, }, message.context.stationId, timestamp); } } if (!message.payload.tbc) { // Default if omitted is false const success = yield this._cache.set(message.payload.requestId.toString(), ReportingModule.GET_BASE_REPORT_COMPLETE_CACHE_VALUE, message.context.stationId); this._logger.info('Completed', success, message.payload.requestId); } else { // tbc (to be continued) is true // Continue to set get base report ongoing. Will extend the timeout. const success = yield this._cache.set(message.payload.requestId.toString(), ReportingModule.GET_BASE_REPORT_ONGOING_CACHE_VALUE, message.context.stationId, this.config.maxCachingSeconds); this._logger.info('Ongoing', success, message.payload.requestId); } // Create response const response = {}; yield this.sendCallResultWithMessage(message, response); this._logger.debug('NotifyReport response sent:', message, props); }); } _handleSecurityEventNotification(message, props) { return __awaiter(this, void 0, void 0, function* () { this._logger.debug('SecurityEventNotification request received:', message, props); yield this._securityEventRepository.createByStationId(message.payload, message.context.stationId); yield this.sendCallResultWithMessage(message, {}); }); } /** * Handle responses */ _handleGetBaseReport(message, props) { this._logger.debug('GetBaseReport response received:', message, props); } _handleGetReport(message, props) { this._logger.debug('GetReport response received:', message, props); const status = message.payload.status; const statusInfo = message.payload.statusInfo; if (status === base_1.OCPP2_0_1.GenericDeviceModelStatusEnumType.Rejected || status === base_1.OCPP2_0_1.GenericDeviceModelStatusEnumType.NotSupported) { this._logger.error('Failed to get report.', status, statusInfo === null || statusInfo === void 0 ? void 0 : statusInfo.reasonCode, statusInfo === null || statusInfo === void 0 ? void 0 : statusInfo.additionalInfo); } } _handleGetMonitoringReport(message, props) { return __awaiter(this, void 0, void 0, function* () { this._logger.debug('GetMonitoringReport response received:', message, props); const status = message.payload.status; const statusInfo = message.payload.statusInfo; if (status === base_1.OCPP2_0_1.GenericDeviceModelStatusEnumType.Rejected || status === base_1.OCPP2_0_1.GenericDeviceModelStatusEnumType.NotSupported) { this._logger.error('Failed to get monitoring report.', status, statusInfo === null || statusInfo === void 0 ? void 0 : statusInfo.reasonCode, statusInfo === null || statusInfo === void 0 ? void 0 : statusInfo.additionalInfo); } }); } _handleGetLog(message, props) { this._logger.debug('GetLog response received:', message, props); } _handleCustomerInformation(message, props) { this._logger.debug('CustomerInformation response received:', message, props); } } exports.ReportingModule = ReportingModule; /** * Get Base Report variables. While NotifyReport requests correlated with a GetBaseReport's requestId * are still being sent, cache value is 'ongoing'. Once a NotifyReport with tbc === false (or undefined) * is received, cache value is 'complete'. */ ReportingModule.GET_BASE_REPORT_REQUEST_ID_MAX = 10000000; // 10,000,000 ReportingModule.GET_BASE_REPORT_ONGOING_CACHE_VALUE = 'ongoing'; ReportingModule.GET_BASE_REPORT_COMPLETE_CACHE_VALUE = 'complete'; __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.LogStatusNotification), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], ReportingModule.prototype, "_handleLogStatusNotification", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.NotifyCustomerInformation), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], ReportingModule.prototype, "_handleNotifyCustomerInformation", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.NotifyMonitoringReport), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], ReportingModule.prototype, "_handleNotifyMonitoringReport", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.NotifyReport), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], ReportingModule.prototype, "_handleNotifyReport", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.SecurityEventNotification), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], ReportingModule.prototype, "_handleSecurityEventNotification", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.GetBaseReport), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", void 0) ], ReportingModule.prototype, "_handleGetBaseReport", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.GetReport), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", void 0) ], ReportingModule.prototype, "_handleGetReport", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.GetMonitoringReport), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", Promise) ], ReportingModule.prototype, "_handleGetMonitoringReport", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.GetLog), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", void 0) ], ReportingModule.prototype, "_handleGetLog", null); __decorate([ (0, base_1.AsHandler)(base_1.OCPPVersion.OCPP2_0_1, base_1.OCPP2_0_1_CallAction.CustomerInformation), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object]), __metadata("design:returntype", void 0) ], ReportingModule.prototype, "_handleCustomerInformation", null); //# sourceMappingURL=module.js.map