getData.py 4.0 KB

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