@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.
Files changed (57) hide show
  1. package/README.md +8 -7
  2. package/dist/ble.d.ts +160 -0
  3. package/dist/ble.js +157 -0
  4. package/dist/capacitive.d.ts +22 -0
  5. package/dist/capacitive.js +27 -0
  6. package/dist/emit.d.ts +139 -0
  7. package/dist/emit.js +152 -0
  8. package/dist/fs.d.ts +21 -1
  9. package/dist/fs.js +29 -21
  10. package/dist/http.d.ts +48 -0
  11. package/dist/http.js +104 -0
  12. package/dist/i2c.d.ts +7 -0
  13. package/dist/i2c.js +15 -4
  14. package/dist/index.d.ts +18 -1
  15. package/dist/index.js +17 -1
  16. package/dist/mdns.d.ts +31 -0
  17. package/dist/mdns.js +43 -0
  18. package/dist/mqtt.d.ts +33 -0
  19. package/dist/mqtt.js +48 -0
  20. package/dist/ota.d.ts +29 -0
  21. package/dist/ota.js +38 -0
  22. package/dist/power.d.ts +7 -0
  23. package/dist/power.js +10 -1
  24. package/dist/preferences.d.ts +11 -2
  25. package/dist/preferences.js +28 -27
  26. package/dist/register.d.ts +12 -4
  27. package/dist/register.js +18 -1
  28. package/dist/rmt.d.ts +48 -0
  29. package/dist/rmt.js +81 -0
  30. package/dist/spi.js +10 -7
  31. package/dist/temperature.d.ts +14 -0
  32. package/dist/temperature.js +17 -0
  33. package/dist/timer.d.ts +14 -17
  34. package/dist/timer.js +20 -22
  35. package/dist/types.d.ts +1 -1
  36. package/dist/wifi.d.ts +67 -0
  37. package/dist/wifi.js +151 -0
  38. package/package.json +6 -5
  39. package/src/ble.ts +209 -0
  40. package/src/capacitive.ts +31 -0
  41. package/src/emit.ts +180 -0
  42. package/src/fs.ts +30 -22
  43. package/src/http.ts +144 -0
  44. package/src/i2c.ts +16 -4
  45. package/src/index.ts +21 -1
  46. package/src/mdns.ts +50 -0
  47. package/src/mqtt.ts +57 -0
  48. package/src/ota.ts +44 -0
  49. package/src/power.ts +11 -1
  50. package/src/preferences.ts +56 -27
  51. package/src/register.ts +16 -4
  52. package/src/rmt.ts +125 -0
  53. package/src/spi.ts +10 -7
  54. package/src/temperature.ts +20 -0
  55. package/src/timer.ts +22 -23
  56. package/src/types.ts +1 -0
  57. package/src/wifi.ts +221 -0
