lijian 2 gadi atpakaļ
vecāks
revīzija
b3d0901dc7
7 mainītis faili ar 266 papildinājumiem un 30 dzēšanām
  1. 110 9
      README.md
  2. 21 4
      netAtSDK/at_client.go
  3. 12 0
      netAtSDK/at_sdk_test.go
  4. 8 15
      server/client.go
  5. 1 2
      server/server.go
  6. 83 0
      services/service.go
  7. 31 0
      services/structs.go

+ 110 - 9
README.md

@@ -15,7 +15,7 @@ type BaseArgs struct {
 
 #### 1.1 查询基站GPS信息
 
-> 返回的lat, lng为原始坐标
+返回的lat, lng为原始坐标
 
 * 方法名: `GetGPSInfo`
 * 请求参数:
@@ -60,8 +60,8 @@ type BaseArgs struct {
 
 #### 1.4 配置工作模式
 
-> 第一个参数 0 不启用该通道; 1 TCP/UDP 透传; 2 MQTT 透传; 3 塔石 DTU 云连接; 4 塔石 IOT 云连接; 5 HTTP 传输模式; 6 阿里云直连
-> B 取值范围 1~4,代表 4 个不同的 SOCKET 通道,省略时仅配置通道 1 默认值:+DTUMODE:1,0,0,0 默认第一路为 TCP/UDP 透传,其他几路为默认关闭
+第一个参数 0 不启用该通道; 1 TCP/UDP 透传; 2 MQTT 透传; 3 塔石 DTU 云连接; 4 塔石 IOT 云连接; 5 HTTP 传输模式; 6 阿里云直连
+B 取值范围 1~4,代表 4 个不同的 SOCKET 通道,省略时仅配置通道 1 默认值:+DTUMODE:1,0,0,0 默认第一路为 TCP/UDP 透传,其他几路为默认关闭
 
 * 方法名: `SetDTUMode`
 * 请求参数:
@@ -77,10 +77,10 @@ type SetDTUModeArgs struct {
 
 #### 1.5 设置连接服务地址
 
-> A 取值范围 1-4,代表 4 个不同的 SOCKET 通道
-> B 为 TCP 或者 UDP
-> C 为服务器地址,可填域名或 IP,长度最大 255
-> D 为端口号,范围 1~65535
+A 取值范围 1-4,代表 4 个不同的 SOCKET 通道
+B 为 TCP 或者 UDP
+C 为服务器地址,可填域名或 IP,长度最大 255
+D 为端口号,范围 1~65535
 
 * 方法名:`SetServerAddr`
 * 请求参数:
@@ -116,7 +116,7 @@ type Addr struct {
 
 #### 1.7 设置串口参数
 
-> 格式:AT+UARTCFG=A,B,C,D
+格式:AT+UARTCFG=A,B,C,D
 A 串口波特率,支持的波特率为 115200、57600、38400、19200、14400、9600、4800、 2400、1200
 B 数据位,取值范围 0~1 0 7 位数据位 1 8 位数据位
 C 校验位,取值范围 0~2 0 无校验 NONE 1 奇校验 ODD 2 偶校验 EVEN
@@ -172,6 +172,7 @@ type DTUIDArgs struct {
 * 方法名:`GetDTUID`
 * 请求参数: `BaseArgs`
 * 返回参数: 
+
 ```go
 type DTUIDReply struct {
 	DTUIDs []*DTUID
@@ -184,4 +185,104 @@ type DTUID struct {
 	Content string
 	Channel int
 }
-```
+```
+
+#### 1.11 查询心跳包配置
+
+* 方法名: `GetKeepAlive`
+* 请求参数: `BaseArgs`
+* 返回参数:
+
+```go
+type KeepAliveReply struct {
+	Channels []*KeepAlive
+}
+
+type KeepAlive struct {
+	Duration int    // 心跳间隔
+	Format   int    // 数据格式
+	Content  string // 心跳包内容
+	Channel  int    // 通道
+}
+```
+
+#### 1.12 设置心跳包配置
+
+* 方法名: `SetKeepAlive`
+* 请求参数:
+```go
+type KeepAliveArgs struct {
+	BaseArgs
+	Duration int    // 心跳间隔
+	Format   int    // 数据格式
+	Content  string // 心跳包内容
+	Channel  int    // 通道
+}
+```
+* 返回参数: `EmptyResult`
+
+#### 1.13 设置轮询使能
+
+A 自定义轮询使能,取值范围 0-1 0 关闭自定义轮询功能 1 开启自定义轮询功能
+B 轮询时间间隔,取值范围 1-3600,表示每条启用指令间的时间间隔,单位秒
+C 轮询数据输入格式,取值范围 0-1 0 ASCII 格式,设置为 0 表示之后输入的轮询指令均为以 ASCII 形式轮询, 即输入什么字串就轮询什么字串 1 HEX 格式,
+设置为 1 表示之后输入的轮询指令需要满足 HEX 格式,轮 询时会自动转成 16 进制对应的 ASCII 字串 默认值:+POLL:0,10,1
+
+* 方法名:`SetPOLL`
+* 请求参数:
+```go
+type PollArgs struct {
+	BaseArgs
+	Sw       int // 是否使能
+	Duration int // 轮询间隔
+	Format   int // 内容格式
+}
+```
+* 返回参数: `EmptyResult`
+
+#### 1.14 查询轮询使能
+
+* 方法名:`GetPOLL`
+* 请求参数: `BaseArgs`
+* 返回参数: 
+```go
+type PollReply struct {
+	Sw       int // 是否使能
+	Duration int // 轮询间隔
+	Format   int // 内容格式
+}
+```
+
+#### 1.15 设置轮询字符串
+
+* 方法名:`SetPollStr`
+* 请求参数: 
+```go
+type PollStrArgs struct {
+	BaseArgs
+	Index   int    // 轮询字串号,取值范围 1-10
+	Sw      int    // 字串轮询使能
+	Crc     int    // CRC使能
+	Content string // 轮询内容
+}
+```
+* 返回参数: `EmptyResult`
+
+#### 1.16 查询轮询字符串
+
+* 方法名:`GetPollStr`
+* 请求参数: `BaseArgs`
+
+* 返回参数:
+
+```go
+type PollStrReply struct {
+    Strings []*PollStr
+}
+
+type PollStr struct {
+    Sw      int    // 字串轮询使能
+    Crc     int    // CRC使能
+    Content string // 轮询内容
+}
+```

+ 21 - 4
netAtSDK/at_client.go

@@ -185,7 +185,7 @@ func (a *ATClient) GetDTUID() (ret []string, err error) {
 	}
 	for _, v := range buf {
 		newV := gstr.Replace(v, "+DTUID: ", "")
-		ret = append(ret, newV)
+		ret = append(ret, gstr.TrimAll(newV))
 	}
 	return
 }
@@ -216,7 +216,7 @@ func (a *ATClient) GetKeepAlive() (ret []string, err error) {
 	}
 	for _, v := range buf {
 		newV := gstr.Replace(v, "+KEEPALIVE: ", "")
-		ret = append(ret, newV)
+		ret = append(ret, gstr.TrimAll(newV))
 	}
 	return
 }
@@ -241,7 +241,8 @@ func (a *ATClient) GetAll() (result []string, err error) {
 格式:AT+POLL=A,B,C
 A 自定义轮询使能,取值范围 0-1 0 关闭自定义轮询功能 1 开启自定义轮询功能
 B 轮询时间间隔,取值范围 1-3600,表示每条启用指令间的时间间隔,单位秒
-C 轮询数据输入格式,取值范围 0-1 0 ASCII 格式,设置为 0 表示之后输入的轮询指令均为以 ASCII 形式轮询, 即输入什么字串就轮询什么字串 1 HEX 格式,设置为 1 表示之后输入的轮询指令需要满足 HEX 格式,轮 询时会自动转成 16 进制对应的 ASCII 字串 默认值:+POLL:0,10,1
+C 轮询数据输入格式,取值范围 0-1 0 ASCII 格式,设置为 0 表示之后输入的轮询指令均为以 ASCII 形式轮询, 即输入什么字串就轮询什么字串 1 HEX 格式,
+设置为 1 表示之后输入的轮询指令需要满足 HEX 格式,轮 询时会自动转成 16 进制对应的 ASCII 字串 默认值:+POLL:0,10,1
 */
 func (a *ATClient) SetPOLL(sw, dur, format int) error {
 	_, err := a.send(fmt.Sprintf("POLL=%d,%d,%d", sw, dur, format))
@@ -273,6 +274,22 @@ func (a *ATClient) SetPOLLStr(index, sw, crc int, str string) error {
 	return err
 }
 
+// GetPollStr 获取轮询字符串配置
+// +POLLSTR:1,0,0,"313233"
+func (a *ATClient) GetPollStr() (result []string, err error) {
+	buf, err := a.send("POLLSTR?")
+	if err != nil {
+		return
+	}
+	for _, v := range buf {
+		index := gstr.Pos(v, ":")
+		if index >= 0 {
+			result = append(result, gstr.TrimAll(v[index+1:]))
+		}
+	}
+	return
+}
+
 // GetGPSInfo AT+GPSINFO:查询经纬度(精度 100m),
 // 查询经纬度信息,仅注册上基站后生效,属于原始 GPS 坐标
 // +GPSINFO: 030.1842195,120.2400433
@@ -303,7 +320,7 @@ func (a *ATClient) send(cmd string) (ret []string, err error) {
 				return
 			}
 			str := string(buf)
-			glog.Debugf("收到:%s, %2X", str, buf)
+			glog.Debugf("收到:%s", str)
 			if gstr.Contains(str, "OK") {
 				return
 			}

+ 12 - 0
netAtSDK/at_sdk_test.go

@@ -1,5 +1,17 @@
 package netAtSDK
 
+import (
+	"github.com/gogf/gf/text/gstr"
+	"testing"
+)
+
 func startTestServer() {
 
 }
+
+func TestNetATClient(t *testing.T) {
+	str := "+POLLSTR13: 0,0,\"0D\""
+	index := gstr.Pos(str, ": ")
+	t.Log(index)
+	t.Log(str[index+1:])
+}

+ 8 - 15
server/client.go

@@ -26,6 +26,7 @@ type Client struct {
 	mu            sync.Mutex
 	waitingATResp bool
 	atClient      *netAtSDK.ATClient
+	sendChan      chan []byte
 }
 
 func NewClient(s *Server, conn *gtcp.Conn) *Client {
@@ -56,7 +57,6 @@ func (c *Client) ReadLoop() {
 			if len(buf) > 0 {
 				if !c.isReg {
 					id := gbinary.DecodeToString(buf)
-					glog.Debugf("收到注册包!id:%s", id)
 					c.SetId(id)
 					c.isReg = true
 					if c.onReg != nil {
@@ -108,19 +108,12 @@ func (c *Client) send(buf []byte) error {
 	return nil
 }
 
-func (c *Client) TestGPS() {
-	for {
-		select {
-		case <-c.closeChan:
-			return
-		default:
-			str, err := c.atClient.GetGPS()
-			if err != nil {
-				glog.Debugf("查询出错:%s", err)
-				continue
-			}
-			glog.Debugf("查询结果 :%s", str)
-		}
-		time.Sleep(10 * time.Second)
+func (c *Client) Test() {
+
+	time.Sleep(60 * time.Second)
+	str, err := c.atClient.GetAll()
+	if err != nil {
+		glog.Debugf("查询出错:%s", err)
 	}
+	glog.Debugf("查询结果 :%s", str)
 }

+ 1 - 2
server/server.go

@@ -45,7 +45,6 @@ func (s *Server) Stop() error {
 }
 
 func (s *Server) onClientConnect(conn *gtcp.Conn) {
-	glog.Debugf("新的设备接入:%s", conn.RemoteAddr())
 	client := NewClient(s, conn)
 	client.closeHandler = func(id string, c *Client) {
 		s.clients.Remove(id)
@@ -55,8 +54,8 @@ func (s *Server) onClientConnect(conn *gtcp.Conn) {
 		glog.Debugf("客户端上线:%s", id)
 		s.clients.Set(id, c)
 	}
-	go client.TestGPS()
 	go client.ReadLoop()
+	go client.Test()
 }
 
 // GetATClient 获取AT操作

+ 83 - 0
services/service.go

@@ -233,3 +233,86 @@ func (a *ATService) GetKeepAlive(ctx context.Context, args *BaseArgs, reply *Kee
 	reply.Channels = channels
 	return nil
 }
+
+// SetKeepAlive 设置心跳包
+func (a *ATService) SetKeepAlive(ctx context.Context, args *KeepAliveArgs, reply *EmptyResult) error {
+	client, err := a.srv.GetATClient(args.IMEI)
+	if err != nil {
+		return err
+	}
+	err = client.SetKeepAlive(args.Duration, args.Format, args.Content, args.Channel)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// SetPOLL 设置轮询使能
+func (a *ATService) SetPOLL(ctx context.Context, args *PollArgs, reply *EmptyResult) error {
+	client, err := a.srv.GetATClient(args.IMEI)
+	if err != nil {
+		return err
+	}
+	err = client.SetPOLL(args.Sw, args.Duration, args.Format)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// GetPOLL 查询轮询使能
+func (a *ATService) GetPOLL(ctx context.Context, args *BaseArgs, reply *PollReply) error {
+	client, err := a.srv.GetATClient(args.IMEI)
+	if err != nil {
+		return err
+	}
+	result, err := client.GetPOLL()
+	if err != nil {
+		return err
+	}
+	arr := gstr.Split(result, ",")
+	if len(arr) > 2 {
+		reply.Sw = gconv.Int(arr[0])
+		reply.Duration = gconv.Int(arr[1])
+		reply.Format = gconv.Int(arr[2])
+	}
+	return nil
+}
+
+// SetPollStr 设置轮询字符串
+func (a *ATService) SetPollStr(ctx context.Context, args *PollStrArgs, reply *EmptyResult) error {
+	client, err := a.srv.GetATClient(args.IMEI)
+	if err != nil {
+		return err
+	}
+	err = client.SetPOLLStr(args.Index, args.Sw, args.Crc, args.Content)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// GetPollStr 查询轮询字符串
+func (a *ATService) GetPollStr(ctx context.Context, args *BaseArgs, reply *PollStrReply) error {
+	client, err := a.srv.GetATClient(args.IMEI)
+	if err != nil {
+		return err
+	}
+	result, err := client.GetPollStr()
+	if err != nil {
+		return err
+	}
+	var strs []*PollStr
+	for _, v := range result {
+		arr := gstr.Split(v, ",")
+		if len(arr) > 2 {
+			strs = append(strs, &PollStr{
+				Sw:      gconv.Int(arr[0]),
+				Crc:     gconv.Int(arr[1]),
+				Content: arr[2],
+			})
+		}
+	}
+	reply.Strings = strs
+	return nil
+}

+ 31 - 0
services/structs.go

@@ -97,3 +97,34 @@ type KeepAlive struct {
 	Content  string // 心跳包内容
 	Channel  int    // 通道
 }
+
+type PollArgs struct {
+	BaseArgs
+	Sw       int // 是否使能
+	Duration int // 轮询间隔
+	Format   int // 内容格式
+}
+
+type PollReply struct {
+	Sw       int // 是否使能
+	Duration int // 轮询间隔
+	Format   int // 内容格式
+}
+
+type PollStrArgs struct {
+	BaseArgs
+	Index   int    // 轮询字串号,取值范围 1-10
+	Sw      int    // 字串轮询使能
+	Crc     int    // CRC使能
+	Content string // 轮询内容
+}
+
+type PollStrReply struct {
+	Strings []*PollStr
+}
+
+type PollStr struct {
+	Sw      int    // 字串轮询使能
+	Crc     int    // CRC使能
+	Content string // 轮询内容
+}