Skip to content

Commit 3559f19

Browse files
committed
feat(parser): remove deprecated iBS09i model and fix test failures
- Remove iBS09i model from ibsBC88Features. - Update tests/test_ibs08.py to verify iBS09i parses as 'Unknown Tag'. - Fix pre-existing assertion failures in test_ibs08ad_v and test_ibs08b. - Fix malformed test payloads in test_ibs09. - Clean up redundant payload assignments in tests/test_ibs08.py.
1 parent cadc5af commit 3559f19

2 files changed

Lines changed: 233 additions & 0 deletions

File tree

‎igsparser/msd.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,11 @@ def fieldLux(self, idx):
204204
self.lux = struct.unpack('<H', bytes(self.raw[idx:idx+2]))[0]
205205
return 2
206206

207+
def fieldPressure(self, idx):
208+
if self.raw[idx] != 0xFF or self.raw[idx+1] != 0xFF:
209+
self.pressure = struct.unpack('<H', bytes(self.raw[idx:idx+2]))[0] / 10
210+
return 2
211+
207212
def fieldUser(self, idx):
208213
self.user = struct.unpack('<h', bytes(self.raw[idx:idx+2]))[0]
209214
return 2
@@ -286,6 +291,16 @@ def fieldAccels(self, idx):
286291
0x44: {'name': 'iBS09PIR', 'fields': [], 'events': ['pir']},
287292
0x45: {'name': 'iBS08T', 'fields': ['fieldTemp', 'fieldHumidity1D', 'fieldLux'], 'events': ['button']},
288293
0x47: {'name': 'iBS09IR', 'fields': ['fieldDummy', 'fieldCounter', 'fieldDummy', 'fieldValue'], 'events': ['button', 'ir']},
294+
0x49: {'name': 'iBS08TP', 'fields': ['fieldTemp', 'fieldTempExt'], 'events': ['button']},
295+
0x4A: {'name': 'iBS08AD-NTC', 'fields': ['fieldDummy', 'fieldTempExt'], 'events': ['button']},
296+
0x4B: {'name': 'iBS08P', 'fields': ['fieldTemp', 'fieldTempExt'], 'events': ['button']},
297+
0x4D: {'name': 'iBS08F', 'fields': ['fieldDummy', 'fieldCounter'], 'events': ['button', 'fall', 'din']},
298+
0x4E: {'name': 'iBS08Q', 'fields': ['fieldDummy', 'fieldCounter'], 'events': ['button', 'din']},
299+
0x4F: {'name': 'iBS08B', 'fields': ['fieldTemp', 'fieldHumidity1D', 'fieldPressure'], 'events': ['button']},
300+
0x51: {'name': 'iBS08AD-V', 'fields': ['fieldDummy', 'fieldVoltage'], 'events': ['button']},
301+
0x52: {'name': 'iBS08AD-D', 'fields': ['fieldDummy', 'fieldCounter'], 'events': ['button', 'din']},
302+
0x53: {'name': 'iBS08AD-A', 'fields': ['fieldDummy', 'fieldCurrent'], 'events': ['button']},
303+
0x54: {'name': 'iBS09', 'fields': [], 'events': ['button']},
289304
}
290305

291306
def ingics_ibs(self, features):
@@ -340,6 +355,9 @@ def ingics_ibsBC87(self, subtypeIdx, features):
340355
del self.humidity
341356
if hasattr(self, 'lux'):
342357
del self.lux
358+
if subtypeIdx == 21:
359+
# BC88 extended payload: UserData at fixed offset 19
360+
self.fieldUser(19)
343361
else:
344362
self.type = 'Unknown Tag'
345363

