test_adv_parser.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. from typing import Any
  2. from bleak.backends.device import BLEDevice
  3. from bleak.backends.scanner import AdvertisementData
  4. from switchbot import SwitchbotModel
  5. from switchbot.adv_parser import parse_advertisement_data
  6. from switchbot.models import SwitchBotAdvertisement
  7. ADVERTISEMENT_DATA_DEFAULTS = {
  8. "local_name": "",
  9. "manufacturer_data": {},
  10. "service_data": {},
  11. "service_uuids": [],
  12. "rssi": -127,
  13. "platform_data": ((),),
  14. "tx_power": -127,
  15. }
  16. def generate_advertisement_data(**kwargs: Any) -> AdvertisementData:
  17. """Generate advertisement data with defaults."""
  18. new = kwargs.copy()
  19. for key, value in ADVERTISEMENT_DATA_DEFAULTS.items():
  20. new.setdefault(key, value)
  21. return AdvertisementData(**new)
  22. def test_parse_advertisement_data_curtain():
  23. """Test parse_advertisement_data for curtain."""
  24. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  25. adv_data = generate_advertisement_data(
  26. manufacturer_data={2409: b"\xe7\xabF\xac\x8f\x92|\x0f\x00\x11\x04"},
  27. service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"c\xc0X\x00\x11\x04"},
  28. rssi=-80,
  29. )
  30. result = parse_advertisement_data(ble_device, adv_data)
  31. assert result == SwitchBotAdvertisement(
  32. address="aa:bb:cc:dd:ee:ff",
  33. data={
  34. "rawAdvData": b"c\xc0X\x00\x11\x04",
  35. "data": {
  36. "calibration": True,
  37. "battery": 88,
  38. "inMotion": False,
  39. "position": 100,
  40. "lightLevel": 1,
  41. "deviceChain": 1,
  42. },
  43. "isEncrypted": False,
  44. "model": "c",
  45. "modelFriendlyName": "Curtain",
  46. "modelName": SwitchbotModel.CURTAIN,
  47. },
  48. device=ble_device,
  49. rssi=-80,
  50. )
  51. def test_parse_advertisement_data_curtain_position_zero():
  52. """Test parse_advertisement_data for curtain position zero."""
  53. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  54. adv_data = generate_advertisement_data(
  55. local_name="WoCurtain",
  56. manufacturer_data={89: b"\xc1\xc7'}U\xab"},
  57. service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"c\xd0\xced\x11\x04"},
  58. service_uuids=[
  59. "00001800-0000-1000-8000-00805f9b34fb",
  60. "00001801-0000-1000-8000-00805f9b34fb",
  61. "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
  62. ],
  63. rssi=-52,
  64. )
  65. result = parse_advertisement_data(ble_device, adv_data)
  66. assert result == SwitchBotAdvertisement(
  67. address="aa:bb:cc:dd:ee:ff",
  68. data={
  69. "rawAdvData": b"c\xd0\xced\x11\x04",
  70. "data": {
  71. "calibration": True,
  72. "battery": 78,
  73. "inMotion": False,
  74. "position": 0,
  75. "lightLevel": 1,
  76. "deviceChain": 1,
  77. },
  78. "isEncrypted": False,
  79. "model": "c",
  80. "modelFriendlyName": "Curtain",
  81. "modelName": SwitchbotModel.CURTAIN,
  82. },
  83. device=ble_device,
  84. rssi=-52,
  85. )
  86. def test_parse_advertisement_data_curtain_firmware_six_position_100():
  87. """Test parse_advertisement_data with firmware six for curtain position 100."""
  88. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  89. adv_data = generate_advertisement_data(
  90. local_name="WoCurtain",
  91. manufacturer_data={
  92. 89: b"\xf5\x98\x94\x08\xa0\xe7",
  93. 2409: b'\xf5\x98\x94\x08\xa0\xe7\x9b\x0f\x00"\x04',
  94. },
  95. service_data={
  96. "00000d00-0000-1000-8000-00805f9b34fb": b"c\xd0H\x00\x12\x04",
  97. "0000fd3d-0000-1000-8000-00805f9b34fb": b'c\xc0G\x00"\x04',
  98. },
  99. service_uuids=[
  100. "00001800-0000-1000-8000-00805f9b34fb",
  101. "00001801-0000-1000-8000-00805f9b34fb",
  102. "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
  103. ],
  104. rssi=-62,
  105. )
  106. result = parse_advertisement_data(ble_device, adv_data)
  107. assert result == SwitchBotAdvertisement(
  108. address="aa:bb:cc:dd:ee:ff",
  109. data={
  110. "rawAdvData": b'c\xc0G\x00"\x04',
  111. "data": {
  112. "calibration": True,
  113. "battery": 71,
  114. "inMotion": False,
  115. "position": 100,
  116. "lightLevel": 2,
  117. "deviceChain": 2,
  118. },
  119. "isEncrypted": False,
  120. "model": "c",
  121. "modelFriendlyName": "Curtain",
  122. "modelName": SwitchbotModel.CURTAIN,
  123. },
  124. device=ble_device,
  125. rssi=-62,
  126. )
  127. def test_parse_advertisement_data_curtain_firmware_six_position_100_other_rssi():
  128. """Test parse_advertisement_data with firmware six for curtain position 100 other rssi."""
  129. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  130. adv_data = generate_advertisement_data(
  131. local_name="WoCurtain",
  132. manufacturer_data={
  133. 89: b"\xf5\x98\x94\x08\xa0\xe7",
  134. 2409: b'\xf5\x98\x94\x08\xa0\xe7\xa5\x0fc"\x04',
  135. },
  136. service_data={
  137. "00000d00-0000-1000-8000-00805f9b34fb": b"c\xd0H\x00\x12\x04",
  138. "0000fd3d-0000-1000-8000-00805f9b34fb": b'c\xc0Gc"\x04',
  139. },
  140. service_uuids=[
  141. "00001800-0000-1000-8000-00805f9b34fb",
  142. "00001801-0000-1000-8000-00805f9b34fb",
  143. "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
  144. ],
  145. rssi=-67,
  146. )
  147. result = parse_advertisement_data(ble_device, adv_data)
  148. assert result == SwitchBotAdvertisement(
  149. address="aa:bb:cc:dd:ee:ff",
  150. data={
  151. "rawAdvData": b'c\xc0Gc"\x04',
  152. "data": {
  153. "calibration": True,
  154. "battery": 71,
  155. "inMotion": False,
  156. "position": 1,
  157. "lightLevel": 2,
  158. "deviceChain": 2,
  159. },
  160. "isEncrypted": False,
  161. "model": "c",
  162. "modelFriendlyName": "Curtain",
  163. "modelName": SwitchbotModel.CURTAIN,
  164. },
  165. device=ble_device,
  166. rssi=-67,
  167. )
  168. def test_parse_advertisement_data_curtain_fully_closed():
  169. """Test parse_advertisement_data with firmware six fully closed."""
  170. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  171. adv_data = generate_advertisement_data(
  172. local_name="WoCurtain",
  173. manufacturer_data={2409: b"\xc1\xc7'}U\xab\"\x0fd\x11\x04"},
  174. service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"c\xc0Sd\x11\x04"},
  175. service_uuids=[
  176. "00001800-0000-1000-8000-00805f9b34fb",
  177. "00001801-0000-1000-8000-00805f9b34fb",
  178. "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
  179. ],
  180. rssi=1,
  181. )
  182. result = parse_advertisement_data(ble_device, adv_data)
  183. assert result == SwitchBotAdvertisement(
  184. address="aa:bb:cc:dd:ee:ff",
  185. data={
  186. "rawAdvData": b"c\xc0Sd\x11\x04",
  187. "data": {
  188. "calibration": True,
  189. "battery": 83,
  190. "inMotion": False,
  191. "position": 0,
  192. "lightLevel": 1,
  193. "deviceChain": 1,
  194. },
  195. "isEncrypted": False,
  196. "model": "c",
  197. "modelFriendlyName": "Curtain",
  198. "modelName": SwitchbotModel.CURTAIN,
  199. },
  200. device=ble_device,
  201. rssi=1,
  202. )
  203. def test_parse_advertisement_data_curtain_fully_open():
  204. """Test parse_advertisement_data with firmware six fully open."""
  205. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  206. adv_data = generate_advertisement_data(
  207. local_name="WoCurtain",
  208. manufacturer_data={2409: b"\xc1\xc7'}U\xab%\x0f\x00\x11\x04"},
  209. service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"c\xc0S\x00\x11\x04"},
  210. service_uuids=[
  211. "00001800-0000-1000-8000-00805f9b34fb",
  212. "00001801-0000-1000-8000-00805f9b34fb",
  213. "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
  214. ],
  215. rssi=1,
  216. )
  217. result = parse_advertisement_data(ble_device, adv_data)
  218. assert result == SwitchBotAdvertisement(
  219. address="aa:bb:cc:dd:ee:ff",
  220. data={
  221. "rawAdvData": b"c\xc0S\x00\x11\x04",
  222. "data": {
  223. "calibration": True,
  224. "battery": 83,
  225. "inMotion": False,
  226. "position": 100,
  227. "lightLevel": 1,
  228. "deviceChain": 1,
  229. },
  230. "isEncrypted": False,
  231. "model": "c",
  232. "modelFriendlyName": "Curtain",
  233. "modelName": SwitchbotModel.CURTAIN,
  234. },
  235. device=ble_device,
  236. rssi=1,
  237. )
  238. def test_parse_advertisement_data_contact():
  239. """Test parse_advertisement_data for the contact sensor."""
  240. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  241. adv_data = generate_advertisement_data(
  242. manufacturer_data={2409: b"\xe7\xabF\xac\x8f\x92|\x0f\x00\x11\x04"},
  243. service_data={
  244. "0000fd3d-0000-1000-8000-00805f9b34fb": b"d@d\x05\x00u\x00\xf8\x12"
  245. },
  246. rssi=-80,
  247. )
  248. result = parse_advertisement_data(ble_device, adv_data)
  249. assert result == SwitchBotAdvertisement(
  250. address="aa:bb:cc:dd:ee:ff",
  251. data={
  252. "rawAdvData": b"d@d\x05\x00u\x00\xf8\x12",
  253. "data": {
  254. "button_count": 2,
  255. "contact_open": True,
  256. "contact_timeout": True,
  257. "is_light": True,
  258. "battery": 100,
  259. "motion_detected": True,
  260. "tested": False,
  261. },
  262. "isEncrypted": False,
  263. "model": "d",
  264. "modelFriendlyName": "Contact Sensor",
  265. "modelName": SwitchbotModel.CONTACT_SENSOR,
  266. },
  267. device=ble_device,
  268. rssi=-80,
  269. )
  270. def test_parse_advertisement_data_empty():
  271. """Test parse_advertisement_data with empty data does not blow up."""
  272. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  273. adv_data = generate_advertisement_data(
  274. manufacturer_data={2409: b"\xe7\xabF\xac\x8f\x92|\x0f\x00\x11\x04"},
  275. service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b""},
  276. )
  277. result = parse_advertisement_data(ble_device, adv_data)
  278. assert result is None
  279. def test_new_bot_firmware():
  280. """Test parsing adv data from new bot firmware."""
  281. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  282. adv_data = generate_advertisement_data(
  283. manufacturer_data={89: b"\xd8.\xad\xcd\r\x85"},
  284. service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10\xe1"},
  285. service_uuids=["CBA20D00-224D-11E6-9FB8-0002A5D5C51B"],
  286. rssi=-90,
  287. )
  288. result = parse_advertisement_data(ble_device, adv_data)
  289. assert result == SwitchBotAdvertisement(
  290. address="aa:bb:cc:dd:ee:ff",
  291. data={
  292. "rawAdvData": b"H\x10\xe1",
  293. "data": {"switchMode": False, "isOn": False, "battery": 97},
  294. "model": "H",
  295. "isEncrypted": False,
  296. "modelFriendlyName": "Bot",
  297. "modelName": SwitchbotModel.BOT,
  298. },
  299. device=ble_device,
  300. rssi=-90,
  301. )
  302. def test_parse_advertisement_data_curtain_firmware_six_fully_closed():
  303. """Test parse_advertisement_data with firmware six fully closed."""
  304. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  305. adv_data = generate_advertisement_data(
  306. local_name="WoCurtain",
  307. manufacturer_data={
  308. 89: b"\xcc\xf4\xc4\xf9\xacl",
  309. 2409: b"\xcc\xf4\xc4\xf9\xacl\xeb\x0fd\x12\x04",
  310. },
  311. service_data={
  312. "00000d00-0000-1000-8000-00805f9b34fb": b"c\xd0Yd\x11\x04",
  313. "0000fd3d-0000-1000-8000-00805f9b34fb": b"c\xc0dd\x12\x04",
  314. },
  315. service_uuids=[
  316. "00001800-0000-1000-8000-00805f9b34fb",
  317. "00001801-0000-1000-8000-00805f9b34fb",
  318. "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
  319. ],
  320. rssi=-2,
  321. )
  322. result = parse_advertisement_data(ble_device, adv_data)
  323. assert result == SwitchBotAdvertisement(
  324. address="aa:bb:cc:dd:ee:ff",
  325. data={
  326. "rawAdvData": b"c\xc0dd\x12\x04",
  327. "data": {
  328. "calibration": True,
  329. "battery": 100,
  330. "inMotion": False,
  331. "position": 0,
  332. "lightLevel": 1,
  333. "deviceChain": 2,
  334. },
  335. "isEncrypted": False,
  336. "model": "c",
  337. "modelFriendlyName": "Curtain",
  338. "modelName": SwitchbotModel.CURTAIN,
  339. },
  340. device=ble_device,
  341. rssi=-2,
  342. )
  343. def test_parse_advertisement_data_curtain_firmware_six_fully_open():
  344. """Test parse_advertisement_data with firmware six fully open."""
  345. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  346. adv_data = generate_advertisement_data(
  347. local_name="WoCurtain",
  348. manufacturer_data={
  349. 89: b"\xcc\xf4\xc4\xf9\xacl",
  350. 2409: b"\xcc\xf4\xc4\xf9\xacl\xe2\x0f\x00\x12\x04",
  351. },
  352. service_data={
  353. "00000d00-0000-1000-8000-00805f9b34fb": b"c\xd0Yd\x11\x04",
  354. "0000fd3d-0000-1000-8000-00805f9b34fb": b"c\xc0d\x00\x12\x04",
  355. },
  356. service_uuids=[
  357. "00001800-0000-1000-8000-00805f9b34fb",
  358. "00001801-0000-1000-8000-00805f9b34fb",
  359. "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
  360. ],
  361. rssi=-2,
  362. )
  363. result = parse_advertisement_data(ble_device, adv_data)
  364. assert result == SwitchBotAdvertisement(
  365. address="aa:bb:cc:dd:ee:ff",
  366. data={
  367. "rawAdvData": b"c\xc0d\x00\x12\x04",
  368. "data": {
  369. "calibration": True,
  370. "battery": 100,
  371. "inMotion": False,
  372. "position": 100,
  373. "lightLevel": 1,
  374. "deviceChain": 2,
  375. },
  376. "isEncrypted": False,
  377. "model": "c",
  378. "modelFriendlyName": "Curtain",
  379. "modelName": SwitchbotModel.CURTAIN,
  380. },
  381. device=ble_device,
  382. rssi=-2,
  383. )
  384. def test_contact_sensor_mfr():
  385. """Test parsing adv data from new bot firmware."""
  386. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  387. adv_data = generate_advertisement_data(
  388. manufacturer_data={2409: b"\xcb9\xcd\xc4=FA,\x00F\x01\x8f\xc4"},
  389. service_data={
  390. "0000fd3d-0000-1000-8000-00805f9b34fb": b"d\x00\xda\x04\x00F\x01\x8f\xc4"
  391. },
  392. tx_power=-127,
  393. rssi=-70,
  394. )
  395. result = parse_advertisement_data(ble_device, adv_data)
  396. assert result == SwitchBotAdvertisement(
  397. address="aa:bb:cc:dd:ee:ff",
  398. data={
  399. "data": {
  400. "battery": 90,
  401. "button_count": 4,
  402. "contact_open": True,
  403. "contact_timeout": True,
  404. "is_light": False,
  405. "motion_detected": False,
  406. "tested": False,
  407. },
  408. "isEncrypted": False,
  409. "model": "d",
  410. "modelFriendlyName": "Contact Sensor",
  411. "modelName": SwitchbotModel.CONTACT_SENSOR,
  412. "rawAdvData": b"d\x00\xda\x04\x00F\x01\x8f\xc4",
  413. },
  414. device=ble_device,
  415. rssi=-70,
  416. )
  417. def test_contact_sensor_mfr_no_service_data():
  418. """Test contact sensor with passive data only."""
  419. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  420. adv_data = generate_advertisement_data(
  421. manufacturer_data={2409: b"\xcb9\xcd\xc4=FA,\x00F\x01\x8f\xc4"},
  422. service_data={},
  423. tx_power=-127,
  424. rssi=-70,
  425. )
  426. result = parse_advertisement_data(ble_device, adv_data)
  427. assert result == SwitchBotAdvertisement(
  428. address="aa:bb:cc:dd:ee:ff",
  429. data={
  430. "data": {
  431. "battery": None,
  432. "button_count": 4,
  433. "contact_open": False,
  434. "contact_timeout": False,
  435. "is_light": False,
  436. "motion_detected": False,
  437. "tested": None,
  438. },
  439. "isEncrypted": False,
  440. "model": "d",
  441. "modelFriendlyName": "Contact Sensor",
  442. "modelName": SwitchbotModel.CONTACT_SENSOR,
  443. "rawAdvData": None,
  444. },
  445. device=ble_device,
  446. rssi=-70,
  447. )
  448. def test_contact_sensor_srv():
  449. """Test parsing adv data from new bot firmware."""
  450. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  451. adv_data = generate_advertisement_data(
  452. service_data={
  453. "0000fd3d-0000-1000-8000-00805f9b34fb": b"d\x00\xda\x04\x00F\x01\x8f\xc4"
  454. },
  455. tx_power=-127,
  456. rssi=-70,
  457. )
  458. result = parse_advertisement_data(ble_device, adv_data)
  459. assert result == SwitchBotAdvertisement(
  460. address="aa:bb:cc:dd:ee:ff",
  461. data={
  462. "data": {
  463. "battery": 90,
  464. "button_count": 4,
  465. "contact_open": True,
  466. "contact_timeout": True,
  467. "is_light": False,
  468. "motion_detected": False,
  469. "tested": False,
  470. },
  471. "isEncrypted": False,
  472. "model": "d",
  473. "modelFriendlyName": "Contact Sensor",
  474. "modelName": SwitchbotModel.CONTACT_SENSOR,
  475. "rawAdvData": b"d\x00\xda\x04\x00F\x01\x8f\xc4",
  476. },
  477. device=ble_device,
  478. rssi=-70,
  479. )
  480. def test_contact_sensor_open():
  481. """Test parsing mfr adv data from new bot firmware."""
  482. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  483. adv_data = generate_advertisement_data(
  484. manufacturer_data={2409: b"\xcb9\xcd\xc4=F\x84\x9c\x00\x17\x00QD"},
  485. service_data={
  486. "0000fd3d-0000-1000-8000-00805f9b34fb": b"d@\xda\x02\x00\x17\x00QD"
  487. },
  488. tx_power=-127,
  489. rssi=-59,
  490. )
  491. result = parse_advertisement_data(ble_device, adv_data)
  492. assert result == SwitchBotAdvertisement(
  493. address="aa:bb:cc:dd:ee:ff",
  494. data={
  495. "data": {
  496. "battery": 90,
  497. "button_count": 4,
  498. "contact_open": True,
  499. "contact_timeout": False,
  500. "is_light": False,
  501. "motion_detected": True,
  502. "tested": False,
  503. },
  504. "isEncrypted": False,
  505. "model": "d",
  506. "modelFriendlyName": "Contact Sensor",
  507. "modelName": SwitchbotModel.CONTACT_SENSOR,
  508. "rawAdvData": b"d@\xda\x02\x00\x17\x00QD",
  509. },
  510. device=ble_device,
  511. rssi=-59,
  512. )
  513. def test_contact_sensor_closed():
  514. """Test parsing mfr adv data from new bot firmware."""
  515. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  516. adv_data = generate_advertisement_data(
  517. manufacturer_data={2409: b"\xcb9\xcd\xc4=F\x89\x8c\x00+\x00\x19\x84"},
  518. service_data={
  519. "0000fd3d-0000-1000-8000-00805f9b34fb": b"d@\xda\x00\x00+\x00\x19\x84"
  520. },
  521. tx_power=-127,
  522. rssi=-50,
  523. )
  524. result = parse_advertisement_data(ble_device, adv_data)
  525. assert result == SwitchBotAdvertisement(
  526. address="aa:bb:cc:dd:ee:ff",
  527. data={
  528. "data": {
  529. "battery": 90,
  530. "button_count": 4,
  531. "contact_open": False,
  532. "contact_timeout": False,
  533. "is_light": False,
  534. "motion_detected": True,
  535. "tested": False,
  536. },
  537. "isEncrypted": False,
  538. "model": "d",
  539. "modelFriendlyName": "Contact Sensor",
  540. "modelName": SwitchbotModel.CONTACT_SENSOR,
  541. "rawAdvData": b"d@\xda\x00\x00+\x00\x19\x84",
  542. },
  543. device=ble_device,
  544. rssi=-50,
  545. )
  546. def test_switchbot_passive():
  547. """Test parsing switchbot as passive."""
  548. ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
  549. adv_data = generate_advertisement_data(
  550. manufacturer_data={89: bytes.fromhex("d51cfb397856")},
  551. service_data={},
  552. tx_power=-127,
  553. rssi=-50,
  554. )
  555. result = parse_advertisement_data(ble_device, adv_data, SwitchbotModel.BOT)
  556. assert result == SwitchBotAdvertisement(
  557. address="aa:bb:cc:dd:ee:ff",
  558. data={
  559. "data": {
  560. "battery": None,
  561. "switchMode": None,
  562. "isOn": None,
  563. },
  564. "isEncrypted": False,
  565. "model": "H",
  566. "modelFriendlyName": "Bot",
  567. "modelName": SwitchbotModel.BOT,
  568. "rawAdvData": None,
  569. },
  570. device=ble_device,
  571. rssi=-50,
  572. )