Networking (WiFi & HTTP)
WiFi and HTTP each live in one class: new WiFi(...) carries the whole link policy
(credentials, security, timeout), and new Request(...) carries the whole request
(method, URL, body, TLS policy). The same calls work three ways — blocking at the top level,
fire-and-forget with callbacks, or async/await.
WiFi
The WiFi link. Construct the policy, then join(). The constructor carries the credentials; join() associates and waits — bounded by timeoutMs (default 15 s) — until the board has an IP address.
Example first
import { WiFi, UART0 } from '@typecad/hal';
const wifi = new WiFi('MyNetwork', { psk: 'correct-horse-battery-staple' });
if (wifi.join()) {
UART0.writeLine(wifi.ip()); // the IP address as a string
}Static IP and radio tuning
Both are construction facts, set at the same time as the credentials. With static ipv4 facts the link comes up without DHCP — join() returns as soon as
the address is applied. Omit psk for an open network; security defaults to WPA2
when a psk is present and OPEN otherwise — override with the WiFi.WPA3 / WiFi.WPA2_WPA3 tokens.
const lab = new WiFi('LabNet', {
psk: 'correct-horse-battery-staple',
timeoutMs: 30000, // 30 s deadline
ipv4: { addr: '10.0.0.5', gateway: '10.0.0.1', netmask: '255.255.255.0' },
powerSave: WiFi.PS_OFF, // disable modem sleep for lower latency
channel: 6, // 0 / omitted = any
});joinStart / linked joinStart(): void
Inside an async function, the join splits into a non-blocking start plus a poll,
so other tasks keep running while the station associates:
const wifi = new WiFi('MyNetwork', { psk: 'hunter22' });
async function network() {
wifi.joinStart(); // fire-and-forget associate
while (!wifi.linked()) { await Time.sleep(100); }
UART0.writeLine(wifi.ip());
}onUp / onDrop onUp(fn): void
wifi.onUp(() => UART0.writeLine('online at ' + wifi.ip()));
wifi.onDrop(() => UART0.writeLine('link lost')); // safe to call join() from here
wifi.join();scan scan(): Scan → read-only handle, fixed pool of 16
const results = wifi.scan();
for (let i = 0; i < results.count(); i++) {
UART0.writeLine(results.ssid(i) + ' ' + results.rssi(i) + ' dBm ch' + results.channel(i));
}All methods
| Member | Description |
|---|---|
| new WiFi(ssid, opts?) | Link policy: psk, security, channel, band, timeoutMs (default 15 s), powerSave, ipv4 { addr, gateway, netmask } |
| join() | Associate and wait for IP connectivity. Awaitable |
| joinStart() | Fire-and-forget associate — poll linked() |
| leave() | Disassociate |
| linked() / rssi() / ip() / mac() | Link state and info |
| onUp(fn) / onDrop(fn) | Link-up / link-down callbacks |
| scan() | One blocking scan; results via the returned handle. Awaitable |
WiFiAP
Access-point mode — bring the radio up as an AP for provisioning.
Example first
import { WiFiAP } from '@typecad/hal';
const ap = new WiFiAP('hal-setup', { psk: 'config123', channel: 6 });
ap.start();
// ...provisioning...
ap.stop();Request
The HTTP/S client. Construction carries method, URL, timeout, body, and TLS policy; header() chains request headers; send() performs the request and leaves the response in the client until the next send.
Example first
import { Request, UART0 } from '@typecad/hal';
const req = new Request('GET', 'http://192.168.2.184:8080/health');
req.header('X-Device', 'typecad-hal');
if (req.send()) {
UART0.writeLine(req.status()); // 200
UART0.writeLine(req.ok()); // true for any 2xx
UART0.writeLine(req.text()); // the body, until the next send
UART0.writeLine(req.responseHeader('Content-Type'));
}Method tokens and chaining
new Request(Request.POST, 'http://api.local/telemetry', {
body: '{"temp":21.5}',
json: true, // sets Content-Type: application/json
timeoutMs: 5000,
}).header('Authorization', 'Bearer x').send();HTTPS and certificate pinning
HTTPS is native; the CA policy is a construction fact. caCert pins a specific CA
(a PEM string — it's converted to binary form at build time, so no PEM parser ships on the
board). insecure: true encrypts but skips verification; don't ship it in
production.
const pinned = new Request(Request.GET, 'https://internal.corp/api', { caCert: CORP_CA_PEM });
const lab = new Request(Request.GET, 'https://lab-server.local', { insecure: true });send (async) await req.send()
Inside an async function, await req.send() splits into send-start
plus done-polling — a slow request never stalls the rest of the program:
async function pollCloud() {
while (true) {
const req = new Request(Request.GET, 'http://api.local/health');
await req.send();
UART0.writeLine(req.status());
await Time.sleep(5000);
}
}All methods
| Member | Description |
|---|---|
| new Request(method, url, opts?) | timeoutMs (default 10 s), body, json, insecure, caCert |
| Request.GET / POST / PUT / DELETE / HEAD / PATCH | Method tokens |
| header(name, value) | Attach a request header; chainable |
| send() | Perform the request. Awaitable |
| status() / ok() / text() | Response status, 2xx check, body (until the next send) |
| contentLength() / responseHeader(name) | Response metadata |
Build-time checks
Two checks run before you flash. Using WiFi, Request, or Mqtt on a board with no WiFi radio is a build error naming an ESP32 target. And a
program that issues HTTP requests without ever bringing a WiFi link up (join() or an
AP) is flagged with a build-time warning — every request would fail at runtime.