Previous: Adding Performance Metrics
In the previous sections we have gone through rather common tasks for any Web Server. Nothing that Nginx, Apache or IIS can’t do far better. In this section we get into the real bread and butter of InqPortal. Microcontrollers are ALL about working with the real world and InqPortal‘s main purpose is to streamline the work required for the developer getting their next project’s information out to all those humans clamoring for its data. When I first started working with Arduino boards years ago I thought it was really cool how a little device like this could be hooked up to a display (even when it required ten logic pins). It was cool!… back then. The second time I needed one, I was over the cool factor. The pain and suffering I experienced using a 20×4 character display… and don’t even get me started on trying to put graphics on it. Enter the ESP8266! I instantly saw the writing on the wall… any graphics, any text, any cosmetics and visible on any and all displays simultaneously! How can you beat that? And all for the price of a can of Coke! …and that is for the cost of the processor. The display is free… or at least already paid for doing something else like being attached to your phone.
Made-Up Scenario
For a real-world example let’s imagine we’re making a weather station and using a temperature sensor of some sort to collect the temperature. There are many ways one might expose the results. This is just one. InqPotal doesn’t enforce any strict way of implementing your core project logic. However, for this tutorial, this just happens to be one of the ways with the least work.
We start out at the top with adding a global working variable temperature. This way we have access to it at any time, even between “sensor” readings. At the bottom, we add a function that handles all the sensor specific duties, does all the pertinent calculations and returns our temperature. IF… If… we were on an Arduino based microcontroller, we might simply call our getTemperature() function from our loop() method and place the returned value in our temperature variable. Like shown here. We then would add some realistic delay()… in this case once a minute is plenty often enough for a weather station.
For ESP8266 based microcontrollers in-general and InqPortal web servers this is a very bad idea.
Warning: DON’T USE the delay() method – This method comes from its Arduino heritage. On an Arduino, there are no low-level routines that need some of the CPU’s time. Not true on the ESP8266. Starving the lower levels will cause all kinds of communications errors and can corrupt data coming in OR going out. You can use delay() sparingly (milliseconds are OK) but the common practice of delaying for a second or more is a severe problem. InqPortal has Interval Callbacks for handling this… which coincidentally makes your code more readable and compartmentalized as well as flexible.
Interval Callbacks
You might have noticed in the previous section’s images that an ESP8266 idling along with little to do, will run the loop() method almost 130,000 times/second. Certainly, you don’t want to send out data that often and using delay is a bad thing. Here we introduce the onInterval() method. Think of it accomplishing several important tasks :
- As a way to setup a more sensor friendly interval. Most sensors can’t handle being accessed 130,000 times per second.
- As a way to setup a more human scale interval. Most people can’t handle once a second, much less 130,000 times a second.
- Leaving the loop() clear and available for something that really needs such high-rate repetition.
- As a way to segregate your code. Typically, one of the hardest problems companies have maintaining code is fixing and modifying it. Another programmer picks up your code and “thinks” they understand it and slaps in some modification that breaks it. Having one onInterval() calling one method that does one thing is something far easier to understand than some convoluted loop() method having to orchestrate, calculate and moderate… twenty different things at five different rates. Instead, we have twenty different onInterval() methods set up to call twenty different routines… all nice and segregated and having their own timing intervals.
- The callback function doing one thing eventually becomes a black box that it totally trustworthy to never break. It simply gets a temperature. Easy to Grok!
Now to modifying the code the ESP8266 way. We’ll keep the working variable temperature at the top of the Sketch and the getTemperature() method that handles the sensor specifics at the bottom. However, now we add InqPortal server onInterval() method (note the red arrows below). This sets up a schedule every second (1000 milliseconds) to call the sendTemperature() method. We have moved the temperature assignment out of the Sketch’s loop() and into its own sendTemperature() method. You can have as many different onInterval() methods as you wish… For instance to gather data at different rates or to do some routine maintenance every 24 hours. Each goes to a different callback routine so you don’t get a cluttered, thousand-lines long loop() method with tons of if-else logic. For more details, see onInterval() in the Reference.
Remember: If you’re tired of typing, the fully commented version of FirstPortal is included in the Examples.
Publishing Variables – Getting the Word Out
If you are familiar with C++/C# private, protected, and public key words to describe the scope of a variable, then you conceptually understand how we use publish. All variable in the Sketch are accessible by the Sketch… well… except those inside a method, but you get the idea. Our temperature variable is, in essence, a public variable to any portion of the Sketch. Think of a published variable as one also being accessible by the browser client application. We have two basic versions of published variables.
- publishRO – This defines a variable that is visible and usable by the client. But, the client cannot modify it. The Sketch, however, can read and modify this type of variable.
- publishRW – This defines a variable that can both be read and written to by both the client and server.
In the InqPortal.h file you included at the top of your Sketch you will find nine versions of each of these methods and each one of those has four or five parameters each. We won’t be using all these parameters in this example so many of these extra parameters have default values and are for advanced purposes. And really… the only significant difference between the nine versions is the type of variable they work with so don’t panic. InqPortal allows you to work with any of the numeric variables including s8, u8, s16, u16, s32, u32, float and double. If you prefer to use the long name versions like unsigned long integer… well… knock yourself out… you can use those too. You can also use fixed length character buffers char[] making the ninth one. It has to be handled slightly differently. InqPortal does NOT work with Arduino String variables. For more details and advanced functionality of these methods consult the publishRO() method in the reference.
Now! Let’s apply this to our example program. Check out the blue arrow pointing in the code above. The first function call – heading() is merely a decorating method we’ll describe in more detail in the next topic. The first parameter is simply an ID. The second parameter is a user friendly label describing the following group of published variables.
The second function is to publish our temperature variable as a read-only variable so our client can read it. See the publishRO() method in the Reference for more details about advanced usage of this method. For now, the first two parameters are the most important. The first, parameter is the ID of the variable. This is an InqPortal (and Web Development) concept. If you are familiar with HTML markup, this will be the ID of an HTML element. Think of it as a alias for your temperature variable. The client will not know about temperature, but it will reference it by the name Temp as we see in this example. If you want, it can be the exact same name… except it must start with a capital letter.
The second parameter of the publishRO() method is the C++ address (note the & prefix) of your temperature variable. If you are not familiar with C++ pointers, they “point” to the location in memory where the variable is located. In this case our temperature variable. Because your temperature variable is of type float, the Arduino compiler knows which InqPortal.h version of publishRO() to use. So really… there are only two versions for you to deal with. Most of the time, the compiler will let you know if you mess up.
Best Practices – In the Sketch coding, the length of the name of a variable (say… float temperature_in_my_second_garage;) makes no difference to the compiled length or performance of the compiled program. HOWEVER, the length of the variable ID name does have some performance issues. Each time it is transferred from server to client or vice versa the name has to go across the WiFi connection along with the value. An ID name (T) versus (temperature_in_my_second_garage) takes that much more time and bandwidth to send and receive. Now this is of no real concern when sending the temperature out once a minute, but if you’re trying to send some data out 200 times a second, this can be quite significant and easily be the difference of working and auguring in.
The third parameter, like in the heading() method is a human friendly description that is merely for decorating that we’ll describe in more detail in the next topic.
This completes all the changes necessary to the server-side Sketch to use your first published variable. Next we’ll turn our attention to how this is used out on the client-side, browser based web applications.