iRobot Roomba i7+ Configuration using Rest980

Hi @lseufer,

I have created two new images in my Hass Repository.

  • rest980_build - this will build the Docker image manually using a clone of the original repo.
  • php_nginx_armv7 - this uses a different php-nginx image which works on armv7
    swapped primary php-nginx to an armv7 supported version.

Note: I dont have Hass running on an armv7 platform, but they both run on armv7 and build successfully in Hass on a amd64 platform - so in theory…they will work? :upside_down_face:

Give it a shot and let me know if it works!

Hi @Syrius,
I converted @gotschi scripts I customized and your scripts I slightly customized
into this new combined version. Since I already had apache2, php, php-gd, php-mbstring packages already installed to host the image.php, I did figure out I needed to install php-curl package as well, it was needed when the vacuum clean finished required by curl_init function. I did create a gray .png file naming it floor.png conveniently defined in image.php so I could see some of the vacuum lines being drawn, some lines are more white than green, so now all the lines can easily be seen, the vacuum last position is easy to spot on the camera image. I still haven’t played with HA themes yet, it was lower priority than this, it’ll be on my next todo list, also floor plans saved as floor.png

I’ve seen a youtube video some time ago someone was using a phone app moving the phone camera around the room corners to generate a floor plan, it wasn’t free, don’t recall what the cost or the app name was.

Thank for the parameters map_width, map_height, x_offset,y_offset they were very helpful to get everything to fit inside the camera view.

/Pierre

I have tried getting the mapping working and I am almost there but I am having an issue with tweaking the x/y offsets to get my map to look good.

$map_width = 1000;
$map_height = 1000;
$x_offset = 700;
$y_offset = 100;
$flip_vertical = true;
$flip_horizontal = true;

Those are my values. I have no issues moving my y_offset between 200-500 and the image adjusts accordingly. However when I try to set it less then 200 to something like 100 or 50, the image doesn’t recreate. Trying to figure out if there is a problem with the math or maybe I am just not understanding the offset correctly.

Hi @drjared88
I just tried modifying $x_offset from 580 to 50, I waited 8-9 seconds, the image got recreated with the roomba dock location close to the left side of the camera view.

I’m not using the php_nginx container, but my test at the very least tells me the image.php math translation is good.

the automations related to vacuum don’t seem to influence this behavior, i disabled all and the image redrew still around 8 sec later.

I was able to use offset lower than 100 also, and @drjared88 sent me his vacuum.log via PM which also worked fine on my setup (using php-nginx).

Not sure if its related to how he is hosting the php file.

I blew away my PHP file and now its working. I must have screwed something up by accident!

1 Like

Hi All,

I have pushed some new updates to the Repository and marked it as Release 0.1a

  • Added Stuck Automation to YAML
  • Updated image.php and image_dev.php
    • Fix issues causing some PHP instances to crash
    • Fix stuck image display
    • Variable for showing stuck positions
    • Remove hardcoded theta variables
  • Update Roomba Stuck icon image to image

Edit - 0.1a Released

  • Maps were not generating correctly using the REST Command. These have been replaced with Shell Commands

Cheers,
Jeremy

1 Like

Hi @Syrius,

I’m getting this error when trying to update the hass-addon:

20-01-24 22:14:10 INFO (SyncWorker_0) [hassio.docker.interface] Pull image 39c40414/amd64-addon-rest980 tag 20191217.
20-01-24 22:14:11 ERROR (SyncWorker_0) [hassio.docker.interface] Can't install 39c40414/amd64-addon-rest980:20191217 -> 404 Client Error: Not Found ("pull access denied for 39c40414/amd64-addon-rest980, repository does not exist or may require 'docker login'").

Please let me know if you want me to make an Issue on GitHub

Hey @LUNZ,

Did you try upgrade or is this a fresh install?

I changed rest980 from using a docker hub image to building it locally (for better compatibility)

Can you try removing it, refresh your add ons and then try installing it again?

just did that – I think it’s working!

Thanks

No worries!

Hey I’m having trouble with getting the camera image running.

I have the camera configured but nothing is showing up (this was also the case before the update).

There is a log file being created in /config/vacuum

In the hassio plugin log, I see the GET request for the image.php file, but nothing is there to return the request. Is there anything else I need to look at to troubleshoot?

@LUNZ I assume your running the php-nginx container.

If you try hit the image.php file in a browser - you get nothing showing up?

I’ve also noticed that with the webhippie php container you need to add a floor.png file in the vacuum directory otherwise the php file won’t render correctly. Can you check if you have added one of these? Set it to the same dimensions as the map

EDIT: I have updated the ha-rest980-roomba repo to include an example floor.png file in the vacuum directly to ensure the map generates during initial deployment.

