Xiaomi & Aqara Devices - Pairing & Keeping them connected

Nah, the Ikea repeaters and outlets are 100% compatible. This has been shown by many dozens of people,

Something else is going on in your case.

@rocketwiz
A long time ago, I did a systematic rebuild of my zigbee mesh. It took a while, and I did it when I was the only one at home so it wouldn't bother anyone. I haven't lost a Xiaomi sensor since. Of course, YMMV and everyone's environment is different.
My steps:

  1. Gracefully shut the hub down and pull power
  2. Unplug all zigbee repeating devices (I like to think this erases all routing tables)
  3. Wait 30 minutes
  4. Plug in those Xiaomi-friendly repeaters
  5. Boot the hub back up and wait a few minutes to ensure the repeaters are talking to the hub.
  6. Re-join all Xiaomi devices, even if they've joined on their own
  7. At this point, I waited for a couple of hours to make sure the Xiaomi's have checked-in a couple of times, and then plug in devices that repeat and are not Xiaomi friendly, if any.

I am sure you are aware, a battery back-up for the hub is a great thing!

1 Like

Thanks for the suggestion. I'll try this next week when my zigbee stuff turn up. That way I can be sure what's connecting to the hub.

Yeah lol. It's now plugged into my UPS. That's where the ST was great with its own battery pack.

I would be very happy to know what else that could be. Because initially I had one Ikea outlet and 2 Xbee as only routers on my Zigbe network. Over time I noticed that Senged bulb would just stop working over time. Bulb was connected through Ikea Outlet. Signal strength for Zigbee devices ranges -50 -60, Recently I added two Ikea repeaters ( they come with Ikea blinds) and one more Ikea outlet. Now I see other segments stopping to work... Also seems that sending any command , like for example "get routing table" to Ikea devices will make them to start routing again.

What zigbee channel are you using? What are the strongest WiFi channels in your house and its immediate vicinity?

I am using channel 25, switched to 20 , went back to 25. WiFI is on 5 GHZ,.. I have been using Xiaomi for years, since ST, never had a lot of problem.

Because of that and bad firmware, I was left with a ruined shelf on my desk and a warped case that kept me from selling the darn thing! :grin:

Maybe your Ikea devices are actually DEFECTIVE... That is different than an incompatibility.

1 Like

Channel 25 generally does not work well with some devices.
Why did you leave 20?

2 Likes

Was getting interference on channel 20. Signal strength is better on 25 for me. Older devices my not work on Zigbee channels 25 and 26... I am not saying that Ikea devices are definitely no good. Just sharing my suspicions. The problem I have does not happen very often, not daily. But seems to be related to HUB reboot or over some period of time, weeks...

I would try a lower channel like 15 or 21.
Have you tried a network scan in XTCU?
It could be interference from a neighboring device.

This is likely no help solving the problem however;

I have two Aqara Temp/Press/Humidity sensors on Hubitat. The only other Zigbee device is a "homemade" sensor/repeater from iharyadi.

The iharyadi sensor is positioned such it might be acting as a repeater for one of the Aqara sensors but doubtful on the other.

These were installed back in mid August. I have no battery backup on my hub and these devices have not dropped once. Through several storm related outages and at least one power loss on the hub only (the iharyadi is mains powered).

My zigbee channel 19.

I only write this to show that the Aqara sensors can be reliably paired with Hubitat, albeit with only a few Zigbee devices.

3 Likes

With xiaomi NOT being on the HE inbuilt Driver list, Couldn’t another factor be the Drivers that are being used by other people ?

2 Likes

I've always used the below for my temp/pressure/humidity sensors:

    /**
 * Xiaomi "Original" Temperature Humidity Sensor - model RTCGQ01LM
 * & Aqara Temperature Humidity Sensor - model WSDCGQ11LM
 * Device Driver for Hubitat Elevation hub
 * Version 0.8.2
 *
 * 2019-08-14  modified.  changed  kPa --> hPa
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 * for the specific language governing permissions and limitations under the License.
 *
 * Based on SmartThings device handler code by a4refillpad
 * With contributions by alecm, alixjg, bspranger, gn0st1c, foz333, jmagnuson, mike.maxwell, rinkek, ronvandegraaf, snalee, tmleafs, twonk, & veeceeoh
 * Code reworked for use with Hubitat Elevation hub by veeceeoh
 *
 * Known issues:
 * + Xiaomi devices send reports based on changes, and a status report every 50-60 minutes. These settings cannot be adjusted.
 * + The battery level / voltage is not reported at pairing. Wait for the first status report, 50-60 minutes after pairing.
 * + Pairing Xiaomi devices can be difficult as they were not designed to use with a Hubitat hub.
 *  Holding the sensor's reset button until the LED blinks will start pairing mode.
 *  3 quick flashes indicates success, while one long flash means pairing has not started yet.
 *  In either case, keep the sensor "awake" by short-pressing the reset button repeatedly, until recognized by Hubitat.
 * + The connection can be dropped without warning. To reconnect, put Hubitat in "Discover Devices" mode, then short-press
 *  the sensor's reset button, and wait for the LED - 3 quick flashes indicates reconnection. Otherwise, short-press again.
 *
 */

metadata {
	definition (name: "Xiaomi Temperature Humidity Sensor", namespace: "veeceeoh", author: "veeceeoh") {
		capability "Battery"
		capability "PressureMeasurement"
		capability "RelativeHumidityMeasurement"
		capability "Sensor"
		capability "TemperatureMeasurement"


		attribute "lastCheckinEpoch", "String"
		attribute "lastCheckinTime", "Date"
		attribute "batteryLastReplaced", "String"

		//fingerprint for Xioami "original" Temperature Humidity Sensor
		fingerprint profileId: "0104", inClusters: "0000,0003,0019,FFFF,0012", outClusters: "0000,0004,0003,0005,0019,FFFF,0012", manufacturer: "LUMI", model:     "lumi.sensor_ht"
		//fingerprint for Xioami Aqara Temperature Humidity Sensor
		fingerprint profileId: "0104", inClusters: "0000, 0003, FFFF, 0402, 0403, 0405", outClusters: "0000, 0004, FFFF", manufacturer: "LUMI", model:     "lumi.weather"

		command "resetBatteryReplacedDate"
	}

	preferences {
		//Temp and Humidity Offsets
		input "tempOffset", "decimal", title:"Temperature Offset", description:"", range:"*..*"
		input "humidityOffset", "decimal", title:"Humidity Offset", description:"", range: "*..*"
		input "pressOffset", "decimal", title:"Pressure Offset (Aqara model only)", description:"", range: "*..*"
		input name:"pressureUnits", type:"enum", title:"Pressure Units (Aqara model only)", description:"", options:["mbar", "hPa", "inHg", "mmHg"]
		//Battery Voltage Range
		input name: "voltsmin", title: "Min Volts (0% battery = ___ volts, range 2.0 to 2.9). Default = 2.9 Volts", description: "", type: "decimal", range:     "2..2.9"
		input name: "voltsmax", title: "Max Volts (100% battery = ___ volts, range 2.95 to 3.4). Default = 3.05 Volts", description: "", type: "decimal", range:     "2.95..3.4"
		//Date/Time Stamp Events Config
		input name: "lastCheckinEnable", type: "bool", title: "Enable custom date/time stamp events for lastCheckin", description: ""
		//Logging Message Config
		input name: "infoLogging", type: "bool", title: "Enable info message logging", description: ""
		input name: "debugLogging", type: "bool", title: "Enable debug message logging", description: ""
		//Firmware 2.0.5 Compatibility Fix Config
		input name: "oldFirmware", type: "bool", title: "DISABLE 2.0.5 firmware compatibility fix (for users of 2.0.4 or earlier)", description: ""
	}
}

