@apocaliss92/nodelink-js 0.4.28 โ†’ 0.4.30

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 CHANGED
@@ -39,27 +39,34 @@ await api.onSimpleEvent((event) => {
39
39
 
40
40
  ## Email Push for Battery Cameras
41
41
 
42
- > ๐Ÿงช **Experimental** โ€” the feature is officially enabled but still under active testing. The default flow uses the manager's built-in SMTP server; expect rough edges and please report any issue you hit.
43
-
44
- Battery cameras (Argus, Go, โ€ฆ) can't reliably keep a TCP/ONVIF push subscription alive while sleeping. The manager app embeds an SMTP server so the camera can deliver motion alerts via email โ€” the most resilient path for sleep-heavy devices.
42
+ Battery cameras (Argus, Go, โ€ฆ) can't reliably keep a TCP/ONVIF push subscription alive while sleeping. The library ships an embedded SMTP intake (`createEmailPushServer`) so cameras can deliver motion alerts via e-mail โ€” the most resilient path for sleep-heavy devices. Both the manager UI and the [Scrypted Reolink Native plugin](https://github.com/apocaliss92/scrypted-reolink-native) consume the same intake.
45
43
 
46
44
  **Flow**:
47
45
 
48
- 1. Enable the manager's built-in SMTP server (**Settings โ†’ Email Push**, default port `2525`). All settings (host, port, domain, auth) remain manually editable.
49
- 2. Each camera gets a unique recipient `cam-<id>@<domain>` (`emailPush.getCameraAddress`).
50
- 3. From the camera's **Email Push** tab in the manager UI (Camera Settings modal), click **Auto-configure** โ€” the manager pushes the right SMTP server, recipients and 24/7 schedule to the camera via Baichuan (`baichuan.setupEmailPushToManager`). You can also fill the fields by hand in the Reolink app: server = your manager `domain`, sender = `authUsername`, password = `authPassword`, port = `2525`, TLS off, receiver = `cam-<id>@<domain>`.
51
- 4. On motion, the camera sends an email. The manager parses it, classifies the trigger (people/vehicle/motion), saves the snapshot under `${DATA_PATH}/email-push/<cameraId>/`, and emits a synthetic motion event into the same bus used by native Baichuan push โ€” so MQTT, Home Assistant, Frigate, etc. see it transparently.
46
+ 1. Spin up the SMTP server. In the manager UI: **Settings โ†’ Email Push** (default port `2525`, random `nodelink-<hex>` + 18-byte base64url credentials auto-generated on first boot). Programmatic: `createEmailPushServer({ config, cameraResolver, logger })` from this package.
47
+ 2. Each camera is reachable at `cam-<cameraId>@<domain>`. The intake matches the recipient local-part against the consumer's `cameraResolver` callback to decide which camera owns the message.
48
+ 3. Configure the camera-side SMTP one of three ways:
49
+ - **Auto** โ€” manager: **Email Push** tab in the camera modal โ†’ *Auto-configure*. Scrypted: open the camera's Settings โ†’ **E-mail Push** group โ†’ *Auto-configure from Email Push Server*. Both call `setupEmailPushToManager` under the hood.
50
+ - **API** โ€” `await api.setupEmailPushToManager({ managerHost, managerPort, recipientLocalPart, domain, authUsername, authPassword, triggerTypes, attachmentType }, channel)`. The lib auto-wraps a bare username as `<user@domain>` so MAIL FROM stays RFC 5321 compliant.
51
+ - **Manual** โ€” fill the Reolink app form: server = manager LAN IP, port = `2525`, sender = `authUsername`, password = `authPassword`, TLS off, receiver = `cam-<id>@<domain>`.
52
+ 4. On motion, the camera sends an e-mail. The intake parses it, classifies the trigger (`MD` / `people` / `vehicle`), and emits an `EmailPushEvent` on the shared bus. Snapshots are kept in memory only (no disk persistence) โ€” they're forwarded to whatever per-event handler the consumer wires (MQTT image entities in the manager, `motionDetected` flip in the Scrypted plugin).
53
+
54
+ See [documentation/baichuan-api/email.md](./documentation/baichuan-api/email.md) for the full Baichuan API surface and [documentation/baichuan-api/time.md](./documentation/baichuan-api/time.md) for the related NTP / DST / system clock setters.
55
+
56
+ **Library entry points**:
52
57
 
53
- See [documentation/baichuan-api/email.md](./documentation/baichuan-api/email.md) for the full API and [documentation/baichuan-api/time.md](./documentation/baichuan-api/time.md) for the related NTP / DST / system clock setters.
58
+ - `createEmailPushServer({ config, cameraResolver, logger, loadTls? })` โ€” factory returning `{ start, stop, restart, updateConfig, getStatus }`
59
+ - `subscribeEmailPushEvents({ cameraId? | match?, channel? })` on a `ReolinkBaichuanApi` instance โ€” bridges per-camera SMTP events into the same `onSimpleEvent` stream native Baichuan push uses
60
+ - `getRecentEmailPushEvents(limit)` โ€” bounded in-memory ring buffer of accepted deliveries
61
+ - `setupEmailPushToManager(params, channel)` โ€” orchestrator: `setEmail` + `setEmailTask` + optional `testEmail`
62
+ - `getEmail`, `setEmail`, `testEmail`, `getEmailTask`, `setEmailTask` โ€” low-level Baichuan accessors
54
63
 
55
- **Key tRPC procedures**:
64
+ **Key manager tRPC procedures**:
56
65
 
57
66
  - `emailPush.status`, `emailPush.start/stop/restart`, `emailPush.updateSettings`
58
67
  - `emailPush.getCameraAddress`, `emailPush.listCameraAddresses`
59
- - `emailPush.recentEvents`, `emailPush.injectTestEvent`
60
- - `baichuan.getEmail`, `baichuan.setEmail`, `baichuan.testEmail`
61
- - `baichuan.getEmailTask`, `baichuan.setEmailTask`
62
- - `baichuan.setupEmailPushToManager` (one-shot orchestrator)
68
+ - `emailPush.recentEvents` (last 300, in-memory)
69
+ - `baichuan.setupEmailPushToManager`, `baichuan.getEmail/setEmail/testEmail`, `baichuan.getEmailTask/setEmailTask`
63
70
 
64
71
  ---
65
72
 
@@ -13204,6 +13204,7 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
13204
13204
  */
13205
13205
  subscribeEmailPushEvents(params) {
13206
13206
  const channel = params.channel ?? 0;
13207
+ const onEvent = params.onEvent;
13207
13208
  const matches = "match" in params ? params.match : (event) => event.cameraId === params.cameraId;
13208
13209
  const off = onEmailPushEvent((event) => {
13209
13210
  if (!matches(event)) return;
@@ -13219,6 +13220,15 @@ var ReolinkBaichuanApi = class _ReolinkBaichuanApi {
13219
13220
  timestamp: event.receivedAtMs
13220
13221
  });
13221
13222
  }
13223
+ if (onEvent) {
13224
+ try {
13225
+ onEvent(event);
13226
+ } catch (err) {
13227
+ this.logger.warn?.(
13228
+ `[ReolinkBaichuanApi] subscribeEmailPushEvents onEvent threw: ${err instanceof Error ? err.message : err}`
13229
+ );
13230
+ }
13231
+ }
13222
13232
  });
13223
13233
  return off;
13224
13234
  }
@@ -24723,4 +24733,4 @@ export {
24723
24733
  isTcpFailureThatShouldFallbackToUdp,
24724
24734
  autoDetectDeviceType
24725
24735
  };
24726
- //# sourceMappingURL=chunk-NQ7D5TLR.js.map
24736
+ //# sourceMappingURL=chunk-AZZKLRJV.js.map