Commit 2a90d4d5 by Administrator

OEM电话机硬件服务器

parents
# 默认忽略的文件
/shelf/
/workspace.xml
# 数据源本地存储已忽略文件
/dataSources/
/dataSources.local.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/jeff_workstation_1.iml" filepath="$PROJECT_DIR$/.idea/jeff_workstation_1.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/mahonia" vcs="Git" />
</component>
</project>
\ No newline at end of file
File added
[http_server]
#debug release
ServerMode = release
ServerPort = :50000
[http_client]
#BaseUrl = http://handandev.swaylink.cn/phone/2/server/
#BaseUrl = http://dev.lezhixy.com/phone/2/server/
BaseUrl = http://127.0.0.1:1234/phone/2/server/
TimeOut = 5
[tcp_long_server]
#TCP服务监听的端口号
TcpPort = 60000
#TCP 最大连接数限制,建议设置实际设备数量的2.5倍
MaxConnections = 20000
#新建立的TCP连接,连上后多久完全没收到数据就判断为非法设备断掉,单位秒
NewConnReadDeadline = 60
#新建立的TCP连接,连上后多久没收到合法完整数据就判断为非法设备断掉,单位秒
NewConnRightfulTimeout = 120
#老连接(已验证通过确实是合法设备的tcp连接),多久没收到数据就断掉,这里设置为3倍心跳时间(若同一台设备建立了新连接,系统会立即释放老连接)
OldConnReadDeadline = 180
[log]
#debug info warn error 只允许设置这3个等级,以保证至少记录error DPanic Panci Fatal
#debug info: 记录流水数据(都存在info.log里)
#warn: 应检查原因,主要来自外部
#error DPanic Panci Fatal: 应立即检查原因来内部或硬件设备或业务服务器
Level = debug
#log文件的存储路径
Path = ./log/
#单个日志文件大小限制,单位MB
FileMaxSize = 10
#info级别日志最多保存多少份
InfoMaxFileNum = 30
#info日志最长保留天数
InfoWithMaxAge = 30
#warn级别日志最多保存多少份
WarnMaxFileNum = 30
#warn日志最长保留天数
WarnWithMaxAge = 90
#Error级别日志最多保存多少份
ErrorMaxFileNum = 10
#Error日志最长保留天数
ErrorWithMaxAge = 180
package devproduct
import "github.com/gin-gonic/gin"
func NewDCFan50(r *gin.Engine) {
var dcFan50TCP DCFan50
dcFan50TCP.NewDCFan50("DCRYM-2018-pswd.", "I can't tell YOU", 0x3E) // config
dcFan50TCP.TCPStart("60000")
dcFan50TCP.NewDCFan50API(r)
}
package devproduct
import (
"github.com/gin-gonic/gin"
"jeff_workstation_1/tcplongserver"
"net/http"
"strconv"
)
func (dev *DCFan50) NewDCFan50API(r *gin.Engine) {
router := r.Group("fan50/")
{
router.GET("online/list", dev.getOnlineList) //查整个在线设备列表
router.GET("online/total", dev.getOnlineTotal) //查在线设备总数量
router.GET("online/:devid", dev.getOnlineDevState) //查询某台设备在线状态
//router.GET("para",getDevPara) //读取某台设备某个参数
//router.POST("para",setDevPara) //设置某台设备某个参数
router.PUT("devctrl/user1/:devid", dev.devCtrlUser1Dev) //登录使用设备 //这里测试用
router.PUT("devctrl/user2/:devid", dev.devCtrlUser2Dev) //登录使用设备 //这里测试用
router.PUT("devctrl/user1stop/:devid", dev.devCtrlUser1StopDev)
router.PUT("devctrl/user2stop/:devid", dev.devCtrlUser2StopDev) //退出登录设备
router.PUT("devctrl/test/:devid", dev.devCtrlTestDev) //测试放吹风
router.PUT("devctrl/updatefirmwareversion/:devid", dev.devCtrlUpdateFirmwareVersion) //启动远程更新
router.PUT("devctrl/setipport/:devid", dev.devCtrSetIpPort) //修改TCP地址
}
}
//查整个在线设备列表
func (dev *DCFan50) getOnlineList(c *gin.Context) {
count := 0
devID := make([]uint32, 0, 5000)
dev.ConnectMap.Range(func(k, _ interface{}) bool {
if d, ok := k.(uint32); ok { // 类型断言
devID = append(devID, d) //strconv.FormatUint(uint64(d),16))
count++
} else {
dev.ConnectMap.Delete(k)
}
return true
})
//devTCP.ConnectMapRWMutex.RLock()
c.JSON(http.StatusOK, gin.H{
"status": 200,
//"data": devTCP.ConnectMap,
"data": devID,
"total": count,
"socket": dev.ConnSocketCount,
//"total": len(devTCP.ConnectMap),
"message": "OK",
})
//devTCP.ConnectMapRWMutex.RUnlock()
}
//查在线设备总数量
func (dev *DCFan50) getOnlineTotal(c *gin.Context) {
count := 0
dev.ConnectMap.Range(func(_, _ interface{}) bool {
count++
return true
})
c.JSON(http.StatusOK, gin.H{
"status": 200,
"total": count,
"socket": dev.ConnSocketCount,
// "total": len(devTCP.ConnectMap),
"message": "OK",
})
}
//查询某台设备在线状态
func (dev *DCFan50) getOnlineDevState(c *gin.Context) {
//type jsonData struct {
// ID int `json:"id"`
// Name string `json:"name"`
//}
code := 200
online := false
errMsg := "OK"
//var conn *net.TCPConn
//var ok bool
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
// devTCP.ConnectMapRWMutex.RLock()
// conn,ok = devTCP.ConnectMap[uint32(id)]
// devTCP.ConnectMapRWMutex.RUnlock()
if _, ok := dev.ConnectMap.Load(uint32(id)); ok {
//if ok {
online = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": online,
"message": errMsg,
})
}
//////////////////////设备控制/////////////////////////////////
// 测试吹风
func (dev *DCFan50) devCtrlTestDev(c *gin.Context) {
code := 200
result := false
errMsg := "OK"
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
var sData tcplongserver.HexData
sData.DevID = uint32(id)
sData.CtrlCode = 0x30
if dev.TCPSend(&sData) == true {
result = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": result,
"message": errMsg,
})
}
//type UserOpen struct {
// // ID int `json:"id"`
// // Name string `json:"name"`
//}
// 开启吹风
func (dev *DCFan50) devCtrlUser1Dev(c *gin.Context) {
money := 1000 //余额 单位分
price := 200 //价格 单位厘
code := 200
result := false
errMsg := "OK"
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
var sData tcplongserver.HexData
sData.DevID = uint32(id)
sData.CtrlCode = 0x20
sData.Data = make([]byte, 31)
sData.Data[0] = 1 //左侧
sData.Data[1] = 1 //硬件账号1
copy(sData.Data[5:], "12345678901234567890")
sData.Data[25] = byte(money)
sData.Data[26] = byte(money >> 8)
sData.Data[27] = byte(money >> 16)
sData.Data[28] = byte(money >> 24)
sData.Data[29] = byte(price)
sData.Data[30] = byte(price >> 8)
sData.Length = 31
if dev.TCPSend(&sData) == true {
result = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": result,
"message": errMsg,
})
}
// 开启吹风
func (dev *DCFan50) devCtrlUser2Dev(c *gin.Context) {
money := 1000 //余额 单位分
price := 200 //价格 单位厘
code := 200
result := false
errMsg := "OK"
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
var sData tcplongserver.HexData
sData.DevID = uint32(id)
sData.CtrlCode = 0x20
sData.Data = make([]byte, 31)
sData.Data[0] = 2 //右侧
sData.Data[1] = 2 //硬件账号1
copy(sData.Data[5:], "12345678901234567890")
sData.Data[25] = byte(money)
sData.Data[26] = byte(money >> 8)
sData.Data[27] = byte(money >> 16)
sData.Data[28] = byte(money >> 24)
sData.Data[29] = byte(price)
sData.Data[30] = byte(price >> 8)
sData.Length = 31
if dev.TCPSend(&sData) == true {
result = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": result,
"message": errMsg,
})
}
func (dev *DCFan50) devCtrlUser1StopDev(c *gin.Context) {
code := 200
result := false
errMsg := "OK"
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
var sData tcplongserver.HexData
sData.DevID = uint32(id)
sData.Data = make([]byte, 5)
sData.Data[0] = 1
sData.Data[1] = 1
sData.Length = 5
sData.CtrlCode = 0x21
if dev.TCPSend(&sData) == true {
result = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": result,
"message": errMsg,
})
}
func (dev *DCFan50) devCtrlUser2StopDev(c *gin.Context) {
code := 200
result := false
errMsg := "OK"
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
var sData tcplongserver.HexData
sData.DevID = uint32(id)
sData.Data = make([]byte, 5)
sData.Data[0] = 2
sData.Data[1] = 2
sData.Length = 5
sData.CtrlCode = 0x21
if dev.TCPSend(&sData) == true {
result = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": result,
"message": errMsg,
})
}
func (dev *DCFan50) devCtrlUpdateFirmwareVersion(c *gin.Context) {
code := 200
result := false
errMsg := "OK"
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
type paraOneString struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value string `json:"value"`
}
var data paraOneString
c.ShouldBindJSON(&data)
var sData tcplongserver.HexData
sData.DevID = uint32(id)
sData.Data = make([]byte, len(data.Value)+1)
copy(sData.Data, data.Value)
sData.Length = byte(len(sData.Data))
sData.CtrlCode = 0x71
if dev.TCPSend(&sData) == true {
result = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": result,
"message": errMsg,
})
}
func (dev *DCFan50) devCtrSetIpPort(c *gin.Context) {
code := 200
result := false
errMsg := "OK"
if id, err := strconv.ParseUint(c.Param("devid"), 16, 32); err == nil {
type paraOneString struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value string `json:"value"`
}
var data paraOneString
c.ShouldBindJSON(&data)
var sData tcplongserver.HexData
sData.DevID = uint32(id)
sData.Data = []byte(data.Value)
sData.Length = byte(len(data.Value))
sData.CtrlCode = 0x03
if dev.TCPSend(&sData) == true {
result = true
}
} else {
code = 1001
errMsg = "未传入正确的设备编号格式"
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": result,
"message": errMsg,
})
}
package devproduct
import (
"fmt"
"jeff_workstation_1/tcplongserver"
)
//type IDCFan50 interface {
// Response(conn *net.TCPConn,data []byte,len int) bool
//}
type DCFan50 struct {
tcplongserver.DCLongTCPHex
}
func (dev *DCFan50) NewDCFan50(password string, iv string, devType uint8) {
dev.InitNewDCLongTCPHex(password, iv, devType, dev.response)
}
//TCP收到的协议解析
func (dev *DCFan50) response(data *tcplongserver.HexData) { //(result devproduct.HexData){
ctrlCode := data.CtrlCode
data.CtrlCode = 0
switch ctrlCode {
case 0x80: //读ID,莫得卵用
case 0x86: //硬件响应修改密钥,莫得卵用
case 0x83: //TCP服务器地址
case 0x84: //心跳参数
fmt.Println("心跳参数: ")
case 0x41: //状态心跳
if data.Length == 15 || data.Length == 35 || data.Length == 55 {
fmt.Printf("状态心跳:%x\n", data.Data[1])
fmt.Printf("通信延迟:%d\n", data.Data[0])
fmt.Printf("左电流:%dmA , 右电流:%dmA\n", uint16(data.Data[3])<<8+uint16(data.Data[2]), uint16(data.Data[5])<<8+uint16(data.Data[4]))
fmt.Printf("左电阻:%d , 右电阻:%d\n", uint16(data.Data[7])<<8+uint16(data.Data[6]), uint16(data.Data[9])<<8+uint16(data.Data[8]))
fmt.Printf("左温度:%d℃ , 右温度:%d℃\n", data.Data[10], data.Data[11])
fmt.Printf("VCC-L:%d , VCC-H:%d\n", data.Data[12], data.Data[13])
fmt.Printf("在用账单: %d", data.Data[14])
if data.Length > 15 {
fmt.Printf("-%s", string(data.Data[15:35]))
}
if data.Length > 35 {
fmt.Printf("-%s", string(data.Data[35:55]))
}
fmt.Println("\n----------------------------------------------------")
} else {
// logger 内容错误
}
data.CtrlCode = ctrlCode | 0x80
data.Length = 0
case 0x7e: //异常
if data.Length == 15 || data.Length == 35 || data.Length == 55 {
fmt.Printf("状态异常:%x\n", data.Data[1])
fmt.Printf("通信延迟:%d\n", data.Data[0])
fmt.Printf("左电流:%dmA , 右电流:%dmA\n", uint16(data.Data[3])<<8+uint16(data.Data[2]), uint16(data.Data[5])<<8+uint16(data.Data[4]))
fmt.Printf("左电阻:%d , 右电阻:%d\n", uint16(data.Data[7])<<8+uint16(data.Data[6]), uint16(data.Data[9])<<8+uint16(data.Data[8]))
fmt.Printf("左温度:%d℃ , 右温度:%d℃\n", data.Data[10], data.Data[11])
fmt.Printf("VCC-L:%d , VCC-H:%d\n", data.Data[12], data.Data[13])
fmt.Printf("在用账单: %d", data.Data[14])
if data.Length > 15 {
fmt.Printf("-%s", string(data.Data[15:35]))
}
if data.Length > 35 {
fmt.Printf("-%s", string(data.Data[35:55]))
}
fmt.Println("\n----------------------------------------------------")
} else {
// logger 内容错误
}
data.CtrlCode = ctrlCode | 0x80
data.Length = 0
case 0x22: // 上报正常账单
if data.Length == 37 {
fmt.Println("收到正常账单:")
fmt.Printf("账单号:%s,消费金额:%d分,使用时长:%dX0.1秒,占用时长:%dX0.1秒,最大电流:%dmA,接触电阻:%d豪欧,温度:%d摄氏度,开关次数:%d,退出原因:%d\n",
data.Data[:20],
int(data.Data[20])+(int(data.Data[21])<<8),
int(data.Data[22])+(int(data.Data[23])<<8)+(int(data.Data[24])<<16)+(int(data.Data[25])<<24),
int(data.Data[26])+(int(data.Data[27])<<8)+(int(data.Data[28])<<16)+(int(data.Data[29])<<24),
int(data.Data[30])+(int(data.Data[31])<<8),
int(data.Data[32])+(int(data.Data[33])<<8),
data.Data[34],
data.Data[35],
data.Data[36])
}
data.CtrlCode = ctrlCode | 0x80
case 0xB0: // 响应进入测试吹风
fmt.Println("硬件响应进入测试吹风模式")
default:
// logger 未知信息
fmt.Printf("协议未收录的控制字:0x%x\n", ctrlCode)
}
//return
}
package devproduct
import (
"github.com/gin-gonic/gin"
"jeff_workstation_1/jeffutil"
)
func NewDCPhone10(r *gin.Engine) {
var dcPhone10TCP DCPhone10
dcPhone10TCP.NewDCPhone10("DCRYM-2018-pswd.", "I can't tell YOU", 0x5A) // config
dcPhone10TCP.TCPStart(jeffutil.TcpLongPort)
dcPhone10TCP.NewDCPhone10API(r)
}
package devproduct
import (
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"jeff_workstation_1/logger"
"jeff_workstation_1/tcplongserver"
"net"
"net/http"
"strconv"
)
func (dev *DCPhone10) NewDCPhone10API(r *gin.Engine) {
router := r.Group("phone10/")
{
router.GET("online/all", dev.getOnlineAll) //查询所有在线设备列表
router.GET("online/list", dev.getOnlineList) //查设备是否在线
router.GET("online/num", dev.getOnlineTotal) //查在线设备总数量
router.DELETE("online/", dev.putOnlineClose) //批量强制关闭设备连接
router.GET("para/:paraName", dev.getDevPara) //读取某些设备某个参数
router.POST("para/:paraName", dev.setDevPara) //设置某些设备某个参数
router.PUT("ctrl/:paraName", dev.setDevPara) //批量重启设备 restart_device
router.GET("ctrl/:paraName", dev.getDevPara) // 读取固件版本号 read_firmware_version
//router.PUT("ctrl/:paraName",dev.setDevPara) //固件更新 update_firmware //远程拨号 online_dial
router.POST("ctrl/:paraName", dev.setDevPara) //远程拨号 online_dial //固件更新 update_firmware
}
}
//查设备是否在线
func (dev *DCPhone10) getOnlineList(c *gin.Context) {
type st struct {
DevID []uint32 `json:"devId"`
}
var dataIn st
if err := c.ShouldBindJSON(&dataIn); err != nil {
logger.Log.Error("c.ShouldBindJSON(&dataIn)",
zap.String("Src", "getOnlineList"),
zap.Error(err))
}
type DataO struct {
Count int `json:"count"`
DevID map[uint32]bool `json:"devId"`
}
var dataOut DataO
dataOut.DevID = make(map[uint32]bool)
for _, id := range dataIn.DevID {
if _, ok := dev.ConnectMap.Load(id); ok {
dataOut.DevID[id] = true
dataOut.Count++
} else {
dataOut.DevID[id] = false
}
}
c.JSON(http.StatusOK, gin.H{
"status": 200,
"data": dataOut,
"message": "OK",
})
}
//查在线设备总数量
func (dev *DCPhone10) getOnlineTotal(c *gin.Context) {
type DataO struct {
Count int `json:"count"`
Socket int `json:"socket"`
}
var dataOut DataO
dev.ConnectMap.Range(func(_, _ interface{}) bool {
dataOut.Count++
return true
})
dataOut.Socket = dev.ConnSocketCount
c.JSON(http.StatusOK, gin.H{
"status": 200,
"data": dataOut,
"message": "OK",
})
}
//查整个在线设备列表
func (dev *DCPhone10) getOnlineAll(c *gin.Context) {
type DataO struct {
Count int `json:"count"`
DevID []uint32 `json:"devId"`
Socket int `json:"socket"`
}
var dataOut DataO
//dataOut.DevID = make([]uint32,0,5000)
dev.ConnectMap.Range(func(k, _ interface{}) bool {
if d, ok := k.(uint32); ok { // 类型断言
dataOut.DevID = append(dataOut.DevID, d) //strconv.FormatUint(uint64(d),16))
dataOut.Count++
} else {
dev.ConnectMap.Delete(k)
}
return true
})
dataOut.Socket = dev.ConnSocketCount
c.JSON(http.StatusOK, gin.H{
"status": 200,
"data": dataOut,
"message": "OK",
})
}
// 主动关闭设备链接
func (dev *DCPhone10) putOnlineClose(c *gin.Context) {
type st struct {
DevID []uint32 `json:"devId"`
}
var data st
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "putOnlineClose"),
zap.Error(err))
}
type DataO struct {
Count int `json:"count"`
DevID map[uint32]bool `json:"devId"`
}
var dataOut DataO
dataOut.DevID = make(map[uint32]bool)
for _, id := range data.DevID {
if conn, ok := dev.ConnectMap.Load(id); ok {
if c, ok := conn.(*net.TCPConn); ok { // 类型断言
_ = c.Close()
} /*else { // 类型断言失败
}*/
dev.ConnectMap.Delete(id)
dataOut.Count++
dataOut.DevID[id] = true
} else {
dataOut.DevID[id] = false
}
}
c.JSON(http.StatusOK, gin.H{
"status": 200,
"data": dataOut,
"message": "OK",
})
}
// 以下为参数处理-----------------------------------------------------------------------------------------
//读取硬件设备参数
func (dev *DCPhone10) getDevPara(c *gin.Context) {
para := c.Param("paraName")
type st struct {
DevID []uint32 `json:"devId"`
}
var data st
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "getDevPara"),
zap.Error(err))
}
type DataO struct {
Count int `json:"count"`
DevID map[uint32]bool `json:"devId"`
}
var dataOut DataO
dataOut.DevID = make(map[uint32]bool)
returnState := 200
returnMsg := "OK"
if value, ok := httpParaNameMapString2Hex[para]; ok {
var sData tcplongserver.HexData
sData.CtrlCode = value
sData.Length = 0
for _, id := range data.DevID {
sData.DevID = id
if dev.TCPSend(&sData) == true {
dataOut.DevID[id] = true
} else {
dataOut.DevID[id] = false
}
}
} else {
returnState = 2001 //
returnMsg = para + ":参数未定义"
}
c.JSON(http.StatusOK, gin.H{
"status": returnState,
"data": dataOut,
"message": returnMsg,
})
}
// 设置硬件设备参数
func (dev *DCPhone10) setDevPara(c *gin.Context) {
returnState := 200
returnMsg := "OK"
type DataO struct {
Count int `json:"count"`
DevID map[uint32]bool `json:"devId"`
}
var dataOut DataO
dataOut.DevID = make(map[uint32]bool)
var sDevId []uint32
var sTcpData tcplongserver.HexData
sTcpData.Data = make([]byte, 255)
para := c.Param("paraName")
sTcpData.CtrlCode = httpParaNameMapString2Hex[para]
switch para {
case "tcp_server_addr":
var data paraTcpServerAddr
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "case \"tcp_server_addr\""),
zap.Error(err))
}
sTcpData.Data = []byte("\"" + data.Value.IP + "\"," + strconv.Itoa(int(data.Value.Port)))
sTcpData.Length = byte(len(sTcpData.Data))
sDevId = data.DevID
case "select_sim_module":
var data paraSelectSimModule
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "case \"select_sim_module\""),
zap.Error(err))
}
sTcpData.Data[0] = data.Value.Net<<1 | data.Value.Call
sTcpData.Length = 1
sDevId = data.DevID
case "heart":
var data paraHeart
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "case \"heart\""),
zap.Error(err))
}
sTcpData.Data[0] = byte(data.Value.Time)
sTcpData.Data[1] = byte(data.Value.Time >> 8)
sTcpData.Data[2] = data.Value.VoidCount
sTcpData.Length = 3
sDevId = data.DevID
case "beep_volume", "speech_volume", "speech_speed": //这些都是1个byte的参数
var data paraOneByte
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "case \"beep_volume\",\"speech_volume\",\"speech_speed\""),
zap.Error(err))
}
sTcpData.Data[0] = data.Value
sTcpData.Length = 1
sDevId = data.DevID
case "key_password", "online_dial", "update_firmware", "restart_device": //
var data paraOneString
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "case \"key_password\",\"online_dial\",\"update_firmware\",\"restart_device\""),
zap.Error(err))
}
sTcpData.Data = []byte(data.Value)
sTcpData.Length = byte(len(data.Value))
sDevId = data.DevID
case "work_time": // 工作时段
var data paraWorkTime
if err := c.ShouldBindJSON(&data); err != nil {
logger.Log.Error("c.ShouldBindJSON(&data)",
zap.String("Src", "case \"work_time\""),
zap.Error(err))
}
i := 0
for ; i < len(data.Value); i++ {
sTcpData.Data[0+i*6] = byte(data.Value[i].Start)
sTcpData.Data[1+i*6] = byte(data.Value[i].Start >> 8)
sTcpData.Data[2+i*6] = byte(data.Value[i].Stop)
sTcpData.Data[3+i*6] = byte(data.Value[i].Stop >> 8)
if data.Value[i].EnableCall {
sTcpData.Data[4+i*6] |= 1
} // 允许刷卡
if data.Value[i].CallIn {
sTcpData.Data[4+i*6] |= 1 << 1
} // 允许呼入
if data.Value[i].EnableKeyboard {
sTcpData.Data[4+i*6] |= 1 << 2
} // 允许键盘拨号
if data.Value[i].EnableMsg {
sTcpData.Data[4+i*6] |= 1 << 3
} // 允许留言
if data.Value[i].EnableSos {
sTcpData.Data[4+i*6] |= 1 << 4
} // 允许紧急呼叫
if len(data.Value[i].WeekDay) == 7 {
for j := 0; j < 7; j++ {
if data.Value[i].WeekDay[j] {
sTcpData.Data[5+i*6] |= 1 << j
}
}
} else {
returnState = 2801 //
returnMsg = para + ":week_day字段长度必须为7"
i = 0
break
}
}
sTcpData.Length = byte(i * 6)
sDevId = data.DevID
default:
returnState = 2001 //
returnMsg = para + ":参数未定义"
}
for _, id := range sDevId {
sTcpData.DevID = id
if dev.TCPSend(&sTcpData) == true {
dataOut.DevID[id] = true
} else {
dataOut.DevID[id] = false
}
}
c.JSON(http.StatusOK, gin.H{
"status": returnState,
"data": dataOut,
"message": returnMsg,
})
}
package devproduct
// const baseSwayUrl = "https://v3.biyingniao.com" // 配置文件
var httpParaNameMapString2Hex = map[string]byte{
// ***设备参数类***
"tcp_server_addr": 0x03, // 硬件连接tcp服务器地址端口
"heart": 0x04, // 心跳间隔次数 和 心跳间隔时间
"beep_volume": 0x05, // 蜂鸣器音量 0-100
"speech_volume": 0x06, // 通话音量 0-10
"speech_speed": 0x07, // 语速 0-9
"select_sim_module": 0x08, // 拨号卡选择
"work_time": 0x09, //工作时段
"key_password": 0x0a, // 最长10个字符(数字加*#)
// ***设备控制类***
"restart_device": 0x32, // 重启设备
"read_firmware_version": 0x70, // 读取固件版本
"update_firmware": 0x71, // 启动远程更新
"online_dial": 0x30, // 远程拨号
}
var httpParaNameMapHex2String = map[byte]string{
// ***设备参数类***
0x03 | 0x80: "para/tcp_server_addr", // 硬件连接tcp服务器地址端口
0x04 | 0x80: "para/heart", // 心跳间隔次数 和 心跳间隔时间
0x05 | 0x80: "para/beep_volume", // 蜂鸣器音量 0-100
0x06 | 0x80: "para/speech_volume", // 通话音量 0-10
0x07 | 0x80: "para/speech_speed", // 语速 0-9
0x08 | 0x80: "para/select_sim_module", // 拨号卡选择
0x09 | 0x80: "para/work_time", //工作时段
0x0a | 0x80: "para/key_password", // 最长10个字符(数字加*#)
// ***设备状态及控制类***
0x32 | 0x80: "ctrl/restart_device", // 重启设备 上下行均空
0x70 | 0x80: "ctrl/read_firmware_version", // 读取固件版本
0x71 | 0x80: "ctrl/update_firmware", // 启动远程更新
0x30 | 0x80: "ctrl/online_dial", // 远程拨号
0x3f: "ctrl/dev_restart_login", // 开机注册
0x41: "ctrl/dev_up_status", // 心跳上报状态
// ***设备使用类***
0x20: "usedevice/dev_get_family_num", // 查询亲情号码
0x23: "usedevice/dev_get_family_msg", // 查询留言
0x24: "usedevice/dev_read_family_msg", //上报已读留言
0x21: "usedevice/dev_get_call_time", // 获取自由拨号允许时长
0x22: "usedevice/dev_post_call_log", // 上报通话记录
}
// 以下其实可以封装成一个,然后value用interface, 但是可能是反射吧,这样用效率可能高些
type devUpRestartLogin struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
ResetReason byte `json:"reset_reason"`
Imei0 string `json:"imei_0"`
Iccid0 string `json:"iccid_0"`
Imei1 string `json:"imei_1"`
Iccid1 string `json:"iccid_1"`
Longitude string `json:"longitude"`
Latitude string `json:"latitude"`
FirmwareVersion string `json:"firmware_version"`
} `json:"value"`
}
type devUpFirmwareInfo struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
MD5 []byte `json:"md5"`
Length uint32 `json:"length"`
Version string `json:"version"`
} `json:"value"`
}
type devUpRespondUpdateFirmware struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
RespondUpdateFirmware bool `json:"respond_update_firmware"`
Version string `json:"version"`
MD5 []byte `json:"md5"` // 只有 espondUpdateFirmware == false 才有
Length uint32 `json:"length"` // 只有 RespondUpdateFirmware == false 才有
} `json:"value"`
}
type paraTcpServerAddr struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
IP string `json:"ip"`
Port uint16 `json:"port"`
} `json:"value"`
}
type paraSelectSimModule struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
Net byte `json:"net"` // 0/1
Call byte `json:"call"` // 0/1
} `json:"value"`
}
type paraHeart struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
Time uint16 `json:"time"` // 推荐60
VoidCount byte `json:"void_count"` // 推荐10
} `json:"value"`
}
type paraNoValue struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
}
type paraOneByte struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value byte `json:"value"`
}
type paraOneString struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value string `json:"value"`
}
type paraWorkTime struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value []struct {
Start uint16 `json:"start"`
Stop uint16 `json:"stop"`
EnableKeyboard bool `json:"enable_keyboard"`
CallIn bool `json:"call_in"`
EnableSos bool `json:"enable_sos"`
EnableCall bool `json:"enable_call"`
EnableMsg bool `json:"enable_msg"`
WeekDay []bool `json:"week_day"`
} `json:"value"`
}
package devproduct
import (
"encoding/json"
"go.uber.org/zap"
"jeff_workstation_1/jeffhttprequest"
"jeff_workstation_1/jeffutil"
"jeff_workstation_1/logger"
"jeff_workstation_1/mahonia"
"jeff_workstation_1/tcplongserver"
"strconv"
"strings"
)
type DCPhone10 struct {
tcplongserver.DCLongTCPHex
}
func (dev *DCPhone10) NewDCPhone10(password string, iv string, devType uint8) {
dev.InitNewDCLongTCPHex(password, iv, devType, dev.response)
}
//TCP收到的协议解析
func (dev *DCPhone10) response(data *tcplongserver.HexData) {
ctrlCode := data.CtrlCode
data.CtrlCode = 0
switch ctrlCode {
// 参数类 para
case 0x03 | 0x80: // "tcp_server_addr", // 硬件连接tcp服务器地址端口 //"\"water-tcp-short.dcrym.com\",8013"
if data.Length > 10 { // len(string(data.Data))
stringsTemp := strings.SplitN(string(data.Data)[1:], "\",", 2) // [1:data.Length]
ip := "error"
var port uint16
if len(stringsTemp) == 2 {
if p, err := strconv.ParseUint(stringsTemp[1], 10, 16); err == nil {
port = uint16(p)
ip = stringsTemp[0]
}
}
jsonStruct := paraTcpServerAddr{
data.TimeUtc,
[]uint32{data.DevID},
struct {
IP string `json:"ip"`
Port uint16 `json:"port"`
}{ip, port},
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x04 | 0x80: // "heart", // 心跳间隔次数 和 心跳间隔时间
if data.Length == 3 {
jsonStruct := paraHeart{
data.TimeUtc,
[]uint32{data.DevID},
struct {
Time uint16 `json:"time"` // 推荐60
VoidCount byte `json:"void_count"` // 推荐0
}{uint16(data.Data[0]) + (uint16(data.Data[1]) << 8), data.Data[2]},
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x05 | 0x80, 0x06 | 0x80, 0x07 | 0x80: //"beep_volume", // 蜂鸣器音量 0-100
// 0x06|0x80, //"speech_volume", // 通话音量 0-10
// 0x07|0x80:// "speech_speed", // 语速 0-9
if data.Length == 1 {
jsonStruct := paraOneByte{
data.TimeUtc,
[]uint32{data.DevID},
data.Data[0],
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x08 | 0x80:
if data.Length == 1 {
jsonStruct := paraSelectSimModule{
data.TimeUtc,
[]uint32{data.DevID},
struct {
Net byte `json:"net"` // 0/1
Call byte `json:"call"` // 0/1
}{0, 0},
}
if data.Data[0]|1 != 0 {
jsonStruct.Value.Call = 1
}
if data.Data[0]|2 != 0 {
jsonStruct.Value.Net = 1
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x09 | 0x80: // "work_time", //工作时段
groupNum := data.Length / 6
workTimeTemp := make([]struct {
Start uint16 `json:"start"`
Stop uint16 `json:"stop"`
EnableKeyboard bool `json:"enable_keyboard"`
CallIn bool `json:"call_in"`
EnableSos bool `json:"enable_sos"`
EnableCall bool `json:"enable_call"`
EnableMsg bool `json:"enable_msg"`
WeekDay []bool `json:"week_day"`
}, groupNum)
var i uint8
for i = 0; i < groupNum; i++ {
workTimeTemp[i].Start = uint16(data.Data[0+i*6]) + uint16(data.Data[1+i*6])<<8
workTimeTemp[i].Stop = uint16(data.Data[2+i*6]) + uint16(data.Data[3+i*6])<<8
if (data.Data[4+i*6] & 1) != 0 {
workTimeTemp[i].EnableCall = true
} // 允许刷卡
if (data.Data[4+i*6] & (1 << 1)) != 0 {
workTimeTemp[i].CallIn = true
} // 允许呼入
if (data.Data[4+i*6] & (1 << 2)) != 0 {
workTimeTemp[i].EnableKeyboard = true
} // 允许键盘拨号
if (data.Data[4+i*6] & (1 << 3)) != 0 {
workTimeTemp[i].EnableMsg = true
} // 允许留言
if (data.Data[4+i*6] & (1 << 4)) != 0 {
workTimeTemp[i].EnableSos = true
} // 允许紧急呼叫
workTimeTemp[i].WeekDay = make([]bool, 7)
for j := 0; j < 7; j++ {
if (data.Data[5+i*6] & (1 << j)) != 0 {
workTimeTemp[i].WeekDay[j] = true
}
}
//fmt.Println(workTimeTemp[i].WeekDay)
}
jsonStruct := paraWorkTime{
DevTime: data.TimeUtc,
DevID: []uint32{data.DevID},
}
jsonStruct.Value = workTimeTemp
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
case 0x0a | 0x80: // "key_password", // 最长10个字符(数字加*#)
jsonStruct := paraOneString{
data.TimeUtc,
[]uint32{data.DevID},
string(data.Data),
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
// 设备控制类ctrl
case 0x32 | 0x80: // 0x32|0x80:"ctrl/restart_device", // 重启设备 上下行均空
jsonStruct := paraNoValue{
data.TimeUtc,
[]uint32{data.DevID},
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
case 0x70 | 0x80: // 0x70|0x80:"ctrl/read_firmware_version", // 读取固件版本
if data.Length > 22 {
jsonStruct := devUpFirmwareInfo{
data.TimeUtc,
[]uint32{data.DevID},
struct {
MD5 []byte `json:"md5"`
Length uint32 `json:"length"`
Version string `json:"version"`
}{
data.Data[0:16],
uint32(data.Data[16]) + (uint32(data.Data[17]) << 8) + (uint32(data.Data[18]) << 16) + (uint32(data.Data[19]) << 24),
string(data.Data[20:]),
},
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x71 | 0x80: // "ctrl/update_firmware", // 启动远程更新
if data.Length > 2 {
jsonStruct := devUpRespondUpdateFirmware{
DevTime: data.TimeUtc,
DevID: []uint32{data.DevID},
}
if data.Data[0] == 1 {
jsonStruct.Value.RespondUpdateFirmware = true
jsonStruct.Value.Version = string(data.Data[1 : data.Length-1])
} else if data.Data[0] == 2 && data.Length > 23 {
jsonStruct.Value.MD5 = data.Data[1:17]
jsonStruct.Value.Length = uint32(data.Data[17]) + (uint32(data.Data[18]) << 8) + (uint32(data.Data[19]) << 16) + (uint32(data.Data[20]) << 24)
jsonStruct.Value.Version = string(data.Data[20:])
} else {
logger.Log.Error("data.Data error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("data.Data[0]", data.Data[0]),
zap.Uint8s("RecvData", data.Data))
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x30 | 0x80:
type AutoGenerated struct {
DevTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
Result byte `json:"result"`
Number string `json:"number"`
} `json:"value"`
}
jsonStruct := AutoGenerated{
data.TimeUtc,
[]uint32{data.DevID},
struct {
Result byte `json:"result"`
Number string `json:"number"`
}{
data.Data[0],
string(data.Data[1:]),
},
}
x, _ := json.Marshal(jsonStruct)
_, _ = jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x)
case 0x3f: // 0x3f:"ctrl/dev_restart_login",// 开机注册
if data.Length > 75 {
jsonStruct := devUpRestartLogin{
DevTime: data.TimeUtc,
DevID: []uint32{data.DevID},
}
jsonStruct.Value.ResetReason = data.Data[0] // test
jsonStruct.Value.Imei0 = string(data.Data[1:16]) //从索引1到索引16(不包含)
jsonStruct.Value.Iccid0 = string(data.Data[16:36])
jsonStruct.Value.Imei1 = string(data.Data[36:51])
jsonStruct.Value.Iccid1 = string(data.Data[51:71])
strTemp := strings.Split(string(data.Data[71:]), "-") //data.Data[71:data.Length]
if len(strTemp) == 3 {
jsonStruct.Value.Longitude = strTemp[0]
jsonStruct.Value.Latitude = strTemp[1]
jsonStruct.Value.FirmwareVersion = strTemp[2]
}
x, _ := json.Marshal(jsonStruct)
if result, err := jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x); err == nil {
type AutoGenerated struct {
Message string `json:"message"`
Status int `json:"status"`
}
var jStruct AutoGenerated
if json.Unmarshal(result, &jStruct) == nil && jStruct.Status == 200 { // 收到服务器的正确响应,则返回给终端收到开机注册
data.CtrlCode = ctrlCode | 0x80
data.Length = 0
} else {
logger.Log.Error("json.Unmarshal err OR jStruct.Status != 200",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)),
zap.Int("Status", jStruct.Status))
}
}
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x41: // "ctrl/dev_up_status",// 心跳上报状态
if data.Length > 2 { // 至少3个字节
type AutoGenerated struct {
DevSendTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
Csq0 byte `json:"csq0"`
Csq1 byte `json:"csq1"`
EnableKeyboard bool `json:"enable_keyboard"`
CallIn bool `json:"call_in"`
EnableSos bool `json:"enable_sos"`
EnableCall bool `json:"enable_call"`
EnableMsg bool `json:"enable_msg"`
CallMoudleStatus byte `json:"call_moudle_status"`
DevErrorCode byte `json:"dev_error_code"`
} `json:"value"`
}
jsonStruct := AutoGenerated{
DevSendTime: data.TimeUtc,
DevID: []uint32{data.DevID},
}
jsonStruct.Value.Csq0 = data.Data[0]
jsonStruct.Value.Csq1 = data.Data[1]
for i := 0; i < 5; i++ {
if (data.Data[2] & 1) != 0 {
jsonStruct.Value.EnableCall = true
} // 允许刷卡
if (data.Data[2] & (1 << 1)) != 0 {
jsonStruct.Value.CallIn = true
} // 允许呼入
if (data.Data[2] & (1 << 2)) != 0 {
jsonStruct.Value.EnableKeyboard = true
} // 允许键盘拨号
if (data.Data[2] & (1 << 3)) != 0 {
jsonStruct.Value.EnableMsg = true
} // 允许留言
if (data.Data[2] & (1 << 4)) != 0 {
jsonStruct.Value.EnableSos = true
} // 允许紧急呼叫
}
if data.Length > 3 {
jsonStruct.Value.CallMoudleStatus = data.Data[3]
} else {
jsonStruct.Value.CallMoudleStatus = 100
}
if data.Length > 4 {
jsonStruct.Value.DevErrorCode = data.Data[4]
}
x, _ := json.Marshal(jsonStruct)
if result, err := jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x); err == nil {
type AutoGenerated struct {
Message string `json:"message"`
Status int `json:"status"`
}
var jStruct AutoGenerated
if json.Unmarshal(result, &jStruct) == nil && jStruct.Status == 200 { // 收到服务器的正确响应,则返回给终端收到
data.CtrlCode = ctrlCode | 0x80
data.Length = 0
} else {
logger.Log.Error("json.Unmarshal err OR jStruct.Status != 200",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)),
zap.Int("Status", jStruct.Status))
}
}
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
//设备使用类 usedevice
case 0x20: // "usedevice/dev_get_family_num",// 查询亲情号码
if data.Length == 5 {
type AutoGenerated struct {
DevSendTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
Page byte `json:"page"`
CardUID uint32 `json:"card_uid"`
} `json:"value"`
}
jsonStruct := AutoGenerated{
data.TimeUtc,
[]uint32{data.DevID},
struct {
Page byte `json:"page"`
CardUID uint32 `json:"card_uid"`
}{
data.Data[0],
uint32(data.Data[1]) + (uint32(data.Data[2]) << 8) + (uint32(data.Data[3]) << 16) + (uint32(data.Data[4]) << 24),
},
}
x, _ := json.Marshal(jsonStruct)
if result, err := jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x); err == nil {
type AutoGenerated struct {
Data struct {
Total byte `json:"total"`
Value []struct {
Number string `json:"number"`
Time int `json:"time"`
Name string `json:"name"`
} `json:"value"`
} `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}
enc := mahonia.NewEncoder("gbk")
var jStruct AutoGenerated
if json.Unmarshal(result, &jStruct) != nil {
logger.Log.Error("json.Unmarshal err",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)))
return
}
tempData := []byte{data.Data[1], data.Data[2], data.Data[3], data.Data[4]}
if jStruct.Status == 200 { // 收到服务器的正确响应,则返回给终端收到开机注册
data.Data = make([]byte, 255)
data.Data[0] = tempData[0] //4字节uid
data.Data[1] = tempData[1]
data.Data[2] = tempData[2]
data.Data[3] = tempData[3]
data.Data[4] = jStruct.Data.Total //亲情号总数
data.Length = 5
for i := 0; i < 4 && i < len(jStruct.Data.Value); i++ { //
if i != 0 {
data.Data[data.Length] = '-'
data.Length++
}
if len(jStruct.Data.Value[i].Number) < 17 {
data.Length += byte(copy(data.Data[data.Length:], jStruct.Data.Value[i].Number))
}
data.Data[data.Length] = '_'
data.Length++
data.Length += byte(copy(data.Data[data.Length:], strconv.Itoa(jStruct.Data.Value[i].Time)))
data.Data[data.Length] = '_'
data.Length++
jStruct.Data.Value[i].Name = jeffutil.DBCtoSBC(jStruct.Data.Value[i].Name) //全角转半角
jStruct.Data.Value[i].Name = enc.ConvertString(jStruct.Data.Value[i].Name) //转成GBK
if len(jStruct.Data.Value[i].Name) < 17 {
data.Length += byte(copy(data.Data[data.Length:], jStruct.Data.Value[i].Name))
}
}
data.CtrlCode = ctrlCode | 0x80
} else if jStruct.Status == 0 { // 收到服务器的异常响应,则返回给终端收到的msg
data.Data = make([]byte, 255)
data.Data[0] = tempData[0] //4字节uid
data.Data[1] = tempData[1]
data.Data[2] = tempData[2]
data.Data[3] = tempData[3]
data.Data[4] = 0xff //亲情号总数
data.Length = 5
jStruct.Message = enc.ConvertString(jStruct.Message) //转成GBK
if len(jStruct.Message) < 251 {
data.Length += byte(copy(data.Data[5:], jStruct.Message))
}
data.CtrlCode = ctrlCode | 0x80
} else {
logger.Log.Error("Status != 0 or 200",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)),
zap.Int("Status", jStruct.Status))
}
}
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x23: // 0x23:"usedevice/dev_get_family_msg",// 查询留言
if data.Length == 4 {
type AutoGenerated struct {
DevSendTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value uint32 `json:"value"`
}
jsonStruct := AutoGenerated{
data.TimeUtc,
[]uint32{data.DevID},
uint32(data.Data[0]) + (uint32(data.Data[1]) << 8) + (uint32(data.Data[2]) << 16) + (uint32(data.Data[3]) << 24),
}
x, _ := json.Marshal(jsonStruct)
if result, err := jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x); err == nil {
type AutoGenerated struct {
Data struct {
Unread byte `json:"unread"`
UserMessage string `json:"user_message"`
MessageID uint32 `json:"message_id"`
} `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}
var jStruct AutoGenerated
if json.Unmarshal(result, &jStruct) != nil {
logger.Log.Error("json.Unmarshal err",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)))
return
}
enc := mahonia.NewEncoder("gbk")
tempData := []byte{data.Data[0], data.Data[1], data.Data[2], data.Data[3]}
// test
// data.Data = make([]byte, 255)
// data.Data[0] = tempData[0] //4字节uid
// data.Data[1] = tempData[1]
// data.Data[2] = tempData[2]
// data.Data[3] = tempData[3]
// data.Data[4] = 88 //未读留言总数
// data.Data[5] = 123 //留言ID
// data.Data[6] = 0 //留言ID
// data.Data[7] = 0 //留言ID
// data.Data[8] = 0 //留言ID
// data.Length = 9
// testMsg := ",!!,,,随着烽!火岁月离我们,,渐渐远去,那些经历过战争的老兵们也,,在慢慢凋零。他们说自己不是英雄,但他们与英雄并肩战斗过!一段段回忆编织成宝贵的精神财富!:。。。*123321abc+-%、、、"
// testMsg = jeffutil.DBCtoSBC(testMsg) //全角转半角
// jStruct.Data.UserMessage = enc.ConvertString(testMsg) //转成GBK
// if len(jStruct.Data.UserMessage) < 247 {
// data.Length += byte(copy(data.Data[9:], jStruct.Data.UserMessage))
// }
// data.CtrlCode = ctrlCode | 0x80
// test end
if jStruct.Status == 200 { // 收到服务器的正确响应,则返回给终端收到开机注册
data.Data = make([]byte, 255)
data.Data[0] = tempData[0] //4字节uid
data.Data[1] = tempData[1]
data.Data[2] = tempData[2]
data.Data[3] = tempData[3]
data.Data[4] = jStruct.Data.Unread //未读留言总数
data.Data[5] = byte(jStruct.Data.MessageID) //留言ID
data.Data[6] = byte(jStruct.Data.MessageID >> 8) //留言ID
data.Data[7] = byte(jStruct.Data.MessageID >> 16) //留言ID
data.Data[8] = byte(jStruct.Data.MessageID >> 24) //留言ID
data.Length = 9
jStruct.Data.UserMessage = jeffutil.DBCtoSBC(jStruct.Data.UserMessage) //全角转半角
jStruct.Data.UserMessage = enc.ConvertString(jStruct.Data.UserMessage) //转成GBK
if len(jStruct.Data.UserMessage) < 247 {
data.Length += byte(copy(data.Data[9:], jStruct.Data.UserMessage))
}
data.CtrlCode = ctrlCode | 0x80
} else if jStruct.Status == 0 { // 收到服务器的异常响应,则返回给终端收到的msg
data.Data = make([]byte, 255)
data.Data[0] = tempData[0] //4字节uid
data.Data[1] = tempData[1]
data.Data[2] = tempData[2]
data.Data[3] = tempData[3] //
data.Data[3] = tempData[3] //
data.Data[4] = 0xff
data.Length = 5
jStruct.Message = enc.ConvertString(jStruct.Message) //转成GBK
if len(jStruct.Message) < 251 {
data.Length += byte(copy(data.Data[5:], jStruct.Message))
}
data.CtrlCode = ctrlCode | 0x80
} else {
logger.Log.Error("Status != 0 or 200",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)),
zap.Int("Status", jStruct.Status))
}
}
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x24: // 上报已读留言
if data.Length == 8 {
type AutoGenerated struct {
DevSendTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
MessageID uint32 `json:"message_id"`
CardUID uint32 `json:"card_uid"`
} `json:"value"`
}
jsonStruct := AutoGenerated{
data.TimeUtc,
[]uint32{data.DevID},
struct {
MessageID uint32 `json:"message_id"`
CardUID uint32 `json:"card_uid"`
}{
uint32(data.Data[4]) + (uint32(data.Data[5]) << 8) + (uint32(data.Data[6]) << 16) + (uint32(data.Data[7]) << 24),
uint32(data.Data[0]) + (uint32(data.Data[1]) << 8) + (uint32(data.Data[2]) << 16) + (uint32(data.Data[3]) << 24),
},
}
x, _ := json.Marshal(jsonStruct)
if result, err := jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x); err == nil {
type AutoGenerated struct {
Message string `json:"message"`
Status int `json:"status"`
}
var jStruct AutoGenerated
if json.Unmarshal(result, &jStruct) == nil && jStruct.Status == 200 { // 收到服务器的正确响应,则返回给终端收到
data.CtrlCode = ctrlCode | 0x80
} else {
logger.Log.Error("json.Unmarshal err OR jStruct.Status != 200",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)),
zap.Int("Status", jStruct.Status))
}
}
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x21: // 0x21:"usedevice/dev_get_call_time",// 获取自由拨号允许时长
if data.Length > 4 {
type AutoGenerated struct {
DevSendTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
CardUID uint32 `json:"card_uid"`
Number string `json:"number"`
} `json:"value"`
}
jsonStruct := AutoGenerated{
data.TimeUtc,
[]uint32{data.DevID},
struct {
CardUID uint32 `json:"card_uid"`
Number string `json:"number"`
}{
uint32(data.Data[0]) + (uint32(data.Data[1]) << 8) + (uint32(data.Data[2]) << 16) + (uint32(data.Data[3]) << 24),
string(data.Data[4:]),
},
}
x, _ := json.Marshal(jsonStruct)
tempCard := []byte{data.Data[0], data.Data[1], data.Data[2], data.Data[3]}
tempNum := make([]byte, data.Length-4)
copy(tempNum, data.Data[4:])
if result, err := jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x); err == nil {
type AutoGenerated struct {
Data byte `json:"data"`
Message string `json:"message"`
Status int `json:"status"`
}
var jStruct AutoGenerated
if json.Unmarshal(result, &jStruct) != nil {
logger.Log.Error("json.Unmarshal err",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)))
return
}
data.Data = make([]byte, 255)
data.Data[0] = tempCard[0]
data.Data[1] = tempCard[1]
data.Data[2] = tempCard[2]
data.Data[3] = tempCard[3]
data.Data[4] = jStruct.Data //可用分钟数
data.Length = 5
//if len(jStruct.Data.Number) < 17 {
data.Length += byte(copy(data.Data[5:], tempNum))
//} else {
// log.WithFields(log.Fields{
// "Src": "TCP-SERVER-response",
// "CtrlCode": ctrlCode,
// "RecvData": data,
// "Req": string(x),
// "Resp": string(result),
// }).Errorln("phone num lenth > 16:",len(jStruct.Data.Number))
//}
data.CtrlCode = ctrlCode | 0x80
if jStruct.Status == 0 { // 收到服务器的异常响应,则返回给终端收到的msg
data.Data[data.Length] = '_'
data.Length++
enc := mahonia.NewEncoder("gbk")
jStruct.Message = enc.ConvertString(jStruct.Message) //转成GBK
if len(jStruct.Message) < 256-int(data.Length) {
data.Length += byte(copy(data.Data[data.Length:], jStruct.Message))
}
} else if jStruct.Status != 200 {
logger.Log.Error("Status != 0 or 200",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)),
zap.Int("Status", jStruct.Status))
}
}
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0x22: // 0x22:"usedevice/dev_post_call_log",// 上报通话记录
if data.Length > 10 {
type AutoGenerated struct {
DevSendTime uint32 `json:"dev_send_time"`
DevID []uint32 `json:"devId"`
Value struct {
CardUID uint32 `json:"message_id"`
StartTime uint32 `json:"start_time"`
TalkTime uint16 `json:"talk_time"`
Number string `json:"number"`
} `json:"value"`
}
jsonStruct := AutoGenerated{
data.TimeUtc,
[]uint32{data.DevID},
struct {
CardUID uint32 `json:"message_id"`
StartTime uint32 `json:"start_time"`
TalkTime uint16 `json:"talk_time"`
Number string `json:"number"`
}{
uint32(data.Data[0]) + (uint32(data.Data[1]) << 8) + (uint32(data.Data[2]) << 16) + (uint32(data.Data[3]) << 24),
uint32(data.Data[4]) + (uint32(data.Data[5]) << 8) + (uint32(data.Data[6]) << 16) + (uint32(data.Data[7]) << 24),
uint16(data.Data[8]) + (uint16(data.Data[9]) << 8),
string(data.Data[10:]),
},
}
x, _ := json.Marshal(jsonStruct)
if result, err := jeffhttprequest.Post(jeffutil.HttpClientBaseUrl+httpParaNameMapHex2String[ctrlCode], x); err == nil {
type AutoGenerated struct {
Message string `json:"message"`
Status int `json:"status"`
}
var jStruct AutoGenerated
if json.Unmarshal(result, &jStruct) == nil && jStruct.Status == 200 { // 收到服务器的正确响应,则返回给终端收到
data.CtrlCode = ctrlCode | 0x80
} else {
logger.Log.Error("json.Unmarshal err OR jStruct.Status != 200",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data),
zap.String("Req", string(x)),
zap.String("Resp", string(result)),
zap.Int("Status", jStruct.Status))
}
}
} else {
logger.Log.Error("data.Length error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
case 0xff: // 硬件被动上报异常
logger.Log.Warn("dev up error 0xff",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
default:
logger.Log.Error("ctrlCode error",
zap.String("Src", "TCP-SERVER-response"),
zap.Uint8("CtrlCode", ctrlCode),
zap.Uint8("DataLen", data.Length),
zap.Uint8s("RecvData", data.Data))
}
}
File added
module jeff_workstation_1
go 1.16
require (
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/gin-gonic/gin v1.7.2 // indirect
github.com/go-playground/validator/v10 v10.7.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lestrrat-go/strftime v1.0.5 // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.13 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/ugorji/go v1.2.6 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
go.uber.org/zap v1.18.1 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
golang.org/x/text v0.3.6 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
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/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.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
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/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.7.0 h1:gLi5ajTBBheLNt0ctewgq7eolXoDALQd5/y90Hh9ZgM=
github.com/go-playground/validator/v10 v10.7.0/go.mod h1:xm76BBt941f7yWdGnI2DVPFFg1UK3YY04qifoXU3lOk=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.0.5 h1:A7H3tT8DhTz8u65w+JRpiBxM4dINQhUXAZnhBa2xeOE=
github.com/lestrrat-go/strftime v1.0.5/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g=
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA=
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
package jeffhttprequest
import (
"bytes"
"go.uber.org/zap"
"io/ioutil"
"jeff_workstation_1/jeffutil"
"jeff_workstation_1/logger"
"net/http"
"time"
)
// Post 发送POST请求
func Post(url string, jsonStr []byte) ([]byte, error) { //直接传BYTE,因为我不知道interface是不是反射,可能影响性能
//jsonStr, _ := json.Marshal(data)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
if err != nil {
logger.Log.Error("req.Header.Add(\"content-type\", \"application/json\")",
zap.String("Src", "HTTP-CLIENT-POST"),
zap.String("Url", url),
zap.Error(err),
zap.ByteString("Req", jsonStr))
return nil, err
}
defer req.Body.Close()
req.Header.Add("content-type", "application/json")
client := &http.Client{Timeout: jeffutil.HttpClientTimeOut}
startTime := time.Now().UnixNano() // time.Now()
resp, err2 := client.Do(req)
spendTime := time.Now().UnixNano() - startTime // spendTime := fmt.Sprintf("%d ms", (time.Since(startTime).Nanoseconds()+500000)/1000000.0)
if err2 != nil {
logger.Log.Error("client.Do(req)",
zap.String("Src", "HTTP-CLIENT-POST"),
zap.String("Url", url),
zap.Int64("SpendNanoS", spendTime),
zap.Error(err2),
zap.ByteString("Req", jsonStr))
return nil, err2
}
defer resp.Body.Close()
// client.CloseIdleConnections()
result, _ := ioutil.ReadAll(resp.Body)
// result, _ := ioutil.ReadAll(transform.NewReader(resp.Body, simplifiedchinese.GBK.NewEncoder()))
//enc := mahonia.NewEncoder("gbk")
//ret := enc.ConvertString(string(result))
//test,_ := ioutil.ReadAll(transform.NewReader(bytes.NewReader([]byte(ret)), simplifiedchinese.GBK.NewEncoder()))
logger.Log.Info(string(result),
zap.String("Src", "HTTP-CLIENT-POST"),
zap.Int64("SpendNanoS", spendTime),
zap.String("Url", url),
zap.ByteString("Req", jsonStr))
//return []byte(ret),nil
return result, nil
}
//发送GET请求
//func Get(url string, jsonStr []byte) ([]byte, error) {
// client := http.Client{Timeout: jeffutil.HttpClientTimeOut}
// startTime := time.Now().UnixNano()// time.Now()
// resp, error := client.Get(url)
// spendTime := time.Now().UnixNano() - startTime
// if error != nil {
// log.WithFields(log.Fields{
// "Src": "HTTP-CLIENT-GET",
// "Url": url,
// "Err": error,
// }).Errorln("client.Get(url)")
// return nil,error
// }
// defer resp.Body.Close()
//
// var buffer [512]byte
// result := bytes.NewBuffer(nil)
// for {
// n, err := resp.Body.Read(buffer[0:])
// result.Write(buffer[0:n])
// if err != nil{
// if err == io.EOF {
// break
// } else {
// log.WithFields(log.Fields{
// "Src": "HTTP-CLIENT-GET",
// "Url": url,
// "Err": err,
// "RespStatus": resp.Status,
// }).Errorln("resp.Body.Read(buffer[0:])")
// return nil,err
// }
// }
// }
//
// resultString := result.Bytes()
//
// // httpClientLogger.Infoln("[GET]",spendTime,"mS-",url,"-",resultString)
// log.WithFields(log.Fields{
// "Src": "HTTP-CLIENT-GET",
// "SpendNanoS":spendTime,
// "Url": url,
// "RespStatus": resp.Status,
// }).Infoln(resultString)
//
// return resultString,nil
//}
File added
package jeffutil
// 全角转换半角
func DBCtoSBC(s string) string {
retstr := ""
for _, i := range s {
inside_code := i
if inside_code == 12288 {
inside_code = 32
} else {
inside_code -= 65248
}
if inside_code < 32 || inside_code > 126 {
retstr += string(i)
} else {
retstr += string(inside_code)
}
}
return retstr
}
//import (
// "sort"
// "strings"
//)
//
//type dict struct {
// x, y rune
//}
//
//var toSBC = []dict{
// {0x00A2, 0xFFE0},
// {0x00A3, 0xFFE1},
// {0x00A5, 0xFFE5},
// {0x00A6, 0xFFE4},
// {0x00AC, 0xFFE2},
// {0x00AF, 0xFFE3},
// {0xFF61, 0x3002},
// {0xFF62, 0x300C},
// {0xFF63, 0x300D},
// {0xFF64, 0x3001},
// {0xFF65, 0x30FB},
// {0xFF66, 0x30F2},
// {0xFF67, 0x30A1},
// {0xFF68, 0x30A3},
// {0xFF69, 0x30A5},
// {0xFF6A, 0x30A7},
// {0xFF6B, 0x30A9},
// {0xFF6C, 0x30E3},
// {0xFF6D, 0x30E5},
// {0xFF6E, 0x30E7},
// {0xFF6F, 0x30C3},
// {0xFF70, 0x30FC},
// {0xFF71, 0x30A2},
// {0xFF72, 0x30A4},
// {0xFF73, 0x30A6},
// {0xFF74, 0x30A8},
// {0xFF75, 0x30AA},
// {0xFF76, 0x30AB},
// {0xFF77, 0x30AD},
// {0xFF78, 0x30AF},
// {0xFF79, 0x30B1},
// {0xFF7A, 0x30B3},
// {0xFF7B, 0x30B5},
// {0xFF7C, 0x30B7},
// {0xFF7D, 0x30B9},
// {0xFF7E, 0x30BB},
// {0xFF7F, 0x30BD},
// {0xFF80, 0x30BF},
// {0xFF81, 0x30C1},
// {0xFF82, 0x30C4},
// {0xFF83, 0x30C6},
// {0xFF84, 0x30C8},
// {0xFF85, 0x30CA},
// {0xFF86, 0x30CB},
// {0xFF87, 0x30CC},
// {0xFF88, 0x30CD},
// {0xFF89, 0x30CE},
// {0xFF8A, 0x30CF},
// {0xFF8B, 0x30D2},
// {0xFF8C, 0x30D5},
// {0xFF8D, 0x30D8},
// {0xFF8E, 0x30DB},
// {0xFF8F, 0x30DE},
// {0xFF90, 0x30DF},
// {0xFF91, 0x30E0},
// {0xFF92, 0x30E1},
// {0xFF93, 0x30E2},
// {0xFF94, 0x30E4},
// {0xFF95, 0x30E6},
// {0xFF96, 0x30E8},
// {0xFF97, 0x30E9},
// {0xFF98, 0x30EA},
// {0xFF99, 0x30EB},
// {0xFF9A, 0x30EC},
// {0xFF9B, 0x30ED},
// {0xFF9C, 0x30EF},
// {0xFF9D, 0x30F3},
// {0xFF9E, 0x309B},
// {0xFF9F, 0x309C},
// {0xFFA0, 0x3164},
// {0xFFC2, 0x314F},
// {0xFFC3, 0x3150},
// {0xFFC4, 0x3151},
// {0xFFC5, 0x3152},
// {0xFFC6, 0x3153},
// {0xFFC7, 0x3154},
// {0xFFCA, 0x3155},
// {0xFFCB, 0x3156},
// {0xFFCC, 0x3157},
// {0xFFCD, 0x3158},
// {0xFFCE, 0x3159},
// {0xFFCF, 0x315A},
// {0xFFD2, 0x315B},
// {0xFFD3, 0x315C},
// {0xFFD4, 0x315D},
// {0xFFD5, 0x315E},
// {0xFFD6, 0x315F},
// {0xFFD7, 0x3160},
// {0xFFDA, 0x3161},
// {0xFFDB, 0x3162},
// {0xFFDC, 0x3163},
// {0xFFE8, 0x2502},
// {0xFFE9, 0x2190},
// {0xFFEA, 0x2191},
// {0xFFEB, 0x2192},
// {0xFFEC, 0x2193},
// {0xFFED, 0x25A0},
// {0xFFEE, 0x25CB},
//}
//
//var toDBC = []dict{
// {0x2190, 0xFFE9},
// {0x2191, 0xFFEA},
// {0x2192, 0xFFEB},
// {0x2193, 0xFFEC},
// {0x3000, 0x0020},
// {0x3001, 0xFF64},
// {0x3002, 0xFF61},
// {0x300C, 0xFF62},
// {0x300D, 0xFF63},
// {0x309B, 0xFF9E},
// {0x309C, 0xFF9F},
// {0x30A1, 0xFF67},
// {0x30A2, 0xFF71},
// {0x30A3, 0xFF68},
// {0x30A4, 0xFF72},
// {0x30A5, 0xFF69},
// {0x30A6, 0xFF73},
// {0x30A7, 0xFF6A},
// {0x30A8, 0xFF74},
// {0x30A9, 0xFF6B},
// {0x30AA, 0xFF75},
// {0x30AB, 0xFF76},
// {0x30AD, 0xFF77},
// {0x30AF, 0xFF78},
// {0x30B1, 0xFF79},
// {0x30B3, 0xFF7A},
// {0x30B5, 0xFF7B},
// {0x30B7, 0xFF7C},
// {0x30B9, 0xFF7D},
// {0x30BB, 0xFF7E},
// {0x30BD, 0xFF7F},
// {0x30BF, 0xFF80},
// {0x30C1, 0xFF81},
// {0x30C3, 0xFF6F},
// {0x30C4, 0xFF82},
// {0x30C6, 0xFF83},
// {0x30C8, 0xFF84},
// {0x30CA, 0xFF85},
// {0x30CB, 0xFF86},
// {0x30CC, 0xFF87},
// {0x30CD, 0xFF88},
// {0x30CE, 0xFF89},
// {0x30CF, 0xFF8A},
// {0x30D2, 0xFF8B},
// {0x30D5, 0xFF8C},
// {0x30D8, 0xFF8D},
// {0x30DB, 0xFF8E},
// {0x30DE, 0xFF8F},
// {0x30DF, 0xFF90},
// {0x30E0, 0xFF91},
// {0x30E1, 0xFF92},
// {0x30E2, 0xFF93},
// {0x30E3, 0xFF6C},
// {0x30E4, 0xFF94},
// {0x30E5, 0xFF6D},
// {0x30E6, 0xFF95},
// {0x30E7, 0xFF6E},
// {0x30E8, 0xFF96},
// {0x30E9, 0xFF97},
// {0x30EA, 0xFF98},
// {0x30EB, 0xFF99},
// {0x30EC, 0xFF9A},
// {0x30ED, 0xFF9B},
// {0x30EF, 0xFF9C},
// {0x30F2, 0xFF66},
// {0x30F3, 0xFF9D},
// {0x30FB, 0xFF65},
// {0x30FC, 0xFF70},
// {0x314F, 0xFFC2},
// {0x3150, 0xFFC3},
// {0x3151, 0xFFC4},
// {0x3152, 0xFFC5},
// {0x3153, 0xFFC6},
// {0x3154, 0xFFC7},
// {0x3155, 0xFFCA},
// {0x3156, 0xFFCB},
// {0x3157, 0xFFCC},
// {0x3158, 0xFFCD},
// {0x3159, 0xFFCE},
// {0x315A, 0xFFCF},
// {0x315B, 0xFFD2},
// {0x315C, 0xFFD3},
// {0x315D, 0xFFD4},
// {0x315E, 0xFFD5},
// {0x315F, 0xFFD6},
// {0x3160, 0xFFD7},
// {0x3161, 0xFFDA},
// {0x3162, 0xFFDB},
// {0x3163, 0xFFDC},
// {0x3164, 0xFFA0},
// {0xFF5F, 0x2985},
// {0xFF60, 0x2986},
// {0xFFE0, 0x00A2},
// {0xFFE1, 0x00A3},
// {0xFFE2, 0x00AC},
// {0xFFE3, 0x00AF},
// {0xFFE4, 0x00A6},
// {0xFFE5, 0x00A5},
// {0xFFE6, 0x20A9},
//}
//
//// 从strings包拷贝,因此不必导入strings包即可使用本函数。
//var Map = strings.Map
//
//// 判断一个字符是否是半角字符
//func IsSBC(c rune) bool {
// switch {
// case c <= 0x007E:
// case c == 0x00A2 || c == 0x00A3:
// case c == 0x00A5 || c == 0x00A6:
// case c == 0x00AC || c == 0x00AF:
// case c == 0x20A9:
// case c == 0x2985 || c == 0x2986:
// case c >= 0xFF61 && c <= 0xFF9F:
// case c >= 0xFFA0 && c <= 0xFFBE:
// case c >= 0xFFC2 && c <= 0xFFC7:
// case c >= 0xFFCA && c <= 0xFFCF:
// case c >= 0xFFD2 && c <= 0xFFD7:
// case c >= 0xFFDA && c <= 0xFFDC:
// case c >= 0xFFE8 && c <= 0xFFEE:
// default:
// return false
// }
// return true
//}
//
//// 如果字符c为全角字符,返回对应半角字符(如有);否则返回c。
//func ToDBC(c rune) rune {
// switch {
// case c <= 0x218F:
// return c
// case c <= 0x2193:
// case c == 0x2502:
// return 0xFFE8
// case c == 0x25A0:
// return 0xFFED
// case c == 0x25CB:
// return 0xFFEE
// case c <= 0x2FFF:
// return c
// case c <= 0x30FC:
// case c <= 0x3130:
// return c
// case c <= 0x314E:
// return c + 0xCE70
// case c <= 0x3164:
// case c <= 0xFF00:
// return c
// case c <= 0xFF5E:
// return c - 0xFEE0
// case c >= 0xFFE7:
// return c
// }
// i := sort.Search(len(toDBC), func(i int) bool { return toDBC[i].x >= c })
// if toDBC[i].x == c {
// return toDBC[i].y
// } else {
// return c
// }
//}
//
//// 如果字符c为半角字符,返回对应全角字符(如有);否则返回c。
//func ToSBC(c rune) rune {
// switch {
// case c <= 0x001F:
// return c
// case c == 0x0020:
// return 0x3000
// case c <= 0x007E:
// return c + 0xFEE0
// case c <= 0x00AF:
// case c == 0x20A9:
// return 0xFFE6
// case c == 0x2985:
// return 0xFF5F
// case c == 0x2986:
// return 0xFF60
// case c <= 0xFF60:
// return c
// case c <= 0xFFA0:
// case c <= 0xFFBE:
// return c - 0xCE70
// case c >= 0xFFEF:
// return c
// }
// i := sort.Search(len(toSBC), func(i int) bool { return toSBC[i].x >= c })
// if toSBC[i].x == c {
// return toSBC[i].y
// } else {
// return c
// }
//}
//
//// 如果字符c为全角ASCII字符,返回对应的半角字符;否则返回c。
//func ToASCIIDBC(r rune) rune {
// if r == 0x3000 {
// return 0x3000
// }
// if r >= 0xFF01 && r <= 0xFF5E {
// return r - 0xFEE0
// }
// return r
//}
//
//// 如果字符c为半角ASCII字符,返回对应的全角字符;否则返回c。
//func ToASCIISBC(r rune) rune {
// if r == 0x0020 {
// return 0x3000
// }
// if r >= 0x0021 && r <= 0x007E {
// return r + 0xFEE0
// }
// return r
//}
package jeffutil
func CheckCRC(buf []byte) bool {
var wCrcData uint16 = 0xffff
for _, v := range buf {
wCrcData ^= uint16(v)
for j := 0; j < 8; j++ {
if wCrcData&1 != 0 {
wCrcData >>= 1
wCrcData ^= 0xa001
} else {
wCrcData >>= 1
}
}
}
return wCrcData == 0
}
// GetCRC 获取2个字节的CRC16
func GetCRC(buf []byte, len int) { //传入的切片必须装得下
var wCrcData uint16 = 0xffff
for i := 0; i < len; i++ {
wCrcData ^= uint16(buf[i])
for j := 0; j < 8; j++ {
if wCrcData&1 != 0 {
wCrcData >>= 1
wCrcData ^= 0xa001
} else {
wCrcData >>= 1
}
}
}
buf[len] = byte(wCrcData)
buf[len+1] = byte(wCrcData >> 8)
}
package jeffutil
import (
"encoding/base64"
"errors"
)
func EncryptBytesToBase64(cleartext []byte, pswd string, iv string) (base64Result []byte) { //看base64库,返回切片更快,本来tcp发送也是切片,不过这里面string也是切片
var pswdIv [16]byte
var pswdSum byte
var i int
cleartextLen := len(cleartext)
var result = make([]byte, cleartextLen+1)
for i = 0; i < 16; i++ {
pswdIv[i] = ((pswd[i] & 0xaa) | (pswd[15-i] & 0x55)) + iv[15-i] + byte(i)
if i%2 == 0 {
pswdSum += pswd[i] + iv[i]
} else {
pswdSum -= pswd[i] - iv[i]
}
}
for i = 0; i < 16; i++ {
if i%2 == 0 {
pswdIv[i] = ^pswdIv[i] + pswdSum
} else {
pswdIv[i] = pswdIv[i] - ^pswdSum
}
}
result[cleartextLen] = ^pswdSum
for i = 0; i < cleartextLen; i++ {
result[cleartextLen] += cleartext[i]
}
for i = 0; i < cleartextLen; i++ {
result[i] = ^((cleartext[i] & 0x72) | (cleartext[cleartextLen-1-i] & 0x8d))
if i%2 == 0 {
result[i] += pswdIv[i%16] - result[cleartextLen]
} else {
result[i] -= pswdIv[i%16] + result[cleartextLen]
}
}
base64Result = make([]byte, base64.StdEncoding.EncodedLen(cleartextLen+1)+2) //多出两个用来装起始结束符
base64.StdEncoding.Encode(base64Result[1:], result)
return
//return base64.StdEncoding.EncodeToString(result)
}
// DecryptBase64ToBytes 解密并转换为bytes
func DecryptBase64ToBytes(ciphertext []byte, pswd string, iv string) ([]byte, error) { //看base64库,传入切片更快,本来tcp接收也是切片,不过这里面string也是切片
var pswdIv [16]byte
var pswdSum byte
var i int
cipherBytes := make([]byte, base64.StdEncoding.DecodedLen(len(ciphertext)))
hexLen, err := base64.StdEncoding.Decode(cipherBytes, ciphertext)
//cipherBytes, err := base64.StdEncoding.DecodeString(ciphertext)
if err != nil {
return nil, err
}
clearLen := hexLen - 1
var resultBytes = make([]byte, clearLen)
var resultBytesTemp = make([]byte, clearLen)
for i = 0; i < 16; i++ {
pswdIv[i] = ((pswd[i] & 0xaa) | (pswd[15-i] & 0x55)) + iv[15-i] + byte(i)
if i%2 == 0 {
pswdSum += pswd[i] + iv[i]
} else {
pswdSum -= pswd[i] - iv[i]
}
}
for i = 0; i < 16; i++ {
if i%2 == 0 {
pswdIv[i] = ^pswdIv[i] + pswdSum
} else {
pswdIv[i] = pswdIv[i] - ^pswdSum
}
}
for i = 0; i < clearLen; i++ {
if i%2 == 0 {
resultBytesTemp[i] = ^(cipherBytes[i] - (pswdIv[i%16] - cipherBytes[clearLen]))
} else {
resultBytesTemp[i] = ^(cipherBytes[i] + (pswdIv[i%16] + cipherBytes[clearLen]))
}
}
var sum byte
for i = 0; i < clearLen; i++ {
resultBytes[i] = (resultBytesTemp[i] & 0x72) | (resultBytesTemp[clearLen-1-i] & 0x8d)
sum += resultBytes[i]
}
sum += ^pswdSum
if sum != cipherBytes[clearLen] {
return nil, errors.New("密文校验错误")
}
return resultBytes, nil
}
package jeffutil
import (
"fmt"
"testing"
)
//测试用例文件使用 go test 指令来执行,没有也不需要 main() 作为函数入口
//所有在以_test结尾的源码内以Test开头的函数会自动被执行。
func TestHex2Cipher(t *testing.T) {
a := "abcABC哈哈哈就glad就是理工科,的垃圾疯狂的建安费、放大算法。dfafajdf!!"
fmt.Println(a)
fmt.Println(DBCtoSBC(a))
//password := "DCRYM-2018-pswd."
//iv := "I can't tell YOU"
//
//type HexData struct {
// TimeUtc uint32
// DevType uint8
// DevID uint32
// CtrlCode uint8
// Length uint8
// Data []byte
//}
//sData := HexData{
// 1626766761,
// 0x3E,
// 0x000001,
// 0x41,
// 201,//15,
// []byte{
// 0, //通讯延迟
// 0x00, //状态码
// 0x01,0x00, //左电流
// 0x02,0x00, //右电流
// 0x03,0x00, //左电阻
// 0x04,0x00, //右电阻
// 0x05, //左温度
// 0x06, //右温度
// 0x07, //VCC_H
// 0x08, //VCC_L
// 0, //正在使用的用户数
// },
//}
//sData.Length = 243 // 255 267 362 // 243 255 346
//fmt.Println("sData.Length:",sData.Length)
//hexBuf := make([]byte, int(sData.Length) + 12)
//hexBuf[0] = byte(sData.TimeUtc >> 24)
//hexBuf[1] = byte(sData.TimeUtc >> 16)
//hexBuf[2] = byte(sData.TimeUtc >> 8)
//hexBuf[3] = byte(sData.TimeUtc)
//hexBuf[4] = sData.DevType
//hexBuf[5] = byte(sData.DevID >> 16)
//hexBuf[6] = byte(sData.DevID >> 8)
//hexBuf[7] = byte(sData.DevID)
//hexBuf[8] = sData.CtrlCode
//hexBuf[9] = sData.Length
//sData.Data = make([]byte,sData.Length)
////if sData.Length>0 {
//copy(hexBuf[10:],sData.Data[:sData.Length])
////}
//fmt.Println("len(hexBuf)",len(hexBuf))
//GetCRC(hexBuf,int(sData.Length)+10)
//sendStr := EncryptBytesToBase64(hexBuf,password,iv)
//
//sendStr[0] = '{'
//sendStr[len(sendStr) - 1] = '}'
//
//fmt.Printf("string(sendStr):%s\nlen:%d\n",string(sendStr),len(sendStr))
}
//func main() {
// a := "4769676162697445746865726E6574302F302F323400"
// bs, err := hex.DecodeString(a)
// if err != nil {
// panic(err)
// }
// fmt.Println(string(bs))
//}
package jeffutil
import (
"go.uber.org/zap/zapcore"
"gopkg.in/ini.v1"
// "jeff_workstation_1/logger"
"time"
)
var (
HttpServerMode string
HttpServerPort string
HttpClientBaseUrl string
HttpClientTimeOut time.Duration
TcpLongPort string
TcpLongMaxConnections int
TcpLongNewConnReadDeadline time.Duration
TcpLongNewConnRightfulTimeout int64
TcpLongOldConnReadDeadline time.Duration
LogLevel zapcore.Level
LogPath string
LogFileMaxSize int // 单个日志文件的最大MB
LogInfoMaxFileNum int
LogInfoMaxFileDay int
LogWarnMaxFileNum int
LogWarnMaxFileDay int
LogErrorMaxFileNum int
LogErrorMaxFileDay int
)
func init() {
file, err := ini.Load("./config.ini")
if err != nil {
// logger.Log.Panic("配置文件读取错误")
panic("配置文件读取错误")
}
HttpServerMode = file.Section("http_server").Key("ServerMode").In("release", []string{"release", "debug"})
HttpServerPort = file.Section("http_server").Key("ServerPort").MustString(":50000")
HttpClientBaseUrl = file.Section("http_client").Key("BaseUrl").MustString("http://handandev.swaylink.cn/phone/2/server/")
HttpClientTimeOut = time.Duration(file.Section("http_client").Key("TimeOut").MustInt(5)) * time.Second
TcpLongPort = file.Section("tcp_long_server").Key("TcpPort").MustString("60000")
TcpLongMaxConnections = int(file.Section("tcp_long_server").Key("MaxConnections").MustUint(20000))
TcpLongNewConnReadDeadline = time.Duration(file.Section("tcp_long_server").Key("NewConnReadDeadline").MustInt(60)) * time.Second
TcpLongNewConnRightfulTimeout = file.Section("tcp_long_server").Key("NewConnRightfulTimeout").MustInt64(120)
TcpLongOldConnReadDeadline = time.Duration(file.Section("tcp_long_server").Key("OldConnReadDeadline").MustInt(180)) * time.Second
logLvlStr := file.Section("log").Key("Level").In("warn", []string{"trace", "debug", "info", "warn", "error"})
switch logLvlStr {
case "debug":
LogLevel = zapcore.DebugLevel
case "info":
LogLevel = zapcore.InfoLevel
case "warn":
LogLevel = zapcore.WarnLevel
case "error":
LogLevel = zapcore.ErrorLevel
}
LogPath = file.Section("log").Key("Path").MustString(".log")
LogFileMaxSize = file.Section("log").Key("FileMaxSize").MustInt(10)
LogInfoMaxFileNum = file.Section("log").Key("InfoMaxFileNum").MustInt(10)
LogInfoMaxFileDay = file.Section("log").Key("InfoWithMaxAge").MustInt(30)
LogWarnMaxFileNum = file.Section("log").Key("WarnMaxFileNum").MustInt(10)
LogWarnMaxFileDay = file.Section("log").Key("WarnWithMaxAge").MustInt(90)
LogErrorMaxFileNum = file.Section("log").Key("ErrorMaxFileNum").MustInt(10)
LogErrorMaxFileDay = file.Section("log").Key("ErrorWithMaxAge").MustInt(180)
//LogTraceWithRotationTime = time.Duration(file.Section("log").Key("TraceWithRotationTime").MustInt(2)) * time.Hour
//LogTraceWithMaxAge = time.Duration(file.Section("log").Key("TraceWithMaxAge").MustInt(24)) * time.Hour
//
//LogDebugWithRotationTime = time.Duration(file.Section("log").Key("DebugWithRotationTime").MustInt(2)) * time.Hour
//LogDebugWithMaxAge = time.Duration(file.Section("log").Key("DebugWithMaxAge").MustInt(24)) * time.Hour
//
//LogInfoWithRotationTime = time.Duration(file.Section("log").Key("InfoWithRotationTime").MustInt(24)) * time.Hour
//LogInfoWithMaxAge = time.Duration(file.Section("log").Key("InfoWithMaxAge").MustInt(3*24)) * time.Hour
//
//LogWarnWithRotationTime = time.Duration(file.Section("log").Key("WarnWithRotationTime").MustInt(24)) * time.Hour
//LogWarnWithMaxAge = time.Duration(file.Section("log").Key("WarnWithMaxAge").MustInt(7*24)) * time.Hour
//
//LogErrorWithRotationTime = time.Duration(file.Section("log").Key("ErrorWithRotationTime").MustInt(10*24)) * time.Hour
//LogErrorWithMaxAge = time.Duration(file.Section("log").Key("ErrorWithMaxAge").MustInt(30*24)) * time.Hour
}
#!/bin/bash
filename="TcpServer"
port=50000
cnt=`netstat -tnlp|grep $port |grep -v grep |wc -l`
#cne=`ps -ef|grep $filename|grep -v grep |wc -l`
if [[ $cnt -eq 0 ]];then
cd /root/
nohup ./$filename &
fi
\ No newline at end of file
package logger
import (
"github.com/gin-gonic/gin"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"jeff_workstation_1/jeffutil"
"os"
"time"
)
var Log *zap.Logger
func InitLogger() {
config := zapcore.EncoderConfig{
MessageKey: "msg", //结构化(json)输出:msg的key
LevelKey: "level", //结构化(json)输出:日志级别的key(INFO,WARN,ERROR等)
TimeKey: "ts", //结构化(json)输出:时间的key(INFO,WARN,ERROR等)
CallerKey: "file", //结构化(json)输出:打印日志的文件对应的Key
EncodeLevel: zapcore.CapitalLevelEncoder, //将日志级别转换成大写(INFO,WARN,ERROR等)
EncodeCaller: zapcore.ShortCallerEncoder, //采用短文件路径编码输出(test/main.go:14 )
EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}, //输出的时间格式
//EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) {
// enc.AppendInt64(int64(d) / 1000000)
//},//
}
//debug info
infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl < zapcore.WarnLevel && lvl >= jeffutil.LogLevel
})
//warn
warnLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl == zapcore.WarnLevel && lvl >= jeffutil.LogLevel
})
//error DPanic Panci Fatal
errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl > zapcore.WarnLevel && lvl >= jeffutil.LogLevel
})
infoWriter := &lumberjack.Logger{
Filename: jeffutil.LogPath + "info.log",
MaxSize: jeffutil.LogFileMaxSize, //最大M数,超过则切割
MaxBackups: jeffutil.LogInfoMaxFileNum, //最大文件保留数,超过就删除最老的日志文件
MaxAge: jeffutil.LogInfoMaxFileDay, //保存30天
Compress: false, //是否压缩
}
warnWriter := &lumberjack.Logger{
Filename: jeffutil.LogPath + "warn.log",
MaxSize: jeffutil.LogFileMaxSize, //最大M数,超过则切割
MaxBackups: jeffutil.LogWarnMaxFileNum, //最大文件保留数,超过就删除最老的日志文件
MaxAge: jeffutil.LogWarnMaxFileDay, //保存30天
Compress: false, //是否压缩
}
errorWriter := &lumberjack.Logger{
Filename: jeffutil.LogPath + "error.log",
MaxSize: jeffutil.LogFileMaxSize, //最大M数,超过则切割
MaxBackups: jeffutil.LogErrorMaxFileNum, //最大文件保留数,超过就删除最老的日志文件
MaxAge: jeffutil.LogErrorMaxFileDay, //保存30天
Compress: false, //是否压缩
}
core := zapcore.NewTee(
zapcore.NewCore(zapcore.NewJSONEncoder(config), zapcore.AddSync(infoWriter), infoLevel), // zapcore.NewConsoleEncoder(encoder)
zapcore.NewCore(zapcore.NewJSONEncoder(config), zapcore.AddSync(warnWriter), warnLevel), //
zapcore.NewCore(zapcore.NewJSONEncoder(config), zapcore.AddSync(errorWriter), errorLevel), //
//zapcore.NewCore(zapcore.NewJSONEncoder(encoder), zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout)), logLevel),//同时将日志输出到控制台,NewJSONEncoder 是结构化输出
)
Log = zap.New(core, zap.AddStacktrace(zap.ErrorLevel))
}
func HttpGinLog() gin.HandlerFunc { //logger *log.Log
return func(c *gin.Context) {
startTime := time.Now().UnixNano()
c.Next()
// stopTime := time.Since(startTime)
// spendTime := stopTime.Nanoseconds()/1000000///fmt.Sprintf("%d ms", (stopTime.Nanoseconds()+500000)/1000000)
spendTime := time.Now().UnixNano() - startTime
hostName, err := os.Hostname()
if err != nil {
hostName = "unknown"
}
statusCode := c.Writer.Status()
clientIp := c.ClientIP()
userAgent := c.Request.UserAgent()
dataSize := c.Writer.Size()
if dataSize < 0 {
dataSize = 0
}
method := c.Request.Method
path := c.Request.RequestURI
//c.Request.Body.Read()
//body := c.Request.Body
//para := c.Params
//entry := Log.WithFields(log.Fields{
// "HostName": hostName,
// "Status": statusCode,
// "SpendNanoS": spendTime,
// "Ip": clientIp,
// "Method": method,
// "Path": path,
// "DataSize": dataSize,
// "Agent": userAgent,
//})
if len(c.Errors) > 0 {
//entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
Log.Error(c.Errors.ByType(gin.ErrorTypePrivate).String(),
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
}
if statusCode >= 500 {
Log.Error("",
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
} else if statusCode >= 400 {
Log.Warn("",
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
} else {
Log.Info("",
zap.String("HostName", hostName),
zap.Int("Status", statusCode),
zap.Int64("SpendNanoS", spendTime),
zap.String("Ip", clientIp),
zap.String("Method", method),
zap.String("Path", path),
zap.Int("DataSize", dataSize),
zap.String("Agent", userAgent))
}
}
}
//import (
// "github.com/gin-gonic/gin"
// rotatelogs "github.com/lestrrat-go/file-rotatelogs"
// "github.com/rifflock/lfshook"
// log "github.com/sirupsen/logrus"
// "jeff_workstation_1/jeffutil"
// "os"
// "time"
//)
//
//func InitLogger(filePath string){
//
// // log.SetOutput(colorable.NewColorableStdout())
//
// // log.SetOutput(f)
// log.SetLevel(jeffutil.LogLevel)
//
// TraceLogWriter,_ := rotatelogs.New(
// filePath+"Trace_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(jeffutil.LogTraceWithMaxAge),
// rotatelogs.WithRotationTime(jeffutil.LogTraceWithRotationTime),
// //rotatelogs.WithLinkName(linkName),
// )
// DebugLogWriter,_ := rotatelogs.New(
// filePath+"Debug_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(jeffutil.LogDebugWithMaxAge),
// rotatelogs.WithRotationTime(jeffutil.LogDebugWithRotationTime),
// //rotatelogs.WithLinkName(linkName),
// )
// infoLogWriter,_ := rotatelogs.New(
// filePath+"Info_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(jeffutil.LogInfoWithMaxAge),
// rotatelogs.WithRotationTime(jeffutil.LogInfoWithRotationTime),
// //rotatelogs.WithLinkName("tcp_info.log"),
// )
// WarnLogWriter,_ := rotatelogs.New(
// filePath+"Warn_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(jeffutil.LogWarnWithMaxAge),
// rotatelogs.WithRotationTime(jeffutil.LogWarnWithRotationTime),
// //rotatelogs.WithLinkName("tcp_warn.log"),
// )
// ErrorLogWriter,_ := rotatelogs.New(
// filePath+"Error_%Y%m%d%H.log",
// rotatelogs.WithMaxAge(jeffutil.LogErrorWithMaxAge),
// rotatelogs.WithRotationTime(jeffutil.LogErrorWithRotationTime),
// //rotatelogs.WithLinkName("tcp_error.log"),
// )
//
// writeMap := lfshook.WriterMap{
// log.TraceLevel: TraceLogWriter,
// log.DebugLevel: DebugLogWriter,
// log.InfoLevel: infoLogWriter,
// log.WarnLevel: WarnLogWriter,
// log.ErrorLevel: ErrorLogWriter,
// log.PanicLevel: ErrorLogWriter,
// log.FatalLevel: ErrorLogWriter,
// }
// hook := lfshook.NewHook(writeMap,&log.JSONFormatter{
// TimestampFormat: "2006-01-02 15:04:05.000000",
// })
//
// log.AddHook(hook)
// return
//}
//
//func HttpGinLog() gin.HandlerFunc{ //logger *log.Log
// return func(c *gin.Context) {
// startTime := time.Now().UnixNano()
// c.Next()
// //stopTime := time.Since(startTime)
// //spendTime := stopTime.Nanoseconds()/1000000///fmt.Sprintf("%d ms", (stopTime.Nanoseconds()+500000)/1000000)
// spendTime := time.Now().UnixNano() - startTime
// hostName, err := os.Hostname()
// if err != nil {
// hostName = "unknown"
// }
// statusCode := c.Writer.Status()
// clientIp := c.ClientIP()
// userAgent := c.Request.UserAgent()
// dataSize := c.Writer.Size()
// if dataSize < 0 {
// dataSize = 0
// }
// method := c.Request.Method
// path := c.Request.RequestURI
//
// //c.Request.Body.Read()
// //body := c.Request.Body
// //para := c.Params
//
// entry := log.WithFields(log.Fields{
// "HostName": hostName,
// "Status": statusCode,
// "SpendNanoS": spendTime,
// "Ip": clientIp,
// "Method": method,
// "Path": path,
// "DataSize": dataSize,
// "Agent": userAgent,
// })
//
// if len(c.Errors) > 0 {
// entry.Error(c.Errors.ByType(gin.ErrorTypePrivate).String())
// }
// if statusCode >= 500 {
// entry.Error()
// } else if statusCode >= 400 {
// entry.Warn()
// } else {
// entry.Info()
// }
// }
//}
package main
import (
"github.com/gin-gonic/gin"
dcphone10 "jeff_workstation_1/devproduct/dcphone10"
"jeff_workstation_1/jeffutil"
"jeff_workstation_1/logger"
"os"
"syscall"
)
//windows
//var (
// kernel32 = syscall.MustLoadDLL("kernel32.dll")
// procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
//)
//
//func setStdHandle(stdhandle int32, handle syscall.Handle) error {
// r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
// if r0 == 0 {
// if e1 != 0 {
// return error(e1)
// }
// return syscall.EINVAL
// }
// return nil
//}
//
//// redirectStderr to the file passed in
//func redirectStderrWindows(f *os.File) {
// err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
// if err != nil {
// logger.Log.Panic(err.Error())
// }
// // SetStdHandle does not affect prior references to stderr
// os.Stderr = f
//}
//windows end
func redirectStderrLinux(f *os.File) {
err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
if err != nil {
logger.Log.Panic(err.Error())
}
}
func init() {
logger.InitLogger()
f, err := os.OpenFile(jeffutil.LogPath+"panic.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
if err != nil {
logger.Log.Panic(err.Error())
}
//redirectStderrWindows(f)
redirectStderrLinux(f)
}
// dcfan50 "jeff_workstation_1/devproduct/dcfan50"
// dcphone10 "jeff_workstation_1/devproduct/dcphone10"
func main() { //
gin.SetMode(jeffutil.HttpServerMode)
r := gin.New()
r.Use(logger.HttpGinLog(), gin.Recovery())
//r.Use()
// dcfan50.NewDCFan50(r)
dcphone10.NewDCPhone10(r)
err := r.Run(jeffutil.HttpServerPort)
if err != nil {
panic(err)
}
}
package main
import (
"testing"
)
func Test(t *testing.T) {
//jeffutil.init()
}
//
//import (
// log "github.com/sirupsen/logrus"
// "os"
// "syscall"
// "testing"
//)
//
//var (
// kernel32 = syscall.MustLoadDLL("kernel32.dll")
// procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
//)
//
//func setStdHandle(stdhandle int32, handle syscall.Handle) error {
// r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
// if r0 == 0 {
// if e1 != 0 {
// return error(e1)
// }
// return syscall.EINVAL
// }
// return nil
//}
//
//// redirectStderr to the file passed in
//func redirectStderrWindows(f *os.File) {
// err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
// if err != nil {
// log.Fatalf("Failed to redirect stderr to file: %v\n", err)
// }
// // SetStdHandle does not affect prior references to stderr
// os.Stderr = f
//}
//
//
//// redirectStderr to the file passed in
////func redirectStderrLinux(f *os.File) {
//// err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
//// if err != nil {
//// log.Fatalf("Failed to redirect stderr to file: %v\n", err)
//// }
////}
//
//
//func Test(t *testing.T) {
// f, err := os.OpenFile("./golang_log.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY,0755)
// if err != nil{
// log.Fatalln(err)
// }
//
// redirectStderrWindows(f)
//
// log.SetOutput(f)
//
// log.Println("1234")
// var testPanic []byte
// testPanic[0] = 1
// // log.Panicln("log.Panicln")
//}
//package main
//
//import (
// "log"
// "os"
// "syscall"
// "testing"
//)
//
//
//var (
// kernel32 = syscall.MustLoadDLL("kernel32.dll")
// procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
//)
//
//func setStdHandle(stdhandle int32, handle syscall.Handle) error {
// r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
// if r0 == 0 {
// if e1 != 0 {
// return error(e1)
// }
// return syscall.EINVAL
// }
// return nil
//}
//
//// redirectStderr to the file passed in
//func redirectStderrWindows(f *os.File) {
// err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
// if err != nil {
// log.Fatalf("Failed to redirect stderr to file: %v\n", err)
// }
// // SetStdHandle does not affect prior references to stderr
// os.Stderr = f
//}
//
//
//// redirectStderr to the file passed in
////func redirectStderrLinux(f *os.File) {
//// err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
//// if err != nil {
//// log.Fatalf("Failed to redirect stderr to file: %v\n", err)
//// }
////}
//
//
//func Test(t *testing.T) {
// f, err := os.OpenFile("./golang_log.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY,0755)
// if err != nil{
// log.Fatalln(err)
// }
//
// redirectStderrWindows(f)
//
// log.SetOutput(f)
// log.SetFlags(log.Ldate|log.Ltime|log.Lmicroseconds|log.Llongfile)
//
// log.Println("1234")
// var testPanic []byte
// testPanic[0] = 1
// // log.Panicln("log.Panicln")
//}
package tcplongserver
import (
"go.uber.org/zap"
"jeff_workstation_1/jeffutil"
"jeff_workstation_1/logger"
"net"
"time"
)
//type IDCLongTCPHex interface {
// receiveResponse(conn *net.TCPConn, data []byte, cnt int) bool
//}
type DCLongTCPHex struct {
TCPLongServer
password string
iv string
devType uint8
protocolAnalysis func(data *HexData) //HexData
}
//type Connection struct {
// conn *net.TCPConn
//}
type HexData struct {
TimeUtc uint32
//DevType uint8
DevID uint32
CtrlCode uint8
Length uint8
Data []byte
}
func (d *DCLongTCPHex) receiveResponse(conn *net.TCPConn, data []byte) uint32 {
c, err := jeffutil.DecryptBase64ToBytes(data, d.password, d.iv)
if err != nil {
logger.Log.Warn("DecryptBase64ToBytes error",
zap.String("Src", "TCP-SERVER-receiveResponse"),
zap.String("RData", string(data)),
zap.Error(err),
zap.String("Conn", conn.RemoteAddr().String()))
return 0
}
if jeffutil.CheckCRC(c) == false {
logger.Log.Error("CheckCRC error",
zap.String("Src", "TCP-SERVER-receiveResponse"),
zap.String("RData", string(data)),
zap.Uint8s("HexData", c),
zap.String("Conn", conn.RemoteAddr().String())) // 解密都校验对了,CRC错了也不应该
return 0
}
cLen := len(c)
if cLen < 12 {
logger.Log.Error("cLen <9 error", // 解密都校验对了,CRC也对了,长度却不够,不应该
zap.String("Src", "TCP-SERVER-receiveResponse"),
zap.String("RData", string(data)),
zap.Uint8s("HexData", c),
zap.Int("cLen", cLen),
zap.String("Conn", conn.RemoteAddr().String()))
return 0
} else if int(c[9])+12 != cLen {
logger.Log.Error("cLen != int(c[9])+12 error", // 解密都校验对了,CRC也对了,长度却不正确,不应该
zap.String("Src", "TCP-SERVER-receiveResponse"),
zap.String("RData", string(data)),
zap.Uint8s("HexData", c),
zap.Int("cLen", cLen),
zap.String("Conn", conn.RemoteAddr().String()))
return 0
}
var rData HexData
rData.TimeUtc = uint32(c[3])<<24 | uint32(c[2])<<16 | uint32(c[1])<<8 | uint32(c[0]) // binary.Read(bytes.NewBuffer(cleartext[:4]), binary.BigEndian, &rData.timeUtc) 肯定效率低下,还是自己拼
// 时间有效性判断
nowTimeUtc := uint32(time.Now().Unix())
if nowTimeUtc > rData.TimeUtc+300 || rData.TimeUtc > nowTimeUtc+300 {
logger.Log.Warn("receive utc err",
zap.String("Src", "TCP-SERVER-receiveResponse"),
zap.String("RData", string(data)),
zap.Uint8s("HexData", c),
zap.Int("cLen", cLen),
zap.Uint32("RUtc", rData.TimeUtc),
zap.Uint32("NowUtc", nowTimeUtc),
zap.String("Conn", conn.RemoteAddr().String()))
return 0
}
// 设备类型判断
if c[4] != d.devType {
logger.Log.Error("devType error", // 设备类型不对,不应该
zap.String("Src", "TCP-SERVER-receiveResponse"),
zap.String("RData", string(data)),
zap.Uint8s("HexData", c),
zap.Int("cLen", cLen),
zap.Uint8("RdevType", c[4]),
zap.String("Conn", conn.RemoteAddr().String()))
return 0
}
rData.DevID = uint32(c[4])<<24 | uint32(c[5])<<16 | uint32(c[6])<<8 | uint32(c[7])
rData.CtrlCode = c[8]
rData.Length = c[9]
rData.Data = c[10 : cLen-2]
logger.Log.Debug("R", //
zap.String("Src", "TCP-SERVER-receive"),
zap.Uint32("DevID", rData.DevID),
zap.String("RData", string(data)),
zap.Uint8s("HexData", c),
zap.String("Conn", conn.RemoteAddr().String()))
/*sBuf := */ d.protocolAnalysis(&rData)
if rData.CtrlCode > 0x80 { // 用来判断返回不为空 被动响应都大于0x80
sendStr := d.packageSendData(&rData)
sendStr[0] = '['
sendStr[len(sendStr)-1] = ']'
//if sendFlag {time.Sleep(20*time.Millisecond)} //这句话是为了多帧发送间隔20MS,可以不加试试
if _, err := conn.Write(sendStr); err != nil {
logger.Log.Debug("conn.Write(sendStr) error", // 刚收到发来的,现在居然发不回去了
zap.String("Src", "TCP-SERVER-receive"),
zap.Uint32("DevID", rData.DevID),
zap.String("RData", string(data)),
zap.String("SendStr", string(sendStr)),
zap.String("Conn", conn.RemoteAddr().String()))
return 0
}
logger.Log.Debug("W", //
zap.String("Src", "TCP-SERVER-receive"),
zap.Uint32("DevID", rData.DevID),
//zap.String("RData", string(data)),
//zap.Uint8s("HexData", c),
zap.String("SendStr", string(sendStr)),
zap.String("Conn", conn.RemoteAddr().String()))
}
return rData.DevID //解密成功且CRC校验成功,设备类型一致,解析长度正确,则为合法设备
}
////============== 按多彩hex协议解析 ===========
///*
//为提高处理速度:
//. 这里认为TCP不会出现断帧,即只收到一帧数据一部分的情况
//. 数据包为base64字符串,起始符:'{',结束符: '}'
//. 空心跳定义为:上行 "{}"
//. 收到空心跳时,响应"[ ",不用判断连接池是否有设备ID没有下发读,因为所有硬件逻辑会主动实现重连了socket发一帧带ID的
//. 认为接收有可能会粘包,分割后对每一帧进行处理,若有多帧需要回复,则不回复空心跳
//. 为防止接收方粘包,多条下发时延迟间隔20mS
//*/
//func (d *DCLongTCPHex)receiveResponse__(conn *net.TCPConn, data []byte, cnt int) (result uint32){
// sendFlag := false
//
// emptyHeart := false
// s := string(data[:cnt])
// r := strings.Fields(s) // ntodo 抽时间改成直接切片里面手动分割,不用字符串处理
// for _,str := range r{
// if str[0] == '{'{
// if len(str)>1{
// c,err := jeffutil.DecryptBase64ToBytes(str[1:],d.password,d.iv)
// if err != nil{
// // ntodo logger 解密错误
// fmt.Println(str,"解密错误:",err)
// continue
// }
// if jeffutil.CheckCRC(c) == false{
// // ntodo logger CRC校验错误
// continue
// }
// cLen := len(c)
// if cLen < 12{
// // ntodo logger 长度不够
// continue
// } else if int(c[9])+12 != cLen {
// // ntodo logger 长度错误
// continue
// }
//
// var rData HexData
// rData.TimeUtc = uint32(c[3])<<24 | uint32(c[2])<<16 | uint32(c[1])<<8 | uint32(c[0]) // binary.Read(bytes.NewBuffer(cleartext[:4]), binary.BigEndian, &rData.timeUtc) 肯定效率低下,还是自己拼
// //rData.DevType = c[4]
// rData.DevID = uint32(c[4])<<24 | uint32(c[5])<<16 | uint32(c[6])<<8 | uint32(c[7])
// rData.CtrlCode = c[8]
// rData.Length = c[9]
// rData.Data = c[10:cLen-2]
//
// if c[4] == d.devType {
// result = rData.DevID //解密成功且CRC校验成功,设备类型一致,解析长度正确,则为合法设备
// } else {
// // ntodo logger
// return //false
// }
//
// fmt.Printf("%v-RX-%X:%v\n",time.Now(),rData.DevID,rData)
// /*sBuf := */d.protocolAnalysis(&rData)
// if rData.CtrlCode > 0x80 { // 用来判断返回不为空 被动响应都大于0x80
// sendStr := d.packageSendData(&rData)
// sendStr[0] = '['
// sendStr[len(sendStr) - 1] = ']'
//
// //if sendFlag {time.Sleep(20*time.Millisecond)} //这句话是为了多帧发送间隔20MS,可以不加试试
//
// if _, err := conn.Write(sendStr); err !=nil {
// // ntodo logger 发送失败
// return //false
// }
// fmt.Println(time.Now(),"-TX:",string(sendStr))
// sendFlag = true
// }
// } else { // 收到空心跳
// // ntodo logger或记录通信时间
// fmt.Println(time.Now(),"-RX:收到空心跳")
// emptyHeart = true
// }
// } /*else {
// if str[0] != nil {
// // ntodo logger 收到起始符不对
// fmt.Println(time.Now(), ":未收到起始符", str)
// }
// }*/
// } // for _,str := range r{
//
// if emptyHeart == true && sendFlag == false{
// if _, err := conn.Write([]byte("[]")); err !=nil { //估计编译器预编译懂得将[]byte("[]")搞成常量,只是估计
// // 这个地方其实可以从connMap里面删除,但是遍历浪费资源,不删也罢
// return //false
// }
// //result = true
// fmt.Println(time.Now(),"-TX:","[]")
// }
//
// return
//}
func (d *DCLongTCPHex) TCPSend(data *HexData) bool {
//d.ConnectMapRWMutex.RLock()
//c,ok := d.ConnectMap[data.DevID]// conn,ok := d.ConnectMap.Load(data.DevID)
//d.ConnectMapRWMutex.RUnlock()
if conn, ok := d.ConnectMap.Load(data.DevID); ok {
if c, ok := conn.(*net.TCPConn); ok { // 类型断言
sendStr := d.packageSendData(data)
sendStr[0] = '['
sendStr[len(sendStr)-1] = ']'
if _, err := c.Write(sendStr); err != nil {
//d.ConnectMapRWMutex.Lock()
//delete(d.ConnectMap,data.DevID)// d.ConnectMap.Delete(data.DevID)
//d.ConnectMapRWMutex.Unlock()
d.ConnectMap.Delete(data.DevID)
logger.Log.Debug("conn.Write(sendStr) error", //
zap.String("Src", "TCP-SERVER-TCPSend"),
zap.Uint32("DevID", data.DevID),
zap.Error(err),
zap.String("SendStr", string(sendStr)),
zap.String("Conn", c.RemoteAddr().String()),
zap.String("State", "offline"))
return false
}
logger.Log.Debug("AW", //
zap.String("Src", "TCP-SERVER-TCPSend"),
zap.Uint32("DevID", data.DevID),
zap.String("SendStr", string(sendStr)),
zap.String("Conn", c.RemoteAddr().String()))
return true
} else {
// ntodo logger map里面存的内容居然类型不对
d.ConnectMap.Delete(data.DevID)
logger.Log.Error("conn.(*net.TCPConn) != ok", //
zap.String("Src", "TCP-SERVER-TCPSend"),
zap.Uint32("DevID", data.DevID),
zap.String("Conn", c.RemoteAddr().String()),
zap.String("State", "offline"))
}
}
return false
}
func (d *DCLongTCPHex) InitNewDCLongTCPHex(password string, iv string, devType uint8, f func(data *HexData)) {
d.password = password
d.iv = iv
d.devType = devType
d.protocolAnalysis = f
d.TCPReceive = d.receiveResponse
// d.ConnectMap = make(map[uint32]*net.TCPConn)
}
// 组装并加密数据
func (d *DCLongTCPHex) packageSendData(sData *HexData) []byte {
hexBuf := make([]byte, sData.Length+12)
sData.TimeUtc = uint32(time.Now().Unix())
hexBuf[0] = byte(sData.TimeUtc)
hexBuf[1] = byte(sData.TimeUtc >> 8)
hexBuf[2] = byte(sData.TimeUtc >> 16)
hexBuf[3] = byte(sData.TimeUtc >> 24)
hexBuf[4] = d.devType
hexBuf[5] = byte(sData.DevID >> 16)
hexBuf[6] = byte(sData.DevID >> 8)
hexBuf[7] = byte(sData.DevID)
hexBuf[8] = sData.CtrlCode
hexBuf[9] = sData.Length
//if sData.Length>0 {
copy(hexBuf[10:], sData.Data[:sData.Length])
//}
jeffutil.GetCRC(hexBuf, int(sData.Length)+10)
return jeffutil.EncryptBytesToBase64(hexBuf, d.password, d.iv)
}
package tcplongserver
import (
"fmt"
"go.uber.org/zap"
"jeff_workstation_1/jeffutil"
"jeff_workstation_1/logger"
"net"
"strconv"
"sync"
"time"
)
type ITCPLongServer interface {
TCPStart(port string)
}
type receiveCallbackFunc func(*net.TCPConn, []byte) uint32 //定义接收到数据的回调函数的函数类型
type TCPLongServer struct {
TCPReceive receiveCallbackFunc
ConnSocketCount int
ConnectMap sync.Map // 用这个可能性能不行,测试下,不行就用map加锁
rwConnSocketCount chan int
// ConnectMapRWMutex sync.RWMutex
// ConnectMap map[uint32]*net.TCPConn // Connection
}
func (s *TCPLongServer) TCPStart(port string) {
go func() {
// 获取一个TCP的Addr
addr, err := net.ResolveTCPAddr("tcp4", "0.0.0.0:"+port)
if err != nil {
panic("error: net.ResolveTCPAddr " + port + err.Error())
}
// 监听服务器地址
listener, err := net.ListenTCP("tcp4", addr)
if err != nil {
logger.Log.Panic("net.ListenTCP:"+port,
zap.String("Src", "TCP-SERVER"),
zap.Error(err))
}
s.rwConnSocketCount = make(chan int)
go func() {
for {
s.ConnSocketCount += <-s.rwConnSocketCount
if s.ConnSocketCount < 0 {
s.ConnSocketCount = 0
logger.Log.Error("s.ConnSocketCount <0",
zap.Int("ConnSocketCount", s.ConnSocketCount))
}
}
}()
// 启动server
for {
conn, err := listener.AcceptTCP() // 阻塞等待客户端建立连接请求
if err != nil {
logger.Log.Warn("listener.AcceptTCP()",
zap.String("Src", "TCP-SERVER"),
zap.Error(err))
continue
}
go s.connectionHandle(conn, s.TCPReceive)
}
}()
}
// 主动断开某链接,其实在新连接上来的时候,可以查下如果map里面有现在的设备号,就可以把旧的断掉
//func (s *TCPLongServer) DeleteConnection(key uint32){
// if conn,ok := s.ConnectMap.Load(key);ok {
// if c,ok := conn.(*net.TCPConn);ok{ // 类型断言
// c.Close()
// }
// }
// s.ConnectMap.Delete(key)
// log.WithFields(log.Fields{
// "Src": "TCP-SERVER-DeleteConnection",
// "DevId": key,
// "Conn":conn.RemoteAddr(),
// "State": "offline",
// }).Debugln("conn.Write(sendStr) error")
//}
func (s *TCPLongServer) connectionHandle(conn *net.TCPConn, callBack receiveCallbackFunc) {
var myDevID uint32 // golang 默认0
s.rwConnSocketCount <- 1
defer func() {
s.rwConnSocketCount <- -1
//if s.ConnSocketCount > 0 {
// s.ConnSocketCount--
//} else {
// logger.Log.Error("s.ConnSocketCount error",
// zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevId", myDevID),
// zap.String("Conn", conn.RemoteAddr().String()),
// zap.Int("ConnSocketCount", s.ConnSocketCount))
//}
if myDevID != 0 {
if connMyID, ok := s.ConnectMap.Load(myDevID); ok { //查一下设备旧链接还在的话,关掉
if co, ok := connMyID.(*net.TCPConn); ok { // 类型断言
if co == conn {
s.ConnectMap.Delete(myDevID)
logger.Log.Debug("device offline",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "offline"))
} else {
// s.ConnectMap.Delete(myDevID) 这里人家存了新的,不能去删了噻
logger.Log.Debug("have a new link,close old link",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "offline"))
}
} else {
s.ConnectMap.Delete(myDevID)
logger.Log.Error("connMyID.(*net.TCPConn) != ok",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "offline")) // 类型断言失败
}
} else {
logger.Log.Debug("map no have myDevID",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "offline"))
}
}
_ = conn.SetReadDeadline(time.Time{}) // 设置回去,但是不知道需不需要这句话
_ = conn.Close()
fmt.Println("-----------------------------------Out ConnSocketCount:", s.ConnSocketCount)
}()
//myDevId := -1
//waitTimeOut := 0
//exit := make(chan bool)
//// 读写分离
//go func() {
// for{
// if myDevId < 0 {
// time.Sleep(100*time.Millisecond)
// waitTimeOut++
// if waitTimeOut > 100 { exit <- true }
// }else{
// data := <-sendMsg[myDevId]
// if _, err := conn.Write(data); err != nil {
// exit <- true
// }
// }
// }
//}()
if s.ConnSocketCount > jeffutil.TcpLongMaxConnections { //限制最大连接数2万个配置文件 最大连接限制数添加到配置文件
logger.Log.Warn("ConnSocketCount overrun:"+strconv.Itoa(jeffutil.TcpLongMaxConnections),
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Int("ConnSocketCount", s.ConnSocketCount))
return
}
_ = conn.SetKeepAlive(false)
buf := make([]byte, 512)
rBuf := make([]byte, 512)
rLen := 0
i := 0
timeConn := time.Now().Unix() + jeffutil.TcpLongNewConnRightfulTimeout //配置文件 120秒
for {
if myDevID == 0 {
if time.Now().Unix() > timeConn { // 连上来2分钟都没整个正确的数据来,就给它断球
logger.Log.Warn("NewConnRightfulTimeout:"+strconv.Itoa(int(jeffutil.TcpLongNewConnRightfulTimeout)), // 超时没收到合法的指令
zap.String("Src", "TCP-SERVER-connectionHandle"),
// zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Int("ConnSocketCount", s.ConnSocketCount))
return
}
if err := conn.SetReadDeadline(time.Now().Add(jeffutil.TcpLongNewConnReadDeadline)); err != nil { // 配置文件 新连接1分钟超时未收到数据(配置文件用秒)
logger.Log.Warn("conn.SetReadDeadline:new", //
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Error(err),
zap.Int("ConnSocketCount", s.ConnSocketCount))
return
}
} else {
if err := conn.SetReadDeadline(time.Now().Add(jeffutil.TcpLongOldConnReadDeadline)); err != nil { // 配置文件 老连接3分钟超时未收到数据(配置文件用秒)
logger.Log.Warn("conn.SetReadDeadline:old", //
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Error(err),
zap.Int("ConnSocketCount", s.ConnSocketCount))
return
}
}
cnt, err := conn.Read(buf)
if err != nil {
// fmt.Println("conn.Read:", err)
// logger debug 其中存在超时,或新连接来关闭了旧链接
logger.Log.Debug("read error",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.Error(err))
return
}
for i = 0; i < cnt; i++ {
if rBuf[0] != '{' || rLen == 0 {
if buf[i] == '{' {
rBuf[0] = '{'
rLen = 1
} else {
rLen = 0
}
} else if buf[i] == '}' {
if rLen == 1 {
if i+1 == cnt { //只有当后面没跟其他数据的时候,才回空心跳
if _, err2 := conn.Write([]byte("[]")); err2 != nil {
return
}
}
} else {
newID := callBack(conn, rBuf[1:rLen])
if newID == 0 {
return
} else if newID != myDevID {
if myDevID == 0 {
if connOld, ok := s.ConnectMap.Load(newID); ok { //查一下设备旧链接还在的话,关掉
if co, ok := connOld.(*net.TCPConn); ok { // 类型断言
s.ConnectMap.Store(newID, conn) //先存新的再关
_ = co.Close()
} /* else {
s.ConnectMap.Delete(newID)
fmt.Printf("newID : s.ConnectMap.类型断言(%08X)错误\n",newID)
// ntodo logger 类型断言不OK
}*/
}
// logger 新链接来的合法设备
logger.Log.Debug("a new link is coming",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", newID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "online"))
} else {
s.ConnectMap.Delete(myDevID)
logger.Log.Error("DevID changed",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("OldDevId", myDevID),
zap.Uint32("NewDevId", newID),
zap.String("Conn", conn.RemoteAddr().String()))
}
s.ConnectMap.Store(newID, conn) //先存新的再关
myDevID = newID
} else { //其实这个地方应该查下map里面有没有,没有就是没对
if connMyID, ok := s.ConnectMap.Load(myDevID); ok { //
if co, ok := connMyID.(*net.TCPConn); ok { // 类型断言
if co != conn {
s.ConnectMap.Store(myDevID, conn)
logger.Log.Error("co != conn",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "restore myDevId"))
}
} else {
s.ConnectMap.Store(myDevID, conn)
logger.Log.Error("connMyID.(*net.TCPConn) != ok",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "restore myDevId")) // 类型断言失败
}
} else {
s.ConnectMap.Store(myDevID, conn)
logger.Log.Debug("map no have myDevID",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()),
zap.String("State", "restore myDevId"))
}
}
}
rLen = 0
} else if buf[i] == '{' {
rBuf[0] = '{'
rLen = 1
} else {
rBuf[rLen] = buf[i]
if rLen < 512 {
rLen++
} else {
logger.Log.Warn("rBufOverrun:512",
zap.String("Src", "TCP-SERVER-connectionHandle"),
zap.Uint8s("RBuf", rBuf),
zap.Int("RLen", rLen),
// zap.Uint32("DevId", myDevID),
zap.String("Conn", conn.RemoteAddr().String()))
rLen = 0
}
}
}
}
}
. 编译成linux的可执行文件
. 编译成linux的可执行文件
1. set GOARCH=amd64
2. set GOOS=linux set GOOS=windows
3. go build -o TcpServer -ldflags "-w -s" main.go
windows编译 go build -o phoneDevServer.exe -ldflags "-w -s -H windowsgui" main.go
前台要打印 go build -ldflags "-w -s" main.go
linux 基本命令
rz 上传文件 (安装 yum install lrzsz)
chmod +x fileName 设置为可执行文件
nohup ./fileName & 后台运行
sz 下载文件
netstat -nltp 看端口
kill -9 进程号 杀掉进程
tail -10f Info_20210730.log 实时监视日志
rm -f fileName 删除文件
rm -f ./* 删除文件夹下所有文件
top 查看服务器占用情况
// 仅监视进程,修改filename和路径/root/XXXXX
#!/bin/bash
filename=TcpServer
port=50000
cnt=`netstat -tnlp|grep $port |grep -v grep |wc -l`
#cne=`ps -ef|grep $filename|grep -v grep |wc -l`
if [[ $cnt -eq 0 ]];then
cd /root/
nohup ./$filename &
fi
// 把.sh文件拷贝过去执行crontab -e,a进入编辑,第一行:* * * * * sleep 10;/bin/sh /root/watchtcpserver.sh,esc->:wq
// sh watchtcpserver.sh 直接执行脚本
// 监视端口和进程,修改filename和路径/root/XXXXX
#!/bin/bash
filename=TcpServer
port=50000
cnt=`netstat -tnlp|grep $port |grep -v grep |wc -l`
cne=`ps -ef|grep $filename|grep -v grep |wc -l`
if [[ $cnt -eq 0 ]] || [[ $cne -eq 0 ]];then
cd /root/
nohup ./$filename &
fi
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment