hdsv2.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package hdsv2
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. "imuslab.com/arozos/mod/iot"
  11. "imuslab.com/arozos/mod/network/mdns"
  12. )
  13. /*
  14. Home Dynamic 2 Controller
  15. This is a module that handles HDSv2 protocol devices scannings
  16. */
  17. type Handler struct {
  18. scanner *mdns.MDNSHost
  19. historyList []*iot.Device
  20. lastScanTime int64
  21. }
  22. //Create a new HDSv2 Protocol Handler
  23. func NewProtocolHandler(scanner *mdns.MDNSHost) *Handler {
  24. //Create a new MDNS Host
  25. return &Handler{
  26. scanner,
  27. []*iot.Device{},
  28. 0,
  29. }
  30. }
  31. //Scan the devices within the LAN
  32. func (h *Handler) Scan() ([]*iot.Device, error) {
  33. foundDevices := []*iot.Device{}
  34. hosts := h.scanner.Scan(3, "hds.arozos.com")
  35. for _, host := range hosts {
  36. thisDevice := iot.Device{
  37. Name: host.HostName,
  38. Port: host.Port,
  39. Model: host.Model,
  40. Version: host.BuildVersion + "-" + host.MinorVersion,
  41. Manufacturer: host.Vendor,
  42. DeviceUUID: host.UUID,
  43. IPAddr: host.IPv4[0].String(),
  44. RequireAuth: false,
  45. RequireConnect: false,
  46. Status: map[string]interface{}{},
  47. }
  48. //Try to get the device status
  49. status, err := getStatusForDevice(&thisDevice)
  50. if err != nil {
  51. //This might be not a valid HDSv2 device. Skip this
  52. log.Println("*HDSv2* Get status failed for device: ", host.HostName, err.Error())
  53. continue
  54. }
  55. thisDevice.Status = status
  56. //Get the device content endpoints
  57. eps, err := getEndpoints(&thisDevice)
  58. if err != nil {
  59. //This might be not a valid HDSv2 device. Skip this
  60. log.Println("*HDSv2* Get endpoints failed for device: ", host.HostName, err.Error())
  61. continue
  62. }
  63. thisDevice.ControlEndpoints = eps
  64. //Push this host into found device list
  65. foundDevices = append(foundDevices, &thisDevice)
  66. }
  67. h.historyList = foundDevices
  68. return foundDevices, nil
  69. }
  70. //Return the history scan list from the handler
  71. func (h *Handler) List() ([]*iot.Device, error) {
  72. return h.historyList, nil
  73. }
  74. //Home Dynamic system's devices no need to established conenction before executing anything
  75. func (h *Handler) Connect(device *iot.Device) error {
  76. return nil
  77. }
  78. //Same rules also apply to disconnect
  79. func (h *Handler) Disconnect(device *iot.Device) error {
  80. return nil
  81. }
  82. //Get the status of the device
  83. func (h *Handler) Status(device *iot.Device) (map[string]interface{}, error) {
  84. return getStatusForDevice(device)
  85. }
  86. //Get the status of the device
  87. func (h *Handler) Execute(device *iot.Device, endpoint *iot.Endpoint, payload interface{}) (interface{}, error) {
  88. var result interface{}
  89. return result, nil
  90. }
  91. //Get endpoint of the given device object
  92. func getEndpoints(device *iot.Device) ([]*iot.Endpoint, error) {
  93. //Parse the URL of the endpoint apis location (eps)
  94. requestURL := "http://" + device.IPAddr + ":" + strconv.Itoa(device.Port) + "/eps"
  95. resp, err := http.Get(requestURL)
  96. if err != nil {
  97. return nil, err
  98. }
  99. //Get the body content
  100. content, err := ioutil.ReadAll(resp.Body)
  101. if err != nil {
  102. return nil, err
  103. }
  104. //Convert the results to Endpoints
  105. endpoints := []iot.Endpoint{}
  106. err = json.Unmarshal(content, &endpoints)
  107. if err != nil {
  108. return nil, err
  109. }
  110. //Convert the structure to array pointers
  111. results := []*iot.Endpoint{}
  112. for _, ep := range endpoints {
  113. thisEp := ep
  114. results = append(results, &thisEp)
  115. }
  116. return results, nil
  117. }
  118. //Get status given the device object.
  119. func getStatusForDevice(device *iot.Device) (map[string]interface{}, error) {
  120. //Parse the URL for its status api endpoint
  121. requestURL := "http://" + device.IPAddr + ":" + strconv.Itoa(device.Port) + "/status"
  122. resp, err := http.Get(requestURL)
  123. if err != nil {
  124. return map[string]interface{}{}, err
  125. }
  126. //Get the body content
  127. content, err := ioutil.ReadAll(resp.Body)
  128. if err != nil {
  129. return map[string]interface{}{}, err
  130. }
  131. //Check if the resp is json
  132. if !isJSON(strings.TrimSpace(string(content))) {
  133. return map[string]interface{}{}, errors.New("Invalid HDSv2 protocol")
  134. }
  135. //Ok. Parse it
  136. status := map[string]interface{}{}
  137. err = json.Unmarshal(content, &status)
  138. if err != nil {
  139. return map[string]interface{}{}, err
  140. }
  141. return status, nil
  142. }