Update alexa range value attribute parameters (#2296)

Related to https://github.com/openhab/openhab-alexa/pull/650.
Related to https://github.com/openhab/openhab-alexa/pull/651.

Signed-off-by: jsetton <jeremy.setton@gmail.com>
pull/2300/head
Jeremy 2024-01-30 03:39:33 -05:00 committed by GitHub
parent 6ea38c34cc
commit 424e646297
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 45 additions and 44 deletions

View File

@ -48,7 +48,7 @@ export default {
parameters: (itemType, item) => [
p.inverted(itemType === 'Rollershutter'),
p.presets(item.stateDescription, '20=Morning,60=Afternoon,80=Evening:@Setting.Night'),
p.language(item.settings && item.settings.regional.language),
p.language(item.settings?.regional?.language),
p.actionMappings({ default: 'value' }, 'Close=0,Open=100,Lower=0,Raise=100', (config) => {
const primaryControl = getGroupParameter('primaryControl', item.groups) || 'position'
if (itemType === 'Dimmer') {
@ -73,7 +73,7 @@ export default {
parameters: (itemType, item) => [
p.inverted(itemType === 'Rollershutter'),
p.presets(item.stateDescription, '20=Morning,60=Afternoon,80=Evening:@Setting.Night'),
p.language(item.settings && item.settings.regional.language),
p.language(item.settings?.regional?.language),
...(getGroupParameter('primaryControl', item.groups) !== 'tilt' ? [] : [
p.actionMappings({ default: 'value' }, 'Close=0,Open=100', (config) => {
if (itemType === 'Dimmer') {
@ -107,7 +107,7 @@ export default {
itemTypes: ['Number', 'String'],
parameters: (itemType, item) => [
p.supportedInputs(item.stateDescription, itemType === 'String' ? 'HDMI1=Cable,HDMI2=Kodi' : '1=Cable,2=Kodi'),
p.language(item.settings && item.settings.regional.language),
p.language(item.settings?.regional?.language),
p.retrievable()
]
},
@ -410,7 +410,7 @@ export default {
p.retrievable(),
p.supportedModes(item.stateDescription),
p.ordered(),
p.language(item.settings && item.settings.regional.language),
p.language(item.settings?.regional?.language),
p.actionMappings(
{ set: 'mode', ...(config.ordered && { adjust: '(±deltaValue)' }) },
'Close=Down,Open=Up,Lower=Down,Raise=Up'
@ -421,7 +421,7 @@ export default {
RangeValue: {
itemTypes: ['Dimmer', 'Number', 'Number:*', 'Rollershutter'],
supports: ['multiInstance'],
parameters: (itemType, item) => [
parameters: (itemType, item, config) => [
p.capabilityNames(item.groups.length ? item.label : '@Setting.RangeValue', '@Setting.FanSpeed,Speed'),
p.inverted(itemType === 'Rollershutter'),
p.nonControllable(item.stateDescription),
@ -432,12 +432,17 @@ export default {
? [p.supportedCommands(['UP', 'DOWN', 'MOVE', 'STOP'], 'UP=@Value.Open,DOWN=@Value.Close,STOP=@Value.Stop')]
: []),
p.supportedRange(
item.stateDescription,
itemType === 'Dimmer' || itemType === 'Rollershutter' ? '0:100:1' : '0:10:1'
item,
config,
itemType === 'Dimmer' || itemType === 'Rollershutter'
? '0:100:1'
: config.nonControllable
? '0:10:0.01'
: '0:10:1'
),
p.presets(item.stateDescription, '1=@Value.Low:Lowest,10=@Value.High:Highest'),
p.unitOfMeasure(item),
p.language(item.settings && item.settings.regional.language),
p.language(item.settings?.regional?.language),
p.actionMappings({ set: 'value', adjust: '(±deltaValue)' }, 'Close=0,Open=100,Lower=(-10),Raise=(+10)'),
p.stateMappings({ default: 'value', range: 'minValue:maxValue' }, 'Closed=0,Open=1:100')
]
@ -452,7 +457,7 @@ export default {
: [p.inverted()]),
p.nonControllable(item.stateDescription),
p.retrievable(),
p.language(item.settings && item.settings.regional.language),
p.language(item.settings?.regional?.language),
p.actionMappings(['ON', 'OFF'], 'Close=OFF,Open=ON'),
p.stateMappings(['ON', 'OFF'], 'Closed=OFF,Open=ON')
]

View File

@ -60,7 +60,7 @@ const thermostatAttributes = [
const blindParameters = (_, item) => {
const attributes = ['PositionState', 'TiltAngle']
const metadata = item.members.map((mbr) => mbr.metadata && mbr.metadata.alexa.value).join(',')
const metadata = item.members.map((mbr) => mbr.metadata?.alexa?.value).filter(Boolean).join(',')
return attributes.every((attr) => metadata.includes(attr)) ? [p.primaryControl()] : []
}

View File

@ -19,7 +19,7 @@ export const docLink = (title, anchor) => {
return `<a class="external text-color-blue" target="_blank" href="${link}">${title}</a>`
}
export const getGroupParameter = (parameter, groups) => {
export const getGroupParameter = (parameter, groups = []) => {
for (const group of groups) {
const config = group.metadata.alexa.config || {}
if (parameter in config) return config[parameter]
@ -39,25 +39,34 @@ export const getSemanticFormat = (type, format) =>
''
)
export const getSupportedRange = (item, config, defaultValue) => {
const { minimum, maximum, step, pattern } = item.stateDescription || {}
if (!isNaN(minimum) && !isNaN(maximum) && !isNaN(step)) return `${minimum}:${maximum}:${step}`
const itemType = item.groupType || item.type
if (itemType.startsWith('Number') && config.nonControllable) {
const { precision, specifier } = pattern?.match(/%\d*(?:\.(?<precision>\d+))?(?<specifier>[df])/)?.groups || {}
const [minimum, maximum] = defaultValue.split(':', 2)
if (specifier === 'd') return `${minimum}:${maximum}:1`
if (precision <= 16) return `${minimum}:${maximum}:${1 / 10 ** precision}`
}
return defaultValue
}
export const getTemperatureScale = (item) => {
const itemType = item.groupType || item.type
const unitSymbol = item.unitSymbol
const statePresentation = (item.stateDescription && item.stateDescription.pattern) || ''
const format = (itemType === 'Number:Temperature' && unitSymbol) || statePresentation
if (format.endsWith('°C')) return 'CELSIUS'
if (format.endsWith('°F')) return 'FAHRENHEIT'
const { measurementSystem } = (item.settings && item.settings.regional) || {}
const format = (itemType === 'Number:Temperature' && item.unitSymbol) || item.stateDescription?.pattern
if (format?.endsWith('°C')) return 'CELSIUS'
if (format?.endsWith('°F')) return 'FAHRENHEIT'
const measurementSystem = item.settings?.regional?.measurementSystem
if (measurementSystem === 'SI') return 'CELSIUS'
if (measurementSystem === 'US') return 'FAHRENHEIT'
}
export const getUnitOfMeasure = (item) => {
const itemType = item.groupType || item.type
const unitSymbol = item.unitSymbol
const statePresentation = (item.stateDescription && item.stateDescription.pattern) || ''
const format =
((itemType === 'Dimmer' || itemType === 'Rollershutter') && '%') ||
(itemType.startsWith('Number:') && unitSymbol) ||
statePresentation
return Object.keys(UNITS_OF_MEASURE).find((id) => format.endsWith(UNITS_OF_MEASURE[id]))
(itemType.startsWith('Number:') && item.unitSymbol) ||
item.stateDescription?.pattern
return Object.keys(UNITS_OF_MEASURE).find((id) => format?.endsWith(UNITS_OF_MEASURE[id]))
}

View File

@ -13,6 +13,7 @@ import {
getGroupParameter,
getOptions,
getSemanticFormat,
getSupportedRange,
getTemperatureScale,
getUnitOfMeasure,
titleCase
@ -202,7 +203,7 @@ export default {
name: 'nonControllable',
label: 'Non-Controllable',
type: 'BOOLEAN',
default: (stateDescription && stateDescription.readOnly) === true,
default: stateDescription?.readOnly === true,
visible: (_, config) => !!config.retrievable
}),
ordered: () => ({
@ -229,14 +230,12 @@ export default {
` (${docLink('Asset Catalog')})`,
type: 'TEXT',
default:
stateDescription &&
stateDescription.options &&
stateDescription.options
.filter((option) => !isNaN(option.value))
stateDescription?.options?.filter((option) => !isNaN(option.value))
.map((option) => `${option.value}=${option.label}`)
.slice(0, STATE_DESCRIPTION_OPTIONS_LIMIT),
placeholder: placeholder.replace(/,/g, '\n'),
multiple: true
multiple: true,
visible: (_, config) => !config.nonControllable
}),
primaryControl: () => ({
name: 'primaryControl',
@ -356,10 +355,7 @@ export default {
description: 'Each input formatted as <code>inputValue=inputName1:inputName2:...</code>',
type: 'TEXT',
default:
stateDescription &&
stateDescription.options &&
stateDescription.options
.map((option) => `${option.value}=${option.label}`)
stateDescription?.options?.map((option) => `${option.value}=${option.label}`)
.slice(0, STATE_DESCRIPTION_OPTIONS_LIMIT),
placeholder: placeholder.replace(/,/g, '\n'),
multiple: true,
@ -372,10 +368,7 @@ export default {
`Each mode formatted as <code>mode=@assetIdOrName1:@assetIdOrName2:...</code> (${docLink('Asset Catalog')})`,
type: 'TEXT',
default:
stateDescription &&
stateDescription.options &&
stateDescription.options
.map((option) => `${option.value}=${option.label}`)
stateDescription?.options?.map((option) => `${option.value}=${option.label}`)
.slice(0, STATE_DESCRIPTION_OPTIONS_LIMIT),
placeholder: 'Normal=Normal:Cottons\nWhites=Whites',
multiple: true,
@ -391,18 +384,12 @@ export default {
multiple: true,
advanced: true
}),
supportedRange: (stateDescription, defaultValue) => ({
supportedRange: (item, config, defaultValue) => ({
name: 'supportedRange',
label: 'Supported Range',
description: 'Formatted as <code>minValue:maxValue:precision</code>',
type: 'TEXT',
default:
stateDescription &&
!isNaN(stateDescription.minimum) &&
!isNaN(stateDescription.maximum) &&
!isNaN(stateDescription.step)
? `${stateDescription.minimum}:${stateDescription.maximum}:${stateDescription.step}`
: defaultValue,
default: getSupportedRange(item, config, defaultValue),
pattern: '[+-]?[0-9]+:[+-]?[0-9]+:[0-9]+'
}),
supportedThermostatModes: () => ({