Help needed: st.zigbee.cluster_base understanding

Hi smartthings community,
I’m new to smartthings and edge driver.

I’m currently playing arround with a thermostat sample that has some manufacturer specific commands and attributes. During my investigation I stumbled over “st.zigbee.cluster_base” class and its functions.

Unfortunately the developer documentation is not helpful at this moment.

what I found out is:
For writing to the manufacturer specific attributes, I can use the function st.zigbee.cluster_base.write_manufacturer_specific_attribute(device, cluster_id, attribute_id, mfg_code, data_type, value) which is working as exspected.

So I suppose ther are some more functions under st.zigbee.cluster_base that can handle my problem.

A search in your community forum leads me finally to the APIv0 Hub Release 41.X where I got a bit more details about these functions.

This is what I know about the command:

cluster: 0x0201
cmd: 0x40 "Setpoint Command"
The Setpoint command SHOULD send: setpointType (enum8) + HeatingSetpoint (16bit)
setpointType(s) are: [0,1,2] // the goal is to lower/raise the heating hysteresis like eco, normal, fast 
direction: client > server

Here are a few questions regarding to my issue:

build_cluster_specific_command(self, device, command_body, direction)
Is this function needed to tell a cluster that there is a manufacturer specific command?
If yes, how do I need to pass it?

build_manufacturer_specific_command(device, cluster_id, cmd_id, mfg_code, payload)
OR is this function needed to tell a cluster that there is a manufacturer specific command?
If yes, how do I need to pass it?

parse_cluster_specific_command(self, command, direction, buf)
Do I need the function to fire the command? If yes, how? What should be inserted to “buf”

If it is possible to solve this problem also with the capability thermostatMode, please tell me which of the modes are usefull for that.
Unfortunately I was not able to find some more descriptions about each of them. Free from the live I would say: energysaveheat, heat and emergencyheat sounds great.

I’m excited to hear from you guys.
Thank you in advance.

Regards ronie

Welcome to the SmartThings Community, @ronie_pilot!

Please, let me know if this info helps:

  • When you have manufacturer-specific commands and attributes, you need to check if they fit with a stock capability. If not, you need to create custom capabilities.
  • Also, taking this example as a reference, you need to make sure:
  • About the commands, I see build_manufacturer_specific_command only helps you to structure the Zigbee TX message adding the manufacturer code, so you still have to send it to the device.
    In the default libraries like lua_libs-api_v0\st\zigbee\defaults\switch_defaults.lua, it uses device:send_to_component() in case the device has more than one endpoint.

Do you mean how you can filter the available enums for thermostatMode? You can set the supportedThermostatModes attributes with the values you need:

device:emit_event( capabilities.thermostatMode.supportedThermostatModes({value = {'...', ...}}))

The capability values don’t do anything by themselves, they just provide a label to show in the ST app, they need to be “translated” for the device, that’s the purpose of the default libraries.
In this case, thermostatMode doesn’t have a default library, so, you can define the corresponding capability handlers and send the TX message you need.

Hi @nayelyz,

thank you for the support and sorry for my delayed answer.

I think I’m now more familiar with the capabilities. In the meantime, I managed to add a “Window Open State” capability and copied from the “lock” capability:

common.WINDOW_OPEN_DETECTION_ID = 0x4000
...
zigbee_handlers = {
      attr = {
        [Thermostat.ID] = {
          [common.WINDOW_OPEN_DETECTION_ID] = common.window_open_detection_handler
        }
      }
}
...

common.WINDOW_OPEN_DETECTION_MAP = {
    [0x00] = "quarantine", 
    [0x01] = "closed", 
    [0x02] = "hold", 
    [0x03] = "opened", 
    [0x04] = "opened_alarm", 
    [0x05] = "disabled"
}

function common.window_open_detection_handler(driver, device, value, zb_rx)
    local attr = capabilities.WindowOpenDetectionCap.windowOpenDetection
    device:emit_event_for_endpoint(zb_rx.address_header.src_endpoint.value, common.WINDOW_OPEN_DETECTION_MAP[value.value])
end

I need to do further tests, but it seems to work.

So for my issue above I’ll also need a custom capability. I will fill it with a list of states and a setCommand function for each of it.

But how can I send a specific command to a cluster which it does not know?

cluster: 0x0201
cmd: 0x40 "Setpoint Command"
The Setpoint command SHOULD send: setpointType (enum8) + HeatingSetpoint (16bit)
setpointType(s) are: [0,1,2] // the goal is to lower/raise the heating hysteresis like eco, normal, fast 
direction: client > server

I’m not sure if it is necessarry to work with such “core” functions like I did.
Is there a documentation/HowTo or a better way how to handle this?

Thank you.

Regards ronie_pilot

I forgot …

the capability that I’ve added is only visible via browser under my.smartthings.com
But the Smartthings App is not showing this capability …

You should check the presentation used by the device to see if the capability’s presentation was included correctly.

  1. Check the property of presentationId included in the device when you get the list.
  2. Get the ID and use it to query its configuration. For example, this is a query using Postman:

Have you checked how this command works? I believe there’s no info about that yet in the Edge reference, there’s tips on how to build a Zigbee command but if the function of build_manufacturer_specific_command helps you, you can save some lines.

Hey @nayelyz
this is what I get calling the presentationID:

{
    "mnmn": "SmartThingsCommunity",
    "vid": "2ae224e8-8a30-3fc6-9978-3e5764afeda0",
    "version": "0.0.1",
    "iconUrl": null,
    "dashboard": {
        "states": [
            {
                "label": "{{temperature.value}} {{temperature.unit}}",
                "alternatives": [
                    {
                        "key": "C",
                        "value": "°C",
                        "type": "active"
                    },
                    {
                        "key": "K",
                        "value": "°K",
                        "type": "active"
                    },
                    {
                        "key": "F",
                        "value": "°F",
                        "type": "active"
                    }
                ],
                "capability": "temperatureMeasurement",
                "version": 1,
                "component": "main",
                "composite": false,
                "group": "main"
            }
        ],
        "actions": [],
        "basicPlus": []
    },
    "detailView": [
        {
            "capability": "preparestream40760.windowOpenDetection",
            "version": 1,
            "label": "Window Open Detection",
            "displayType": "list",
            "list": {
                "state": {
                    "value": "windowOpenDetection.value",
                    "valueType": "string",
                    "alternatives": [
                        {
                            "key": "quarantine",
                            "value": "Quarantine",
                            "type": "inactive"
                        },
                        {
                            "key": "closed",
                            "value": "Closed",
                            "type": "inactive"
                        },
                        {
                            "key": "opened",
                            "value": "Opened",
                            "type": "active"
                        },
                        {
                            "key": "hold",
                            "value": "Opening or Closing ...",
                            "type": "active"
                        },
                        {
                            "key": "opened_alarm",
                            "value": "Attention! Window was opened from the outside.",
                            "type": "active"
                        }
                    ]
                }
            },
            "state": null,
            "component": "main"
        },
        {
            "capability": "preparestream40760.heatMode",
            "version": 1,
            "label": "Heat Mode",
            "displayType": "list",
            "list": {
                "state": {
                    "value": "setpointMode.value",
                    "valueType": "string",
                    "alternatives": [
                        {
                            "key": "fast",
                            "value": "Fast",
                            "type": "active"
                        },
                        {
                            "key": "normal",
                            "value": "Normal",
                            "type": "active"
                        },
                        {
                            "key": "eco",
                            "value": "Eco",
                            "type": "active"
                        }
                    ]
                }
            },
            "state": null,
            "component": "main"
        },
        {
            "capability": "thermostatHeatingSetpoint",
            "version": 1,
            "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.THERMOSTATHEATINGSETPOINT_DEFAULT",
            "displayType": "slider",
            "slider": {
                "range": [
                    5.0,
                    35.0
                ],
                "step": 0.5,
                "unit": "heatingSetpoint.unit",
                "command": "setHeatingSetpoint",
                "argumentType": "number",
                "value": "heatingSetpoint.value",
                "valueType": "number"
            },
            "state": null,
            "component": "main"
        },
        {
            "capability": "battery",
            "version": 1,
            "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.BATTERY_DEFAULT",
            "displayType": "slider",
            "slider": {
                "range": [
                    0.0,
                    100.0
                ],
                "step": null,
                "unit": "battery.unit",
                "value": "battery.value",
                "valueType": "integer"
            },
            "state": null,
            "component": "main"
        },
        {
            "capability": "temperatureMeasurement",
            "version": 1,
            "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.TEMPERATUREMEASUREMENT_DEFAULT",
            "displayType": "slider",
            "slider": {
                "range": [
                    -20.0,
                    50.0
                ],
                "step": null,
                "unit": "temperature.unit",
                "value": "temperature.value",
                "valueType": "number"
            },
            "state": null,
            "component": "main"
        },
        {
            "capability": "refresh",
            "version": 1,
            "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.REFRESH_DEFAULT",
            "displayType": "pushButton",
            "pushButton": {
                "command": "refresh"
            },
            "state": null,
            "component": "main"
        }
    ],
    "automation": {
        "conditions": [
            {
                "capability": "preparestream40760.windowOpenDetection",
                "version": 1,
                "label": "Window Open Detection",
                "displayType": "list",
                "list": {
                    "alternatives": [
                        {
                            "key": "quarantine",
                            "value": "Quarantine",
                            "type": "inactive"
                        },
                        {
                            "key": "closed",
                            "value": "Closed",
                            "type": "inactive"
                        },
                        {
                            "key": "opened",
                            "value": "Opened",
                            "type": "active"
                        },
                        {
                            "key": "hold",
                            "value": "Opening or Closing ...",
                            "type": "active"
                        },
                        {
                            "key": "opened_alarm",
                            "value": "Attention! Window was opened from the outside.",
                            "type": "active"
                        }
                    ],
                    "value": "windowOpenDetection.value",
                    "valueType": "string"
                },
                "exclusion": [],
                "component": "main"
            },
            {
                "capability": "preparestream40760.heatMode",
                "version": 1,
                "label": "Heat Mode",
                "displayType": "list",
                "list": {
                    "alternatives": [
                        {
                            "key": "fast",
                            "value": "Fast",
                            "type": "active"
                        },
                        {
                            "key": "normal",
                            "value": "Normal",
                            "type": "active"
                        },
                        {
                            "key": "eco",
                            "value": "Eco",
                            "type": "active"
                        }
                    ],
                    "value": "setpointMode.value",
                    "valueType": "string"
                },
                "exclusion": [],
                "component": "main"
            },
            {
                "capability": "thermostatHeatingSetpoint",
                "version": 1,
                "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.THERMOSTATHEATINGSETPOINT_DEFAULT",
                "displayType": "numberField",
                "numberField": {
                    "value": "heatingSetpoint.value",
                    "valueType": "number",
                    "unit": "heatingSetpoint.unit",
                    "range": [
                        5.0,
                        35.0
                    ]
                },
                "exclusion": [],
                "component": "main"
            },
            {
                "capability": "battery",
                "version": 1,
                "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.BATTERY_DEFAULT",
                "displayType": "numberField",
                "numberField": {
                    "value": "battery.value",
                    "valueType": "integer",
                    "unit": "battery.unit",
                    "range": [
                        0.0,
                        100.0
                    ]
                },
                "exclusion": [],
                "component": "main"
            },
            {
                "capability": "temperatureMeasurement",
                "version": 1,
                "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.TEMPERATUREMEASUREMENT_DEFAULT",
                "displayType": "numberField",
                "numberField": {
                    "value": "temperature.value",
                    "valueType": "number",
                    "unit": "temperature.unit",
                    "range": [
                        -20.0,
                        50.0
                    ]
                },
                "exclusion": [],
                "component": "main"
            }
        ],
        "actions": [
            {
                "capability": "thermostatHeatingSetpoint",
                "version": 1,
                "label": "___PO_CODE_CAPABILITY.SMARTTHINGS.THERMOSTATHEATINGSETPOINT_DEFAULT_COMMANDS_SETHEATINGSETPOINT",
                "displayType": "numberField",
                "numberField": {
                    "command": "setHeatingSetpoint",
                    "argumentType": "number",
                    "unit": "heatingSetpoint.unit",
                    "range": [
                        0.0,
                        40.0
                    ]
                },
                "component": "main",
                "exclusion": []
            },
            {
                "capability": "preparestream40760.heatMode",
                "version": 1,
                "label": "Heat Mode",
                "displayType": "list",
                "list": {
                    "alternatives": [
                        {
                            "key": "fast",
                            "value": "Fast",
                            "type": "active"
                        },
                        {
                            "key": "normal",
                            "value": "Normal",
                            "type": "active"
                        },
                        {
                            "key": "eco",
                            "value": "Eco",
                            "type": "active"
                        }
                    ]
                },
                "component": "main",
                "exclusion": []
            }
        ]
    },
    "dpInfo": [
        {
            "os": "ios",
            "dpUri": "plugin://com.samsung.ios.plugin.stplugin/assets/files/index.html"
        },
        {
            "os": "android",
            "dpUri": "plugin://com.samsung.android.plugin.stplugin"
        },
        {
            "os": "web",
            "dpUri": "wwst://com.samsung.one.plugin.stplugin"
        }
    ],
    "language": [
        {
            "locale": "en",
            "poCodes": [
                {
                    "label": "Heating temperature",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.THERMOSTATHEATINGSETPOINT_DEFAULT_ATTRIBUTES_HEATINGSETPOINT"
                },
                {
                    "label": "Heating temperature",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.THERMOSTATHEATINGSETPOINT_DEFAULT"
                },
                {
                    "label": "Heating temperature",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.THERMOSTATHEATINGSETPOINT_DEFAULT_COMMANDS_SETHEATINGSETPOINT"
                },
                {
                    "label": "Refresh",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.REFRESH_DEFAULT"
                },
                {
                    "label": "Refresh",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.REFRESH_DEFAULT_COMMANDS_REFRESH"
                },
                {
                    "label": "Temperature",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.TEMPERATUREMEASUREMENT_DEFAULT_ATTRIBUTES_TEMPERATURE"
                },
                {
                    "label": "Temperature",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.TEMPERATUREMEASUREMENT_DEFAULT"
                },
                {
                    "label": "Battery",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.BATTERY_DEFAULT_ATTRIBUTES_BATTERY"
                },
                {
                    "label": "Battery",
                    "po": "___PO_CODE_CAPABILITY.SMARTTHINGS.BATTERY_DEFAULT"
                },
                {
                    "label": "setpointMode",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.HEATMODE_DEFAULT_ATTRIBUTES_SETPOINTMODE"
                },
                {
                    "label": "fast",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.HEATMODE_DEFAULT_ATTRIBUTES_SETPOINTMODE_FAST"
                },
                {
                    "label": "Heat Mode",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.HEATMODE_DEFAULT"
                },
                {
                    "label": "eco",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.HEATMODE_DEFAULT_ATTRIBUTES_SETPOINTMODE_ECO"
                },
                {
                    "label": "normal",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.HEATMODE_DEFAULT_ATTRIBUTES_SETPOINTMODE_NORMAL"
                },
                {
                    "label": "quarantine",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.WINDOWOPENDETECTION_DEFAULT_ATTRIBUTES_WINDOWOPENDETECTION_QUARANTINE"
                },
                {
                    "label": "opened_alarm",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.WINDOWOPENDETECTION_DEFAULT_ATTRIBUTES_WINDOWOPENDETECTION_OPENED_ALARM"
                },
                {
                    "label": "closed",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.WINDOWOPENDETECTION_DEFAULT_ATTRIBUTES_WINDOWOPENDETECTION_CLOSED"
                },
                {
                    "label": "hold",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.WINDOWOPENDETECTION_DEFAULT_ATTRIBUTES_WINDOWOPENDETECTION_HOLD"
                },
                {
                    "label": "opened",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.WINDOWOPENDETECTION_DEFAULT_ATTRIBUTES_WINDOWOPENDETECTION_OPENED"
                },
                {
                    "label": "windowOpenDetection",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.WINDOWOPENDETECTION_DEFAULT_ATTRIBUTES_WINDOWOPENDETECTION"
                },
                {
                    "label": "Window Open Detection",
                    "po": "___PO_CODE_CAPABILITY.PREPARESTREAM40760.WINDOWOPENDETECTION_DEFAULT"
                }
            ]
        }
    ],
    "manufacturerName": "SmartThingsCommunity",
    "presentationId": "2ae224e8-8a30-3fc6-9978-3e5764afeda0"
}

