소스 검색

Added iot list scanner api and updates of HDSv2 example

TC pushbot 5 4 년 전
부모
커밋
2e6d576a03
7개의 변경된 파일308개의 추가작업 그리고 6개의 파일을 삭제
  1. 8 0
      examples/HomeDynamic2/Base/Base.ino
  2. 7 6
      iot.go
  3. 171 0
      mod/iot/common.go
  4. 48 0
      mod/iot/handlerManager.go
  5. 1 0
      mod/iot/hdsv2/hdsv2.go
  6. 1 0
      mod/iot/iot.go
  7. 72 0
      web/SystemAO/iot/info.html

+ 8 - 0
examples/HomeDynamic2/Base/Base.ino

@@ -83,6 +83,7 @@ void setup() {
   server.on("/", handle_index);
   server.on("/status", handle_status);
   server.on("/eps", handle_endpoints);
+  server.on("/hello", handle_hello);
   
   server.begin();
   Serial.println("HTTP server started");
@@ -95,6 +96,12 @@ void handle_index() {
   server.send(200, "text/html", "index"); 
 }
 
+void handle_hello() {
+  Serial.println("Hello World");
+  server.send(200, "text/html", "OK"); 
+}
+
+
 void handle_status() {
   server.send(200, "application/json", "{\
   \"power\":true,\
@@ -105,6 +112,7 @@ void handle_status() {
 void handle_endpoints() {
   server.send(200, "application/json", "[{\
     \"Name\": \"Hello World\",\
+    \"RelPath\":\"hello\",\
     \"Desc\":\"Print out Hello World in Serial\",\
     \"Type\":\"none\"\
   }]"); 

+ 7 - 6
iot.go

@@ -1,7 +1,6 @@
 package main
 
 import (
-	"log"
 	"net/http"
 
 	"imuslab.com/arozos/mod/iot"
@@ -28,11 +27,11 @@ func IoTHubInit() {
 
 		//Register IoT Setting Interfaces
 		registerSetting(settingModule{
-			Name:     "IoT Manager",
-			Desc:     "Manage IoT Devices Permission",
+			Name:     "IoT Hub",
+			Desc:     "Manage IoT Devices Scanners",
 			IconPath: "SystemAO/iot/img/small_icon.png",
 			Group:    "Device",
-			StartDir: "SystemAO/iot/manager.html",
+			StartDir: "SystemAO/iot/info.html",
 		})
 
 		//Register IoT Devices Endpoints
@@ -54,12 +53,14 @@ func IoTHubInit() {
 			},
 		})
 
+		//IoT Panel control APIs
 		router.HandleFunc("/system/iot/scan", iotManager.HandleScanning)
+		router.HandleFunc("/system/iot/list", iotManager.HandleListing)
 
-		log.Println("Work in progress breakpoint: ", router, adminRouter)
+		//IoT Hub Info APIs
+		adminRouter.HandleFunc("/system/iot/listScanner", iotManager.HandleScannerList)
 
 		//Start of the IoT Management Handlers
-
 		//Home Dynamic v2
 		hdsv2Handler := hdsv2.NewProtocolHandler(MDNS)
 		iotManager.RegisterHandler(hdsv2Handler)

+ 171 - 0
mod/iot/common.go

@@ -0,0 +1,171 @@
+package iot
+
+import (
+	"bufio"
+	"encoding/base64"
+	"errors"
+	"io/ioutil"
+	"log"
+	"net/http"
+	"os"
+	"time"
+)
+
+/*
+	SYSTEM COMMON FUNCTIONS
+
+	This is a system function that put those we usually use function but not belongs to
+	any module / system.
+
+	E.g. fileExists / IsDir etc
+
+*/
+
+/*
+	Basic Response Functions
+
+	Send response with ease
+*/
+//Send text response with given w and message as string
+func sendTextResponse(w http.ResponseWriter, msg string) {
+	w.Write([]byte(msg))
+}
+
+//Send JSON response, with an extra json header
+func sendJSONResponse(w http.ResponseWriter, json string) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Write([]byte(json))
+}
+
+func sendErrorResponse(w http.ResponseWriter, errMsg string) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Write([]byte("{\"error\":\"" + errMsg + "\"}"))
+}
+
+func sendOK(w http.ResponseWriter) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Write([]byte("\"OK\""))
+}
+
+/*
+	The paramter move function (mv)
+
+	You can find similar things in the PHP version of ArOZ Online Beta. You need to pass in
+	r (HTTP Request Object)
+	getParamter (string, aka $_GET['This string])
+
+	Will return
+	Paramter string (if any)
+	Error (if error)
+
+*/
+func mv(r *http.Request, getParamter string, postMode bool) (string, error) {
+	if postMode == false {
+		//Access the paramter via GET
+		keys, ok := r.URL.Query()[getParamter]
+
+		if !ok || len(keys[0]) < 1 {
+			//log.Println("Url Param " + getParamter +" is missing")
+			return "", errors.New("GET paramter " + getParamter + " not found or it is empty")
+		}
+
+		// Query()["key"] will return an array of items,
+		// we only want the single item.
+		key := keys[0]
+		return string(key), nil
+	} else {
+		//Access the parameter via POST
+		r.ParseForm()
+		x := r.Form.Get(getParamter)
+		if len(x) == 0 || x == "" {
+			return "", errors.New("POST paramter " + getParamter + " not found or it is empty")
+		}
+		return string(x), nil
+	}
+
+}
+
+func stringInSlice(a string, list []string) bool {
+	for _, b := range list {
+		if b == a {
+			return true
+		}
+	}
+	return false
+}
+
+func fileExists(filename string) bool {
+	_, err := os.Stat(filename)
+	if os.IsNotExist(err) {
+		return false
+	}
+	return true
+}
+
+func isDir(path string) bool {
+	if fileExists(path) == false {
+		return false
+	}
+	fi, err := os.Stat(path)
+	if err != nil {
+		log.Fatal(err)
+		return false
+	}
+	switch mode := fi.Mode(); {
+	case mode.IsDir():
+		return true
+	case mode.IsRegular():
+		return false
+	}
+	return false
+}
+
+func inArray(arr []string, str string) bool {
+	for _, a := range arr {
+		if a == str {
+			return true
+		}
+	}
+	return false
+}
+
+func timeToString(targetTime time.Time) string {
+	return targetTime.Format("2006-01-02 15:04:05")
+}
+
+func loadImageAsBase64(filepath string) (string, error) {
+	if !fileExists(filepath) {
+		return "", errors.New("File not exists")
+	}
+	f, _ := os.Open(filepath)
+	reader := bufio.NewReader(f)
+	content, _ := ioutil.ReadAll(reader)
+	encoded := base64.StdEncoding.EncodeToString(content)
+	return string(encoded), nil
+}
+
+func pushToSliceIfNotExist(slice []string, newItem string) []string {
+	itemExists := false
+	for _, item := range slice {
+		if item == newItem {
+			itemExists = true
+		}
+	}
+
+	if !itemExists {
+		slice = append(slice, newItem)
+	}
+
+	return slice
+}
+
+func removeFromSliceIfExists(slice []string, target string) []string {
+	newSlice := []string{}
+	for _, item := range slice {
+		if item != target {
+			newSlice = append(newSlice, item)
+		}
+	}
+
+	return newSlice
+}

+ 48 - 0
mod/iot/handlerManager.go

@@ -1,6 +1,7 @@
 package iot
 
 import (
+	"encoding/json"
 	"log"
 	"net/http"
 )
@@ -39,7 +40,54 @@ func (m *Manager) RegisterHandler(h ProtocolHandler) error {
 	return nil
 }
 
+//Handle listing of all avaible scanner and its stats
+func (m *Manager) HandleScannerList(w http.ResponseWriter, r *http.Request) {
+	stats := []Stats{}
+	for _, scanner := range m.RegisteredHandler {
+		thisScannerStat := scanner.Stats()
+		stats = append(stats, thisScannerStat)
+	}
+
+	js, _ := json.Marshal(stats)
+	sendJSONResponse(w, string(js))
+}
+
 //Handle IoT Scanning Request
 func (m *Manager) HandleScanning(w http.ResponseWriter, r *http.Request) {
+	scannedDevices := []*Device{}
+	for _, ph := range m.RegisteredHandler {
+		//Scan devices using this handler
+		thisProtcolDeviceList, err := ph.Scan()
+		if err != nil {
+			continue
+		}
+
+		//Append it to list
+		for _, dev := range thisProtcolDeviceList {
+			scannedDevices = append(scannedDevices, dev)
+		}
+	}
+
+	js, _ := json.Marshal(scannedDevices)
+	sendJSONResponse(w, string(js))
+}
+
+//Handle IoT Listing Request
+func (m *Manager) HandleListing(w http.ResponseWriter, r *http.Request) {
+	listedDevices := []*Device{}
+	for _, ph := range m.RegisteredHandler {
+		//Scan devices using this handler
+		thisProtcolDeviceList, err := ph.List()
+		if err != nil {
+			continue
+		}
+
+		//Append it to list
+		for _, dev := range thisProtcolDeviceList {
+			listedDevices = append(listedDevices, dev)
+		}
+	}
 
+	js, _ := json.Marshal(listedDevices)
+	sendJSONResponse(w, string(js))
 }

+ 1 - 0
mod/iot/hdsv2/hdsv2.go

@@ -59,6 +59,7 @@ func (h *Handler) Scan() ([]*iot.Device, error) {
 			RequireAuth:    false,
 			RequireConnect: false,
 			Status:         map[string]interface{}{},
+			Handler:        h,
 		}
 		//Try to get the device status
 		status, err := getStatusForDevice(&thisDevice)

+ 1 - 0
mod/iot/iot.go

@@ -37,6 +37,7 @@ type Device struct {
 	RequireConnect   bool                   //Require pre-connection before use
 	Status           map[string]interface{} //Status of the device, support multi channels
 	ControlEndpoints []*Endpoint            //Endpoints avabile for this device
+	Handler          ProtocolHandler        //Its parent protocol handler
 }
 
 type AuthInfo struct {

+ 72 - 0
web/SystemAO/iot/info.html

@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html ng-app="App">
+<head>
+    <title>IoT Control Panel</title>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0 user-scalable=no">
+    <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
+    <script type="text/javascript" src="../../script/jquery.min.js"></script>
+    <script type="text/javascript" src="../../script/semantic/semantic.min.js"></script>
+</head>
+<body>
+    <div class="ui container">
+        <div class="ui basic segment">
+            <h3 class="ui header">
+                IoT Hub
+                <div class="sub header">List of supported IoT protocol scanners for this Host</div>
+            </h3>
+        </div>
+        <div>
+            <table class="ui celled  very basic compact table">
+                <thead>
+                  <tr><th>Protocol Name</th>
+                  <th>Description</th>
+                  <th>Version (Protocol)</th>
+                  <th>Author</th>
+                  <th>Release Date</th>
+                </tr></thead>
+                <tbody id="protocolScannerList">
+                  <tr>
+                    <td data-label="">Home Dynamic v2</td>
+                    <td data-label="">A basic IoT communication protocol for ESP8266 made by Makers</td>
+                    <td data-label="">v2 (v2)</td>
+                    <td data-label=""><i class="user icon"></i>tobychui
+                        <br><i class="mail icon"></i><a href="mailto:[email protected]">[email protected]</a>
+                        <br><i class="globe icon"></i><a href="hds.arozos.com">hds.arozos.com</a></td>
+                    <td data-label=""></td>
+                  </tr>
+                </tbody>
+              </table>
+        </div>
+    </div>
+    <script>
+        initScannerHandlerList();
+        function initScannerHandlerList(){
+            $.get("../../system/iot/listScanner", function(data){
+                if (data.error !== undefined){
+                    alert(data.error);
+                }else{
+                    $("#protocolScannerList").html("");
+                    data.forEach(ph => {
+                        var releaseDate = new Date(ph.ReleaseDate * 1000);
+                        var year = releaseDate.getFullYear();
+                        var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
+                        var month = months[releaseDate.getMonth()];
+                        var date = releaseDate.getDate();
+                        var displayReleaseDate = date + " " + month + " " + year;
+                        $("#protocolScannerList").append(`<tr>
+                            <td data-label="">${ph.Name}</td>
+                            <td data-label="">${ph.Desc}</td>
+                            <td data-label="">v${ph.Version} (v${ph.ProtocolVer})</td>
+                            <td data-label=""><i class="user icon"></i>${ph.Author}
+                                <br><i class="mail icon"></i><a href="mailto:${ph.AuthorEmail}">${ph.AuthorEmail}</a>
+                                <br><i class="globe icon"></i><a href="${ph.AuthorWebsite}">${ph.AuthorWebsite}</a></td>
+                            <td data-label="">${displayReleaseDate}</td>
+                        </tr>`);
+                    });
+                }
+            })
+        }
+    </script>
+</body>
+</html>