@@ -12,7 +12,7 @@ import * as namron from "../lib/namron";
1212import * as reporting from "../lib/reporting" ;
1313import { payload } from "../lib/reporting" ;
1414import * as sunricher from "../lib/sunricher" ;
15- import type { DefinitionWithExtend , Fz , KeyValue , ModernExtend , Tz , Zh } from "../lib/types" ;
15+ import type { DefinitionWithExtend , DummyDevice , Expose , Fz , KeyValue , ModernExtend , Tz , Zh } from "../lib/types" ;
1616import * as utils from "../lib/utils" ;
1717import { addActionGroup , hasAlreadyProcessedMessage , postfixWithEndpointName } from "../lib/utils" ;
1818
@@ -21,6 +21,16 @@ const e = exposes.presets;
2121const ea = exposes . access ;
2222
2323const sunricherManufacturerCode = 0x1224 ;
24+ const sunricherDaliEndpointIds = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ] as const ;
25+ const sunricherDaliEndpointNames = [ "l1" , "l2" , "l3" , "l4" , "l5" , "l6" , "l7" , "l8" ] ;
26+ const sunricherDaliDimmableLightDeviceId = 0x0101 ;
27+ const sunricherDaliColorTempLightDeviceId = 0x010c ;
28+ const sunricherDaliColorTempRange : [ number , number ] = [ 150 , 500 ] ;
29+
30+ interface SunricherDaliEndpointInfo {
31+ id : number ;
32+ deviceID ?: number ;
33+ }
2434
2535export interface SunricherHvacThermostat {
2636 attributes : {
@@ -257,6 +267,93 @@ async function syncTimeWithTimeZone(endpoint: Zh.Endpoint) {
257267 }
258268}
259269
270+ function sunricherDaliIsEnabledEndpoint ( endpoint : Zh . Endpoint ) {
271+ return (
272+ sunricherDaliEndpointIds . includes ( endpoint . ID as ( typeof sunricherDaliEndpointIds ) [ number ] ) &&
273+ [ sunricherDaliDimmableLightDeviceId , sunricherDaliColorTempLightDeviceId ] . includes ( endpoint . deviceID )
274+ ) ;
275+ }
276+
277+ function sunricherDaliIsColorTempEndpoint ( endpoint : { deviceID ?: number } ) {
278+ return endpoint . deviceID === sunricherDaliColorTempLightDeviceId ;
279+ }
280+
281+ function sunricherDaliEndpointName ( endpointID : number ) {
282+ return `l${ endpointID } ` ;
283+ }
284+
285+ function sunricherDaliEnabledEndpoints ( device : Zh . Device ) {
286+ return device . endpoints . filter ( sunricherDaliIsEnabledEndpoint ) ;
287+ }
288+
289+ function sunricherDaliEndpointInfos ( device : Zh . Device | DummyDevice ) : SunricherDaliEndpointInfo [ ] {
290+ if ( "isDummyDevice" in device ) {
291+ return sunricherDaliEndpointIds . map ( ( id ) => ( { id, deviceID : sunricherDaliColorTempLightDeviceId } ) ) ;
292+ }
293+
294+ return sunricherDaliEnabledEndpoints ( device ) . map ( ( endpoint ) => ( { id : endpoint . ID , deviceID : endpoint . deviceID } ) ) ;
295+ }
296+
297+ function sunricherDaliEndpoint ( device : Zh . Device ) {
298+ return Object . fromEntries ( sunricherDaliEnabledEndpoints ( device ) . map ( ( endpoint ) => [ sunricherDaliEndpointName ( endpoint . ID ) , endpoint . ID ] ) ) ;
299+ }
300+
301+ function sunricherDaliExposes ( device : Zh . Device | DummyDevice ) : Expose [ ] {
302+ return sunricherDaliEndpointInfos ( device ) . map ( ( endpoint ) => {
303+ const expose = e . light ( ) . withBrightness ( ) ;
304+
305+ if ( sunricherDaliIsColorTempEndpoint ( endpoint ) ) {
306+ expose . withColorTemp ( sunricherDaliColorTempRange ) ;
307+ }
308+
309+ return expose . withEndpoint ( sunricherDaliEndpointName ( endpoint . id ) ) ;
310+ } ) ;
311+ }
312+
313+ async function sunricherDaliReadInitialState ( endpoint : Zh . Endpoint ) {
314+ await endpoint . read ( "genOnOff" , [ "onOff" ] ) ;
315+ await endpoint . read ( "genLevelCtrl" , [ "currentLevel" ] ) ;
316+
317+ if ( sunricherDaliIsColorTempEndpoint ( endpoint ) ) {
318+ await endpoint . read ( "lightingColorCtrl" , [ "colorMode" , "colorTemperature" ] ) ;
319+ }
320+ }
321+
322+ function sunricherDaliController ( ) : ModernExtend {
323+ return {
324+ fromZigbee : [ fz . on_off , fz . brightness , fz . level_config , fz . color_colortemp ] ,
325+ toZigbee : [
326+ { ...tz . light_onoff_brightness , endpoints : sunricherDaliEndpointNames } ,
327+ tz . ignore_transition ,
328+ tz . level_config ,
329+ tz . ignore_rate ,
330+ tz . light_brightness_move ,
331+ tz . light_brightness_step ,
332+ tz . light_colortemp ,
333+ tz . light_colortemp_move ,
334+ tz . light_colortemp_step ,
335+ tz . light_color_mode ,
336+ tz . light_color_options ,
337+ ] ,
338+ exposes : [ sunricherDaliExposes ] ,
339+ endpoint : sunricherDaliEndpoint ,
340+ meta : { multiEndpoint : true } ,
341+ configure : [
342+ async ( device , coordinatorEndpoint ) => {
343+ for ( const endpoint of sunricherDaliEnabledEndpoints ( device ) ) {
344+ const clusters = sunricherDaliIsColorTempEndpoint ( endpoint )
345+ ? [ "genOnOff" , "genLevelCtrl" , "lightingColorCtrl" ]
346+ : [ "genOnOff" , "genLevelCtrl" ] ;
347+
348+ await reporting . bind ( endpoint , coordinatorEndpoint , clusters ) ;
349+ await sunricherDaliReadInitialState ( endpoint ) ;
350+ }
351+ } ,
352+ ] ,
353+ isModernExtend : true ,
354+ } ;
355+ }
356+
260357export const definitions : DefinitionWithExtend [ ] = [
261358 {
262359 zigbeeModel : [ "HK-DIM-PIR" ] ,
@@ -1964,6 +2061,21 @@ export const definitions: DefinitionWithExtend[] = [
19642061 description : "Zigbee micro smart dimmer" ,
19652062 extend : [ m . light ( { configureReporting : true } ) , m . electricityMeter ( ) , sunricher . extend . externalSwitchType ( ) , sunricher . extend . minimumPWM ( ) ] ,
19662063 } ,
2064+ {
2065+ fingerprint : [
2066+ {
2067+ type : "Router" ,
2068+ modelID : "Light" ,
2069+ manufacturerID : sunricherManufacturerCode ,
2070+ manufacturerName : "Sunricher" ,
2071+ priority : 1 ,
2072+ } ,
2073+ ] ,
2074+ model : "SR-2421-Z2D8C" ,
2075+ vendor : "Sunricher" ,
2076+ description : "Zigbee to DALI controller" ,
2077+ extend : [ sunricherDaliController ( ) ] ,
2078+ } ,
19672079 {
19682080 zigbeeModel : [ "HK-ZD-DIM-A" ] ,
19692081 model : "SRP-ZG9105-CC" ,
0 commit comments