Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

Open the Val Town Office Doors with Switchbot

We installed two switchbot robots in our office:

  1. Ground Floor
  2. Office Door

This webpage will let Val Town employees or guests to use these bots.

The original version of this val was for a party. That fork is preserved here: @stevekrouse/switchbot_party

Next steps

  • Remove party theme
  • Add one of @pomdtr's login methods
  • Allow all @val.town emails to login
  • Have any other email login ping me for approval or make a private val with a list of approved emails
  • Add the office door to the site
  • Add instructions (ie turn off wifi completely downstairs; be gentle with the office door one)

Switchbot API

This val authenticates to the switchbot API with SWITCHBOT_TOKEN and SWITCHBOT_KEY.

Learn how to get your own Switchbot API keys here: Switchbot Docs.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// This val creates a simple web interface for opening the Val Town office door.
// It uses the Hono framework for routing and HTML rendering, and interacts with
// the SwitchBot API to control the door. The approach includes:
// 1. A frontend route that displays a button to open the door
// 2. A backend route that handles the door opening request
// 3. Integration with SwitchBot API for door control
// 4. Basic error handling and email notification on failure
/** @jsxImportSource npm:hono/jsx */
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo";
import { email } from "https://esm.town/v/std/email?v=12";
import { Buffer } from "node:buffer";
import { createHmac } from "node:crypto";
import { Hono } from "npm:hono";
const app = new Hono();
const ValTownOfficeDeviceId = "CD6F3A810848";
async function switchbotRequest(path, args) {
const token = Deno.env.get("SWITCHBOT_TOKEN");
const secret = Deno.env.get("SWITCHBOT_KEY");
const t = Date.now();
const nonce = Math.floor(Math.random() * 1000000);
const sign = createHmac("sha256", secret)
.update(Buffer.from(token + t + nonce, "utf-8"))
.digest()
.toString("base64");
const response = await fetch(`https://api.switch-bot.com/${path}`, {
headers: {
"Authorization": token,
t,
nonce,
sign,
"Content-Type": "application/json",
},
...args,
});
return response.json();
}
function botPress(device) {
return switchbotRequest(`v1.1/devices/${device}/commands`, {
method: "POST",
body: JSON.stringify({
"command": "press",
"parameter": "default",
"commandType": "command",
}),
});
}
const styles = `
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f0f0f0;
color: #333;
}
.container {
text-align: center;
background: white;
padding: 2rem;
border-radius: 15px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
h1 {
font-size: 2.5rem;
margin-bottom: 1.5rem;
}
button {
font-size: 1.5rem;
padding: 15px 30px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #45a049;
}
a {
color: #4CAF50;
text-decoration: none;
font-weight: bold;
}
a:hover {
text-decoration: underline;
}
.val-link {
margin-top: 20px;
display: inline-block;
stevekrouse-switchbot.web.val.run
August 5, 2024