mx-remote 6.2.0__tar.gz → 7.0.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.
- {mx_remote-6.2.0 → mx_remote-7.0.0}/PKG-INFO +1 -1
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/api.md +46 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/oneip.md +67 -1
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/Interface.py +228 -8
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/Interface.pyi +72 -1
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/const.py +1 -1
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Constants.py +106 -3
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Constants.pyi +51 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Factory.py +6 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayStatus.py +36 -8
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayStatus.pyi +6 -0
- mx_remote-7.0.0/mx_remote/proto/FrameDiscover.py +44 -0
- mx_remote-7.0.0/mx_remote/proto/FrameDiscover.pyi +12 -0
- mx_remote-7.0.0/mx_remote/proto/FrameUnitCommand.py +70 -0
- mx_remote-7.0.0/mx_remote/proto/FrameUnitCommand.pyi +20 -0
- mx_remote-7.0.0/mx_remote/proto/FrameUnitStatus.py +64 -0
- mx_remote-7.0.0/mx_remote/proto/FrameUnitStatus.pyi +15 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPDeviceConfiguration.py +52 -9
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPDeviceConfiguration.pyi +4 -2
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/ConnectionAsync.py +5 -2
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Device.py +120 -2
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Device.pyi +17 -2
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Remote.py +80 -7
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Remote.pyi +2 -2
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/handlers.py +1 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/mesh.py +8 -2
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/proto_stamp.py +1 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/run.py +3 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/smoke.py +2 -1
- mx_remote-7.0.0/tests/staterequest.py +119 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/structs.py +20 -0
- mx_remote-7.0.0/tests/unit.py +181 -0
- mx_remote-7.0.0/tests/v2ipptp.py +93 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/v2ipsettings.py +53 -0
- mx_remote-6.2.0/mx_remote/proto/FrameDiscover.py +0 -25
- mx_remote-6.2.0/mx_remote/proto/FrameDiscover.pyi +0 -8
- {mx_remote-6.2.0 → mx_remote-7.0.0}/.gitignore +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/AGENTS.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/CLAUDE.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/LICENSE +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/README.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/README.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/_static/brand.css +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/_static/favicon.svg +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/_static/logo-dark.svg +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/_static/logo.svg +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/audio.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/callbacks.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/conf.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/configuration.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/devices-and-bays.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/diagnostics.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/index.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/multiviewer.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/requirements.txt +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/docs/routing.md +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/hatch_build.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/Uid.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/Uid.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/__init__.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/__init__.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/compat.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/compat.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/const.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/deprecated.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/deprecated.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/main.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/main.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/BayConfig.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/BayConfig.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Data.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Data.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Factory.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAmpDolbySettings.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAmpDolbySettings.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAmpZoneSettings.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAmpZoneSettings.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAudioClip.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAudioClip.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAudioSetRoute.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameAudioSetRoute.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBase.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBase.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayConfig.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayConfig.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayConfigSecondary.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayConfigSecondary.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayHide.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameBayHide.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameConnectStatus.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameConnectStatus.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameDebug.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameDebug.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameEDID.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameEDID.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameEDIDProfile.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameEDIDProfile.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameFactoryReset.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameFactoryReset.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameFilterStatus.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameFilterStatus.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameFirmwareVersion.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameFirmwareVersion.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameHeader.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameHeader.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameHello.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameHello.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameLinks.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameLinks.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameMeshOperation.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameMeshOperation.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameMirrorStatus.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameMirrorStatus.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameMonitoringPulse.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameMonitoringPulse.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameNetworkStatus.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameNetworkStatus.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FramePing.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FramePing.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FramePowerChange.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FramePowerChange.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCAction.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCAction.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCIr.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCIr.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCKey.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCKey.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCSettings.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRCSettings.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameReboot.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameReboot.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRoutingChange.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameRoutingChange.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetInstaller.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetInstaller.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetName.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetName.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetRoute.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetRoute.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetupStatus.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSetupStatus.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSignalStatus.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSignalStatus.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSignalStatusNew.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSignalStatusNew.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSysTemperature.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSysTemperature.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSystemStatus.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameSystemStatus.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTXRCAction.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTXRCAction.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTXRCKey.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTXRCKey.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTime.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTime.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTimeZone.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTimeZone.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTopology.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTopology.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTxIR.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameTxIR.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameUpgradeFPGA.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameUpgradeFPGA.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPAudio.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPAudio.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPBayMapping.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPBayMapping.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPDetectBays.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPDetectBays.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPLink.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPLink.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPManualSourceSwitch.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPManualSourceSwitch.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPMultiviewer.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPMultiviewer.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPPowerSave.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPPowerSave.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSetMaster.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSetMaster.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSettingsAll.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSettingsAll.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSourceSwitch.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSourceSwitch.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSources.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPSources.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPStats.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPStats.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPTestcard.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPTestcard.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPTiling.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPTiling.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPVideoWall.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameV2IPVideoWall.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolume.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolume.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolumeDown.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolumeDown.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolumeSet.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolumeSet.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolumeUp.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/FrameVolumeUp.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/LinkConfig.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/LinkConfig.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Multiviewer.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Multiviewer.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Svd.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/Svd.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/V2IPConfig.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/V2IPConfig.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/V2IPStats.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/V2IPStats.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/__init__.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/__init__.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/proto/svd.csv +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/py.typed +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Bay.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Bay.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/ConnectionAsync.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Link.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/Link.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/State.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/State.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/V2IP.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/mx_remote/remote/V2IP.pyi +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/pyproject.toml +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/audio_ir.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/audiolock.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/capture.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/complete.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/deprecated.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/e2e.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/entry.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/handlers_cover.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/hello.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/idempotent.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/lengths.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/merge.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/newops.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/offline.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/offsets.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/ping.py +1 -1
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/protogate.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/rcsettings.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/roundtrip.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/sources.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/stats.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/txresult.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/unknowns.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/v2ipscaling.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/v2ipsubject.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/v2iptestcard.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/v2ipvlan.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/vdetails.py +0 -0
- {mx_remote-6.2.0 → mx_remote-7.0.0}/tests/wirefix.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mx_remote
|
|
3
|
-
Version:
|
|
3
|
+
Version: 7.0.0
|
|
4
4
|
Summary: Python 3 library for interfacing with MX Remote compatible devices
|
|
5
5
|
Project-URL: Homepage, https://github.com/opdenkamp/mx-remote/
|
|
6
6
|
Project-URL: Documentation, https://opdenkamp.github.io/mx-remote/
|
|
@@ -94,6 +94,52 @@ bit, and the range of the infrared profiles.
|
|
|
94
94
|
.. autodata:: mx_remote.proto.Constants.ONEIP_VLAN_ID_MAX
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
+
## OneIP PTP
|
|
98
|
+
|
|
99
|
+
A device's PTP settings, which it reports and a controller writes, and the PTP
|
|
100
|
+
state only the device reports.
|
|
101
|
+
|
|
102
|
+
```{eval-rst}
|
|
103
|
+
.. autoclass:: mx_remote.OneIPPtpState
|
|
104
|
+
:members:
|
|
105
|
+
|
|
106
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPPtpMode
|
|
107
|
+
:members:
|
|
108
|
+
|
|
109
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPPtpFlag
|
|
110
|
+
:members:
|
|
111
|
+
|
|
112
|
+
.. autoclass:: mx_remote.proto.Constants.OneIPPtpLock
|
|
113
|
+
:members:
|
|
114
|
+
|
|
115
|
+
.. autodata:: mx_remote.proto.Constants.ONEIP_DEVICE_SETTINGS_PTP
|
|
116
|
+
|
|
117
|
+
.. autodata:: mx_remote.proto.Constants.ONEIP_PTP_DOMAIN_MAX
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Unit status and commands
|
|
121
|
+
|
|
122
|
+
A unit's health and IP configuration, and the commands sent to one unit.
|
|
123
|
+
|
|
124
|
+
```{eval-rst}
|
|
125
|
+
.. autoclass:: mx_remote.UnitStatus
|
|
126
|
+
:members:
|
|
127
|
+
|
|
128
|
+
.. autoclass:: mx_remote.UnitNetConfig
|
|
129
|
+
:members:
|
|
130
|
+
|
|
131
|
+
.. autoclass:: mx_remote.proto.Constants.UnitFlag
|
|
132
|
+
:members:
|
|
133
|
+
|
|
134
|
+
.. autoclass:: mx_remote.proto.Constants.UnitCommandKind
|
|
135
|
+
:members:
|
|
136
|
+
|
|
137
|
+
.. autoclass:: mx_remote.proto.Constants.UnitCommandFlag
|
|
138
|
+
:members:
|
|
139
|
+
|
|
140
|
+
.. autodata:: mx_remote.proto.Constants.UNIT_MAX_TEMPERATURES
|
|
141
|
+
```
|
|
142
|
+
|
|
97
143
|
## OneIP test card
|
|
98
144
|
|
|
99
145
|
A sink's test pattern, tone and lip-sync flash, and the ranges it accepts.
|
|
@@ -222,6 +222,35 @@ goes out at 176 bytes: a receiver with the schedule ignores the settings of a
|
|
|
222
222
|
shorter frame, and one whose settings end at the idle minutes takes it all the
|
|
223
223
|
same.
|
|
224
224
|
|
|
225
|
+
### PTP
|
|
226
|
+
|
|
227
|
+
A device's PTP mode, domain and grandmaster priority1 are settings like the
|
|
228
|
+
others, each behind its own bit.
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from mx_remote import OneIPPtpMode
|
|
232
|
+
|
|
233
|
+
print(settings.ptp_mode, settings.ptp_domain, settings.ptp_priority1)
|
|
234
|
+
|
|
235
|
+
await device.set_oneip_ptp_mode(OneIPPtpMode.AUTO) # follow, or lead when no one does
|
|
236
|
+
await device.set_oneip_ptp_domain(0) # up to ONEIP_PTP_DOMAIN_MAX
|
|
237
|
+
await device.set_oneip_ptp_priority1(128) # lower wins
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
A mode this library does not name and a domain above `ONEIP_PTP_DOMAIN_MAX` are
|
|
241
|
+
refused before they are sent, and not cached from another controller's write.
|
|
242
|
+
|
|
243
|
+
What the device's clock is actually doing is its PTP state, which only the
|
|
244
|
+
device reports about itself and nothing writes:
|
|
245
|
+
|
|
246
|
+
```python
|
|
247
|
+
ptp = device.oneip_ptp # None: no report yet, no PTP, or in power save
|
|
248
|
+
if ptp is not None:
|
|
249
|
+
print(ptp.mode, ptp.domain, ptp.lock, ptp.port_state) # port_state per IEEE 1588
|
|
250
|
+
print(ptp.followed) # locked to a master since PTP started
|
|
251
|
+
print(ptp.grandmaster) # its clock identity, None while there is none
|
|
252
|
+
```
|
|
253
|
+
|
|
225
254
|
### VLAN
|
|
226
255
|
|
|
227
256
|
A device that announces `DeviceFeature.VLAN` tags its uplink by a VLAN
|
|
@@ -300,7 +329,44 @@ await mx.set_all_oneip_device_settings(OneIPDeviceSettings(
|
|
|
300
329
|
Nothing is cached from it: each device that applies a change reports its
|
|
301
330
|
settings, and its `oneip_settings` reads that. What every device would ignore is
|
|
302
331
|
refused rather than sent - no setting at all, one only a device reports about
|
|
303
|
-
itself, a profile out of range, or a schedule time that
|
|
332
|
+
itself, a profile, PTP mode or PTP domain out of range, or a schedule time that
|
|
333
|
+
is not a time of day.
|
|
334
|
+
|
|
335
|
+
## Unit status and commands
|
|
336
|
+
|
|
337
|
+
A unit on protocol 0x2C reports its health and IP configuration with its
|
|
338
|
+
periodic broadcast, and within a few seconds of a change to its flags, status
|
|
339
|
+
or addresses.
|
|
340
|
+
|
|
341
|
+
```python
|
|
342
|
+
from mx_remote import UnitFlag
|
|
343
|
+
|
|
344
|
+
status = device.unit_status # None until the unit has reported
|
|
345
|
+
print(status.uptime, status.boot_count, status.reboot_count)
|
|
346
|
+
print(status.network) # address, netmask, gateway, two DNS servers
|
|
347
|
+
print(status.fan_rpm, status.temperatures, status.status_message)
|
|
348
|
+
print(UnitFlag.DHCP in status.flags, status.network_pending)
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
A unit takes a command only from its mesh controller or a management
|
|
352
|
+
application, which this client announces itself as:
|
|
353
|
+
|
|
354
|
+
```python
|
|
355
|
+
from mx_remote import UnitNetConfig
|
|
356
|
+
|
|
357
|
+
await device.clear_unit_status()
|
|
358
|
+
await device.upgrade_unit_video_processor(force=False)
|
|
359
|
+
await device.set_unit_network(UnitNetConfig(
|
|
360
|
+
ip='10.1.2.3', netmask='255.255.255.0', gateway='10.1.2.254', dns1='10.1.2.254'))
|
|
361
|
+
await device.confirm_unit_network() # keep it, once the unit reports it
|
|
362
|
+
await device.set_unit_dhcp()
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
A changed IP configuration applies at once and reverts unless the mesh
|
|
366
|
+
controller confirms it in time; `status.network_pending` says whether it still
|
|
367
|
+
waits. Each command returns False without sending for a device that is not a
|
|
368
|
+
OneIP unit, one below 0x2C, or an address and netmask a unit cannot hold.
|
|
369
|
+
Nothing acknowledges a command: `unit_status` reads what the unit reports next.
|
|
304
370
|
|
|
305
371
|
## Mesh and firmware
|
|
306
372
|
|
|
@@ -42,7 +42,7 @@ def mxr_valid_addresses() -> list[str]:
|
|
|
42
42
|
Get the list of valid local_ip addresses that can be used
|
|
43
43
|
|
|
44
44
|
Returns:
|
|
45
|
-
|
|
45
|
+
list[str]: the IP addresses that can be used for the local_ip parameter
|
|
46
46
|
"""
|
|
47
47
|
addresses:list[str] = []
|
|
48
48
|
for iface in netifaces.interfaces():
|
|
@@ -1946,6 +1946,133 @@ def _vlan_port_index(wire:int) -> int|None:
|
|
|
1946
1946
|
'''A port index from its 1-based wire form.'''
|
|
1947
1947
|
return (wire - 1) if (1 <= wire <= ONEIP_VLAN_PORTS) else None
|
|
1948
1948
|
|
|
1949
|
+
@dataclass(frozen=True)
|
|
1950
|
+
class UnitNetConfig:
|
|
1951
|
+
"""An IP configuration: the addresses a unit uses, or is told to use."""
|
|
1952
|
+
ip: str = '0.0.0.0'
|
|
1953
|
+
"""The address."""
|
|
1954
|
+
netmask: str = '0.0.0.0'
|
|
1955
|
+
"""The netmask."""
|
|
1956
|
+
gateway: str = '0.0.0.0'
|
|
1957
|
+
"""The gateway."""
|
|
1958
|
+
dns1: str = '0.0.0.0'
|
|
1959
|
+
"""The primary DNS server."""
|
|
1960
|
+
dns2: str = '0.0.0.0'
|
|
1961
|
+
"""The secondary DNS server."""
|
|
1962
|
+
|
|
1963
|
+
@property
|
|
1964
|
+
def addresses(self) -> tuple[str, str, str, str, str]:
|
|
1965
|
+
"""The five addresses, in the order the wire carries them."""
|
|
1966
|
+
return (self.ip, self.netmask, self.gateway, self.dns1, self.dns2)
|
|
1967
|
+
|
|
1968
|
+
def is_valid(self) -> bool:
|
|
1969
|
+
"""Whether every address parses, the address is one a unit can hold,
|
|
1970
|
+
and the netmask is a run of ones from the top."""
|
|
1971
|
+
try:
|
|
1972
|
+
for address in self.addresses:
|
|
1973
|
+
ipaddress.IPv4Address(address)
|
|
1974
|
+
ip = ipaddress.IPv4Address(self.ip)
|
|
1975
|
+
mask = int(ipaddress.IPv4Address(self.netmask))
|
|
1976
|
+
except ValueError:
|
|
1977
|
+
return False
|
|
1978
|
+
host = ~mask & 0xFFFFFFFF # all ones from the bottom for a valid netmask
|
|
1979
|
+
return not (ip.is_unspecified or ip.is_multicast or (int(ip) == 0xFFFFFFFF)) \
|
|
1980
|
+
and (mask != 0) and ((host & (host + 1)) == 0)
|
|
1981
|
+
|
|
1982
|
+
def __str__(self) -> str:
|
|
1983
|
+
return f"{self.ip}/{self.netmask} gw {self.gateway} dns {self.dns1} {self.dns2}"
|
|
1984
|
+
|
|
1985
|
+
@dataclass(frozen=True)
|
|
1986
|
+
class UnitStatus:
|
|
1987
|
+
"""
|
|
1988
|
+
A unit's health and IP configuration, as it last reported them.
|
|
1989
|
+
|
|
1990
|
+
A unit reports this about itself with its periodic broadcast, and within a
|
|
1991
|
+
few seconds of a change to its flags, its status or its addresses.
|
|
1992
|
+
"""
|
|
1993
|
+
flags: UnitFlag = UnitFlag(0)
|
|
1994
|
+
"""The report's flags."""
|
|
1995
|
+
uptime: int = 0
|
|
1996
|
+
"""Seconds since the unit booted."""
|
|
1997
|
+
boot_count: int|None = None
|
|
1998
|
+
"""How often the unit has booted, None while it does not report it."""
|
|
1999
|
+
reboot_count: int = 0
|
|
2000
|
+
"""How often the unit has rebooted."""
|
|
2001
|
+
encoder_health: int = 0
|
|
2002
|
+
"""The encoder's health, a mask of the unit's encoder status bits."""
|
|
2003
|
+
decoder_health: int = 0
|
|
2004
|
+
"""The decoder's health, a mask of the unit's decoder status and state bits."""
|
|
2005
|
+
network: UnitNetConfig = UnitNetConfig()
|
|
2006
|
+
"""The IP configuration in use."""
|
|
2007
|
+
fan_rpm: int|None = None
|
|
2008
|
+
"""The fan speed in RPM, None while the unit does not report it."""
|
|
2009
|
+
fan_duty: int = 0
|
|
2010
|
+
"""The fan duty cycle, in percent."""
|
|
2011
|
+
status: int = 0
|
|
2012
|
+
"""The unit's system status."""
|
|
2013
|
+
net_revert_s: int = 0
|
|
2014
|
+
"""Seconds before a pending IP configuration is reverted."""
|
|
2015
|
+
temperatures: tuple[int, ...] = ()
|
|
2016
|
+
"""Temperatures in degrees Celsius, at most UNIT_MAX_TEMPERATURES of them."""
|
|
2017
|
+
status_message: str = ''
|
|
2018
|
+
"""The message of the current system status."""
|
|
2019
|
+
|
|
2020
|
+
@property
|
|
2021
|
+
def network_pending(self) -> bool:
|
|
2022
|
+
"""Whether an IP configuration changed through the mesh waits for the
|
|
2023
|
+
mesh controller to confirm it."""
|
|
2024
|
+
return UnitFlag.NET_PENDING in self.flags
|
|
2025
|
+
|
|
2026
|
+
def __str__(self) -> str:
|
|
2027
|
+
return (f"up {self.uptime}s boots {self.boot_count} reboots {self.reboot_count} "
|
|
2028
|
+
f"encoder {self.encoder_health:#x} decoder {self.decoder_health:#x} net [{self.network}] "
|
|
2029
|
+
f"fan {self.fan_rpm} rpm {self.fan_duty}% status {self.status} '{self.status_message}' "
|
|
2030
|
+
f"temperatures {list(self.temperatures)} flags {self.flags!r}")
|
|
2031
|
+
|
|
2032
|
+
@dataclass(frozen=True)
|
|
2033
|
+
class OneIPPtpState:
|
|
2034
|
+
"""
|
|
2035
|
+
A OneIP device's PTP state, as it reports it about itself.
|
|
2036
|
+
|
|
2037
|
+
Only the device can read its own video processor, so this is never written
|
|
2038
|
+
to a device, and a controller's frame about one carries none.
|
|
2039
|
+
"""
|
|
2040
|
+
flags: OneIPPtpFlag = OneIPPtpFlag(0)
|
|
2041
|
+
"""The block's flags."""
|
|
2042
|
+
mode: OneIPPtpMode|int = OneIPPtpMode.OFF
|
|
2043
|
+
"""The mode the video processor runs; a raw int for one this library does
|
|
2044
|
+
not name."""
|
|
2045
|
+
domain: int = 0
|
|
2046
|
+
"""The domain the video processor runs in."""
|
|
2047
|
+
port_state: int = 0
|
|
2048
|
+
"""The IEEE 1588 portState."""
|
|
2049
|
+
lock: OneIPPtpLock|int = OneIPPtpLock.UNLOCKED
|
|
2050
|
+
"""How far the clock has locked; a raw int for a value this library does
|
|
2051
|
+
not name."""
|
|
2052
|
+
clock_identity: bytes = bytes(8)
|
|
2053
|
+
"""The device's own clock identity."""
|
|
2054
|
+
grandmaster_identity: bytes = bytes(8)
|
|
2055
|
+
"""The clock identity of the grandmaster the device runs on, all zero
|
|
2056
|
+
while it runs on none."""
|
|
2057
|
+
|
|
2058
|
+
@property
|
|
2059
|
+
def followed(self) -> bool:
|
|
2060
|
+
"""Whether the device locked to a master since its PTP started, so its
|
|
2061
|
+
mesh holds a time."""
|
|
2062
|
+
return OneIPPtpFlag.FOLLOWED in self.flags
|
|
2063
|
+
|
|
2064
|
+
@property
|
|
2065
|
+
def grandmaster(self) -> bytes|None:
|
|
2066
|
+
"""The grandmaster the device runs on, None while it runs on none."""
|
|
2067
|
+
return self.grandmaster_identity if any(self.grandmaster_identity) else None
|
|
2068
|
+
|
|
2069
|
+
def __str__(self) -> str:
|
|
2070
|
+
mode = self.mode.name.lower() if isinstance(self.mode, OneIPPtpMode) else self.mode
|
|
2071
|
+
lock = self.lock.name.lower() if isinstance(self.lock, OneIPPtpLock) else self.lock
|
|
2072
|
+
gm = self.grandmaster.hex(':') if (self.grandmaster is not None) else 'none'
|
|
2073
|
+
return (f"{mode} domain {self.domain} port state {self.port_state} {lock}"
|
|
2074
|
+
f"{' followed' if self.followed else ''} clock {self.clock_identity.hex(':')} grandmaster {gm}")
|
|
2075
|
+
|
|
1949
2076
|
@dataclass(frozen=True)
|
|
1950
2077
|
class OneIPVlan:
|
|
1951
2078
|
"""
|
|
@@ -2117,7 +2244,8 @@ class OneIPDeviceSettings:
|
|
|
2117
2244
|
def __init__(self, valid:OneIPDeviceSetting=OneIPDeviceSetting(0),
|
|
2118
2245
|
flags:OneIPDeviceSetting=OneIPDeviceSetting(0), ir_profiles:int=0,
|
|
2119
2246
|
ir_profile:int=0, ir_profile_sink:int=0, auto_power_save:int=0,
|
|
2120
|
-
power_save:OneIPPowerSaveSchedule|None=None
|
|
2247
|
+
power_save:OneIPPowerSaveSchedule|None=None, ptp_mode:OneIPPtpMode|int=OneIPPtpMode.OFF,
|
|
2248
|
+
ptp_domain:int=0, ptp_priority1:int=0) -> None:
|
|
2121
2249
|
self._valid = OneIPDeviceSetting(valid)
|
|
2122
2250
|
self._flags = OneIPDeviceSetting(flags)
|
|
2123
2251
|
self._ir_profiles = ir_profiles
|
|
@@ -2125,6 +2253,9 @@ class OneIPDeviceSettings:
|
|
|
2125
2253
|
self._ir_profile_sink = ir_profile_sink
|
|
2126
2254
|
self._auto_power_save = auto_power_save
|
|
2127
2255
|
self._power_save = power_save if (power_save is not None) else OneIPPowerSaveSchedule()
|
|
2256
|
+
self._ptp_mode = int(ptp_mode)
|
|
2257
|
+
self._ptp_domain = ptp_domain
|
|
2258
|
+
self._ptp_priority1 = ptp_priority1
|
|
2128
2259
|
|
|
2129
2260
|
@property
|
|
2130
2261
|
def valid(self) -> OneIPDeviceSetting:
|
|
@@ -2180,6 +2311,29 @@ class OneIPDeviceSettings:
|
|
|
2180
2311
|
return None
|
|
2181
2312
|
return self._power_save
|
|
2182
2313
|
|
|
2314
|
+
@property
|
|
2315
|
+
def ptp_mode(self) -> OneIPPtpMode|int|None:
|
|
2316
|
+
"""The PTP mode, a raw int for one this library does not name, None
|
|
2317
|
+
while it is not reported."""
|
|
2318
|
+
if (OneIPDeviceSetting.PTP_MODE not in self._valid):
|
|
2319
|
+
return None
|
|
2320
|
+
return _wire_enum(OneIPPtpMode, self._ptp_mode)
|
|
2321
|
+
|
|
2322
|
+
@property
|
|
2323
|
+
def ptp_domain(self) -> int|None:
|
|
2324
|
+
"""The PTP domain, up to ONEIP_PTP_DOMAIN_MAX, None while it is not reported."""
|
|
2325
|
+
if (OneIPDeviceSetting.PTP_DOMAIN not in self._valid):
|
|
2326
|
+
return None
|
|
2327
|
+
return self._ptp_domain
|
|
2328
|
+
|
|
2329
|
+
@property
|
|
2330
|
+
def ptp_priority1(self) -> int|None:
|
|
2331
|
+
"""The priority1 the device announces as a PTP grandmaster, lower
|
|
2332
|
+
winning, None while it is not reported."""
|
|
2333
|
+
if (OneIPDeviceSetting.PTP_PRIORITY1 not in self._valid):
|
|
2334
|
+
return None
|
|
2335
|
+
return self._ptp_priority1
|
|
2336
|
+
|
|
2183
2337
|
def merge(self, previous:'OneIPDeviceSettings|None') -> 'OneIPDeviceSettings':
|
|
2184
2338
|
"""
|
|
2185
2339
|
Fold this received block onto the cached one.
|
|
@@ -2203,31 +2357,46 @@ class OneIPDeviceSettings:
|
|
|
2203
2357
|
auto_power_save=(self._auto_power_save if (OneIPDeviceSetting.AUTO_POWER_SAVE in valid)
|
|
2204
2358
|
else previous._auto_power_save),
|
|
2205
2359
|
power_save=(self._power_save if (OneIPDeviceSetting.POWER_SAVE_SCHEDULE in valid)
|
|
2206
|
-
else previous._power_save)
|
|
2360
|
+
else previous._power_save),
|
|
2361
|
+
ptp_mode=(self._ptp_mode if (OneIPDeviceSetting.PTP_MODE in valid)
|
|
2362
|
+
else previous._ptp_mode),
|
|
2363
|
+
ptp_domain=(self._ptp_domain if (OneIPDeviceSetting.PTP_DOMAIN in valid)
|
|
2364
|
+
else previous._ptp_domain),
|
|
2365
|
+
ptp_priority1=(self._ptp_priority1 if (OneIPDeviceSetting.PTP_PRIORITY1 in valid)
|
|
2366
|
+
else previous._ptp_priority1))
|
|
2207
2367
|
|
|
2208
2368
|
def as_applied_to(self, reported:OneIPDeviceSetting) -> 'OneIPDeviceSettings':
|
|
2209
2369
|
"""
|
|
2210
2370
|
This block limited to what a device takes from a write about it.
|
|
2211
2371
|
|
|
2212
|
-
A device applies a setting only if it has it, a profile
|
|
2213
|
-
range, and never what only it can report about
|
|
2372
|
+
A device applies a setting only if it has it, a profile, PTP mode or PTP
|
|
2373
|
+
domain only within its range, and never what only it can report about
|
|
2374
|
+
itself.
|
|
2214
2375
|
"""
|
|
2215
2376
|
valid = (self._valid & reported) & ~ONEIP_DEVICE_SETTINGS_REPORTED_ONLY
|
|
2216
2377
|
if not (0 <= self._ir_profile < ONEIP_IR_PROFILE_MAX):
|
|
2217
2378
|
valid &= ~OneIPDeviceSetting.IR_PROFILE
|
|
2218
2379
|
if not (ONEIP_IR_PROFILE_NOT_SET <= self._ir_profile_sink < ONEIP_IR_PROFILE_MAX):
|
|
2219
2380
|
valid &= ~OneIPDeviceSetting.IR_PROFILE_SINK
|
|
2381
|
+
if (self._ptp_mode > OneIPPtpMode.AUTO):
|
|
2382
|
+
valid &= ~OneIPDeviceSetting.PTP_MODE
|
|
2383
|
+
if (self._ptp_domain > ONEIP_PTP_DOMAIN_MAX):
|
|
2384
|
+
valid &= ~OneIPDeviceSetting.PTP_DOMAIN
|
|
2220
2385
|
return OneIPDeviceSettings(valid=valid, flags=self._flags, ir_profiles=self._ir_profiles,
|
|
2221
2386
|
ir_profile=self._ir_profile, ir_profile_sink=self._ir_profile_sink,
|
|
2222
|
-
auto_power_save=self._auto_power_save, power_save=self._power_save
|
|
2387
|
+
auto_power_save=self._auto_power_save, power_save=self._power_save,
|
|
2388
|
+
ptp_mode=self._ptp_mode, ptp_domain=self._ptp_domain,
|
|
2389
|
+
ptp_priority1=self._ptp_priority1)
|
|
2223
2390
|
|
|
2224
2391
|
def __eq__(self, other:Any) -> bool:
|
|
2225
2392
|
if not isinstance(other, OneIPDeviceSettings):
|
|
2226
2393
|
return NotImplemented
|
|
2227
2394
|
return ((self._valid, self._flags, self._ir_profiles, self._ir_profile, self._ir_profile_sink,
|
|
2228
|
-
self._auto_power_save, self._power_save
|
|
2395
|
+
self._auto_power_save, self._power_save, self._ptp_mode, self._ptp_domain,
|
|
2396
|
+
self._ptp_priority1)
|
|
2229
2397
|
== (other._valid, other._flags, other._ir_profiles, other._ir_profile, other._ir_profile_sink,
|
|
2230
|
-
other._auto_power_save, other._power_save
|
|
2398
|
+
other._auto_power_save, other._power_save, other._ptp_mode, other._ptp_domain,
|
|
2399
|
+
other._ptp_priority1))
|
|
2231
2400
|
|
|
2232
2401
|
def __ne__(self, other:Any) -> bool:
|
|
2233
2402
|
result = self.__eq__(other)
|
|
@@ -2249,6 +2418,12 @@ class OneIPDeviceSettings:
|
|
|
2249
2418
|
parts.append(f"auto_power_save={self.auto_power_save}")
|
|
2250
2419
|
if (self.power_save_schedule is not None):
|
|
2251
2420
|
parts.append(f"power_save=[{self.power_save_schedule}]")
|
|
2421
|
+
if ((mode := self.ptp_mode) is not None):
|
|
2422
|
+
parts.append(f"ptp_mode={mode.name.lower() if isinstance(mode, OneIPPtpMode) else mode}")
|
|
2423
|
+
if (self.ptp_domain is not None):
|
|
2424
|
+
parts.append(f"ptp_domain={self.ptp_domain}")
|
|
2425
|
+
if (self.ptp_priority1 is not None):
|
|
2426
|
+
parts.append(f"ptp_priority1={self.ptp_priority1}")
|
|
2252
2427
|
return " ".join(parts)
|
|
2253
2428
|
|
|
2254
2429
|
def __repr__(self) -> str:
|
|
@@ -2575,6 +2750,39 @@ class DeviceBase(ABC):
|
|
|
2575
2750
|
'''The VLAN configuration this OneIP device last reported about itself,
|
|
2576
2751
|
None until it has reported one.'''
|
|
2577
2752
|
|
|
2753
|
+
@property
|
|
2754
|
+
@abstractmethod
|
|
2755
|
+
def unit_status(self) -> UnitStatus|None:
|
|
2756
|
+
'''The health and IP configuration this unit last reported, None until
|
|
2757
|
+
it has reported them.'''
|
|
2758
|
+
|
|
2759
|
+
@abstractmethod
|
|
2760
|
+
async def clear_unit_status(self) -> bool:
|
|
2761
|
+
'''clear the unit's current system status'''
|
|
2762
|
+
|
|
2763
|
+
@abstractmethod
|
|
2764
|
+
async def upgrade_unit_video_processor(self, force:bool=False) -> bool:
|
|
2765
|
+
'''upgrade the unit's video processor to the latest image it holds'''
|
|
2766
|
+
|
|
2767
|
+
@abstractmethod
|
|
2768
|
+
async def set_unit_dhcp(self) -> bool:
|
|
2769
|
+
'''switch the unit to an IP configuration from DHCP'''
|
|
2770
|
+
|
|
2771
|
+
@abstractmethod
|
|
2772
|
+
async def set_unit_network(self, network:UnitNetConfig) -> bool:
|
|
2773
|
+
'''give the unit a static IP configuration'''
|
|
2774
|
+
|
|
2775
|
+
@abstractmethod
|
|
2776
|
+
async def confirm_unit_network(self) -> bool:
|
|
2777
|
+
'''keep the unit's pending IP configuration'''
|
|
2778
|
+
|
|
2779
|
+
@property
|
|
2780
|
+
@abstractmethod
|
|
2781
|
+
def oneip_ptp(self) -> OneIPPtpState|None:
|
|
2782
|
+
'''The PTP state this OneIP device last reported about itself, None
|
|
2783
|
+
until it has reported one, and while it has no PTP to report: none on
|
|
2784
|
+
its video processor, or in power save.'''
|
|
2785
|
+
|
|
2578
2786
|
@property
|
|
2579
2787
|
@abstractmethod
|
|
2580
2788
|
def oneip_testcard(self) -> OneIPTestcard|None:
|
|
@@ -2848,6 +3056,18 @@ class DeviceBase(ABC):
|
|
|
2848
3056
|
async def set_oneip_power_save_schedule(self, schedule:OneIPPowerSaveSchedule) -> bool:
|
|
2849
3057
|
'''set the device's daily power save windows'''
|
|
2850
3058
|
|
|
3059
|
+
@abstractmethod
|
|
3060
|
+
async def set_oneip_ptp_mode(self, mode:OneIPPtpMode) -> bool:
|
|
3061
|
+
'''set the PTP mode the device runs'''
|
|
3062
|
+
|
|
3063
|
+
@abstractmethod
|
|
3064
|
+
async def set_oneip_ptp_domain(self, domain:int) -> bool:
|
|
3065
|
+
'''set the PTP domain the device runs in'''
|
|
3066
|
+
|
|
3067
|
+
@abstractmethod
|
|
3068
|
+
async def set_oneip_ptp_priority1(self, priority1:int) -> bool:
|
|
3069
|
+
'''set the priority1 the device announces as a PTP grandmaster'''
|
|
3070
|
+
|
|
2851
3071
|
@abstractmethod
|
|
2852
3072
|
async def set_oneip_vlan(self, vlan:OneIPVlan) -> bool:
|
|
2853
3073
|
'''change the device's VLAN configuration'''
|
|
@@ -696,6 +696,49 @@ class OneIPPowerSaveSchedule:
|
|
|
696
696
|
def __eq__(self, other: Any) -> bool: ...
|
|
697
697
|
def __hash__(self) -> int: ...
|
|
698
698
|
|
|
699
|
+
@dataclass(frozen=True)
|
|
700
|
+
class UnitNetConfig:
|
|
701
|
+
ip: str = ...
|
|
702
|
+
netmask: str = ...
|
|
703
|
+
gateway: str = ...
|
|
704
|
+
dns1: str = ...
|
|
705
|
+
dns2: str = ...
|
|
706
|
+
@property
|
|
707
|
+
def addresses(self) -> tuple[str, str, str, str, str]: ...
|
|
708
|
+
def is_valid(self) -> bool: ...
|
|
709
|
+
|
|
710
|
+
@dataclass(frozen=True)
|
|
711
|
+
class UnitStatus:
|
|
712
|
+
flags: UnitFlag = ...
|
|
713
|
+
uptime: int = ...
|
|
714
|
+
boot_count: int | None = ...
|
|
715
|
+
reboot_count: int = ...
|
|
716
|
+
encoder_health: int = ...
|
|
717
|
+
decoder_health: int = ...
|
|
718
|
+
network: UnitNetConfig = ...
|
|
719
|
+
fan_rpm: int | None = ...
|
|
720
|
+
fan_duty: int = ...
|
|
721
|
+
status: int = ...
|
|
722
|
+
net_revert_s: int = ...
|
|
723
|
+
temperatures: tuple[int, ...] = ...
|
|
724
|
+
status_message: str = ...
|
|
725
|
+
@property
|
|
726
|
+
def network_pending(self) -> bool: ...
|
|
727
|
+
|
|
728
|
+
@dataclass(frozen=True)
|
|
729
|
+
class OneIPPtpState:
|
|
730
|
+
flags: OneIPPtpFlag = ...
|
|
731
|
+
mode: OneIPPtpMode | int = ...
|
|
732
|
+
domain: int = ...
|
|
733
|
+
port_state: int = ...
|
|
734
|
+
lock: OneIPPtpLock | int = ...
|
|
735
|
+
clock_identity: bytes = ...
|
|
736
|
+
grandmaster_identity: bytes = ...
|
|
737
|
+
@property
|
|
738
|
+
def followed(self) -> bool: ...
|
|
739
|
+
@property
|
|
740
|
+
def grandmaster(self) -> bytes | None: ...
|
|
741
|
+
|
|
699
742
|
@dataclass(frozen=True)
|
|
700
743
|
class OneIPVlan:
|
|
701
744
|
flags: OneIPVlanFlag = ...
|
|
@@ -747,7 +790,7 @@ class OneIPTestcard:
|
|
|
747
790
|
def supported(self) -> bool: ...
|
|
748
791
|
|
|
749
792
|
class OneIPDeviceSettings:
|
|
750
|
-
def __init__(self, valid: OneIPDeviceSetting = ..., flags: OneIPDeviceSetting = ..., ir_profiles: int = 0, ir_profile: int = 0, ir_profile_sink: int = 0, auto_power_save: int = 0, power_save: OneIPPowerSaveSchedule | None = None) -> None: ...
|
|
793
|
+
def __init__(self, valid: OneIPDeviceSetting = ..., flags: OneIPDeviceSetting = ..., ir_profiles: int = 0, ir_profile: int = 0, ir_profile_sink: int = 0, auto_power_save: int = 0, power_save: OneIPPowerSaveSchedule | None = None, ptp_mode: OneIPPtpMode | int = ..., ptp_domain: int = 0, ptp_priority1: int = 0) -> None: ...
|
|
751
794
|
@property
|
|
752
795
|
def valid(self) -> OneIPDeviceSetting: ...
|
|
753
796
|
@property
|
|
@@ -763,6 +806,12 @@ class OneIPDeviceSettings:
|
|
|
763
806
|
def auto_power_save(self) -> int | None: ...
|
|
764
807
|
@property
|
|
765
808
|
def power_save_schedule(self) -> OneIPPowerSaveSchedule | None: ...
|
|
809
|
+
@property
|
|
810
|
+
def ptp_mode(self) -> OneIPPtpMode | int | None: ...
|
|
811
|
+
@property
|
|
812
|
+
def ptp_domain(self) -> int | None: ...
|
|
813
|
+
@property
|
|
814
|
+
def ptp_priority1(self) -> int | None: ...
|
|
766
815
|
def merge(self, previous: OneIPDeviceSettings | None) -> OneIPDeviceSettings: ...
|
|
767
816
|
def as_applied_to(self, reported: OneIPDeviceSetting) -> OneIPDeviceSettings: ...
|
|
768
817
|
def __eq__(self, other: Any) -> bool: ...
|
|
@@ -956,6 +1005,22 @@ class DeviceBase(ABC):
|
|
|
956
1005
|
def oneip_vlan(self) -> OneIPVlan | None: ...
|
|
957
1006
|
@property
|
|
958
1007
|
@abstractmethod
|
|
1008
|
+
def unit_status(self) -> UnitStatus | None: ...
|
|
1009
|
+
@abstractmethod
|
|
1010
|
+
async def clear_unit_status(self) -> bool: ...
|
|
1011
|
+
@abstractmethod
|
|
1012
|
+
async def upgrade_unit_video_processor(self, force: bool = False) -> bool: ...
|
|
1013
|
+
@abstractmethod
|
|
1014
|
+
async def set_unit_dhcp(self) -> bool: ...
|
|
1015
|
+
@abstractmethod
|
|
1016
|
+
async def set_unit_network(self, network: UnitNetConfig) -> bool: ...
|
|
1017
|
+
@abstractmethod
|
|
1018
|
+
async def confirm_unit_network(self) -> bool: ...
|
|
1019
|
+
@property
|
|
1020
|
+
@abstractmethod
|
|
1021
|
+
def oneip_ptp(self) -> OneIPPtpState | None: ...
|
|
1022
|
+
@property
|
|
1023
|
+
@abstractmethod
|
|
959
1024
|
def oneip_testcard(self) -> OneIPTestcard | None: ...
|
|
960
1025
|
@property
|
|
961
1026
|
@abstractmethod
|
|
@@ -1081,6 +1146,12 @@ class DeviceBase(ABC):
|
|
|
1081
1146
|
@abstractmethod
|
|
1082
1147
|
async def set_oneip_power_save_schedule(self, schedule: OneIPPowerSaveSchedule) -> bool: ...
|
|
1083
1148
|
@abstractmethod
|
|
1149
|
+
async def set_oneip_ptp_mode(self, mode: OneIPPtpMode) -> bool: ...
|
|
1150
|
+
@abstractmethod
|
|
1151
|
+
async def set_oneip_ptp_domain(self, domain: int) -> bool: ...
|
|
1152
|
+
@abstractmethod
|
|
1153
|
+
async def set_oneip_ptp_priority1(self, priority1: int) -> bool: ...
|
|
1154
|
+
@abstractmethod
|
|
1084
1155
|
async def set_oneip_vlan(self, vlan: OneIPVlan) -> bool: ...
|
|
1085
1156
|
@abstractmethod
|
|
1086
1157
|
async def set_audio_endpoint_locked(self, endpoint: int, locked: bool) -> bool: ...
|