فهرست منبع

Complted hdsv2 action control

TC pushbot 5 4 سال پیش
والد
کامیت
3eb0c60852
6فایلهای تغییر یافته به همراه150 افزوده شده و 15 حذف شده
  1. 20 5
      examples/HomeDynamic2/Examples/Examples.ino
  2. 1 0
      iot.go
  3. 56 0
      mod/iot/handlerManager.go
  4. 17 0
      mod/iot/hdsv2/hdsv2.go
  5. 30 1
      mod/iot/hdsv2/utils.go
  6. 26 9
      web/SystemAO/iot/hub/index.html

+ 20 - 5
examples/HomeDynamic2/Examples/Examples.ino

@@ -15,6 +15,12 @@
 const String DeviceName = "HDsv2-Test"; //The name of this IoT device
 const int ListeningPort = 12110;        //The port where this IoT device listen
 
+//Runtime values
+String stringInput = "default";
+int integerInput = 0;
+float floatInput = 2.5;
+bool booleanInput = true;
+
 //Library Objects
 ESP8266WiFiMulti wifiMulti;     // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
 ESP8266WebServer server(ListeningPort);    //Create an Web Server on the listening port
@@ -102,6 +108,7 @@ void handle_index() {
 void handle_string() {
   String value = server.arg("value");
   Serial.println(value);
+  stringInput = value;
   //Use value (String) to do something
   server.send(200, "text/html", "OK"); 
 }
@@ -110,14 +117,16 @@ void handle_integer() {
   String value = server.arg("value");
   int number = value.toInt();
   Serial.println(number);
+  integerInput = number;
   //Use number (int) to do something
   server.send(200, "text/html", "OK"); 
 }
 
 void handle_float() {
   String value = server.arg("value");
-  int floatNumber = value.toFloat();
+  float floatNumber = value.toFloat();
   Serial.println(floatNumber);
+  floatInput = floatNumber;
   //Use floatNumber to do something else
   server.send(200, "text/html", "OK"); 
 }
@@ -132,6 +141,8 @@ void handle_bool() {
     Serial.println("False");
   }
 
+  booleanInput = result;
+
   //Use result to do something else
   server.send(200, "text/html", "OK"); 
 }
