Control your Nest thermostat with Twilio and FastAPI
Change the temperature on your Nest thermostat with a single text
import os
from fastapi import FastAPI, Request
from twilio.twiml.messaging_response import MessagingResponse
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow, InstalledAppFlow
from googleapiclient.discovery import build
app = FastAPI()
# Set your Twilio Account SID, Auth Token, and Google Credentials JSON file
twilio_account_sid = "YOUR_TWILIO_ACCOUNT_SID"
twilio_auth_token = "YOUR_TWILIO_AUTH_TOKEN"
google_credentials_file = "YOUR_GOOGLE_CREDENTIALS_JSON_FILE"
# Set the device ID of your Nest thermostat
nest_thermostat_device_id = "YOUR_NEST_THERMOSTAT_DEVICE_ID"
# Set up Google API client
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = google_credentials_file
flow = InstalledAppFlow.from_client_secrets_file(google_credentials_file, ["https://www.googleapis.com/auth/sdm.service"])
credentials = flow.run_local_server(port=0)
google_api = build("smartdevicemanagement", "v1", credentials=credentials)
@app.post("/sms")
async def handle_sms(request: Request):
form_data = await request.form()
message_body = form_data.get("Body")
try:
temperature = int(message_body.strip())
except ValueError:
response = MessagingResponse()
response.message("Invalid temperature value. Please send a valid number.")
return str(response)
try:
set_temperature(nest_thermostat_device_id, temperature)
response = MessagingResponse()
response.message(f"Temperature set to {temperature}°F.")
return str(response)
except Exception as e:
response = MessagingResponse()
response.message("Failed to set temperature. Please try again.")
return str(response)
def set_temperature(device_id: str, temperature_f: int):
temperature_c = (temperature_f - 32) * (5 / 9)
request_body = {
"command" : "sdm.devices.commands.ThermostatTemperatureSetpoint.SetHeat",
"params" : {"heatCelsius": temperature_c}
}
google_api.enterprises().devices().executeCommand(name=device_id, body=request_body).execute()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)