コード例 #1
0
ファイル: wf_rest.cs プロジェクト: bpaauwe/WFNodeServer
        private string ChunkedRead(HttpWebResponse response)
        {
            Stream reader;

            byte[] buf = new byte[4096];
            int    len;
            string chunk;
            string resp = "";

            reader = response.GetResponseStream();
            try {
                do
                {
                    len = reader.Read(buf, 0, buf.Length);
                    //Console.WriteLine("  -> Read " + len.ToString() + " bytes from stream.");
                    if (len > 0)
                    {
                        chunk = new String(Encoding.ASCII.GetString(buf).ToCharArray(), 0, len);
                        resp += chunk;
                    }
                } while (len > 0);
            } catch {
                WFLogging.Debug("Ignoring reader exception?");
            }

            reader.Close();

            return(resp);
        }
コード例 #2
0
ファイル: wf_websocket.cs プロジェクト: bpaauwe/WFNodeServer
 private static void ProcessWSData(string json)
 {
     if (json.Contains("obs_air"))
     {
         WeatherFlowNS.NS.udp_client.WSObservations(json);
     }
     else if (json.Contains("obs_sky"))
     {
         WeatherFlowNS.NS.udp_client.WSObservations(json);
     }
     else if (json.Contains("rapid_wind"))
     {
         WeatherFlowNS.NS.udp_client.RapidWindEvt(json);
     }
     else if (json.Contains("evt_strike"))
     {
         WeatherFlowNS.NS.udp_client.LigtningStrikeEvt(json);
     }
     else if (json.Contains("evt_precip"))
     {
     }
     else if (json.Contains("ack"))
     {
     }
     else
     {
         WFLogging.Error("Unknown type of WebSocket packet");
         WFLogging.Error(json);
     }
 }
コード例 #3
0
ファイル: wf_websocket.cs プロジェクト: bpaauwe/WFNodeServer
        private void ReceiveLoop()
        {
            StateObject state = new StateObject();

            WFLogging.Info("    Starting receive loop");
            state.workSocket = client;
            while (!finished)
            {
                // Start receive data from server
                while (client.Client.Available == 0)
                {
                    Thread.Sleep(100);
                }

                state.offset = 0;
                client.Client.BeginReceive(state.buffer, 0, StateObject.bufsize, 0, new AsyncCallback(ReceiveCallback), state);
                receiveDone.WaitOne();
            }

            // Wait for server to close connection
            WFLogging.Info("   Waiting for server close.");
            CloseDone.WaitOne();
            client.Close();
            Thread.Sleep(500);
            Started = false;
        }
コード例 #4
0
        internal static void LogPage(HttpListenerContext context)
        {
            byte[] page;

            // Process changes
            if (context.Request.ContentLength64 > 0)
            {
                int    len  = (int)context.Request.ContentLength64;
                byte[] post = new byte[1024];

                context.Request.InputStream.Read(post, 0, len);
                string resp = Encoding.Default.GetString(post);
                resp = resp.Substring(0, len);

                foreach (string item in resp.Split('&'))
                {
                    string[] pair = item.Split('=');
                    switch (pair[0])
                    {
                    case "sLogLevel":
                        int l = 0;
                        int.TryParse(pair[1], out l);
                        if (l != WF_Config.LogLevel)
                        {
                            WF_Config.LogLevel = l;
                            WFLogging.Level    = (LOG_LEVELS)l;
                            WeatherFlowNS.SaveConfiguration();
                        }
                        break;

                    case "Save":
                        // Look up value of filename and save log to that file
                        string fname = element(resp, "filename");
                        try {
                            using (StreamWriter sw = new StreamWriter(fname)) {
                                sw.Write(WFLogging.ToString());
                            }
                        } catch (Exception ex) {
                            WFLogging.Error(ex.Message);
                        }
                        break;

                    case "Clear":
                        WFLogging.Clear();
                        break;
                    }
                }
            }

            page = ASCIIEncoding.ASCII.GetBytes(MakeLog());

            context.Response.ContentType     = "text/html";
            context.Response.ContentLength64 = page.Length;
            context.Response.AddHeader("Date", DateTime.Now.ToString("r"));
            context.Response.StatusCode = (int)HttpStatusCode.OK;
            context.Response.OutputStream.Write(page, 0, page.Length);
            context.Response.OutputStream.Flush();
            context.Response.OutputStream.Close();
            context.Response.Close();
        }
コード例 #5
0
ファイル: wf_rest.cs プロジェクト: bpaauwe/WFNodeServer
        internal void REST_POST(string url, string content, int len)
        {
            HttpWebRequest  request;
            HttpWebResponse response;
            string          rest_url;
            int             code;

            rest_url = Base + url;

            WFLogging.Debug(rest_url);
            request           = (HttpWebRequest)HttpWebRequest.Create(rest_url);
            request.UserAgent = "WFNodeServer";
            if (AuthRequired)
            {
                request.Headers.Add("Authorization", Authorize());
            }
            request.Proxy         = null;
            request.KeepAlive     = false;
            request.Method        = "POST";
            request.ContentLength = len;
            request.ContentType   = "application/xml";

            Stream datastream = request.GetRequestStream();

            datastream.Write(Encoding.ASCII.GetBytes(content), 0, len);
            datastream.Close();

            try {
                response = (HttpWebResponse)request.GetResponse();
                code     = (int)response.StatusCode;
                response.Close();
            } catch (Exception ex) {
                WFLogging.Error(ex.Message);
            }
        }
コード例 #6
0
        internal static void UploadFile(rest Rest, int profile, string resname, string type)
        {
            Assembly assembly;
            string   resourceName;
            string   contents = "";

            // Load resource into string
            assembly     = Assembly.GetExecutingAssembly();
            resourceName = "WFNodeServer.nodesetup." + resname;
            using (Stream stream = assembly.GetManifestResourceStream(resourceName)) {
                using (StreamReader reader = new StreamReader(stream)) {
                    contents = reader.ReadToEnd();
                }
            }

            if (contents.Length > 0)
            {
                // Send to ISY
                // This is just a http post to /rest/ns/profile/<profile>/upload/<type>/<filename>
                Rest.AuthRequired = true;
                try {
                    Rest.REST_POST("ns/profile/" + profile.ToString() + "/upload/" + type + "/" + resname, contents, contents.Length);
                } catch (Exception ex) {
                    WFLogging.Error(resname + " upload failed: " + ex.Message);
                }
            }
        }
コード例 #7
0
        internal bool GetStationMeta(string station_id)
        {
            string               resp;
            RootObject           root;
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            resp = WFRest.REST("/swd/rest/stations/" + station_id + "?api_key=6c8c96f9-e561-43dd-b173-5198d8797e0a");

            if (resp == "")
            {
                return(false);
            }
            if (resp.Contains("ERROR"))
            {
                return(false);
            }

            if (resp != "")
            {
                try {
                    root = serializer.Deserialize <RootObject>(resp);

                    if (root.stations.Count == 0)
                    {
                        return(false);
                    }

                    Latitude  = root.stations[0].latitude;
                    Longitude = root.stations[0].longitude;

                    //Console.WriteLine("latitude:  " + root.stations[0].latitude.ToString());
                    //Console.WriteLine("longitude: " + root.stations[0].longitude.ToString());
                    //Console.WriteLine("elevation: " + root.stations[0].station_meta.elevation.ToString());
                    foreach (Device device in root.stations[0].devices)
                    {
                        // Types that we're interested in are:
                        //   SK - sky
                        //   AR - air
                        //Console.WriteLine("Sensor: " + device.device_id.ToString() + " is " + device.device_type + " -agl = " + device.device_meta.agl.ToString());
                        if (device.device_type == "AR")
                        {
                            Elevation = root.stations[0].station_meta.elevation + device.device_meta.agl;
                            Air       = device.device_id;
                            AirSN     = device.serial_number;
                        }
                        else if (device.device_type == "SK")
                        {
                            Sky   = device.device_id;
                            SkySN = device.serial_number;
                        }
                    }
                } catch (Exception ex) {
                    WFLogging.Error("Error: " + ex.Message);
                    return(false);
                }
            }
            return(true);
        }
コード例 #8
0
ファイル: wf_websocket.cs プロジェクト: bpaauwe/WFNodeServer
        internal void StopListenRapid(string device_id)
        {
            string message = "{ \"type\":\"listen_rapid_stop\", \"device_id\":";

            message += device_id;
            message += ", \"id\":\"random-id-23456\" }";

            WFLogging.Info("    Stopping listen for device " + device_id);
            SendMessage(client, message, 0x01);
        }
コード例 #9
0
ファイル: wf_udp.cs プロジェクト: bpaauwe/WFNodeServer
 internal void Start()
 {
     if (!Active)
     {
         WFLogging.Log("Starting WeatherFlow data collection thread.");
         udp_thread = new Thread(new ThreadStart(WeatherFlowThread));
         udp_thread.IsBackground = true;
         udp_thread.Start();
     }
 }
コード例 #10
0
ファイル: wf_heartbeat.cs プロジェクト: bpaauwe/WFNodeServer
        internal void Updated(string address, int timestamp, WeatherFlow_UDP.DataType t)
        {
            // Check for missing data here.
            UDPTime  utime;
            TimeSpan epoch = DateTime.UtcNow - new DateTime(1970, 1, 1);

            utime.timestamp = timestamp;
            utime.now       = (int)epoch.TotalSeconds;

            if (!SecondsSinceUpdate.ContainsKey(address))
            {
                SecondsSinceUpdate[address] = utime;
            }

            // TODO: The diff should be 2x the interval. Is there some way to get that
            //       information here?
            int diff = timestamp - SecondsSinceUpdate[address].timestamp;

            switch (t)
            {
            case WeatherFlow_UDP.DataType.AIR:
            case WeatherFlow_UDP.DataType.SKY:
                // Expect data every 60 seconds
                if (diff >= 120)
                {
                    WFLogging.Warning("Possible Missing data for " + address + ": " + diff.ToString() + " seconds");
                }
                break;

            case WeatherFlow_UDP.DataType.DEVICE:
                // Expect data every 60 seconds
                if (diff >= 90)
                {
                    WFLogging.Warning("Possible Missing data for " + address + ": " + diff.ToString() + " seconds");
                }
                break;

            case WeatherFlow_UDP.DataType.HUB:
                // Expect data every 10 seconds
                if (diff >= 20)
                {
                    WFLogging.Warning("Possible Missing data for " + address + ": " + diff.ToString() + " seconds");
                }
                break;

            case WeatherFlow_UDP.DataType.WIND:
                // Expect data every 3 seconds
                if (diff >= 6)
                {
                    WFLogging.Warning("Possible Missing data for " + address + ": " + diff.ToString() + " seconds");
                }
                break;
            }
            SecondsSinceUpdate[address] = utime;
        }
コード例 #11
0
ファイル: wf_websocket.cs プロジェクト: bpaauwe/WFNodeServer
        internal void StartListen(string device_id)
        {
            string message = "{ \"type\":\"listen_start\", \"device_id\":";

            message += device_id;
            message += ", \"id\":\"random-id-23456\" }";

            WFLogging.Info("    Starting listen for device " + device_id);
            SendMessage(client, message, 0x01);
            started.Add(device_id, true);
        }
コード例 #12
0
        internal void PrecipitationEvt(string json)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            try {
                // evt[0] = timestamp
                PreciptObj = serializer.Deserialize <PreciptData>(json);
                WeatherFlowNS.NS.RaiseRainEvent(this, new RainEventArgs(PreciptObj));
            } catch (Exception ex) {
                WFLogging.Error("Failed to deserialize precipitation event: " + ex.Message);
            }
        }
コード例 #13
0
ファイル: wf_rest.cs プロジェクト: bpaauwe/WFNodeServer
        private string MakeRequest(string rest_url)
        {
            HttpWebRequest  request;
            HttpWebResponse response;
            int             code;
            DateTime        start = DateTime.Now;
            string          xml   = "";

            request           = (HttpWebRequest)HttpWebRequest.Create(rest_url);
            request.UserAgent = "WFNodeServer";
            if (AuthRequired)
            {
                request.Headers.Add("Authorization", Authorize());
            }
            request.Proxy = null;
            request.ServicePoint.ConnectionLimit = 10;
            request.Timeout   = 4000;
            request.KeepAlive = true;
            //request.Pipelined = true;

            // Read data from the stream
            try {
                response = (HttpWebResponse)request.GetResponse();
                code     = (int)response.StatusCode;
                if (code != 200)
                {
                    response.Close();
                    throw new RestException(code, response.StatusDescription);
                }

                if (response.ContentLength == 0)
                {
                    return("");
                }

                // sucess with content
                xml = ChunkedRead(response);
                response.Close();
            } catch (WebException ex) {
                if (ex.Status == WebExceptionStatus.ProtocolError)
                {
                    throw new RestException(400, ex.Message);
                }

                WFLogging.Error("GetResponse thew exception: " + ex.Status.ToString());
                throw new RestException(0, ex.Message);
            }

            stats.RequestTime = DateTime.Now.Subtract(start).TotalMilliseconds;
            stats.Count++;
            return(xml);
        }
コード例 #14
0
        internal void LigtningStrikeEvt(string json)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            try {
                // evt[0] = timestamp
                // evt[1] = distance (km)
                // evt[2] = energy
                StrikeObj = serializer.Deserialize <StrikeData>(json);
                WeatherFlowNS.NS.RaiseLightningEvent(this, new LightningEventArgs(StrikeObj));
            } catch (Exception ex) {
                WFLogging.Error("Failed to deserialize strike event: " + ex.Message);
            }
        }
コード例 #15
0
ファイル: wf_rest.cs プロジェクト: bpaauwe/WFNodeServer
        // This is handling the SetParent service only at this point but could
        // be expanded to handle other ISY WSDL reuests if needed.
        internal void SendWSDLReqeust(string service, string parent, string node)
        {
            string          url = "http://" + WF_Config.ISY + "/services";
            HttpWebRequest  request;
            HttpWebResponse response;
            string          reqString = "";

            reqString  = "<? version=\'1.0\' encoding=\'utf-8\'?>";
            reqString += "<s:Envelope>";
            reqString += "<s:Body>";
            reqString += "<u:" + service + " xmlns:u=\'urn:udi-com:service:X_Insteon_Lighting_Service:1\'>";

            reqString += "<node>" + node + "</node>";
            reqString += "<nodeType>1</nodeType>";
            reqString += "<parent>" + parent + "</parent>";
            reqString += "<parentType>1</parentType>";

            reqString += "</u:" + service + ">";
            reqString += "</s:Body>";
            reqString += "</s:Envelope>";
            reqString += "\r\n";

            request             = (HttpWebRequest)HttpWebRequest.Create(url);
            request.KeepAlive   = true;
            request.Method      = "POST";
            request.ContentType = "text/xml; charset-utf-8";
            request.Headers.Add("Authorization", Authorize());
            request.Headers.Add("SOAPAction", "urn:udi-com:device:X_Insteon_Lighting_Service:1#" + service);

            Stream data = request.GetRequestStream();

            data.Write(Encoding.ASCII.GetBytes(reqString), 0, reqString.Length);
            data.Flush();
            data.Close();

            response = (HttpWebResponse)request.GetResponse();
            if (response.StatusCode == HttpStatusCode.OK)
            {
                WFLogging.Log("Grouped " + node + " as a child of " + parent);
            }
            else
            {
                WFLogging.Error("Group of " + node + " under " + parent + "failed: " + response.StatusDescription);
            }

            response.Close();

            return;
        }
