新增协议
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
u_boot
|
u_boot
|
||||||
|
归档.zip
|
||||||
35
main.go
35
main.go
@@ -72,8 +72,7 @@ func main() {
|
|||||||
// 客户端{"Type":"ping"}
|
// 客户端{"Type":"ping"}
|
||||||
// 服务端{"Type":"pong"}
|
// 服务端{"Type":"pong"}
|
||||||
|
|
||||||
// 服务端发 {"Type":"ota","Ip":"192.168.31.1:80","File":"/xxx/1.bin"}
|
// 服务端发 {\"Type\":\"ota\",\"Ip\":\"http://8.141.8.18/V1002.bin\"}
|
||||||
// 服务端发 {\"Type\":\"ota\",\"Ip\":\"192.168.31.1:80\",\"File\":\"/xxx/1.bin\"}
|
|
||||||
// 客户端回复 {"Type":"ota","State":"1"}
|
// 客户端回复 {"Type":"ota","State":"1"}
|
||||||
|
|
||||||
// 开始实时上传数据
|
// 开始实时上传数据
|
||||||
@@ -88,4 +87,36 @@ func main() {
|
|||||||
// 服务端发 {\"Type\":\"server\",\"Ip\":\"1222\",\"Port\":\"1222\"}
|
// 服务端发 {\"Type\":\"server\",\"Ip\":\"1222\",\"Port\":\"1222\"}
|
||||||
// 客户端回复 {"Type":"server","State":"1"}
|
// 客户端回复 {"Type":"server","State":"1"}
|
||||||
|
|
||||||
|
// 设置楼层信息
|
||||||
|
// 服务器端发 {"Type":"SetConfig","Conf":{"zong":"10","ceng":["-2","-1","1","2","3","4","5","6","7","8"],"height":"4"}}
|
||||||
|
// 客户端回复 {"Type":"SetConfig","State":"1"}
|
||||||
|
|
||||||
|
// 获取楼层信息
|
||||||
|
// 服务器端发 {"Type":"GetConfig"}
|
||||||
|
// 客户端回复 {"Type":"GetConfig","Conf":{"zong":"10","ceng":["-2","-1","1","2","3","4","5","6","7","8"],"height":"4"}}
|
||||||
|
|
||||||
|
// 设置第一段语音
|
||||||
|
// 服务器端发 {"Type":"mp3a","jg":"10","MpData":"内容" }
|
||||||
|
// 客户端回复 {"Type":"mp3a","State":"1"}
|
||||||
|
|
||||||
|
// 设置第二段语音
|
||||||
|
// 服务器端发 {"Type":"mp3b","jg":"10","MpData":"内容"}
|
||||||
|
// 客户端回复 {"Type":"mp3b","State":"1"}
|
||||||
|
|
||||||
|
// 设置第三段语音
|
||||||
|
// 服务器端发 {"Type":"mp3c","jg":"10","MpData":"内容"}
|
||||||
|
// 客户端回复 {"Type":"mp3c","State":"1"}
|
||||||
|
|
||||||
|
// 服务端设置语音配置
|
||||||
|
// 服务器端发 {"Type":"SetVoiceConf","VoiceConf":{"fyr":"0","yl":"8","ys":"8","yd":"8","isPlay":"0"}}
|
||||||
|
// 客户端回复 {"Type":"SetVoiceConf","State":"1"}
|
||||||
|
|
||||||
|
// 服务端获取客户端语音配置
|
||||||
|
// 服务器端发 {"Type":"GetVoiceConf"}
|
||||||
|
// 客户端回复 {"Type":"GetVoiceConf","VoiceConf":{"fyr":"0","yl":"8","ys":"8","yd":"8","isPlay":"0"}}
|
||||||
|
|
||||||
|
//播放
|
||||||
|
|
||||||
//{\n\t"Type":"ping"}
|
//{\n\t"Type":"ping"}
|
||||||
|
|
||||||
|
//{\"Type\":\"txt\",\"content\":\"c4e3bac3a3accac0bde7a3a1\","jg":"21""} 间隔秒
|
||||||
|
|||||||
189
tcpserver/func.go
Normal file
189
tcpserver/func.go
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
package tcpserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"DT/repository"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *Server) HandleHeartbeat(client *Client, message []byte) error {
|
||||||
|
if !client.IsAuth {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg.Type == "ping" {
|
||||||
|
client.LastPing = time.Now()
|
||||||
|
//response := Message{
|
||||||
|
// MessageType: MessageType{Type: "pong"},
|
||||||
|
//}
|
||||||
|
response := struct {
|
||||||
|
Type string `json:"Type"`
|
||||||
|
}{
|
||||||
|
Type: "pong",
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData, err := json.Marshal(response)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = client.Conn.Write(append(responseData, '\r', '\n'))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) HandleAuth(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "reg" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
model, err := repository.GroupRepositorys.Device.GetDevice(map[string]interface{}{"imei": msg.Imei})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("设备不存在")
|
||||||
|
}
|
||||||
|
if msg.Pwd != model.DriverPass {
|
||||||
|
return fmt.Errorf("设备密码不正确")
|
||||||
|
}
|
||||||
|
|
||||||
|
model.DriverVer = msg.Ver
|
||||||
|
err = repository.GroupRepositorys.Device.UpdateDevice(model)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("更新设备版本号失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
if client.authTimer != nil {
|
||||||
|
client.authTimer.Stop()
|
||||||
|
client.authTimer = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Imei = msg.Imei
|
||||||
|
client.IsAuth = true
|
||||||
|
|
||||||
|
//response := Message{
|
||||||
|
// MessageType: MessageType{Type: "reg"},
|
||||||
|
// MessageTime: MessageTime{Time: time.Now().Unix()},
|
||||||
|
//}
|
||||||
|
response := struct {
|
||||||
|
Type string `json:"Type"`
|
||||||
|
Time int64 `json:"Time,omitempty"`
|
||||||
|
}{
|
||||||
|
Type: "reg",
|
||||||
|
Time: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
|
||||||
|
responseData, err := json.Marshal(response)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.Conn.Write(append(responseData, '\r', '\n'))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (s *Server) HandleOta(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "ota" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("设备升级结果:%s\r\n", msg.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) RealTimeReporting(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "start" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("设备实时上报数据:%v\r\n", msg.MessageStartData.StartDatas)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) StopRealTimeReporting(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "stop" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("设备停止实时上报数据:%s\r\n", msg.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) TimingReporting(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "up" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("设备定时上报数据:%v\r\n", msg.MessageUpData)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) SetConfig(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "SetConfig" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("设备楼层设置结果:%v\r\n", msg.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) GetConfig(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "GetConfig" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("获取设备楼层设置:%v\r\n", msg.MessageConf)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) Mp3(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "mp3c" && msg.Type != "mp3b" && msg.Type != "mp3a" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("客户端设置语音状态:%v\r\n", msg.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) SetVoiceConf(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "SetVoiceConf" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("客户端语音配置状态:%v\r\n", msg.State)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *Server) GetVoiceConf(client *Client, message []byte) error {
|
||||||
|
var msg Message
|
||||||
|
if err := json.Unmarshal(message, &msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if msg.Type != "SetVoiceConf" {
|
||||||
|
return fmt.Errorf("unauthorized")
|
||||||
|
}
|
||||||
|
fmt.Printf("客户端语音配置状态:%v\r\n", msg.MessageVoiceConf)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package tcpserver
|
package tcpserver
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"DT/repository"
|
|
||||||
"DT/ws"
|
"DT/ws"
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -9,7 +8,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TCPHandler struct {
|
type TCPHandler struct {
|
||||||
@@ -107,7 +105,7 @@ func (h *TCPHandler) HandleClient(conn net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := h.Server.RealTimeReporting(client, message); err != nil {
|
if err := h.Server.RealTimeReporting(client, message); err != nil {
|
||||||
fmt.Printf("OTA 错误: %v\n", err)
|
fmt.Printf("实时上报错误: %v\n", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
broadcastMessage(message)
|
broadcastMessage(message)
|
||||||
@@ -135,7 +133,63 @@ func (h *TCPHandler) HandleClient(conn net.Conn) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
broadcastMessage(message)
|
broadcastMessage(message)
|
||||||
|
case "SetConfig":
|
||||||
|
if !client.IsAuth {
|
||||||
|
fmt.Printf("来自未授权客户端的消息 %s\n", conn.RemoteAddr())
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.Server.SetConfig(client, message); err != nil {
|
||||||
|
fmt.Printf("客户端楼层设置 错误: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
broadcastMessage(message)
|
||||||
|
|
||||||
|
case "GetConfig":
|
||||||
|
if !client.IsAuth {
|
||||||
|
fmt.Printf("来自未授权客户端的消息 %s\n", conn.RemoteAddr())
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.Server.GetConfig(client, message); err != nil {
|
||||||
|
fmt.Printf("获取客户端楼层设置错误: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
broadcastMessage(message)
|
||||||
|
|
||||||
|
case "mp3a", "mp3b", "mp3c":
|
||||||
|
if !client.IsAuth {
|
||||||
|
fmt.Printf("来自未授权客户端的消息 %s\n", conn.RemoteAddr())
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.Server.Mp3(client, message); err != nil {
|
||||||
|
fmt.Printf("客户端设置语音内容错误: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
broadcastMessage(message)
|
||||||
|
case "SetVoiceConf":
|
||||||
|
if !client.IsAuth {
|
||||||
|
fmt.Printf("来自未授权客户端的消息 %s\n", conn.RemoteAddr())
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.Server.SetVoiceConf(client, message); err != nil {
|
||||||
|
fmt.Printf("客户端语音配置错误: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
broadcastMessage(message)
|
||||||
|
case "GetVoiceConf":
|
||||||
|
if !client.IsAuth {
|
||||||
|
fmt.Printf("来自未授权客户端的消息 %s\n", conn.RemoteAddr())
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := h.Server.GetVoiceConf(client, message); err != nil {
|
||||||
|
fmt.Printf("获取客户端语音配置错误: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
broadcastMessage(message)
|
||||||
default:
|
default:
|
||||||
if !client.IsAuth {
|
if !client.IsAuth {
|
||||||
fmt.Printf("来自未授权客户端的消息 %s\n", conn.RemoteAddr())
|
fmt.Printf("来自未授权客户端的消息 %s\n", conn.RemoteAddr())
|
||||||
@@ -146,121 +200,3 @@ func (h *TCPHandler) HandleClient(conn net.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) HandleHeartbeat(client *Client, message []byte) error {
|
|
||||||
if !client.IsAuth {
|
|
||||||
return fmt.Errorf("unauthorized")
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg Message
|
|
||||||
if err := json.Unmarshal(message, &msg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if msg.Type == "ping" {
|
|
||||||
client.LastPing = time.Now()
|
|
||||||
response := Message{
|
|
||||||
MessageType: MessageType{Type: "pong"},
|
|
||||||
}
|
|
||||||
|
|
||||||
responseData, err := json.Marshal(response)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = client.Conn.Write(append(responseData, '\r', '\n'))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) HandleAuth(client *Client, message []byte) error {
|
|
||||||
var msg Message
|
|
||||||
if err := json.Unmarshal(message, &msg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if msg.Type != "reg" {
|
|
||||||
return fmt.Errorf("unauthorized")
|
|
||||||
}
|
|
||||||
|
|
||||||
model, err := repository.GroupRepositorys.Device.GetDevice(map[string]interface{}{"imei": msg.Imei})
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("设备不存在")
|
|
||||||
}
|
|
||||||
if msg.Pwd != model.DriverPass {
|
|
||||||
return fmt.Errorf("设备密码不正确")
|
|
||||||
}
|
|
||||||
|
|
||||||
model.DriverVer = msg.Ver
|
|
||||||
err = repository.GroupRepositorys.Device.UpdateDevice(model)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("更新设备版本号失败")
|
|
||||||
}
|
|
||||||
|
|
||||||
if client.authTimer != nil {
|
|
||||||
client.authTimer.Stop()
|
|
||||||
client.authTimer = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
client.Imei = msg.Imei
|
|
||||||
client.IsAuth = true
|
|
||||||
|
|
||||||
response := Message{
|
|
||||||
MessageType: MessageType{Type: "reg"},
|
|
||||||
MessageTime: MessageTime{Time: time.Now().Unix()},
|
|
||||||
}
|
|
||||||
responseData, err := json.Marshal(response)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.Conn.Write(append(responseData, '\r', '\n'))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) HandleOta(client *Client, message []byte) error {
|
|
||||||
var msg Message
|
|
||||||
if err := json.Unmarshal(message, &msg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if msg.Type != "ota" {
|
|
||||||
return fmt.Errorf("unauthorized")
|
|
||||||
}
|
|
||||||
fmt.Printf("设备升级结果:%s\r\n", msg.State)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) RealTimeReporting(client *Client, message []byte) error {
|
|
||||||
var msg Message
|
|
||||||
if err := json.Unmarshal(message, &msg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if msg.Type != "start" {
|
|
||||||
return fmt.Errorf("unauthorized")
|
|
||||||
}
|
|
||||||
fmt.Printf("设备实时上报数据:%v\r\n", msg)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) StopRealTimeReporting(client *Client, message []byte) error {
|
|
||||||
var msg Message
|
|
||||||
if err := json.Unmarshal(message, &msg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if msg.Type != "stop" {
|
|
||||||
return fmt.Errorf("unauthorized")
|
|
||||||
}
|
|
||||||
fmt.Printf("设备停止实时上报数据:%s\r\n", msg.State)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Server) TimingReporting(client *Client, message []byte) error {
|
|
||||||
var msg Message
|
|
||||||
if err := json.Unmarshal(message, &msg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if msg.Type != "up" {
|
|
||||||
return fmt.Errorf("unauthorized")
|
|
||||||
}
|
|
||||||
fmt.Printf("设备定时上报数据:%v\r\n", msg.MessageData)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -19,10 +19,32 @@ type MessageState struct {
|
|||||||
State string `json:"State,omitempty"`
|
State string `json:"State,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageData struct {
|
//type MessageData struct {
|
||||||
UpDataStruct
|
// UpDataStruct
|
||||||
|
//}
|
||||||
|
|
||||||
|
type MessageUpData struct {
|
||||||
|
Sum int `json:"sum"`
|
||||||
|
Time int `json:"time"`
|
||||||
|
Mile int `json:"mile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MessageStartData struct {
|
||||||
|
StartDatas []string `json:"Datas,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageConf struct {
|
||||||
|
Zong string `json:"zong"`
|
||||||
|
Ceng []string `json:"ceng"`
|
||||||
|
Height string `json:"height"`
|
||||||
|
}
|
||||||
|
type MessageVoiceConf struct {
|
||||||
|
Fyr string `json:"fyr"`
|
||||||
|
Yl string `json:"yl"`
|
||||||
|
Ys string `json:"ys"`
|
||||||
|
Yd string `json:"yd"`
|
||||||
|
IsPlay string `json:"isPlay"`
|
||||||
|
}
|
||||||
type Message struct {
|
type Message struct {
|
||||||
MessageType
|
MessageType
|
||||||
MessageImei
|
MessageImei
|
||||||
@@ -30,11 +52,8 @@ type Message struct {
|
|||||||
MessageVer
|
MessageVer
|
||||||
MessageTime
|
MessageTime
|
||||||
MessageState
|
MessageState
|
||||||
MessageData `json:"Data"`
|
MessageUpData `json:"Data,omitempty"`
|
||||||
}
|
MessageStartData
|
||||||
|
MessageConf `json:"Conf,omitempty"`
|
||||||
type UpDataStruct struct {
|
MessageVoiceConf `json:"VoiceConf,omitempty"`
|
||||||
Sum int `json:"sum"`
|
|
||||||
Time int `json:"time"`
|
|
||||||
Mile int `json:"mile"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user