Compare commits
No commits in common. "main" and "618d97432af243ee0ed89961f2390a7d1492b564" have entirely different histories.
main
...
618d97432a
@ -1,20 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"os/exec"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ChangePermission(iface string) error {
|
|
||||||
log.Println("changing the mod of file")
|
|
||||||
|
|
||||||
cmd := exec.Command("chmod", "a+rw", iface)
|
|
||||||
b, err := cmd.CombinedOutput()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(b))
|
|
||||||
return nil
|
|
||||||
}
|
|
94
cli.go
94
cli.go
@ -1,94 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"git.godopu.net/lab/etri-smartfarm-poc-controller-serial/puserial"
|
|
||||||
"github.com/rjeczalik/notify"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ctx context.Context
|
|
||||||
var cancel context.CancelFunc
|
|
||||||
var ch_discover chan notify.EventInfo
|
|
||||||
var _managerObj *_manager
|
|
||||||
var registerHandleFunc func(e Event)
|
|
||||||
var removeHandleFunc func(e Event)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ctx, cancel = context.WithCancel(context.Background())
|
|
||||||
ch_discover = make(chan notify.EventInfo)
|
|
||||||
devWithUUID := map[string]*_device{}
|
|
||||||
devWithIface := map[interface{}]*_device{}
|
|
||||||
chanForSync := map[string]chan map[string]interface{}{}
|
|
||||||
|
|
||||||
_managerObj = &_manager{
|
|
||||||
devicesWithUUID: devWithUUID,
|
|
||||||
devicesWithIface: devWithIface,
|
|
||||||
chanForSync: chanForSync,
|
|
||||||
SyncListener: &SyncHandler{devices: devWithUUID, chanForSync: chanForSync, mutex: &sync.Mutex{}, states: map[string]map[string]interface{}{}},
|
|
||||||
RecvListener: &RecvHandler{devices: devWithIface, chanForSync: chanForSync},
|
|
||||||
}
|
|
||||||
|
|
||||||
registerHandleFunc = nil
|
|
||||||
removeHandleFunc = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddRegisterHandleFunc(h func(e Event)) {
|
|
||||||
registerHandleFunc = h
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddRemoveHandleFunc(h func(e Event)) {
|
|
||||||
removeHandleFunc = h
|
|
||||||
}
|
|
||||||
|
|
||||||
func Close() {
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
func Sync(key string, param map[string]interface{}) {
|
|
||||||
_managerObj.onSync(key, param)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 Run() error {
|
|
||||||
ifaces, err := puserial.InitDevice()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, e := range ifaces {
|
|
||||||
go _managerObj.onAdded(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
go puserial.WatchNewDevice(ctx, ch_discover)
|
|
||||||
|
|
||||||
for {
|
|
||||||
e, ok := <-ch_discover
|
|
||||||
if !ok {
|
|
||||||
log.Println("manager exit")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
switch e.Event() {
|
|
||||||
case notify.Create:
|
|
||||||
go _managerObj.onAdded(e.Path())
|
|
||||||
// case notify.Remove:
|
|
||||||
// log.Println("USB Disconnected!!")
|
|
||||||
// _managerObj.onAdded(e.Path())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func recv(port io.Reader, r Receiver) {
|
|
||||||
reader := bufio.NewReader(port)
|
|
||||||
|
|
||||||
for {
|
|
||||||
b, _, err := reader.ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
log.Println("USB is disconnected")
|
|
||||||
_managerObj.onRemoved(port)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
recvObj := map[string]interface{}{}
|
|
||||||
err = json.Unmarshal(b, &recvObj)
|
|
||||||
|
|
||||||
if err == nil {
|
|
||||||
r.onRecv(port, recvObj)
|
|
||||||
}
|
|
||||||
// data = string(b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// for {
|
|
||||||
// fmt.Print("> ")
|
|
||||||
// cmd, _, _ := cmdReader.ReadLine()
|
|
||||||
// cmdTkns := strings.Split(string(cmd), " ")
|
|
||||||
|
|
||||||
// if cmdTkns[0] == "light" {
|
|
||||||
// command["code"] = 1
|
|
||||||
// if cmdTkns[1] == "on" {
|
|
||||||
// command["light"] = 100
|
|
||||||
// } else {
|
|
||||||
// command["light"] = 0
|
|
||||||
// }
|
|
||||||
// } else if cmdTkns[0] == "fan" {
|
|
||||||
// command["code"] = 2
|
|
||||||
// if cmdTkns[1] == "on" {
|
|
||||||
// command["status"] = 1
|
|
||||||
// } else {
|
|
||||||
// command["status"] = 0
|
|
||||||
// }
|
|
||||||
// } else if cmdTkns[0] == "servo" {
|
|
||||||
// command["code"] = 3
|
|
||||||
// angle, err := strconv.Atoi(cmdTkns[1])
|
|
||||||
// if err != nil {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// command["angle"] = angle
|
|
||||||
// } else if cmdTkns[0] == "print" {
|
|
||||||
// fmt.Println(data)
|
|
||||||
// }
|
|
||||||
// err := encoder.Encode(command)
|
|
||||||
// if err != nil {
|
|
||||||
// panic(err)
|
|
||||||
// }
|
|
||||||
// }
|
|
55
constants/constatns.go
Normal file
55
constants/constatns.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package constants
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/magiconair/properties"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Config = map[string]string{}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
|
||||||
|
if _, err := os.Stat("./config.properties"); errors.Is(err, os.ErrNotExist) {
|
||||||
|
// path/to/whatever does not exist
|
||||||
|
f, err := os.Create("./config.properties")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
p := properties.NewProperties()
|
||||||
|
p.SetValue("serverAddr", "localhost:3000")
|
||||||
|
p.SetValue("cname", "controller-A")
|
||||||
|
p.Write(f, properties.UTF8)
|
||||||
|
Config["serverAddr"] = "localhost:3000"
|
||||||
|
Config["cname"] = "controller-A"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p := properties.MustLoadFile("./config.properties", properties.UTF8)
|
||||||
|
Config["serverAddr"] = p.GetString("serverAddr", "localhost:3000")
|
||||||
|
Config["cname"] = p.GetString("cname", "controller-A")
|
||||||
|
Config["cid"] = p.GetString("cid", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Set(key, value string) {
|
||||||
|
|
||||||
|
var p *properties.Properties
|
||||||
|
if _, err := os.Stat("./config.properties"); errors.Is(err, os.ErrNotExist) {
|
||||||
|
p = properties.NewProperties()
|
||||||
|
} else {
|
||||||
|
p = properties.MustLoadFile("./config.properties", properties.UTF8)
|
||||||
|
os.Remove("./config.properties")
|
||||||
|
}
|
||||||
|
f, err := os.Create("./config.properties")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
p.SetValue(key, value)
|
||||||
|
p.Write(f, properties.UTF8)
|
||||||
|
Config[key] = value
|
||||||
|
}
|
72
devicemanager/discovery.go
Normal file
72
devicemanager/discovery.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package devicemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
manager "git.godopu.net/lab/etri-smartfarm-poc-controller-serial"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PostDevice(w http.ResponseWriter, r *http.Request) {
|
||||||
|
defer log.Println("Post Device End")
|
||||||
|
// 장치로 부터 전달된 데이터 처리
|
||||||
|
parameter := map[string]interface{}{}
|
||||||
|
|
||||||
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
err := decoder.Decode(¶meter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 탐색 이벤트를 처리 큐에 입력
|
||||||
|
respCh := make(chan []byte)
|
||||||
|
ctx := context.WithValue(context.Background(), managerKey(parameterKey), parameter)
|
||||||
|
ctx = context.WithValue(ctx, managerKey(waitResponseKey), respCh)
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
taskQueue <- &task{Event: DISCOVERY, Ctx: ctx}
|
||||||
|
select {
|
||||||
|
case resp := <-respCh:
|
||||||
|
if len(resp) == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
w.Write(resp)
|
||||||
|
case <-r.Context().Done():
|
||||||
|
w.WriteHeader(http.StatusNotAcceptable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterHandler(e manager.Event) {
|
||||||
|
param := e.Params()
|
||||||
|
payload := map[string]interface{}{}
|
||||||
|
payload["dname"] = param["uuid"]
|
||||||
|
payload["type"] = "device"
|
||||||
|
payload["sname"] = param["sname"]
|
||||||
|
|
||||||
|
// b, err := json.Marshal(payload)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Println(err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// resp, err := http.Post("http://localhost:4000/devices", "application/json", bytes.NewReader(b))
|
||||||
|
// if err != nil {
|
||||||
|
// log.Println(err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
respCh := make(chan []byte)
|
||||||
|
ctx := context.WithValue(context.Background(), managerKey(parameterKey), payload)
|
||||||
|
ctx = context.WithValue(ctx, managerKey(waitResponseKey), respCh)
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
taskQueue <- &task{Event: DISCOVERY, Ctx: ctx}
|
||||||
|
|
||||||
|
fmt.Println(string(<-respCh))
|
||||||
|
}
|
81
devicemanager/handler.go
Normal file
81
devicemanager/handler.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package devicemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"etrismartfarmpoccontroller/model"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
manager "git.godopu.net/lab/etri-smartfarm-poc-controller-serial"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewRecvHandler() manager.EventHandler {
|
||||||
|
return manager.NewEventHandler(func(e manager.Event) {
|
||||||
|
fmt.Println("RECV: ", e.Params())
|
||||||
|
parmas := e.Params()
|
||||||
|
payload := map[string]interface{}{}
|
||||||
|
|
||||||
|
var ok bool
|
||||||
|
payload["uuid"], ok = parmas["uuid"]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := model.GetDBHandler("sqlite", "./dump.db")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
device, err := db.GetDeviceID(payload["uuid"].(string))
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
device.DName = payload["uuid"].(string)
|
||||||
|
device.SID, err = db.GetSID(device.SName)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
parameter := map[string]interface{}{
|
||||||
|
"params": parmas,
|
||||||
|
"device": device,
|
||||||
|
}
|
||||||
|
respCh := make(chan []byte)
|
||||||
|
ctx := context.WithValue(context.Background(), managerKey(parameterKey), parameter)
|
||||||
|
ctx = context.WithValue(ctx, managerKey(waitResponseKey), respCh)
|
||||||
|
taskQueue <- &task{Event: STATUSREPORT, Ctx: ctx}
|
||||||
|
|
||||||
|
resp := map[string]interface{}{}
|
||||||
|
b := <-respCh
|
||||||
|
err = json.Unmarshal(b, &resp)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(string(b))
|
||||||
|
} else {
|
||||||
|
|
||||||
|
changed := db.StatusCheck(device.DID, resp)
|
||||||
|
|
||||||
|
if changed {
|
||||||
|
fmt.Println("change property: ", resp)
|
||||||
|
manager.Sync(device.DName, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ctx, cancel := context.WithCancel(ctx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemovedHandler(e manager.Event) {
|
||||||
|
param := e.Params()
|
||||||
|
payload := map[string]interface{}{}
|
||||||
|
payload["dname"] = param["uuid"]
|
||||||
|
respCh := make(chan []byte)
|
||||||
|
ctx := context.WithValue(context.Background(), managerKey(parameterKey), payload)
|
||||||
|
ctx = context.WithValue(ctx, managerKey(waitResponseKey), respCh)
|
||||||
|
taskQueue <- &task{Event: DISCONNECTED, Ctx: ctx}
|
||||||
|
|
||||||
|
fmt.Println(string(<-respCh))
|
||||||
|
}
|
91
devicemanager/manager.go
Normal file
91
devicemanager/manager.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package devicemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"etrismartfarmpoccontroller/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type task struct {
|
||||||
|
Event int
|
||||||
|
Ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
var taskQueue = make(chan *task, 100)
|
||||||
|
|
||||||
|
type managerKey int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DISCOVERY int = iota
|
||||||
|
DISCONNECTED
|
||||||
|
STATUSREPORT
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
waitResponseKey managerKey = iota
|
||||||
|
parameterKey
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewManager() (func(), func()) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
run := func() {
|
||||||
|
go run(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return run, cancel
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case t := <-taskQueue:
|
||||||
|
|
||||||
|
switch t.Event {
|
||||||
|
case DISCOVERY:
|
||||||
|
p := t.Ctx.Value(managerKey(parameterKey))
|
||||||
|
b, err := RegisterDevice(p.(map[string]interface{}), t.Ctx.Done())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
respCh, ok := t.Ctx.Value(managerKey(waitResponseKey)).(chan []byte)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respCh <- b
|
||||||
|
|
||||||
|
case DISCONNECTED:
|
||||||
|
p := t.Ctx.Value(managerKey(parameterKey))
|
||||||
|
b, err := DeleteDevice(p.(map[string]interface{}))
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
respCh, ok := t.Ctx.Value(managerKey(waitResponseKey)).(chan []byte)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respCh <- b
|
||||||
|
// p := t.Ctx.Value(managerKey(parameterKey))
|
||||||
|
|
||||||
|
case STATUSREPORT:
|
||||||
|
p := t.Ctx.Value(managerKey(parameterKey))
|
||||||
|
params, _ := p.(map[string]interface{})["params"].(map[string]interface{})
|
||||||
|
device, _ := p.(map[string]interface{})["device"].(*model.Device)
|
||||||
|
|
||||||
|
respCh, ok := t.Ctx.Value(managerKey(waitResponseKey)).(chan []byte)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ForwardMessage(device.DID, device.SID, params)
|
||||||
|
if err != nil {
|
||||||
|
respCh <- []byte(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
respCh <- b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
122
devicemanager/operation.go
Normal file
122
devicemanager/operation.go
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
package devicemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"etrismartfarmpoccontroller/constants"
|
||||||
|
"etrismartfarmpoccontroller/model"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RegisterDevice(payload map[string]interface{}, cancelCh <-chan struct{}) ([]byte, error) {
|
||||||
|
payload["cid"] = constants.Config["cid"]
|
||||||
|
b, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
req, err := http.NewRequestWithContext(
|
||||||
|
ctx,
|
||||||
|
"POST",
|
||||||
|
"http://"+constants.Config["serverAddr"]+"/devices",
|
||||||
|
bytes.NewReader(b),
|
||||||
|
)
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
var resp *http.Response
|
||||||
|
done := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
resp, err = http.DefaultClient.Do(req)
|
||||||
|
if resp == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
done <- true
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case <-cancelCh:
|
||||||
|
return nil, errors.New("cancel error")
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode == http.StatusCreated {
|
||||||
|
db, err := model.GetDBHandler("sqlite", "./dump.db")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var device model.Device
|
||||||
|
json.Unmarshal(b, &device)
|
||||||
|
err = db.AddDevice(&device)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// db := model.GetDBHandler("sqlite", "./dump.db")
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteDevice(payload map[string]interface{}) ([]byte, error) {
|
||||||
|
payload["cid"] = constants.Config["cid"]
|
||||||
|
b, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(
|
||||||
|
"DELETE",
|
||||||
|
"http://"+constants.Config["serverAddr"]+"/devices",
|
||||||
|
bytes.NewReader(b),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ForwardMessage(did, sid string, payload map[string]interface{}) ([]byte, error) {
|
||||||
|
|
||||||
|
b, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req, err := http.NewRequest("PUT", "http://localhost:3000/services/"+sid+"/"+did, bytes.NewBuffer(b))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return b, nil
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
manager "git.godopu.net/lab/etri-smartfarm-poc-controller-serial"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
manager.AddRecvListener(manager.NewEventHandler(func(e manager.Event) {
|
|
||||||
fmt.Println("RECV: ", e.Params())
|
|
||||||
}))
|
|
||||||
|
|
||||||
manager.AddRegisterHandleFunc(func(e manager.Event) {
|
|
||||||
param := e.Params()
|
|
||||||
fmt.Println(param["uuid"].(string), " is registered!! ] ", param["sname"])
|
|
||||||
})
|
|
||||||
|
|
||||||
manager.AddRemoveHandleFunc(func(e manager.Event) {
|
|
||||||
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)
|
|
||||||
b, _, _ := reader.ReadLine()
|
|
||||||
cmd := string(b)
|
|
||||||
fmt.Println("cmd: ", cmd)
|
|
||||||
if cmd == "exit" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tkns := strings.Split(cmd, " ")
|
|
||||||
key := tkns[0]
|
|
||||||
value, err := strconv.Atoi(tkns[2])
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
param[tkns[1]] = value
|
|
||||||
manager.Sync(key, param)
|
|
||||||
}
|
|
||||||
}
|
|
19
go.mod
19
go.mod
@ -1,10 +1,21 @@
|
|||||||
module git.godopu.net/lab/etri-smartfarm-poc-controller-serial
|
module etrismartfarmpoccontroller
|
||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4
|
git.godopu.net/lab/etri-smartfarm-poc-controller-serial v0.1.6
|
||||||
github.com/rjeczalik/notify v0.9.2
|
github.com/gorilla/mux v1.8.0
|
||||||
|
github.com/magiconair/properties v1.8.5
|
||||||
|
github.com/urfave/negroni v1.0.0
|
||||||
|
gorm.io/driver/sqlite v1.2.3
|
||||||
|
gorm.io/gorm v1.22.2
|
||||||
)
|
)
|
||||||
|
|
||||||
require golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7 // indirect
|
require (
|
||||||
|
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.2 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.9 // indirect
|
||||||
|
github.com/rjeczalik/notify v0.9.2 // indirect
|
||||||
|
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7 // indirect
|
||||||
|
)
|
||||||
|
30
go.sum
30
go.sum
@ -1,6 +1,36 @@
|
|||||||
|
git.godopu.net/lab/etri-smartfarm-poc-controller-serial v0.1.6 h1:wHBwaWOfkdfX6U6C+eqmzUgf/IxyKdF4PdyaLH08Qg0=
|
||||||
|
git.godopu.net/lab/etri-smartfarm-poc-controller-serial v0.1.6/go.mod h1:G7GCLSX0CnuA50+PBlW7555iga99j7t3n3G4xN/37oo=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4 h1:G2ztCwXov8mRvP0ZfjE6nAlaCX2XbykaeHdbT6KwDz0=
|
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4 h1:G2ztCwXov8mRvP0ZfjE6nAlaCX2XbykaeHdbT6KwDz0=
|
||||||
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4/go.mod h1:2RvX5ZjVtsznNZPEt4xwJXNJrM3VTZoQf7V6gk0ysvs=
|
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4/go.mod h1:2RvX5ZjVtsznNZPEt4xwJXNJrM3VTZoQf7V6gk0ysvs=
|
||||||
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
|
github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI=
|
||||||
|
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
|
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
|
||||||
|
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
|
github.com/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8=
|
||||||
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
|
github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/urfave/negroni v1.0.0 h1:kIimOitoypq34K7TG7DUaJ9kq/N4Ofuwi1sjz0KipXc=
|
||||||
|
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
|
||||||
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7 h1:bit1t3mgdR35yN0cX0G8orgLtOuyL9Wqxa1mccLB0ig=
|
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7 h1:bit1t3mgdR35yN0cX0G8orgLtOuyL9Wqxa1mccLB0ig=
|
||||||
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gorm.io/driver/sqlite v1.2.3 h1:OwKm0xRAnsZMWAl5BtXJ9BsXAZHIt802DOTVMQuzWN8=
|
||||||
|
gorm.io/driver/sqlite v1.2.3/go.mod h1:wkiGvZF3le/8vjCRYg0bT8TSw6APZ5rtgKW8uQYE3sc=
|
||||||
|
gorm.io/gorm v1.22.0/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||||
|
gorm.io/gorm v1.22.2 h1:1iKcvyJnR5bHydBhDqTwasOkoo6+o4Ms5cknSt6qP7I=
|
||||||
|
gorm.io/gorm v1.22.2/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||||
|
21
interface.go
21
interface.go
@ -1,21 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
type Event interface {
|
|
||||||
Params() map[string]interface{}
|
|
||||||
Key() interface{}
|
|
||||||
}
|
|
||||||
type EventHandler interface {
|
|
||||||
Handle(e Event)
|
|
||||||
}
|
|
||||||
|
|
||||||
type Receiver interface {
|
|
||||||
onRecv(key interface{}, params map[string]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
type Syncronizer interface {
|
|
||||||
onSync(key interface{}, params map[string]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
147
listener.go
147
listener.go
@ -1,147 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
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)
|
|
||||||
if !ok {
|
|
||||||
srcV = float64(value.(int))
|
|
||||||
}
|
|
||||||
|
|
||||||
dstV, ok := dst[key].(float64)
|
|
||||||
if !ok {
|
|
||||||
dstV = float64(dst[key].(int))
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
sh.states[device.UUID] = origin
|
|
||||||
// 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.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
|
|
||||||
}
|
|
||||||
log.Println("wrong: ", state)
|
|
||||||
log.Println("resend: ", sh.states[device.UUID])
|
|
||||||
err := encoder.Encode(sh.states[device.UUID])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
type RecvHandler struct {
|
|
||||||
devices map[interface{}]*_device
|
|
||||||
chanForSync map[string]chan map[string]interface{}
|
|
||||||
next EventHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
152
main.go
Normal file
152
main.go
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"etrismartfarmpoccontroller/constants"
|
||||||
|
"etrismartfarmpoccontroller/devicemanager"
|
||||||
|
"etrismartfarmpoccontroller/router"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
manager "git.godopu.net/lab/etri-smartfarm-poc-controller-serial"
|
||||||
|
)
|
||||||
|
|
||||||
|
// func runBootstrap() {
|
||||||
|
// l, err := net.NewListenUDP("udp4", "", net.WithHeartBeat(time.Second*5))
|
||||||
|
// if err != nil {
|
||||||
|
// log.Println(err)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// defer l.Close()
|
||||||
|
|
||||||
|
// init := false
|
||||||
|
// minTimeout := time.Second * 5
|
||||||
|
// timeout := minTimeout
|
||||||
|
|
||||||
|
// d := func() {
|
||||||
|
// s := udp.NewServer(udp.WithTransmission(time.Second, timeout/2, 2))
|
||||||
|
// var wg sync.WaitGroup
|
||||||
|
// defer wg.Wait()
|
||||||
|
// defer s.Stop()
|
||||||
|
// wg.Add(1)
|
||||||
|
// go func() {
|
||||||
|
// defer wg.Done()
|
||||||
|
// s.Serve(l)
|
||||||
|
// }()
|
||||||
|
|
||||||
|
// ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||||
|
// defer cancel()
|
||||||
|
|
||||||
|
// req, err := client.NewGetRequest(ctx, "/bs") /* msg.Option{
|
||||||
|
// ID: msg.URIQuery,
|
||||||
|
// Value: []byte("rt=oic.wk.d"),
|
||||||
|
// }*/
|
||||||
|
// if err != nil {
|
||||||
|
// panic(fmt.Errorf("cannot create discover request: %w", err))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// req.SetMessageID(udpmessage.GetMID())
|
||||||
|
// req.SetType(udpmessage.NonConfirmable)
|
||||||
|
// defer pool.ReleaseMessage(req)
|
||||||
|
|
||||||
|
// err = s.DiscoveryRequest(req, bootstrapAddr, func(cc *client.ClientConn, resp *pool.Message) {
|
||||||
|
// b, err := ioutil.ReadAll(resp.Body())
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// fmt.Println(string(b))
|
||||||
|
// init = true
|
||||||
|
// })
|
||||||
|
// if err != nil {
|
||||||
|
// panic(err)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for {
|
||||||
|
// d()
|
||||||
|
// if init {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
func register() error {
|
||||||
|
// Controller 이름을 읽어옴
|
||||||
|
payload := map[string]string{}
|
||||||
|
payload["cname"] = constants.Config["cname"]
|
||||||
|
fmt.Println(constants.Config["cname"])
|
||||||
|
b, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controller 등록 메시지 송신
|
||||||
|
resp, err := http.Post(
|
||||||
|
fmt.Sprintf("http://%s/%s", constants.Config["serverAddr"], "controllers"),
|
||||||
|
"application/json",
|
||||||
|
bytes.NewReader(b),
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 응답 메시지 수신
|
||||||
|
b, err = ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
json.Unmarshal(b, &payload)
|
||||||
|
|
||||||
|
// 등록 후 생성된 Controller ID 저장
|
||||||
|
constants.Set("cid", payload["cid"])
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
if constants.Config["cid"] == "" {
|
||||||
|
err := register()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run, _ := devicemanager.NewManager()
|
||||||
|
run()
|
||||||
|
|
||||||
|
manager.AddRecvListener(devicemanager.NewRecvHandler())
|
||||||
|
// handler := devicemanager.NewRecvHandler()
|
||||||
|
manager.AddRegisterHandleFunc(devicemanager.RegisterHandler)
|
||||||
|
manager.AddRemoveHandleFunc(devicemanager.RemovedHandler)
|
||||||
|
|
||||||
|
go manager.Run()
|
||||||
|
|
||||||
|
http.ListenAndServe(":4000", router.NewRouter())
|
||||||
|
|
||||||
|
// for {
|
||||||
|
// fmt.Println("> ")
|
||||||
|
// var cmd string
|
||||||
|
// fmt.Scanln(&cmd)
|
||||||
|
// if cmd == "exit" {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// handler.Handle(&Temp{})
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// type Temp struct{}
|
||||||
|
|
||||||
|
// func (*Temp) Key() interface{} {
|
||||||
|
// return &struct{}{}
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (*Temp) Params() map[string]interface{} {
|
||||||
|
// return map[string]interface{}{
|
||||||
|
// "uuid": "DEVICE-A-UUID",
|
||||||
|
// }
|
||||||
|
// }
|
131
manager.go
131
manager.go
@ -1,131 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/jacobsa/go-serial/serial"
|
|
||||||
)
|
|
||||||
|
|
||||||
type _manager struct {
|
|
||||||
devicesWithUUID map[string]*_device
|
|
||||||
devicesWithIface map[interface{}]*_device
|
|
||||||
chanForSync map[string]chan map[string]interface{}
|
|
||||||
RegisterListener EventHandler
|
|
||||||
SyncListener EventHandler
|
|
||||||
RecvListener EventHandler
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *_manager) onRegistered(dev *_device) {
|
|
||||||
// if m.RegisterListener != nil {
|
|
||||||
// m.RegisterListener.Handle(&EventStruct{key: })
|
|
||||||
// }
|
|
||||||
if registerHandleFunc != nil {
|
|
||||||
param := map[string]interface{}{}
|
|
||||||
param["uuid"] = dev.UUID
|
|
||||||
param["sname"] = dev.Sname
|
|
||||||
|
|
||||||
registerHandleFunc(&EventStruct{key: dev.UUID, params: param})
|
|
||||||
}
|
|
||||||
go recv(dev.Iface, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *_manager) onRemoved(port io.Reader) {
|
|
||||||
dev := _managerObj.devicesWithIface[port]
|
|
||||||
delete(m.devicesWithUUID, dev.UUID)
|
|
||||||
delete(m.devicesWithIface, port)
|
|
||||||
ch, ok := m.chanForSync[dev.UUID]
|
|
||||||
if ok {
|
|
||||||
close(ch)
|
|
||||||
delete(m.chanForSync, dev.UUID)
|
|
||||||
}
|
|
||||||
|
|
||||||
if removeHandleFunc != nil {
|
|
||||||
param := map[string]interface{}{}
|
|
||||||
param["uuid"] = dev.UUID
|
|
||||||
|
|
||||||
removeHandleFunc(&EventStruct{key: dev.UUID, params: param})
|
|
||||||
}
|
|
||||||
// log.Println(m.devicesWithUUID)
|
|
||||||
// log.Println(m.devicesWithIface)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *_manager) onAdded(iface string) {
|
|
||||||
err := ChangePermission(iface)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up options.
|
|
||||||
options := serial.OpenOptions{
|
|
||||||
PortName: iface,
|
|
||||||
BaudRate: 9600,
|
|
||||||
DataBits: 8,
|
|
||||||
StopBits: 1,
|
|
||||||
MinimumReadSize: 16,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open the port.
|
|
||||||
go func() {
|
|
||||||
port, err := serial.Open(options)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("serial.Open: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
reader := bufio.NewReader(port)
|
|
||||||
encoder := json.NewEncoder(port)
|
|
||||||
|
|
||||||
sndMsg := map[string]interface{}{}
|
|
||||||
sndMsg["code"] = 100
|
|
||||||
|
|
||||||
for {
|
|
||||||
b, _, _ := reader.ReadLine()
|
|
||||||
rcvMsg := map[string]interface{}{}
|
|
||||||
err := json.Unmarshal(b, &rcvMsg)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
code, ok := rcvMsg["code"].(float64)
|
|
||||||
if ok && code == 100 {
|
|
||||||
newDevice := &_device{
|
|
||||||
UUID: rcvMsg["uuid"].(string),
|
|
||||||
IfaceName: iface,
|
|
||||||
Iface: port,
|
|
||||||
Sname: rcvMsg["sname"].(string),
|
|
||||||
states: map[string]interface{}{},
|
|
||||||
}
|
|
||||||
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(key interface{}, params map[string]interface{}) {
|
|
||||||
if m.SyncListener != nil {
|
|
||||||
m.SyncListener.Handle(&EventStruct{key: key, params: params})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *_manager) onRecv(key interface{}, params map[string]interface{}) {
|
|
||||||
if m.RecvListener != nil {
|
|
||||||
m.RecvListener.Handle(&EventStruct{key: key, params: params})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *_manager) addRecvListener(h EventHandler) {
|
|
||||||
m.RecvListener = &RecvHandler{next: h, devices: m.devicesWithIface, chanForSync: m.chanForSync}
|
|
||||||
}
|
|
15
model.go
15
model.go
@ -1,15 +0,0 @@
|
|||||||
package manager
|
|
||||||
|
|
||||||
import "io"
|
|
||||||
|
|
||||||
type _device struct {
|
|
||||||
UUID string
|
|
||||||
IfaceName string
|
|
||||||
Sname string
|
|
||||||
Iface io.ReadWriter
|
|
||||||
states map[string]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type RecvEvent struct {
|
|
||||||
Params map[string]interface{}
|
|
||||||
}
|
|
69
model/cache.go
Normal file
69
model/cache.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"etrismartfarmpoccontroller/constants"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *dbHandler) StatusCheck(did string, new map[string]interface{}) bool {
|
||||||
|
origin, ok := s.states[did]
|
||||||
|
if !ok {
|
||||||
|
fmt.Println(did)
|
||||||
|
fmt.Println("insert origin, before", s.states[did])
|
||||||
|
s.states[did] = new
|
||||||
|
// origin = map[string]interface{}{}
|
||||||
|
// s.states[did] = origin
|
||||||
|
// for k, v := range new {
|
||||||
|
// origin[k] = v
|
||||||
|
// }
|
||||||
|
fmt.Println("insert origin, after", s.states[did])
|
||||||
|
fmt.Println("insert origin, new", new)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
changed := false
|
||||||
|
for k, v := range new {
|
||||||
|
if v.(float64) != origin[k].(float64) {
|
||||||
|
fmt.Println("origin, new", v, origin[k])
|
||||||
|
origin[k] = v
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *dbHandler) GetSID(sname string) (string, error) {
|
||||||
|
sid, ok := s.cache[sname]
|
||||||
|
if !ok {
|
||||||
|
req, err := http.NewRequest("GET",
|
||||||
|
fmt.Sprintf("http://%s/%s", constants.Config["serverAddr"], "services"),
|
||||||
|
nil,
|
||||||
|
)
|
||||||
|
|
||||||
|
req.Header.Set("sname", sname)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
} else if resp.ContentLength == 0 {
|
||||||
|
return "", errors.New("not exist service")
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
sid = string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sid, nil
|
||||||
|
}
|
62
model/device.go
Normal file
62
model/device.go
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "gorm.io/gorm"
|
||||||
|
|
||||||
|
type Device struct {
|
||||||
|
gorm.Model
|
||||||
|
DID string `gorm:"uniqueIndex;column:did" json:"did"` // Device ID
|
||||||
|
DName string `gorm:"column:dname" json:"dname"` // Device Name
|
||||||
|
Type string `gorm:"column:type" json:"type"` // Device Type
|
||||||
|
CID string `gorm:"column:cid" json:"cid"` // Controller ID
|
||||||
|
SID string `gorm:"column:sid" json:"sid"` // Service ID
|
||||||
|
SName string `gorm:"column:sname" json:"sname"` // Service Name
|
||||||
|
// Opts []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *dbHandler) GetDevices() ([]*Device, int, error) {
|
||||||
|
var devices []*Device
|
||||||
|
|
||||||
|
result := s.db.Find(&devices)
|
||||||
|
|
||||||
|
if result.Error != nil {
|
||||||
|
return nil, -1, result.Error
|
||||||
|
}
|
||||||
|
return devices, int(result.RowsAffected), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (s *dbHandler) GetDevice() *Device {
|
||||||
|
// device := &Device{}
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (s *dbHandler) AddDevice(device *Device) error {
|
||||||
|
|
||||||
|
tx := s.db.Create(device)
|
||||||
|
if tx.Error != nil {
|
||||||
|
return tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.First(device, "did=?", device.DID)
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *dbHandler) GetDeviceID(dname string) (*Device, error) {
|
||||||
|
var device Device
|
||||||
|
tx := s.db.Select("did", "sname").First(&device, "dname=?", dname)
|
||||||
|
|
||||||
|
if tx.Error != nil {
|
||||||
|
return nil, tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return &device, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *dbHandler) GetServiceForDevice(did string) (string, error) {
|
||||||
|
var device Device
|
||||||
|
tx := s.db.Select("sname").First(&device, "did=?", did)
|
||||||
|
if tx.Error != nil {
|
||||||
|
return "", tx.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.GetSID(device.SName)
|
||||||
|
}
|
44
model/handler.go
Normal file
44
model/handler.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gorm.io/driver/sqlite"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type dbHandler struct {
|
||||||
|
db *gorm.DB
|
||||||
|
cache map[string]string
|
||||||
|
states map[string]map[string]interface{}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSqliteHandler(path string) (DBHandler, error) {
|
||||||
|
db, err := gorm.Open(sqlite.Open(path), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
db.AutoMigrate(&Device{})
|
||||||
|
|
||||||
|
return &dbHandler{
|
||||||
|
db: db,
|
||||||
|
cache: map[string]string{},
|
||||||
|
states: map[string]map[string]interface{}{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// func newPostgresqlHandler(path string) (DBHandler, error) {
|
||||||
|
// dsn := "host=localhost user=user password=user_password dbname=godopudb port=5432 sslmode=disable TimeZone=Asia/Seoul"
|
||||||
|
// db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// db.AutoMigrate(&Device{})
|
||||||
|
|
||||||
|
// return &dbHandler{db: db, cache: map[string]string{}}, nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// func (s *dbHandler) GetDevice() *Device {
|
||||||
|
// device := &Device{}
|
||||||
|
// }
|
29
model/interface.go
Normal file
29
model/interface.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
// func newDBHandler(dbtype, path string) (*gorm.DB, error) {
|
||||||
|
// if dbtype == "sqlite" {
|
||||||
|
// return gorm.Open(sqlite.Open("./test.db"), &gorm.Config{})
|
||||||
|
// } else {
|
||||||
|
// dsn := "host=localhost user=user password=user_password dbname=godopudb port=5432 sslmode=disable TimeZone=Asia/Seoul"
|
||||||
|
// return gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
type DBHandler interface {
|
||||||
|
GetDevices() ([]*Device, int, error)
|
||||||
|
AddDevice(device *Device) error
|
||||||
|
GetSID(sname string) (string, error)
|
||||||
|
GetServiceForDevice(did string) (string, error)
|
||||||
|
GetDeviceID(dname string) (*Device, error)
|
||||||
|
StatusCheck(did string, new map[string]interface{}) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
var db DBHandler
|
||||||
|
|
||||||
|
func GetDBHandler(dbtype, path string) (DBHandler, error) {
|
||||||
|
if db == nil {
|
||||||
|
db, _ = newSqliteHandler(path)
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
return db, nil
|
||||||
|
}
|
@ -1,174 +0,0 @@
|
|||||||
package puserial
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/rjeczalik/notify"
|
|
||||||
)
|
|
||||||
|
|
||||||
func InitDevice() ([]string, error) {
|
|
||||||
fs, err := ioutil.ReadDir("/dev")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var result []string = nil
|
|
||||||
for _, f := range fs {
|
|
||||||
if strings.Contains(f.Name(), "ttyACM") {
|
|
||||||
result = append(result, filepath.Join("/dev", f.Name()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func WatchNewDevice(ctx context.Context, ch_discover chan<- notify.EventInfo) error {
|
|
||||||
defer close(ch_discover)
|
|
||||||
|
|
||||||
filter := make(chan notify.EventInfo, 1)
|
|
||||||
if err := notify.Watch("/dev", filter, notify.Create); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer notify.Stop(filter)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil
|
|
||||||
case e := <-filter:
|
|
||||||
if strings.Contains(e.Path(), "/dev/ttyACM") {
|
|
||||||
fmt.Println(e.Path())
|
|
||||||
ch_discover <- e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// func InitUSB() (string, error) {
|
|
||||||
// fs, err := ioutil.ReadDir("/dev")
|
|
||||||
// if err != nil {
|
|
||||||
// return "", err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for _, f := range fs {
|
|
||||||
// if strings.Contains(f.Name(), "ttyACM") {
|
|
||||||
// return filepath.Join("/dev", f.Name()), nil
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return "", errors.New("USB Not found")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func Run() {
|
|
||||||
// dev, err := InitUSB()
|
|
||||||
// if err != nil {
|
|
||||||
// if err.Error() == "USB Not found" {
|
|
||||||
// dev = DiscoverUSB()
|
|
||||||
// } else {
|
|
||||||
// log.Fatalln(err.Error())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fmt.Println("discover: ", dev)
|
|
||||||
// time.Sleep(time.Second)
|
|
||||||
|
|
||||||
// log.Println("changing the mod of file")
|
|
||||||
// cmd := exec.Command("chmod", "a+rw", dev)
|
|
||||||
// b, _ := cmd.CombinedOutput()
|
|
||||||
// fmt.Println(string(b))
|
|
||||||
|
|
||||||
// // Set up options.
|
|
||||||
// options := serial.OpenOptions{
|
|
||||||
// PortName: dev,
|
|
||||||
// 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()
|
|
||||||
|
|
||||||
// // Write 4 bytes to the port.
|
|
||||||
// // b := []byte{0x00, 0x01, 0x02, 0x03}
|
|
||||||
// // n, err := port.Write(b)
|
|
||||||
// // if err != nil {
|
|
||||||
// // log.Fatalf("port.Write: %v", err)
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // fmt.Println("Wrote", n, "bytes.")
|
|
||||||
// // var tokenByte string
|
|
||||||
|
|
||||||
// reader := bufio.NewReader(port)
|
|
||||||
// // decoder := json.NewDecoder(port)
|
|
||||||
// encoder := json.NewEncoder(port)
|
|
||||||
// command := map[string]interface{}{}
|
|
||||||
// command["code"] = 1
|
|
||||||
// command["light"] = 0
|
|
||||||
|
|
||||||
// var data string
|
|
||||||
// go func() {
|
|
||||||
// for {
|
|
||||||
// b, _, _ := reader.ReadLine()
|
|
||||||
// recvObj := map[string]interface{}{}
|
|
||||||
// err := json.Unmarshal(b, &recvObj)
|
|
||||||
// // err = readJsonFromSerial(recvObj, decoder)
|
|
||||||
// if err != nil {
|
|
||||||
// if err.Error() == "EOF" {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fmt.Println("error: ", string(b))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// data = string(b)
|
|
||||||
// // fmt.Println("line : ", recvObj)
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
|
|
||||||
// cmdReader := bufio.NewReader(os.Stdin)
|
|
||||||
// for {
|
|
||||||
// fmt.Print("> ")
|
|
||||||
// cmd, _, _ := cmdReader.ReadLine()
|
|
||||||
// cmdTkns := strings.Split(string(cmd), " ")
|
|
||||||
|
|
||||||
// if cmdTkns[0] == "light" {
|
|
||||||
// command["code"] = 1
|
|
||||||
// if cmdTkns[1] == "on" {
|
|
||||||
// command["light"] = 100
|
|
||||||
// } else {
|
|
||||||
// command["light"] = 0
|
|
||||||
// }
|
|
||||||
// } else if cmdTkns[0] == "fan" {
|
|
||||||
// command["code"] = 2
|
|
||||||
// if cmdTkns[1] == "on" {
|
|
||||||
// command["status"] = 1
|
|
||||||
// } else {
|
|
||||||
// command["status"] = 0
|
|
||||||
// }
|
|
||||||
// } else if cmdTkns[0] == "servo" {
|
|
||||||
// command["code"] = 3
|
|
||||||
// angle, err := strconv.Atoi(cmdTkns[1])
|
|
||||||
// if err != nil {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// command["angle"] = angle
|
|
||||||
// } else if cmdTkns[0] == "print" {
|
|
||||||
// fmt.Println(data)
|
|
||||||
// }
|
|
||||||
// err := encoder.Encode(command)
|
|
||||||
// if err != nil {
|
|
||||||
// panic(err)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
103
router/route.go
Normal file
103
router/route.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"etrismartfarmpoccontroller/constants"
|
||||||
|
"etrismartfarmpoccontroller/devicemanager"
|
||||||
|
"etrismartfarmpoccontroller/model"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/urfave/negroni"
|
||||||
|
)
|
||||||
|
|
||||||
|
var dbHandler model.DBHandler
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var err error
|
||||||
|
dbHandler, err = model.GetDBHandler("sqlite", "./dump.db")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func NewRouter() http.Handler {
|
||||||
|
m := mux.NewRouter()
|
||||||
|
|
||||||
|
m.HandleFunc("/echo", Echo).Methods("GET")
|
||||||
|
m.HandleFunc("/devices", devicemanager.PostDevice).Methods("POST")
|
||||||
|
|
||||||
|
// sub := mux.NewRouter()
|
||||||
|
// sub.PathPrefix("/{did}/").HandlerFunc(EchoPath)
|
||||||
|
m.PathPrefix("/devices/{did}/").HandlerFunc(EchoPath)
|
||||||
|
|
||||||
|
n := negroni.Classic() // 파일 서버 및 로그기능을 제공함
|
||||||
|
n.UseHandler(m)
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func EchoPath(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
path := r.URL.Path[(len([]rune("/devices"))+len([]rune(vars["did"])))+1:]
|
||||||
|
|
||||||
|
sname, err := dbHandler.GetServiceForDevice(vars["did"])
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sid, err := dbHandler.GetSID(sname)
|
||||||
|
if err != nil || len(sid) == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// w.Write([]byte("http://" + constants.Config["serverAddr"] + "/services/" + sid + path))
|
||||||
|
req, err := http.NewRequest(
|
||||||
|
r.Method,
|
||||||
|
"http://"+constants.Config["serverAddr"]+"/services/"+sid+path,
|
||||||
|
r.Body,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// 잘못된 메시지 포맷이 전달된 경우
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
fmt.Fprint(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// 잘못된 메시지 포맷이 전달된 경우
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
fmt.Fprint(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
io.Copy(w, resp.Body)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Forward(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
|
||||||
|
sname, err := dbHandler.GetServiceForDevice(vars["did"])
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sid, err := dbHandler.GetSID(sname)
|
||||||
|
if err != nil || len(sid) == 0 {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(sid))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Echo(w http.ResponseWriter, r *http.Request) {
|
||||||
|
io.Copy(w, r.Body)
|
||||||
|
}
|
28
structure.go
28
structure.go
@ -1,28 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
type EventHandlerStruct struct {
|
|
||||||
EventHandler
|
|
||||||
HandleFunc func(e Event)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ehs *EventHandlerStruct) Handle(e Event) {
|
|
||||||
ehs.HandleFunc(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEventHandler(h func(e Event)) *EventHandlerStruct {
|
|
||||||
return &EventHandlerStruct{HandleFunc: h}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user