In part one of this 2020 update, I began a journey of updating my OAuth2 example to use a new feature in LabVIEW 2020–the new hash function that supports SHA-256, among other algorithms.
Where I left off, I needed to modify the output of the new VI to create a byte array instead of converting it to a lowercase hex string.
I proposed three choices:
Ignore the 2020 VI and just use the .Net implementation I used in 2019.
In my SHA256.vi, add code after Byte Array Checksum.vi to convert the hex string back into a binary array.
Make my own copy of Byte Array Checksum.vi and remove the subVI which converts to a lowercase string.
Which one did you choose? I decided to try all three. I already had #1, since it was the 2019 version. Here’s a quick and dirty implementation of #2, where I convert the hex string back to a byte array.
And here’s an implementation of #3, where I went and found the VI that called Bytes to Lowercase Hex String, made a copy of it, and removed the subVI call. I replaced it with a straight Byte Array to String.
What do you think so far? There are things I dislike about both #2 and #3.
In #2, it seems wasteful to convert it to ASCII, and then convert it back. These aren’t large strings, but it just seems like a hack.
In #3, I dislike the idea of modifying a vi.lib VI–especially one that’s not on the palettes.
I’m leaning towards #3, because it feels like the right implementation, even if it violates the “don’t mess with vi.lib VIs” principle.
Before I commit to a solution, let’s run the unit tests on each. The results for #1 pass with flying colors, of course. The results for both #2 and #3, though, fail. And I thought this was going to be easy. Keep reading below…
After LabVIEW 2020 released, I thought I should revisit my OAuth2 example to see how I could apply new features to improve the code. I thought it would be simple and straightforward and magically better, and fit into a single blog post. But, I think it’s going to be more of a journey than that.
I decided to start with something simple: LabVIEW 2020’s implementation of the SHA-256 secure hash that’s needed for the code verifier. This ought to be able to replace the SHA256.vi in my 2019 example, which was based on a .Net call. This is one of the only things that was Windows-specific in my code.
My first step was to create a new repo for my 2020 code. I think I want to keep my 2019 version around, so I’m hesitant to create a branch to merge back into it. I may regret it, but it felt like a new repo was the way to go.
Next, after loading the project into LabVIEW 2020, I went to SHA256.vi and selected Find -> Callers. It’s only called from two places, one of which is a unit test helper VI. (Aside: The unit test was only listed because it used a helper VI. If you think that Find -> Callers should have also reported which .lvtest files call the VI, kudo this idea.)
Good, I thought–I have unit tests and can ensure that the new VI passes all my old tests. Spoiler alert: it wasn’t that easy. Keep reading below.
I’ve been designing a test system for a customer, and it’s going to be a mix of PXI and LXI instrumentation. Most NI customers understand PXI, but aren’t very familiar with LXI, which is the standard for Ethernet-based instrumentation. Up until about five years ago, I was a member of the LXI Consortium, and closely followed all of its technical developments. For my new project, I’ve been searching the internet so I can catch up and learn about the latest with LXI. While doing so, I realize there’s not a lot out there that discusses how to get started with LXI and LabVIEW (and NI MAX and NI VISA).
Around the same time, a customer asked me to teach the National Instruments “LabVIEW Instrument Control” course, which hasn’t been updated in about ten years. It also doesn’t cover much in the way of Ethernet or USB instrumentation.
So, I felt like I should do something about this dearth of content. I thought a video or two might be the best way to explain how to get started. I asked my friends at the LXI Consortium if anyone could loan me an LXI device, and Keithley Instruments graciously sent me a very nice DMM.
With that DMM on my bench, I created a couple of short videos (attached below). Part one is a good starting point if you’ve never used LXI with LabVIEW before. Part two begins to cover some of the issues if you want to use LXI in a production environment where the system needs to be more robust and maintainable.
For those wanting to learn even more, I’m developing additional custom training to help people who are building LabVIEW-based test systems that include more modern buses like USB and Ethernet. Contact us if you are interested in this custom training.
I’d love to hear your feedback on these videos. Please comment below!
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.
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:
In part one, we created a web service that the authentication process is going to use to call us back with an authentication code. In part two, we wrote code to go through the authentication process and call an example Google web service. Here in part three, we’re going to start writing some tests, replace the JSON parser, and think about what we else we could do to improve the example.
Improvements for Testing
I’m usually not a Test-Driven Development (TDD) kind of guy. That’s where you write unit tests first, show that they fail, and then write the code that passes the tests. I’ll sometimes use TDD when I clearly know what the right answer for a function ought to be. For example, I once used TDD for figuring out a SQL query to a database—I could look at the database and deduce what I wanted the query to return, so I wrote a test for that. Then I iterated until I got a SQL query that returned the right answer, and then iterated until it was efficient.
In our OAuth2 case, I decided from the start not to use TDD. I wasn’t as confident that I knew the “right answer” to each step. But I still kept testability in mind as I went along, and I wasn’t afraid to go back and write tests (and refactor for testability) after the first pass of the app was “done”.
It’s worth talking about the structure of the C# example
that I started from. It was badly
structured for testability. Here’s a
high-level pseudo-code overview of this structure:
In part one, we created a web service that the authentication process uses to call us back with an authentication code. Here in part two, we’ll write code to actually go through the authentication process and call an example Google web service.
Calling the Authentication Server
Okay, with the callback ready, we can now call the authentication server and request a code. Fortunately, Google has conveniently set up example servers and client codes to make testing with their endpoints easy. That’s what we’ll use for this example.
We will call https://accounts.google.com/o/OAuth2/v2/auth as our authorization endpoint. It takes several parameters that are part of the OAuth2 standard which we’ll pass with the URL:
redirect_uri=<our redirect endpoint>
client_id=<client id registered in advance>
code_challenge=<code challenge that’s part of the PKCE extension hashed with SHA256>
The “redirect_uri” is what we created in part one of this blog post. The “client_id” for our example belongs to an “AppAuth Example” which Google created for testing. The “state” is a random string used to discriminate between calls. “code_challenge” and “code_challenge_method” are part of the PKCE extension.
This is part one of a three four part blog post where I describe how to use OAuth2 (and PKCE) with LabVIEW. OAuth2 is used to authenticate with web services such as Google, Twitter, Facebook, and almost every major cloud-based service today.
I own a slightly faulty beverage refrigerator. What makes it slightly faulty is that it sometimes wants to be a beverage freezer—it starts cooling, and doesn’t stop. It only does this rarely, and is otherwise a nice enough refrigerator that fits conveniently in a spot in our laundry room, so I’m hesitant to replace it. Instead, being the engineer I am, I decided to address the issue with more technology!
I purchased a Wireless
Sensor Tag and a Wemo Mini
Smart Plug to solve the problem. The
Wemo Wifi plug controls power to the refrigerator. The Wireless Tag monitors temperature and
humidity in the fridge. I use an IFTTT recipe to turn
on the power when the temperature is too high, and turn off the power when the
temperature is too low. I ask it to keep
the temperature within a four Fahrenheit degree temperature range. On average, it is on for one hour, off for
four hours, and then repeats.
It works surprisingly well. I set the Wireless Tag to send its data to the cloud every five minutes. I can view temperature and humidity graphs over the last several months and know it’s working. IFTTT is imperfect as a control system, but has worked out more reliably than expected. It’s only missed the too-high/too-low alarm twice in the few months since I’ve had this setup, and I work around this by having the alarm continue to trigger every fifteen minutes until the temperature is back in range.
All in, I’ve spent about $90 to avoid buying a new,
inexpensive refrigerator—but it was way more fun to do it this way!
I can’t help but wonder about using LabVIEW to replace IFTTT as the controller, or to use LabVIEW to analyze my months of temperature and humidity data—and that’s where this journey begins…
I don’t recall, exactly, what prompted me to pick up and read this book again in May of this year. I first read it many years ago–probably when the first edition (1987) was new. I imagine someone referenced it at this year’s NIWeek conference. It might have been Steve Watts, who has been known to suggest that software engineering is somehow related to people.
And indeed it is. This book is quite aligned with my management philosophy that software developers are people, too. Many of them darn smart, good, and interesting, worth cultivating as humans, and not just churners out of code.
Build teams to last…
I tend to favor efforts that benefit the long term view–even at the (hopefully limited) expense of the short term. The best way to build good software is to grow a team that knows how to build good software–that is, you should invest in your people.
We stopped talking about building teams, and talked instead of growing them. The agricultural image seemed right. Agriculture isn’t entirely controllable. You enrich the soil, you plant seeds, you water according to the latest theory, and you hold your breath. You just might get a crop; you might not. If it all comes up roses, you’ll feel fine, but next year you’ll be sweating it out again. That’s pretty close to how team formation works.
— Peopleware, by Tom DeMarco
Let’s obsess for a moment about the short term. “We have product to get out the door. Our customers depend on it. Our company depends on it, or we’ll go out of business.” To be clear, I in no way suggest we eschew market realities. What I don’t like is when cutting corners becomes a way of life.
Here’s everything you need to know about my software development philosophy:
“The competent programmer is fully aware of the strictly limited size of his own skull; therefore he approaches the programming task in full humility, and among other things he avoids clever tricks like the plague.”
– Edsger W. Dijkstra, The Humble Programmer, ACM Turing Lecture 1972
Six years ago, I wrote a series of articles about being a humble programmer, based on the ideas of some really smart people, like Dr. Dijkstra. The articles have gotten a lot of views and positive comments, and I think they’re still relevant reading today.
I wrote them back when I worked at National Instruments. I had a blog called labviewjournal.com. (I saved all that content. It’s now at https://stravaro.com/lvjournal, and the old hostname redirects there.) My colleague, Nancy, and I wrote several articles about our world of helping people develop better software.
We both find that helping developers be more successful is fun and rewarding. That’s why I created Stravaro.
Anyway, back to the old blog series–there’s almost nothing I would change if I were writing it today. It feels just as relevant as when I wrote it. Even though the articles were written with the LabVIEW developer in mind, I believe it’s a philosophy that should be followed regardless of programming language. When I worked at athenahealth, I gave a presentation on the same theme at an internal technical conference.
If you haven’t read the series, I invite you to do so now. Do any of you have a similar philosophy that’s worked well? Or a radically different one? Leave a reply below to share your thoughts.
“Every person that you meet knows something you don’t; learn from them.”
– H. Jackson Brown Jr.
“The greatest lesson in life is to know that even fools are right sometimes.”
The other day, I saw this tweet from Darren Nattinger, replying to a tweet by Jim Kring, of JKI…
And I realized that it’s been over ten years since we released 64-bit LabVIEW. I wrote about it in the blog I had at the time (which lives forever, like everything on the internet 🙂 ).
I led a team of two other amazing developers, Adam and Kyle. The three of us just plowed through the few million lines of C/C++ and made it 64-bit aware. No big deal. 😉 When we first started, I felt like there was a greater than 50% chance that we’d fail. Most likely, that we’d decide it wasn’t worth the effort–we’d hit some very large boulder, and decide not to go on. But we persisted, and ended up coming in ahead of schedule and below budget. We actually had to wait (a year, I think) for the device driver groups to catch up with their 64-bit support.