package manager import ( "encoding/json" "fmt" "log" ) type SyncHandler struct { devices map[string]*_device chanForSync map[string]chan map[string]interface{} } func compareMap(src map[string]interface{}, dst map[string]interface{}) bool { for key, value := range src { if key == "code" { continue } srcV, ok := value.(int) if !ok { srcV = int(value.(float64)) } dstV, ok := dst[key].(int) if !ok { dstV = int(dst[key].(float64)) } if srcV != dstV { fmt.Println("diff ", key, "] ", srcV, " vs ", dstV) return false } } return true } func (sh *SyncHandler) Handle(e Event) { device, ok := sh.devices[e.Key().(string)] // fmt.Println("sync] ", device.IfaceName) // fmt.Println(sh.devices) if !ok { return } params := e.Params() if params == nil { return } go func() { encoder := json.NewEncoder(device.Iface) origin := map[string]interface{}{} origin["code"] = 200 for key, value := range params { origin[key] = value } // props := []string{"fan", "light", "servo"} err := encoder.Encode(origin) if err != nil { return } _, ok := sh.chanForSync[device.IfaceName] if ok { close(sh.chanForSync[device.IfaceName]) delete(sh.chanForSync, device.IfaceName) } chanForSync := make(chan map[string]interface{}) sh.chanForSync[device.IfaceName] = make(chan map[string]interface{}) for state := range chanForSync { if compareMap(origin, state) { close(sh.chanForSync[device.IfaceName]) delete(sh.chanForSync, device.IfaceName) return } log.Println("wrong: ", state) log.Println("resend: ", origin) err := encoder.Encode(origin) if err != nil { log.Println("sync routine is died") return } } }() } type RecvHandler struct { devices map[interface{}]*_device chanForSync map[string]chan map[string]interface{} next EventHandler } func (rh *RecvHandler) Handle(e Event) { device, ok := rh.devices[e.Key()] if !ok { return } param := e.Params() code, _ := param["code"].(float64) if int(code) == 100 { return } device.states = param channel, ok := rh.chanForSync[device.IfaceName] if ok { channel <- device.states } if rh.next != nil { rh.next.Handle(e) } // fmt.Println("recv] ", device.states) }