This is what I got in the WebGUI:

and this is what I can see in the ST app on android (Samsung Galaxy S3):

I’ve already tried different things like adjusting device presentation to renew vid ID, restart ST app/ smartphone/ST hub several times, uninstall the driver etc … checking/removing/adding both custom caps again and again without no success …

Here are my custom caps:
window open detection cap:

{
  "name": "Window Open Detection",
  "attributes": {
    "windowOpenDetection": {
      "schema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "enum": [
              "quarantine",
              "closed",
              "hold",
              "opened",
              "opened_alarm"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "value"
        ]
      },
      "enumCommands": []
    }
  },
  "commands": {}
}

window open detection cap presentation:

{
    "dashboard": {
        "states": [],
        "actions": [],
        "basicPlus": []
    },
	"detailView": [
	  {
		"label": "Window Open Detection",
		"displayType": "list",
		"list": {
		  "state": {
			"value": "windowOpenDetection.value",
			"valueType": "string",
			"alternatives": [
			  {
				"key": "quarantine",
				"value": "Quarantine",
				"type": "inactive"
			  },
			  {
				"key": "closed",
				"value": "Closed",
				"type": "inactive"
			  },
			  {
				"key": "opened",
				"value": "Opened",
				"type": "active"
			  },
			  {
				"key": "hold",
				"value": "Opening or Closing ...",
				"type": "active"
			  },
			  {
				"key": "opened_alarm",
				"value": "Attention! Window was opened from the outside.",
				"type": "active"
			  }
			]
		  }
		}
	  }
	],
	"automation": {
		"conditions": [
		  {
			"label": "Window Open Detection",
			"displayType": "list",
			"list": {
				"alternatives": [
					{
						"key": "quarantine",
						"value": "Quarantine",
						"type": "inactive"
					},
					{
						"key": "closed",
						"value": "Closed",
						"type": "inactive"
					},
					{
						"key": "opened",
						"value": "Opened",
						"type": "active"
					},
					{
						"key": "hold",
						"value": "Opening or Closing ...",
						"type": "active"
					},
					{
						"key": "opened_alarm",
						"value": "Attention! Window was opened from the outside.",
						"type": "active"
					}
				],
				"value": "windowOpenDetection.value",
          		"valueType": "string"
			}
		}],
		"actions": []
	  },
    "id": "preparestream40760.windowOpenDetection",
    "version": 1
}

heat mode cap:

{
  "name": "Heat Mode",
  "attributes": {
    "setpointMode": {
      "schema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "enum": [
              "fast",
              "eco",
              "normal"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "value"
        ]
      },
      "enumCommands": [
        {
          "command": "fast",
          "value":"fast"
        },
        {
          "command": "normal",
          "value":"normal"
        },
        {
          "command": "eco",
          "value":"eco"
        }        
      ]
    }
  },
  "commands": {
    "fast": {
      "name": "fast",
      "arguments": []
    },
    "normal":{
      "name": "normal",
      "arguments": []
    },
    "eco":{
      "name": "eco",
      "arguments": []
    }
  }
}

heat mode cap presentation:

{
    "dashboard": {
        "states": [],
        "actions": [],
        "basicPlus": []
    },
    "detailView": [
    {
      "label": "Heat Mode",
      "displayType": "list",
      "list": {
        "state": {
          "alternatives": [
            {
              "key": "fast",
              "value": "Fast",
              "type": "active"
            },
            {
              "key": "normal",
              "value": "Normal",
              "type": "active"
            },
            {
              "key": "eco",
              "value": "Eco",
              "type": "active"
            }
          ],
          "value": "setpointMode.value",
          "valueType": "string"
        }
      },
      "state": null
    }
  ],
  "automation": {
    "conditions": [
      {
        "label": "Heat Mode",
        "displayType": "list",
        "list": {
          "alternatives": [
            {
              "key": "fast",
              "value": "Fast",
              "type": "active"
            },
            {
              "key": "normal",
              "value": "Normal",
              "type": "active"
            },
            {
              "key": "eco",
              "value": "Eco",
              "type": "active"
            }
          ],
          "value": "setpointMode.value",
          "valueType": "string"
        }
      }
    ],
    "actions": [
      {
        "label": "Heat Mode",
        "displayType": "list",
        "list": {
          "alternatives": [
            {
              "key": "fast",
              "value": "Fast",
              "type": "active"
            },
            {
              "key": "normal",
              "value": "Normal",
              "type": "active"
            },
            {
              "key": "eco",
              "value": "Eco",
              "type": "active"
            }
          ]
        }
      }
    ]
  },
  "id": "preparestream40760.heatMode",
  "version": 1
}

This is my customized device presentation:

{
    "dashboard": {
        "states": [
            {
                "component": "main",
                "capability": "temperatureMeasurement",
                "version": 1,
                "idx": 0,
                "group": "main",
                "values": [],
                "composite": false
            }
        ],
        "actions": [],
        "basicPlus": []
    },
    "detailView": [
        {
            "component": "main",
            "capability": "preparestream40760.windowOpenDetection",
            "version": 1,
            "values": [],
            "patch": []
        },
        {
            "component": "main",
            "capability": "preparestream40760.heatMode",
            "version": 1,
            "values": [],
            "patch": []
        },
        {
            "component": "main",
            "capability": "thermostatHeatingSetpoint",
            "version": 1,
            "values": [{
                "key": "heatingSetpoint.value",
                "enabledValues": [],
                "range": [
                    5,
                    35
                ],
                "step": 0.5
            }],
            "patch": []
        },
        {
            "component": "main",
            "capability": "battery",
            "version": 1,
            "values": [],
            "patch": []
        },
        {
            "component": "main",
            "capability": "temperatureMeasurement",
            "version": 1,
            "values": [],
            "patch": []
        },
        {
            "component": "main",
            "capability": "refresh",
            "version": 1,
            "values": [],
            "patch": []
        }
    ],
    "automation": {
        "conditions": [
            {
                "component": "main",
                "capability": "preparestream40760.windowOpenDetection",
                "version": 1,
                "values": [],
                "patch": [],
                "exclusion": []
            },
            {
                "component": "main",
                "capability": "preparestream40760.heatMode",
                "version": 1,
                "values": [],
                "patch": []
            },
            {
                "component": "main",
                "capability": "thermostatHeatingSetpoint",
                "version": 1,
                "values": [{
                    "key": "heatingSetpoint.value",
                    "enabledValues": [],
                    "range": [
                        5,
                        35
                    ],
                    "step": 0.5
                }],
                "patch": [],
                "exclusion": []
            },
            {
                "component": "main",
                "capability": "battery",
                "version": 1,
                "values": [],
                "patch": [],
                "exclusion": []
            },
            {
                "component": "main",
                "capability": "temperatureMeasurement",
                "version": 1,
                "values": [],
                "patch": [],
                "exclusion": []
            }
        ],
        "actions": [
            {
                "component": "main",
                "capability": "thermostatHeatingSetpoint",
                "version": 1,
                "values": [{
                    "key": "heatingSetpoint.value",
                    "enabledValues": [],
                    "range": [
                        5,
                        35
                    ],
                    "step": 0.5
                }],
                "patch": [],
                "exclusion": []
            },
            {
                "component": "main",
                "capability": "preparestream40760.heatMode",
                "version": 1,
                "values": [],
                "patch": []
            },
            {
                "component": "main",
                "capability": "refresh",
                "version": 1,
                "values": [],
                "patch": []
            }
        ]
    },
    "type": "profile"
}

Nevertheless, my heatmode capability command seems to be passed through via the CLI:

Thermostat

Capabilities:
┌───┬────────────────────────────────────────┐
│ 1 │ preparestream40760.windowOpenDetection │
├───┼────────────────────────────────────────┤
│ 2 │ preparestream40760.heatMode            │
├───┼────────────────────────────────────────┤
│ 3 │ thermostatMode                         │
├───┼────────────────────────────────────────┤
│ 4 │ thermostatHeatingSetpoint              │
├───┼────────────────────────────────────────┤
│ 5 │ powerSource                            │
├───┼────────────────────────────────────────┤
│ 6 │ battery                                │
├───┼────────────────────────────────────────┤
│ 7 │ temperatureMeasurement                 │
├───┼────────────────────────────────────────┤
│ 8 │ firmwareUpdate                         │
├───┼────────────────────────────────────────┤
│ 9 │ refresh                                │
└───┴────────────────────────────────────────┘
? Enter capability index or id 2

