diff --git a/lib/extension/publish.ts b/lib/extension/publish.ts index 755ad938c6..b53ad96be9 100644 --- a/lib/extension/publish.ts +++ b/lib/extension/publish.ts @@ -10,7 +10,7 @@ import Group from '../model/group'; import Device from '../model/device'; import bind from 'bind-decorator'; -const topicGetSetRegex = new RegExp(`^(.+?)(?:/([^/]+))?/(get|set)(?:/(.+))?`); +const topicGetSetRegex = new RegExp(`^(.+?)/(get|set)(?:/(.+))?`); const stateValues = ['on', 'off', 'toggle', 'open', 'close', 'stop', 'lock', 'unlock']; const sceneConverterKeys = ['scene_store', 'scene_add', 'scene_remove', 'scene_remove_all', 'scene_rename']; @@ -56,20 +56,13 @@ export default class Publish extends Extension { // After it there will be an optional attribute name. const match = topic.match(topicGetSetRegex); if (!match) return null; - let deviceName = match[1]; - let endpointName = match[2]; - const attribute = match[4]; - - // There can be some ambiguoty between 'device_name/endpoint' and 'device/name/with/slashes' with no endpoint - // Try to ensure the device with one of these names exist - const re = this.zigbee.resolveEntity(deviceName); - if (re == null && endpointName) { - // Possibly the last before get/set is just a continuation of the device name - deviceName = `${deviceName}/${endpointName}`; - endpointName = null; - } - return {ID: deviceName, endpoint: endpointName, type: match[3] as 'get' | 'set', attribute: attribute}; + const deviceNameAndEndpoint = match[1]; + const attribute = match[3]; + + // Now parse the device/group name, and endpoint name + const entity = this.zigbee.resolveEntityAndEndpoint(deviceNameAndEndpoint); + return {ID: entity.ID, endpoint: entity.endpointID, type: match[2] as 'get' | 'set', attribute: attribute}; } parseMessage(parsedTopic: ParsedTopic, data: eventdata.MQTTMessage): KeyValue | null { diff --git a/lib/zigbee.ts b/lib/zigbee.ts index 2e78b8417f..600d669057 100644 --- a/lib/zigbee.ts +++ b/lib/zigbee.ts @@ -293,19 +293,20 @@ export default class Zigbee { // device/name (device name with slashes) // device/name/ep_name (device name with slashes, and endpoint numeric ID or name) - // First split the input token by the latest slash - const match = ID.match(entityIDRegex); + // The function tries to find an exact match first + let entityName = ID; + let deviceOrGroup = this.resolveEntity(ID); + let endpointNameOrID = null; - // Try to match 'device_name/endpoint' pattern - let entityName = match[1]; - let deviceOrGroup = this.resolveEntity(match[1]); - let endpointNameOrID = match[2]; - - // If 'device_name/endpoint' pattern does not match, perhaps this is device name with slashes + // If exact match did not happenc, try matching a device_name/endpoint pattern if (!deviceOrGroup) { - entityName = ID; - deviceOrGroup = this.resolveEntity(ID); - endpointNameOrID = null; + // First split the input token by the latest slash + const match = ID.match(entityIDRegex); + + // Get the resulting IDs from the match + entityName = match[1]; + deviceOrGroup = this.resolveEntity(match[1]); + endpointNameOrID = match[2]; } // If the function returns non-null endpoint name, but the endpoint field is null, then