Frient Energy Monitor - Driver

I am new to Hubitat and in the process of migrating my entire automation to Hubitat from ST. I am using one Frient Energy monitor(Zigbee) and I have the ST device handler. I got the custom device handler from GitHub. Can somebody please help me to convert it for Hubitat?

If you can post a link to the driver (or post the code in a Summary block) I can take a first swipe at it.

1 Like

Thank you. Please see the below link.

This should be close:

https://raw.githubusercontent.com/thebearmay/hubitat/main/development/zbPowerMeter.groovy

5 Likes

Thanks for the help. I will try the same and update you.

1 Like

Wow.... That is some nice farking niceness right there. Another example of why I love this community....

5 Likes

I paired the frient energy monitor using the customer handler you provided to me. But it's not showing the power consumption.

Then I removed the same from HE and added it back to the ST hub and provided the following handler and it started working in ST.
Could you please help me with the handler? I am pasting the working ST handler here.

/**

  • Copyright 2019 SmartThings
  • 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.

*/
metadata {
definition (name: "Frient Zigbee Power Meter", namespace: "smartthings", author: "SmartThings", mnmn: "SmartThings", ocfDeviceType: "x.com.st.d.energymeter", vid: "SmartThings-smartthings-Aeon_Home_Energy_Meter") {
capability "Energy Meter"
capability "Power Meter"
capability "Refresh"
capability "Health Check"
capability "Sensor"
capability "Configuration"

    fingerprint profileId: "0104", deviceId:"0053", inClusters: "0000, 0003, 0004, 0B04, 0702", outClusters: "0019", manufacturer: "", model: "E240-KR080Z0-HA", deviceJoinName: "Energy Monitor" //Smart Sub-meter(CT Type)
    fingerprint profileId: "0104", deviceId:"0007", inClusters: "0000,0003,0702", outClusters: "000A", manufacturer: "Develco", model: "ZHEMI101", deviceJoinName: "frient Energy Monitor" // frient External Meter Interface (develco) 02 0104 0007 00 03 0000 0003 0702 01 000A
    fingerprint profileId: "0104", manufacturer: "Develco Products A/S", model: "EMIZB-132", deviceJoinName: "frient Energy Monitor" // frient Norwegian HAN (develco) 02 0104 0053 00 06 0000 0003 0020 0702 0704 0B04 03 0003 000A 0019
}

// tile definitions
tiles(scale: 2) {
    multiAttributeTile(name:"power", type: "generic", width: 6, height: 4){
        tileAttribute("device.power", key: "PRIMARY_CONTROL") {
            attributeState("default", label:'${currentValue} W')
        }
        tileAttribute("device.energy", key: "SECONDARY_CONTROL") {
            attributeState("default", label:'${currentValue} kWh')
        }
    }
    standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
        state "default", label:'reset kWh', action:"reset"
    }
    standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
        state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
    }

    main (["power", "energy"])
    details(["power", "energy", "reset", "refresh"])
}

}