package/dist/wifi.d.ts ADDED
@@ -0,0 +1,67 @@
1
+ /** Normalized WiFi link status (mapped from esp_wifi events by the runtime shim). */
2
+ export declare enum WiFiStatus {
3
+ Idle = 0,
4
+ Connecting = 1,
5
+ Connected = 2,
6
+ ConnectFailed = 3,
7
+ Disconnected = 4
8
+ }
9
+ export declare enum WiFiEncryption {
10
+ Open = 0,
11
+ WEP = 1,
12
+ WPA = 2,
13
+ WPA2 = 3,
14
+ WPA3 = 4,
15
+ Enterprise = 5
16
+ }
17
+ /**
18
+ * WiFi radio / link control, lowered to native ESP-IDF (`esp_wifi` /
19
+ * `esp_netif` / `esp_event` / `nvs_flash`) by framework-esp32.
20
+ *
21
+ * No `include()` calls here — ESP-IDF headers are framework-owned and added
22
+ * via forcedIncludes when the program uses wifi.* ops (the Preferences
23
+ * lesson: HAL files must not carry platform headers). Frameworks without a
24
+ * wifi lowering reject these ops with a diagnostic.
25
+ */
26
+ export declare class WiFiClass {
27
+ static readonly __instance_name = "WiFi";
28
+ /** Blocking at top level; cooperatively awaitable inside async functions. */
29
+ connect(ssid: string, password?: string, timeoutMs?: number): Promise<boolean>;
30
+ /** Fire-and-forget STA begin; poll status() / untilConnected(). */
31
+ connectAsync(ssid: string, password?: string): void;
32
+ untilConnected(timeoutMs?: number): Promise<boolean>;
33
+ untilDisconnected(): Promise<void>;
34
+ disconnect(): void;
35
+ isConnected(): boolean;
36
+ status(): WiFiStatus;
37
+ localIP(): string;
38
+ rssi(): number;
39
+ macAddress(): string;
40
+ hostname(name: string): this;
41
+ staticIP(ip: string, gateway: string, subnet: string, dns?: string): this;
42
+ autoReconnect(enabled: boolean): this;
43
+ powerSave(mode: "default" | "none"): this;
44
+ /** Cap TX power in dBm (roughly 2–20). Safe to call before connect() —
45
+ * the value is applied after the radio starts. */
46
+ txPower(dbm: number): this;
47
+ saveCredentials(ssid: string, password: string): void;
48
+ connectSaved(timeoutMs?: number): boolean;
49
+ clearCredentials(): void;
50
+ onConnect(handler: () => void): void;
51
+ onDisconnect(handler: () => void): void;
52
+ startAP(ssid: string, password?: string): boolean;
53
+ apChannel(ch: number): this;
54
+ apHidden(hidden: boolean): this;
55
+ apMaxClients(n: number): this;
56
+ stopAP(): void;
57
+ apClientCount(): number;
58
+ apIP(): string;
59
+ scan(): number;
60
+ scanAsync(): Promise<void>;
61
+ scanCount(): number;
62
+ scanSSID(i: number): string;
63
+ scanRSSI(i: number): number;
64
+ scanEncryption(i: number): WiFiEncryption;
65
+ scanChannel(i: number): number;
66
+ }
67
+ export declare const WiFi: WiFiClass;
package/dist/wifi.js ADDED
@@ -0,0 +1,151 @@
1
+ import { wifiConnect, wifiConnectStart, wifiDisconnect, wifiStatus, wifiIsConnected, wifiLocalIp, wifiRssi, wifiMac, wifiSetHostname, wifiSetStaticIp, wifiSetAutoReconnect, wifiSetPowerSave, wifiSetTxPower, wifiOnEvent, wifiApStart, wifiApStop, wifiApClientCount, wifiApIp, wifiApSetChannel, wifiApSetHidden, wifiApSetMaxClients, wifiScan, wifiScanStart, wifiScanCount, wifiScanSsid, wifiScanRssi, wifiScanEncryption, wifiScanChannel, wifiSaveCredentials, wifiConnectSaved, wifiClearCredentials, wifiWaitConnected, wifiWaitDisconnected, } from './emit.js';
2
+ import { callback } from './callback.js';
3
+ /** Normalized WiFi link status (mapped from esp_wifi events by the runtime shim). */
4
+ export var WiFiStatus;
5
+ (function (WiFiStatus) {
6
+ WiFiStatus[WiFiStatus["Idle"] = 0] = "Idle";
7
+ WiFiStatus[WiFiStatus["Connecting"] = 1] = "Connecting";
8
+ WiFiStatus[WiFiStatus["Connected"] = 2] = "Connected";
9
+ WiFiStatus[WiFiStatus["ConnectFailed"] = 3] = "ConnectFailed";
10
+ WiFiStatus[WiFiStatus["Disconnected"] = 4] = "Disconnected";
11
+ })(WiFiStatus || (WiFiStatus = {}));
12
+ export var WiFiEncryption;
13
+ (function (WiFiEncryption) {
14
+ WiFiEncryption[WiFiEncryption["Open"] = 0] = "Open";
15
+ WiFiEncryption[WiFiEncryption["WEP"] = 1] = "WEP";
16
+ WiFiEncryption[WiFiEncryption["WPA"] = 2] = "WPA";
17
+ WiFiEncryption[WiFiEncryption["WPA2"] = 3] = "WPA2";
18
+ WiFiEncryption[WiFiEncryption["WPA3"] = 4] = "WPA3";
19
+ WiFiEncryption[WiFiEncryption["Enterprise"] = 5] = "Enterprise";
20
+ })(WiFiEncryption || (WiFiEncryption = {}));
21
+ /**
22
+ * WiFi radio / link control, lowered to native ESP-IDF (`esp_wifi` /
23
+ * `esp_netif` / `esp_event` / `nvs_flash`) by framework-esp32.
24
+ *
25
+ * No `include()` calls here — ESP-IDF headers are framework-owned and added
26
+ * via forcedIncludes when the program uses wifi.* ops (the Preferences
27
+ * lesson: HAL files must not carry platform headers). Frameworks without a
28
+ * wifi lowering reject these ops with a diagnostic.
29
+ */
30
+ export class WiFiClass {
31
+ /** Blocking at top level; cooperatively awaitable inside async functions. */
32
+ connect(ssid, password, timeoutMs = 15000) {
33
+ wifiConnect(ssid, password, timeoutMs);
34
+ return Promise.resolve(false);
35
+ }
36
+ /** Fire-and-forget STA begin; poll status() / untilConnected(). */
37
+ connectAsync(ssid, password) {
38
+ wifiConnectStart(ssid, password);
39
+ }
40
+ untilConnected(timeoutMs = 15000) {
41
+ wifiWaitConnected(timeoutMs);
42
+ return Promise.resolve(false);
43
+ }
44
+ untilDisconnected() {
45
+ wifiWaitDisconnected();
46
+ return Promise.resolve();
47
+ }
48
+ disconnect() {
49
+ wifiDisconnect();
50
+ }
51
+ isConnected() {
52
+ return wifiIsConnected();
53
+ }
54
+ status() {
55
+ return wifiStatus();
56
+ }
57
+ localIP() {
58
+ return wifiLocalIp();
59
+ }
60
+ rssi() {
61
+ return wifiRssi();
62
+ }
63
+ macAddress() {
64
+ return wifiMac();
65
+ }
66
+ hostname(name) {
67
+ wifiSetHostname(name);
68
+ return this;
69
+ }
70
+ staticIP(ip, gateway, subnet, dns) {
71
+ wifiSetStaticIp(ip, gateway, subnet, dns);
72
+ return this;
73
+ }
74
+ autoReconnect(enabled) {
75
+ wifiSetAutoReconnect(enabled);
76
+ return this;
77
+ }
78
+ powerSave(mode) {
79
+ wifiSetPowerSave(mode);
80
+ return this;
81
+ }
82
+ /** Cap TX power in dBm (roughly 2–20). Safe to call before connect() —
83
+ * the value is applied after the radio starts. */
84
+ txPower(dbm) {
85
+ wifiSetTxPower(dbm);
86
+ return this;
87
+ }
88
+ saveCredentials(ssid, password) {
89
+ wifiSaveCredentials(ssid, password);
90
+ }
91
+ connectSaved(timeoutMs = 15000) {
92
+ return wifiConnectSaved(timeoutMs);
93
+ }
94
+ clearCredentials() {
95
+ wifiClearCredentials();
96
+ }
97
+ onConnect(handler) {
98
+ wifiOnEvent("connect", callback(handler));
99
+ }
100
+ onDisconnect(handler) {
101
+ wifiOnEvent("disconnect", callback(handler));
102
+ }
103
+ startAP(ssid, password) {
104
+ return wifiApStart(ssid, password);
105
+ }
106
+ apChannel(ch) {
107
+ wifiApSetChannel(ch);
108
+ return this;
109
+ }
110
+ apHidden(hidden) {
111
+ wifiApSetHidden(hidden);
112
+ return this;
113
+ }
114
+ apMaxClients(n) {
115
+ wifiApSetMaxClients(n);
116
+ return this;
117
+ }
118
+ stopAP() {
119
+ wifiApStop();
120
+ }
121
+ apClientCount() {
122
+ return wifiApClientCount();
123
+ }
124
+ apIP() {
125
+ return wifiApIp();
126
+ }
127
+ scan() {
128
+ return wifiScan();
129
+ }
130
+ scanAsync() {
131
+ wifiScanStart();
132
+ return Promise.resolve();
133
+ }
134
+ scanCount() {
135
+ return wifiScanCount();
136
+ }
137
+ scanSSID(i) {
138
+ return wifiScanSsid(i);
139
+ }
140
+ scanRSSI(i) {
141
+ return wifiScanRssi(i);
142
+ }
143
+ scanEncryption(i) {
144
+ return wifiScanEncryption(i);
145
+ }
146
+ scanChannel(i) {
147
+ return wifiScanChannel(i);
148
+ }
149
+ }
150
+ WiFiClass.__instance_name = "WiFi";
151
+ export const WiFi = new WiFiClass();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typecad/hal",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "1.0.0-alpha.11",
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": "0.1.0-alpha.2",
53
- "@typecad/board-arduino-uno": "0.1.0-alpha.2",
54
- "@typecad/mcu-atmega328p": "0.1.0-alpha.2"
53
+ "@typecad/expect": "1.0.0-alpha.11",
54
+ "@typecad/board-arduino-uno": "1.0.0-alpha.11",
55
+ "@typecad/mcu-atmega328p": "1.0.0-alpha.11"
55
56
  },
