@citrineos/data
Version:
The OCPP data module which includes all persistence layer implementation.
434 lines • 23.4 kB
JavaScript
"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