Skip to content

Commit

Permalink
fix: Add modern extend for 'text' converter (#7846)
Browse files Browse the repository at this point in the history
  • Loading branch information
chdefrene authored Dec 8, 2024
1 parent c6f6bef commit 1fb99be
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 24 deletions.
15 changes: 0 additions & 15 deletions src/converters/toZigbee.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1891,21 +1891,6 @@ const converters2 = {
// #endregion

// #region Non-generic converters
elko_display_text: {
key: ['display_text'],
convertSet: async (entity, key, value, meta) => {
utils.assertString(value);
if (value.length <= 14) {
await entity.write('hvacThermostat', {elkoDisplayText: value});
return {state: {display_text: value}};
} else {
throw new Error('Length of text is greater than 14');
}
},
convertGet: async (entity, key, meta) => {
await entity.read('hvacThermostat', ['elkoDisplayText']);
},
} satisfies Tz.Converter,
elko_power_status: {
key: ['system_mode'],
convertSet: async (entity, key, value, meta) => {
Expand Down
23 changes: 14 additions & 9 deletions src/devices/elko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import fz from '../converters/fromZigbee';
import tz from '../converters/toZigbee';
import * as constants from '../lib/constants';
import * as exposes from '../lib/exposes';
import {binary, enumLookup, light, numeric} from '../lib/modernExtend';
import {binary, enumLookup, light, numeric, text} from '../lib/modernExtend';
import * as reporting from '../lib/reporting';
import {DefinitionWithExtend} from '../lib/types';
import {assertString} from '../lib/utils';

const ea = exposes.access;
const e = exposes.presets;
Expand Down Expand Up @@ -38,14 +39,19 @@ const definitions: DefinitionWithExtend[] = [
vendor: 'ELKO',
description: 'ESH Plus Super TR RF PH',
fromZigbee: [fz.elko_thermostat],
toZigbee: [
tz.thermostat_occupied_heating_setpoint,
tz.elko_display_text,
tz.elko_power_status,
tz.elko_relay_state,
tz.elko_local_temperature_calibration,
],
toZigbee: [tz.thermostat_occupied_heating_setpoint, tz.elko_power_status, tz.elko_relay_state, tz.elko_local_temperature_calibration],
extend: [
text({
name: 'display_text',
cluster: 'hvacThermostat',
attribute: 'elkoDisplayText',
description: 'Displayed text on thermostat display (zone). Max 14 characters',
access: 'ALL',
validate: (value) => {
assertString(value);
if (value.length > 14) throw new Error('Length of text is greater than 14');
},
}),
numeric({
name: 'load',
cluster: 'hvacThermostat',
Expand Down Expand Up @@ -154,7 +160,6 @@ const definitions: DefinitionWithExtend[] = [
}),
],
exposes: [
e.text('display_text', ea.ALL).withDescription('Displayed text on thermostat display (zone). Max 14 characters'),
e
.climate()
.withSetpoint('occupied_heating_setpoint', 5, 50, 1)
Expand Down
59 changes: 59 additions & 0 deletions src/lib/modernExtend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2243,6 +2243,65 @@ export function binary(args: BinaryArgs): ModernExtend {
return {exposes: [expose], fromZigbee, toZigbee, configure, isModernExtend: true};
}

export interface TextArgs {
name: string;
cluster: string | number;
attribute: string | {ID: number; type: number};
description: string;
zigbeeCommandOptions?: {manufacturerCode: number};
endpointName?: string;
reporting?: ReportingConfig;
access?: 'STATE' | 'STATE_GET' | 'STATE_SET' | 'SET' | 'ALL';
entityCategory?: 'config' | 'diagnostic';
validate?(value: unknown): void;
}
export function text(args: TextArgs): ModernExtend {
const {name, cluster, attribute, description, zigbeeCommandOptions, endpointName, reporting, entityCategory, validate} = args;
const attributeKey = isString(attribute) ? attribute : attribute.ID;
const access = ea[args.access ?? 'ALL'];

let expose = e.text(name, access).withDescription(description);
if (endpointName) expose = expose.withEndpoint(endpointName);
if (entityCategory) expose = expose.withCategory(entityCategory);

const fromZigbee: Fz.Converter[] = [
{
cluster: cluster.toString(),
type: ['attributeReport', 'readResponse'],
convert: (model, msg, publish, options, meta) => {
if (attributeKey in msg.data && (!endpointName || getEndpointName(msg, model, meta) === endpointName)) {
return {[expose.property]: msg.data[attributeKey]};
}
},
},
];

const toZigbee: Tz.Converter[] = [
{
key: [name],
convertSet:
access & ea.SET
? async (entity, key, value, meta) => {
void validate(value);
const payload = isString(attribute) ? {[attribute]: value} : {[attribute.ID]: {value, type: attribute.type}};
await determineEndpoint(entity, meta, cluster).write(cluster, payload, zigbeeCommandOptions);
return {state: {[key]: value}};
}
: undefined,
convertGet:
access & ea.GET
? async (entity, key, meta) => {
await determineEndpoint(entity, meta, cluster).read(cluster, [attributeKey], zigbeeCommandOptions);
}
: undefined,
},
];

const configure: Configure[] = [setupConfigureForReporting(cluster, attribute, reporting, access)];

return {exposes: [expose], fromZigbee, toZigbee, configure, isModernExtend: true};
}

export type Parse = (msg: Fz.Message, attributeKey: string | number) => unknown;
export interface ActionEnumLookupArgs {
actionLookup: KeyValue;
Expand Down

0 comments on commit 1fb99be

Please sign in to comment.