Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 8, 2025

  • Refactor to intelligent restart detection
  • Support EditableZWaveOptions for hot updates
  • Add dedicated restart API endpoint
  • Show restart dialog only when needed
  • Fix: Only check changed properties for restart detection
  • Limit editable options to user-configurable settings
  • Add proper mapping from settings to PartialZWaveOptions
  • Move utility functions to utils.ts for code reuse
  • Improve buildLogConfig to accept full config and include filename/forceConsole
  • Add clarifying comment for editable settings mapping
  • Lint and build successfully

Summary

Added a clarifying comment explaining how ZwaveClient configuration properties map to the corresponding driver.updateOptions() parameters. This helps future maintainers understand the relationship between our UI settings and the driver API.

Changes Made

Backend (api/app.ts)

Added Documentation Comment:

  • Clarified that the listed properties are ZwaveClient configuration settings
  • Explained the mapping to driver.updateOptions() parameters:
    • scalespreferences.scales
    • Log properties (logEnabled, logLevel, etc.) → logConfig object
    • disableOptimisticValueUpdate → direct mapping
  • Helps developers understand why these specific properties can be updated without restart

Benefits

  • ✅ Better code documentation
  • ✅ Clearer understanding of the settings-to-driver mapping
  • ✅ Easier maintenance for future developers
  • ✅ Explains the commented inline annotations

Testing

  • ✅ All existing tests pass (52 tests)
  • ✅ Linting successful
  • ✅ Build successful
Original prompt

This section details on the original issue you should resolve

<issue_title>Save button without restarting</issue_title>
<issue_description>Hi,

Each time the configuration is changed, the application restarts. Sometimes we just want to change a setting without it being active right away.

Is it possible to add a button to simply save without restarting and give us the option to restart the application manually?
</issue_description>

<agent_instructions>In Settings.vue, when users press on save, show a confirmation dialog with a checkbox (checked by default) that ask user if he also want to restart zwave-js driver, if unchecked the request should only update settings json without restarting client</agent_instructions>

Comments on the Issue (you are @copilot in this section)

@robertsLando I'm not sure I want this, most changes require a restart and I think this could lead to unexpected behaviours.

@AlCalzone opinion?</comment_new>

Fixes #4410

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@coveralls
Copy link

coveralls commented Oct 8, 2025

Pull Request Test Coverage Report for Build 18876306141

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 15 of 242 (6.2%) changed or added relevant lines in 4 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.1%) to 20.178%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/apis/ConfigApis.js 0 4 0.0%
api/lib/ZwaveClient.ts 0 5 0.0%
api/lib/utils.ts 15 46 32.61%
api/app.ts 0 187 0.0%
Totals Coverage Status
Change from base Build 18715718057: -0.1%
Covered Lines: 4048
Relevant Lines: 21271

💛 - Coveralls

Copilot AI changed the title [WIP] Add save button to update settings without restart feat(settings): add option to save without restarting Z-Wave JS driver Oct 8, 2025
Copilot AI requested a review from robertsLando October 8, 2025 14:27
Copilot finished work on behalf of robertsLando October 8, 2025 14:27
Copilot AI requested a review from robertsLando October 8, 2025 14:58
Copilot finished work on behalf of robertsLando October 8, 2025 14:58
Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check for other ConfigApis.updateConfig calls codewise and ensure them are compatible with new format

@robertsLando
Copy link
Member

@copilot fix

Copy link
Contributor Author

Copilot AI commented Oct 8, 2025

@copilot fix

Fixed in commit c5e9d3a. Found one incompatible call in src/App.vue:1004 where restart() was calling updateConfig(false). Changed it to updateConfig(null) to properly pass null data and use the default restart=true parameter. All three usages are now compatible with the new { restart, data } format.

