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.

265 lines
6.9 KiB

  1. package hue2
  2. import (
  3. "encoding/xml"
  4. "fmt"
  5. "git.aiterp.net/lucifer/new-server/models"
  6. "strings"
  7. "time"
  8. )
  9. type DeviceData struct {
  10. ID string `json:"id"`
  11. LegacyID string `json:"id_v1"`
  12. Metadata DeviceMetadata `json:"metadata"`
  13. Type string `json:"type"`
  14. ProductData DeviceProductData `json:"product_data"`
  15. Services []ResourceLink `json:"services"`
  16. }
  17. type DeviceMetadata struct {
  18. Archetype string `json:"archetype"`
  19. Name string `json:"name"`
  20. }
  21. type DeviceProductData struct {
  22. Certified bool `json:"certified"`
  23. ManufacturerName string `json:"manufacturer_name"`
  24. ModelID string `json:"model_id"`
  25. ProductArchetype string `json:"product_archetype"`
  26. ProductName string `json:"product_name"`
  27. SoftwareVersion string `json:"software_version"`
  28. }
  29. type SSEUpdate struct {
  30. CreationTime time.Time `json:"creationTime"`
  31. ID string `json:"id"`
  32. Type string `json:"type"`
  33. Data []ResourceData `json:"data"`
  34. }
  35. type ResourceData struct {
  36. ID string `json:"id"`
  37. LegacyID string `json:"id_v1"`
  38. Metadata DeviceMetadata `json:"metadata"`
  39. Type string `json:"type"`
  40. Mode *string `json:"mode"`
  41. Owner *ResourceLink `json:"owner"`
  42. ProductData *DeviceProductData `json:"product_data"`
  43. Services []ResourceLink `json:"services"`
  44. Button *SensorButton `json:"button"`
  45. Power *LightPower `json:"on"`
  46. Color *LightColor `json:"color"`
  47. ColorTemperature *LightCT `json:"color_temperature"`
  48. Dimming *LightDimming `json:"dimming"`
  49. Dynamics *LightDynamics `json:"dynamics"`
  50. Alert *LightAlert `json:"alert"`
  51. PowerState *PowerState `json:"power_state"`
  52. Temperature *SensorTemperature `json:"temperature"`
  53. Motion *SensorMotion `json:"motion"`
  54. Status *string `json:"status"`
  55. }
  56. func (res *ResourceData) ServiceID(kind string) *string {
  57. for _, ptr := range res.Services {
  58. if ptr.Kind == kind {
  59. return &ptr.ID
  60. }
  61. }
  62. return nil
  63. }
  64. func (res *ResourceData) ServiceIndex(kind string, id string) int {
  65. idx := 0
  66. for _, link := range res.Services {
  67. if link.ID == id {
  68. return idx
  69. } else if link.Kind == kind {
  70. idx += 1
  71. }
  72. }
  73. return -1
  74. }
  75. func (res *ResourceData) WithUpdate(update ResourceUpdate) *ResourceData {
  76. resCopy := *res
  77. if update.Power != nil {
  78. cp := *resCopy.Power
  79. resCopy.Power = &cp
  80. resCopy.Power.On = *update.Power
  81. }
  82. if update.ColorXY != nil {
  83. cp := *resCopy.Color
  84. resCopy.Color = &cp
  85. resCopy.Color.XY = *update.ColorXY
  86. }
  87. if update.Mirek != nil {
  88. cp := *resCopy.ColorTemperature
  89. resCopy.ColorTemperature = &cp
  90. mirek := *update.Mirek
  91. resCopy.ColorTemperature.Mirek = &mirek
  92. }
  93. if update.Brightness != nil {
  94. cp := *resCopy.Dimming
  95. resCopy.Dimming = &cp
  96. resCopy.Dimming.Brightness = *update.Brightness
  97. }
  98. return &resCopy
  99. }
  100. type SensorButton struct {
  101. LastEvent string `json:"last_event"`
  102. }
  103. type SensorMotion struct {
  104. Motion bool `json:"motion"`
  105. Valid bool `json:"motion_valid"`
  106. }
  107. type SensorTemperature struct {
  108. Temperature float64 `json:"temperature"`
  109. Valid bool `json:"temperature_valid"`
  110. }
  111. type PowerState struct {
  112. BatteryState string `json:"battery_state"`
  113. BatteryLevel float64 `json:"battery_level"`
  114. }
  115. type LightPower struct {
  116. On bool `json:"on"`
  117. }
  118. type LightDimming struct {
  119. Brightness float64 `json:"brightness"`
  120. }
  121. type LightColor struct {
  122. Gamut models.ColorGamut `json:"gamut"`
  123. GamutType string `json:"gamut_type"`
  124. XY models.ColorXY `json:"xy"`
  125. }
  126. type LightCT struct {
  127. Mirek *int `json:"mirek"`
  128. MirekSchema LightCTMirekSchema `json:"mirek_schema"`
  129. MirekValid bool `json:"mirek_valid"`
  130. }
  131. type LightCTMirekSchema struct {
  132. MirekMaximum int `json:"mirek_maximum"`
  133. MirekMinimum int `json:"mirek_minimum"`
  134. }
  135. type LightDynamics struct {
  136. Speed float64 `json:"speed"`
  137. SpeedValid bool `json:"speed_valid"`
  138. Status string `json:"status"`
  139. StatusValues []string `json:"status_values"`
  140. }
  141. type LightAlert struct {
  142. ActionValues []string `json:"action_values"`
  143. }
  144. type ResourceUpdate struct {
  145. Power *bool
  146. ColorXY *models.ColorXY
  147. Brightness *float64
  148. Mirek *int
  149. TransitionDuration *time.Duration
  150. }
  151. func (r ResourceUpdate) MarshalJSON() ([]byte, error) {
  152. chunks := make([]string, 0, 4)
  153. if r.Power != nil {
  154. chunks = append(chunks, fmt.Sprintf(`"on":{"on":%v}`, *r.Power))
  155. }
  156. if r.ColorXY != nil {
  157. chunks = append(chunks, fmt.Sprintf(`"color":{"xy":{"x":%f,"y":%f}}`, r.ColorXY.X, r.ColorXY.Y))
  158. }
  159. if r.Brightness != nil {
  160. chunks = append(chunks, fmt.Sprintf(`"dimming":{"brightness":%f}`, *r.Brightness))
  161. }
  162. if r.Mirek != nil {
  163. chunks = append(chunks, fmt.Sprintf(`"color_temperature":{"mirek":%d}`, *r.Mirek))
  164. }
  165. if r.TransitionDuration != nil {
  166. chunks = append(chunks, fmt.Sprintf(`"dynamics":{"duration":%d}`, r.TransitionDuration.Truncate(time.Millisecond*100).Milliseconds()))
  167. }
  168. return []byte(fmt.Sprintf("{%s}", strings.Join(chunks, ","))), nil
  169. }
  170. type ResourceLink struct {
  171. ID string `json:"rid"`
  172. Kind string `json:"rtype"`
  173. }
  174. func (rl *ResourceLink) Path() string {
  175. return fmt.Sprintf("/clip/v2/resource/%s/%s", rl.Kind, rl.ID)
  176. }
  177. type CreateUserInput struct {
  178. DeviceType string `json:"devicetype"`
  179. }
  180. type CreateUserResponse struct {
  181. Success *struct {
  182. Username string `json:"username"`
  183. } `json:"success"`
  184. Error *struct {
  185. Type int `json:"type"`
  186. Address string `json:"address"`
  187. Description string `json:"description"`
  188. } `json:"error"`
  189. }
  190. type DiscoveryEntry struct {
  191. Id string `json:"id"`
  192. InternalIPAddress string `json:"internalipaddress"`
  193. }
  194. type BridgeDeviceInfo struct {
  195. XMLName xml.Name `xml:"root"`
  196. Text string `xml:",chardata"`
  197. Xmlns string `xml:"xmlns,attr"`
  198. SpecVersion struct {
  199. Text string `xml:",chardata"`
  200. Major string `xml:"major"`
  201. Minor string `xml:"minor"`
  202. } `xml:"specVersion"`
  203. URLBase string `xml:"URLBase"`
  204. Device struct {
  205. Text string `xml:",chardata"`
  206. DeviceType string `xml:"deviceType"`
  207. FriendlyName string `xml:"friendlyName"`
  208. Manufacturer string `xml:"manufacturer"`
  209. ManufacturerURL string `xml:"manufacturerURL"`
  210. ModelDescription string `xml:"modelDescription"`
  211. ModelName string `xml:"modelName"`
  212. ModelNumber string `xml:"modelNumber"`
  213. ModelURL string `xml:"modelURL"`
  214. SerialNumber string `xml:"serialNumber"`
  215. UDN string `xml:"UDN"`
  216. PresentationURL string `xml:"presentationURL"`
  217. IconList struct {
  218. Text string `xml:",chardata"`
  219. Icon struct {
  220. Text string `xml:",chardata"`
  221. Mimetype string `xml:"mimetype"`
  222. Height string `xml:"height"`
  223. Width string `xml:"width"`
  224. Depth string `xml:"depth"`
  225. URL string `xml:"url"`
  226. } `xml:"icon"`
  227. } `xml:"iconList"`
  228. } `xml:"device"`
  229. }