コード例 #16
0
        internal static void LogText(HttpListenerContext context)
        {
            byte[] page;

            page = ASCIIEncoding.ASCII.GetBytes(WFLogging.ToString());

            context.Response.ContentType     = "text/text";
            context.Response.ContentLength64 = page.Length;
            context.Response.AddHeader("Date", DateTime.Now.ToString("r"));
            context.Response.StatusCode = (int)HttpStatusCode.OK;
            context.Response.OutputStream.Write(page, 0, page.Length);
            context.Response.OutputStream.Flush();
            context.Response.OutputStream.Close();
            context.Response.Close();
        }
コード例 #17
0
ファイル: wf_rest.cs プロジェクト: bpaauwe/WFNodeServer
        //
        // Given a REST partial URL, make the connection and return
        // the XML response
        //
        internal string REST(string url)
        {
            string rest_url;
            string resp = "";

            rest_url = Base + url;

            if (rest_url == "")
            {
                WFLogging.Error("ISY REST called with missing URL.");
                WFLogging.Error("  Does this mean there's no connection to an ISY?");
                return("");
            }

            lock (RateLimit) {
                WFLogging.Debug(rest_url);
                int retrys = 0;

                while (retrys < 5)
                {
                    try {
                        resp = MakeRequest(rest_url);
                        break;
                    } catch (RestException re) {
                        if (re.Code != 0)
                        {
                            WFLogging.Error("REST request " + url + " failed " + re.Message);
                            break;
                        }
                        else
                        {
                            // Timeout or failed to get result
                            retrys++;
                            if (retrys == 5)
                            {
                                WFLogging.Error("REST request " + url + " failed after 5 retries with " + re.Message);
                            }
                            Thread.Sleep(50 * retrys);
                        }
                    }
                }
            }
            return(resp);
        }
コード例 #18
0
        internal static void callback(IAsyncResult result)
        {
            UdpClient  u = (UdpClient)((UdpState)(result.AsyncState)).client;
            IPEndPoint e = (IPEndPoint)((UdpState)(result.AsyncState)).ep;

            Byte[] receiveBytes  = u.EndReceive(result, ref e);
            string receiveString = Encoding.ASCII.GetString(receiveBytes);
            //Console.WriteLine("Received: {0}", receiveString);

            // Parse IP address / port from recieved text
            int i1 = receiveString.IndexOf("//");
            int i2 = receiveString.IndexOf("/desc");

            if (i1 > 0)
            {
                i1        += 2;
                ISYAddress = receiveString.Substring(i1, (i2 - i1));
            }
            WFLogging.Log("Found ISY at " + ISYAddress);
        }
コード例 #19
0
ファイル: wf_websocket.cs プロジェクト: bpaauwe/WFNodeServer
        internal void Stop()
        {
            string message = "close";

            WFLogging.Info("    Stop all listening.");
            foreach (string key in started.Keys)
            {
                StopListen(key);
            }
            started.Clear();

            foreach (string key in started_rapid.Keys)
            {
                StopListenRapid(key);
            }
            started_rapid.Clear();

            SendMessage(client, message, 0x08);
            finished = true;
        }
コード例 #20
0
        internal void Server()
        {
            Thread      handleClient;
            TcpListener server = new TcpListener(IPAddress.Parse(Address), Port);

            server.Start();
            WFLogging.Log("Logging server has started on port " + Port.ToString());

            // Add a new log client to get new events and send over
            // the websocket.
            WFLogging.AddListener(WSLog);

            while (true)
            {
                WFLogging.Info("Waiting for log client to connect");
                client       = server.AcceptTcpClient();
                handleClient = new Thread(() => ClientHandler(client));
                handleClient.Start();
            }
        }
