serial.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. package main
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "io"
  6. "sync"
  7. "time"
  8. "github.com/goburrow/serial"
  9. "lc/edge/ipole/modbus"
  10. "lc/edge/ipole/ym485"
  11. "lc/edge/ipole/zigbee"
  12. )
  13. const (
  14. // SerialDefaultTimeout Serial Default timeout
  15. SerialDefaultTimeout = 2000 * time.Millisecond
  16. // SerialDefaultAutoReconnect Serial Default auto reconnect count
  17. SerialDefaultAutoReconnect = 6
  18. SerialReadMaxLength = 40
  19. FlagModbusRtu = 0
  20. FlagChZigbee = 1
  21. FlagYm485 = 2
  22. )
  23. var ErrClosedConnection = errors.New("use of closed connection")
  24. // serialPort has configuration and I/O controller.
  25. type serialPort struct {
  26. // Serial port configuration.
  27. serial.Config
  28. mu sync.Mutex
  29. port io.ReadWriteCloser
  30. // if > 0, when disconnected,it will try to reconnect the remote
  31. // but if we activate close self,it will not to reconnect
  32. // if == 0 auto reconnect not active
  33. autoReconnect byte
  34. }
  35. // Connect try to connect the remote server
  36. func (sf *serialPort) Connect() (err error) {
  37. sf.mu.Lock()
  38. err = sf.connect()
  39. sf.mu.Unlock()
  40. return
  41. }
  42. // Caller must hold the mutex before calling this method.
  43. func (sf *serialPort) connect() error {
  44. port, err := serial.Open(&sf.Config)
  45. if err != nil {
  46. return err
  47. }
  48. sf.port = port
  49. return nil
  50. }
  51. // IsConnected returns a bool signifying whether the client is connected or not.
  52. func (sf *serialPort) IsConnected() (b bool) {
  53. sf.mu.Lock()
  54. b = sf.isConnected()
  55. sf.mu.Unlock()
  56. return b
  57. }
  58. // Caller must hold the mutex before calling this method.
  59. func (sf *serialPort) isConnected() bool {
  60. return sf.port != nil
  61. }
  62. // SetAutoReconnect set auto reconnect count
  63. // if cnt == 0, disable auto reconnect
  64. // if cnt > 0 ,enable auto reconnect,but max 6
  65. func (sf *serialPort) SetAutoReconnect(cnt byte) {
  66. sf.mu.Lock()
  67. sf.autoReconnect = cnt
  68. if sf.autoReconnect > 6 {
  69. sf.autoReconnect = 6
  70. }
  71. sf.mu.Unlock()
  72. }
  73. // setSerialConfig set serial config
  74. func (sf *serialPort) setSerialConfig(config serial.Config) {
  75. sf.Config = config
  76. }
  77. func (sf *serialPort) setTCPTimeout(time.Duration) {}
  78. // Close current connection.
  79. func (sf *serialPort) Close() (err error) {
  80. sf.mu.Lock()
  81. if sf.port != nil {
  82. err = sf.port.Close()
  83. sf.port = nil
  84. }
  85. sf.mu.Unlock()
  86. return
  87. }
  88. func (sf *serialPort) send(aduRequest []byte) error {
  89. var err error
  90. var tryCnt byte
  91. for {
  92. if _, err = sf.port.Write(aduRequest); err == nil {
  93. break
  94. }
  95. if sf.autoReconnect == 0 {
  96. break
  97. }
  98. for {
  99. if err = sf.connect(); err == nil {
  100. break
  101. }
  102. if tryCnt++; tryCnt <= sf.autoReconnect {
  103. return err //超过最大重试次数则退出
  104. }
  105. time.Sleep(1 * time.Second) //1秒后重试
  106. }
  107. }
  108. return err
  109. }
  110. func (sf *serialPort) recv(flag uint8) ([]byte, error) {
  111. var n int
  112. var aduResponse []byte
  113. var err error
  114. data := make([]byte, SerialReadMaxLength, SerialReadMaxLength)
  115. for {
  116. if n, err = sf.port.Read(data); err != nil {
  117. if VerifyCrc16(aduResponse, flag) {
  118. err = nil //读取完整
  119. break
  120. }
  121. break
  122. }
  123. if n > 0 {
  124. aduResponse = append(aduResponse, data[:n]...)
  125. if n <= SerialReadMaxLength { //读取少于等于SerialReadMaxLength字节,可能已经读完,判断CRC16确认
  126. if VerifyCrc16(aduResponse, flag) {
  127. break //读取完整
  128. }
  129. }
  130. } else if n == 0 {
  131. break
  132. }
  133. }
  134. return aduResponse, err
  135. }
  136. func (sf *serialPort) waitSendRecv(aduRequest []byte, flag uint8, wait uint) {
  137. var bytesToRead = 0
  138. if flag == 0 { //标准modbusRTU协议
  139. bytesToRead = modbus.CalculateResponseLength(aduRequest)
  140. } else if flag == 1 { //长和单灯控制器,zigbee协议
  141. bytesToRead = zigbee.CalculateChddjkZigbeeResponselength(aduRequest)
  142. }
  143. time.Sleep(sf.calculateDelay(len(aduRequest) + bytesToRead))
  144. if wait > 0 {
  145. time.Sleep(time.Duration(wait) * time.Millisecond)
  146. }
  147. }
  148. // SendRecvData 发送和接收
  149. func (sf *serialPort) SendRecvData(aduRequest []byte, flag uint8, wait uint) (aduResponse []byte, err error) {
  150. sf.mu.Lock()
  151. defer sf.mu.Unlock()
  152. //连接检查
  153. if !sf.isConnected() {
  154. //重试一次
  155. if err := sf.connect(); err != nil {
  156. return nil, ErrClosedConnection
  157. }
  158. }
  159. //发送请求
  160. if err := sf.send(aduRequest); err != nil {
  161. return nil, err
  162. }
  163. //等待发完和从机处理返回
  164. sf.waitSendRecv(aduRequest, flag, wait)
  165. //接收响应
  166. return sf.recv(flag)
  167. }
  168. // SendData 仅发送,用于广播
  169. func (sf *serialPort) SendData(aduRequest []byte, flag uint8, wait uint) error {
  170. sf.mu.Lock()
  171. defer sf.mu.Unlock()
  172. //连接检查
  173. if !sf.isConnected() {
  174. //重试一次
  175. if err := sf.connect(); err != nil {
  176. return ErrClosedConnection
  177. }
  178. }
  179. err := sf.send(aduRequest)
  180. if err == nil {
  181. sf.waitSendRecv(aduRequest, flag, wait) //等待发完
  182. }
  183. return err
  184. }
  185. func (sf *serialPort) calculateDelay(chars int) time.Duration {
  186. var characterDelay, frameDelay int // us
  187. if sf.BaudRate <= 0 || sf.BaudRate > 19200 {
  188. characterDelay = 750
  189. frameDelay = 1750
  190. } else {
  191. characterDelay = 15000000 / sf.BaudRate
  192. frameDelay = 35000000 / sf.BaudRate
  193. }
  194. return time.Duration(characterDelay*chars+frameDelay) * time.Microsecond
  195. }
  196. // VerifyCrc16 标准Modbus-RTU,末尾2字节是crc16,大端
  197. // 长和单灯控制器zigbee协议,末尾2字节是crc16
  198. func VerifyCrc16(data []byte, flag uint8) bool {
  199. if flag == FlagYm485 {
  200. return ym485.VerifySum(data)
  201. }
  202. datalen := len(data)
  203. if datalen > 4 {
  204. var crc_ uint16
  205. crc := modbus.CRC16(data[:datalen-2])
  206. if flag == FlagModbusRtu {
  207. crc_ = binary.LittleEndian.Uint16(data[datalen-2 : datalen])
  208. } else if flag == FlagChZigbee {
  209. crc_ = binary.BigEndian.Uint16(data[datalen-2 : datalen])
  210. } else {
  211. crc_ = binary.LittleEndian.Uint16(data[datalen-2 : datalen])
  212. }
  213. if crc == crc_ {
  214. return true
  215. }
  216. }
  217. return false
  218. }