Gearbest Flash sale on Aqara contact, Button switch, Temp/Humidity sensor


#1

http://www.gearbest.com/aqara-_gear/

Aqara Temp. sensor $8.99
Aqara Contact $6.99
Aqara Button switch $6.99

Xiaomi motion sensor $9.99
Xiaomi contact sensor $7.99
Xiaomi button switch $6.99
Xiaomi temperature sensor $8.99


(Eric) #2

I’m assuming as they are zigbee they (the sensors) will work in the US even though the switches and plugs are for the UK… Correct?


(Brian Spranger) #3

Yes the battery powered zigbee devices work in the US.

I have a lot of door sensors, motion sensors and temp sensors.

They work well. I have 3 that do not like to stay online.


#4

I have 3 of these Aqara buttons, but cannot get them to work in any useful fashion.

I managed to get the ST hub to find them, then had to associate them with a device handler, so used the a4refillpad : Xiaomi Zigbee Button found on this community site (I couldn’t find anything more suitable).

The only event I can get them to sometimes respond to is a 4 second hold, the normal press seems to send through nothing.
They also seem to eventually drop off and become inactive after a few hours and cannot be restarted without completely removing and re-pairing.

Anybody had more success with these buttons?


#5

Has anyone reported that the Aqara motion sensors work?

fyi “TWITTER” coupon code will currently get you %8 off.


#6

I would like to know if those work as well. The addition of the holder make them a better choice for mounting. They also have built in illuminance detection, which will work better for lighting applications than the other Xiaomi motion sensors I previously purchased.


(Brian Spranger) #7

I have not tried the aqara motion sensors but I do have the aqara temp and aqara door sensors working. I had to make new device handlers for them. I have them on got hub. I might try to pickup an aqara motion sensor. But it would be a while before I got one.


#8

I have a few aqara door and temp sensors on order do you mind sharing your device handlers for them, if you haven’t already?

I also have a few Aqara motion sensors on the order, Ill post my experience with them when they arrive.


(Brian Spranger) #9

My code is on git hub.


(Sergio Ferreira) #10

Thanks @ArstenA for the DH.

I tested and it is working for the Aqara Motion sensor except the intensity feature.
Anyone has implemented it?

regards


(Sergio Ferreira) #11

I tried to merge with another DH…but still getting 0 for the illuminance:

/**

  • Xiaomi Aqara Motion Sensor
  • 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 original DH by Eric Maycock 2015
  • modified 29/12/2016 a4refillpad
  • Added fingerprinting
  • Added heartbeat/lastcheckin for monitoring
  • Added battery and refresh
  • Motion background colours consistent with latest DH
  • Fixed max battery percentage to be 100%
  • Added Last update to main tile
  • Added last motion tile
  • Heartdeat icon plus improved localisation of date
  • removed non working tiles and changed layout and incorporated latest colours
  • added experimental health check as worked out by rolled54.Why

*/

