service.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package switchRelay
  2. import (
  3. "encoding/hex"
  4. "github.com/valyala/bytebufferpool"
  5. )
  6. func (x DataPack) GetSwitchRelayCommand() *bytebufferpool.ByteBuffer {
  7. buf := bytebufferpool.Get()
  8. x.Function = 0x05
  9. decodeAddress, _ := hex.DecodeString(x.Address)
  10. buf.Write(decodeAddress)
  11. buf.WriteByte(x.Function)
  12. buf.Write([]byte{0x00, byte(x.Way - 1)})
  13. if x.Command == 1 {
  14. buf.Write([]byte{0xFF, 0x00})
  15. } else {
  16. buf.Write([]byte{0x00, 0x00})
  17. }
  18. x.Crc = calculateCRC16Modbus(buf.Bytes())
  19. buf.Write([]byte{byte(x.Crc & 0xFF), byte(x.Crc >> 8)})
  20. return buf
  21. }
  22. func (x MultiLoopDataPack) GetControlMuchSwitchRelayCommand() *bytebufferpool.ByteBuffer {
  23. buf := bytebufferpool.Get()
  24. x.Function = 0x10
  25. decodeAddress, _ := hex.DecodeString(x.Address)
  26. buf.Write(decodeAddress)
  27. buf.WriteByte(x.Function)
  28. if x.TurnOff == 1 { //控制多路打开
  29. buf.Write([]byte{0x04, 0x1A, 0x00, 0x02, 0x04, 0x00})
  30. } else if x.TurnOff == 0 { //控制多路关闭
  31. buf.Write([]byte{0x04, 0x1C, 0x00, 0x02, 0x04, 0x00})
  32. } else { //控制多路取反
  33. buf.Write([]byte{0x04, 0x1E, 0x00, 0x02, 0x04, 0x00})
  34. }
  35. buf.Write(generateHexSwitchState(x.State))
  36. x.Command = []byte{0x00, 0x00}
  37. buf.Write(x.Command)
  38. x.Crc = calculateCRC16Modbus(buf.Bytes())
  39. buf.Write([]byte{byte(x.Crc & 0xFF), byte(x.Crc >> 8)})
  40. return buf
  41. }
  42. func calculateCRC16Modbus(data []byte) uint16 {
  43. var crc uint16 = 0xFFFF // CRC-16 初始化值
  44. for _, byteVal := range data {
  45. crc ^= uint16(byteVal) // 对字节进行异或操作
  46. for i := 0; i < 8; i++ {
  47. if crc&0x0001 != 0 {
  48. crc >>= 1
  49. crc ^= 0xA001 // 多项式 0xA001
  50. } else {
  51. crc >>= 1
  52. }
  53. }
  54. }
  55. return crc
  56. }
  57. func generateHexSwitchState(switches []int) []byte {
  58. var state int
  59. // 遍历切片,设置对应位置的开关为 1
  60. for _, s := range switches {
  61. state |= 1 << (s - 1) // 设置第s位为1,s从1开始
  62. }
  63. // 返回字节切片,使用 []byte{} 来包裹十六进制值
  64. return []byte{byte(state)}
  65. }