node-zwave-js/docs/getting-started/migrating/v13.md

149 lines
11 KiB
Markdown

# Migrating to v13 <!-- {docsify-ignore-all} -->
As part of the ongoing efforts towards Z-Wave certification, I've found an issue in our `Meter CC` implementation that required a breaking change. Therefore I've collected a few other changes that would be breaking and decided to bundle them all into a major release.
## Changes to the `Meter CC` implementation
It has been found that the encoding of the Meter CC Reset command in version 6 was different from the specification. As a result, the `MeterCCResetOptions` type had to be changed, because all 4 fields are required to send a V6 command:
```ts
type: number;
scale: number;
rateType: RateType;
targetValue: number;
```
This also means calls to `MeterCCAPI.reset(options: MeterCCResetOptions)` need to be updated.
In addition, the `reset` values for single meters now refer to a combination of meter type/scale/rate type and are only created for **accumulated** scales, since others cannot be reset. This will leave some orphaned values that need a re-interview to be removed.
## Moved several Z-Wave specific definitions out of the `ConfigManager`
Historically the `ConfigManager` was used to parse Z-Wave specific definitions like Indicators, Scales, Meter types, etc. from disk. However it was found that Z-Wave JS updates at a much higher frequency than the Z-Wave specifications, so being able to statically reference certain definitions in code is far more useful than the possibility of updating config files outside of a driver update.
All types/methods below are exported from `@zwave-js/core`. The corresponding exports from `@zwave-js/config` have been removed.
### Device Classes
`BasicDeviceClass` is now an enum. "Slave" has been renamed to "End Node", "Routing Slave" to "Routing End Node". To get the corresponding string of a basic device class, use `getEnumMemberName(BasicDeviceClass, value)`.
`GenericDeviceClass` and `SpecificDeviceClass` are no longer class instances, but simple objects.
All methods related to device classes have been removed from `ConfigManager`. To look up a generic/specific device class, use the `getGenericDeviceClass` or `getSpecificDeviceClass` functions.
The constructor of the `DeviceClass` class no longer takes an instance of a `ConfigManager`.
All instances where the basic device class is used are now typed with the `BasicDeviceClass` enum. This include node mocks, NIF, Z-Wave Protocol CC, and several serial API commands.
### Indicators
Defined indicators are now exposed via the `Indicator` enum. To get the corresponding string of an indicator ID, use `getEnumMemberName(Indicator, indicatorId)`.
`IndicatorProperty` is no longer a class instance, but a simple object.
All methods related to indicators have been removed from `ConfigManager`. To look up an indicator property and its information, use the `getIndicatorProperty` function. This is strongly typed, so you should see the indicator property information in your IDE at compile time.
To list all indicator properties, use `getAllIndicatorProperties()`.
### Meters
`Meter` and `MeterScale` are no longer class instances, but simple objects. `MeterScale` now has an additional `unit` field.
All methods related to meters have been removed from `ConfigManager`. To look up a meter or meter scale, use the `getMeter` or `getMeterScale` functions. These are strongly typed, so you should see the definitions in your IDE at compile time.
To list all meters, use `getAllMeters()`. To list all scales of a meter, use `getAllMeterScales(meterType)` or iterate the `scales` property of the meter definition returned by `getMeter`.
### Sensors and Scales
`Scale` is no longer a class instances, but a simple object. `SensorType` is now called `Sensor` and also just a simple object type.
All named scales (e.g. "temperature") now have their type derived from the specific scale definition.
All methods related to sensors and scales have been removed from `ConfigManager`. To look up a sensor or scale, use the `getSensor` or `getSensorScale` functions. To look up a group of named scales or a specific one, use `getNamedScaleGroup` or `getNamedScale`. All of these are strongly typed, so you should see the definitions in your IDE at compile time.
To list all named scale groups, use `getAllNamedScaleGroups()`. To list all sensors, use `getAllSensors()`. To list all scales of a sensor, use `getAllSensorScales(sensorType)` or iterate the `scales` property of the sensor definition returned by `getSensor`.
### Notifications
The types for notification definitions have been reworked and are all simple object types now instead of class instances. Applications might interact with the following ones:
- `Notification`: The definition for a single notification type, with all its variables and events
- `NotificationVariable`: The definition for a (stateful) notification variable, which can have multiple states defined by `NotificationState`
- `NotificationEvent`: The definition for a (stateless) notification event
- `NotificationValue`: A generic notification value that can either be a state or an event
- `NotificationParameter`: A union of the possible notification parameter types, namely `NotificationParameterWithDuration`, `NotificationParameterWithCommandClass`, `NotificationParameterWithValue`, `NotificationParameterWithEnum`. These can be distinguished by their `type` property.
All methods related to notifications have been removed from `ConfigManager`. To look up a notification or value, use the `getNotification` or `getNotificationValue` functions. `getNotificationValue` needs access to the object returned by `getNotification`.
To list all defined notifications, use `getAllNotifications()`.
### Removed files
The following files have been removed from the `config` directory: `deviceClasses.json`, `indicators.json`, `meters.json`, `scales.json`, `sensorTypes.json`. If you used them in custom configuration, those are no longer needed.
## Replaced `Controller.isAssociationAllowed` with `Controller.checkAssociation`
Previously, the information that was returned when adding an association was not allowed was not very helpful for end users. The `isAssociationAllowed` method of the `Controller` class has been replaced with `checkAssociation` which returns a result with more detailed information why an association may not be added:
```ts
public checkAssociation(
source: AssociationAddress,
group: number,
destination: AssociationAddress,
): AssociationCheckResult;
enum AssociationCheckResult {
OK = 0x01,
/** The association is forbidden, because the destination is a ZWLR node. ZWLR does not support direct communication between end devices. */
Forbidden_DestinationIsLongRange,
/** The association is forbidden, because the source is a ZWLR node. ZWLR does not support direct communication between end devices. */
Forbidden_SourceIsLongRange,
/** The association is forbidden, because a node cannot be associated with itself. */
Forbidden_SelfAssociation,
/** The association is forbidden, because the source node's CC versions require the source and destination node to have the same (highest) security class. */
Forbidden_SecurityClassMismatch,
/** The association is forbidden, because the source node's CC versions require the source node to have the key for the destination node's highest security class. */
Forbidden_DestinationSecurityClassNotGranted,
/** The association is forbidden, because none of the CCs the source node sends are supported by the destination. */
Forbidden_NoSupportedCCs,
}
```
Although we recommend embracing the new return values, the old behavior can be restored by comparing the result with `AssociationCheckResult.OK`.
## Route health checks, neighbors and Z-Wave Long Range
Since Z-Wave Long Range (ZWLR) does not support routing, a few changes had to be made to methods that are concerned with routing and node neighbors:
- The route health check `node.checkRouteHealth(...)` now throws when either the source or target node is ZWLR.
- `LifelineHealthCheckResult.numNeighbors` is now an optional property and may be `undefined`. The number of neighbors is no longer considered when rating the lifeline health.
- `Controller.getNodeNeighbors` now throws when the given node ID is for a ZWLR node.
It is recommended to check if `node.protocol === Protocols.ZWaveLongRange` or `isLongRangeNodeId(nodeId)` is true before calling any of these methods.
## Rename "Master Code" to "Admin Code"
The Z-Wave specifications have been changed in language to replace "Master" with "Admin" where applicable. With this PR, we follow suit.
This requires some breaking API changes though:
- Renamed `DoorLockLoggingEventType.MasterCodeChanged` to `DoorLockLoggingEventType.AdminCodeChanged`
- Renamed the `UserCodeCommand` enum members `MasterCodeSet`, `MasterCodeGet`, `MasterCodeReport` to `AdminCodeSet`, `AdminCodeGet`, `AdminCodeReport` respectively
- Renamed the corresponding `User Code CC` subclasses to `UserCodeCCAdminCodeSet`, `UserCodeCCAdminCodeGet` and `UserCodeCCAdminCodeReport`
- Renamed all occurences of the `masterCode` property in `User Code CC` to `adminCode`
- Renamed `UserCodeCC.supportsMasterCodeDeactivationCached(...)` to `UserCodeCC.supportsAdminCodeDeactivationCached(...)`
- Renamed the User Code CC APIs `getMasterCode` and `setMasterCode` to `getAdminCode` and `setAdminCode`, respectively
For end users, the `property` of the Admin Code value ID has been changed from `masterCode` to `adminCode`, which means the old value will no longer be updated on changes.
## Removed deprecated things
- The first (`secure: boolean`) parameter of the `"inclusion started"` event has been replaced with the second parameter (`strategy: InclusionStrategy`), which was unfortunately undocumented, except in types. To determine whether an inclusion is supposed to be secure, check if `strategy !== InclusionStrategy.Insecure`.
- The `noBulkSupport` property of `ConfigurationMetadata` has been removed. There is no replacement, as it was never meant to be user-facing
- The `enableSoftReset` property of the `ZWaveOptions` has been removed. Use `features.softReset` instead.
- The `mandatorySupportedCCs` and `mandatorControlledCCs` properties of the `DeviceClass` class have been removed. There is no replacement.
## Migrated to Yarn 4 and Corepack
The repository has been migrated to Yarn v4 and now uses [Corepack](https://github.com/nodejs/corepack) to automatically install the correct package manager version, without having to check it into git. This should work out of the box, unless `yarn` was previously installed globally as a system package on Linux. In that case, you may have to uninstall the Linux package and remove any additions to the `PATH` environment variable.
It was found that Yarn 4 interacts with already-installed packages differently than Yarn 3. We patch `typescript` and it seems that Yarn 4 always undoes this when executing `yarn` or `yarn install`. Therefore you should not install packages yourself, but rather use the `yarn bootstrap` script to take care of everything.