Xiaomi Robot Vacuum Binding

@ThomDietrich not yet reported…but fixed now.
Thanks

1 Like

You can try to discover it with this binding. It may ‘speak’ the miio protocol.
In that case it will be discovered as unsupported device, but you can try to google for commands and control it via the command channel (hidden by default)

first at all, thanks for your binding.
My robot not connected to openhab. I added the Xiaomi Robot Vacuum V1 it manually but it get following error:

2018-01-24 08:27:50.109 [ERROR] [st.core.internal.thing.ThingResource] - Exception during HTTP PUT request for update config at 'things/miio:vacuum:963f243d/config'
java.lang.NullPointerException: null
        at org.openhab.binding.miio.handler.MiIoAbstractHandler.dispose(MiIoAbstractHandler.java:146) [224:org.openhab.binding.miio:2.3.0.201712272046]
        at org.eclipse.smarthome.core.thing.binding.BaseThingHandler.handleConfigurationUpdate(BaseThingHandler.java:171) [116:org.eclipse.smarthome.core.thing:0.10.0.b1]
        at org.eclipse.smarthome.core.thing.internal.ThingRegistryImpl.updateConfiguration(ThingRegistryImpl.java:94) [116:org.eclipse.smarthome.core.thing:0.10.0.b1]
        at org.eclipse.smarthome.io.rest.core.internal.thing.ThingResource.updateConfiguration(ThingResource.java:413) [126:org.eclipse.smarthome.io.rest.core:0.10.0.b1]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:?]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[?:?]
        at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:144) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:161) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:160) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:99) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:389) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:347) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:102) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.ServerRuntime$2.run(ServerRuntime.java:326) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271) [177:org.glassfish.jersey.core.jersey-common:2.22.2]
        at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267) [177:org.glassfish.jersey.core.jersey-common:2.22.2]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:315) [177:org.glassfish.jersey.core.jersey-common:2.22.2]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:297) [177:org.glassfish.jersey.core.jersey-common:2.22.2]
        at org.glassfish.jersey.internal.Errors.process(Errors.java:267) [177:org.glassfish.jersey.core.jersey-common:2.22.2]
        at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:317) [177:org.glassfish.jersey.core.jersey-common:2.22.2]
        at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:305) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1154) [178:org.glassfish.jersey.core.jersey-server:2.22.2]
        at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:473) [175:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
        at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:427) [175:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:388) [175:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:341) [175:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
        at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:228) [175:org.glassfish.jersey.containers.jersey-container-servlet-core:2.22.2]
        at com.eclipsesource.jaxrs.publisher.internal.ServletContainerBridge.service(ServletContainerBridge.java:76) [15:com.eclipsesource.jaxrs.publisher:5.3.1.201602281253]
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:848) [88:org.eclipse.jetty.servlet:9.3.22.v20171030]
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:584) [88:org.eclipse.jetty.servlet:9.3.22.v20171030]
        at org.ops4j.pax.web.service.jetty.internal.HttpServiceServletHandler.doHandle(HttpServiceServletHandler.java:71) [191:org.ops4j.pax.web.pax-web-jetty:6.0.7]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548) [85:org.eclipse.jetty.security:9.3.22.v20171030]
        at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.ops4j.pax.web.service.jetty.internal.HttpServiceContext.doHandle(HttpServiceContext.java:284) [191:org.ops4j.pax.web.pax-web-jetty:6.0.7]
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:512) [88:org.eclipse.jetty.servlet:9.3.22.v20171030]
        at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.ops4j.pax.web.service.jetty.internal.JettyServerHandlerCollection.handle(JettyServerHandlerCollection.java:80) [191:org.ops4j.pax.web.pax-web-jetty:6.0.7]
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.server.Server.handle(Server.java:534) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:333) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251) [87:org.eclipse.jetty.server:9.3.22.v20171030]
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:283) [79:org.eclipse.jetty.io:9.3.22.v20171030]
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:108) [79:org.eclipse.jetty.io:9.3.22.v20171030]
        at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93) [79:org.eclipse.jetty.io:9.3.22.v20171030]
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303) [90:org.eclipse.jetty.util:9.3.22.v20171030]
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148) [90:org.eclipse.jetty.util:9.3.22.v20171030]
        at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136) [90:org.eclipse.jetty.util:9.3.22.v20171030]
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671) [90:org.eclipse.jetty.util:9.3.22.v20171030]
        at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589) [90:org.eclipse.jetty.util:9.3.22.v20171030]
        at java.lang.Thread.run(Thread.java:748) [?:?]

