Starting Rest Streaming from an embedded system

馋奶兔 提交于 2019-12-23 02:31:05

问题


I'm using a fairly limited embedded system so I can't use any of the libraries and I'm on my own building HTTP requests. I'm able to handle the stats pretty well with polling but I'm trying to turn on Rest Streaming

The Nest site directs you to the Firebase site which directs you to the W3C site and all I get through all of that is to 'include the header: Accept: text/event-stream in your request'.

If I send the request (after the redirect):

GET /?auth=[auth code] HTTP/1.1
Host: firebase-apiserver02-tah01-iad01.dapi.production.nest.com:9553

I get the full structure as JSON. If I send:

GET /?auth=[auth code] HTTP/1.1
Host: firebase-apiserver02-tah01-iad01.dapi.production.nest.com:9553
Accept: text/event-stream
Connection: keep-alive

I get a 200 OK response but nothing else. The connection doesn't close but nothing comes after. Am I on the right track here? It seems like this should be a bigger deal, and it must be because I got nothing and no clue where to go next.

Is anybody using Rest Streaming with Nest (without the libraries)?


回答1:


The socket is kept alive and any updates are sent over it. It returns a 200 OK with the entire data to start with and then keeps sending you updates as they happen. Here is an example with curl. One thing to notice is that if you update the state of your thermostat (via the web or physically), you get back an update.

< HTTP/1.1 200 OK
< Content-Type: text/event-stream; charset=UTF-8
< Access-Control-Allow-Origin: *
< Cache-Control: private, no-cache, max-age=0
<
event: put
data: {"path":"/","data":{"devices":{...}}

event: keep-alive
data: null

...

Hope that helps




回答2:


audiotech, It looks like nest-firebase is using WebSockets to send updates back to the client. I am working in C# WindowsForms, but what I found will be useful to you.

I can get my structure info using this:

    HttpWebRequest myStructHttpWebRequest=(HttpWebRequest)WebRequest.Create("https://developer-api.nest.com/structures/?auth=" + AccessToken);
myStructHttpWebRequest.Method = "GET";
myStructHttpWebRequest.MaximumAutomaticRedirections=3;
myStructHttpWebRequest.AllowAutoRedirect=true;
myStructHttpWebRequest.Accept = "text/event-stream; application/json";
myStructHttpWebRequest.Credentials = CredentialCache.DefaultCredentials;
myStructHttpWebRequest.KeepAlive = false;
using(HttpWebResponse myHttpWebResponse = (HttpWebResponse) myStructHttpWebRequest.GetResponseAsync())
{
    if (null != myHttpWebResponse)
    {
        // Store the response.
        Stream sData = myHttpWebResponse.GetResponseStream(); 
        StreamReader readStream = new StreamReader (sData, Encoding.UTF8);
        string data = readStream.ReadToEnd();
        readStream.Close();
        Debug.WriteLine("Response Structure stream received: " + data);
        success = deserializeStructure(data);
    }
}

I changed the code above to: myStructHttpWebRequest.AllowAutoRedirect=false; and got the redirect address path:

if (HttpStatusCode.TemporaryRedirect == myHttpWebResponse.StatusCode)
{
    string[] redirect = myHttpWebResponse.Headers.GetValues("Location");
    path = redirect[0];
}

I start a web socket connection to this new path with this function and receive this message back from the firebase server: "{\"t\":\"c\",\"d\":{\"t\":\"h\",\"d\":{\"ts\":1406745104997,\"v\":\"5\",\"h\":\"firebase-apiserver01-tah01-iad01.dapi.production.nest.com:9553\",\"s\":\"session-819323581\"}}}"

Here is my WebSocket code:

        private async void startNestWebSocketConnection(string path)
    {
        try
        {
            listener = new ClientWebSocket();
            if (path.StartsWith("https:"))
            {
                path = "wss:" + path.Substring(6) + ":" + COMMUNICATION_PORT.ToString();
            }
            await listener.ConnectAsync(new Uri(path),CancellationToken.None);
            var buffer = new byte[1024 * 4];
            Debug.WriteLine("ClientWebSocket connected " + listener.State.ToString());
            while (true)
            {
                ArraySegment<byte> segment = new ArraySegment<byte>(buffer);

                WebSocketReceiveResult result = await listener.ReceiveAsync(segment, CancellationToken.None);

                if (result.MessageType == WebSocketMessageType.Close)
                {
                    Debug.WriteLine("ClientWebSocket CLOSING");
                    await listener.CloseAsync(WebSocketCloseStatus.InvalidMessageType, "Closing ClientWebSocket", CancellationToken.None);
                    return;
                }

                int count = result.Count;
                while (!result.EndOfMessage)
                {
                    if (count >= buffer.Length)
                    {
                        await listener.CloseAsync(WebSocketCloseStatus.InvalidPayloadData, "That's too long", CancellationToken.None);
                        return;
                    }

                    segment = new ArraySegment<byte>(buffer, count, buffer.Length - count);
                    result = await listener.ReceiveAsync(segment, CancellationToken.None);
                    count += result.Count;
                    Debug.WriteLine("ClientWebSocket getting " + count.ToString());
                }

                string message = Encoding.UTF8.GetString(buffer, 0, count);
                Debug.WriteLine(">" + message);
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine("startNestWebSocketConnection path=" + path + " Exception=" + ex.ToString());
        }
    }

I don't know what the reply means yet, but it shows a time stamp, and a session id! I will let you know more when I do more testing.



来源:https://stackoverflow.com/questions/24962370/starting-rest-streaming-from-an-embedded-system

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!