Skip to content

Instantly share code, notes, and snippets.

@floitsch
Last active July 14, 2024 11:30
Show Gist options
  • Save floitsch/96ca6729ffca7d3d9e5b79158c2977fc to your computer and use it in GitHub Desktop.
Save floitsch/96ca6729ffca7d3d9e5b79158c2977fc to your computer and use it in GitHub Desktop.
// Copyright (C) 2024 Florian Loitsch.
// Use of this source code is governed by a Zero-Clause BSD license.
import bme280
import certificate-roots
import encoding.json
import gpio
import http
import http.server as http
import i2c
import net
BME-SDA ::= 32
BME-SCL ::= 33
HEATING-PIN ::= 26
FORECAST-URL ::= "https://www.example.com"
class Heater:
task_/Task? := null
pin_/gpio.Pin := gpio.Pin HEATING-PIN --output
constructor:
set-heating value/bool:
pin_.set (value ? 1 : 0)
switch-to-local:
if task_: task_.cancel
task_ = task::
sda := gpio.Pin BME-SDA
scl := gpio.Pin BME-SCL
bus := i2c.Bus --sda=sda --scl=scl
device := bus.device bme280.I2C-ADDRESS
bme := bme280.Driver device
try:
while true:
set-heating (bme.read-temperature < 20)
sleep (Duration --m=1)
finally:
critical-do:
bme.close
bus.close
scl.close
sda.close
task_ = null
switch-to-manual --should-heat:
if task_: task_.cancel
set-heating should-heat
switch-to-forecast:
if task_: task_.cancel
task_ = task::
network := net.open
client := http.Client network
try:
while true:
e := catch:
response := client.get --uri=FORECAST-URL
decoded := json.decode-stream response.body
set-heating (decoded["temperature"] < 20)
if e: print "Error: $e"
sleep (Duration --h=1)
finally:
critical-do:
client.close
network.close
task_ = null
INDEX-HTML ::= """
<html>
<head>
<title>Heating control</title>
</head>
<body>
<h1>Heating control</h1>
<p><a href="/on">Turn on</a> | <a href="/off">Turn off</a></p>
<p><a href="/forecast">Weather forecast</a> | <a href="/local">Local temperature</a></p>
</body>
</html>
"""
run-server heater/Heater:
network := net.open
tcp_socket := network.tcp_listen 80
print "Server on http://$network.address:$tcp_socket.local_address.port/"
server := http.Server
server.listen tcp_socket:: | request/http.RequestIncoming writer/http.ResponseWriter |
resource := request.query.resource
content-type := "text/plain"
is-404 := false
response/string := ?
if resource == "/" or resource == "/index.html":
content-type = "text/html"
response = INDEX-HTML
else if resource == "/on":
heater.switch-to-manual --should-heat
response = "Heating turned on"
else if resource == "/off":
heater.switch-to-manual --should-heat=false
response = "Heating turned off"
else if resource == "/forecast":
heater.switch-to-forecast
response = "Heating switched to forecast"
else if resource == "/local":
heater.switch-to-local
response = "Heating switched to local temperature"
else:
is-404 = true
response = "Unknown resource: $resource"
writer.headers.set "Content-Type" content-type
if is-404: writer.write-headers 404
writer.out.write response
writer.close
main:
certificate-roots.install-common-trusted-roots
heater := Heater
heater.switch-to-local
run-server heater
sdk: ^2.0.0-alpha.145
prefixes:
bme280: bme280-driver
certificate_roots: toit-cert-roots
http: pkg-http
packages:
bme280-driver:
url: github.com/toitware/bme280-driver
name: bme280
version: 1.0.0
hash: 65b88ac19a5e2b48627a2dbae6d7757ae45c502c
pkg-http:
url: github.com/toitlang/pkg-http
name: http
version: 2.7.2
hash: 614dd0f374e70aab09f12e9466a35b779b9a8d63
toit-cert-roots:
url: github.com/toitware/toit-cert-roots
name: certificate_roots
version: 1.6.1
hash: 55d3be82ed53d8d332338b2de931865cf69fe48b
dependencies:
bme280:
url: github.com/toitware/bme280-driver
version: ^1.0.0
certificate_roots:
url: github.com/toitware/toit-cert-roots
version: ^1.6.1
http:
url: github.com/toitlang/pkg-http
version: ^2.7.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment