Example Program Drafts

Showing results for 
Search instead for 
Did you mean: 

LabVIEW WebSockets Library

by Member samsharp99 on ‎11-21-2014 09:26 AM - edited on ‎02-09-2017 08:16 AM by Community Team Kristi_Martinez Community Team

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.

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.

 

I've been waiting for an excuse use WebSockets as a tech demo for my work - we have used LabVIEW Remote Front Panels in the past for communicating with LabVIEW (a cRIO). Although it was easy to setup, it requires the LabVIEW run-time engine to be installed and only works with certain browsers (Internet Explorer). Having done quite a lot of web development, I know that there is an absolutely vast pool of resources for using a web browser for displaying data and doing asynchronous communications using JavaScript and I'd like to leverage that to create great looking user interfaces (using HTML and CSS) that anyone can view/use with any web browser - including mobile devices (and especially tablets - iPad etc.)! WebSockets fulfils the requirement of having data update in real-time and allow the user to press buttons & enter values.

 

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.

 

API - Server

 

Here's an overview of the API for the LabVIEW Side:

2014-11-21_13-57-17.png

 

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.

 

API - Client

For writing your javascript for establishing the connection and sending/receiving data from the server I suggest you check out the wealth of tutorials and information available on the internet. The included example (see below) has the basics and I wrote a little more about the Javascript side at the link for the myRIO Giant Tetris which includes some sample code.

 

Example

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:

2014-11-21_13-31-56.png

 

Known Limitations:

  • Currently only supports sending/receiving string data even though the WebSocket spec supports binary data transfer. I figured that this wouldn't be a huge problem as I figured the most likely use case is using strings or json-encoded data and if you used binary you would need to be able to do the conversion between javascript and LabVIEW formats yourself.
  • It hasn't been tested for sending frames with a long data segment. The WebSocket spec packages the header differently depending on data length and I haven't fully tested that these are correctly prepared for longer data segments.

 

Usage / Disclaimer:

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.

 

If you use it, it would be great if you credit me (Sam Sharp - MediaMongrels Ltd - sam@mediamongrels.com - http://www.mediamongrels.com) but I'm not going to demand it.

 

Installation/Usage:

The VI package is available/installed through the LabVIEW Tools Network VIPM repository at the following link: vipm://mediamongrels_ltd_lib_websockets_api

 

The VI Package is for >=LV2013. You can probably save for a previous version - I don't think it uses anything specific to LV2013 but I was using it with a myRIO hence LV2013 (plus LV2013 has those neat JSON encode/decode which is great for converting between LV and Javascript data types!).

 

Changelog:

V1.6.0.22 (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.

 

V1.3.0.13 (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.

 

V1.2.0.9 (04/02/2015) - Made mask values more clear in source and updated calculation of message length bytes. (Thanks Stuart)

 

V1.1.2.8 (14/01/2015) - Fixed an error in accepting the request due to casing of the initial HTTP headers sent by IE. Fixed the javascript example throwing an error in Firefox. (Thanks Martin)

 

V1.1.1.7 (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).

Comments
Member chrylarson
Member

This is awesome!

Member MartinMcD
Member

This is excellent, thank you. I'm using IE11 and the handshake was failing on the 'Is Websocket Request?' check because 'Upgrade' was returning 'Websocket' and not 'websocket'. I cast the string to lower case before doing the IsEquals check and it works fine now.

In Firefox, it wasn't working for me - the browser was saying the connect() function was not defined. I moved the curly brace in websockets.js from line 69 to line 10 which fixed it.

Member samsharp99
Member

Hi Martin,

Nice find - thank you.

I will update the library and post a new version soon.

Member Andreas-Zeiner
Member

This is absolutly awesome! I was looking for such a thing for months and wanted to code it on my own ... thx a lot man!!! :-)

Member DCatz
Member

Brilliant! Good work Sam. I have been banging on about Websockets for ages - this will really help the community to embrace them! Thanks.

Member john_wu
Member

Great job Sam!  This is just the thing I've been looking for.  One question tho, you've included a sample LabVIEW server and a web page client in your package.  How would one go about making a LabVIEW websocket client that uses your VIs?  I don't see a "send handshake request" subVI in your API.

Member samsharp99
Member

Hi John, I haven't implemented the websocket client side of things to connect to an existing websocket server as:

1) I didn't need to...I was only interested in having LabVIEW act as a server to talk to a browser rather than have LabVIEW communicate with an existing WebSocket server/API

2) It's slightly more complicated as the client implementation must mask outgoing data where as it is optional for a server

Like I said above - it's not a full implementation of the WebSockets standard - but I am open to suggestions/contributions on how to improve it and make it better!

Member Henrik_Molsen
Member

The presentation of this at CLA Summit Europe 2015 was great! And the wireless connection from the phones in the audience worked perfectly! Thanks for a very nice and inspiring piece of software.

Now I have a lot of things to try out....

Thanks Sam.

Member rockyData
Member

I tried your similar code but when i tried to send message from client to server through javascript socket.send() it will gave an exception and connection is closed.

Exception is - 'Invalid Frame Header'

Please provide some solution for this problem.

Thanks !

Member jasonlinker
Member

Is it possible to use this with data other than strings?

Member samsharp99
Member

What do you have in mind? The WebSockets protocol itself supports binary data transfer but then you have the complexity of converting between LabVIEW and JS native data types and I haven't implemented this functionality in my library.

For anything else, you can use the convert to/from JSON functions in LabVIEW for other data types (e.g. clusters) to flatten them to a string that you can read in JavaScript. If you need to transfer binary data (e.g. files/pictures) - you could base64 encode/decode the data to send it as a string.

