I want to build a Raspberry Pi (RPi) based device similar to the Nest Thermostat, except that I want to control light switches. I know I could easily code up a Node.js script on the RPi and then just hook it up to my local router and control it with a PC hooked up to the same router.
But, I want to make it more like a Nest. I want to be able to control 20 (or more) RPis across different subnets through a cloud provider like Heroku.
The Nest thermostat does not require the user to open a port on their router so that the Nest server can communicate with it.
How is Nest able to control customer's thermostats over the web without enabling port forwarding in the customer's router?
Blog post Nest Thermostat API using Node JS and Nest API Update discusses the API between the thermostat and the nest lab servers. In particular:
The API uses mostly JSON formatted data POSTed to their web servers.
So there is your answer. By periodically POSTing data to the nest web servers using HTTPS, Nest is able to avoid having the user open any ports on their router.
I think the thermostat periodically posts a request with the thermostat serial number to nest. It may have timeouts in the http headers set to infinity or more likely, the nest server simply closes the connection after a minute or so if no command for that device has come in. Whenever nest closes the connection the thermostat opens a new one. When a command request comes in with serial number, its a quick lookup to find the thread currently connected to that thermostat. The command is sent in the payload of the current thermostat request, which is executed, the connection is closed, and the thermostat opens a new request to nest .
Take a look at eventSource in the HTML 5 standard. It does everything that is required.