serial.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. // Close current connection.
  78. func (sf *serialPort) Close() (err error) {
  79. sf.mu.Lock()
  80. if sf.port != nil {
  81. err = sf.port.Close()
  82. sf.port = nil
  83. }
  84. sf.mu.Unlock()
  85. return
  86. }
  87. func (sf *serialPort) send(aduRequest []byte) error {
  88. var err error
  89. var tryCnt byte
  90. for {
  91. if _, err = sf.port.Write(aduRequest); err == nil {
  92. break
  93. }
  94. if sf.autoReconnect == 0 {
  95. break
  96. }
  97. for {
  98. if err = sf.connect(); err == nil {
  99. break
  100. }
  101. if tryCnt++; tryCnt <= sf.autoReconnect {
  102. return err //超过最大重试次数则退出
  103. }
  104. time.Sleep(1 * time.Second) //1秒后重试
  105. }
  106. }
  107. return err
  108. }
  109. func (sf *serialPort) recv(flag uint8) ([]byte, error) {
  110. var n int
  111. var aduResponse []byte
  112. var err error
  113. data := make([]byte, SerialReadMaxLength, SerialReadMaxLength)
  114. for {
  115. if n, err = sf.port.Read(data); err != nil {
  116. if VerifyCrc16(aduResponse, flag) {
  117. err = nil //读取完整
  118. break
  119. }
  120. break
  121. }
  122. if n > 0 {
  123. aduResponse = append(aduResponse, data[:n]...)
  124. if n <= SerialReadMaxLength { //读取少于等于SerialReadMaxLength字节,可能已经读完,判断CRC16确认
  125. if VerifyCrc16(aduResponse, flag) {
  126. break //读取完整
  127. }
  128. }
  129. } else if n == 0 {
  130. break
  131. }
  132. }
  133. return aduResponse, err
  134. }
  135. func (sf *serialPort) waitSendRecv(aduRequest []byte, flag uint8, wait uint) {
  136. var bytesToRead = 0
  137. if flag == 0 { //标准modbusRTU协议
  138. bytesToRead = modbus.CalculateResponseLength(aduRequest)
  139. } else if flag == 1 { //长和单灯控制器,zigbee协议
  140. bytesToRead = zigbee.CalculateChddjkZigbeeResponselength(aduRequest)
  141. }
  142. time.Sleep(sf.calculateDelay(len(aduRequest) + bytesToRead))
  143. if wait > 0 {
  144. time.Sleep(time.Duration(wait) * time.Millisecond)
  145. }
  146. }
  147. // SendRecvData 发送和接收
  148. func (sf *serialPort) SendRecvData(aduRequest []byte, flag uint8, wait uint) (aduResponse []byte, err error) {
  149. sf.mu.Lock()
  150. defer sf.mu.Unlock()
  151. //连接检查
  152. if !sf.isConnected() {
  153. //重试一次
  154. if err := sf.connect(); err != nil {
  155. return nil, ErrClosedConnection
  156. }
  157. }
  158. //发送请求
  159. if err := sf.send(aduRequest); err != nil {
  160. return nil, err
  161. }
  162. //等待发完和从机处理返回
  163. sf.waitSendRecv(aduRequest, flag, wait)
  164. //接收响应
  165. return sf.recv(flag)
  166. }
  167. // SendData 仅发送,用于广播
  168. func (sf *serialPort) SendData(aduRequest []byte, flag uint8, wait uint) error {
  169. sf.mu.Lock()
  170. defer sf.mu.Unlock()
  171. //连接检查
  172. if !sf.isConnected() {
  173. //重试一次
  174. if err := sf.connect(); err != nil {
  175. return ErrClosedConnection
  176. }
  177. }
  178. err := sf.send(aduRequest)
  179. if err == nil {
  180. sf.waitSendRecv(aduRequest, flag, wait) //等待发完
  181. }
  182. return err
  183. }
  184. func (sf *serialPort) calculateDelay(chars int) time.Duration {
  185. var characterDelay, frameDelay int // us
  186. if sf.BaudRate <= 0 || sf.BaudRate > 19200 {
  187. characterDelay = 750
  188. frameDelay = 1750
  189. } else {
  190. characterDelay = 15000000 / sf.BaudRate
  191. frameDelay = 35000000 / sf.BaudRate
  192. }
  193. return time.Duration(characterDelay*chars+frameDelay) * time.Microsecond
  194. }
  195. // VerifyCrc16 标准Modbus-RTU,末尾2字节是crc16,大端
  196. // 长和单灯控制器zigbee协议,末尾2字节是crc16
  197. func VerifyCrc16(data []byte, flag uint8) bool {
  198. if flag == FlagYm485 {
  199. return ym485.VerifySum(data)
  200. }
  201. datalen := len(data)
  202. if datalen > 4 {
  203. var crc_ uint16
  204. crc := modbus.CRC16(data[:datalen-2])
  205. if flag == FlagModbusRtu {
  206. crc_ = binary.LittleEndian.Uint16(data[datalen-2 : datalen])
  207. } else if flag == FlagChZigbee {
  208. crc_ = binary.BigEndian.Uint16(data[datalen-2 : datalen])
  209. } else {
  210. crc_ = binary.LittleEndian.Uint16(data[datalen-2 : datalen])
  211. }
  212. if crc == crc_ {
  213. return true
  214. }
  215. }
  216. return false
  217. }