From d0c6572c32a5c002274570f96b45ad6eedaf5159 Mon Sep 17 00:00:00 2001 From: corbamico Date: Wed, 1 Jan 2020 21:46:02 +0800 Subject: [PATCH] change to aircat-srv-go path --- .github/workflows/go.yml | 2 +- .gitignore | 1 + README.md | 2 +- {server => aircat-srv-go}/config.json | 8 +- aircat-srv-go/go.mod | 3 + .../internal/aircatsrv.go | 336 +++++++++--------- .../internal/influxdb.go | 98 ++--- {server => aircat-srv-go}/internal/message.go | 144 ++++---- {server => aircat-srv-go}/internal/restsrv.go | 126 +++---- {server => aircat-srv-go}/main.go | 30 +- server/go.mod | 3 - 11 files changed, 377 insertions(+), 376 deletions(-) rename {server => aircat-srv-go}/config.json (96%) create mode 100644 aircat-srv-go/go.mod rename {server => aircat-srv-go}/internal/aircatsrv.go (95%) rename {server => aircat-srv-go}/internal/influxdb.go (95%) rename {server => aircat-srv-go}/internal/message.go (95%) rename {server => aircat-srv-go}/internal/restsrv.go (96%) rename {server => aircat-srv-go}/main.go (70%) delete mode 100644 server/go.mod diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index f32b881..6459c6e 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -14,4 +14,4 @@ jobs: id: go - name: Build - run: go get -v -u github.com/corbamico/phicomm-aircat-srv/server + run: go get -v -u github.com/corbamico/phicomm-aircat-srv/aircat-srv-go diff --git a/.gitignore b/.gitignore index ad0aa48..ec01caa 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ # Dependency directories (remove the comment below to include it) # vendor/ .vscode +release/ \ No newline at end of file diff --git a/README.md b/README.md index e57d9f8..4eb67a4 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ curl http://localhost:8080/v1/aircat You can run *phicomm-aircat-srv* in router(ex. Phicomm k2p),too. ```shell -GOOS=linux GOARCH=mipsle go build github.com/corbamico/phicomm-aircat-srv/server +GOOS=linux GOARCH=mipsle go build github.com/corbamico/phicomm-aircat-srv/aircat-srv ``` ## Reference diff --git a/server/config.json b/aircat-srv-go/config.json similarity index 96% rename from server/config.json rename to aircat-srv-go/config.json index e1cd3b5..aa6ce85 100644 --- a/server/config.json +++ b/aircat-srv-go/config.json @@ -1,5 +1,5 @@ -{ - "ServerAddr": ":9000", - "RESTServerAddr": "localhost:8080", - "InfluxdbServer": "localhost:8086" +{ + "ServerAddr": ":9000", + "RESTServerAddr": "localhost:8080", + "InfluxdbServer": "localhost:8086" } \ No newline at end of file diff --git a/aircat-srv-go/go.mod b/aircat-srv-go/go.mod new file mode 100644 index 0000000..00c2931 --- /dev/null +++ b/aircat-srv-go/go.mod @@ -0,0 +1,3 @@ +module github.com/corbamico/phicomm-aircat-srv/aircat-srv-go + +go 1.13 diff --git a/server/internal/aircatsrv.go b/aircat-srv-go/internal/aircatsrv.go similarity index 95% rename from server/internal/aircatsrv.go rename to aircat-srv-go/internal/aircatsrv.go index 484177e..45cbc3a 100644 --- a/server/internal/aircatsrv.go +++ b/aircat-srv-go/internal/aircatsrv.go @@ -1,168 +1,168 @@ -package internal - -import ( - "encoding/hex" - "encoding/json" - "log" - "net" - "os" -) - -//AircatServer run at port 9000 -type AircatServer struct { - w influxdb - controlChan chan string //used for send json/string from restSrv to aircatDevice.listenControl() - device *aircatDevice //currently, we only keep one device connection. maybe we create vec in future. - restSrv *restServer -} - -//NewAircatServer create a AircatServer -func NewAircatServer() AircatServer { - controlChan := make(chan string) - - return AircatServer{ - w: influxdb{addr: configs.InfluxdbServer}, - controlChan: controlChan, - device: nil, - restSrv: newrestServer(controlChan), - } -} - -//Run AircatServer at port 9000 -func (s *AircatServer) Run() { - listen, err := net.Listen("tcp", configs.ServerAddr) - if err != nil { - log.Fatalln(err) - } - log.Printf("Server run at %s\n", listen.Addr().String()) - //run REST Server in backend go-routine - s.restSrv.setAircatServer(s) - s.restSrv.Run() - - //run recieve controlmsg in backend go-routine - go s.listenControl() - - for { - conn, err := listen.Accept() - - if err != nil { - log.Println(err) - continue - } - log.Printf("Cient connected at %s\n", conn.RemoteAddr().String()) - //Caution: - //we only keep one device connection - if s.device != nil { - s.device.cleanup() - } - s.device = newAircatDevice(s, conn) - go s.device.run() - } -} - -func (s *AircatServer) listenControl() { - for { - select { - case json, ok := <-s.controlChan: - if !ok { - //chan closed. - return - } - if s.device != nil { - //we ignore error - s.device.sendControl(json) - } - } - } -} -func (s *AircatServer) getCurrentMessage() (res string) { - if s.device != nil { - res = s.device.msg.json - } - return -} - -type aircatDevice struct { - sever *AircatServer - conn net.Conn - msg message //last report message -} - -func newAircatDevice(sever *AircatServer, conn net.Conn) *aircatDevice { - return &aircatDevice{sever: sever, conn: conn} -} - -func (client *aircatDevice) run() { - buf := make([]byte, 10240) - for { - len, err := client.conn.Read(buf) - var msg message - if err != nil { - break - } - if len < sizeMinMessage || len > sizeMaxMessage { - continue - } - if err = msg.readMsg(buf[0:len]); err != nil { - continue - } - //we got right packet - //then we write to influxdb - if msg.header.MsgType == 4 { - client.msg = msg - } - client.sever.w.write(hex.EncodeToString(msg.header.Mac[1:7]), msg.json) - } - client.conn.Close() -} - -func (client *aircatDevice) cleanup() { - if client.conn != nil { - client.conn.Close() - } -} -func (client *aircatDevice) sendControl(json string) { - bytes := client.msg.controlMsg(json) - client.conn.Write(bytes) - // log.Println("\n", hex.Dump(bytes)) - // if n, err := client.conn.Write(bytes); err == nil { - // log.Printf("send control message (size=%d)\n", n) - // } -} - -//Config for running programme -//{ -// "ServerAddr":":9000", -// "InfluxdbServer":"localhost:8086" -//} -type Config struct { - ServerAddr string //default as ":9000" - RESTServerAddr string //default as ":8080" - Influxdb bool - InfluxdbServer string //default as "localhost:8086" -} - -var configs Config - -//LoadConfig load config file -func LoadConfig(file string) error { - configFile, err := os.Open(file) - if err != nil { - return err - } - defer configFile.Close() - jsonParse := json.NewDecoder(configFile) - if err = jsonParse.Decode(&configs); err != nil { - return err - } - if configs.ServerAddr == "" { - configs.ServerAddr = ":9000" - } - if configs.RESTServerAddr == "" { - configs.RESTServerAddr = ":8080" - } - // if configs.InfluxdbServer == "" { - // configs.InfluxdbServer = "localhost:8086" - // } - return nil -} +package internal + +import ( + "encoding/hex" + "encoding/json" + "log" + "net" + "os" +) + +//AircatServer run at port 9000 +type AircatServer struct { + w influxdb + controlChan chan string //used for send json/string from restSrv to aircatDevice.listenControl() + device *aircatDevice //currently, we only keep one device connection. maybe we create vec in future. + restSrv *restServer +} + +//NewAircatServer create a AircatServer +func NewAircatServer() AircatServer { + controlChan := make(chan string) + + return AircatServer{ + w: influxdb{addr: configs.InfluxdbServer}, + controlChan: controlChan, + device: nil, + restSrv: newrestServer(controlChan), + } +} + +//Run AircatServer at port 9000 +func (s *AircatServer) Run() { + listen, err := net.Listen("tcp", configs.ServerAddr) + if err != nil { + log.Fatalln(err) + } + log.Printf("Server run at %s\n", listen.Addr().String()) + //run REST Server in backend go-routine + s.restSrv.setAircatServer(s) + s.restSrv.Run() + + //run recieve controlmsg in backend go-routine + go s.listenControl() + + for { + conn, err := listen.Accept() + + if err != nil { + log.Println(err) + continue + } + log.Printf("Cient connected at %s\n", conn.RemoteAddr().String()) + //Caution: + //we only keep one device connection + if s.device != nil { + s.device.cleanup() + } + s.device = newAircatDevice(s, conn) + go s.device.run() + } +} + +func (s *AircatServer) listenControl() { + for { + select { + case json, ok := <-s.controlChan: + if !ok { + //chan closed. + return + } + if s.device != nil { + //we ignore error + s.device.sendControl(json) + } + } + } +} +func (s *AircatServer) getCurrentMessage() (res string) { + if s.device != nil { + res = s.device.msg.json + } + return +} + +type aircatDevice struct { + sever *AircatServer + conn net.Conn + msg message //last report message +} + +func newAircatDevice(sever *AircatServer, conn net.Conn) *aircatDevice { + return &aircatDevice{sever: sever, conn: conn} +} + +func (client *aircatDevice) run() { + buf := make([]byte, 10240) + for { + len, err := client.conn.Read(buf) + var msg message + if err != nil { + break + } + if len < sizeMinMessage || len > sizeMaxMessage { + continue + } + if err = msg.readMsg(buf[0:len]); err != nil { + continue + } + //we got right packet + //then we write to influxdb + if msg.header.MsgType == 4 { + client.msg = msg + } + client.sever.w.write(hex.EncodeToString(msg.header.Mac[1:7]), msg.json) + } + client.conn.Close() +} + +func (client *aircatDevice) cleanup() { + if client.conn != nil { + client.conn.Close() + } +} +func (client *aircatDevice) sendControl(json string) { + bytes := client.msg.controlMsg(json) + client.conn.Write(bytes) + // log.Println("\n", hex.Dump(bytes)) + // if n, err := client.conn.Write(bytes); err == nil { + // log.Printf("send control message (size=%d)\n", n) + // } +} + +//Config for running programme +//{ +// "ServerAddr":":9000", +// "InfluxdbServer":"localhost:8086" +//} +type Config struct { + ServerAddr string //default as ":9000" + RESTServerAddr string //default as ":8080" + Influxdb bool + InfluxdbServer string //default as "localhost:8086" +} + +var configs Config + +//LoadConfig load config file +func LoadConfig(file string) error { + configFile, err := os.Open(file) + if err != nil { + return err + } + defer configFile.Close() + jsonParse := json.NewDecoder(configFile) + if err = jsonParse.Decode(&configs); err != nil { + return err + } + if configs.ServerAddr == "" { + configs.ServerAddr = ":9000" + } + if configs.RESTServerAddr == "" { + configs.RESTServerAddr = ":8080" + } + // if configs.InfluxdbServer == "" { + // configs.InfluxdbServer = "localhost:8086" + // } + return nil +} diff --git a/server/internal/influxdb.go b/aircat-srv-go/internal/influxdb.go similarity index 95% rename from server/internal/influxdb.go rename to aircat-srv-go/internal/influxdb.go index 1dc46e3..6d19c4d 100644 --- a/server/internal/influxdb.go +++ b/aircat-srv-go/internal/influxdb.go @@ -1,49 +1,49 @@ -package internal - -import ( - "encoding/json" - "fmt" - "net/http" - "strings" -) - -type writer interface { - write(mac string, json string) -} - -//example for line procotol: -//curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000' -//we use as : -//aircat,mac=xxx temperature=1,humidity=2,value=3,hcho=4 -type influxdb struct { - addr string -} - -func (s *influxdb) write(mac string, json string) { - if s.addr == "" { - println(mac, json) - return - } - if line := formatLineProtocol(mac, json); line != "" { - //we ignore error - go func() { - http.Post(fmt.Sprintf("http://%s/write?db=aircat", s.addr), "", strings.NewReader(line)) - }() - } - -} -func formatLineProtocol(mac string, js string) string { - var air AirMeasure - if err := json.Unmarshal([]byte(js), &air); err != nil { - return "" - } - return fmt.Sprintf("aircat,mac=\"%s\" humidity=%s,temperature=%s,value=%s,hcho=%s", mac, air.Humidity, air.Temperature, air.Value, air.Hcho) -} - -//AirMeasure reported from device -type AirMeasure struct { - Humidity string - Temperature string - Value string - Hcho string -} +package internal + +import ( + "encoding/json" + "fmt" + "net/http" + "strings" +) + +type writer interface { + write(mac string, json string) +} + +//example for line procotol: +//curl -i -XPOST 'http://localhost:8086/write?db=mydb' --data-binary 'cpu_load_short,host=server01,region=us-west value=0.64 1434055562000000000' +//we use as : +//aircat,mac=xxx temperature=1,humidity=2,value=3,hcho=4 +type influxdb struct { + addr string +} + +func (s *influxdb) write(mac string, json string) { + if s.addr == "" { + println(mac, json) + return + } + if line := formatLineProtocol(mac, json); line != "" { + //we ignore error + go func() { + http.Post(fmt.Sprintf("http://%s/write?db=aircat", s.addr), "", strings.NewReader(line)) + }() + } + +} +func formatLineProtocol(mac string, js string) string { + var air AirMeasure + if err := json.Unmarshal([]byte(js), &air); err != nil { + return "" + } + return fmt.Sprintf("aircat,mac=\"%s\" humidity=%s,temperature=%s,value=%s,hcho=%s", mac, air.Humidity, air.Temperature, air.Value, air.Hcho) +} + +//AirMeasure reported from device +type AirMeasure struct { + Humidity string + Temperature string + Value string + Hcho string +} diff --git a/server/internal/message.go b/aircat-srv-go/internal/message.go similarity index 95% rename from server/internal/message.go rename to aircat-srv-go/internal/message.go index 8e00638..0439319 100644 --- a/server/internal/message.go +++ b/aircat-srv-go/internal/message.go @@ -1,72 +1,72 @@ -package internal - -import ( - "bytes" - "encoding/binary" - "errors" -) - -//protocol for phicomm-m1 talks to server(port 9000) -type rawmessage struct { - header Rawheader - json string - end [5]uint8 //fixed as FF 23 45 4E 44 23 -} - -//sizeof rawheader = 16 + 12 = 28 -const ( - sizeRawHeader = 28 - sizeActiveMessage = 33 - sizeMinMessage = 33 - sizeMaxMessage = 150 //we guess -) - -/*Rawheader show as - 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 -00 -------unknown--------- 0B 00 00 00 00 00 00 00 -16 ---------MAC----------- len 00 00 typ -*/ -type Rawheader struct { - Unknown [16]uint8 //fixed for every device - Mac [8]uint8 //00-mac-00 - Length uint8 //length of (padding + msgType + json) - Padding [2]uint8 //fixed as 00 00 - MsgType uint8 //1:active,2:control,4:report -} - -type message struct { - header Rawheader - json string -} - -func (m *message) readMsg(buf []byte) error { - - b := bytes.NewBuffer(buf) - if err := binary.Read(b, binary.LittleEndian, &m.header); err != nil { - return err - } - jsonBegin := 28 - jsonEnd := jsonBegin + int(m.header.Length) - 3 - - if !(jsonBegin < len(buf) && jsonBegin <= jsonEnd && jsonBegin < len(buf)) { - return errors.New("bad packet") - } - m.json = string(buf[jsonBegin:jsonEnd]) - return nil -} - -func (m *message) controlMsg(json string) []byte { - var header Rawheader - var b bytes.Buffer - header = m.header - header.MsgType = 2 - header.Length = uint8(len(json)) + 3 - b.Write([]byte(header.Unknown[:])) - b.Write([]byte(header.Mac[:])) - b.WriteByte(header.Length) - b.Write([]byte(header.Padding[:])) - b.WriteByte(header.MsgType) - b.WriteString(json) - b.Write([]byte{0xFF, 0x23, 0x45, 0x4E, 0x44, 0x23}) - return b.Bytes() -} +package internal + +import ( + "bytes" + "encoding/binary" + "errors" +) + +//protocol for phicomm-m1 talks to server(port 9000) +type rawmessage struct { + header Rawheader + json string + end [5]uint8 //fixed as FF 23 45 4E 44 23 +} + +//sizeof rawheader = 16 + 12 = 28 +const ( + sizeRawHeader = 28 + sizeActiveMessage = 33 + sizeMinMessage = 33 + sizeMaxMessage = 150 //we guess +) + +/*Rawheader show as + 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 +00 -------unknown--------- 0B 00 00 00 00 00 00 00 +16 ---------MAC----------- len 00 00 typ +*/ +type Rawheader struct { + Unknown [16]uint8 //fixed for every device + Mac [8]uint8 //00-mac-00 + Length uint8 //length of (padding + msgType + json) + Padding [2]uint8 //fixed as 00 00 + MsgType uint8 //1:active,2:control,4:report +} + +type message struct { + header Rawheader + json string +} + +func (m *message) readMsg(buf []byte) error { + + b := bytes.NewBuffer(buf) + if err := binary.Read(b, binary.LittleEndian, &m.header); err != nil { + return err + } + jsonBegin := 28 + jsonEnd := jsonBegin + int(m.header.Length) - 3 + + if !(jsonBegin < len(buf) && jsonBegin <= jsonEnd && jsonBegin < len(buf)) { + return errors.New("bad packet") + } + m.json = string(buf[jsonBegin:jsonEnd]) + return nil +} + +func (m *message) controlMsg(json string) []byte { + var header Rawheader + var b bytes.Buffer + header = m.header + header.MsgType = 2 + header.Length = uint8(len(json)) + 3 + b.Write([]byte(header.Unknown[:])) + b.Write([]byte(header.Mac[:])) + b.WriteByte(header.Length) + b.Write([]byte(header.Padding[:])) + b.WriteByte(header.MsgType) + b.WriteString(json) + b.Write([]byte{0xFF, 0x23, 0x45, 0x4E, 0x44, 0x23}) + return b.Bytes() +} diff --git a/server/internal/restsrv.go b/aircat-srv-go/internal/restsrv.go similarity index 96% rename from server/internal/restsrv.go rename to aircat-srv-go/internal/restsrv.go index 426e6b4..2909ae8 100644 --- a/server/internal/restsrv.go +++ b/aircat-srv-go/internal/restsrv.go @@ -1,63 +1,63 @@ -package internal - -import ( - "io/ioutil" - "log" - "net/http" -) - -/* -APIs: - 1.query current measure, ignore mac - GET v1/aircat/{id} - Response: {"temperature"=1,"humidity"=2,"value"=3,"hcho"=4} - 2.change brightness. currently ignore mac, we have only one aircat. - PUT v1/aricat/{id} - {"brightness":"100","type":2} -*/ - -//restServer run at port 9000 -type restServer struct { - controlChan chan string - aircatServer *AircatServer -} - -//newrestServer create a restServer -func newrestServer(controlChan chan string) *restServer { - return &restServer{controlChan: controlChan} -} - -func (s *restServer) setAircatServer(aircatServer *AircatServer) { - s.aircatServer = aircatServer -} - -//Run restServer at port 9000 -func (s *restServer) Run() { - go func() { - http.HandleFunc("/v1/aircat", handlerFunc(s)) - log.Printf("REST Server run at %s\n", configs.RESTServerAddr) - log.Fatalln(http.ListenAndServe(configs.RESTServerAddr, nil)) - }() -} - -func handlerFunc(s *restServer) func(w http.ResponseWriter, r *http.Request) { - handler := func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodGet { - w.Header().Add("Content-Type", "application/json") - w.Write([]byte(s.aircatServer.getCurrentMessage())) - return - } - if r.Method == http.MethodPut { - body, err := ioutil.ReadAll(r.Body) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - } - s.controlChan <- string(body) - w.WriteHeader(http.StatusNoContent) - return - } - w.WriteHeader(http.StatusBadRequest) - return - } - return handler -} +package internal + +import ( + "io/ioutil" + "log" + "net/http" +) + +/* +APIs: + 1.query current measure, ignore mac + GET v1/aircat/{id} + Response: {"temperature"=1,"humidity"=2,"value"=3,"hcho"=4} + 2.change brightness. currently ignore mac, we have only one aircat. + PUT v1/aricat/{id} + {"brightness":"100","type":2} +*/ + +//restServer run at port 9000 +type restServer struct { + controlChan chan string + aircatServer *AircatServer +} + +//newrestServer create a restServer +func newrestServer(controlChan chan string) *restServer { + return &restServer{controlChan: controlChan} +} + +func (s *restServer) setAircatServer(aircatServer *AircatServer) { + s.aircatServer = aircatServer +} + +//Run restServer at port 9000 +func (s *restServer) Run() { + go func() { + http.HandleFunc("/v1/aircat", handlerFunc(s)) + log.Printf("REST Server run at %s\n", configs.RESTServerAddr) + log.Fatalln(http.ListenAndServe(configs.RESTServerAddr, nil)) + }() +} + +func handlerFunc(s *restServer) func(w http.ResponseWriter, r *http.Request) { + handler := func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodGet { + w.Header().Add("Content-Type", "application/json") + w.Write([]byte(s.aircatServer.getCurrentMessage())) + return + } + if r.Method == http.MethodPut { + body, err := ioutil.ReadAll(r.Body) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + } + s.controlChan <- string(body) + w.WriteHeader(http.StatusNoContent) + return + } + w.WriteHeader(http.StatusBadRequest) + return + } + return handler +} diff --git a/server/main.go b/aircat-srv-go/main.go similarity index 70% rename from server/main.go rename to aircat-srv-go/main.go index 27e2fdb..1065d58 100644 --- a/server/main.go +++ b/aircat-srv-go/main.go @@ -1,15 +1,15 @@ -package main - -import ( - "github.com/corbamico/phicomm-aircat-srv/server/internal" - "log" -) - -func main() { - if err := internal.LoadConfig("config.json"); err != nil { - log.Fatalln(err) - } - s := internal.NewAircatServer() - s.Run() - return -} +package main + +import ( + "github.com/corbamico/phicomm-aircat-srv/aircat-srv-go/internal" + "log" +) + +func main() { + if err := internal.LoadConfig("config.json"); err != nil { + log.Fatalln(err) + } + s := internal.NewAircatServer() + s.Run() + return +} diff --git a/server/go.mod b/server/go.mod deleted file mode 100644 index 67094ad..0000000 --- a/server/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/corbamico/phicomm-aircat-srv/server - -go 1.13