Commands:
┌───┬──────────┐
│ 1 │ eco()    │
├───┼──────────┤
│ 2 │ normal() │
├───┼──────────┤
│ 3 │ fast()   │
└───┴──────────┘
? Enter command 1
Command executed successfully
PS Q:\smartthings> 

But I end up with the following error:

2022-04-06T07:27:08.355943542+00:00 TRACE Thermostat  Received event with handler capability
2022-04-06T07:27:08.374915875+00:00 INFO Thermostat  <ZigbeeDevice: c0c56f39-0417-4b3e-beb6-015b31b2c0df [0x213A] (Thermostat)> received command: {"args":[],"component":"main","positional_args":[],"capability":"preparestream40760.heatMode","command":"eco"}
2022-04-06T07:27:08.381206542+00:00 TRACE Thermostat  Found CapabilityCommandDispatcher handler in popp-smart-thermostat
2022-04-06T07:27:08.386679542+00:00 DEBUG Thermostat  ### heat_cmd_handler ...
2022-04-06T07:27:08.403806209+00:00 ERROR Thermostat  Thermostat thread encountered error: [string "st/dispatcher.lua"]:229: Error encountered while processing event for <ZigbeeDevice: c0c56f39-0417-4b3e-beb6-015b31b2c0df [0x213A] (Thermostat)>:
    arg1: table: 0x23ab288
[string "common.lua"]:118: [string "dkjson.lua"]:397: bad argument #1 to 'strfind' (string expected, got light userdata)

My handler look like this:

capability_handlers = {
  ...
  [HeatingMode.ID] = {
	[HeatingMode.commands.fast.NAME] = common.heat_cmd_handler,
	[HeatingMode.commands.normal.NAME] = common.heat_cmd_handler,
	[HeatingMode.commands.eco.NAME] = common.heat_cmd_handler
  }
}

And the called function looks like this:

function common.heat_cmd_handler(driver, device, command)
	device:emit_event(HeatingMode.setpointMode(command.command))
end

I’ve tried several tries like these (inspired by alot of examples in the SDK and other ST repositories):

device:send_to_component(command.component, HeatingMode.setpointMode({value = "Fast"}))  // is it the caps attribute value??
device:emit_event(HeatingMode.setpointMode({value = tostring(command.command)})) // eco, fast, normal ???
device:emit_event(HeatingMode.setpointMode({value = command.command}))
device:emit_event(HeatingMode.setpointMode({state = command.command }))
device:emit_event(HeatingMode.setpointMode(HeatingMode.setpointMode.eco.NAME))
device:emit_event(HeatingMode.setpointMode("eco"))		fast, normal ???
device:emit_event(HeatingMode.setpointMode({value = {command.command}}))
device:emit_event(HeatingMode.setpointMode.eco())

but I got still the same error … What am I doing wrong and how the the correct device:emit_event() should look like n my case?

Thank you in advance.

OK, there are different things to consider:

  1. Some stock capabilities have a custom UI, so, even if you copy their config in a custom capability, they won’t appear the same.
  2. In the case of the list display type of a custom capability, the properties of “command” and “state” must be included.
  3. In the detail view, enum commands are not supported, so you need to configure a setter in the capability definition
  4. The command of device:emit_event will send the event to the capability in SmartThings. And, it should be like this:
device:emit_event(capabilities["namespace.capabilityId"].attributeName(command.args.value))

Make sure you use the correct capabilityID, attributeName and path to the command argument, it is generally command.args.value but it depends on your capability’s definition.

  1. Update: The team mentioned that we can use the helper function build_manufacturer_specific_command to build the zigbee command and use device:send to send the command.
    If you want to construct the message yourself, you can check this documentation:
    Zigbee Messages — SmartThings Edge Device Drivers documentation

Thanks @nayelyz .

I’ll try to check and consider points 1) to 4) tomorrow asap.

About 5)

I suppose I’m very close to the correct cmd, but I’m not sure how the payload should look like …

I know there are two variables defined as follows:

local cmd_body ={
      { 
        name= 'setpointType', 
        type= data_types.enum8,
        value = 1  
      },
      { 
        name = 'setpoint', 
        type = data_types.int16,
        value = 2500 
      }
    }

So I’ve tried this payload:

local cmd_id = 0x40
local cmd = cluster_base.build_manufacturer_specific_command(device, Thermostat.ID, cmd_id, MFG_CODE, cmd_body )
device:send(cmd)

result:

2022-04-06T19:38:51.088629321+00:00 DEBUG Thermostat  ### cmd #2: {address_header={cluster={field_name="cluster", value=513}, dest_addr={field_name="dest_addr", value=8506}, dest_endpoint={field_name="dest_endpoint", value=1}, profile={field_name="profile", value=260}, src_addr={field_name="src_addr", value=0}, src_endpoint={field_name="src_endpoint", value=1}}, body={zcl_body={body_bytes={{name="setpointType", value=1}, {name="setpoint", value=2500}}}, zcl_header={cmd={value=64}, frame_ctrl={field_name="frame_ctrl", value=5}, mfg_code={field_name="mfg_code", value=4678}, seqno={field_name="seqno", value=0}}}, tx_options={value=0}}      cmd table       true
2022-04-06T19:38:51.095813321+00:00 ERROR Thermostat Thermostat thread encountered error: [string "st/dispatcher.lua"]:229: Error encountered while processing event for <ZigbeeDevice: c0c56f39-0417-4b3e-beb6-015b31b2c0df [0x213A] (Thermostat)>:
    arg1: infoChanged
    arg2: table: 0x28fb640
[string "st/zigbee/generic_body.lua"]:46: attempt to call a nil value (method 'sub')

and this payload - {setpointType=1,setpoint=2500}:

local cmd_id = 0x40
local cmd = cluster_base.build_manufacturer_specific_command(device, Thermostat.ID, cmd_id, MFG_CODE, {setpointType=1,setpoint=2500})
device:send(cmd)

result