metadata {
definition (name: “Xiaomi Aqara Motion Sensor Teste”, namespace: “a4refillpad”, author: “a4refillpad”) {
capability "Motion Sensor"
capability "Configuration"
capability "Battery"
capability "Sensor"
capability "Refresh"
capability "Health Check"
capability “Illuminance Measurement”

    attribute "lastCheckin", "String"
    attribute "lastMotion", "String"

	fingerprint profileId: "0104", deviceId: "0104", inClusters: "0000, 0003, FFFF, 0019", outClusters: "0000, 0004, 0003, 0006, 0008, 0005, 0019", manufacturer: "LUMI", model: "lumi.sensor_motion", deviceJoinName: "Xiaomi Motion"
    
    command "reset"
    command "Refresh"
    
}

// simulator metadata
simulator {
	status "dark": "illuminance: 8"
	status "light": "illuminance: 300"
	status "bright": "illuminance: 1000"
}

preferences {
	input "motionReset", "number", title: "Number of seconds after the last reported activity to report that motion is inactive (in seconds). \n\n(The device will always remain blind to motion for 60seconds following first detected motion. This value just clears the 'active' status after the number of seconds you set here but the device will still remain blind for 60seconds in normal operation.)", description: "", value:120, displayDuringSetup: false
}

tiles(scale: 2) {
	multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
		tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
			attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00a0dc"
			attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
		}
        tileAttribute("device.lastCheckin", key: "SECONDARY_CONTROL") {
			attributeState("default", label:'Last Update: ${currentValue}',icon: "st.Health & Wellness.health9")
        }
	}
	valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
		state "battery", label:'${currentValue}% battery', unit:""
	}
          
    standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
        state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
    }
    standardTile("configure", "device.configure", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
		state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
    }       
    
	standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat", width: 2, height: 1) {
		state "default", action:"reset", label: "Reset Motion"
	}
	standardTile("icon", "device.refresh", inactiveLabel: false, decoration: "flat", width: 4, height: 1) {
        state "default", label:'Last Motion:', icon:"st.Entertainment.entertainment15"
    }
    valueTile("lastmotion", "device.lastMotion", decoration: "flat", inactiveLabel: false, width: 4, height: 1) {
		state "default", label:'${currentValue}'
    }
    standardTile("refresh", "command.refresh", inactiveLabel: false) {
		state "default", label:'refresh', action:"refresh.refresh", icon:"st.secondary.refresh-icon"
   }
   	valueTile("illuminance", "device.illuminance", width: 2, height: 2) {
		state("illuminance", label:'${currentValue}', unit:"lux"
		)
	}

	main(["motion"])
	details(["motion", "battery", "icon", "lastmotion", "reset", "refresh","illuminance"])
}

}

def parse(String description) {
def linkText = getLinkText(device)
log.debug “${linkText} Parsing: $description”

Map map = [:]
if (description?.startsWith('catchall:')) {
	map = parseCatchAllMessage(description)
}
else if (description?.startsWith('read attr -')) {
	map = parseReportAttributeMessage(description)
}

log.debug "${linkText} Parse returned: $map"
def result = map ? createEvent(map) : null

// send event for heartbeat
def now = new Date().format(“yyyy MMM dd EEE h:mm:ss a”, location.timeZone)
sendEvent(name: “lastCheckin”, value: now)

if (description?.startsWith('enroll request')) {
	List cmds = enrollResponse()
    log.debug "${linkText} enroll response: ${cmds}"
    result = cmds?.collect { new physicalgraph.device.HubAction(it) }
}

	
if (description?.startsWith("illuminance: ")) {
	def raw = description - "illuminance: "
	if (raw.isNumber()) {
		result = createEvent(
			name:  "illuminance",
			value: Math.round(zigbee.lux(raw as Integer)).toString(),
			unit:  "lux"
		)
	}
	log.debug "Parse returned ${result?.descriptionText}"
}

   return result

}

private Map getBatteryResult(rawValue) {
//log.debug 'Battery’
def linkText = getLinkText(device)

//log.debug rawValue

def result = [
	name: 'battery',
	value: '--'
]

def volts = rawValue / 1

def maxVolts = 100

if (volts > maxVolts) {
			volts = maxVolts
}

result.value = volts
result.descriptionText = "${linkText} battery was ${result.value}%"

return result

}

private Map parseCatchAllMessage(String description) {
def linkText = getLinkText(device)

Map resultMap = [:]
def cluster = zigbee.parse(description)
log.debug cluster
if (shouldProcessMessage(cluster)) {
	switch(cluster.clusterId) {
		case 0x0000:
		resultMap = getBatteryResult(cluster.data.get(30))
		break

		case 0xFC02:
		log.debug '${linkText}: ACCELERATION'
		break

		case 0x0402:
		log.debug '${linkText}: TEMP'
			// temp is last 2 data values. reverse to swap endian
			String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
			def value = getTemperature(temp)
			resultMap = getTemperatureResult(value)
			break
	}
}

return resultMap

}

private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}

def configure() {
def linkText = getLinkText(device)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "${linkText}: ${device.deviceNetworkId}"
def endpointId = 1
log.debug "${linkText}: ${device.zigbeeId}"
log.debug "${linkText}: ${zigbeeEui}“
def configCmds = [
//battery reporting and heartbeat
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 1 {${device.zigbeeId}} {}”, “delay 200”,
“zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}”, “delay 200”,
“send 0x${device.deviceNetworkId} 1 ${endpointId}”, “delay 1500”,

		// Writes CIE attribute on end device to direct reports to the hub's EUID
		"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
		"send 0x${device.deviceNetworkId} 1 1", "delay 500",
]

