127 lines
3.4 KiB
JavaScript
127 lines
3.4 KiB
JavaScript
{
|
|
var dataFile = "smartbattdata.json";
|
|
var interval;
|
|
var storage=require("Storage");
|
|
var settings = Object.assign({
|
|
//Record Interval stored in ms
|
|
doLogging:false
|
|
}, require('Storage').readJSON("smartbatt.settings.json", true) || {});
|
|
|
|
var logFile = "smartbattlog.json";
|
|
var doLogging=true;
|
|
|
|
function logBatterySample(entry) {
|
|
let log = storage.readJSON(logFile, 1) || [];
|
|
|
|
// Keep it from growing forever (optional: only keep last 100 entries)
|
|
if (log.length > 100) log.shift();
|
|
|
|
log.push(entry);
|
|
storage.writeJSON(logFile, log);
|
|
}
|
|
|
|
|
|
|
|
// Record current battery reading into current average
|
|
function recordBattery() {
|
|
let now = Date.now();
|
|
let data = getData();
|
|
|
|
let batt = E.getBattery();
|
|
let battChange = data.battLastRecorded - batt;
|
|
let deltaHours = (now - data.timeLastRecorded) / (1000 * 60 * 60);
|
|
// Default reason (in case we skip)
|
|
let reason = "Recorded";
|
|
|
|
|
|
if (battChange <= 0) {
|
|
reason = "Skipped: battery fluctuated or no change";
|
|
if(Math.abs(battChange)<5){
|
|
//less than 6% difference, average percents
|
|
var newBatt=(batt+data.battLastRecorded)/2;
|
|
data.battLastRecorded = newBatt;
|
|
}else{
|
|
//probably charged, ignore average
|
|
data.battLastRecorded = batt;
|
|
}
|
|
|
|
storage.writeJSON(dataFile, data);
|
|
} else if (deltaHours <= 0 || !isFinite(deltaHours)) {
|
|
reason = "Skipped: invalid time delta";
|
|
data.timeLastRecorded = now;
|
|
data.battLastRecorded = batt;
|
|
storage.writeJSON(dataFile, data);
|
|
} else {
|
|
|
|
let currentDrainage = battChange / deltaHours;
|
|
|
|
let newAvg = weightedAverage(data.avgBattDrainage, data.totalHours, currentDrainage, deltaHours);
|
|
data.avgBattDrainage=newAvg;
|
|
data.timeLastRecorded = now;
|
|
data.totalCycles += 1;
|
|
data.totalHours+=deltaHours;
|
|
data.battLastRecorded = batt;
|
|
storage.writeJSON(dataFile, data);
|
|
|
|
reason = "Drainage recorded: " + currentDrainage.toFixed(3) + "%/hr";
|
|
}
|
|
if(settings.doLogging){
|
|
// Always log the sample
|
|
logBatterySample({
|
|
time: now,
|
|
battNow: batt,
|
|
battLast: data.battLastRecorded,
|
|
battChange: battChange,
|
|
deltaHours: deltaHours,
|
|
avgDrainage: data.avgBattDrainage,
|
|
reason: reason
|
|
});
|
|
}
|
|
}
|
|
|
|
function weightedAverage(oldValue, oldWeight, newValue, newWeight) {
|
|
return (oldValue * oldWeight + newValue * newWeight) / (oldWeight + newWeight);
|
|
}
|
|
|
|
|
|
|
|
function getData() {
|
|
return storage.readJSON(dataFile, 1) || {
|
|
avgBattDrainage: 0,
|
|
battLastRecorded: E.getBattery(),
|
|
timeLastRecorded: Date.now(),
|
|
totalCycles: 0,
|
|
totalHours:0
|
|
};
|
|
}
|
|
|
|
|
|
|
|
// Estimate hours remaining
|
|
function estimateBatteryLife() {
|
|
let data = getData();
|
|
var batt = E.getBattery();
|
|
var hrsLeft = Math.abs(batt / data.avgBattDrainage);
|
|
return {
|
|
batt: batt,
|
|
hrsLeft: hrsLeft,
|
|
};
|
|
}
|
|
|
|
function deleteData(){
|
|
storage.erase(dataFile);
|
|
storage.erase(logFile);
|
|
}
|
|
// Expose public API
|
|
exports.record = recordBattery;
|
|
exports.deleteData = deleteData;
|
|
exports.get = estimateBatteryLife;
|
|
exports.changeInterval = function(newInterval) {
|
|
clearInterval(interval);
|
|
interval=setInterval(recordBattery, newInterval);
|
|
};
|
|
// Start recording every 5 minutes
|
|
interval=setInterval(recordBattery, 600000);
|
|
recordBattery(); // Log immediately
|
|
}
|