3
3
from __future__ import annotations
4
4
5
5
import logging
6
+ import math
6
7
from enum import Enum
7
8
from typing import Literal , overload
8
9
@@ -84,6 +85,50 @@ def _initialize_features(self) -> None:
84
85
attribute_setter = "set_threshold" ,
85
86
type = Feature .Type .Number ,
86
87
category = Feature .Category .Config ,
88
+ range_getter = lambda : (0 , 100 ),
89
+ )
90
+ )
91
+
92
+ self ._add_feature (
93
+ Feature (
94
+ device = self ._device ,
95
+ container = self ,
96
+ id = "pir_triggered" ,
97
+ name = "PIR Triggered" ,
98
+ icon = "mdi:motion-sensor" ,
99
+ attribute_getter = "pir_triggered" ,
100
+ attribute_setter = None ,
101
+ type = Feature .Type .Sensor ,
102
+ category = Feature .Category .Primary ,
103
+ )
104
+ )
105
+
106
+ self ._add_feature (
107
+ Feature (
108
+ device = self ._device ,
109
+ container = self ,
110
+ id = "pir_value" ,
111
+ name = "PIR Reading" ,
112
+ icon = "mdi:motion-sensor" ,
113
+ attribute_getter = "pir_value" ,
114
+ attribute_setter = None ,
115
+ type = Feature .Type .Sensor ,
116
+ category = Feature .Category .Info ,
117
+ )
118
+ )
119
+
120
+ self ._add_feature (
121
+ Feature (
122
+ device = self ._device ,
123
+ container = self ,
124
+ id = "pir_percent" ,
125
+ name = "PIR Percentage" ,
126
+ icon = "mdi:motion-sensor" ,
127
+ attribute_getter = "pir_percent" ,
128
+ attribute_setter = None ,
129
+ type = Feature .Type .Sensor ,
130
+ category = Feature .Category .Info ,
131
+ unit_getter = lambda : "%" ,
87
132
)
88
133
)
89
134
@@ -97,21 +142,49 @@ def _initialize_features(self) -> None:
97
142
attribute_getter = "adc_value" ,
98
143
attribute_setter = None ,
99
144
type = Feature .Type .Sensor ,
100
- category = Feature .Category .Primary ,
145
+ category = Feature .Category .Debug ,
101
146
)
102
147
)
103
148
104
149
self ._add_feature (
105
150
Feature (
106
151
device = self ._device ,
107
152
container = self ,
108
- id = "pir_triggered " ,
109
- name = "PIR Triggered " ,
153
+ id = "pir_adc_min " ,
154
+ name = "PIR ADC Min " ,
110
155
icon = "mdi:motion-sensor" ,
111
- attribute_getter = "is_triggered " ,
156
+ attribute_getter = "adc_min " ,
112
157
attribute_setter = None ,
113
158
type = Feature .Type .Sensor ,
114
- category = Feature .Category .Primary ,
159
+ category = Feature .Category .Debug ,
160
+ )
161
+ )
162
+
163
+ self ._add_feature (
164
+ Feature (
165
+ device = self ._device ,
166
+ container = self ,
167
+ id = "pir_adc_mid" ,
168
+ name = "PIR ADC Mid" ,
169
+ icon = "mdi:motion-sensor" ,
170
+ attribute_getter = "adc_midpoint" ,
171
+ attribute_setter = None ,
172
+ type = Feature .Type .Sensor ,
173
+ category = Feature .Category .Debug ,
174
+ )
175
+ )
176
+
177
+ self ._add_feature (
178
+ Feature (
179
+ device = self ._device ,
180
+ container = self ,
181
+ id = "pir_adc_max" ,
182
+ name = "PIR ADC Max" ,
183
+ icon = "mdi:motion-sensor" ,
184
+ attribute_getter = "adc_max" ,
185
+ attribute_setter = None ,
186
+ type = Feature .Type .Sensor ,
187
+ category = Feature .Category .Debug ,
115
188
)
116
189
)
117
190
@@ -134,6 +207,26 @@ def enabled(self) -> bool:
134
207
"""Return True if module is enabled."""
135
208
return bool (self .config ["enable" ])
136
209
210
+ @property
211
+ def adc_min (self ) -> int :
212
+ """Return minimum ADC sensor value."""
213
+ return int (self .config ["min_adc" ])
214
+
215
+ @property
216
+ def adc_max (self ) -> int :
217
+ """Return maximum ADC sensor value."""
218
+ return int (self .config ["max_adc" ])
219
+
220
+ @property
221
+ def adc_midpoint (self ) -> int :
222
+ """
223
+ Return the midpoint for the ADC (Analog to Digital Converter), representing the zero point for the PIR sensor waveform.
224
+
225
+ Currently this is estimated by:
226
+ math.floor(abs(adc_max - adc_min) / 2)
227
+ """
228
+ return math .floor (abs (self .adc_max - self .adc_min ) / 2 )
229
+
137
230
async def set_enabled (self , state : bool ) -> dict :
138
231
"""Enable/disable PIR."""
139
232
return await self .call ("set_enable" , {"enable" : int (state )})
@@ -247,9 +340,25 @@ async def set_inactivity_timeout(self, timeout: int) -> dict:
247
340
@property
248
341
def adc_value (self ) -> int :
249
342
"""Return motion adc value."""
250
- return int (self .data ["get_adc_value" ]["value" ])
343
+ return self .data ["get_adc_value" ]["value" ]
344
+
345
+ @property
346
+ def pir_value (self ) -> int :
347
+ """Return the computed PIR sensor value."""
348
+ return self .adc_midpoint - self .adc_value
349
+
350
+ @property
351
+ def pir_percent (self ) -> float :
352
+ """Return the computed PIR sensor value, in percentile form."""
353
+ amp = self .pir_value
354
+ per : float
355
+ if amp < 0 :
356
+ per = (float (amp ) / (self .adc_midpoint - self .adc_min )) * 100
357
+ else :
358
+ per = (float (amp ) / (self .adc_max - self .adc_midpoint )) * 100
359
+ return per
251
360
252
361
@property
253
- def is_triggered (self ) -> bool :
362
+ def pir_triggered (self ) -> bool :
254
363
"""Return if the motion sensor has been triggered."""
255
- return (self .enabled ) and (self .adc_value < self .threshold )
364
+ return (self .enabled ) and (abs ( self .pir_percent ) > ( 100 - self .threshold ) )
0 commit comments