OAuth2 and LabVIEW — Part Four, Reusability
After finishing part three of this series of posts on OAuth2, I went back to my original goal of writing code to interact with my Wireless Sensor Tags for measuring temperature and humidity. The further I went down that path, the more I wanted to change the existing example code.
Since this is a blog post that is partly about how the example evolved, I wanted to write a part four to describe my thought process. The code has been updated in the repository: https://gitlab.com/bhpowell/oauth2-labview-tutorial
Overall file organization
My first step in adding support for the Wireless Tag web service was to duplicate Main.vi. I called the new copy “Wireless Tag.vi”, and began changing out the endpoints, IDs, secrets, and such. To reduce confusion about two top-level VIs, I renamed Main.vi to “Example Get Google Photo.vi”. Not necessarily a great name, but more descriptive than “Main”.
As I began changing out “google.com” and “googleapis.com” endpoints for “my.wirelesstag.net” endpoints, I realized I’d saved several of the subVIs with default values for those endpoints. So, even though I found all of the URLs on the top-level diagram that needed to be updated, when I ran the VI, it was still access Google APIs because of the default values.
Here’s an example for the VI that exchanges the code for the token. First, the original way I used the subVI:
And now the new way. Note that I specifically wire in the token endpoint (on the top) and the client secret (on the bottom), instead of depending on their default values.
I also made those inputs (and a few others) required. Why did I do this? Because the values conceptually belong to the caller that knows it’s talking to Google. The subVI is agnostic of which web service is used, so it shouldn’t hardcode anything to do with Google or any other web service.
This is obvious in retrospect, but I wasn’t really thinking about this when I was working on the original example. It’s only when you try to reuse your code do you really understand how reusable it is.
With these changes, along with one major bug (described below), I realized I needed to update the code on Gitlab.com. But I was now working in a project file that contained both Google and Wireless Tag content. Things were getting messy. I decided to separate the two projects—one for Google, one for Wireless Tag.
But obviously, I wanted to share a lot of the code. I created two Project Libraries for the reusable code—Useful HTTP VIs, and Useful OAuth VIs. I divided up the old “subVIs” folder into those two categories, along with a new folder that was for “Google API subVIs”. This way, each project can reference the two Project Libraries to share the code.
A Bad Request
The most frustrating part of switching to the Wireless Tag API was that I kept getting a bad request when trying to get the access_token:
The perfectly happy “no error” error out is also an indication that my error checking isn’t very good.
I renamed “Parse GET Headers.vi” to “Parse HTTP Response Headers.vi” (because it’s useful for more than just GETs), and added code to parse the HTTP response code (400, in this case) and ensure that any 4xx/5xx errors get reported in the error cluster. This can probably still be improved—I debated whether to put the response code directly into the error cluster code. For now, I just map any HTTP errors to a generic error, but I think there could be merit in putting the HTTP response code in there, instead. Or maybe this is a case where we should use Dmitry’s Error Classes. What do you think? Please Comment below.
With better error checking in place, I wasn’t any closer to figuring out why I was getting a bad request. I kept comparing some C# code that was working to my LabVIEW code that wasn’t. I gave up one evening, hoping that sleep would lead me to the solution. After another hour or so the next morning, I figured it out.
The AddHeader.vi that’s part of the HTTP Client library in LabVIEW has a Combo Box input for common headers. I mistakenly chose “Accept-Encoding”. The proper header I needed to set was “Accept”. This was an error in translation from C#, which clearly used Accept. The Combo Box in LabVIEW doesn’t have “Accept” in its predefined list of values—you have to type it in by hand, and I guess I assumed that “Accept-Encoding” was the right thing to select when I first wrote the code. The Google web server and API accepted this. The Microsoft IIS web server and Wireless Tag API did not.
How did I figure this out? I stared and stared at the request body looking for typos in the client ID or secret, or some other syntax. I searched for known LabVIEW incompatibilities with the HTTP Client library. Ultimately, I installed Wireshark (an Ethernet packet capture tool), and saw that my Accept-Encoding header was in the request along with “Accept: */*”. This caused me to go back and see the obvious setting in the C# example. Making this simple change is all that was needed.
After I got the Wireless Tag example working for a simple API call, I went back to my Google example and tried it. It was broken—I had to go add the new required inputs. Once I fixed that, it ran correctly.
Zoom the Picture Control
The final thing I want to talk about is an answer that Matthew Newland provided to my Question #5, in Part Two. He proposed a solution to resizing the photo in the picture control by using the Picture Control’s ability to zoom. Thank you, Matthew!
I shuffled around the code for calling Draw Flattened Pixmap in the top-level VI, and wired the raw image data and a reference to the picture control into a VI using that snippet above. The result is my entire bald head, not just a corner of it:
I think this has been a good exercise in improving reusability of the code. I do still think of this as mostly an example. I don’t think the pieces are reusable enough to be a VI Package of some sort. My “Useful HTTP VIs” and “Useful OAuth VIs” don’t cover enough use cases for that. They just provide solutions for this example.
For now, I’m just making my VIs available in Gitlab. In the future, I am hopeful that the GCentral initiative will lead to the availability of more reusable code that we all end up sharing. Wouldn’t it be great if we were all contributing towards a common “Useful HTTP VIs” collection?