217 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			217 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			Python
		
	
	
	
| """
 | |
| 
 | |
| Integrierte Spannungsmessung
 | |
| 
 | |
| Ideen:
 | |
|   - Umschaltung Datenquelle: intern, N2K
 | |
|   - Umschaltung analog / digital / Graphik
 | |
|   - Historische Werte vom YD-Batteriemonitor
 | |
| 
 | |
| """
 | |
| 
 | |
| import cairo
 | |
| import math
 | |
| from .page import Page
 | |
| 
 | |
| class Voltage(Page):
 | |
| 
 | |
|     avg = (1, 10, 60, 300);
 | |
| 
 | |
|     def __init__(self, pageno, cfg, appdata, boatdata):
 | |
|         super().__init__(pageno, cfg, appdata, boatdata)
 | |
|         self.trend = True
 | |
|         self.mode = 'A'
 | |
|         self.avgindex = 0
 | |
|         self.buttonlabel[1] = 'AVG'
 | |
|         self.buttonlabel[2] = 'MODE'
 | |
|         self.buttonlabel[5] = 'TRD'
 | |
|         self.lastvalue = self.bd.voltage.value
 | |
| 
 | |
|     def handle_key(self, buttonid):
 | |
|         if buttonid == 1:
 | |
|             if self.avgindex < len(self.avg) -1:
 | |
|                 self.avgindex += 1
 | |
|             else:
 | |
|                 self.avgindex = 0
 | |
|         elif buttonid == 2:
 | |
|             if self.mode == 'A':
 | |
|                 self.mode = 'D'
 | |
|             else:
 | |
|                 self.mode = 'A'
 | |
|         elif buttonid == 5:
 | |
|             self.trend = not self.trend
 | |
| 
 | |
|     def setBoatValue(self, boatvalue):
 | |
|         # Einstellen welcher Wert dargestellt werden soll
 | |
|         self.value1 = boatvalue
 | |
| 
 | |
|     def draw(self, ctx):
 | |
