diff --git a/README.md b/README.md index 184d1e7..28fbab0 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,12 @@ [![Greenkeeper badge](https://badges.greenkeeper.io/sbender9/signalk-derived-data.svg)](https://greenkeeper.io/) -Generates deltas for values derived from signalk values +Generates deltas for values derived from SignalK values It currently calculates: * Outside air density (based on humidity, temperature and pressure) - * Battery Power + * Battery Power and Time to Full / Time to Empty * Depth Below Keel (based on depth.belowSurface and design.draft.maximum) * Depth Below Keel (based on depth.belowTransducer and depth.transducerToKeel) * Depth Below Surface (based on depth.belowKeel and design.draft.maximum) @@ -31,7 +31,7 @@ It currently calculates: * Moon illumination and times (based on time and navigation.position) * Sunlight Times: sunrise, sunriseEnd, goldenHourEnd, solarNoon, goldenHour, sunsetStart, sunset, dusk, nauticalDusk, night, nadir, nightEnd, nauticalDawn, dawn (based on time and navigation.position) * Outside Heat Index (based on temperature and humidity) - * True Course Over Goround (based on courseOverGroundMagnetic and magneticVariation) + * True Course Over Ground (based on courseOverGroundMagnetic and magneticVariation) * Magnetic Course Over Ground (based on courseOverGroundTrue and magneticVariation) To add new calculations, just create a new file under the `./calcs` directory. diff --git a/calcs/batteryTime.js b/calcs/batteryTime.js new file mode 100644 index 0000000..0519301 --- /dev/null +++ b/calcs/batteryTime.js @@ -0,0 +1,75 @@ +const _ = require('lodash') + +module.exports = function (app, plugin) { + return plugin.batteries.map(instance => { + return { + group: 'electrical', + optionKey: 'batteryTime' + instance, + title: 'Battery ' + instance + ' Time to Full / Empty', + properties: { + ['capacity.' + instance]: { + type: 'number', + title: 'Capacity of battery bank in Wh', + default: 5120 + }, + ['socHigh.' + instance]: { + type: 'number', + title: 'State of Charge at Full (Percentage)', + default: 100 + }, + ['socLow.' + instance]: { + type: 'number', + title: 'State of Charge at Empty (Percentage)', + default: 20 + } + }, + derivedFrom: function () { + return [ + 'electrical.batteries.' + instance + '.power', + 'electrical.batteries.' + instance + '.capacity.stateOfCharge' + ] + }, + calculator: function (p, soc) { + let capacity = parseFloat( + plugin.properties.electrical['capacity.' + instance] + ) + let socLow = + parseFloat(plugin.properties.electrical['socLow.' + instance]) / 100 + let socHigh = + parseFloat(plugin.properties.electrical['socHigh.' + instance]) / 100 + + // app.debug('Capacity: ' + capacity) + // app.debug('SocLow: ' + socLow) + // app.debug('SocHigh: ' + socHigh) + + output = [] + + // how long til full? + let time_to_full = 0 + if (p > 0 && soc < 0.99) { + time_to_full = Math.round(capacity * 60 * 60 * (socHigh - soc) / p) + } + output.push({ + path: 'electrical.batteries.' + instance + '.capacity.timeToFull', + value: time_to_full + }) + + // how long til empty? + let soc_remaining = soc - socLow + let time_to_empty = 0 + if (soc_remaining > 0 && p < 0) { + p = Math.abs(p) + time_to_empty = Math.round(capacity * 60 * 60 * soc_remaining / p) + } + output.push({ + path: 'electrical.batteries.' + instance + '.capacity.timeToEmpty', + value: time_to_empty + }) + + // app.debug(output) + + return output + } + } + }) +}