// Parse incoming device messages to generate events
def parse(String description) {
	def cluster = description.split(",").find {it.split(":")[0].trim() == "cluster"}?.split(":")[1].trim()
	def attrId = description.split(",").find {it.split(":")[0].trim() == "attrId"}?.split(":")[1].trim()
	def encoding = Integer.parseInt(description.split(",").find {it.split(":")[0].trim() == "encoding"}?.split(":")[1].trim(), 16)
	def valueHex = description.split(",").find {it.split(":")[0].trim() == "value"}?.split(":")[1].trim()
	Map map = [:]

	if (!oldFirmware & valueHex != null & encoding > 0x18 & encoding < 0x3e) {
		displayDebugLog("Data type of payload is little-endian; reversing byte order")
		// Reverse order of bytes in description's payload for LE data types - required for Hubitat firmware 2.0.5 or newer
		valueHex = reverseHexString(valueHex)
	}

	displayDebugLog("Parsing message: ${description}")
	displayDebugLog("Message payload: ${valueHex}")

	// Send message data to appropriate parsing function based on the type of report
	if (cluster == "0402")
		map = parseTemperature(valueHex)
	else if (cluster == "0405")
		map = parseHumidity(valueHex)
	else if (cluster == "0403")
		map = parsePressure(valueHex)
	else if (cluster == "0000" & attrId == "0005")
		displayDebugLog("Reset button was short-pressed")
	else if	(cluster == "0000" & (attrId == "FF01" || attrId == "FF02"))
		// Parse battery level from hourly announcement message
		map = parseBattery(valueHex)
	else
		displayDebugLog("Unable to parse message")

	if (map != [:]) {
		displayInfoLog(map.descriptionText)
		displayDebugLog("Creating event $map")
		return createEvent(map)
	} else
		return map
}

// Reverses order of bytes in hex string
def reverseHexString(hexString) {
	def reversed = ""
	for (int i = hexString.length(); i > 0; i -= 2) {
		reversed += hexString.substring(i - 2, i )
	}
	return reversed
}

// Calculate temperature with 0.01 precision in C or F unit as set by hub location settings
private parseTemperature(description) {
	float temp = Integer.parseInt(description,16)/100
	temp = (temp > 100) ? (temp - 655.35) : temp
	displayDebugLog("Raw reported temperature = ${temp}°C")
	temp = (location.temperatureScale == "F") ? ((temp * 1.8) + 32) : temp
	temp = tempOffset ? (temp + tempOffset) : temp
	temp = temp.round(2)
	return [
		name: 'temperature',
		value: temp,
		unit: "°${location.temperatureScale}",
		descriptionText: "Temperature is ${temp}°${location.temperatureScale}",
		translatable:true
	]
}

// Calculate humidity with 0.1 precision
private parseHumidity(description) {
	float humidity = Integer.parseInt(description,16)/100
	displayDebugLog("Raw reported humidity = ${humidity}%")
	humidity = humidityOffset ? (humidity + humidityOffset) : humidity
	humidity = humidity.round(1)
	return [
		name: 'humidity',
		value: humidity,
		unit: "%",
		descriptionText: "Humidity is ${humidity}%",
	]
}

// Parse pressure report
private parsePressure(description) {
	float pressureval = Integer.parseInt(description[0..3], 16)
	if (!(pressureUnits)) {
		pressureUnits = "mbar"
	}
	displayDebugLog("Converting ${pressureval} to ${pressureUnits}")
	switch (pressureUnits) {
		case "mbar":
			pressureval = (pressureval/10) as Float
			pressureval = pressureval.round(1);
			break;
		case "hPa":
			pressureval = (pressureval/10) as Float
			pressureval = pressureval.round(2);
            pressureUnits = "hPa"
			break;
		case "inHg":
			pressureval = (((pressureval/10) as Float) * 0.0295300)
			pressureval = pressureval.round(2);
			break;
		case "mmHg":
			pressureval = (((pressureval/10) as Float) * 0.750062)
			pressureval = pressureval.round(2);
			break;
	}
	pressureval = pressOffset ? (pressureval + pressOffset) : pressureval
	pressureval = pressureval.round(2);

	return [
		name: 'pressure',
		value: pressureval,
		unit: pressureUnits,
		descriptionText: "Pressure is ${pressureval} ${pressureUnits}"
	]
}

// Convert raw 4 digit integer voltage value into percentage based on minVolts/maxVolts range
private parseBattery(description) {
	displayDebugLog("Battery parse string = ${description}")
	def rawValue = Integer.parseInt((description[8..9] + description[6..7]),16)
	def rawVolts = rawValue / 1000
	def minVolts = voltsmin ? voltsmin : 2.9
	def maxVolts = voltsmax ? voltsmax : 3.05
	def pct = (rawVolts - minVolts) / (maxVolts - minVolts)
	def roundedPct = Math.min(100, Math.round(pct * 100))
	def descText = "Battery level is ${roundedPct}% (${rawVolts} Volts)"
	return [
		name: 'battery',
		value: roundedPct,
		unit: "%",
		descriptionText: descText
	]
	// lastCheckinEpoch is for apps that can use Epoch time/date and lastCheckinTime can be used with Hubitat Dashboard
	if (lastCheckinEnable) {
		sendEvent(name: "lastCheckinEpoch", value: now())
		sendEvent(name: "lastCheckinTime", value: new Date().toLocaleString())
	}
	return result
}

