From aaaef5e7da4e9d56288b76a011c7256d5e5cd11c Mon Sep 17 00:00:00 2001 From: XANTRONIX Development Date: Mon, 1 Jan 2024 02:17:12 -0500 Subject: [PATCH] Thermometer? You bet! --- py/hexagram/cluster.py | 14 +++++++--- py/hexagram/fuel.py | 5 +++- py/hexagram/thermo.py | 63 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 py/hexagram/thermo.py diff --git a/py/hexagram/cluster.py b/py/hexagram/cluster.py index faafa3c..129db8e 100644 --- a/py/hexagram/cluster.py +++ b/py/hexagram/cluster.py @@ -9,6 +9,7 @@ from hexagram.dial import Dial from hexagram.speedo import Speedo from hexagram.tacho import Tacho from hexagram.fuel import FuelGauge +from hexagram.thermo import ThermoGauge class ShiftIndicator(Gauge): __slots__ = 'x', 'y', 'rpm_redline', 'rpm_max', @@ -65,7 +66,7 @@ class Cluster(): SHIFT_INDICATOR_X = 392 SHIFT_INDICATOR_Y = 24 - __slots__ = 'gauges', 'speedo', 'tacho', 'fuel', + __slots__ = 'gauges', 'speedo', 'fuel', 'tacho', 'thermo', def __init__(self, rpm_redline: float, rpm_max: float): self.gauges: List[Gauge] = list() @@ -75,18 +76,23 @@ class Cluster(): self.HEIGHT / 2, 200.0) + self.fuel = FuelGauge(self.HEIGHT / 2, + self.HEIGHT / 2, + self.HEIGHT / 2) + self.tacho = Tacho(self.WIDTH - self.HEIGHT / 2, self.HEIGHT / 2, self.HEIGHT / 2, 8000) - self.fuel = FuelGauge(self.HEIGHT / 2, - self.HEIGHT / 2, - self.HEIGHT / 2) + self.thermo = ThermoGauge(self.WIDTH - self.HEIGHT / 2, + self.HEIGHT / 2, + self.HEIGHT / 2) self.gauges.append(self.speedo) self.gauges.append(self.fuel) self.gauges.append(self.tacho) + self.gauges.append(self.thermo) self.gauges.append(ShiftIndicator(self.SHIFT_INDICATOR_X, self.SHIFT_INDICATOR_Y, diff --git a/py/hexagram/fuel.py b/py/hexagram/fuel.py index 9ff71b8..1803ae4 100644 --- a/py/hexagram/fuel.py +++ b/py/hexagram/fuel.py @@ -53,9 +53,12 @@ class FuelGauge(Dial): cr.set_line_width(6.0) for level in range(0, self.MAX_VALUE+1): - if level < 4: + if level < 2: min_radius = 0.84 cr.set_source_rgb(1, 0, 0) + elif level < 4: + min_radius = 0.82 + cr.set_source_rgb(1, 0, 0) else: min_radius = 0.82 cr.set_source_rgb(1, 1, 1) diff --git a/py/hexagram/thermo.py b/py/hexagram/thermo.py new file mode 100644 index 0000000..8333547 --- /dev/null +++ b/py/hexagram/thermo.py @@ -0,0 +1,63 @@ +import enum +import math +import cairo + +from hexagram.dial import Dial + +class ThermoGauge(Dial): + MIN_ANGLE = 144.0 * (math.pi / 180.0) + MAX_ANGLE = 216.0 * (math.pi / 180.0) + + MIN_VALUE = 85 + MAX_VALUE = 110 + WARN_VALUE = 106 + + FONT_FACE = "Muli" + + def __init__(self, x: float, y: float, radius: float): + super().__init__(x, y, radius, self.MIN_ANGLE, self.MAX_ANGLE, self.MAX_VALUE - self.MIN_VALUE) + + def draw_value(self, cr: cairo.Context, radius: float, value: float, text: str, x_offset: float, y_offset: float): + scale = (self.max_value - value) / self.max_value + angle = self.min_angle + ((self.max_angle - self.min_angle) * scale) - self.ANGLE_OFFSET + + cr.move_to(self.x + radius * self.radius * math.cos(angle) + x_offset, + self.y + radius * self.radius * math.sin(angle) + y_offset) + + cr.show_text(text) + cr.stroke() + + def draw_mark(self, cr: cairo.Context, min_radius: float, max_radius: float, value: float): + angle = self.min_angle + \ + ((self.max_angle - self.min_angle) * (value / self.max_value)) - self.ANGLE_OFFSET + + cr.move_to(self.x + (min_radius * self.radius) * math.cos(angle), + self.y + (min_radius * self.radius) * math.sin(angle)) + + cr.line_to(self.x + (max_radius * self.radius) * math.cos(angle), + self.y + (max_radius * self.radius) * math.sin(angle)) + + cr.stroke() + + def draw_bg(self, cr: cairo.Context): + cr.select_font_face(self.FONT_FACE, + cairo.FontSlant.NORMAL, + cairo.FontWeight.BOLD) + + cr.set_font_size(self.radius * 0.1) + + cr.set_source_rgb(1, 1, 1) + self.draw_value(cr, 0.78, 0, "C", 0, 5) + + cr.set_source_rgb(1, 0, 0) + self.draw_value(cr, 0.75, self.MAX_VALUE - self.MIN_VALUE, "H", -5, 5) + + cr.set_line_width(6.0) + + for level in range(0, self.MAX_VALUE - self.MIN_VALUE, math.ceil((self.MAX_VALUE - self.MIN_VALUE) / 9)): + if level + self.MIN_VALUE >= self.WARN_VALUE: + cr.set_source_rgb(0.8, 0, 0) + else: + cr.set_source_rgb(1, 1, 1) + + self.draw_mark(cr, 0.83, 0.87, self.max_value - level)