Merge branch 'espruino:master' into master
commit
90abce783b
|
|
@ -1 +1,2 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
|
0.02: Allow forcing monotonic battery voltage/percentage
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
# Power manager
|
# Power manager
|
||||||
|
|
||||||
Manages settings for charging. You can set a warning threshold to be able to disconnect the charger at a given percentage. Also allows to set the battery calibration offset.
|
Manages settings for charging.
|
||||||
|
Features:
|
||||||
|
* Warning threshold to be able to disconnect the charger at a given percentage
|
||||||
|
* Set the battery calibration offset.
|
||||||
|
* Force monotonic battery percentage or voltage
|
||||||
|
|
||||||
## Internals
|
## Internals
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,4 +26,26 @@
|
||||||
Bangle.on("charging",handleCharging);
|
Bangle.on("charging",handleCharging);
|
||||||
handleCharging(Bangle.isCharging());
|
handleCharging(Bangle.isCharging());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.forceMonoPercentage){
|
||||||
|
var p = (E.getBattery()+E.getBattery()+E.getBattery()+E.getBattery())/4;
|
||||||
|
var op = E.getBattery;
|
||||||
|
E.getBattery = function() {
|
||||||
|
var current = Math.round((op()+op()+op()+op())/4);
|
||||||
|
if (Bangle.isCharging() && current > p) p = current;
|
||||||
|
if (!Bangle.isCharging() && current < p) p = current;
|
||||||
|
return p;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.forceMonoVoltage){
|
||||||
|
var v = (NRF.getBattery()+NRF.getBattery()+NRF.getBattery()+NRF.getBattery())/4;
|
||||||
|
var ov = NRF.getBattery;
|
||||||
|
NRF.getBattery = function() {
|
||||||
|
var current = (ov()+ov()+ov()+ov())/4;
|
||||||
|
if (Bangle.isCharging() && current > v) v = current;
|
||||||
|
if (!Bangle.isCharging() && current < v) v = current;
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
"warnEnabled": false,
|
"warnEnabled": false,
|
||||||
"warn": 96
|
"warn": 96,
|
||||||
|
"forceMonoVoltage": false,
|
||||||
|
"forceMonoPercentage": false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "powermanager",
|
"id": "powermanager",
|
||||||
"name": "Power Manager",
|
"name": "Power Manager",
|
||||||
"shortName": "Power Manager",
|
"shortName": "Power Manager",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Allow configuration of warnings and thresholds for battery charging and display.",
|
"description": "Allow configuration of warnings and thresholds for battery charging and display.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "bootloader",
|
"type": "bootloader",
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,20 @@
|
||||||
'title': 'Power Manager'
|
'title': 'Power Manager'
|
||||||
},
|
},
|
||||||
'< Back': back,
|
'< Back': back,
|
||||||
|
'Monotonic percentage': {
|
||||||
|
value: !!settings.forceMonoPercentage,
|
||||||
|
format: v => settings.forceMonoPercentage ? "On" : "Off",
|
||||||
|
onchange: v => {
|
||||||
|
writeSettings("forceMonoPercentage", v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Monotonic voltage': {
|
||||||
|
value: !!settings.forceMonoVoltage,
|
||||||
|
format: v => settings.forceMonoVoltage ? "On" : "Off",
|
||||||
|
onchange: v => {
|
||||||
|
writeSettings("forceMonoVoltage", v);
|
||||||
|
}
|
||||||
|
},
|
||||||
'Charge warning': function() {
|
'Charge warning': function() {
|
||||||
E.showMenu(submenu_chargewarn);
|
E.showMenu(submenu_chargewarn);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
/* Code to handle Backup/Restore functionality */
|
||||||
|
|
||||||
|
const BACKUP_STORAGEFILE_DIR = "storage-files";
|
||||||
|
|
||||||
|
function bangleDownload() {
|
||||||
|
var zip = new JSZip();
|
||||||
|
Progress.show({title:"Scanning...",sticky:true});
|
||||||
|
var normalFiles, storageFiles;
|
||||||
|
console.log("Listing normal files...");
|
||||||
|
Comms.listFiles({sf:false}).then(f => {
|
||||||
|
normalFiles = f;
|
||||||
|
console.log(" - "+f.join(","));
|
||||||
|
console.log("Listing StorageFiles...");
|
||||||
|
return Comms.listFiles({sf:true});
|
||||||
|
}).then(f => {
|
||||||
|
storageFiles = f;
|
||||||
|
console.log(" - "+f.join(","));
|
||||||
|
var fileCount = normalFiles.length + storageFiles.length;
|
||||||
|
var promise = Promise.resolve();
|
||||||
|
// Normal files
|
||||||
|
normalFiles.forEach((filename,n) => {
|
||||||
|
promise = promise.then(() => {
|
||||||
|
Progress.hide({sticky: true});
|
||||||
|
var percent = n/fileCount;
|
||||||
|
Progress.show({title:`Download ${filename}`,sticky:true,min:percent,max:percent,percent:0});
|
||||||
|
return Comms.readFile(filename).then(data => zip.file(filename,data));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Storage files
|
||||||
|
if (storageFiles.length) {
|
||||||
|
var zipStorageFiles = zip.folder(BACKUP_STORAGEFILE_DIR);
|
||||||
|
storageFiles.forEach((filename,n) => {
|
||||||
|
promise = promise.then(() => {
|
||||||
|
Progress.hide({sticky: true});
|
||||||
|
var percent = (normalFiles.length+n)/fileCount;
|
||||||
|
Progress.show({title:`Download ${filename}`,sticky:true,min:percent,max:percent,percent:0});
|
||||||
|
return Comms.readStorageFile(filename).then(data => zipStorageFiles.file(filename,data));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("Listing StorageFiles...");
|
||||||
|
return promise;
|
||||||
|
}).then(() => {
|
||||||
|
return zip.generateAsync({type:"blob"});
|
||||||
|
}).then(content => {
|
||||||
|
Progress.hide({ sticky: true });
|
||||||
|
showToast('Backup complete!', 'success');
|
||||||
|
Espruino.Core.Utils.fileSaveDialog(content, "Banglejs backup.zip");
|
||||||
|
}).catch(err => {
|
||||||
|
Progress.hide({ sticky: true });
|
||||||
|
showToast('Backup failed, ' + err, 'error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bangleUpload() {
|
||||||
|
Espruino.Core.Utils.fileOpenDialog({
|
||||||
|
id:"backup",
|
||||||
|
type:"arraybuffer",
|
||||||
|
mimeType:".zip,application/zip"}, function(data) {
|
||||||
|
if (data===undefined) return;
|
||||||
|
var promise = Promise.resolve();
|
||||||
|
var zip = new JSZip();
|
||||||
|
var cmds = "";
|
||||||
|
zip.loadAsync(data).then(function(zip) {
|
||||||
|
return showPrompt("Restore from ZIP","Are you sure? This will remove all existing apps");
|
||||||
|
}).then(()=>{
|
||||||
|
Progress.show({title:`Reading ZIP`});
|
||||||
|
zip.forEach(function (path, file){
|
||||||
|
console.log("path");
|
||||||
|
promise = promise
|
||||||
|
.then(() => file.async("string"))
|
||||||
|
.then(data => {
|
||||||
|
console.log("decoded", path);
|
||||||
|
if (path.startsWith(BACKUP_STORAGEFILE_DIR)) {
|
||||||
|
path = path.substr(BACKUP_STORAGEFILE_DIR.length+1);
|
||||||
|
cmds += AppInfo.getStorageFileUploadCommands(path, data)+"\n";
|
||||||
|
} else if (!path.includes("/")) {
|
||||||
|
cmds += AppInfo.getFileUploadCommands(path, data)+"\n";
|
||||||
|
} else console.log("Ignoring "+path);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return promise;
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
Progress.hide({sticky:true});
|
||||||
|
Progress.show({title:`Erasing...`});
|
||||||
|
return Comms.removeAllApps(); })
|
||||||
|
.then(() => {
|
||||||
|
Progress.hide({sticky:true});
|
||||||
|
Progress.show({title:`Restoring...`, sticky:true});
|
||||||
|
return Comms.showMessage(`Restoring...`); })
|
||||||
|
.then(() => Comms.write("\x10"+Comms.getProgressCmd()+"\n"))
|
||||||
|
.then(() => Comms.uploadCommandList(cmds, 0, cmds.length))
|
||||||
|
.then(() => Comms.showMessage(Const.MESSAGE_RELOAD))
|
||||||
|
.then(() => {
|
||||||
|
Progress.hide({sticky:true});
|
||||||
|
showToast('Restore complete!', 'success');
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
Progress.hide({sticky:true});
|
||||||
|
showToast('Restore failed, ' + err, 'error');
|
||||||
|
});
|
||||||
|
return promise;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('load', (event) => {
|
||||||
|
document.getElementById("downloadallapps").addEventListener("click",event=>{
|
||||||
|
bangleDownload();
|
||||||
|
});
|
||||||
|
document.getElementById("uploadallapps").addEventListener("click",event=>{
|
||||||
|
bangleUpload();
|
||||||
|
});
|
||||||
|
});
|
||||||
2
core
2
core
|
|
@ -1 +1 @@
|
||||||
Subproject commit affb0b15b41eb35a1548373831af7001bad64435
|
Subproject commit 05f97e6ade4605ac7a6105def52a34280f4f0c4d
|
||||||
|
|
@ -81,7 +81,7 @@ a.btn.btn-link.dropdown-toggle {
|
||||||
min-height: 8em;
|
min-height: 8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tile-content { position: relative; }
|
.tile-content { position: relative; word-break: break-all; }
|
||||||
.link-github {
|
.link-github {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
top: 36px;
|
top: 36px;
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,8 @@
|
||||||
<button class="btn" id="removeall">Remove all Apps</button>
|
<button class="btn" id="removeall">Remove all Apps</button>
|
||||||
<button class="btn" id="installdefault">Install default apps</button>
|
<button class="btn" id="installdefault">Install default apps</button>
|
||||||
<button class="btn" id="installfavourite">Install favourite apps</button></p>
|
<button class="btn" id="installfavourite">Install favourite apps</button></p>
|
||||||
|
<p><button class="btn tooltip tooltip-right" id="downloadallapps" data-tooltip="Download all Bangle.js files to a ZIP file">Backup</button>
|
||||||
|
<button class="btn tooltip tooltip-right" id="uploadallapps" data-tooltip="Restore Bangle.js from a ZIP file">Restore</button></p>
|
||||||
<h3>Settings</h3>
|
<h3>Settings</h3>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-switch">
|
<label class="form-switch">
|
||||||
|
|
@ -170,6 +172,8 @@
|
||||||
<script src="core/lib/heatshrink.js"></script>
|
<script src="core/lib/heatshrink.js"></script>
|
||||||
<script src="core/js/utils.js"></script>
|
<script src="core/js/utils.js"></script>
|
||||||
<script src="loader.js"></script>
|
<script src="loader.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script> <!-- for backup.js -->
|
||||||
|
<script src="backup.js"></script>
|
||||||
<script src="core/js/ui.js"></script>
|
<script src="core/js/ui.js"></script>
|
||||||
<script src="core/js/comms.js"></script>
|
<script src="core/js/comms.js"></script>
|
||||||
<script src="core/js/appinfo.js"></script>
|
<script src="core/js/appinfo.js"></script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue