Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Inovelli VZM30-SN switch #8469

Merged
merged 1 commit into from
Dec 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 55 additions & 2 deletions src/devices/inovelli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Zcl} from 'zigbee-herdsman';
import fz from '../converters/fromZigbee';
import tz from '../converters/toZigbee';
import * as exposes from '../lib/exposes';
import {deviceAddCustomCluster, deviceEndpoints, electricityMeter, identify} from '../lib/modernExtend';
import {deviceAddCustomCluster, deviceEndpoints, electricityMeter, humidity, identify, temperature} from '../lib/modernExtend';
import * as reporting from '../lib/reporting';
import * as globalStore from '../lib/store';
import {DefinitionWithExtend, Expose, Fz, Tz, Zh} from '../lib/types';
Expand Down Expand Up @@ -478,6 +478,8 @@ const COMMON_ATTRIBUTES: {[s: string]: Attribute} = {
max: 127,
readOnly: true,
description: 'The temperature measured by the temperature sensor inside the chip, in degrees Celsius',
category: 'diagnostic',
unit: '°C',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Koenkk - I just realized that on all of the Inovelli devices, the internalTemperature parameter doesn't show up as the device_class: temperature when MQTT sends it to Home Assistant. I thought adding the unit and category would fix that, but it doesn't seem to be doing so. Is there something else that needs to be set?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool - since it's a separate repo, we can handle it separately after this is merged if that's okay with you.

},
overheat: {
ID: 33,
Expand Down Expand Up @@ -1005,6 +1007,16 @@ const COMMON_DIMMER_ON_OFF_ATTRIBUTES: {[s: string]: Attribute} = {
},
};

const VZM30_ATTRIBUTES: {[s: string]: Attribute} = {
...COMMON_ATTRIBUTES,
...COMMON_DIMMER_ON_OFF_ATTRIBUTES,
switchType: {
...COMMON_ATTRIBUTES.switchType,
values: {'Single Pole': 0, 'Aux Switch': 1},
max: 1,
},
};

const VZM31_ATTRIBUTES: {[s: string]: Attribute} = {
...COMMON_DIMMER_ATTRIBUTES,
...COMMON_DIMMER_ON_OFF_ATTRIBUTES,
Expand Down Expand Up @@ -1917,13 +1929,16 @@ const exposeBreezeMode = () => {
.withCategory('config');
};

const exposesListVZM30: Expose[] = [e.light_brightness(), exposeLedEffects(), exposeIndividualLedEffects()];

const exposesListVZM31: Expose[] = [e.light_brightness(), exposeLedEffects(), exposeIndividualLedEffects()];

const exposesListVZM35: Expose[] = [e.fan().withModes(Object.keys(fanModes)), exposeLedEffects(), exposeIndividualLedEffects(), exposeBreezeMode()];

const exposesListVZM36: Expose[] = [e.light_brightness(), e.fan().withModes(Object.keys(fanModes)), exposeBreezeMode()];

// Populate exposes list from the attributes description
attributesToExposeList(VZM30_ATTRIBUTES, exposesListVZM30);
attributesToExposeList(VZM31_ATTRIBUTES, exposesListVZM31);
attributesToExposeList(VZM35_ATTRIBUTES, exposesListVZM35);
attributesToExposeList(VZM36_ATTRIBUTES, exposesListVZM36);
Expand Down Expand Up @@ -1953,11 +1968,49 @@ const buttonTapSequences = [
'config_quintuple',
];

exposesListVZM30.push(e.action(buttonTapSequences));
exposesListVZM31.push(e.action(buttonTapSequences));

exposesListVZM35.push(e.action(buttonTapSequences));

const definitions: DefinitionWithExtend[] = [
{
zigbeeModel: ['VZM30-SN'],
model: 'VZM30-SN',
vendor: 'Inovelli',
description: 'On/off switch',
exposes: exposesListVZM30.concat(identify().exposes as Expose[]),
extend: [
deviceEndpoints({
endpoints: {'1': 1, '2': 2, '3': 3, '4': 4},
multiEndpointSkip: ['state', 'voltage', 'power', 'current', 'energy', 'brightness', 'temperature', 'humidity'],
}),
inovelliExtend.addCustomClusterInovelli(),
temperature(),
humidity(),
electricityMeter(),
],
toZigbee: [
tzLocal.light_onoff_brightness_inovelli,
tz.power_on_behavior,
tz.ignore_transition,
tz.identify,
tzLocal.inovelli_led_effect,
tzLocal.inovelli_individual_led_effect,
tzLocal.inovelli_parameters(VZM30_ATTRIBUTES),
tzLocal.inovelli_parameters_readOnly(VZM30_ATTRIBUTES),
],
fromZigbee: [fz.on_off, fz.brightness, fz.level_config, fz.power_on_behavior, fz.ignore_basic_report, fzLocal.inovelli(VZM30_ATTRIBUTES)],
ota: true,
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
await reporting.bind(endpoint, coordinatorEndpoint, ['genOnOff', 'genLevelCtrl']);
await reporting.onOff(endpoint);

// Bind for Button Event Reporting
const endpoint2 = device.getEndpoint(2);
await reporting.bind(endpoint2, coordinatorEndpoint, ['manuSpecificInovelli']);
},
},
{
zigbeeModel: ['VZM31-SN'],
model: 'VZM31-SN',
Expand Down
Loading