@typecad/hal 1.0.0-alpha.7 → 1.0.0-alpha.8
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/dist/capacitive.d.ts +22 -0
- package/dist/capacitive.js +27 -0
- package/dist/emit.js +5 -0
- package/dist/fs.d.ts +21 -1
- package/dist/fs.js +29 -21
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- 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/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/wifi.d.ts +0 -1
- package/dist/wifi.js +0 -3
- package/package.json +6 -5
- package/src/capacitive.ts +31 -0
- package/src/emit.ts +5 -0
- package/src/fs.ts +30 -22
- package/src/index.ts +12 -0
- package/src/mdns.ts +50 -0
- package/src/mqtt.ts +57 -0
- package/src/ota.ts +44 -0
- package/src/temperature.ts +20 -0
- package/src/timer.ts +22 -23
- package/src/wifi.ts +0 -4
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CapacitiveClass — ESP32 on-chip capacitive touch pins.
|
|
3
|
+
*
|
|
4
|
+
* ESP32-family chips have dedicated capacitive-sensing GPIOs (10 on classic
|
|
5
|
+
* ESP32, up to 14 on S3) that read touch/proximity without external
|
|
6
|
+
* components — distinct from the I2C/SPI touch *display* controllers (FT6336U,
|
|
7
|
+
* GT911, etc.). Lowered to capacitive.* HAL ops: ESP-IDF's touch_sensor driver.
|
|
8
|
+
*
|
|
9
|
+
* Pin numbers are the touch-pad-capable GPIOs (GPIO4, GPIO0, GPIO2, ... on
|
|
10
|
+
* classic ESP32); the framework maps them to touch_channel indices.
|
|
11
|
+
*/
|
|
12
|
+
export declare class CapacitiveClass {
|
|
13
|
+
static readonly __instance_name = "Capacitive";
|
|
14
|
+
/** Read the raw capacitive value of a touch pin. Higher = more capacitance
|
|
15
|
+
* (touched). The raw scale is chip-dependent; use a threshold calibrated
|
|
16
|
+
* against the untouched reading. */
|
|
17
|
+
read(pin: number): number;
|
|
18
|
+
/** True when the pin's reading exceeds `threshold` (a convenience over read()). */
|
|
19
|
+
isTouched(pin: number, threshold: number): boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare const Capacitive: CapacitiveClass;
|
|
22
|
+
export declare function capacitiveRead(pin: number): number;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CapacitiveClass — ESP32 on-chip capacitive touch pins.
|
|
3
|
+
*
|
|
4
|
+
* ESP32-family chips have dedicated capacitive-sensing GPIOs (10 on classic
|
|
5
|
+
* ESP32, up to 14 on S3) that read touch/proximity without external
|
|
6
|
+
* components — distinct from the I2C/SPI touch *display* controllers (FT6336U,
|
|
7
|
+
* GT911, etc.). Lowered to capacitive.* HAL ops: ESP-IDF's touch_sensor driver.
|
|
8
|
+
*
|
|
9
|
+
* Pin numbers are the touch-pad-capable GPIOs (GPIO4, GPIO0, GPIO2, ... on
|
|
10
|
+
* classic ESP32); the framework maps them to touch_channel indices.
|
|
11
|
+
*/
|
|
12
|
+
export class CapacitiveClass {
|
|
13
|
+
/** Read the raw capacitive value of a touch pin. Higher = more capacitance
|
|
14
|
+
* (touched). The raw scale is chip-dependent; use a threshold calibrated
|
|
15
|
+
* against the untouched reading. */
|
|
16
|
+
read(pin) {
|
|
17
|
+
return capacitiveRead(pin);
|
|
18
|
+
}
|
|
19
|
+
/** True when the pin's reading exceeds `threshold` (a convenience over read()). */
|
|
20
|
+
isTouched(pin, threshold) {
|
|
21
|
+
return capacitiveRead(pin) > threshold;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
CapacitiveClass.__instance_name = "Capacitive";
|
|
25
|
+
export const Capacitive = new CapacitiveClass();
|
|
26
|
+
// ── Semantic primitive (resolved to capacitive.* HAL op by the transpiler) ──
|
|
27
|
+
export function capacitiveRead(pin) { return 0; }
|
package/dist/emit.js
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.
|
package/dist/fs.d.ts
CHANGED
|
@@ -1,13 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* FSClass provides a high-level abstraction for filesystem operations.
|
|
3
|
-
*
|
|
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.
|
|
4
12
|
*/
|
|
5
13
|
export declare class FSClass {
|
|
6
14
|
static readonly __instance_name = "FS";
|
|
15
|
+
/** Mount the filesystem. Returns true on success. */
|
|
7
16
|
begin(): boolean;
|
|
17
|
+
/** Read a UTF-8 text file into a string. Returns "" if the file is missing
|
|
18
|
+
* or unreadable. The returned buffer is caller-owned. */
|
|
8
19
|
readText(path: string): string;
|
|
20
|
+
/** Write a string to a file (overwrites). Silently no-ops if the file
|
|
21
|
+
* cannot be opened for writing. */
|
|
9
22
|
writeText(path: string, content: string): void;
|
|
23
|
+
/** True if a file exists at the path. */
|
|
10
24
|
exists(path: string): boolean;
|
|
25
|
+
/** Delete a file. Returns true if deleted. */
|
|
11
26
|
remove(path: string): boolean;
|
|
12
27
|
}
|
|
13
28
|
export declare const FS: FSClass;
|
|
29
|
+
export declare function fsBegin(): void;
|
|
30
|
+
export declare function fsReadText(path: string): string;
|
|
31
|
+
export declare function fsWriteText(path: string, content: string): void;
|
|
32
|
+
export declare function fsExists(path: string): boolean;
|
|
33
|
+
export declare function fsRemove(path: string): boolean;
|
package/dist/fs.js
CHANGED
|
@@ -1,39 +1,47 @@
|
|
|
1
|
-
import { rawCpp } from './emit.js';
|
|
2
|
-
import { include } from './include.js';
|
|
3
1
|
/**
|
|
4
2
|
* FSClass provides a high-level abstraction for filesystem operations.
|
|
5
|
-
*
|
|
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.
|
|
6
12
|
*/
|
|
7
13
|
export class FSClass {
|
|
14
|
+
/** Mount the filesystem. Returns true on success. */
|
|
8
15
|
begin() {
|
|
9
|
-
|
|
10
|
-
rawCpp(`return FS.begin();`);
|
|
16
|
+
fsBegin();
|
|
11
17
|
return true;
|
|
12
18
|
}
|
|
19
|
+
/** Read a UTF-8 text file into a string. Returns "" if the file is missing
|
|
20
|
+
* or unreadable. The returned buffer is caller-owned. */
|
|
13
21
|
readText(path) {
|
|
14
|
-
|
|
15
|
-
rawCpp(`File f = FS.open(${path}.c_str(), "r");`);
|
|
16
|
-
rawCpp(`if (!f) return "";`);
|
|
17
|
-
rawCpp(`String s = f.readString();`);
|
|
18
|
-
rawCpp(`f.close();`);
|
|
19
|
-
rawCpp(`return s.c_str();`);
|
|
20
|
-
return "";
|
|
22
|
+
return fsReadText(path);
|
|
21
23
|
}
|
|
24
|
+
/** Write a string to a file (overwrites). Silently no-ops if the file
|
|
25
|
+
* cannot be opened for writing. */
|
|
22
26
|
writeText(path, content) {
|
|
23
|
-
|
|
24
|
-
rawCpp(`File f = FS.open(${path}.c_str(), "w");`);
|
|
25
|
-
rawCpp(`if (f) { f.print(${content}.c_str()); f.close(); }`);
|
|
27
|
+
fsWriteText(path, content);
|
|
26
28
|
}
|
|
29
|
+
/** True if a file exists at the path. */
|
|
27
30
|
exists(path) {
|
|
28
|
-
|
|
29
|
-
rawCpp(`return FS.exists(${path}.c_str());`);
|
|
30
|
-
return false;
|
|
31
|
+
return fsExists(path);
|
|
31
32
|
}
|
|
33
|
+
/** Delete a file. Returns true if deleted. */
|
|
32
34
|
remove(path) {
|
|
33
|
-
|
|
34
|
-
rawCpp(`return FS.remove(${path}.c_str());`);
|
|
35
|
-
return false;
|
|
35
|
+
return fsRemove(path);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
FSClass.__instance_name = "FS";
|
|
39
39
|
export const FS = new FSClass();
|
|
40
|
+
// ── Semantic primitives (resolved to fs.* HAL ops by the transpiler) ──
|
|
41
|
+
// These are inert at runtime (tests, type-checking); the cuttlefish transpiler
|
|
42
|
+
// intercepts calls by name and lowers them to typed HAL op IR.
|
|
43
|
+
export function fsBegin() { }
|
|
44
|
+
export function fsReadText(path) { return ""; }
|
|
45
|
+
export function fsWriteText(path, content) { }
|
|
46
|
+
export function fsExists(path) { return false; }
|
|
47
|
+
export function fsRemove(path) { return false; }
|
package/dist/index.d.ts
CHANGED
|
@@ -33,6 +33,18 @@ export { DACClass, DAC } from './dac.js';
|
|
|
33
33
|
export { PreferencesClass, Preferences } from './preferences.js';
|
|
34
34
|
export { HardwareTimer, Timer0, Timer1, Timer2 } from './timer.js';
|
|
35
35
|
export { FSClass, FS } from './fs.js';
|
|
36
|
+
export { fsBegin, fsReadText, fsWriteText, fsExists, fsRemove } from './fs.js';
|
|
37
|
+
export { MdnsClass, MDNS } from './mdns.js';
|
|
38
|
+
export { mdnsStart, mdnsSetHostname, mdnsAddService, mdnsAnnounce, mdnsStop } from './mdns.js';
|
|
39
|
+
export { MqttClass, MQTT } from './mqtt.js';
|
|
40
|
+
export { mqttConnect, mqttOnMessage, mqttSubscribe, mqttPublish, mqttConnected, mqttDisconnect } from './mqtt.js';
|
|
41
|
+
export { OtaClass, OTA } from './ota.js';
|
|
42
|
+
export { otaFromUrl, otaBegin, otaWrite, otaApply } from './ota.js';
|
|
43
|
+
export { TemperatureClass, Temperature } from './temperature.js';
|
|
44
|
+
export { tempRead } from './temperature.js';
|
|
45
|
+
export { hwtimerSetFrequency, hwtimerOnOverflow, hwtimerStart, hwtimerStop } from './timer.js';
|
|
46
|
+
export { CapacitiveClass, Capacitive } from './capacitive.js';
|
|
47
|
+
export { capacitiveRead } from './capacitive.js';
|
|
36
48
|
export { PowerClass, Power } from './power.js';
|
|
37
49
|
export { AsyncClass, Async } from './async.js';
|
|
38
50
|
export { WiFiClass, WiFi, WiFiStatus, WiFiEncryption } from './wifi.js';
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,18 @@ export { DACClass, DAC } from './dac.js';
|
|
|
26
26
|
export { PreferencesClass, Preferences } from './preferences.js';
|
|
27
27
|
export { HardwareTimer, Timer0, Timer1, Timer2 } from './timer.js';
|
|
28
28
|
export { FSClass, FS } from './fs.js';
|
|
29
|
+
export { fsBegin, fsReadText, fsWriteText, fsExists, fsRemove } from './fs.js';
|
|
30
|
+
export { MdnsClass, MDNS } from './mdns.js';
|
|
31
|
+
export { mdnsStart, mdnsSetHostname, mdnsAddService, mdnsAnnounce, mdnsStop } from './mdns.js';
|
|
32
|
+
export { MqttClass, MQTT } from './mqtt.js';
|
|
33
|
+
export { mqttConnect, mqttOnMessage, mqttSubscribe, mqttPublish, mqttConnected, mqttDisconnect } from './mqtt.js';
|
|
34
|
+
export { OtaClass, OTA } from './ota.js';
|
|
35
|
+
export { otaFromUrl, otaBegin, otaWrite, otaApply } from './ota.js';
|
|
36
|
+
export { TemperatureClass, Temperature } from './temperature.js';
|
|
37
|
+
export { tempRead } from './temperature.js';
|
|
38
|
+
export { hwtimerSetFrequency, hwtimerOnOverflow, hwtimerStart, hwtimerStop } from './timer.js';
|
|
39
|
+
export { CapacitiveClass, Capacitive } from './capacitive.js';
|
|
40
|
+
export { capacitiveRead } from './capacitive.js';
|
|
29
41
|
export { PowerClass, Power } from './power.js';
|
|
30
42
|
export { AsyncClass, Async } from './async.js';
|
|
31
43
|
export { WiFiClass, WiFi, WiFiStatus, WiFiEncryption } from './wifi.js';
|
package/dist/mdns.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
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 declare class MdnsClass {
|
|
14
|
+
static readonly __instance_name = "MDNS";
|
|
15
|
+
/** Initialize mDNS and set the host name (advertised as <name>.local). */
|
|
16
|
+
start(hostname: string): boolean;
|
|
17
|
+
/** Set/override the host name after start(). */
|
|
18
|
+
setHostname(name: string): void;
|
|
19
|
+
/** Publish a service instance. proto is "_tcp" or "_udp". */
|
|
20
|
+
addService(instance: string, proto: string, port: number): void;
|
|
21
|
+
/** Advertise that the device is reachable (sends a probe/announce). */
|
|
22
|
+
announce(): void;
|
|
23
|
+
/** Tear down the mDNS responder. */
|
|
24
|
+
stop(): void;
|
|
25
|
+
}
|
|
26
|
+
export declare const MDNS: MdnsClass;
|
|
27
|
+
export declare function mdnsStart(hostname: string): void;
|
|
28
|
+
export declare function mdnsSetHostname(name: string): void;
|
|
29
|
+
export declare function mdnsAddService(instance: string, proto: string, port: number): void;
|
|
30
|
+
export declare function mdnsAnnounce(): void;
|
|
31
|
+
export declare function mdnsStop(): void;
|
package/dist/mdns.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
/** Initialize mDNS and set the host name (advertised as <name>.local). */
|
|
15
|
+
start(hostname) {
|
|
16
|
+
mdnsStart(hostname);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
/** Set/override the host name after start(). */
|
|
20
|
+
setHostname(name) {
|
|
21
|
+
mdnsSetHostname(name);
|
|
22
|
+
}
|
|
23
|
+
/** Publish a service instance. proto is "_tcp" or "_udp". */
|
|
24
|
+
addService(instance, proto, port) {
|
|
25
|
+
mdnsAddService(instance, proto, port);
|
|
26
|
+
}
|
|
27
|
+
/** Advertise that the device is reachable (sends a probe/announce). */
|
|
28
|
+
announce() {
|
|
29
|
+
mdnsAnnounce();
|
|
30
|
+
}
|
|
31
|
+
/** Tear down the mDNS responder. */
|
|
32
|
+
stop() {
|
|
33
|
+
mdnsStop();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
MdnsClass.__instance_name = "MDNS";
|
|
37
|
+
export const MDNS = new MdnsClass();
|
|
38
|
+
// ── Semantic primitives (resolved to mdns.* HAL ops by the transpiler) ──
|
|
39
|
+
export function mdnsStart(hostname) { }
|
|
40
|
+
export function mdnsSetHostname(name) { }
|
|
41
|
+
export function mdnsAddService(instance, proto, port) { }
|
|
42
|
+
export function mdnsAnnounce() { }
|
|
43
|
+
export function mdnsStop() { }
|
package/dist/mqtt.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MqttClass — MQTT 3.1.1 pub/sub client (ESP-IDF esp_mqtt).
|
|
3
|
+
*
|
|
4
|
+
* Lowered to native MQTT HAL ops (mqtt.*): ESP-IDF's esp_mqtt_client_* API.
|
|
5
|
+
* Covers the common IoT pub/sub path: connect to a broker, publish, subscribe
|
|
6
|
+
* with an onMessage callback, and disconnect. The runtime shim owns the event
|
|
7
|
+
* loop translation (ESP-IDF's MQTT event handler → the user's TS callback).
|
|
8
|
+
*
|
|
9
|
+
* Requires a network connection (WiFi) before connect().
|
|
10
|
+
*/
|
|
11
|
+
export declare class MqttClass {
|
|
12
|
+
static readonly __instance_name = "MQTT";
|
|
13
|
+
/** Connect to a broker URI (e.g. "mqtt://broker.local" or "mqtts://..."). */
|
|
14
|
+
connect(brokerUri: string, clientId: string): boolean;
|
|
15
|
+
/** Set a handler invoked for every received PUBLISH on a subscribed topic.
|
|
16
|
+
* The handler receives (topic, payload). */
|
|
17
|
+
onMessage(handler: (topic: string, payload: string) => void): void;
|
|
18
|
+
/** Subscribe to a topic filter (e.g. "sensors/#"). */
|
|
19
|
+
subscribe(topic: string): void;
|
|
20
|
+
/** Publish a message to a topic. */
|
|
21
|
+
publish(topic: string, data: string): void;
|
|
22
|
+
/** True if the client is currently connected to the broker. */
|
|
23
|
+
connected(): boolean;
|
|
24
|
+
/** Disconnect from the broker and free the client. */
|
|
25
|
+
disconnect(): void;
|
|
26
|
+
}
|
|
27
|
+
export declare const MQTT: MqttClass;
|
|
28
|
+
export declare function mqttConnect(brokerUri: string, clientId: string): void;
|
|
29
|
+
export declare function mqttOnMessage(handler: string): void;
|
|
30
|
+
export declare function mqttSubscribe(topic: string): void;
|
|
31
|
+
export declare function mqttPublish(topic: string, data: string): void;
|
|
32
|
+
export declare function mqttConnected(): boolean;
|
|
33
|
+
export declare function mqttDisconnect(): void;
|
package/dist/mqtt.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { callback } from './callback.js';
|
|
2
|
+
/**
|
|
3
|
+
* MqttClass — MQTT 3.1.1 pub/sub client (ESP-IDF esp_mqtt).
|
|
4
|
+
*
|
|
5
|
+
* Lowered to native MQTT HAL ops (mqtt.*): ESP-IDF's esp_mqtt_client_* API.
|
|
6
|
+
* Covers the common IoT pub/sub path: connect to a broker, publish, subscribe
|
|
7
|
+
* with an onMessage callback, and disconnect. The runtime shim owns the event
|
|
8
|
+
* loop translation (ESP-IDF's MQTT event handler → the user's TS callback).
|
|
9
|
+
*
|
|
10
|
+
* Requires a network connection (WiFi) before connect().
|
|
11
|
+
*/
|
|
12
|
+
export class MqttClass {
|
|
13
|
+
/** Connect to a broker URI (e.g. "mqtt://broker.local" or "mqtts://..."). */
|
|
14
|
+
connect(brokerUri, clientId) {
|
|
15
|
+
mqttConnect(brokerUri, clientId);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
/** Set a handler invoked for every received PUBLISH on a subscribed topic.
|
|
19
|
+
* The handler receives (topic, payload). */
|
|
20
|
+
onMessage(handler) {
|
|
21
|
+
mqttOnMessage(callback(handler));
|
|
22
|
+
}
|
|
23
|
+
/** Subscribe to a topic filter (e.g. "sensors/#"). */
|
|
24
|
+
subscribe(topic) {
|
|
25
|
+
mqttSubscribe(topic);
|
|
26
|
+
}
|
|
27
|
+
/** Publish a message to a topic. */
|
|
28
|
+
publish(topic, data) {
|
|
29
|
+
mqttPublish(topic, data);
|
|
30
|
+
}
|
|
31
|
+
/** True if the client is currently connected to the broker. */
|
|
32
|
+
connected() {
|
|
33
|
+
return mqttConnected();
|
|
34
|
+
}
|
|
35
|
+
/** Disconnect from the broker and free the client. */
|
|
36
|
+
disconnect() {
|
|
37
|
+
mqttDisconnect();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
MqttClass.__instance_name = "MQTT";
|
|
41
|
+
export const MQTT = new MqttClass();
|
|
42
|
+
// ── Semantic primitives (resolved to mqtt.* HAL ops by the transpiler) ──
|
|
43
|
+
export function mqttConnect(brokerUri, clientId) { }
|
|
44
|
+
export function mqttOnMessage(handler) { }
|
|
45
|
+
export function mqttSubscribe(topic) { }
|
|
46
|
+
export function mqttPublish(topic, data) { }
|
|
47
|
+
export function mqttConnected() { return false; }
|
|
48
|
+
export function mqttDisconnect() { }
|
package/dist/ota.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
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 declare class OtaClass {
|
|
12
|
+
static readonly __instance_name = "OTA";
|
|
13
|
+
/** Download and apply a firmware image from an HTTPS URL, then reboot.
|
|
14
|
+
* Blocks until the update is written and verified. Returns true on success
|
|
15
|
+
* (the reboot happens inside the shim on success, so a true return means
|
|
16
|
+
* the new firmware is about to boot). */
|
|
17
|
+
fromUrl(url: string): boolean;
|
|
18
|
+
/** Begin a manual update session (caller writes chunks via write()). */
|
|
19
|
+
begin(): boolean;
|
|
20
|
+
/** Write a chunk of firmware data to the OTA partition. */
|
|
21
|
+
write(chunk: string): void;
|
|
22
|
+
/** Finalize the update: verify, set the boot partition, and reboot. */
|
|
23
|
+
apply(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare const OTA: OtaClass;
|
|
26
|
+
export declare function otaFromUrl(url: string): boolean;
|
|
27
|
+
export declare function otaBegin(): boolean;
|
|
28
|
+
export declare function otaWrite(chunk: string): void;
|
|
29
|
+
export declare function otaApply(): void;
|
package/dist/ota.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
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
|
+
/** Download and apply a firmware image from an HTTPS URL, then reboot.
|
|
13
|
+
* Blocks until the update is written and verified. Returns true on success
|
|
14
|
+
* (the reboot happens inside the shim on success, so a true return means
|
|
15
|
+
* the new firmware is about to boot). */
|
|
16
|
+
fromUrl(url) {
|
|
17
|
+
return otaFromUrl(url);
|
|
18
|
+
}
|
|
19
|
+
/** Begin a manual update session (caller writes chunks via write()). */
|
|
20
|
+
begin() {
|
|
21
|
+
return otaBegin();
|
|
22
|
+
}
|
|
23
|
+
/** Write a chunk of firmware data to the OTA partition. */
|
|
24
|
+
write(chunk) {
|
|
25
|
+
otaWrite(chunk);
|
|
26
|
+
}
|
|
27
|
+
/** Finalize the update: verify, set the boot partition, and reboot. */
|
|
28
|
+
apply() {
|
|
29
|
+
otaApply();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
OtaClass.__instance_name = "OTA";
|
|
33
|
+
export const OTA = new OtaClass();
|
|
34
|
+
// ── Semantic primitives (resolved to ota.* HAL ops by the transpiler) ──
|
|
35
|
+
export function otaFromUrl(url) { return false; }
|
|
36
|
+
export function otaBegin() { return false; }
|
|
37
|
+
export function otaWrite(chunk) { }
|
|
38
|
+
export function otaApply() { }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TemperatureClass — on-chip die temperature sensor.
|
|
3
|
+
*
|
|
4
|
+
* Lowered to the temp.* HAL op: ESP-IDF's temperature_sensor driver reads the
|
|
5
|
+
* internal die temperature in °C. Useful for thermal monitoring and
|
|
6
|
+
* compensation. No external components required.
|
|
7
|
+
*/
|
|
8
|
+
export declare class TemperatureClass {
|
|
9
|
+
static readonly __instance_name = "Temperature";
|
|
10
|
+
/** Read the on-chip die temperature in degrees Celsius. */
|
|
11
|
+
read(): number;
|
|
12
|
+
}
|
|
13
|
+
export declare const Temperature: TemperatureClass;
|
|
14
|
+
export declare function tempRead(): number;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TemperatureClass — on-chip die temperature sensor.
|
|
3
|
+
*
|
|
4
|
+
* Lowered to the temp.* HAL op: ESP-IDF's temperature_sensor driver reads the
|
|
5
|
+
* internal die temperature in °C. Useful for thermal monitoring and
|
|
6
|
+
* compensation. No external components required.
|
|
7
|
+
*/
|
|
8
|
+
export class TemperatureClass {
|
|
9
|
+
/** Read the on-chip die temperature in degrees Celsius. */
|
|
10
|
+
read() {
|
|
11
|
+
return tempRead();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
TemperatureClass.__instance_name = "Temperature";
|
|
15
|
+
export const Temperature = new TemperatureClass();
|
|
16
|
+
// ── Semantic primitive (resolved to temp.* HAL op by the transpiler) ──
|
|
17
|
+
export function tempRead() { return 0; }
|
package/dist/timer.d.ts
CHANGED
|
@@ -3,33 +3,30 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Hardware timers are distinct from the software-based setInterval/setTimeout
|
|
5
5
|
* and are typically used for high-precision timing, PWM generation, or
|
|
6
|
-
* interrupt-driven tasks.
|
|
6
|
+
* interrupt-driven tasks. Lowered to hwtimer.* HAL ops: ESP-IDF's GPTimer
|
|
7
|
+
* driver (driver/gptimer.h); Arduino's HardwareTimer (Timer0/1/2 on STM32).
|
|
8
|
+
*
|
|
9
|
+
* The instance index maps to the platform's timer numbering (ESP-IDF GPTimer
|
|
10
|
+
* unit 0..n, STM32 TIM0..n).
|
|
7
11
|
*/
|
|
8
12
|
export declare class HardwareTimer {
|
|
9
13
|
private _instance;
|
|
10
14
|
constructor(instance: number);
|
|
11
|
-
/**
|
|
12
|
-
* Sets the timer frequency in Hertz.
|
|
13
|
-
* Note: The actual frequency may be limited by the hardware's clock dividers.
|
|
14
|
-
*/
|
|
15
|
+
/** Sets the timer frequency in Hertz. */
|
|
15
16
|
setFrequency(hz: number): void;
|
|
16
|
-
/**
|
|
17
|
-
* Attaches an interrupt handler that executes when the timer overflows.
|
|
18
|
-
*/
|
|
17
|
+
/** Attaches an interrupt handler that executes when the timer overflows. */
|
|
19
18
|
onOverflow(handler: () => void): void;
|
|
20
|
-
/**
|
|
21
|
-
* Starts the timer.
|
|
22
|
-
*/
|
|
19
|
+
/** Starts the timer. */
|
|
23
20
|
start(): void;
|
|
24
|
-
/**
|
|
25
|
-
* Stops the timer.
|
|
26
|
-
*/
|
|
21
|
+
/** Stops the timer. */
|
|
27
22
|
stop(): void;
|
|
28
|
-
/**
|
|
29
|
-
* Returns the bit resolution of the timer (e.g., 8, 16, 32).
|
|
30
|
-
*/
|
|
23
|
+
/** Returns the bit resolution of the timer (e.g., 8, 16, 32). */
|
|
31
24
|
getBits(): number;
|
|
32
25
|
}
|
|
33
26
|
export declare const Timer0: HardwareTimer;
|
|
34
27
|
export declare const Timer1: HardwareTimer;
|
|
35
28
|
export declare const Timer2: HardwareTimer;
|
|
29
|
+
export declare function hwtimerSetFrequency(instance: number, hz: number): void;
|
|
30
|
+
export declare function hwtimerOnOverflow(instance: number, handler: string): void;
|
|
31
|
+
export declare function hwtimerStart(instance: number): void;
|
|
32
|
+
export declare function hwtimerStop(instance: number): void;
|
package/dist/timer.js
CHANGED
|
@@ -1,44 +1,37 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { boardResolve } from './emit.js';
|
|
2
2
|
import { callback } from './callback.js';
|
|
3
3
|
/**
|
|
4
4
|
* HardwareTimer provides direct control over the board's hardware timers.
|
|
5
5
|
*
|
|
6
6
|
* Hardware timers are distinct from the software-based setInterval/setTimeout
|
|
7
7
|
* and are typically used for high-precision timing, PWM generation, or
|
|
8
|
-
* interrupt-driven tasks.
|
|
8
|
+
* interrupt-driven tasks. Lowered to hwtimer.* HAL ops: ESP-IDF's GPTimer
|
|
9
|
+
* driver (driver/gptimer.h); Arduino's HardwareTimer (Timer0/1/2 on STM32).
|
|
10
|
+
*
|
|
11
|
+
* The instance index maps to the platform's timer numbering (ESP-IDF GPTimer
|
|
12
|
+
* unit 0..n, STM32 TIM0..n).
|
|
9
13
|
*/
|
|
10
14
|
export class HardwareTimer {
|
|
11
15
|
constructor(instance) {
|
|
12
16
|
this._instance = instance;
|
|
13
17
|
}
|
|
14
|
-
/**
|
|
15
|
-
* Sets the timer frequency in Hertz.
|
|
16
|
-
* Note: The actual frequency may be limited by the hardware's clock dividers.
|
|
17
|
-
*/
|
|
18
|
+
/** Sets the timer frequency in Hertz. */
|
|
18
19
|
setFrequency(hz) {
|
|
19
|
-
|
|
20
|
+
hwtimerSetFrequency(this._instance, hz);
|
|
20
21
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Attaches an interrupt handler that executes when the timer overflows.
|
|
23
|
-
*/
|
|
22
|
+
/** Attaches an interrupt handler that executes when the timer overflows. */
|
|
24
23
|
onOverflow(handler) {
|
|
25
|
-
|
|
24
|
+
hwtimerOnOverflow(this._instance, callback(handler));
|
|
26
25
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Starts the timer.
|
|
29
|
-
*/
|
|
26
|
+
/** Starts the timer. */
|
|
30
27
|
start() {
|
|
31
|
-
|
|
28
|
+
hwtimerStart(this._instance);
|
|
32
29
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Stops the timer.
|
|
35
|
-
*/
|
|
30
|
+
/** Stops the timer. */
|
|
36
31
|
stop() {
|
|
37
|
-
|
|
32
|
+
hwtimerStop(this._instance);
|
|
38
33
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Returns the bit resolution of the timer (e.g., 8, 16, 32).
|
|
41
|
-
*/
|
|
34
|
+
/** Returns the bit resolution of the timer (e.g., 8, 16, 32). */
|
|
42
35
|
getBits() {
|
|
43
36
|
// "peripherals.timer" (singular) matches the board-resolver's array-key
|
|
44
37
|
// derivation (TIMER_INSTANCES → peripherals.timer.<index>.*).
|
|
@@ -48,3 +41,8 @@ export class HardwareTimer {
|
|
|
48
41
|
export const Timer0 = new HardwareTimer(0);
|
|
49
42
|
export const Timer1 = new HardwareTimer(1);
|
|
50
43
|
export const Timer2 = new HardwareTimer(2);
|
|
44
|
+
// ── Semantic primitives (resolved to hwtimer.* HAL ops by the transpiler) ──
|
|
45
|
+
export function hwtimerSetFrequency(instance, hz) { }
|
|
46
|
+
export function hwtimerOnOverflow(instance, handler) { }
|
|
47
|
+
export function hwtimerStart(instance) { }
|
|
48
|
+
export function hwtimerStop(instance) { }
|
package/dist/wifi.d.ts
CHANGED
|
@@ -49,7 +49,6 @@ export declare class WiFiClass {
|
|
|
49
49
|
clearCredentials(): void;
|
|
50
50
|
onConnect(handler: () => void): void;
|
|
51
51
|
onDisconnect(handler: () => void): void;
|
|
52
|
-
onGotIP(handler: () => void): void;
|
|
53
52
|
startAP(ssid: string, password?: string): boolean;
|
|
54
53
|
apChannel(ch: number): this;
|
|
55
54
|
apHidden(hidden: boolean): this;
|
package/dist/wifi.js
CHANGED
|
@@ -100,9 +100,6 @@ export class WiFiClass {
|
|
|
100
100
|
onDisconnect(handler) {
|
|
101
101
|
wifiOnEvent("disconnect", callback(handler));
|
|
102
102
|
}
|
|
103
|
-
onGotIP(handler) {
|
|
104
|
-
wifiOnEvent("got_ip", callback(handler));
|
|
105
|
-
}
|
|
106
103
|
startAP(ssid, password) {
|
|
107
104
|
return wifiApStart(ssid, password);
|
|
108
105
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typecad/hal",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.8",
|
|
4
4
|
"description": "TypeCAD hardware abstraction layer — GPIO, I2C, SPI, UART as regular TypeScript",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"build": "tsc",
|
|
14
14
|
"prepublishOnly": "npm run build",
|
|
15
15
|
"test:hw": "npm exec -- cuttlefish-test",
|
|
16
|
-
"test:hw:basics": "npm exec -- cuttlefish-test tests/01-gpio.test.ts"
|
|
16
|
+
"test:hw:basics": "npm exec -- cuttlefish-test tests/01-gpio.test.ts",
|
|
17
|
+
"test:hw:preferences": "npm exec -- cuttlefish-test tests/14-preferences.test.ts"
|
|
17
18
|
},
|
|
18
19
|
"license": "MIT",
|
|
19
20
|
"publishConfig": {
|
|
@@ -49,9 +50,9 @@
|
|
|
49
50
|
},
|
|
50
51
|
"author": "typecad0",
|
|
51
52
|
"devDependencies": {
|
|
52
|
-
"@typecad/expect": "1.0.0-alpha.
|
|
53
|
-
"@typecad/board-arduino-uno": "1.0.0-alpha.
|
|
54
|
-
"@typecad/mcu-atmega328p": "1.0.0-alpha.
|
|
53
|
+
"@typecad/expect": "1.0.0-alpha.8",
|
|
54
|
+
"@typecad/board-arduino-uno": "1.0.0-alpha.8",
|
|
55
|
+
"@typecad/mcu-atmega328p": "1.0.0-alpha.8"
|
|
55
56
|
},
|
|
56
57
|
"sideEffects": false,
|
|
57
58
|
"exports": {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CapacitiveClass — ESP32 on-chip capacitive touch pins.
|
|
3
|
+
*
|
|
4
|
+
* ESP32-family chips have dedicated capacitive-sensing GPIOs (10 on classic
|
|
5
|
+
* ESP32, up to 14 on S3) that read touch/proximity without external
|
|
6
|
+
* components — distinct from the I2C/SPI touch *display* controllers (FT6336U,
|
|
7
|
+
* GT911, etc.). Lowered to capacitive.* HAL ops: ESP-IDF's touch_sensor driver.
|
|
8
|
+
*
|
|
9
|
+
* Pin numbers are the touch-pad-capable GPIOs (GPIO4, GPIO0, GPIO2, ... on
|
|
10
|
+
* classic ESP32); the framework maps them to touch_channel indices.
|
|
11
|
+
*/
|
|
12
|
+
export class CapacitiveClass {
|
|
13
|
+
static readonly __instance_name = "Capacitive";
|
|
14
|
+
|
|
15
|
+
/** Read the raw capacitive value of a touch pin. Higher = more capacitance
|
|
16
|
+
* (touched). The raw scale is chip-dependent; use a threshold calibrated
|
|
17
|
+
* against the untouched reading. */
|
|
18
|
+
read(pin: number): number {
|
|
19
|
+
return capacitiveRead(pin);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** True when the pin's reading exceeds `threshold` (a convenience over read()). */
|
|
23
|
+
isTouched(pin: number, threshold: number): boolean {
|
|
24
|
+
return capacitiveRead(pin) > threshold;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const Capacitive = new CapacitiveClass();
|
|
29
|
+
|
|
30
|
+
// ── Semantic primitive (resolved to capacitive.* HAL op by the transpiler) ──
|
|
31
|
+
export function capacitiveRead(pin: number): number { return 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.
|
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/index.ts
CHANGED
|
@@ -44,6 +44,18 @@ 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';
|
|
49
61
|
export { WiFiClass, WiFi, WiFiStatus, WiFiEncryption } from './wifi.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 {}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TemperatureClass — on-chip die temperature sensor.
|
|
3
|
+
*
|
|
4
|
+
* Lowered to the temp.* HAL op: ESP-IDF's temperature_sensor driver reads the
|
|
5
|
+
* internal die temperature in °C. Useful for thermal monitoring and
|
|
6
|
+
* compensation. No external components required.
|
|
7
|
+
*/
|
|
8
|
+
export class TemperatureClass {
|
|
9
|
+
static readonly __instance_name = "Temperature";
|
|
10
|
+
|
|
11
|
+
/** Read the on-chip die temperature in degrees Celsius. */
|
|
12
|
+
read(): number {
|
|
13
|
+
return tempRead();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const Temperature = new TemperatureClass();
|
|
18
|
+
|
|
19
|
+
// ── Semantic primitive (resolved to temp.* HAL op by the transpiler) ──
|
|
20
|
+
export function tempRead(): number { return 0; }
|
package/src/timer.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { boardResolve } from './emit.js';
|
|
2
2
|
import { callback } from './callback.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* HardwareTimer provides direct control over the board's hardware timers.
|
|
6
|
-
*
|
|
6
|
+
*
|
|
7
7
|
* Hardware timers are distinct from the software-based setInterval/setTimeout
|
|
8
8
|
* and are typically used for high-precision timing, PWM generation, or
|
|
9
|
-
* interrupt-driven tasks.
|
|
9
|
+
* interrupt-driven tasks. Lowered to hwtimer.* HAL ops: ESP-IDF's GPTimer
|
|
10
|
+
* driver (driver/gptimer.h); Arduino's HardwareTimer (Timer0/1/2 on STM32).
|
|
11
|
+
*
|
|
12
|
+
* The instance index maps to the platform's timer numbering (ESP-IDF GPTimer
|
|
13
|
+
* unit 0..n, STM32 TIM0..n).
|
|
10
14
|
*/
|
|
11
15
|
export class HardwareTimer {
|
|
12
16
|
private _instance: number;
|
|
@@ -15,38 +19,27 @@ export class HardwareTimer {
|
|
|
15
19
|
this._instance = instance;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
/**
|
|
19
|
-
* Sets the timer frequency in Hertz.
|
|
20
|
-
* Note: The actual frequency may be limited by the hardware's clock dividers.
|
|
21
|
-
*/
|
|
22
|
+
/** Sets the timer frequency in Hertz. */
|
|
22
23
|
setFrequency(hz: number): void {
|
|
23
|
-
|
|
24
|
+
hwtimerSetFrequency(this._instance, hz);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
/**
|
|
27
|
-
* Attaches an interrupt handler that executes when the timer overflows.
|
|
28
|
-
*/
|
|
27
|
+
/** Attaches an interrupt handler that executes when the timer overflows. */
|
|
29
28
|
onOverflow(handler: () => void): void {
|
|
30
|
-
|
|
29
|
+
hwtimerOnOverflow(this._instance, callback(handler));
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
/**
|
|
34
|
-
* Starts the timer.
|
|
35
|
-
*/
|
|
32
|
+
/** Starts the timer. */
|
|
36
33
|
start(): void {
|
|
37
|
-
|
|
34
|
+
hwtimerStart(this._instance);
|
|
38
35
|
}
|
|
39
36
|
|
|
40
|
-
/**
|
|
41
|
-
* Stops the timer.
|
|
42
|
-
*/
|
|
37
|
+
/** Stops the timer. */
|
|
43
38
|
stop(): void {
|
|
44
|
-
|
|
39
|
+
hwtimerStop(this._instance);
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
/**
|
|
48
|
-
* Returns the bit resolution of the timer (e.g., 8, 16, 32).
|
|
49
|
-
*/
|
|
42
|
+
/** Returns the bit resolution of the timer (e.g., 8, 16, 32). */
|
|
50
43
|
getBits(): number {
|
|
51
44
|
// "peripherals.timer" (singular) matches the board-resolver's array-key
|
|
52
45
|
// derivation (TIMER_INSTANCES → peripherals.timer.<index>.*).
|
|
@@ -57,3 +50,9 @@ export class HardwareTimer {
|
|
|
57
50
|
export const Timer0 = new HardwareTimer(0);
|
|
58
51
|
export const Timer1 = new HardwareTimer(1);
|
|
59
52
|
export const Timer2 = new HardwareTimer(2);
|
|
53
|
+
|
|
54
|
+
// ── Semantic primitives (resolved to hwtimer.* HAL ops by the transpiler) ──
|
|
55
|
+
export function hwtimerSetFrequency(instance: number, hz: number): void {}
|
|
56
|
+
export function hwtimerOnOverflow(instance: number, handler: string): void {}
|
|
57
|
+
export function hwtimerStart(instance: number): void {}
|
|
58
|
+
export function hwtimerStop(instance: number): void {}
|
package/src/wifi.ts
CHANGED
|
@@ -157,10 +157,6 @@ export class WiFiClass {
|
|
|
157
157
|
wifiOnEvent("disconnect", callback(handler));
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
onGotIP(handler: () => void): void {
|
|
161
|
-
wifiOnEvent("got_ip", callback(handler));
|
|
162
|
-
}
|
|
163
|
-
|
|
164
160
|
startAP(ssid: string, password?: string): boolean {
|
|
165
161
|
return wifiApStart(ssid, password);
|
|
166
162
|
}
|