|         ctx.select_font_face("Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
 | |
|         if self.mode == 'A':
 | |
|             self.draw_analog(ctx)
 | |
|         else:
 | |
|             self.draw_digital(ctx)
 | |
| 
 | |
|     def draw_analog(self, ctx):
 | |
|         # TODO schönes Viertelkreis-Instrument
 | |
|         # Skala von 9V bis 15V
 | |
|         # d.h. 90° entsprechend unterteilen in 6 Stücke je 15°
 | |
|         # Beschriftung 10, 11, 12, 13, 14
 | |
| 
 | |
|         # Datenquelle
 | |
|         ctx.set_font_size(16)
 | |
|         ctx.move_to(300, 40)
 | |
|         ctx.show_text("Source:")
 | |
|         ctx.move_to(300, 60)
 | |
|         ctx.show_text("VBat")
 | |
| 
 | |
|         # Batterietyp
 | |
|         ctx.move_to(300, 90)
 | |
|         ctx.show_text("Type:")
 | |
|         ctx.move_to(300, 110)
 | |
|         ctx.show_text("AGM")
 | |
| 
 | |
|         # Glättung
 | |
|         ctx.move_to(300, 140)
 | |
|         ctx.show_text("Avg:")
 | |
|         ctx.move_to(300, 160)
 | |
|         ctx.show_text("1s")
 | |
|         ctx.stroke()
 | |
| 
 | |
|         # Gleichstromsymbol
 | |
|         ctx.set_font_size(32)
 | |
|         ctx.move_to(20, 80)
 | |
|         ctx.show_text("V")
 | |
|         ctx.set_line_width(3)
 | |
|         ctx.move_to(20, 86.5) # obere Linie
 | |
|         ctx.line_to(40, 86.5)
 | |
|         ctx.move_to(20, 91.5) # untere drei kurzen Linien
 | |
|         ctx.line_to(25, 91.5)
 | |
|         ctx.move_to(27, 91.5)
 | |
|         ctx.line_to(33, 91.5)
 | |
|         ctx.move_to(35, 91.5)
 | |
|         ctx.line_to(40, 91.5)
 | |
|         ctx.stroke()
 | |
| 
 | |
|         # Kreis-segment 90°
 | |
| 
 | |
|         # Rotationszentrum
 | |
|         cx = 260
 | |
|         cy = 270
 | |
| 
 | |
|         # Radius des Instruments
 | |
|         r = 240
 | |
| 
 | |
|         ctx.set_source_rgb(*self.fgcolor)
 | |
|         ctx.set_line_width(2)
 | |
| 
 | |
|         ctx.arc(cx, cy, r, math.pi, 1.5*math.pi)
 | |
|         ctx.stroke()
 | |
| 
 | |
| 
 | |
|         # Beschriftung
 | |
|         ctx.set_font_size(20)
 | |
|         label = {285: "10", 300: "11", 315: "12", 330: "13", 345: "14"}
 | |
|         for angle in label:
 | |
|             x, y = self.rotate((cx, cy), ((cx, cy - r + 30),), angle)[0]
 | |
|             self.draw_text_center(ctx, x, y, label[angle])
 | |
| 
 | |
|         # grobe Skala
 | |
|         p = ((cx, cy-r), (cx, cy - r + 12))
 | |
|         ctx.set_line_width(2)
 | |
|         for angle in label:
 | |
|             line = self.rotate((cx, cy), p, angle)
 | |
|             ctx.move_to(*line[0])
 | |
|             ctx.line_to(*line[1])
 | |
|         ctx.stroke()
 | |
| 
 | |
|         # feine Skala
 | |
|         p = ((cx, cy-r), (cx, cy - r + 5))
 | |
|         ctx.set_line_width(1)
 | |
|         for angle in [x for x in range(273, 360, 3)]:
 | |
|             if angle in label:
 | |
|                 continue
 | |
|             line = self.rotate((cx, cy), p, angle)
 | |
|             ctx.move_to(*line[0])
 | |
|             ctx.line_to(*line[1])
 | |
|         ctx.stroke()
 | |
| 
 | |
|         # Zeiger auf 0-Position
 | |
|         val = float(self.bd.voltage.format())
 | |
|         if not val:
 | |
|             angle = -0.5
 | |
|         elif val > 15:
 | |
|             angle = 91
 | |
|         elif val <= 9:
 | |
|             angle = -0.5
 | |
|         else:
 | |
|             angle = (val - 9) * 15
 | |
|         p = ((cx - 2, cy + 4),
 | |
|              (cx - r + 35, cy + 2),
 | |
|              (cx - r + 35, cy + 1),
 | |
|              (cx - r + 5,  cy + 1),
 | |
|              (cx - r + 5,  cy - 1),
 | |
|              (cx - r + 35, cy - 1),
 | |
|              (cx - r + 35, cy - 2),
 | |
|              (cx - 2, cy - 4))
 | |
|         zeiger = self.rotate((cx, cy), p, angle)
 | |
| 
 | |
|         # Zeiger zeichnen
 | |
|         ctx.set_line_width(1)
 | |
|         ctx.move_to(*zeiger[0])
 | |
|         for point in zeiger[1:]:
 | |
|             ctx.line_to(*point)
 | |
|         ctx.fill()
 | |
| 
 | |
|         # Zeigerbasis 
 | |
|         ctx.arc(cx, cy, 6, 0, 2*math.pi)
 | |
|         ctx.set_source_rgb(*self.bgcolor)
 | |
|         ctx.fill_preserve()
 | |
|         ctx.set_line_width(2)
 | |
|         ctx.set_source_rgb(*self.fgcolor)
 | |
|         ctx.stroke()
 | |
| 
 | |
|     def draw_digital(self, ctx):
 | |
|         # Name
 | |
|         ctx.set_font_size(60) 
 | |
|         ctx.move_to(20, 100)
 | |
|         ctx.show_text("VBat")
 | |
|         # Unit
 | |
|         ctx.set_font_size(40)
 | |
|         ctx.move_to(270, 100)
 | |
|         ctx.show_text("V")
 | |
|         # Battery type
 | |
|         ctx.set_font_size(16)
 | |
|         ctx.move_to(294, 100)
 | |
|         ctx.show_text("AGM")
 | |
|         # Mittelwert
 | |
|         ctx.move_to(320, 84)
 | |
|         ctx.show_text("Avg: {}s".format(self.avg[self.avgindex]))
 | |
|         ctx.stroke()
 | |
| 
 | |
|         ctx.select_font_face("DSEG7 Classic")
 | |
|         ctx.set_font_size(100)
 | |
|         ctx.move_to(40, 240)
 | |
|         ctx.show_text(self.bd.voltage.format())
 | |
|         ctx.stroke()
 | |
| 
 | |
|         # Trendanzeige
 | |
|         if self.trend and self.bd.voltage.value and self.lastvalue:
 | |
|             ctx.rectangle(315, 183, 35, 4)
 | |
|             ctx.fill()
 | |
|             size = 11
 | |
|             if self.lastvalue < self.bd.voltage.value:
 | |
|                 ctx.move_to(320, 174)
 | |
|                 ctx.line_to(320+size*2, 174)
 | |
|                 ctx.line_to(320+size, 174-size*2)
 | |
|                 ctx.line_to(320, 174)
 | |
|                 ctx.fill()
 | |
|             elif self.lastvalue > self.bd.voltage.value:
 | |
|                 ctx.move_to(320, 195)
 | |
|                 ctx.line_to(320+size*2, 195)
 | |
|                 ctx.line_to(320+size, 195+size*2)
 | |
|                 ctx.line_to(320, 195)
 | |
|                 ctx.fill()
 | |
| 
 | |
|         self.lastvalue = self.bd.voltage.value
 |