Help with iRobot MQTT

Got it!

My theory that rest980 was occupying the MQTT connection was correct. Once I shut down the rest980 instance, I was able to connect using this Python script:
https://github.com/koalazak/dorita980/issues/10#issuecomment-296666429

When reviewing that code, I noticed that the client ID was set to the blid, which matched what I saw in the dorita980 code. That appears to have been a crucial piece. Once I made that change, I was able to connect with MQTT Explorer.

Next step is to work on the driver in Hubitat!

I've hit a wall. I've tried everything I can think of, but I can't get Hubitat to connect to the local Roomba MQTT broker. The code in the driver is pretty straightforward:

try
{
    interfaces.mqtt.connect(
        "ssl://192.168.1.196:8883", 
        "xxx", //blid from my Roomba
        "xxx", //blid from my Roomba
        "yyy", //password from my Roomba
        tlsVersion: "1.2", 
        privateKey: privateKey, 
        caCertificate: caCert, 
        clientCertificate: clientCert
    )
    if (interfaces.mqtt.isConnected()) {
        interfaces.mqtt.disconnect()
    } else {
        log.debug "MQTT failed to connect..."
    }
}
catch (e) {
   log.debug e
}

But the only response I ever get is Connection refused.

I am able to connect to the Roomba with this Python code:
https://github.com/koalazak/dorita980/issues/10#issuecomment-296666429
and I've used it to confirm that the MQTT connection is available and that the private key, client cretificate, and CA certificate are all valid. I've tried it with TLS 1, 1.1, and 1.2. I've tried it without TLS. But nothing seems to work.

I don't know what could be wrong or what else to try, so I'm going to have to give up on this for now. As an alternative, I'm going to try setting up Mosquitto as an MQTT bridge and have Hubitat communicate through that instead. I had wanted to eliminate the dependency on my Raspberry Pi, but it doesn't look like I'm going to be able to accomplish that. With Mosquitto, I'm hoping to get real-time updates from the Roomba, instead of having to poll the REST API through rest980.

Wish me luck!

How did you validate the certificates? The python script, by my eye, seems to be ignoring certificate validation -- I am able to connect to my Roomba using MQTT Explorer with cert validation disabled -- but not sure what certificates (I tried creating my own, with no success in using them to connect) to plug in?

I don't know much about MQTT, been doing some reading -- had been thinking along the same lines, to try to remove the rPi from the middle.

I’m thinking along the same lines as you: the certificates are ultimately the problem.

To answer your question, I got different errors in Hubitat when the private key and the client certificate didn’t line up. I got similar errors in the Python script until I generated them correctly. When it went back to Connection refused on Hubitat, I assumed the key and certificate were correct.

I went through several iterations of the CA certificate. I tried sample ones and I tried generating my own self-signed certificate, but those didn’t work. The Python script uses the ones stored the Raspberry Pi, but that didn’t work in Hubitat either. I eventually figured out how to pull the real certificates directly from the Roomba, but that didn’t work either. They appear to be self-signed too, and that may ultimately be what Hubitat can’t handle.

I also failed in my attempt to set up an MQTT bridge today. I think it is due to similar issues. Mosquitto gives slightly better error messages. I believe the last one I got was something like dh key too small. I’m not certain but I think this has to do with the ciphers, but neither Hubitat nor the Mosquitto bridge connection allow you to change which ciphers are being used.

Have you tried using TLS but NO certs? Maybe it supports that? Something like:

interfaces.mqtt.connect(
"ssl://192.168.1.196:8883",
"xxx", //blid from my Roomba
"xxx", //blid from my Roomba
"yyy", //password from my Roomba
tlsVersion: "1.2"
)

Edit: actually, maybe remove the tlsVersion too... let it auto negotiate

Edit 2: client.tls_set("/etc/ssl/certs/ca-certificates.crt", None, None, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1, ciphers=None)

Yeah, that's the paho MQTT call, it provices the CA cert but no client cert or key and says the cert_reqs is none for the client. so Try just the caCertificate but remove privateKey and clientCertificate

I think I tried that, but I’ve tried so many things now, I really don’t know... :stuck_out_tongue:

I remember reading this in the Hubitat MQTT documentation:

Note, all 4 parameters (tlsVersion, privateKey, caCertificate, clientCertificate) are required for TLS secure connection

So at some point, I just started using them all.

I just tried it to see, but I still get Connection refused.

