Test out admin mode commands; it looks like the basic idea works for now at least
This commit is contained in:
parent
f1723ff5bd
commit
3a7bb60360
20
dev/dev.htm
20
dev/dev.htm
|
@ -166,11 +166,12 @@ async function updateCharts() {
|
|||
}
|
||||
|
||||
const sleep = (ms) => new Promise(r => setTimeout(r, ms))
|
||||
var chart_update_millis = 2000
|
||||
|
||||
async function chartupdater() {
|
||||
if (chart_updater != null) return
|
||||
|
||||
await sleep(2000)
|
||||
await sleep(chart_update_millis)
|
||||
// wait at least two seconds to avoid wasting a lot of bandwidth
|
||||
const resp = await fetch("/api/update")
|
||||
chart_updater = null
|
||||
|
@ -200,6 +201,19 @@ async function waitThenUpdateStatus() {
|
|||
updateStatus()
|
||||
}
|
||||
|
||||
async function testAdminMode() {
|
||||
const msg = JSON.stringify({
|
||||
auth: "password",
|
||||
data: {
|
||||
manual_mode: true
|
||||
}
|
||||
})
|
||||
await fetch("/api/admin", {
|
||||
method: "POST",
|
||||
body: msg
|
||||
})
|
||||
}
|
||||
|
||||
window.onload = () => {
|
||||
initCharts()
|
||||
updateCharts()
|
||||
|
@ -212,6 +226,9 @@ window.onload = () => {
|
|||
document.getElementById('autoupdate').addEventListener('click', (e) => {
|
||||
autoupdate = document.getElementById('autoupdate').checked
|
||||
})
|
||||
document.getElementById('test-admin').addEventListener('click', (e) => {
|
||||
testAdminMode()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
@ -223,6 +240,7 @@ window.onload = () => {
|
|||
<form>
|
||||
<input type=checkbox id=autoupdate checked>Autoupdate</input>
|
||||
<input type=button id=update value="Update"></input>
|
||||
<input type=button id=test-admin value="Test admin mode"></input>
|
||||
<!-- TODO add decimation and window size options -->
|
||||
<span id=status></span>
|
||||
</form>
|
||||
|
|
|
@ -31,6 +31,8 @@ type ShroomStatus struct {
|
|||
NumConnections int
|
||||
Wait chan struct{}
|
||||
StatusWait chan struct{}
|
||||
|
||||
Commands chan []byte
|
||||
}
|
||||
|
||||
func (s *ShroomStatus) Update() {
|
||||
|
@ -71,7 +73,7 @@ func parseMsg(line []byte, db *sql.DB, status *ShroomStatus) {
|
|||
// we got a data packet
|
||||
status.Update()
|
||||
} else if data.Status != -1 {
|
||||
log.Println("received status ", data.Status)
|
||||
//log.Println("received status ", data.Status)
|
||||
status.Lock()
|
||||
// TODO change to have more detailed data
|
||||
status.HumidifierOn = (data.Status & 1) == 1
|
||||
|
@ -96,6 +98,12 @@ func InitTcpServer(db *sql.DB, status *ShroomStatus) {
|
|||
log.Println("tcp accept error: ", err)
|
||||
return
|
||||
}
|
||||
// not spawning a goroutine here
|
||||
// should limit the number of connections to
|
||||
// one hopefully
|
||||
|
||||
// wrapping in a func() so that I can use defer
|
||||
// to automatically decrement the number of connections
|
||||
func() {
|
||||
status.Lock()
|
||||
status.NumConnections += 1
|
||||
|
@ -112,8 +120,27 @@ func InitTcpServer(db *sql.DB, status *ShroomStatus) {
|
|||
|
||||
log.Println("connection started")
|
||||
|
||||
// write loop; waits for commands and forwards them
|
||||
exiting := make(chan struct{})
|
||||
go func() {
|
||||
// TODO deal with the write side of the connection
|
||||
for {
|
||||
select {
|
||||
case v, ok := <-status.Commands:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
v = append(v, []byte("\n")...)
|
||||
_, err := conn.Write(v)
|
||||
if err != nil {
|
||||
log.Println("tcp write err: ", err)
|
||||
}
|
||||
case <-exiting:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
defer func() {
|
||||
close(exiting)
|
||||
}()
|
||||
|
||||
// deal with the read side of the connection
|
||||
|
|
|
@ -29,6 +29,11 @@ type statusJson struct {
|
|||
Humidifier bool `json:"humidifier"`
|
||||
}
|
||||
|
||||
type adminMsg struct {
|
||||
Auth string `json:"auth"`
|
||||
Msg map[string]interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func dumpData(db *sql.DB, multiplier int64) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, req *http.Request) {
|
||||
now := time.Now().Unix()
|
||||
|
@ -70,6 +75,7 @@ func main() {
|
|||
status := s.ShroomStatus{
|
||||
Wait: make(chan struct{}),
|
||||
StatusWait: make(chan struct{}),
|
||||
Commands: make(chan []byte),
|
||||
}
|
||||
s.InitTcpServer(db, &status)
|
||||
|
||||
|
@ -106,7 +112,7 @@ func main() {
|
|||
msg, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to marshal json: %w", err)
|
||||
w.WriteHeader(500)
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(err.Error()))
|
||||
} else {
|
||||
w.Write(msg)
|
||||
|
@ -114,9 +120,49 @@ func main() {
|
|||
}
|
||||
|
||||
adminHandler := func(w http.ResponseWriter, req *http.Request) {
|
||||
w.WriteHeader(500)
|
||||
w.Write([]byte("unimplemented"))
|
||||
// TODO
|
||||
if req.Method != "POST" {
|
||||
w.WriteHeader(405)
|
||||
w.Write([]byte("method must be POST"))
|
||||
return
|
||||
}
|
||||
msg := make([]byte, 256)
|
||||
l, err := req.Body.Read(msg)
|
||||
if err != nil && l == 0 {
|
||||
err = fmt.Errorf("unable to read body: %w", err)
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
adminReq := adminMsg{}
|
||||
err = json.Unmarshal(msg[:l], &adminReq)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to unmarshal body as json: %w", err)
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// TODO switch to embedded secret
|
||||
if adminReq.Auth != "password" {
|
||||
w.WriteHeader(401)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
inner_msg, err := json.Marshal(adminReq.Msg)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to marshal inner message: %w", err)
|
||||
w.WriteHeader(400)
|
||||
w.Write([]byte(err.Error()))
|
||||
return
|
||||
}
|
||||
select {
|
||||
case status.Commands <- inner_msg:
|
||||
w.Write([]byte("ok"))
|
||||
default:
|
||||
w.WriteHeader(503)
|
||||
w.Write([]byte("unable to forward request; controller may not be connected"))
|
||||
}
|
||||
}
|
||||
|
||||
updateHandler := func(w http.ResponseWriter, req *http.Request) {
|
||||
|
|
Loading…
Reference in New Issue