More succd into succbone subdirectory
This commit is contained in:
parent
519312605d
commit
1669b48dbd
9 changed files with 0 additions and 0 deletions
121
succbone/succd/http.go
Normal file
121
succbone/succd/http.go
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coder/websocket"
|
||||
"github.com/coder/websocket/wsjson"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed index.html
|
||||
templateIndexText string
|
||||
templateIndex = template.Must(template.New("index").Parse(templateIndexText))
|
||||
)
|
||||
|
||||
func formatVolts(v float32) string {
|
||||
return fmt.Sprintf("%.4f V", v)
|
||||
}
|
||||
|
||||
// formatMbar formats a millibar value using scientific notation and returns a
|
||||
// HTML fragment (for superscript support).
|
||||
func formatMbar(v float32) template.HTML {
|
||||
exp := 0
|
||||
for v < 1 {
|
||||
v *= 10
|
||||
exp -= 1
|
||||
}
|
||||
for v >= 10 {
|
||||
v /= 10
|
||||
exp += 1
|
||||
}
|
||||
res := fmt.Sprintf("%.3f", v)
|
||||
res += fmt.Sprintf(" x 10<sup>%d</sup>", exp)
|
||||
res += " mbar"
|
||||
return template.HTML(res)
|
||||
}
|
||||
|
||||
// httpIndex is the / view.
|
||||
func (d *daemon) httpIndex(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
volts, mbar := d.pirani()
|
||||
|
||||
loadB, err := os.ReadFile("/proc/loadavg")
|
||||
load := "unknown"
|
||||
if err == nil {
|
||||
parts := strings.Fields(string(loadB))
|
||||
load = strings.Join(parts[:3], " ")
|
||||
}
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
hostname = "unknown"
|
||||
}
|
||||
|
||||
templateIndex.Execute(w, map[string]any{
|
||||
"volts": formatVolts(volts),
|
||||
"mbar": formatMbar(mbar),
|
||||
"hostname": hostname,
|
||||
"load": load,
|
||||
})
|
||||
}
|
||||
|
||||
// httpStream is the websocket clientwards data hose, returning a 10Hz update
|
||||
// stream of pressure/voltage.
|
||||
func (d *daemon) httpStream(w http.ResponseWriter, r *http.Request) {
|
||||
c, err := websocket.Accept(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer c.CloseNow()
|
||||
|
||||
t := time.NewTicker(time.Second / 10)
|
||||
defer t.Stop()
|
||||
|
||||
ctx := c.CloseRead(r.Context())
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
c.Close(websocket.StatusNormalClosure, "")
|
||||
return
|
||||
case <-t.C:
|
||||
// TODO(q3k): don't poll, get notified when new ADC readout is available.
|
||||
volts, mbar := d.pirani()
|
||||
v := struct {
|
||||
Volts string
|
||||
Mbar string
|
||||
MbarFloat float32
|
||||
}{
|
||||
Volts: formatVolts(volts),
|
||||
Mbar: string(formatMbar(mbar)),
|
||||
MbarFloat: mbar,
|
||||
}
|
||||
if err := wsjson.Write(ctx, c, v); err != nil {
|
||||
klog.Errorf("Websocket write failed: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// httpMetrics serves minimalistic Prometheus-compatible metrics.
|
||||
func (d *daemon) httpMetrics(w http.ResponseWriter, r *http.Request) {
|
||||
// TODO(q3k): also serve Go stuff using the actual Prometheus metrics client
|
||||
// library.
|
||||
_, mbar := d.pirani()
|
||||
fmt.Fprintf(w, "# HELP sem_pressure_mbar Pressure in the SEM chamber, in millibar\n")
|
||||
fmt.Fprintf(w, "# TYPE sem_pressure_mbar gauge\n")
|
||||
fmt.Fprintf(w, "sem_pressure_mbar %f\n", mbar)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue