Skip to content

Commit 9f16536

Browse files
authored
Added smart weather device examples (#10)
* add smart weather device * add a space at the end of the line * remove binary file * update ruff.toml * add license for dashboard file * add new line
1 parent 4b593ff commit 9f16536

4 files changed

Lines changed: 2171 additions & 0 deletions

File tree

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
2+
# SPDX-FileCopyrightText: Copyright (c) 2026 ThingsBoard Inc.
3+
#
4+
# SPDX-License-Identifier: Unlicense
5+
6+
import time
7+
8+
import adafruit_sht31d
9+
import adafruit_ssd1306
10+
import board
11+
import busio
12+
import requests
13+
14+
from tb_device_mqtt import TBDeviceMqttClient
15+
16+
THINGSBOARD_HOST = "YOUR_THINGSBOARD_HOST"
17+
THINGSBOARD_TOKEN = "YOUR_THINGSBOARD_DEVICE_TOKEN"
18+
THINGSBOARD_PORT = 1883
19+
20+
OPENWEATHER_API_KEY = "YOUR_WEATHER_API_KEY"
21+
DEFAULT_CITY = "Kyiv,UA"
22+
23+
WEATHER_UPDATE_PERIOD = 600
24+
DISPLAY_REFRESH_PERIOD = 2
25+
TELEMETRY_SEND_PERIOD = 10
26+
27+
selected_city = DEFAULT_CITY
28+
29+
i2c = busio.I2C(board.SCL, board.SDA)
30+
display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c)
31+
sensor = adafruit_sht31d.SHT31D(i2c)
32+
33+
34+
def draw_screen(indoor_temp, indoor_humidity, outdoor_temp, outdoor_humidity):
35+
display.fill(0)
36+
37+
display.text(f"InT:{indoor_temp:5.1f}C", 0, 0, 1)
38+
display.text(f"InH:{indoor_humidity:5.1f}%", 64, 0, 1)
39+
40+
if outdoor_temp is not None:
41+
display.text(f"OutT:{outdoor_temp:4.1f}C", 0, 16, 1)
42+
else:
43+
display.text("OutT: N/A", 0, 16, 1)
44+
45+
if outdoor_humidity is not None:
46+
display.text(f"OutH:{outdoor_humidity:4.1f}%", 64, 16, 1)
47+
else:
48+
display.text("OutH: N/A", 64, 16, 1)
49+
50+
display.show()
51+
52+
53+
def get_current_weather(city_name):
54+
url = "https://api.openweathermap.org/data/2.5/weather"
55+
params = {"q": city_name, "appid": OPENWEATHER_API_KEY, "units": "metric"}
56+
57+
try:
58+
response = requests.get(url, params=params, timeout=10)
59+
response.raise_for_status()
60+
data = response.json()
61+
62+
return {
63+
"temp": float(data["main"]["temp"]),
64+
"humidity": float(data["main"]["humidity"]),
65+
}
66+
except Exception as e:
67+
print("Weather request failed:", e)
68+
return None
69+
70+
71+
def main():
72+
weather_data = {"temp": None, "humidity": None}
73+
74+
last_weather_update = 0.0
75+
last_display_refresh = 0.0
76+
last_telemetry_send = 0.0
77+
78+
client = TBDeviceMqttClient(
79+
THINGSBOARD_HOST, port=THINGSBOARD_PORT, access_token=THINGSBOARD_TOKEN
80+
)
81+
client.connect()
82+
83+
initial_weather = get_current_weather(selected_city)
84+
if initial_weather is not None:
85+
weather_data["temp"] = initial_weather["temp"]
86+
weather_data["humidity"] = initial_weather["humidity"]
87+
88+
while True:
89+
now = time.monotonic()
90+
91+
indoor_temp = sensor.temperature
92+
indoor_humidity = sensor.relative_humidity
93+
94+
if now - last_weather_update >= WEATHER_UPDATE_PERIOD:
95+
last_weather_update = now
96+
updated_weather = get_current_weather(selected_city)
97+
if updated_weather is not None:
98+
weather_data["temp"] = updated_weather["temp"]
99+
weather_data["humidity"] = updated_weather["humidity"]
100+
101+
if now - last_display_refresh >= DISPLAY_REFRESH_PERIOD:
102+
last_display_refresh = now
103+
draw_screen(
104+
indoor_temp, indoor_humidity, weather_data["temp"], weather_data["humidity"]
105+
)
106+
107+
if now - last_telemetry_send >= TELEMETRY_SEND_PERIOD:
108+
last_telemetry_send = now
109+
110+
telemetry = {
111+
"indoorTemp": round(indoor_temp, 1),
112+
"indoorHumidity": round(indoor_humidity, 1),
113+
"outdoorTemp": weather_data["temp"],
114+
"outdoorHumidity": weather_data["humidity"],
115+
"city": selected_city,
116+
}
117+
118+
try:
119+
client.send_telemetry(telemetry)
120+
print("Telemetry sent:", telemetry)
121+
except Exception as e:
122+
print("Telemetry send failed:", e)
123+
124+
time.sleep(0.1)
125+
126+
127+
if __name__ == "__main__":
128+
main()

0 commit comments

Comments
 (0)