56
57
  "sideEffects": false,
57
58
  "exports": {
package/src/ble.ts ADDED
@@ -0,0 +1,209 @@
1
+ import {
2
+ bleServerBegin,
3
+ bleAdvertiseStart,
4
+ bleAdvertiseStop,
5
+ bleAddService,
6
+ bleAddChar,
7
+ bleOnRead,
8
+ bleOnWrite,
9
+ bleOnConnect,
10
+ bleOnDisconnect,
11
+ bleNotify,
12
+ bleIsConnected,
13
+ bleClientCount,
14
+ bleSetName,
15
+ bleUntilConnected,
16
+ bleUntilConnectedStart,
17
+ bleSetTxPower,
18
+ bleStatus,
19
+ } from './emit.js';
20
+ import { callback } from './callback.js';
21
+
22
+ /** Characteristic value encoding — drives both TS callback types and C++ marshalling. */
23
+ export enum BleValueType {
24
+ Uint8 = 'uint8',
25
+ Uint16 = 'uint16',
26
+ Uint32 = 'uint32',
27
+ Int8 = 'int8',
28
+ Int16 = 'int16',
29
+ Int32 = 'int32',
30
+ Float32 = 'float32',
31
+ Utf8 = 'utf8',
32
+ Boolean = 'boolean',
33
+ Bytes = 'bytes',
34
+ }
35
+
36
+ /** GATT characteristic permission flags. Combine with `|`. */
37
+ export enum BlePerm {
38
+ Read = 1,
39
+ Write = 2,
40
+ Notify = 4,
41
+ }
42
+
43
+ /** BLE peripheral status (mirrored by the runtime shim). */
44
+ export enum BleStatus {
45
+ Idle = 0,
46
+ Initializing = 1,
47
+ Advertising = 2,
48
+ Connected = 3,
49
+ Error = 4,
50
+ }
51
+
52
+ export enum BleAdvertisingMode {
53
+ Connectable = 'connectable',
54
+ NonConnectable = 'non_connectable',
55
+ }
56
+
57
+ /** A well-known GATT characteristic entry in the catalog. */
58
+ export interface GattCharacteristicDef {
59
+ readonly uuid: string;
60
+ readonly type: BleValueType;
61
+ readonly read?: boolean;
62
+ readonly write?: boolean;
63
+ readonly notify?: boolean;
64
+ }
65
+
66
+ /**
67
+ * Standard GATT services/characteristics. Autocomplete walks the hierarchy:
68
+ * GATT.ENVIRONMENTAL. -> TEMPERATURE, HUMIDITY, ...
69
+ * Pass the .uuid, .type, and computed perms to BleServer.characteristic().
70
+ */
71
+ export const GATT = {
72
+ DEVICE_INFO: {
73
+ MANUFACTURER_NAME: { uuid: '2A29', type: BleValueType.Utf8, read: true },
74
+ MODEL_NUMBER: { uuid: '2A24', type: BleValueType.Utf8, read: true },
75
+ FIRMWARE_REVISION: { uuid: '2A26', type: BleValueType.Utf8, read: true },
76
+ },
77
+ ENVIRONMENTAL: {
78
+ TEMPERATURE: { uuid: '2A6E', type: BleValueType.Int16, read: true, notify: true },
79
+ HUMIDITY: { uuid: '2A6F', type: BleValueType.Uint16, read: true, notify: true },
80
+ PRESSURE: { uuid: '2A6D', type: BleValueType.Uint32, read: true, notify: true },
81
+ },
82
+ BATTERY: {
83
+ LEVEL: { uuid: '2A19', type: BleValueType.Uint8, read: true, notify: true },
84
+ },
85
+ } as const;
86
+
87
+ /** The value passed to/from callbacks — narrowed per characteristic by type. */
88
+ export type CharValue = number | string | boolean | Uint8Array;
89
+
90
+ /**
91
+ * BLE GATT peripheral control, lowered to native ESP-IDF NimBLE
92
+ * (`nimble_host` / `ble_gap` / `ble_gatts`) by framework-esp32.
93
+ *
94
+ * No `include()` calls here — NimBLE headers are framework-owned and added via
95
+ * forcedIncludes when the program uses ble.* ops.
96
+ *
97
+ * Transpiler note: method bodies pass parameters directly into semantic calls
98
+ * (no local consts / module counters) so the resolver can statically track every
99
+ * argument. The characteristic index is carried through the chain via
100
+ * `this._charCount` fieldValues, mirroring how HttpRequest carries _method/_url.
101
+ */
102
+ export class BleClass {
103
+ static readonly __instance_name = "Ble";
104
+
105
+ /** Begin building a GATT server with the given advertised device name. */
106
+ server(name: string): BleServer {
107
+ bleSetName(name);
108
+ return new BleServer(name, 0, 1);
109
+ }
110
+
111
+ /** Initialize NimBLE, register services, and start advertising. */
112
+ begin(): void {
113
+ bleServerBegin("TypeCAD");
114
+ bleAdvertiseStart();
115
+ }
116
+
117
+ advertise(): void { bleAdvertiseStart(); }
118
+ stopAdvertising(): void { bleAdvertiseStop(); }
119
+
120
+ /** Blocking at top level; cooperatively awaitable inside async functions. */
121
+ untilConnected(timeoutMs: number = 0): Promise<boolean> {
122
+ bleUntilConnected(timeoutMs);
123
+ return Promise.resolve(false);
124
+ }
125
+
126
+ untilConnectedStart(): void { bleUntilConnectedStart(); }
127
+ isConnected(): boolean { return bleIsConnected(); }
128
+ status(): BleStatus { return bleStatus() as BleStatus; }
129
+ clientCount(): number { return bleClientCount(); }
130
+ txPower(dbm: number): this { bleSetTxPower(dbm); return this; }
131
+ notify(index: number, value: number): void { bleNotify(index, value); }
132
+ }
133
+
134
+ /**
135
+ * Fluent GATT server builder. Returned by `Ble.server()`.
136
+ *
137
+ * Single-class fluent chain (like HttpRequest): characteristic() returns `this`,
138
+ * so onRead/onWrite/onSubscribe chain directly. The _charCount field tracks
139
+ * which characteristic slot the callbacks attach to.
140
+ *
141
+ * Field tracking (read by the transpiler resolver via ctor field assignment):
142
+ * _name — advertised device name
143
+ * _charCount — current characteristic index (the last characteristic() target)
144
+ * _svcCount — current service index
145
+ */
146
+ export class BleServer {
147
+ private _name: string;
148
+ private _charCount: number;
149
+ private _lastChar: number;
150
+ private _svcCount: number;
151
+
152
+ constructor(name: string, charCount: number, svcCount: number) {
153
+ this._name = name;
154
+ this._charCount = charCount;
155
+ this._lastChar = charCount;
156
+ this._svcCount = svcCount;
157
+ }
158
+
159
+ /** Add a characteristic by UUID, value type, and permissions.
160
+ * Combine permissions with `|`: `BlePerm.Read | BlePerm.Notify`.
161
+ * Returns this for chaining. */
162
+ characteristic(uuid: string, type: BleValueType, perms: number): this {
163
+ bleAddChar(this._charCount, uuid, type, perms, this._svcCount);
164
+ return this;
165
+ }
166
+
167
+ /** Begin a new service grouping. Subsequent characteristics attach to it. */
168
+ service(uuid: string): this {
169
+ bleAddService(uuid);
170
+ return this;
171
+ }
172
+
173
+ /** Register a read handler for the most recently added characteristic. */
174
+ onRead(handler: () => CharValue): this {
175
+ bleOnRead(this._lastChar, callback(handler));
176
+ return this;
177
+ }
178
+
179
+ /** Register a write handler for the most recently added characteristic. */
180
+ onWrite(handler: (value: number) => void): this {
181
+ bleOnWrite(this._lastChar, callback(handler));
182
+ return this;
183
+ }
184
+
185
+ /** Register a connect handler (called when a central connects). */
186
+ onConnect(handler: () => void): this {
187
+ bleOnConnect(callback(handler));
188
+ return this;
189
+ }
190
+
191
+ /** Register a disconnect handler (called when a central disconnects). */
192
+ onDisconnect(handler: () => void): this {
193
+ bleOnDisconnect(callback(handler));
194
+ return this;
195
+ }
196
+
197
+ /** Push a new value to subscribed clients on the most recently added characteristic. */
198
+ notify(value: number): void {
199
+ bleNotify(this._lastChar, value);
200
+ }
201
+
202
+ /** Initialize NimBLE, register services, and start advertising. */
203
+ begin(): void {
204
+ bleServerBegin(this._name);
205
+ bleAdvertiseStart();
206
+ }
207
+ }
208
+
209
+ export const Ble = new BleClass();
@@ -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; }