Member jasonlinker
Member

Also, is it possible to have multiple connections through the same websocket and port? I am trying to have multiple users read and write data to and from the myRIO.  If so, would this be done in Labview or in JavaScript?

Member Staab_Engineering
Member

Websocket rides on TCP, so no. One connection per port.

Member samsharp99
Member

You listen on one port, but once the connection has been established the TCP connection negotiates it's own port for maintaining each connection to free up the listener port for another connection.

Take a look at the multiple client / server examples in LabVIEW or take a look at my WebSockets Chat demo code here: https://decibel.ni.com/content/docs/DOC-41778

Proven Zealot Proven Zealot
Proven Zealot

Staab_Engineering wrote:


                       

Websocket rides on TCP, so no. One connection per port.


                   

Actually that is not exactly correct. A TCP connection is characterized by the two endpoints with IP address and port number each and for TCP to work, every connection needs to be different in at least one of the 4 elements involved here (2 endpoints with 2 characterization values each).

The server can only handle one incoming connection request at the same time but typically it simply hands that incoming connection of to some other code, either a loop going through each connection repeatedly (works well for a few connections but scales very badly for larger number of connections) or starting of a new reentrant handler for it, and then goes back waiting for the next connection request.

The code as presented in the image in the post would need some modifications to allow handling multiple incoming connections seemlessly but it isn't impossible at all.

Member Staab_Engineering
Member

Absolutely correct, rolf. I'm not sure where my head was at when I made that post, but I'm a little emabarrased of it. I've since written a couple of multi-connection server implementations with this library, and it works fine serving mutiple clients through a single port (because all that code is outside the scope of the library).

Member egjohndoe77
Member

After I download v1.3.0.13 and double click to launch, I get the message:

"This package is not compativle with any LabVIEW version on this computer."

I have LV 2009, 2011, 2012, 2014 installed on this computer and have used all of them.

I'm new to this "package" stuff.

Am I missing something?  Does it require LV2013?

thanks!

Member egjohndoe77
Member

AHA!

My Package Manager was too old so I updated it.

It is now "compativle" (ha ha)!

It worked.  Sweet.

still, thanks

Member edvinj
Member

Hi Sam,

Thank you for creating this and sharing with the community -- now this Library is being used across the globe for variety of amazing projects!

We have recently come across a small problem when using the Library on cRIO (same would happen for Linux or any other Unix-alike) when communicating to ROS framework (http://www.ros.org/).

InitiateClientHandshake.vi uses 'End of Line' constant in 'Search and Replace String' function, which differs between OS'. Instead of using LabVIEW constant, '\r\n' (which has the same meaning in Windows) would make the parsing to work cross-platform as expected. To use '\' as part of the string, you need to right click on a string constant and select "'\' Codes Display" instead of "Normal Display".

Thanks,

Edvin

Member samsharp99
Member

Hi edvin - this is an issue that I am aware of, I just haven't gotten around to fixing it in the 'initiate client handshake' VI (it is fixed in the server-side handshake VI). I'm aware of the difference between 'normal' and '\ codes' display . Glad to hear you are making good use of the library!

Member Bestzzh
Member

Hi, Sam,

The websocket interface you designed is perfect. It helps me a lot since I want to communicate with web app. Thanks you very much.

I have tested the "WebSockets Chat" which is based on "intelligent_energy_lib_websockets_api-1.2.0.9.vip". It can works perfectly.

I know you have updated the vip to V1.3.0.13 (20/04/2015) . It seems to be more easy and convenient than the old version.

But I don't know how to use the new version V1.3.0.13. Would you please share some examples or detailed guidances. 

Thanks a lot.

Member Staab_Engineering
Member

Been using this API happily for a long time. One of my applications needs to face the public Internet, which means I need to move to WSS protocol (Websocket over TLS). Do you -- or does anyone who sees this -- have an upgraded API that provides that protocol to LV?

Member samsharp99
Member

Hi, I have not needed it (always using local connections) so I haven't implemented it in the library. It should be relatively easy to replace the TCP/IP VIs with a secure equivalent as I believe that is the only difference. I'm not too familiar with the inner workings of SSL and how it relates to a socket connection.

It looks like someone has done SSL communications in LabVIEW here: https://decibel.ni.com/content/docs/DOC-34833

It might also be possible using .NET to do the TCP/IP calls over a secure socket.

There is also a discussion about SSL TCP/IP here: http://forums.ni.com/t5/LabVIEW/TCP-IP-using-SSL/td-p/2583817

Active Participant cirrusio
Active Participant

I haven't used this yet, but am starting to question why I didn't investigate this when beginning to work with web services. This looks awesome, but why has NI not fully embraced this as part of the standard toolset yet?

Member SEMAK
Member

Hi,

Thumb up for Engineer. SamSharp,It’s really a priceless effort from Samsharp.

Dear All,

I have a quick questions related to the Topic as well 

 

1-I’ve small LabVIEW Code running on Raspberry –pi3 platform where I have couple of devices to be monitored and controlled .

   My Question is How to  Read and write to those Peripheral remotely while my Raspberry PI is connected to internet through WIFI?

   I’ve created Web services to use NI UI Web-builder but stuck with “How to connect OR access Raspberry PI over WIFI” ?

   Could you please advise me how to use SamSharp libraries to achieve this OR would be great if there is any example etc.  OR any advice would be welcome and appreciated .

   Thanks for your time and consideration guys.