They're definitely not all required. Not sure why it says that. My Rheem integration uses none of them and connects via TLS. Connection refused doesn't sound like an SSL error to me. In Java, that's a ConnectionException which means you didn't even connect to the IP/port. SSL/TLS isn't negotiated until after connection and if it fails I think you'd get a disconnection error, not a connection refused. I'm surprised though because you said MQTT explorer works... Hmm. I'll unplug my Dorita tomorrow and see if I can connect to my Roomba. I have an i7.

No firewalls between your HE and Roomba, right?

Not that I know of. I have an access point with the same SSID, and I’ve had issues with other products (e.g. Konnected) not working when one device is connected to the AP and one is connected directly to the router. But in this case, I’ve been able to connect using MQTT Explorer on multiple computers around my house (some wired, some wireless).

I haven’t run MQTT Explorer directly from the Raspberry Pi though. I wasn’t able to get it to run. But I have been able to connect using the Python script and dorita980, so I think that rules out networking issues on the Pi itself.

Not sure if that makes any difference for Hubitat.

Sorry, why would we be talking about network issues on the rpi? I thought you're trying to connect HE -> Roomba directly, right? So no rpi involved?

Yep, you’re right. I should call it a night as I’m clearly not thinking straight any more!

No firewalls that I know of between HE and Roomba.

1 Like

Ok. I'll play around tomorrow too. As a note, it does appear to be self-signed certs which if we do get it connected will be an issue. The HE team is considering supporting self-signed certs in a future firmware release.

Release 2.2.5 might be the key to getting this working? Haven't had a chance to play with it yet.

It was a necessary addition to make this work, but it won’t resolve a connection refused error.

Agree that the error/exception doesn't seem to align with a cert issue, but wondered if the cert exception might be getting caught and swallowed somewhere in the HE sw. It doesn't seem to make much sense, since we've proven that the Roomba will accept a connection on the ip/port. Even a firewall would likely end in a Connection Timeout, dropping the packets, instead of outright refusing?

Yeah I agree, usually a connection refused means nothing listening on that ip/port. Having experienced MQTT cert errors elsewhere in HE though, I can tell you you get an SSLHandshakeException, not a ConnectionException.

Hi! Just driving by with some information I discovered while trying to setup a bridge to a roomba s9 in Mosquitto.

Unfortunately, not good news for Mosquitto, I don't believe it is currently possible to setup a bridge to a roomba (S9 anyway) because there is something funky in the SSL cert chain that roomba is using.

I've opened a ticket with mosquitto with some extra info here: https: //github .com/eclipse/mosquitto/issues/2061

In theory, if Mosquitto could ignore the validation issue, it could connect like so:
mosquitto_sub -t "#" -d --host $ROBOT_HOST -p 8883 -i $ROBOT_BLID -u $ROBOT_BLID -P $ROBOT_PASSWORD --insecure --tls-version tlsv1.2 --ciphers DEFAULT@SECLEVEL=1

But it cant due to the SSL cert issue, you will get OpenSSL Error[0]: error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed Error: A TLS error occurred..

Juuuuust in case it is useful to anyone though, it is possible to get the self-signed CA cert that irobot is using out of their app. By:

  1. Downloading the irobot app apk from somewhere like apkmirror https ://www.apkmirror .com/?post_type=app_release&searchtype=apk&s=irobot
  2. Unpack the apk and the nested "base" apk using a tool like apktool or just an archive tool. Find a file called irobotkeystore.bks.
  3. Get a copy of the latest bouncy castle jar and download it.
  4. Use keytool to extract the cert (the entry you are looking for is "0") keytool -keystore res/raw/irobotkeystore.bks -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath ~/Downloads/bcprov-jdk15to18-168.jar -exportcert -alias 0 -file irobot0.pem -rfc

And that is the root cert, I've verified the chain is valid:

