diff --git a/gauge.py b/gauge.py index a1ae7f2..ef01adc 100644 --- a/gauge.py +++ b/gauge.py @@ -114,6 +114,8 @@ if "gauges" in _cfg: "min": float(g.get("min", 0)), "max": float(g.get("max", 100)), "max_steps": int(g.get("max_steps", 4000)), + "speed": float(g.get("speed", 5000.0)), + "acceleration": float(g.get("acceleration", 6000.0)), "entity_name": g.get("entity_name", f"Gauge {i + 1}"), "unit": g.get("unit", ""), "ws2812_red": tuple(led_cfg.get("ws2812_red", [255, 0, 0])), @@ -128,6 +130,8 @@ else: "min": float(_cfg.get("gauge_min", 0)), "max": float(_cfg.get("gauge_max", 7300)), "max_steps": int(_cfg.get("gauge_max_steps", 4000)), + "speed": float(_cfg.get("gauge_speed", 5000.0)), + "acceleration": float(_cfg.get("gauge_acceleration", 6000.0)), "entity_name": _cfg.get("gauge_entity_name", "Selsyn 1 Power"), "unit": _cfg.get("gauge_unit", "W"), "ws2812_red": tuple(_cfg.get("ws2812_red", [255, 0, 0])), @@ -194,6 +198,14 @@ def gauge_zero(gauge_idx): arduino_send(f"ZERO {gauge_idx}") +def gauge_set_speed(gauge_idx, speed): + arduino_send(f"SPEED {gauge_idx} {speed}") + + +def gauge_set_acceleration(gauge_idx, acceleration): + arduino_send(f"ACCEL {gauge_idx} {acceleration}") + + def _set_led(gauge_idx, idx, r, g, b): arduino_send(f"LED {gauge_idx} {idx} {r} {g} {b}") @@ -251,6 +263,8 @@ def _apply_blink_or_led(gauge_idx, led_idx, color, effect): gauge_targets = [g["min"] for g in gauges] gauge_last_rezero = [utime.ticks_ms() for _ in gauges] +gauge_speeds = [g["speed"] for g in gauges] +gauge_accelerations = [g["acceleration"] for g in gauges] backlight_color = [(0, 0, 0) for _ in range(num_gauges)] backlight_brightness = [100 for _ in range(num_gauges)] @@ -378,6 +392,12 @@ def make_gauge_topics(prefix, gauge_id): "status": f"{prefix}/gauge{gauge_id}/status", "zero": f"{prefix}/gauge{gauge_id}/zero", "disc": f"homeassistant/number/{MQTT_CLIENT_ID}_g{gauge_id}/config", + "speed": f"{prefix}/gauge{gauge_id}/speed/set", + "speed_state": f"{prefix}/gauge{gauge_id}/speed/state", + "speed_disc": f"homeassistant/number/{MQTT_CLIENT_ID}_g{gauge_id}_speed/config", + "acceleration": f"{prefix}/gauge{gauge_id}/acceleration/set", + "acceleration_state": f"{prefix}/gauge{gauge_id}/acceleration/state", + "acceleration_disc": f"homeassistant/number/{MQTT_CLIENT_ID}_g{gauge_id}_acceleration/config", "led_red": f"{prefix}/gauge{gauge_id}/led/red/set", "led_green": f"{prefix}/gauge{gauge_id}/led/green/set", "led_bl": f"{prefix}/gauge{gauge_id}/led/backlight/set", @@ -503,6 +523,32 @@ def on_message(topic, payload): warn(f"Invalid set value for gauge {i}: '{payload}'") return + if topic == gt["speed"]: + try: + speed = float(payload) + if speed <= 0.0: + raise ValueError + gauge_speeds[i] = speed + gauge_set_speed(i, speed) + _publish(gt["speed_state"], str(speed), retain=True) + info(f"Gauge {i} speed -> {speed}") + except ValueError: + warn(f"Invalid speed for gauge {i}: '{payload}'") + return + + if topic == gt["acceleration"]: + try: + acceleration = float(payload) + if acceleration <= 0.0: + raise ValueError + gauge_accelerations[i] = acceleration + gauge_set_acceleration(i, acceleration) + _publish(gt["acceleration_state"], str(acceleration), retain=True) + info(f"Gauge {i} acceleration -> {acceleration}") + except ValueError: + warn(f"Invalid acceleration for gauge {i}: '{payload}'") + return + if topic == gt["led_red"]: try: data = ujson.loads(payload) @@ -680,6 +726,8 @@ def _subscribe_all(c): prefix = f"{MQTT_PREFIX}/gauge{i}" c.subscribe(f"{prefix}/set") c.subscribe(f"{prefix}/zero") + c.subscribe(f"{prefix}/speed/set") + c.subscribe(f"{prefix}/acceleration/set") c.subscribe(f"{prefix}/led/red/set") c.subscribe(f"{prefix}/led/green/set") c.subscribe(f"{prefix}/led/backlight/set") @@ -794,6 +842,54 @@ def publish_discovery(client): ) info(f"Discovery: gauge {i} ({g['name']})") + client.publish( + gt["speed_disc"], + ujson.dumps( + { + "name": f"{g['name']} Speed", + "unique_id": f"{MQTT_CLIENT_ID}_g{i}_speed", + "cmd_t": gt["speed"], + "stat_t": gt["speed_state"], + "avty_t": gt["status"], + "min": 1, + "max": 50000, + "step": 1, + "mode": "box", + "unit_of_meas": "steps/s", + "icon": "mdi:speedometer", + "enabled_by_default": False, + "entity_category": "config", + "dev": _dev_ref, + } + ), + retain=True, + ) + info(f"Discovery: gauge {i} speed") + + client.publish( + gt["acceleration_disc"], + ujson.dumps( + { + "name": f"{g['name']} Acceleration", + "unique_id": f"{MQTT_CLIENT_ID}_g{i}_acceleration", + "cmd_t": gt["acceleration"], + "stat_t": gt["acceleration_state"], + "avty_t": gt["status"], + "min": 1, + "max": 100000, + "step": 1, + "mode": "box", + "unit_of_meas": "steps/s²", + "icon": "mdi:chart-bell-curve-cumulative", + "enabled_by_default": False, + "entity_category": "config", + "dev": _dev_ref, + } + ), + retain=True, + ) + info(f"Discovery: gauge {i} acceleration") + for _ in range(5): client.check_msg() utime.sleep_ms(10) @@ -913,6 +1009,14 @@ def publish_state(client): for i in range(num_gauges): gt = gauge_topics[i] client.publish(gt["state"], str(gauge_targets[i])) + client.publish(gt["speed_state"], str(gauge_speeds[i]), retain=True) + client.publish(gt["acceleration_state"], str(gauge_accelerations[i]), retain=True) + + +def apply_motion_defaults(): + for i in range(num_gauges): + gauge_set_speed(i, gauge_speeds[i]) + gauge_set_acceleration(i, gauge_accelerations[i]) # --------------------------------------------------------------------------- @@ -933,6 +1037,7 @@ def main(): publish_discovery(client_ref) _subscribe_all(client_ref) + apply_motion_defaults() info("Draining initial retained messages...") for _ in range(50): client_ref.check_msg()