Smartthings Button Battery

The ikea buttons battery drain is a different story!

The ST button has a temperature sensor, so I suggested that if he wanted to try to implement the temperature reports setting.

The ikea buttons thing is for trying different edge drives

Hello

Yes I have multiple custom DTH, if one exist for the button to avoid temp sensor, Im willing to try!

Also, not to feel rude but Sakari, maybe you can make a different thread for your ikea button?

thanks!

Thanks @milandjurovic71 for posting these. :blush:

What comes to battery drain I only have one remote that does it. Others have been working ok. Styrbar is latest dimmer and interesting because it uses AAA batteries. Rechargable batteries are quite cheap and easy to change. Also Styrbar costs only 8€ here where I live.

:thinking:

I found a custom dth online, and change the check interval, don’t know if it will help or not

/*

  • Copyright 2016 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.
    */
    import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
    import physicalgraph.zigbee.zcl.DataType

metadata {
definition(name: “SmartSense Button Custom”, namespace: “smartthings”, author: “SmartThings”, runLocally: true, minHubCoreVersion: ‘000.022.0000’, executeCommandsLocally: false, mnmn: “SmartThings”, vid: “SmartThings-smartthings-SmartSense_Button”, ocfDeviceType: “x.com.st.d.remotecontroller”) {
capability “Configuration”
capability “Battery”
capability “Refresh”
capability “Temperature Measurement”
capability “Button”
capability “Holdable Button”
capability “Health Check”
capability “Sensor”

    fingerprint inClusters: "0000,0001,0003,0020,0402,0500", outClusters: "0019", manufacturer: "Samjin", model: "button", deviceJoinName: "Button"
}

simulator {
    status "button 1 pushed": "catchall: 0104 0500 01 01 0140 00 6C3F 00 00 0000 01 01 020000190100"
}

preferences {
    section {
        image(name: 'educationalcontent', multiple: true, images: [
                "http://cdn.device-gse.smartthings.com/Moisture/Moisture1.png",
                "http://cdn.device-gse.smartthings.com/Moisture/Moisture2.png",
                "http://cdn.device-gse.smartthings.com/Moisture/Moisture3.png"
        ])
    }
    section {
        input "tempOffset", "number", title: "Temperature offset", description: "Select how many degrees to adjust the temperature.", range: "-100..100", displayDuringSetup: false
    }
}

tiles(scale: 2) {
    multiAttributeTile(name: "button", type: "generic", width: 6, height: 4) {
        tileAttribute("device.button", key: "PRIMARY_CONTROL") {
            attributeState "pushed", label: "Pressed", icon:"st.Weather.weather14", backgroundColor:"#53a7c0"
            attributeState "double", label: "Pressed Twice", icon:"st.Weather.weather11", backgroundColor:"#53a7c0"
            attributeState "held", label: "Held", icon:"st.Weather.weather13", backgroundColor:"#53a7c0"
        }
    }
    valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
        state "temperature", label: '${currentValue}°',
                backgroundColors: [
                        [value: 31, color: "#153591"],
                        [value: 44, color: "#1e9cbb"],
                        [value: 59, color: "#90d2a7"],
                        [value: 74, color: "#44b621"],
                        [value: 84, color: "#f1d801"],
                        [value: 95, color: "#d04e00"],
                        [value: 96, color: "#bc2323"]
                ]
    }
    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"
    }

    main(["button", "temperature"])
    details(["button", "temperature", "battery", "refresh"])
}

}

def installed() {
sendEvent(name: “supportedButtonValues”, value: [“pushed”,“held”,“double”].encodeAsJSON(), displayed: false)
sendEvent(name: “numberOfButtons”, value: 1, displayed: false)
sendEvent(name: “button”, value: “pushed”, data: [buttonNumber: 1], displayed: false)
}

private List collectAttributes(Map descMap) {
List descMaps = new ArrayList()

descMaps.add(descMap)

if (descMap.additionalAttrs) {
    descMaps.addAll(descMap.additionalAttrs)
}

return  descMaps

}

def parse(String description) {
log.debug “description: $description”

// getEvent will handle temperature and humidity
Map map = zigbee.getEvent(description)
if (!map) {
    if (description?.startsWith('zone status')) {
        map = parseIasMessage(description)
    } else {
        Map descMap = zigbee.parseDescriptionAsMap(description)

        if (descMap?.clusterInt == zigbee.POWER_CONFIGURATION_CLUSTER && descMap.commandInt != 0x07 && descMap.value) {
            List<Map> descMaps = collectAttributes(descMap)

            if (device.getDataValue("manufacturer") == "Samjin") {
                def battMap = descMaps.find { it.attrInt == 0x0021 }

                if (battMap) {
                    map = getBatteryPercentageResult(Integer.parseInt(battMap.value, 16))
                }
            } else {
                def battMap = descMaps.find { it.attrInt == 0x0020 }

                if (battMap) {
                    map = getBatteryResult(Integer.parseInt(battMap.value, 16))
                }
            }
        } else if (descMap?.clusterInt == 0x0500 && descMap.attrInt == 0x0002) {
            def zs = new ZoneStatus(zigbee.convertToInt(descMap.value, 16))
            map = translateZoneStatus(zs)
        } else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) {
            if (descMap.data[0] == "00") {
                log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap"
                sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
            } else {
                log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
            }
        } else if (descMap?.clusterInt == zigbee.IAS_ZONE_CLUSTER && descMap.attrInt == zigbee.ATTRIBUTE_IAS_ZONE_STATUS && descMap?.value) {
            map = translateZoneStatus(new ZoneStatus(zigbee.convertToInt(descMap?.value)))
        }
    }
} else if (map.name == "temperature") {
    if (tempOffset) {
        map.value = new BigDecimal((map.value as float) + (tempOffset as float)).setScale(1, BigDecimal.ROUND_HALF_UP)
        map.unit = getTemperatureScale()
    }
    map.descriptionText = getTemperatureScale() == 'C' ? "${ device.displayName } was ${ map.value }°C" : "${ device.displayName } was ${ map.value }°F"
    map.translatable = true
}

