@@ -3,10 +3,20 @@ import { faClose, faPlus } from "@fortawesome/free-solid-svg-icons";
33import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" ;
44import { type JSX , memo , useCallback , useEffect , useMemo , useRef , useState } from "react" ;
55import { useTranslation } from "react-i18next" ;
6+ import type { Zigbee2MQTTAPI } from "zigbee2mqtt" ;
7+ import { useShallow } from "zustand/react/shallow" ;
8+ import { type AppState , useAppStore } from "../../../store.js" ;
69import type { Device } from "../../../types.js" ;
710import { sendMessage } from "../../../websocket/WebSocketManager.js" ;
811import Button from "../../Button.js" ;
9- import { aggregateReporting , makeDefaultReporting , type ReportingEndpoint , type ReportingRule } from "../../reporting/index.js" ;
12+ import {
13+ aggregateReporting ,
14+ getClusterAttribute ,
15+ isAnalogDataType ,
16+ makeDefaultReporting ,
17+ type ReportingEndpoint ,
18+ type ReportingRule ,
19+ } from "../../reporting/index.js" ;
1020import ReportingRow from "../ReportingRow.js" ;
1121
1222interface ReportingProps {
@@ -18,12 +28,13 @@ interface ReportingEndpointSectionProps extends ReportingEndpoint {
1828 device : Device ;
1929 sourceIdx : number ;
2030 onApply ( rule : ReportingRule ) : Promise < void > ;
31+ bridgeDefinitions : AppState [ "bridgeDefinitions" ] [ number ] ;
2132}
2233
2334const getRuleKey = ( rule : ReportingRule ) : string =>
2435 `${ rule . endpoint } -${ rule . cluster } -${ rule . attribute } -${ rule . minimum_report_interval } -${ rule . maximum_report_interval } ` ;
2536
26- const ReportingEndpointSection = memo ( ( { endpointId, rules, device, sourceIdx, onApply } : ReportingEndpointSectionProps ) => {
37+ const ReportingEndpointSection = memo ( ( { endpointId, rules, device, sourceIdx, onApply, bridgeDefinitions } : ReportingEndpointSectionProps ) => {
2738 const { t } = useTranslation ( [ "zigbee" , "common" ] ) ;
2839 const arrowRef = useRef ( null ) ;
2940 const [ isAddOpen , setIsAddOpen ] = useState ( false ) ;
@@ -84,6 +95,7 @@ const ReportingEndpointSection = memo(({ endpointId, rules, device, sourceIdx, o
8495 key = { getRuleKey ( rule ) }
8596 sourceIdx = { sourceIdx }
8697 rule = { rule }
98+ bridgeDefinitions = { bridgeDefinitions }
8799 device = { device }
88100 onApply = { handleApply }
89101 onSync = { onSync }
@@ -112,7 +124,14 @@ const ReportingEndpointSection = memo(({ endpointId, rules, device, sourceIdx, o
112124 < FontAwesomeIcon icon = { faClose } />
113125 </ Button >
114126 </ div >
115- < ReportingRow sourceIdx = { sourceIdx } rule = { draftRule } device = { device } onApply = { handleApply } showDivider = { false } />
127+ < ReportingRow
128+ sourceIdx = { sourceIdx }
129+ rule = { draftRule }
130+ bridgeDefinitions = { bridgeDefinitions }
131+ device = { device }
132+ onApply = { handleApply }
133+ showDivider = { false }
134+ />
116135 </ div >
117136 < FloatingArrow
118137 ref = { arrowRef }
@@ -128,30 +147,45 @@ const ReportingEndpointSection = memo(({ endpointId, rules, device, sourceIdx, o
128147} ) ;
129148
130149export default function Reporting ( { sourceIdx, device } : ReportingProps ) : JSX . Element {
150+ const bridgeDefinitions = useAppStore ( useShallow ( ( state ) => state . bridgeDefinitions [ sourceIdx ] ) ) ;
131151 const reportingsByEndpoints = useMemo ( ( ) => aggregateReporting ( device ) , [ device ] ) ;
132152
133153 const onApply = useCallback (
134154 async ( rule : ReportingRule ) : Promise < void > => {
135155 const { cluster, endpoint, attribute, minimum_report_interval, maximum_report_interval, reportable_change } = rule ;
136-
137- await sendMessage ( sourceIdx , "bridge/request/device/reporting/configure" , {
156+ const attrDef = getClusterAttribute ( bridgeDefinitions , device . ieee_address , cluster , attribute ) ;
157+ // default to consider analog if can't find attribute definition
158+ const isAnalogAttribute = attrDef == null || isAnalogDataType ( attrDef ) ;
159+ const payload : Zigbee2MQTTAPI [ "bridge/request/device/reporting/configure" ] = {
138160 id : device . ieee_address ,
139161 endpoint,
140162 cluster,
141163 attribute,
142164 minimum_report_interval,
143165 maximum_report_interval,
144- reportable_change,
145166 option : { } , // TODO: check this
146- } ) ;
167+ } ;
168+
169+ if ( isAnalogAttribute ) {
170+ payload . reportable_change = reportable_change ;
171+ }
172+
173+ await sendMessage ( sourceIdx , "bridge/request/device/reporting/configure" , payload ) ;
147174 } ,
148- [ sourceIdx , device . ieee_address ] ,
175+ [ sourceIdx , device . ieee_address , bridgeDefinitions ] ,
149176 ) ;
150177
151178 return (
152179 < div className = "flex flex-col w-full gap-3" >
153180 { reportingsByEndpoints . map ( ( reportings ) => (
154- < ReportingEndpointSection key = { reportings . endpointId } { ...reportings } device = { device } sourceIdx = { sourceIdx } onApply = { onApply } />
181+ < ReportingEndpointSection
182+ key = { reportings . endpointId }
183+ { ...reportings }
184+ device = { device }
185+ sourceIdx = { sourceIdx }
186+ onApply = { onApply }
187+ bridgeDefinitions = { bridgeDefinitions }
188+ />
155189 ) ) }
156190 </ div >
157191 ) ;
0 commit comments