Add support for irobot roomba clean specific room

This is difficult but BRILLIANT!! Thank you for posting.

I found a way easier way to find the rooms than using docker/node. Thanks to bradymholt for figuring out the service commands. The integration has all the information you need, but it is not exposed! This will preserve your old configuration. I perhaps will try a PR to the built-in integration, but this give you all the information you need:

Download the the homeassistant core from github (click Code Button, Download Zip):
https://github.com/home-assistant/core

Unzip the core-dev.zip core-dev/homeassistant/componets/roomba folder to
config/custom_components/roomba

edit the manifest.json to add this line above the dhcp line:
"version": "1.0",

edit the irobot_base.py file around line 178:

old line:
state_attrs = {ATTR_SOFTWARE_VERSION: software_version}
replace with
state_attrs = {ATTR_SOFTWARE_VERSION: software_version,"RAW_STATE": state}

save and restart homeassistant. The roomba state will now have the entire state available in the attributes. Seach for the lastCommand line.

You could also make a specfic lastcommand (or anyother state) state if you want to:
state_attrs = {ATTR_SOFTWARE_VERSION: software_version,"lastCommand": state.get("lastCommand"),"RAW_STATE": state}

There is a ton of information in the raw state.
edit: seems the irobot_base.py is only called when docked. If want live you need to add the command into either roomba.py, brava.py (also for the j7Combo), etc. Eg if have brava.py add a line at 134 which has:
state_attrs["raw_state_2"] = state

6 Likes

I can get the BLID and PASSWORD but am unable to get the pmap_id, regions, and user_pmapv_id

When running the command in Step 5 I am displayed with the following:

npm notice npm notice New major version of npm available! 8.5.5 -> 9.1.2 npm notice Changelog: https://github.com/npm/cli/releases/tag/v9.1.2 npm notice Run npm install -g [email protected] to update! npm notice

Then nothing happens. I tried to update but apparently, npm isn’t a valid command on my HA.

Hi guy’s … you did an amazing investigation job on the iRobot…

I have been struggle myself for a little while trying to make something to work on mine without succeeding anything brillant. With everything mentioned above I’m still having two questions based on my HA installation.

Rapsberrypi 4 I think
Running HASSIO

  1. Docker: When you mentioned to make sure Docker is installed & running, does that statement apply to HASSIO 2022.12 version ?
  2. iRobot: You are underlying the i7, i9 … does that solution can also be apply to the iRobot i4+

I got the first part working and I see the extended state. But I don’t understand the edit: what is the dictionary key ‘raw_state_2’, where is it coming from? And why do I set it to state, where is that variable coming from? I don’t see it in the roomba.py extra_state_attributes() function. Thanks.

Ah, I see in braava.py that state comes from self.vacuum_state, so I changed that. Still don’t know what the key " raw_state_2" means. Can I just set it and that works?

raw_state_2 is just a random name I made up. It is because the base and the robot have two different states (I think). It is taking the full state of the vacuum. Then we add that state into the attributes, now you can look at the attributes and find the lastCommand anytime you like.

Opps. I forgot a step. In roomba.py: def extra_state_attributes(self):
make this line the last line before the return.
state_attrs = {“RAW_STATE2”: self.vacuum_state}

1 Like

Thanks! Figured out that I have to use self.state instead of state (which is not defined anywhere) myself already :slight_smile: Now I am working on the automation.

I can’t seem to get the Robot State working.

Whenever I call getLastCommand I don’t get the command :frowning:

I am following the instruction from @bradymholt here

Manually running the node command, and when I try to getRobotState() I just get the following

> dorita980.Local(process.env.BLID, process.env.PASSWORD, process.env.ROBOT_IP).getRobotState()
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 1392,
  [Symbol(trigger_async_id_symbol)]: 5
}

What am I doing wrong?

Edit:
Solved!
getRobotState() is async command and needs to wait for the data.
this command works
robot.getRobotState().then((st)=> { console.log(st.lastCommand) });

Hey jaaem,

thanks for your initiative to find and easier way! I tried your suggested solution but I get the following error:

‘Traceback (most recent call last):
File “/usr/src/homeassistant/homeassistant/loader.py”, line 749, in get_platform
cache[full_name] = self._import_platform(platform_name)
File “/usr/src/homeassistant/homeassistant/loader.py”, line 766, in _import_platform
return importlib.import_module(f"{self.pkg_path}.{platform_name}")
File “/usr/local/lib/python3.10/importlib/init.py”, line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File “”, line 1050, in _gcd_import
File “”, line 1027, in _find_and_load
File “”, line 1006, in _find_and_load_unlocked
File “”, line 688, in _load_unlocked
File “”, line 883, in exec_module
File “”, line 241, in _call_with_frames_removed
File “/config/custom_components/roomba/vacuum.py”, line 12, in
from .roomba import RoombaVacuum, RoombaVacuumCarpetBoost
File “/config/custom_components/roomba/roomba.py”, line 13, in
state_attrs[“raw_state_2”] = state
NameError: name ‘state’ is not defined’

I also tried “self.vacuum_state” instead of state as suggested in another post but it did not work either.

Do you have any suggestions what I need to change?

Not sure. Your error says you edited line 13 of roomba.py, but you shouldn’t have. The edits I think are in the extra_state_attributes(self): function. The code may have changed since I posted these instructions, search around for that function.