2022-04-06T19:29:23.261842450+00:00 DEBUG Thermostat  ### cmd #2: {address_header={cluster={field_name="cluster", value=513}, dest_addr={field_name="dest_addr", value=8506}, dest_endpoint={field_name="dest_endpoint", value=1}, profile={field_name="profile", value=260}, src_addr={field_name="src_addr", value=0}, src_endpoint={field_name="src_endpoint", value=1}}, body={zcl_body={body_bytes={setpoint=2500, setpointType=1}}, zcl_header={cmd={value=64}, frame_ctrl={field_name="frame_ctrl", value=5}, mfg_code={field_name="mfg_code", value=4678}, seqno={field_name="seqno", value=0}}}, tx_options={value=0}}      cmd table       true
2022-04-06T19:29:23.306488450+00:00 INFO Thermostat  <ZigbeeDevice: c0c56f39-0417-4b3e-beb6-015b31b2c0df [0x213A] (Thermostat)> sending Zigbee message: < ZigbeeMessageTx || Uint16: 0x0000, < AddressHeader || src_addr: 
0x0000, src_endpoint: 0x01, dest_addr: 0x213A, dest_endpoint: 0x01, profile: 0x0104, cluster: Thermostat >, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x05, mfg_code: 0x1246, seqno: 0x00, ZCLCommandId: 0x40 >, GenericBody:  > >
2022-04-06T19:29:23.313728116+00:00 ERROR Thermostat Thermostat thread encountered error: [string "st/dispatcher.lua"]:229: Error encountered while processing event for <ZigbeeDevice: c0c56f39-0417-4b3e-beb6-015b31b2c0df [0x213A] (Thermostat)>:
    arg1: infoChanged
    arg2: table: 0xe073f0
[string "st/zigbee/utils.lua"]:19: attempt to concatenate a table value

Am I on the right way?

Thank you in advance.

So, this is to send two values in the same command?
It seems the helper works for only certain cases, for example, I created this fake command and it is actually sent to the device:

cluster_base.build_manufacturer_specific_command(device, 0xFC02, 0x0012, 0x1241, "1")

So, in your case, you could build the TX message directly (Zigbee Messages — SmartThings Edge Device Drivers documentation)

Let me know if that helps. In the meantime, I’ll keep making tests

OK, there are different things to consider:

  1. Some stock capabilities have a custom UI, so, even if you copy their config in a custom capability, they won’t appear the same.
  2. In the case of the list display type of a custom capability, the properties of “command” and “state” must be included.
  3. In the detail view, enum commands are not supported, so you need to configure a setter in the capability definition
  4. The command of device:emit_event will send the event to the capability in SmartThings. And, it should be like this:
device:emit_event(capabilities["namespace.capabilityId"].attributeName(command.args.value))

Make sure you use the correct capabilityID , attributeName and path to the command argument, it is generally command.args.value but it depends on your capability’s definition.

I changed the heatMode capability to this:

{
  "name": "Heat Mode",
  "attributes": {
    "setpointMode": {
      "schema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "enum": [
              "fast",
              "eco",
              "normal"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "value"
        ]
      },
      "setter": "setSetpointMode",
      "enumCommands": []
    }
  },
  "commands": {
    "setSetpointMode": {
      "name": "setSetpointMode",
      "arguments": [
        {
          "name": "mode",
          "optional": false,
          "schema": {
            "type": "string",
            "enum": [
              "fast",
              "eco",
              "normal"
            ]
          }
        }
      ]
    }
  }
}

and its presentation to this:

{
  "dashboard": {
      "states": [],
      "actions": [],
      "basicPlus": []
  },
  "detailView": [
    {
      "label": "Heat Mode",
      "displayType": "list",
      "list": {
        "command": {
          "name": "setSetpointMode",
          "alternatives": [
            {
              "key": "fast",
              "value": "Fast"
            },
            {
              "key": "normal",
              "value": "Normal"
            },
            {
              "key": "eco",
              "value": "Eco"
            }
          ]
        },
        "state": {
          "alternatives": [
            {
              "key": "fast",
              "value": "Fast"
            },
            {
              "key": "normal",
              "value": "Normal"
            },
            {
              "key": "eco",
              "value": "Eco"
            }
          ],
          "value": "setpointMode.value"
        }
      },
      "state": null
    }
  ],
  "automation": {
    "conditions": [
      {
        "label": "Heat Mode",
        "displayType": "list",
        "list": {
          "alternatives": [
            {
              "key": "fast",
              "value": "Fast"
            },
            {
              "key": "normal",
              "value": "Normal"
            },
            {
              "key": "eco",
              "value": "Eco"
            }
          ],
          "value": "setpointMode.value"
        }
      }
    ],
    "actions": [
      {
        "label": "Heat Mode",
        "displayType": "list",
        "list": {
          "command": "setSetpointMode",
          "alternatives": [
            {
              "key": "fast",
              "value": "Fast"
            },
            {
              "key": "normal",
              "value": "Normal"
            },
            {
              "key": "eco",
              "value": "Eco"
            }
          ]
        }
      }
    ]
  },
  "id": "preparestream40760.heatMode",
  "version": 1
}

In the app it seems to work correct now.

but I have a problem with the capability_handler. From my perspective, I guess it needs to be called like this:

