iRobot 9xx on openHAB

To all of you Roomba / OH3 users out there - I put together my first pass of an openHAB v3.x Widget to control the Roomba. See this thread:

Hello everbody, i made “something” the last days. New version is available as usual here and corresponding code here. Change-Log:

  1. Massive refactoring
  2. Fixed password fetching for Roomba-980 and Roomba-I7
  3. Added handler for Braava, Roomba E-Series and S-Series. They are not complete, due to missing devices or json outputs. For the same reason, i was unable to test them.
  4. Add a lot of channels, like language, life-time statistics and so on.
  5. Massively improved map generation. Now to be able to run a binding new bundles shall be installed:
bundle:install https://repo1.maven.org/maven2/org/locationtech/jts/jts-core/1.18.1/jts-core-1.18.1.jar
bundle:install https://github.com/falkena/binaries/raw/master/opencv-4.3.0-4.jar
  1. Support for cleanRegions was not migrated to my fork. It’s on my ToDo list.

Greetings,

Alexander.

EDIT: I’m not sure about robot states i shall catch to generate a map. Currently i start new map, if cleanMissionStatus.phase goes to “run”. And finalize the map, if cleanMissionStatus.phase goes to “hmPostMsn” or “hmUsrDock”. Any help on this topic is welcome :slight_smile:

1 Like

I think I might be missing something. I had the binding that comes in 3.0.1 installed and working so I removed it, stopped openhab and cleared the cache and temp folders, restarted openhab and did the bundle:install commands you list for jts-code and opencv but when I put the addon file from your link I get this big error:

