Xiaomi smart light sensor

Where are you located? (that will affect device recommendations)

In general, if its available where you are, the hue outdoor motion sensor is supposed to be a pretty good lux sensor.

3 Likes

The Hue outdoor is excellent. I agree on that. Expensive, but an Amazon Warehouse deal comes up every so often on them. That’s how I got mine and it has been great.

The new Xiaomi Mijia light sensor is Zigbee 3.0 and they warn that it won’t even work with their older Xiaomi gateways with Zigbee 1.2. That’s what they mean by “For use with Smart multi-mode gateway”. That’s what they call their new Zigbee 3.0 gateways.

So unless you’ve got a way to bridge one of their gateways and use the light measurements in HE via the bridges connection, then I’d suggest the Hue Outdoor motion sensor instead.

2 Likes

Thanks for replying.

@Ryan780 I live in Brazil and virtually the only way to get zigbee devices is from AliExpress. I mean, sometimes I buy from Amazon, eBay etc (i.e. Hubitat hub ), but most of times shipping and custom taxes are prohibitive, unfortunately.

2 Likes

Only thing I can think of you being able to possibly do is use a HomeKit automation with the new Mijia gateway to trigger an HE virtual switch when a light value is reached, But that's about all you can do with HomeKit. They can't compare one value to another. They can only trigger off a reference value.

And then of course, you need to be already in Apple's ecosystem with an iOS device and an Apple TV 4, or iPad (with latest iOS), or a HomePod. So if you are an Apple user, you're half-way there. If not, you can begin to see how it's probably going to be much less expensive to import a Hue Outdoor motion sensor. :wink:

Well well...
Does anyone have tried this device ?

Smart Home Motion Sensor Human Body Sensor ZigBee 3.0 Wireless Connection Light Intensity Motion Sensor switch for xiaomi
https://a.aliexpress.com/pqV6kUkg

Does it also measure light only when motion is detected ?

No way I'm going to buy all this Apple stuff to simply turn my front yard lights on, it doesn't make sense to me.

Actually if I can't find a way to automate this function with hubitat and a zigbee device, I'll leave it as it is using this kind of relay :

Automatic Light Sensor Photo Control Switch Mayitr Relay Photoswitch 180-240V for Outdoor Street Llighting Lamp LED Lights
https://a.aliexpress.com/nYx3IDaC

It's not ideal and not what I want, but at least it works and I don't need to sell a kidney to buy it.
Anyway I appreciate your help.

1 Like

This thread is about that Konke device:

There's no mention of luminescence. The other thing I'll say is this - the Konke devices only work on zigbee channels 15, 20 and 25.

2 Likes

Thanks a lot @aaiyar. :+1:

Good idea. Not everything needs to be “smart” :wink:

The goal should be automation and convenience, no matter what form it takes. Unless you gain something from the endeavor of making it hub controlled, then it just ends up being expensive for no particular reason.

I’d go with Hue Outdoor over Xiaomi any day.
Although the cost is higher they’ll be easier to get working and will STAY working.

That is a brand new product, just introduced to the Chinese mainland market last November. As mentioned, it requires a Xiaomi Mijia Multimode Gateway (hub).

From my reading, nobody has gotten it working with a non-Xiaomi hub yet, but DeConz users and Koenkk zigbee2mqtt users are attempting to get it working with their respective HA solutions.

As for a Hubitat driver, I would probably be the person to make one - if it even works with the Hubitat hub. As inexpensive as they are, I haven't bought one of these yet because I'd like to see if the light sensor can be gotten to work with the two above-mentioned HA solutions.

If anyone has ordered a few and wants to ship one to me, I will gladly take a crack at it, though!

TL;DR:

There is no Hubitat driver for the Xiaomi Mijia Smart Light Sensor (Zigbee 3.0) and it will probably be a while before any driver is available - if the device works with the Hubitat hub at all (which is unknown at this time.)

1 Like

Thanks for replying.
I'd be happy to send you this device, but I can't find it on Amazon. Give me your address so I can ship it to you through AliExpress.

Thanks for the offer!

Actually after reading some more information about them, I just decided to order two Xiaomi Light Sensors via AliExpress.

With Chinese New year just the past weekend, though, I expect it will take a while for them to be delivered.

I will work on a Hubitat driver once I've received them.

Great. I'm looking forward for that.
Thanks

I have some of these, bought on a whim. I did have it working with ST, but so far I've not got them working with HE yet - but I'm only just switching over to HE so yet to work out what all the differences are in terms of device handlers etc.

The raw numbers reported back are somewhat on the high side from what I saw under ST.

1 Like

Okay. I have this working. But it's a bit of a hacked together driver at the moment. I need to tidy it up then I'll post it.

1 Like

Great !!! Looking forward.

Hi, I've got one of the xiaomi illuminance sensor. Any advice about existing drivers (if any) to let it work?

Hi @karl2, I wouldn't bother you, but have you any good news for us :wink:?

1 Like

Hi mate, did you get this driver working, just received my sensor today and really desperate to get it working. Happy to test for you if you want a guinea pig :slight_smile:

This is my first device driver.
I cannot get the illuminance value. The driver detects the button pushes, it receives and parses correctly the messages but never intercept the illuminance value.
Some more experienced DD/Groovy guy can take a look at the code?
Please do not expect much from it...

/**
 *  My Xiaomi Mijia Smart Light 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.
 */

// see: https://github.com/dresden-elektronik/deconz-rest-plugin/issues/2300
import hubitat.zigbee.zcl.DataType
import groovy.json.JsonSlurper

def getVersionNum() { return "0.0.0" }
private def getVersionLabel() { return "My Xiaomi Mijia Smart Light Sensor ${getVersionNum()}" }