コード例 #21
0
ファイル: wf_server.cs プロジェクト: bpaauwe/WFNodeServer
        private bool AddStation(station_form a_form)
        {
            wf_station station = new wf_station(api_key);

            if (station.GetStationMeta(a_form.station_id.ToString()) || (a_form.station_id == 0))
            {
                a_form.air_id    = (a_form.air_id == 0) ? station.Air : a_form.air_id;
                a_form.sky_id    = (a_form.sky_id == 0) ? station.Sky : a_form.sky_id;
                a_form.air_sn    = (a_form.air_sn == "") ? station.AirSN : a_form.air_sn;
                a_form.sky_sn    = (a_form.sky_sn == "") ? station.SkySN : a_form.sky_sn;
                a_form.elevation = (a_form.elevation == 0) ? station.Elevation : a_form.elevation;
                WeatherFlowNS.NS.AddStation(a_form.station_id, a_form.elevation, a_form.air_id, a_form.sky_id, a_form.remote, station.AirSN, station.SkySN, a_form.rapid);
                return(true);
            }
            else
            {
                WFLogging.Error("Failed to find station " + a_form.station_id.ToString());
                cfg_file_status = "Station " + a_form.station_id.ToString() + " lookup failed.";
            }
            return(false);
        }
コード例 #22
0
        internal void RapidWindEvt(string json)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            try {
                // evt[0] = timestamp
                // evt[1] = speed (m/s)
                // evt[2] = direction
                WindObj = serializer.Deserialize <WindData>(json);

                StationInfo si = wf_station.FindStationSky(WindObj.serial_number);
                if (si.rapid)
                {
                    WeatherFlowNS.NS.RaiseRapidEvent(this, new RapidEventArgs(WindObj));
                    WeatherFlowNS.NS.RaiseUpdateEvent(this, new UpdateEventArgs((int)WindObj.ob[0], WindObj.serial_number + "_r", DataType.WIND));
                }
            } catch (Exception ex) {
                WFLogging.Error("Failed to deserialize rapid wind event: " + ex.Message);
                WFLogging.Error(json);
            }
        }
コード例 #23
0
ファイル: wf_server.cs プロジェクト: bpaauwe/WFNodeServer
 private void Listen()
 {
     using (listener = new HttpListener()) {
         try {
             listener.Prefixes.Add("http://*:" + port.ToString() + "/");
             listener.Start();
         } catch (Exception ex) {
             WFLogging.Error("Failed to start web server on port " + port.ToString());
             WFLogging.Error("  Error was: " + ex.Message);
             return;
         }
         while (true)
         {
             try {
                 HttpListenerContext context = listener.GetContext();
                 Process(context);
             } catch (Exception ex) {
                 WFLogging.Error("Failed to process connection: " + ex.Message);
             }
             //Thread.Sleep(5000);
         }
     }
 }
コード例 #24
0
        // TODO:
        //   How do we want to handle the device status?  There should
        //   be at least 2 devices present (Air & Sky). Do we create
        //   a HS record for each and use that as a place to store the
        //   device specific data?  Or do we just create an internal
        //   list of devivces?
        //
        //   Whatever we do here we should probably do for the hub
        //   as well (treat it as a third device).
        private void DeviceStatus(string json)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            try {
                DeviceObj = serializer.Deserialize <DeviceData>(json);

                // Add event to update this info.
                try {
                    WeatherFlowNS.NS.RaiseDeviceEvent(this, new WFNodeServer.DeviceEventArgs(DeviceObj));
                } catch {
                    WFLogging.Warning("Failed to process device event.");
                }
                WeatherFlowNS.NS.RaiseUpdateEvent(this, new UpdateEventArgs((int)DeviceObj.timestamp, DeviceObj.serial_number + "_d", DataType.DEVICE));

                //Console.WriteLine("Serial Number:     " + DeviceObj.serial_number);
                //Console.WriteLine("Device Type:       " + DeviceObj.type);
                //Console.WriteLine("Hub Serial Number: " + DeviceObj.hub_sn);
                //Console.WriteLine("timestamp:         " + DeviceObj.timestamp.ToString());
                //Console.WriteLine("uptime:            " + DeviceObj.uptime.ToString());
                //Console.WriteLine("Voltage:           " + DeviceObj.voltage.ToString());
                //Console.WriteLine("Firmware:          " + DeviceObj.firmware_revision.ToString());
                //Console.WriteLine("RSSI:              " + DeviceObj.rssi.ToString());
                //Console.WriteLine("Sensor status:     " + DeviceObj.sensor_status.ToString());

                if (Sensors.ContainsKey(DeviceObj.serial_number))
                {
                    Sensors[DeviceObj.serial_number] = DeviceObj;
                }
                else
                {
                    Sensors.Add(DeviceObj.serial_number, DeviceObj);
                }
            } catch (Exception ex) {
                WFLogging.Error("Deserialization of device status failed: " + ex.Message);
            }
        }
