mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-13 02:26:37 +00:00
fix(web): reject true and 5.5 for row_address_type and multiplexing
Both still went straight through int(), so a JSON true saved as 1 and 5.5 as 5. They now use the shared hardware range check like the other panel fields. Review feedback on #586. Also: the RP1 Backend tooltip said it is ignored on Pi 3/4 (it is ignored on every model but the Pi 5), and the README gave the dynamic-duration default cap as 90s; the code default is 180s. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+5
-4
@@ -54,10 +54,11 @@ Web interface:
|
|||||||
parallel is 1–3 and PWM dither bits 0–2, matching the library. A stored GPIO
|
parallel is 1–3 and PWM dither bits 0–2, matching the library. A stored GPIO
|
||||||
slowdown, PWM dither bits or refresh-rate cap of 0 no longer shows (and
|
slowdown, PWM dither bits or refresh-rate cap of 0 no longer shows (and
|
||||||
re-saves) as 3, 1 or 120, and the refresh cap accepts 0 (no cap). The config
|
re-saves) as 3, 1 or 120, and the refresh cap accepts 0 (no cap). The config
|
||||||
API rejects out-of-range `rows`, `cols`, `chain_length`, `parallel`,
|
API rejects out-of-range or non-integer `rows`, `cols`, `chain_length`,
|
||||||
`brightness`, `scan_mode`, `pwm_bits`, `pwm_dither_bits`,
|
`parallel`, `brightness`, `scan_mode`, `pwm_bits`, `pwm_dither_bits`,
|
||||||
`pwm_lsb_nanoseconds`, `limit_refresh_rate_hz` and `gpio_slowdown` with a
|
`pwm_lsb_nanoseconds`, `limit_refresh_rate_hz`, `row_address_type`,
|
||||||
400 instead of saving a config the matrix refuses to start with.
|
`multiplexing` and `gpio_slowdown` with a 400 (JSON `true` or `5.5` used to
|
||||||
|
save as 1 or 5) instead of saving a config the matrix refuses to start with.
|
||||||
- Display setting help tips and README / config-reference entries corrected
|
- Display setting help tips and README / config-reference entries corrected
|
||||||
and completed: `panel_type` and `rp1_rio` are documented,
|
and completed: `panel_type` and `rp1_rio` are documented,
|
||||||
`show_refresh_rate` prints to the console rather than drawing on the panel,
|
`show_refresh_rate` prints to the console rather than drawing on the panel,
|
||||||
|
|||||||
@@ -701,7 +701,7 @@ Controls how long each installed plugin stays visible in seconds before switchin
|
|||||||
- Some plugins can automatically adjust their display time based on content
|
- Some plugins can automatically adjust their display time based on content
|
||||||
- This setting limits how long they can extend (prevents one display from dominating)
|
- This setting limits how long they can extend (prevents one display from dominating)
|
||||||
- Example: If set to 60, a plugin can extend up to 60 seconds even if it requests longer
|
- Example: If set to 60, a plugin can extend up to 60 seconds even if it requests longer
|
||||||
- Leave unset to use the default cap (typically 90 seconds)
|
- Leave unset to use the default cap (180 seconds; the web UI accepts 30-1800)
|
||||||
|
|
||||||
### Example Configuration
|
### Example Configuration
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,8 @@ def test_waveshare_96x48_v2_settings_all_save(api_v3_client, saved, as_strings):
|
|||||||
('cols', 16), ('cols', 192), ('cols', 512),
|
('cols', 16), ('cols', 192), ('cols', 512),
|
||||||
('chain_length', 1), ('chain_length', 32),
|
('chain_length', 1), ('chain_length', 32),
|
||||||
('parallel', 3),
|
('parallel', 3),
|
||||||
('row_address_type', 0), ('row_address_type', 5),
|
('row_address_type', 0), ('row_address_type', 5), ('row_address_type', 5.0),
|
||||||
|
('multiplexing', 0), ('multiplexing', 22),
|
||||||
('gpio_slowdown', 0), ('gpio_slowdown', 10),
|
('gpio_slowdown', 0), ('gpio_slowdown', 10),
|
||||||
('pwm_bits', 1), ('pwm_bits', 11),
|
('pwm_bits', 1), ('pwm_bits', 11),
|
||||||
('pwm_dither_bits', 0), ('pwm_dither_bits', 2),
|
('pwm_dither_bits', 0), ('pwm_dither_bits', 2),
|
||||||
@@ -108,6 +109,8 @@ def test_values_in_range_are_saved(api_v3_client, saved, field, value):
|
|||||||
('chain_length', 0),
|
('chain_length', 0),
|
||||||
('parallel', 0), ('parallel', 4),
|
('parallel', 0), ('parallel', 4),
|
||||||
('row_address_type', -1), ('row_address_type', 6),
|
('row_address_type', -1), ('row_address_type', 6),
|
||||||
|
('row_address_type', True), ('row_address_type', 5.5),
|
||||||
|
('multiplexing', -1), ('multiplexing', 23), ('multiplexing', True),
|
||||||
('gpio_slowdown', -1), ('gpio_slowdown', 11),
|
('gpio_slowdown', -1), ('gpio_slowdown', 11),
|
||||||
('pwm_bits', 0), ('pwm_bits', 12),
|
('pwm_bits', 0), ('pwm_bits', 12),
|
||||||
('pwm_dither_bits', 3),
|
('pwm_dither_bits', 3),
|
||||||
|
|||||||
@@ -555,15 +555,6 @@ def save_main_config():
|
|||||||
if 'panel_type' in data and data['panel_type'] not in PANEL_TYPE_ALLOWED:
|
if 'panel_type' in data and data['panel_type'] not in PANEL_TYPE_ALLOWED:
|
||||||
return jsonify({'status': 'error', 'message': f"Invalid panel type '{data['panel_type']}'. Allowed values: Standard (empty), FM6126A, FM6127"}), 400
|
return jsonify({'status': 'error', 'message': f"Invalid panel type '{data['panel_type']}'. Allowed values: Standard (empty), FM6126A, FM6127"}), 400
|
||||||
|
|
||||||
# Validate multiplexing
|
|
||||||
if 'multiplexing' in data:
|
|
||||||
try:
|
|
||||||
mux_val = int(data['multiplexing'])
|
|
||||||
if mux_val < 0 or mux_val > 22:
|
|
||||||
return jsonify({'status': 'error', 'message': f"Invalid multiplexing value '{data['multiplexing']}'. Must be an integer from 0 to 22."}), 400
|
|
||||||
except (ValueError, TypeError, OverflowError):
|
|
||||||
return jsonify({'status': 'error', 'message': f"Invalid multiplexing value '{data['multiplexing']}'. Must be an integer from 0 to 22."}), 400
|
|
||||||
|
|
||||||
# Validate pixel_mapper_config (free-form mapper string, e.g. "U-mapper;Rotate:90")
|
# Validate pixel_mapper_config (free-form mapper string, e.g. "U-mapper;Rotate:90")
|
||||||
if 'pixel_mapper_config' in data and not isinstance(data['pixel_mapper_config'], str):
|
if 'pixel_mapper_config' in data and not isinstance(data['pixel_mapper_config'], str):
|
||||||
return jsonify({'status': 'error', 'message': 'pixel_mapper_config must be a string (e.g. "U-mapper;Rotate:90" or empty)'}), 400
|
return jsonify({'status': 'error', 'message': 'pixel_mapper_config must be a string (e.g. "U-mapper;Rotate:90" or empty)'}), 400
|
||||||
@@ -573,15 +564,6 @@ def save_main_config():
|
|||||||
if 'orientation' in data and data['orientation'] not in ORIENTATION_ALLOWED:
|
if 'orientation' in data and data['orientation'] not in ORIENTATION_ALLOWED:
|
||||||
return jsonify({'status': 'error', 'message': f"Invalid orientation '{data['orientation']}'. Allowed values: {', '.join(sorted(ORIENTATION_ALLOWED))}"}), 400
|
return jsonify({'status': 'error', 'message': f"Invalid orientation '{data['orientation']}'. Allowed values: {', '.join(sorted(ORIENTATION_ALLOWED))}"}), 400
|
||||||
|
|
||||||
# Validate row_address_type
|
|
||||||
if 'row_address_type' in data:
|
|
||||||
try:
|
|
||||||
rat_val = int(data['row_address_type'])
|
|
||||||
if rat_val < 0 or rat_val > 5:
|
|
||||||
return jsonify({'status': 'error', 'message': f"Invalid row_address_type '{data['row_address_type']}'. Must be an integer from 0 to 5."}), 400
|
|
||||||
except (ValueError, TypeError, OverflowError):
|
|
||||||
return jsonify({'status': 'error', 'message': f"Invalid row_address_type '{data['row_address_type']}'. Must be an integer from 0 to 5."}), 400
|
|
||||||
|
|
||||||
# Panel geometry, PWM and GPIO timing, held to what the rgbmatrix library
|
# Panel geometry, PWM and GPIO timing, held to what the rgbmatrix library
|
||||||
# accepts (RGBMatrix::Options::Validate in lib/options-initialize.cc,
|
# accepts (RGBMatrix::Options::Validate in lib/options-initialize.cc,
|
||||||
# the gpio_slowdown check in lib/led-matrix.cc). Outside those ranges
|
# the gpio_slowdown check in lib/led-matrix.cc). Outside those ranges
|
||||||
@@ -617,6 +599,7 @@ def save_main_config():
|
|||||||
('pwm_bits', 1, 11, False), ('pwm_dither_bits', 0, 2, False),
|
('pwm_bits', 1, 11, False), ('pwm_dither_bits', 0, 2, False),
|
||||||
('pwm_lsb_nanoseconds', 50, 3000, False),
|
('pwm_lsb_nanoseconds', 50, 3000, False),
|
||||||
('limit_refresh_rate_hz', 0, None, False),
|
('limit_refresh_rate_hz', 0, None, False),
|
||||||
|
('row_address_type', 0, 5, False), ('multiplexing', 0, 22, False),
|
||||||
('gpio_slowdown', 0, 10, False)):
|
('gpio_slowdown', 0, 10, False)):
|
||||||
if field in data:
|
if field in data:
|
||||||
error = _hardware_int_error(field, low, high, even)
|
error = _hardware_int_error(field, low, high, even)
|
||||||
|
|||||||
@@ -222,7 +222,7 @@
|
|||||||
|
|
||||||
<div class="form-group" id="setting-display-rp1_rio" data-setting-key="display.runtime.rp1_rio">
|
<div class="form-group" id="setting-display-rp1_rio" data-setting-key="display.runtime.rp1_rio">
|
||||||
<label for="rp1_rio" class="block text-sm font-medium text-gray-700">
|
<label for="rp1_rio" class="block text-sm font-medium text-gray-700">
|
||||||
RP1 Backend <span class="text-xs text-gray-400 font-normal">(Pi 5 only)</span>{{ ui.help_tip('Pi 5 RP1 coprocessor driver mode.\nPIO (0) is the default and uses less CPU. RIO (1) can push a higher refresh rate but inverts the GPIO Slowdown behavior. Ignored on Pi 3/4.', 'RP1 Backend') }}
|
RP1 Backend <span class="text-xs text-gray-400 font-normal">(Pi 5 only)</span>{{ ui.help_tip('Pi 5 RP1 coprocessor driver mode.\nPIO (0) is the default and uses less CPU. RIO (1) can push a higher refresh rate but inverts the GPIO Slowdown behavior. Ignored on every other Pi model.', 'RP1 Backend') }}
|
||||||
</label>
|
</label>
|
||||||
<select id="rp1_rio" name="rp1_rio" class="form-control">
|
<select id="rp1_rio" name="rp1_rio" class="form-control">
|
||||||
<option value="0" {% if main_config.display.get('runtime', {}).get('rp1_rio', 0)|int == 0 %}selected{% endif %}>0 — PIO (default, low CPU)</option>
|
<option value="0" {% if main_config.display.get('runtime', {}).get('rp1_rio', 0)|int == 0 %}selected{% endif %}>0 — PIO (default, low CPU)</option>
|
||||||
|
|||||||
Reference in New Issue
Block a user