|
|
package mill
import ( "bytes" "encoding/json" "fmt" lucifer3 "git.aiterp.net/lucifer3/server" "git.aiterp.net/lucifer3/server/device" "git.aiterp.net/lucifer3/server/events" "git.aiterp.net/lucifer3/server/internal/gentools" "log" "math" "net/http" "strings" "sync" "time" )
type WifiBridge struct { ID string IP string
state *device.State
mx sync.Mutex started bool bus *lucifer3.EventBus }
func (w *WifiBridge) SetBus(bus *lucifer3.EventBus) { w.bus = bus }
func (w *WifiBridge) SetState(id string, state device.State) bool { if !strings.HasPrefix(id, w.ID) { return false }
return true }
func (w *WifiBridge) Start() { if err := w.refresh(); err != nil { w.bus.RunEvent(deviceFailed(w.ID, err)) return }
w.started = true go func() { defer func() { recover()
log.Printf("Mill: %s stopped unexpectedly", w.ID) w.started = false }()
for { time.Sleep(1 * time.Minute)
if err := w.refresh(); err != nil { w.bus.RunEvent(deviceFailed(w.ID, err)) break } } }() }
func (w *WifiBridge) IsStarted() bool { return w.started }
func (w *WifiBridge) refresh() error { w.mx.Lock() defer w.mx.Unlock()
temp, err := w.getTemperature() if err != nil { return err }
if w.state != nil { w.state = &device.State{ Temperature: gentools.Ptr(temp), }
w.bus.RunEvent(events.DeviceReady{ID: w.ID}) w.bus.RunEvent(events.HardwareMetadata{ID: w.ID, Icon: "heater"}) w.bus.RunEvent(events.HardwareState{ ID: w.ID, InternalName: "Mill heater @ " + w.IP, SupportFlags: device.SFlagTemperature, State: *w.state, }) }
w.state.Temperature = gentools.Ptr(*w.state.Temperature - math.Mod(*w.state.Temperature, 0.5))
if math.Abs(temp-*w.state.Temperature) >= 0.1 { if err := w.writeTemperature(); err != nil { return err } }
return nil }
func (w *WifiBridge) getTemperature() (float64, error) { body, err := json.Marshal(getSetTemperatureBody{Type: "Normal"}) if err != nil { return 0.0, err }
req, err := http.NewRequest( "GET", fmt.Sprintf("http://%s/set-temperature", w.IP), bytes.NewReader(body), ) if err != nil { return 0.0, err }
res, err := http.DefaultClient.Do(req) if err != nil { return 0.0, err }
var resBody getSetTemperatureResponse err = json.NewDecoder(res.Body).Decode(&resBody) if err != nil || resBody.Status != "ok" { return 0.0, fmt.Errorf("refresh failed %s (bad response from query)", w.ID) }
return resBody.Value, nil }
func (w *WifiBridge) writeTemperature() error { body, err := json.Marshal(postSetTemperatureBody{ Type: "Normal", Value: *w.state.Temperature, }) if err != nil { return err }
req, err := http.NewRequest( "POST", fmt.Sprintf("http://%s/set-temperature", w.IP), bytes.NewReader(body), ) if err != nil { return err }
res, err := http.DefaultClient.Do(req) if err != nil { return err }
var resBody postSetTemperatureResponse err = json.NewDecoder(res.Body).Decode(&resBody) if err != nil || resBody.Status != "ok" { return fmt.Errorf("refresh failed %s (bad response from query)", w.ID) }
w.bus.RunEvent(events.HardwareState{ ID: w.ID, InternalName: "Mill heater @ " + w.IP, SupportFlags: device.SFlagTemperature, State: *w.state, }) return nil }
type getSetTemperatureBody struct { Type string `json:"type"` }
type postSetTemperatureBody struct { Type string `json:"type"` Value float64 `json:"value"` }
type getSetTemperatureResponse struct { Value float64 `json:"value"` Status string `json:"status"` }
type postSetTemperatureResponse struct { Status string `json:"status"` }
|