コード例 #25
0
        private void HubStatus(string json)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            try {
                HubObj = serializer.Deserialize <HubData>(json);
                WeatherFlowNS.NS.RaiseHubEvent(this, new WFNodeServer.HubEventArgs(HubObj));
                WeatherFlowNS.NS.RaiseUpdateEvent(this, new UpdateEventArgs((int)HubObj.timestamp, HubObj.serial_number, DataType.HUB));

                //Console.WriteLine("Serial Number:     " + HubObj.serial_number);
                //Console.WriteLine("Device Type:       " + HubObj.type);
                //Console.WriteLine("Firmware:          " + HubObj.firmware_revision.ToString());
                //Console.WriteLine("uptime:            " + HubObj.uptime.ToString());
                //Console.WriteLine("RSSI:              " + HubObj.rssi.ToString());
                //Console.WriteLine("timestamp:         " + HubObj.timestamp.ToString());
                //Console.WriteLine("Reset Flags:       " + HubObj.reset_flags);
                //Console.WriteLine("Stack:             " + HubObj.stack);
                //Console.WriteLine("Sequence:          " + HubObj.seq.ToString());
                //Console.WriteLine("External File:     " + HubObj.fs.ToString());
                ValidHub = true;
            } catch (Exception ex) {
                WFLogging.Error("Deserialization of device status failed: " + ex.Message);
            }
        }
コード例 #26
0
        private void SkyObservations(string json)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            try {
                SkyObj       = serializer.Deserialize <SkyData>(json);
                SkyObj.valid = true;

                WFNodeServer.SkyEventArgs evnt = new SkyEventArgs(SkyObj);
                evnt.SetDaily = CalcDailyPrecipitation();
                evnt.Raw      = json;

                try {
                    WeatherFlowNS.NS.RaiseSkyEvent(this, evnt);
                } catch (Exception ex) {
                    WFLogging.Warning("Failed to process Sky event. " + ex.Message);
                }
                WeatherFlowNS.NS.RaiseUpdateEvent(this, new UpdateEventArgs((int)SkyObj.obs[0][0].GetValueOrDefault(), SkyObj.serial_number, DataType.SKY));
            } catch (Exception ex) {
                WFLogging.Error("Deserialization failed for sky data: " + ex.Message);
                WFLogging.Verbose(json);
                return;
            }
        }
コード例 #27
0
        //  Look for UPNP broadcast messages from an ISY. If it finds
        //  one, then use it.
        //
        //  FIXME: How do we know this is the right ISY?  What if there
        //  is more than one on the network?
        internal static string IsyAutoDetect()
        {
            UdpClient  listen_udp;
            IPAddress  group_ip;
            IPEndPoint group_ep;
            string     ip = "";

            byte[] recv_data;
            int    i;
            string buf   = "";
            int    tries = 100;

            using (listen_udp = new UdpClient()) {
                listen_udp.ExclusiveAddressUse = false;
                listen_udp.Client.SetSocketOption(SocketOptionLevel.Socket,
                                                  SocketOptionName.ReuseAddress, true);
                group_ip = IPAddress.Parse("239.255.255.250");
                //group_ep = new IPEndPoint(IPAddress.Any, 1900);
                group_ep = new IPEndPoint(IPAddress.Any, 20034);

                try {
                    listen_udp.Client.Bind(group_ep);
                } catch (Exception e) {
                    WFLogging.Error("Failed to bind to broadcast address");
                    WFLogging.Error(e.Message);
                    return("");
                }

                listen_udp.EnableBroadcast = true;

                try {
                    listen_udp.JoinMulticastGroup(group_ip);
                } catch (Exception e) {
                    WFLogging.Error("Failed to join Multicast group: " + e.Message);
                    //listen_udp.Close();
                    return("");
                }

                // Set the timeout at 90 seconds.  If we haven't received anything in
                // that time, we probably won't.
                listen_udp.Client.ReceiveTimeout = 90000;

                while ((ip == ""))
                {
                    try {
                        recv_data = listen_udp.Receive(ref group_ep);
                    } catch {
                        WFLogging.Error("Timed out trying to discover ISY.");
                        return("");
                    }
                    if (recv_data.Length != 0)
                    {
                        // Found somelthing
                        buf = Encoding.ASCII.GetString(recv_data);

                        // Now see if this is really an ISY
                        if (buf.Contains("X_Insteon") == false)
                        {
                            if (--tries == 0)
                            {
                                WFLogging.Error("Failed to detect ISY on the network.");
                                return("");
                            }
                        }
                        else
                        {
                            // This really is an ISY.  Pull the location field
                            // from the string.
                            i = buf.IndexOf("LOCATION:");
                            if ((i > 0))
                            {
                                ip = buf.Substring((i + 9)).Split('\r')[0];
                            }
                        }
                    }
                }
                listen_udp.DropMulticastGroup(group_ip);
                //listen_udp.Close();
            }

            WFLogging.Log(("Found an ISY: " + ip));
            return(ip);
        }
