getData.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import asyncio
  2. from bleak import BleakClient, BleakScanner
  3. from bleak.backends.characteristic import BleakGATTCharacteristic
  4. import struct
  5. import sqlite3
  6. from dotenv import load_dotenv
  7. import os
  8. import smbus2
  9. import bme280
  10. # Initialise the BME280
  11. port = 1
  12. address = 0x76
  13. bus = smbus2.SMBus(port)
  14. calibration_params = bme280.load_calibration_params(bus, address)
  15. load_dotenv()
  16. outdoorName = os.getenv("BLE_PERIPHERAL_NAME")
  17. outdoorConnected = 0
  18. TEMP_UUID = "2A6E"
  19. PRESSURE_UUID = "2A6D"
  20. HUMIDITY_UUID = "2A6F"
  21. ALTITUDE_UUID = "2AB3"
  22. indoorValues = {
  23. "Temperature": 0,
  24. "Pressure": 0,
  25. "Humidity": 0,
  26. "Altitude": 0,
  27. }
  28. outdoorValues = {
  29. "Temperature": 0,
  30. "Pressure": 0,
  31. "Humidity": 0,
  32. "Altitude": 0,
  33. }
  34. def notification_handler(characteristic: BleakGATTCharacteristic, data: bytearray):
  35. global outdoorValues
  36. outdoorValues[characteristic.description] = struct.unpack("<i", data)[0]
  37. async def ble_task():
  38. global outdoorConnected
  39. while True:
  40. disconnect_event = asyncio.Event()
  41. device = await BleakScanner.find_device_by_name(outdoorName)
  42. if device is None:
  43. outdoorConnected = 0
  44. print("no device found, wait then scan again")
  45. await asyncio.sleep(10)
  46. continue
  47. try:
  48. async with BleakClient(device, disconnected_callback=lambda c: disconnect_event.set()) as client:
  49. outdoorConnected = 1
  50. print(f"connected to {outdoorName}")
  51. await client.start_notify(TEMP_UUID, notification_handler)
  52. await client.start_notify(PRESSURE_UUID, notification_handler)
  53. await client.start_notify(HUMIDITY_UUID, notification_handler)
  54. await client.start_notify(ALTITUDE_UUID, notification_handler)
  55. await disconnect_event.wait()
  56. except Exception:
  57. outdoorConnected = 0
  58. print("exception while connecting or getting data")
  59. async def sensor_task():
  60. global indoorValues
  61. while True:
  62. data = bme280.sample(bus, address, calibration_params)
  63. indoorValues["Temperature"] = round(data.temperature * 100)
  64. indoorValues["Pressure"] = round(data.pressure * 100)
  65. indoorValues["Humidity"] = round(data.humidity * 100)
  66. indoorValues["Altitude"] = 0 # * 100
  67. await asyncio.sleep(1)
  68. conn = sqlite3.connect('./data/meteostanica.sqlite')
  69. cursor = conn.cursor()
  70. cursor.execute(
  71. """CREATE TABLE IF NOT EXISTS data (
  72. timestamp datetime default current_timestamp primary key,
  73. indoorTemp text not null,
  74. indoorPressure text not null,
  75. indoorHumidity text not null,
  76. indoorAltitude text not null,
  77. outdoorConnected integer not null,
  78. outdoorTemp text not null,
  79. outdoorPressure text not null,
  80. outdoorHumidity text not null,
  81. outdoorAltitude text not null
  82. );"""
  83. )
  84. conn.commit()
  85. async def write_task():
  86. while True:
  87. cursor.execute(f"""INSERT INTO data (
  88. 'indoorTemp', 'indoorPressure', 'indoorHumidity', 'indoorAltitude', 'outdoorConnected', 'outdoorTemp', 'outdoorPressure', 'outdoorHumidity', 'outdoorAltitude'
  89. ) VALUES (
  90. ?, ?, ?, ?, ?, ?, ?, ?, ?
  91. )""",
  92. (
  93. indoorValues["Temperature"],
  94. indoorValues["Pressure"],
  95. indoorValues["Humidity"],
  96. indoorValues["Altitude"],
  97. outdoorConnected,
  98. outdoorValues["Temperature"],
  99. outdoorValues["Pressure"],
  100. outdoorValues["Humidity"],
  101. outdoorValues["Altitude"]
  102. ))
  103. conn.commit()
  104. print(f"indoor: {indoorValues["Temperature"] / 100}°C, outdoor: {outdoorConnected} - {outdoorValues["Temperature"] / 100}°C")
  105. await asyncio.sleep(10)
  106. async def main():
  107. try:
  108. t1 = asyncio.create_task(ble_task())
  109. t2 = asyncio.create_task(sensor_task())
  110. t3 = asyncio.create_task(write_task())
  111. await asyncio.gather(t1, t2, t3)
  112. except asyncio.exceptions.CancelledError:
  113. pass
  114. asyncio.run(main())