Earlier this year I posted about the myRIO Giant Tetris project I worked on which ended up appearing at NI Week in Texas and NI Days in the UK this year. One of the coolest features of this was the ability to control the game using a web browser from a computer or mobile device. The technology for doing this was WebSockets which allows you to create and maintain an open WebSocket connection (using TCP/IP) and send data with low-latency and overhead between a modern web-browser and a server (in this case LabVIEW RT).
I have finally been able to tidy up the code and offer it to the community to play with!
Here's what I originally wrote about WebSockets for the Giant Tetris:
WebSockets is a web technology that allows a browser and a server to communicate in a way similar to TCP/IP. The browser sends a WebSocket upgrade request (very similar to a HTTP request), the server sends a HTTP response with specific headers and then you can send/receive data through the open connection. To implement this in LabVIEW I used the TCP/IP VIs and some additional VIs for performing the HTTP handshaking and framing the websockets data. In my case, the browser is communicating directly with the myRIO (or it could be other RT targets or PCs) with no intermediate server.
The library I have produced acts as a wrapper for the TCP Read/Write VIs and includes a handshaking VI for reading and responding to an incoming handshake request from the browser.
Here's an overview of the API for the LabVIEW Side:
Do Handshake: Performs the WebSocket handshaking after a connection is made - reads the headers from the HTTP request and replies with the appropriate WebSocket key to open the connection.
Do Client Handshake: This VI allows you to initiate a connection acting as a WebSocket client, communicating to an existing WebSocket server (either implementing in LabVIEW or otherwise). It sends the necessary HTTP header to start a WebSocket connection and waits for the reply from the server.
Get Header: I store the header name/value pairs as variant attributes, you can use this VI to retrieve a header value.
Read: Wrapper for the TCP Read primitive that splits out the data from the WebSocket frame. The returned Opcode is as per the WebSocket standard.
Write: Wrapper for the TCP Write primitive that packages the data into a WebSocket frame and sends to the connection.
Close: Sends the WebSocket close Opcode to the browser. According to the WebSockets spec, both sides of the connection are supposed to send the close Opcode before terminating the TCP connection so this VI doesn't close the TCP connection.
As it's just a wrapper for TCP/IP functions with some maths/string manipulation (for hashing the WebSocket key) it works on RT and Windows targets.
The included example VI, when run, acts as a server for an incoming WebSocket connection, displays the string data received from the connected browser and allows you to send string data back to the browser. The included index.html file in the installed package acts as a client to connect and display the string data:
I've published this in an attempt that it will be useful for the NI community. The package/source is released under the MIT License.
If you find anything wrong with it then I hope you'll let me know in the comments so it can be improved and built upon.
The VI package is available/installed through the LabVIEW Tools Network VIPM repository at the following link: vipm://mediamongrels_ltd_lib_websockets_api
V184.108.40.206 (19/10/2016) - The package has now been released on the NI LabVIEW Tools Network package repository! This and future versions will be available directly through VIPM (link: vipm://mediamongrels_ltd_lib_websockets_api). Changes in this version include:
- Fixed an issue with the incorrect EOL being used in InitiateClientHandshake.vi for better cross-platform support.
- Added support for sending additional headers in the client handshake / server response
- Added support for Sec-WebSocket-Protocol: The DoHandshake.vi now has a 'supported protocols' input which allows supported protocols to be listed (in order of preference). This will increase compatibility with existing WebSocket servers.
- The package is now released under the MIT License
Note: The VI package has also changed name. Please uninstall any previous versions of this package before upgrading.
V220.127.116.11 (20/04/2015) - Added functionality to be able to act as a WebSockets client - incoming/outgoing messages are now de-masked correctly and optionally masked for transmission. Added VI for creating & sending the HTTP handshake. This WS client functionality has not been fully tested (e.g. with external WS servers) but has been tested with a LabVIEW server using my library.
V18.104.22.168 (04/02/2015) - Made mask values more clear in source and updated calculation of message length bytes. (Thanks Stuart)
V22.214.171.124 (19/12/2014) - Fixed an error in DoHandshake that was causing the VI to finish only on timeout instead of at the end of the HTTP header (causing connections to take longer than required).