@@ -25,13 +25,152 @@ import {
25
25
} from '../lib/modernExtend' ;
26
26
import * as reporting from '../lib/reporting' ;
27
27
import * as globalStore from '../lib/store' ;
28
- import { DefinitionWithExtend , Fz , Zh } from '../lib/types' ;
28
+ import { Configure , DefinitionWithExtend , Expose , Fz , ModernExtend , Tz , Zh } from '../lib/types' ;
29
29
import * as utils from '../lib/utils' ;
30
30
31
31
const NS = 'zhc:sunricher' ;
32
32
const e = exposes . presets ;
33
33
const ea = exposes . access ;
34
34
35
+ const sunricherManufacturerCode = 0x1224 ;
36
+
37
+ function sunricherExternalSwitchType ( ) : ModernExtend {
38
+ const attribute = 0x8803 ;
39
+ const data_type = 0x20 ;
40
+ const value_map : { [ key : number ] : string } = {
41
+ 0 : 'push_button' ,
42
+ 1 : 'normal_on_off' ,
43
+ 2 : 'three_way' ,
44
+ } ;
45
+ const value_lookup : { [ key : string ] : number } = {
46
+ push_button : 0 ,
47
+ normal_on_off : 1 ,
48
+ three_way : 2 ,
49
+ } ;
50
+
51
+ const fromZigbee : Fz . Converter [ ] = [
52
+ {
53
+ cluster : 'genBasic' ,
54
+ type : [ 'attributeReport' , 'readResponse' ] ,
55
+ convert : ( model , msg , publish , options , meta ) => {
56
+ if ( Object . prototype . hasOwnProperty . call ( msg . data , attribute ) ) {
57
+ const value = msg . data [ attribute ] ;
58
+ return {
59
+ external_switch_type : value_map [ value ] || 'unknown' ,
60
+ external_switch_type_numeric : value ,
61
+ } ;
62
+ }
63
+ return undefined ;
64
+ } ,
65
+ } satisfies Fz . Converter ,
66
+ ] ;
67
+
68
+ const toZigbee : Tz . Converter [ ] = [
69
+ {
70
+ key : [ 'external_switch_type' ] ,
71
+ convertSet : async ( entity , key , value : string , meta ) => {
72
+ const numericValue = value_lookup [ value ] ?? parseInt ( value , 10 ) ;
73
+ await entity . write ( 'genBasic' , { [ attribute ] : { value : numericValue , type : data_type } } , { manufacturerCode : sunricherManufacturerCode } ) ;
74
+ return { state : { external_switch_type : value } } ;
75
+ } ,
76
+ convertGet : async ( entity , key , meta ) => {
77
+ await entity . read ( 'genBasic' , [ attribute ] , { manufacturerCode : sunricherManufacturerCode } ) ;
78
+ } ,
79
+ } satisfies Tz . Converter ,
80
+ ] ;
81
+
82
+ const exposes : Expose [ ] = [
83
+ e . enum ( 'external_switch_type' , ea . ALL , [ 'push_button' , 'normal_on_off' , 'three_way' ] ) . withLabel ( 'External switch type' ) ,
84
+ ] ;
85
+
86
+ const configure : [ Configure ] = [
87
+ async ( device , coordinatorEndpoint , definition ) => {
88
+ const endpoint = device . getEndpoint ( 1 ) ;
89
+ try {
90
+ await endpoint . read ( 'genBasic' , [ attribute ] , { manufacturerCode : sunricherManufacturerCode } ) ;
91
+ } catch ( error ) {
92
+ console . warn ( `Failed to read external switch type attribute: ${ error } ` ) ;
93
+ }
94
+ } ,
95
+ ] ;
96
+
97
+ return {
98
+ fromZigbee,
99
+ toZigbee,
100
+ exposes,
101
+ configure,
102
+ isModernExtend : true ,
103
+ } ;
104
+ }
105
+
106
+ function sunricherMinimumPWM ( ) : ModernExtend {
107
+ const attribute = 0x7809 ;
108
+ const data_type = 0x20 ;
109
+
110
+ const fromZigbee : Fz . Converter [ ] = [
111
+ {
112
+ cluster : 'genBasic' ,
113
+ type : [ 'attributeReport' , 'readResponse' ] ,
114
+ convert : ( model , msg , publish , options , meta ) => {
115
+ if ( Object . prototype . hasOwnProperty . call ( msg . data , attribute ) ) {
116
+ console . log ( `from ` , msg . data [ attribute ] ) ;
117
+ const value = Math . round ( msg . data [ attribute ] / 5.1 ) ;
118
+ return {
119
+ minimum_pwm : value ,
120
+ } ;
121
+ }
122
+ return undefined ;
123
+ } ,
124
+ } ,
125
+ ] ;
126
+
127
+ const toZigbee : Tz . Converter [ ] = [
128
+ {
129
+ key : [ 'minimum_pwm' ] ,
130
+ convertSet : async ( entity : Zh . Endpoint , key : string , value : number | string , meta ) => {
131
+ console . log ( `to ` , value ) ;
132
+ const numValue = typeof value === 'string' ? parseInt ( value ) : value ;
133
+ const zgValue = Math . round ( numValue * 5.1 ) ;
134
+ await entity . write ( 'genBasic' , { [ attribute ] : { value : zgValue , type : data_type } } , { manufacturerCode : sunricherManufacturerCode } ) ;
135
+ return { state : { minimum_pwm : numValue } } ;
136
+ } ,
137
+ convertGet : async ( entity : Zh . Endpoint , key : string , meta ) => {
138
+ await entity . read ( 'genBasic' , [ attribute ] , { manufacturerCode : sunricherManufacturerCode } ) ;
139
+ } ,
140
+ } ,
141
+ ] ;
142
+
143
+ const exposes : Expose [ ] = [
144
+ e
145
+ . numeric ( 'minimum_pwm' , ea . ALL )
146
+ . withLabel ( 'Minimum PWM' )
147
+ . withDescription ( 'Power off the device and wait for 3 seconds before reconnecting to apply the settings.' )
148
+ . withValueMin ( 0 )
149
+ . withValueMax ( 50 )
150
+ . withUnit ( '%' )
151
+ . withValueStep ( 1 ) ,
152
+ ] ;
153
+
154
+ const configure : [ Configure ] = [
155
+ async ( device , coordinatorEndpoint , definition ) => {
156
+ const endpoint = device . getEndpoint ( 1 ) ;
157
+ try {
158
+ await endpoint . read ( 'genBasic' , [ attribute ] , { manufacturerCode : sunricherManufacturerCode } ) ;
159
+ } catch ( error ) {
160
+ console . warn ( `Failed to read external switch type attribute: ${ error } ` ) ;
161
+ }
162
+ } ,
163
+ ] ;
164
+
165
+ return {
166
+ fromZigbee,
167
+ toZigbee,
168
+ exposes,
169
+ configure,
170
+ isModernExtend : true ,
171
+ } ;
172
+ }
173
+
35
174
const fzLocal = {
36
175
sunricher_SRZGP2801K45C : {
37
176
cluster : 'greenPower' ,
@@ -378,7 +517,7 @@ const definitions: DefinitionWithExtend[] = [
378
517
model : 'SR-ZG9040A/ZG9041A-D' ,
379
518
vendor : 'Sunricher' ,
380
519
description : 'Zigbee micro smart dimmer' ,
381
- extend : [ light ( { configureReporting : true } ) , electricityMeter ( ) ] ,
520
+ extend : [ light ( { configureReporting : true } ) , electricityMeter ( ) , sunricherExternalSwitchType ( ) , sunricherMinimumPWM ( ) ] ,
382
521
} ,
383
522
{
384
523
zigbeeModel : [ 'HK-ZD-DIM-A' ] ,
0 commit comments