def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
log.info event
if (event.name == "power") {
def descMap = zigbee.parseDescriptionAsMap(description)
log.debug "event : Desc Map: $descMap"
if (descMap.clusterInt == 0x0B04 && descMap.attrInt == 0x050b) {
event.value = event.value/activePowerDivisor
event.unit = "W"
} else {
event.value = event.value/powerDivisor
event.unit = "W"
}
} else if (event.name == "energy") {
event.value = event.value/(energyDivisor * 1000)
event.unit = "kWh"
}
log.info "event outer:$event"
sendEvent(event)
} else {
List result = []
def descMap = zigbee.parseDescriptionAsMap(description)
log.debug "Desc Map: $descMap"

    List attrData = [[clusterInt: descMap.clusterInt ,attrInt: descMap.attrInt, value: descMap.value, isValidForDataType: descMap.isValidForDataType]]
    descMap.additionalAttrs.each {
        attrData << [clusterInt: descMap.clusterInt, attrInt: it.attrInt, value: it.value, isValidForDataType: it.isValidForDataType]
    }
    attrData.each {
            def map = [:]
            if (it.isValidForDataType && (it.value != null)) {
                if (it.clusterInt == 0x0702 && it.attrInt == 0x0400) {
                    log.debug "meter"
                    map.name = "power"
                    map.value = zigbee.convertHexToInt(it.value)/powerDivisor
                    map.unit = "W"
                }
                if (it.clusterInt == 0x0B04 && it.attrInt == 0x050b) {
                    log.debug "meter"
                    map.name = "power"
                    map.value = zigbee.convertHexToInt(it.value)/activePowerDivisor
                    map.unit = "W"
                }
                if (it.clusterInt == 0x0702 && it.attrInt == 0x0000) {
                    log.debug "energy"
                    map.name = "energy"
                    map.value = zigbee.convertHexToInt(it.value)/(energyDivisor * 1000)
                    map.unit = "kWh"
                }
            }
            
            if (map) {
                    result << createEvent(map)
            }
            log.debug "Parse returned $map"
    }
    return result      
}

}

/**

  • PING is used by Device-Watch in attempt to reach the Device
  • */
    def ping() {
    return refresh()
    }

def refresh() {
log.debug "refresh "
zigbee.electricMeasurementPowerRefresh() +
zigbee.simpleMeteringPowerRefresh()
}

def configure() {
// this device will send instantaneous demand and current summation delivered every 1 minute
sendEvent(name: "checkInterval", value: 2 * 60 + 10 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])

log.debug "Configuring Reporting"
return refresh() +
       zigbee.simpleMeteringPowerConfig() +
       zigbee.electricMeasurementPowerConfig()

}

private getActivePowerDivisor() { 10 }
private getPowerDivisor() { isFrientSensor() ? 1 : 450 }
private getEnergyDivisor() { isFrientSensor() ? 1 : 450 }

private Boolean isFrientSensor() {
device.getDataValue("manufacturer") == "Develco Products A/S" ||
device.getDataValue("manufacturer") == "Develco"
}

Looks like the code should work, but I do see a possibility of the attribute powerConsumption not being retained. Made a small revision to the code at:

https://raw.githubusercontent.com/thebearmay/hubitat/main/development/zbPowerMeter.groovy

2 Likes

Thanks for your effort. I tried the above one but not working. One more input, Looks like there is some changes/modification in the Original ST device handler in the Github and that's why I pasted my working ST handler in my previous post. Please see the below log output.

2022-04-15 06:31:06.690 pm debugParse returned [:]

dev:3262022-04-15 06:31:06.687 pm debugDesc Map: [raw:catchall: 0000 0013 00 00 0040 00 59A6 00 00 0000 00 00 67A659271C021B00BC150000, profileId:0000, clusterId:0013, clusterInt:19, sourceEndpoint:00, destinationEndpoint:00, options:0040, messageType:00, dni:59A6, isClusterSpecific:false, isManufacturerSpecific:false, manufacturerId:0000, command:00, direction:00, data:[67, A6, 59, 27, 1C, 02, 1B, 00, BC, 15, 00, 00]]

Removed the ST specific from the code you posted, and it compiles:

Frient Energy Monitor (ST Port)
/**

Copyright 2019 SmartThings
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.
*/
metadata {
definition (name: "Frient Zigbee Power Meter", namespace: "smartthings", author: "SmartThings", mnmn: "SmartThings", ocfDeviceType: "x.com.st.d.energymeter", vid: "SmartThings-smartthings-Aeon_Home_Energy_Meter") {
capability "Energy Meter"
capability "Power Meter"
capability "Refresh"
capability "Health Check"
capability "Sensor"
capability "Configuration"

    fingerprint profileId: "0104", deviceId:"0053", inClusters: "0000, 0003, 0004, 0B04, 0702", outClusters: "0019", manufacturer: "", model: "E240-KR080Z0-HA", deviceJoinName: "Energy Monitor" //Smart Sub-meter(CT Type)
    fingerprint profileId: "0104", deviceId:"0007", inClusters: "0000,0003,0702", outClusters: "000A", manufacturer: "Develco", model: "ZHEMI101", deviceJoinName: "frient Energy Monitor" // frient External Meter Interface (develco) 02 0104 0007 00 03 0000 0003 0702 01 000A
    fingerprint profileId: "0104", manufacturer: "Develco Products A/S", model: "EMIZB-132", deviceJoinName: "frient Energy Monitor" // frient Norwegian HAN (develco) 02 0104 0053 00 06 0000 0003 0020 0702 0704 0B04 03 0003 000A 0019
}

}