Let me know how you go!

When I try to update the docker image in Hassio I get an error.

20-01-26 18:02:59 INFO (SyncWorker_9) [hassio.docker.addon] Start Docker add-on koalazak/rest980 with version latest

20-01-26 18:03:33 INFO (SyncWorker_3) [hassio.docker.interface] Update image koalazak/rest980:latest to c4fe18d5/amd64-addon-rest980:20191217

20-01-26 18:03:33 INFO (SyncWorker_3) [hassio.docker.interface] Pull image c4fe18d5/amd64-addon-rest980 tag 20191217.

20-01-26 18:03:34 ERROR (SyncWorker_3) [hassio.docker.interface] Can’t install c4fe18d5/amd64-addon-rest980:20191217 -> 404 Client Error: Not Found (“pull access denied for c4fe18d5/amd64-addon-rest980, repository does not exist or may require ‘docker login’”).

I changed rest980 from using a docker hub image to building it locally (for better compatibility)

Can you try removing it, refresh your add ons and then try installing it again?

1 Like

Just thought I’d share my floor plan that I made just by taking a screen shot from the roomba app. Obviously not the best but a very quick easy way to get a floor plan!

I had to tweak the colors to get it to show up better on this floorplan.

3 Likes

For anyone still using the lovelace front end to manage cards, here are the three cards fomr @Syrius 's lovelace example broken out.

