mx-remote 5.11.0__tar.gz → 6.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.
Files changed (247) hide show
  1. {mx_remote-5.11.0 → mx_remote-6.2.0}/AGENTS.md +11 -0
  2. {mx_remote-5.11.0 → mx_remote-6.2.0}/PKG-INFO +2 -2
  3. {mx_remote-5.11.0 → mx_remote-6.2.0}/README.md +1 -1
  4. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/README.md +1 -1
  5. mx_remote-6.2.0/docs/api.md +167 -0
  6. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/audio.md +20 -0
  7. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/configuration.md +1 -1
  8. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/oneip.md +113 -38
  9. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/Interface.py +442 -160
  10. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/Interface.pyi +158 -72
  11. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/__init__.py +8 -2
  12. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/const.py +4 -4
  13. mx_remote-6.2.0/mx_remote/deprecated.py +80 -0
  14. mx_remote-6.2.0/mx_remote/deprecated.pyi +16 -0
  15. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Constants.py +186 -58
  16. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Constants.pyi +77 -21
  17. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Factory.py +3 -0
  18. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayStatus.py +1 -1
  19. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameMeshOperation.py +11 -0
  20. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameMeshOperation.pyi +3 -0
  21. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameMirrorStatus.py +2 -2
  22. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTimeZone.py +12 -1
  23. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTimeZone.pyi +2 -0
  24. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameUpgradeFPGA.py +2 -2
  25. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPAudio.py +66 -12
  26. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPAudio.pyi +25 -5
  27. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPBayMapping.py +2 -2
  28. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPDetectBays.py +4 -4
  29. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPDeviceConfiguration.py +99 -41
  30. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPDeviceConfiguration.pyi +15 -11
  31. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPLink.py +2 -2
  32. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPManualSourceSwitch.py +9 -9
  33. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPManualSourceSwitch.pyi +4 -4
  34. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPMultiviewer.py +2 -2
  35. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPPowerSave.py +2 -2
  36. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSetMaster.py +2 -2
  37. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSettingsAll.py +6 -6
  38. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSettingsAll.pyi +3 -3
  39. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSourceSwitch.py +10 -10
  40. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSources.py +8 -8
  41. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSources.pyi +2 -2
  42. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPStats.py +6 -6
  43. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPStats.pyi +2 -2
  44. mx_remote-6.2.0/mx_remote/proto/FrameV2IPTestcard.py +107 -0
  45. mx_remote-6.2.0/mx_remote/proto/FrameV2IPTestcard.pyi +28 -0
  46. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPTiling.py +2 -2
  47. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPVideoWall.py +1 -1
  48. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/V2IPConfig.py +19 -19
  49. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/V2IPConfig.pyi +12 -12
  50. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/V2IPStats.py +11 -5
  51. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/V2IPStats.pyi +1 -1
  52. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Bay.py +38 -38
  53. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Bay.pyi +11 -11
  54. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Device.py +316 -138
  55. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Device.pyi +49 -34
  56. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Remote.py +29 -18
  57. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Remote.pyi +4 -3
  58. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/V2IP.py +13 -13
  59. mx_remote-6.2.0/mx_remote/remote/V2IP.pyi +28 -0
  60. mx_remote-6.2.0/tests/audiolock.py +119 -0
  61. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/complete.py +7 -7
  62. mx_remote-6.2.0/tests/deprecated.py +205 -0
  63. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/e2e.py +4 -4
  64. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/handlers.py +2 -0
  65. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/handlers_cover.py +16 -16
  66. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/merge.py +16 -10
  67. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/mesh.py +74 -21
  68. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/ping.py +1 -1
  69. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/proto_stamp.py +1 -0
  70. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/run.py +4 -0
  71. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/smoke.py +8 -8
  72. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/sources.py +2 -2
  73. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/stats.py +3 -3
  74. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/txresult.py +7 -7
  75. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/unknowns.py +1 -1
  76. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/v2ipscaling.py +76 -25
  77. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/v2ipsettings.py +54 -54
  78. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/v2ipsubject.py +36 -36
  79. mx_remote-6.2.0/tests/v2iptestcard.py +179 -0
  80. mx_remote-6.2.0/tests/v2ipvlan.py +152 -0
  81. mx_remote-5.11.0/docs/api.md +0 -95
  82. mx_remote-5.11.0/mx_remote/remote/V2IP.pyi +0 -28
  83. {mx_remote-5.11.0 → mx_remote-6.2.0}/.gitignore +0 -0
  84. {mx_remote-5.11.0 → mx_remote-6.2.0}/CLAUDE.md +0 -0
  85. {mx_remote-5.11.0 → mx_remote-6.2.0}/LICENSE +0 -0
  86. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/_static/brand.css +0 -0
  87. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/_static/favicon.svg +0 -0
  88. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/_static/logo-dark.svg +0 -0
  89. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/_static/logo.svg +0 -0
  90. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/callbacks.md +0 -0
  91. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/conf.py +0 -0
  92. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/devices-and-bays.md +0 -0
  93. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/diagnostics.md +0 -0
  94. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/index.md +0 -0
  95. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/multiviewer.md +0 -0
  96. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/requirements.txt +0 -0
  97. {mx_remote-5.11.0 → mx_remote-6.2.0}/docs/routing.md +0 -0
  98. {mx_remote-5.11.0 → mx_remote-6.2.0}/hatch_build.py +0 -0
  99. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/Uid.py +0 -0
  100. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/Uid.pyi +0 -0
  101. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/__init__.pyi +0 -0
  102. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/compat.py +0 -0
  103. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/compat.pyi +0 -0
  104. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/const.pyi +0 -0
  105. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/main.py +0 -0
  106. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/main.pyi +0 -0
  107. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/BayConfig.py +0 -0
  108. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/BayConfig.pyi +0 -0
  109. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Data.py +0 -0
  110. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Data.pyi +0 -0
  111. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Factory.pyi +0 -0
  112. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAmpDolbySettings.py +0 -0
  113. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAmpDolbySettings.pyi +0 -0
  114. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAmpZoneSettings.py +0 -0
  115. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAmpZoneSettings.pyi +0 -0
  116. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAudioClip.py +0 -0
  117. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAudioClip.pyi +0 -0
  118. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAudioSetRoute.py +0 -0
  119. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameAudioSetRoute.pyi +0 -0
  120. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBase.py +0 -0
  121. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBase.pyi +0 -0
  122. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayConfig.py +0 -0
  123. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayConfig.pyi +0 -0
  124. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayConfigSecondary.py +0 -0
  125. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayConfigSecondary.pyi +0 -0
  126. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayHide.py +0 -0
  127. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayHide.pyi +0 -0
  128. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameBayStatus.pyi +0 -0
  129. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameConnectStatus.py +0 -0
  130. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameConnectStatus.pyi +0 -0
  131. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameDebug.py +0 -0
  132. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameDebug.pyi +0 -0
  133. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameDiscover.py +0 -0
  134. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameDiscover.pyi +0 -0
  135. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameEDID.py +0 -0
  136. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameEDID.pyi +0 -0
  137. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameEDIDProfile.py +0 -0
  138. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameEDIDProfile.pyi +0 -0
  139. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameFactoryReset.py +0 -0
  140. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameFactoryReset.pyi +0 -0
  141. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameFilterStatus.py +0 -0
  142. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameFilterStatus.pyi +0 -0
  143. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameFirmwareVersion.py +0 -0
  144. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameFirmwareVersion.pyi +0 -0
  145. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameHeader.py +0 -0
  146. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameHeader.pyi +0 -0
  147. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameHello.py +0 -0
  148. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameHello.pyi +0 -0
  149. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameLinks.py +0 -0
  150. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameLinks.pyi +0 -0
  151. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameMirrorStatus.pyi +0 -0
  152. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameMonitoringPulse.py +0 -0
  153. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameMonitoringPulse.pyi +0 -0
  154. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameNetworkStatus.py +0 -0
  155. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameNetworkStatus.pyi +0 -0
  156. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FramePing.py +0 -0
  157. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FramePing.pyi +0 -0
  158. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FramePowerChange.py +0 -0
  159. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FramePowerChange.pyi +0 -0
  160. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCAction.py +0 -0
  161. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCAction.pyi +0 -0
  162. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCIr.py +0 -0
  163. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCIr.pyi +0 -0
  164. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCKey.py +0 -0
  165. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCKey.pyi +0 -0
  166. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCSettings.py +0 -0
  167. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRCSettings.pyi +0 -0
  168. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameReboot.py +0 -0
  169. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameReboot.pyi +0 -0
  170. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRoutingChange.py +0 -0
  171. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameRoutingChange.pyi +0 -0
  172. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetInstaller.py +0 -0
  173. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetInstaller.pyi +0 -0
  174. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetName.py +0 -0
  175. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetName.pyi +0 -0
  176. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetRoute.py +0 -0
  177. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetRoute.pyi +0 -0
  178. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetupStatus.py +0 -0
  179. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSetupStatus.pyi +0 -0
  180. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSignalStatus.py +0 -0
  181. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSignalStatus.pyi +0 -0
  182. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSignalStatusNew.py +0 -0
  183. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSignalStatusNew.pyi +0 -0
  184. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSysTemperature.py +0 -0
  185. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSysTemperature.pyi +0 -0
  186. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSystemStatus.py +0 -0
  187. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameSystemStatus.pyi +0 -0
  188. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTXRCAction.py +0 -0
  189. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTXRCAction.pyi +0 -0
  190. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTXRCKey.py +0 -0
  191. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTXRCKey.pyi +0 -0
  192. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTime.py +0 -0
  193. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTime.pyi +0 -0
  194. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTopology.py +0 -0
  195. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTopology.pyi +0 -0
  196. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTxIR.py +0 -0
  197. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameTxIR.pyi +0 -0
  198. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameUpgradeFPGA.pyi +0 -0
  199. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPBayMapping.pyi +0 -0
  200. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPDetectBays.pyi +0 -0
  201. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPLink.pyi +0 -0
  202. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPMultiviewer.pyi +0 -0
  203. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPPowerSave.pyi +0 -0
  204. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSetMaster.pyi +0 -0
  205. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPSourceSwitch.pyi +0 -0
  206. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPTiling.pyi +0 -0
  207. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameV2IPVideoWall.pyi +0 -0
  208. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolume.py +0 -0
  209. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolume.pyi +0 -0
  210. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolumeDown.py +0 -0
  211. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolumeDown.pyi +0 -0
  212. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolumeSet.py +0 -0
  213. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolumeSet.pyi +0 -0
  214. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolumeUp.py +0 -0
  215. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/FrameVolumeUp.pyi +0 -0
  216. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/LinkConfig.py +0 -0
  217. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/LinkConfig.pyi +0 -0
  218. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Multiviewer.py +0 -0
  219. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Multiviewer.pyi +0 -0
  220. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Svd.py +0 -0
  221. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/Svd.pyi +0 -0
  222. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/__init__.py +0 -0
  223. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/__init__.pyi +0 -0
  224. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/proto/svd.csv +0 -0
  225. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/py.typed +0 -0
  226. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/ConnectionAsync.py +0 -0
  227. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/ConnectionAsync.pyi +0 -0
  228. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Link.py +0 -0
  229. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/Link.pyi +0 -0
  230. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/State.py +0 -0
  231. {mx_remote-5.11.0 → mx_remote-6.2.0}/mx_remote/remote/State.pyi +0 -0
  232. {mx_remote-5.11.0 → mx_remote-6.2.0}/pyproject.toml +0 -0
  233. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/audio_ir.py +0 -0
  234. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/capture.py +0 -0
  235. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/entry.py +0 -0
  236. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/hello.py +0 -0
  237. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/idempotent.py +0 -0
  238. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/lengths.py +0 -0
  239. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/newops.py +0 -0
  240. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/offline.py +0 -0
  241. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/offsets.py +0 -0
  242. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/protogate.py +0 -0
  243. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/rcsettings.py +0 -0
  244. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/roundtrip.py +0 -0
  245. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/structs.py +0 -0
  246. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/vdetails.py +0 -0
  247. {mx_remote-5.11.0 → mx_remote-6.2.0}/tests/wirefix.py +0 -0
