Compare commits

..

No commits in common. "main" and "v0.1.2" have entirely different histories.
main ... v0.1.2

5 changed files with 58 additions and 88 deletions

35
cli.go
View File

@ -2,8 +2,8 @@ package manager
import (
"context"
"errors"
"log"
"sync"
"git.godopu.net/lab/etri-smartfarm-poc-controller-serial/puserial"
"github.com/rjeczalik/notify"
@ -27,7 +27,7 @@ func init() {
devicesWithUUID: devWithUUID,
devicesWithIface: devWithIface,
chanForSync: chanForSync,
SyncListener: &SyncHandler{devices: devWithUUID, chanForSync: chanForSync, mutex: &sync.Mutex{}, states: map[string]map[string]interface{}{}},
SyncListener: &SyncHandler{devices: devWithUUID, chanForSync: chanForSync},
RecvListener: &RecvHandler{devices: devWithIface, chanForSync: chanForSync},
}
@ -55,23 +55,24 @@ func AddRecvListener(h EventHandler) {
_managerObj.addRecvListener(h)
}
// func SetDevicePropsToSync(uuid string, propsToSync []string) error {
// device, ok := _managerObj.devicesWithUUID[uuid]
// if !ok {
// return errors.New("device not found")
// }
// device.propsToSync = propsToSync
// return nil
// }
func SetDevicePropsToSync(uuid string, propsToSync []string) error {
device, ok := _managerObj.devicesWithUUID[uuid]
if !ok {
return errors.New("device not found")
}
device.propsToSync = propsToSync
return nil
}
func Run() error {
ifaces, err := puserial.InitDevice()
iface, err := puserial.InitDevice()
if err != nil {
return err
}
for _, e := range ifaces {
go _managerObj.onAdded(e)
if err.Error() != "USB Not found" {
return err
}
} else {
// _managerObj.onAdd(iface)
_managerObj.onAdded(iface)
}
go puserial.WatchNewDevice(ctx, ch_discover)
@ -84,7 +85,7 @@ func Run() error {
}
switch e.Event() {
case notify.Create:
go _managerObj.onAdded(e.Path())
_managerObj.onAdded(e.Path())
// case notify.Remove:
// log.Println("USB Disconnected!!")
// _managerObj.onAdded(e.Path())

View File

@ -24,11 +24,8 @@ func main() {
param := e.Params()
fmt.Println(param["uuid"].(string), " is removed!!")
})
go manager.Run()
defer manager.Close()
param := map[string]interface{}{}
for {
fmt.Print("> ")
reader := bufio.NewReader(os.Stdin)
@ -37,6 +34,9 @@ func main() {
fmt.Println("cmd: ", cmd)
if cmd == "exit" {
return
} else if cmd == "setup" {
manager.SetDevicePropsToSync("DEVICE-A-UUID", []string{"fan", "servo"})
continue
}
tkns := strings.Split(cmd, " ")
@ -45,7 +45,9 @@ func main() {
if err != nil {
continue
}
param[tkns[1]] = value
param := map[string]interface{}{
tkns[1]: value,
}
manager.Sync(key, param)
}
}

View File

@ -4,52 +4,34 @@ import (
"encoding/json"
"fmt"
"log"
"reflect"
"sync"
)
type SyncHandler struct {
devices map[string]*_device
mutex *sync.Mutex
chanForSync map[string]chan map[string]interface{}
states map[string]map[string]interface{}
}
func compareMap(src map[string]interface{}, dst map[string]interface{}) bool {
for key, value := range src {
if key == "code" {
continue
}
if reflect.TypeOf(value).String() == "string" {
dstV, ok := dst[key].(string)
if !ok || value != dstV {
return false
}
continue
}
srcV, ok := value.(float64)
func compareMap(src map[string]interface{}, dst map[string]interface{}, props []string) bool {
for _, prop := range props {
srcV, ok := src[prop].(int)
if !ok {
srcV = float64(value.(int))
srcV = int(src[prop].(float64))
}
dstV, ok := dst[key].(float64)
dstV, ok := dst[prop].(int)
if !ok {
dstV = float64(dst[key].(int))
dstV = int(dst[prop].(float64))
}
if srcV != dstV {
fmt.Println("diff ", key, "] ", srcV, " vs ", dstV)
fmt.Println("diff ", prop, "] ", 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)
@ -66,47 +48,37 @@ func (sh *SyncHandler) Handle(e Event) {
encoder := json.NewEncoder(device.Iface)
origin := map[string]interface{}{}
origin["code"] = 200
for key, value := range params {
origin[key] = value
}
sh.states[device.UUID] = origin
props := device.propsToSync
// props := []string{"fan", "light", "servo"}
for _, pname := range props {
prop, ok := params[pname]
if !ok {
origin[pname] = device.states[pname]
} else {
origin[pname] = prop
}
}
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.Unlock()
}
chanForSync := make(chan map[string]interface{})
sh.mutex.Lock()
sh.chanForSync[device.IfaceName] = chanForSync
sh.mutex.Unlock()
for state := range chanForSync {
if compareMap(sh.states[device.UUID], state) {
sh.mutex.Lock()
sh.chanForSync[device.IfaceName] = make(chan map[string]interface{})
for state := range sh.chanForSync[device.IfaceName] {
if compareMap(origin, state, props) {
log.Println("Same!!")
close(sh.chanForSync[device.IfaceName])
delete(sh.chanForSync, device.IfaceName)
sh.mutex.Unlock()
return
}
log.Println("wrong: ", state)
log.Println("resend: ", sh.states[device.UUID])
err := encoder.Encode(sh.states[device.UUID])
log.Println("resend: ", origin)
err := encoder.Encode(origin)
if err != nil {
return
}
}
}()
}
@ -117,11 +89,6 @@ type RecvHandler struct {
}
func (rh *RecvHandler) Handle(e Event) {
defer func() {
if r := recover(); r != nil {
fmt.Println("panic recover - ", r)
}
}()
device, ok := rh.devices[e.Key()]
if !ok {
return

View File

@ -3,11 +3,12 @@ package manager
import "io"
type _device struct {
UUID string
IfaceName string
Sname string
Iface io.ReadWriter
states map[string]interface{}
UUID string
IfaceName string
Sname string
Iface io.ReadWriter
states map[string]interface{}
propsToSync []string
}
type RecvEvent struct {

View File

@ -2,6 +2,7 @@ package puserial
import (
"context"
"errors"
"fmt"
"io/ioutil"
"path/filepath"
@ -10,22 +11,20 @@ import (
"github.com/rjeczalik/notify"
)
func InitDevice() ([]string, error) {
func InitDevice() (string, error) {
fs, err := ioutil.ReadDir("/dev")
if err != nil {
return nil, err
return "", err
}
var result []string = nil
for _, f := range fs {
if strings.Contains(f.Name(), "ttyACM") {
result = append(result, filepath.Join("/dev", f.Name()))
return filepath.Join("/dev", f.Name()), nil
}
}
return result, nil
return "", errors.New("USB Not found")
}
func WatchNewDevice(ctx context.Context, ch_discover chan<- notify.EventInfo) error {
defer close(ch_discover)