UNPKG

@yachteye/signalk-engineroom-plugin

Version:

Get EngineRoom data from the source (database or other) and add it to the SignalK graph.

208 lines (207 loc) 9.82 kB
"use strict"; 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()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const _1 = require("."); const mssql_1 = __importDefault(require("mssql")); const utils = require('@signalk/nmea0183-utilities'); /** * Access to the BDE database with Engine Data. */ class SqlBDE { constructor(settings, definitions) { this.pool = null; this.dataDefinitions = definitions; this.config = { server: settings.sqlServer, database: settings.sqlDb, user: settings.sqlUser, password: settings.sqlPassword, pool: { max: 10, min: 0, idleTimeoutMillis: 30000, }, options: { trustServerCertificate: settings.trustServerCertificate, }, }; if (settings.sqlPort > 0) { this.config.port = settings.sqlPort; } mssql_1.default .connect(this.config) .then((pool) => { pool.on('error', (err) => { console.error(`[SqlBDE] pool error: ${err}`); }); pool.on('warn', (warn) => { console.error(`[SqlBDE] pool warn: ${warn}`); }); pool.on('info', (info) => { console.error(`[SqlBDE] pool info: ${info}`); }); console.log(`[SqlBDE] ctor: connecting=${pool.connecting}, connected=${pool.connected}.`); this.pool = pool; this.getIds(); }) .catch((err) => { console.error('[SqlBDE]', 'Error creating connection pool', err); }); } /** * */ disconnect() { return __awaiter(this, void 0, void 0, function* () { if (this.pool) { try { this.pool.removeAllListeners(); yield this.pool.close(); } catch (err) { console.error(`[SqlBDE] disconnect() error: ${err}`); } } }); } /** * Get the database [Id] and [Scale] values for the data we need to retrieve. */ getIds() { console.log(`[SqlBDE] getIds()`); this.dataDefinitions.forEach((dataDef) => { if (this.pool) { this.pool .query(`SELECT [Id], [Scale] from [BDE].[dbo].[T_Tag] WHERE [DisplayName] LIKE '${dataDef.displayNameDb}'`) .then((r) => { if (r.recordset.length === 0) { if (!dataDef.displayNameDb.startsWith('N.A. ')) { console.warn(`[SqlBDE] getIds() No data found for '${dataDef.displayNameDb}' path='${dataDef.path}' `); } } else { dataDef.Id = r.recordset[0].Id; if (r.recordset[0].Scale) { dataDef.scaleDb = r.recordset[0].Scale; } } }) .catch((reason) => { console.error(`[SqlBDE] getIds() error for ${dataDef.displayNameDb}: ${reason}`); }); } }); } /** * Get the specified value from the database table [T_Data]. The SQL Value is specified as bigint or null. * @param id The database Id to query. * @returns A Promise. */ queryDataById(id) { return __awaiter(this, void 0, void 0, function* () { // console.log(`[SqlBDE] queryDataById( ${id} )`); if (this.pool) { try { // const result = await this.pool.request() // .input('input_parameter', sql.Int, id) // .output('Value', sql.BigInt) // .output('Time',sql.DateTime2(7)) // .query('SELECT TOP(1) * FROM [BDE].[dbo].[T_Data] WHERE [Id] = @input_parameter ORDER BY [Time] DESC'); const result = yield this.pool.query(`SELECT TOP(1) [Time], [Value] FROM [BDE].[dbo].[T_Data] WHERE [Id] = ${id} ORDER BY [Time] DESC`); // console.log('Q', id, JSON.stringify(result)); // {"recordsets":[[{"Time":"2024-06-25T05:44:02.096Z","Value":"0"}]],"recordset":[{"Time":"2024-06-25T05:44:02.096Z","Value":"0"}],"output":{},"rowsAffected":[1]} const v = result.recordset[0].Value === null ? null : parseInt(result.recordset[0].Value, 10); return { sqlValue: v, timestamp: result.recordset[0].Time }; } catch (err) { console.error(`[SqlBDE] queryDataById( ${id} ) error: ${err}`); } } console.error(`[SqlBDE] queryDataById( ${id} ) No SQL connection pool`); return null; }); } /** * Get all the required data from the database. * @returns A Promise with a dictionary with the data (keyed by path). */ getData() { return __awaiter(this, void 0, void 0, function* () { var _a; console.log(`[SqlBDE] getData(): connected = ${(_a = this.pool) === null || _a === void 0 ? void 0 : _a.connected} `); const data = {}; const raw = {}; for (const dataDef of this.dataDefinitions) { if (dataDef.Id) { const value = yield this.queryDataById(dataDef.Id); let dataValue = (value === null) ? null : value.sqlValue; // console.warn('[SqlBDE] Value for', dataDef.Id, dataDef.displayNameDb, dataValue); if (dataValue !== null) { if (dataDef.scaleDb !== undefined && dataDef.scaleDb !== 1) { dataValue = dataValue / dataDef.scaleDb; } if (dataDef.type === _1.IDataType.Ratio) { if (dataValue > 100 || dataValue < -100) { console.warn(`[SqlBDE] getData(): unexpected percentage value ${dataValue} for ${JSON.stringify(dataDef)} .`); } dataValue /= 100; } else if (dataDef.type === 'running_off') { // Values are not just 0 or 1 as one would expect, so check for 0 and treat everything else as 'running'. dataValue = dataValue === 0 ? 'off' : 'running'; } if (dataDef.unit === 'W' && typeof dataValue === 'number') { dataValue *= 1000; // kW to W. } else if (dataDef.unit === 'K' && typeof dataValue === 'number') { dataValue = utils.transform(dataValue, 'C', 'K'); } else if (dataDef.unit === 'Pa' && typeof dataValue === 'number') { dataValue *= 100000; // bar to Pa. } else if (dataDef.unit === 'degrees' && dataDef.type === _1.IDataType.Number && typeof dataValue === 'number') { dataValue = utils.transform(dataValue, 'deg', 'rad'); } if (dataDef.type === _1.IDataType.Number && typeof dataValue === 'number') { if (dataDef.min !== undefined && dataValue < dataDef.min) { console.log(`[SqlBDE] getData(): unexpected value ${dataValue} for ${JSON.stringify(dataDef)} .`); } if (dataDef.max !== undefined && dataValue > dataDef.max) { console.log(`[SqlBDE] getData(): unexpected value ${dataValue} for ${JSON.stringify(dataDef)} .`); } } } raw[dataDef.path] = { id: String(dataDef.Id), value: (value === null) ? null : value.sqlValue, parsed: dataValue, path: dataDef.path, displayNameDb: dataDef.displayNameDb, lastUpdate: (value === null) ? null : value.timestamp, }; data[dataDef.path] = dataValue; } else if (dataDef.type === _1.IDataType.Fixed) { data[dataDef.path] = dataDef.fixed === undefined ? 0 : dataDef.fixed; } else { // console.warn('[SqlBDE] getData() no ID for', dataDef.displayNameDb, dataDef.Id); data[dataDef.path] = null; } } return { data, raw }; }); } } exports.default = SqlBDE;