Description
I am trying to connect a custom client to Z2M and have noticed several inconsistencies in the API topics.
So I'd like to share my thoughts with you and welcome feedback on whether there's a pattern I haven't seen yet, or whether it has simply grown over time. Since MQTT is completely new to me, my view of this project may be very naive - so please don't judge me.
Bridge topics vs. device topics
I see the topic segments /bridge
for the coordinator and Z2M config, but for devices it is /<device name>
...
- Will I run into a conflict if I name a device "bridge"?
- Since the coordinator is also a node in the mesh, would it make sense to treat it in the same way? (What about multiple?)
/<bridge name>
&/<device name>
or use a different style which is more easy to subscribe like/bridge/<bridge ident>
&/device/<device ident>
.
Bridge availability vs. device availability
It is confusing to me, that ...
/bridge/state
seems the same like the/device/availability
/bridge/info
is kinda/device/state
Transactions vs. requests vs. responses
It looks mixed here and I have problems to understand how to deal with the transaction topics:
- Some use a
/bridge/request
+/bridge/response
combo, while others use the request topic only. - The scene management is totally different than the rest and not possible to filter via path.
Device related vs. Bridge related topics
I know a lot of management technically happens in the coordinator/bridge. But does it make sense to always add the /bridge
segment for mostly everything? I wonder if a more "RESTful" approach would help understanding the topics and get rid of request
& response
:
/device/<device ident>/availability
/group/<group ident>/devices
/bridge/<bridge ident>/devices
/scene/<scene ident>/recall
/network/open
I hope someone could explain some of the details to me and maybe, if it makes sense, we can improve some things in a future API v2 =)
I tried to build myself an index of all the topics, to help understand the patterns.
export type TOPIC_DEFINITIONS = 'bridge/definitions'
export type TOPIC_DEVICES = 'bridge/devices'
export type TOPIC_EXTENSIONS = 'bridge/extensions'
export type TOPIC_GROUPS = 'bridge/groups'
export type TOPIC_LOGGING = 'bridge/logging'
// ---------- Bridge ----------
export type TOPIC_BRIDGE_INFO = 'bridge/info' // should be bridge/state ?
export type TOPIC_BRIDGE_STATE = 'bridge/state' // should be bridge/availability ?
export type TOPIC_BRIDGE_CODE_ADD = 'bridge/request/install_code/add'
export type TOPIC_BRIDGE_NETWORK_OPEN = 'bridge/request/permit_join'
export type TOPIC_BRIDGE_OPTIONS_REQUEST = 'bridge/request/options'
export type TOPIC_BRIDGE_RESTART_REQUEST = 'bridge/request/restart'
export type TOPIC_EXTENSION_WRITE = 'bridge/request/extension/save'
export type TOPIC_EXTENSION_REMOVE = 'bridge/request/extension/remove'
export type TOPIC_BACKUP_REQUEST = 'bridge/request/backup'
export type TOPIC_BACKUP_RESPONSE = 'bridge/response/backup'
export type TOPIC_TOUCHLINK_IDENTIFY_REQUEST = 'bridge/request/touchlink/identify'
export type TOPIC_TOUCHLINK_IDENTIFY_RESPONSE = 'bridge/response/touchlink/identify'
export type TOPIC_TOUCHLINK_RESET_REQUEST = 'bridge/request/touchlink/factory_reset'
export type TOPIC_TOUCHLINK_RESET_RESPONSE = 'bridge/response/touchlink/factory_reset'
export type TOPIC_TOUCHLINK_SCAN_REQUEST = 'bridge/request/touchlink/scan'
export type TOPIC_TOUCHLINK_SCAN_RESPONSE = 'bridge/response/touchlink/scan'
// ---------- Groups ----------
export type TOPIC_GROUP_CREATE = 'bridge/request/group/add'
export type TOPIC_GROUP_REMOVE = 'bridge/request/group/remove'
export type TOPIC_GROUP_RENAME = 'bridge/request/group/rename'
export type TOPIC_GROUP_EXTEND = 'bridge/request/group/members/add'
export type TOPIC_GROUP_REDUCE = 'bridge/request/group/members/remove'
export type TOPIC_MAP_REQUEST = 'bridge/request/networkmap'
export type TOPIC_MAP_RESPONSE = 'bridge/response/networkmap'
// ---------- Devices ----------
export type TOPIC_DEVICE_AVAILABILITY = `${string}/availability`
export type TOPIC_DEVICE_STATE = `${string}/state`
export type TOPIC_DEVICE_STATE_QUERY = `${string}/get` // TODO: is polling required in some place?
export type TOPIC_DEVICE_STATE_WRITE = `${string}/set`
export type TOPIC_DEVICE_CONFIGURE_REQUEST = 'bridge/request/device/configure'
export type TOPIC_DEVICE_INTERVIEW_REQUEST = 'bridge/request/device/interview'
export type TOPIC_DEVICE_REMOVE_REQUEST = 'bridge/request/device/remove'
export type TOPIC_DEVICE_RENAME_REQUEST = 'bridge/request/device/rename'
export type TOPIC_DEVICE_OPTIONS_REQUEST = 'bridge/request/device/options'
export type TOPIC_DEVICE_BIND_REQUEST = `bridge/request/device/bind`
export type TOPIC_DEVICE_UNBIND_REQUEST = `bridge/request/device/unbind`
export type TOPIC_DEVICE_OTAU_CHECK_REQUEST = 'bridge/request/device/ota_update/check'
export type TOPIC_DEVICE_OTAU_EXEC_REQUEST = 'bridge/request/device/ota_update/update'
export type TOPIC_DEVICE_ATTRIBUTE_WRITE = `${/*device*/ string}/${/*attribute*/ string}/set`
export type TOPIC_DEVICE_SCENE_WRITE = `${string}/set`
export type TOPIC_DEVICE_SCENE_RECALL = `${string}/set`
export type TOPIC_DEVICE_SCENE_REMOVE = `${string}/set`
export type TOPIC_DEVICE_DEFINITION_REQUEST = 'bridge/request/device/generate_external_definition'
export type TOPIC_DEVICE_DEFINITION_RESPONSE = 'bridge/response/device/generate_external_definition'