@@ -163,6 +163,17 @@ A 24-byte header, then the payload:
163
163
 
164
164
  Built by `proto/Factory.py::create_mxr_frame`, decoded by `proto/FrameHeader.py`.
165
165
 
166
+ ## Public names
167
+
168
+ V2IP and FPGA are the firmware's internal names. What a user reads - API
169
+ names, docstrings, log messages, console output, docs - says OneIP and video
170
+ processor instead (`oneip_settings`, `OneIPVideoProcessorFeature`), including
171
+ for a name ported from the firmware or the Rust crate, which keep the internal
172
+ spelling. Wire-level code under `proto/` that mirrors a firmware struct may keep
173
+ it too. The names released before the rename resolve through
174
+ `mx_remote/deprecated.py`, and `tests/deprecated.py` fails on any new public
175
+ name spelled V2IP or FPGA.
176
+
166
177
  ## Working on the protocol
167
178
 
168
179
  When adding or editing a `Frame*` class, byte layouts **must match the MatrixOS firmware C
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: mx_remote
3
- Version: 5.11.0
3
+ Version: 6.2.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/
@@ -112,7 +112,7 @@ API reference generated from the docstrings, and are readable here in
112
112
  | [Routing](docs/routing.md) | Selecting video and audio sources for an output. |
