コード例 #1
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;
        }
コード例 #2
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);
        }
コード例 #3
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);
        }
コード例 #4
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();
            }
        }
コード例 #5
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;
        }
コード例 #6
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));
                }
            }
        }
コード例 #7
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();
        }
コード例 #8
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();
        }
コード例 #9
0
ファイル: wf_heartbeat.cs プロジェクト: bpaauwe/WFNodeServer
        private void UpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            string   report;
            string   prefix = "ns/" + WF_Config.Profile.ToString() + "/nodes/";
            DateTime start  = DateTime.Now;

            if (++interval >= 10)
            {
                WFLogging.Info("ISY Request Rate: " + WeatherFlowNS.NS.Rest.stats.Rate + " requests/minute");
                interval = 0;
            }

            foreach (string address in WeatherFlowNS.NS.NodeList.Keys)
            {
                if (WeatherFlowNS.NS.NodeList[address] == "WF_Hub")
                {
                    if (!HeartBeat.ContainsKey(address))
                    {
                        HeartBeat.Add(address, true);
                    }

                    if (HeartBeat[address])
                    {
                        report = prefix + address + "/report/status/GV0/1/0";
                    }
                    else
                    {
                        report = prefix + address + "/report/status/GV0/-1/0";
                    }
                    HeartBeat[address] = !HeartBeat[address];
                    WeatherFlowNS.NS.Rest.REST(report);

                    // CHECKME: Should we have a last update value for the hub?
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_AirD")
                {
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_SkyD")
                {
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_Lightning")
                {
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_RapidWind")
                {
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_LightningUS")
                {
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_RapidWindUS")
                {
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_LightningUK")
                {
                }
                else if (WeatherFlowNS.NS.NodeList[address] == "WF_RapidWindUK")
                {
                }
                else
                {
                    // this should only sky & air nodes
                    lock (_locker) {
                        TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1);

                        if (SecondsSinceUpdate.ContainsKey(address))
                        {
                            int elapsed = (int)t.TotalSeconds - SecondsSinceUpdate[address].now;
                            report = prefix + address + "/report/status/GV0/" + elapsed.ToString() + "/58";
                            WeatherFlowNS.NS.Rest.REST(report);
                        }
                        else
                        {
                            UDPTime utime;
                            utime.timestamp             = (int)t.TotalSeconds; // On startup, we don't know when the last message was sent
                            utime.now                   = (int)t.TotalSeconds;
                            SecondsSinceUpdate[address] = utime;
                        }
                    }
                }
            }
            WFLogging.Info("HandleHeartbeat " + DateTime.Now.Subtract(start).TotalMilliseconds.ToString("#.00") + " ms");
        }
コード例 #10
0
ファイル: wf_server.cs プロジェクト: bpaauwe/WFNodeServer
        private void ConfigPage(HttpListenerContext context)
        {
            string cfg_page;

            byte[] page;
            byte[] post = new byte[1024];
            Thread do_something;

            //Console.WriteLine("content length = " + context.Request.ContentLength64.ToString());
            if (context.Request.ContentLength64 > 0)
            {
                string[] list;
                string[] pair;
                int      len     = (int)context.Request.ContentLength64;
                bool     initISY = false;
                bool     saveCfg = false;

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

                //Console.WriteLine("Response = " + resp);

                cfg_file_status = "";

                if (resp.Contains("stationcfg"))
                {
                    station_form a_form = GetStationInfo(resp);
                    switch (a_form.action)
                    {
                    case "Delete":
                        WFLogging.Info("Delete station " + a_form.station_id.ToString());
                        WeatherFlowNS.NS.DeleteStation(a_form.station_id);
                        saveCfg = true;
                        break;

                    case "++Add++":
                        bool exists = false;
                        WFLogging.Info("Add station " + a_form.station_id.ToString());
                        // Check if station already exists
                        foreach (StationInfo s in WF_Config.WFStationInfo)
                        {
                            if (s.station_id == a_form.station_id)
                            {
                                cfg_file_status = "Station " + a_form.station_id.ToString() + " already exists.";
                                exists          = true;
                                break;
                            }
                        }
                        if (!exists)
                        {
                            saveCfg = AddStation(a_form);
                        }
                        break;

                    case "Update":
                        WFLogging.Info("Update station " + a_form.station_id.ToString());
                        saveCfg = AddStation(a_form);
                        break;

                    default:
                        WFLogging.Warning("Unknown action [" + a_form.action + "]");
                        break;
                    }
                }
                else if (resp.Contains("upload"))
                {
                    // Upload profile files  TODO: Should this be done in a thread?
                    do_something = new Thread(WeatherFlowNS.NS.UpdateProfileFiles);
                    do_something.IsBackground = true;
                    do_something.Start();
                }
                else
                {
                    list = resp.Split('&');
                    foreach (string item in list)
                    {
                        int v = 0;
                        pair    = item.Split('=');
                        pair[1] = HttpUtility.UrlDecode(pair[1]);
                        switch (pair[0])
                        {
                        case "sAddress":
                            if (pair[1] != WF_Config.ISY)
                            {
                                WF_Config.ISY = pair[1];
                                initISY       = true;
                                saveCfg       = true;
                            }
                            break;

                        case "sUsername":
                            if (pair[1] != WF_Config.Username)
                            {
                                WF_Config.Username = pair[1];
                                initISY            = true;
                                saveCfg            = true;
                            }
                            break;

                        case "sPassword":
                            if (pair[1] != WF_Config.Password)
                            {
                                WF_Config.Password = pair[1];
                                initISY            = true;
                                saveCfg            = true;
                            }
                            break;

                        case "sProfile":
                            int.TryParse(pair[1], out v);
                            if (v != WF_Config.Profile)
                            {
                                WF_Config.Profile = v;
                                initISY           = true;
                                saveCfg           = true;
                            }
                            break;

                        case "webPort":
                            int.TryParse(pair[1], out v);
                            if (v != WF_Config.Port)
                            {
                                WF_Config.Port = v;
                                saveCfg        = true;
                            }
                            break;

                        case "sSI":
                            bool imperial = (pair[1] == "1");
                            if (imperial != WF_Config.SI)
                            {
                                WF_Config.SI = (pair[1] == "1");
                                saveCfg      = true;
                            }
                            break;

                        case "sHub":
                            bool hub = (pair[1] == "1");
                            if (hub != WF_Config.Hub)
                            {
                                WF_Config.Hub = (pair[1] == "1");
                                saveCfg       = true;
                            }
                            break;

                        case "sDevice":
                            bool device = (pair[1] == "1");
                            if (device != WF_Config.Device)
                            {
                                WF_Config.Device = (pair[1] == "1");
                                saveCfg          = true;
                            }
                            break;

                        case "sUnits":
                            int.TryParse(pair[1], out v);
                            if (v != WF_Config.Units)
                            {
                                WF_Config.Units = v;
                                saveCfg         = true;
                            }
                            break;

                        case "sLogLevel":
                            int.TryParse(pair[1], out v);
                            if (v != WF_Config.LogLevel)
                            {
                                WF_Config.LogLevel = v;
                                WFLogging.Level    = (LOG_LEVELS)v;
                                saveCfg            = true;
                            }
                            break;

                        case "serverctl":
                            if (pair[1].Contains("Restart"))
                            {
                                WeatherFlowNS.NS.udp_client.Start();
                                WeatherFlowNS.NS.heartbeat.Start();
                                cfg_file_status = "Server Started";
                                Thread.Sleep(400);
                            }
                            else if (pair[1].Contains("Pause"))
                            {
                                WeatherFlowNS.NS.heartbeat.Stop();
                                WeatherFlowNS.NS.udp_client.Stop();
                                cfg_file_status = "Server Paused";
                            }
                            break;

                        case "websocket":
                            if (pair[1].Contains("Start"))
                            {
                                try {
                                    WeatherFlowNS.NS.StartWebSocket();
                                } catch (Exception ex) {
                                    WFLogging.Error("Starting websocket client failed: " + ex.Message);
                                }
                                cfg_file_status = "Websocket Client Started";
                                Thread.Sleep(400);
                            }
                            else if (pair[1].Contains("Stop"))
                            {
                                WeatherFlowNS.NS.wsi.Stop();
                                cfg_file_status = "Websocket Client Stopped";
                                Thread.Sleep(800);
                            }
                            break;

                        default:
                            break;
                        }
                    }
                }

                if (saveCfg)
                {
                    cfg_file_status += WeatherFlowNS.SaveConfiguration();
                }
                if (initISY)
                {
                    WeatherFlowNS.NS.InitializeISY();
                }
            }

            try {
                cfg_page = MakeConfigPage();
            } catch (Exception ex) {
                WFLogging.Error("Failed to make configuration web page.");
                WFLogging.Error(ex.Message);
                context.Response.Close();
                return;
            }
            // How can we substitute values into the page?  May need to dynamically
            // generate the page instead of storing it as a resource.  That would
            // be a bit of a pain.

            page = ASCIIEncoding.ASCII.GetBytes(cfg_page);

            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();
        }
コード例 #11
0
ファイル: wf_server.cs プロジェクト: bpaauwe/WFNodeServer
        private void Process(HttpListenerContext context)
        {
            string filename = context.Request.Url.AbsolutePath;

            //Console.WriteLine(" request = " + filename);

            if (filename.Contains("config") || filename == "/")
            {
                // Handle configuration
                ConfigPage(context);
                return;
            }

            if (filename.Contains("/log"))
            {
                WFWebLog.LogPage(context);
                return;
            }

            if (filename == "/wflog")
            {
                WFWebLog.LogText(context);
                return;
            }

            if (filename == "/nodeinfo")
            {
                WFNodeInfo.NodeDocPage(context);
                return;
            }

            // WeatherFlow/install  - install
            // Weatherflow/nodes/<address>/query - Query the node and report status
            // WeatherFlow/nodes/<address>/status - report current status
            // WeatherFlow/add/nodes - Add all nodes
            //  These could have a ?requestid=<requestid> at the end
            //  that means we need to send a message after completing the task
            // WeatherFlow/nodes/<address>/report/add
            // WeatherFlow/nodes/<address>/report/remove
            // WeatherFlow/nodes/<address>/report/rename
            // WeatherFlow/nodes/<address>/report/enable
            // WeatherFlow/nodes/<address>/report/disable

            // TODO: Parse out the request id if present
            if (filename.Contains("install"))
            {
                WFLogging.Info("Recieved request to install the profile files.");
            }
            else if (filename.Contains("query"))
            {
                string[] parts;
                parts = filename.Split('/');

                WFLogging.Info("Query node " + parts[3]);
            }
            else if (filename.Contains("status"))
            {
                string[] parts;
                parts = filename.Split('/');

                WFLogging.Info("Get status of node " + parts[3]);
                NodeStatus();
            }
            else if (filename.Contains("add"))
            {
                WFLogging.Info("Add our node.  How is this different from report/Add?");
                AddNodes();

                // the report API is not yet implemented on the ISY so we'll
                // never get anything of these until it is.
            }
            else if (filename.Contains("report/add"))
            {
                WFLogging.Info("Report that a node was added?");
            }
            else if (filename.Contains("report/rename"))
            {
            }
            else if (filename.Contains("report/remove"))
            {
            }
            else if (filename.Contains("report/enable"))
            {
            }
            else if (filename.Contains("report/disable"))
            {
            }
            else if (filename.Contains("favicon.ico"))
            {
            }
            else
            {
                WFLogging.Error("Unknown Request: " + filename);
            }

            context.Response.ContentType     = "text/plain";
            context.Response.ContentLength64 = 0;
            context.Response.AddHeader("Date", DateTime.Now.ToString("r"));
            context.Response.StatusCode = (int)HttpStatusCode.OK;
            context.Response.OutputStream.Flush();
            context.Response.OutputStream.Close();
            context.Response.Close();
        }