Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
5fa75efee5 | |||
652d936d83 | |||
0f1e5e610e | |||
2a77d039a0 | |||
ce91a11c5a | |||
37705d6fe5 | |||
ab08e7ab15 | |||
a0ff2d6f52 | |||
31b00fb912 | |||
0788b44783 | |||
29a7d73791 |
31
cli.go
31
cli.go
@ -2,8 +2,8 @@ package manager
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"log"
|
"log"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"git.godopu.net/lab/etri-smartfarm-poc-controller-serial/puserial"
|
"git.godopu.net/lab/etri-smartfarm-poc-controller-serial/puserial"
|
||||||
"github.com/rjeczalik/notify"
|
"github.com/rjeczalik/notify"
|
||||||
@ -27,7 +27,7 @@ func init() {
|
|||||||
devicesWithUUID: devWithUUID,
|
devicesWithUUID: devWithUUID,
|
||||||
devicesWithIface: devWithIface,
|
devicesWithIface: devWithIface,
|
||||||
chanForSync: chanForSync,
|
chanForSync: chanForSync,
|
||||||
SyncListener: &SyncHandler{devices: devWithUUID, chanForSync: chanForSync},
|
SyncListener: &SyncHandler{devices: devWithUUID, chanForSync: chanForSync, mutex: &sync.Mutex{}, states: map[string]map[string]interface{}{}},
|
||||||
RecvListener: &RecvHandler{devices: devWithIface, chanForSync: chanForSync},
|
RecvListener: &RecvHandler{devices: devWithIface, chanForSync: chanForSync},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,24 +55,23 @@ func AddRecvListener(h EventHandler) {
|
|||||||
_managerObj.addRecvListener(h)
|
_managerObj.addRecvListener(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetDevicePropsToSync(uuid string, propsToSync []string) error {
|
// func SetDevicePropsToSync(uuid string, propsToSync []string) error {
|
||||||
device, ok := _managerObj.devicesWithUUID[uuid]
|
// device, ok := _managerObj.devicesWithUUID[uuid]
|
||||||
if !ok {
|
// if !ok {
|
||||||
return errors.New("device not found")
|
// return errors.New("device not found")
|
||||||
}
|
// }
|
||||||
device.propsToSync = propsToSync
|
// device.propsToSync = propsToSync
|
||||||
return nil
|
// return nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
func Run() error {
|
func Run() error {
|
||||||
iface, err := puserial.InitDevice()
|
ifaces, err := puserial.InitDevice()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != "USB Not found" {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// _managerObj.onAdd(iface)
|
for _, e := range ifaces {
|
||||||
_managerObj.onAdded(iface)
|
go _managerObj.onAdded(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
go puserial.WatchNewDevice(ctx, ch_discover)
|
go puserial.WatchNewDevice(ctx, ch_discover)
|
||||||
@ -85,7 +84,7 @@ func Run() error {
|
|||||||
}
|
}
|
||||||
switch e.Event() {
|
switch e.Event() {
|
||||||
case notify.Create:
|
case notify.Create:
|
||||||
_managerObj.onAdded(e.Path())
|
go _managerObj.onAdded(e.Path())
|
||||||
// case notify.Remove:
|
// case notify.Remove:
|
||||||
// log.Println("USB Disconnected!!")
|
// log.Println("USB Disconnected!!")
|
||||||
// _managerObj.onAdded(e.Path())
|
// _managerObj.onAdded(e.Path())
|
||||||
|
@ -24,8 +24,11 @@ func main() {
|
|||||||
param := e.Params()
|
param := e.Params()
|
||||||
fmt.Println(param["uuid"].(string), " is removed!!")
|
fmt.Println(param["uuid"].(string), " is removed!!")
|
||||||
})
|
})
|
||||||
|
|
||||||
go manager.Run()
|
go manager.Run()
|
||||||
defer manager.Close()
|
defer manager.Close()
|
||||||
|
|
||||||
|
param := map[string]interface{}{}
|
||||||
for {
|
for {
|
||||||
fmt.Print("> ")
|
fmt.Print("> ")
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
@ -34,9 +37,6 @@ func main() {
|
|||||||
fmt.Println("cmd: ", cmd)
|
fmt.Println("cmd: ", cmd)
|
||||||
if cmd == "exit" {
|
if cmd == "exit" {
|
||||||
return
|
return
|
||||||
} else if cmd == "setup" {
|
|
||||||
manager.SetDevicePropsToSync("DEVICE-A-UUID", []string{"fan", "servo"})
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tkns := strings.Split(cmd, " ")
|
tkns := strings.Split(cmd, " ")
|
||||||
@ -45,9 +45,7 @@ func main() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
param := map[string]interface{}{
|
param[tkns[1]] = value
|
||||||
tkns[1]: value,
|
|
||||||
}
|
|
||||||
manager.Sync(key, param)
|
manager.Sync(key, param)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
83
listener.go
83
listener.go
@ -4,34 +4,52 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SyncHandler struct {
|
type SyncHandler struct {
|
||||||
devices map[string]*_device
|
devices map[string]*_device
|
||||||
|
mutex *sync.Mutex
|
||||||
chanForSync map[string]chan map[string]interface{}
|
chanForSync map[string]chan map[string]interface{}
|
||||||
|
states map[string]map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func compareMap(src map[string]interface{}, dst map[string]interface{}, props []string) bool {
|
func compareMap(src map[string]interface{}, dst map[string]interface{}) bool {
|
||||||
for _, prop := range props {
|
|
||||||
srcV, ok := src[prop].(int)
|
for key, value := range src {
|
||||||
if !ok {
|
if key == "code" {
|
||||||
srcV = int(src[prop].(float64))
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
dstV, ok := dst[prop].(int)
|
if reflect.TypeOf(value).String() == "string" {
|
||||||
if !ok {
|
dstV, ok := dst[key].(string)
|
||||||
dstV = int(dst[prop].(float64))
|
if !ok || value != dstV {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
srcV, ok := value.(float64)
|
||||||
|
if !ok {
|
||||||
|
srcV = float64(value.(int))
|
||||||
|
}
|
||||||
|
|
||||||
|
dstV, ok := dst[key].(float64)
|
||||||
|
if !ok {
|
||||||
|
dstV = float64(dst[key].(int))
|
||||||
|
}
|
||||||
|
|
||||||
if srcV != dstV {
|
if srcV != dstV {
|
||||||
fmt.Println("diff ", prop, "] ", srcV, " vs ", dstV)
|
fmt.Println("diff ", key, "] ", srcV, " vs ", dstV)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sh *SyncHandler) Handle(e Event) {
|
func (sh *SyncHandler) Handle(e Event) {
|
||||||
|
|
||||||
device, ok := sh.devices[e.Key().(string)]
|
device, ok := sh.devices[e.Key().(string)]
|
||||||
// fmt.Println("sync] ", device.IfaceName)
|
// fmt.Println("sync] ", device.IfaceName)
|
||||||
// fmt.Println(sh.devices)
|
// fmt.Println(sh.devices)
|
||||||
@ -48,37 +66,47 @@ func (sh *SyncHandler) Handle(e Event) {
|
|||||||
encoder := json.NewEncoder(device.Iface)
|
encoder := json.NewEncoder(device.Iface)
|
||||||
origin := map[string]interface{}{}
|
origin := map[string]interface{}{}
|
||||||
origin["code"] = 200
|
origin["code"] = 200
|
||||||
props := device.propsToSync
|
for key, value := range params {
|
||||||
|
origin[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
sh.states[device.UUID] = origin
|
||||||
// props := []string{"fan", "light", "servo"}
|
// 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)
|
err := encoder.Encode(origin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sh.chanForSync[device.IfaceName] = make(chan map[string]interface{})
|
_, ok := sh.chanForSync[device.IfaceName]
|
||||||
for state := range sh.chanForSync[device.IfaceName] {
|
if ok {
|
||||||
if compareMap(origin, state, props) {
|
sh.mutex.Lock()
|
||||||
log.Println("Same!!")
|
|
||||||
close(sh.chanForSync[device.IfaceName])
|
close(sh.chanForSync[device.IfaceName])
|
||||||
delete(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()
|
||||||
|
close(sh.chanForSync[device.IfaceName])
|
||||||
|
delete(sh.chanForSync, device.IfaceName)
|
||||||
|
sh.mutex.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Println("wrong: ", state)
|
log.Println("wrong: ", state)
|
||||||
log.Println("resend: ", origin)
|
log.Println("resend: ", sh.states[device.UUID])
|
||||||
err := encoder.Encode(origin)
|
err := encoder.Encode(sh.states[device.UUID])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +117,11 @@ type RecvHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (rh *RecvHandler) Handle(e Event) {
|
func (rh *RecvHandler) Handle(e Event) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
fmt.Println("panic recover - ", r)
|
||||||
|
}
|
||||||
|
}()
|
||||||
device, ok := rh.devices[e.Key()]
|
device, ok := rh.devices[e.Key()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
|
1
model.go
1
model.go
@ -8,7 +8,6 @@ type _device struct {
|
|||||||
Sname string
|
Sname string
|
||||||
Iface io.ReadWriter
|
Iface io.ReadWriter
|
||||||
states map[string]interface{}
|
states map[string]interface{}
|
||||||
propsToSync []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecvEvent struct {
|
type RecvEvent struct {
|
||||||
|
@ -2,7 +2,6 @@ package puserial
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -11,20 +10,22 @@ import (
|
|||||||
"github.com/rjeczalik/notify"
|
"github.com/rjeczalik/notify"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitDevice() (string, error) {
|
func InitDevice() ([]string, error) {
|
||||||
fs, err := ioutil.ReadDir("/dev")
|
fs, err := ioutil.ReadDir("/dev")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var result []string = nil
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
if strings.Contains(f.Name(), "ttyACM") {
|
if strings.Contains(f.Name(), "ttyACM") {
|
||||||
return filepath.Join("/dev", f.Name()), nil
|
result = append(result, filepath.Join("/dev", f.Name()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", errors.New("USB Not found")
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func WatchNewDevice(ctx context.Context, ch_discover chan<- notify.EventInfo) error {
|
func WatchNewDevice(ctx context.Context, ch_discover chan<- notify.EventInfo) error {
|
||||||
defer close(ch_discover)
|
defer close(ch_discover)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user