From e1f533c0041f1702831b8d04b06d595759c36a33 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Tue, 28 Jan 2020 17:04:24 -0800 Subject: [PATCH] add support for retrieving current brightness value prior to performing action --- wemo.go | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/wemo.go b/wemo.go index ffbab45..0a02d44 100644 --- a/wemo.go +++ b/wemo.go @@ -3,6 +3,7 @@ package main import ( "bytes" "encoding/json" + "encoding/xml" "fmt" "io/ioutil" "log" @@ -17,6 +18,7 @@ import ( "git.lerch.org/lobo/wemo/wemodiscovery" ) + type basementPost struct { MovieMode bool } @@ -31,6 +33,7 @@ type controlData struct { type deviceAction struct { Device, Action, Content string + StartAction, StartContent, StartField string Steps, Seconds, Start, End int EndOff bool } @@ -39,10 +42,28 @@ type soapActions struct { On, Off []deviceAction } +type soapResponse struct { + XMLName xml.Name `xml:"Envelope"` + Body getBinaryStateBody `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"` +} +type getBinaryStateBody struct { + XMLName xml.Name + GetBinaryStateResponse getBinaryStateBodyResponse `xml:"urn:Belkin:service:basicevent:1 GetBinaryStateResponse"` +} +type getBinaryStateBodyResponse struct { + XMLName xml.Name + State bool `xml:"BinaryState"` + Brightness int `xml:"brightness"` + Fader string `xml:"fader"` +} + + var command string var client http.Client func main() { + getState := "\"urn:Belkin:service:basicevent:1#GetBinaryState\"" + getStateContent := "" command = os.Getenv("CMD") port := os.Getenv("PORT") if port == "" { port = ":8081" } else { port = ":" + port } @@ -50,10 +71,25 @@ func main() { if len(os.Args) > 1 { if os.Args[1] == "on" { movieMode(true) - }else{ + time.Sleep(10 * time.Second) // Allow the thread time to do magic + }else if os.Args[1] == "off" { movieMode(false) + time.Sleep(10 * time.Second) // Allow the thread time to do magic + }else if os.Args[1] == "scan" { + refreshControl() + println("control file updated") + }else if os.Args[1] == "getState" { + logger.Infof("getState") + addresses := readAddresses() + for _, address := range addresses.Devices { + if address.Name == os.Args[2] { + dim := getCurrentDimValue(address.Url+addresses.BasicEvent, address.Name, getState, getStateContent) + println("dim value is ", dim) + } + } + }else{ + println("wemo [on|off|scan|getState] [device name]") } - time.Sleep(10 * time.Second) // movieMode(false) os.Exit(0) } @@ -131,13 +167,17 @@ func commandDevice(url string, device deviceAction) { sendCommand(url, device, device.Content) return } - logger.Tracef("%s: Stepping the change. %d to %d over %d steps", device.Device, device.Start, device.End, device.Steps) + start := device.Start + if start == -1 { + start = getCurrentDimValue(url, device.Device, device.StartAction, device.StartContent) + } + logger.Tracef("%s: Stepping the change. %d to %d over %d steps", device.Device, start, device.End, device.Steps) // We want to fade something... millisecondsPerTick := device.Seconds * 1000 / device.Steps logger.Tracef("%s: %d ms per step over %d seconds", device.Device, millisecondsPerTick, device.Seconds) - deltaPerTick := (device.End - device.Start) / (device.Steps - 1) + deltaPerTick := (device.End - start) / (device.Steps - 1) logger.Tracef("%s: %d change per command", device.Device, deltaPerTick) - currentValue := device.Start + currentValue := start currentSteps := 0 ticker := time.NewTicker(time.Duration(millisecondsPerTick) * time.Millisecond) quit := make(chan struct{}) @@ -192,6 +232,35 @@ func sendCommand(url string, device deviceAction, content string) { } } +func getCurrentDimValue(url string, name string, action string, content string) int { + req, err := http.NewRequest("POST", url, nil) + rc := 0 + if err != nil { + logger.Errorf("Error building http request to device %s: %s", name, err) + } + req.Header.Add("SOAPACTION", action) + req.Header.Add("Content-type", `text/xml; charset="utf-8"`) + req.Body = ioutil.NopCloser(bytes.NewBufferString(content)) + res, err := client.Do(req) + if err != nil { + logger.Errorf("Error on http request to device %s: %s", name, err) + }else{ + responseBytes, err := ioutil.ReadAll(res.Body) + logger.Tracef("%s: Response from lights: %s", name, responseBytes) + if err != nil { + logger.Errorf("Error reading response from device %s: %s", name, err) + } + var envelope soapResponse + xml.Unmarshal(responseBytes, &envelope) + rc = envelope.Body.GetBinaryStateResponse.Brightness + logger.Tracef("%s: Unmarshal: #v", name, envelope) + logger.Tracef("%s: Brightness: %d", name, rc) + logger.Tracef("%s: State: %t", name, envelope.Body.GetBinaryStateResponse.State) + logger.Tracef("%s: Fader: %s", name, envelope.Body.GetBinaryStateResponse.Fader) + } + return rc +} + func readAddresses() controlData { var rc controlData bytes, err := ioutil.ReadFile("controlData.json")