HTML Processing
Introduction
The NetBurner Web Server automatically processes all content in your project's html/
folder. Whether you're using HTML examples, the application wizard, or creating a project from scratch, the web server provides powerful tools for serving both static and dynamic content.
Quick Start
- Create an
html/
folder in your project (if it doesn't exist)
- Add your web content (HTML, CSS, JavaScript, images, etc.)
- Call
StartHttp()
or StartHttps()
in your application
- Build your project - content is automatically compiled and linked
The NetBurner build system automatically compiles web content into your application image, eliminating the need for external file storage (though file system delivery is also supported).
Web Server Initialization
void StartHttps(uint16_t ssl_port, uint16_t http_port)
Start the HTTPS secure web server.
void StartHttp(uint16_t port, bool RunConfigMirror)
Start the HTTP web server. Further documentation in the Initialization section Initialization - Syste...
Content Sources
Web content can be delivered from multiple sources:
Content Sources
│
v
┌──────────┬───────┴───────┬──────────┬──────────┐
│ │ │ │ │
v v v v v
Compiled Generated EFFS-STD EFFS-FAT Mixed
Into App Runtime (On-chip) (SD Card) Sources
Dynamic Content Overview
Dynamic content is generated at runtime on your NetBurner device, enabling real-time updates, interactive controls, and data visualization.
Dynamic Content Methods
User Request (Browser)
│
v
┌────────┴────────┐
│ │
│ Web Server │
│ │
└────────┬────────┘
│
v
Processing
│
┌────────┬───┴───┬────────┬─────────┬─────────┐
│ │ │ │ │ │
v v v v v v
HTML Callback Variable GET POST WebSocket
Tags Functions Tags Handler Handler Real-time
Available methods:
- HTML Tags - Embed dynamic content directly in HTML
- Function Callbacks - Execute C/C++ functions during page rendering
- Variable Tags - Insert application variable values in real-time
- JavaScript - Client-side dynamic behavior
- GET Handlers - Intercept and customize page requests
- POST Handlers - Process form submissions
- WebSockets - Two-way real-time communication
HTML Tags
HTML tags enable real-time dynamic content by embedding directives in your HTML source code. When the web server streams content to the browser, it processes these tags and takes appropriate action.
Tag Overview
Tag | Purpose | Use Case |
CPPCALL | Execute C++ function without parameters | Display computed data, trigger actions |
VARIABLE() | Execute C++ function with parameters | Parameterized callbacks, complex operations |
VARIABLE | Insert application variable value | Display sensor readings, system state |
CONFIGVALUE | Display configuration variable | Show system settings |
CONFIGINPUT | Create input field with config value | Edit system configuration |
CONFIGTABLE | Generate configuration table | Display hierarchical settings |
Tag Syntax
Tags are embedded within HTML comments to avoid interfering with standard HTML processing:
<!--CPPCALL functionName -->
<!--VARIABLE expression -->
<!--VARIABLE functionName(fd, parameters) -->
Important**: Spacing matters!
- No space between
<!--
and tag name
- Space required before
-->
Correct: <!--CPPCALL myFunction -->
Incorrect: <!-- CPPCALL myFunction-->
Incorrect: <!--CPPCALL myFunction-->
The CPPCALL Tag
The CPPCALL
tag executes a C++ function when encountered during page rendering. The function receives the socket file descriptor and URL, giving it full control over response generation.
Function Flow
Browser Request
│
v
Web Server Parsing
│
v
Encounters <!--CPPCALL funcName -->
│
v
Calls funcName(socket, url)
│
v
Function Generates Output
│
v
Output Sent to Browser
Function Signature
void YourFunctionName(int sock, PCSTR url)
{
}
Example: Display Client Information
HTML Code:**
<html>
<body>
<h1>Connection Information</h1>
Client Address: <!--CPPCALL webShowClientInfo -->
</body>
</html>
C++ Implementation:**
void webShowClientInfo(int sock, PCSTR url)
{
fdprintf(sock,
":%d<br>\r\n", remotePort);
}
Used to hold and manipulate IPv4 and IPv6 addresses in dual stack mode.
Definition ipv6_addr.h:41
void fdprint(int fd, bool bCompact=true, bool bShowV4Raw=false) const
Print the IP address to the specified file descriptor.
int fdprintf(int fd, const char *format,...)
Print formatted output to a file descriptor.
IPADDR GetSocketLocalAddr(int fd)
Get the local interface IP address for a socket connection.
Definition tcp.h:9470
uint16_t GetSocketRemotePort(int fd)
Get the remote host port number for a socket connection.
Result:**
Client Address: 192.168.1.100:54321
The VARIABLE Tag
The VARIABLE
tag has two distinct uses:
- Direct Variable Display - Insert variable or expression value
- Parameterized Function Call - Execute function with custom parameters
Use Case 1: Display Variables
HTML Tag: <!--VARIABLE expression -->
│
v
Build Process Converts To:
│
v
WriteHtmlVariable(fd, expression);
│
v
Value Written to Socket
Simple Variable Display:**
<!-- Display system uptime in ticks -->
System Ticks: <!--VARIABLE TimeTick -->
<!-- Display uptime in seconds using expression -->
Uptime: <!--VARIABLE TimeTick/TICKS_PER_SECOND --> seconds
Supported Variable Types
The following types are automatically supported (defined in htmlfiles.h
):
void WriteHtmlVariable(int fd, char c);
void WriteHtmlVariable(int fd, int i);
void WriteHtmlVariable(int fd, short i);
void WriteHtmlVariable(int fd, long i);
void WriteHtmlVariable(int fd, uint8_t b);
void WriteHtmlVariable(int fd, uint16_t w);
void WriteHtmlVariable(int fd, unsigned long dw);
void WriteHtmlVariable(int fd, const char *);
void WriteHtmlVariable(
int fd,
MACADR ma);
void WriteHtmlVariable(
int fd,
IPADDR ip);
Used to store and manipulate MAC addresses.
Definition nettypes.h:69
Use Case 2: Parameterized Function Calls
When you need to pass parameters to a function (beyond the fixed CPPCALL signature), use VARIABLE()
:
HTML: <!--VARIABLE MyFunc(fd, param1, param2) -->
│
v
Converted To: WriteHtmlVariable(fd, MyFunc(fd, param1, param2));
│
v
MyFunc Executes and Returns Result
│
v
Result Written to Browser
Header Declaration:**
const char* DisplaySensorData(int fd, int sensorId);
HTML Usage:**
Sensor 1: <!--VARIABLE DisplaySensorData(fd, 1) --><br>
Sensor 2: <!--VARIABLE DisplaySensorData(fd, 2) --><br>
Implementation:**
const char* DisplaySensorData(int fd, int sensorId)
{
int reading = ReadSensor(sensorId);
fdprintf(fd,
"Sensor %d: %d units", sensorId, reading);
return "";
}
The INCLUDE Tag and htmlvar.h
For the build system to resolve variable and function references in HTML tags, it needs access to appropriate headers.
Two Methods for Include Resolution
HTML Processing
│
v
Need Headers?
│
┌────────┴────────┐
│ │
v v
Method 1 Method 2
│ │
v v
INCLUDE Tag htmlvar.h File
(In HTML) (In Project)
Method 1: INCLUDE Tag in HTML
Place the include directive directly in your HTML file:
<html>
<body>
<!--INCLUDE myIncludeFile.h -->
Value = <!--VARIABLE MyVar --><br>
</body>
</html>
Method 2: htmlvar.h Header File
Create a file named htmlvar.h
in your project. The build system automatically searches for this file:
#ifndef HTMLVARS_H_
#define HTMLVARS_H_
#include <nbrtos.h>
extern int gIntVal;
extern char gStrVal[];
const char* DisplayWithParam(int fd, int value);
#endif
Include Resolution Flow
Build System
│
v
Search for INCLUDE tags in HTML
│
┌─────────┴─────────┐
│ │
Found Not Found
│ │
v v
Use Specified Search for htmlvar.h
Headers │
v
Use htmlvar.h if found
Extending VARIABLE Tag Support
You can extend the VARIABLE
tag to support custom types by overloading WriteHtmlVariable()
.
Custom Type Example
Define Custom Structure:**
struct SensorData {
int temperature;
int humidity;
char location[80];
uint32_t timestamp;
};
SensorData sensor1;
Add to htmlvar.h:**
void WriteHtmlVariable(int fd, SensorData data);
Use in HTML:**
Sensor Status: <!--VARIABLE sensor1 -->
Implement the Function:**
void WriteHtmlVariable(int fd, SensorData data)
{
fdprintf(fd,
" Location: %s<br>", data.location);
fdprintf(fd,
" Temperature: %dC<br>", data.temperature);
fdprintf(fd,
" Humidity: %d%%<br>", data.humidity);
fdprintf(fd,
" Timestamp: %lu", data.timestamp);
}
System Example: MAC Address Display
Here's how the system implements MAC address display:
void WriteHtmlVariable(
int fd,
MACADR ma)
{
PBYTE lpb = (PBYTE)&ma;
for (int i = 0; i < 5; i++)
{
fd_writehex(fd, lpb[i]);
}
fd_writehex(fd, lpb[5]);
}
int write(int fd, const char *buf, int nbytes)
Write data to the stream associated with a file descriptor (fd). Can be used to write data to stdio,...
Configuration System Tags
The CONFIG tags simplify displaying and modifying system configuration and application variables from the Configuration Record.
Configuration Tag Types
Tag | Function | Creates |
CONFIGVALUE | Display value | Read-only text |
CONFIGINPUT | Display + edit | HTML input field |
CONFIGTABLE | Display hierarchy | HTML table |
Configuration Tree Structure
Configuration Record
│
v
┌────────┴────────┐
│ │
v v
Sys AppData
(System) (Application)
│ │
v v
NetIf Custom Variables
Application Your Data
Settings
Example: Display Configuration Values
<!-- Display system hostname -->
Hostname: <!--CONFIGVALUE Sys/Application/HostName -->
<!-- Create editable input for application variable -->
Device Name: <!--CONFIGINPUT AppData/DeviceName -->
<!-- Display entire configuration section as table -->
<!--CONFIGTABLE Sys/NetIf -->
Configuration Access Flow
CONFIG Tag in HTML
│
v
Parse Path (e.g., "Sys/NetIf")
│
v
Locate in Configuration Tree
│
v
┌─────────┼─────────┬─────────┐
│ │ │ │
v v v v
VALUE INPUT TABLE
│ │ │
v v v
Display Create Generate
Value Field Table
HTTP GET Request Handler
GET handlers intercept browser requests before normal file serving, enabling URL encoding, custom processing, and dynamic routing.
When to Use GET Handlers
- URL-encoded parameters:
http://device/status?sensor=1
- Dynamic page generation based on request
- Stateful applications (session management via URL)
- API endpoints
- Custom routing logic
GET Handler Flow
Browser Request: GET /status.html
│
v
Web Server Receives Request
│
v
Check for GET Handler Match
│
┌────────┴────────┐
│ │
Match Found No Match
│ │
v v
Execute Normal File
Handler Processing
│
v
Custom Processing
│
v
Generate Response
│
v
Send to Browser
Creating a GET Handler
Step 1: Define Callback Function**
{
if ((Secs % 2) == 0)
else
return 1;
}
void SendHTMLHeader(int sock)
Send a HTML response header.
int32_t SendFileFragment(char const *name, int32_t fd, PCSTR url=NULL)
Send a file fragment without a header.
HTTP Request Structure.
Definition http.h:87
IPADDR client_IPaddr
IP address of client.
Definition http.h:100
Step 2: Register Handler**
"OddEven.html",
callbackGetOddEven,
0,
true
);
Implements the HtmlPageHandler class as a function pointer callback for GET requests.
Definition http.h:326
@ tGet
GET request.
Definition http.h:37
CallBackFunctionPageHandler Parameters
Constructor Parameters
│
┌────────┬───┴───┬────────┬─────────┬──────────┐
│ │ │ │ │ │
v v v v v v
pURL pFunc reqType access before
Group Files
Parameter | Description | Example |
pURL | URL mask to match (supports wildcards) | "status.html" , "api/*" |
pFunction | Pointer to callback function | myCallback |
reqType | Request type (tGet , tPost , etc.) | tGet |
accessGroup | Security group (0 = no restriction) | 0 |
beforeFiles | When to call: true = always, false = only if file not found | true |
URL Encoding Example
{
const char* id = GetRequestParameter(request, "id");
const char* type = GetRequestParameter(request, "type");
fdprintf(sock,
"Sensor ID: %s<br>",
id);
int value = ReadSensor(atoi(id));
fdprintf(sock,
"Value: %d</body></html>", value);
return 1;
}
HTTP Form POST Handler
POST handlers process form submissions, enabling user input, configuration updates, and interactive web applications.
Creating a POST Handler
HTML Form Creation
│
v
POST Handler Callback
│
v
Handler Declaration
│
v
Processing Complete
Step 1: Create HTML Form
<html>
<title>Configuration Form</title>
<body>
<h1>Device Configuration</h1>
<form action="updateconfig" method="post">
Device Name: <input type="text" name="DeviceName" value="Default"><br>
IP Address: <input type="text" name="IPAddress" value="192.168.1.100"><br>
Port: <input type="text" name="Port" value="80"><br>
Enable: <input type="checkbox" name="Enable" checked><br>
<br>
<input type="submit" value="Update Configuration">
</form>
</body>
</html>
Step 2: Create Callback Function
void configPostCallback(int sock, PostEvents event,
const char* pName, const char* pValue)
{
static char deviceName[80];
static char ipAddress[20];
static int port;
static bool enabled;
static bool error = false;
switch(event)
{
case eStartingPost:
deviceName[0] = '\0';
ipAddress[0] = '\0';
port = 0;
enabled = false;
error = false;
break;
case eVariable:
if (strcmp("DeviceName", pName) == 0)
{
strncpy(deviceName, pValue, 79);
printf("Device Name: %s\r\n", deviceName);
}
else if (strcmp("IPAddress", pName) == 0)
{
strncpy(ipAddress, pValue, 19);
printf("IP Address: %s\r\n", ipAddress);
}
else if (strcmp("Port", pName) == 0)
{
port = atoi(pValue);
printf("Port: %d\r\n", port);
}
else if (strcmp("Enable", pName) == 0)
{
enabled = (strcmp(pValue, "on") == 0);
printf("Enabled: %s\r\n", enabled ? "true" : "false");
}
else
{
printf("Unknown variable: %s\r\n", pName);
error = true;
}
break;
case eFile:
break;
case eEndOfPost:
if (error)
{
}
else
{
ApplyConfiguration(deviceName, ipAddress, port, enabled);
}
break;
}
}
void RedirectResponse(int sock, PCSTR new_page)
Redirect a HTTP request to a different page.
Step 3: Register Handler
"updateconfig*",
configPostCallback
);
Implements the HtmlPostVariableListHandler class as a function pointer callback for HTTP POST submiss...
Definition httppost.h:131
POST Event Flow
Form Submitted by Browser
│
v
eStartingPost (once)
│
v
eVariable (per form field)
│
v
┌────────┼────────┬────────┐
│ │ │ │
Field1 Field2 Field3 Field4
│ │ │ │
└────────┴────────┴────────┘
│
v
eFile (if file upload)
│
v
eEndOfPost (once)
│
v
Send Response
POST Events
Event | When Called | Purpose |
eStartingPost | Once at start | Initialize variables, clear state |
eVariable | Once per form field | Process each input value |
eFile | If file uploaded | Handle file data |
eEndOfPost | Once at end | Finalize, validate, send response |
Multiple Form Handling
You can use wildcards to handle multiple forms with one callback:
void multiFormHandler(int sock, PostEvents event,
const char* pName, const char* pValue)
{
switch(event)
{
case eStartingPost:
break;
}
}
Complete Examples
Example 1: System Status Page with Mixed Tags
<!DOCTYPE html>
<html>
<head>
<title>System Status</title>
<!--INCLUDE htmlvar.h -->
</head>
<body>
<h1>NetBurner System Status</h1>
<h2>System Information</h2>
<table border="1">
<tr>
<td>Uptime (seconds):</td>
<td><!--VARIABLE Secs --></td>
</tr>
<tr>
<td>Uptime (ticks):</td>
<td><!--VARIABLE TimeTick --></td>
</tr>
<tr>
<td>MAC Address:</td>
<td><!--VARIABLE GetMacAddress() --></td>
</tr>
<tr>
<td>Client Info:</td>
<td><!--CPPCALL webShowClientInfo --></td>
</tr>
</table>
<h2>Configuration</h2>
Hostname: <!--CONFIGVALUE Sys/Application/HostName --><br>
<h2>Sensor Readings</h2>
Temperature: <!--VARIABLE ReadTemperature(fd) -->C<br>
Pressure: <!--VARIABLE ReadPressure(fd) --> kPa<br>
</body>
</html>
Example 2: Interactive Control Panel
HTML Form:**
<html>
<head><title>Control Panel</title></head>
<body>
<h1>Device Control Panel</h1>
<form action="control" method="post">
<h2>Output Control</h2>
Output 1: <input type="checkbox" name="Out1"><br>
Output 2: <input type="checkbox" name="Out2"><br>
Output 3: <input type="checkbox" name="Out3"><br>
<h2>PWM Settings</h2>
Duty Cycle: <input type="range" name="Duty" min="0" max="100" value="50">
<span id="duty-value">50</span>%<br>
<br>
<input type="submit" value="Apply Settings">
</form>
<script>
// Update duty cycle display
document.querySelector('input[name="Duty"]').oninput = function() {
document.getElementById('duty-value').textContent = this.value;
};
</script>
</body>
</html>
POST Handler:**
void controlPostCallback(int sock, PostEvents event,
const char* pName, const char* pValue)
{
static bool out1 = false, out2 = false, out3 = false;
static int dutyCycle = 0;
switch(event)
{
case eStartingPost:
out1 = out2 = out3 = false;
dutyCycle = 0;
break;
case eVariable:
if (strcmp("Out1", pName) == 0)
out1 = (strcmp(pValue, "on") == 0);
else if (strcmp("Out2", pName) == 0)
out2 = (strcmp(pValue, "on") == 0);
else if (strcmp("Out3", pName) == 0)
out3 = (strcmp(pValue, "on") == 0);
else if (strcmp("Duty", pName) == 0)
dutyCycle = atoi(pValue);
break;
case eEndOfPost:
SetOutput(1, out1);
SetOutput(2, out2);
SetOutput(3, out3);
SetPWMDutyCycle(dutyCycle);
printf("Outputs: %d %d %d, Duty: %d%%\r\n",
out1, out2, out3, dutyCycle);
break;
}
}
Best Practices
Tag Usage Guidelines
Choose Your Approach
│
┌─────────┼─────────┬─────────┐
│ │ │ │
v v v v
Simple Parametric Display Config
Display Function Config Data
│ │ │ │
v v v v
VARIABLE VARIABLE() CPPCALL CONFIG
Tag Tag Tag Tags
Use VARIABLE when:**
- Displaying simple variable values
- Showing calculated expressions
Output is straightforward text/numbers
Use VARIABLE() when:**
- Need to pass parameters to function
- Require conditional formatting
Complex data processing needed
Use CPPCALL when:**
- Need full control over output
- Complex HTML generation
Multiple operations required
Use CONFIG tags when:**
- Working with Configuration Record
- Simplifying configuration UI
- Displaying system settings
Performance Considerations
- Minimize Function Calls: Each tag invokes processing overhead
- Buffer Output: Use efficient I/O operations
- Cache Values: Don't recalculate on every request
- Use Appropriate Tags: CONFIG tags are optimized for configuration data
Security Guidelines
- Validate Input: Always validate POST data
- Sanitize Output: Prevent injection attacks
- Use Access Groups: Restrict sensitive pages
- Implement Timeouts: Prevent resource exhaustion
Code Organization
Project Structure
│
┌─────────┼─────────┬─────────┬──────────┐
│ │ │ │ │
v v v v v
html/ src/ htmlvar.h makefile
│
v
┌─────────┼─────────┬─────────┐
│ │ │ │
v v v
main.cpp handlers.cpp utils.cpp
Recommended:**
- Keep HTML files in
html/
folder
- Centralize handlers in dedicated source files
- Use
htmlvar.h
for all HTML-exposed declarations
- Document callback functions clearly
- Group related handlers together
Troubleshooting
Common Issues and Solutions
Issue: CPPCALL function not found**
Symptom: Linker error or runtime error
Solution: Verify function signature exactly matches:
void FunctionName(int sock, PCSTR url)
Issue: VARIABLE not displaying**
Symptom: Blank output where variable should appear
Solution:
1. Check htmlvar.h includes proper headers
2. Verify variable is extern declared
3. Ensure WriteHtmlVariable() overload exists for type
Issue: POST variables not received**
Symptom: eVariable not called for form fields
Solution:
1. Verify form action matches handler URL mask
2. Check method="post" in form tag
3. Ensure input fields have name attributes
Issue: Spacing in tags**
Symptom: Tag not processed, appears as comment
Solution: Verify spacing:
Correct: <!--CPPCALL func -->
Incorrect: <!-- CPPCALL func -->
Incorrect: <!--CPPCALL func-->
Debug Checklist
Debug Flow
│
v
Verify Tag Syntax
│
v
Check Include Files
│
v
Validate Function Signatures
│
v
Test URL Matching
│
v
Review Serial Console Output
│
v
Examine Browser Developer Tools
- Enable serial console debugging with
printf()
- Check web browser developer console for errors
- Verify HTML is syntactically correct
- Test with minimal examples first
- Use
RedirectResponse()
for POST debugging
- Monitor socket operations with diagnostic output
Additional Resources
Related Documentation
- Web Server Examples:
\nburn\examples\web
- Configuration System: NetBurner Configuration Guide
- WebSockets: WebSocket Programming Guide
- Security: Authentication and Access Control
Key Header Files
#include <http.h>
#include <htmlfiles.h>
#include <nbrtos.h>
#include <netinterface.h>
Quick Reference
Tag Syntax:**
<!--CPPCALL functionName -->
<!--VARIABLE expression -->
<!--VARIABLE function(fd, params) -->
<!--CONFIGVALUE path/to/variable -->
<!--CONFIGINPUT path/to/variable -->
Function Signatures:**
void FunctionName(int sock, PCSTR url);
const char* FunctionName(int fd, int param);
void HandlerName(int sock, PostEvents event,
const char* pName, const char* pValue);
Declaration Templates:**
Summary
NetBurner's HTML processing system provides a comprehensive toolkit for building dynamic web applications on embedded devices:
Core Capabilities:**
The NetBurner HTML processing system eliminates the complexity of traditional CGI or server-side scripting while providing powerful dynamic content capabilities optimized for embedded systems.