InqPortal – Quick Start Guide v5

This is one of our Just the facts… Mam posts. In this post, we are making the assumption you are an Arduino IDE Jedi, have already a solid working knowledge with ESP8266 development. If you are in this category, and with the comments below, you’ll probably be an InqPortal wizard in less than 30 minutes. If you think you might be close on one topic or another, the code below is well linked to the pertinent pages so you can quickly jump to more details. If you need a little more than a little help… head to the Tutorial. These both work on the same project… just at drastically different rates.

Good luck… Inq

The main take away of looking at the code below… is just how minimal it is for what it’s doing for you…

  • A web server – Think of it as a tiny Nginx, Apache or IIS on an ESP8266.
  • A management system – Think of it as a tiny CPanel or IIS Manager.
  • A files system with file manager capabilities with Drag and Drop functionality.
  • High-speed WebSocket communications between your server and client browser applications.
  • Over the Air (OTA) binary upgrading.
  • Easy and transparent data I/O – It might be called invisible. In its simplest usage, you do not have to write any code to handle the back and forth communication of published variables.
  • Instant Histograms to study data trends in your server’s performance. Include your application’s custom published data along side to easily correlate system performance to milestones in your logic.
  • Rapid integration within your server AND within your HTML pages.

Prerequisites

Before actually compiling and trying out InqPortal there are several items you must have. Considering your an old hand at this, you probably have most of it ready to go. If not, here is a step-by-step to building the required build environment.

  1. The Arduino IDE 1.8.19 or greater
  2. The InqPortal library 5.4.0 or greater (can be found in Arduino IDE Library Manager)
  3. The ESP8266 Boards library 3.1.2 or greater (can be loaded via Arduino IDE Boards Manager)

firstportal.ino

First, we’ll start out showing our server-side code without comments so you can get a feel for just how minimal the code requirements are. Don’t worry… down below you’ll find the complete flowery, annotated, commented, linked code. This example has the following features. Other features and capabilities can be found in the InqPortal Topics page.

  • This firstportal.ino server code simulates a simple web-based thermometer… although the thermometer is made up so we don’t have to wire up stuff just to demonstrate software. If you’re in this topic, you’re an olde-hand at the hardware side and you’ll get the point.
  • Publishes four variables.
    • Temperature (T) that will be read-only on the client(s)
    • The room name (Room). This is to mainly here to demonstrate some of the slight differences required to publish strings versus numbers.
    • Two pseudo factors (M) and (B) that are used for linear modified calibration purposes. These will be published and edit-able from the browser side.
  • Automatic persistence of (M), (B) and (Room) variables so they’ll come back up as they were left after a re-boot.
  • Automatic performance metrics sent to the Admin to monitor server health.
  • A little labeling and grouping logic so the published variables can be readily Grok’d next year when you come back to the Admin to see what’s going on with your crawl-space temperature gauge.
#include <InqPortal.h>

ADC_MODE(ADC_VCC);

struct FirstPersist
{
    float m;
    float b;
    char room[32];
};

FirstPersist config = { 1.0, 0.0, "Garage" };

InqPortal svr((u8*)&config, sizeof(FirstPersist));

float temperature = 0;

void setup() 
{
  svr.heading("LW", "Run-Time Variables");
  svr.publishRO("Temp", &temperature, "Temperature (°C)"); 

  svr.heading("LP", "Persisted Editable Variables");
  svr.publishRW("Room", config.room, sizeof(config.room),
    "Temperature in room");
  svr.publishRW("M", &config.m, "Slope"); 
  svr.publishRW("B", &config.b, "Offset"); 
  
  svr.onInterval(sendTemperature, 1000);

  svr.begin("FirstPortal", NULL, 
    "<your router SSID>", "<your router Password>"); 
}

void loop() 
{
}

void sendTemperature(void* tag)
{
    temperature = getTemperature();
}

float getTemperature()
{
    #define MIN_P_CYCLE 1
    #define MS_P_MIN 60000
    u32 fraction = millis() % (MS_P_MIN * MIN_P_CYCLE);
    float alpha = (float)(fraction / (float)(MS_P_MIN * MIN_P_CYCLE)) *
        2.0 * PI;
    return (float)(sin(alpha) * 100.0);
}

Now… the commented up version. There is no difference in the working code, just lots of comments and references.

// FirstPortal.ino Complete

// Include the InqPortal library
// Usage - https://inqonthat.com/inqportal-bare-essentials/
#include <InqPortal.h>

// Uses the analog pin A0 to get supply voltage.
// This is sent out with the other performace metrics.
// Usage - https://inqonthat.com/inqportal-adding-performance-metrics/#ADC_MODE
ADC_MODE(ADC_VCC);

// This is a custom C++ struct for your persisted variables.  
// For this example, we use it to adjust results of our temperature sensor
// for "calibration" purposes.  InqPortal recognizes all numeric types,
// including s8, u8, s16, u16, s32, u32, float, double and of course all the
// long winded versions if you prefer.  It also supports fixed-length 
// character buffers.  It does NOT support Arduino String objects!
// Use of persisted variables is optional.  If you don't need any persisted
// data, you can skip this part.
struct FirstPersist
{
    float m;
    float b;
    char room[32];
};

// If you need persisted data, now make an instance of your object and 
// initialize it with your default values.  If you interact with the UI and
// and change these values, they will be automatically persisted in case of
// power failure.  The persisted values will override these defaults on 
// power up.
FirstPersist config = { 1.0, 0.0, "Garage" };

// Declare an InqPortal server, with the address of your custom persist
// struct and its size.  If you don't need persisted data, the default
// constructor ( InqPortal svr; )  is sufficient.
// Usage - https://inqonthat.com/inqportal-bare-essentials/
// Reference - https://inqonthat.com/inqportal-class-reference/#InqPortal
InqPortal svr((u8*)&config, sizeof(FirstPersist));

// Define any of your published varibles before setup() so they can be 
// accessed by your Sketch code as well as InqPortal.  Being outside of
// the your custom persist struct means when the power goes out, they will
// be lost.  In this example, this is a runtime variable for temperature.  
float temperature = 0;

void setup() 
{
  // Add a heading on our Admin "App" tab.  Purely optional and cosmetic.
  // Usage - https://inqonthat.com/inqportal-pushing-data/#variable
  // Reference - https://inqonthat.com/inqportal-class-reference/#heading
  svr.heading("LW", "Run-Time Variables");
  
  // Add a published run-time variable that you want your clients to have
  // access.  RO - stands for readonly.  It is read only by your clients.
  // Of course the Sketch can change it at any time.
  // Temp - is the published variable name and how it will be referenced in
  // the clients.  It must start with a capital letter.
  // &temperature - Note:  You are giving the address to your Sketch variable. 
  // "Temperature..." - This is the friendly label used in the Admin.
  // More details and other options for defining your published variables can
  // be found:
  // Usage - https://inqonthat.com/inqportal-pushing-data/#variable
  // Reference - https://inqonthat.com/inqportal-class-reference/#variable
  svr.publishRO("Temp", &temperature, "Temperature (°C)"); 

  // Add a second heading on our Admin "App" tab.
  svr.heading("LP", "Persisted Editable Variables");

  // Define our published variables to access our persisted values.  
  // RW - stands for read/write.  This allows the client to make changes
  // to these values.  The method parameters are the same as publishRO().
  svr.publishRW("Room", config.room, sizeof(config.room), 
    "Temperature in room");
  svr.publishRW("M", &config.m, "Slope"); 
  svr.publishRW("B", &config.b, "Offset"); 

  // Set up an Interval callback.  Similar to Ticker, but integrated into
  // InqPortal.  It is NOT based on Interrupts, so you do not have to be
  // concerned about interrupt synchronization issues.
  // Usage - https://inqonthat.com/inqportal-pushing-data/#intervalCallbacks
  // Reference - https://inqonthat.com/inqportal-class-reference/#onInterval
  svr.onInterval(sendTemperature, 1000);

  // Start the InqPortal server.  
  // All the parameters for begin() are optional.  During development, or if
  // you're building an app just for yourself, you might want to define the
  // connections.  Once you distribute, or sell your project, you can remove
  // the parameters and use the Admin to configure them like IoT products do.
  // (1) SSID for the SoftAP (Built-in access point)
  // (2) Password for the SoftAP.
  // (3) SSID for the router you want it to connect.
  // (4) Password for the router you want it to connect.
  // For more information and options, see:
  // Usage - https://inqonthat.com/inqportal-bare-essentials/
  // Reference - https://inqonthat.com/inqportal-class-reference/#begin
  svr.begin("FirstPortal", NULL, 
    "<your router SSID>", "<your router Password>");
}

