jbd-plugin
Version:
jbd battery plugin for SignalK
182 lines (162 loc) • 6.31 kB
JavaScript
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;
};