hds.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. package hds
  2. import (
  3. "errors"
  4. "log"
  5. "strconv"
  6. "strings"
  7. "sync"
  8. "imuslab.com/arozos/mod/iot"
  9. )
  10. /*
  11. Home Dynamic System
  12. Author: tobychui
  13. This is a compaitbility module for those who are still using HDSv1 protocol
  14. If you are still using HDSv1, you should consider upgrading it to the latest
  15. version of HDS protocols.
  16. */
  17. type Handler struct {
  18. lastScanTime int64
  19. }
  20. //Create a new HDS Protocol Handler
  21. func NewProtocolHandler() *Handler {
  22. //Create a new MDNS Host
  23. return &Handler{}
  24. }
  25. //Start the HDSv1 scanner, which no startup process is required
  26. func (h *Handler) Start() error {
  27. log.Println("*IoT* Home Dynamic System (Legacy) Loaded")
  28. return nil
  29. }
  30. //Scan all the HDS devices in LAN using the legacy ip scanner methods
  31. func (h *Handler) Scan() ([]*iot.Device, error) {
  32. //Get the current local IP address
  33. ip := getLocalIP()
  34. if ip == "" {
  35. //Not connected to a network?
  36. return nil, errors.New("Unable to get ip address of host device")
  37. }
  38. //Only handle a small subset of ip ranges (Last 255 addfress)
  39. scanBase := ""
  40. valid := false
  41. if ip[:8] == "192.168." {
  42. tmp := strings.Split(ip, ".")
  43. tmp = tmp[:len(tmp)-1]
  44. scanBase = strings.Join(tmp, ".") + "." //Return 192.168.0.
  45. valid = true
  46. } else if ip[:4] == "172." {
  47. //Handle 172.16.x.x - 172.31.x.x
  48. tmp := strings.Split(ip, ".")
  49. val, err := strconv.Atoi(tmp[1])
  50. if err == nil {
  51. if val >= 16 && val <= 31 {
  52. //Private addr range
  53. valid = true
  54. scanBase = strings.Join(tmp, ".") + "." //Return 172.16.0.
  55. }
  56. }
  57. }
  58. //Check if the IP range is supported by HDS protocol
  59. if !valid {
  60. log.Println("*IoT* Home Dynamic Protocol requirement not satisfied. Skipping Scan")
  61. return nil, nil
  62. }
  63. results := []*iot.Device{}
  64. //Create a IP scanner
  65. var wg sync.WaitGroup
  66. for i := 1; i < 256; i++ {
  67. wg.Add(1)
  68. go func(wg *sync.WaitGroup) {
  69. defer wg.Done()
  70. targetIP := scanBase + strconv.Itoa(i)
  71. uuid, err := tryGetHDSUUID(targetIP)
  72. if err != nil {
  73. //Not an HDS device
  74. return
  75. }
  76. //This is an HDS device. Get its details
  77. devName, className, err := tryGetHDSInfo(targetIP)
  78. if err != nil {
  79. //Corrupted HDS device?
  80. return
  81. }
  82. //Get the device status
  83. deviceState := map[string]interface{}{}
  84. statusText, err := getHDSStatus(targetIP)
  85. if err != nil {
  86. //No status
  87. } else {
  88. deviceState["status"] = strings.TrimSpace(statusText)
  89. }
  90. results = append(results, &iot.Device{
  91. Name: devName,
  92. Port: 80, //HDS device use port 80 by default
  93. Model: className,
  94. Version: "1.0",
  95. Manufacturer: "Generic",
  96. DeviceUUID: uuid,
  97. IPAddr: targetIP,
  98. RequireAuth: false,
  99. RequireConnect: false,
  100. Status: deviceState,
  101. Handler: h,
  102. })
  103. log.Println("*HDS* Found device ", devName, " at ", targetIP, " with UUID ", uuid)
  104. }(&wg)
  105. }
  106. wg.Wait()
  107. return results, nil
  108. }
  109. //Home Dynamic system's devices no need to established conenction before executing anything
  110. func (h *Handler) Connect(device *iot.Device, authInfo *iot.AuthInfo) error {
  111. return nil
  112. }
  113. //Same rules also apply to disconnect
  114. func (h *Handler) Disconnect(device *iot.Device) error {
  115. return nil
  116. }
  117. //Get the status of the device
  118. func (h *Handler) Execute(device *iot.Device, endpoint *iot.Endpoint, payload interface{}) (interface{}, error) {
  119. var result interface{}
  120. return result, nil
  121. }
  122. //Get the status of the device
  123. func (h *Handler) Status(device *iot.Device) (map[string]interface{}, error) {
  124. resp, err := tryGet("http://" + device.IPAddr + "/status")
  125. if err != nil {
  126. return map[string]interface{}{}, err
  127. }
  128. //Convert the resp into map string itnerface
  129. result := map[string]interface{}{}
  130. result["status"] = resp
  131. return result, nil
  132. }
  133. //Return the specification of this protocol handler
  134. func (h *Handler) Stats() iot.Stats {
  135. return iot.Stats{
  136. Name: "Home Dynamic",
  137. Desc: "A basic IoT communication protocol for ESP8266 for ArOZ Online Beta",
  138. Version: "1.0",
  139. ProtocolVer: "1.0",
  140. Author: "tobychui",
  141. AuthorWebsite: "https://git.hkwtc.org/TC/HomeDynamic",
  142. AuthorEmail: "",
  143. ReleaseDate: 1576094199,
  144. }
  145. }