Thanks for your quick reply, that solved my problem. I had the entry “state_attrs[“raw_state_2”] = state” in line 13 and “state_attrs = {“RAW_STATE2”: self.vacuum_state}” in line 40. Line 13 is not required, I just deleted it and now I can see all stats in the attributes of my roomba.

Very smooth and easy solution, thanks a lot!

Followed everything for my j7+. It was easy to get the BLID, PASSWORD and ROBOT_IP through ‘get-roomba-password-cloud’. However, when trying to get pmap_id etc. I am stuck. Following the steps to disable ‘continuous’ mode, sending to clean a room, force closing the app, and then firing the following command:

docker run -e BLID=‘XXXXXXXXC46E1’ -e PASSWORD=‘:1:1XXXXXXXXXXbUJjf2’ -e ROBOT_IP=‘192.168.0.23’ -it -w /root node sh -c “npm install --silent --no-progress dorita980 && NODE_DEBUG=net node -e "var dorita980 = require(‘dorita980’); var robot = new dorita980.Local(process.env.BLID, process.env.PASSWORD, process.env.ROBOT_IP); robot.getRobotState([‘lastCommand’]).then((st) => { console.log(st.lastCommand); process.exit(0); });"”

However, it is then stuck in an seemingly endless loop trying to connect somehow!? See below the output for the command given above:

npm notice
npm notice New minor version of npm available! 9.4.0 → 9.5.1
npm notice Changelog: Release v9.5.1 ¡ npm/cli ¡ GitHub
npm notice Run npm install -g [email protected] to update!
npm notice
NET 27: pipe false undefined
NET 27: connect: find host localhost
NET 27: connect: dns options { family: undefined, hints: 32 }
NET 27: _read
NET 27: _read wait for connection
NET 27: afterConnect
NET 27: destroy
NET 27: close
NET 27: close handle
NET 27: emit close
NET 27: pipe false undefined
NET 27: connect: find host localhost
NET 27: connect: dns options { family: undefined, hints: 32 }
NET 27: _read
NET 27: _read wait for connection
NET 27: afterConnect
NET 27: destroy
NET 27: close
NET 27: close handle
NET 27: emit close
… repeating many times …

This is docker desktop running on Windows 11, could this be an issue? Why is it saying: connect: find host localhost? Is it trying to connect to localhost instead of ROBOT_IP??
What could be wrong here? All are in the same network, ROBOT_IP can be pinged just fine… Any thoughts?

This raw state thingy is awesome! Thanks for posting it, this opens a lot of possibilities, i think!
The whole region map can be read from here, and also it can possibly be detected if the current task is finished or not.

Glad you like it! It is already there, just needed to be exposed as an attribute. It’s a little strange that can be exposed in 3 different places, so maybe the authors ( @pschmitt @cyr-ius @shenxn ) will add it in a better way.

Big thank you to the folks who posted here about how to get Roomba to clean specific rooms. For any Node Red users out there, I was able to get a flow set up that calls Roomba to specific/multiple rooms based on toggling room switches on the dashboard. I could not find good examples elsewhere so I thought I’d post my solution for others who come looking.

Hello everybody,

so i got no response if i type the code into the cmd.
Having a look at the log:

2023-04-16 16:10:28 SyntaxError: missing ) after argument list
2023-04-16 16:10:28 at new Script (node:vm:100:7)
2023-04-16 16:10:28 at createScript (node:vm:258:10)
2023-04-16 16:10:28 at Object.runInThisContext (node:vm:306:10)
2023-04-16 16:10:28 at node:internal/process/execution:83:21
2023-04-16 16:10:28 at [eval]-wrapper:6:24
2023-04-16 16:10:28 at runScript (node:internal/process/execution:82:62)
2023-04-16 16:10:28 at evalScript (node:internal/process/execution:104:10)
2023-04-16 16:10:28 at node:internal/main/eval_string:50:3
2023-04-16 16:10:28
2023-04-16 16:10:28 Node.js v19.9.0

What does that mean?

Thanks in advance

It works! not easy at the first time…
THANK YOU

Hi, @jaaem, I am unable to seem to get this to work.

My roomba.py now includes…

class RoombaVacuum(IRobotVacuum):
    """Basic Roomba robot (without carpet boost)."""

    @property
    def extra_state_attributes(self):
        """Return the state attributes of the device."""
        state_attrs = super().extra_state_attributes

        # Get bin state
        bin_raw_state = self.vacuum_state.get("bin", {})
        bin_state = {}
        if bin_raw_state.get("present") is not None:
            bin_state[ATTR_BIN_PRESENT] = bin_raw_state.get("present")
        if bin_raw_state.get("full") is not None:
            bin_state[ATTR_BIN_FULL] = bin_raw_state.get("full")
        state_attrs.update(bin_state)
        state_attrs[“raw_state_2”] = self.state
        state_attrs = {“RAW_STATE2”: self.vacuum_state}

        return state_attrs

And my irobot_base.py now includes…

def extra_state_attributes(self):
        """Return the state attributes of the device."""
        state = self.vacuum_state

        # Roomba software version
        software_version = state.get("softwareVer")

        # Set properties that are to appear in the GUI
        state_attrs = {ATTR_SOFTWARE_VERSION: software_version,"RAW_STATE": state}

But I don’t see anything new under the “Attributes”.

I must be missing something. Any help is appreciated.

does this still work? was able to follow all the steps but it doesnt seem to work anymore