Skip to content

Add support for new ubisys S1-R (Series 2). #7915

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

Merged
merged 4 commits into from
Sep 6, 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
58 changes: 58 additions & 0 deletions src/devices/ubisys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as constants from '../lib/constants';
import * as exposes from '../lib/exposes';
import * as legacy from '../lib/legacy';
import {logger} from '../lib/logger';
import {commandsColorCtrl, commandsLevelCtrl, commandsOnOff, deviceEndpoints, electricityMeter, identify, onOff} from '../lib/modernExtend';
import * as ota from '../lib/ota';
import * as reporting from '../lib/reporting';
import {DefinitionWithExtend, Fz, OnEventType, Tz, OnEventData, Zh, KeyValue, KeyValueAny} from '../lib/types';
Expand Down Expand Up @@ -38,6 +39,15 @@ const ubisysOnEventReadCurrentSummDelivered = async function (type: OnEventType,
}
};

const ubisysPollCurrentSummDelivered = async (type: OnEventType, data: OnEventData, device: Zh.Device, endpointId: number, options: KeyValue) => {
const endpoint = device.getEndpoint(endpointId);
const poll = async () => {
await endpoint.read('seMetering', ['currentSummDelivered']);
};

utils.onEventPoll(type, data, device, options, 'measurement', 60, poll);
};

const ubisys = {
fz: {
dimmer_setup: {
Expand Down Expand Up @@ -725,6 +735,54 @@ const definitions: DefinitionWithExtend[] = [
},
ota: ota.ubisys,
},
{
// S1-R Series 2 uses the same modelId as the regular S1-R, but the energy clusters are located in endpoint 1 (instead of 4, like the regular S1-R).
fingerprint: [
{
manufacturerName: 'ubisys',
modelID: 'S1-R (5601)',
endpoints: [{ID: 1, profileID: 260, deviceID: 266, inputClusters: [0, 3, 4, 5, 6, 1794, 2820], outputClusters: []}],
},
],
model: 'S1-R-2',
vendor: 'ubisys',
description: 'Power switch S1-R (Series 2)',
extend: [
deviceEndpoints({endpoints: {'1': 1, '2': 2, '3': 3, '232': 232}, multiEndpointSkip: ['state', 'power', 'energy']}),
identify(),
onOff({powerOnBehavior: false}),
electricityMeter({cluster: 'metering', configureReporting: false}),
commandsOnOff({endpointNames: ['2', '3']}),
commandsLevelCtrl({endpointNames: ['2', '3']}),
commandsColorCtrl({endpointNames: ['2', '3']}),
],
options: [exposes.options.measurement_poll_interval()],
configure: async (device, coordinatorEndpoint) => {
const endpoint = device.getEndpoint(1);
Copy link
Owner

Choose a reason for hiding this comment

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

Everything inside here is not needed because of electricityMeter

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think its needed because configureReporting is set to false for electricityMeter. The reason is that the currentSummDelivered is not bindable for this device (as far i can tell for the most ubisys devices). As workaround only the instantaneousDemand attribute is binded manually and currentSummDelivered read in onEvent.

Copy link
Owner

Choose a reason for hiding this comment

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

I see now, I think we can improve the ubisysOnEventReadCurrentSummDelivered a bit, I see 2 issues with it:

  • In case the Ubisys devices is sending a lot of messages, a lot of reads are done
  • In case no messages are send, the value becomes stale

We can solve this by polling at a certain interval, you can use the Tuya one as an example

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good. I will take a closer look at the weekend when I have the device for testing at hand.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was a bit uncertain to change this for devices i do not own myself, so i added a separate method that can be used for polling.

await reporting.bind(endpoint, coordinatorEndpoint, ['seMetering']);
await reporting.readMeteringMultiplierDivisor(endpoint);
await reporting.instantaneousDemand(endpoint);
},
onEvent: async (type, data, device, settings) => {
/*
* As per technical doc page 18 section 7.3.4
* https://www.ubisys.de/wp-content/uploads/ubisys-s1-technical-reference.pdf
*
* This cluster uses the binding table for managing command targets.
* When factory fresh, this cluster is bound to endpoint #1 to
* enable local control.
*
* We use addBinding to 'record' this default binding.
*/
if (type === 'deviceInterview') {
const ep1 = device.getEndpoint(1);
const ep2 = device.getEndpoint(2);
ep2.addBinding('genOnOff', ep1);
} else {
await ubisysPollCurrentSummDelivered(type, data, device, 1, settings);
}
},
},
{
zigbeeModel: ['S2 (5502)', 'S2-R (5602)'],
model: 'S2',
Expand Down
Loading