Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,73 @@
## [6.0.0]

feat: Local control - devices answer signed commands over the LAN, so they keep working while SinricPro is unreachable.

* UDP listener on port 3333, joined to multicast group `224.9.9.9` and answering unicast on the same port. Replies go back to the peer that sent the request, never to the cloud websocket.
* mDNS announcement of `_sinricpro._udp.local.` (host `sinricpro-<mac>`, TXT `deviceIds`, `sdk`, `udp=1`), re-announced only when the device list changes. `bonjour-service` is a required dependency, so a default install announces without extra steps. Local control is on by default; set `localControl: false` to opt out.
* LAN requests are dispatched through the same capability callbacks as cloud requests - no application changes required.
* A request that fails signature verification is answered with a signed "Signature is invalid" response, so a client can tell a wrong app secret from an unreachable device.
* Disable with `localControl: false` (or `SINRICPRO_NO_LOCAL_CONTROL=1`); disable only the announcement with `mdns: false` (or `SINRICPRO_NOMDNS=1`).

fix: Messages are signed over the exact bytes that are transmitted; incoming signatures are verified against the received bytes rather than a re-encoding of the parsed message, and digests are compared in constant time.

fix: `instanceId` was added to the response payload after signing, which invalidated the signature of every response carrying one.

fix: The send queue is no longer gated on the cloud connection as a whole - each message is routed by its own origin, so a LAN reply goes out even when the websocket has never connected. The offline websocket backlog is now bounded.

fix: A websocket error no longer crashes the process when the application registered no `error` listener.

change: `begin()` no longer rejects when the cloud is unreachable. The SDK starts, retries in the background and keeps answering local control; only invalid configuration throws. Call `isConnected()` for cloud state. Callers that relied on `begin()` rejecting to detect an outage must check it instead.


| | |
|---|---|
| Transport | UDP port `3333`, multicast group `224.9.9.9`, unicast to the host on the same port |
| Discovery | mDNS service `_sinricpro._udp.local.`, host `sinricpro-<mac>`, TXT `deviceIds`, `sdk`, `udp=1` |
| Authentication | HMAC-SHA256 over the payload, keyed with your `APP_SECRET` |

### Discovery

Announcing over mDNS needs an optional peer dependency:

```bash
npm install bonjour-service
```

Without it, local control still works for a client that already knows the
device's address; only discovery is unavailable.

Check the announcement with:

```bash
avahi-browse -r _sinricpro._udp # Linux
dns-sd -B _sinricpro._udp # macOS / Windows
```

### Turning it off

```typescript
await SinricPro.begin({
appKey: 'YOUR-APP-KEY',
appSecret: 'YOUR-APP-SECRET',
localControl: false, // no UDP listener, no mDNS
mdns: false, // keep the UDP listener, do not announce
});
```

The environment variables `SINRICPRO_NO_LOCAL_CONTROL=1` and `SINRICPRO_NOMDNS=1`
do the same without touching code.

### Notes

- A request whose signature does not verify is answered with a signed
"Signature is invalid" response rather than silence, so a client can tell a
wrong secret from an unreachable device.
- An Android client needs a `WifiManager.MulticastLock` and an iOS client needs
`_sinricpro._udp` in `NSBonjourServices`, or mDNS returns nothing at all.
- On a host with several interfaces (Docker, VPN, WSL), the multicast group is
joined on every non-internal IPv4 interface; the join outcome is logged.


## [5.2.0]

feat: Send a device setting event to SinricPro
Expand Down
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Official SinricPro SDK for Node.js and TypeScript. Control your IoT devices with
- ✅ Modern async/await API
- ✅ WebSocket with automatic reconnection
- ✅ HMAC-SHA256 authentication
- ✅ Local control over the LAN (works while SinricPro is unreachable)
- ✅ Event rate limiting
- ✅ Multiple device types (Switch, Light, Thermostat, etc.)
- ✅ Comprehensive error handling
Expand Down Expand Up @@ -95,6 +96,48 @@ ts-node app.ts

---

## 🏠 Local Control

Devices also answer signed commands over the local network, so they keep working
while SinricPro is unreachable. It is on by default and needs no application
changes: a LAN request runs the same callbacks as a cloud request. UDP listener on port `3333`, joined to multicast group `224.9.9.9` and answering unicast on the same port. Replies go back to the peer that sent the request, never to the cloud websocket.

The mDNS announcement uses `bonjour-service`, installed with the SDK:

```bash
npm install sinricpro
```

---

## Troubleshooting

### Connection Issues

1. **Check credentials** - Ensure APP_KEY and APP_SECRET are correct
2. **Check device ID** - Verify the device ID is exactly 24 hexadecimal characters
3. **Check network** - Ensure you have internet connectivity
4. **Enable debug logging** -

```js
import { SinricProSdkLogger, LogLevel } from 'sinricpro';
SinricProSdkLogger.setLevel(LogLevel.DEBUG); // DEBUG, INFO, WARN, ERROR, NONE
```


### Local Control Issues

1. **No device found on the LAN** - check the log for
`Local control listening on UDP 3333`. A failed multicast join leaves nothing
listening, and the log line says so.
2. **No mDNS record** - install the extra: `pip install sinricpro[mdns]`.
3. **Discovery answers on the wrong network** - set `local_control_interface` to the
LAN address of the host.
4. **Android clients need a `WifiManager.MulticastLock`**, and iOS clients need
`_sinricpro._udp` listed in `NSBonjourServices`, or discovery returns nothing.

---

## 🤝 Contributing

Contributions welcome! Please:
Expand Down
62 changes: 62 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v3.0.0.html).

## [1.0.0] - 2024-XX-XX

### Added
- Initial release of SinricPro SDK for Node.js and TypeScript
- Core SDK infrastructure with WebSocket communication
- HMAC-SHA256 authentication
- Event rate limiting
- Device types:
- SinricProSwitch
- SinricProLight
- SinricProThermostat
- Capability controllers:
- PowerStateController
- BrightnessController
- ColorController
- ColorTemperatureController
- TemperatureSensor
- Full TypeScript support with type definitions
- Async/await API
- Automatic reconnection
- Comprehensive examples (Switch, Light, Thermostat)
- Unit tests with Jest
- Complete documentation
- Migration guide from C++ SDK

### Features
- ✅ WebSocket connection with SSL/TLS
- ✅ Automatic message signing
- ✅ Event-driven architecture
- ✅ EventEmitter-based pub/sub
- ✅ Composable capability mixins
- ✅ Strong typing with TypeScript
- ✅ Error handling and logging
- ✅ Heartbeat/ping-pong
- ✅ Device state restoration

### Documentation
- README with quick start guide
- API documentation
- Migration guide from C++ SDK
- Example applications
- TypeScript type definitions

## [Unreleased]

### Planned
- UDP multicast support
- Additional device types (Fan, TV, Lock, Camera)
- Additional capabilities (Media, Volume, Thermostat modes)
- OTA update support
- Module-level commands
- Health reporting
- Browser compatibility layer
- Performance optimizations
- Additional examples
Loading
Loading