Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 

181 rinda
7.6 KiB

  1. #
  2. # Copyright (c) 2020 Olaf Landsiedel, based on a code example from Tony DiCola
  3. #
  4. # SPDX-License-Identifier: Apache-2.0
  5. #
  6. #NOTE: seems not to work well on some iMACs
  7. import logging
  8. import time
  9. import uuid
  10. import struct
  11. import binascii
  12. import Adafruit_BluefruitLE
  13. # Enable debug output.
  14. #logging.basicConfig(level=logging.DEBUG)
  15. # Define service and characteristic UUIDs used by the Covid service.
  16. COVID_SERVICE_UUID = uuid.UUID('F2110D79-699F-6A98-EA42-A7AD9EC75106')
  17. NEXT_KEY_UUID = uuid.UUID('F3110D79-699F-6A98-EA42-A7AD9EC75106')
  18. NEW_KEY_UUID = uuid.UUID('F4110D79-699F-6A98-EA42-A7AD9EC75106')
  19. INFECTED_KEY_CNT_UUID = uuid.UUID('F5110D79-699F-6A98-EA42-A7AD9EC75106')
  20. PERIOD_KEY_0_UUID = uuid.UUID('00110D79-699F-6A98-EA42-A7AD9EC75106')
  21. PERIOD_KEY_1_UUID = uuid.UUID('01110D79-699F-6A98-EA42-A7AD9EC75106')
  22. PERIOD_KEY_2_UUID = uuid.UUID('02110D79-699F-6A98-EA42-A7AD9EC75106')
  23. PERIOD_KEY_3_UUID = uuid.UUID('03110D79-699F-6A98-EA42-A7AD9EC75106')
  24. PERIOD_KEY_4_UUID = uuid.UUID('04110D79-699F-6A98-EA42-A7AD9EC75106')
  25. PERIOD_KEY_5_UUID = uuid.UUID('05110D79-699F-6A98-EA42-A7AD9EC75106')
  26. PERIOD_KEY_6_UUID = uuid.UUID('06110D79-699F-6A98-EA42-A7AD9EC75106')
  27. PERIOD_KEY_7_UUID = uuid.UUID('07110D79-699F-6A98-EA42-A7AD9EC75106')
  28. PERIOD_KEY_8_UUID = uuid.UUID('08110D79-699F-6A98-EA42-A7AD9EC75106')
  29. PERIOD_KEY_9_UUID = uuid.UUID('09110D79-699F-6A98-EA42-A7AD9EC75106')
  30. PERIOD_KEY_10_UUID = uuid.UUID('0A110D79-699F-6A98-EA42-A7AD9EC75106')
  31. PERIOD_KEY_11_UUID = uuid.UUID('0B110D79-699F-6A98-EA42-A7AD9EC75106')
  32. PERIOD_KEY_12_UUID = uuid.UUID('0C110D79-699F-6A98-EA42-A7AD9EC75106')
  33. PERIOD_KEY_13_UUID = uuid.UUID('0D110D79-699F-6A98-EA42-A7AD9EC75106')
  34. infected_period_keys = []
  35. # Get the BLE provider for the current platform.
  36. ble = Adafruit_BluefruitLE.get_provider()
  37. def check_infection(covid):
  38. infected_key_cnt_reader = covid.find_characteristic(INFECTED_KEY_CNT_UUID)
  39. period_key_readers = (
  40. covid.find_characteristic(PERIOD_KEY_0_UUID),
  41. covid.find_characteristic(PERIOD_KEY_1_UUID),
  42. covid.find_characteristic(PERIOD_KEY_2_UUID),
  43. covid.find_characteristic(PERIOD_KEY_3_UUID),
  44. covid.find_characteristic(PERIOD_KEY_4_UUID),
  45. covid.find_characteristic(PERIOD_KEY_5_UUID),
  46. covid.find_characteristic(PERIOD_KEY_6_UUID),
  47. covid.find_characteristic(PERIOD_KEY_7_UUID),
  48. covid.find_characteristic(PERIOD_KEY_8_UUID),
  49. covid.find_characteristic(PERIOD_KEY_9_UUID),
  50. covid.find_characteristic(PERIOD_KEY_10_UUID),
  51. covid.find_characteristic(PERIOD_KEY_11_UUID),
  52. covid.find_characteristic(PERIOD_KEY_12_UUID),
  53. covid.find_characteristic(PERIOD_KEY_13_UUID)
  54. )
  55. #check for infection
  56. ret = bytearray(infected_key_cnt_reader.read_value())
  57. infected_key_cnt = int.from_bytes(ret, byteorder='little', signed=False)
  58. print('device has: infected key cnt ', infected_key_cnt)
  59. for i in range(infected_key_cnt):
  60. ret = bytearray(period_key_readers[i].read_value())
  61. if ret not in infected_period_keys:
  62. print('adding to DB new infected key ', i, ': ', binascii.hexlify(bytearray(ret)))
  63. infected_period_keys.append(ret)
  64. else:
  65. print('infected key ', i , 'already known in DB: ', binascii.hexlify(bytearray(ret)))
  66. def upload_keys(covid):
  67. next_key = covid.find_characteristic(NEXT_KEY_UUID)
  68. new_key = covid.find_characteristic(NEW_KEY_UUID)
  69. go_on = True
  70. while go_on:
  71. print("read key")
  72. ret = bytearray(next_key.read_value())
  73. expected_index = int.from_bytes(ret, byteorder='little', signed=False)
  74. print('expected key index of device is ', expected_index, ', we have upto id ', len(infected_period_keys))
  75. #TODO: check for maximum storage on device
  76. if( expected_index >= 0 and expected_index < len(infected_period_keys) ):
  77. print('Sending key ', expected_index, ' from DB to device...')
  78. new_key.write_value(infected_period_keys[expected_index])
  79. #TODO do we need this?
  80. time.sleep(1)
  81. else:
  82. go_on = False
  83. # Main function implements the program logic so it can run in a background
  84. # thread. Most platforms require the main thread to handle GUI events and other
  85. # asyncronous events like BLE actions. All of the threading logic is taken care
  86. # of automatically though and you just need to provide a main function that uses
  87. # the BLE provider.
  88. def main():
  89. # Clear any cached data because both bluez and CoreBluetooth have issues with
  90. # caching data and it going stale.
  91. ble.clear_cached_data()
  92. # Get the first available BLE network adapter and make sure it's powered on.
  93. adapter = ble.get_default_adapter()
  94. adapter.power_on()
  95. print('Using adapter: {0}'.format(adapter.name))
  96. # Disconnect any currently connected UART devices. Good for cleaning up and
  97. # starting from a fresh state.
  98. print('Disconnecting any connected Covid devices...')
  99. ble.disconnect_devices([COVID_SERVICE_UUID])
  100. while True:
  101. # Scan for Covid devices.
  102. print('Searching for Covid device...')
  103. try:
  104. adapter.start_scan()
  105. # Search for the first Covid device found (will time out after 60 seconds
  106. # but you can specify an optional timeout_sec parameter to change it).
  107. device = ble.find_device(service_uuids=[COVID_SERVICE_UUID])
  108. if device is None:
  109. raise RuntimeError('Failed to find Covid device!')
  110. finally:
  111. # Make sure scanning is stopped before exiting.
  112. adapter.stop_scan()
  113. if device is not None:
  114. print('Connecting to device...')
  115. device.connect() # Will time out after 60 seconds, specify timeout_sec parameter
  116. # to change the timeout.
  117. # Once connected do everything else in a try/finally to make sure the device
  118. # is disconnected when done.
  119. try:
  120. # Wait for service discovery to complete for at least the specified
  121. # service and characteristic UUID lists. Will time out after 60 seconds
  122. # (specify timeout_sec parameter to override).
  123. print('Discovering services...')
  124. device.discover([COVID_SERVICE_UUID], [NEXT_KEY_UUID, NEW_KEY_UUID,
  125. INFECTED_KEY_CNT_UUID,
  126. PERIOD_KEY_0_UUID,
  127. PERIOD_KEY_1_UUID,
  128. PERIOD_KEY_2_UUID,
  129. PERIOD_KEY_3_UUID,
  130. PERIOD_KEY_4_UUID,
  131. PERIOD_KEY_5_UUID,
  132. PERIOD_KEY_6_UUID,
  133. PERIOD_KEY_7_UUID,
  134. PERIOD_KEY_8_UUID,
  135. PERIOD_KEY_9_UUID,
  136. PERIOD_KEY_10_UUID,
  137. PERIOD_KEY_11_UUID,
  138. PERIOD_KEY_12_UUID,
  139. PERIOD_KEY_13_UUID
  140. ])
  141. # Find the Covid service and its characteristics.
  142. covid = device.find_service(COVID_SERVICE_UUID)
  143. check_infection(covid)
  144. upload_keys(covid)
  145. finally:
  146. # Make sure device is disconnected on exit.
  147. device.disconnect()
  148. # Initialize the BLE system. MUST be called before other BLE calls!
  149. ble.initialize()
  150. # Start the mainloop to process BLE events, and run the provided function in
  151. # a background thread. When the provided main function stops running, returns
  152. # an integer status code, or throws an error the program will exit.
  153. ble.run_mainloop_with(main)