log.debug "${linkText} configure: Write IAS CIE"
return configCmds

}

def enrollResponse() {
def linkText = getLinkText(device)
log.debug “${linkText}: Enrolling device into the IAS Zone”
[
// Enrolling device into the IAS Zone
"raw 0x500 {01 23 00 00 00}", “delay 200”,
“send 0x${device.deviceNetworkId} 1 1”
]
}

def refresh() {
def linkText = getLinkText(device)
log.debug “${linkText}: Refreshing Battery”
// def endpointId = 0x01
// [
// “st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0000 0x0000”, “delay 200”
// “st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0000”, “delay 200”
// ] //+ enrollResponse()

zigbee.configureReporting(0x0001, 0x0021, 0x20, 300, 600, 0x01)

}

private Map parseReportAttributeMessage(String description) {
Map descMap = (description - “read attr - “).split(”,”).inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
//log.debug “Desc Map: $descMap”

Map resultMap = [:]
def now = new Date().format("yyyy MMM dd EEE h:mm:ss a", location.timeZone)

if (descMap.cluster == "0001" && descMap.attrId == "0020") {
	resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16))
}
else if (descMap.cluster == "0406" && descMap.attrId == "0000") {
	def value = descMap.value.endsWith("01") ? "active" : "inactive"
    sendEvent(name: "lastMotion", value: now)
    if (settings.motionReset == null || settings.motionReset == "" ) settings.motionReset = 120
    if (value == "active") runIn(settings.motionReset, stopMotion)
	resultMap = getMotionResult(value)
} 
return resultMap

}

private Map parseCustomMessage(String description) {
Map resultMap = [:]
return resultMap
}

private Map parseIasMessage(String description) {
def linkText = getLinkText(device)
List parsedMsg = description.split(’ ')
String msgCode = parsedMsg[2]

Map resultMap = [:]
switch(msgCode) {
    case '0x0020': // Closed/No Motion/Dry
    	resultMap = getMotionResult('inactive')
        break

    case '0x0021': // Open/Motion/Wet
    	resultMap = getMotionResult('active')
        break

    case '0x0022': // Tamper Alarm
    	log.debug '${linkText}: motion with tamper alarm'
    	resultMap = getMotionResult('active')
        break

    case '0x0023': // Battery Alarm
        break

    case '0x0024': // Supervision Report
    	log.debug '${linkText}: no motion with tamper alarm'
    	resultMap = getMotionResult('inactive')
        break

    case '0x0025': // Restore Report
        break

    case '0x0026': // Trouble/Failure
    	log.debug '${linkText}: motion with failure alarm'
    	resultMap = getMotionResult('active')
        break

    case '0x0028': // Test Mode
        break
}
return resultMap

}

private Map getMotionResult(value) {
def linkText = getLinkText(device)
//log.debug "${linkText}: motion"
String descriptionText = value == ‘active’ ? “${linkText} detected motion” : "${linkText} motion has stopped"
def commands = [
name: ‘motion’,
value: value,
descriptionText: descriptionText
]
return commands
}

private byte[] reverseArray(byte[] array) {
byte tmp;
tmp = array[1];
array[1] = array[0];
array[0] = tmp;
return array
}

private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}

def stopMotion() {
sendEvent(name:“motion”, value:“inactive”)
}

def reset() {
sendEvent(name:“motion”, value:“inactive”)
}

def installed() {
// Device wakes up every 1 hour, this interval allows us to miss one wakeup notification before marking offline
def linkText = getLinkText(device)
log.debug "${linkText}: Configured health checkInterval when installed()"
sendEvent(name: “checkInterval”, value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: “zigbee”, hubHardwareId: device.hub.hardwareID])
}

def updated() {
// Device wakes up every 1 hours, this interval allows us to miss one wakeup notification before marking offline
def linkText = getLinkText(device)
log.debug "${linkText}: Configured health checkInterval when updated()"
sendEvent(name: “checkInterval”, value: 2 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: “zigbee”, hubHardwareId: device.hub.hardwareID])
}