def parse(String description) {
    log.debug "description is $description"
    def event = zigbee.getEvent(description)
    if (event) {
        log.info event
        if (event.name == "power") {
            def descMap = zigbee.parseDescriptionAsMap(description)
            log.debug "event : Desc Map: $descMap"
            if (descMap.clusterInt == 0x0B04 && descMap.attrInt == 0x050b) {
                event.value = event.value/activePowerDivisor
                event.unit = "W"
            } else {
                event.value = event.value/powerDivisor
                event.unit = "W"
            }
        } else if (event.name == "energy") {
            event.value = event.value/(energyDivisor * 1000)
            event.unit = "kWh"
        }
        log.info "event outer:$event"
        sendEvent(event)
    } else {
        List result = []
        def descMap = zigbee.parseDescriptionAsMap(description)
        log.debug "Desc Map: $descMap"

    List attrData = [[clusterInt: descMap.clusterInt ,attrInt: descMap.attrInt, value: descMap.value, isValidForDataType: descMap.isValidForDataType]]
    descMap.additionalAttrs.each {
        attrData << [clusterInt: descMap.clusterInt, attrInt: it.attrInt, value: it.value, isValidForDataType: it.isValidForDataType]
    }
    attrData.each {
            def map = [:]
            if (it.isValidForDataType && (it.value != null)) {
                if (it.clusterInt == 0x0702 && it.attrInt == 0x0400) {
                    log.debug "meter"
                    map.name = "power"
                    map.value = zigbee.convertHexToInt(it.value)/powerDivisor
                    map.unit = "W"
                }
                if (it.clusterInt == 0x0B04 && it.attrInt == 0x050b) {
                    log.debug "meter"
                    map.name = "power"
                    map.value = zigbee.convertHexToInt(it.value)/activePowerDivisor
                    map.unit = "W"
                }
                if (it.clusterInt == 0x0702 && it.attrInt == 0x0000) {
                    log.debug "energy"
                    map.name = "energy"
                    map.value = zigbee.convertHexToInt(it.value)/(energyDivisor * 1000)
                    map.unit = "kWh"
                }
            }
            
            if (map) {
                    result << createEvent(map)
            }
            log.debug "Parse returned $map"
    }
    return result      
}
}

/**

PING is used by Device-Watch in attempt to reach the Device
*/
def ping() {
return refresh()
}
def refresh() {
log.debug "refresh "
zigbee.electricMeasurementPowerRefresh() +
zigbee.simpleMeteringPowerRefresh()
}

def configure() {
// this device will send instantaneous demand and current summation delivered every 1 minute
sendEvent(name: "checkInterval", value: 2 * 60 + 10 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])

log.debug "Configuring Reporting"
return refresh() +
       zigbee.simpleMeteringPowerConfig() +
       zigbee.electricMeasurementPowerConfig()
}

private getActivePowerDivisor() { 10 }
private getPowerDivisor() { isFrientSensor() ? 1 : 450 }
private getEnergyDivisor() { isFrientSensor() ? 1 : 450 }

private Boolean isFrientSensor() {
device.getDataValue("manufacturer") == "Develco Products A/S" ||
device.getDataValue("manufacturer") == "Develco"
}
1 Like

Thanks for your response. I tried the same. But not showing the power reading. The console device property shows only "check interval". please see the below log output and screen shot.

