@typecad/hal 0.1.0-alpha.2 → 1.0.0-alpha.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -7
- package/dist/ble.d.ts +160 -0
- package/dist/ble.js +157 -0
- package/dist/capacitive.d.ts +22 -0
- package/dist/capacitive.js +27 -0
- package/dist/emit.d.ts +139 -0
- package/dist/emit.js +152 -0
- package/dist/fs.d.ts +21 -1
- package/dist/fs.js +29 -21
- package/dist/http.d.ts +48 -0
- package/dist/http.js +104 -0
- package/dist/i2c.d.ts +7 -0
- package/dist/i2c.js +15 -4
- package/dist/index.d.ts +18 -1
- package/dist/index.js +17 -1
- package/dist/mdns.d.ts +31 -0
- package/dist/mdns.js +43 -0
- package/dist/mqtt.d.ts +33 -0
- package/dist/mqtt.js +48 -0
- package/dist/ota.d.ts +29 -0
- package/dist/ota.js +38 -0
- package/dist/power.d.ts +7 -0
- package/dist/power.js +10 -1
- package/dist/preferences.d.ts +11 -2
- package/dist/preferences.js +28 -27
- package/dist/register.d.ts +12 -4
- package/dist/register.js +18 -1
- package/dist/rmt.d.ts +48 -0
- package/dist/rmt.js +81 -0
- package/dist/spi.js +10 -7
- package/dist/temperature.d.ts +14 -0
- package/dist/temperature.js +17 -0
- package/dist/timer.d.ts +14 -17
- package/dist/timer.js +20 -22
- package/dist/types.d.ts +1 -1
- package/dist/wifi.d.ts +67 -0
- package/dist/wifi.js +151 -0
- package/package.json +6 -5
- package/src/ble.ts +209 -0
- package/src/capacitive.ts +31 -0
- package/src/emit.ts +180 -0
- package/src/fs.ts +30 -22
- package/src/http.ts +144 -0
- package/src/i2c.ts +16 -4
- package/src/index.ts +21 -1
- package/src/mdns.ts +50 -0
- package/src/mqtt.ts +57 -0
- package/src/ota.ts +44 -0
- package/src/power.ts +11 -1
- package/src/preferences.ts +56 -27
- package/src/register.ts +16 -4
- package/src/rmt.ts +125 -0
- package/src/spi.ts +10 -7
- package/src/temperature.ts +20 -0
- package/src/timer.ts +22 -23
- package/src/types.ts +1 -0
- package/src/wifi.ts +221 -0
package/src/emit.ts
CHANGED
|
@@ -5,6 +5,11 @@
|
|
|
5
5
|
// resolver. The framework strategy translates each operation into
|
|
6
6
|
// framework-specific C++ at code generation time.
|
|
7
7
|
//
|
|
8
|
+
// EMIT BOUNDARY: This file is a canonical entry point of the HAL lowering
|
|
9
|
+
// surface (A) — its C++ output lands in user sketches. The emitted bytes are
|
|
10
|
+
// covered by the TypeCAD Runtime Exception (see RUNTIME_EXCEPTION.md at the
|
|
11
|
+
// repository root) and are not subject to the license of this tool source.
|
|
12
|
+
//
|
|
8
13
|
// Pin parameters accept both `number` (legacy framework pin number) and
|
|
9
14
|
// `string` (MCU port name like "PB5"). The transpiler resolves port names
|
|
10
15
|
// to framework pin numbers via the MCU package's pin mapping.
|
|
@@ -30,6 +35,49 @@ export function gpioSetMode(pin: number | string, mode: string): void {}
|
|
|
30
35
|
/** Write PWM duty cycle to a pin. */
|
|
31
36
|
export function pwmWrite(pin: number | string, duty: number): void {}
|
|
32
37
|
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// RMT — Remote Control Transceiver (addressable LEDs, IR, raw digital waveforms)
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// rmtTxInit/rmtRxInit are POSITIONAL semantic primitives — the ergonomic
|
|
42
|
+
// opts-object form lives in hal/rmt.ts (which destructures and forwards). The
|
|
43
|
+
// resolver collapses object literals, so HALOpIR fields must be scalars; the
|
|
44
|
+
// rmt.ts wrapper bridges the ergonomic API to these positional calls.
|
|
45
|
+
//
|
|
46
|
+
// Pin params accept Pin | number | string so callers can pass a board alias
|
|
47
|
+
// like LED (a Pin object) directly; the transpiler resolves it to its number.
|
|
48
|
+
import type { Pin } from './gpio.js';
|
|
49
|
+
type RmtPin = Pin | number | string;
|
|
50
|
+
|
|
51
|
+
/** Positional semantic primitive. Args: pin, resolutionHz, bit0Hi, bit0Lo,
|
|
52
|
+
* bit1Hi, bit1Lo, msbFirst, queueDepth. Use rmtTxInit() from hal/rmt.ts. */
|
|
53
|
+
export function rmtTxInit(
|
|
54
|
+
pin: RmtPin,
|
|
55
|
+
resolutionHz: number,
|
|
56
|
+
bit0Hi: number, bit0Lo: number, bit1Hi: number, bit1Lo: number,
|
|
57
|
+
msbFirst: boolean, queueDepth: number,
|
|
58
|
+
): void {}
|
|
59
|
+
/** Write bytes via the channel's bytes-encoder (timings fixed at init). */
|
|
60
|
+
export function rmtTxWriteBytes(pin: RmtPin, bytes: number[] | Uint8Array): void {}
|
|
61
|
+
/** Write raw RMT symbols — arbitrary [hiTicks, loTicks] pairs. */
|
|
62
|
+
export function rmtTxWriteSymbols(pin: RmtPin, symbols: [number, number][]): void {}
|
|
63
|
+
/** Block until the queued TX completes. */
|
|
64
|
+
export function rmtTxWaitDone(pin: RmtPin, timeoutMs?: number): void {}
|
|
65
|
+
/** Tear down the TX channel and release its slot. */
|
|
66
|
+
export function rmtTxDeinit(pin: RmtPin): void {}
|
|
67
|
+
|
|
68
|
+
/** Positional semantic primitive — use rmtRxInit() from hal/rmt.ts. */
|
|
69
|
+
export function rmtRxInit(pin: RmtPin, resolutionHz: number): void {}
|
|
70
|
+
/** Register a callback-by-name invoked when an RX burst completes. */
|
|
71
|
+
export function rmtRxOnReceived(pin: RmtPin, handler: string): void {}
|
|
72
|
+
/** Start receiving. */
|
|
73
|
+
export function rmtRxStart(pin: RmtPin): void {}
|
|
74
|
+
/** Stop receiving. */
|
|
75
|
+
export function rmtRxStop(pin: RmtPin): void {}
|
|
76
|
+
/** Blocking read — returns flattened symbols [d0,l0,d1,l1,…] in ticks. */
|
|
77
|
+
export function rmtRxRead(pin: RmtPin, maxCount: number): number[] { return []; }
|
|
78
|
+
/** Tear down the RX channel and release its slot. */
|
|
79
|
+
export function rmtRxDeinit(pin: RmtPin): void {}
|
|
80
|
+
|
|
33
81
|
// ---------------------------------------------------------------------------
|
|
34
82
|
// ADC — analog-to-digital conversion
|
|
35
83
|
// ---------------------------------------------------------------------------
|
|
@@ -99,6 +147,15 @@ export function i2cRequestFrom(bus: string, address: number, quantity: number, s
|
|
|
99
147
|
export function i2cAvailable(bus: string): number { return 0; }
|
|
100
148
|
/** Read a byte from I2C. */
|
|
101
149
|
export function i2cRead(bus: string): number { return 0; }
|
|
150
|
+
/**
|
|
151
|
+
* Drain `count` bytes requested from the I2C bus into a caller-provided buffer.
|
|
152
|
+
* Semantic primitive: lowers to the `i2c.read_buffer` HAL op. The `buffer`
|
|
153
|
+
* argument is emitted as a placeholder (`__HAL_READ_BUF__`) that the var-init
|
|
154
|
+
* transformer rewrites to the caller's own buffer variable, so bytes land in
|
|
155
|
+
* the `uint8_t data[N]` declared in user scope — NOT an internal temp that
|
|
156
|
+
* decays to a pointer on return. Keeps `data.length` / `data[i]` valid.
|
|
157
|
+
*/
|
|
158
|
+
export function i2cReadBuffer(bus: string, count: number, buffer: number[] | Uint8Array): void {}
|
|
102
159
|
|
|
103
160
|
// ---------------------------------------------------------------------------
|
|
104
161
|
// SPI — serial peripheral interface
|
|
@@ -118,6 +175,14 @@ export function spiEndTx(bus: string): void {}
|
|
|
118
175
|
export function spiCsLow(pin: number | string): void {}
|
|
119
176
|
/** Set SPI chip-select pin HIGH. */
|
|
120
177
|
export function spiCsHigh(pin: number | string): void {}
|
|
178
|
+
/**
|
|
179
|
+
* Read `count` bytes from the SPI bus into a caller-provided buffer by clocking
|
|
180
|
+
* dummy (0x00) transfers. Semantic primitive: lowers to the `spi.read_buffer`
|
|
181
|
+
* HAL op (per-byte `bus.transfer(0)` read loop). The `buffer` placeholder is
|
|
182
|
+
* rewritten to the caller's variable. Mirrors i2cReadBuffer. The caller is
|
|
183
|
+
* responsible for asserting/de-asserting chip-select around it.
|
|
184
|
+
*/
|
|
185
|
+
export function spiReadBuffer(bus: string, count: number, buffer: number[] | Uint8Array): void {}
|
|
121
186
|
/** Set SPI data mode. */
|
|
122
187
|
export function spiSetMode(bus: string, mode: number): void {}
|
|
123
188
|
/** Set SPI bit order. */
|
|
@@ -201,6 +266,104 @@ export function powerDeepSleep(ms: number): void {}
|
|
|
201
266
|
export function powerLightSleep(): void {}
|
|
202
267
|
/** Set the CPU frequency (MHz). */
|
|
203
268
|
export function powerSetCpuFrequency(mhz: number): void {}
|
|
269
|
+
/** Enter deep sleep until `pin` reaches `level` (pin wakeup). Architecture-aware:
|
|
270
|
+
* ext0 on Xtensa (RTC pins), gpio-wakeup on RISC-V. */
|
|
271
|
+
export function powerDeepSleepPin(pin: number, level: number): void {}
|
|
272
|
+
|
|
273
|
+
// ---------------------------------------------------------------------------
|
|
274
|
+
// Preferences (NVS-backed key/value store)
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
|
|
277
|
+
export function preferencesBegin(namespace: string, readOnly: boolean): void {}
|
|
278
|
+
export function preferencesEnd(): void {}
|
|
279
|
+
export function preferencesClear(): void {}
|
|
280
|
+
export function preferencesRemove(key: string): void {}
|
|
281
|
+
export function preferencesPutInt(key: string, value: number): void {}
|
|
282
|
+
export function preferencesGetInt(key: string, defaultValue: number): number { return 0; }
|
|
283
|
+
export function preferencesPutUInt(key: string, value: number): void {}
|
|
284
|
+
export function preferencesGetUInt(key: string, defaultValue: number): number { return 0; }
|
|
285
|
+
export function preferencesPutBool(key: string, value: boolean): void {}
|
|
286
|
+
export function preferencesGetBool(key: string, defaultValue: boolean): boolean { return false; }
|
|
287
|
+
export function preferencesPutFloat(key: string, value: number): void {}
|
|
288
|
+
export function preferencesGetFloat(key: string, defaultValue: number): number { return 0; }
|
|
289
|
+
export function preferencesPutString(key: string, value: string): void {}
|
|
290
|
+
export function preferencesGetString(key: string, defaultValue: string): string { return ""; }
|
|
291
|
+
|
|
292
|
+
export function wifiConnect(ssid: string, password?: string, timeoutMs?: number): boolean { return false; }
|
|
293
|
+
export function wifiConnectStart(ssid: string, password?: string): void {}
|
|
294
|
+
export function wifiDisconnect(): void {}
|
|
295
|
+
export function wifiStatus(): number { return 0; }
|
|
296
|
+
export function wifiIsConnected(): boolean { return false; }
|
|
297
|
+
export function wifiLocalIp(): string { return ""; }
|
|
298
|
+
export function wifiRssi(): number { return 0; }
|
|
299
|
+
export function wifiMac(): string { return ""; }
|
|
300
|
+
export function wifiSetHostname(name: string): void {}
|
|
301
|
+
export function wifiSetStaticIp(ip: string, gateway: string, subnet: string, dns?: string): void {}
|
|
302
|
+
export function wifiSetAutoReconnect(enabled: boolean): void {}
|
|
303
|
+
export function wifiSetPowerSave(mode: string): void {}
|
|
304
|
+
export function wifiSetTxPower(dbm: number): void {}
|
|
305
|
+
export function wifiOnEvent(event: string, handler: string): void {}
|
|
306
|
+
export function wifiApStart(ssid: string, password?: string, channel?: number, hidden?: boolean, maxClients?: number): boolean { return false; }
|
|
307
|
+
export function wifiApStop(): void {}
|
|
308
|
+
export function wifiApClientCount(): number { return 0; }
|
|
309
|
+
export function wifiApIp(): string { return ""; }
|
|
310
|
+
export function wifiApSetChannel(channel: number): void {}
|
|
311
|
+
export function wifiApSetHidden(hidden: boolean): void {}
|
|
312
|
+
export function wifiApSetMaxClients(maxClients: number): void {}
|
|
313
|
+
export function wifiScan(): number { return 0; }
|
|
314
|
+
export function wifiScanStart(): void {}
|
|
315
|
+
export function wifiScanCount(): number { return 0; }
|
|
316
|
+
export function wifiScanSsid(index: number): string { return ""; }
|
|
317
|
+
export function wifiScanRssi(index: number): number { return 0; }
|
|
318
|
+
export function wifiScanEncryption(index: number): number { return 0; }
|
|
319
|
+
export function wifiScanChannel(index: number): number { return 0; }
|
|
320
|
+
export function wifiSaveCredentials(ssid: string, password: string): void {}
|
|
321
|
+
export function wifiConnectSaved(timeoutMs?: number): boolean { return false; }
|
|
322
|
+
export function wifiClearCredentials(): void {}
|
|
323
|
+
export function wifiWaitConnected(timeoutMs?: number): boolean { return false; }
|
|
324
|
+
export function wifiWaitDisconnected(): void {}
|
|
325
|
+
|
|
326
|
+
// ---------------------------------------------------------------------------
|
|
327
|
+
// HTTP client
|
|
328
|
+
// ---------------------------------------------------------------------------
|
|
329
|
+
|
|
330
|
+
export function httpBegin(method: string, url: string): void {}
|
|
331
|
+
export function httpReset(): void {}
|
|
332
|
+
export function httpSetHeader(name: string, value: string): void {}
|
|
333
|
+
export function httpSetTimeout(ms: number): void {}
|
|
334
|
+
export function httpSetMaxBody(bytes: number): void {}
|
|
335
|
+
export function httpSetBody(data: string, json?: boolean): void {}
|
|
336
|
+
export function httpSetInsecure(): void {}
|
|
337
|
+
export function httpSetCaCert(pem: string): void {}
|
|
338
|
+
export function httpSend(): boolean { return false; }
|
|
339
|
+
export function httpSendStart(): void {}
|
|
340
|
+
export function httpStatus(): number { return 0; }
|
|
341
|
+
export function httpOk(): boolean { return false; }
|
|
342
|
+
export function httpBody(): string { return ""; }
|
|
343
|
+
export function httpContentLength(): number { return 0; }
|
|
344
|
+
export function httpResponseHeader(name: string): string { return ""; }
|
|
345
|
+
|
|
346
|
+
// ---------------------------------------------------------------------------
|
|
347
|
+
// BLE (NimBLE GATT peripheral)
|
|
348
|
+
// ---------------------------------------------------------------------------
|
|
349
|
+
|
|
350
|
+
export function bleServerBegin(name: string): void {}
|
|
351
|
+
export function bleAdvertiseStart(): void {}
|
|
352
|
+
export function bleAdvertiseStop(): void {}
|
|
353
|
+
export function bleAddService(uuid: string): void {}
|
|
354
|
+
export function bleAddChar(index: number, uuid: string, type: string, perms: number, svcIndex: number): void {}
|
|
355
|
+
export function bleOnRead(index: number, handler: string): void {}
|
|
356
|
+
export function bleOnWrite(index: number, handler: string): void {}
|
|
357
|
+
export function bleOnConnect(handler: string): void {}
|
|
358
|
+
export function bleOnDisconnect(handler: string): void {}
|
|
359
|
+
export function bleNotify(index: number, value: number | string): void {}
|
|
360
|
+
export function bleIsConnected(): boolean { return false; }
|
|
361
|
+
export function bleClientCount(): number { return 0; }
|
|
362
|
+
export function bleSetName(name: string): void {}
|
|
363
|
+
export function bleUntilConnected(timeoutMs?: number): boolean { return false; }
|
|
364
|
+
export function bleUntilConnectedStart(): void {}
|
|
365
|
+
export function bleSetTxPower(dbm: number): void {}
|
|
366
|
+
export function bleStatus(): number { return 0; }
|
|
204
367
|
|
|
205
368
|
// ---------------------------------------------------------------------------
|
|
206
369
|
// Raw C++ escape hatch
|
|
@@ -208,3 +371,20 @@ export function powerSetCpuFrequency(mhz: number): void {}
|
|
|
208
371
|
|
|
209
372
|
/** Emit raw C++ code (escape hatch for unsupported operations). */
|
|
210
373
|
export function rawCpp(code: string): void {}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Emit raw C++ in expression context. Use when an IDF macro or constructor
|
|
377
|
+
* must produce a value (e.g. `WIFI_INIT_CONFIG_DEFAULT()` expands to a struct
|
|
378
|
+
* initializer; there's no TS-side way to construct it). The type parameter
|
|
379
|
+
* is purely a TS hint — the transpiler doesn't check it; it just emits the
|
|
380
|
+
* raw text in expression position.
|
|
381
|
+
*
|
|
382
|
+
* const cfg = rawCpp<wifi_init_config_t>('WIFI_INIT_CONFIG_DEFAULT()');
|
|
383
|
+
*
|
|
384
|
+
* lowers to:
|
|
385
|
+
*
|
|
386
|
+
* wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
387
|
+
*/
|
|
388
|
+
export function rawCppExpr<T>(code: string): T {
|
|
389
|
+
return undefined as unknown as T;
|
|
390
|
+
}
|
package/src/fs.ts
CHANGED
|
@@ -1,46 +1,54 @@
|
|
|
1
|
-
import { rawCpp } from './emit.js';
|
|
2
|
-
import { include } from './include.js';
|
|
3
|
-
|
|
4
1
|
/**
|
|
5
2
|
* FSClass provides a high-level abstraction for filesystem operations.
|
|
6
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* Lowered to native filesystem HAL ops (fs.*): ESP-IDF mounts an SD card via
|
|
5
|
+
* esp_vfs_fat_sdmmc_mount (FAT on SDMMC/SDSPI); Arduino uses SD.h / LittleFS.
|
|
6
|
+
* The per-framework runtime shim owns the open/read/write/close dance and
|
|
7
|
+
* returns heap strings for readText.
|
|
8
|
+
*
|
|
9
|
+
* The semantic primitives (fsBegin / fsReadText / ...) are resolved to fs.*
|
|
10
|
+
* HAL ops by the transpiler's hal-plugins switch; this class is the
|
|
11
|
+
* ergonomic, type-checking surface.
|
|
7
12
|
*/
|
|
8
13
|
export class FSClass {
|
|
9
14
|
static readonly __instance_name = "FS";
|
|
10
15
|
|
|
16
|
+
/** Mount the filesystem. Returns true on success. */
|
|
11
17
|
begin(): boolean {
|
|
12
|
-
|
|
13
|
-
rawCpp(`return FS.begin();`);
|
|
18
|
+
fsBegin();
|
|
14
19
|
return true;
|
|
15
20
|
}
|
|
16
21
|
|
|
22
|
+
/** Read a UTF-8 text file into a string. Returns "" if the file is missing
|
|
23
|
+
* or unreadable. The returned buffer is caller-owned. */
|
|
17
24
|
readText(path: string): string {
|
|
18
|
-
|
|
19
|
-
rawCpp(`File f = FS.open(${path}.c_str(), "r");`);
|
|
20
|
-
rawCpp(`if (!f) return "";`);
|
|
21
|
-
rawCpp(`String s = f.readString();`);
|
|
22
|
-
rawCpp(`f.close();`);
|
|
23
|
-
rawCpp(`return s.c_str();`);
|
|
24
|
-
return "";
|
|
25
|
+
return fsReadText(path);
|
|
25
26
|
}
|
|
26
27
|
|
|
28
|
+
/** Write a string to a file (overwrites). Silently no-ops if the file
|
|
29
|
+
* cannot be opened for writing. */
|
|
27
30
|
writeText(path: string, content: string): void {
|
|
28
|
-
|
|
29
|
-
rawCpp(`File f = FS.open(${path}.c_str(), "w");`);
|
|
30
|
-
rawCpp(`if (f) { f.print(${content}.c_str()); f.close(); }`);
|
|
31
|
+
fsWriteText(path, content);
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
/** True if a file exists at the path. */
|
|
33
35
|
exists(path: string): boolean {
|
|
34
|
-
|
|
35
|
-
rawCpp(`return FS.exists(${path}.c_str());`);
|
|
36
|
-
return false;
|
|
36
|
+
return fsExists(path);
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
/** Delete a file. Returns true if deleted. */
|
|
39
40
|
remove(path: string): boolean {
|
|
40
|
-
|
|
41
|
-
rawCpp(`return FS.remove(${path}.c_str());`);
|
|
42
|
-
return false;
|
|
41
|
+
return fsRemove(path);
|
|
43
42
|
}
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
export const FS = new FSClass();
|
|
46
|
+
|
|
47
|
+
// ── Semantic primitives (resolved to fs.* HAL ops by the transpiler) ──
|
|
48
|
+
// These are inert at runtime (tests, type-checking); the cuttlefish transpiler
|
|
49
|
+
// intercepts calls by name and lowers them to typed HAL op IR.
|
|
50
|
+
export function fsBegin(): void {}
|
|
51
|
+
export function fsReadText(path: string): string { return ""; }
|
|
52
|
+
export function fsWriteText(path: string, content: string): void {}
|
|
53
|
+
export function fsExists(path: string): boolean { return false; }
|
|
54
|
+
export function fsRemove(path: string): boolean { return false; }
|
package/src/http.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import {
|
|
2
|
+
httpBegin,
|
|
3
|
+
httpReset,
|
|
4
|
+
httpSetHeader,
|
|
5
|
+
httpSetTimeout,
|
|
6
|
+
httpSetMaxBody,
|
|
7
|
+
httpSetBody,
|
|
8
|
+
httpSetInsecure,
|
|
9
|
+
httpSetCaCert,
|
|
10
|
+
httpSend,
|
|
11
|
+
httpStatus,
|
|
12
|
+
httpOk,
|
|
13
|
+
httpBody,
|
|
14
|
+
httpContentLength,
|
|
15
|
+
httpResponseHeader,
|
|
16
|
+
} from './emit.js';
|
|
17
|
+
|
|
18
|
+
export enum HttpMethod {
|
|
19
|
+
GET = 0,
|
|
20
|
+
POST = 1,
|
|
21
|
+
PUT = 2,
|
|
22
|
+
DELETE = 3,
|
|
23
|
+
HEAD = 4,
|
|
24
|
+
PATCH = 5,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Fluent HTTP/S request builder, lowered to native ESP-IDF
|
|
29
|
+
* `esp_http_client` by framework-esp32 (TLS via esp-tls / mbedTLS bundle).
|
|
30
|
+
* Response fields are read from this object after send() — mirrors
|
|
31
|
+
* `await WiFi.connect(); WiFi.localIP()`.
|
|
32
|
+
*
|
|
33
|
+
* No `include()` calls here — ESP-IDF headers are framework-owned and added
|
|
34
|
+
* via forcedIncludes when the program uses http.* ops.
|
|
35
|
+
*/
|
|
36
|
+
export class HttpRequest {
|
|
37
|
+
private _method: string;
|
|
38
|
+
private _url: string;
|
|
39
|
+
|
|
40
|
+
constructor(method: string, url: string) {
|
|
41
|
+
this._method = method;
|
|
42
|
+
this._url = url;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
header(name: string, value: string): this {
|
|
46
|
+
httpSetHeader(name, value);
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
timeout(ms: number): this {
|
|
51
|
+
httpSetTimeout(ms);
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
maxBody(bytes: number): this {
|
|
56
|
+
httpSetMaxBody(bytes);
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
body(data: string): this {
|
|
61
|
+
httpSetBody(data, false);
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
jsonBody(json: string): this {
|
|
66
|
+
httpSetBody(json, true);
|
|
67
|
+
return this;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Skip TLS certificate verification (development only). */
|
|
71
|
+
insecure(): this {
|
|
72
|
+
httpSetInsecure();
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
caCert(pem: string): this {
|
|
77
|
+
httpSetCaCert(pem);
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Blocking at top level; cooperatively awaitable inside async functions. */
|
|
82
|
+
send(): Promise<boolean> {
|
|
83
|
+
httpBegin(this._method, this._url);
|
|
84
|
+
httpSend();
|
|
85
|
+
return Promise.resolve(false);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
status(): number {
|
|
89
|
+
return httpStatus();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
ok(): boolean {
|
|
93
|
+
return httpOk();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** Response body as a C string (valid until the next request). */
|
|
97
|
+
text(): string {
|
|
98
|
+
return httpBody();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
contentLength(): number {
|
|
102
|
+
return httpContentLength();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
responseHeader(name: string): string {
|
|
106
|
+
return httpResponseHeader(name);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export class HttpClass {
|
|
111
|
+
static readonly __instance_name = "Http";
|
|
112
|
+
|
|
113
|
+
get(url: string): HttpRequest {
|
|
114
|
+
httpReset();
|
|
115
|
+
return new HttpRequest("GET", url);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
post(url: string): HttpRequest {
|
|
119
|
+
httpReset();
|
|
120
|
+
return new HttpRequest("POST", url);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
put(url: string): HttpRequest {
|
|
124
|
+
httpReset();
|
|
125
|
+
return new HttpRequest("PUT", url);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
del(url: string): HttpRequest {
|
|
129
|
+
httpReset();
|
|
130
|
+
return new HttpRequest("DELETE", url);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
head(url: string): HttpRequest {
|
|
134
|
+
httpReset();
|
|
135
|
+
return new HttpRequest("HEAD", url);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
patch(url: string): HttpRequest {
|
|
139
|
+
httpReset();
|
|
140
|
+
return new HttpRequest("PATCH", url);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const Http = new HttpClass();
|
package/src/i2c.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i2cBegin, i2cEnd, i2cSetClock, i2cBeginTx, i2cWrite, i2cWriteBuffer, i2cEndTx, i2cRequestFrom, i2cAvailable, i2cRead, rawCpp } from './emit.js';
|
|
1
|
+
import { i2cBegin, i2cEnd, i2cSetClock, i2cBeginTx, i2cWrite, i2cWriteBuffer, i2cEndTx, i2cRequestFrom, i2cAvailable, i2cRead, i2cReadBuffer, rawCpp } from './emit.js';
|
|
2
2
|
import { include } from './include.js';
|
|
3
3
|
|
|
4
4
|
export class I2CDevice {
|
|
@@ -10,6 +10,16 @@ export class I2CDevice {
|
|
|
10
10
|
this._address = address;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/** The 7-bit I2C address this accessor targets. Exposed so I2CDevice
|
|
14
|
+
* structurally satisfies the @typecad/simulator II2CDeviceAccessor contract
|
|
15
|
+
* (which declares `readonly address`), letting the same driver function be
|
|
16
|
+
* typed against the contract and accept either a real board device or a
|
|
17
|
+
* simulated one. The transpiler strips HAL class bodies to IR, so this
|
|
18
|
+
* getter carries no runtime cost in the generated C++. */
|
|
19
|
+
get address(): number {
|
|
20
|
+
return this._address;
|
|
21
|
+
}
|
|
22
|
+
|
|
13
23
|
writeByte(register: number, value: number): void {
|
|
14
24
|
include("<Wire.h>");
|
|
15
25
|
i2cBeginTx(this._bus, this._address);
|
|
@@ -41,9 +51,11 @@ export class I2CDevice {
|
|
|
41
51
|
i2cWrite(this._bus, register);
|
|
42
52
|
i2cEndTx(this._bus, false);
|
|
43
53
|
i2cRequestFrom(this._bus, this._address, count, true);
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
rawCpp
|
|
54
|
+
// Drain the requested bytes into the caller's buffer (declared by the
|
|
55
|
+
// Uint8Array return marker as `uint8_t data[count]`). Using the semantic
|
|
56
|
+
// primitive — NOT rawCpp — keeps the buffer in user scope so it survives
|
|
57
|
+
// the return (no decayed pointer) and `data.length` / `data[i]` work.
|
|
58
|
+
i2cReadBuffer(this._bus, count, new Uint8Array(count));
|
|
47
59
|
return new Uint8Array(count);
|
|
48
60
|
}
|
|
49
61
|
}
|
package/src/index.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type { SPIBitOrder, SPIMode, SPISettings } from './types.js';
|
|
|
19
19
|
export { include } from './include.js';
|
|
20
20
|
export { board } from './board.js';
|
|
21
21
|
export { callback } from './callback.js';
|
|
22
|
-
export { rawCpp, boardResolve } from './emit.js';
|
|
22
|
+
export { rawCpp, rawCppExpr, boardResolve } from './emit.js';
|
|
23
23
|
export { HIGH, LOW, OUTPUT, INPUT, INPUT_PULLUP, INPUT_PULLDOWN, OUTPUT_OPEN_DRAIN, ANALOG, LED_BUILTIN, LSBFIRST, MSBFIRST, WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S } from './constants.js';
|
|
24
24
|
export { delay, millis, micros, delayMicroseconds, map, constrain, TimingClass, Timing } from './timing.js';
|
|
25
25
|
export { freeHeap, setInterval, setTimeout, clearInterval, clearTimeout } from './timing.js';
|
|
@@ -44,5 +44,25 @@ export { DACClass, DAC } from './dac.js';
|
|
|
44
44
|
export { PreferencesClass, Preferences } from './preferences.js';
|
|
45
45
|
export { HardwareTimer, Timer0, Timer1, Timer2 } from './timer.js';
|
|
46
46
|
export { FSClass, FS } from './fs.js';
|
|
47
|
+
export { fsBegin, fsReadText, fsWriteText, fsExists, fsRemove } from './fs.js';
|
|
48
|
+
export { MdnsClass, MDNS } from './mdns.js';
|
|
49
|
+
export { mdnsStart, mdnsSetHostname, mdnsAddService, mdnsAnnounce, mdnsStop } from './mdns.js';
|
|
50
|
+
export { MqttClass, MQTT } from './mqtt.js';
|
|
51
|
+
export { mqttConnect, mqttOnMessage, mqttSubscribe, mqttPublish, mqttConnected, mqttDisconnect } from './mqtt.js';
|
|
52
|
+
export { OtaClass, OTA } from './ota.js';
|
|
53
|
+
export { otaFromUrl, otaBegin, otaWrite, otaApply } from './ota.js';
|
|
54
|
+
export { TemperatureClass, Temperature } from './temperature.js';
|
|
55
|
+
export { tempRead } from './temperature.js';
|
|
56
|
+
export { hwtimerSetFrequency, hwtimerOnOverflow, hwtimerStart, hwtimerStop } from './timer.js';
|
|
57
|
+
export { CapacitiveClass, Capacitive } from './capacitive.js';
|
|
58
|
+
export { capacitiveRead } from './capacitive.js';
|
|
47
59
|
export { PowerClass, Power } from './power.js';
|
|
48
60
|
export { AsyncClass, Async } from './async.js';
|
|
61
|
+
export { WiFiClass, WiFi, WiFiStatus, WiFiEncryption } from './wifi.js';
|
|
62
|
+
export { HttpClass, Http, HttpRequest, HttpMethod } from './http.js';
|
|
63
|
+
export {
|
|
64
|
+
BleClass, Ble, BleServer,
|
|
65
|
+
BleValueType, BlePerm, BleStatus, BleAdvertisingMode, GATT,
|
|
66
|
+
} from './ble.js';
|
|
67
|
+
export type { GattCharacteristicDef, CharValue } from './ble.js';
|
|
68
|
+
export { RmtChannel } from './rmt.js';
|
package/src/mdns.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MdnsClass — mDNS service discovery (ESP-IDF esp_mdns).
|
|
3
|
+
*
|
|
4
|
+
* Lowered to native mDNS HAL ops (mdns.*): ESP-IDF's esp_mdns component
|
|
5
|
+
* advertises the device on the local network as `<hostname>.local` and
|
|
6
|
+
* publishes services (e.g. `_http._tcp`) for discovery by Bonjour/Avahi.
|
|
7
|
+
*
|
|
8
|
+
* The semantic primitives (mdnsStart / mdnsAddService / ...) are resolved to
|
|
9
|
+
* mdns.* HAL ops by the transpiler; this class is the ergonomic surface.
|
|
10
|
+
*
|
|
11
|
+
* Requires WiFi to be connected (mDNS rides on the station interface).
|
|
12
|
+
*/
|
|
13
|
+
export class MdnsClass {
|
|
14
|
+
static readonly __instance_name = "MDNS";
|
|
15
|
+
|
|
16
|
+
/** Initialize mDNS and set the host name (advertised as <name>.local). */
|
|
17
|
+
start(hostname: string): boolean {
|
|
18
|
+
mdnsStart(hostname);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Set/override the host name after start(). */
|
|
23
|
+
setHostname(name: string): void {
|
|
24
|
+
mdnsSetHostname(name);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Publish a service instance. proto is "_tcp" or "_udp". */
|
|
28
|
+
addService(instance: string, proto: string, port: number): void {
|
|
29
|
+
mdnsAddService(instance, proto, port);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Advertise that the device is reachable (sends a probe/announce). */
|
|
33
|
+
announce(): void {
|
|
34
|
+
mdnsAnnounce();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Tear down the mDNS responder. */
|
|
38
|
+
stop(): void {
|
|
39
|
+
mdnsStop();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const MDNS = new MdnsClass();
|
|
44
|
+
|
|
45
|
+
// ── Semantic primitives (resolved to mdns.* HAL ops by the transpiler) ──
|
|
46
|
+
export function mdnsStart(hostname: string): void {}
|
|
47
|
+
export function mdnsSetHostname(name: string): void {}
|
|
48
|
+
export function mdnsAddService(instance: string, proto: string, port: number): void {}
|
|
49
|
+
export function mdnsAnnounce(): void {}
|
|
50
|
+
export function mdnsStop(): void {}
|
package/src/mqtt.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { callback } from './callback.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MqttClass — MQTT 3.1.1 pub/sub client (ESP-IDF esp_mqtt).
|
|
5
|
+
*
|
|
6
|
+
* Lowered to native MQTT HAL ops (mqtt.*): ESP-IDF's esp_mqtt_client_* API.
|
|
7
|
+
* Covers the common IoT pub/sub path: connect to a broker, publish, subscribe
|
|
8
|
+
* with an onMessage callback, and disconnect. The runtime shim owns the event
|
|
9
|
+
* loop translation (ESP-IDF's MQTT event handler → the user's TS callback).
|
|
10
|
+
*
|
|
11
|
+
* Requires a network connection (WiFi) before connect().
|
|
12
|
+
*/
|
|
13
|
+
export class MqttClass {
|
|
14
|
+
static readonly __instance_name = "MQTT";
|
|
15
|
+
|
|
16
|
+
/** Connect to a broker URI (e.g. "mqtt://broker.local" or "mqtts://..."). */
|
|
17
|
+
connect(brokerUri: string, clientId: string): boolean {
|
|
18
|
+
mqttConnect(brokerUri, clientId);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Set a handler invoked for every received PUBLISH on a subscribed topic.
|
|
23
|
+
* The handler receives (topic, payload). */
|
|
24
|
+
onMessage(handler: (topic: string, payload: string) => void): void {
|
|
25
|
+
mqttOnMessage(callback(handler));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Subscribe to a topic filter (e.g. "sensors/#"). */
|
|
29
|
+
subscribe(topic: string): void {
|
|
30
|
+
mqttSubscribe(topic);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Publish a message to a topic. */
|
|
34
|
+
publish(topic: string, data: string): void {
|
|
35
|
+
mqttPublish(topic, data);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** True if the client is currently connected to the broker. */
|
|
39
|
+
connected(): boolean {
|
|
40
|
+
return mqttConnected();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Disconnect from the broker and free the client. */
|
|
44
|
+
disconnect(): void {
|
|
45
|
+
mqttDisconnect();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const MQTT = new MqttClass();
|
|
50
|
+
|
|
51
|
+
// ── Semantic primitives (resolved to mqtt.* HAL ops by the transpiler) ──
|
|
52
|
+
export function mqttConnect(brokerUri: string, clientId: string): void {}
|
|
53
|
+
export function mqttOnMessage(handler: string): void {}
|
|
54
|
+
export function mqttSubscribe(topic: string): void {}
|
|
55
|
+
export function mqttPublish(topic: string, data: string): void {}
|
|
56
|
+
export function mqttConnected(): boolean { return false; }
|
|
57
|
+
export function mqttDisconnect(): void {}
|
package/src/ota.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OtaClass — over-the-air firmware update (ESP-IDF esp_https_ota / esp_app_format).
|
|
3
|
+
*
|
|
4
|
+
* Lowered to native OTA HAL ops (ota.*): ESP-IDF's esp_https_ota downloads a
|
|
5
|
+
* firmware image over HTTPS and writes it to the OTA partition, then reboots
|
|
6
|
+
* into it. The runtime shim owns the session/progress/verification dance.
|
|
7
|
+
*
|
|
8
|
+
* Requires a network connection (WiFi) and that the partition table defines
|
|
9
|
+
* at least two OTA app slots (the framework's default partitions.csv does).
|
|
10
|
+
*/
|
|
11
|
+
export class OtaClass {
|
|
12
|
+
static readonly __instance_name = "OTA";
|
|
13
|
+
|
|
14
|
+
/** Download and apply a firmware image from an HTTPS URL, then reboot.
|
|
15
|
+
* Blocks until the update is written and verified. Returns true on success
|
|
16
|
+
* (the reboot happens inside the shim on success, so a true return means
|
|
17
|
+
* the new firmware is about to boot). */
|
|
18
|
+
fromUrl(url: string): boolean {
|
|
19
|
+
return otaFromUrl(url);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Begin a manual update session (caller writes chunks via write()). */
|
|
23
|
+
begin(): boolean {
|
|
24
|
+
return otaBegin();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Write a chunk of firmware data to the OTA partition. */
|
|
28
|
+
write(chunk: string): void {
|
|
29
|
+
otaWrite(chunk);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Finalize the update: verify, set the boot partition, and reboot. */
|
|
33
|
+
apply(): void {
|
|
34
|
+
otaApply();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const OTA = new OtaClass();
|
|
39
|
+
|
|
40
|
+
// ── Semantic primitives (resolved to ota.* HAL ops by the transpiler) ──
|
|
41
|
+
export function otaFromUrl(url: string): boolean { return false; }
|
|
42
|
+
export function otaBegin(): boolean { return false; }
|
|
43
|
+
export function otaWrite(chunk: string): void {}
|
|
44
|
+
export function otaApply(): void {}
|