Edit: Fixed, token was wrong!

Great binding, it works for me, I can switch my Xiaomi Smart Wifi Plug on and off. :slight_smile:

But I noticed errors in openhab.log:

2018-01-24 16:02:58.678 [WARN ] [nal.transport.MiIoAsyncCommunication] - Could not parse '{"result":{"life":276022,"cfg_time":0,"token":"xxx","mac":"xxx","fw_ver":"1.2.4_17","hw_ver":"MW300","model":"chuangmi.plug.m1","wifi_fw_ver":"SD878x-14.76.36.p84-702.1.0-WM","ap":{"rssi":-41,"ssid":"xxx","bssid":"xxx"},"netif":{"localIp":"xxx","mask":"xxx","gw":"xxx"},"mmfree":28572,,"otu_stat":[0,0,0,0,0,1],"ott_stat":[68928, 0, 0, 10]},"id":5}' <- {"id":5,"method":"miIO.info","params":[]} (Device: 03EEA388) gave error com.google.gson.stream.MalformedJsonException: Expected name at line 1 column 378 path $.result.mmfree

Note: I replaced some data with xxx, but the content looks “normal” to me.

What I do not get from the plug is network#rssi and network#life. Don’t know if these channels contain useful data, but no data is coming in.

In case you are interested in sunrise and sunset commands:

RGB:
sunrise:

set_scene["cf",3,1,"50,1,16731392,1,360000,2,1700,10,540000,2,2700,100"]

sunset:

set_scene["cf",3,2,"50,2,2700,10,180000,2,1700,5,420000,1,16731136,1"]

Ceiling:
Sunrise

set_scene["cf",2,1,"50,2,4000,1,900000,2,4000,100"]

Sunset command for ceiling:

set_scene["cf",2,2,"50,2,4000,50,600000,2,4000,1"]
1 Like

Hey @marcel_verpaalen,

I just got my new Yeelight Yeelight JIAOYUE 650 with surrounding ambient lighting.

Your binding reports it as unsupported but it so far it seems to work… Is there anything I can send you (json, Yeelight app .tar, etc.) to make this one supported?

I could also fork your repo and add it myself if you would kindly nudge me into the right direction from where to start :wink:

best regards
Anthrax

@Anthrax nice light :slight_smile:

Yes, it is reported as unsupported because the modelId is not yet known. To get started you can add (manually) a basic device, change the modelId (in the config) to the modelId’s of one of the yeelights (e.g. yeelink.light.color1)

To get you started… There are 2 places which need update to have a basic device supported:

  1. MiIoDevices.java this file defines which thingtype to use it should be THING_TYPE_BASIC
  2. A database entry, this is a json file containing the command mapping : e.g. you can start of the yeeligh color. If all commands are the same you could just suffice with adding the id of your light to the first section of id’s

Sorry I have bit less time this last month to hence my slower reply.
I would appreciate your pull request

@Roi the reply has “mmfree”:28572, double comma, which is I think what gson is complaining about.
network#rssi and network#life. I think these channels are not too relevant… rssi is the signal strenght and life is I think the connection time to the wifi.

Hi @marcel_verpaalen

I have a Yeelight RGB Bulb. I’ve been trying to use it with the so called “Yeelight binding” but it has lots of network problems when it comes to device discovery.

I’m now trying your binding which hopefully will solve all my problems. In fact I have installed it, and it seems to discover my device without problem. The strange thing about it is that when I setup the Thing, only the following channels are offered:

  • Network --> network#ssid
  • Network --> network#bssid
  • Network --> network#rssi
  • Network --> network#life
  • Actions --> actions#commands

None of them makes sense for my device. Any clue on how can I make it work?

Thanks!
Pedro

Hi @pfiol,
You most likely have a model that this not yet supported.
remove your discovered thing and instead manually add the thing as a basic type. (with the right token & ip)
Than change the modelId to one of the supported ones. e.g. you can try try yeelink.light.color1 or yeelink.light.lamp1)

