client.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package server
  2. import (
  3. "bth-rs30-gateway/protocol"
  4. "bytes"
  5. "encoding/binary"
  6. "errors"
  7. "fmt"
  8. "github.com/gogf/gf/encoding/gbinary"
  9. "github.com/gogf/gf/net/gtcp"
  10. "github.com/gogf/gf/os/glog"
  11. "github.com/gogf/gf/util/gconv"
  12. "io"
  13. "net"
  14. "strconv"
  15. "strings"
  16. "syscall"
  17. "time"
  18. )
  19. type Client struct {
  20. Id string
  21. srv *Server
  22. conn *gtcp.Conn
  23. sendChan chan []byte
  24. closeChan chan struct{}
  25. closeHandler func(id string, c *Client)
  26. regHandler func(id string, c *Client)
  27. isReg bool
  28. }
  29. func NewClient(s *Server, conn *gtcp.Conn) *Client {
  30. return &Client{
  31. srv: s,
  32. conn: conn,
  33. sendChan: make(chan []byte),
  34. closeChan: make(chan struct{}),
  35. }
  36. }
  37. func (c *Client) SetId(id string) {
  38. c.Id = id
  39. }
  40. func (c *Client) SendLoop() {
  41. for {
  42. select {
  43. case buf := <-c.sendChan:
  44. err := c.send(buf)
  45. if err != nil {
  46. glog.Errorf("指令发送失败:%s", err.Error())
  47. continue
  48. }
  49. timer := time.NewTimer(5 * time.Second)
  50. for {
  51. timer.Reset(5 * time.Second)
  52. select {
  53. case <-timer.C:
  54. glog.Error("接收指令超时")
  55. break
  56. default:
  57. receiveBuf, err := c.conn.Recv(-1)
  58. if err != nil {
  59. c.readError(err)
  60. break
  61. }
  62. if !c.isReg {
  63. id := gbinary.DecodeToString(receiveBuf)
  64. glog.Debugf("收到注册包!id:%s", id)
  65. c.SetId(id)
  66. c.isReg = true
  67. if c.regHandler != nil {
  68. c.regHandler(c.Id, c)
  69. }
  70. break
  71. }
  72. glog.Debugf("收到数据:%2X", receiveBuf)
  73. if err := c.decodeAndReport(receiveBuf); err != nil {
  74. glog.Debugf("处理数据失败:%s", err.Error())
  75. break
  76. }
  77. }
  78. break
  79. }
  80. }
  81. }
  82. }
  83. // 收到数据:01 03 04 00 FD 00 8A EA 64
  84. func (c *Client) decodeAndReport(buf []byte) error {
  85. length := len(buf)
  86. var crc crc
  87. crc.reset().pushBytes(buf[0 : length-2])
  88. checksum := uint16(buf[length-1])<<8 | uint16(buf[length-2])
  89. if checksum != crc.value() {
  90. return errors.New(fmt.Sprintf("modbus: response crc '%v' does not match expected '%v'", checksum, crc.value()))
  91. }
  92. if buf[1] == 0x03 {
  93. data := &protocol.Data{}
  94. data.Temperature = gconv.Float32(caleTemperature(buf[3:5])) * 0.1
  95. data.Humidly = gconv.Float32(gbinary.BeDecodeToUint16(buf[5:7])) * 0.1
  96. if err := c.srv.ReportStatus(c.Id, data); err != nil {
  97. return err
  98. }
  99. }
  100. return nil
  101. }
  102. func (c *Client) readError(err error) {
  103. defer c.closeConnection()
  104. if err == io.EOF || isErrConnReset(err) {
  105. return
  106. }
  107. glog.Errorf("读取数据发生错误:%s", err.Error())
  108. }
  109. func (c *Client) closeConnection() {
  110. _ = c.conn.Close()
  111. c.conn = nil
  112. close(c.closeChan)
  113. c.SetId("")
  114. c.isReg = false
  115. if c.closeHandler != nil {
  116. c.closeHandler(c.Id, c)
  117. }
  118. }
  119. // 计算温度值, 处理零下的情况
  120. func caleTemperature(data []byte) int {
  121. var ym uint16
  122. var isBlowZero bool
  123. var result int
  124. bm := binary.BigEndian.Uint16(data)
  125. var bitNum = len(data) * 8
  126. f := "%." + strconv.Itoa(bitNum) + "b"
  127. bmStr := fmt.Sprintf(f, bm)
  128. if string(bmStr[0]) == "1" { // blow zero
  129. ym = ^bm + 1
  130. isBlowZero = true
  131. } else {
  132. ym = bm
  133. }
  134. result = int(ym)
  135. if isBlowZero {
  136. result = int(ym) * -1
  137. }
  138. return result
  139. }
  140. // isErrConnReset read: connection reset by peer
  141. func isErrConnReset(err error) bool {
  142. if ne, ok := err.(*net.OpError); ok {
  143. return strings.Contains(ne.Err.Error(), syscall.ECONNRESET.Error())
  144. }
  145. return false
  146. }
  147. // SetOffset 设置温湿度偏移值
  148. func (c *Client) SetOffset(act, value, slaveId int) error {
  149. var sendBuf []byte
  150. buffer := bytes.NewBuffer(sendBuf)
  151. buffer.Write(gbinary.BeEncodeInt(slaveId))
  152. var funcByte byte
  153. var address []byte
  154. if act == 1 || act == 3 {
  155. funcByte = 0x10
  156. address = []byte{0x00, 0x50}
  157. }
  158. if act == 2 || act == 4 {
  159. funcByte = 0x06
  160. address = []byte{0x00, 0x52}
  161. }
  162. buffer.WriteByte(funcByte)
  163. buffer.Write(address)
  164. if act == 1 || act == 3 {
  165. number := []byte{0x00, 0x02}
  166. buffer.Write(number)
  167. buffer.Write([]byte{0x00, 0x01})
  168. buffer.Write(dataBlock(value))
  169. } else if act == 2 || act == 4 {
  170. buffer.Write([]byte{0x00, 0x00})
  171. }
  172. var mCrc crc
  173. checkSum := mCrc.reset().pushBytes(buffer.Bytes()).value()
  174. buffer.Write([]byte{byte(checkSum), byte(checkSum >> 8)})
  175. return c.send(buffer.Bytes())
  176. }
  177. func dataBlock(value int) []byte {
  178. buffer := &bytes.Buffer{}
  179. if value < 0 {
  180. buffer.WriteByte(0xFF)
  181. } else {
  182. buffer.WriteByte(0x00)
  183. }
  184. buffer.Write(gbinary.BeEncodeInt(value))
  185. return buffer.Bytes()
  186. }
  187. func (c *Client) GetSendByte() {
  188. for {
  189. c.sendChan <- []byte{0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B}
  190. time.Sleep(10 * time.Second)
  191. }
  192. }
  193. func (c *Client) send(buf []byte) error {
  194. if c.conn == nil {
  195. return nil
  196. }
  197. glog.Debugf("----->%2X", buf)
  198. err := c.conn.Send(buf)
  199. if err != nil {
  200. glog.Error(c.srv.ctx, err)
  201. c.closeConnection()
  202. return err
  203. }
  204. return nil
  205. }