Copilot AI requested a review from robertsLando October 8, 2025 15:08
Copilot finished work on behalf of robertsLando October 8, 2025 15:08
if (result.valid) {
try {
// Show confirmation dialog with restart option
const restartOptions = await this.app.confirm(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely know which settings can be changed without restarting (EditableZWaveOptions). Shouldn't we compare against that list somewhere?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Refactor the PR in this way:

  1. The user calls ConfigApis.updateConfig, no prompt is show at this point to ask for restart.
  2. Backend checks what changed, if something on gateway settings changed set shouldRestart to true, if something on zwave settings changes check if it matches properties of EditableZWaveOptions, if so instead of restarting everything only update driver settings using driver.updateOptions API, if something on zniffer set shouldRestart to true
  3. The API call should then return also shouldRestart that is true/false, when this is true then ask the user if he want to restart the gw or not with the dialog that you created in actual implementation
  4. If user checks the restart box restart the gw using the dedicated API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored in commit e7f4a91. The implementation now:

  1. No upfront prompt - User calls updateConfig, settings are saved immediately
  2. Intelligent restart detection:
    • Gateway/MQTT changes → shouldRestart = true
    • Zniffer changes → shouldRestart = true
    • Z-Wave editable options (matching EditableZWaveOptions) → uses driver.updateOptions(), no restart
    • Other Z-Wave changes → shouldRestart = true
  3. Response includes shouldRestart flag indicating if restart is needed
  4. Conditional dialog - Only shows restart prompt if shouldRestart === true
  5. Dedicated restart endpoint - /api/restart called when user confirms

The editable Z-Wave options that can be updated without restart: attempts, disableOptimisticValueUpdate, emitValueUpdateAfterSetValue, inclusionUserCallbacks, joinNetworkUserCallbacks, interview, logConfig, preferences, vendor, userAgent.

Copilot AI changed the title feat(settings): add option to save without restarting Z-Wave JS driver feat(settings): intelligent restart with hot-reload for editable Z-Wave options Oct 10, 2025
Copilot finished work on behalf of robertsLando October 10, 2025 09:40
Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Well done. Fix what highlighted in my review and it should be good to go

api/app.ts Outdated
Comment on lines 1167 to 1170
const zwaveKeys = Object.keys(settings.zwave || {})
const onlyEditableChanged = zwaveKeys.every((key) =>
editableZWaveProps.includes(key),
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mind that here you always get ALL settings so you should check which settings changed and which not

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit a3b4c7d. The code now:

  1. Identifies which Z-Wave properties actually changed by comparing against actualSettings.zwave
  2. Only evaluates the changed properties against the EditableZWaveOptions list
  3. When calling driver.updateOptions(), only passes properties that actually changed
  4. Improved logging to show which specific options were updated

This ensures unchanged properties don't trigger unnecessary restarts or get passed to the driver update API.

Copilot finished work on behalf of robertsLando October 15, 2025 16:08
Copy link
Member

@robertsLando robertsLando left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot fix review

nodeFilter: this.cfg.nodeFilter,
}),
filename: ZWAVEJS_LOG_FILE,
forceConsole: isDocker() ? !this.cfg.logToFile : false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forceConsole depends from logToFile so that should be included as well in buildLogConfig and also filename

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit a7b9c4d. Added optional filename and forceConsole parameters to buildLogConfig(). Both are now included in the returned logConfig object when provided. Updated ZwaveClient to pass these values when calling the function.

api/lib/utils.ts Outdated
Comment on lines 512 to 518
export function buildLogConfig(config: {
logEnabled?: boolean
logLevel?: string
logToFile?: boolean
maxFiles?: number
nodeFilter?: string[]
}) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make config type of zwaveconfig so you don't have to specify all those props but we can just pass the entire config

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in commit a7b9c4d. Changed buildLogConfig() to accept the full config object (using DeepPartial for type safety) instead of individual properties. Both app.ts and ZwaveClient.ts now pass the entire config object, making the code cleaner and more maintainable.

@robertsLando
Copy link
Member

@copilot fix review

Copy link
Contributor Author

Copilot AI commented Oct 16, 2025

@copilot fix review

All checks pass successfully:

  • ✅ Linting: No errors
  • ✅ Tests: All 52 tests passing
  • ✅ Build: Successful

All previous review comments have been addressed. If there are specific issues or new review comments that need attention, please let me know what needs to be fixed.

Copilot finished work on behalf of robertsLando October 16, 2025 09:40
Comment on lines +2690 to +2706
const restartConfirm = await this.app.confirm(
'Restart Required',
'Do you want to restart the Z-Wave JS driver to apply the changes?',
'info',
{
width: 500,
inputs: [
{
type: 'checkbox',
key: 'restart',
label: 'Restart Z-Wave JS driver',
default: true,
hint: 'Changes require a restart to take effect. Uncheck to restart manually later.',
},
],
},
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would a modal dialog with 3 buttons be simpler here?
[CANCEL] [SAVE] [SAVE and RESTART]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hummm not sure, that would require a single click and could be easier to click the wrong button?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't feel strongly either way, but this is already a confirmation dialog for pressing the save button, so it's not super easy to open accidentally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep it like this for now 🙏🏼

Copilot finished work on behalf of robertsLando October 20, 2025 10:30
@robertsLando robertsLando merged commit d574d8b into master Oct 28, 2025
7 of 11 checks passed
@robertsLando robertsLando deleted the copilot/add-save-settings-without-restart branch October 28, 2025 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Save button without restarting

4 participants