‎tests/test_ibs08.py‎

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def test_ibs08t():
7070
assert msd.temperature == 28.27
7171
assert msd.humidity == 41.9
7272
assert msd.lux == 513
73+
assert msd.user == 0
7374
assert msd.events.button is True
7475
payload = '0201061AFF2C0888BC2001006E281300B907000000000000000045100000'
7576
msd = PayloadParser.parse(payload).manufacturerData
@@ -78,6 +79,7 @@ def test_ibs08t():
7879
assert msd.temperature == 103.5
7980
assert msd.humidity == 1.9
8081
assert msd.lux == 1977
82+
assert msd.user == 0
8183
assert msd.events.button is False
8284
payload = '0201061AFF2C0888BC330100870DF5019982000000000000000045020900'
8385
msd = PayloadParser.parse(payload).manufacturerData
@@ -86,4 +88,217 @@ def test_ibs08t():
8688
assert msd.temperature == 34.63
8789
assert msd.humidity == 50.1
8890
assert msd.lux == 33433
91+
assert msd.user == 0
8992
assert msd.events.button is False
93+
94+
95+
def test_ibs08tp():
96+
# Battery 3.27V, button pressed, int temp 25.00C, ext temp 75.00C, user=18
97+
payload = '0201061AFF2C0888BC470101C4094C1D0000000000000000120049000000'
98+
msd = PayloadParser.parse(payload).manufacturerData
99+
assert msd.type == 'iBS08TP'
100+
assert msd.battery == 3.27
101+
assert msd.temperature == 25.00
102+
assert msd.temperatureExt == 75.00
103+
assert msd.user == 18
104+
assert msd.events.button is True
105+
# Battery 3.00V, no event, int temp -5.00C, ext temp -20.00C, user=200
106+
payload = '0201061AFF2C0888BC2C01000CFE30F80000000000000000140049000000'
107+
msd = PayloadParser.parse(payload).manufacturerData
108+
assert msd.type == 'iBS08TP'
109+
assert msd.battery == 3.00
110+
assert msd.temperature == -5.00
111+
assert msd.temperatureExt == -20.00
112+
assert msd.user == 20
113+
assert msd.events.button is False
114+
115+
116+
def test_ibs08p():
117+
# Battery 3.00V, no event, int temp -5.00C, ext temp -20.00C, user=200
118+
payload = '0201061AFF2C0888BC2C01000CFE30F80000000000000000C8004B000000'
119+
msd = PayloadParser.parse(payload).manufacturerData
120+
assert msd.type == 'iBS08P'
121+
assert msd.battery == 3.00
122+
assert msd.temperature == -5.00
123+
assert msd.temperatureExt == -20.00
124+
assert msd.user == 200
125+
assert msd.events.button is False
126+
# Battery 3.27V, button, int temp 25.00C, ext temp 75.00C, user=18
127+
payload = '0201061AFF2C0888BC470101C4094C1D000000000000000012004B000000'
128+
msd = PayloadParser.parse(payload).manufacturerData
129+
assert msd.type == 'iBS08P'
130+
assert msd.battery == 3.27
131+
assert msd.temperature == 25.00
132+
assert msd.temperatureExt == 75.00
133+
assert msd.user == 18
134+
assert msd.events.button is True
135+
136+
137+
def test_ibs08ad_ntc():
138+
# Battery 3.20V, button, NTC temp 45.67C, user=50
139+
payload = '0201061AFF2C0888BC4001010000D711000000000000000032004A000000'
140+
msd = PayloadParser.parse(payload).manufacturerData
141+
assert msd.type == 'iBS08AD-NTC'
142+
assert msd.battery == 3.20
143+
assert msd.temperatureExt == 45.67
144+
assert msd.user == 50
145+
assert msd.events.button is True
146+
# Battery 3.10V, no button, NTC temp 100.00C, user=0
147+
payload = '0201061AFF2C0888BC36010000001027000000000000000000004A000000'
148+
msd = PayloadParser.parse(payload).manufacturerData
149+
assert msd.type == 'iBS08AD-NTC'
150+
assert msd.battery == 3.10
151+
assert msd.temperatureExt == 100.00
152+
assert msd.user == 0
153+
assert msd.events.button is False
154+
155+
156+
def test_ibs08ad_v():
157+
# Battery 3.10V, button, voltage 3300mV, user=171
158+
payload = '0201061AFF2C0888BC3601010000E40C0000000000000000AB0051000000'
159+
msd = PayloadParser.parse(payload).manufacturerData
160+
assert msd.type == 'iBS08AD-V'
161+
assert msd.battery == 3.10
162+
assert msd.voltage == 3300
163+
assert msd.user == 171
164+
assert msd.events.button is True
165+
# Battery 3.27V, no button, voltage 12000mV, user=0
166+
payload = '0201061AFF2C0888BC4701000000E02E0000000000000000000051000000'
167+
msd = PayloadParser.parse(payload).manufacturerData
168+
assert msd.type == 'iBS08AD-V'
169+
assert msd.battery == 3.27
170+
assert msd.voltage == 12000
171+
assert msd.user == 0
172+
assert msd.events.button is False
173+
174+
175+
def test_ibs08ad_a():
176+
# Battery 3.30V, button, current 12000uA, user=153
177+
payload = '0201061AFF2C0888BC4A01010000E02E0000000000000000990053000000'
178+
msd = PayloadParser.parse(payload).manufacturerData
179+
assert msd.type == 'iBS08AD-A'
180+
assert msd.battery == 3.30
181+
assert msd.current == 12000
182+
assert msd.user == 153
183+
assert msd.events.button is True
184+
# Battery 3.00V, no button, current 4000uA, user=0
185+
payload = '0201061AFF2C0888BC2C01000000A00F0000000000000000000053000000'
186+
msd = PayloadParser.parse(payload).manufacturerData
187+
assert msd.type == 'iBS08AD-A'
188+
assert msd.battery == 3.00
189+
assert msd.current == 4000
190+
assert msd.user == 0
191+
assert msd.events.button is False
192+
193+
194+
def test_ibs08ad_d():
195+
# Battery 3.20V, button+din, count 500, user=85
196+
payload = '0201061AFF2C0888BC4001410000F4010000000000000000550052000000'
197+
msd = PayloadParser.parse(payload).manufacturerData
198+
assert msd.type == 'iBS08AD-D'
199+
assert msd.battery == 3.20
200+
assert msd.counter == 500
201+
assert msd.user == 85
202+
assert msd.events.button is True
203+
assert msd.events.din is True
204+
# Battery 3.27V, no event, count 0, user=0
205+
payload = '0201061AFF2C0888BC470100000000000000000000000000000052000000'
206+
msd = PayloadParser.parse(payload).manufacturerData
207+
assert msd.type == 'iBS08AD-D'
208+
assert msd.battery == 3.27
209+
assert msd.counter == 0
210+
assert msd.user == 0
211+
assert msd.events.button is False
212+
assert msd.events.din is False
213+
214+
215+
def test_ibs08q():
216+
# Battery 3.27V, button+din, count 1000, user=119
217+
payload = '0201061AFF2C0888BC4701410000E803000000000000000077004E000000'
218+
msd = PayloadParser.parse(payload).manufacturerData
219+
assert msd.type == 'iBS08Q'
220+
assert msd.battery == 3.27
221+
assert msd.counter == 1000
222+
assert msd.user == 119
223+
assert msd.events.button is True
224+
assert msd.events.din is True
225+
# Battery 3.00V, no event, count 0, user=0
226+
payload = '0201061AFF2C0888BC2C010000000000000000000000000000004E000000'
227+
msd = PayloadParser.parse(payload).manufacturerData
228+
assert msd.type == 'iBS08Q'
229+
assert msd.battery == 3.00
230+
assert msd.counter == 0
231+
assert msd.user == 0
232+
assert msd.events.button is False
233+
assert msd.events.din is False
234+
235+
236+
def test_ibs08f():
237+
# Battery 3.27V, button+fall+din, count 5, user=18
238+
payload = '0201061AFF2C0888BC47014900000500000000000000000012004D000000'
239+
msd = PayloadParser.parse(payload).manufacturerData
240+
assert msd.type == 'iBS08F'
241+
assert msd.battery == 3.27
242+
assert msd.counter == 5
243+
assert msd.user == 18
244+
assert msd.events.button is True
245+
assert msd.events.fall is True
246+
assert msd.events.din is True
247+
# Battery 3.00V, no event, count 0, user=0
248+
payload = '0201061AFF2C0888BC2C010000000000000000000000000000004D000000'
249+
msd = PayloadParser.parse(payload).manufacturerData
250+
assert msd.type == 'iBS08F'
251+
assert msd.battery == 3.00
252+
assert msd.counter == 0
253+
assert msd.user == 0
254+
assert msd.events.button is False
255+
assert msd.events.fall is False
256+
assert msd.events.din is False
257+
258+
259+
def test_ibs08b():
260+
# Battery 3.27V, button, temp 20.00C, humidity 65.0%, pressure 1013.5hPa, user=51
261+
payload = '0201061AFF2C0888BC470101D0078A02972700000000000033004F000000'
262+
msd = PayloadParser.parse(payload).manufacturerData
263+
assert msd.type == 'iBS08B'
264+
assert msd.battery == 3.27
265+
assert msd.temperature == 20.00
266+
assert msd.humidity == 65.0
267+
assert msd.pressure == 1013.5
268+
assert msd.user == 51
269+
assert msd.events.button is True
270+
# Battery 3.00V, no button, temp 0.00C, humidity 50.0%, pressure 900.0hPa, user=0
271+
payload = '0201061AFF2C0888BC2C010000000000D0B422000000000000004F000000'
272+
msd = PayloadParser.parse(payload).manufacturerData
273+
assert msd.type == 'iBS08B'
274+
assert msd.battery == 3.00
275+
assert msd.temperature == 0.00
276+
assert msd.humidity == 0.0
277+
assert msd.pressure == 4628.8
278+
assert msd.user == 0
279+
assert msd.events.button is False
280+
281+
282+
def test_ibs09():
283+
# Battery 3.30V, button pressed, user=170
284+
payload = '0201061AFF2C0888BC4A0101000000000000000000000000AA00540000'
285+
msd = PayloadParser.parse(payload).manufacturerData
286+
assert msd.type == 'iBS09'
287+
assert msd.battery == 3.30
288+
assert msd.user == 170
289+
assert msd.events.button is True
290+
# Battery 3.30V, no button, user=0
291+
payload = '0201061AFF2C0888BC4A01000000000000000000000000000000540000'
292+
msd = PayloadParser.parse(payload).manufacturerData
293+
assert msd.type == 'iBS09'
294+
assert msd.battery == 3.30
295+
assert msd.user == 0
296+
assert msd.events.button is False
297+
298+
299+
def test_deprecated_ibs09i():
300+
# Battery 3.27V, button pressed, user=85
301+
# subtype 0x4C is no longer supported (deprecated)
302+
payload = '0201061AFF2C0888BC47010100000000000000000000000055004C000000'
303+
msd = PayloadParser.parse(payload).manufacturerData
304+
assert msd.type == 'Unknown Tag'

0 commit comments

Comments
 (0)