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
5 changes: 2 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ jobs:

# Only run this job if initiator is not the Homey Github Actions Bot to prevent loops and check if if a version bump is provided and current branch is production or testing
if: github.actor != 'homey-bot'
&& (github.ref == 'refs/heads/production' || github.ref == 'refs/heads/testing')
&& (github.event.inputs.versionBumpType == 'patch' || github.event.inputs.versionBumpType == 'minor' || github.event.inputs.versionBumpType == 'major' || contains(github.event.head_commit.message, '#patch') || contains(github.event.head_commit.message, '#minor') || contains(github.event.head_commit.message, '#major'))
&& (github.ref == 'refs/heads/production' || github.ref == 'refs/heads/testing')
&& (github.event.inputs.versionBumpType == 'patch' || github.event.inputs.versionBumpType == 'minor' || github.event.inputs.versionBumpType == 'major' || contains(github.event.head_commit.message, '#patch') || contains(github.event.head_commit.message, '#minor') || contains(github.event.head_commit.message, '#major'))

runs-on: ubuntu-latest

Expand All @@ -47,7 +47,6 @@ jobs:
id-token: write

steps:

# Checks out the current repository.
- name: Checkout git repository
uses: actions/checkout@v4
Expand Down
40 changes: 20 additions & 20 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,30 @@ name: Deploy Documentation To GitHub Pages

on:
push:
branches: [ production ]
branches: [production]
workflow_dispatch:

jobs:
deploy:
name: Build & Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc

# Build
- name: Build
run: |
npm ci
npm run build

# Deploy
- name: Deploy To GitHub Pages
uses: peaceiris/actions-gh-pages@v3.8.0
with:
personal_token: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }}
publish_dir: ./build
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc

# Build
- name: Build
run: |
npm ci
npm run build

# Deploy
- name: Deploy To GitHub Pages
uses: peaceiris/actions-gh-pages@v3.8.0
with:
personal_token: ${{ secrets.HOMEY_GITHUB_ACTIONS_BOT_PERSONAL_ACCESS_TOKEN }}
publish_dir: ./build
14 changes: 7 additions & 7 deletions .github/workflows/generate-types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ on:
- production
- testing
paths:
- "lib/clusters/**/*.js"
- "scripts/generate-types.mts"
- "scripts/template.d.ts.txt"
- "index.js"
- "lib/Cluster.js"
- "lib/constants.js"
- 'lib/clusters/**/*.js'
- 'scripts/generate-types.mts'
- 'scripts/template.d.ts.txt'
- 'index.js'
- 'lib/Cluster.js'
- 'lib/constants.js'
workflow_dispatch:

jobs:
Expand All @@ -32,7 +32,7 @@ jobs:
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: "npm"
cache: 'npm'

- name: Install dependencies
run: npm ci
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ jobs:
name: Lint
runs-on: ubuntu-latest
steps:

# Checks out the current repository.
- uses: actions/checkout@v4

Expand All @@ -34,3 +33,5 @@ jobs:
- run: npm ci

- run: npm run lint

- run: npm run format:check
7 changes: 7 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
build
index.d.ts
*.pdf
.claude

