getData.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. client = None
  40. try:
  41. while True:
  42. device = await BleakScanner.find_device_by_name(outdoorName)
  43. if device is None:
  44. outdoorConnected = 0
  45. print("No device found, wait then scan again")
  46. await asyncio.sleep(10)
  47. continue
  48. try:
  49. async with BleakClient(device) as client:
  50. outdoorConnected = 1
  51. print(f"Connected to {outdoorName}")
  52. await client.start_notify(TEMP_UUID, notification_handler)
  53. await client.start_notify(PRESSURE_UUID, notification_handler)
  54. await client.start_notify(HUMIDITY_UUID, notification_handler)
  55. await client.start_notify(ALTITUDE_UUID, notification_handler)
  56. while client.is_connected:
  57. await asyncio.sleep(1)
  58. except Exception as e:
  59. print(f"Connection lost or error: {e}")
  60. finally:
  61. outdoorConnected = 0
  62. print("Cleaning up connection state...")
  63. except asyncio.CancelledError:
  64. print("BLE task is being cancelled...")
  65. if client and client.is_connected:
  66. await client.disconnect()
  67. outdoorConnected = 0
  68. raise
  69. async def sensor_task():
  70. global indoorValues
  71. while True:
  72. data = bme280.sample(bus, address, calibration_params)
  73. indoorValues["Temperature"] = round(data.temperature * 100)
  74. indoorValues["Pressure"] = round(data.pressure * 100)
  75. indoorValues["Humidity"] = round(data.humidity * 100)
  76. indoorValues["Altitude"] = 0 # * 100
  77. await asyncio.sleep(1)
  78. conn = sqlite3.connect('./data/meteostanica.sqlite')
  79. cursor = conn.cursor()
  80. cursor.execute(
  81. """CREATE TABLE IF NOT EXISTS data (
  82. timestamp datetime default current_timestamp primary key,
  83. indoorTemp text not null,
  84. indoorPressure text not null,
  85. indoorHumidity text not null,
  86. indoorAltitude text not null,
  87. outdoorConnected integer not null,
  88. outdoorTemp text not null,
  89. outdoorPressure text not null,
  90. outdoorHumidity text not null,
  91. outdoorAltitude text not null
  92. );"""
  93. )
  94. conn.commit()
  95. async def write_task():
  96. while True:
  97. cursor.execute(f"""INSERT INTO data (
  98. 'indoorTemp', 'indoorPressure', 'indoorHumidity', 'indoorAltitude', 'outdoorConnected', 'outdoorTemp', 'outdoorPressure', 'outdoorHumidity', 'outdoorAltitude'
  99. ) VALUES (
  100. ?, ?, ?, ?, ?, ?, ?, ?, ?
  101. )""",
  102. (
  103. indoorValues["Temperature"],
  104. indoorValues["Pressure"],
  105. indoorValues["Humidity"],
  106. indoorValues["Altitude"],
  107. outdoorConnected,
  108. outdoorValues["Temperature"],
  109. outdoorValues["Pressure"],
  110. outdoorValues["Humidity"],
  111. outdoorValues["Altitude"]
  112. ))
  113. conn.commit()
  114. print(f"indoor: {indoorValues["Temperature"] / 100}°C, outdoor: {outdoorConnected} - {outdoorValues["Temperature"] / 100}°C")
  115. await asyncio.sleep(10)
  116. async def main():
  117. try:
  118. t1 = asyncio.create_task(ble_task())
  119. t2 = asyncio.create_task(sensor_task())
  120. t3 = asyncio.create_task(write_task())
  121. await asyncio.gather(t1, t2, t3)
  122. except asyncio.exceptions.CancelledError:
  123. pass
  124. asyncio.run(main())