[HeatingMode.ID] = {
        [HeatingMode.commands.setSetpointMode.NAME] = common.heat_cmd_handler  

but the log tells me

2022-04-07T11:32:16.814250053+00:00 FATAL Thermostat  Lua: runtime error: [string "init.lua"]:483: attempt to index a nil value (field 'setSetpointMode')
stack traceback:
        [string "init.lua"]:483: in main chunk

The same happens if I use [HeatingMode.commands.setpointMode.NAME] instead. It seems not to exist …

2022-04-07T11:30:49.882365678+00:00 FATAL Thermostat  Lua: runtime error: [string "init.lua"]:483: attempt to index a nil value (field 'setSetpointMode')
stack traceback:
        [string "init.lua"]:483: in main chunk

My heat mode capability table look like this:

{ID="fast", NAME="fast", arg_list={}, 
capability={ID="preparestream40760.heatMode", NAME="Heat Mode", add_attribute=function: 0x1214590, add_command=function: 0x1214638, commands={eco={ID="eco", NAME="eco", arg_list={}, capability=RecursiveTable: capability}, fast={ID="fast", NAME="fast", arg_list={}, capability=RecursiveTable: capability}, normal={ID="normal", NAME="normal", arg_list={}, capability=RecursiveTable: capability}}, setpointMode={ID="setpointMode", NAME="setpointMode", capability=RecursiveTable: capability, eco={NAME="eco", attribute=RecursiveTable: setpointMode}, fast={NAME="fast", attribute=RecursiveTable: setpointMode}, normal={NAME="normal", attribute=RecursiveTable: setpointMode}, schema={additionalProperties=false, properties={value={enum={"fast", "eco", "normal"}, type="string"}}, required={"value"}, type="object"}}

I’m a bit confused why my command is not shown and the old ones are still there. Is this because they where mapped by the enum somehow?

If I use [HeatingMode.commands.eco.NAME] //fast/normal instead it gives me this:

2022-04-07T11:07:25.000548755+00:00 ERROR Thermostat Thermostat thread encountered error: [string "st/driver.lua"]:188: attempt to index a nil value (field '?')

and the handler function isn’t called. Same on a local function.

But sending the emit_event is working now :slight_smile:

Which command did you use to print the configuration of the capability (local variable HeatingMode)?
Are you just calling the existing configuration from the capabilities library?

local capName = capabilities["namespace.capabilityId"]

yes, like in the HowTo described:

local capabilities = require "st.capabilities"
local HeatingMode = capabilities["preparestream40760.heatMode"]

About the command:

seems the problem is the parsing output during the device:send … if I transmit the whole payload as string, it will be passed through and acknowledged by the device as MALEFORMED e.g.

2022-04-07T14:13:12.554074628+00:00 INFO Thermostat  <ZigbeeDevice: e5e63ee0-e81b-4c77-a6c9-aaf5e4a0fb8a [0x46DA] (Thermostat)> sending Zigbee message: < ZigbeeMessageTx || Uint16: 0x0000, < AddressHeader || src_addr: 
0x0000, src_endpoint: 0x01, dest_addr: 0x46DA, dest_endpoint: 0x01, profile: 0x0104, cluster: Thermostat >, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x05, mfg_code: 0x1246, seqno: 0x00, ZCLCommandId: 0x40 >, GenericBody:  7B 31 2C 32 
35 30 30 7D > >
2022-04-07T14:13:12.572603628+00:00 DEBUG Thermostat  ## >>>>>#END#<<<<< ## 
2022-04-07T14:13:12.581581295+00:00 DEBUG Thermostat  Thermostat device thread event handled
2022-04-07T14:13:17.718092964+00:00 TRACE Thermostat  Received event with handler zigbee
2022-04-07T14:13:17.730538298+00:00 INFO Thermostat  <ZigbeeDevice: e5e63ee0-e81b-4c77-a6c9-aaf5e4a0fb8a [0x46DA] (Thermostat)> received Zigbee message: < ZigbeeMessageRx || type: 0x00, < AddressHeader || src_addr: 0x46DA, src_endpoint: 0x01, dest_addr: 0x0000, dest_endpoint: 0x01, profile: 0x0104, cluster: Thermostat >, lqi: 0xB4, rssi: -55, body_length: 0x0007, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x0C, mfg_code: 0x1246, seqno: 0x29, ZCLCommandId: 0x0B >, < DefaultResponse || cmd: 0x40, ZclStatus: MALFORMED_COMMAND > > >

So, in your case, you could build the TX message directly

Is there any example that could be interesting for my case? In my imagine the build_manufacturer_specific_command() function is already doing this for me :face_with_spiral_eyes: :sweat_smile:

Sure, I created this sample to write an attribute:

//From a handler I just call this function 
messageHandler.build_write_tx_message(device, 0xFC02,0x0012, 0x1241,"Int16", 5)

//Result - Log
< ZigbeeMessageTx || Uint16: 0x0000, < AddressHeader || src_addr: 0x0000, src_endpoint: 0x01, dest_addr: 0x3C7B, dest_endpoint: 0x01, profile: 0x0104, cluster: 0xFC02 >, < ZCLMessageBody || < ZCLHeader || frame_ctrl: 0x04, mfg_code: 0x1241, seqno: 0x00, ZCLCommandId: 0x02 >, < WriteAttribute || < AttributeRecord || attr_id: 0x0012, DataType: Int16, data: 5 > > > >

Please, let me know if this is helpful

Hey @nayelyz ,

This is my “new” function for passing the ZigbeeMessageTx:

--- structure A
local cmd_body = {
  ID = 0x40,
  data_type = data_types.Int8,
  args_def = {
	setpointType = {
		name = 'setpointType',
		data_type = data_types.enum8,
		value = 1
	  },
	  setpoint = {
		name = 'setpoint',
		data_type = data_types.Int16,
		value = 2500
	  }
	}
 }
 --[[ structure B 
 local cmd_body = {
	ID = 0x40,
	data_type = data_types.Int8,
	args_def = {
		{
			field_name = 'setpointType',
			data_type = data_types.enum8,
			value = 1
		},{
			field_name = 'setpoint',
			data_type = data_types.enum8,
			value = 2500
		}
	}
} ]]--

custom_build_manufacturer_specific_command = function(device, cluster_id, cmd_id.ID, mfg_code, payload)
    local zclh = zcl_messages.ZclHeader({
      cmd = data_types.ZCLCommandId(cmd_id)
      --cmd = data_types.ZCLCommandId(global_commands.parse_global_zcl_command(cmd_id, payload)) // does it make sence to use this here
    })
    zclh.frame_ctrl:set_mfg_specific()
    zclh.frame_ctrl:set_cluster_specific()
    zclh.mfg_code = data_types.validate_or_build_type(mfg_code, data_types.Uint16, "mfg_code")
    local addrh = messages.AddressHeader(
        zb_const.HUB.ADDR,
        zb_const.HUB.ENDPOINT,
        device:get_short_address(),
        device:get_endpoint(cluster_id),
        zb_const.HA_PROFILE_ID,
        cluster_id
    )
    local message_body = zcl_messages.ZclMessageBody({
      zcl_header = zclh,
      zcl_body = generic_body.GenericBody(payload)
    })

    return messages.ZigbeeMessageTx({
      address_header = addrh,
      body = message_body
    })
 end
 
local cmd1 = custom_build_manufacturer_specific_command(device, Thermostat.ID, cmd_id, MFG_CODE, tostring(cmd_body)) -- {setpointType=1,setpoint=2500}
device:send(cmd1)

Actually I adjusted my command body. Not sure if there is a predefined pattern in smartthings how the key names should be addressed and how the structuire should look like.
I’m also in the contact with the manufacturer support.

If I do not use generic_body.GenericBody() :

local message_body = zcl_messages.ZclMessageBody({
        zcl_header = zclh,
        zcl_body = payload --//generic_body.GenericBody(payload)
      })

and pass the payload directly wether as native object or stringified object, I got this error message:

2022-04-08T09:01:11.016177901+00:00 ERROR POPP Smart Thermostat  POPP Smart Thermostat thread encountered error: [string "st/dispatcher.lua"]:229: Error encountered while processing event for <ZigbeeDevice: e5e63ee0-e81b-4c77-a6c9-aaf5e4a0fb8a [0x46DA] (POPP Smart Thermostat)>:
    arg1: infoChanged
    arg2: table: 0x2204ac0
[string "st/zigbee/utils.lua"]:56: attempt to call a nil value (method 'pretty_print')

So I suppose, the command in bytes would be the best - will see what the manufacturer says.

I’ve also tried your example with your code and it has worked so far.
Is there also a way to build a command or command payload like you did in build_write_tx_message() with the attribute? Like:

local cie_attr_write = write_attribute.WriteAttributeAttributeRecord(
		data_types.AttributeId(attr_id),
		data_types.ZigbeeDataType(data_types[attr_type].ID),
		data_types[attr_type](attr_value)
)
local write_body = write_attribute.WriteAttribute({ cie_attr_write })

at least I have found nothing comparable in the libraries.

Any idea why this is not working?

What do you mean? the cie_attr_write variable has the attribute ID, data type, and value that are necessary for the Zigbee Tx message.
Do you want to remove the part of write_attribute.WriteAttributeAttributeRecord()?

About this one, I made some tests with your capability and it worked correctly, I didn’t receive the error you mentioned.
Did you reinstall the device to force a refresh? As you see the previous configuration of the capability, the issue might be related to the cache.

cie_attr_write looks for me like defining the AttributeRecord which should be send then.
So is this also necessary for a command like defining a “CommandRecord”? Or is a command treated as an attribute so I can use this either?

Ok, I’ll give it another try on Monday, hopefully it’ll work out then.

I know I have a lot of questions :sweat_smile:
Thank you for being so patient with me.

Oh, so the command you want to send is different than writeAttribute and not related to a specific attribute?
Can you provide a sample of that, please?

Don’t worry, we’re all here to help each other. Keep the questions coming, others could benefit from this thread :smiley:

Ok, I have a command with ID 0x40 that was added to the Thermostat Cluster (0x0201) by the manufacturer - I suppose this, because it is not listed under the Zigbee Cluster Thermostat Commands. This command should send a payload with two values:

  • setpointType is Enum8 with values [0,1,2] for “normal”, “fast”, “eco”
  • setpoint is Int16 for Temperature value like 2500 for 25 C°

-Btw. this is what the heatMode capability is for.

If I would like to write to an attribute I use this:

write_attribute.WriteAttributeAttributeRecord(
		data_types.AttributeId(attr_id),
		data_types.ZigbeeDataType(data_types[attr_type].ID),
		data_types[attr_type](attr_value)
)

to produce an attribute record. So my question is, is there something similar to do this for commands - let’s say a SendCommandCommandRecord() function? Or is it just enough to pass the payload as zcl_body?

Hey @nayelyz

the payload needs to be passed as byte string, which can easily done with cluster_base.build_manufacturer_specific_command() so that’s working now.

About my “Window Open Detection” capability:

I would like to show the current of a set of different states.
Since yet I’ve tried this with display type list which requires a setter/command to be displayed but this is not my intention here.

Is there a way to use the “state” display type instead but with the same batch of alternatives?
If yes how shoudl then the cap definition and it’s presentation look like?

CAP.json

{
  "name": "Window Open Detection",
  "attributes": {
    "windowOpenDetection": {
      "schema": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "enum": [
              "quarantine",
              "closed",
              "hold",
              "opened",
              "opened_alarm"
            ]
          }
        },
        "additionalProperties": false,
        "required": [
          "value"
        ]
      },
      "enumCommands": [],
	  "setter": "setWindowOpenDetection"
    }
  },
  "commands": {
	  "setWindowOpenDetection": {
		  "name": "setWindowOpenDetection",
		  "arguments": [
			{
			  "name": "mode",
			  "optional": false,
			  "schema": {
				"type": "string",
				"enum": [
				  "quarantine",
				  "closed",
				  "hold",
				  "opened",
				  "opened_alarm"
				]
			  }
			}
		  ]
		}
	}
}

