133 lines
2.4 KiB
Go
133 lines
2.4 KiB
Go
package manager
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
)
|
|
|
|
type SyncHandler struct {
|
|
devices map[string]*_device
|
|
mutex *sync.Mutex
|
|
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 {
|
|
sh.mutex.Lock()
|
|
close(sh.chanForSync[device.IfaceName])
|
|
delete(sh.chanForSync, device.IfaceName)
|
|
sh.mutex.Lock()
|
|
}
|
|
chanForSync := make(chan map[string]interface{})
|
|
sh.chanForSync[device.IfaceName] = make(chan map[string]interface{})
|
|
|
|
for state := range chanForSync {
|
|
|
|
if compareMap(origin, state) {
|
|
sh.mutex.Lock()
|
|
close(sh.chanForSync[device.IfaceName])
|
|
delete(sh.chanForSync, device.IfaceName)
|
|
sh.mutex.Lock()
|
|
return
|
|
}
|
|
log.Println("wrong: ", state)
|
|
log.Println("resend: ", origin)
|
|
err := encoder.Encode(origin)
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
log.Println("sync routine is died")
|
|
}()
|
|
}
|
|
|
|
type RecvHandler struct {
|
|
devices map[interface{}]*_device
|
|
mutex *sync.Mutex
|
|
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
|
|
rh.mutex.Lock()
|
|
channel, ok := rh.chanForSync[device.IfaceName]
|
|
rh.mutex.Unlock()
|
|
if ok {
|
|
channel <- device.states
|
|
}
|
|
|
|
if rh.next != nil {
|
|
rh.next.Handle(e)
|
|
}
|
|
|
|
// fmt.Println("recv] ", device.states)
|
|
}
|