-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.rs
148 lines (136 loc) · 4.62 KB
/
main.rs
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! Serve on a web interface to control The Kit
//! Set `stty -F /dev/ttyACM0 -hupcl` in a udev rule first
//
// Copyright 2021 Zhang Maiyun <me@maiyun.me>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
use std::fs::OpenOptions;
use std::io::{Read, Write};
use tiny_http::{Header, Response, Server};
/// Read one line from a `Read`, discarding the trailing newline
fn unbuffered_readline<R: Read>(mut file: R) -> String {
let mut buffer = [0; 1];
let mut resp = String::new();
while let Ok(n) = file.read(&mut buffer) {
// Stop reading when line ends
if buffer[0] as char == '\n' {
break;
}
// Stop if the stream is empty
if n == 0 {
break;
}
resp.push(buffer[0] as char);
}
resp
}
fn main() {
let server = Server::http("0.0.0.0:8780").unwrap();
for request in server.incoming_requests() {
let url = request.url();
println!("Request at {}", url);
if url == "/" {
let header = Header::from_bytes(&b"Location"[..], &b"/dashboard"[..]).unwrap();
let mut response = Response::empty(302);
response.add_header(header);
request.respond(response).ok();
continue;
}
if url.starts_with("/dashboard") {
let header = Header::from_bytes(&b"Content-Type"[..], &b"text/html"[..]).unwrap();
let mut response = Response::from_string(DASHBOARD);
response.add_header(header);
request.respond(response).ok();
continue;
}
// Run the command
let command = &url[1..];
let response_string = match OpenOptions::new()
.read(true)
.write(true)
.open("/dev/ttyACM0")
{
Ok(mut tty) => {
if let Err(error) = writeln!(&mut tty, "{}", command) {
format!("{{\"error\": \"{:?}\"}}", error)
} else {
// Get the response
unbuffered_readline(&tty)
}
}
Err(error) => {
format!("{{\"error\": \"{:?}\"}}", error)
}
};
println!("Response is: {}", response_string);
let header = Header::from_bytes(&b"Content-Type"[..], &b"application/json"[..]).unwrap();
let mut response = Response::from_string(&response_string);
response.add_header(header);
request.respond(response).ok();
}
}
const DASHBOARD: &str = r#"
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="UTF-8" />
<title> The Kit Controller </title>
<style>
h1, button {
width: 100%;
text-align: center;
font-size: 2em;
}
#resblk {
width: 100%;
}
button {
background: black;
color: white;
}
</style>
</head>
<body>
<h1> The Kit Controller </h1>
<button id="turnon" type="button" onclick="lightSwitch(true)"> Turn Light On </button>
<button id="turnoff" type="button" onclick="lightSwitch(false)"> Turn Light Off </button>
<button id="playaudio" type="button" onclick="playAudio()"> Play Audio </button>
<button id="getinfo" type="button" onclick="getInfo()"> Get System Information </button>
<pre id="resblk"></pre>
<script>
function xhrGlue(endpoint) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
const obj = JSON.parse(this.responseText);
document.getElementById("resblk").innerHTML = JSON.stringify(obj, null, 2);
}
};
xhttp.open("GET", endpoint, true);
xhttp.send();
}
function lightSwitch(on) {
xhrGlue("/light_" + (on ? "on" : "off"));
}
function playAudio() {
xhrGlue("/play");
}
function getInfo() {
xhrGlue("/get_info");
}
</script>
</body>
</html>
"#;