# Literal formatting is the content here, and Prettier mangles the M* emphasis markers.
AGENTS.md
3 changes: 1 addition & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 100,
"plugins": ["prettier-plugin-jsdoc"]
"printWidth": 100
}
26 changes: 16 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ const COMMANDS = {
// --- Client to Server Commands ---

// Description from spec.
commandName: { // Mandatory
// Mandatory
commandName: {
id: 0x0000,
args: {
argName: ZCLDataTypes.uint8,
Expand All @@ -186,7 +187,8 @@ const COMMANDS = {
// --- Server to Client Commands ---

// Description from spec.
notificationName: { // Optional
// Optional
notificationName: {
id: 0x0020, // 32
direction: Cluster.DIRECTION_SERVER_TO_CLIENT,
args: {
Expand Down Expand Up @@ -224,11 +226,13 @@ module.exports = ExampleCluster;
1. **Description placement**: ABOVE the attribute/command
2. **M/O marker placement**:
- Single-line: at END of line (`attrName: { ... }, // Mandatory`)
- Multi-line: on OPENING brace (`attrName: { // Mandatory`)
- Multi-line: on its own line ABOVE the key (`// Mandatory` then `attrName: {`),
below the description if there is one. Not on the opening brace: Prettier pulls a
comment there inside the braces, where it reads as if it belongs to `id`.
- NEVER on closing brace
3. **Copy exactly**: Text from spec, 1-on-1
4. **Skip if >5 sentences**: Skip and only refer to section in spec
5. **Line wrap**: Respect 100 char limit (ESLint)
5. **Line wrap**: Respect 100 char limit (Prettier `printWidth`); run `npm run format:write`
6. **M/O source for attrs**: Server-side column in spec table
7. **M/O source for cmds**:
- Server "receives" → server-side M/O
Expand All @@ -252,15 +256,15 @@ pirUnoccupiedToOccupiedDelay: { id: 0x0011, type: ZCLDataTypes.uint16 }, // 17,

| Field | Format | Notes |
|-------|--------|-------|
| `id` | Hex (`0x0000`) | Always 4-digit format (0x0000); add decimal comment if > 9 |
| `id` | Hex (`0x0000`) | Always 4-digit format (0x0000), lowercase digits; add decimal comment if > 9 |
| `type` | `ZCLDataTypes.*` | See type reference below |
| M/O | Inline comment | `// Mandatory`, `// Optional`, or `// Conditional` |

#### Hex with Decimal Comments

For hex values > 9 (where hex differs from decimal), add decimal in comment:
```javascript
id: 0x000A, // 10
id: 0x000a, // 10
id: 0x0010, // 16
id: 0x0100, // 256
```
Expand All @@ -271,9 +275,10 @@ id: 0x0000,
id: 0x0009,
```

For multi-line definitions, decimal goes on the `id:` line, M/O on opening brace:
For multi-line definitions, decimal goes on the `id:` line, M/O above the key:
```javascript
operatingMode: { // Optional
// Optional
operatingMode: {
id: 0x0025, // 37
type: ZCLDataTypes.enum8({
normal: 0,
Expand All @@ -300,7 +305,7 @@ attr3: { ... },

| Field | Required | Notes |
|-------|----------|-------|
| `id` | Yes | Always 4-digit hex format (0x0000); add decimal comment if > 9 |
| `id` | Yes | Always 4-digit hex format (0x0000), lowercase digits; add decimal comment if > 9 |
| `args` | If has params | Object with typed fields |
| `response` | If expects response | Has own `id` and `args` |
| `encodeMissingFieldsBehavior` | Controls the behavior of missing fields when encoding the struct | Set to `skip` if some fields are optional, omit if all fields are mandatory |
Expand All @@ -313,7 +318,8 @@ attr3: { ... },
lockDoor: { id: 0x0000, ... }, // Mandatory

// --- Server to Client Commands ---
operationEventNotification: { // Optional
// Optional
operationEventNotification: {
id: 0x0020, // 32
direction: Cluster.DIRECTION_SERVER_TO_CLIENT,
...
Expand Down
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ v2.0.0
- Changed `Cluster.readAttributes` signature, attributes must now be specified as an array of strings.

```js
zclNode.endpoints[1].clusters.basic.readAttributes(["modelId", "manufacturerName"]);
zclNode.endpoints[1].clusters.basic.readAttributes(['modelId', 'manufacturerName']);
```

## Release
Expand Down Expand Up @@ -70,8 +70,8 @@ In order to communicate with a Zigbee node retrieve a `node` instance from `Mana
`/drivers/my-driver/device.js`

```js
const Homey = require("homey");
const { ZCLNode, CLUSTER } = require("zigbee-clusters");
const Homey = require('homey');
const { ZCLNode, CLUSTER } = require('zigbee-clusters');

class MyDevice extends Homey.Device {
onInit() {
Expand Down Expand Up @@ -101,7 +101,7 @@ class MyDevice extends Homey.Device {
// timeout (10000ms) before the command is considered rejected.
// The timeout starts after sending the frame and receiving a low-level ack.
timeout: 5000,
}
},
);
});
}
Expand All @@ -113,8 +113,8 @@ class MyDevice extends Homey.Device {
`/drivers/my-driver/device.js`

```js
const Homey = require("homey");
const { ZCLNode, CLUSTER } = require("zigbee-clusters");
const Homey = require('homey');
const { ZCLNode, CLUSTER } = require('zigbee-clusters');

class MyDevice extends Homey.Device {
onInit() {
Expand All @@ -134,10 +134,10 @@ class MyDevice extends Homey.Device {

// And listen for incoming attribute reports by binding a listener on the cluster
zclNode.endpoints[1].clusters[CLUSTER.COLOR_CONTROL.NAME].on(
"attr.currentSaturation",
'attr.currentSaturation',
(currentSaturation) => {
// handle reported attribute value
}
},
);
});
}
Expand Down Expand Up @@ -181,7 +181,7 @@ class OnOffCluster extends Cluster {
}

static get NAME() {
return "onOff"; // The cluster name
return 'onOff'; // The cluster name
}

static get ATTRIBUTES() {
Expand Down Expand Up @@ -214,7 +214,7 @@ Zigbee nodes can send commands to Homey via bound clusters. This requires a bind
`/lib/LevelControlBoundCluster.js`

```js
const { BoundCluster } = require("zigbee-clusters");
const { BoundCluster } = require('zigbee-clusters');

class LevelControlBoundCluster extends BoundCluster {
constructor({ onMove }) {
Expand All @@ -237,7 +237,7 @@ module.exports = LevelControlBoundCluster;
`/drivers/my-driver/device.js`

```js
const LevelControlBoundCluster = require("../../lib/LevelControlBoundCluster");
const LevelControlBoundCluster = require('../../lib/LevelControlBoundCluster');

// Register the `BoundCluster` implementation with the `ZCLNode`
zclNode.endpoints[1].bind(
Expand All @@ -246,7 +246,7 @@ zclNode.endpoints[1].bind(
onMove: (payload) => {
// Do something with the received payload
},
})
}),
);
```

Expand All @@ -257,7 +257,7 @@ There are cases where it is required to implement a custom cluster, for example
`lib/IkeaSpecificSceneCluster.js`

```js
const { ScenesCluster, ZCLDataTypes } = require("zigbee-clusters");
const { ScenesCluster, ZCLDataTypes } = require('zigbee-clusters');

class IkeaSpecificSceneCluster extends ScenesCluster {
// Here we override the `COMMANDS` getter from the `ScenesClusters` by
Expand Down Expand Up @@ -299,14 +299,14 @@ module.exports = IkeaSpecificSceneCluster;
`/drivers/my-driver/device.js`

```js
const IkeaSpecificSceneCluster = require("../../lib/IkeaSpecificSceneCluster");
const IkeaSpecificSceneCluster = require('../../lib/IkeaSpecificSceneCluster');

// Important: we have created a new `Cluster` instance which needs to be added before
// it becomes available on any `ZCLNode` instance.
Cluster.addCluster(IkeaSpecificSceneCluster);

// Example invocation of custom cluster command
zclNode.endpoints[1].clusters["scenes"].ikeaSceneMove({ mode: 0, transitionTime: 10 });
zclNode.endpoints[1].clusters['scenes'].ikeaSceneMove({ mode: 0, transitionTime: 10 });
```

This also works for `BoundClusters`, if a node sends commands to Homey using a custom cluster it is necessary to implement a custom `BoundCluster` and bind it to the `ZCLNode` instance. For an example check the implementation in the `com.ikea.tradfri` driver [remote_control](https://github.com/athombv/com.ikea.tradfri-example/tree/master/drivers/remote_control/device.js).
Expand All @@ -328,6 +328,7 @@ This runs `scripts/generate-types.js` which loads all cluster modules and genera
### Automatic Generation (GitHub Actions)

TypeScript types are automatically regenerated when changes are pushed to the `develop` branch that affect:

- `lib/clusters/**/*.js` - cluster definitions
- `scripts/generate-types.js` - the generator script

Expand Down
5 changes: 1 addition & 4 deletions docs/jsdoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
"readme": "./README.md",
"destination": "./build"
},
"plugins": [
"jsdoc-ts-utils",
"plugins/markdown"
],
"plugins": ["jsdoc-ts-utils", "plugins/markdown"],
"templates": {
"default": {
"outputSourceFiles": false
Expand Down
6 changes: 1 addition & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,7 @@ function debug(flag = true, namespaces = '*') {
_debug.disable();
}

const {
ZCLDataTypes,
ZCLDataType,
ZCLStruct,
} = zclTypes;
const { ZCLDataTypes, ZCLDataType, ZCLStruct } = zclTypes;

const { ZIGBEE_PROFILE_ID, ZIGBEE_DEVICE_ID, IAS_ZONE_TYPE } = require('./lib/constants');

Expand Down
Loading
Loading