Skip to content

Commit 44b8d68

Browse files
committed
Initial commit
Temperature monitoring script - Polls temperature sensor via 1-Wire interface. - Maintains a rolling 24-hour window for high/low temperature tracking. - Sends current, highest, and lowest temperatures along with timestamps to a Hubitat home automation hub via API calls. - Configurable placeholders for sensor hardware address, API base URL, access token, and device IDs.
1 parent ba8598c commit 44b8d68

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
temperature/notes.txt
2+
temperature/temperature-monitor.service
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Simple RPi Temperature Monitor Script for Hubitat
4+
5+
This script polls a temperature sensor via the 1-Wire interface,
6+
calculates the current temperature along with the highest and lowest
7+
temperatures over a rolling 24-hour window, and sends these values to a
8+
Hubitat home automation hub via API calls.
9+
10+
Before deploying, populate these placeholders with the appropriate values:
11+
- SENSOR_ID: The hardware address for your temperature sensor.
12+
- API_BASE_URL: The base URL for your Habitat hub's API.
13+
- ACCESS_TOKEN: Your API access token.
14+
- CURRENT_DEVICE_ID, HIGHEST_DEVICE_ID, LOWEST_DEVICE_ID, TIMESTAMP_DEVICE_ID:
15+
The device IDs for the virtual sensors on the Habitat hub.
16+
17+
Notes:
18+
- Python 3.9.2
19+
- Can be configured as a service
20+
21+
"""
22+
23+
import os
24+
import glob
25+
import time
26+
import subprocess
27+
from datetime import datetime
28+
import urllib.parse
29+
30+
# Load kernel modules for the 1-Wire interface
31+
os.system('modprobe w1-gpio')
32+
os.system('modprobe w1-therm')
33+
34+
# Base directory where sensor devices are located
35+
base_dir = '/sys/bus/w1/devices/'
36+
37+
# TODO: Replace with your actual sensor hardware address (e.g., '28-XXXXXXXXXXXX')
38+
SENSOR_ID = '28-XXXXXXXXXXXX'
39+
device_folder_water = glob.glob(base_dir + SENSOR_ID)[0]
40+
device_file_water = device_folder_water + '/w1_slave'
41+
42+
def water_temp_raw():
43+
"""Read raw data from the temperature sensor."""
44+
with open(device_file_water, 'r') as f:
45+
lines = f.readlines()
46+
return lines
47+
48+
def water_temp():
49+
"""
50+
Parse the raw sensor data and return the temperature in Fahrenheit (as an integer).
51+
The sensor outputs temperature in Celsius, which is converted to Fahrenheit.
52+
"""
53+
lines = water_temp_raw()
54+
# Wait until the sensor output is valid
55+
while lines[0].strip()[-3:] != 'YES':
56+
time.sleep(0.2)
57+
lines = water_temp_raw()
58+
equals_pos = lines[1].find('t=')
59+
if equals_pos != -1:
60+
temp_string = lines[1][equals_pos + 2:]
61+
temp_c = float(temp_string) / 1000.0
62+
temp_f = temp_c * 9.0 / 5.0 + 32.0
63+
return int(round(temp_f, 0))
64+
return None
65+
66+
# Initialize current, highest, and lowest temperatures using the first sensor reading
67+
current_temperature = water_temp()
68+
highest_temperature = current_temperature
69+
lowest_temperature = current_temperature
70+
71+
# Maintain a history of temperature readings as tuples (temperature, timestamp)
72+
temperature_history = [(current_temperature, time.time())]
73+
74+
while True:
75+
temperature = water_temp()
76+
current_timestamp = time.time()
77+
78+
# Append current temperature to history
79+
temperature_history.append((temperature, current_timestamp))
80+
81+
# Remove entries older than 24 hours
82+
temperature_history = [
83+
(temp, ts) for temp, ts in temperature_history
84+
if current_timestamp - ts <= 24 * 60 * 60
85+
]
86+
87+
# Determine highest and lowest temperatures in the past 24 hours
88+
highest_temperature = max(temp for temp, _ in temperature_history)
89+
lowest_temperature = min(temp for temp, _ in temperature_history)
90+
91+
# Format the current timestamp into a date string
92+
dt = datetime.fromtimestamp(current_timestamp)
93+
date_str = dt.strftime('%-m/%-d/%Y\n%-H:%M')
94+
encoded_date_str = urllib.parse.quote(date_str, safe='')
95+
96+
# TODO: Update these values with your Habitat hub details
97+
API_BASE_URL = "http://YOUR_HUB_IP/apps/api/9/devices"
98+
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN"
99+
CURRENT_DEVICE_ID = "CURRENT_DEVICE_ID"
100+
HIGHEST_DEVICE_ID = "HIGHEST_DEVICE_ID"
101+
LOWEST_DEVICE_ID = "LOWEST_DEVICE_ID"
102+
TIMESTAMP_DEVICE_ID = "TIMESTAMP_DEVICE_ID"
103+
104+
# Construct API URLs for current, highest, and lowest temperatures, and the timestamp
105+
current_url = f"{API_BASE_URL}/{CURRENT_DEVICE_ID}/setTemperature/{temperature}?access_token={ACCESS_TOKEN}"
106+
highest_url = f"{API_BASE_URL}/{HIGHEST_DEVICE_ID}/setTemperature/{highest_temperature}?access_token={ACCESS_TOKEN}"
107+
lowest_url = f"{API_BASE_URL}/{LOWEST_DEVICE_ID}/setTemperature/{lowest_temperature}?access_token={ACCESS_TOKEN}"
108+
timestamp_url = f"{API_BASE_URL}/{TIMESTAMP_DEVICE_ID}/setVariable/{encoded_date_str}?access_token={ACCESS_TOKEN}"
109+
110+
# Send API calls using curl
111+
subprocess.run(f'curl {current_url}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
112+
subprocess.run(f'curl {highest_url}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
113+
subprocess.run(f'curl {lowest_url}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
114+
subprocess.run(f'curl {timestamp_url}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
115+
116+
# Output the temperature readings to the console for debugging/logging purposes
117+
print(f"Current Temperature: {temperature}°F")
118+
print(f"Highest Temperature (last 24 hours): {highest_temperature}°F")
119+
print(f"Lowest Temperature (last 24 hours): {lowest_temperature}°F")
120+
121+
# Wait for 15 minutes before the next reading
122+
time.sleep(900)

0 commit comments

Comments
 (0)