Securifi Peanut Plug Power Meter

driver

#1

Just wondering if anyone ever managed to hack together a working driver to expose the power meter capability of these plugs.


#2

The Generic Zigbee Outlet driver displays power. Mine shows power: 0 because I don’t have anything plugged in. It’s a repeater only for me .

EDIT: I went and plugged an iron into it which should be enough for it to detect power but it hasn’t so far, been about 12 minutes. Event logs show power equal to zero, implying the device sends that.

Edit2: After waiting til the iron self turned off, (25 min) there was no Power report from the Peanut Plug.


#3

The peanut plugs required a firmware update to report power, even on ST. And you can only update the firmware using an Almond router. Sorry.


#4

Thanks for testing that and discovering what I was afraid of as well. I saw Ryan's comment as well. Maybe I'll pickup a used Almond router just for the heck of it sometime.
Thanks Guys!!


#5

Thanks for the info!!


#6

Don't bother picking up an almond. I have the latest firmware and it worked great with a custom DTH on ST with power and energy reporting. It doesn't really work with HE generic zigbee driver. The power reporting is all over the place.


#7

Yeahhh...I started messing with that driver in an attempt to port it to HE, but I don't think a few of the power reporting capabilities are in place yet in the com.hubitat.zigbee.DataType.
I was using this as the base:


#8

Ha, I don't recall how I found it, nor does power reporting work(have latest firmware
Here's the driver from same guy, can't find the link for the life of me.
Hope it helps you

metadata {
definition (name: "Peanut Plug", namespace: "pakmanwg", author: "pakmanw@sbcglobal.net", ocfDeviceType: "oic.d.switch",
vid: "generic-switch-power-energy") {
capability "Energy Meter"
capability "Actuator"
capability "Switch"
capability "Power Meter"
capability "Polling"
capability "Refresh"
capability "Configuration"
capability "Sensor"
capability "Light"
capability "Health Check"
capability "Voltage Measurement"

	attribute "current","number"

	command "reset"
   
	fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0B04, 0B05",
		outClusters: "0000, 0001, 0003, 0004, 0005, 0006, 0019, 0B04, 0B05"
}

// tile definitions
tiles {
	standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
		state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
		state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
	valueTile("power", "device.power") {
		state "default", label:'${currentValue} W'
	}
	valueTile("energy", "device.energy") {
		state "default", label:'${currentValue} kWh'
	}
	valueTile("voltage", "device.voltage") {
		state "default", label:'${currentValue} V'
	}
	valueTile("current", "device.current") {
		state "default", label:'${currentValue} A'
	}
	standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat") {
		state "default", label:'reset kWh', action:"reset"
	}
	standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
		state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
	}

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

}

def parse(String description) {

log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
	if (event.name == "power") {
		def powerValue
		powerValue = (event.value as Integer) * getPowerMultiplier()
		sendEvent(name: "power", value: powerValue)
		def time = (now() - state.time) / 3600000 / 1000
		state.time = now()
		log.debug "powerValues is $state.powerValue"
		state.energyValue = state.energyValue + (time * state.powerValue)
		state.powerValue = powerValue
		// log.debug "energyValue is $state.energyValue"
		sendEvent(name: "energy", value: state.energyValue)
	} else {
		sendEvent(event)
	}
} else if (description?.startsWith("read attr -")) {
	def descMap = zigbee.parseDescriptionAsMap(description)
    log.debug "Desc Map: $descMap"
    if (descMap.clusterInt == zigbee.ELECTRICAL_MEASUREMENT_CLUSTER) {
    	def intVal = Integer.parseInt(descMap.value,16)
    	if (descMap.attrInt == 0x0600) {
        	log.debug "ACVoltageMultiplier $intVal"
            state.voltageMultiplier = intVal
        } else if (descMap.attrInt == 0x0601) {
        	log.debug "ACVoltageDivisor $intVal"
            state.voltageDivisor = intVal
        } else if (descMap.attrInt == 0x0602) {
        	log.debug "ACCurrentMultiplier $intVal"
            state.currentMultiplier = intVal
        } else if (descMap.attrInt == 0x0603) {
        	log.debug "ACCurrentDivisor $intVal"
            state.currentDivisor = intVal
        } else if (descMap.attrInt == 0x0604) {
        	log.debug "ACPowerMultiplier $intVal"
            state.powerMultiplier = intVal
        } else if (descMap.attrInt == 0x0605) {
        	log.debug "ACPowerDivisor $intVal"
            state.powerDivisor = intVal
        } else if (descMap.attrInt == 0x0505) {
            def voltageValue = intVal * getVoltageMultiplier()
            log.debug "Voltage ${voltageValue}"
            state.voltage = $voltageValue
            sendEvent(name: "voltage", value: voltageValue)
        } else if (descMap.attrInt == 0x0508) {
            def currentValue = intVal * getCurrentMultiplier()
            log.debug "Current ${currentValue}"
            state.current = $currentValue
            sendEvent(name: "current", value: currentValue)
        }
    } else {
    	log.warn "Not an electrical measurement"
    }
} else {
	log.warn "DID NOT PARSE MESSAGE for description : $description"
	log.debug zigbee.parseDescriptionAsMap(description)
}

}

