Skip to content

Commit

Permalink
New HA entity naming
Browse files Browse the repository at this point in the history
  • Loading branch information
tsightler committed Aug 26, 2023
1 parent 5f5fbc6 commit 6efa660
Show file tree
Hide file tree
Showing 14 changed files with 40 additions and 42 deletions.
50 changes: 24 additions & 26 deletions devices/base-ring-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,70 +57,68 @@ export default class RingDevice {

// ***** Build a Home Assistant style MQTT discovery message *****
// Legacy versions of ring-mqtt created entity names and IDs for single function devices
// without using any type of suffix. To maintain compatibility with older versions, entities
// can set the "isLegacyEntity" flag in the entity definition. In this case the device will
// also get legacy device name generation (i.e. no name suffix either). However, automatic
// name generation can also be completely overridden by the entity 'name' parameter.
// without using any type of suffix. Modern versions of Home Assistant do not allow
// the device name to be part of the entity name so now the code simply sets the name
// of these entities to "None" which tells Home Assistant that this entity represents
// the primary function of the device.
//
// I know the code below will offend the sensibilities of some people, especially with
// regards to formatting and nested ternaries, but, for whatever reason, my brain reads
// and parses the logic out easily, more so than other methods I've tried, so I've
// decided I can live with it.
let discoveryMessage = {
... entity.hasOwnProperty('name')
...entity.hasOwnProperty('name')
? { name: entity.name }
: entity.hasOwnProperty('isLegacyEntity') || this.deviceData.name.toLowerCase().match(entityKey) // Use legacy name generation
? { name: `${this.deviceData.name}` }
: { name: `${this.deviceData.name} ${entityKey.replace(/_/g," ").replace(/(^\w{1})|(\s+\w{1})/g, letter => letter.toUpperCase())}` },
... entity.hasOwnProperty('unique_id') // If device provides own unique_id use that in all cases
: { name: `${entityKey.replace(/_/g," ").replace(/(^\w{1})|(\s+\w{1})/g, letter => letter.toUpperCase())}` },
...entity.hasOwnProperty('unique_id') // If device provides own unique_id use that in all cases
? { unique_id: entity.unique_id }
: entity.hasOwnProperty('isLegacyEntity') // Use legacy entity ID generation
: entity.name === 'None' // Use legacy entity ID generation the for primary device entity
? { unique_id: `${this.deviceId}` }
: { unique_id: `${this.deviceId}_${entityKey}` },
... entity.component === 'camera'
...entity.component === 'camera'
? { topic: entityStateTopic }
: entity.component === 'climate'
? { mode_state_topic: entityStateTopic }
: { state_topic: entityStateTopic },
... entity.component.match(/^(switch|number|light|fan|lock|alarm_control_panel|select)$/)
...entity.component.match(/^(switch|number|light|fan|lock|alarm_control_panel|select)$/)
? { command_topic: `${entityTopic}/command` } : {},
... entity.hasOwnProperty('device_class')
...entity.hasOwnProperty('device_class')
? { device_class: entity.device_class } : {},
... entity.hasOwnProperty('unit_of_measurement')
...entity.hasOwnProperty('unit_of_measurement')
? { unit_of_measurement: entity.unit_of_measurement } : {},
... entity.hasOwnProperty('state_class')
...entity.hasOwnProperty('state_class')
? { state_class: entity.state_class } : {},
... entity.hasOwnProperty('value_template')
...entity.hasOwnProperty('value_template')
? { value_template: entity.value_template } : {},
... entity.hasOwnProperty('min')
...entity.hasOwnProperty('min')
? { min: entity.min } : {},
... entity.hasOwnProperty('max')
...entity.hasOwnProperty('max')
? { max: entity.max } : {},
... entity.hasOwnProperty('attributes')
...entity.hasOwnProperty('attributes')
? { json_attributes_topic: `${entityTopic}/attributes` }
: entityKey === "info"
? { json_attributes_topic: `${entityStateTopic}` } : {},
... entity.hasOwnProperty('icon')
...entity.hasOwnProperty('icon')
? { icon: entity.icon }
: entityKey === "info"
? { icon: 'mdi:information-outline' } : {},
... entity.component === 'alarm_control_panel' && utils.config().disarm_code
...entity.component === 'alarm_control_panel' && utils.config().disarm_code
? { code: utils.config().disarm_code.toString(),
code_arm_required: false,
code_disarm_required: true } : {},
... entity.hasOwnProperty('brightness_scale')
...entity.hasOwnProperty('brightness_scale')
? { brightness_state_topic: `${entityTopic}/brightness_state`,
brightness_command_topic: `${entityTopic}/brightness_command`,
brightness_scale: entity.brightness_scale } : {},
... entity.component === 'fan'
...entity.component === 'fan'
? { percentage_state_topic: `${entityTopic}/percent_speed_state`,
percentage_command_topic: `${entityTopic}/percent_speed_command`,
preset_mode_state_topic: `${entityTopic}/speed_state`,
preset_mode_command_topic: `${entityTopic}/speed_command`,
preset_modes: [ "low", "medium", "high" ],
speed_range_min: 11,
speed_range_max: 100 } : {},
... entity.component === 'climate'
...entity.component === 'climate'
? { action_topic: `${entityTopic}/action_state`,
aux_state_topic: `${entityTopic}/aux_state`,
aux_command_topic: `${entityTopic}/aux_command`,
Expand All @@ -135,14 +133,14 @@ export default class RingDevice {
mode_command_topic: `${entityTopic}/mode_command`,
temperature_state_topic: `${entityTopic}/temperature_state`,
temperature_command_topic: `${entityTopic}/temperature_command`,
... entity.modes.includes('auto')
...entity.modes.includes('auto')
? { temperature_high_state_topic: `${entityTopic}/temperature_high_state`,
temperature_high_command_topic: `${entityTopic}/temperature_high_command`,
temperature_low_state_topic: `${entityTopic}/temperature_low_state`,
temperature_low_command_topic: `${entityTopic}/temperature_low_command`,
} : {},
temperature_unit: 'C' } : {},
... entity.component === 'select'
...entity.component === 'select'
? { options: entity.options } : {},
availability_topic: this.availabilityTopic,
payload_available: 'online',
Expand Down
2 changes: 1 addition & 1 deletion devices/beam.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default class Beam extends RingSocketDevice {
}

this.entity.beam_duration = {
name: this.device.name+' Duration',
name: 'Duration',
unique_id: this.deviceId+'_duration',
component: 'number',
min: 0,
Expand Down
2 changes: 1 addition & 1 deletion devices/binary-sensor.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export default class BinarySensor extends RingSocketDevice {
this.entity[this.entityName] = {
component: 'binary_sensor',
...device_class ? { device_class: device_class } : {},
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}

// Only official Ring sensors can be bypassed
Expand Down
2 changes: 1 addition & 1 deletion devices/camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export default class Camera extends RingPolledDevice {
stream: {
component: 'switch',
attributes: true,
name: `${this.deviceData.name} Live Stream`,
name: 'Live Stream',
icon: 'mdi:cctv'
},
event_stream: {
Expand Down
2 changes: 1 addition & 1 deletion devices/co-alarm.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class CoAlarm extends RingSocketDevice {
this.entity.co = {
component: 'binary_sensor',
device_class: 'gas',
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}
}

Expand Down
2 changes: 1 addition & 1 deletion devices/fan.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default class Fan extends RingSocketDevice {

this.entity.fan = {
component: 'fan',
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}

this.data = {
Expand Down
2 changes: 1 addition & 1 deletion devices/lock.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default class Lock extends RingSocketDevice {

this.entity.lock = {
component: 'lock',
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}
}

Expand Down
2 changes: 1 addition & 1 deletion devices/modes-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class ModesPanel extends RingPolledDevice {

this.entity.mode = {
component: 'alarm_control_panel',
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}

this.data = {
Expand Down
2 changes: 1 addition & 1 deletion devices/multi-level-switch.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default class MultiLevelSwitch extends RingSocketDevice {
this.entity.light = {
component: 'light',
brightness_scale: 100,
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}
}

Expand Down
8 changes: 4 additions & 4 deletions devices/security-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ export default class SecurityPanel extends RingSocketDevice {
alarm: {
component: 'alarm_control_panel',
attributes: true,
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
},
siren: {
component: 'switch',
icon: 'mdi:alarm-light',
name: `${this.device.location.name} Siren`
name: 'Siren'
},
...utils.config().enable_panic ? {
police: {
component: 'switch',
name: `${this.device.location.name} Panic - Police`,
name: 'Panic - Police',
icon: 'mdi:police-badge'
},
fire: {
component: 'switch',
name: `${this.device.location.name} Panic - Fire`,
name: 'Panic - Fire',
icon: 'mdi:fire'
}
} : {}
Expand Down
2 changes: 1 addition & 1 deletion devices/siren.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default class Siren extends RingSocketDevice {
siren: {
component: 'switch',
icon: 'mdi:alarm-light',
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
},
...(this.device.data.deviceType === 'siren.outdoor-strobe') ? {
volume: {
Expand Down
2 changes: 1 addition & 1 deletion devices/smoke-alarm.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class SmokeAlarm extends RingSocketDevice {
this.entity.smoke = {
component: 'binary_sensor',
device_class: 'smoke',
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}
}

Expand Down
2 changes: 1 addition & 1 deletion devices/smoke-co-listener.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class SmokeCoListener extends RingSocketDevice {
this.entity.co = {
component: 'binary_sensor',
device_class: 'gas',
name: `${this.deviceData.name} CO`, // Legacy compatibility
name: 'CO', // Legacy compatibility
unique_id: `${this.deviceId}_gas` // Legacy compatibility
}
}
Expand Down
2 changes: 1 addition & 1 deletion devices/switch.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default class Switch extends RingSocketDevice {

this.entity[this.component] = {
component: this.component,
isLegacyEntity: true // Legacy compatibility
name: 'None' // Indicates primary entity to Home Assistant
}
}

Expand Down

0 comments on commit 6efa660

Please sign in to comment.