You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

417 lines
8.3 KiB

  1. package lifx
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. "git.aiterp.net/lucifer/new-server/models"
  6. "math"
  7. "time"
  8. )
  9. type GetService struct{}
  10. func (p *GetService) Decode([]byte) error {
  11. return nil
  12. }
  13. func (p *GetService) Encode() []byte {
  14. return []byte{}
  15. }
  16. func (p *GetService) PacketType() uint16 {
  17. return 2
  18. }
  19. func (p *GetService) Flags() (ackRequired bool, resRequired bool) {
  20. return false, true
  21. }
  22. func (p *GetService) String() string {
  23. return "GetService()"
  24. }
  25. type GetVersion struct{}
  26. func (p *GetVersion) Decode([]byte) error {
  27. return nil
  28. }
  29. func (p *GetVersion) Encode() []byte {
  30. return []byte{}
  31. }
  32. func (p *GetVersion) PacketType() uint16 {
  33. return 32
  34. }
  35. func (p *GetVersion) Flags() (ackRequired bool, resRequired bool) {
  36. return false, true
  37. }
  38. func (p *GetVersion) String() string {
  39. return "GetVersion()"
  40. }
  41. type GetHostFirmware struct{}
  42. func (p *GetHostFirmware) Decode([]byte) error {
  43. return nil
  44. }
  45. func (p *GetHostFirmware) Encode() []byte {
  46. return []byte{}
  47. }
  48. func (p *GetHostFirmware) PacketType() uint16 {
  49. return 14
  50. }
  51. func (p *GetHostFirmware) Flags() (ackRequired bool, resRequired bool) {
  52. return false, true
  53. }
  54. func (p *GetHostFirmware) String() string {
  55. return "GetHostFirmware()"
  56. }
  57. type StateHostFirmware struct {
  58. BuildTime time.Time
  59. Major uint16
  60. Minor uint16
  61. }
  62. func (p *StateHostFirmware) Decode(data []byte) error {
  63. if len(data) < 20 {
  64. return models.ErrPayloadTooShort
  65. }
  66. ts := int64(binary.LittleEndian.Uint64(data[0:8]))
  67. p.BuildTime = time.Unix(ts/1000000000, ts%1000000000)
  68. p.Major = binary.LittleEndian.Uint16(data[16:18])
  69. p.Minor = binary.LittleEndian.Uint16(data[18:20])
  70. return nil
  71. }
  72. func (p *StateHostFirmware) Encode() []byte {
  73. var data [20]byte
  74. binary.LittleEndian.PutUint64(data[0:8], uint64(p.BuildTime.UnixNano()))
  75. binary.LittleEndian.PutUint16(data[16:18], p.Major)
  76. binary.LittleEndian.PutUint16(data[18:20], p.Minor)
  77. return data[:]
  78. }
  79. func (p *StateHostFirmware) PacketType() uint16 {
  80. return 15
  81. }
  82. func (p *StateHostFirmware) Flags() (ackRequired bool, resRequired bool) {
  83. return false, false
  84. }
  85. func (p *StateHostFirmware) String() string {
  86. return fmt.Sprintf("StateHostFirmware(major=%d, minor=%d, build=%s)", p.Major, p.Minor, p.BuildTime.Format(time.RFC3339))
  87. }
  88. type StateVersion struct {
  89. Vendor uint32
  90. Product uint32
  91. }
  92. func (p *StateVersion) Decode(data []byte) error {
  93. if len(data) < 8 {
  94. return models.ErrPayloadTooShort
  95. }
  96. p.Vendor = binary.LittleEndian.Uint32(data[0:4])
  97. p.Product = binary.LittleEndian.Uint32(data[4:8])
  98. return nil
  99. }
  100. func (p *StateVersion) Encode() []byte {
  101. var data [12]byte
  102. binary.LittleEndian.PutUint32(data[0:4], p.Vendor)
  103. binary.LittleEndian.PutUint32(data[4:8], p.Product)
  104. return data[:]
  105. }
  106. func (p *StateVersion) PacketType() uint16 {
  107. return 33
  108. }
  109. func (p *StateVersion) Flags() (ackRequired bool, resRequired bool) {
  110. return false, false
  111. }
  112. func (p *StateVersion) String() string {
  113. return fmt.Sprintf("StateVersion(vendor=%d, product=%d)", p.Vendor, p.Product)
  114. }
  115. type GetColor struct{}
  116. func (p *GetColor) Decode([]byte) error {
  117. return nil
  118. }
  119. func (p *GetColor) Encode() []byte {
  120. return []byte{}
  121. }
  122. func (p *GetColor) PacketType() uint16 {
  123. return 101
  124. }
  125. func (p *GetColor) Flags() (ackRequired bool, resRequired bool) {
  126. return false, true
  127. }
  128. func (p *GetColor) String() string {
  129. return "GetColor()"
  130. }
  131. type Acknowledgement struct{}
  132. func (p *Acknowledgement) Decode([]byte) error {
  133. return nil
  134. }
  135. func (p *Acknowledgement) Encode() []byte {
  136. return []byte{}
  137. }
  138. func (p *Acknowledgement) PacketType() uint16 {
  139. return 45
  140. }
  141. func (p *Acknowledgement) Flags() (ackRequired bool, resRequired bool) {
  142. return false, true
  143. }
  144. func (p *Acknowledgement) String() string {
  145. return "Acknowledgement()"
  146. }
  147. type SetColor struct {
  148. Hue float64
  149. Sat float64
  150. Bri float64
  151. Kelvin int
  152. TransitionTime time.Duration
  153. }
  154. func (p *SetColor) Decode(data []byte) error {
  155. if len(data) < 13 {
  156. return models.ErrPayloadTooShort
  157. }
  158. hue := binary.LittleEndian.Uint16(data[1:3])
  159. sat := binary.LittleEndian.Uint16(data[3:5])
  160. bri := binary.LittleEndian.Uint16(data[5:7])
  161. kelvin := binary.LittleEndian.Uint16(data[7:9])
  162. transitionMs := binary.LittleEndian.Uint32(data[9:13])
  163. p.Hue = float64(hue) / (65536 / 360)
  164. p.Sat = float64(sat) / 65535
  165. p.Bri = float64(bri) / 65535
  166. p.Kelvin = int(kelvin)
  167. p.TransitionTime = time.Duration(transitionMs) * time.Millisecond
  168. return nil
  169. }
  170. func (p *SetColor) Encode() []byte {
  171. var data [13]byte
  172. data[0] = 0x00 // reserved
  173. binary.LittleEndian.PutUint16(data[1:3], uint16(math.Mod(p.Hue, 360)*(65536/360)))
  174. binary.LittleEndian.PutUint16(data[3:5], uint16(p.Sat*65535))
  175. binary.LittleEndian.PutUint16(data[5:7], uint16(p.Bri*65535))
  176. binary.LittleEndian.PutUint16(data[7:9], uint16(p.Kelvin))
  177. binary.LittleEndian.PutUint32(data[9:13], uint32(p.TransitionTime.Milliseconds()))
  178. return data[:]
  179. }
  180. func (p *SetColor) PacketType() uint16 {
  181. return 102
  182. }
  183. func (p *SetColor) Flags() (ackRequired bool, resRequired bool) {
  184. return true, false
  185. }
  186. func (p *SetColor) String() string {
  187. return fmt.Sprintf("SetColor(hsvk={%f, %f, %f, %d}, ttime=%s)",
  188. p.Hue,
  189. p.Sat,
  190. p.Bri,
  191. p.Kelvin,
  192. p.TransitionTime,
  193. )
  194. }
  195. type SetLightPower struct {
  196. On bool
  197. TransitionTime time.Duration
  198. }
  199. func (p *SetLightPower) Decode(data []byte) error {
  200. if len(data) < 6 {
  201. return models.ErrPayloadTooShort
  202. }
  203. level := binary.LittleEndian.Uint16(data[0:2])
  204. transitionMs := binary.LittleEndian.Uint32(data[2:6])
  205. p.On = level > 0
  206. p.TransitionTime = time.Duration(transitionMs) * time.Millisecond
  207. return nil
  208. }
  209. func (p *SetLightPower) Encode() []byte {
  210. var data [6]byte
  211. if p.On {
  212. data[0], data[1] = 0xff, 0xff
  213. } else {
  214. data[0], data[1] = 0x00, 0x00
  215. }
  216. binary.LittleEndian.PutUint32(data[2:6], uint32(p.TransitionTime.Milliseconds()))
  217. return data[:]
  218. }
  219. func (p *SetLightPower) PacketType() uint16 {
  220. return 117
  221. }
  222. func (p *SetLightPower) Flags() (ackRequired bool, resRequired bool) {
  223. return true, false
  224. }
  225. func (p *SetLightPower) String() string {
  226. return fmt.Sprintf("SetLightPower(on=%t, ttime=%s)",
  227. p.On,
  228. p.TransitionTime,
  229. )
  230. }
  231. type StateService struct {
  232. Service int
  233. Port int
  234. }
  235. func (p *StateService) String() string {
  236. return fmt.Sprintf("StateService(service=%d, port=%d)", p.Service, p.Port)
  237. }
  238. func (p *StateService) Decode(data []byte) error {
  239. if len(data) < 5 {
  240. return models.ErrPayloadTooShort
  241. }
  242. p.Service = int(data[0])
  243. p.Port = int(binary.LittleEndian.Uint32(data[1:5]))
  244. return nil
  245. }
  246. func (p *StateService) Encode() []byte {
  247. var data [5]byte
  248. data[0] = uint8(p.Service)
  249. binary.LittleEndian.PutUint32(data[1:5], uint32(p.Port))
  250. return data[:]
  251. }
  252. func (p *StateService) PacketType() uint16 {
  253. return 3
  254. }
  255. func (p *StateService) Flags() (ackRequired bool, resRequired bool) {
  256. return false, false
  257. }
  258. type LightState struct {
  259. Hue float64
  260. Sat float64
  261. Bri float64
  262. Kelvin int
  263. On bool
  264. Label string
  265. }
  266. func (p *LightState) String() string {
  267. return fmt.Sprintf("LightState(hsvk=(%f, %f, %f, %d), on=%t, label=%+v)",
  268. p.Hue, p.Sat, p.Bri, p.Kelvin,
  269. p.On, p.Label,
  270. )
  271. }
  272. func (p *LightState) Decode(data []byte) error {
  273. if len(data) < 52 {
  274. return models.ErrPayloadTooShort
  275. }
  276. hue := binary.LittleEndian.Uint16(data[0:2])
  277. sat := binary.LittleEndian.Uint16(data[2:4])
  278. bri := binary.LittleEndian.Uint16(data[4:6])
  279. kelvin := binary.LittleEndian.Uint16(data[6:8])
  280. power := binary.LittleEndian.Uint16(data[10:12])
  281. p.Hue = float64(hue) / (65536 / 360)
  282. p.Sat = float64(sat) / 65535
  283. p.Bri = float64(bri) / 65535
  284. p.Kelvin = int(kelvin)
  285. p.On = power > 32767
  286. p.Label = ""
  287. for i, v := range data[14:46] {
  288. if v == 0 {
  289. p.Label = string(data[14 : 14+i])
  290. break
  291. }
  292. }
  293. return nil
  294. }
  295. func (p *LightState) Encode() []byte {
  296. var data [52]byte
  297. power := uint16(0)
  298. if p.On {
  299. power = 0xffff
  300. }
  301. binary.LittleEndian.PutUint16(data[0:2], uint16(math.Mod(p.Hue, 360)*(65536/360)))
  302. binary.LittleEndian.PutUint16(data[2:4], uint16(p.Sat*65535))
  303. binary.LittleEndian.PutUint16(data[4:6], uint16(p.Bri*65535))
  304. binary.LittleEndian.PutUint16(data[6:8], uint16(p.Kelvin))
  305. binary.LittleEndian.PutUint16(data[10:12], power)
  306. label := p.Label
  307. labelBytes := []byte(label)
  308. for len(labelBytes) > 31 {
  309. label = label[:len(label)-1]
  310. labelBytes = []byte(label)
  311. }
  312. copy(data[14:], labelBytes)
  313. return data[:]
  314. }
  315. func (p *LightState) PacketType() uint16 {
  316. return 107
  317. }
  318. func (p *LightState) Flags() (ackRequired bool, resRequired bool) {
  319. return false, false
  320. }