UNPKG

jbd-plugin

Version:

jbd battery plugin for SignalK

182 lines (162 loc) 6.31 kB
const fs = require('fs'); const path = require('path'); const lastUpdateTimes = {}; const id = 'jbd-plugin'; module.exports = function(app) { var plugin = {}; var pythonProcess; plugin.id = id; plugin.name = 'JBD/Fogstar Battery Plugin'; plugin.description = 'Connects to multiple JBD style batteries over BLE'; plugin.start = function(options, restartPlugin) { app.debug("Plugin starting JBD") app.debug(options) // Store python processes in an array to manage them later const pythonProcesses = []; options.batteries.forEach(battery => { lastUpdateTimes[battery.id] = Date.now(); const fifoPath = path.join('/var/run', `nav${battery.id}`); const fifoStream = fs.createReadStream(fifoPath, { encoding: 'utf8' }); fifoStream.on('data', (data) => { app.debug(`Received data from Python script for battery ${battery.id}: ${data.toString().trim()}`); try { const msg = JSON.parse(data.toString()); if (msg.type == "data"){ const jsonData = msg.data; app.handleMessage(plugin.id, { updates: [ { values: [ { path: `electrical.batteries.${battery.bus}.voltage.${battery.id}`, value: jsonData["Total Voltage"] }, { path: `electrical.batteries.${battery.bus}.name.${battery.id}`, value: battery.name }, { path: `electrical.batteries.${battery.bus}.capacity.nominal.${battery.id}`, value: jsonData["Nominal Capacity J"] }, { path: `electrical.batteries.${battery.bus}.capacity.remaining.${battery.id}`, value: jsonData["Residual Capacity J"] }, { path: `electrical.batteries.${battery.bus}.current.${battery.id}`, // Ensure this path is correct value: jsonData["Current"] }, { path: `electrical.batteries.${battery.bus}.capacity.stateOfCharge.${battery.id}`, // Ensure this path is correct value: jsonData["RSOC"] }, { path: `electrical.batteries.${battery.bus}.cycles.${battery.id}`, // Ensure this path is correct value: jsonData["Cycle Life"] }, { path: `electrical.batteries.${battery.bus}.temperature.${battery.id}`, // Ensure this path is correct value: jsonData["Temperature"] }, { path: `electrical.batteries.${battery.bus}.protection.${battery.id}`, // Ensure this path is correct value: jsonData["Protection Status"] }, { path: `electrical.batteries.${battery.bus}.chemistry.${battery.id}`, // Ensure this path is correct value: 'LiFePO4' } ] } ] }); lastUpdateTimes[battery.id] = Date.now(); } if (msg.type == "status"){ app.handleMessage(plugin.id, { updates: [ { values: [ { path: `electrical.batteries.${battery.bus}.connection.${battery.id}`, value: msg["string"] } ] } ] }); } } catch (error) { app.debug(`Error parsing JSON data for battery ${battery.id}: ${error}`); app.debug(`Received data from Python script for battery ${battery.id}: ${data.toString().trim()}`); } }); // Function to check for stale data function checkForStaleData() { const TIMEOUT = 60000; // 1 minute timeout const currentTime = Date.now(); options.batteries.forEach(battery => { if (currentTime - lastUpdateTimes[battery.id] > TIMEOUT) { // Data is stale, send update to set values to null or ignore app.debug(`Stale data for battery ID ${battery.id}`) app.handleMessage(plugin.id, { updates: [ { values: [ { path: `electrical.batteries.${battery.bus}.voltage.${battery.id}`, value: null }, { path: `electrical.batteries.${battery.bus}.capacity.${battery.id}`, value: null }, // ... set other paths to null or ignore as needed ] } ] }); } }); } // Set an interval to periodically check for stale data setInterval(checkForStaleData, 5000); // Check every 5 seconds, for example }); plugin.stop = function() { pythonProcesses.forEach(process => { if (process) { process.kill(); } }); }; }; plugin.schema = { type: 'object', properties: { batteries: { type: 'array', title: 'Batteries', items: { type: 'object', required: ['name', 'bus', 'id'], properties: { name: { type: 'string', title: 'Name' }, bus: { type: 'string', title: 'Bus' }, id: { type: 'number', title: 'Battery ID' } } } }, refresh: { type: 'number', title: 'Refresh Rate', description: 'How many seconds between updates', default: 1 } } }; return plugin; };