@@ -144,12 +155,16 @@ void handle_output() {
 //This function return the status of the current device. 
 //If the name of status matches one of the input endpoints, the value will be used as auto fill
 void handle_status() {
+  String boolValue = "true";
+  if (booleanInput == false){
+    boolValue = "false";
+  }
   server.send(200, "application/json", "{\
   \"Global Status\":\"It is working\",\
-  \"String Input\":\"default value\",\
-  \"Integer Input\":8,\
-  \"Float Input\":4.5,\
-  \"Boolean Input\":true\
+  \"String Input\":\"" + stringInput + "\",\
+  \"Integer Input\":" + String(integerInput) + ",\
+  \"Float Input\":" + String(floatInput, 2) + ",\
+  \"Boolean Input\":" + boolValue + "\
 }"); 
 }
 

+ 1 - 0
iot.go

@@ -72,6 +72,7 @@ func IoTHubInit() {
 		router.HandleFunc("/system/iot/scan", iotManager.HandleScanning)
 		router.HandleFunc("/system/iot/list", iotManager.HandleListing)
 		router.HandleFunc("/system/iot/status", iotManager.HandleGetDeviceStatus)
+		router.HandleFunc("/system/iot/execute", iotManager.HandleExecute)
 
 		//IoT Hub Info APIs
 		adminRouter.HandleFunc("/system/iot/listScanner", iotManager.HandleScannerList)

+ 56 - 0
mod/iot/handlerManager.go

@@ -53,6 +53,62 @@ func (m *Manager) HandleScannerList(w http.ResponseWriter, r *http.Request) {
 	sendJSONResponse(w, string(js))
 }
 
+//Get the device object by id
+func (m *Manager) GetDeviceByID(devid string) *Device {
+	for _, dev := range m.cachedDeviceList {
+		if dev.DeviceUUID == devid {
+			return dev
+		}
+	}
+	return nil
+}
+
+//Handle listing of all avaible scanner and its stats
+func (m *Manager) HandleExecute(w http.ResponseWriter, r *http.Request) {
+	devid, err := mv(r, "devid", true)
+	if err != nil {
+		sendErrorResponse(w, "Invalid device id")
+		return
+	}
+
+	eptname, err := mv(r, "eptname", true)
+	if err != nil {
+		sendErrorResponse(w, "Invalid endpoint name")
+		return
+	}
+
+	payload, _ := mv(r, "payload", true)
+
+	//Get device by device id
+	dev := m.GetDeviceByID(devid)
+	if dev == nil {
+		sendErrorResponse(w, "Given device id not found")
+		return
+	}
+
+	//Get its endpoint
+	var targetEndpoint Endpoint
+	for _, ept := range dev.ControlEndpoints {
+		if ept.Name == eptname {
+			//This is the endpoint we are looking for
+			targetEndpoint = *ept
+			break
+		}
+	}
+
+	//log.Println(dev.IPAddr, targetEndpoint, payload)
+
+	//Send request to the target IoT device
+	result, err := dev.Handler.Execute(dev, &targetEndpoint, payload)
+	if err != nil {
+		sendErrorResponse(w, err.Error())
+		return
+	}
+
+	js, _ := json.Marshal(result)
+	sendJSONResponse(w, string(js))
+}
+
 //Get status of the given device ID
 func (m *Manager) HandleGetDeviceStatus(w http.ResponseWriter, r *http.Request) {
 	devid, err := mv(r, "devid", true)

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

@@ -102,6 +102,23 @@ func (h *Handler) Status(device *iot.Device) (map[string]interface{}, error) {
 //Get the status of the device
 func (h *Handler) Execute(device *iot.Device, endpoint *iot.Endpoint, payload interface{}) (interface{}, error) {
 	var result interface{}
+
+	targetURL := "http://" + device.IPAddr + ":" + strconv.Itoa(device.Port) + "/" + endpoint.RelPath
+
+	//Check if there are payload for this request
+	if payload == nil {
+		//No payload. Just call it
+
+	} else {
+		//Payload exists. Append it to the end with value=?
+		targetURL += "?value=" + payload.(string)
+	}
+
+	result, err := tryGet(targetURL)
+	if err != nil {
+		return nil, err
+	}
+
 	return result, nil
 }
 

+ 30 - 1
mod/iot/hdsv2/utils.go

@@ -1,8 +1,37 @@
 package hdsv2
 
-import "encoding/json"
+import (
+	"encoding/json"
+	"errors"
+	"io/ioutil"
+	"net/http"
+	"strconv"
+	"time"
+)
 
 func isJSON(s string) bool {
 	var js map[string]interface{}
 	return json.Unmarshal([]byte(s), &js) == nil
 }
+
+func tryGet(url string) (string, error) {
+	client := http.Client{
+		Timeout: 10 * time.Second,
+	}
+
+	resp, err := client.Get(url)
+	if err != nil {
+		return "", err
+	}
+
+	if resp.StatusCode != 200 {
+		return "", errors.New("Server side return status code " + strconv.Itoa(resp.StatusCode))
+	}
+
+	content, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return "", err
+	}
+
+	return string(content), nil
+}

+ 26 - 9
web/SystemAO/iot/hub/index.html

@@ -260,7 +260,20 @@
 				}
 			}
 
+			//Request the backend to activate the endpoint
 			console.log(deviceID, epd, targetValue);
+			$.ajax({
+				url: "../../../system/iot/execute",
+				data: {devid: deviceID, eptname: epd.Name, payload: targetValue},
+				success: function(data){
+					if (data.error !== undefined){
+						alert(data.error);
+					}else{
+						//OK. Reload status
+						updateStatus(deviceID);
+					}
+				}
+			})
 		}
 
 		const stringToRegex = str => {
@@ -345,7 +358,7 @@
 					}else if (ept.Type == "bool"){
 						$("#actionForm").append(`<div name="${ept.Name}" devid="${deviceID}" epd="${encodedEptData}" class="field">
 							<div class="ts toggle checkbox">
-								<input type="checkbox" id="${encodeURIComponent(ept.Name)}" onchange="executeEndpoint(this.parentNode.parentNode, this.value);">
+								<input type="checkbox" id="${encodeURIComponent(ept.Name)}" onchange="executeEndpoint(this.parentNode.parentNode, this.checked);">
 								<label for="${encodeURIComponent(ept.Name)}">${ept.Name}</label>
 						</div></div>`);
 						
@@ -357,10 +370,19 @@
 					}
 				});
 
-				//Get its status
-				$.ajax({
+				updateStatus(deviceData.DeviceUUID);
+			}
+
+			console.log(deviceData);
+
+			$("#actioninterface").fadeIn('fast');
+		}
+
+		function updateStatus(deviceUUID){
+			//Get its status
+			$.ajax({
 					url: "../../../system/iot/status",
-					data: {devid: deviceData.DeviceUUID},
+					data: {devid: deviceUUID},
 					success: function(data){
 						//Look for fields that have the same name. If not, append it to status field
 						if (data.error !== undefined){
@@ -403,11 +425,6 @@
 						}
 					}
 				})
-			}
-
-			console.log(deviceData);
-
-			$("#actioninterface").fadeIn('fast');
 		}
 
 		function updateIframeSize(){