Dynamic Buttons (Full Clean/Pause/Resume + Dock/EmptyBin

type: horizontal-stack
cards:
  - type: 'custom:button-card'
    entity: rest_command.vacuum_action
    icon: |
      [[[
        if (states['sensor.vacuum_cycle'].state == "Ready")
          return "mdi:play";
        else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
          return "mdi:play-pause";
        return "mdi:pause"
      ]]]
    layout: icon_name
    lock:
      enabled: |
        [[[
          if (states['sensor.vacuum_phase'].state == "Emptying Robot")
            return true;
          return false;
        ]]]
      exemptions: []
    name: |
      [[[
        if (states['sensor.vacuum_cycle'].state == "Ready")
          return "Full Clean";
        else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
          return "Resume";
        return "Pause"
      ]]]
    styles:
      card:
        - height: 50px
    tap_action:
      action: call-service
      service: rest_command.vacuum_action
      service_data:
        command: |
          [[[
            if (states['sensor.vacuum_cycle'].state == "Ready")
              return "start";
            else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
              return "resume";
            return "pause"
          ]]]
    hold_action:
      action: call-service
      service: rest_command.vacuum_action
      service_data:
        command: |
          [[[
            if (states['sensor.vacuum_cycle'].state == "Ready")
              return "start";
            else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
              return "stop";
            return "stop"
          ]]]   
  - type: 'custom:button-card'
    entity: rest_command.vacuum_action
    icon: 'mdi:home-minus'
    layout: icon_name
    lock:
      enabled: |
        [[[
          if (states['sensor.vacuum_phase'].state == "Emptying Robot")
            return true;
          return false;
        ]]]
      exemptions: []
    name: |
      [[[
        if ((states['sensor.vacuum_phase'].state == "Charging") || (states['sensor.vacuum_phase'].state == "Fully Charged") || (states['sensor.vacuum_phase'].state == "Emptying Robot"))
          return "Empty Bin";
        return "Dock"
      ]]]
    styles:
      card:
        - height: 50px
    tap_action:
      action: call-service
      service: rest_command.vacuum_action
      service_data:
        command: dock

Map

aspect_ratio: 0%
type: picture-glance
camera_image: camera.roomba
entities: []

States & Select Room Cleaning

type: entities
entities:
  - entity: sensor.vacuum_phase
  - entity: sensor.vacuum_cycle
  - entity: sensor.vacuum_battery
  - entity: sensor.vacuum_bin
  - entity: sensor.vacuum_dock
  - entity: sensor.vacuum_location
  - entities:
      - input_boolean.vacuum_bathroom
      - input_boolean.vacuum_breakfast_nook
      - input_boolean.vacuum_dining_room
      - input_boolean.vacuum_entryway
      - input_boolean.vacuum_foyer
      - input_boolean.vacuum_great_room
      - input_boolean.vacuum_hallway
      - input_boolean.vacuum_kitchen
      - input_boolean.vacuum_laundry_room
      - input_boolean.vacuum_living_room
      - input_boolean.vacuum_office
      - input_boolean.vacuum_playroom
      - entity: automation.vacuum_clean_rooms
        lock:
          enabled: |
            [[[
              if (states['group.vacuum_rooms'].state == "off")
                return true;
              return false;
            ]]]
          exemptions: []
        name: Clean Rooms
        styles:
          card:
            - height: 50px
        tap_action:
          action: call-service
          service: automation.trigger
          service_data:
            entity_id: automation.vacuum_clean_rooms
        type: 'custom:button-card'
    head:
      label: Selective Room Cleaning
      type: section
    type: 'custom:fold-entity-row'
show_header_toggle: false

I cleaned up the lovelace card to make it a little more compact if anyone is interested.

vacuum

cards:
  - entity: sensor.vacuum_phase
    secondary_info: last-changed
    type: 'custom:multiple-entity-row'
    name: Gerbert
    name_state: Status
    primary:
      entity: sensor.vacuum_battery
      name: Battery
    secondary:
      entity: sensor.vacuum_cycle
      name: Cycle
  - entities:
      - input_boolean.vacuum_dining_room
      - input_boolean.vacuum_kitchen
      - input_boolean.vacuum_hallway
      - input_boolean.vacuum_living_room
      - input_boolean.vacuum_bathroom
      - input_boolean.vacuum_kais_bedroom
      - input_boolean.vacuum_ensuite
      - input_boolean.vacuum_master_bedroom
      - entity: automation.vacuum_clean_rooms
        lock:
          enabled: |-
            [[[
              if (states['group.vacuum_rooms'].state == "off")
                return true;
              return false;
            ]]]
          exemptions: []
        name: Clean Rooms
        styles:
          card:
            - height: 50px
              border-radius: 10px
        tap_action:
          action: call-service
          service: automation.trigger
          service_data:
            entity_id: automation.vacuum_clean_rooms
        type: 'custom:button-card'
    head:
      label: Select Rooms to Clean
      type: section
    type: 'custom:fold-entity-row'
  - type: horizontal-stack
    cards:
      - type: 'custom:button-card'
        color_type: blank-card
        styles:
          card:
            - width: 25px
      - type: 'custom:button-card'
        entity: rest_command.vacuum_action
        icon: |
          [[[
            if (states['sensor.vacuum_cycle'].state == "Ready")
              return "mdi:play";
            else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
              return "mdi:play-pause";
            return "mdi:pause"
          ]]]
        color: 'rgb(68, 115, 158)'
        layout: icon_name
        lock:
          enabled: |
            [[[
              if (states['sensor.vacuum_phase'].state == "Emptying Robot")
                return true;
              return false;
            ]]]
          exemptions: []
        name: |
          [[[
            if (states['sensor.vacuum_cycle'].state == "Ready")
              return "Full Clean";
            else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
              return "Resume";
            return "Pause"
          ]]]
        styles:
          card:
            - border-radius: 10px
        tap_action:
          action: call-service
          service: rest_command.vacuum_action
          service_data:
            command: |
              [[[
                if (states['sensor.vacuum_cycle'].state == "Ready")
                  return "start";
                else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
                  return "resume";
                return "pause"
              ]]]
        hold_action:
          action: call-service
          service: rest_command.vacuum_action
          service_data:
            command: |
              [[[
                if (states['sensor.vacuum_cycle'].state == "Ready")
                  return "start";
                else if ((states['sensor.vacuum_phase'].state == "Stopped/Paused") || (states['sensor.vacuum_phase'].state == "Stuck") || (states['sensor.vacuum_phase'].state == "Charging"))
                  return "stop";
                return "stop"
              ]]]   
      - type: 'custom:button-card'
        entity: rest_command.vacuum_action
        icon: 'mdi:home-minus'
        color: 'rgb(68, 115, 158)'
        layout: icon_name
        lock:
          enabled: |
            [[[
              if (states['sensor.vacuum_phase'].state == "Emptying Robot")
                return true;
              return false;
            ]]]
          exemptions: []
        name: |
          [[[
            if ((states['sensor.vacuum_phase'].state == "Charging") || (states['sensor.vacuum_phase'].state == "Fully Charged") || (states['sensor.vacuum_phase'].state == "Emptying Robot"))
              return "Empty Bin";
            return "Dock"
          ]]]
        styles:
          card:
            - border-radius: 10px
        tap_action:
          action: call-service
          service: rest_command.vacuum_action
          service_data:
            command: dock
      - type: 'custom:button-card'
        color_type: blank-card
        styles:
          card:
            - width: 25px
show_header_toggle: false
title: Vacuum
type: vertical-stack
2 Likes

Nice work @drjared88 !

I didn’t know about about the multiple-entity-row plugin - but that definitely looks clean! :smiley:

Time for some customizing :wink:

I have my first vacuum job going right now since I wiped the setup and reinstalled.

How long should it take for an image to populate for the camera.roomba entity?

Mine still looks like:

image