The Eject-A-Bed: Part 2
June 25, 2013 Leave a comment
Now that we have a way of controlling the bed via a Netduino, we need a way of controlling the Netduino. We thought about different scenarios – hacking into an alarm clock, a phone app, some kind of light sensor, etc… In all of these scenarios, it made sense to make the Netduino Ethernet aware so I went and bought a new Netduino plus. The two day wait for Amazon prime reminded me how we have come full-circle with getting our goods. I am going to re-write the lyrics from the Music Man’s Well’s Fargo Wagon to the Amazon Wagon
O-ho the Am Azon Wagon is a-comin‘ down the street,
Oh please let it be for me!
O-ho the Am Azon Wagon is a-comin’ down the street,
I wish, I wish I knew what it could be!
In any event event, with the Netduino plus, I could send signals to the Netduino to move the bed up and down. I checked Dan Theyer’s post about how build a solid class to cover Ethernet communications and I checked out this article to get a “Hello World’ Ethernet project up and going.
I decided to start with the ground up happy path using the ‘Hello World’ project. To that end, I added a socket instance to the project
- private static Socket _socket = null;
I then add the SetUpWebServer method like so:
- private static void SetUpWebServer()
- {
- _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
- IPEndPoint ipEndpoint = new IPEndPoint(IPAddress.Any, 80);
- _socket.Bind(ipEndpoint);
- _socket.Listen(10);
- ListenForRequest();
- }
And the ListenForRequest like so:
- public static void ListenForRequest()
- {
- while(true)
- {
- using (Socket clientSocket = _socket.Accept())
- {
- IPEndPoint clientIP = clientSocket.RemoteEndPoint as IPEndPoint;
- EndPoint clientEndPoint = clientSocket.RemoteEndPoint;
- int bytesReceived = clientSocket.Available;
- if (bytesReceived > 0)
- {
- byte[] buffer = new Byte[bytesReceived];
- int byteCount = clientSocket.Receive(buffer, bytesReceived, SocketFlags.None);
- String request = new String(Encoding.UTF8.GetChars(buffer));
- HandleRequest(clientSocket, request);
- SendResponse(clientSocket, request);
- }
- }
- }
- }
You will notice a lack of exception handling and threading. Typically, the _socket.Accept() method should be on the main thread and then handling the message should be done on a separate thread so the _socket can get to listening the next message as fast as possible. However, since the servo is directly tied to individual messages, I thought it was better to make the entire execution serial. Plus, I am lazy.
In any event, once the Netduino gets a request, it then needs to adjust the servo:
- private static void HandleRequest(Socket clientSocket, String request)
- {
- String[] chunkedRequest = request.Split('/');
- String verb = chunkedRequest[0];
- String direction = chunkedRequest[1];
- String amount = chunkedRequest[2];
- Int32 duration = Int32.Parse(amount);
- ActivateServoForBellows(direction, duration);
- }
And the actual controlling of the servo we have seen before:
- private static void ActivateServoForBellows(String direction, Int32 duration)
- {
- if (direction == "UP")
- {
- _servo.Duration = 1250;
- }
- else if (direction == "DOWN")
- {
- _servo.Duration = 1750;
- }
- Thread.Sleep(duration);
- _servo.Duration = 1500;
- }
There can be some confusion about the word “duration”. duration with a little ‘d’ means how long the servo stays in the non-straight position – effectivly how long the bed is moving. Duration with the big ‘D’ means the location of the servo as it rotates around the center – how far the servo moves. When I make this ready for prime time, my covering class will fix this ambiguity because I am a big believer in domain-unique language. I will also be copying much of Dan’s code.
In any event, I also created a response method so the requestor can see something:
- private static void SendResponse(Socket clientSocket, String request)
- {
- String[] chunkedRequest = request.Split('/');
- String verb = chunkedRequest[0];
- String direction = chunkedRequest[1];
- String amount = chunkedRequest[2];
- Int32 duration = Int32.Parse(amount);
- String response = direction + " : " + amount + " was sent.";
- String header = "HTTP/1.0 200 OK\r\nContent-Type: text;charset=utf-8\r\nContent-Length: " +
- response.Length.ToString() + "\r\nConnection: close\r\n\r\n";
- clientSocket.Send(Encoding.UTF8.GetBytes(header), header.Length, SocketFlags.None);
- clientSocket.Send(Encoding.UTF8.GetBytes(response), response.Length, SocketFlags.None);
- }
So now when I send a browser request on my local Ethernet:
And sure enough, we can control the servo with my web browser
And then put together and using the browser in my phone:
Now if there was only a way to speed up the motor so I can launch my kid out of bed in the morning with more force….