CAP_PRES.json

{
    "dashboard": {
        "states": [],
        "actions": [],
        "basicPlus": []
    },
	"detailView": [
	  {
		"label": "Window Open Detection",
		"displayType": "state",
		"state": {
			"label": "{{windowOpenDetection.value}}",
			"alternatives": [
			  {
				"key": "quarantine",
				"value": "Quarantine"
			  },
			  {
				"key": "closed",
				"value": "Closed"
			  },
			  {
				"key": "opened",
				"value": "Opened"
			  },
			  {
				"key": "hold",
				"value": "Opening or Closing ..."
			  },
			  {
				"key": "opened_alarm",
				"value": "Attention! Window was opened from the outside."
			  }
			]
		}
	  }
	],
	"automation": {
		"conditions": [
		  {
			"label": "Window Open Detection",
			"displayType": "list",
			"list": {
				"alternatives": [
					{
						"key": "quarantine",
						"value": "Quarantine"
					},
					{
						"key": "closed",
						"value": "Closed"
					},
					{
						"key": "opened",
						"value": "Opened"
					},
					{
						"key": "hold",
						"value": "Opening or Closing ..."
					},
					{
						"key": "opened_alarm",
						"value": "Attention! Window was opened from the outside."
					}
				],
				"value": "windowOpenDetection.value"
			}
		}],
		"actions": []
	  },
    "id": "preparestream40760.windowOpenDetection",
    "version": 1
}

Thank you in advance!