2022-04-16 01:45:13.283 pm errorgroovy.lang.MissingMethodException: No signature of method: com.hubitat.zigbee.Zigbee.simpleMeteringPowerRefresh() is applicable for argument types: () values: [] on line 99 (method refresh)

dev:3852022-04-16 01:45:13.252 pm debugrefresh

dev:3852022-04-16 01:45:07.438 pm errorgroovy.lang.MissingMethodException: No signature of method: com.hubitat.zigbee.Zigbee.simpleMeteringPowerRefresh() is applicable for argument types: () values: [] on line 99 (method ping)

dev:3852022-04-16 01:45:07.405 pm debugrefresh

dev:3852022-04-16 01:44:59.148 pm errorgroovy.lang.MissingMethodException: No signature of method: com.hubitat.zigbee.Zigbee.simpleMeteringPowerRefresh() is applicable for argument types: () values: [] on line 99 (method configure)

dev:3852022-04-16 01:44:59.114 pm debugrefresh

dev:3852022-04-16 01:44:59.113 pm debugConfiguring Reporting

dev:3852022-04-16 01:44:56.919 pm errorgroovy.lang.MissingMethodException: No signature of method: com.hubitat.zigbee.Zigbee.simpleMeteringPowerRefresh() is applicable for argument types: () values: [] on line 99 (method refresh)

dev:3852022-04-16 01:44:56.884 pm debugrefresh

dev:3852022-04-16 01:42:26.357 pm errorgroovy.lang.MissingMethodException: No signature of method: com.hubitat.zigbee.Zigbee.simpleMeteringPowerRefresh() is applicable for argument types: () values: [] on line 99 (method refresh)

dev:3852022-04-16 01:42:26.324 pm debugrefresh

dev:3852022-04-16 01:41:12.167 pm debugParse returned [:]

dev:3852022-04-16 01:41:12.164 pm debugDesc Map: [raw:catchall: 0000 0013 00 00 0040 00 7839 00 00 0000 00 00 383978271C021B00BC150000, profileId:0000, clusterId:0013, clusterInt:19, sourceEndpoint:00, destinationEndpoint:00, options:0040, messageType:00, dni:7839, isClusterSpecific:false, isManufacturerSpecific:false, manufacturerId:0000, command:00, direction:00, data:[38, 39, 78, 27, 1C, 02, 1B, 00, BC, 15, 00, 00]]

Don’t know how to fix that one, should be part of the zigbee library I’d think. @mike.maxwell

We dont have a simpleMeteringPowerRefresh method. Have you tried the generic zigbee outlet driver with this device?

1 Like

Just now I tried with generic zigbee outlet driver and just flashed an LED on the meter probe, the first time it showed some value for power(42W) and after that, it's not responding. Please see the log file.

Do I need to try some other zigbee driver?

2022-04-16 03:40:03.769 pm debugdescMap:[raw:catchall: 0000 0013 00 00 0040 00 96DF 00 00 0000 00 00 7DDF96271C021B00BC150000, profileId:0000, clusterId:0013, clusterInt:19, sourceEndpoint:00, destinationEndpoint:00, options:0040, messageType:00, dni:96DF, isClusterSpecific:false, isManufacturerSpecific:false, manufacturerId:0000, command:00, direction:00, data:[7D, DF, 96, 27, 1C, 02, 1B, 00, BC, 15, 00, 00]]

dev:4372022-04-16 03:40:02.452 pm infoskipped- attribute:0000, value:00000000001F, status:null

dev:4372022-04-16 03:40:02.448 pm infoskipped- attribute:0102, value:FFFFFFFFFFFF, status:null

dev:4372022-04-16 03:40:02.443 pm infoskipped- attribute:0100, value:FFFFFFFFFFFF, status:null

dev:4372022-04-16 03:40:02.440 pm infoskipped- attribute:0200, value:00, status:null

