commit 2021-12-10]15:45:25
This commit is contained in:
parent
fac5330b9c
commit
8934cbfa4c
74
cli.go
74
cli.go
@ -1,15 +1,11 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.godopu.net/lab/etri-smartfarm-poc-controller-serial/puserial"
|
"git.godopu.net/lab/etri-smartfarm-poc-controller-serial/puserial"
|
||||||
"github.com/jacobsa/go-serial/serial"
|
|
||||||
"github.com/rjeczalik/notify"
|
"github.com/rjeczalik/notify"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,62 +17,34 @@ var _managerObj *_manager
|
|||||||
func init() {
|
func init() {
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
ctx, cancel = context.WithCancel(context.Background())
|
||||||
ch_discover = make(chan notify.EventInfo)
|
ch_discover = make(chan notify.EventInfo)
|
||||||
|
devWithUUID := map[string]*_device{}
|
||||||
|
devWithIface := map[interface{}]*_device{}
|
||||||
|
chanForSync := map[string]chan map[string]interface{}{}
|
||||||
|
|
||||||
_managerObj = &_manager{
|
_managerObj = &_manager{
|
||||||
devices: map[string]*_device{},
|
devicesWithUUID: devWithUUID,
|
||||||
SyncListener: nil,
|
devicesWithIface: devWithIface,
|
||||||
RecvListener: nil,
|
SyncListener: &SyncHandler{devices: devWithUUID, chanForSync: chanForSync},
|
||||||
|
RecvListener: &RecvHandler{devices: devWithIface, chanForSync: chanForSync},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Close() {
|
func Close() {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
func register(iface string) {
|
func Sync(key string, param map[string]interface{}) {
|
||||||
fmt.Println("Handle] ", iface)
|
_managerObj.onSync(key, param)
|
||||||
|
}
|
||||||
|
|
||||||
// change permission
|
func SetDevicePropsToSync(uuid string, propsToSync []string) error {
|
||||||
err := ChangePermission(iface)
|
device, ok := _managerObj.devicesWithUUID[uuid]
|
||||||
if err != nil {
|
if !ok {
|
||||||
panic(err)
|
return errors.New("device not found")
|
||||||
}
|
}
|
||||||
|
device.propsToSync = propsToSync
|
||||||
// Set up options.
|
return nil
|
||||||
options := serial.OpenOptions{
|
|
||||||
PortName: iface,
|
|
||||||
BaudRate: 9600,
|
|
||||||
DataBits: 8,
|
|
||||||
StopBits: 1,
|
|
||||||
MinimumReadSize: 16,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the port.
|
|
||||||
port, err := serial.Open(options)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("serial.Open: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure to close it later.
|
|
||||||
defer port.Close()
|
|
||||||
reader := bufio.NewReader(port)
|
|
||||||
dev := &_device{}
|
|
||||||
|
|
||||||
for {
|
|
||||||
b, _, _ := reader.ReadLine()
|
|
||||||
|
|
||||||
err := json.Unmarshal(b, &dev)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(dev)
|
|
||||||
port.Write([]byte{200})
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// var data string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run() error {
|
func Run() error {
|
||||||
@ -87,7 +55,7 @@ func Run() error {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// _managerObj.onAdd(iface)
|
// _managerObj.onAdd(iface)
|
||||||
register(iface)
|
_managerObj.onAdded(iface)
|
||||||
}
|
}
|
||||||
|
|
||||||
go puserial.WatchNewDevice(ctx, ch_discover)
|
go puserial.WatchNewDevice(ctx, ch_discover)
|
||||||
@ -98,6 +66,6 @@ func Run() error {
|
|||||||
log.Println("manager exit")
|
log.Println("manager exit")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
register(e.Path())
|
_managerObj.onAdded(e.Path())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,13 @@ package manager
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func recv(reader bufio.Reader, input chan<- Event) {
|
func recv(port io.Reader, r Receiver) {
|
||||||
|
reader := bufio.NewReader(port)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
b, _, err := reader.ReadLine()
|
b, _, err := reader.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -19,20 +20,14 @@ func recv(reader bufio.Reader, input chan<- Event) {
|
|||||||
}
|
}
|
||||||
recvObj := map[string]interface{}{}
|
recvObj := map[string]interface{}{}
|
||||||
err = json.Unmarshal(b, &recvObj)
|
err = json.Unmarshal(b, &recvObj)
|
||||||
// err = readJsonFromSerial(recvObj, decoder)
|
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Println("line : ", string(b))
|
r.onRecv(port, recvObj)
|
||||||
|
|
||||||
}
|
}
|
||||||
// data = string(b)
|
// data = string(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(sender io.Writer, output <-chan Event) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// for {
|
// for {
|
||||||
// fmt.Print("> ")
|
// fmt.Print("> ")
|
||||||
// cmd, _, _ := cmdReader.ReadLine()
|
// cmd, _, _ := cmdReader.ReadLine()
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
manager "git.godopu.net/lab/etri-smartfarm-poc-controller-serial"
|
manager "git.godopu.net/lab/etri-smartfarm-poc-controller-serial"
|
||||||
)
|
)
|
||||||
@ -10,13 +13,28 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
go manager.Run()
|
go manager.Run()
|
||||||
|
|
||||||
fmt.Print("> ")
|
for {
|
||||||
var cmd string
|
fmt.Print("> ")
|
||||||
fmt.Scanln(&cmd)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
b, _, _ := reader.ReadLine()
|
||||||
|
cmd := string(b)
|
||||||
|
fmt.Println("cmd: ", cmd)
|
||||||
|
if cmd == "exit" {
|
||||||
|
return
|
||||||
|
} else if cmd == "setup" {
|
||||||
|
manager.SetDevicePropsToSync("DEVICE-A-UUID", []string{"fan", "servo"})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if cmd == "exit" {
|
tkns := strings.Split(cmd, " ")
|
||||||
manager.Close()
|
key := tkns[0]
|
||||||
|
value, err := strconv.Atoi(tkns[2])
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
param := map[string]interface{}{
|
||||||
|
tkns[1]: value,
|
||||||
|
}
|
||||||
|
manager.Sync(key, param)
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
}
|
||||||
|
11
interface.go
11
interface.go
@ -1,8 +1,17 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
type Event interface {
|
type Event interface {
|
||||||
ToJson()
|
Params() map[string]interface{}
|
||||||
|
Key() interface{}
|
||||||
}
|
}
|
||||||
type EventHandler interface {
|
type EventHandler interface {
|
||||||
Handle(e Event)
|
Handle(e Event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Receiver interface {
|
||||||
|
onRecv(key interface{}, params map[string]interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Syncronizer interface {
|
||||||
|
onSync(key interface{}, params map[string]interface{})
|
||||||
|
}
|
||||||
|
107
listener.go
107
listener.go
@ -1,13 +1,108 @@
|
|||||||
package manager
|
package manager
|
||||||
|
|
||||||
type SyncHandler struct{}
|
import (
|
||||||
|
"encoding/json"
|
||||||
func (_ *SyncHandler) Handle() {
|
"fmt"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SyncHandler struct {
|
||||||
|
devices map[string]*_device
|
||||||
|
chanForSync map[string]chan map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type RecvHandler struct{}
|
func compareMap(src map[string]interface{}, dst map[string]interface{}, props []string) bool {
|
||||||
|
for _, prop := range props {
|
||||||
func (_ *RecvHandler) Handle() {
|
srcV, ok := src[prop].(int)
|
||||||
|
if !ok {
|
||||||
|
srcV = int(src[prop].(float64))
|
||||||
|
}
|
||||||
|
|
||||||
|
dstV, ok := dst[prop].(int)
|
||||||
|
if !ok {
|
||||||
|
dstV = int(dst[prop].(float64))
|
||||||
|
}
|
||||||
|
if srcV != 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)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
params := e.Params()
|
||||||
|
if params == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
encoder := json.NewEncoder(device.Iface)
|
||||||
|
origin := map[string]interface{}{}
|
||||||
|
origin["code"] = 200
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("wrong: ", state)
|
||||||
|
log.Println("resend: ", origin)
|
||||||
|
err := encoder.Encode(origin)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
type RecvHandler struct {
|
||||||
|
devices map[interface{}]*_device
|
||||||
|
chanForSync map[string]chan map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
device.states = param
|
||||||
|
}
|
||||||
|
|
||||||
|
channel, ok := rh.chanForSync[device.IfaceName]
|
||||||
|
if ok {
|
||||||
|
channel <- device.states
|
||||||
|
}
|
||||||
|
|
||||||
|
// fmt.Println("recv] ", device.states)
|
||||||
}
|
}
|
||||||
|
63
manager.go
63
manager.go
@ -3,18 +3,25 @@ package manager
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/jacobsa/go-serial/serial"
|
"github.com/jacobsa/go-serial/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
type _manager struct {
|
type _manager struct {
|
||||||
devices map[string]*_device
|
devicesWithUUID map[string]*_device
|
||||||
SyncListener EventHandler
|
devicesWithIface map[interface{}]*_device
|
||||||
RecvListener EventHandler
|
SyncListener EventHandler
|
||||||
|
RecvListener EventHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *_manager) onAdd(iface string) {
|
func (m *_manager) onRegistered(dev *_device) {
|
||||||
|
go recv(dev.Iface, m)
|
||||||
|
log.Println("> End onRegistered")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *_manager) onAdded(iface string) {
|
||||||
err := ChangePermission(iface)
|
err := ChangePermission(iface)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -33,43 +40,55 @@ func (m *_manager) onAdd(iface string) {
|
|||||||
go func() {
|
go func() {
|
||||||
port, err := serial.Open(options)
|
port, err := serial.Open(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("serial.Open: %v", err)
|
log.Printf("serial.Open: %v", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := bufio.NewReader(port)
|
reader := bufio.NewReader(port)
|
||||||
|
encoder := json.NewEncoder(port)
|
||||||
|
|
||||||
|
sndMsg := map[string]interface{}{}
|
||||||
|
sndMsg["code"] = 100
|
||||||
|
|
||||||
for {
|
for {
|
||||||
port.Write([]byte("Introduce\n"))
|
b, _, _ := reader.ReadLine()
|
||||||
|
rcvMsg := map[string]interface{}{}
|
||||||
|
err := json.Unmarshal(b, &rcvMsg)
|
||||||
|
|
||||||
b, _, err := reader.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var obj map[string]interface{}
|
|
||||||
err = json.Unmarshal(b, &obj)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
uuid, ok := obj["uuid"]
|
code, ok := rcvMsg["code"].(float64)
|
||||||
if ok {
|
if ok && code == 100 {
|
||||||
m.devices[iface] = &_device{
|
newDevice := &_device{
|
||||||
UUID: uuid.(string),
|
UUID: rcvMsg["uuid"].(string),
|
||||||
IfaceName: iface,
|
IfaceName: iface,
|
||||||
Iface: port,
|
Iface: port,
|
||||||
|
states: map[string]interface{}{},
|
||||||
}
|
}
|
||||||
break
|
m.devicesWithUUID[rcvMsg["uuid"].(string)] = newDevice
|
||||||
|
m.devicesWithIface[port] = newDevice
|
||||||
|
|
||||||
|
m.onRegistered(newDevice)
|
||||||
|
fmt.Println("onAdded sub-routine is died")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
encoder.Encode(sndMsg)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
fmt.Println("onAdded main-routine is died")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *_manager) onSync(e Event) {
|
func (m *_manager) onSync(key interface{}, params map[string]interface{}) {
|
||||||
|
if m.SyncListener != nil {
|
||||||
|
m.SyncListener.Handle(&EventStruct{key: key, params: params})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *_manager) onRecv(e Event) {
|
func (m *_manager) onRecv(key interface{}, params map[string]interface{}) {
|
||||||
|
if m.RecvListener != nil {
|
||||||
|
m.RecvListener.Handle(&EventStruct{key: key, params: params})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
11
model.go
11
model.go
@ -3,12 +3,15 @@ package manager
|
|||||||
import "io"
|
import "io"
|
||||||
|
|
||||||
type _device struct {
|
type _device struct {
|
||||||
UUID string
|
UUID string
|
||||||
IfaceName string
|
IfaceName string
|
||||||
Iface io.ReadWriter
|
Iface io.ReadWriter
|
||||||
states []map[string]interface{}
|
states map[string]interface{}
|
||||||
|
propsToSync []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
type RecvEvent struct {
|
type RecvEvent struct {
|
||||||
Params map[string]interface{}
|
Params map[string]interface{}
|
||||||
}
|
}
|
||||||
|
15
structure.go
Normal file
15
structure.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package manager
|
||||||
|
|
||||||
|
type EventStruct struct {
|
||||||
|
Event
|
||||||
|
params map[string]interface{}
|
||||||
|
key interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *EventStruct) Params() map[string]interface{} {
|
||||||
|
return es.params
|
||||||
|
}
|
||||||
|
|
||||||
|
func (es *EventStruct) Key() interface{} {
|
||||||
|
return es.key
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user