瀏覽代碼

其他: 提交国荣web01的最新代码

zhangjie 3 年之前
父節點
當前提交
f001cb20be
共有 32 個文件被更改,包括 605 次插入128 次删除
  1. 2 0
      .gitignore
  2. 1 0
      Bus/api.go
  3. 7 0
      Bus/bus.go
  4. 25 7
      Bus/ftpDtu.go
  5. 1 0
      Bus/go.mod
  6. 56 0
      Bus/go.sum
  7. 18 4
      Bus/mqtt.go
  8. 1 0
      cloudserver/CloudServer_test.go
  9. 6 1
      cloudserver/Conf.go
  10. 0 1
      cloudserver/go.mod
  11. 0 2
      cloudserver/go.sum
  12. 二進制
      cmd/ammeter
  13. 二進制
      cmd/cmd
  14. 1 1
      cmd/conf.json
  15. 3 2
      cmd/go.mod
  16. 47 2
      cmd/go.sum
  17. 二進制
      cmd/local.db
  18. 6 2
      cmd/main.go
  19. 59 0
      cmd/nohup.out
  20. 0 0
      config/db.go
  21. 2 2
      drivers/Api.go
  22. 99 37
      drivers/ameter.go
  23. 18 3
      drivers/device.go
  24. 38 0
      drivers/go.sum
  25. 54 19
      drivers/uemis.go
  26. 0 0
      middleware/gmqtt.go
  27. 11 9
      platform/gateway.go
  28. 1 1
      platform/gateway_test.go
  29. 56 0
      platform/go.sum
  30. 61 19
      platform/platform.go
  31. 16 14
      protocol/dlt645.go
  32. 16 2
      protocol/dlt645_test.go

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+*.iml
+*.idea

+ 1 - 0
Bus/api.go

@@ -37,4 +37,5 @@ type IBus interface {
 	ScanChannel(stream []byte, conn int) IChannel
 	Send(chn IChannel, buff interface{}) (int, error)
 	Recive(chn IChannel, buff interface{}) (int, error)
+	TimeStamp() int64
 }

+ 7 - 0
Bus/bus.go

@@ -58,6 +58,7 @@ func (chn *BusChannel) GetBus() IBus {
 
 type baseBus struct {
 	BusId   string
+	TsLast  uint64
 	ChnList map[string]IChannel
 	mutex   *sync.Mutex
 }
@@ -146,13 +147,19 @@ func (bus *baseBus) ScanChannel(stream []byte, connID int) IChannel {
 }
 
 func (bus *baseBus) Send(chn IChannel, buff interface{}) (int, error) {
+	bus.TsLast = uint64(time.Now().Unix())
 	return 0, nil
 }
 
 func (bus *baseBus) Recive(chn IChannel, buff interface{}) (int, error) {
+	bus.TsLast = uint64(time.Now().Unix())
 	return 0, nil
 }
 
+func (bus *baseBus) TimeStamp() int64 {
+	return int64(bus.TsLast)
+}
+
 type funcRegBus func(param []interface{}) IBus
 type funcGetID func(string, []interface{}) string
 

+ 25 - 7
Bus/ftpDtu.go

@@ -20,11 +20,14 @@ const (
 	DEF_FTP_PORT = 10010
 )
 
+var cmdQueryAddr []byte = []byte{0xfe, 0xfe, 0xfe, 0xfe, 0x68, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x68, 0x13, 0x00, 0xDF, 0x16}
+
 type DtuServer struct {
 	baseBus
 	Port      int
 	name      string
 	lis       net.Listener
+	lisAlt    net.Listener
 	connlist  map[int]net.Conn
 	clientNum int
 	loop      bool
@@ -63,20 +66,25 @@ func (dtu *DtuServer) LookupChannel(buf []byte, idx int, conn net.Conn) IChannel
 	return dtu.baseBus.ScanChannel(buf, idx)
 }
 
-func (dtu *DtuServer) ClientConnect(conn net.Conn, idx int) {
+func (dtu *DtuServer) ClientConnect(conn net.Conn, idx int, altFlag bool) {
 	var ic IChannel = nil
 	remoteAddr := conn.RemoteAddr().String()
+	//SrcPort := uint(conn.RemoteAddr().(*net.TCPAddr).Port)
 	defer dtu.closeConn(conn, idx, ic)
 
 	var err error
 	var buf [1024]byte
 	n := 0
 	for ic == nil {
+		if altFlag {
+			conn.Write(cmdQueryAddr)
+		}
 		n, err = conn.Read(buf[:])
 		if err != nil {
 			log.Infof("read from %s header faild err:[%v]\n", remoteAddr, err)
 			return
 		}
+		log.Infof("Connected(alternat port:%t) with code %X", altFlag, buf[:n])
 		ic = dtu.LookupChannel(buf[:n], idx, conn)
 	}
 
@@ -117,9 +125,9 @@ func (dtu *DtuServer) ClientConnect(conn net.Conn, idx int) {
 	}
 }
 
-func (dtu *DtuServer) StartServer() {
+func (dtu *DtuServer) StartServer(lister *net.Listener, altFlag bool) {
 	defer func() {
-		dtu.lis.Close()
+		(*lister).Close()
 	}()
 	idx := 0
 
@@ -129,7 +137,7 @@ func (dtu *DtuServer) StartServer() {
 			time.Sleep(5 * time.Second)
 			continue
 		}
-		conn, err := dtu.lis.Accept()
+		conn, err := (*lister).Accept()
 		if err != nil {
 			log.Errorf("listen err:[%v]\n", err)
 		}
@@ -138,7 +146,7 @@ func (dtu *DtuServer) StartServer() {
 		idx++
 		dtu.clientNum++
 		dtu.mutex.Unlock()
-		go dtu.ClientConnect(conn, idx-1)
+		go dtu.ClientConnect(conn, idx-1, altFlag)
 	}
 }
 
@@ -157,7 +165,17 @@ func (dtu *DtuServer) Init() error {
 		defer dtu.mutex.Unlock()
 
 		dtu.loop = true
-		go dtu.StartServer()
+		go dtu.StartServer(&dtu.lis, false)
+
+		addr = fmt.Sprintf("0.0.0.0:%d", dtu.Port+10)
+		log.Info("Alternat port listen start ", addr)
+		dtu.lisAlt, err = net.Listen("tcp", addr)
+		if err != nil {
+			log.Errorf("err! addr %s open faild err:[%v]\n", addr, err)
+			return err
+		}
+		go dtu.StartServer(&dtu.lisAlt, true)
+
 	}
 	return nil
 }
@@ -210,7 +228,7 @@ func (dtu *DtuServer) Send(ichn IChannel, buff interface{}) (int, error) {
 			}
 		}
 	}
-	return 0, nil
+	return dtu.baseBus.Send(ichn, buff)
 }
 
 func GetFtpServerConfig(param []interface{}) int {

+ 1 - 0
Bus/go.mod

@@ -9,6 +9,7 @@ replace github.com/ammeter/config => ../config
 require (
 	github.com/ammeter/config v0.0.0-00010101000000-000000000000
 	github.com/eclipse/paho.mqtt.golang v1.3.5
+	github.com/gin-gonic/gin v1.7.7
 	github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726
 	github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726
 )

+ 56 - 0
Bus/go.sum

@@ -1,14 +1,70 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
 github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
+github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+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/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
+github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726 h1:3BSFfDVmj5yqpvj3H9m1EpZWhEKgJXW2C4MbTRv6rIM=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:i+SDEIi6IWgErb4Yq6H542yr5F8vxSoNbe9wFC+N5jc=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/sqlite v1.1.6 h1:p3U8WXkVFTOLPED4JjrZExfndjOtya3db8w9/vEMNyI=
+gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=
+gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
+gorm.io/gorm v1.21.16 h1:YBIQLtP5PLfZQz59qfrq7xbrK7KWQ+JsXXCH/THlMqs=
+gorm.io/gorm v1.21.16/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=

+ 18 - 4
Bus/mqtt.go

@@ -40,7 +40,7 @@ func (mqtt *QMqtt) subTopic(subtopic string, Qos byte, hdlr MQTT.MessageHandler)
 func (mqtt *QMqtt) PublishObj(topic string, qos byte, in interface{}) {
 	jsonBytes, _ := json.Marshal(in)
 	sjson := string(jsonBytes)
-	log.Info(topic)
+	log.Info(mqtt.User, ",", topic)
 	log.Info(sjson)
 	mqtt.cnn.Publish(topic, qos, true, sjson)
 }
@@ -75,7 +75,7 @@ func (mqtt *QMqtt) ConnServer(retry int, cbSubs CbRegistMqttSubs) error {
 			if cbSubs != nil {
 				cbSubs(mqtt)
 			}
-			log.Info("MQTT connect OK!")
+			log.Info("MQTT connect " + mqtt.User + " OK!")
 			return nil
 		} else {
 			log.Error("Retry to connect the MQTT server!! ", token.Error())
@@ -107,11 +107,11 @@ func (mqtt *QMqtt) Uninit() {
 
 func (mqtt *QMqtt) Send(chn IChannel, buff interface{}) (int, error) {
 	mqtt.PublishObj(chn.ID(), mqtt.Qos, buff)
-	return 0, nil
+	return mqtt.baseBus.Send(chn, buff)
 }
 
 func (mqtt *QMqtt) Recive(chn IChannel, buff interface{}) (int, error) {
-	return 0, nil
+	return mqtt.baseBus.Recive(chn, buff)
 }
 
 func AppMqttSubs(mqtt *QMqtt) int {
@@ -128,6 +128,7 @@ func NewMqtt(param []interface{}) IBus {
 		cnn:     nil,
 		cliLock: new(sync.Mutex),
 	}
+	mq.BusId = GenMqttId("mqtt", param)
 
 	if len(param) >= 1 {
 		var cfgmq *QMqtt = nil
@@ -150,6 +151,19 @@ func NewMqtt(param []interface{}) IBus {
 	return mq
 }
 
+func GenMqttId(name string, param []interface{}) string {
+	if len(param) > 0 {
+		switch param[0].(type) {
+		case string:
+			return "mqtt-" + param[0].(string)
+		case *QMqtt:
+			return "mqtt-" + param[0].(*QMqtt).User
+		}
+	}
+	return "mqtt"
+}
+
 func init() {
 	BusReg["mqtt"] = NewMqtt
+	BusGetID["mqtt"] = GenMqttId
 }

+ 1 - 0
cloudserver/CloudServer_test.go

@@ -81,6 +81,7 @@ func getTestConf() *CloudServerConf {
 		AppId:     "fvWmjGCU",
 		AppSecret: "054e7df0881eff8328858092f9e8ac0b0f356676",
 		ServerUrl: "https://test-admin.pacom.cn",
+		Route:     "gw4g-cloudserver",
 	}
 	return &res
 }

+ 6 - 1
cloudserver/Conf.go

@@ -16,7 +16,12 @@ type CloudServerConf struct {
 	Route     string
 }
 
-var defConf = &CloudServerConf{}
+var defConf = &CloudServerConf{
+	AppId:     "fvWmjGCU",
+	AppSecret: "054e7df0881eff8328858092f9e8ac0b0f356676",
+	ServerUrl: "https://test-admin.pacom.cn",
+	Route:     "gw4g-cloudserver",
+}
 
 func (c *CloudServerConf) GenerateSignature() string {
 	res := md5V(c.AppId + "-pacom-" + c.AppSecret)

+ 0 - 1
cloudserver/go.mod

@@ -3,7 +3,6 @@ module github.com/ammeter/cloudserver
 go 1.14
 
 require (
-	github.com/YuGuorong/go v0.0.0-20180604090527-bdc77568d726
 	github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726
 	github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726
 )

+ 0 - 2
cloudserver/go.sum

@@ -1,5 +1,3 @@
-github.com/YuGuorong/go v0.0.0-20180604090527-bdc77568d726 h1:hUngjIpd9EPORkayfhtwxqMM7LvBvxtRaAMPEDXdciw=
-github.com/YuGuorong/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:GbYXqsEgfdVZCQqV2sbQBsKePf1x+0A1bkVreGmCIE8=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726 h1:3BSFfDVmj5yqpvj3H9m1EpZWhEKgJXW2C4MbTRv6rIM=

二進制
cmd/ammeter


二進制
cmd/cmd


File diff suppressed because it is too large
+ 1 - 1
cmd/conf.json


+ 3 - 2
cmd/go.mod

@@ -14,10 +14,11 @@ replace github.com/ammeter/protocol => ../protocol
 
 replace github.com/ammeter/Bus => ../Bus
 
+replace github.com/ammeter/middleware => ../middleware
+
 require (
-	github.com/ammeter/cloudserver v0.0.0-00010101000000-000000000000
 	github.com/ammeter/config v0.0.0-00010101000000-000000000000
+	github.com/ammeter/middleware v0.0.0-00010101000000-000000000000
 	github.com/ammeter/platform v0.0.0-00010101000000-000000000000
-	github.com/eclipse/paho.mqtt.golang v1.3.5
 	github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726
 )

+ 47 - 2
cmd/go.sum

@@ -1,31 +1,76 @@
-github.com/YuGuorong/go v0.0.0-20180604090527-bdc77568d726 h1:hUngjIpd9EPORkayfhtwxqMM7LvBvxtRaAMPEDXdciw=
-github.com/YuGuorong/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:GbYXqsEgfdVZCQqV2sbQBsKePf1x+0A1bkVreGmCIE8=
 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/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
 github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
+github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 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/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
 github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+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/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726 h1:3BSFfDVmj5yqpvj3H9m1EpZWhEKgJXW2C4MbTRv6rIM=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:i+SDEIi6IWgErb4Yq6H542yr5F8vxSoNbe9wFC+N5jc=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+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.1.6 h1:p3U8WXkVFTOLPED4JjrZExfndjOtya3db8w9/vEMNyI=
 gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=

二進制
cmd/local.db


+ 6 - 2
cmd/main.go

@@ -6,6 +6,7 @@ import (
 	"github.com/yuguorong/go/log"
 
 	"github.com/ammeter/config"
+	"github.com/ammeter/middleware"
 	"github.com/ammeter/platform"
 )
 
@@ -43,8 +44,11 @@ func main() {
 	p := platform.PaPlatform{}
 	p.SetGatewayUrl("/platform/dev/get-4G-gateway-list")
 	p.SetModel("ammeter", REQ_AMMETER_URL)
-	p.SetModel("SAIR10", REQ_AIR_URL)
+	p.SetModel("SA10", REQ_AIR_URL)
 	p.SaveModel()
 
-	platform.StartServer()
+	mainloop := make(chan interface{})
+
+	middleware.RestServerStart(mainloop)
+	platform.StartServer(mainloop)
 }

File diff suppressed because it is too large
+ 59 - 0
cmd/nohup.out


+ 0 - 0
config/db.go


+ 2 - 2
drivers/Api.go

@@ -3,7 +3,7 @@ package drviers
 type IDriver interface {
 	Name() string
 	Probe(name string, param interface{})
-	CreateDevice(model interface{}) (int, []IDevice)
+	CreateDevice(model interface{}, filterGwId string) (int, []IDevice)
 	GetModel() interface{}
 	GetDevice(id string) IDevice
 	GetDeviceList() map[string]IDevice
@@ -24,7 +24,7 @@ func (drv *baseDriver) Probe(name string, param interface{}) {
 	drv.DevList = make(map[string]IDevice)
 }
 
-func (drv *baseDriver) CreateDevice(model interface{}) (int, []IDevice) {
+func (drv *baseDriver) CreateDevice(model interface{}, filterGwId string) (int, []IDevice) {
 	dev := make([]IDevice, len(drv.DevList))
 	i := 0
 	for _, v := range drv.DevList {

+ 99 - 37
drivers/ameter.go

@@ -2,6 +2,7 @@ package drviers
 
 import (
 	"encoding/hex"
+	"fmt"
 	"reflect"
 	"strconv"
 	"strings"
@@ -33,29 +34,33 @@ type AmmeterModel struct {
 
 type Ammeter struct {
 	AmmeterModel
-	timestamp   int32
+	TsSample    int64
 	TotalEnergy float64
-	TransDeno   float64 ` gorm:"-"`
-	TransDiv    float64 ` gorm:"-"`
+	TransDeno   float64 `gorm:"-"`
+	TransDiv    float64 `gorm:"-"`
+	DBStatus    int     `json:"-"`
 }
 
 type AmMeterHub struct {
 	baseDevice
-	DutSn      string
-	Protocol   string
-	chnExit    chan bool
-	loopserver bool
-	sampleTmr  *time.Timer
-	amList     map[string]*Ammeter
-	persitList map[string]*Ammeter
-	tmrPersist *time.Timer
-	queryIdx   int
+	DutSn       string
+	DevCompCode string ` gorm:"-"`
+	Protocol    string
+	chnExit     chan bool
+	loopserver  bool
+	sampleTmr   *time.Timer
+	amList      map[string]*Ammeter
+	persitList  map[string]*Ammeter
+	tmrPersist  *time.Timer
+
+	queryIdx int
 }
 
 func (dev *AmMeterHub) Close() error {
 	dev.sampleTmr.Stop()
 	dev.loopserver = false
 	dev.chnExit <- true
+	dev.baseDevice.Close()
 	return nil
 }
 
@@ -63,15 +68,31 @@ func (dev *AmMeterHub) OnAttach(chn bus.IChannel) {
 	log.Info(dev.DutSn, " Attached!")
 	chn.SetTimeout(DEF_TCP_READ_TIMEOUT)
 	dev.sampleTmr.Reset(DEF_SAMPLE_PEER_DURATION)
+	dev.baseDevice.OnAttach(chn)
 }
 
 func (dev *AmMeterHub) OnDetach(chn bus.IChannel) {
 	log.Info(dev.DutSn, " Detached!")
 	dev.sampleTmr.Stop()
+	dev.baseDevice.OnDetach(chn)
 }
 
 func (dev *AmMeterHub) ChannelDispatch(stream []byte, args interface{}) bus.ChnDispResult {
-	if len(stream) != 5 {
+	if len(stream) > 8 {
+		if stream[0] == 0x68 && stream[7] == 0x68 && stream[8] == 0x93 {
+			devname := ""
+			mret := dev.Route[1].iproto.ParsePacket(stream, &devname)
+			if mret != nil && devname == dev.DeviceName {
+				return bus.DispatchSingle
+			}
+			// for i := 0; i < 6; i++ {
+			// 	if stream[i+1] != stream[i+10] {
+			// 		return bus.DispatchNone
+			// 	}
+			// }
+			// log.Infof("MOUNT meter:0000[%x]", stream[1:7])
+			// return bus.DispatchSingle
+		}
 		return bus.DispatchNone
 	}
 	if ret := dev.baseDevice.ChannelDispatch(stream, args); ret != bus.DispatchNone {
@@ -129,11 +150,16 @@ func (dev *AmMeterHub) AdjustTelemetry(mval interface{}, devname string) {
 
 		if val, has := vlist["TotalActivePower"]; has {
 			diff := val.(float64) - am.TotalEnergy
+			if am.DBStatus == 0 { //数据库清0
+				diff = 0
+				am.DBStatus = 1
+			}
 			am.TotalEnergy = val.(float64)
 			vlist["ActivePowerIncrement"] = diff
 			if len(dev.persitList) == 0 {
 				dev.tmrPersist.Reset(POSTPONE_PERSIST_TIME)
 			}
+
 			dev.persitList[am.DevName] = am
 		}
 	}
@@ -150,15 +176,18 @@ func (dev *AmMeterHub) Run() error {
 		case msg := <-dev.Route[1].router[0]:
 			if reflect.TypeOf(msg).Kind() == reflect.Slice {
 				b := msg.([]byte)
-				log.Info(hex.EncodeToString(b))
+				log.Info("[", dev.DutSn, "]:", hex.EncodeToString(b))
 				devname := "" //pam.DevName
 				mret := dev.Route[1].iproto.ParsePacket(b, &devname)
-				if mret != nil && devname != "" {
+				if mret != nil && reflect.TypeOf(mret).Kind() == reflect.Map && devname != "" {
 					log.Info(devname, mret)
-					devname = "AM10-" + devname + dev.DutSn[:4]
+					devname = "AM10-" + devname + dev.DevCompCode[:4]
 					dev.AdjustTelemetry(mret, devname)
 					telemetry := dev.Route[0].iproto.PackageCmd(devname, mret)
 					dev.Route[0].ibus.Send(dev.Route[0].iChn, telemetry)
+					if meter, has := dev.amList[devname]; has {
+						meter.TsSample = time.Now().Unix()
+					}
 					dev.SchedulNextSample(tmrTxTimout)
 				}
 			}
@@ -170,13 +199,15 @@ func (dev *AmMeterHub) Run() error {
 			dev.loopserver = false
 		case <-dev.tmrPersist.C:
 			for k, am := range dev.persitList {
+				if am.DBStatus == 0 {
+
+				}
 				config.GetDB().Save(am)
 				delete(dev.persitList, k)
 			}
 		}
 	}
 	return nil
-
 }
 
 func DutchanDispatch(rxin interface{}, param interface{}) interface{} {
@@ -189,7 +220,6 @@ func DutchanDispatch(rxin interface{}, param interface{}) interface{} {
 }
 
 func (dev *AmMeterHub) Open(param ...interface{}) error {
-
 	if dev.DutSn != "" {
 		dev.SetRoute(dev, dev.Protocol, "dtuFtpServer", dev.DutSn, 0)
 	}
@@ -207,6 +237,23 @@ func (dev *AmMeterHub) GetDevice(devname string) interface{} {
 	return nil
 }
 
+func (dev *AmMeterHub) ListDevices() interface{} {
+	mdev := make(map[string]interface{})
+	mdev["State"] = dev.Status
+	dinfo := make(map[string]interface{})
+	for sname, subdev := range dev.amList {
+
+		meterval := make(map[string]string)
+		meterval["TotalEnergy"] = fmt.Sprintf("%f", subdev.TotalEnergy)
+		if subdev.TsSample != 0 {
+			meterval["TsSample"] = time.Unix(subdev.TsSample, 0).Format("2006-01-02 15:04:05")
+		}
+		dinfo[sname] = meterval
+	}
+	mdev["Sub Meters"] = dinfo
+	return mdev
+}
+
 /*
 [{"code":"26462285","devName":"SAIR10-0000000026462285","gwDevId":"1ec2d8421b2ed30bf52b38d8579115b","id":"1ec2d84cc494690bf52b38d8579115b","protocol":"HJ212"},
  {"code":"61748803","devName":"SAIR10-0000000061748803","gwDevId":"1ec2d8421b2ed30bf52b38d8579115b","id":"1ec2d84eb428160bf52b38d8579115b","protocol":"HJ212"}]
@@ -225,40 +272,55 @@ func (drv *AmmeterDrv) ParseTransRatio(dev *Ammeter) {
 	}
 }
 
-func (drv *AmmeterDrv) CreateDevice(model interface{}) (int, []IDevice) {
+func (drv *AmmeterDrv) CreateDevice(model interface{}, filterGwId string) (int, []IDevice) {
 	if model != nil {
 		models := model.(*[]AmmeterModel)
 		for _, m := range *models {
 			var hub IDevice = nil
 			var has bool
+			if m.GwDevId != filterGwId {
+				continue
+			}
+			if len(m.Code) < 4 || len(m.Address) < 8 {
+				continue
+			}
+			devCompID := m.DutSn
+			if m.DutSn == "" {
+				m.DutSn = m.Code + m.Address
+				devCompID = "0000"
+			}
 			if hub, has = drv.DevList[m.DutSn]; !has {
 				hub = &AmMeterHub{
-					DutSn:      m.DutSn,
-					Protocol:   m.Protocol,
-					chnExit:    make(chan bool),
-					loopserver: false,
-					sampleTmr:  nil,
-					amList:     make(map[string]*Ammeter),
-					persitList: make(map[string]*Ammeter),
-					queryIdx:   0,
+					DutSn:       m.DutSn,
+					Protocol:    m.Protocol,
+					chnExit:     make(chan bool),
+					loopserver:  false,
+					sampleTmr:   nil,
+					amList:      make(map[string]*Ammeter),
+					persitList:  make(map[string]*Ammeter),
+					queryIdx:    0,
+					DevCompCode: devCompID,
 				}
 				hub.Probe(m.DutSn, drv)
 				drv.DevList[m.DutSn] = hub
 			}
 
-			dev := &Ammeter{
-				TotalEnergy: 0,
-				timestamp:   0,
-				TransDiv:    1,
-				TransDeno:   1,
+			if _, has := hub.(*AmMeterHub).amList[m.DevName]; !has {
+				dev := &Ammeter{
+					TotalEnergy: 0,
+					TsSample:    0,
+					TransDiv:    1,
+					TransDeno:   1,
+					DBStatus:    0,
+				}
+				config.GetDB().Find(dev, "dev_name='"+m.DevName+"'")
+				dev.AmmeterModel = m
+				drv.ParseTransRatio(dev)
+				hub.(*AmMeterHub).amList[dev.DevName] = dev
 			}
-			config.GetDB().Find(dev, "dev_name='"+m.DevName+"'")
-			dev.AmmeterModel = m
-			drv.ParseTransRatio(dev)
-			hub.(*AmMeterHub).amList[dev.DevName] = dev
 		}
 	}
-	return drv.baseDriver.CreateDevice(model)
+	return drv.baseDriver.CreateDevice(model, filterGwId)
 }
 
 func (drv *AmmeterDrv) GetModel() interface{} {

+ 18 - 3
drivers/device.go

@@ -1,15 +1,14 @@
 package drviers
 
 import (
-	"encoding/hex"
 	"reflect"
 
 	bus "github.com/ammeter/Bus"
 	"github.com/ammeter/protocol"
-	"github.com/yuguorong/go/log"
 )
 
 type IDevice interface {
+	Name() string
 	Probe(name string, drv IDriver) error
 	Open(...interface{}) error
 	Close() error
@@ -17,6 +16,7 @@ type IDevice interface {
 	Suspend() error
 	Resume() error
 	GetDevice(string) interface{}
+	ListDevices() interface{}
 	SetRoute(evt bus.IBusEvent, prot string, busName string, chn string, param ...interface{}) int
 }
 
@@ -29,10 +29,16 @@ type routePath struct {
 
 type baseDevice struct {
 	DeviceName string
+	Status     string
 	drv        IDriver
+	Id         string
 	Route      []routePath
 }
 
+func (dev *baseDevice) Name() string {
+	return dev.DeviceName
+}
+
 func (dev *baseDevice) Probe(name string, driver IDriver) error {
 	dev.Route = make([]routePath, 0)
 	dev.DeviceName = name
@@ -42,13 +48,15 @@ func (dev *baseDevice) Probe(name string, driver IDriver) error {
 
 //bus.IBusEvent
 func (dev *baseDevice) OnAttach(chn bus.IChannel) {
+	dev.Status = "Attached"
 }
 
 func (dev *baseDevice) OnDetach(chn bus.IChannel) {
+	dev.Status = "Detached"
 }
 
 func (dev *baseDevice) ChannelDispatch(stream []byte, args interface{}) bus.ChnDispResult {
-	log.Info(dev.drv.Name(), "-", dev.DeviceName, " try Dispatch: ", hex.EncodeToString(stream))
+	//log.Info(dev.drv.Name(), "-", dev.DeviceName, " try Dispatch: ", hex.EncodeToString(stream))
 	k := reflect.TypeOf(args).Kind()
 	if k == reflect.Ptr {
 		iprot := args.(protocol.IProtocol)
@@ -77,6 +85,13 @@ func (dev *baseDevice) GetDevice(string) interface{} {
 	return dev
 }
 
+func (dev *baseDevice) ListDevices() interface{} {
+	dinfo := make(map[string]string)
+	dinfo["Name"] = dev.DeviceName
+	dinfo["State"] = dev.Status
+	return dinfo
+}
+
 func (dev *baseDevice) Suspend() error {
 	return nil
 }

+ 38 - 0
drivers/go.sum

@@ -2,27 +2,65 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
 github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
+github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 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/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
 github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726 h1:3BSFfDVmj5yqpvj3H9m1EpZWhEKgJXW2C4MbTRv6rIM=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:i+SDEIi6IWgErb4Yq6H542yr5F8vxSoNbe9wFC+N5jc=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/sqlite v1.1.6 h1:p3U8WXkVFTOLPED4JjrZExfndjOtya3db8w9/vEMNyI=
 gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=

+ 54 - 19
drivers/uemis.go

@@ -1,17 +1,43 @@
 package drviers
 
 import (
+	"bytes"
 	"errors"
 
+	bus "github.com/ammeter/Bus"
 	"github.com/yuguorong/go/log"
 )
 
+type SAirModel struct {
+	Id       string `json:"id"`
+	DevName  string `json:"devName"`
+	Code     string `json:"code"`
+	Protocol string `json:"protocol"`
+	GwDevId  string `json:"gwDevId"`
+}
+
 type Uemis struct {
 	baseDevice
+	devList    map[string]SAirModel //name->Id
 	chnExit    chan bool
 	loopserver bool
 }
 
+func (u *Uemis) ChannelDispatch(stream []byte, args interface{}) bus.ChnDispResult {
+	devName := ""
+	buf := bytes.NewBuffer(stream)
+	mret := u.Route[1].iproto.ParsePacket(buf.Bytes(), &devName)
+	if mret != nil && devName != "" {
+		devN := devName[8:]
+		devN = "SA10" + "-00000000" + devN
+		if _, has := u.devList[devN]; has {
+			log.Info(u.DeviceName+" Dispatch ["+devN+"]: ", string(stream))
+			return bus.DispatchMulti
+		}
+	}
+	return bus.DispatchNone
+}
+
 func (u *Uemis) Run() error {
 	u.loopserver = true
 	for u.loopserver {
@@ -23,8 +49,8 @@ func (u *Uemis) Run() error {
 			if mret != nil && devName != "" {
 				v := mret.(map[string]interface{})
 				dev := devName[8:]
-				dev = u.DeviceName + "-00000000" + dev
-				log.Info(dev, v)
+				dev = "SA10" + "-00000000" + dev
+				log.Info(u.baseDevice.Id+"/"+dev, v)
 				telemetry := u.Route[0].iproto.PackageCmd(dev, mret)
 				u.Route[0].ibus.Send(u.Route[0].iChn, telemetry)
 			}
@@ -41,7 +67,7 @@ func (u *Uemis) Open(...interface{}) error {
 	if lenr < 1 {
 		return errors.New("wrong route config")
 	} else if lenr < 2 {
-		u.SetRoute(u, "HJ212", "dtuFtpServer", "HJ212", 0)
+		u.SetRoute(u, "HJ212", "dtuFtpServer", "HJ212-"+u.Id, 0)
 	}
 	if !u.loopserver {
 		go u.Run()
@@ -59,14 +85,6 @@ func (u *Uemis) GetDevice(s string) interface{} {
 	return u
 }
 
-type SAirModel struct {
-	Id       string `json:"id"`
-	DevName  string `json:"devName"`
-	Code     string `json:"code"`
-	Protocol string `json:"protocol"`
-	GwDevId  string `json:"gwDevId"`
-}
-
 type UemisDrv struct {
 	baseDriver
 }
@@ -75,13 +93,30 @@ func (drv *UemisDrv) GetModel() interface{} {
 	return &[]SAirModel{}
 }
 
-func (drv *UemisDrv) CreateDevice(model interface{}) (int, []IDevice) {
-	drv.baseDriver.CreateDevice(model)
-	dev := new(Uemis)
-	dev.loopserver = false
-	dev.Probe(drv.Name(), drv)
-	drv.baseDriver.DevList[drv.Name()] = dev
-	return drv.baseDriver.CreateDevice(model)
+func (drv *UemisDrv) CreateDevice(model interface{}, filterGwId string) (int, []IDevice) {
+	drv.baseDriver.CreateDevice(model, filterGwId)
+	devlist := make([]IDevice, 0)
+	mlist := model.(*[]SAirModel)
+
+	var dev *Uemis = nil
+	for _, m := range *mlist {
+		if m.GwDevId == filterGwId {
+			if dev == nil {
+				dev = new(Uemis)
+				dev.loopserver = false
+				dev.devList = make(map[string]SAirModel)
+
+				dev.Id = m.Id
+				dev.DeviceName = "S5-" + dev.Id
+				dev.Probe(dev.DeviceName, drv)
+				drv.baseDriver.DevList[dev.DeviceName] = dev
+				devlist = append(devlist, dev)
+			}
+			//m.DevName = strings.ReplaceAll(m.DevName, "SAIR10", "S10")
+			dev.devList[m.DevName] = m
+		}
+	}
+	return len(devlist), devlist
 }
 
 func NewUemis(param interface{}) IDriver {
@@ -90,5 +125,5 @@ func NewUemis(param interface{}) IDriver {
 }
 
 func init() {
-	driverReg["SAIR10"] = NewUemis
+	driverReg["SA10"] = NewUemis
 }

+ 0 - 0
middleware/gmqtt.go


+ 11 - 9
platform/gateway.go

@@ -32,7 +32,7 @@ type Gateway struct {
 	Uid        string
 	modelList  map[string]string
 	NorthRoute interface{}
-	DeviceList []drviers.IDriver
+	DeviceList map[string]drviers.IDevice
 }
 
 func (gw *Gateway) SyncCloudModelDevice(url string, model interface{}) error {
@@ -70,26 +70,28 @@ func priotyInf(ni *netinfo, name string) bool {
 
 func (gw *Gateway) InitGateway(modelList map[string]string) {
 	//gw.GetGatewayName()
-	gw.DeviceList = make([]drviers.IDriver, 0)
+	gw.DeviceList = make(map[string]drviers.IDevice)
 	gw.modelList = modelList
 
 }
 
-func (gw *Gateway) StartServer(uid string) {
+//
+func (gw *Gateway) ApplyProfile(uid string) {
 	//	name := "ammeter"
 	//	drvU := drviers.Install("SAIR10", nil)
-	for name, url := range gw.modelList {
-		drv := drviers.Install(name, nil)
-		model := drv.GetModel()
+	for name, url := range gw.modelList { //model name + model cloud api url
+		drv := drviers.Install(name, nil) //If already installed ,return installed instance.
+		model := drv.GetModel()           //model: cloud information of device, create exact device absctrace from model
 		if url != "" {
 			if gw.SyncCloudModelDevice(url, model) != nil {
-				model = config.GetSysConfig().GetProfile("gateway/"+name+"/amlist", model)
+				model = config.GetSysConfig().GetProfile("gateway/"+name+"/amlist", model) //Cloud failed ,using local saved model
 			} else {
-				config.GetSysConfig().SetProfile("gateway/"+name+"/amlist", model)
+				config.GetSysConfig().SetProfile("gateway/"+name+"/amlist", model) //update local model
 			}
 		}
-		if sz, devlist := drv.CreateDevice(model); sz > 0 {
+		if sz, devlist := drv.CreateDevice(model, gw.Mqttcfg.Uid); sz > 0 {
 			for _, dev := range devlist {
+				gw.DeviceList[dev.Name()] = dev
 				dev.SetRoute(nil, "ThingsBoards", "mqtt", "v1/gateway/telemetry", &gw.Mqttcfg)
 				dev.Open()
 			}

+ 1 - 1
platform/gateway_test.go

@@ -19,7 +19,7 @@ func TestPlatform(T *testing.T) {
 	p := PaPlatform{}
 	p.SetGatewayUrl("/platform/dev/get-4G-gateway-list")
 	p.SetModel("ammeter", REQ_AMMETER_URL)
-	p.SetModel("SAIR10", REQ_AIR_URL)
+	p.SetModel("SA10", REQ_AIR_URL)
 	p.SaveModel()
 
 }

+ 56 - 0
platform/go.sum

@@ -1,14 +1,70 @@
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqnNN1bdl41Y=
 github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
+github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
+github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+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/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
+github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 h1:xT+JlYxNGqyT+XcU8iUrN18JYed2TvG9yN5ULG2jATM=
 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726 h1:3BSFfDVmj5yqpvj3H9m1EpZWhEKgJXW2C4MbTRv6rIM=
 github.com/yuguorong/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:i+SDEIi6IWgErb4Yq6H542yr5F8vxSoNbe9wFC+N5jc=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0 h1:Jcxah/M+oLZ/R4/z5RzfPzGbPXnVDPkEDtf2JnuxN+U=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gorm.io/driver/sqlite v1.1.6 h1:p3U8WXkVFTOLPED4JjrZExfndjOtya3db8w9/vEMNyI=
+gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=
+gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
+gorm.io/gorm v1.21.16 h1:YBIQLtP5PLfZQz59qfrq7xbrK7KWQ+JsXXCH/THlMqs=
+gorm.io/gorm v1.21.16/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=

+ 61 - 19
platform/platform.go

@@ -1,6 +1,9 @@
 package platform
 
 import (
+	"reflect"
+	"time"
+
 	"github.com/yuguorong/go/log"
 
 	bus "github.com/ammeter/Bus"
@@ -17,7 +20,7 @@ const (
 
 type PaPlatform struct {
 	gwUrl       string
-	GatewayList []*Gateway
+	GatewayList map[string]*Gateway
 	modelList   map[string]string
 }
 
@@ -38,19 +41,43 @@ func (p *PaPlatform) SyncCloudGWConfig() *[]bus.QMqtt {
 }
 
 func (p *PaPlatform) LoadGatewayProfile() {
-	p.GatewayList = make([]*Gateway, 0)
-	mqttList := &[]bus.QMqtt{}
-	config.GetSysConfig().GetValue("mqtt_list", mqttList)
-	if mqrmt := p.SyncCloudGWConfig(); mqrmt != nil {
-		mqttList = mqrmt
-		config.GetSysConfig().SetValue("mqtt_list", mqttList)
+	gwMqttList := &[]bus.QMqtt{}
+	config.GetSysConfig().GetValue("mqtt_list", gwMqttList)
+	if gwrmt := p.SyncCloudGWConfig(); gwrmt != nil {
+		gwMqttList = gwrmt
+		config.GetSysConfig().SetValue("mqtt_list", gwMqttList)
 	}
-	for _, mq := range *mqttList {
-		gw := InitGateway(&mq, p.modelList)
-		p.GatewayList = append(p.GatewayList, gw)
-		gw.StartServer(mq.Uid)
+	for _, mq := range *gwMqttList {
+		gw, has := p.GatewayList[mq.Uid]
+		if !has {
+			gw = InitGateway(&mq, p.modelList)
+			p.GatewayList[gw.Uid] = gw
+		}
+		gw.ApplyProfile(mq.Uid)
 	}
+}
+
+func (p *PaPlatform) ListDevices() interface{} {
+
+	devmap := make(map[string]interface{})
 
+	for _, gw := range p.GatewayList {
+		mgw := make(map[string]interface{})
+		for n, dev := range gw.DeviceList {
+			mgw[n] = dev.ListDevices()
+		}
+		mgw["ID"] = gw.Uid
+		mgw["URL"] = gw.Mqttcfg.MqttUrl
+		devmap[gw.Mqttcfg.Name] = mgw
+	}
+
+	return devmap
+}
+
+func (p *PaPlatform) Init() {
+	p.GatewayList = make(map[string]*Gateway)
+	p.LoadModles()
+	p.LoadGatewayProfile()
 }
 
 func (p *PaPlatform) SetModel(sname string, surl string) {
@@ -76,15 +103,30 @@ func (p *PaPlatform) SetGatewayUrl(url string) {
 	p.gwUrl = url
 }
 
-var mainloop chan interface{}
+func StartServer(mainloop chan interface{}) {
+	p := PaPlatform{}
+	p.Init()
 
-func StartServer() {
-	p := &PaPlatform{}
-	p.LoadModles()
-	p.LoadGatewayProfile()
-	mainloop = make(chan interface{})
+	ticksAutoFresh := time.NewTicker(time.Duration(time.Minute * 10))
 
-	v := <-mainloop
-	log.Info("exit now", v)
+	for loop := true; loop; {
+		select {
+		case msg := <-mainloop:
+			if reflect.TypeOf(msg).Kind() == reflect.String {
+				switch msg.(string) {
+				case "UpdateDevice":
+					p.LoadGatewayProfile()
+				case "ListDevices":
+					chn := <-mainloop
+					chn.(chan interface{}) <- p.ListDevices()
+				case "exit":
+					loop = false
+				}
+			}
+		case <-ticksAutoFresh.C:
+			p.LoadGatewayProfile()
+		}
+	}
+	log.Info("exit now")
 
 }

+ 16 - 14
protocol/dlt645.go

@@ -58,7 +58,7 @@ const (
 
 	//功能码
 	C_2007_CODE_BRC = 0x08 //广播校时
-	C_2007_CODE_RD  = 0X11 //读数据
+	C_2007_CODE_RD  = 0x11 //读数据
 	C_2007_CODE_RDM = 0x12 //读后续数据
 	C_2007_CODE_RDA = 0x13 //读通信地址
 	C_2007_CODE_WR  = 0x14 //写数据
@@ -230,7 +230,7 @@ func (p *dlt645) setDltCheckSum(buff []byte) {
 
 func (p *dlt645) PackageCmd(opcode string, param ...interface{}) interface{} {
 	amaddr := param[0].(string)
-	buff := []byte{0xFE, 0xFE, 0xFE, 0xFE, DLT_CHAR_FRAME_START, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, DLT_CHAR_FRAME_START, DLT_DEF_CHAR_OPCODE, 0x00, 0x00, 0x00, 0x00, 0x00, 0X00}
+	buff := []byte{0xFE, 0xFE, 0xFE, 0xFE, DLT_CHAR_FRAME_START, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, DLT_CHAR_FRAME_START, DLT_DEF_CHAR_OPCODE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 	pkPos := DLT_LEAD_LEN + DLT_ADDR_POS
 	err := p.setDltAddr(buff[pkPos:pkPos+DLT_ADDR_LEN], amaddr)
 	if err != nil {
@@ -306,7 +306,6 @@ func (p *dlt645) ParsePacket(rxb []byte, params ...interface{}) (mapv interface{
 	Assert(rxb[pos+DLT_FILED_POS] == DLT_CHAR_FRAME_START, int(rxb[pos+DLT_FILED_POS]))
 	//CMD. opcode
 	cmd := rxb[pos+DLT_OPCODE_POS]
-	Assert(cmd == (C_2007_CODE_RD|DLT_CMD_DIR_REVERT), int(rxb[pos+DLT_DICCODE_POS]))
 
 	//PARAM = DIC_CODE + PARAM
 	pos += DLT_DICCODE_POS
@@ -319,28 +318,31 @@ func (p *dlt645) ParsePacket(rxb []byte, params ...interface{}) (mapv interface{
 	dicBuff := bytes.NewBuffer(rxb[pos : pos+DLT_DICCODE_LEN])
 	binary.Read(dicBuff, binary.LittleEndian, &dicCode)
 
-	pos += DLT_DICCODE_LEN
-
-	lenParam = lenParam - DLT_DICCODE_LEN
 	Assert(lenParam+pos < lenb-1, lenParam)
 	param := make([]byte, lenParam)
 	for i := 0; i < lenParam; i++ {
 		param[lenParam-i-1] = rxb[pos+i] - 0x33
-		rxb[pos+i] = 0
 	}
 	pos += lenParam
 
 	Assert(rxb[pos+1] == DLT_CHAR_TAIL, int(rxb[pos+1]))
 
-	val := float64(bcd2int(param)) / 100.0
-	Assert(val != 0, 0)
-	for k, v := range Cmd2Code {
-		if int(v) == dicCode {
-			mapv := make(map[string]interface{})
-			mapv[k] = val
-			return mapv
+	if cmd == (C_2007_CODE_RD | DLT_CMD_DIR_REVERT) {
+		val := float64(bcd2int(param[:lenParam-DLT_DICCODE_LEN])) / 100.0
+		for k, v := range Cmd2Code {
+			if int(v) == dicCode {
+				mapv := make(map[string]interface{})
+				mapv[k] = val
+				return mapv
+			}
 		}
+	} else if cmd == (C_2007_CODE_RDA | DLT_CMD_DIR_REVERT) {
+		return saddr
+
+	} else {
+		log.Error("unkown DLT645 cmd:", cmd)
 	}
+
 	return nil
 }
 

+ 16 - 2
protocol/dlt645_test.go

@@ -9,6 +9,7 @@ import (
 
 //fefefefe68040042050821681104333333332516
 //fefefefe68040042050821681104333333332516
+
 func TestPacket(t *testing.T) {
 	dlt645 := LoadProtocol("DLT645-2007")
 
@@ -21,16 +22,29 @@ func TestPacket(t *testing.T) {
 
 }
 
+//020068361211
 func TestParse(t *testing.T) {
 	dlt645 := LoadProtocol("DLT645-2007")
+
+	cap := []byte{104, 2, 0, 104, 54, 18, 17, 104, 145, 8, 51, 51, 51, 51, 51, 51, 51, 51, 196, 22}
+	//104, 17, 18, 54, 104, 0, 2, 104, 147, 6, 53, 51, 155, 105, 69, 68, 33, 22}
 	//t1 := []byte{0xfe, 0xfe, 0xfe, 0xfe, 0x68, 0x04, 0x00, 0x42, 0x05, 0x08, 0x21, 0x68, 0x11, 0x04, 0x33, 0x33, 0x33, 0x33, 0x25, 0x16}
-	tcmd := []byte{0xfe, 0xfe, 0xfe, 0xfe, 0x68, 0x06, 0x00, 0x42, 0x05, 0x08, 0x21, 0x68, 0x11, 0x04, 0x33, 0x33, 0x33, 0x33, 0x27, 0x16}
+	addr_ack := []byte{0x68, 0x08, 0x00, 0x01, 0x04, 0x06, 0x01, 0x68, 0x93, 0x06, 0x3B, 0x33, 0x34, 0x37, 0x39, 0x34, 0xC3, 0x16}
+	//tcmd := []byte{0xfe, 0xfe, 0xfe, 0xfe, 0x68, 0x06, 0x00, 0x42, 0x05, 0x08, 0x21, 0x68, 0x11, 0x04, 0x33, 0x33, 0x33, 0x33, 0x27, 0x16}
+
 	tack := []byte{0xfe, 0xfe, 0xfe, 0xfe, 0x68, 0x06, 0x00, 0x42, 0x05, 0x08, 0x21, 0x68, 0x91, 0x08, 0x33, 0x33, 0x33, 0x33, 0x47, 0xc5, 0x33, 0x33, 0x1d, 0x16}
 	//tdec := []byte{0xfe, 0xfe, 0xfe, 0xfe, 0x68, 0x04, 0x00, 0x42, 0x05, 0x08, 0x21, 0x68, 0x91, 0x08, 0x33, 0x33, 0x33, 0x33, 0xb4, 0xbc, 0x34, 0x33, 0x80, 0x16}
-	vret := dlt645.ParsePacket(tack, tcmd)
+	devname := ""
+	v1 := dlt645.ParsePacket(cap, &devname)
+	t.Log(v1)
+	vret := dlt645.ParsePacket(tack, &devname)
 	if vret == nil {
 		t.Error("Error in parse packet")
 	}
+
+	mret := dlt645.ParsePacket(addr_ack, &devname)
+	t.Log(mret, ",", devname)
+
 	t.Logf("Get param: [%#v]\n", vret)
 }