dev:4372022-04-16 03:40:02.437 pm debugdescMap:[raw:96DF0207023E0000251F000000000000021800000125FFFFFFFFFFFF020125FFFFFFFFFFFF, dni:96DF, endpoint:02, cluster:0702, size:3E, attrId:0000, encoding:25, command:0A, value:00000000001F, clusterInt:1794, attrInt:0, additionalAttrs:[[value:00, encoding:18, attrId:0200, consumedBytes:4, attrInt:512], [value:FFFFFFFFFFFF, encoding:25, attrId:0100, consumedBytes:9, attrInt:256], [value:FFFFFFFFFFFF, encoding:25, attrId:0102, consumedBytes:9, attrInt:258]]]

dev:4372022-04-16 03:40:00.769 pm debugdescMap:[raw:catchall: 0000 0013 00 00 0040 00 96DF 00 00 0000 00 00 7CDF96271C021B00BC150000, profileId:0000, clusterId:0013, clusterInt:19, sourceEndpoint:00, destinationEndpoint:00, options:0040, messageType:00, dni:96DF, isClusterSpecific:false, isManufacturerSpecific:false, manufacturerId:0000, command:00, direction:00, data:[7C, DF, 96, 27, 1C, 02, 1B, 00, BC, 15, 00, 00]]

Just one more input, I just added this device freshly and provided the generic zigbee outlet and enabled the automatic power reporting option. Now it started reporting the power. please see the below screenshot.

image

I have to connect it to the electricity meter and check it.

I am getting the below log file output.

dev:4372022-04-16 04:11:20.042 pm infoskipped- attribute:0000, value:0000000003A6, status:null

dev:4372022-04-16 04:11:20.040 pm infoskipped- attribute:0102, value:FFFFFFFFFFFF, status:null

dev:4372022-04-16 04:11:20.037 pm infoskipped- attribute:0100, value:FFFFFFFFFFFF, status:null

dev:4372022-04-16 04:11:20.034 pm infoskipped- attribute:0200, value:00, status:null

dev:4372022-04-16 04:11:20.031 pm infoHome Energy Meter power is 37W

dev:4372022-04-16 04:11:20.028 pm debugdescMap:[raw:96DF0207024A000025A6030000000000042A7B010000021800000125FFFFFFFFFFFF020125FFFFFFFFFFFF, dni:96DF, endpoint:02, cluster:0702, size:4A, attrId:0000, encoding:25, command:0A, value:0000000003A6, clusterInt:1794, attrInt:0, additionalAttrs:[[value:00017B, encoding:2A, attrId:0400, consumedBytes:6, attrInt:1024], [value:00, encoding:18, attrId:0200, consumedBytes:4, attrInt:512], [value:FFFFFFFFFFFF, encoding:25, attrId:0100, consumedBytes:9, attrInt:256], [value:FFFFFFFFFFFF, encoding:25, attrId:0102, consumedBytes:9, attrInt:258]]]

Connected it in Electricity meter but the reading is not accurate and it's very less. Should I try some other Zigbee outlet driver?
Do you have some suggestions? @mike.maxwell

Have you looked at iotawatt instead? It my be less of an issue and it can not only monitor whole house but individual circuits and works on uk electric. It's a bit more but direct integration. If you can return that the iotawatt may be your solution (better than pulling out your hair)

Thanks for your suggestion. The Frient energy monitor I purchased around 7 months back and I will wait for some more time and if I am not getting this driver, I will think about this iotawatt.

It's fantastic. I use it to monitor whole house energy but I also use it for triggers. So I have a clamp on my washer circuit and one on my dryer circuit. I can use it to set notifications. (wash/dryer done) I also watch my water heaters and hvac..

So was there any progress on this in the last 6 months?

This device is pretty neat and the price is very reasonable. As far as accuracy is concerned it should be spot on with the billing as it is just displaying what the wall meter actually measures, not a V x A calc that current clamp meters do - note this isn't 100% accurate as our instantaneous voltage (in Aus anyway) does fluctuate and of course the CT taps can't allow for the exact power factor in each individual home)

However, if anyone has this, it does work in zigbee2mqtt so all is not lost! :grinning:

1 Like