コード例 #28
0
        // handle a client connection
        private void ClientHandler(TcpClient client)
        {
            Byte[]        bytes;
            NetworkStream stream = client.GetStream();

            WFLogging.Info("Log client connected.");
            // Wait for data to be available
            while (!stream.DataAvailable)
            {
                ;
            }

            bytes = new Byte[client.Available];
            stream.Read(bytes, 0, bytes.Length);

            //translate bytes of request to string
            String data = Encoding.UTF8.GetString(bytes);

            byte[]       response = null;
            const string eol      = "\r\n"; // HTTP/1.1 defines the sequence CR LF as the end-of-line marker

            WFLogging.Debug("GOT:" + bytes.Length.ToString() + ": " + data);

            if (new System.Text.RegularExpressions.Regex("^GET").IsMatch(data))
            {
            }

            string protocol = new System.Text.RegularExpressions.Regex("Sec-WebSocket-Protocol: (.*)").Match(data).Groups[1].Value.Trim();

            Console.WriteLine("Protocol: " + protocol);
            int l = bytes.Length;

            if (bytes[l - 1] == '\n' && bytes[l - 2] == '\r' && bytes[l - 3] == '\n')
            {
                response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + eol
                                                  + "Upgrade: websocket" + eol
                                                  + "Connection: Upgrade" + eol
                                                  + "Sec-WebSocket-Protocol: " + protocol + eol
                                                  + "Sec-WebSocket-Accept: " + Convert.ToBase64String(
                                                      System.Security.Cryptography.SHA1.Create().ComputeHash(
                                                          Encoding.UTF8.GetBytes(
                                                              new System.Text.RegularExpressions.Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups[1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
                                                              )
                                                          )
                                                      ) + eol
                                                  + eol);
                stream.Write(response, 0, response.Length);
                stream.Flush();
                WFLogging.Debug(Encoding.ASCII.GetString(response));
            }
            else
            {
                // What do we do here if we don't get a proper header (or complete header)?
                WFLogging.Info("Didn't get a proper header, closing connection");
                client.Close();
                return;
            }

            // Start sending the log.
            //  Only send the most recent 500 lines of data because sending more
            //  here makes the interface unresponse for too long while it processes
            //  it all.
            int start = (WFLogging.EventLogCount > 500) ? (WFLogging.EventLogCount - 500) : 0;

            for (int i = start; i < WFLogging.EventLogCount; i++)
            {
                string[] e = WFLogging.GetEvent(i);
                try {
                    SendMessage(client, e[0] + "\t" + e[1], 0x01);
                } catch {
                    // Sending to client failed for some reason. So abort.
                    client.Close();
                    return;
                }
            }

            // Push the client to the client list
            clients.Add(client);

            // Handle data comming in over the connection. Mainly we want to
            // check for a close connection frame. If we get a close frame
            // then close the connection.
            while (stream.DataAvailable)
            {
                bytes = new Byte[client.Available];
                stream.Read(bytes, 0, bytes.Length);

                // Data from client that needs to be decoded?
                WFLogging.Debug("Got " + bytes.Length.ToString() + " bytes from client to decode");
                if ((bytes[0] & 0x80) == 0x80)
                {
                    int payload_type    = bytes[0] & 0x0f;
                    int payload_size    = bytes[1] & 0x7f;
                    int payload_masking = bytes[1] & 0x80;
                    WFLogging.Debug("type = " + payload_type.ToString() + " mask = " + payload_masking.ToString() + " len = " + payload_size.ToString());
                    if (payload_size < 126)
                    {
                        if (payload_masking == 0x80)
                        {
                            byte[] mask = new byte[4];
                            mask[0] = bytes[2];
                            mask[1] = bytes[3];
                            mask[2] = bytes[4];
                            mask[3] = bytes[5];
                            for (int i = 0; i < payload_size; i++)
                            {
                                bytes[6 + i] = (byte)(bytes[6 + i] ^ mask[i % 4]);
                            }
                            WFLogging.Debug("Payload: " + Encoding.ASCII.GetString(bytes, 6, payload_size));
                        }
                        else
                        {
                            //for (int i = 0; i < payload_size; i++)
                            //   state.buffer[2+i] = (byte)(state.buffer[2+i] ^ 0x10);
                            WFLogging.Debug("Payload: " + Encoding.ASCII.GetString(bytes, 2, payload_size));
                        }
                    }
                    else
                    {
                        WFLogging.Debug("Extended size: " + payload_size.ToString());
                    }

                    switch (payload_type)
                    {
                    case 0x01:      // text payload
                        Console.WriteLine("Got a text payload");
                        break;

                    case 0x02:      // binary payload
                        Console.WriteLine("Got a binary payload");
                        break;

                    case 0x0A:      // Pong
                        break;

                    case 0x09:      // Ping
                        // Send a pong message back
                        Console.WriteLine("Received ping frame, should send a pong");
                        break;

                    case 0x08:      // close connection
                        Console.WriteLine("Received close frame, closing connection");
                        clients.Remove(client);
                        client.Close();
                        return;
                    }
                }
                else
                {
                    WFLogging.Debug("Non Frame: " + Encoding.ASCII.GetString(bytes, 0, bytes.Length));
                }
            }
        }