openssl s_client -connect 192.168.2.5:8883 -CAfile irobot0.pem
CONNECTED(00000003)
Can't use SSL_get_servername
depth=1 C = US, ST = Massachusetts, L = Beford, O = iRobot Corporation, OU = HBU, CN = Robot Intermediate CA A01
verify error:num=26:unsupported certificate purpose
verify return:1
depth=2 C = US, ST = MA, L = Bedford, O = iRobot, OU = HBU, CN = Roomba CA
verify return:1
depth=1 C = US, ST = Massachusetts, L = Beford, O = iRobot Corporation, OU = HBU, CN = Robot Intermediate CA A01
verify return:1
depth=0 C = US, ST = Massachusetts, L = Bedford, O = iRobot Corporation, OU = Production, CN = iRobot-783545A45675422DB5A4576E7829A1F4
verify return:1
---
Certificate chain
 0 s:C = US, ST = Massachusetts, L = Bedford, O = iRobot Corporation, OU = Production, CN = iRobot-783545A45675422DB5A4576E7829A1F4
   i:C = US, ST = Massachusetts, L = Beford, O = iRobot Corporation, OU = HBU, CN = Robot Intermediate CA A01
 1 s:C = US, ST = Massachusetts, L = Beford, O = iRobot Corporation, OU = HBU, CN = Robot Intermediate CA A01
   i:C = US, ST = MA, L = Bedford, O = iRobot, OU = HBU, CN = Roomba CA

Except for the issue with the intermediate cert purpose :).

Here is the cert in pem format for reference:

-----BEGIN CERTIFICATE-----
MIIDSzCCAjOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBfMQswCQYDVQQGEwJVUzEL
MAkGA1UECBMCTUExEDAOBgNVBAcTB0JlZGZvcmQxDzANBgNVBAoTBmlSb2JvdDEM
MAoGA1UECxMDSEJVMRIwEAYDVQQDEwlSb29tYmEgQ0EwHhcNMTUwMzEzMDAwMDAw
WhcNMjUxMjMxMDAwMDAwWjBfMQswCQYDVQQGEwJVUzELMAkGA1UECBMCTUExEDAO
BgNVBAcTB0JlZGZvcmQxDzANBgNVBAoTBmlSb2JvdDEMMAoGA1UECxMDSEJVMRIw
EAYDVQQDEwlSb29tYmEgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQDIooRE+Q2qQ/3SiYbTtwBUwyY/YMncCMrhMoDcvkfJEawL1bHG9eL9c4qXSzec
t22lnY93LsZ80+0nQic5bPz21y89KNAC6Df4Yb4TWUwaZIDocNKjzC4keAKvxmVD
xycKMRM7Vf/f12gVRqXOeFZJUb+RzeIfWGvvNcqSEU234C0REQhtPaT+6jK/Qx04
lepgw8EYM4eoT5Ks10PIGzXemMZu7T44lvCcksog00YAMZaJ7skZ+vnBQhhjQdh+
mJGZtvMCG7Mk1cucu5JPVZwmzT9YKA6NMb3wEsujMI3bhY3QnFtF+a+IrbdjbNy+
/i2mT8yoCs/Q9TaKerT124DDAgMBAAGjEjAQMA4GA1UdDwEB/wQEAwICBDANBgkq
hkiG9w0BAQsFAAOCAQEAWE45Bxe2wpf3/5IRUF0bmf8eXKunsSPlM7+dSo/DKuUz
vyDBQt07NIp9e+OQp3Fojo94C14b27I9UmRPFJRDD3gI8wNKExKCvkUNEAIRVf3w
uRef860RwFodfJWjD4yBEQInLxxCRlCLTJ0gcqiRV8X6HSFCnLGJtIvKqF8hLwdP
m5WfPXr/zHzilTC7745FCZFlOtim5O+nMZMeHZp2urssjFLPvrkb1Q9l+FbF6jMr
gTzcLAd1L3a+NKR/i1TKZ+rn9tNnA9aUAXN9BnxResfBkIEKoQ6HJoFlZyfzKAiW
CRju2zTBnR6vg+kWjPxVCwcGRdzAZeDgc8xFqTxRMw==
-----END CERTIFICATE-----

I have my blid and using my account user name and login. When I enter the blid as the client ID for MQTT explorer and the username and password for my account I get a

"Connection refused Identifier rejected error" message.

Any suggestions?

Been a while since I tried to connect with mqtt explorer - but the mqtt authentication uses the blid and a robot-specific password - not your account password. The dorita980 nodejs package has utilities for getting this info from the robot... Or you'd have to sniff packets from the irobot app to decode this data

Hi
I want to send the MQTT commands directly from my homeserver (GIRA / KNX). So I'm figuring out how to setup this in the homeserver.

I can connect to my roomba with MQTT Explorer. I'm trying to publish also from MQTT Explorer. Did you manage to send a command directly with the MQTT Explorer.

{"command":"clean","time":1640965400,"initiator":"localApp"}

I'm having trouble with publishing this clean command, any suggestions?
Is the syntax OK. because then I can start implementing that.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.