iRobot Roomba 980 integration
Moderator: leecollings
-
- Posts: 10
- Joined: Monday 05 December 2016 9:05
- Target OS: Raspberry Pi / ODroid
- Domoticz version: Latest
- Location: Netherlands
- Contact:
iRobot Roomba 980 integration
Hi,
I have an iRobot Roomba 980 robot vacuum cleaner, with wifi connection.
It is possible to control the robot via an app and I know how to control this robot via HTTP POST commands.
Can someone advise me how to accomplish this with Lua, or do I have to call Curl via the Lua script?
Also I want to query the status of the robot every 15 minutes, to check if the robot is back on it's base again.
If I use Curl to query the status, the command would look like (assume Roomba has IP 192.168.10.70);
curl -H "Content-Type: application/json" -H "Connection: close" -H "User-Agent: aspen%20production/2618 CFNetwork/758.3.15 Darwin/15.4.0" -H "Content-Encoding: identity" -H "Accept: */*" -H "Accept-Language: en-us" -H "Host: 192.168.10.70" -H "Authorization: Basic [base64-password]" -X POST -d '{"do":"get","args":["mssn"],"id":1}' -k https://192.168.10.70/umi
Then I get (for example) the following response;
{"ok":{"flags":0,"cycle":"none","phase":"charge","pos":{"theta":179,"point":{"x":221,"y":-12}},"batPct":97,"expireM":0,"rechrgM":0,"error":0,"notReady":0,"mssnM":0,"sqft":0},"id":1}
"cycle":"none" tells me the robot is not driving around.
"phase":"charge" tells me the robot is on it's base station, charging.
Also the "error" and "notReady" fields are possibly interesting to monitor.
I would like to query these fields with a Lua script and put them individually in Domoticz variables for further processing.
There is a lot more possible with HTTP POST commands, so if someone is able to write a plugin for full integration of the Roomba 980 in Domoticz that would be even better!
Start a cleaning-job:
POST https://192.168.10.70/umi
Content-Type: application/json
Connection: close
User-Agent: aspen%20production/2618 CFNetwork/758.3.15 Darwin/15.4.0
Content-Encoding: identity
Accept: */*
Accept-Language: en-us
Host: 192.168.10.70
Authorization: Basic [base64-password]
{"do":"set","args":["cmd" {"op":"start"}],"id":1}
Pause the cleaning-job (replace the commands above with):
{"do":"set","args":["cmd" {"op":"pause"}],"id":1}
Resume the cleaning-job (replace the commands above with):
{"do":"set","args":["cmd" {"op":"resume"}],"id":1}
Stop the cleaning-job (replace the commands above with):
{"do":"set","args":["cmd" {"op":"stop"}],"id":1}
Return to base (replace the commands above with):
{"do":"set","args":["cmd" {"op":"dock"}],"id":1}
You will need to get the uniq device password (replace field [base64-password] above, without brackets) and that can be a bit difficult.
Please check the article on the following page to accomplish that;
https://community.smartthings.com/t/roo ... g/44860/93
For more possible commands, please check the source code of the following project;
https://github.com/koalazak/dorita980/
Kind regards,
Rene.
I have an iRobot Roomba 980 robot vacuum cleaner, with wifi connection.
It is possible to control the robot via an app and I know how to control this robot via HTTP POST commands.
Can someone advise me how to accomplish this with Lua, or do I have to call Curl via the Lua script?
Also I want to query the status of the robot every 15 minutes, to check if the robot is back on it's base again.
If I use Curl to query the status, the command would look like (assume Roomba has IP 192.168.10.70);
curl -H "Content-Type: application/json" -H "Connection: close" -H "User-Agent: aspen%20production/2618 CFNetwork/758.3.15 Darwin/15.4.0" -H "Content-Encoding: identity" -H "Accept: */*" -H "Accept-Language: en-us" -H "Host: 192.168.10.70" -H "Authorization: Basic [base64-password]" -X POST -d '{"do":"get","args":["mssn"],"id":1}' -k https://192.168.10.70/umi
Then I get (for example) the following response;
{"ok":{"flags":0,"cycle":"none","phase":"charge","pos":{"theta":179,"point":{"x":221,"y":-12}},"batPct":97,"expireM":0,"rechrgM":0,"error":0,"notReady":0,"mssnM":0,"sqft":0},"id":1}
"cycle":"none" tells me the robot is not driving around.
"phase":"charge" tells me the robot is on it's base station, charging.
Also the "error" and "notReady" fields are possibly interesting to monitor.
I would like to query these fields with a Lua script and put them individually in Domoticz variables for further processing.
There is a lot more possible with HTTP POST commands, so if someone is able to write a plugin for full integration of the Roomba 980 in Domoticz that would be even better!
Start a cleaning-job:
POST https://192.168.10.70/umi
Content-Type: application/json
Connection: close
User-Agent: aspen%20production/2618 CFNetwork/758.3.15 Darwin/15.4.0
Content-Encoding: identity
Accept: */*
Accept-Language: en-us
Host: 192.168.10.70
Authorization: Basic [base64-password]
{"do":"set","args":["cmd" {"op":"start"}],"id":1}
Pause the cleaning-job (replace the commands above with):
{"do":"set","args":["cmd" {"op":"pause"}],"id":1}
Resume the cleaning-job (replace the commands above with):
{"do":"set","args":["cmd" {"op":"resume"}],"id":1}
Stop the cleaning-job (replace the commands above with):
{"do":"set","args":["cmd" {"op":"stop"}],"id":1}
Return to base (replace the commands above with):
{"do":"set","args":["cmd" {"op":"dock"}],"id":1}
You will need to get the uniq device password (replace field [base64-password] above, without brackets) and that can be a bit difficult.
Please check the article on the following page to accomplish that;
https://community.smartthings.com/t/roo ... g/44860/93
For more possible commands, please check the source code of the following project;
https://github.com/koalazak/dorita980/
Kind regards,
Rene.
-
- Posts: 10
- Joined: Monday 05 December 2016 9:05
- Target OS: Raspberry Pi / ODroid
- Domoticz version: Latest
- Location: Netherlands
- Contact:
Re: iRobot Roomba 980 integration
So far I have accomplished this with a bash script, but I can imagine this can be done prettier;
Code: Select all
#!/bin/bash
function jsonValue()
{
key=$1
num=$2
awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'$key'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p
}
output=`curl -s -H "Content-Type: application/json" -H "Connection: close" -H "User-Agent: aspen%20production/2618 CFNetwork/758.3.15 Darwin/15.4.0" -H "Content-Encoding: identity" -H "Accept-Language: en-us" -H "Host: 192.168.10.70" -H "Authorization: Basic [base64-password]" -X POST -d '{"do":"get","args":["mssn"],"id":1}' -k https://192.168.10.70/umi`
RoombaActivity=`echo $output | jsonValue cycle 1`
RoombaStatus=`echo $output | jsonValue phase 1`
if [ "$RoombaActivity" == "none" ]; then
RoombaActivity='Geen'
else
RoombaActivity='Bezig'
fi
if [ "$RoombaStatus" == "charge" ]; then
RoombaStatus='Opladen'
elif [ "$RoombaStatus" == "stop" ]; then
RoombaStatus='Gestopt'
else
RoombaStatus='Bezig'
fi
echo "Roomba Activiteit :" $RoombaActivity
echo -n "Bijgewerkt Domoticz :" && curl -s "http://127.0.0.1:8080/json.htm?type=command¶m=updateuservariable&vname=RoombaActivity&vtype=2&vvalue=$RoombaActivity" | jsonValue status 1
echo "Roomba Status :" $RoombaStatus
echo -n "Bijgewerkt Domoticz :" && curl -s "http://127.0.0.1:8080/json.htm?type=command¶m=updateuservariable&vname=RoombaStatus&vtype=2&vvalue=$RoombaStatus" | jsonValue status 1
-
- Posts: 485
- Joined: Thursday 17 September 2015 10:13
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
Re: iRobot Roomba 980 integration
Thanks for sharing this @Renermbrmb wrote:Hi,
I have an iRobot Roomba 980 robot vacuum cleaner, with wifi connection.
...
I have one that will be delivered to me tomorrow and of course it needs to be automated. Awesome!
Cheers
-
- Posts: 10
- Joined: Monday 05 December 2016 9:05
- Target OS: Raspberry Pi / ODroid
- Domoticz version: Latest
- Location: Netherlands
- Contact:
Re: iRobot Roomba 980 integration
You are welcome.
The only problem at this moment is that iRobot has pushed firmware 2.x, and since this release they have changed the communication protocol completely. The iRobot is now using MQTT in stead of HTTP with firmware 1.x.
There are more people looking for a solution... See also:
https://community.smartthings.com/t/roo ... /44860/144
The only problem at this moment is that iRobot has pushed firmware 2.x, and since this release they have changed the communication protocol completely. The iRobot is now using MQTT in stead of HTTP with firmware 1.x.
There are more people looking for a solution... See also:
https://community.smartthings.com/t/roo ... /44860/144
-
- Posts: 485
- Joined: Thursday 17 September 2015 10:13
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
Re: iRobot Roomba 980 integration
I've installed the dorita980: unofficial iRobot Roomba 980 NodeJS library / SDK and it's firmware 2.0.0 compatible. I installed it on a different Raspberry Pi, not the one that I use for Domoticz. The HTTP REST API interface is not firmware 2.0.0 compatible yet.rmbrmb wrote:You are welcome.
The only problem at this moment is that iRobot has pushed firmware 2.x, and since this release they have changed the communication protocol completely. The iRobot is now using MQTT in stead of HTTP with firmware 1.x.
There are more people looking for a solution... See also:
https://community.smartthings.com/t/roo ... /44860/144
Cheers!
Last edited by BakSeeDaa on Friday 24 February 2017 9:46, edited 2 times in total.
-
- Posts: 485
- Joined: Thursday 17 September 2015 10:13
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
Re: iRobot Roomba 980 integration
Below is my current working solution for a RaspBerry Pi. It might be improved in many ways but I will await further development of the dorita980: unofficial iRobot Roomba 980 NodeJS library / SDK and the HTTP REST API interface before doing more.
First install the dorita980: unofficial iRobot Roomba 980 NodeJS library / SDK
Set up a Node.js-environment on your Raspberry Pi if You haven't done that already.
Create a dummy Text Device in Domoticz and name it "Adolf Status". (Yes, my iRobot Roomba 980 is named Adolf. Your iRobot Roomba 980 may be named differently.)
Optionally create a dummy Switch Device in Domoticz and name it "schAdolf". Assign a schedule to it and enter when the iRobot Roomba 980 is allowed to autostart)
Created a couple of dummy switches (Adolf Start, Adolf Stop, Adolf Pause, Adolf Resume), entered a 2 second delay off on each switch and put some LUA code into work. Then I made the following LUA script:
script_device_adolf.lua (Your tmp directory might be /tmp instead of /var/tmp Change if necessary!)
Create a user variable in Domoticz named roomba980LastRun
Create the following shell script:
/home/pi/domoticz/scripts/sh/adolfGetMission.sh
Create the following script:
home/pi/domoticz/scripts/js/adolf-getMission.js (Your tmp directory might be /tmp instead of /var/tmp Change if necessary!)
Assign proper permissions
Try if it's working:
When it works, make a crontab entry:
Wait 10 minutes and check if the process is up and running
Below some LUA code that I use in my system to autostart the iRobot Roomba 980 when I leave the premises. It's here just to give You some ideas. You will not be able to use exactly the same LUA script in your system.
First install the dorita980: unofficial iRobot Roomba 980 NodeJS library / SDK
Set up a Node.js-environment on your Raspberry Pi if You haven't done that already.
Create a dummy Text Device in Domoticz and name it "Adolf Status". (Yes, my iRobot Roomba 980 is named Adolf. Your iRobot Roomba 980 may be named differently.)
Optionally create a dummy Switch Device in Domoticz and name it "schAdolf". Assign a schedule to it and enter when the iRobot Roomba 980 is allowed to autostart)
Created a couple of dummy switches (Adolf Start, Adolf Stop, Adolf Pause, Adolf Resume), entered a 2 second delay off on each switch and put some LUA code into work. Then I made the following LUA script:
script_device_adolf.lua (Your tmp directory might be /tmp instead of /var/tmp Change if necessary!)
Code: Select all
commandArray = {}
if (devicechanged['Adolf Start'] == 'On') then -- Virtual switch to set on/off state
os.execute('echo -ne start > /var/tmp/adolf-cmd > /dev/null 2>&1 &')
end
if (devicechanged['Adolf Stop'] == 'On') then -- Virtual switch to set on/off state
os.execute('echo -ne stop > /var/tmp/adolf-cmd > /dev/null 2>&1 &')
end
if (devicechanged['Adolf Pause'] == 'On') then -- Virtual switch to set on/off state
os.execute('echo -ne pause > /var/tmp/adolf-cmd > /dev/null 2>&1 &')
end
if (devicechanged['Adolf Resume'] == 'On') then -- Virtual switch to set on/off state
os.execute('echo -ne resume > /var/tmp/adolf-cmd > /dev/null 2>&1 &')
end
if (devicechanged['Adolf Dock'] == 'On') then -- Virtual switch to set on/off state
os.execute('echo -ne dock > /var/tmp/adolf-cmd > /dev/null 2>&1 &')
end
return commandArray
Create the following shell script:
/home/pi/domoticz/scripts/sh/adolfGetMission.sh
Code: Select all
#!/bin/bash
if pidof -x "adolf-getMission.js" >/dev/null; then
echo "Adolf getMission process already running"
exit 0
fi
node /home/pi/domoticz/scripts/js/adolf-getMission.js &
home/pi/domoticz/scripts/js/adolf-getMission.js (Your tmp directory might be /tmp instead of /var/tmp Change if necessary!)
Code: Select all
#!/usr/bin/nodejs
var dorita980 = require('dorita980');
var request = require("request");
var fs = require('fs');
var domoHostAndPort = 'http://DOMOUSERNAME:DOMOPASSW@DOMOHOSTNAME:8080';
var domoTextDeviceIdx = 503; // Change this
var cleanMissionStatus = 5000; // default is 800ms
var myRobotViaLocal = new dorita980.Local('MyUsernameBlid', 'MyPassword', '192.168.4.70', 2, cleanMissionStatus);
var lastPhase = '';
myRobotViaLocal.on('mission', function (data) {
var phase = data.cleanMissionStatus.phase;
//console.log(phase);
if (phase != lastPhase) {
lastPhase = phase;
tellDomoticz('Adolf', phase, domoTextDeviceIdx);
}
var cmdfile = '/var/tmp/adolf-cmd';
fs.exists(cmdfile, function(exists) {
if(exists) {
var contents = fs.readFileSync(cmdfile, 'utf8');
console.log('Received command: ' + contents);
if (contents == 'start') myRobotViaLocal.start();
if (contents == 'stop') myRobotViaLocal.stop();
if (contents == 'dock') myRobotViaLocal.dock();
if (contents == 'pause') myRobotViaLocal.pause();
if (contents == 'resume') myRobotViaLocal.resume();
fs.unlinkSync(cmdfile);
}
});
});
function getDateTime() {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
var sec = date.getSeconds();
sec = (sec < 10 ? "0" : "") + sec;
var year = date.getFullYear();
var month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
var day = date.getDate();
day = (day < 10 ? "0" : "") + day;
return year + "-" + month + "-" + day + " " + hour + ":" + min + ":" + sec;
}
function tellDomoticz(robotName, newText, idx) {
if (newText == 'run') {
request(domoHostAndPort + "/json.htm?type=command¶m=saveuservariable&vname=roomba980LastRun&vtype=2&vvalue=" + newText, function(error, response, body) {
console.log(getDateTime() + ' Storing last run info for ' + robotName + ' : ' + response.statusCode);
})
}
request(domoHostAndPort + "/json.htm?type=command¶m=udevice&idx=" + idx + "&nvalue=0&svalue=" + newText, function(error, response, body) {
console.log(getDateTime() + ' ' + robotName + ' ' + newText + ': ' + response.statusCode);
})
}
Code: Select all
chmod 755 /home/pi/domoticz/scripts/js/adolf-getMission.js
chmod 755 /home/pi/domoticz/scripts/sh/adolfGetMission.sh
Code: Select all
/usr/bin/nodejs /home/pi/domoticz/scripts/js/adolf-getMission.js
Code: Select all
*/10 * * * * /home/pi/domoticz/scripts/sh/adolfGetMission.sh
Code: Select all
ps -ef|grep dolf
Code: Select all
commandArray = {}
-- Start Adolf automatically ?
if ((devicechanged['Z1 Alarm'])
or (devicechanged['schAdolf'] == 'On')) then
if ((otherdevices_svalues['Z1 Alarm'] == 'Arm Away')
and (otherdevices['schAdolf'] == 'On')) then
getMyDomo()
-- Has it been more than 36 hours since last time Adolf went out?
if (mydomo.utils.timedifference(uservariables_lastupdate['roomba980LastRun']) > (3600*36) ) then
if (otherdevices['Adolf Status'] ~= 'run') then
commandArray['Adolf Start'] = 'On'
end
end
end
end
-- Pause Adolf if necessary when I'm engaged in a phone conversation
if (devicechanged['PhoneConversation'] or devicechanged['A580 IP']) then
local switchCmd = 'Off'
if (((otherdevices['PhoneConversation'] == 'On') or (otherdevices['A580 IP'] == 'On'))
and (otherdevices_svalues['Adolf Status'] == 'run')) then
commandArray['Adolf Pause'] = 'On'
elseif (((otherdevices['PhoneConversation'] == 'Off') and (otherdevices['A580 IP'] == 'Off'))
and (otherdevices_svalues['Adolf Status'] == 'stop')) then
commandArray['Adolf Resume'] = 'On'
end
end
return commandArray
Last edited by BakSeeDaa on Friday 24 February 2017 10:30, edited 5 times in total.
-
- Posts: 10
- Joined: Monday 05 December 2016 9:05
- Target OS: Raspberry Pi / ODroid
- Domoticz version: Latest
- Location: Netherlands
- Contact:
Re: iRobot Roomba 980 integration
Thanks for sharing!
-
- Posts: 485
- Joined: Thursday 17 September 2015 10:13
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
Re: iRobot Roomba 980 integration
The code that I shared above has been updated.rmbrmb wrote:Thanks for sharing!
Re: iRobot Roomba 980 integration
Hello all,
I recently bougth an iRobot Roomba (896) and was looking at this post to include the Roomba to my Domoticz environment.
My Roomba was delivered with a newer firmware than dorita980 supports (in my case 3.2.7) and therefor the software/code needed some changes.
I wanted to share my code for people with the same "problem".
We need to change the local.js file from dorita980 because the variable "pose" does not exist in the 896 3.2.7 software.
Changes to "dorita980/lib/v2/local.js":
We also need to change the "-getMission.js", besides the "pose" we need to change seeing the variable does not exist we also need to change the code so we don't leave any open streams to our Roomba.
As a bonus we will create a file that stores the last phase so we won't keep updating it unnecessarily.
FYI my Roomba is called Dusty so change the settings to your liking:
I changed the crontab as well seeing I don't want to check the status at night because the Roomba will light up and we have pets:
Hope this helps,
Drago
I recently bougth an iRobot Roomba (896) and was looking at this post to include the Roomba to my Domoticz environment.
My Roomba was delivered with a newer firmware than dorita980 supports (in my case 3.2.7) and therefor the software/code needed some changes.
I wanted to share my code for people with the same "problem".
We need to change the local.js file from dorita980 because the variable "pose" does not exist in the 896 3.2.7 software.
Changes to "dorita980/lib/v2/local.js":
Code: Select all
'use strict';
const mqtt = require('mqtt');
var dorita980 = function localV2 (user, password, host, emitIntervalTime) {
if (!user) throw new Error('robotID is required.');
if (!password) throw new Error('password is required.');
if (!host) throw new Error('host is required.');
emitIntervalTime = emitIntervalTime || 800;
var robotState = {};
var missionInterval;
const url = 'tls://' + host;
var options = {
port: 8883,
clientId: user,
rejectUnauthorized: false,
protocolId: 'MQTT',
protocolVersion: 4,
clean: false,
username: user,
password: password
};
const client = mqtt.connect(url, options);
client.on('error', function (e) {
throw e;
});
client.on('connect', function () {
missionInterval = setInterval(() => {
if (robotState.cleanMissionStatus) { //) { && robotState.pose) {
client.emit('mission', filterProps(['cleanMissionStatus', 'bin'])); //'pose', 'bin']));
}
}, emitIntervalTime);
});
client.on('close', function () {
clearInterval(missionInterval);
});
client.on('packetreceive', function (packet) {
if (packet.payload) {
try {
const msg = JSON.parse(packet.payload.toString());
robotState = Object.assign(robotState, msg.state.reported);
client.emit('update', msg);
client.emit('state', robotState);
} catch (e) {}
}
});
function _apiCall (topic, command) {
return new Promise((resolve, reject) => {
let cmd = {command: command, time: Date.now() / 1000 | 0, initiator: 'localApp'};
if (topic === 'delta') {
cmd = {'state': command};
}
client.publish(topic, JSON.stringify(cmd), function (e) {
if (e) return reject(e);
resolve({ok: null}); // for retro compatibility
});
});
}
function hasAllProps (obj, properties) {
for (var p in properties) {
if (!obj.hasOwnProperty(properties[p])) {
return false;
}
}
return true;
}
function filterProps (properties) {
let ret = {};
if (properties.length === 1) return robotState[properties[0]];
for (var p in properties) {
ret[properties[p]] = robotState[properties[p]];
}
return ret;
}
function waitPreferences (decode, waitFor, returnOnlyThat) {
waitFor = (typeof waitFor === 'string') ? [waitFor] : waitFor;
return new Promise((resolve) => {
var checkInterval = setInterval(() => {
if (hasAllProps(robotState, waitFor)) {
clearInterval(checkInterval);
resolve(returnOnlyThat ? filterProps(waitFor) : robotState);
}
}, 100);
});
}
return Object.assign(client, {
getTime: () => waitPreferences(false, ['utctime'], true),
getBbrun: () => waitPreferences(false, ['bbrun'], true),
getLangs: () => waitPreferences(false, ['langs'], true),
getSys: () => waitPreferences(false, ['bbrstinfo', 'cap', 'sku', 'batteryType', 'soundVer', 'uiSwVer', 'navSwVer', 'wifiSwVer', 'mobilityVer', 'bootloaderVer', 'umiVer', 'softwareVer', 'audio', 'bin'], true),
getWirelessLastStatus: () => waitPreferences(false, ['wifistat', 'wlcfg'], true),
getWeek: () => waitPreferences(false, ['cleanSchedule'], true),
getPreferences: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'cleanSchedule', 'name', 'vacHigh', 'pose', 'signal'], false),
getRobotState: (fields) => waitPreferences(false, fields, false),
getMission: (decode) => waitPreferences(decode, ['cleanMissionStatus', 'pose', 'bin', 'batPct'], true),
getWirelessConfig: () => waitPreferences(false, ['wlcfg', 'netinfo'], true),
getWirelessStatus: () => waitPreferences(false, ['wifistat', 'netinfo'], true),
getCloudConfig: () => waitPreferences(false, ['cloudEnv'], true),
getSKU: () => waitPreferences(false, ['sku'], true),
start: () => _apiCall('cmd', 'start'),
pause: () => _apiCall('cmd', 'pause'),
stop: () => _apiCall('cmd', 'stop'),
resume: () => _apiCall('cmd', 'resume'),
dock: () => _apiCall('cmd', 'dock'),
setWeek: (args) => _apiCall('delta', {cleanSchedule: args}),
setPreferences: (args) => _apiCall('delta', args),
setCarpetBoostAuto: () => _apiCall('delta', {'carpetBoost': true, 'vacHigh': false}),
setCarpetBoostPerformance: () => _apiCall('delta', {'carpetBoost': false, 'vacHigh': true}),
setCarpetBoostEco: () => _apiCall('delta', {'carpetBoost': false, 'vacHigh': false}),
setEdgeCleanOn: () => _apiCall('delta', {'openOnly': false}),
setEdgeCleanOff: () => _apiCall('delta', {'openOnly': true}),
setCleaningPassesAuto: () => _apiCall('delta', {'noAutoPasses': false, twoPass: false}),
setCleaningPassesOne: () => _apiCall('delta', {'noAutoPasses': true, twoPass: false}),
setCleaningPassesTwo: () => _apiCall('delta', {'noAutoPasses': true, twoPass: true}),
setAlwaysFinishOn: () => _apiCall('delta', {'binPause': false}),
setAlwaysFinishOff: () => _apiCall('delta', {'binPause': true})
});
};
module.exports = dorita980;
As a bonus we will create a file that stores the last phase so we won't keep updating it unnecessarily.
FYI my Roomba is called Dusty so change the settings to your liking:
Code: Select all
#!/usr/bin/nodejs
var dorita980 = require('/usr/lib/node_modules/dorita980');
var request = require('/usr/lib/node_modules/dorita980/node_modules/request');
var fs = require('fs');
var domoHostAndPort = 'http://admin:DomoPassword@IP-Address:Port';
var domoTextDeviceIdx = 16; //Device idx of the Roomba state device
var cleanMissionStatus = 5000;
var myRobotViaLocal = new dorita980.Local('MyUsernameBlid', 'MyPassword', 'IP-Address', 2, cleanMissionStatus);
var lastPhaseFile = '/usr/local/domoticz/stateFiles/dustyLastPhase';
var lastPhase = fs.readFileSync(lastPhaseFile, 'utf8');
var cmdfile = '/var/tmp/dusty-cmd';
myRobotViaLocal.on('mission', function (data) {
var phase = data.cleanMissionStatus.phase;
if (phase != lastPhase) {
lastPhase = phase;
fs.writeFile(lastPhaseFile, lastPhase, function(err) {
if(err) {
return console.log(err);
}
console.log("Dusty current state saved in state file!");
});
tellDomoticz('Dusty', phase, domoTextDeviceIdx);
}
else {
console.log('Dusty Phase same as before = ' + phase);
}
fs.exists(cmdfile, function(exists) {
if(exists) {
var contents = fs.readFileSync(cmdfile, 'utf8');
console.log('Received command: ' + contents);
if (contents == 'start'){
myRobotViaLocal.start()
.then(() => myRobotViaLocal.end()) // disconnect to leave the channel open for the mobile app.
.catch(console.log);
}
if (contents == 'stop'){
myRobotViaLocal.stop()
.then(() => myRobotViaLocal.end()) // disconnect to leave the channel open for the mobile app.
.catch(console.log);
}
if (contents == 'dock'){
myRobotViaLocal.dock()
.then(() => myRobotViaLocal.end()) // disconnect to leave the channel open for the mobile app.
.catch(console.log);
}
if (contents == 'pause'){
myRobotViaLocal.pause()
.then(() => myRobotViaLocal.end()) // disconnect to leave the channel open for the mobile app.
.catch(console.log);
}
if (contents == 'resume'){
myRobotViaLocal.resume()
.then(() => myRobotViaLocal.end()) // disconnect to leave the channel open for the mobile app.
.catch(console.log);
}
fs.unlinkSync(cmdfile);
}
myRobotViaLocal.end();
});
});
function getDateTime() {
var date = new Date();
var hour = date.getHours();
hour = (hour < 10 ? "0" : "") + hour;
var min = date.getMinutes();
min = (min < 10 ? "0" : "") + min;
var sec = date.getSeconds();
sec = (sec < 10 ? "0" : "") + sec;
var year = date.getFullYear();
var month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
var day = date.getDate();
day = (day < 10 ? "0" : "") + day;
return year + "-" + month + "-" + day + " " + hour + ":" + min + ":" + sec;
}
function tellDomoticz(robotName, newText, idx) {
if (newText == 'run') {
request(domoHostAndPort + "/json.htm?type=command¶m=updateuservariable&vname=dustyLastRun&vtype=2&vvalue=" + newText, function(error, response, body) {
console.log(getDateTime() + ' Storing last run info for ' + robotName + ' : ' + response.statusCode);
})
}
request(domoHostAndPort + "/json.htm?type=command¶m=udevice&idx=" + idx + "&nvalue=0&svalue=" + newText, function(error, response, body) {
console.log(getDateTime() + ' ' + robotName + ' ' + newText + ': ' + response.statusCode);
})
}
Code: Select all
*/10 06-19 * * * /usr/local/domoticz/scripts/sh/dustyGetMission.sh
Drago
-
- Posts: 39
- Joined: Friday 09 March 2018 18:52
- Target OS: Linux
- Domoticz version: 3.9203
- Location: Italy
- Contact:
Re: iRobot Roomba 980 integration
Hi BakSeeDaa, I'd like to post some questions about your configuration if it is possible. Thanks!
Then..Do I have to put a lua script inside each device? I am confused.....I am a noob sorry.
When Roomba start I can see the Vicky_Pause status changing (from charge to run to dock to pause...). But it is not supposed to work in this way.
I am missing something....
Can you help me?
Thanks
Xavier
My roomba980 is named Vicky. I managed to create Vicky Status under Configuration -> Device. I created it as: Dummy (Does nothing, use for virtual switches only).
Whats do you mean? I created 5 virtual devices, text type, and I named them: Vicky Start, Vicky Stop, Vicky Pause, Vicky Resume.
Then..Do I have to put a lua script inside each device? I am confused.....I am a noob sorry.
I changed Idx value putting value "5" that is the value of Dummy Hardware IDX but it is also the value of the first Virtual DEvice tha is called Vicky_Pause.BakSeeDaa wrote: ↑Thursday 23 February 2017 11:28Code: Select all
var domoTextDeviceIdx = 503; // Change this
When Roomba start I can see the Vicky_Pause status changing (from charge to run to dock to pause...). But it is not supposed to work in this way.
I am missing something....
Can you help me?
Thanks
Xavier
-
- Posts: 1
- Joined: Thursday 17 October 2019 23:58
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
- Contact:
Re: iRobot Roomba 980 integration
hello,
when I launch my script receive this
iRobot Phase same as before = stop
Received command: start
but the robot don't start
you know why ?
when I launch my script receive this
iRobot Phase same as before = stop
Received command: start
but the robot don't start
you know why ?
- bewo
- Posts: 74
- Joined: Monday 13 July 2015 12:27
- Target OS: Linux
- Domoticz version: 2021.1
- Location: Bavaria - Germany
- Contact:
Re: iRobot Roomba 980 integration
Hi guys...!
Thank's for the idea's, your scripts and the inspiration... I've did it in a different way.
The Rest API which offered beside dorita980 by koalazak (linked above) is updated and works.
So i thougt this an nicer way...
In my house are working two roboters. So i've set up an instance of the restAPI for each robot. Then i use two lua scripts. One time triggered for status updating and the other one device triggered to control the robots.
My comments are german. So if there's somebody who want to use, or there is a question -> just ask, i will do my best @translating.
This are the control switches:
This are the sensor devices:
This is the status script (time triggered):
And this is my script for controlling (device triggered):
Best regards and a Happy New Year together!
Thank's for the idea's, your scripts and the inspiration... I've did it in a different way.
The Rest API which offered beside dorita980 by koalazak (linked above) is updated and works.
So i thougt this an nicer way...
In my house are working two roboters. So i've set up an instance of the restAPI for each robot. Then i use two lua scripts. One time triggered for status updating and the other one device triggered to control the robots.
My comments are german. So if there's somebody who want to use, or there is a question -> just ask, i will do my best @translating.
This are the control switches:
This are the sensor devices:
This is the status script (time triggered):
Code: Select all
-- Skript zum Prüfen des Status eines Staubsauger-Roboter iRobot Roomba
-- --------------------------------------------------------------------
-- Skript funktioniert nur im Zusammenspiel mit zweiten Steuer-Skript:
-- Der Roboter kann auch per Tastendruck am Roboter selbst gesteuert werden. Deshalb muss jeweils unterschieden
-- werden zwischen tatsächlichem Schaltbefehl, und reinem Status setzen. Dieses Skript ruft über die App-Schnittstelle
-- des Roboters eine JSON-Datei ab und setzt diese wenn notwendig in Domoticz-Uservariablen.
-- Skriptanforderungen und Voraussetzungen siehe ganz unten!
-- Domoticz-JSON-Bibliothek laden (notwendig zum Parsen der JSON-Datei):
json = (loadfile "/opt/domoticz/scripts/lua/JSON.lua")()
commandArray = {}
-- Hier die einzelnen Roboter bestimmen:
Roboter = {
Erdgeschoss = { Name = 'Goofy', API_URL = 'http://localhost:3000/api/local' },
Obergeschoss = { Name = 'Pluto', API_URL = 'http://localhost:3001/api/local' }
}
-- Und los:
for Roboter,Roboter in pairs(Roboter) do
-- Da die Roboter mit WLAN arbeiten, erfolgt alles unter der Voraussetzung, dass WLAN an ist.
if otherdevices['WLAN-Name'] == 'On' then
-- #############################################################################################################
-- Informationen vom Roboter abrufen und in LUA-Tabelle schreiben:
json_abruf=assert(io.popen('curl '..Roboter.API_URL..'/info/mission'))
json_Roboter_Daten = json_abruf:read('*all')
json_abruf:close()
Roboter_Daten = json:decode(json_Roboter_Daten)
-- Zuordnung der einzelnen Infos:
Art_Mission = Roboter_Daten.cleanMissionStatus.cycle -- Art der Misson
Status = Roboter_Daten.cleanMissionStatus.phase -- Aktueller Status
--Ablaufzeit = Roboter_Daten.cleanMissionStatus.expireM -- Zeit bis die Mission abgelaufen ist, also in der die Mission wieder aufgenommen werden könnte
--Restakkuzeit = Roboter_Daten.cleanMissionStatus.rechrgM -- Betriebszeit bis zu leerem Akku
Fehler = Roboter_Daten.cleanMissionStatus.error -- Fehler vorhanden, gibt eine Nummer aus
Nicht_Bereit = Roboter_Daten.cleanMissionStatus.notReady -- Status "nicht bereit", gibt auch eine Nummer aus
--Missions_Dauer = Roboter_Daten.cleanMissionStatus.mssnM -- Bisherige Dauer der Mission
--Flaeche = Roboter_Daten.cleanMissionStatus.sqft -- Gereinigte Fläche in der aktuellen Mission
--Ausloeser = Roboter_Daten.cleanMissionStatus.initiator -- Auslöser der aktuellen Mission
--Missions_Nummer = Roboter_Daten.cleanMissionStatus.nMssn -- Nummer der aktuellen Mission
Schmutzbehaelter_vorhanden = tostring(Roboter_Daten.bin.present) -- Schmutzbehälter vorhanden? Ja/Nein
Schmutzbehaelter_voll = tostring(Roboter_Daten.bin.full) -- Schmutzbehälter voll? Ja/Nein
Batterieprozent = Roboter_Daten.batPct -- Aktueller Batteriestand in Prozent (Zehnerstufen)
-- #############################################################################################################
-- Domoticz-Nutzervariablen aktualisieren, falls notwendig:
-- Art der Misson in Nutzervariable schreiben:
if Art_Mission ~= uservariables[Roboter.Name..'_JSON_Art_Mission'] then
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_JSON_Art_Mission'] = Art_Mission}
print('Staubsauger-Roboter: '..Roboter.Name..' -> Art der Misson auf '..Art_Mission..' aktualisiert.')
end
-- Status in Nutzervariable schreiben:
if Status ~= uservariables[Roboter.Name..'_JSON_Status'] then
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_JSON_Status'] = Status}
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status auf '..Status..' aktualisiert.')
end
-- #############################################################################################################
-- Störungen setzen und Meldung verschicken:
if Fehler > 0 or (Nicht_Bereit > 0 and Nicht_Bereit < 15) and otherdevices[Roboter.Name] ~= 'Störung' and
Schmutzbehaelter_vorhanden == 'true' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 20'} -- Level 20 = Störung
print('Staubsauger-Roboter: '..Roboter.Name..' -> Achtung! Fehler-Nr.: '..Fehler..' ist vorhanden.')
if uservariables[Roboter.Name..'_Nachrichtenstatus'] ~= 'Versendet: Störung' then
commandArray[#commandArray+1] = {['SendNotification'] = string.upper(Roboter.Name)..'#Achtung, der Staubsauger-Roboter '..Roboter.Name..' meldet eine Störung. Bitte prüfen!'}
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Nachrichtenstatus'] = 'Versendet: Störung'} -- Level 20 = Störung
end
elseif Nicht_Bereit == 15 then
if Batterieprozent <= 20 and otherdevices[Roboter.Name] ~= 'Störung' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 20'} -- Level 20 = Störung
print('Staubsauger-Roboter: '..Roboter.Name..' -> Achtung Akku leer!')
if string.sub(uservariables[Roboter.Name..'_Nachrichtenstatus'], 1, 9) ~= 'Versendet' then
commandArray[#commandArray+1] = {['SendNotification'] = string.upper(Roboter.Name)..'#Achtung, der Akku von Staubsauger-Roboter '..Roboter.Name..' ist komplett leer. Bitte manuell zum Aufladen ins Dock bringen!'}
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Nachrichtenstatus'] = 'Versendet: Akku leer'}
end
elseif Batterieprozent > 20 and otherdevices[Roboter.Name] ~= 'Aufladen' and Art_Mission == 'none' and Status == 'charge' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 0'} -- Level 0 = Aufladen
print('Staubsauger-Roboter: '..Roboter.Name..' -> Akku war komplett leer, aktuell läuft der Ladevorgang!')
if string.sub(uservariables[Roboter.Name..'_Nachrichtenstatus'], 1, 9) ~= 'Versendet' then
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Nachrichtenstatus'] = 'Bereit'}
end
end
end
-- Störung wieder freigeben:
if Fehler == 0 and Nicht_Bereit == 0 then
if uservariables[Roboter.Name..'_Nachrichtenstatus'] == 'Versendet: Störung' then
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Nachrichtenstatus'] = 'Bereit'}
print('Staubsauger-Roboter: '..Roboter.Name..' -> Nachrichtenstatus zurück gesetzt.')
end
end
-- #############################################################################################################
-- Schmutzbehälter-Service (Anzeige von Nachricht und Symbol)
--
-- Damit ein Hinweis auf einen (teils) gefüllten Schmutzbehälter gegeben werden kann, wird die Laufzeit des
-- Roboters gezählt (im Zeitzähler-Skript) und unterstellt, dass sich der Schmutzbehälter mit der Zeit füllt.
-- Bei Laufzeit von 90 min. und nicht geleertem Behälter wird ein Hinweis verschickt.
schmutzbehaelter_device = Roboter.Name..' Status Schmutzbehälter'
-- Status auf OK setzen und Laufzeit zurück setzen
if Schmutzbehaelter_vorhanden == 'true' then
if uservariables[Roboter.Name..'_Laufzeit'] <= 45 then
textstatus = 'Behälter ist leer. Alles OK!'
if otherdevices_svalues[schmutzbehaelter_device] ~= textstatus then
commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[schmutzbehaelter_device]..'|1|'..textstatus} -- 1 = grün
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status Schmutzbehälter aktualisiert.')
end
-- Versandmeldung zurück setzen
if uservariables[Roboter.Name..'_Nachrichtenstatus'] == 'Versendet: Behälter leeren' then
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Nachrichtenstatus'] = 'Bereit'}
end
-- Ändern des Textes, nachdem Goofy schon ein wenig gelaufen ist.
elseif uservariables[Roboter.Name..'_Laufzeit'] > 45 and uservariables[Roboter.Name..'_Laufzeit'] < 90 then
textstatus = 'Behälter ist schmutzig, aber nicht voll.'
if otherdevices_svalues[schmutzbehaelter_device] ~= textstatus then
commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[schmutzbehaelter_device]..'|2|'..textstatus} -- 2 = gelb
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status Schmutzbehälter aktualisiert.')
end
-- Hinweis bei vermutet gefülltem Behälter
elseif uservariables[Roboter.Name..'_Laufzeit'] >= 90 then
textstatus = 'Behälter ist vermutlich voll. Bitte leeren!'
if otherdevices_svalues[schmutzbehaelter_device] ~= textstatus then
commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[schmutzbehaelter_device]..'|3|'..textstatus} -- 3 = orange
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status Schmutzbehälter aktualisiert.')
end
if string.sub(uservariables[Roboter.Name..'_Nachrichtenstatus'], 1, 9) ~= 'Versendet' then
commandArray[#commandArray+1] = {['SendNotification'] = string.upper(Roboter.Name)..'#Der Schmutzbehälter von Staubsauger-Roboter '..Roboter.Name..' sollte gefüllt sein. Bitte demnächst leeren!'}
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Nachrichtenstatus'] = 'Versendet: Behälter leeren' }
end
end
else
-- Behälter wurde raus genommen -> Status ändern und Laufzeit zurück setzen:
textstatus = 'Behälter ist nicht eingesetzt.'
if otherdevices[schmutzbehaelter_device] ~= textstatus then
commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[schmutzbehaelter_device]..'|0|'..textstatus} -- 0 = grau
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Laufzeit'] = tostring(0) }
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status Schmutzbehälter aktualisiert.')
end
end
-- Hinweis & Co. bei wirklich vollem Schmutzbehälter (Der Roboter meldet selbst voll!):
if Schmutzbehaelter_voll == 'true' and otherdevices[Roboter.Name] ~= 'Störung' then
textstatus = 'Behälter ist VOLL. Muss zwingend geleert werden!'
if otherdevices_svalues[schmutzbehaelter_device] ~= textstatus then
commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[schmutzbehaelter_device]..'|4|'..textstatus} -- 3 = rot
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 20' } -- Level 20 = Störung
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status Schmutzbehälter aktualisiert.')
end
if string.sub(uservariables[Roboter.Name..'_Nachrichtenstatus'], 1, 9) ~= 'Versendet' then
print(Roboter.Name..': Achtung der Schmutzbehälter ist voll! Muss geleert werden!')
commandArray[#commandArray+1] = {['SendNotification'] = string.upper(Roboter.Name)..'#Achtung der Schmutzbehälter von '..Roboter.Name..' ist voll! Muss zwingend geleert werden!'}
commandArray[#commandArray+1] = {['Variable:'..Roboter.Name..'_Nachrichtenstatus'] = 'Versendet: Behälter leeren' }
end
end
-- #############################################################################################################
-- Batteriestatus (Symbol und Stand) aktualisieren:
batterie_device = Roboter.Name..' Batteriestand'
-- Passends Batterie-Icon festlegen:
if Batterieprozent <= 20 then
batteriesymbol = '102'
elseif Batterieprozent > 20 and Batterieprozent <= 50 then
batteriesymbol = '104'
elseif Batterieprozent > 50 and Batterieprozent <= 90 then
batteriesymbol = '101'
elseif Batterieprozent > 90 then
batteriesymbol = '103'
end
-- Batteriestand schreiben
if Batterieprozent ~= tonumber(otherdevices_svalues[batterie_device]) then
commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[batterie_device]..'|0|'..Batterieprozent}
print('Staubsauger-Roboter: '..Roboter.Name..' -> Batteriestand auf '..Batterieprozent..'% aktualisiert.')
os.execute('curl "http://localhost:8077/json.htm?type=setused&idx='..otherdevices_idx[batterie_device]..'&name='..Roboter.Name..'%20Batteriestand&description=&switchtype=0&customimage='..batteriesymbol..'&devoptions=1;%25&used=true"')
end
-- Roboter in's Dock holen, wenn die Batterie leer wird:
if Batterieprozent <= 30 and Status ~= 'hmUsrDock' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 10' } -- Level 10 = Dock
print('Staubsauger-Roboter: '..Roboter.Name..' -> Akkustand geht bald zu Ende. Modus auf Dock gestellt.')
end
-- #############################################################################################################
-- Status des Roboter-Wahlschalters aktualisieren, falls manuell am Roboter gedrückt wurde:
if Fehler == 0 and Nicht_Bereit == 0 then
-- Roboter ist auf dem Weg in's Dock:
if (Art_Mission == 'clean' or Art_Mission == 'dock') and Status == 'hmUsrDock' and
otherdevices[Roboter.Name] ~= 'Dock' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 10' } -- Level 10 = Dock
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status auf Dock aktualisiert.')
-- Roboter ist schon im Dock, aber der Akku noch leer:
elseif Art_Mission == 'none' and Status == 'charge' and Batterieprozent <= 80 and
otherdevices[Roboter.Name] ~= 'Aufladen' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 0' } -- Level 0 = Aufladen
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status auf Aufladen aktualisiert.')
-- Roboter ist schon im Dock, und der Akku ausreichend geladen:
elseif Art_Mission == 'none' and Status == 'charge' and Batterieprozent > 80 and
otherdevices[Roboter.Name] ~= 'Dock' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 10' } -- Level 10 = Dock
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status auf Dock aktualisiert.')
-- Roboter ist außerhalb des Docks und nicht aktiv, bzw. Reinigungsmission wurde pausiert:
elseif (Art_Mission == 'none' or Art_Mission == 'clean') and Status == 'stop' and
otherdevices[Roboter.Name] ~= 'Pause' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 30' } -- Level 30 = Pause
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status auf Pause aktualisiert.')
-- Roboter ist im Spotbetrieb:
elseif Art_Mission == 'spot' and Status == 'run' and
otherdevices[Roboter.Name] ~= 'Saugen' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 40' } -- Level 40 = Saugen
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status auf Saugen aktualisiert.')
-- Roboter ist im normalen Saugbetrieb:
elseif Art_Mission == 'clean' and (Status == 'run' or Status == 'hmPostMsn') and
otherdevices[Roboter.Name] ~= 'Saugen' then
commandArray[#commandArray+1] = {[Roboter.Name] = 'Set Level 40' } -- Level 40 = Saugen
print('Staubsauger-Roboter: '..Roboter.Name..' -> Status auf Saugen aktualisiert.')
end
end
end
-- Batteriestatus aktiv halten (ohne WLAN, oder bei fehlender Veränderung)
if os.date('*t').min == 15 then
Batterieprozent = tonumber(otherdevices_svalues[Roboter.Name..' Batteriestand'])
commandArray[#commandArray+1]={['UpdateDevice'] = otherdevices_idx[Roboter.Name..' Batteriestand']..'|0|'..Batterieprozent}
print('Staubsauger-Roboter: '..Roboter.Name..' -> Batteriestand aktiv gehalten.')
end
end
return commandArray
--[[
Hinweise und Erklärungen:
-------------------------
-> Bei den einzelnen Geräten sind jeweils der Robotername und die Rest-API-URL zu setzen!
Folgende Variabeln / Schalter usw. müssen pro Roboter angelegt sein:
- Wahlschalter mit folgenden Stufen: Aufladen, Dock, Störung, Pause, Saugen
- Sensor-Device für Batteriestand (Custom Sensor) mit Namen *Robotername* Batteriestand
- Text-Device für Schmutzbehälter-Status mit Namen *Robotername* Status Schmutzbehälter
- Zeitzähler-Device für die Gesamtlaufzeit (wenn gewünscht)
Folgende Nutzervariablen müssen angelegt sein:
- *Robotername*_JSON_Art_Mission
- *Robotername*_JSON_Status
- *Robotername*_Nachrichtenstatus
- *Robotername*_Laufzeit
*Robotername* ist dabei immer entsprechend anzupassen!
Beispiel, der Roboter heißt Goofy. Dann würde eine Variable Goofy_JSON_Art_Mission heißen.
--]]
And this is my script for controlling (device triggered):
Code: Select all
-- Skript zum Steuern von Staubsauger-Roboteren des Typs iRobot Roomba
-- -------------------------------------------------------------------
-- Skript funktioniert nur im Zusammenspiel mit zweiten Status-Skript!
-- Der Roboter kann auch per Tastendruck am Roboter selbst gesteuert werden. Deshalb muss jeweils unterschieden
-- werden zwischen tatsächlichem Schaltbefehl, und reinem Status setzen. Dieses Skript schickt die tatsächlichen
-- Schaltbefehle, das zweite Skript aktualsiert minütlich und setzt die entsprechenden Stati, wenn notwendig.
commandArray = {}
-- Laden der eigenen Funktions-Sammlung
dofile("/opt/domoticz/scripts/lua/Eigene_Funktionen.lua")
-- Hier die einzelnen Roboter bestimmen:
Roboter = {
Erdgeschoss = { Name = 'Goofy', API_URL = 'http://localhost:3000/api/local' },
Obergeschoss = { Name = 'Pluto', API_URL = 'http://localhost:3001/api/local' }
}
-- Und los:
for Roboter,Roboter in pairs(Roboter) do
var_Mission = tostring(Roboter.Name..'_JSON_Art_Mission')
var_Status = Roboter.Name..'_JSON_Status'
Batteriestand = tonumber(otherdevices_svalues[Roboter.Name..' Batteriestand'])
-- Da der Roboter mit WLAN arbeitet, erfolgt alles unter der Voraussetzung, dass WLAN an ist.
if otherdevices['WLAN-Name'] == 'On' then
---------------------------------------------------------------------------------------------------------
-- Starten des Dockvorgang
if devicechanged[Roboter.Name] == 'Dock' then
-- Aus dem aktiven Reinigungsbetrieb in's Dock holen:
if uservariables[var_Mission] == 'clean' and uservariables[var_Status] == 'run' then
os.execute ('curl '..Roboter.API_URL..'/action/pause && sleep 1 && curl '..Roboter.API_URL..'/action/dock')
commandArray['Variable:'..var_Status] = 'hmUsrDock'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Befehl zum in das Dock-Fahren verschickt!')
-- Aus der Pause in's Dock holen:
elseif uservariables[var_Status] == 'stop' then
os.execute ('curl '..Roboter.API_URL..'/action/dock')
commandArray['Variable:'..var_Status] = 'hmUsrDock'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Befehl zum in das Dock-Fahren verschickt!')
end
end
---------------------------------------------------------------------------------------------------------
-- Pausieren des Reinigungsvorgangs (im normalen Reinigungsbetrieb oder auf dem Weg zum Dock)
if devicechanged[Roboter.Name] == 'Pause' and
(uservariables[var_Mission] == 'clean' or uservariables[var_Mission] == 'dock') and
(uservariables[var_Status] == 'run' or uservariables[var_Status] == 'hmUsrDock') then
os.execute ('curl '..Roboter.API_URL..'/action/pause')
commandArray['Variable:'..var_Status] = 'stop'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Aktiver Vorgang wurde pausiert!')
end
---------------------------------------------------------------------------------------------------------
-- Starten des Reinigungsvorgangs
if devicechanged[Roboter.Name] == 'Saugen' then
-- aus Ladestation oder unterwegs
if uservariables[var_Mission] == 'none' and
(uservariables[var_Status] == 'charge' or uservariables[var_Status] == 'stop') then
os.execute ('curl '..Roboter.API_URL..'/action/start')
commandArray['Variable:'..var_Mission] = 'clean'
commandArray['Variable:'..var_Status] = 'run'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Saugmission gestartet!')
-- weiter machen nach Störung
elseif uservariables[var_Mission] == 'clean' and uservariables[var_Status] == 'stuck' then
os.execute ('curl '..Roboter.API_URL..'/action/resume')
commandArray['Variable:'..var_Mission] = 'clean'
commandArray['Variable:'..var_Status] = 'run'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Saugmission wieder aufgenommen!')
-- weiter machen nach Pause
elseif uservariables[var_Mission] == 'clean' and uservariables[var_Status] == 'stop' then
os.execute ('curl '..Roboter.API_URL..'/action/resume')
commandArray['Variable:'..var_Mission] = 'clean'
commandArray['Variable:'..var_Status] = 'run'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Saugmission wieder aufgenommen!')
-- in normale Reinigung wechseln nach 10 Minuten Spot-Modus
elseif uservariables[var_Mission] == 'spot' and uservariables[var_Status] == 'run' and
timedifference(otherdevices_lastupdate[Roboter.Name]) > 600 then
os.execute ('curl '..Roboter.API_URL..'/action/pause && sleep 1 && curl '..Roboter.API_URL..'/action/start')
commandArray['Variable:'..var_Mission] = 'clean'
commandArray['Variable:'..var_Status] = 'run'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Saugmission gestartet (nach Spot-Modus)!')
-- in normale Reinigung wechseln bei diesem selstamen hmPostMsn-Modus
-- und momentan auch Benachrichtigung schicken um das zu prüfen
elseif uservariables[var_Mission] == 'clean' and uservariables[var_Status] == 'hmPostMsn' and
Batteriestand > 30 then
os.execute ('curl '..Roboter.API_URL..'/action/pause && sleep 1 && curl '..Roboter.API_URL..'/action/start')
commandArray['Variable:'..var_Mission] = 'clean'
commandArray['Variable:'..var_Status] = 'run'
print('Staubsauger-Roboter: '..Roboter.Name..' -> Saugmission gestartet (nach hmPostMsn)!')
end
end
end
end
return commandArray
Best regards and a Happy New Year together!
Last edited by bewo on Monday 13 January 2020 12:51, edited 1 time in total.
Individual projects:
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
-
- Posts: 30
- Joined: Sunday 12 January 2020 19:06
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
- Contact:
Re: iRobot Roomba 980 integration
Hi,
Great post!
I followed through all the guides and were able to get the rest980 working and communicating with my iRobot 960. I also used the scripts as provided (tweaked some directories / language) and was working!
I also was able to run the mapping (Localhost:3000/map) and worked well.
Currently I face the problem that the rest980 stops communicating after a couple of minutes. I see error logs in Domoticz when this happens and when I try to open the mapping then there is no connection. When I do a restart (nmp start) everting is workin again, but sagain stops after a couple of minutes.
Any idea what is going wrong?
Thanks
Wim
Great post!
I followed through all the guides and were able to get the rest980 working and communicating with my iRobot 960. I also used the scripts as provided (tweaked some directories / language) and was working!
I also was able to run the mapping (Localhost:3000/map) and worked well.
Currently I face the problem that the rest980 stops communicating after a couple of minutes. I see error logs in Domoticz when this happens and when I try to open the mapping then there is no connection. When I do a restart (nmp start) everting is workin again, but sagain stops after a couple of minutes.
Any idea what is going wrong?
Thanks
Wim
- bewo
- Posts: 74
- Joined: Monday 13 July 2015 12:27
- Target OS: Linux
- Domoticz version: 2021.1
- Location: Bavaria - Germany
- Contact:
Re: iRobot Roomba 980 integration
Hi Wim,
welcome in the forum!
In which way do you start the node?
welcome in the forum!
In which way do you start the node?
Individual projects:
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
-
- Posts: 30
- Joined: Sunday 12 January 2020 19:06
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
- Contact:
Re: iRobot Roomba 980 integration
Hi,
I managed to get rest980 to run as a service and is working now.
Where did you get the nice icons for the robot and battery?
I managed to get rest980 to run as a service and is working now.
Where did you get the nice icons for the robot and battery?
- bewo
- Posts: 74
- Joined: Monday 13 July 2015 12:27
- Target OS: Linux
- Domoticz version: 2021.1
- Location: Bavaria - Germany
- Contact:
Re: iRobot Roomba 980 integration
The robot icon i've created myself, the battery icons are from the BatteryLevel-Plugin (and @logread got it from wpclipart.com), so there's no license, the icon can be used.. There they are:
Last edited by bewo on Friday 17 January 2020 12:43, edited 1 time in total.
Individual projects:
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
- bewo
- Posts: 74
- Joined: Monday 13 July 2015 12:27
- Target OS: Linux
- Domoticz version: 2021.1
- Location: Bavaria - Germany
- Contact:
Re: iRobot Roomba 980 integration
Individual projects:
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
-
- Posts: 30
- Joined: Sunday 12 January 2020 19:06
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
- Contact:
Re: iRobot Roomba 980 integration
Vielen Dank!!!
-
- Posts: 30
- Joined: Sunday 12 January 2020 19:06
- Target OS: Raspberry Pi / ODroid
- Domoticz version:
- Contact:
Re: iRobot Roomba 980 integration
The run time does not work, could it be that the script to calculate the ‘_Laufzeit’ is missing?
Many thanks again!
Many thanks again!
- bewo
- Posts: 74
- Joined: Monday 13 July 2015 12:27
- Target OS: Linux
- Domoticz version: 2021.1
- Location: Bavaria - Germany
- Contact:
Re: iRobot Roomba 980 integration
Hi Vondee,
yes that could be.
If you copied my script 1:1, just add this lines above the "end" of the for loop:
yes that could be.
If you copied my script 1:1, just add this lines above the "end" of the for loop:
Code: Select all
-- Count the working time
if otherdevices[Roboter.Name] == 'Saugen' then
working_time = tonumber(uservariables[Roboter.Name..'_Laufzeit']) + 1
commandArray[#commandArray+1]={['Variable:'..Roboter.Name..'_Laufzeit'] = tostring(working_time)}
end
Individual projects:
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
Domoticz on a Intel Xeon Server | AeonLabs Z-Wave Gen.5 | RFXCOM RFXtrx433E USB | ESP-Wifi-Modules | Shellys
Wall-mounted 22" Touch Control Display (self construct) | LUA wind monitor| LUA heating control | and many many more :)
Who is online
Users browsing this forum: No registered users and 0 guests