113
113
  | [Callbacks](docs/callbacks.md) | Reacting to state changes rather than polling for them. |
114
114
  | [Audio](docs/audio.md) | Volume, mute and remote-control passthrough. |
115
- | [OneIP and V2IP](docs/oneip.md) | Streaming endpoints, stream sources and statistics. |
115
+ | [OneIP](docs/oneip.md) | Streaming endpoints, stream sources and statistics. |
116
116
  | [Multiviewer](docs/multiviewer.md) | Layout, sources and output configuration. |
117
117
  | [Diagnostics](docs/diagnostics.md) | Network status, the mxr console app and capture replay. |
118
118
 
@@ -79,7 +79,7 @@ API reference generated from the docstrings, and are readable here in
79
79
  | [Routing](docs/routing.md) | Selecting video and audio sources for an output. |
80
80
  | [Callbacks](docs/callbacks.md) | Reacting to state changes rather than polling for them. |
81
81
  | [Audio](docs/audio.md) | Volume, mute and remote-control passthrough. |
82
- | [OneIP and V2IP](docs/oneip.md) | Streaming endpoints, stream sources and statistics. |
82
+ | [OneIP](docs/oneip.md) | Streaming endpoints, stream sources and statistics. |
83
83
  | [Multiviewer](docs/multiviewer.md) | Layout, sources and output configuration. |
84
84
  | [Diagnostics](docs/diagnostics.md) | Network status, the mxr console app and capture replay. |
85
85
 
@@ -9,6 +9,6 @@ The API reference for `mx_remote`. Start at the [project README](https://github.
9
9
  | [Routing](routing.md) | Selecting video and audio sources for an output. |
10
10
  | [Callbacks](callbacks.md) | Reacting to state changes rather than polling for them. |
11
11
  | [Audio](audio.md) | Volume, mute and remote-control passthrough. |
12
- | [OneIP and V2IP](oneip.md) | Streaming endpoints, stream sources and statistics. |
12
+ | [OneIP](oneip.md) | Streaming endpoints, stream sources and statistics. |
13
13
  | [Multiviewer](multiviewer.md) | Layout, sources and output configuration. |
14
14
  | [Diagnostics](diagnostics.md) | Network status, the mxr console app and capture replay. |
@@ -0,0 +1,167 @@
1
+ # API reference
2
+
3
+ Generated from the docstrings in the package. The guides cover how these fit
4
+ together; this page is the exhaustive list.
5
+
6
+ Autodoc emits reStructuredText, which the markdown parser does not read, so
7
+ every directive below sits in an `eval-rst` block. Without it the page renders
8
+ the directive source as prose and the build still succeeds.
9
+
10
+ ```{eval-rst}
11
+ .. automodule:: mx_remote
12
+ ```
13
+
14
+ ## Client
15
+
16
+ `Remote` owns the socket, the device registry and the background probe that
17
+ keeps both in step with the mesh.
18
+
19
+ ```{eval-rst}
20
+ .. automodule:: mx_remote.remote.Remote
21
+ :members:
22
+ ```
23
+
24
+ ## Devices, bays and callbacks
25
+
26
+ A client works against these types rather than the classes implementing them:
27
+ they are what the registry hands out and what a callback receives.
28
+
29
+ ```{eval-rst}
30
+ .. automodule:: mx_remote.Interface
31
+ :members:
32
+ ```
33
+
34
+ ## Device identity
35
+
36
+ ```{eval-rst}
37
+ .. automodule:: mx_remote.Uid
38
+ :members:
39
+ ```
40
+
41
+ ## Remote-control keys and actions
42
+
43
+ The key and action codes a bay reports, and the target a key was aimed at.
44
+
45
+ ```{eval-rst}
46
+ .. autoclass:: mx_remote.proto.Constants.RCKey
47
+ :members:
48
+ :undoc-members:
49
+
50
+ .. autoclass:: mx_remote.proto.Constants.RCAction
51
+ :members:
52
+ :undoc-members:
53
+
54
+ .. autoclass:: mx_remote.proto.Constants.RCType
55
+ :members:
56
+ :undoc-members:
57
+
58
+ .. autodata:: mx_remote.proto.Constants.MXR_PROTOCOL_VERSION
59
+ ```
60
+
61
+ ## OneIP device settings
62
+
63
+ The settings a OneIP device reports and a controller writes, each behind its own
64
+ bit, and the range of the infrared profiles.
65
+
66
+ ```{eval-rst}
67
+ .. autoclass:: mx_remote.proto.Constants.OneIPDeviceSetting
68
+ :members:
69
+ :undoc-members:
70
+
71
+ .. autodata:: mx_remote.proto.Constants.ONEIP_DEVICE_SETTING_SWITCHES
72
+
73
+ .. autodata:: mx_remote.proto.Constants.ONEIP_IR_PROFILE_NOT_SET
74
+
75
+ .. autodata:: mx_remote.proto.Constants.ONEIP_IR_PROFILE_MAX
76
+
77
+ .. autodata:: mx_remote.proto.Constants.ONEIP_DEVICE_SETTINGS_REPORTED_ONLY
78
+
79
+ .. autodata:: mx_remote.proto.Constants.ONEIP_MINUTES_PER_DAY
80
+
81
+ .. autoclass:: mx_remote.OneIPPowerSaveSchedule
82
+ :members:
83
+
84
+ .. autoclass:: mx_remote.OneIPVlan
85
+ :members:
86
+
87
+ .. autoclass:: mx_remote.proto.Constants.OneIPVlanFlag
88
+ :members:
89
+
90
+ .. autodata:: mx_remote.proto.Constants.ONEIP_VLAN_PORTS
91
+
92
+ .. autodata:: mx_remote.proto.Constants.ONEIP_VLAN_PORT_SFP
93
+
94
+ .. autodata:: mx_remote.proto.Constants.ONEIP_VLAN_ID_MAX
95
+ ```
96
+
97
+ ## OneIP test card
98
+
99
+ A sink's test pattern, tone and lip-sync flash, and the ranges it accepts.
100
+
101
+ ```{eval-rst}
102
+ .. autoclass:: mx_remote.OneIPTestcard
103
+ :members:
104
+
105
+ .. autoclass:: mx_remote.OneIPTestTone
106
+ :members:
107
+
108
+ .. autoclass:: mx_remote.OneIPTestSync
109
+ :members:
110
+
111
+ .. autoclass:: mx_remote.proto.Constants.OneIPTestPattern
112
+ :members:
113
+
114
+ .. autoclass:: mx_remote.proto.Constants.OneIPToneMode
115
+ :members:
116
+
117
+ .. autoclass:: mx_remote.proto.Constants.OneIPTestcardFlag
118
+ :members:
119
+
120
+ .. autodata:: mx_remote.proto.Constants.ONEIP_TONE_FREQ_MIN
121
+
122
+ .. autodata:: mx_remote.proto.Constants.ONEIP_TONE_FREQ_MAX
123
+
124
+ .. autodata:: mx_remote.proto.Constants.ONEIP_TONE_LEVEL_MIN
125
+
126
+ .. autodata:: mx_remote.proto.Constants.ONEIP_TONE_CHANNELS_MAX
127
+
128
+ .. autodata:: mx_remote.proto.Constants.ONEIP_TONE_RATES
129
+
130
+ .. autodata:: mx_remote.proto.Constants.ONEIP_SYNC_OFFSET_MAX
131
+
132
+ .. autodata:: mx_remote.proto.Constants.ONEIP_SYNC_BEEP_MS_MIN
133
+
134
+ .. autodata:: mx_remote.proto.Constants.ONEIP_SYNC_BEEP_MS_MAX
135
+ ```
136
+
137
+ ## Mesh time
138
+
139
+ The time zone and clock a mesh controller announces.
140
+
141
+ ```{eval-rst}
142
+ .. autoclass:: mx_remote.TimeZone
143
+ :members:
144
+
145
+ .. autoclass:: mx_remote.DeviceClock
146
+ :members:
147
+ ```
148
+
149
+ ## Names from before OneIP
150
+
151
+ Releases up to 5.11 used the firmware's internal names in the public API: V2IP
152
+ for OneIP and FPGA for the video processor. Each old name maps to the new one
153
+ by spelling alone - `V2IP` becomes `OneIP` (`ONEIP` in a constant, `oneip` in
154
+ a member), and `Fpga` or `FPGA` becomes `VideoProcessor` or `VIDEO_PROCESSOR`:
155
+ `device.v2ip_settings` is `device.oneip_settings`, `V2IPFpgaFeature` is
156
+ `OneIPVideoProcessorFeature`, `FirmwareType.FPGA` is
157
+ `FirmwareType.VIDEO_PROCESSOR`.
158
+
159
+ The old names still resolve. A module-level name or a class member raises a
160
+ `DeprecationWarning` naming its replacement; an enum member and an
161
+ `AudioFeatures` bit constant are plain aliases, since those cannot warn. The old
162
+ names are left out of `from mx_remote import *` and out of the type stubs, so a
163
+ type checker reports them, and they will be removed in a future major release.
164
+
165
+ One rename has no alias: a OneIP device's `temperatures` dict reports the video
166
+ processor's sensor under `'Video Processor'`, where it used `'FPGA'`.
167
+
@@ -12,6 +12,26 @@ bay.volume_set(volume=50, muted=False)
12
12
  bay.mute_set(mute=True)
13
13
  ```
14
14
 
15
+ ## Audio endpoints
16
+
17
+ A OneIP device reports its audio endpoints, each with its features and a status
18
+ word on the same bits: `FEATURE_MUTE` while it is muted, `FEATURE_TRIGGER`
19
+ while its trigger is active, and `FEATURE_AUDIO_LOCK` while its audio source is
20
+ locked.
21
+
22
+ ```python
23
+ ep = device.audio_endpoint_by_id(1)
24
+ print(ep.features, ep.status, ep.audio_locked)
25
+
26
+ # keep the endpoint's audio source when the video route changes
27
+ await device.set_audio_endpoint_locked(1, True)
28
+ ```
29
+
30
+ Only an endpoint whose features include `FEATURE_AUDIO_LOCK` is written, since
31
+ the device ignores the rest. The device answers by reporting its endpoints
32
+ again, so `audio_locked` reads the lock once that report arrives, and a report
33
+ whose only change is a status fires the device's callbacks.
34
+
15
35
  ## Remote Control
16
36
 
17
37
  Send remote control key presses and actions:
@@ -57,7 +57,7 @@ device.config_initialised # False if the device broadcasts config blocks built
57
57
  device.temperatures # dict of temperature sensor readings
58
58
 
59
59
  # device type checks
60
- device.is_v2ip # Pulse-Eight OneIP HDMI-over-IP device
60
+ device.is_oneip # Pulse-Eight OneIP HDMI-over-IP device
61
61
  device.is_video_matrix # neo video matrix
62
62
  device.is_audio_matrix # audio-only matrix
63
63
  device.is_amp # ProAmp8 audio amplifier
@@ -1,15 +1,21 @@
1
- # OneIP and V2IP
1
+ # OneIP
2
2
 
3
3
  Streaming endpoints, stream sources and statistics.
4
4
 
5
+ Releases up to 5.11 named this API after the firmware's internal names: V2IP
6
+ for OneIP and FPGA for the video processor, as in `device.v2ip_settings` or
7
+ `V2IPFpgaFeature`. Those spellings still work, with a `DeprecationWarning`,
8
+ and will be removed in a future major release; see
9
+ [the API reference](api.md#names-from-before-oneip).
10
+
5
11
  ## Pulse-Eight OneIP Devices
6
12
 
7
13
  [Pulse-Eight OneIP](https://www.pulse-eight.com/p/248/oneip-tx) HDMI-over-IP devices expose additional streaming properties:
8
14
 
9
15
  ```python
10
16
  # stream source addresses
11
- if device.is_v2ip and device.v2ip_sources:
12
- for source in device.v2ip_sources:
17
+ if device.is_oneip and device.oneip_sources:
18
+ for source in device.oneip_sources:
13
19
  print(f"Video: {source.video.ip}:{source.video.port}")
14
20
  print(f"Audio: {source.audio.ip}:{source.audio.port}")
15
21
 
@@ -17,8 +23,8 @@ if device.is_v2ip and device.v2ip_sources:
17
23
  # A configuration frame names its subject in the payload, so a controller's
18
24
  # write for a transceiver reaches the transceiver's record - the controller's
19
25
  # own stays empty, which is what the device always meant.
20
- if device.v2ip_details:
21
- details = device.v2ip_details
26
+ if device.oneip_details:
27
+ details = device.oneip_details
22
28
  print(f"Video: {details.video}")
23
29
  print(f"TX rate: {details.tx_rate}") # None when the sender offered no rate
24
30
 
@@ -31,7 +37,7 @@ if device.v2ip_details:
31
37
  # mode, so call this again inside the minute to keep the 1Hz reports coming.
32
38
  await device.read_stats(enable=True) # start collecting
33
39
  # ... later ...
34
- stats = device.v2ip_stats
40
+ stats = device.oneip_stats
35
41
 
36
42
  # what the sink's decoder recovered from the codestream it is being given.
37
43
  # Three answers, and they mean different things:
@@ -69,7 +75,7 @@ the query is sent, so a single tick can carry an answer read fractionally
69
75
  before the switch.
70
76
 
71
77
  ```python
72
- before = device.v2ip_stats.decoder.reading.updates
78
+ before = device.oneip_stats.decoder.reading.updates
73
79
  await sink.switch_source(...)
74
80
  # ... wait until reading.updates - before >= 2 (mod 65536) ...
75
81
  ```
@@ -104,21 +110,21 @@ the other where it is.
104
110
  # what the sink reports. Trust this block only from a device whose hello carries
105
111
  # CONFIG_INITIALISED - firmware without it builds the block over uninitialised
106
112
  # stack, where the valid bit itself is noise.
107
- scaling = device.v2ip_details.scaling
113
+ scaling = device.oneip_details.scaling
108
114
  print(scaling.auto_scaling) # None when the sender did not say
109
115
  print(scaling.configured_mode) # (signal type, refresh), None when it has none
110
116
 
111
117
  # a mode is given as a depth and a colour space, never as a packed signal-type
112
118
  # word read back off the wire: a sink with no mode reports the word carrying the
113
119
  # index for "no depth", which a receiver decodes to zero and drops in silence.
114
- mode = mx_remote.V2IPOutputMode(svd=16, depth=12,
120
+ mode = mx_remote.OneIPOutputMode(svd=16, depth=12,
115
121
  colour=mx_remote.VideoColourSpace.YUV422, refresh=60)
116
122
 
117
- await device.set_v2ip_auto_scaling(False) # turn it off before setting a mode
118
- await device.set_v2ip_output_mode(mode)
119
- await device.set_v2ip_auto_scaling(True) # back on, if that is what you want
123
+ await device.set_oneip_auto_scaling(False) # turn it off before setting a mode
124
+ await device.set_oneip_output_mode(mode)
125
+ await device.set_oneip_auto_scaling(True) # back on, if that is what you want
120
126
 
121
- await device.clear_v2ip_output_mode() # the only way to say "no mode"
127
+ await device.clear_oneip_output_mode() # the only way to say "no mode"
122
128
  ```
123
129
 
124
130
  **Set the mode with automatic scaling off.** A sink scaling automatically
@@ -127,19 +133,19 @@ in silence. Setting the mode first and turning automatic scaling back on
127
133
  afterwards is the order that survives, because the mode is checked while
128
134
  automatic scaling is still off.
129
135
 
130
- Nothing acknowledges any of these. `set_v2ip_output_mode` returns False for a
136
+ Nothing acknowledges any of these. `set_oneip_output_mode` returns False for a
131
137
  mode no sink would take, but a True only says the frame went out: the sink
132
138
  weighs the format against the display's EDID and against what its own output
133
- stage can produce, and refuses silently either way. Read `v2ip_details.scaling`
139
+ stage can produce, and refuses silently either way. Read `oneip_details.scaling`
134
140
  back on the device's next report to learn what it did.
135
141
 
136
142
  A scaling change makes the device rebuild and rebroadcast its sink block, so
137
- expect `device.v2ip_sink` to read empty for a moment afterwards - see
143
+ expect `device.oneip_sink` to read empty for a moment afterwards - see
138
144
  [what an empty sink block means](#what-an-empty-sink-block-means).
139
145
 
140
146
  ## What an empty sink block means
141
147
 
142
- `device.v2ip_sink` addresses that read as unset mean "no route, or the sink
148
+ `device.oneip_sink` addresses that read as unset mean "no route, or the sink
143
149
  could not work one out", never "definitely not subscribed". This is the one part
144
150
  of a device configuration with no validity marker of its own, so a sink with
145
151
  nothing to say sends zeros and the library stores them. A sender leaves it
@@ -163,29 +169,29 @@ device's configuration sends it zeroed, and the library ignores that copy.
163
169
 
164
170
  ## Device settings
165
171
 
166
- A V2IP device reports its settings in its configuration: decoder auto-disable,
172
+ A OneIP device reports its settings in its configuration: decoder auto-disable,
167
173
  HDMI off without signal, IR modulation, the status and network LEDs, quiet fan,
168
174
  CEC combo keys, and the infrared profiles. Each sits behind its own bit, so a
169
175
  device reports only the settings it has, and a write changes one without
170
176
  restating the rest.
171
177
 
172
178
  ```python
173
- from mx_remote import V2IPDeviceSetting
179
+ from mx_remote import OneIPDeviceSetting
174
180
 
175
- settings = device.v2ip_settings # None until the device has reported
176
- print(settings.get(V2IPDeviceSetting.FAN_QUIET)) # None: the device lacks it
181
+ settings = device.oneip_settings # None until the device has reported
182
+ print(settings.get(OneIPDeviceSetting.FAN_QUIET)) # None: the device lacks it
177
183
  print(settings.ir_profile, settings.ir_profile_sink)
178
184
 
179
- await device.set_v2ip_setting(V2IPDeviceSetting.STATUS_LED, False)
180
- await device.set_v2ip_ir_profile(2)
181
- await device.set_v2ip_sink_ir_profile(mx_remote.V2IP_IR_PROFILE_NOT_SET) # follow the global port
185
+ await device.set_oneip_setting(OneIPDeviceSetting.STATUS_LED, False)
186
+ await device.set_oneip_ir_profile(2)
187
+ await device.set_oneip_sink_ir_profile(mx_remote.ONEIP_IR_PROFILE_NOT_SET) # follow the global port
182
188
  ```
183
189
 
184
190
  A write returns False, without sending anything, for whatever the device would
185
191
  ignore in silence: a setting it has not reported, a profile out of range, or a
186
192
  device that has reported no settings at all. So a True is never a change that
187
193
  does not happen, though nothing acknowledges it either: the device answers by
188
- reporting its settings, and until then `v2ip_settings` reads back what was
194
+ reporting its settings, and until then `oneip_settings` reads back what was
189
195
  written.
190
196
 
191
197
  A write from another controller is cached only as far as the device takes it.
@@ -200,14 +206,14 @@ after midnight, Monday first; a window that ends before it starts runs past
200
206
  midnight, and one that ends where it starts means none that day.
201
207
 
202
208
  ```python
203
- from mx_remote import V2IPPowerSaveSchedule
209
+ from mx_remote import OneIPPowerSaveSchedule
204
210
 
205
211
  print(settings.auto_power_save) # idle minutes, 0 for never
206
212
  print(settings.power_save_schedule) # e.g. "mon 22:00-07:00, ..."
207
- print(settings.get(V2IPDeviceSetting.CLOCK_SET))
213
+ print(settings.get(OneIPDeviceSetting.CLOCK_SET))
208
214
 
209
- await device.set_v2ip_auto_power_save(30)
210
- await device.set_v2ip_power_save_schedule(V2IPPowerSaveSchedule(
215
+ await device.set_oneip_auto_power_save(30)
216
+ await device.set_oneip_power_save_schedule(OneIPPowerSaveSchedule(
211
217
  start=(22 * 60,) * 5 + (0, 0), end=(7 * 60,) * 5 + (0, 0))) # weeknights
212
218
  ```
213
219
 
@@ -216,23 +222,83 @@ goes out at 176 bytes: a receiver with the schedule ignores the settings of a
216
222
  shorter frame, and one whose settings end at the idle minutes takes it all the
217
223
  same.
218
224
 
225
+ ### VLAN
226
+
227
+ A device that announces `DeviceFeature.VLAN` tags its uplink by a VLAN
228
+ configuration: its own VLAN id, one per external port (the SFP port, the UTP
229
+ port with PoE, then the UTP port), and the port pinned as the uplink. Ids run
230
+ 0 to `ONEIP_VLAN_ID_MAX`, 0 meaning untagged; ports are numbered from 1 on the
231
+ wire, 0 meaning detect the uplink.
232
+
233
+ ```python
234
+ from mx_remote import OneIPVlan
235
+
236
+ vlan = device.oneip_vlan # None until the device reports one
237
+ print(vlan.device, vlan.port, vlan.pinned_uplink_port, vlan.active_uplink_port)
238
+ print(vlan.is_pending, vlan.revert_s)
239
+
240
+ await device.set_oneip_vlan(OneIPVlan(device=10, port=(0, 20, 0), uplink=2))
241
+ ```
242
+
243
+ Only the device knows what it runs, so `oneip_vlan` is read only from the device
244
+ describing itself, and a write is not cached. The device applies a change at
245
+ once and reverts it after `revert_s` seconds unless the mesh controller, hearing
246
+ it report the change as pending, confirms it.
247
+
248
+ Only the ids, the uplink and the trunk bit are written. Refused before sending:
249
+ a device without the VLAN feature or that has not reported its configuration, an
250
+ id above `ONEIP_VLAN_ID_MAX`, an uplink that names no port, and an SFP uplink on
251
+ a device that reports no SFP port. The write goes out as a settings write that
252
+ carries no setting plus the block, so a receiver that predates the block sees a
253
+ frame it already understood.
254
+
255
+ ### Test pattern, tone and lip-sync
256
+
257
+ A sink whose video processor reports `OneIPVideoProcessorFeature.SINK_TEST_PATTERN` draws a
258
+ test card on its output: a pattern, a test tone, and a lip-sync flash that marks
259
+ a frame and beeps a set number of sample periods after it.
260
+
261
+ ```python
262
+ from mx_remote import OneIPTestPattern, OneIPTestSync, OneIPTestTone, OneIPToneMode
263
+
264
+ await sink.request_oneip_testcard() # the sink reports straight back
265
+ await sink.set_oneip_test_pattern(OneIPTestPattern.FLAT, 0x3050A0)
266
+ await sink.set_oneip_test_tone(OneIPTestTone(mode=OneIPToneMode.CONTINUOUS,
267
+ freq=1000, level=-20, channels=2, rate=48000))
268
+ await sink.set_oneip_test_sync(OneIPTestSync(period=60, lead=0, offset=0, beep_ms=40))
269
+ await sink.set_oneip_test_pattern(OneIPTestPattern.OFF)
270
+
271
+ print(sink.oneip_testcard) # None until the sink has reported
272
+ ```
273
+
274
+ A pattern runs until it is turned off, and holds the output on while it does.
275
+ The sink answers every request and change with its test card, on the group, so
276
+ every client records it against the sink; a write is not cached. A sink with the
277
+ feature but without the module that draws the test card does not answer.
278
+
279
+ Each value is checked against the ranges the sink accepts, since it drops what
280
+ falls outside them in silence: see `OneIPTestTone.is_valid()` and
281
+ `OneIPTestSync.is_valid()`. A tone turned off goes out whatever else it holds,
282
+ as the sink stops it regardless. The frame needs protocol 0x2B, so a sink
283
+ announcing less is refused as well.
284
+
219
285
  ### Every device at once
220
286
 
221
- One broadcast changes settings on every V2IP device of the mesh. Each device
287
+ One broadcast changes settings on every OneIP device of the mesh. Each device
222
288
  applies the settings it has and ignores the rest, and none below protocol 0x2A
223
289
  applies any.
224
290
 
225
291
  ```python
226
- from mx_remote import V2IPDeviceSettings
292
+ from mx_remote import OneIPDeviceSettings
227
293
 
228
- await mx.set_all_v2ip_device_settings(V2IPDeviceSettings(
229
- valid=V2IPDeviceSetting.STATUS_LED | V2IPDeviceSetting.AUTO_POWER_SAVE,
230
- flags=V2IPDeviceSetting.STATUS_LED, # the LED on
294
+ await mx.set_all_oneip_device_settings(OneIPDeviceSettings(
295
+ valid=OneIPDeviceSetting.STATUS_LED | OneIPDeviceSetting.AUTO_POWER_SAVE,
296
+ flags=OneIPDeviceSetting.STATUS_LED, # the LED on
231
297
  auto_power_save=30))
232
298
  ```
233
299
 
234
300
  Nothing is cached from it: each device that applies a change reports its
235
- settings, and its `v2ip_settings` reads that. What every device would ignore is
301
+ settings, and its `oneip_settings` reads that. What every device would ignore is
236
302
  refused rather than sent - no setting at all, one only a device reports about
237
303
  itself, a profile out of range, or a schedule time that is not a time of day.
238
304
 
@@ -242,13 +308,20 @@ itself, a profile out of range, or a schedule time that is not a time of day.
242
308
  # mesh operations
243
309
  await device.mesh_promote() # promote to mesh master
244
310
  await device.mesh_remove() # remove from mesh
311
+ await source.auto_assign_oneip_source_addresses() # drop addresses set by hand
245
312
 
246
313
  # firmware versions
247
- if device.v2ip_firmware_versions:
248
- for fw_type, fw in device.v2ip_firmware_versions.items():
314
+ if device.oneip_firmware_versions:
315
+ for fw_type, fw in device.oneip_firmware_versions.items():
249
316
  print(f"{fw_type}: {fw.version}")
250
317
  ```
251
318
 
319
+ A OneIP source acts on `auto_assign_oneip_source_addresses()` only from
320
+ management, which this client announces itself as, and nothing acknowledges it:
321
+ the source's next configuration report carries the addresses it ends up with, in
322
+ `oneip_details`. A device that is not a source, or announces less than protocol
323
+ 0x2B, would ignore the operation, so it is refused before anything is sent.
324
+
252
325
  ### Time zone and time
253
326
 
254
327
  The mesh controller announces its time zone and clock with every periodic
@@ -260,6 +333,7 @@ print(controller.time_zone) # TimeZone(zone='Europe/Amsterdam', rule='CET-1CES
260
333
  print(controller.clock) # its clock as of now, None until it has announced one
261
334
 
262
335
  await mx.set_mesh_time_zone('Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3')
336
+ await mx.clear_mesh_time_zone() # no time zone: the devices keep UTC
263
337
  await mx.set_mesh_time() # now; or pass a datetime
264
338
  ```
265
339
 
@@ -267,7 +341,8 @@ A device takes either only from the controller or a management application,
267
341
  which is what this client announces itself as; the controller takes them too
268
342
  and announces them from then on. A device keeps its own clock where it is within
269
343
  2s of the time sent. A name or rule that is empty, holds a NUL or is too long
270
- for its field, and a time before 1970 or past 2106, are refused.
344
+ for its field, and a time before 1970 or past 2106, are refused. A controller
345
+ without a time zone announces an empty one.
271
346
 
272
347
  ---
273
348