void loop() 
{
    // Using multiple onInterval() to define routine callbacks frees up the 
    // loop() method for tasks that need high rates ~100 kHz.  This 
    // permits a cleaner, best practice of segregating concerns.
}

void sendTemperature(void* tag)
{
    // Our callback every 1 second.  Call our routine that deals with the
    // "sensor" and set our published variable.
    temperature = getTemperature();
}

float getTemperature()
{
    // We'll use a nice smooth trigonometry function so we can the results
    // can be qualitatively evaluated.
    #define MIN_P_CYCLE 1
    #define MS_P_MIN 60000
    u32 fraction = millis() % (MS_P_MIN * MIN_P_CYCLE);
    float alpha = (float)(fraction / (float)(MS_P_MIN * MIN_P_CYCLE)) *
        2.0 * PI;
    return (float)(sin(alpha) * 100.0);
}

What did this buy us?

If you’re like me, I always dreaded starting a new project. There was so much common code that went into just getting started and seeing what was going on in the program. Then if you wanted to quickly change values, you had to add some kind of input… be it through the Arduino IDE Serial Monitor or if you were real ambitious, by actual hardware buttons and dials. Then for the real masochist among us, adding some kind of display. Oh boy!… a 20 character x 4 line LCD display was the pinnacle ten years ago. By the time I got all that rudimentary stuff in the project, I’d forgotten what the meat of the project was. Here we have your dedicated Admin App tab with all your headings and published read-only and read-write variables. They’re continuously updated based on your Sketch’s code. Changing is even easier… just enter a new value and hit the Update button and the changes occur immediately in your Sketch.

And debugging – What pain can you endure? Have you ever had a slow memory leak cause a reboot overnight. Ten thousand lines of Serial output is like reading the dictionary. And that is if you’re lucky and the important data hasn’t fallen off the Serial monitor’s buffer… or worse yet… the whole Arduino IDE goes belly-up and disappears leaving you with a blank desktop and some choice four-letter expletives.

Here we have the main Settings tab. Besides settings for configuring your WiFi connectivity, you have information about your system’s status. Everything from how many time it rebooted during the night, current memory usage to how taxed the processor is running your program.

For a qualitative sense you can view the History tab where you can combine system metrics with your app’s custom data to see where large spikes of usage, or power drain or those dreaded memory leaks are occurring. The time base can be set between seconds and days. And although we have not demonstrated the logging in this tutorial, we do have the same Serial Monitor type output. The differences being (1) you don’t have to be USB connected to your device and (2) you can selectively disable logging of certain items at run time without having to recompile.

Keep on, Keeping on…

Even for experts that can build their own web server from Arduino Core libraries, you can see the advantages that only ten lines of code can bring you. You can get to the meat of your project in minutes instead of hours or days. For those, that either can’t deal or don’t want to deal with the intricacies of WiFi, WebServers, WebSockets, HTML and JavaScript… you don’t have to. InqPortal can be your entire, go-to User Interface. However, if you prefer, the client-side programming is just as easy to get started and flesh out. Create an extensive custom, proprietary (to you) user interface. The built-in Admin uses the same API’s and highlights some of its advanced capabilities.

There is even a quick-start option in version 5 that takes your App’s published variables and builds a single page UI complete with sample HTML, JavaScript and CSS and even creates your own History Graph. From there, you can re-arrange, and style wherever your creative genius leads you. It all follows standard web development.

More… ?

Wasn’t that the quickest self-guided tour in the world? It covered all the broad strokes. Actually, this is about the 90 percent of the InqPortal libraries. The InqPortal Tutorial covers all the topics above in more detail. There are other aspects not covered like server-side validation and triggering so you can do specific chores related to changes in your published data. These and more advanced topics or performance benchmarks and design guidelines will be found in InqPortal Topics.