2021-03-18 11:18:54.305 [ERROR] [org.openhab.binding.irobot          ] - bundle org.openhab.binding.irobot:3.1.0.202103161903 (281)[org.openhab.binding.irobot.internal.IRobotHandlerFactory(363)] :  Error during instantiation of the implementation object
java.lang.NoClassDefFoundError: Could not initialize class org.openhab.binding.irobot.internal.IRobotHandlerFactory
	at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?]
	at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:?]
	at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:?]
	at java.lang.reflect.Constructor.newInstance(Constructor.java:490) ~[?:?]
	at org.apache.felix.scr.impl.inject.ComponentConstructor.newInstance(ComponentConstructor.java:309) ~[bundleFile:?]
	at org.apache.felix.scr.impl.manager.SingleComponentManager.createImplementationObject(SingleComponentManager.java:277) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.SingleComponentManager.createComponent(SingleComponentManager.java:114) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:982) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.SingleComponentManager.getServiceInternal(SingleComponentManager.java:955) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.SingleComponentManager.getService(SingleComponentManager.java:900) [bundleFile:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse$1.run(ServiceFactoryUse.java:212) [org.eclipse.osgi-3.12.100.jar:?]
	at java.security.AccessController.doPrivileged(Native Method) [?:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.factoryGetService(ServiceFactoryUse.java:210) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceFactoryUse.getService(ServiceFactoryUse.java:111) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceConsumer$2.getService(ServiceConsumer.java:45) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.getService(ServiceRegistrationImpl.java:508) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.getService(ServiceRegistry.java:461) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.BundleContextImpl.getService(BundleContextImpl.java:624) [org.eclipse.osgi-3.12.100.jar:?]
	at org.apache.felix.scr.impl.manager.SingleRefPair.getServiceObject(SingleRefPair.java:86) [bundleFile:?]
	at org.apache.felix.scr.impl.inject.BindParameters.getServiceObject(BindParameters.java:47) [bundleFile:?]
	at org.apache.felix.scr.impl.inject.methods.BindMethod.getServiceObject(BindMethod.java:664) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.DependencyManager.getServiceObject(DependencyManager.java:2308) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.DependencyManager.doInvokeBindMethod(DependencyManager.java:1805) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.DependencyManager.invokeBindMethod(DependencyManager.java:1788) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.SingleComponentManager.invokeBindMethod(SingleComponentManager.java:435) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.DependencyManager$MultipleDynamicCustomizer.addedService(DependencyManager.java:325) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.DependencyManager$MultipleDynamicCustomizer.addedService(DependencyManager.java:294) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1216) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.customizerAdded(ServiceTracker.java:1137) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.trackAdding(ServiceTracker.java:944) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.ServiceTracker$AbstractTracked.track(ServiceTracker.java:880) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.ServiceTracker$Tracked.serviceChanged(ServiceTracker.java:1168) [bundleFile:?]
	at org.apache.felix.scr.impl.BundleComponentActivator$ListenerInfo.serviceChanged(BundleComponentActivator.java:125) [bundleFile:?]
	at org.eclipse.osgi.internal.serviceregistry.FilteredServiceListener.serviceChanged(FilteredServiceListener.java:109) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:920) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEventPrivileged(ServiceRegistry.java:862) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.publishServiceEvent(ServiceRegistry.java:801) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistrationImpl.register(ServiceRegistrationImpl.java:127) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.serviceregistry.ServiceRegistry.registerService(ServiceRegistry.java:225) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.BundleContextImpl.registerService(BundleContextImpl.java:469) [org.eclipse.osgi-3.12.100.jar:?]
	at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:906) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.AbstractComponentManager$3.register(AbstractComponentManager.java:892) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.RegistrationManager.changeRegistration(RegistrationManager.java:128) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.AbstractComponentManager.registerService(AbstractComponentManager.java:959) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.AbstractComponentManager.activateInternal(AbstractComponentManager.java:732) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.AbstractComponentManager.enableInternal(AbstractComponentManager.java:666) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.AbstractComponentManager.enable(AbstractComponentManager.java:432) [bundleFile:?]
	at org.apache.felix.scr.impl.manager.ConfigurableComponentHolder.enableComponents(ConfigurableComponentHolder.java:665) [bundleFile:?]
	at org.apache.felix.scr.impl.BundleComponentActivator.initialEnable(BundleComponentActivator.java:338) [bundleFile:?]
	at org.apache.felix.scr.impl.Activator.loadComponents(Activator.java:382) [bundleFile:?]
	at org.apache.felix.scr.impl.Activator.access$200(Activator.java:49) [bundleFile:?]
	at org.apache.felix.scr.impl.Activator$ScrExtension.start(Activator.java:264) [bundleFile:?]
	at org.apache.felix.scr.impl.AbstractExtender.createExtension(AbstractExtender.java:196) [bundleFile:?]
	at org.apache.felix.scr.impl.AbstractExtender.modifiedBundle(AbstractExtender.java:169) [bundleFile:?]
	at org.apache.felix.scr.impl.AbstractExtender.modifiedBundle(AbstractExtender.java:49) [bundleFile:?]
	at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:482) [osgi.core-6.0.0.jar:?]
	at org.osgi.util.tracker.BundleTracker$Tracked.customizerModified(BundleTracker.java:415) [osgi.core-6.0.0.jar:?]
	at org.osgi.util.tracker.AbstractTracked.track(AbstractTracked.java:232) [osgi.core-6.0.0.jar:?]
	at org.osgi.util.tracker.BundleTracker$Tracked.bundleChanged(BundleTracker.java:444) [osgi.core-6.0.0.jar:?]
	at org.eclipse.osgi.internal.framework.BundleContextImpl.dispatchEvent(BundleContextImpl.java:908) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEventPrivileged(EquinoxEventPublisher.java:213) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:120) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.EquinoxEventPublisher.publishBundleEvent(EquinoxEventPublisher.java:112) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.EquinoxContainerAdaptor.publishModuleEvent(EquinoxContainerAdaptor.java:168) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.container.Module.publishEvent(Module.java:476) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.container.Module.start(Module.java:467) [org.eclipse.osgi-3.12.100.jar:?]
	at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:383) [org.eclipse.osgi-3.12.100.jar:?]
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1260) [bundleFile:3.6.4]
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1233) [bundleFile:3.6.4]
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:520) [bundleFile:3.6.4]
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:365) [bundleFile:3.6.4]
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:316) [bundleFile:3.6.4]

but then weirdly it adds my roomba to the inbox but when I try to add it as a thing I get this

2021-03-18 11:19:14.161 [WARN ] [g.discovery.internal.PersistentInbox] - Cannot create thing. No binding found that supports creating a thing of type irobot:roomba.

if I do a bundle:list from the karaf console I see this:

279 │ Resolved │  80 │ 1.18.1                  │ jts-core
280 │ Resolved │  80 │ 4.3.0.4                 │ OpenPnP OpenCV
281 │ Waiting  │  80 │ 3.1.0.202103161903      │ openHAB Add-ons :: Bundles :: iRobot Binding

Any ideas?

@falkena I saw you are continue working on your iRobot feature branch. The commit “Fix command send due to breaking changes in core.”, can this be the solution, why I cannot send a command?
When will you provide a jar file?

For me your current snapshot doesn’t work.

Remains in Pending Configuration and connection is lost:

2021-03-20 13:39:43.954 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'irobot:roomba:67ef7b2e14' changed from ONLINE (CONFIGURATION_PENDING): Robot authentication is successful to UNINITIALIZED
2021-03-20 13:39:43.961 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'irobot:roomba:67ef7b2e14' changed from UNINITIALIZED to UNINITIALIZED (DISABLED)
2021-03-20 13:39:44.494 [WARN ] [ore.internal.thing.ThingTypeResource] - Cannot find channel group type: irobot:statistics
2021-03-20 13:39:45.463 [INFO ] [.transport.mqtt.MqttBrokerConnection] - Starting MQTT broker connection to '192.168.0.44' with clientid 3167031442422570
2021-03-20 13:39:53.231 [INFO ] [.reconnect.PeriodicReconnectStrategy] - Try to restore connection to '192.168.0.44'. Next attempt in 10000ms
2021-03-20 13:39:58.436 [WARN ] [internal.handler.RoombaCommonHandler] - Established connection without broker pointer
2021-03-20 13:39:58.437 [WARN ] [.core.thing.binding.BaseThingHandler] - Handler Roomba9ModelsHandler tried updating the thing status although the handler was already disposed.
2021-03-20 13:39:58.554 [WARN ] [internal.handler.RoombaCommonHandler] - MQTT connection failed: Timeout
2021-03-20 13:39:58.554 [WARN ] [.core.thing.binding.BaseThingHandler] - Handler Roomba9ModelsHandler tried updating the thing status although the handler was already disposed.
2021-03-20 13:39:44.494 [WARN ] [ore.internal.thing.ThingTypeResource] - Cannot find channel group type: irobot:statistics

Hello everybody,
it took ages to figure out, that this and this broke my snapshot. I’ve uploaded rebuild to my binary repository. Attention: The version requires at least S2270 core snapshot. Additionally, since OpenCV maintenaner merged my pull-request for OpenCV, i’ve bumped the version to 4.5.1:

bundle:update <ID> https://repo1.maven.org/maven2/org/openpnp/opencv/4.5.1-2/opencv-4.5.1-2.jar

Group type statistics was renamed to common, since i added some new channels.

Greetings,

Alexander

Hi,

which paltform you run on? Please, take a look here which ones are supported.

Greetings,

Alexander

I’m running on raspbian (albeit the docker version of openhab) so ARMv7. Your last update seems to have changed things a bit, now when starting or trying a discovery I just get this error. Unfortunately it seems that the discovery service won’t work then but the bundle itself shows active (as well as jts-core 1.18.1 and OpenPnP OpenCV 4.5.1.2). Is there maybe an update for the Google Json Library for Java that I need? here are my versions for that and the core google Java libraries:

27 │ Active │  80 │ 2.8.2.v20180104-1110    │ Gson: Google Json Library for Java
28 │ Active │  80 │ 27.1.0.jre              │ Guava: Google Core Libraries for Java
2021-03-21 14:48:31.889 [WARN ] [mmon.WrappedScheduledExecutorService] - Scheduled runnable ended with an exception: 
java.lang.NoSuchMethodError: 'com.google.gson.JsonElement com.google.gson.JsonParser.parseString(java.lang.String)'
	at org.openhab.binding.irobot.internal.discovery.IRobotDiscoveryService.lambda$0(IRobotDiscoveryService.java:114) ~[?:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[?:?]
	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305) ~[?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305) ~[?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
	at java.lang.Thread.run(Thread.java:834) [?:?]

Hello @falkena
I’m running on OH S2271, but your new snapshot cannot connect:

2021-03-23 20:07:08.768 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'irobot:roomba:D0C5D38E4EF0' changed from UNINITIALIZED to UNINITIALIZED (DISABLED)
2021-03-23 20:07:09.401 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'irobot:roomba:D0C5D38E4EF0' changed from UNINITIALIZED (DISABLED) to INITIALIZING
2021-03-23 20:07:09.404 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'irobot:roomba:D0C5D38E4EF0' changed from INITIALIZING to UNKNOWN
2021-03-23 20:07:10.406 [INFO ] [ab.event.ThingStatusInfoChangedEvent] - Thing 'irobot:roomba:D0C5D38E4EF0' changed from UNKNOWN to OFFLINE (COMMUNICATION_ERROR): Receive timed out

What’s really curious, binding find two new things now, but both cannot connect:

2021-03-23 20:10:45.809 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'irobot:roomba:D0C5D38E4EF0' to inbox.
2021-03-23 20:12:43.187 [INFO ] [g.discovery.internal.PersistentInbox] - Added new thing 'irobot:roomba:192_168_0_44' to inbox.

I just got a Braava M6, if i can help you out any please let me no

Hello everybody,

there is small update available. Change - Log:

  1. (Hopefully) Fix trigger for map generation
  2. Fix map rendering issue

@ tardismechanic: You need at least S2270 snapshot.
@davesen Please, check, if app is connected with roomba. IRobot allowes single MQTT connection only and app connects via mqtt if within same network. If no, please try to restart openhab: Sometime, openhab get ghost things. I “fix” the problem, that i remove roomba instance from thing file, restart openhab. And if openhab is started, add the roomba instance back to the things file.

seems to be the discovery from new binding and

old discovery.
@alacard Thanks! The first step would be, to check, if discovery and password fetch work for M6. Then i would need the JSON from robot: There is a channel for. I think, that common stuff, like network, language and so on shall work out of the box. Map visualisation will not work now. But i think, this issue is not a huge problem.

Kind regrads,

Alexander.

Hope this what you needed
afterPasswordDiscovery.txt (60.9 KB) beforePasswordDiscovery.log (2.1 KB)

P.S. both auto discovery and password discovery works, could not find a way to get the raw json from bundle so used “Roomba980-Python” to get it

Sorry, I saw that earlier but it didn’t click that you meant openhab snapshot build. I think I thought you meant a snapshot version of the opencv library or something. Switching to the openhab snapshot build of course fixed the issue and it’s working fine now. Thanks!

1 Like

Hi all,
I am very excited that I found this by accident.
I am running OH3.0.1, Roomba 960, i could download the binding plus jts-core plus OpenPNP and I could setup a thing that I see after a start the batterystatus and phase saying charing… so far so good.
But: I could not manage to trigger a control-command. Looking into the “offical” Binding I used the item plus Map … but no reaction with this binding. Any thoughts what I am doing wrong … sadly I do not see any negative response in the log…
THis is really an exciting piece of work - I looking forward to see the first MAP!!!
Thanks for any help / suggestion.

Same problem for me. Status items work, but not control command. When I set a command, connection get lost. Seems to be a wrong command enumeration?
Another question: How can I get map information? Where?

Hello everybody,

ok, let’s dive in. As i wrote above, i haven’t migrate start command with region support introduced here. Are another commands working?

Switch RoombaSearch       { channel="irobot:roomba:Roomba:control#find" }
Switch RoombaAlwaysFinish { channel="irobot:roomba:Roomba:control#always_finish" }
String RoombaCleanPasses  { channel="irobot:roomba:Roomba:control#clean_passes" }
String RoombaLanguage     { channel="irobot:roomba:Roomba:control#language" }
Switch RoombaUploadMap    { channel="irobot:roomba:Roomba:control#upload_map" }

If command was send successfully, then robot shall make a noise. Talk we only about?

String RoombaCommand      { channel="irobot:roomba:Roomba:control#command" }

Map can be found in mission group:

Image       RoombaMissionMap { channel="irobot:roomba:Roomba:mission#map" }

There are a lot of advanced channels. Please, be sure to activate the check box to seems them.

@alacard Thanks for JSON :slight_smile: It helped a lot. Binding have a channel for:

String RoombaJSON  "Roomba JSON [%s]" { channel="irobot:roomba:Roomba:state#json" }

every change will be logged in events.log file

Greetings,
Alexander

Danke!
Thanks for your fast reply- I will try it out ASAP

Hi!
When switching control#find to ON no sound comes up and after ~10seconds the switch goes back to OFF.
The state#json does not show any messages and while cleaning.
A map is not generated at the of a mission.

Greetings - Michael

Hello! I am very happy that the binding found a new maintainer. I simply don’t have time for it, i moved on to other projects

I use the “original” binding, coming with openHAB 3.1.0 Build #2271.

When I trigger command from Stop to Clean, nothing happens, here the log:

2021-03-27 14:13:15.854 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'RoombaKommando' received command clean
2021-03-27 14:13:15.858 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'RoombaKommando' predicted to become clean
2021-03-27 14:13:15.861 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'RoombaKommando' changed from stop to clean
==> /var/log/openhab2/openhab.log <==
2021-03-27 14:13:20.958 [INFO ] [.reconnect.PeriodicReconnectStrategy] - Try to restore connection to '192.168.0.44'. Next attempt in 5000ms
2021-03-27 14:13:20.978 [INFO ] [.transport.mqtt.MqttBrokerConnection] - Starting MQTT broker connection to '192.168.0.44' with clientid 3167031442422570
==> /var/log/openhab2/events.log <==
2021-03-27 14:13:22.732 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'RoombaKommando' changed from clean to stop