Summary
async_set_bass, async_set_treble, and async_set_balance in lync_client.py build a frame the real Lync12 hardware either silently ignores or rejects with an Echo Error Status. Confirmed the correct TX encoding via direct hardware testing and have a suggested fix below.
Testing methodology (please read before the findings)
This was tested with a PC connected directly to the Lync12 controller's RS232 port via a USB-RS232 adapter (38400 8N1) — not through a WGW-SLX or any other network gateway. That gateway was bypassed because ours failed independently during troubleshooting (a genuine hardware fault, confirmed by elimination: cable swap, direct-vs-crossed wiring, and the controller responding normally once addressed directly).
If you're controlling your Lync12 through a WGW-SLX or similar gateway, and that gateway performs any protocol-level translation, your results could differ from what's documented here. I believe (based on the gateway's transparent-bridge design, and the fact that other commands — volume, power, source-select — already work correctly through it using this library's existing, un-translated encoding) that no translation occurs. But I haven't independently verified that with a live capture through a working gateway, so treat that as an assumption, not a confirmed fact.
Findings
Sending a bass/treble/balance SET command as currently implemented (COMMON_COMMAND_CODE wrapper, value as trailing extra data) gets one of two results on real hardware:
- No response at all, or
- An Echo Error Status (
0x1B) with an error code matching the relevant parameter (e.g. error 4 = "Bass setting range error") — identical response regardless of the value sent, confirming it's a frame-shape rejection, not a real range check.
Correct encoding, confirmed with real, audible before/after changes across the full range of each parameter on a live zone:
- Command byte = the setting's own code (
0x18 bass / 0x17 treble / 0x16 balance) used directly, not wrapped under 0x04
- Value = a plain 8-bit two's-complement signed byte, no
+0x80 offset — identical to the RX/response-side encoding this library already parses correctly (see convert_value() / the zone status parsing)
- Frame:
[0x02, 0x00, zone, CMD, value_byte, checksum]
Test data (zone 8, real Lync12 hardware, audio playing, changes confirmed by ear):
| Parameter |
Values tested |
Result |
| Bass |
+10, +5, 0, -5, -10 |
All correct, audible, direction-matched |
| Treble |
+10, -10 |
Both correct, audible |
| Balance |
+18, -18, 0 |
All correct, audible pan |
Suggested fix
async def async_set_bass(self, zone: int, bass: int):
zone_info = self.get_zone(zone)
if zone_info.bass == bass:
return
return await self._async_send_and_validate(
lambda z: z.bass == bass,
zone,
HtdLyncCommands.BASS_SETTING_CONTROL_COMMAND_CODE,
bass & 0xff
)
Same pattern for async_set_treble (TREBLE_SETTING_CONTROL_COMMAND_CODE) and async_set_balance (BALANCE_SETTING_CONTROL_COMMAND_CODE). Note async_set_balance is already structured this way (setting code used directly, no COMMON_COMMAND_CODE wrapper) — it's only missing the & 0xff mask, so it hits the same crash as bass/treble for negative values (bytearray() can't hold a negative int). The & 0xff mask fixes that crash as a side effect of fixing the encoding.
One more thing worth flagging separately: these three commands essentially never echo a confirming response even when they succeed (per the table above), so _async_send_and_validate's response-driven retry loop can time out and raise even when the command actually worked. Might be worth a _send_cmd + optimistic local-state-update path for these specifically, rather than the generic validate-and-retry wrapper used for commands that do reliably echo (power, volume, mute).
Happy to test a patch against real hardware if useful — I have direct RS232 access to a Lync12 at the moment.
Summary
async_set_bass,async_set_treble, andasync_set_balanceinlync_client.pybuild a frame the real Lync12 hardware either silently ignores or rejects with an Echo Error Status. Confirmed the correct TX encoding via direct hardware testing and have a suggested fix below.Testing methodology (please read before the findings)
This was tested with a PC connected directly to the Lync12 controller's RS232 port via a USB-RS232 adapter (38400 8N1) — not through a WGW-SLX or any other network gateway. That gateway was bypassed because ours failed independently during troubleshooting (a genuine hardware fault, confirmed by elimination: cable swap, direct-vs-crossed wiring, and the controller responding normally once addressed directly).
If you're controlling your Lync12 through a WGW-SLX or similar gateway, and that gateway performs any protocol-level translation, your results could differ from what's documented here. I believe (based on the gateway's transparent-bridge design, and the fact that other commands — volume, power, source-select — already work correctly through it using this library's existing, un-translated encoding) that no translation occurs. But I haven't independently verified that with a live capture through a working gateway, so treat that as an assumption, not a confirmed fact.
Findings
Sending a bass/treble/balance SET command as currently implemented (
COMMON_COMMAND_CODEwrapper, value as trailing extra data) gets one of two results on real hardware:0x1B) with an error code matching the relevant parameter (e.g. error4= "Bass setting range error") — identical response regardless of the value sent, confirming it's a frame-shape rejection, not a real range check.Correct encoding, confirmed with real, audible before/after changes across the full range of each parameter on a live zone:
0x18bass /0x17treble /0x16balance) used directly, not wrapped under0x04+0x80offset — identical to the RX/response-side encoding this library already parses correctly (seeconvert_value()/ the zone status parsing)[0x02, 0x00, zone, CMD, value_byte, checksum]Test data (zone 8, real Lync12 hardware, audio playing, changes confirmed by ear):
Suggested fix
Same pattern for
async_set_treble(TREBLE_SETTING_CONTROL_COMMAND_CODE) andasync_set_balance(BALANCE_SETTING_CONTROL_COMMAND_CODE). Noteasync_set_balanceis already structured this way (setting code used directly, noCOMMON_COMMAND_CODEwrapper) — it's only missing the& 0xffmask, so it hits the same crash as bass/treble for negative values (bytearray()can't hold a negative int). The& 0xffmask fixes that crash as a side effect of fixing the encoding.One more thing worth flagging separately: these three commands essentially never echo a confirming response even when they succeed (per the table above), so
_async_send_and_validate's response-driven retry loop can time out and raise even when the command actually worked. Might be worth a_send_cmd+ optimistic local-state-update path for these specifically, rather than the generic validate-and-retry wrapper used for commands that do reliably echo (power, volume, mute).Happy to test a patch against real hardware if useful — I have direct RS232 access to a Lync12 at the moment.