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: 4 additions & 1 deletion .github/workflows/check-copilot-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,14 @@ jobs:
uses: actions/github-script@v9
with:
script: |
// Setup issues are labelled copilot-setup and update issues template-update, both carry
// automation. Filtering on both labels never matched the update issues, so a new one was
// opened every week.
const { data: issues } = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'copilot-setup,automation'
labels: 'automation'
});

const setupIssues = issues.filter(issue =>
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/test-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ on:
- 'v[0-9]+.[0-9]+.[0-9]+-**'
pull_request: {}

# Cancel previous PR/branch runs when a new commit is pushed.
# Release runs (tag pushes) are never cancelled - cancelling them aborts the deploy job and
# leaves the release half finished, which the ioBroker repo checker reports as W3032.
# Cancel previous runs for the same ref when a new commit is pushed (repo checker W3009).
# A release tag is its own ref, so a release run is only cancelled if that same tag is pushed again.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ !startsWith(github.ref, 'refs/tags/') }}
group: ${{ github.ref }}
cancel-in-progress: true

# Restrict the default GITHUB_TOKEN to read-only; the deploy job widens this for itself.
permissions:
Expand Down Expand Up @@ -51,7 +50,7 @@ jobs:
# otherwise a single flaky OS/node combination hides all other results
fail-fast: false
matrix:
node-version: [22.x, 24.x]
node-version: [22.x, 24.x, 26.x]
os: [ubuntu-latest, windows-latest, macos-latest]

steps:
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,12 @@ When the adapter crashes or another Code error happens, this error message that
* (DutchmanNL) **CI/CD**: Fixed deployment failure by adding missing sentry-version-prefix parameter to GitHub Actions workflow
* (DutchmanNL) **CI/CD**: Updated GitHub Copilot instructions template from v0.4.2 to v0.5.6 - adds ESLint configuration, translation management, lint-first CI/CD workflow guidance
* (DutchmanNL) Dependencies updated to current versions
* (arteck) **FIXED**: The `_online` state of a device that cannot be reached is written as boolean `false` again instead of a text, which logged "has to be type boolean but received type string" ([#788](https://github.com/DrozmotiX/ioBroker.wled/issues/788), [#794](https://github.com/DrozmotiX/ioBroker.wled/issues/794), [#792](https://github.com/DrozmotiX/ioBroker.wled/pull/792))
* (DutchmanNL) **FIXED**: A device that stays offline logs "Unable to initialise" as a warning once, further attempts are logged at debug level ([#788](https://github.com/DrozmotiX/ioBroker.wled/issues/788))
* (DutchmanNL) **FIXED**: Devices that are offline can be deleted from the instance settings again ([#787](https://github.com/DrozmotiX/ioBroker.wled/issues/787))
* (DutchmanNL) **ENHANCED**: Tests now also run on Node.js 26 ([#872](https://github.com/DrozmotiX/ioBroker.wled/issues/872))
* (DutchmanNL) **ENHANCED**: Updated @iobroker/testing to 6.3.0
* (DutchmanNL) Removed a broken README link ([#876](https://github.com/DrozmotiX/ioBroker.wled/issues/876))

### 0.9.2 (2026-02-16)
* (DutchmanNL) solve auto deployment issues
Expand Down Expand Up @@ -186,11 +192,7 @@ When the adapter crashes or another Code error happens, this error message that

This adapter uses GitHub Actions with **NPM Trusted Publishing** for automated deployment.

For maintainers troubleshooting deployment issues, see [docs/DEPLOYMENT_SETUP.md](docs/DEPLOYMENT_SETUP.md) for:
- Verifying trusted publishing configuration on npmjs.com
- Required workflow and job name settings
- Troubleshooting authentication errors
- Testing deployment with pre-release versions
Releases are published by the `deploy` job of `.github/workflows/test-and-release.yml` when a version tag is pushed. The npm package must list this repository and that workflow as a trusted publisher on npmjs.com, no `NPM_TOKEN` secret is needed. See the [npm trusted publishing documentation](https://docs.npmjs.com/trusted-publishers) for setup and troubleshooting.

## License
MIT License
Expand Down
35 changes: 25 additions & 10 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -528,13 +528,13 @@
this.log.debug(`Delete device request received for IP: ${deviceIP}`);

try {
// Find device ID by IP address
let deviceId = null;
for (const ip in this.devices) {
if (ip === deviceIP) {
deviceId = this.devices[ip].name;
break;
}
// Find device ID (MAC address) by IP address. A device that is offline since
// adapter start may be missing from the devices array, so check the object tree as well
let deviceId = this.devices[deviceIP]?.mac || null;
if (!deviceId) {
const knownDevices = await this.getDevicesAsync();
const knownDevice = knownDevices.find(device => device.native?.ip === deviceIP);
deviceId = knownDevice?.native?.mac || null;
}

if (deviceId) {
Expand Down Expand Up @@ -1381,18 +1381,33 @@
}

if (!deviceData) {
this.log.warn(`Unable to initialise ${deviceIP} will retry in scheduled interval !`);
if (!this.devices[deviceIP]) {
// Manually added IP that does not answer, nothing to update yet
this.log.warn(`Unable to initialise ${deviceIP}, device does not respond`);
return 'failed';
}
// Warn once per outage, further attempts of a device that stays offline are logged as debug
if (!this.devices[deviceIP].offlineWarned) {
this.log.warn(`Unable to initialise ${deviceIP} will retry in scheduled interval !`);
this.devices[deviceIP].offlineWarned = true;
} else {
this.log.debug(`Unable to initialise ${deviceIP} will retry in scheduled interval !`);
}
this.devices[deviceIP].initialized = false;
this.devices[deviceIP].connected = false;
// Update device working state
if (this.devices[deviceIP].mac != null) {
await this.create_state(
`${this.devices[deviceIP].mac}._info` + `._online`,
'Online status',
{ val: false, ack: true },
false,
);
}
return 'failed';
}
if (this.devices[deviceIP]) {
this.devices[deviceIP].offlineWarned = false;
}
this.log.debug(`Info Data received from WLED device ${JSON.stringify(deviceData)}`);
this.log.info(`Initialising : " ${deviceData.info.name}" on IP : ${deviceIP}`);
await this.handleBasicStates(deviceIP, deviceData);
Expand Down Expand Up @@ -1646,7 +1661,7 @@
* Wrapper for error handling
*
* @param {string} source Message to send
* @param {any} error Error message (including stack) to handle exceptions

Check warning on line 1664 in main.js

View workflow job for this annotation

GitHub Actions / check-and-lint

Prefer a more specific type to `any`
* @param {boolean=} debugMode - Error message (including stack) to handle exceptions
*/
errorHandler(source, error, debugMode) {
Expand Down Expand Up @@ -1766,7 +1781,7 @@
this.cleanupDeviceBackend(ip, mac);
}

const name = deviceId.replace(/wled\.\d\./, '');
const name = deviceId.replace(/^wled\.\d+\./, '');
const res = await this.deleteDeviceAsync(name);
if (res !== null) {
this.log.info(`${name} deleted`);
Expand Down
Loading
Loading