コード例 #29
0
ファイル: wf_websocket.cs プロジェクト: bpaauwe/WFNodeServer
        internal void Start()
        {
            byte[] buf = new byte[512];
            int    len;
            bool   header = false;

            while (Started)
            {
                int retries = 0;

                WFLogging.Warning("Attempt to start already active WebSocket connection " + retries.ToString());
                Thread.Sleep(1000);

                if (retries++ > 10)
                {
                    WFLogging.Error("Giving up after 10 attempts.");
                    return;
                }
            }

            client = new TcpClient(Host, Port);
            if (!client.Connected)
            {
                WFLogging.Error("Client not connected to " + Port);
            }

            WFLogging.Log("Starting communication with websocket server.");
            finished = false;
            Started  = true;

            // Send header
            var seckeybytes = Encoding.UTF8.GetBytes(seckey);

            client.Client.Send(Encoding.ASCII.GetBytes("GET " + Path + " HTTP/1.1\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Host: " + Host + ":" + Port.ToString() + "\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Upgrade: websocket\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Connection: Upgrade\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Pragma: no-cache\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Origin: http://" + Host + "\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Cache-Control: no-cache\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Sec-WebSocket-Key: " + System.Convert.ToBase64String(seckeybytes) + "\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("Sec-WebSocket-Version: 13\r\n"));
            client.Client.Send(Encoding.ASCII.GetBytes("\r\n"));

            WFLogging.Info("    Waiting for handshake");
            Thread.Sleep(100);
            // Receive handshake
            while (!header)
            {
                if (client.Client.Available > 0)
                {
                    len = client.Client.Receive(buf, (client.Client.Available - 1), SocketFlags.None);
                    if (len > 0)
                    {
                        string strbuf = Encoding.ASCII.GetString(buf, 0, len);
                        // Just look for the a websock type response, ignore the rest of the headers
                        if (strbuf.Contains("HTTP/1.1 101"))
                        {
                            header = true;
                        }
                    }
                }
                Thread.Sleep(500);
            }

            receive_thread = new Thread(new ThreadStart(ReceiveLoop));
            receive_thread.IsBackground = true;
            receive_thread.Start();
        }
コード例 #30
0
ファイル: wf_websocket.cs プロジェクト: bpaauwe/WFNodeServer
        private static void ReceiveCallback(IAsyncResult ar)
        {
            StateObject state  = (StateObject)ar.AsyncState;
            TcpClient   client = state.workSocket;

            int bytes_read = client.Client.EndReceive(ar);

            if (bytes_read > 0)
            {
                int    bi   = 0;
                byte[] mask = new byte[4];
                if ((state.buffer[0] & 0x80) == 0x80)
                {
                    int payload_type    = state.buffer[0] & 0x0f;
                    int payload_size    = state.buffer[1] & 0x7f;
                    int payload_masking = state.buffer[1] & 0x80;
                    bi += 2;
                    //Console.WriteLine("type = " + payload_type.ToString() + " mask = " + payload_masking.ToString() + " len = " + payload_size.ToString());
                    if (payload_size == 126)
                    {
                        payload_size = (state.buffer[bi++] << 8) + state.buffer[bi++];
                        //Console.WriteLine("extended size = " + payload_size.ToString());
                    }
                    if (payload_masking == 0x80)
                    {
                        mask[0] = state.buffer[bi++];
                        mask[1] = state.buffer[bi++];
                        mask[2] = state.buffer[bi++];
                        mask[3] = state.buffer[bi++];
                    }

                    if (bytes_read > payload_size)
                    {
                        for (int i = 0; i < payload_size; i++)
                        {
                            if (payload_masking == 0x80)
                            {
                                state.buffer[bi + i] = (byte)(state.buffer[bi + i] ^ mask[i % 4]);
                            }
                        }

                        if (payload_type == 0x01)
                        {
                            // TODO: Text type payload so send it somewhere
                            //Console.WriteLine("Payload: " + Encoding.ASCII.GetString(state.buffer, bi, payload_size));
                            //Program.RaiseEvent(new WSEventArgs(Encoding.ASCII.GetString(state.buffer, bi, payload_size)));
                            ProcessWSData(Encoding.ASCII.GetString(state.buffer, bi, payload_size));
                        }
                        else if (payload_type == 0x02)
                        {
                            // Binary payload
                        }
                        else if (payload_type == 0x00)
                        {
                            WFLogging.Error("Got a continuation opcode, currently not supported.");
                        }
                        else if (payload_type == 0x08)
                        {
                            // Close frame
                            finished = true;
                            SendMessage(client, Encoding.ASCII.GetString(state.buffer, bi, payload_size), 0x08);
                        }
                        else if (payload_type == 0x09)
                        {
                            // Ping so we need to pong
                            SendMessage(client, Encoding.ASCII.GetString(state.buffer, bi, payload_size), 0x0A);
                        }

                        receiveDone.Set();
                        return;
                    }
                    else
                    {
                        // We need to read more data
                        WFLogging.Info("Need more data to complete frame");
                        client.Client.BeginReceive(state.buffer, 0, StateObject.bufsize, 0, new AsyncCallback(ReceiveCallback), state);
                        return;
                    }
                }
            }
            receiveDone.Set();
        }