TC pushbot 5 4 роки тому
батько
коміт
2ffbd2fa20

+ 46 - 6
examples/HomeDynamic2/Base/Base.ino

@@ -10,11 +10,15 @@
 #include <ESP8266WiFi.h>        // Include the Wi-Fi library
 #include <ESP8266WiFiMulti.h>   // Include the Wi-Fi-Multi library
 #include <ESP8266mDNS.h>        // Include the mDNS library
-
-ESP8266WiFiMulti wifiMulti;     // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
+#include <ESP8266WebServer.h>   // Include the WebServer library
 
 //Change the properties of the IoT device
-const String DeviceName = "HDSv2-Demo"; //The name of this IoT device
+const String DeviceName = "HDSv2-Base"; //The name of this IoT device
+const int ListeningPort = 12110;        //The port where this IoT device listen
+
+//Library Objects
+ESP8266WiFiMulti wifiMulti;     // Create an instance of the ESP8266WiFiMulti class, called 'wifiMulti'
+ESP8266WebServer server(ListeningPort);    //Create an Web Server on the listening port
 
 //Change the WiFi Settings
 void WiFiConfig(){
@@ -31,7 +35,7 @@ void MDNSDynamicServiceTxtCallback(const MDNSResponder::hMDNSService p_hService)
     MDNS.addDynamicServiceTxt(p_hService, "protocol","hdsv2");
 
     //Define the OEM written values
-    MDNS.addDynamicServiceTxt(p_hService, "uuid","00000000-0000-0000-0000-000000000000");
+    MDNS.addDynamicServiceTxt(p_hService, "uuid",getMacAddress());
     MDNS.addDynamicServiceTxt(p_hService, "model","Generic");
     MDNS.addDynamicServiceTxt(p_hService, "vendor","HomeDynamic Project");
     MDNS.addDynamicServiceTxt(p_hService, "version_minor","0.00");
@@ -49,6 +53,7 @@ void setup() {
   delay(10);
   Serial.println('\n');
 
+  //Start WiFi Conenction Routines
   WiFiConfig();
   
   Serial.println("Connecting ...");
@@ -61,7 +66,8 @@ void setup() {
   Serial.println(WiFi.SSID());
   Serial.print("IP address:\t");
   Serial.println(WiFi.localIP());
-
+  
+  //Startup MDNS Responder
   MDNS.setHostProbeResultCallback(hostProbeResult);
   
   if (!MDNS.begin(DeviceName)) {             // Start the mDNS responder for esp8266.local
@@ -69,10 +75,44 @@ void setup() {
   }
 
   //Advertise the port that you are using
-  MDNS.addService("http", "tcp", 12110);
+  MDNS.addService("http", "tcp", ListeningPort);
   Serial.println("mDNS responder started");
+
+  //Startup the Web Server Endpoints
+  delay(100);
+  server.on("/", handle_index);
+  server.on("/status", handle_status);
+  server.on("/eps", handle_endpoints);
+  
+  server.begin();
+  Serial.println("HTTP server started");
+  Serial.print("Listening on port: ");
+  Serial.println(ListeningPort);
 }
 
+//Handlers for Web Server
+void handle_index() {
+  server.send(200, "text/html", "index"); 
+}
+
+void handle_status() {
+  server.send(200, "application/json", "{\
+  \"power\":true,\
+  \"network\":true\
+}"); 
+}
+
+void handle_endpoints() {
+  server.send(200, "application/json", "[{\
+    \"Name\": \"Hello World\",\
+    \"Desc\":\"Print out Hello World in Serial\",\
+    \"Type\":\"none\"\
+  }]"); 
+}
+
+
+//Main Loop
 void loop() { 
+   server.handleClient();
    MDNS.update();
  }

+ 16 - 0
examples/HomeDynamic2/Base/helper.ino

@@ -0,0 +1,16 @@
+//Get MAC Address of the ESP8266, require WiFi
+String MACString;
+const char* getMacAddress(){
+  unsigned char mac[6];
+  WiFi.macAddress(mac);
+  MACString = "";
+  for (int i = 0; i < 6; ++i) {
+    MACString += String(mac[i], 16);
+    if (i < 5){
+      MACString += '-';
+    }
+  }
+  
+  const char* _result = MACString.c_str();
+  return _result;
+}

+ 12 - 0
iot.go

@@ -0,0 +1,12 @@
+package main
+
+/*
+	IoT Hub
+	Author: tobychui
+
+	This script handle the IoT service start up and mangement
+*/
+
+func IoTHubInit() {
+
+}

+ 136 - 2
mod/iot/hdsv2/hdsv2.go

@@ -1,6 +1,13 @@
 package hdsv2
 
 import (
+	"encoding/json"
+	"errors"
+	"io/ioutil"
+	"net/http"
+	"strconv"
+	"strings"
+
 	"imuslab.com/arozos/mod/iot"
 	"imuslab.com/arozos/mod/network/mdns"
 )
@@ -15,7 +22,7 @@ import (
 
 type Handler struct {
 	scanner      *mdns.MDNSHost
-	historyList  []iot.Device
+	historyList  []*iot.Device
 	lastScanTime int64
 }
 
@@ -24,11 +31,138 @@ func NewProtocolHandler(scanner *mdns.MDNSHost) *Handler {
 	//Create a new MDNS Host
 	return &Handler{
 		scanner,
-		[]iot.Device{},
+		[]*iot.Device{},
 		0,
 	}
 }
 
+//Scan the devices within the LAN
 func (h *Handler) Scan() ([]*iot.Device, error) {
+	foundDevices := []*iot.Device{}
+	hosts := h.scanner.Scan(3, "hds.arozos.com")
+	for _, host := range hosts {
+		thisDevice := iot.Device{
+			Name:         host.HostName,
+			Port:         host.Port,
+			Model:        host.Model,
+			Version:      host.BuildVersion + "-" + host.MinorVersion,
+			Manufacturer: host.Vendor,
+			DeviceUUID:   host.UUID,
+
+			IPAddr:         host.IPv4[0].String(),
+			RequireAuth:    false,
+			RequireConnect: false,
+			Status:         map[string]interface{}{},
+		}
+		//Try to get the device status
+		status, err := getStatusForDevice(&thisDevice)
+		if err != nil {
+			//This might be not a valid HDSv2 device. Skip this
+			continue
+		}
+		thisDevice.Status = status
+
+		//Get the device content endpoints
+		eps, err := getEndpoints(&thisDevice)
+		if err != nil {
+			//This might be not a valid HDSv2 device. Skip this
+			continue
+		}
+		thisDevice.ControlEndpoints = eps
+
+		//Push this host into found device list
+		foundDevices = append(foundDevices, &thisDevice)
+	}
+
+	h.historyList = foundDevices
+
+	return foundDevices, nil
+}
+
+//Return the history scan list from the handler
+func (h *Handler) List() ([]*iot.Device, error) {
+	return h.historyList, nil
+}
+
+//Home Dynamic system's devices no need to established conenction before executing anything
+func (h *Handler) Connect(device *iot.Device) error {
+	return nil
+}
+
+//Same rules also apply to disconnect
+func Disconnect(device *iot.Device) error {
+	return nil
+}
+
+//Get the status of the device
+func (h *Handler) Status(device *iot.Device) (map[string]interface{}, error) {
+	return getStatusForDevice(device)
+}
+
+//Get the status of the device
+func (h *Handler) Execute(device *iot.Device, endpoint *iot.Endpoint, payload interface{}) (interface{}, error) {
+	var result interface{}
+	return result, nil
+}
+
+//Get endpoint of the given device object
+func getEndpoints(device *iot.Device) ([]*iot.Endpoint, error) {
+	//Parse the URL of the endpoint apis location (eps)
+	requestURL := "http://" + device.IPAddr + ":" + strconv.Itoa(device.Port) + "/eps"
+	resp, err := http.Get(requestURL)
+	if err != nil {
+		return nil, err
+	}
+
+	//Get the body content
+	content, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	//Check if the resp is json
+	if !isJSON(strings.TrimSpace(string(content))) {
+		return nil, errors.New("Invalid HDSv2 protocol")
+	}
+
+	//Convert the results to Endpoints
+	endpoints := []*iot.Endpoint{}
+	err = json.Unmarshal(content, &endpoints)
+	if err != nil {
+		return nil, err
+	}
+
+	return endpoints, nil
+
+}
+
+//Get status given the device object.
+func getStatusForDevice(device *iot.Device) (map[string]interface{}, error) {
+	//Parse the URL for its status api endpoint
+	requestURL := "http://" + device.IPAddr + ":" + strconv.Itoa(device.Port) + "/status"
+	resp, err := http.Get(requestURL)
+	if err != nil {
+		return map[string]interface{}{}, err
+	}
+
+	//Get the body content
+	content, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return map[string]interface{}{}, err
+	}
+
+	//Check if the resp is json
+	if !isJSON(strings.TrimSpace(string(content))) {
+		return map[string]interface{}{}, errors.New("Invalid HDSv2 protocol")
+	}
+
+	//Ok. Parse it
+	status := map[string]interface{}{}
+	err = json.Unmarshal(content, &status)
+	if err != nil {
+		return map[string]interface{}{}, err
+	}
+
+	return status, nil
 
 }

+ 9 - 0
mod/iot/hdsv2/utils.go

@@ -0,0 +1,9 @@
+package hdsv2
+
+import "encoding/json"
+
+func isJSON(s string) bool {
+	var js map[string]interface{}
+	return json.Unmarshal([]byte(s), &js) == nil
+
+}

+ 11 - 2
mod/iot/iot.go

@@ -12,11 +12,21 @@ type Endpoint struct {
 	RelPath string //Relative path for this endpoint. If the access path is 192.168.0.100:8080/api1, then this value should be /api1
 	Name    string //Name of the this endpoint. E.g. "Toggle Light"
 	Desc    string //Description of function. E.g. "Toggle the ligh on and off"
+	Type    string //Type of endpoint data. Accept {string, integer, float, bool, none}
+
+	//Filter for string type inputs
+	Regex string
+
+	//Filter for integer and float type inputs
+	Min   float64
+	Max   float64
+	Steps float64
 }
 
 //Defination of an IoT device
 type Device struct {
 	Name         string //Name of the device
+	Port         int    //The communication port on the device. -1 for N/A
 	Model        string //Model number of the device
 	Version      string //Device firmware
 	Manufacturer string //<amifacturer of device
@@ -27,14 +37,13 @@ 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
-	SourceHandler    *ProtocolHandler       //The source handler that this device is scanned / discovered by
 }
 
 type ProtocolHandler interface {
 	Scan() ([]*Device, error)                                                             //Scan the nearby devices
 	List() ([]*Device, error)                                                             //Return the previous scanned list
 	Connect(device *Device) error                                                         //Connect to the device
-	Status(device *Device) (map[string]string, error)                                     //Get status of the IoT device                                    //Connect to a given device
+	Status(device *Device) (map[string]interface{}, error)                                //Get status of the IoT device                                    //Connect to a given device
 	Execute(device *Device, endpoint *Endpoint, payload interface{}) (interface{}, error) //Execute an endpoint for a device
 	Disconnect(device *Device) error                                                      //Disconnect from a device connection
 }

+ 5 - 0
mod/user/quota.go

@@ -78,6 +78,11 @@ func (u *User) GetFileOwner(realpath string) string {
 		return ""
 	}
 
+	if fsHandler.UUID == "user" {
+		//This file is inside user's root. It must be this user's file
+		return u.Username
+	}
+
 	owner, err := fsHandler.GetFileRecord(realpath)
 	if err != nil {
 		//Error occured. Either this file is not tracked or this file has no owner

+ 5 - 0
quota.go

@@ -102,6 +102,11 @@ func system_disk_quota_handleQuotaInfo(w http.ResponseWriter, r *http.Request) {
 	})
 
 	sendJSONResponse(w, string(jsonString))
+
+	go func() {
+		//Update this user's quota estimation in go routine
+		userinfo.StorageQuota.CalculateQuotaUsage()
+	}()
 }
 
 //Get all the users file and see how

+ 1 - 0
startup.go

@@ -86,6 +86,7 @@ func RunStartup() {
 	FTPServerInit() //Start FTP Server Endpoints
 	WebDAVInit()    //Start WebDAV Endpoint
 	ClusterInit()   //Start Cluster Services
+	IoTHubInit()    //Inialize ArozOS IoT Hub module
 
 	ModuleInstallerInit() //Start Module Installer