log.debug "Parse returned $map"
def result = map ? createEvent(map) : [:]

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

}

private Map parseIasMessage(String description) {
ZoneStatus zs = zigbee.parseZoneStatus(description)

translateZoneStatus(zs)

}

private Map translateZoneStatus(ZoneStatus zs) {
if (zs.isAlarm1Set() && zs.isAlarm2Set()) {
return getButtonResult(‘held’)
} else if (zs.isAlarm1Set()) {
return getButtonResult(‘pushed’)
} else if (zs.isAlarm2Set()) {
return getButtonResult(‘double’)
} else { }
}

private Map getBatteryResult(rawValue) {
log.debug “Battery rawValue = ${rawValue}”
def linkText = getLinkText(device)

def result = [:]

def volts = rawValue / 10

if (!(rawValue == 0 || rawValue == 255)) {
    result.name = 'battery'
    result.translatable = true
    result.descriptionText = "${ device.displayName } battery was ${ value }%"
    if (device.getDataValue("manufacturer") == "SmartThings") {
        volts = rawValue // For the batteryMap to work the key needs to be an int
        def batteryMap = [28: 100, 27: 100, 26: 100, 25: 90, 24: 90, 23: 70,
                          22: 70, 21: 50, 20: 50, 19: 30, 18: 30, 17: 15, 16: 1, 15: 0]
        def minVolts = 15
        def maxVolts = 28

        if (volts < minVolts)
            volts = minVolts
        else if (volts > maxVolts)
            volts = maxVolts
        def pct = batteryMap[volts]
        result.value = pct
    } else {
        def minVolts = 2.1
        def maxVolts = 3.0
        def pct = (volts - minVolts) / (maxVolts - minVolts)
        def roundedPct = Math.round(pct * 100)
        if (roundedPct <= 0)
            roundedPct = 1
        result.value = Math.min(100, roundedPct)
    }

}

return result

}

private Map getBatteryPercentageResult(rawValue) {
log.debug “Battery Percentage rawValue = ${rawValue} → ${rawValue / 2}%”
def result = [:]

if (0 <= rawValue && rawValue <= 200) {
    result.name = 'battery'
    result.translatable = true
    result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
    result.value = Math.round(rawValue / 2)
}

return result

}

private Map getButtonResult(value) {
def descriptionText
if (value == “pushed”)
descriptionText = “${ device.displayName } was pushed”
else if (value == “held”)
descriptionText = “${ device.displayName } was held”
else
descriptionText = “${ device.displayName } was pushed twice”
return [
name : ‘button’,
value : value,
descriptionText: descriptionText,
translatable : true,
isStateChange : true,
data : [buttonNumber: 1]
]
}

/**

  • PING is used by Device-Watch in attempt to reach the Device
  • */
    def ping() {
    zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS)
    }

def refresh() {
log.debug “Refreshing Values”
def refreshCmds =

if (device.getDataValue("manufacturer") == "Samjin") {
    refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021)
} else {
    refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
}
refreshCmds += zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
    zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) +
    zigbee.enrollResponse()

return refreshCmds

}

def configure() {
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
// Sets up low battery threshold reporting
sendEvent(name: “DeviceWatch-Enroll”, displayed: false, value: [protocol: “zigbee”, hubHardwareId: device.hub.hardwareID, scheme: “TRACKED”, checkInterval: 2 * 60 * 60 + 1 * 60, lowBatteryThresholds: [15, 7, 3], offlinePingable: “1”].encodeAsJSON())

log.debug "Configuring Reporting"
def configCmds = []

// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
if (device.getDataValue("manufacturer") == "Samjin") {
    configCmds += zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0021, DataType.UINT8, 30, 21600, 0x10)
} else {
    configCmds += zigbee.batteryConfig()
}
configCmds += zigbee.temperatureConfig(30, 300)

return refresh() + configCmds + refresh() // send refresh cmds as part of config

}

Sorry, I just assumed you knew the procedure.
In my first answer is the link to a post that explains how to do it and has at the end the link to the button code and four other devices.

Click on this post to open the whole conversation and access the link of the dth code in github and intructions.

1 Like

Sorry missed the thread, with all those replies haha

thanks a lot, just installed the dth and set the new parameters

will see if it help :slight_smile:
thanks a lot

1 Like

@Sakari, @milandjurovic71,

At the moment in this beta phase I do not see anything in the documentation that they have implemented something for the button capability or I cannot find it.
We will have to wait!

@Mariano_Colmenarejo I think that @iquix made edge driver for IKEA shortcut button. Maybe he can recommend how can be done

I’ve uploaded source code of some of my drivers.

Bunch of Zigbee dimmer switches has been added to the channel. I haven’t have any luck pairing my Ikea dimmer, which is listed as one of the fingerprints. Have anyone else tried this yet?

I’ve had a go at making a styrbar driver here Ikea Styrbar Remote