[Release] Xiaomi / Aqara device drivers



Yeah, I have checked the events list in the past and the inactive event was definitely not being sent.

I have 3 cats and they trigger the motion sensors quite a lot, especially the ones on the stairs (one likes to sleep on the stairs). From a quick scan of the logs, each motion sensor is triggered about 40 times in a 24 hour period. There are 3 sensors in active use at present in the same area so that’s 120 calls to runIn() in a day. It seems to take around 2-3 days before I have to reboot the hub, so if there’s a limit on the number of timers used by runIn() and there’s a resource leak then that limit would be about 256.

Of course I could be entirely wrong in my diagnosis, but without access to more detailed logs of the internals of Hubitat it’s hard to be sure.


I find that really hard to believe, as runIn() is used by Apps for all kinds of delay-based automations. If there are limits on how many / how often it and other chon schedule calls can be used per day, it hasn’t been mentioned anywhere.

Sounds like something to ask the Hubitat folks about.


I hope you’re right about that. It would certainly be a surprise. I’ve enabled info and debug logging in a couple of the motion sensors - unfortunately that doesn’t seem to include any debugging for calls to runIn()


I’ve added some debugging code to my version to see if there’s a possibility that the device state isn’t as expected. I’ll see how it runs for a few days.


As I understand it, the device driver code is executed once for each message received from a device or command sent, and then exits. But, the runIn() call initializes a scheduled execution of the driver code, and at the scheduled time, it goes right to the function named in runIn() and then exits.

Since I can’t add any log message above the “level” of device driver execution, all I can do is put a confirmation info log message in the function that resets motion to inactive, and it’s no more helpful that checking whether the inactive event was sent.

So if the system is not honoring scheduled execution requests, there’s no way to have the device driver code let you know about that. It would require system or admin level logging.


Understood, it would be nice to have access to lower level logs.

The only other possibility that occurs to me is whether setting the device state is an atomic operation. If not then perhaps a motion event that occurs at the same time as the timer is trying to reset the state could cause the condition to fail. ie

(device.currentState('motion')?.value == "active")

suppose that device.currentState(‘motion’) is null - then the condition would fail and the reset would never happen.


I only know that for SmartThings device handler code, atomic state objects are not supported. I’m not sure if this also applies to device level states that are set by events for capabilities named in the code.

However, even if for some strange reason the current value of motion was null, it would immediately be set to a value of active the next time a motion detected message was sent from the sensor.

The reason I put it the conditional check for a current state of active was to avoid unnecessary inactive events being sent. In truth, it’s pretty safe to assume that when the runIn() call to resetToMotionInactive() occurs, the current value will still be active, because - at least in SmartThings and I would assume also on the Hubitat - every time a runIn() is called that refers to the same function, it replaces the previous call, effectively extending the countdown timer.

So in practical terms, as long as my runIn() is at least a second longer than the hardware’s motion detection reset time, if a motion detected message is sent, a new motion - active event occurs, and a new runIn() starts the countdown again, with no interruption by an inactive event. I just put the conditional check in the case that more than one instance of the runIn() occurs.

Either way, an easy way to find out if that condition is the cause of the problem is to add a debug message line above it, like this:

// If currently in 'active' motion detected state, resetToMotionInactive() resets to 'inactive' state and displays 'no motion'
def resetToMotionInactive() {
	displaydebugLog("Current value of motion state is ${device.currentState('motion')?.value}")
	if (device.currentState('motion')?.value == "active") {
		def seconds = motionreset ? motionreset : 61
		def descText = "Reset to motion inactive after ${seconds} seconds"
		sendEvent(name: "lastMotion", value: now())
			isStateChange: true,
			descriptionText: descText

Since you’re saying that things work for some days and then a reboot is needed to get it working again, perhaps the issue is that the state of motion is no longer being stored correctly, or can’t be read?


That’s possible, certainly. I’ll get back to you if I get any useful data.


Are you able to add that displaydebugLog line (in my above post) to your copy of the device driver code? That would definitely help settle the question of whether the (device.currentState('motion')?.value == "active") conditional is leading to the inactive state to never occur.


I already added the same line to a new else branch :slight_smile: I didn’t want to pollute the log while it’s working.


Wow! you just added my feature request in a matter of hours, let alone days :open_mouth:
Thanks a ton!


I face the exact same issue. Trouble is that sometimes, I find the lights have been on for hours together just because the inactive command never got sent!
Also, it’s worth noting that I see these issues with an Aeon sensor of mine too. Not sure if they are related.


One of the Aeon Multisensors, right?

If you’re also consistently not seeing a motion inactive event from an Aeon sensor then I would place higher suspicion that the problem may be because the Hubitat hub is “ignoring” the event.

This is because for the Aeon the reset to no motion is hardware-based. So there is no runIn() call in the code. Also, the Aeon code uses a createEvent() for motion inactive while in the Xiaomi sensor code sendEvent has to be used (due to the code being executed via runIn()). So it’s probably safe to say it’s not due to using sendEvent() versus createEvent().

I understand, but I would suggest putting that displaydebugLog line before the conditional so it’s possible to rule out the issue being because the runIn() call not working. So if my above theory is correct, you’d see the log message “Current value of motion state is active”, but then there would not be any motion inactive event.

I’ve added that log output line in my code for my Hubitat, but I’m not sure how helpful that will be because I have not seen the same behavior both you and @ajayjohnm have seen.


Precisely, it is a Aeon MultiSensor. I agree with your theory, it may not really be the call made.
Will dig into the logs a bit deeper to try to prove that the Hubitat hub may be ignoring the event.


There are no limits, some of the presence enabled zigbee fobs call runin every time the device reports every 20 seconds or so.
Since runin on these motion sensors is used to set motion inactive, it’s obviously not going to fire if the device stops reporting to the hub.


Thanks for that Mike, clearly that’s not the problem here then.

I’ll be keeping an eye on the debug messages


Thank you @veeceeoh etal for these drivers. I’m using them for some Aqara Temp/Humidity sensors and Aqara Window/Door contact sensors. They were discovered immediately and have been checking in regularly for a couple of days.
I’m having an issue with the contact sensors though. I’m not seeing open/closed states on the device pages and when I look at the logs, I see the raw event messages are being sent but they are unable to be parsed. Am I goofing-up the pairing process somehow?



If they are actually pairing with the Hubitat, the only thing that could possibly go wrong at the time of pairing is that correct device driver was not selected. So the first thing to do is double-check that the “Xiaomi Door/Window Sensor” device driver was assigned as the device Type, looking in the device details page for each of your contact sensors:

If it wasn’t correctly assigned, change it and hit “save”.

If it was correctly assigned, then I’d need to see a screenshot of the debug messages that occur when the contact sensor is opened and closed, to know how to troubleshoot your problem.

I have seen Ali Express sellers listing a “new 2017” version of the Aqara Door/Window contact sensors, so there’s a chance that they send different messages than the “original” version. This was true for a new model of the Aqara button, and I had to make changes to the device driver so it would work correctly with that new model.


That is very possible as I just got these through Ali Express.

They are assigned the correct driver at discovery, and like I said, continue to report . Below is the debug logs for close then open. Thank you.


Well, that was actually my fault!

Somehow I removed an important line in the code on the most recent update, probably after my testing, and didn’t realize it. So thank you for identifying it. Now updated…

[UPDATE] v0.7.1 of Door/Window Contact Sensor Device Driver
Works with both the “original” Xiaomi and Aqara Door/Window sensors


  • Parsing of open/close messages now works correctly again