def installed() {
reset()
configure()
refresh()
}

def off() {
zigbee.off()
}

def on() {
zigbee.on()
}

def refresh() {
Integer reportIntervalMinutes = 5
zigbee.onOffRefresh() +
zigbee.simpleMeteringPowerRefresh() +
zigbee.electricMeasurementPowerRefresh() +
zigbee.onOffConfig(0, reportIntervalMinutes * 60) +
zigbee.simpleMeteringPowerConfig() +
zigbee.electricMeasurementPowerConfig() +
voltageMeasurementRefresh() +
voltageMeasurementConfig() +
currentMeasurementRefresh() +
currentMeasurementConfig() +
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0600) +
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0601) +
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0602) +
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0603) +
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0604) +
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0605)
}

def currentMeasurementConfig(minReportTime=1, maxReportTime=600, reportableChange=0x0030) {
zigbee.configureReporting(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0508, DataType.UINT16, minReportTime, maxReportTime, reportableChange)
}

def currentMeasurementRefresh() {
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0508);
}

def voltageMeasurementConfig(minReportTime=1, maxReportTime=600, reportableChange=0x0018) {
zigbee.configureReporting(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0505, DataType.UINT16, minReportTime, maxReportTime, reportableChange)
}

def voltageMeasurementRefresh() {
zigbee.readAttribute(zigbee.ELECTRICAL_MEASUREMENT_CLUSTER, 0x0505);
}

def getCurrentMultiplier() {
if (state.currentMultiplier && state.currentDivisor) {
return (state.currentMultiplier / state.currentDivisor)
} else {
return 0.001831
}
}

def getVoltageMultiplier() {
if (state.voltageMultiplier && state.voltageDivisor) {
return (state.voltageMultiplier / state.voltageDivisor)
} else {
return 0.0045777
}
}

def getPowerMultiplier() {
if (state.powerMultiplier && state.powerDivisor) {
return (state.powerMultiplier / state.powerDivisor)
} else {
return 0.277
}
}

def configure() {
log.debug "in configure()"
return configureHealthCheck()
}

def configureHealthCheck() {
Integer hcIntervalMinutes = 12
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
return refresh()
}

def updated() {
log.debug "in updated()"
// updated() doesn't have it's return value processed as hub commands, so we have to send them explicitly
def cmds = configureHealthCheck()
cmds.each{ sendHubCommand(new hubitat.device.HubAction(it)) }
}

def ping() {
return zigbee.onOffRefresh()
}

def reset() {
state.energyValue = 0.0
state.powerValue = 0.0
state.voltage = 0.0
state.current = 0.0
state.time = now()
sendEvent(name: "energy", value: state.energyValue)
}


#9

Did it work?


#10

I don't have a Securifi Almond to update the Peanuts with so have paused my effort on this. If I ever come across a cheapo Almond I may try to make it work.


#11

I have a couple of Peanut Plugs and installed this driver. It works for on/off, but never seems to get any values for any of the power settings. I had a driver installed in my ST days and it was always sketchy as well. I'll keep my eye out for anything I see.


#12

My peanut plugs are up-to-date and with the above driver. It worked perfectly on ST but not on HE. I get this on HE in the log.

warnDID NOT PARSE MESSAGE for description : read attr - raw: 91AD010B040A0505215266, dni: 91AD, endpoint: 01, cluster: 0B04, size: 0A, attrId: 0505, encoding: 21, command: 0A, value: 5266


#13

I updated the penaut plugs using almond router/hub
using generic zigbee outlet driver, it is working so far, but the values are sometimes wrong, like 2588 watts when it's usually around 250. not sure if someone has another code that I could try


Securifi Products
#14

did u sort out your peanut problems?


#15

Sorry for the late response. Never got the power reading to work. I just use the plugs for ON/OFF and repeaters.