metadata {
    definition (name: "My Xiaomi Mijia Smart Light Sensor", namespace: "r.brunialti", author: "r.brunialti") {
        capability "Illuminance Measurement"
        capability "Sensor"
        capability "Battery"
        
        attribute "batteryLastReplaced", "String"
		attribute "lastCheckin", "String"
		attribute "version", "String"
        
        //fingerprint profileId: "0104", inClusters: "0000,0400,0003,0001", outClusters: "0003", manufacturer: "LUMI", model: "lumi.sen_ill.mgl01", deviceJoinName: "Xiaomi Mijia Smart Home Light Sensor", ocfDeviceType: "oic.r.sensor.illuminance"      
        fingerprint profileId: "0104", inClusters: "0000,0400,0003,0001", outClusters: "0003", manufacturer: "LUMI", model: "lumi.sen_ill.mgl01", deviceJoinName: "Xiaomi Mijia Smart Home Light Sensor", ocfDeviceType: "oic.r.illuminance"      

        command "resetBatteryReplacedDate"
        command "configure"
    }
    preferences {
		input "luxOffset", "decimal", title: "Lux Value Offsetv", description: "", range: "*..*"
		//Battery Voltage Range
 		input name: "voltsmin", title: "Min Volts (0% battery = ___ volts, range 2.0 to 2.9). Default = 2.5 Volts", description: "", type: "decimal", range: "2..2.7"
 		input name: "voltsmax", title: "Max Volts (100% battery = ___ volts, range 2.8 to 3.5). Default = 3.0 Volts", description: "Default = 3.0 Volts", type: "decimal", range: "2.8..3.4"
 		//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: ""
	}
}

def parse(String description) {
    Map map = [:]
    def descMap = zigbee.parseDescriptionAsMap(description)
    displayDebugLog("A - Received message: ${description}")  
    displayDebugLog("B - Parsed message: ${descMap}")  

    // lastCheckin can be used with webCoRE
    sendEvent(name: "lastCheckin", value: now())    
    
    if (description?.startsWith('read attr - ')) {
		description = description - "read attr - "
        //def encoding = Integer.parseInt(description.split(",").find {it.split(":")[0].trim() == "encoding"}?.split(":")[1].trim(), 16)
    	def encoding = Integer.parseInt(descMap.encoding, 16)
        if (descMap.value != null & encoding > 0x18 & encoding < 0x3e) {
    		displayDebugLog("C1 - 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
    		descMap.value = reverseHexString(descMap.value)
            displayDebugLog("C2 - Reversed payload value: ${descMap.value}")
	    }
        // Send message data to appropriate     parsing function based on the type of report    
        if (descMap.cluster == "0400" & descMap.attrInt == 0)
    		// Parse illuminance value report
    		map = parseIlluminance(descMap.value)
    	else if (descMap.cluster == "0000" & descMap.attrInt == 5)
    		// Button short-pressed
            displayDebugLog("C3 - Reset button of [${descMap.value}] was short-pressed")
            // Button management: insert code here following
    	else if (descMap.cluster == "0001" & descMap.attrInt == 32)
    		// Parse battery level from hourly announcement message
	    	map = parseBattery(descMap.value)
	    else
            displayDebugLogelvalueHex.("C4 - Unknown cluster/attribute: cluster=${cluster}, attribute=${descMap.attrId}")
    } else if (description?.startsWith('cat')){ 
		displayDebugLog("C5 - Catchall message ignored")
    } else
		displayDebugLog("C6 - Unknown message type")
        
	if (map != [:]) {
		displayDebugLog("D - Creating event $map")
		return createEvent(map)   
    }
}

private parseIlluminance(description) {
	def offset = luxOffset ? luxOffset : 0
	def lux = Integer.parseInt(description,16) + offset
	return [
		name: 'illuminance',
		value: lux,
		unit: 'lux',
		isStateChange: true,
		descriptionText: "Illuminance is ${lux} lux"
	]
}

// Convert raw 4 digit integer voltage value -> percentage based on minVolts/maxVolts range
private parseBattery(description) {
	displayDebugLog("Battery parse string = ${description}")
	def MsgLength = description.size()
	def rawValue
	for (int i = 4; i < (MsgLength-3); i+=2) {
		if (description[i..(i+1)] == "21") { // Search for byte preceeding battery voltage bytes
			rawValue = Integer.parseInt((description[(i+4)..(i+5)] + description[(i+2)..(i+3)]),16)
			break
		}
	}
	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)"
	// 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())
	}
	displayInfoLog(descText)
	return [
		name: 'battery',
		value: roundedPct,
		unit: "%",
		descriptionText: descText
	]
}

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

//
def init() {
    if (!device.currentValue('batteryLastReplaced'))
		resetBatteryReplacedDate(true)
}
    
// configure() runs after installed() when a sensor is paired
    def configure() {
	displayInfoLog("Configuring")
    //Configure: empty stublatest/ref-doc/zigbee-ref.html 
    //zigbee.configureReporting(Integer Cluster, Integer attributeId, Integer dataType, Integer minReportTime, Integer MaxReportTime, [Integer reportableChange],    Map additionalParams=[:])
    //zigbee.readAttribute(Integer Cluster, Integer attributeId, Map additionalParams=[])
	init()
	sendEvent(name: "version", value:getVersionNum())
	state.prefsSetCount = 1
}

//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 Laast Replace date")
    }
    
// updated() will run every time user saves preferences
def updated() {
	displayInfoLog("Updating preference settings")
	init()
	displayInfoLog("Info message logging enabled")
	displayInfoLog("Debug message logging enabled")
}
    
//
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}"
}
2 Likes