matter-python-client 1.1.8a0.dev20260707__tar.gz → 1.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/PKG-INFO +1 -1
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_python_client.egg-info/PKG-INFO +1 -1
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_python_client.egg-info/SOURCES.txt +3 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/client/client.py +163 -73
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/errors.py +35 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/models.py +27 -11
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/pyproject.toml +4 -1
- matter_python_client-1.2.0/tests/test_credentials.py +197 -0
- matter_python_client-1.2.0/tests/test_event_dispatch.py +35 -0
- matter_python_client-1.2.0/tests/test_icd.py +208 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/tests/test_integration.py +28 -2
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/README.md +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/ChipUtility.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/ClusterObjects.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/Objects.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/Types.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/AccessControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/AccountLogin.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Actions.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ActivatedCarbonFilterMonitoring.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/AdministratorCommissioning.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/AirQuality.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/AmbientContextSensing.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ApplicationBasic.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ApplicationLauncher.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/AudioOutput.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/BasicInformation.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Binding.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/BooleanState.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/BooleanStateConfiguration.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/BridgedDeviceBasicInformation.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CameraAvSettingsUserLevelManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CameraAvStreamManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CarbonDioxideConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CarbonMonoxideConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Channel.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Chime.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ClosureControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ClosureDimension.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ColorControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CommissionerControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CommodityMetering.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CommodityPrice.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/CommodityTariff.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ContentAppObserver.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ContentControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ContentLauncher.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Descriptor.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/DeviceEnergyManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/DeviceEnergyManagementMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/DiagnosticLogs.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/DishwasherAlarm.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/DishwasherMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/DoorLock.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/DraftElectricalMeasurementCluster.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/EcosystemInformation.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ElectricalEnergyMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ElectricalGridConditions.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ElectricalPowerMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/EnergyEvse.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/EnergyEvseMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/EnergyPreference.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/EthernetNetworkDiagnostics.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/EveCluster.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/FanControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/FixedLabel.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/FlowMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/FormaldehydeConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/GeneralCommissioning.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/GeneralDiagnostics.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Globals.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/GroupKeyManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Groupcast.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Groups.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/HeimanCluster.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/HepaFilterMonitoring.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/IcdManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Identify.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/IlluminanceMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/InovelliCluster.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/JointFabricAdministrator.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/JointFabricDatastore.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/KeypadInput.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/LaundryDryerControls.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/LaundryWasherControls.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/LaundryWasherMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/LevelControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/LocalizationConfiguration.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/LowPower.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/MediaInput.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/MediaPlayback.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Messages.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/MeterIdentification.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/MicrowaveOvenControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/MicrowaveOvenMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ModeSelect.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/NeoCluster.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/NetworkCommissioning.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/NitrogenDioxideConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OccupancySensing.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OnOff.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OperationalCredentials.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OperationalState.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OtaSoftwareUpdateProvider.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OtaSoftwareUpdateRequestor.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OvenCavityOperationalState.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OvenMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/OzoneConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Pm10ConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Pm1ConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Pm25ConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/PowerSource.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/PowerSourceConfiguration.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/PowerTopology.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/PressureMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/PumpConfigurationAndControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/PushAvStreamTransport.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/RadonConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/RefrigeratorAlarm.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/RefrigeratorAndTemperatureControlledCabinetMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/RelativeHumidityMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/RvcCleanMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/RvcOperationalState.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/RvcRunMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ScenesManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ServiceArea.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/SmokeCoAlarm.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/SoftwareDiagnostics.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/SoilMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Switch.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TargetNavigator.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TclDehumidifierCluster.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TemperatureAlarm.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TemperatureControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TemperatureMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/Thermostat.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ThermostatUserInterfaceConfiguration.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ThirdRealityMeteringCluster.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ThreadBorderRouterManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ThreadNetworkDiagnostics.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ThreadNetworkDirectory.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TimeFormatLocalization.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TimeSynchronization.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TlsCertificateManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TlsClientManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/TotalVolatileOrganicCompoundsConcentrationMeasurement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/UnitLocalization.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/UserLabel.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ValveConfigurationAndControl.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WakeOnLan.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WaterHeaterManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WaterHeaterMode.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WaterTankLevelMonitoring.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WebRtcTransportDefinitions.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WebRtcTransportProvider.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WebRtcTransportRequestor.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WiFiNetworkDiagnostics.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WiFiNetworkManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/WindowCovering.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/ZoneManagement.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/cluster_defs/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/clusters/enum.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/tlv/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/chip/tlv/tlvlist.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_python_client.egg-info/dependency_links.txt +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_python_client.egg-info/not-zip-safe +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_python_client.egg-info/requires.txt +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_python_client.egg-info/top_level.txt +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/client/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/client/connection.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/client/exceptions.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/client/models/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/client/models/device_types.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/client/models/node.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/const.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/custom_clusters.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/helpers/__init__.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/helpers/api.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/helpers/json.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/common/helpers/util.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/matter_server/py.typed +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/setup.cfg +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/tests/test_client_integration.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/tests/test_imports.py +0 -0
- {matter_python_client-1.1.8a0.dev20260707 → matter_python_client-1.2.0}/tests/test_webrtc_protocol.py +0 -0
|
@@ -179,6 +179,9 @@ matter_server/common/helpers/api.py
|
|
|
179
179
|
matter_server/common/helpers/json.py
|
|
180
180
|
matter_server/common/helpers/util.py
|
|
181
181
|
tests/test_client_integration.py
|
|
182
|
+
tests/test_credentials.py
|
|
183
|
+
tests/test_event_dispatch.py
|
|
184
|
+
tests/test_icd.py
|
|
182
185
|
tests/test_imports.py
|
|
183
186
|
tests/test_integration.py
|
|
184
187
|
tests/test_webrtc_protocol.py
|
|
@@ -25,6 +25,7 @@ from matter_server.common.models import (
|
|
|
25
25
|
ErrorResultMessage,
|
|
26
26
|
EventMessage,
|
|
27
27
|
EventType,
|
|
28
|
+
IcdStateData,
|
|
28
29
|
MatterNodeData,
|
|
29
30
|
MatterNodeEvent,
|
|
30
31
|
MatterSoftwareVersion,
|
|
@@ -127,32 +128,45 @@ class MatterClient:
|
|
|
127
128
|
|
|
128
129
|
async def set_default_fabric_label(self, label: str | None) -> None:
|
|
129
130
|
"""Set the default fabric label."""
|
|
130
|
-
await self.send_command(
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
await self.send_command(APICommand.SET_DEFAULT_FABRIC_LABEL, require_schema=11, label=label)
|
|
132
|
+
|
|
133
|
+
async def get_fabric_label(self) -> str | None:
|
|
134
|
+
"""Return the currently configured fabric label."""
|
|
135
|
+
result = await self.send_command(APICommand.GET_FABRIC_LABEL, require_schema=12)
|
|
136
|
+
return cast("str | None", result["fabric_label"])
|
|
133
137
|
|
|
134
138
|
async def commission_with_code(
|
|
135
|
-
self,
|
|
139
|
+
self,
|
|
140
|
+
code: str,
|
|
141
|
+
network_only: bool = False,
|
|
142
|
+
wifi_credentials_id: str | None = None,
|
|
143
|
+
thread_dataset_id: str | None = None,
|
|
136
144
|
) -> MatterNodeData:
|
|
137
145
|
"""
|
|
138
146
|
Commission a device using a QR Code or Manual Pairing Code.
|
|
139
147
|
|
|
140
148
|
:param code: The QR Code or Manual Pairing Code for device commissioning.
|
|
141
149
|
:param network_only: If True, restricts device discovery to network only.
|
|
150
|
+
:param wifi_credentials_id: Optional id of the WiFi credentials entry to use.
|
|
151
|
+
:param thread_dataset_id: Optional id of the Thread dataset entry to use.
|
|
142
152
|
|
|
143
153
|
:return: The NodeInfo of the commissioned device.
|
|
144
154
|
"""
|
|
155
|
+
extra: dict[str, str] = {}
|
|
156
|
+
if wifi_credentials_id is not None:
|
|
157
|
+
extra["wifi_credentials_id"] = wifi_credentials_id
|
|
158
|
+
if thread_dataset_id is not None:
|
|
159
|
+
extra["thread_dataset_id"] = thread_dataset_id
|
|
145
160
|
data = await self.send_command(
|
|
146
161
|
APICommand.COMMISSION_WITH_CODE,
|
|
147
|
-
require_schema=6 if network_only else None,
|
|
162
|
+
require_schema=12 if extra else (6 if network_only else None),
|
|
148
163
|
code=code,
|
|
149
164
|
network_only=network_only,
|
|
165
|
+
**extra,
|
|
150
166
|
)
|
|
151
167
|
return dataclass_from_dict(MatterNodeData, data)
|
|
152
168
|
|
|
153
|
-
async def commission_on_network(
|
|
154
|
-
self, setup_pin_code: int, ip_addr: str | None = None
|
|
155
|
-
) -> MatterNodeData:
|
|
169
|
+
async def commission_on_network(self, setup_pin_code: int, ip_addr: str | None = None) -> MatterNodeData:
|
|
156
170
|
"""
|
|
157
171
|
Do the routine for OnNetworkCommissioning.
|
|
158
172
|
|
|
@@ -169,23 +183,130 @@ class MatterClient:
|
|
|
169
183
|
)
|
|
170
184
|
return dataclass_from_dict(MatterNodeData, data)
|
|
171
185
|
|
|
172
|
-
async def set_wifi_credentials(self, ssid: str, credentials: str) -> None:
|
|
186
|
+
async def set_wifi_credentials(self, ssid: str, credentials: str, entry_id: str = "default") -> None:
|
|
173
187
|
"""Set WiFi credentials for commissioning to a (new) device."""
|
|
174
188
|
await self.send_command(
|
|
175
|
-
APICommand.SET_WIFI_CREDENTIALS,
|
|
189
|
+
APICommand.SET_WIFI_CREDENTIALS,
|
|
190
|
+
require_schema=12 if entry_id != "default" else None,
|
|
191
|
+
ssid=ssid,
|
|
192
|
+
credentials=credentials,
|
|
193
|
+
id=entry_id,
|
|
176
194
|
)
|
|
177
195
|
|
|
178
|
-
async def set_thread_operational_dataset(self, dataset: str) -> None:
|
|
196
|
+
async def set_thread_operational_dataset(self, dataset: str, entry_id: str = "default") -> None:
|
|
179
197
|
"""Set Thread Operational dataset in the stack."""
|
|
180
|
-
await self.send_command(
|
|
198
|
+
await self.send_command(
|
|
199
|
+
APICommand.SET_THREAD_DATASET,
|
|
200
|
+
require_schema=12 if entry_id != "default" else None,
|
|
201
|
+
dataset=dataset,
|
|
202
|
+
id=entry_id,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
async def remove_wifi_credentials(self, entry_id: str = "default") -> None:
|
|
206
|
+
"""Remove stored WiFi credentials from the server.
|
|
207
|
+
|
|
208
|
+
:param entry_id: Id of the entry to remove; "default" removes the default entry.
|
|
209
|
+
"""
|
|
210
|
+
await self.send_command(
|
|
211
|
+
APICommand.REMOVE_WIFI_CREDENTIALS,
|
|
212
|
+
require_schema=12 if entry_id != "default" else None,
|
|
213
|
+
id=entry_id,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
async def remove_thread_dataset(self, entry_id: str = "default") -> None:
|
|
217
|
+
"""Remove a stored Thread Operational dataset from the server.
|
|
218
|
+
|
|
219
|
+
:param entry_id: Id of the entry to remove; "default" removes the default entry.
|
|
220
|
+
"""
|
|
221
|
+
await self.send_command(
|
|
222
|
+
APICommand.REMOVE_THREAD_DATASET,
|
|
223
|
+
require_schema=12 if entry_id != "default" else None,
|
|
224
|
+
id=entry_id,
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
async def get_all_credentials(self) -> dict[str, Any]:
|
|
228
|
+
"""Return summaries (no secrets) of all stored WiFi and Thread credentials."""
|
|
229
|
+
result: dict[str, Any] = await self.send_command(APICommand.GET_ALL_CREDENTIALS, require_schema=12)
|
|
230
|
+
return result
|
|
231
|
+
|
|
232
|
+
async def get_thread_border_routers(self) -> list[dict[str, Any]]:
|
|
233
|
+
"""Return mDNS-discovered Thread Border Routers (passive discovery).
|
|
234
|
+
|
|
235
|
+
Each entry describes a discovered Border Router (extended address, addresses,
|
|
236
|
+
network name, extended PAN ID, mDNS TXT metadata, …). Requires schema 12.
|
|
237
|
+
"""
|
|
238
|
+
result: list[dict[str, Any]] = await self.send_command(APICommand.GET_THREAD_BORDER_ROUTERS, require_schema=12)
|
|
239
|
+
return result
|
|
240
|
+
|
|
241
|
+
async def get_thread_diagnostics(self, ext_pan_id: str | None = None, force: bool = False) -> Any:
|
|
242
|
+
"""Return per-Thread-network diagnostics collected from Border Routers.
|
|
243
|
+
|
|
244
|
+
Also streamed via the ``thread_diagnostics_updated`` event. Requires schema 12.
|
|
245
|
+
|
|
246
|
+
:param ext_pan_id: 16-char hex extended PAN ID to fetch a single network (awaits a
|
|
247
|
+
fresh collection and returns the batch, or ``None`` when nothing is cached);
|
|
248
|
+
omitted returns the *current* cache for all known networks immediately (a list) and
|
|
249
|
+
triggers a background refresh whose fresh batches arrive via ``thread_diagnostics_updated``.
|
|
250
|
+
:param force: Bypass the server-side cache and re-fetch. For the all-networks form the refresh
|
|
251
|
+
is fire-and-forget (the call still returns the current cache at once); pass ``ext_pan_id``
|
|
252
|
+
when you need to await synchronously fresh data for one network.
|
|
253
|
+
"""
|
|
254
|
+
args: dict[str, Any] = {}
|
|
255
|
+
if ext_pan_id is not None:
|
|
256
|
+
args["ext_pan_id"] = ext_pan_id
|
|
257
|
+
if force:
|
|
258
|
+
args["force"] = True
|
|
259
|
+
return await self.send_command(APICommand.GET_THREAD_DIAGNOSTICS, require_schema=12, **args)
|
|
260
|
+
|
|
261
|
+
async def get_icd_state(self, node_id: int) -> IcdStateData:
|
|
262
|
+
"""Return the controller-side ICD (Intermittently Connected Device) state for a node.
|
|
263
|
+
|
|
264
|
+
Requires schema 12.
|
|
265
|
+
"""
|
|
266
|
+
data = await self.send_command(APICommand.GET_ICD_STATE, require_schema=12, node_id=node_id)
|
|
267
|
+
return dataclass_from_dict(IcdStateData, data)
|
|
268
|
+
|
|
269
|
+
async def register_icd(
|
|
270
|
+
self,
|
|
271
|
+
node_id: int,
|
|
272
|
+
allow_multi_admin: bool | None = None,
|
|
273
|
+
ignored_vendors: list[int] | None = None,
|
|
274
|
+
) -> IcdStateData:
|
|
275
|
+
"""Register this controller as an ICD monitor for a node.
|
|
276
|
+
|
|
277
|
+
Requires schema 12.
|
|
278
|
+
|
|
279
|
+
:param allow_multi_admin: Proceed even when other admin fabrics may not support LIT
|
|
280
|
+
(raises IcdMultiAdmin otherwise).
|
|
281
|
+
:param ignored_vendors: Vendor ids to skip during the multi-admin check.
|
|
282
|
+
"""
|
|
283
|
+
args: dict[str, Any] = {}
|
|
284
|
+
if allow_multi_admin is not None:
|
|
285
|
+
args["allow_multi_admin"] = allow_multi_admin
|
|
286
|
+
if ignored_vendors is not None:
|
|
287
|
+
args["ignored_vendors"] = ignored_vendors
|
|
288
|
+
data = await self.send_command(APICommand.REGISTER_ICD, require_schema=12, node_id=node_id, **args)
|
|
289
|
+
return dataclass_from_dict(IcdStateData, data)
|
|
181
290
|
|
|
182
|
-
async def
|
|
183
|
-
"""
|
|
184
|
-
await self.send_command(APICommand.REMOVE_WIFI_CREDENTIALS)
|
|
291
|
+
async def unregister_icd(self, node_id: int, force: bool = False) -> IcdStateData:
|
|
292
|
+
"""Unregister this controller as an ICD monitor for a node.
|
|
185
293
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
294
|
+
Requires schema 12.
|
|
295
|
+
|
|
296
|
+
:param force: Skip the peer round-trip and only clear local registration state
|
|
297
|
+
(for an unreachable peer).
|
|
298
|
+
"""
|
|
299
|
+
data = await self.send_command(
|
|
300
|
+
APICommand.UNREGISTER_ICD, require_schema=12, node_id=node_id, force=force
|
|
301
|
+
)
|
|
302
|
+
return dataclass_from_dict(IcdStateData, data)
|
|
303
|
+
|
|
304
|
+
async def resync_icd(self, node_id: int) -> None:
|
|
305
|
+
"""Drop the local ICD registration for a node and reconnect (the peer re-registers).
|
|
306
|
+
|
|
307
|
+
Requires schema 12.
|
|
308
|
+
"""
|
|
309
|
+
await self.send_command(APICommand.RESYNC_ICD, require_schema=12, node_id=node_id)
|
|
189
310
|
|
|
190
311
|
async def open_commissioning_window(
|
|
191
312
|
self,
|
|
@@ -233,14 +354,10 @@ class MatterClient:
|
|
|
233
354
|
if node.available:
|
|
234
355
|
await self.refresh_attribute(
|
|
235
356
|
node_id,
|
|
236
|
-
create_attribute_path_from_attribute(
|
|
237
|
-
0, Clusters.OperationalCredentials.Attributes.Fabrics
|
|
238
|
-
),
|
|
357
|
+
create_attribute_path_from_attribute(0, Clusters.OperationalCredentials.Attributes.Fabrics),
|
|
239
358
|
)
|
|
240
359
|
|
|
241
|
-
fabrics: list[
|
|
242
|
-
Clusters.OperationalCredentials.Structs.FabricDescriptorStruct
|
|
243
|
-
] = node.get_attribute_value(
|
|
360
|
+
fabrics: list[Clusters.OperationalCredentials.Structs.FabricDescriptorStruct] = node.get_attribute_value(
|
|
244
361
|
0, None, Clusters.OperationalCredentials.Attributes.Fabrics
|
|
245
362
|
)
|
|
246
363
|
|
|
@@ -278,9 +395,7 @@ class MatterClient:
|
|
|
278
395
|
await self.send_command(APICommand.PING_NODE, node_id=node_id),
|
|
279
396
|
)
|
|
280
397
|
|
|
281
|
-
async def get_node_ip_addresses(
|
|
282
|
-
self, node_id: int, prefer_cache: bool = True, scoped: bool = False
|
|
283
|
-
) -> list[str]:
|
|
398
|
+
async def get_node_ip_addresses(self, node_id: int, prefer_cache: bool = True, scoped: bool = False) -> list[str]:
|
|
284
399
|
"""Return the currently known (scoped) IP-address(es)."""
|
|
285
400
|
if TYPE_CHECKING:
|
|
286
401
|
assert self.server_info is not None
|
|
@@ -300,9 +415,7 @@ class MatterClient:
|
|
|
300
415
|
attribute = Clusters.GeneralDiagnostics.Attributes.NetworkInterfaces
|
|
301
416
|
network_interface: Clusters.GeneralDiagnostics.Structs.NetworkInterface
|
|
302
417
|
ip_addresses: list[str] = []
|
|
303
|
-
for network_interface in node.get_attribute_value(
|
|
304
|
-
0, cluster=None, attribute=attribute
|
|
305
|
-
):
|
|
418
|
+
for network_interface in node.get_attribute_value(0, cluster=None, attribute=attribute):
|
|
306
419
|
# ignore invalid/non-operational interfaces
|
|
307
420
|
if not network_interface.isOperational:
|
|
308
421
|
continue
|
|
@@ -326,26 +439,15 @@ class MatterClient:
|
|
|
326
439
|
mac_address = None
|
|
327
440
|
attribute = Clusters.GeneralDiagnostics.Attributes.NetworkInterfaces
|
|
328
441
|
network_interface: Clusters.GeneralDiagnostics.Structs.NetworkInterface
|
|
329
|
-
for network_interface in (
|
|
330
|
-
node.get_attribute_value(0, cluster=None, attribute=attribute) or []
|
|
331
|
-
):
|
|
442
|
+
for network_interface in node.get_attribute_value(0, cluster=None, attribute=attribute) or []:
|
|
332
443
|
# ignore invalid/non-operational interfaces
|
|
333
444
|
if not network_interface.isOperational:
|
|
334
445
|
continue
|
|
335
|
-
if
|
|
336
|
-
network_interface.type
|
|
337
|
-
== Clusters.GeneralDiagnostics.Enums.InterfaceTypeEnum.kThread
|
|
338
|
-
):
|
|
446
|
+
if network_interface.type == Clusters.GeneralDiagnostics.Enums.InterfaceTypeEnum.kThread:
|
|
339
447
|
network_type = NetworkType.THREAD
|
|
340
|
-
elif
|
|
341
|
-
network_interface.type
|
|
342
|
-
== Clusters.GeneralDiagnostics.Enums.InterfaceTypeEnum.kWiFi
|
|
343
|
-
):
|
|
448
|
+
elif network_interface.type == Clusters.GeneralDiagnostics.Enums.InterfaceTypeEnum.kWiFi:
|
|
344
449
|
network_type = NetworkType.WIFI
|
|
345
|
-
elif
|
|
346
|
-
network_interface.type
|
|
347
|
-
== Clusters.GeneralDiagnostics.Enums.InterfaceTypeEnum.kEthernet
|
|
348
|
-
):
|
|
450
|
+
elif network_interface.type == Clusters.GeneralDiagnostics.Enums.InterfaceTypeEnum.kEthernet:
|
|
349
451
|
network_type = NetworkType.ETHERNET
|
|
350
452
|
else:
|
|
351
453
|
# unknown interface: ignore
|
|
@@ -362,14 +464,10 @@ class MatterClient:
|
|
|
362
464
|
node_type = NodeType.UNKNOWN
|
|
363
465
|
network_name = None
|
|
364
466
|
if network_type == NetworkType.THREAD:
|
|
365
|
-
thread_cluster: Clusters.ThreadNetworkDiagnostics = node.get_cluster(
|
|
366
|
-
0, Clusters.ThreadNetworkDiagnostics
|
|
367
|
-
)
|
|
467
|
+
thread_cluster: Clusters.ThreadNetworkDiagnostics = node.get_cluster(0, Clusters.ThreadNetworkDiagnostics)
|
|
368
468
|
if thread_cluster:
|
|
369
469
|
if isinstance(thread_cluster.networkName, bytes):
|
|
370
|
-
network_name = thread_cluster.networkName.decode(
|
|
371
|
-
"utf-8", errors="replace"
|
|
372
|
-
)
|
|
470
|
+
network_name = thread_cluster.networkName.decode("utf-8", errors="replace")
|
|
373
471
|
elif thread_cluster.networkName != NullValue:
|
|
374
472
|
network_name = thread_cluster.networkName
|
|
375
473
|
|
|
@@ -428,9 +526,7 @@ class MatterClient:
|
|
|
428
526
|
# get active fabrics for this node
|
|
429
527
|
active_fabrics = await self.get_matter_fabrics(node_id)
|
|
430
528
|
# get active fabric index
|
|
431
|
-
fabric_index = node.get_attribute_value(
|
|
432
|
-
0, None, Clusters.OperationalCredentials.Attributes.CurrentFabricIndex
|
|
433
|
-
)
|
|
529
|
+
fabric_index = node.get_attribute_value(0, None, Clusters.OperationalCredentials.Attributes.CurrentFabricIndex)
|
|
434
530
|
return NodeDiagnostics(
|
|
435
531
|
node_id=node_id,
|
|
436
532
|
network_type=network_type,
|
|
@@ -526,9 +622,7 @@ class MatterClient:
|
|
|
526
622
|
|
|
527
623
|
The "softwareVersionString" is a human friendly version string.
|
|
528
624
|
"""
|
|
529
|
-
data = await self.send_command(
|
|
530
|
-
APICommand.CHECK_NODE_UPDATE, node_id=node_id, require_schema=10
|
|
531
|
-
)
|
|
625
|
+
data = await self.send_command(APICommand.CHECK_NODE_UPDATE, node_id=node_id, require_schema=10)
|
|
532
626
|
if data is None:
|
|
533
627
|
return None
|
|
534
628
|
|
|
@@ -561,6 +655,7 @@ class MatterClient:
|
|
|
561
655
|
"""
|
|
562
656
|
response = await self.send_command(
|
|
563
657
|
APICommand.SEND_WEBRTC_PROVIDER_COMMAND,
|
|
658
|
+
require_schema=12,
|
|
564
659
|
node_id=node_id,
|
|
565
660
|
endpoint_id=endpoint_id,
|
|
566
661
|
command_name=command_name,
|
|
@@ -643,19 +738,12 @@ class MatterClient:
|
|
|
643
738
|
await self.connect()
|
|
644
739
|
|
|
645
740
|
try:
|
|
646
|
-
message = CommandMessage(
|
|
647
|
-
message_id=uuid.uuid4().hex, command=APICommand.START_LISTENING
|
|
648
|
-
)
|
|
741
|
+
message = CommandMessage(message_id=uuid.uuid4().hex, command=APICommand.START_LISTENING)
|
|
649
742
|
await self.connection.send_message(message)
|
|
650
|
-
nodes_msg = cast(
|
|
651
|
-
SuccessResultMessage, await self.connection.receive_message_or_raise()
|
|
652
|
-
)
|
|
743
|
+
nodes_msg = cast(SuccessResultMessage, await self.connection.receive_message_or_raise())
|
|
653
744
|
# a full dump of all nodes will be the result of the start_listening command
|
|
654
745
|
# create MatterNode objects from the basic MatterNodeData objects
|
|
655
|
-
nodes = [
|
|
656
|
-
MatterNode(dataclass_from_dict(MatterNodeData, x))
|
|
657
|
-
for x in nodes_msg.result
|
|
658
|
-
]
|
|
746
|
+
nodes = [MatterNode(dataclass_from_dict(MatterNodeData, x)) for x in nodes_msg.result]
|
|
659
747
|
self._nodes = {node.node_id: node for node in nodes}
|
|
660
748
|
# once we've hit this point we're all set
|
|
661
749
|
self.logger.info("Matter client initialized.")
|
|
@@ -741,9 +829,7 @@ class MatterClient:
|
|
|
741
829
|
node_id = msg.data["node_id"]
|
|
742
830
|
endpoint_id = msg.data["endpoint_id"]
|
|
743
831
|
self.logger.debug("Endpoint removed: %s/%s", node_id, endpoint_id)
|
|
744
|
-
self._signal_event(
|
|
745
|
-
EventType.ENDPOINT_REMOVED, data=msg.data, node_id=node_id
|
|
746
|
-
)
|
|
832
|
+
self._signal_event(EventType.ENDPOINT_REMOVED, data=msg.data, node_id=node_id)
|
|
747
833
|
# cleanup endpoint only after signalling subscribers
|
|
748
834
|
if node := self._nodes.get(node_id):
|
|
749
835
|
node.endpoints.pop(endpoint_id, None)
|
|
@@ -783,6 +869,12 @@ class MatterClient:
|
|
|
783
869
|
node_id=node_event.node_id,
|
|
784
870
|
)
|
|
785
871
|
return
|
|
872
|
+
# An event type unknown to this (older) client is passed through by parse_value as a raw
|
|
873
|
+
# string; forwarding it would crash on `event.value` in _signal_event. Drop it instead so a
|
|
874
|
+
# newer server emitting a new event type can never disconnect the client.
|
|
875
|
+
if not isinstance(msg.event, EventType):
|
|
876
|
+
self.logger.debug("Ignoring unknown event type: %s", msg.event)
|
|
877
|
+
return
|
|
786
878
|
# simply forward all other events as-is
|
|
787
879
|
if self.logger.isEnabledFor(logging.DEBUG):
|
|
788
880
|
self.logger.debug("Received event: %s", msg)
|
|
@@ -814,9 +906,7 @@ class MatterClient:
|
|
|
814
906
|
await self.connect()
|
|
815
907
|
return self
|
|
816
908
|
|
|
817
|
-
async def __aexit__(
|
|
818
|
-
self, exc_type: Exception, exc_value: str, traceback: TracebackType
|
|
819
|
-
) -> None:
|
|
909
|
+
async def __aexit__(self, exc_type: Exception, exc_value: str, traceback: TracebackType) -> None:
|
|
820
910
|
"""Disconnect from the websocket."""
|
|
821
911
|
await self.disconnect()
|
|
822
912
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import json
|
|
6
|
+
|
|
5
7
|
# mapping from error_code to Exception class
|
|
6
8
|
ERROR_MAP: dict[int, type] = {}
|
|
7
9
|
|
|
@@ -89,6 +91,39 @@ class UpdateError(MatterError):
|
|
|
89
91
|
error_code = 11
|
|
90
92
|
|
|
91
93
|
|
|
94
|
+
class IcdMultiAdmin(MatterError):
|
|
95
|
+
"""Error raised when ICD registration is rejected due to other admin fabrics.
|
|
96
|
+
|
|
97
|
+
OHF extension (python-matter-server codes stop at 11); `details` is a JSON string
|
|
98
|
+
`{"message": str, "admin_vendor_ids": list[int]}`.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
error_code = 100
|
|
102
|
+
|
|
103
|
+
_FALLBACK_MESSAGE = "ICD registration rejected: the peer has administrator fabrics from other vendors"
|
|
104
|
+
|
|
105
|
+
def __init__(self, details: str | None = None) -> None:
|
|
106
|
+
"""Parse `details` and expose `admin_vendor_ids`."""
|
|
107
|
+
self.admin_vendor_ids: list[int] = []
|
|
108
|
+
message = details if details else self._FALLBACK_MESSAGE
|
|
109
|
+
if details:
|
|
110
|
+
try:
|
|
111
|
+
parsed = json.loads(details)
|
|
112
|
+
except (json.JSONDecodeError, TypeError):
|
|
113
|
+
parsed = None
|
|
114
|
+
if isinstance(parsed, dict):
|
|
115
|
+
vendor_ids = parsed.get("admin_vendor_ids")
|
|
116
|
+
if isinstance(vendor_ids, list):
|
|
117
|
+
self.admin_vendor_ids = vendor_ids
|
|
118
|
+
parsed_message = parsed.get("message")
|
|
119
|
+
message = (
|
|
120
|
+
parsed_message
|
|
121
|
+
if isinstance(parsed_message, str) and parsed_message
|
|
122
|
+
else self._FALLBACK_MESSAGE
|
|
123
|
+
)
|
|
124
|
+
super().__init__(message)
|
|
125
|
+
|
|
126
|
+
|
|
92
127
|
def exception_from_error_code(error_code: int) -> type[MatterError]:
|
|
93
128
|
"""Return correct Exception class from error_code."""
|
|
94
129
|
return ERROR_MAP.get(error_code, MatterError)
|
|
@@ -24,6 +24,7 @@ class EventType(Enum):
|
|
|
24
24
|
ENDPOINT_ADDED = "endpoint_added"
|
|
25
25
|
ENDPOINT_REMOVED = "endpoint_removed"
|
|
26
26
|
WEBRTC_CALLBACK = "webrtc_callback"
|
|
27
|
+
THREAD_DIAGNOSTICS_UPDATED = "thread_diagnostics_updated" # schema 12+
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class APICommand(str, Enum):
|
|
@@ -54,9 +55,17 @@ class APICommand(str, Enum):
|
|
|
54
55
|
CHECK_NODE_UPDATE = "check_node_update"
|
|
55
56
|
UPDATE_NODE = "update_node"
|
|
56
57
|
SET_DEFAULT_FABRIC_LABEL = "set_default_fabric_label"
|
|
58
|
+
GET_FABRIC_LABEL = "get_fabric_label"
|
|
57
59
|
SET_ACL_ENTRY = "set_acl_entry"
|
|
58
60
|
SET_NODE_BINDING = "set_node_binding"
|
|
59
61
|
SEND_WEBRTC_PROVIDER_COMMAND = "send_webrtc_provider_command"
|
|
62
|
+
GET_ALL_CREDENTIALS = "get_all_credentials"
|
|
63
|
+
GET_THREAD_BORDER_ROUTERS = "get_thread_border_routers"
|
|
64
|
+
GET_THREAD_DIAGNOSTICS = "get_thread_diagnostics"
|
|
65
|
+
GET_ICD_STATE = "get_icd_state"
|
|
66
|
+
REGISTER_ICD = "register_icd"
|
|
67
|
+
RESYNC_ICD = "resync_icd"
|
|
68
|
+
UNREGISTER_ICD = "unregister_icd"
|
|
60
69
|
|
|
61
70
|
|
|
62
71
|
EventCallBackType = Callable[[EventType, Any], None]
|
|
@@ -91,9 +100,7 @@ class MatterNodeData:
|
|
|
91
100
|
# all attribute subscriptions we need to persist for this node,
|
|
92
101
|
# a set of tuples in format (endpoint_id, cluster_id, attribute_id)
|
|
93
102
|
# where each value can also be a None for wildcard
|
|
94
|
-
attribute_subscriptions: set[tuple[int | None, int | None, int | None]] = field(
|
|
95
|
-
default_factory=set
|
|
96
|
-
)
|
|
103
|
+
attribute_subscriptions: set[tuple[int | None, int | None, int | None]] = field(default_factory=set)
|
|
97
104
|
|
|
98
105
|
|
|
99
106
|
@dataclass
|
|
@@ -192,7 +199,9 @@ class ErrorResultMessage(ResultMessageBase):
|
|
|
192
199
|
class EventMessage:
|
|
193
200
|
"""Message sent when server or client signals a (stateless) event."""
|
|
194
201
|
|
|
195
|
-
event
|
|
202
|
+
# An event type unknown to this client is passed through by parse_value as a raw string rather
|
|
203
|
+
# than an EventType, so consumers must narrow before relying on enum members.
|
|
204
|
+
event: EventType | str
|
|
196
205
|
data: Any
|
|
197
206
|
|
|
198
207
|
|
|
@@ -212,13 +221,7 @@ class ServerInfoMessage:
|
|
|
212
221
|
ble_proxy_enabled: bool = False
|
|
213
222
|
|
|
214
223
|
|
|
215
|
-
MessageType =
|
|
216
|
-
CommandMessage
|
|
217
|
-
| EventMessage
|
|
218
|
-
| SuccessResultMessage
|
|
219
|
-
| ErrorResultMessage
|
|
220
|
-
| ServerInfoMessage
|
|
221
|
-
)
|
|
224
|
+
MessageType = CommandMessage | EventMessage | SuccessResultMessage | ErrorResultMessage | ServerInfoMessage
|
|
222
225
|
|
|
223
226
|
|
|
224
227
|
@dataclass
|
|
@@ -254,6 +257,19 @@ class CommissioningParameters:
|
|
|
254
257
|
setup_qr_code: str
|
|
255
258
|
|
|
256
259
|
|
|
260
|
+
@dataclass
|
|
261
|
+
class IcdStateData:
|
|
262
|
+
"""ICD controller-side state for a node. Note: Only available with OHF Matter Server."""
|
|
263
|
+
|
|
264
|
+
supported: bool
|
|
265
|
+
lit_supported: bool
|
|
266
|
+
registered: bool
|
|
267
|
+
operating_mode: str | None
|
|
268
|
+
awake: bool | None
|
|
269
|
+
available: bool | None
|
|
270
|
+
next_expected_checkin: int | None
|
|
271
|
+
|
|
272
|
+
|
|
257
273
|
class UpdateSource(Enum):
|
|
258
274
|
"""Enum with possible sources for a software update."""
|
|
259
275
|
|
|
@@ -25,7 +25,7 @@ license = "Apache-2.0"
|
|
|
25
25
|
name = "matter-python-client"
|
|
26
26
|
readme = "README.md"
|
|
27
27
|
requires-python = ">=3.12"
|
|
28
|
-
version = "1.
|
|
28
|
+
version = "1.2.0"
|
|
29
29
|
|
|
30
30
|
[project.urls]
|
|
31
31
|
Homepage = "https://github.com/matter-js/matterjs-server"
|
|
@@ -117,6 +117,9 @@ disable_error_code = [
|
|
|
117
117
|
module = "tests.*"
|
|
118
118
|
disallow_untyped_defs = false
|
|
119
119
|
disallow_untyped_calls = false
|
|
120
|
+
disable_error_code = [
|
|
121
|
+
"method-assign",
|
|
122
|
+
]
|
|
120
123
|
|
|
121
124
|
[tool.pylint.MAIN]
|
|
122
125
|
extension-pkg-allow-list = [
|