Skip to content

Commit

Permalink
Valetudo 0.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Hypfer committed Apr 6, 2019
1 parent 7ce6d5c commit 382e1a1
Show file tree
Hide file tree
Showing 19 changed files with 736 additions and 817 deletions.
36 changes: 12 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This Project is made possible by the work of many voluntary contributers. ❤
As of now, only **Gen1 + Gen2 Xiaomi Vacuums** are rootable and hence supported by Valetudo.

### Getting started
For newcomers, there is [a simple Guide](https://github.com/dgiese/dustcloud/wiki/Cloud-Free-Firmware-Image-With-Valetudo) which will walk you through the process of rooting a factory-new Vacuum and installing Valetudo on it.
Just follow the [installation guide in the wiki](https://github.com/Hypfer/Valetudo/wiki/Installation-Instructions).

The configuration file stored in `/mnt/data/valetudo/config.json` survives firmware upgrades.
The Valetudo binary however does not so if you are upgrading your firmware, you will have to follow said guide again.
Expand All @@ -37,29 +37,17 @@ The Valetudo binary however does not so if you are upgrading your firmware, you
* Volume Control

### Screenshots:

![image](https://user-images.githubusercontent.com/974410/53036687-88f52d80-3478-11e9-8e9d-e3af35161de0.png)
![image](https://user-images.githubusercontent.com/974410/53036893-1cc6f980-3479-11e9-9cc5-efefea03eb90.png)
![image](https://user-images.githubusercontent.com/974410/53036815-e7221080-3478-11e9-9dc0-db5bedc741af.png)
![image](https://user-images.githubusercontent.com/974410/53036921-2a7c7f00-3479-11e9-87da-633a7319c1bf.png)
![image](https://user-images.githubusercontent.com/974410/53036855-028d1b80-3479-11e9-93a1-3ac7764f1089.png)
![image](https://user-images.githubusercontent.com/974410/53036928-2fd9c980-3479-11e9-8fe9-7ae1e124e4d7.png)
![image](https://user-images.githubusercontent.com/974410/53036939-35cfaa80-3479-11e9-9276-ff5333c98dd6.png)
![image](https://user-images.githubusercontent.com/974410/53036947-3a945e80-3479-11e9-9c40-71775322635b.png)
![image](https://user-images.githubusercontent.com/974410/53037020-657eb280-3479-11e9-9cf4-c9e69740d0e1.png)
![image](https://user-images.githubusercontent.com/974410/53036972-45e78a00-3479-11e9-83c3-c55320ced3ca.png)

#### Updating to newer versions
1. Stop the running service `service valetudo stop`.
2. Replace the binary `/usr/local/bin/valetudo` by the new one (make sure to `chmod +x` it).
3. Start the service again `service valetudo start`.

### Misc
Valetudo does not feature access controls and I'm not planning on adding it since I trust my local network.
You could just put a reverse proxy with authentication in front of it if you really need it.

Please don't just forward the port to make it accessible on the go..

![image](https://user-images.githubusercontent.com/974410/55658091-bc0f3880-57fc-11e9-8840-3e88186d5f56.png)
![image](https://user-images.githubusercontent.com/974410/55658093-be719280-57fc-11e9-97f2-e2a51120bace.png)
![image](https://user-images.githubusercontent.com/974410/55658098-c16c8300-57fc-11e9-9a72-9d702be19482.png)
![image](https://user-images.githubusercontent.com/974410/55658101-c4677380-57fc-11e9-93dd-0551be98b047.png)
![image](https://user-images.githubusercontent.com/974410/55658077-abf75900-57fc-11e9-91c6-9f35f596f773.png)
![image](https://user-images.githubusercontent.com/974410/55658114-cd584500-57fc-11e9-9e01-1ff3c1bcde80.png)
![image](https://user-images.githubusercontent.com/974410/55658120-d47f5300-57fc-11e9-913c-10bc5f8288c4.png)
![image](https://user-images.githubusercontent.com/974410/55658162-fa0c5c80-57fc-11e9-93a0-e67e977c3151.png)
![image](https://user-images.githubusercontent.com/974410/55658169-009ad400-57fd-11e9-9955-856c75054da0.png)
![image](https://user-images.githubusercontent.com/974410/55658203-1a3c1b80-57fd-11e9-8fb2-25cfc1fad4a9.png)
![image](https://user-images.githubusercontent.com/974410/55658219-29bb6480-57fd-11e9-8a66-0d00739c9359.png)
### FAQ
**Q:** Why the name?

Expand Down
46 changes: 23 additions & 23 deletions client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1374,32 +1374,31 @@
import { VacuumMap } from "./zone/js-modules/vacuum-map.js"
const loadingBar = document.getElementById('loading-bar-map');
let map = null;
let currentRefreshTimer = null;

function updateMapPage() {
loadingBar.setAttribute("indeterminate", "indeterminate");
fn.request("api/map/latest?doNotTransformPath", "GET", function (err, mapData) {
fn.request("api/map/latest", "GET", function (err, mapData) {
loadingBar.removeAttribute("indeterminate");
if (!err) {
if(map === null) {
map = new VacuumMap(document.getElementById('map-canvas'));
map.initCanvas(mapData);
map.initWebSocket();
} else {
map.updateMap(mapData);
}
} else {
ons.notification.toast(err, { buttonLabel: 'Dismiss', timeout: 1500 })
}
currentRefreshTimer = window.setTimeout(function () {
updateMapPage();
}.bind(this), 5000);
})
}

// Register update function to be accessible outside of es6 module (see <script> below)
window.fn.updateMapPage = updateMapPage;
window.fn.cancelUpdateMap = () => {
window.clearTimeout(currentRefreshTimer);
if(map !== null) {
map.closeWebSocket();
}
};

/**
Expand Down Expand Up @@ -1450,14 +1449,15 @@
};
ons.getScriptPage().onHide = function () {
window.fn.cancelUpdateMap();

};
</script>
<style>
:root {
--map-background-1: #efeff4;
--map-background-2: #afafaf;
--map-free: #0076ff;
--map-occupied: #6699ff;
--map-occupied: #52aeff;
--path: #ffffff;
}

Expand Down Expand Up @@ -1999,7 +1999,7 @@
function loadNextRemainingElements() {
if (remainingShownCount>0) {
loadingBarSettingsCleaningHistory.setAttribute("indeterminate", "indeterminate");
var historyTimestamp = historyArray.shift(); //array is sorted with latest items in the beginning
var historyTimestamp = historyArray.shift(); //array is sorted with latest items in the beginning
fn.requestWithPayload("api/clean_record", JSON.stringify({recordId : historyTimestamp}) , "PUT", function (err, res) {
loadingBarSettingsCleaningHistory.removeAttribute("indeterminate");
if (err) {
Expand Down Expand Up @@ -2027,28 +2027,28 @@
" <ons-col width='400px' vertical-align='center' style='text-align:center;'>#" + currentEntryId + " started on " + fromTime + "</ons-col>" +
" <ons-col></ons-col>" +
" </ons-row>" +
" <ons-row>" +
" <ons-row>" +
" <ons-col></ons-col>" +
" <ons-col vertical-align='center' width='100px'>Duration</ons-col>" +
" <ons-col vertical-align='center' width='150px'>" + durationHours + ":" + formatTwoDigitNumber(durationMinutes) + ":" + formatTwoDigitNumber(durationSeconds) + "</ons-col>" +
" <ons-col vertical-align='center' width='100px'>Duration</ons-col>" +
" <ons-col vertical-align='center' width='150px'>" + durationHours + ":" + formatTwoDigitNumber(durationMinutes) + ":" + formatTwoDigitNumber(durationSeconds) + "</ons-col>" +
" <ons-col></ons-col>" +
" </ons-row>"+
" <ons-row>" +
" <ons-row>" +
" <ons-col></ons-col>" +
" <ons-col vertical-align='center' width='100px'>Area</ons-col>" +
" <ons-col vertical-align='center' width='150px'>" + area + " m<sup>2</sup></ons-col>" +
" <ons-col vertical-align='center' width='100px'>Area</ons-col>" +
" <ons-col vertical-align='center' width='150px'>" + area + " m<sup>2</sup></ons-col>" +
" <ons-col></ons-col>" +
" </ons-row>"+
" <ons-row>" +
" <ons-row>" +
" <ons-col></ons-col>" +
" <ons-col vertical-align='center' width='100px'>Completed</ons-col>" +
" <ons-col vertical-align='center' width='150px'>" + (completedFlag?"<ons-icon icon='fa-check-circle' style='color:green;'>":"<ons-icon icon='fa-times-circle' style='color:red;'>") + "</ons-col>" +
" <ons-col vertical-align='center' width='100px'>Completed</ons-col>" +
" <ons-col vertical-align='center' width='150px'>" + (completedFlag?"<ons-icon icon='fa-check-circle' style='color:green;'>":"<ons-icon icon='fa-times-circle' style='color:red;'>") + "</ons-col>" +
" <ons-col></ons-col>" +
" </ons-row>"+
(errorCode>0?
" <ons-row>" +
" <ons-row>" +
" <ons-col></ons-col>" +
" <ons-col vertical-align='center' width='400px' style='text-align:center;'><ons-icon icon='fa-warning' style='color:red;'></ons-icon>&nbsp;" + errorDescription + " (Code: " + errorCode + ")</ons-col>" +
" <ons-col vertical-align='center' width='400px' style='text-align:center;'><ons-icon icon='fa-warning' style='color:red;'></ons-icon>&nbsp;" + errorDescription + " (Code: " + errorCode + ")</ons-col>" +
" <ons-col></ons-col>" +
" </ons-row>"
: "" ) +
Expand Down Expand Up @@ -2610,12 +2610,12 @@

function hideTimeZoneDialog() {
document.getElementById('edit-timezone-dialog').hide();
}
}

function saveTimeZone() {
var timeZoneSelection = document.getElementById('timezone-selection');
var newTimezone = timeZoneSelection.options[timeZoneSelection.selectedIndex].value;

ons.notification.confirm('Do you really want to set your timezone to "' + newTimezone + '"?').then(function (answer) {
if (answer === 1) {
loadingBarSettingsTimers.setAttribute("indeterminate", "indeterminate");
Expand All @@ -2636,7 +2636,7 @@
document.getElementById('edit-dnd-form').start_minute.value = (startMinute>=0?startMinute:"");
document.getElementById('edit-dnd-form').end_hour.value = (endHour>=0?endHour:"");
document.getElementById('edit-dnd-form').end_minute.value = (endMinute>=0?endMinute:"");
document.getElementById('edit-dnd-timer-dialog').show();
document.getElementById('edit-dnd-timer-dialog').show();
};

var hideDndTimerDialog = function() {
Expand Down Expand Up @@ -2925,7 +2925,7 @@
if (timerId == -1) {
clearNewTimerDialog();
}
document.getElementById('add-timer-dialog').show();
document.getElementById('add-timer-dialog').show();
};

var hideNewTimerDialog = function() {
Expand Down
2 changes: 1 addition & 1 deletion client/zone/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
--map-background-2: #afafaf;

--map-free: #0076ff;
--map-occupied: #6699ff;
--map-occupied: #52aeff;
--path: #ffffff;
}

Expand Down
6 changes: 0 additions & 6 deletions client/zone/js-modules/coordinate-transforms.js

This file was deleted.

75 changes: 27 additions & 48 deletions client/zone/js-modules/map-drawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@
export function MapDrawer() {
const mapCanvas = document.createElement('canvas');
const mapCtx = mapCanvas.getContext("2d");
let boundingBox = {
minX: 0,
minY: 0,
maxX: 1024,
maxY: 1024
}

mapCanvas.width = 1024;
mapCanvas.height = 1024;
Expand All @@ -30,59 +24,44 @@ export function MapDrawer() {
* @param {Array<Array<number>>} mapData - the data containing the map image (array of pixel offsets and colors)
*/
function draw(mapData) {
this.boundingBox = getBoundingBox(mapData, mapCanvas.width, mapCanvas.height);

const freeColor = hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--map-free') || '#0076ff');
const occupiedColor = hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--map-occupied') || '#6699ff');
const occupiedColor = hexToRgb(getComputedStyle(document.documentElement).getPropertyValue('--map-occupied') || '#52aeff');

mapCtx.clearRect(0, 0, mapCanvas.width, mapCanvas.height);
const imgData = mapCtx.createImageData(mapCanvas.width, mapCanvas.height);
mapData.forEach(function (px) {
if (px[1] === 0 && px[2] === 0 && px[3] === 0) {
imgData.data[px[0]] = occupiedColor.r;
imgData.data[px[0] + 1] = occupiedColor.g;
imgData.data[px[0] + 2] = occupiedColor.b;
imgData.data[px[0] + 3] = 255;

} else {
imgData.data[px[0]] = freeColor.r;
imgData.data[px[0] + 1] = freeColor.g;
imgData.data[px[0] + 2] = freeColor.b;
imgData.data[px[0] + 3] = 255;
}
});
mapCtx.putImageData(imgData, 0, 0);
}
if(mapData && mapData.pixels) {
Object.keys(mapData.pixels).forEach(function(key){
var color;
switch(key) {
case "floor":
color = freeColor;
break;
case "obstacle_weak":
color = occupiedColor;
break;
case "obstacle_strong":
color = occupiedColor;
break;
}

/**
* This function calculates the bounding box of the map.
* This is used in order to zoom onto the map on first load of the page.
* @param {Array<Array<number>>} mapData - the data containing the map image (array of pixel offsets and colors)
* @param {number} maxWidth - usually the width of the mapCanvas
* @param {number} maxHeight - usually the height of the mapCanvas
*/
function getBoundingBox(mapData, maxWidth, maxHeight) {
let minX = maxWidth;
let maxX = 0;
let minY = maxHeight;
let maxY = 0;
mapData.pixels[key].forEach(function(px){
const imgDataOffset = (px[0] + mapData.position.left + (px[1] + mapData.position.top) * mapCanvas.width) * 4;

mapData.forEach(function (px) {
const pxOffset = px[0] / 4;
const x = pxOffset % maxWidth;
const y = Math.floor(pxOffset / maxWidth);
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (y < minY) minY = y;
if (y > maxY) maxY = y;
});
imgData.data[imgDataOffset] = color.r;
imgData.data[imgDataOffset + 1] = color.g;
imgData.data[imgDataOffset + 2] = color.b;
imgData.data[imgDataOffset + 3] = 255;
})
});
}

return { minX, minY, maxX, maxY };

mapCtx.putImageData(imgData, 0, 0);
}

return {
draw: draw,
canvas: mapCanvas,
boundingBox: boundingBox
canvas: mapCanvas
};
}
Loading

0 comments on commit 382e1a1

Please sign in to comment.