Let me know the modelID of your light and if one of the above models work for your light and I can add it to the database

Hi again,

Thank you for the quick reply. I’ve tried to do as you mention but it didn’t work. I see some messages on the log similar to this one:

2018-01-28 09:16:08.514 [WARN ] [nal.transport.MiIoAsyncCommunication] - Error while polling/sending message
java.nio.BufferOverflowException: null
	at java.nio.Buffer.nextPutIndex(Buffer.java:527) [?:?]
	at java.nio.HeapByteBuffer.putInt(HeapByteBuffer.java:372) [?:?]
	at org.openhab.binding.miio.internal.Message.createMsgData(Message.java:64) [252:org.openhab.binding.miio:2.3.0.201712272046]
	at org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication.sendCommand(MiIoAsyncCommunication.java:232) [252:org.openhab.binding.miio:2.3.0.201712272046]
	at org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication.sendMiIoSendCommand(MiIoAsyncCommunication.java:154) [252:org.openhab.binding.miio:2.3.0.201712272046]
	at org.openhab.binding.miio.internal.transport.MiIoAsyncCommunication$MessageSenderThread.run(MiIoAsyncCommunication.java:205) [252:org.openhab.binding.miio:2.3.0.201712272046]

Also other messages like:

2018-01-28 09:34:19.729 [WARN ] [nal.transport.MiIoAsyncCommunication] - Send command '{"id":66,"method":"get_prop","params":["power","bright","delayoff","ct","color_mode"]}' -> 192.168.0.160 (Device: 0332F846) gave error Given final block not properly padded

Any idea?

Hey,

your second message indicates that your token is not the right one.

The RGB bulb is working for me. Maybe check again, if you are using the right token for this device.

You were absolutely right! There was a typo error on the Token ID. Now it works perfectly :slight_smile:

Thanks a lot!

Hi @marcel_verpaalen,

Just wondering if you have a come across this issue with token retrieval. I’ve just set up Robot Vacuum V1. I am able to control the vacuum from the app.

Robot Vacuum firmware is : 3.3.9_003094
Mi Home App Version : 5.1.1

When I use the tool kit it works successfully but the output window only shows ip address no token;
Picture1

And if I look in the miio2 db file the token field is blank.

Cheers
Mike

I think they changed something in new Mi Home App… token for vacuum no longer saved on phone…?
I think you can use this app to get the token… (I haven’t tried myself)
Setup the vacuum in the app then do a Export to SD Card and the token is in the RobotConfig.frc file
https://xiaomi.flole.de/

that would indeed be new. If no longer in the database, it will hamper the usabge of the binding for many new users.
Very unfortunate. Then the effort to receive the tokens needs to be accelerated…
(meaning, we need to reverse engineer the logon procedure to the Xiaomi cloud, as the app gets the updated tokens each time it logs on)

Hello everyone,

I had the same problem last night as I tried to add my new Robot to openhab. Fortunately I was able to extract the token using the Flole app (as mentioned by nisseDILLIGAF). You have to install the official Mi Home first and setup your vacuum in there. After that open the Flole app and import the robot definition from Mi Home. Export the configuration to Google drive (using the Flole app) and open the file “FloleXiaomiRemote.settings” with a text editor. The digits after ‘“e”:’ are your token which you can directly copy to the binding configuration.

Thank you Marcel for the great binding by the way!

Best regards

Thorsten

2 Likes

Same issue, just downloaded and installed version 5.0.19. I picked ups a philips Xiaomi desk lamp, On and Off works. How do I get started on sending commands, it supports dimming and different white light modes, I am just not sure how to structure the command. Thanks.

Hi @nisseDILLIGAF / @marcel_verpaalen,

Thanks for the info on the FloleVac app. Works fine.

I used the same method as @hachinga by uploading to Google Drive.

At first I thought that I messed up… (wanted to add Yeelights to this binding now)

Just install the old APK (https://www.apkmirror.com/apk/xiaomi-inc/mihome/mihome-5-0-19-release/mihome-5-0-19-android-apk-download/ ), extract the tokens and afterwards you can upgrade the app again.

Edit: @marcel_verpaalen Is it possible to add something that the bulbs turn off when the brightness is 0?