UNPKG

@citrineos/base

Version:

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

189 lines 7.78 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.AbstractMessageRouter = void 0; const ajv_1 = require("ajv"); const __1 = require("../.."); const tslog_1 = require("tslog"); class AbstractMessageRouter { /** * Constructor of abstract ocpp router. * * @param {Ajv} ajv - The Ajv instance to use for schema validation. */ constructor(config, cache, handler, sender, networkHook, logger, ajv) { this._config = config; this._cache = cache; this._handler = handler; this._sender = sender; this._networkHook = networkHook; this._ajv = ajv || new ajv_1.Ajv({ removeAdditional: 'all', useDefaults: true, coerceTypes: 'array', strict: false, }); this._logger = logger ? logger.getSubLogger({ name: this.constructor.name }) : new tslog_1.Logger({ name: this.constructor.name }); // Set module for proper message flow. this._handler.module = this; } /** * Getters & Setters */ get cache() { return this._cache; } get sender() { return this._sender; } get handler() { return this._handler; } get config() { return this._config; } set networkHook(value) { this._networkHook = value; } /** * Sets the system configuration for the module. * * @param {SystemConfig} config - The new configuration to set. */ set config(config) { this._config = config; // Update all necessary settings for hot reload this._logger.info('Updating system configuration for ocpp router...'); this._logger.settings.minLevel = this._config.logLevel; } /** * Public Methods */ handle(message) { return __awaiter(this, void 0, void 0, function* () { this._logger.debug('Received message:', message); if (message.state === __1.MessageState.Response) { if (message.payload instanceof __1.OcppError) { yield this.sendCallError(message.context.correlationId, message.context.stationId, message.context.tenantId, message.protocol, message.action, message.payload, message.origin); } else { yield this.sendCallResult(message.context.correlationId, message.context.stationId, message.context.tenantId, message.protocol, message.action, message.payload, message.origin); } } else if (message.state === __1.MessageState.Request) { yield this.sendCall(message.context.stationId, message.context.tenantId, message.protocol, message.action, message.payload, message.context.correlationId, message.origin); } }); } /** * Protected Methods */ /** * Validates a Call object against its schema. * * @param {string} identifier - The identifier of the EVSE. * @param {Call} message - The Call object to validate. * @param {string} protocol - The subprotocol of the Websocket, i.e. "ocpp1.6" or "ocpp2.0.1". * @return {boolean} - Returns true if the Call object is valid, false otherwise. */ _validateCall(identifier, message, protocol) { const action = message[2]; const payload = message[3]; let schema; switch (protocol) { case __1.OCPPVersion.OCPP1_6: schema = __1.OCPP1_6_CALL_SCHEMA_MAP.get(action); break; case __1.OCPPVersion.OCPP2_0_1: schema = __1.OCPP2_0_1_CALL_SCHEMA_MAP.get(action); break; default: this._logger.error('Unknown subprotocol', protocol); return { isValid: false }; } if (schema) { let validate = this._ajv.getSchema(schema['$id']); if (!validate) { schema['$id'] = `${protocol}-${schema['$id']}`; this._logger.debug(`Updated call result schema id: ${schema['$id']}`); validate = this._ajv.compile(schema); } const result = validate(payload); if (!result) { const validationErrorsDeepCopy = JSON.parse(JSON.stringify(validate.errors)); this._logger.debug('Validate CallResult failed', validationErrorsDeepCopy); return { isValid: false, errors: validationErrorsDeepCopy }; } else { return { isValid: true }; } } else { this._logger.error('No schema found for action', action, message); return { isValid: false }; // TODO: Implement config for this behavior } } /** * Validates a CallResult object against its schema. * * @param {string} identifier - The identifier of the EVSE. * @param {CallAction} action - The original CallAction. * @param {CallResult} message - The CallResult object to validate. * @param {string} protocol - The protocol of the Websocket. * @return {boolean} - Returns true if the CallResult object is valid, false otherwise. */ _validateCallResult(identifier, action, message, protocol) { const payload = message[2]; let schema; switch (protocol) { case __1.OCPPVersion.OCPP1_6: schema = __1.OCPP1_6_CALL_RESULT_SCHEMA_MAP.get(action); break; case __1.OCPPVersion.OCPP2_0_1: schema = __1.OCPP2_0_1_CALL_RESULT_SCHEMA_MAP.get(action); break; default: this._logger.error('Unknown subprotocol', protocol); return { isValid: false }; } if (schema) { let validate = this._ajv.getSchema(schema['$id']); if (!validate) { schema['$id'] = `${protocol}-${schema['$id']}`; this._logger.debug(`Updated call result schema id: ${schema['$id']}`); validate = this._ajv.compile(schema); } const result = validate(payload); if (!result) { const validationErrorsDeepCopy = JSON.parse(JSON.stringify(validate.errors)); this._logger.debug('Validate CallResult failed', validationErrorsDeepCopy); return { isValid: false, errors: validationErrorsDeepCopy }; } else { return { isValid: true }; } } else { this._logger.error('No schema found for call result with action', action, message); return { isValid: false }; // TODO: Implement config for this behavior } } } exports.AbstractMessageRouter = AbstractMessageRouter; //# sourceMappingURL=AbstractRouter.js.map