1+ import { Zcl } from "zigbee-herdsman" ;
2+
13import * as fz from "../converters/fromZigbee" ;
24import * as tz from "../converters/toZigbee" ;
35import * as exposes from "../lib/exposes" ;
@@ -117,6 +119,50 @@ const fzLocal = {
117119 return payload ;
118120 } ,
119121 } satisfies Fz . Converter ,
122+
123+ owonFds315 : {
124+ cluster : "fallDetectionOwon" ,
125+ type : [ "attributeReport" , "readResponse" ] ,
126+ convert : ( model , msg , publish , options , meta ) => {
127+ const result : Record < string , unknown > = { } ;
128+ const data = msg . data ;
129+ const status_mapping : Record < number , string > = {
130+ 0 : "unoccupied" ,
131+ 1 : "occupied" ,
132+ 2 : "sitting" ,
133+ 3 : "on_the_bed" ,
134+ 4 : "low_posture" ,
135+ 5 : "falling" ,
136+ } ;
137+
138+ if ( data . status !== undefined ) {
139+ const code = data . status ;
140+ result . status = status_mapping [ code ] || `Unknown (${ code } )` ;
141+ }
142+ if ( data . breathing_rate !== undefined ) result . breathing_rate = data . breathing_rate ;
143+ if ( data . location_x !== undefined ) result . location_x = data . location_x ;
144+ if ( data . location_y !== undefined ) result . location_y = data . location_y ;
145+
146+ const keys = [
147+ "bedUpperLeftX" ,
148+ "bedUpperLeftY" ,
149+ "bedLowerRightX" ,
150+ "bedLowerRightY" ,
151+ "doorCenterX" ,
152+ "doorCenterY" ,
153+ "leftFallDetectionRange" ,
154+ "rightFallDetectionRange" ,
155+ "frontFallDetectionRange" ,
156+ ] ;
157+ const values = keys . map ( ( k ) => ( data [ k ] !== undefined ? data [ k ] : null ) ) ;
158+
159+ if ( ! values . includes ( null ) ) {
160+ result . fall_detection_settings = values . join ( "," ) ;
161+ }
162+
163+ return result ;
164+ } ,
165+ } satisfies Fz . Converter ,
120166} ;
121167
122168const tzLocal = {
@@ -127,6 +173,50 @@ const tzLocal = {
127173 await entity . command ( 0xffe0 , 0x00 , { } , { disableDefaultResponse : true } ) ;
128174 } ,
129175 } satisfies Tz . Converter ,
176+
177+ owonFds315SetFallSettings : {
178+ key : [ "fall_detection_settings" ] ,
179+ convertSet : async ( entity , key , value , meta ) => {
180+ const mapping : Record < number , { id : number ; type : number } > = {
181+ 0 : { id : 0x0100 , type : 0x29 } ,
182+ 1 : { id : 0x0101 , type : 0x29 } ,
183+ 2 : { id : 0x0102 , type : 0x29 } ,
184+ 3 : { id : 0x0103 , type : 0x29 } ,
185+ 4 : { id : 0x0108 , type : 0x29 } ,
186+ 5 : { id : 0x0109 , type : 0x29 } ,
187+ 6 : { id : 0x010c , type : 0x21 } ,
188+ 7 : { id : 0x010d , type : 0x21 } ,
189+ 8 : { id : 0x010e , type : 0x21 } ,
190+ } ;
191+
192+ const strValue = String ( value ) ;
193+ const values = strValue ?. split ( "," ) . map ( Number ) ;
194+ if ( values . length !== 9 ) throw new Error ( "Incorrect number of values." ) ;
195+
196+ const payload : Record < number , { value : number ; type : number } > = { } ;
197+ values . forEach ( ( val , idx ) => {
198+ const { id, type} = mapping [ idx ] ;
199+ payload [ id ] = { value : val , type} ;
200+ } ) ;
201+
202+ await entity . write ( "fallDetectionOwon" , payload , { manufacturerCode : 0x113c } ) ;
203+ return { state : { fall_detection_settings : value } } ;
204+ } ,
205+ convertGet : async ( entity , key , meta ) => {
206+ const attrs = [
207+ "bedUpperLeftX" ,
208+ "bedUpperLeftY" ,
209+ "bedLowerRightX" ,
210+ "bedLowerRightY" ,
211+ "doorCenterX" ,
212+ "doorCenterY" ,
213+ "leftFallDetectionRange" ,
214+ "rightFallDetectionRange" ,
215+ "frontFallDetectionRange" ,
216+ ] ;
217+ await entity . read ( "fallDetectionOwon" , attrs , { manufacturerCode : 0x113c } ) ;
218+ } ,
219+ } satisfies Tz . Converter ,
130220} ;
131221
132222export const definitions : DefinitionWithExtend [ ] = [
@@ -479,4 +569,52 @@ export const definitions: DefinitionWithExtend[] = [
479569 description : "Sleeping pad monitor" ,
480570 extend : [ m . battery ( ) , m . iasZoneAlarm ( { zoneType : "contact" , zoneAttributes : [ "alarm_1" , "battery_low" , "tamper" ] } ) ] ,
481571 } ,
572+ {
573+ zigbeeModel : [ "FDS315" ] ,
574+ model : "FDS315" ,
575+ vendor : "OWON" ,
576+ description : "Fall Detection Sensor" ,
577+ extend : [
578+ m . deviceAddCustomCluster ( "fallDetectionOwon" , {
579+ ID : 0xfd00 ,
580+ manufacturerCode : Zcl . ManufacturerCode . OWON_TECHNOLOGY_INC ,
581+ attributes : {
582+ status : { ID : 0x0000 , type : Zcl . DataType . ENUM8 } ,
583+ breathing_rate : { ID : 0x0002 , type : Zcl . DataType . UINT8 } ,
584+ location_x : { ID : 0x0003 , type : Zcl . DataType . INT16 } ,
585+ location_y : { ID : 0x0004 , type : Zcl . DataType . INT16 } ,
586+ bedUpperLeftX : { ID : 0x0100 , type : Zcl . DataType . INT16 } ,
587+ bedUpperLeftY : { ID : 0x0101 , type : Zcl . DataType . INT16 } ,
588+ bedLowerRightX : { ID : 0x0102 , type : Zcl . DataType . INT16 } ,
589+ bedLowerRightY : { ID : 0x0103 , type : Zcl . DataType . INT16 } ,
590+ doorCenterX : { ID : 0x0108 , type : Zcl . DataType . INT16 } ,
591+ doorCenterY : { ID : 0x0109 , type : Zcl . DataType . INT16 } ,
592+ leftFallDetectionRange : { ID : 0x010c , type : Zcl . DataType . UINT16 } ,
593+ rightFallDetectionRange : { ID : 0x010d , type : Zcl . DataType . UINT16 } ,
594+ frontFallDetectionRange : { ID : 0x010e , type : Zcl . DataType . UINT16 } ,
595+ } ,
596+ commands : { } ,
597+ commandsResponse : { } ,
598+ } ) ,
599+ ] ,
600+ fromZigbee : [ fz . identify , fzLocal . owonFds315 ] ,
601+ toZigbee : [ tzLocal . owonFds315SetFallSettings ] ,
602+ exposes : [
603+ e . enum ( "status" , ea . STATE , [ "unoccupied" , "occupied" , "sitting" , "on_the_bed" , "low_posture" , "falling" ] ) ,
604+ e . numeric ( "breathing_rate" , ea . STATE ) . withUnit ( "breaths/min" ) . withDescription ( "Breathing rate." ) ,
605+ e . numeric ( "location_x" , ea . STATE ) . withUnit ( "cm" ) . withDescription ( "X coordinate of human activity." ) ,
606+ e . numeric ( "location_y" , ea . STATE ) . withUnit ( "cm" ) . withDescription ( "Y coordinate of human activity." ) ,
607+ e
608+ . text ( "fall_detection_settings" , ea . ALL )
609+ . withDescription (
610+ "Comma-separated values for bed, door and fall detection settings: bedUpperLeftX, bedUpperLeftY, bedLowerRightX, bedLowerRightY, doorCenterX, doorCenterY, leftFallDetectionRange, rightFallDetectionRange, frontFallDetectionRange. Put -21931 for disabled bed and door." ,
611+ ) ,
612+ ] ,
613+ configure : async ( device , coordinatorEndpoint ) => {
614+ const endpoint = device . getEndpoint ( 1 ) ;
615+ await endpoint . bind ( "ssIasZone" , coordinatorEndpoint ) ;
616+ await endpoint . bind ( "genBasic" , coordinatorEndpoint ) ;
617+ await endpoint . bind ( "fallDetectionOwon" , coordinatorEndpoint ) ;
618+ } ,
619+ } ,
482620] ;
0 commit comments