UNPKG

@citrineos/data

Version:

The OCPP data module which includes all persistence layer implementation.

434 lines 23.4 kB
"use strict"; // Copyright (c) 2023 S44, LLC // Copyright Contributors to the CitrineOS Project // // SPDX-License-Identifier: Apache 2.0 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.SequelizeDeviceModelRepository = void 0; const base_1 = require("@citrineos/base"); const Base_1 = require("./Base"); const sequelize_1 = require("sequelize"); const DeviceModel_1 = require("../model/DeviceModel"); const ComponentVariable_1 = require("../model/DeviceModel/ComponentVariable"); // TODO: Document this class SequelizeDeviceModelRepository extends Base_1.SequelizeRepository { constructor(config, logger, sequelizeInstance, variable, component, evse, componentVariable, variableCharacteristics, variableStatus) { super(config, DeviceModel_1.VariableAttribute.MODEL_NAME, logger, sequelizeInstance); this.variable = variable ? variable : new Base_1.SequelizeRepository(config, DeviceModel_1.Variable.MODEL_NAME, logger, sequelizeInstance); this.component = component ? component : new Base_1.SequelizeRepository(config, DeviceModel_1.Component.MODEL_NAME, logger, sequelizeInstance); this.evse = evse ? evse : new Base_1.SequelizeRepository(config, DeviceModel_1.Evse.MODEL_NAME, logger, sequelizeInstance); this.componentVariable = componentVariable ? componentVariable : new Base_1.SequelizeRepository(config, ComponentVariable_1.ComponentVariable.MODEL_NAME, logger, sequelizeInstance); this.variableCharacteristics = variableCharacteristics ? variableCharacteristics : new Base_1.SequelizeRepository(config, DeviceModel_1.VariableCharacteristics.MODEL_NAME, logger, sequelizeInstance); this.variableStatus = variableStatus ? variableStatus : new Base_1.SequelizeRepository(config, DeviceModel_1.VariableStatus.MODEL_NAME, logger, sequelizeInstance); } createOrUpdateDeviceModelByStationId(tenantId, value, stationId, isoTimestamp) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d; // Doing this here so that no records are created if the data is invalid const variableAttributeTypes = value.variableAttribute.map((attr) => { var _a; return (_a = attr.type) !== null && _a !== void 0 ? _a : base_1.OCPP2_0_1.AttributeEnumType.Actual; }); if (variableAttributeTypes.length !== new Set(variableAttributeTypes).size) { throw new Error('All variable attributes in ReportData must have different types.'); } const [component, variable] = yield this.findOrCreateEvseAndComponentAndVariable(tenantId, value.component, value.variable, stationId); let dataType = null; if (value.variableCharacteristics) { const variableCharacteristicsType = value.variableCharacteristics; dataType = variableCharacteristicsType.dataType; const vc = { tenantId, unit: (_a = variableCharacteristicsType.unit) !== null && _a !== void 0 ? _a : null, dataType, minLimit: (_b = variableCharacteristicsType.minLimit) !== null && _b !== void 0 ? _b : null, maxLimit: (_c = variableCharacteristicsType.maxLimit) !== null && _c !== void 0 ? _c : null, valuesList: (_d = variableCharacteristicsType.valuesList) !== null && _d !== void 0 ? _d : null, supportsMonitoring: variableCharacteristicsType.supportsMonitoring, variableId: variable.id, }; yield this.s.transaction((transaction) => __awaiter(this, void 0, void 0, function* () { const savedVariableCharacteristics = yield this.s.models[DeviceModel_1.VariableCharacteristics.MODEL_NAME].findOne({ where: { variableId: variable.id, }, transaction, }); if (!savedVariableCharacteristics) { const createdVariableCharacteristics = yield DeviceModel_1.VariableCharacteristics.create(vc, { transaction, }); this.variableCharacteristics.emit('created', [createdVariableCharacteristics]); return createdVariableCharacteristics; } else { return yield this.variableCharacteristics.updateAllByQuery(tenantId, vc, { where: { variableId: variable.id, }, transaction, }); } })); } return yield Promise.all(value.variableAttribute.map((variableAttribute) => __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e, _f, _g; const [savedVariableAttribute, variableAttributeCreated] = yield this.readOrCreateByQuery(tenantId, { where: { tenantId, // the composite unique index of VariableAttribute stationId: stationId, variableId: variable.id, componentId: component.id, type: (_a = variableAttribute.type) !== null && _a !== void 0 ? _a : base_1.OCPP2_0_1.AttributeEnumType.Actual, }, defaults: { evseDatabaseId: component.evseDatabaseId, dataType, value: variableAttribute.value, generatedAt: isoTimestamp, mutability: (_b = variableAttribute.mutability) !== null && _b !== void 0 ? _b : base_1.OCPP2_0_1.MutabilityEnumType.ReadWrite, persistent: variableAttribute.persistent ? variableAttribute.persistent : false, constant: variableAttribute.constant ? variableAttribute.constant : false, }, }); if (!variableAttributeCreated) { return (yield this.updateByKey(tenantId, { evseDatabaseId: component.evseDatabaseId, dataType: dataType !== null && dataType !== void 0 ? dataType : savedVariableAttribute.dataType, type: (_c = variableAttribute.type) !== null && _c !== void 0 ? _c : savedVariableAttribute.type, value: (_d = variableAttribute.value) !== null && _d !== void 0 ? _d : null, mutability: (_e = variableAttribute.mutability) !== null && _e !== void 0 ? _e : savedVariableAttribute.mutability, persistent: (_f = variableAttribute.persistent) !== null && _f !== void 0 ? _f : false, constant: (_g = variableAttribute.constant) !== null && _g !== void 0 ? _g : false, generatedAt: isoTimestamp, }, savedVariableAttribute.id)); } return savedVariableAttribute; }))); }); } findOrCreateEvseAndComponentAndVariable(tenantId, componentType, variableType, stationId) { return __awaiter(this, void 0, void 0, function* () { const component = yield this.findOrCreateEvseAndComponent(tenantId, componentType, stationId); const [variable] = yield this.variable.readOrCreateByQuery(tenantId, { where: { tenantId, name: variableType.name, instance: variableType.instance ? variableType.instance : null, }, defaults: Object.assign({}, variableType), }); // This can happen asynchronously yield this.componentVariable.readOrCreateByQuery(tenantId, { where: { tenantId, componentId: component.id, variableId: variable.id }, }); return [component, variable]; }); } findOrCreateEvseAndComponent(tenantId, componentType, stationId) { return __awaiter(this, void 0, void 0, function* () { const evse = componentType.evse ? (yield this.evse.readOrCreateByQuery(tenantId, { where: { tenantId, id: componentType.evse.id, connectorId: componentType.evse.connectorId ? componentType.evse.connectorId : null, }, }))[0] : undefined; const [component, componentCreated] = yield this.component.readOrCreateByQuery(tenantId, { where: { tenantId, name: componentType.name, instance: componentType.instance ? componentType.instance : null, }, }); // Note: this permits changing the evse related to the component if (component.evseDatabaseId !== (evse === null || evse === void 0 ? void 0 : evse.databaseId) && evse) { yield this.component.updateByKey(tenantId, { evseDatabaseId: evse.databaseId }, component.get('id')); } if (componentCreated && stationId) { const defaultComponentVariableNames = ['Present', 'Available', 'Enabled']; for (const defaultComponentVariableName of defaultComponentVariableNames) { const [defaultComponentVariable, _defaultComponentVariableCreated] = yield this.variable.readOrCreateByQuery(tenantId, { where: { tenantId, name: defaultComponentVariableName, instance: null, }, }); yield this.componentVariable.readOrCreateByQuery(tenantId, { where: { tenantId, componentId: component.id, variableId: defaultComponentVariable.id }, }); yield this.create(tenantId, DeviceModel_1.VariableAttribute.build({ tenantId, stationId, variableId: defaultComponentVariable.id, componentId: component.id, evseDatabaseId: evse === null || evse === void 0 ? void 0 : evse.databaseId, dataType: base_1.OCPP2_0_1.DataEnumType.boolean, value: 'true', mutability: base_1.OCPP2_0_1.MutabilityEnumType.ReadOnly, })); } } return component; }); } createOrUpdateByGetVariablesResultAndStationId(tenantId, getVariablesResult, stationId, isoTimestamp) { return __awaiter(this, void 0, void 0, function* () { const savedVariableAttributes = []; for (const result of getVariablesResult) { const savedVariableAttribute = (yield this.createOrUpdateDeviceModelByStationId(tenantId, { component: Object.assign({}, result.component), variable: Object.assign({}, result.variable), variableAttribute: [ { type: result.attributeType, value: result.attributeValue, }, ], }, stationId, isoTimestamp))[0]; yield this.variableStatus.create(tenantId, DeviceModel_1.VariableStatus.build({ tenantId, value: result.attributeValue, status: result.attributeStatus, statusInfo: result.attributeStatusInfo, variableAttributeId: savedVariableAttribute.get('id'), }, { include: [DeviceModel_1.VariableAttribute] })); savedVariableAttributes.push(savedVariableAttribute); } return savedVariableAttributes; }); } createOrUpdateBySetVariablesDataAndStationId(tenantId, setVariablesData, stationId, isoTimestamp) { return __awaiter(this, void 0, void 0, function* () { const savedVariableAttributes = []; for (const data of setVariablesData) { const savedVariableAttribute = (yield this.createOrUpdateDeviceModelByStationId(tenantId, { component: Object.assign({}, data.component), variable: Object.assign({}, data.variable), variableAttribute: [ { type: data.attributeType, value: data.attributeValue, }, ], }, stationId, isoTimestamp))[0]; savedVariableAttributes.push(savedVariableAttribute); } return savedVariableAttributes; }); } updateResultByStationId(tenantId, result, stationId, isoTimestamp) { const _super = Object.create(null, { readOnlyOneByQuery: { get: () => super.readOnlyOneByQuery } }); return __awaiter(this, void 0, void 0, function* () { var _a; const savedVariableAttribute = yield _super.readOnlyOneByQuery.call(this, tenantId, { where: { stationId, type: (_a = result.attributeType) !== null && _a !== void 0 ? _a : base_1.OCPP2_0_1.AttributeEnumType.Actual }, include: [ { model: DeviceModel_1.Component, where: { name: result.component.name, instance: result.component.instance ? result.component.instance : null, }, }, { model: DeviceModel_1.Variable, where: { name: result.variable.name, instance: result.variable.instance ? result.variable.instance : null, }, }, ], }); if (savedVariableAttribute) { yield this.variableStatus.create(tenantId, DeviceModel_1.VariableStatus.build({ tenantId, value: savedVariableAttribute.value, status: result.attributeStatus, statusInfo: result.attributeStatusInfo, variableAttributeId: savedVariableAttribute.get('id'), })); if (result.attributeStatus !== base_1.OCPP2_0_1.SetVariableStatusEnumType.Accepted) { const mostRecentAcceptedStatus = (yield this.variableStatus.readAllByQuery(tenantId, { where: { variableAttributeId: savedVariableAttribute.get('id'), status: base_1.OCPP2_0_1.SetVariableStatusEnumType.Accepted, }, limit: 1, order: [['createdAt', 'DESC']], }))[0]; savedVariableAttribute.setDataValue('value', mostRecentAcceptedStatus === null || mostRecentAcceptedStatus === void 0 ? void 0 : mostRecentAcceptedStatus.value); } savedVariableAttribute.set('generatedAt', isoTimestamp); yield savedVariableAttribute.save(); // Reload in order to include the statuses return yield savedVariableAttribute.reload({ include: [DeviceModel_1.VariableStatus], }); } else { throw new Error('Unable to update variable attribute status...'); } }); } readAllSetVariableByStationId(tenantId, stationId) { const _super = Object.create(null, { readAllByQuery: { get: () => super.readAllByQuery } }); return __awaiter(this, void 0, void 0, function* () { const variableAttributeArray = yield _super.readAllByQuery.call(this, tenantId, { where: { stationId, bootConfigSetId: { [sequelize_1.Op.ne]: null }, }, include: [{ model: DeviceModel_1.Component, include: [DeviceModel_1.Evse] }, DeviceModel_1.Variable], }); return variableAttributeArray.map((variableAttribute) => this.createSetVariableDataType(variableAttribute)); }); } readAllByQuerystring(tenantId, query) { const _super = Object.create(null, { readAllByQuery: { get: () => super.readAllByQuery } }); return __awaiter(this, void 0, void 0, function* () { const readQuery = this.constructQuery(query); readQuery.include.push(DeviceModel_1.VariableStatus); return yield _super.readAllByQuery.call(this, tenantId, readQuery); }); } existByQuerystring(tenantId, query) { const _super = Object.create(null, { existByQuery: { get: () => super.existByQuery } }); return __awaiter(this, void 0, void 0, function* () { return yield _super.existByQuery.call(this, tenantId, this.constructQuery(query)); }); } deleteAllByQuerystring(tenantId, query) { const _super = Object.create(null, { deleteAllByQuery: { get: () => super.deleteAllByQuery } }); return __awaiter(this, void 0, void 0, function* () { return yield _super.deleteAllByQuery.call(this, tenantId, this.constructQuery(query)); }); } findComponentAndVariable(tenantId, componentType, variableType) { return __awaiter(this, void 0, void 0, function* () { const component = yield this.component.readOnlyOneByQuery(tenantId, { where: { name: componentType.name, instance: componentType.instance ? componentType.instance : null, }, }); const variable = yield this.variable.readOnlyOneByQuery(tenantId, { where: { name: variableType.name, instance: variableType.instance ? variableType.instance : null, }, }); if (variable) { const variableCharacteristics = yield this.variableCharacteristics.readOnlyOneByQuery(tenantId, { where: { variableId: variable.get('id') }, }); variable.variableCharacteristics = variableCharacteristics; } return [component, variable]; }); } findEvseByIdAndConnectorId(tenantId, id, connectorId) { return __awaiter(this, void 0, void 0, function* () { const storedEvses = yield this.evse.readAllByQuery(tenantId, { where: { id: id, connectorId: connectorId, }, }); return storedEvses.length > 0 ? storedEvses[0] : undefined; }); } findVariableCharacteristicsByVariableNameAndVariableInstance(tenantId, variableName, variableInstance) { return __awaiter(this, void 0, void 0, function* () { const variableCharacteristics = yield this.variableCharacteristics.readAllByQuery(tenantId, { include: [ { model: DeviceModel_1.Variable, where: { name: variableName, instance: variableInstance, }, }, ], }); return variableCharacteristics.length > 0 ? variableCharacteristics[0] : undefined; }); } /** * Private Methods */ createSetVariableDataType(input) { if (!input.value) { throw new Error('Value must be present to generate SetVariableDataType from VariableAttribute'); } else { return { attributeType: input.type, attributeValue: input.value, component: Object.assign({}, input.component), variable: Object.assign({}, input.variable), }; } } constructQuery(queryParams) { var _a; const evseInclude = ((_a = queryParams.component_evse_id) !== null && _a !== void 0 ? _a : queryParams.component_evse_connectorId) ? { model: DeviceModel_1.Evse, where: Object.assign(Object.assign({}, (queryParams.component_evse_id ? { id: queryParams.component_evse_id } : {})), (queryParams.component_evse_connectorId ? { connectorId: queryParams.component_evse_connectorId } : {})), } : DeviceModel_1.Evse; const attributeType = queryParams.type && queryParams.type.toUpperCase() === 'NULL' ? null : queryParams.type; return { where: Object.assign(Object.assign(Object.assign(Object.assign({}, (queryParams.stationId ? { stationId: queryParams.stationId } : {})), (queryParams.type === undefined ? {} : { type: attributeType })), (queryParams.value ? { value: queryParams.value } : {})), (queryParams.status === undefined ? {} : { status: queryParams.status })), include: [ { model: DeviceModel_1.Component, where: Object.assign(Object.assign({}, (queryParams.component_name ? { name: queryParams.component_name } : {})), (queryParams.component_instance ? { instance: queryParams.component_instance } : {})), include: [evseInclude], }, { model: DeviceModel_1.Variable, where: Object.assign(Object.assign({}, (queryParams.variable_name ? { name: queryParams.variable_name } : {})), (queryParams.variable_instance ? { instance: queryParams.variable_instance } : {})), include: [DeviceModel_1.VariableCharacteristics], }, ], }; } } exports.SequelizeDeviceModelRepository = SequelizeDeviceModelRepository; //# sourceMappingURL=DeviceModel.js.map