Introduction
This week, I created the skeleton of the program for the Arduino stack. I'm not ready to share my source code yet. Let me get the rest of the meat on the skeleton first.
Security
I listed some ideas for my cybersecurity scheme last week. I have incorporated all of the measure I listed into my program. I'm sure there's a hacker out there somewhere who will figure it out. My description here isn't meant as a challenge to them. It's just to inform you of some simple things that worked for me.
- I've chosen a port number, out of the 65,535 available, that's easy to remember.
- The server will only accept client requests from specified devices, and not from the world at large. Although MAC address spoofing is a thing, this will stop all but the most determined hackers.
- The server will use TCP instead of HTTP, trading long and legible transactions for short and incomprehensible ones.
- The router autoforward will be tweaked so that only TCP requests via the specified port can get through to the Arduino.
- The server uses a challenge-and-response mechanism, like two spies swapping passwords. When a socket is opened and the client's authorization is verified, the server sends the client a randomly-generated numeric sequence. The client must reply with the proper numeric sequence. I intend to keep the details of this algorithm proprietary. Sorry, folks.
- It may be necessary to have the server go through the challenge-and-response several times in the life of a connection.
Robustness and Reliability
The terms "robust" and "reliable" are not synonymous. "Reliable" means that the system will not fail during regular operation as a result of stupidity — my stupidity, to be specific. "Robust" means that the system can recover from power failures and loss of Wifi signal all by itself, without any human intervention.
When the Arduino is first powered up, or when it recovers from a power failure, it looks through its list of available Wifi routers and tries each one in turn, until it gets a connection. If it doesn't get a connection at all, then it sets a timer for 10 minutes and tries again. This is because it can take DSL modems and Wifi routers a while to recover from a power failure too, so if it doesn't catch one the first time, it gives it time to reboot.
After it gets a Wifi connection, it sets up a permanent TCP socket to listen for client requests. Although client requests are the whole reason for its existence, they're not very frequent, so it will spend most of its time being idle.
Every 10 minutes or so, it will ping the Wifi router, to verify that it still has the connection. If the ping fails, then the Arduino has lost the connection, so it goes through the power-up sequence again.
When a client requests a connection, the Arduino opens a temporary TCP socket for that client. It will be up to the client to send a TCP query every second or so, unless it's sending a button-push command. It's up to the client, whether it's a webpage or an Android app, to politely say goodbye and close the socket when it exits. (I'm sure that Corona SDK and JavaScript include onExit() event servers, or something similar.)
But it's possible for the remote client to just drop the connection - battery dies, phone gets run over, computer blue-screens, that sort of thing. So the Arduino will set a watchdog timer when it opens the temporary socket. Any query from the client resets the watchdog timer (that's called "kicking the watchdog" in Embedded Programming Land). If the client doesn't send a query for a long time, the watchdog timer expires, the Arduino says goodbye to the client in case the client is listening, and then the Arduino closes the socket.
When the Arduino is first powered up, or when it recovers from a power failure, it looks through its list of available Wifi routers and tries each one in turn, until it gets a connection. If it doesn't get a connection at all, then it sets a timer for 10 minutes and tries again. This is because it can take DSL modems and Wifi routers a while to recover from a power failure too, so if it doesn't catch one the first time, it gives it time to reboot.
After it gets a Wifi connection, it sets up a permanent TCP socket to listen for client requests. Although client requests are the whole reason for its existence, they're not very frequent, so it will spend most of its time being idle.
Every 10 minutes or so, it will ping the Wifi router, to verify that it still has the connection. If the ping fails, then the Arduino has lost the connection, so it goes through the power-up sequence again.
When a client requests a connection, the Arduino opens a temporary TCP socket for that client. It will be up to the client to send a TCP query every second or so, unless it's sending a button-push command. It's up to the client, whether it's a webpage or an Android app, to politely say goodbye and close the socket when it exits. (I'm sure that Corona SDK and JavaScript include onExit() event servers, or something similar.)
But it's possible for the remote client to just drop the connection - battery dies, phone gets run over, computer blue-screens, that sort of thing. So the Arduino will set a watchdog timer when it opens the temporary socket. Any query from the client resets the watchdog timer (that's called "kicking the watchdog" in Embedded Programming Land). If the client doesn't send a query for a long time, the watchdog timer expires, the Arduino says goodbye to the client in case the client is listening, and then the Arduino closes the socket.
TCP/IP
I haven't decided whether to allow multiple clients yet. Normally, only my wife and I will be using the app, and very seldom at the same time. It would be crazily rare to have three people trying to control the garage door at once. Still, it would be annoying for one person to open the app on their phone, and the other person try to open it on theirs, and get the equivalent of a busy signal. So I'll probably have to allow multiple clients.
I haven't put in the actual TCP/IP commands yet. That's for later.
Sensor and Actuator
I haven't wired up the Hall effect sensor, and I haven't written any code for it. And although I haven't actually connected the relay to the garage door opener yet, I have written the relay code, and I've verified that the relay shield plays nicely with the ESP8266 shield.
What's Next
I'll stick with this program until it's finished. Then I'll need to write a server in plain vanilla C, or maybe Python, to test it. Once the program is finished and it works, I'll post the source code.
To read the other postings about this project, click here and scroll to the end.
No comments:
Post a Comment