// installed() runs just after a sensor is paired
def installed() {
	displayDebugLog("Installing")
	state.prefsSetCount = 0
	init()
}

// configure() runs after installed() when a sensor is paired
def configure() {
	displayInfoLog("Configuring")
	init()
	state.prefsSetCount = 1
}

// updated() will run every time user saves preferences
def updated() {
	displayInfoLog("Updating preference settings")
	init()
	if (lastCheckinEnable)
		displayInfoLog("Last checkin events enabled")
	displayInfoLog("Info message logging enabled")
	displayDebugLog("Debug message logging enabled")
}

def init() {
	if (!device.currentValue('batteryLastReplaced'))
		resetBatteryReplacedDate(true)
}

//Reset the batteryLastReplaced date to current date
def resetBatteryReplacedDate(paired) {
	def newlyPaired = paired ? " for newly paired sensor" : ""
	sendEvent(name: "batteryLastReplaced", value: new Date().format("MMM dd yyyy", location.timeZone))
	displayInfoLog("Setting Battery Last Replaced to current date${newlyPaired}")
}

private def displayDebugLog(message) {
	if (debugLogging) log.debug "${device.displayName}: ${message}"
}

private def displayInfoLog(message) {
	if (infoLogging || state.prefsSetCount != 1)
		log.info "${device.displayName}: ${message}"
}
// -- eof --

My repeaters consist of 2 XBees and 1 IKEA Outlet, the same as your initial lineup of repeaters. I haven't had the same experience with the IKEA Outlet, however. One of my Sengled classic bulbs and a few Aqara sensors are connected through the IKEA Outlet and I've never seen any of those stop working.

I don't have any experience with the IKEA repeaters, though. I haven't bought any after reading that it seems they have limited range due to signal strength on the weak side.

For what's worth, my ZigBee channel is 20, has been that way for a long time on my C4 hub.



If by "factor", you mean factor in pairing / connection difficulties, then the answer is no. All pairing / connection issues happen completely outside the functions of the Xiaomi / Aqara drivers.

For what it's worth setting my zigbee channel to 13 and wifi to 12 seems to have stabilised my system. It's managed to survive one hub power down with only 4 (xiaomi only) devices dropping off in 24 hours since. The only problematic device has been the aqara temp sensor and I've just re-paired it afresh next to the hub rather than in place to see if that solves it.

Repeaters are all ikea and a couple of rebranded netvox power outlets.

I have not heard any reports on whether Xiaomi / Aqara devices "play well" with Netvox smart plugs. It's possible Xiaomi / Aqara devices drop their connection when connected via a Netvox plug.

1 Like

How do you see this? Using the /hub/zigbee/getChildAndRouteInfo link will show no devices using the ikea repeaters but not all devices are shown as child devices of the hub. I'm using channel 15. I suppose you use the xbee routing map feature...

Well I was feeling very happy up to yesterday, found the best way to keep my wireless switches sweet was to clear all my ZigBee devices down, connect the ikea plugs first then go round and reconnect everything else, all fine for two months, then the power cut......since then the wireless switches have gone back to their unresponsiveness, the wired no neutral switches work fine but the wireless switches when pressed do nothing, however if you press them multiple times they will come back to life, for awhile, then back to unresponsive again which seems strange as I would expect to have to reconnect them again not just press them a few times and they suddenly work. Beyond me and unfortunately she who must be obeyed :slight_smile: soooo I will clear down the ZigBee devices and start again, incidentally the last update blew away all my ikea plugs and they all had to be reconnected.

getChildAndRouteInfo does (sometimes) show the Sengled bulb as connected through the IKEA Outlet, but yes the XBee mesh network map reveals things that aren't displayed using the getChildAndRouteInfo link.

1 Like