This writes a value of 0x40 to the OnOffTransitionTime attribute of the Level cluster. I've similarly also tried writes to other attributes like OnLevel, and to the StartUpOnOff attribute 0x4003 of the On/Off cluster. I've also tried to Tapo WiFi dimmers, AiDot bulbs, and Nanoleaf devices with no luck - no matter what I try to write to, the attributes remain unchanged
I figure I'm doing something wrong with the write command. Does anybody have examples of a write command that they have tested and know works (and which devices did they work on), or know why my code isn't working?
Here's an example of the logged command produced by my example code. All looks OK
dev:522024-03-10 11:27:33.107 AMdebugWriting: [[ep:0x01, cluster:0x0008, attr:0x0010, data:050040]] using command string: he wattrs [{"ep":"0x01","cluster":"0x0008","attr":"0x0010","data":"050040"}]
Hmmm, is it an issue of privileges (Section 7.6 of Matter Core Spec.)?
Per the Matter Spec ...
StartUpOnOff attribute of the on/off cluster requires "VM" privilege (View and Manage)
OnLevel, OnTransitionTime, OffTransitionTime of the Level cluster all require View and Operate privileges
Actually, I have not made it work as well. Some months ago, I tried writeAttribute to Identify cluster without success. And I have left this issue 'for later' ...
Also, writing to a Matter Lock cluster attribute 0x0000 (LockState) failed in my attempts to control a lock.
The "LockState" issue you are having is a bit more straightforward (I think). LockState is a Read-Only Attribute. See Access column in Section 5.2.6 of the Matter Cluster Spec:
What you need to do is to send one of the Commands from Section 5.2.7 of the Matter Cluster Spec. to cause a Lock or Unlock to occur. That will then cause the lock to change the LockState attribute. In other words, if a Attribute is a "R" rather than "RW" only the device itself can change it (usually following some event or command).
The commands for Lock and Unlock should be formed very similar to "On" and "Off" in my cluster library for cluster 0x0006. I did some quick edits to those (untested) - but you could give these a try (they take an endpoint parameter named "ep:") - for example
The Matter connection to the Nuki lock is OK because I receive successfully the LockState attribute updates (locked/unlocked) when the lock is controlled locally or from other Matter controllers (Apple Home, for example).
I did a very simple driver that writes to the OnLevel attribute 0x0011 for Matter Cluster 0x0008 and then reads it back (with a Refresh). This is a mandatory RW cluster.
It looks like the write is sent properly, but when I read back, there is no change.
It should work on any dimmer / bulb and I've tested with Nanoleaf to no effect.
import hubitat.matter.DataType
import hubitat.helper.HexUtils
metadata {
definition (name: "Matter Simple Write Test Driver", namespace: "matterTools", author: "jvm33") {
capability "Refresh"
}
preferences {
input( name: "MatterOnLevel", type:"number", title:"Turn On Level (%)", description: "When turning on light, set to this level.", range:"1..100")
}
}
void parse(String description) {
log.debug matter.parseDescriptionAsMap(description)
}
void updated(){
log.info "${device.displayName}: Processing Preference changes..."
Integer MatterOnLevel = device.getSetting("MatterOnLevel") * 2.54
if (MatterOnLevel) {
String MatterOnLevelHex = HexUtils.integerToHexString(MatterOnLevel, 1)
List<Map<String, String>> attrWriteRequests = []
attrWriteRequests.add(matter.attributeWriteRequest(1, 0x0008, 0x0011, DataType.UINT8, MatterOnLevelHex))
String cmd = matter.writeAttributes(attrWriteRequests)
log.debug "Setting Matter onLevel to ${MatterOnLevel} using command : ${cmd}"
sendHubCommand(new hubitat.device.HubAction(cmd, hubitat.device.Protocol.MATTER))
}
}
void refresh() {
refreshMatter(ep:0x01, clusterInt: 0x0008, attrInt: 0x0011)
}
// Performs a refresh on a designated endpoint / cluster / attribute (all specified in Integer)
// Does a wildcard refresh if parameters are not specified (ep=FFFF / cluster=FFFFFFFF/ endpoint=FFFFFFFF is the Matter wildcard designation
void refreshMatter(Map params = [:]) {
try {
Map inputs = [ep:0xFFFF, clusterInt: 0xFFFFFFFF, attrInt: 0xFFFFFFFF] << params
assert inputs.ep instanceof Integer // Make sure the type is as expected!
assert inputs.clusterInt instanceof Integer || inputs.clusterInt instanceof Long
assert inputs.attrInt instanceof Integer || inputs.attrInt instanceof Long
// Groovy Slashy String form of a GString https://docs.groovy-lang.org/latest/html/documentation/#_slashy_string
String cmd = /he rattrs [{"ep":"${inputs.ep}","cluster":"${inputs.clusterInt}","attr":"${inputs.attrInt}"}]/
sendHubCommand(new hubitat.device.HubAction(cmd, hubitat.device.Protocol.MATTER))
} catch (AssertionError e) {
log.error "<pre>${e}<br><br>Stack trace:<br>${getStackTrace(e) }"
} catch(e){
log.error "<pre>${e}<br><br>when processing refreshMatter with inputs ${inputs}<br><br>Stack trace:<br>${getStackTrace(e) }"
}
}
No, currently I am not using any writeAttributes Matter commands in any of my drivers at this time.
I temporarily put my custom Matter driver developments on hold until there are some improvements in the Hubitat platform related to error processing.
HE invoking automatically the initialize() method on each and every error returned by the matter device makes the developments really difficult.