|
3 | 3 | // for Matter coexistence: diag_on_status() only snapshots (no socket I/O under the |
4 | 4 | // CHIP stack lock); the `watch` stream and the TCP accept loop run in their own tasks. |
5 | 5 | #include <stdio.h> |
| 6 | +#include <stdlib.h> |
6 | 7 | #include <string.h> |
7 | 8 | #include <ctype.h> |
8 | 9 | #include <unistd.h> |
@@ -176,13 +177,52 @@ static int cmd_decode(int argc, char **argv) |
176 | 177 | return 0; |
177 | 178 | } |
178 | 179 |
|
| 180 | +// Bench probe for #52 (display byte unknown). Sends the CURRENT command frame with one |
| 181 | +// payload byte replaced, so a miss is a no-op rather than a surprise mode/setpoint change. |
| 182 | +// |
| 183 | +// Deliberately single-shot: there is no auto-sweep. hisense_parse_status() decodes no |
| 184 | +// display state (power_display/q_display are ProductType CAPABILITY bits, not live |
| 185 | +// status), so the only oracle is the panel LED and every probe needs a human looking at |
| 186 | +// the unit before the next one goes out. An unattended sweep would just log offsets. |
| 187 | +static int cmd_tx(int argc, char **argv) |
| 188 | +{ |
| 189 | + if (argc < 3) { |
| 190 | + printf("usage: tx <offset> <value> (both accept 0x.. or decimal)\r\n" |
| 191 | + " payload offsets %u..%u; header and checksum/terminator are rejected\r\n" |
| 192 | + " current suspect (#52): tx 36 0xC0 then tx 36 0x40\r\n" |
| 193 | + " watch the PANEL after each probe -- there is no status read-back\r\n", |
| 194 | + (unsigned) HISENSE_CMD_HEADER_LEN, (unsigned) HISENSE_CMD_CHK_OFFSET - 1); |
| 195 | + return 1; |
| 196 | + } |
| 197 | + long off = strtol(argv[1], NULL, 0); |
| 198 | + long val = strtol(argv[2], NULL, 0); |
| 199 | + if (val < 0 || val > 0xFF) { printf("value out of range (0..0xFF)\r\n"); return 1; } |
| 200 | + |
| 201 | + switch (diag_tx_override((int) off, (uint8_t) val)) { |
| 202 | + case -1: |
| 203 | + printf("rejected: offset %ld is outside the payload [%u,%u)\r\n", |
| 204 | + off, (unsigned) HISENSE_CMD_HEADER_LEN, (unsigned) HISENSE_CMD_CHK_OFFSET); |
| 205 | + return 1; |
| 206 | + case -2: |
| 207 | + printf("TX queue full -- NOT sent, retry\r\n"); |
| 208 | + return 1; |
| 209 | + default: |
| 210 | + break; |
| 211 | + } |
| 212 | + printf("sent: frame[%ld] = 0x%02lX (every other byte = current A/C state)\r\n" |
| 213 | + " -> check the panel now; any change is attributable to this byte alone\r\n" |
| 214 | + " -> to undo, drive the unit normally from HA (rebuilds the baseline frame)\r\n", |
| 215 | + off, (unsigned long) val); |
| 216 | + return 0; |
| 217 | +} |
| 218 | + |
179 | 219 | // Compact codec self-check (subset of the host golden vectors). |
180 | 220 | static int cmd_selftest(int, char **) |
181 | 221 | { |
182 | 222 | int fails = 0; |
183 | 223 | uint8_t f[64]; |
184 | 224 | HisenseCommand c = { HISENSE_MODE_COOL, 22, false, HISENSE_FAN_LOW, |
185 | | - HISENSE_SWING_OFF, HISENSE_SWING_OFF, HISENSE_FEATURE_ECO, false }; |
| 225 | + HISENSE_SWING_OFF, HISENSE_SWING_OFF, HISENSE_FEATURE_ECO, HISENSE_DISPLAY_NOCHANGE }; |
186 | 226 | size_t n = hisense_build_command(&c, f, sizeof(f)); |
187 | 227 | if (!(n && f[16] == 0x0B && f[18] == 0x50 && f[19] == 0x2D && f[33] == 0x30)) fails++; |
188 | 228 | uint8_t hi = 0, lo = 0; |
@@ -290,6 +330,8 @@ extern "C" void diag_console_start(void) |
290 | 330 | { "watch", "stream decoded frames ~1Hz: watch [on|off]", NULL, cmd_watch, NULL, NULL }, |
291 | 331 | { "decode", "offline-decode a pasted hex frame", NULL, cmd_decode, NULL, NULL }, |
292 | 332 | { "selftest", "compact on-target codec self-check", NULL, cmd_selftest, NULL, NULL }, |
| 333 | + { "tx", "#52 bench probe: tx <offset> <value> — current frame, one byte overridden", |
| 334 | + NULL, cmd_tx, NULL, NULL }, |
293 | 335 | }; |
294 | 336 | for (size_t i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) esp_console_cmd_register(&cmds[i]); |
295 | 337 | } |
|
0 commit comments