From 7b7b239cfcdc3e9d1f4408f1ac448dec70b0c70c Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 12 Nov 2021 12:29:32 -0500 Subject: [PATCH 01/82] changed from bpi to pi0 --- input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.py b/input.py index fc054eb..71ce83a 100644 --- a/input.py +++ b/input.py @@ -116,7 +116,7 @@ if configure.input_pcf8575: from pcf8575 import PCF8575 - i2c_port_num = 0 + i2c_port_num = 1 pcf_address = 0x20 pcf = PCF8575(i2c_port_num, pcf_address) From db65868622ea574bda299e8a003ceb1cbcd7ac54 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 14 Nov 2021 14:26:27 -0500 Subject: [PATCH 02/82] cleanup --- lcars_clr_ili9341.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/lcars_clr_ili9341.py b/lcars_clr_ili9341.py index 9e03959..2676150 100644 --- a/lcars_clr_ili9341.py +++ b/lcars_clr_ili9341.py @@ -37,9 +37,6 @@ TFT.initLCD(DC, RST, LED) - - - # Load default font. font = ImageFont.truetype("assets/babs.otf",13) titlefont = ImageFont.truetype("assets/babs.otf",16) From 17c944eeb43fc5be52db885dda7fbb54b43cd351 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 22:56:53 -0500 Subject: [PATCH 03/82] button test --- input.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/input.py b/input.py index 8db4209..4296e05 100644 --- a/input.py +++ b/input.py @@ -223,7 +223,7 @@ def read(self): # if the alert pin is brought LOW if GPIO.input(configure.ALERTPIN) == 0 and configure.eventready[0] == False: - print("touch received") + #print("touch received") # collect the event list from the chip reading = cap1208.get_input_status() @@ -368,8 +368,10 @@ def read(self): if configure.input_pcf8575: if not configure.eventready[0]: - print("button state = ", pcf.port) - for this, button in enumerate(pcf.port): + this_frame = pcf.port + print("button state = ", this_frame) + for this, button in enumerate(this_frame): + # if an item is pressed if not button: From 3cf8dea4603f2116f194a594f9d441bee558a047 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 23:08:52 -0500 Subject: [PATCH 04/82] more feedback --- input.py | 1 + 1 file changed, 1 insertion(+) diff --git a/input.py b/input.py index 4296e05..85a3c5d 100644 --- a/input.py +++ b/input.py @@ -380,6 +380,7 @@ def read(self): # mark it in the pressed list print("pad press registered") + print(this) self.pressed[this] = True configure.eventready[0] = True configure.beep_ready[0] = True From 7b1080ebba551b1c98e4399a5d316932febba990 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 23:12:47 -0500 Subject: [PATCH 05/82] feedback --- input.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/input.py b/input.py index 85a3c5d..5c5a4d1 100644 --- a/input.py +++ b/input.py @@ -368,10 +368,10 @@ def read(self): if configure.input_pcf8575: if not configure.eventready[0]: - this_frame = pcf.port - print("button state = ", this_frame) - for this, button in enumerate(this_frame): + this_frame = list(pcf.port) + for this, button in enumerate(this_frame): + print("button state = ", this_frame) # if an item is pressed if not button: From e41c200602fac4caa2736e6a39025050dc812eef Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 23:15:50 -0500 Subject: [PATCH 06/82] feedback --- input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.py b/input.py index 5c5a4d1..da1558c 100644 --- a/input.py +++ b/input.py @@ -117,7 +117,7 @@ if configure.input_pcf8575: from pcf8575 import PCF8575 i2c_port_num = 1 - pcf_address = 0x20 + pcf_address = 0x26 pcf = PCF8575(i2c_port_num, pcf_address) # the input class handles all the requirements for handling user directed inputs From 01e99eceb62a02801a3593c961ce09418cd2b9ac Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 23:45:39 -0500 Subject: [PATCH 07/82] pcf8575 --- input.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/input.py b/input.py index da1558c..76a242f 100644 --- a/input.py +++ b/input.py @@ -117,9 +117,11 @@ if configure.input_pcf8575: from pcf8575 import PCF8575 i2c_port_num = 1 - pcf_address = 0x26 + pcf_address = 0x20 pcf = PCF8575(i2c_port_num, pcf_address) + button_table = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,0,3,2,0] + # the input class handles all the requirements for handling user directed inputs class Inputs(object): @@ -380,12 +382,12 @@ def read(self): # mark it in the pressed list print("pad press registered") - print(this) - self.pressed[this] = True + + self.pressed[button_table[this]] = True configure.eventready[0] = True configure.beep_ready[0] = True else: - self.pressed[this] = False + self.pressed[button_table[this]] = False From 71ff70530f9018736ff466d569db61947e0f203a Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 23:50:59 -0500 Subject: [PATCH 08/82] test stuff --- input.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/input.py b/input.py index 76a242f..12c04df 100644 --- a/input.py +++ b/input.py @@ -120,7 +120,7 @@ pcf_address = 0x20 pcf = PCF8575(i2c_port_num, pcf_address) - button_table = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,0,3,2,0] + button_table = [-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,0,3,2,4] # the input class handles all the requirements for handling user directed inputs class Inputs(object): @@ -381,7 +381,8 @@ def read(self): if not self.pressed[this]: # mark it in the pressed list - print("pad press registered") + print("pad press registered at ", this) + print("raising an event at address ", button_table[this]) self.pressed[button_table[this]] = True configure.eventready[0] = True From 94b0209d6794ee0907e9536fb759be46cadb3169 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 23:51:19 -0500 Subject: [PATCH 09/82] test --- input.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/input.py b/input.py index 12c04df..547070f 100644 --- a/input.py +++ b/input.py @@ -373,7 +373,7 @@ def read(self): this_frame = list(pcf.port) for this, button in enumerate(this_frame): - print("button state = ", this_frame) + # if an item is pressed if not button: From 6bb6f620b37c7c5a5ca697e0b3bbc9d546d6e2f7 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Nov 2021 23:56:26 -0500 Subject: [PATCH 10/82] pipe into eventlist --- input.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/input.py b/input.py index 547070f..30a8f3c 100644 --- a/input.py +++ b/input.py @@ -390,6 +390,11 @@ def read(self): else: self.pressed[button_table[this]] = False + configure.eventlist[0] = self.pressed + + # return the pressed data + return self.pressed + def keypress(self): From 87418ca96266a34e99fde544afd056ea29951798 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 20 Nov 2021 00:01:19 -0500 Subject: [PATCH 11/82] sensors on. --- objects.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/objects.py b/objects.py index 509bb5d..3258bfc 100644 --- a/objects.py +++ b/objects.py @@ -80,8 +80,8 @@ def __init__(self): # Toggles individual sensor support self.system_vitals = True - self.bme = False - self.amg8833 = False + self.bme = True + self.amg8833 = True #sets the upper and lower threshold for the alert self.TEMP_ALERT = (0,100) From 9acfc88b3038455a542b1cc3479fef50497de04e Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 20 Nov 2021 00:08:55 -0500 Subject: [PATCH 12/82] address change --- amg8833_pil.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/amg8833_pil.py b/amg8833_pil.py index 882694d..9e8d590 100644 --- a/amg8833_pil.py +++ b/amg8833_pil.py @@ -37,7 +37,7 @@ import busio import board i2c = busio.I2C(board.SCL, board.SDA) - amg = adafruit_amg88xx.AMG88XX(i2c) + amg = adafruit_amg88xx.AMG88XX(i2c, addr=0x68) From 4e36b49819ca0cc209fa7db896511f20e78c0f56 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 20 Nov 2021 14:17:17 -0500 Subject: [PATCH 13/82] attemptying to unify codebases --- display.py | 32 ++++++++++++++++++++++++++++++++ lcars_clr.py | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 display.py diff --git a/display.py b/display.py new file mode 100644 index 0000000..e982e2a --- /dev/null +++ b/display.py @@ -0,0 +1,32 @@ +# attempts to be a tranmission for a range of different + + +# load requirements + +# Provide a response to the display argument. + +# take in a PIL image and push it to the required screen. + +def get_device(actual_args=None): + """ + Create device from command-line arguments and return it. + """ + if actual_args is None: + actual_args = sys.argv[1:] + parser = cmdline.create_parser(description='luma.examples arguments') + args = parser.parse_args(actual_args) + + if args.config: + # load config from file + config = cmdline.load_config(args.config) + args = parser.parse_args(config + actual_args) + + # create device + try: + device = cmdline.create_device(args) + print(display_settings(device, args)) + return device + + except error.Error as e: + parser.error(e) + return None diff --git a/lcars_clr.py b/lcars_clr.py index c3e94c2..288f362 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -35,7 +35,7 @@ if not configure.pc: - serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST)# ,bus_speed_hz=24000000) + serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST) ,bus_speed_hz=32000000) device = st7735(serial, width = 160, height = 128, mode = "RGB") From a741390a436c7c72d34ac936d2d2db55a9e72b47 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 19 Feb 2022 17:39:50 -0500 Subject: [PATCH 14/82] spacecat tests --- amg8833_pil.py | 1 + display.py | 9 +++++++++ lcars_clr.py | 1 - main.py | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/amg8833_pil.py b/amg8833_pil.py index e21ea86..fe06878 100644 --- a/amg8833_pil.py +++ b/amg8833_pil.py @@ -1,4 +1,5 @@ print("Loading AMG8833 Thermal Camera Module") +# changed. #import pygame import random import math diff --git a/display.py b/display.py index ac082ae..3d8fbbe 100644 --- a/display.py +++ b/display.py @@ -10,6 +10,12 @@ import sys import logging +# remove this part and replace with display +from luma.core.interface.serial import spi +from luma.core.render import canvas +from luma.lcd.device import st7735 +from luma.emulator.device import pygame + from luma.core import cmdline, error @@ -69,3 +75,6 @@ def get_device(actual_args=None): except error.Error as e: parser.error(e) return None + +class GenericDisplay(object): + pass diff --git a/lcars_clr.py b/lcars_clr.py index 69afeba..28124bb 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -23,7 +23,6 @@ from amg8833_pil import * from plars import * from objects import * - from modulated_em import * # Load default font. diff --git a/main.py b/main.py index 27bc8ba..7bdb201 100644 --- a/main.py +++ b/main.py @@ -41,7 +41,7 @@ if configure.tr109: if configure.display == 2: - from lcars_clr import * + from lcars_clr_ili9341 import * # 1.8" TFT colour LCD if configure.display == 1: From ad2a2bee4f475225fda49abf6301fa0016d4455d Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 19 Feb 2022 21:31:10 -0500 Subject: [PATCH 15/82] adding display "2" behaviours --- main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 7bdb201..7eaf336 100644 --- a/main.py +++ b/main.py @@ -66,7 +66,7 @@ def Main(): if configure.display == 0: dotscreen = NokiaScreen() - if configure.display == 1: + if configure.display == 1 or configure.display == 2: colourscreen = ColourScreen() colourscreen.start_up() @@ -131,7 +131,7 @@ def Main(): if configure.display == 0: configure.status[0] = dotscreen.push(data) - if configure.display == 1: + if configure.display == 1 or configure.display == 2: configure.status[0] = colourscreen.graph_screen() if configure.status[0] == "mode_b": @@ -147,7 +147,7 @@ def Main(): if configure.tr109: if configure.display == 0: configure.status[0] = dotscreen.push(data) - if configure.display == 1: + if configure.display == 1 or configure.display == 2: configure.status[0] = colourscreen.em_screen() if configure.status[0] == "mode_c": @@ -167,7 +167,7 @@ def Main(): if configure.tr109: if configure.display == 0: configure.status[0] = dotscreen.push() - if configure.display == 1: + if configure.display == 1 or configure.display == 2: configure.status[0] = colourscreen.settings() # Handles the poweroff screen @@ -176,7 +176,7 @@ def Main(): if configure.tr109: if configure.display == 0: configure.status[0] = dotscreen.push() - if configure.display == 1: + if configure.display == 1 or configure.display == 2: configure.status[0] = colourscreen.powerdown() if configure.status[0] == "shutdown": From 02419931f757cf048ce59aec88bcbb4e96dbeb37 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 19 Feb 2022 23:54:47 -0500 Subject: [PATCH 16/82] tft24t changes to main lcars_clr --- lcars_clr.py | 75 +++++++++++++++++++++++++++++++++----------- lcars_clr_ili9341.py | 61 ++++++++++++++++++++++++++++------- main.py | 5 +-- 3 files changed, 107 insertions(+), 34 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 28124bb..0dd7e3f 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -1,16 +1,47 @@ #!/usr/bin/env python # This module controls the st7735 type screens print("Loading 160x128 LCARS Interface") +from objects import * import math import time from operator import itemgetter -# remove this part and replace with display -from luma.core.interface.serial import spi -from luma.core.render import canvas -from luma.lcd.device import st7735 -from luma.emulator.device import pygame +if configure.display = 1: + # remove this part and replace with display + from luma.core.interface.serial import spi + from luma.core.render import canvas + from luma.lcd.device import st7735 + from luma.emulator.device import pygame + + # Raspberry Pi hardware SPI config: + DC = 23 + RST = 24 + SPI_PORT = 0 + SPI_DEVICE = 0 + + if not configure.pc: + serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST) ,bus_speed_hz=32000000) + device = st7735(serial, width = 160, height = 128, mode = "RGB") + else: + device = pygame(width = 160, height = 128) + +# for TFT24T screens +elif configure.display = 2: + # Details pulled from https://github.com/BehindTheSciences/ili9341_SPI_TouchScreen_LCD_Raspberry-Pi/blob/master/BTS-ili9341-touch-calibration.py + from lib_tft24T import TFT24T + import RPi.GPIO as GPIO + GPIO.setmode(GPIO.BCM) + GPIO.setwarnings(False) + import spidev + DC = 24 + RST = 25 + LED = 15 + PEN = 26 + TFT = TFT24T(spidev.SpiDev(), GPIO) + # Initialize display and touch. + TFT.initLCD(DC, RST, LED) + # Load up the image library stuff to help draw bitmaps to push to the screen import PIL.ImageOps @@ -22,7 +53,8 @@ from pilgraph import * from amg8833_pil import * from plars import * -from objects import * + + from modulated_em import * # Load default font. @@ -35,20 +67,10 @@ # Load assets logo = Image.open('assets/picorderOS_logo.png') -# Raspberry Pi hardware SPI config: -DC = 23 -RST = 24 -SPI_PORT = 0 -SPI_DEVICE = 0 -TRANSITION = [False] -if not configure.pc: - serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST) ,bus_speed_hz=32000000) - device = st7735(serial, width = 160, height = 128, mode = "RGB") -else: - device = pygame(width = 160, height = 128) + # Standard LCARS colours @@ -605,6 +627,9 @@ def push(self, draw): return status + + + # Controls the LCARS frame, measures the label and makes sure the top frame bar has the right spacing. class MultiFrame(object): @@ -962,6 +987,9 @@ class ColourScreen(object): def __init__(self): + if configure.display = 2 + self.surface = TFT.draw() + # instantiates an image and uses it in a draw object. self.image = Image.open('assets/lcarsframe.png')#.convert('1') self.blankimage = Image.open('assets/lcarsframeblank.png') @@ -1042,4 +1070,15 @@ def powerdown(self): def pixdrw(self): thisimage = self.newimage.convert(mode = "RGB") - device.display(thisimage) + + # the following is only for screens that use Luma.LCD + if configure.display = 1: + device.display(thisimage) + + # the following is only for TFT24T screens + elif configure.display = 2: + # Resize the image and rotate it so it's 240x320 pixels. + thisimage = self.newimage.rotate(90,0,1).resize((240, 320)) + # Draw the image on the display hardware. + self.surface.pasteimage(thisimage,(0,0)) + TFT.display() diff --git a/lcars_clr_ili9341.py b/lcars_clr_ili9341.py index 2676150..fe13900 100644 --- a/lcars_clr_ili9341.py +++ b/lcars_clr_ili9341.py @@ -22,17 +22,12 @@ import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) - import spidev -from time import sleep - DC = 24 RST = 25 LED = 15 PEN = 26 - TFT = TFT24T(spidev.SpiDev(), GPIO) - # Initialize display and touch. TFT.initLCD(DC, RST, LED) @@ -620,9 +615,46 @@ def push(self,draw): return status -# governs the screen drawing of the entire program. Everything flows through Screen. -# Screen instantiates a draw object and passes it the image background. -# Screen monitors button presses and passes flags for interface updates to the draw object. + + +class StartUp(object): + def __init__(self): + self.titlex = 0 + self.titley = 77 + self.labely = 102 + self.jump = 22 + + self.graphcycle = 0 + self.decimal = 1 + + self.divider = 47 + self.labely = 102 + + + self.title = LabelObj("PicorderOS " + configure.version,bigfont, colour = lcars_peach) + self.item = LabelObj(configure.boot_message,font,colour = lcars_peach) + + # creates and interval timer for screen refresh. + self.interval = timer() + self.interval.logtime() + + def push(self, draw): + + draw.bitmap((59,15),logo) + #draw the frame heading + self.title.center(self.titley,0,160,draw) + + #draw the title and version + self.item.center(self.titley+self.jump,0, 160,draw) + + + if self.interval.timelapsed() > configure.boot_delay and configure.sensor_ready[0]: + status = "mode_a" + else: + status = "startup" + + + return status class ThermalFrame(object): def __init__(self): @@ -749,20 +781,25 @@ def __init__(self): self.powerdown_frame = PowerDown() + def start_up(self): + self.newimage = self.burgerfull.copy() + self.draw = ImageDraw.Draw(self.newimage) + self.status = self.startup_frame.push(self.draw) + + self.pixdrw() + + return self.status + def get_size(self): return self.multi_frame.get_x() def graph_screen(self): - self.newimage = self.image.copy() self.draw = ImageDraw.Draw(self.newimage) self.status = self.multi_frame.push(self.draw) - self.pixdrw() - return self.status - def thermal_screen(self): self.newimage = self.image.copy() self.draw = ImageDraw.Draw(self.newimage) diff --git a/main.py b/main.py index 7eaf336..fdaf1ba 100644 --- a/main.py +++ b/main.py @@ -40,11 +40,8 @@ # for the TR-109 there are two display modes supported. if configure.tr109: - if configure.display == 2: - from lcars_clr_ili9341 import * - # 1.8" TFT colour LCD - if configure.display == 1: + if configure.display == 1 or configure.display == 2: from lcars_clr import * # Nokia 5110 black and white dot matrix screen. From a6413960abb0796e3df11a82f943b48b869b70ac Mon Sep 17 00:00:00 2001 From: chris Date: Sun, 20 Feb 2022 17:52:34 -0500 Subject: [PATCH 17/82] == not = --- lcars_clr.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 0dd7e3f..98f64bc 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -7,7 +7,7 @@ from operator import itemgetter -if configure.display = 1: +if configure.display == 1: # remove this part and replace with display from luma.core.interface.serial import spi from luma.core.render import canvas @@ -27,7 +27,7 @@ device = pygame(width = 160, height = 128) # for TFT24T screens -elif configure.display = 2: +elif configure.display == 2: # Details pulled from https://github.com/BehindTheSciences/ili9341_SPI_TouchScreen_LCD_Raspberry-Pi/blob/master/BTS-ili9341-touch-calibration.py from lib_tft24T import TFT24T import RPi.GPIO as GPIO @@ -987,7 +987,7 @@ class ColourScreen(object): def __init__(self): - if configure.display = 2 + if configure.display == 2 self.surface = TFT.draw() # instantiates an image and uses it in a draw object. @@ -1072,11 +1072,11 @@ def pixdrw(self): thisimage = self.newimage.convert(mode = "RGB") # the following is only for screens that use Luma.LCD - if configure.display = 1: + if configure.display == 1: device.display(thisimage) # the following is only for TFT24T screens - elif configure.display = 2: + elif configure.display == 2: # Resize the image and rotate it so it's 240x320 pixels. thisimage = self.newimage.rotate(90,0,1).resize((240, 320)) # Draw the image on the display hardware. From 3905558d6119f956943fcdfa70da9e8e0f648f37 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 20 Feb 2022 20:30:17 -0500 Subject: [PATCH 18/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 98f64bc..f9b6e0f 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -21,7 +21,7 @@ SPI_DEVICE = 0 if not configure.pc: - serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST) ,bus_speed_hz=32000000) + serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST) device = st7735(serial, width = 160, height = 128, mode = "RGB") else: device = pygame(width = 160, height = 128) From 6540a08061b651860bad84a6d4fb3caa7838a878 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 20 Feb 2022 20:38:39 -0500 Subject: [PATCH 19/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index f9b6e0f..0d06ea7 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -987,7 +987,7 @@ class ColourScreen(object): def __init__(self): - if configure.display == 2 + if configure.display == 2: self.surface = TFT.draw() # instantiates an image and uses it in a draw object. From ed27c50fc106220fb446e4241ab843dd177b12fa Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 21 Feb 2022 14:58:50 -0500 Subject: [PATCH 20/82] test --- README.md | 2 ++ leds.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 421756c..d743fe9 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ sudo apt-get update sudo apt-get upgrade +sudo apt install libsdl2-2.0-0 libsdl2-gfx-1.0-0 libsdl2-image-2.0-0 libsdl2-mixer-2.0-0 libsdl2-net-2.0-0 libsdl2-ttf-2.0-0 + sudo apt-get install libatlas-base-dev libsdl2-dev libopenjp2-7-dev libtiff5 python3-pandas python3-psutil pip3 install --upgrade colour luma.lcd luma.emulator adafruit-circuitpython-bme680 sense-hat adafruit-circuitpython-mpr121 pygame==2.0.0 diff --git a/leds.py b/leds.py index a46386e..738cea5 100644 --- a/leds.py +++ b/leds.py @@ -128,7 +128,7 @@ def resetleds(): # # This way you can just manually set them as you please. def screen_on(): if configure.tr109: - GPIO.output(sc_led, GPIO.HIGH) + GPIO.output(sc_led, GPIO.LOW) def leda_on(): GPIO.output(led1, GPIO.HIGH) From 28cd84dd0ab307129514b6b28390fed7eb04a40d Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 21 Feb 2022 14:59:09 -0500 Subject: [PATCH 21/82] fix --- leds.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/leds.py b/leds.py index 738cea5..1c75e2f 100644 --- a/leds.py +++ b/leds.py @@ -128,7 +128,10 @@ def resetleds(): # # This way you can just manually set them as you please. def screen_on(): if configure.tr109: - GPIO.output(sc_led, GPIO.LOW) + if configure.display == 0: + GPIO.output(sc_led, GPIO.HIGH) + elif configure.display == 1: + GPIO.output(sc_led, GPIO.LOW) def leda_on(): GPIO.output(led1, GPIO.HIGH) From cf0335b50bd54f35b73862b0f1e6fb1e4e17df10 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 21 Feb 2022 15:01:14 -0500 Subject: [PATCH 22/82] fix --- leds.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/leds.py b/leds.py index 1c75e2f..49de674 100644 --- a/leds.py +++ b/leds.py @@ -128,9 +128,9 @@ def resetleds(): # # This way you can just manually set them as you please. def screen_on(): if configure.tr109: - if configure.display == 0: + if configure.display == 1: GPIO.output(sc_led, GPIO.HIGH) - elif configure.display == 1: + elif configure.display == 2: GPIO.output(sc_led, GPIO.LOW) def leda_on(): From 342f81864463d147b5927568cec57d9c8c48e0ca Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 21 Feb 2022 15:04:39 -0500 Subject: [PATCH 23/82] fix --- leds.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/leds.py b/leds.py index 49de674..ca395a9 100644 --- a/leds.py +++ b/leds.py @@ -130,8 +130,6 @@ def screen_on(): if configure.tr109: if configure.display == 1: GPIO.output(sc_led, GPIO.HIGH) - elif configure.display == 2: - GPIO.output(sc_led, GPIO.LOW) def leda_on(): GPIO.output(led1, GPIO.HIGH) From b81afe9fc657da4fc8c71549ecef237e05225310 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 25 Feb 2022 14:05:47 -0500 Subject: [PATCH 24/82] tests for various components. --- main.py | 7 +++++++ objects.py | 3 +++ pilgraph.py | 30 ++++++++++++++++++++---------- sensors.py | 6 +++++- tos_display.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 11 deletions(-) diff --git a/main.py b/main.py index 27bc8ba..7c1a38b 100644 --- a/main.py +++ b/main.py @@ -154,6 +154,13 @@ def Main(): if configure.tr109: if configure.display == 1: configure.status[0] = colourscreen.thermal_screen() + + if configure.tr108: + configure.status[0] = PyScreen.video_screen() + if not configure.pc: + leda_on() + ledb_on() + ledc_off() if (configure.status[0] == "settings"): diff --git a/objects.py b/objects.py index eb57301..f6f4c90 100644 --- a/objects.py +++ b/objects.py @@ -29,7 +29,10 @@ def createMissingINI(self,filepath): config['SENSORS'] = {'# Only TR-108 uses SenseHat':None, 'sensehat':'yes', # Only TR-108 uses this 'system_vitals':'yes', + '# BME680 Raw Values':None, 'bme':'no', + '# BME680 VOC BSEC':None, + 'bme_bsec':'no', 'amg8833':'no', 'pocket_geiger':'no', '# IR Infrared Imaging':None, diff --git a/pilgraph.py b/pilgraph.py index a71d5f4..c8e17e5 100644 --- a/pilgraph.py +++ b/pilgraph.py @@ -2,8 +2,8 @@ # PILgraph provides an object (graphlist) that will draw a new graph each frame. -# It was written to contain memory of the previous sensor readings, but this -# feature is no longer necessary. +# It was written to contain all the previous sensor readings, but this +# feature is no longer necessary as PLARS now handles all data history. # To do: # - request from PLARS the N most recent values for the sensor assigned to this identifier @@ -11,8 +11,11 @@ # it is initialized with: -# - a graph identifier so it knows which sensor to grab data for -# - +# - ident: a graph identifier so it knows which sensor to grab data for +# - graphcoords: list containing the top left x,y coordinates +# - graphspan: list containing the x and y span in pixels +# - cycle: time per division of the graph (not working) +# - from objects import * from PIL import Image @@ -28,20 +31,26 @@ class graph_area(object): def __init__(self, ident, graphcoords, graphspan, cycle = 0, colour = 0, width = 1, type = 0, samples = False): + # if a samplesize is provided use it, otherwise grab global setting. if not samples: self.samples = configure.samples else: self.samples = samples - self.new = True self.cycle = cycle - self.tock = timer() - self.tock.logtime() + + self.glist = array('f', []) self.dlist = array('f', []) + self.colour = colour + + #controls auto scaling (set by global variable at render) self.auto = True + + # controls width self.width = width + self.dotw = 6 self.doth = 6 self.buff = array('f', []) @@ -201,8 +210,9 @@ def render(self, draw, auto = True, dot = True, ranger = None): # standard pilgraph: takes DSC,DEV keypairs from screen drawer, asks # plars for data, graphs it. - if self.type == 0: + # Standard graph + if self.type == 0: index = configure.sensors[self.ident][0] dsc,dev,sym,maxi,mini = configure.sensor_info[index] recent = plars.get_recent(dsc,dev,num = self.samples) @@ -211,12 +221,12 @@ def render(self, draw, auto = True, dot = True, ranger = None): elif self.type == 1: recent = plars.get_top_em_history(no = self.samples) - # Testing a stream graph + # Testing a new graph elif self.type == 2: recent = plars.get_recent(dsc,dev,num = self.samples) - cords = self.graphprep(recent) + cords = self.graphprep(recent) self.buff = recent # draws the line graph diff --git a/sensors.py b/sensors.py index 620d38a..5614c29 100644 --- a/sensors.py +++ b/sensors.py @@ -180,6 +180,10 @@ def __init__(self): self.bme_humi = Fragment(0,100,"Hygrometer", "%", "BME680") self.bme_press = Fragment(300,1100,"Barometer","hPa", "BME680") self.bme_voc = Fragment(300000,1100000,"VOC","KOhm", "BME680") + self.voc_procc = subprocess.Popen(['./bsec_bme680'], stdout=subprocess.PIPE) + + if configure.bme_bsec: + self.bme_bsec = Fragment(-40,85,"Quality",self.deg_sym + "Q", "BME680") if configure.pocket_geiger: self.radiat = Fragment(0.0, 10000.0, "Radiation", "urem/hr", "pocketgeiger") @@ -266,7 +270,7 @@ def get(self): # times 100 to convert to urem/h self.radiat.set(rad_data*100, timestamp) - + sensorlist.append(self.radiat) if configure.amg8833: diff --git a/tos_display.py b/tos_display.py index 4471120..96d2f36 100644 --- a/tos_display.py +++ b/tos_display.py @@ -581,6 +581,7 @@ def frame(self): if keys[1]: status = "mode_b" + configure.eventready[0] = False return status if keys[2]: @@ -750,6 +751,51 @@ def frame(self): def visible(self,item,option): self.visibility[item] = option +#experimental video screen written by scifi.radio from the mycorder discord +class Video_Screen(object): + def __init__(self,surface): + self.status = "mode_c" + self.surface = surface + self.videobg = Image() + self.videobg.update(videobg, 0,0) + + + def frame(self): + self.status = "mode_c" + if configure.eventready[0]: + + # The following code handles inputs and button presses. + keys = configure.eventlist[0] + + # if a key is registering as pressed. + if keys[0]: + print("Button 1") + status = "mode_b" + configure.eventready[0] = False + return self.status + + if keys[1]: + status = "mode_d" + print("Button 2") + configure.eventready[0] = False + return self.status + + + if keys[2]: + configure.last_status[0] = "mode_d" + print("Button 3") + status = "settings" + configure.eventready[0] = False + return self.status + + configure.eventready[0] = False + + #draws Background gridplane + self.videobg.draw(self.surface) + #draws UI to frame buffer + pygame.display.update() + + return status class Slider_Screen(object): From a8d3e0c6ad3702d1ad271d2c67b9f768c0cacce3 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 25 Feb 2022 14:38:05 -0500 Subject: [PATCH 25/82] video slide tests --- assets/videobg.png | Bin 0 -> 25620 bytes tos_display.py | 12 +++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 assets/videobg.png diff --git a/assets/videobg.png b/assets/videobg.png new file mode 100644 index 0000000000000000000000000000000000000000..3ba234a3b41cf0763d5cecf107bfb480e78ae55d GIT binary patch literal 25620 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 Date: Fri, 25 Feb 2022 14:44:30 -0500 Subject: [PATCH 26/82] fixes for video screen. --- tos_display.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tos_display.py b/tos_display.py index fad6ff1..c701d73 100644 --- a/tos_display.py +++ b/tos_display.py @@ -944,6 +944,7 @@ def __init__(self): self.timed = time.time() self.graphscreen = Graph_Screen(self.surface) + self.videoscreen = Video_Screen(self.surface) self.slidescreen = Slider_Screen(self.surface) self.settings_screen = Settings_Panel(self.surface) From ddbb49b898aaf2aeff37011175879c9d81a65dfc Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 25 Feb 2022 14:45:58 -0500 Subject: [PATCH 27/82] fixes video --- tos_display.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tos_display.py b/tos_display.py index c701d73..13a8959 100644 --- a/tos_display.py +++ b/tos_display.py @@ -71,6 +71,7 @@ backgraph = pygame.image.load('assets/backgraph.png') slidera = pygame.image.load('assets/slider.png') sliderb = pygame.image.load('assets/slider2.png') +videobg = pygame.image.load('assets/videobg.png') status = "startup" last_status = "startup" From 31c189c7ae9994f3374bb4f26d54ffdb08068f85 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 25 Feb 2022 14:47:32 -0500 Subject: [PATCH 28/82] video fixes --- tos_display.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tos_display.py b/tos_display.py index 13a8959..2030ce1 100644 --- a/tos_display.py +++ b/tos_display.py @@ -796,7 +796,7 @@ def frame(self): #draws UI to frame buffer pygame.display.update() - return status + return self.status class Slider_Screen(object): From 60670846ce7b13c1b73cec6ee1e381a93eb6feb8 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 25 Feb 2022 15:08:07 -0500 Subject: [PATCH 29/82] video fixes --- main.py | 8 ++++---- tos_display.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/main.py b/main.py index 7c1a38b..b52e54c 100644 --- a/main.py +++ b/main.py @@ -115,7 +115,7 @@ def Main(): # The rest of these loops all handle a different mode, switched by buttons within the functions. - if (configure.status[0] == "mode_a"): + if configure.status[0] == "mode_a": # the following is only run if the tr108 flag is set if configure.tr108: @@ -154,7 +154,7 @@ def Main(): if configure.tr109: if configure.display == 1: configure.status[0] = colourscreen.thermal_screen() - + if configure.tr108: configure.status[0] = PyScreen.video_screen() if not configure.pc: @@ -162,7 +162,7 @@ def Main(): ledb_on() ledc_off() - if (configure.status[0] == "settings"): + if configure.status[0] == "settings": if configure.tr108: configure.status[0] = PyScreen.settings() @@ -178,7 +178,7 @@ def Main(): configure.status[0] = colourscreen.settings() # Handles the poweroff screen - if (configure.status[0] == "poweroff"): + if configure.status[0] == "poweroff": if configure.tr109: if configure.display == 0: diff --git a/tos_display.py b/tos_display.py index 2030ce1..af9cd4b 100644 --- a/tos_display.py +++ b/tos_display.py @@ -771,12 +771,12 @@ def frame(self): # if a key is registering as pressed. if keys[0]: print("Button 1") - status = "mode_b" + self.status = "mode_b" configure.eventready[0] = False return self.status if keys[1]: - status = "mode_c" + self.status = "mode_c" print("Button 2") configure.eventready[0] = False return self.status @@ -785,7 +785,7 @@ def frame(self): if keys[2]: configure.last_status[0] = "mode_c" print("Button 3") - status = "settings" + self.status = "settings" configure.eventready[0] = False return self.status From 9b5210d0ee81a869e4b0a56fd938d4c5db6048b3 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Mar 2022 14:48:11 -0500 Subject: [PATCH 30/82] display module groundwork --- amg8833_pil.py | 303 ------------------------------------------------- display.py | 120 +++++++++----------- lcars_clr.py | 49 +------- 3 files changed, 54 insertions(+), 418 deletions(-) delete mode 100644 amg8833_pil.py diff --git a/amg8833_pil.py b/amg8833_pil.py deleted file mode 100644 index fe06878..0000000 --- a/amg8833_pil.py +++ /dev/null @@ -1,303 +0,0 @@ -print("Loading AMG8833 Thermal Camera Module") -# changed. -#import pygame -import random -import math - -# Load up the image library stuff to help draw bitmaps to push to the screen -import PIL.ImageOps - - -# from https://learn.adafruit.com/adafruit-amg8833-8x8-thermal-camera-sensor/raspberry-pi-thermal-camera -# interpolates the data into a smoothed screen res -import numpy as np -from scipy.interpolate import griddata -from colour import Color - - -# some utility functions -def constrain(val, min_val, max_val): - return min(max_val, max(min_val, val)) - - -def map_value(x, in_min, in_max, out_min, out_max): - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min - -from PIL import Image -from PIL import ImageFont -from PIL import ImageDraw -from colour import Color -# The following are for LCARS colours from LCARScom.net -lcars_orange = (255,153,0) -lcars_pink = (204,153,204) -lcars_blue = (153,152,208) -lcars_red = (204,102,102) -lcars_peach = (255,204,153) -lcars_bluer = (153,153,255) -lcars_orpeach = (255,153,102) -lcars_pinker = (204,102,153) - -standard_blue = (0,0,255) -standard_red = (255,0,0) - -# low range of the sensor (this will be blue on the screen) -MINTEMP = -2.0 - -# high range of the sensor (this will be red on the screen) -MAXTEMP = 150.0 - -# how many color values we can have -COLORDEPTH = 1024 - -# pylint: disable=invalid-slice-index -points = [(math.floor(ix / 8), (ix % 8)) for ix in range(0, 64)] -grid_x, grid_y = np.mgrid[0:7:32j, 0:7:32j] -# pylint: enable=invalid-slice-index -# sensor is an 8x8 grid so lets do a square -height = 133 -width = 71 - -# the list of colors we can choose from -cool = Color(rgb=(0.0, 0.0, 0.0)) #Color("blue") -hot = Color(rgb=(0.8, 0.4, 0.6))#"red") -#blue = Color("indigo") -colors = list(cool.range_to(hot, COLORDEPTH)) - -# create the array of colors -colors = [(int(c.red * 255), int(c.green * 255), int(c.blue * 255)) for c in colors] - -displayPixelWidth = width / 30 -displayPixelHeight = height / 30 - - -colrange = list(cool.range_to(hot, 256)) - -rotate = False -fliplr = False -flipud = True - -from objects import * - -import sensors - -if configure.amg8833: - import adafruit_amg88xx - import busio - import board - i2c = busio.I2C(board.SCL, board.SDA) - amg = adafruit_amg88xx.AMG88XX(i2c, addr=0x68) - - - -#some utility functions -def constrain(val, min_val, max_val): - return min(max_val, max(min_val, val)) - -def map(x, in_min, in_max, out_min, out_max): - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min - -# create an 8x8 array for testing purposes. Displays random 'sensor data'. -def makegrid(random = True): - dummyvalue = [] - # - for i in range(8): - dummyrow = [] - for r in range(8): - if random: - dummyrow.append(random.uniform(1.0,81.0)) - else: - dummyrow.append(0) - dummyvalue.append(dummyrow) - - return dummyvalue - -# a single pixel of temperature information -class ThermalPixel(object): - - def __init__(self,x,y,w,h): - self.x = x - self.y = y - self.w = w - self.h = h - self.colour = (255,255,255) - self.temp = 0 - self.count = 0 - - - def update(self,value,high,low,surface): - - if configure.auto[0]: - color = map(value, low, high, 0, 254) - else: - color = map(value, 0, 80, 0, 254) - if color > 255: - color = 255 - if color < 0: - color = 0 - - colorindex = int(color) - - temp = colrange[colorindex].rgb - - red = int(temp[0] * 255.0) - green = int(temp[1] * 255.0) - blue = int(temp[2] * 255.0) - - self.count += 1 - - if self.count > 255: - self.count = 0 - - surface.rectangle([(self.x, self.y), (self.x + self.w, self.y + self.h)], fill = (red,green,blue), outline=None) - -class ThermalColumns(object): - - def __init__(self,x,y,w,h): - self.x = x - self.y = y - self.w = w - self.h = h - - self.pixels = [] - - for i in range(8): - self.pixels.append(ThermalPixel(self.x, self.y + (i * (h/8)), self.w, self.h / 8)) - - #[10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0] - def update(self,data,high,low,surface): - for i in range(8): - self.pixels[i].update(data[i],high, low, surface) - -class ThermalRows(object): - - def __init__(self,x,y,w,h): - self.x = x - self.y = y - self.w = w - self.h = h - - self.pixels = [] - - for i in range(8): - self.pixels.append(ThermalPixel(self.x + (i * (w/8)), self.y, self.w / 8, self.h)) - - #[10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0] - def update(self,data,high,low,surface): - for i in range(8): - self.pixels[i].update(data[i],high, low, surface) - -class ThermalGrid(object): - - def __init__(self,x,y,w,h): - self.x = x - self.y = y - self.h = h - self.w = w - self.data = [] - - self.rows = [] - self.high = 0.0 - self.low = 0.0 - self.average = 0 - self.ticks = 0 - - for i in range(8): - self.rows.append(ThermalRows(self.x, self.y + (i * (h/8)), self.w, self.h / 8)) - - self.update() - - def push(self,surface): - if not configure.interpolate[0]: - for i in range(8): - self.rows[i].update(self.data[i],self.high,self.low,surface) - else: - self.interpolate(surface) - # Function to draw a pretty pattern to the display for demonstration. - def animate(self): - - self.dummy = makegrid(random = False) - - for x in range(8): - for y in range(8): - cx = x + 0.5*math.sin(self.ticks/5.0) - cy = y + 0.5*math.cos(self.ticks/3.0) - a = math.sin(math.sqrt(1.0*(math.pow(cx, 2.0)+math.pow(cy, 2.0))+1.0)+self.ticks) - b = math.sin(10*(x * math.sin(self.ticks/2) + y * math.cos(self.ticks/3))+self.ticks) - v = (a + 1.0)/2.0 - - v = int(v*256.0) - self.dummy[x][y] = v - #dsense.set_pixel(x,y,v,v,v) - self.ticks = self.ticks+1 - return self.dummy - - def interpolate(self, surface): - - height = self.w - width = self.h - displayPixelWidth = width / 30 - displayPixelHeight = height / 30 - - if configure.auto[0]: - # low range of the sensor (this will be blue on the screen) - mintemp = self.low - # high range of the sensor (this will be red on the screen) - maxtemp = self.high - else: - mintemp = MINTEMP - maxtemp = MAXTEMP - - pixels = [] - - for row in self.data: - pixels = pixels + list(row) - pixels = [map_value(p, mintemp, maxtemp, 0, COLORDEPTH - 1) for p in pixels] - - # perform interpolation - bicubic = griddata(points, pixels, (grid_x, grid_y), method="cubic") - - # draw everything - for ix, row in enumerate(bicubic): - for jx, pixel in enumerate(row): - x = self.x + (displayPixelHeight * ix) - y = self.y + (displayPixelWidth * jx) - x2 = x + displayPixelHeight - y2 = y + displayPixelWidth - surface.rectangle([(x, y), (x2, y2)], fill = colors[constrain(int(pixel), 0, COLORDEPTH - 1)], outline=None) - - def update(self): - - if configure.amg8833: - self.data = amg.pixels - else: - self.data = self.animate() - - if rotate: - self.data = np.transpose(self.data).tolist() - - if fliplr: - self.data = np.fliplr(self.data).tolist() - - if flipud: - self.data = np.flipud(self.data).tolist() - - thisaverage = 0 - rangemax = [] - rangemin = [] - - for i in range(8): - - for j in range(8): - thisaverage += self.data[i][j] - - thismax = max(self.data[i]) - thismin = min(self.data[i]) - rangemin.append(thismin) - rangemax.append(thismax) - - self.average = thisaverage / (8*8) - - self.high = max(rangemax) - self.low = min(rangemin) - - return self.average, self.high, self.low diff --git a/display.py b/display.py index 3d8fbbe..d66dc6f 100644 --- a/display.py +++ b/display.py @@ -1,80 +1,62 @@ - args = parser.parse_args(actual_args) - -# -*- coding: utf-8 -*- -# Originally found: https://github.com/rm-hull/luma.examples/blob/master/examples/demo_opts.py -# Modified for PicorderOS -# Copyright (c) 2014-18 Richard Hull and contributors -# See LICENSE.rst for details. - print("Unified Display Module loading") import sys import logging -# remove this part and replace with display -from luma.core.interface.serial import spi -from luma.core.render import canvas -from luma.lcd.device import st7735 -from luma.emulator.device import pygame - -from luma.core import cmdline, error - - -# logging -logging.basicConfig( - level=logging.DEBUG, - format='%(asctime)-15s - %(message)s' -) -# ignore PIL debug messages -logging.getLogger('PIL').setLevel(logging.ERROR) - +if configure.display == 1: + from luma.core.interface.serial import spi + from luma.core.render import canvas + from luma.lcd.device import st7735 + from luma.emulator.device import pygame + + # Raspberry Pi hardware SPI config: + DC = 23 + RST = 24 + SPI_PORT = 0 + SPI_DEVICE = 0 + + if not configure.pc: + serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST) + device = st7735(serial, width = 160, height = 128, mode = "RGB") + else: + device = pygame(width = 160, height = 128) + +# for TFT24T screens +elif configure.display == 2: + # Details pulled from https://github.com/BehindTheSciences/ili9341_SPI_TouchScreen_LCD_Raspberry-Pi/blob/master/BTS-ili9341-touch-calibration.py + from lib_tft24T import TFT24T + import RPi.GPIO as GPIO + GPIO.setmode(GPIO.BCM) + GPIO.setwarnings(False) + import spidev + DC = 24 + RST = 25 + LED = 15 + PEN = 26 + device = TFT24T(spidev.SpiDev(), GPIO) + # Initialize display and touch. + TFT.initLCD(DC, RST, LED) -def display_settings(device, args): - """ - Display a short summary of the settings. - :rtype: str - """ - iface = '' - display_types = cmdline.get_display_types() - if args.display not in display_types['emulator']: - iface = 'Interface: {}\n'.format(args.interface) - - lib_name = cmdline.get_library_for_display_type(args.display) - if lib_name is not None: - lib_version = cmdline.get_library_version(lib_name) - else: - lib_name = lib_version = 'unknown' - - import luma.core - version = 'luma.{} {} (luma.core {})'.format( - lib_name, lib_version, luma.core.__version__) - - return 'Version: {}\nDisplay: {}\n{}Dimensions: {} x {}\n{}'.format( - version, args.display, iface, device.width, device.height, '-' * 60) +class GenericDisplay(object): + def __init__(self -def get_device(actual_args=None): - """ - Create device from command-line arguments and return it. - """ - if actual_args is None: - actual_args = sys.argv[1:] - parser = cmdline.create_parser(description='luma.examples arguments') - args = parser.parse_args(actual_args) + # lib_tft24 screens require us to create a drawing surface for the screen + # and add to it. + if configure.display == 2: + self.surface = device.draw() - if args.config: - # load config from file - config = cmdline.load_config(args.config) - args = parser.parse_args(config + actual_args) - # create device - try: - device = cmdline.create_device(args) - print(display_settings(device, args)) - return device + # Display takes a PILlow based drawobject and pushes it to screen. + def display(self,frame): - except error.Error as e: - parser.error(e) - return None + # the following is only for screens that use Luma.LCD + if configure.display == 1: + device.display(frame) -class GenericDisplay(object): - pass + # the following is only for TFT24T screens + elif configure.display == 2: + # Resize the image and rotate it so it's 240x320 pixels. + frame = frame.rotate(90,0,1).resize((240, 320)) + # Draw the image on the display hardware. + self.surface.pasteimage(frame,(0,0)) + device.display() diff --git a/lcars_clr.py b/lcars_clr.py index 0d06ea7..a1aa387 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -7,41 +7,9 @@ from operator import itemgetter -if configure.display == 1: - # remove this part and replace with display - from luma.core.interface.serial import spi - from luma.core.render import canvas - from luma.lcd.device import st7735 - from luma.emulator.device import pygame - - # Raspberry Pi hardware SPI config: - DC = 23 - RST = 24 - SPI_PORT = 0 - SPI_DEVICE = 0 - - if not configure.pc: - serial = spi(port = SPI_PORT, device = SPI_DEVICE, gpio_DC = DC, gpio_RST = RST) - device = st7735(serial, width = 160, height = 128, mode = "RGB") - else: - device = pygame(width = 160, height = 128) - -# for TFT24T screens -elif configure.display == 2: - # Details pulled from https://github.com/BehindTheSciences/ili9341_SPI_TouchScreen_LCD_Raspberry-Pi/blob/master/BTS-ili9341-touch-calibration.py - from lib_tft24T import TFT24T - import RPi.GPIO as GPIO - GPIO.setmode(GPIO.BCM) - GPIO.setwarnings(False) - import spidev - DC = 24 - RST = 25 - LED = 15 - PEN = 26 - TFT = TFT24T(spidev.SpiDev(), GPIO) - # Initialize display and touch. - TFT.initLCD(DC, RST, LED) +from display import GenericDisplay +display = GenericDisplay() # Load up the image library stuff to help draw bitmaps to push to the screen import PIL.ImageOps @@ -1070,15 +1038,4 @@ def powerdown(self): def pixdrw(self): thisimage = self.newimage.convert(mode = "RGB") - - # the following is only for screens that use Luma.LCD - if configure.display == 1: - device.display(thisimage) - - # the following is only for TFT24T screens - elif configure.display == 2: - # Resize the image and rotate it so it's 240x320 pixels. - thisimage = self.newimage.rotate(90,0,1).resize((240, 320)) - # Draw the image on the display hardware. - self.surface.pasteimage(thisimage,(0,0)) - TFT.display() + device.display(thisimage) From f0aff168acffc868410c046e3c0f9b13b4d94b2e Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Mar 2022 14:57:33 -0500 Subject: [PATCH 31/82] fixes --- display.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/display.py b/display.py index d66dc6f..0d668f4 100644 --- a/display.py +++ b/display.py @@ -38,7 +38,7 @@ class GenericDisplay(object): - def __init__(self + def __init__(self): # lib_tft24 screens require us to create a drawing surface for the screen # and add to it. From b55c80ea55e17c45f4d3cf308cae7294f28269b3 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Mar 2022 14:58:12 -0500 Subject: [PATCH 32/82] fixes --- display.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/display.py b/display.py index 0d668f4..ce55df1 100644 --- a/display.py +++ b/display.py @@ -38,16 +38,16 @@ class GenericDisplay(object): - def __init__(self): + def __init__(self): - # lib_tft24 screens require us to create a drawing surface for the screen - # and add to it. + # lib_tft24 screens require us to create a drawing surface for the screen + # and add to it. if configure.display == 2: self.surface = device.draw() - # Display takes a PILlow based drawobject and pushes it to screen. - def display(self,frame): + # Display takes a PILlow based drawobject and pushes it to screen. + def display(self,frame): # the following is only for screens that use Luma.LCD if configure.display == 1: From d33f80e96bbc49cdcf4209295ddfc12f9458dfa8 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Mar 2022 14:58:47 -0500 Subject: [PATCH 33/82] fixes --- display.py | 1 + 1 file changed, 1 insertion(+) diff --git a/display.py b/display.py index ce55df1..55a8848 100644 --- a/display.py +++ b/display.py @@ -1,6 +1,7 @@ print("Unified Display Module loading") import sys import logging +from objects import * if configure.display == 1: from luma.core.interface.serial import spi From 65f04eed00838cab2c36fb21a20d2b363db5b8fd Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Mar 2022 15:00:46 -0500 Subject: [PATCH 34/82] fixes --- amg8833_pil.py | 302 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 amg8833_pil.py diff --git a/amg8833_pil.py b/amg8833_pil.py new file mode 100644 index 0000000..7d8b704 --- /dev/null +++ b/amg8833_pil.py @@ -0,0 +1,302 @@ +print("Loading AMG8833 Thermal Camera Module") +#import pygame +import random +import math + +# Load up the image library stuff to help draw bitmaps to push to the screen +import PIL.ImageOps + + +# from https://learn.adafruit.com/adafruit-amg8833-8x8-thermal-camera-sensor/raspberry-pi-thermal-camera +# interpolates the data into a smoothed screen res +import numpy as np +from scipy.interpolate import griddata +from colour import Color + + +# some utility functions +def constrain(val, min_val, max_val): + return min(max_val, max(min_val, val)) + + +def map_value(x, in_min, in_max, out_min, out_max): + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min + +from PIL import Image +from PIL import ImageFont +from PIL import ImageDraw +from colour import Color +# The following are for LCARS colours from LCARScom.net +lcars_orange = (255,153,0) +lcars_pink = (204,153,204) +lcars_blue = (153,152,208) +lcars_red = (204,102,102) +lcars_peach = (255,204,153) +lcars_bluer = (153,153,255) +lcars_orpeach = (255,153,102) +lcars_pinker = (204,102,153) + +standard_blue = (0,0,255) +standard_red = (255,0,0) + +# low range of the sensor (this will be blue on the screen) +MINTEMP = -2.0 + +# high range of the sensor (this will be red on the screen) +MAXTEMP = 150.0 + +# how many color values we can have +COLORDEPTH = 1024 + +# pylint: disable=invalid-slice-index +points = [(math.floor(ix / 8), (ix % 8)) for ix in range(0, 64)] +grid_x, grid_y = np.mgrid[0:7:32j, 0:7:32j] +# pylint: enable=invalid-slice-index +# sensor is an 8x8 grid so lets do a square +height = 133 +width = 71 + +# the list of colors we can choose from +cool = Color(rgb=(0.0, 0.0, 0.0)) #Color("blue") +hot = Color(rgb=(0.8, 0.4, 0.6))#"red") +#blue = Color("indigo") +colors = list(cool.range_to(hot, COLORDEPTH)) + +# create the array of colors +colors = [(int(c.red * 255), int(c.green * 255), int(c.blue * 255)) for c in colors] + +displayPixelWidth = width / 30 +displayPixelHeight = height / 30 + + +colrange = list(cool.range_to(hot, 256)) + +rotate = False +fliplr = False +flipud = True + +from objects import * + +import sensors + +if configure.amg8833: + import adafruit_amg88xx + import busio + import board + i2c = busio.I2C(board.SCL, board.SDA) + amg = adafruit_amg88xx.AMG88XX(i2c) + + + +#some utility functions +def constrain(val, min_val, max_val): + return min(max_val, max(min_val, val)) + +def map(x, in_min, in_max, out_min, out_max): + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min + +# create an 8x8 array for testing purposes. Displays random 'sensor data'. +def makegrid(random = True): + dummyvalue = [] + # + for i in range(8): + dummyrow = [] + for r in range(8): + if random: + dummyrow.append(random.uniform(1.0,81.0)) + else: + dummyrow.append(0) + dummyvalue.append(dummyrow) + + return dummyvalue + +# a single pixel of temperature information +class ThermalPixel(object): + + def __init__(self,x,y,w,h): + self.x = x + self.y = y + self.w = w + self.h = h + self.colour = (255,255,255) + self.temp = 0 + self.count = 0 + + + def update(self,value,high,low,surface): + + if configure.auto[0]: + color = map(value, low, high, 0, 254) + else: + color = map(value, 0, 80, 0, 254) + if color > 255: + color = 255 + if color < 0: + color = 0 + + colorindex = int(color) + + temp = colrange[colorindex].rgb + + red = int(temp[0] * 255.0) + green = int(temp[1] * 255.0) + blue = int(temp[2] * 255.0) + + self.count += 1 + + if self.count > 255: + self.count = 0 + + surface.rectangle([(self.x, self.y), (self.x + self.w, self.y + self.h)], fill = (red,green,blue), outline=None) + +class ThermalColumns(object): + + def __init__(self,x,y,w,h): + self.x = x + self.y = y + self.w = w + self.h = h + + self.pixels = [] + + for i in range(8): + self.pixels.append(ThermalPixel(self.x, self.y + (i * (h/8)), self.w, self.h / 8)) + + #[10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0] + def update(self,data,high,low,surface): + for i in range(8): + self.pixels[i].update(data[i],high, low, surface) + +class ThermalRows(object): + + def __init__(self,x,y,w,h): + self.x = x + self.y = y + self.w = w + self.h = h + + self.pixels = [] + + for i in range(8): + self.pixels.append(ThermalPixel(self.x + (i * (w/8)), self.y, self.w / 8, self.h)) + + #[10.0,10.0,10.0,10.0,10.0,10.0,10.0,10.0] + def update(self,data,high,low,surface): + for i in range(8): + self.pixels[i].update(data[i],high, low, surface) + +class ThermalGrid(object): + + def __init__(self,x,y,w,h): + self.x = x + self.y = y + self.h = h + self.w = w + self.data = [] + + self.rows = [] + self.high = 0.0 + self.low = 0.0 + self.average = 0 + self.ticks = 0 + + for i in range(8): + self.rows.append(ThermalRows(self.x, self.y + (i * (h/8)), self.w, self.h / 8)) + + self.update() + + def push(self,surface): + if not configure.interpolate[0]: + for i in range(8): + self.rows[i].update(self.data[i],self.high,self.low,surface) + else: + self.interpolate(surface) + # Function to draw a pretty pattern to the display for demonstration. + def animate(self): + + self.dummy = makegrid(random = False) + + for x in range(8): + for y in range(8): + cx = x + 0.5*math.sin(self.ticks/5.0) + cy = y + 0.5*math.cos(self.ticks/3.0) + a = math.sin(math.sqrt(1.0*(math.pow(cx, 2.0)+math.pow(cy, 2.0))+1.0)+self.ticks) + b = math.sin(10*(x * math.sin(self.ticks/2) + y * math.cos(self.ticks/3))+self.ticks) + v = (a + 1.0)/2.0 + + v = int(v*256.0) + self.dummy[x][y] = v + #dsense.set_pixel(x,y,v,v,v) + self.ticks = self.ticks+1 + return self.dummy + + def interpolate(self, surface): + + height = self.w + width = self.h + displayPixelWidth = width / 30 + displayPixelHeight = height / 30 + + if configure.auto[0]: + # low range of the sensor (this will be blue on the screen) + mintemp = self.low + # high range of the sensor (this will be red on the screen) + maxtemp = self.high + else: + mintemp = MINTEMP + maxtemp = MAXTEMP + + pixels = [] + + for row in self.data: + pixels = pixels + list(row) + pixels = [map_value(p, mintemp, maxtemp, 0, COLORDEPTH - 1) for p in pixels] + + # perform interpolation + bicubic = griddata(points, pixels, (grid_x, grid_y), method="cubic") + + # draw everything + for ix, row in enumerate(bicubic): + for jx, pixel in enumerate(row): + x = self.x + (displayPixelHeight * ix) + y = self.y + (displayPixelWidth * jx) + x2 = x + displayPixelHeight + y2 = y + displayPixelWidth + surface.rectangle([(x, y), (x2, y2)], fill = colors[constrain(int(pixel), 0, COLORDEPTH - 1)], outline=None) + + def update(self): + + if configure.amg8833: + self.data = amg.pixels + else: + self.data = self.animate() + + if rotate: + self.data = np.transpose(self.data).tolist() + + if fliplr: + self.data = np.fliplr(self.data).tolist() + + if flipud: + self.data = np.flipud(self.data).tolist() + + thisaverage = 0 + rangemax = [] + rangemin = [] + + for i in range(8): + + for j in range(8): + thisaverage += self.data[i][j] + + thismax = max(self.data[i]) + thismin = min(self.data[i]) + rangemin.append(thismin) + rangemax.append(thismax) + + self.average = thisaverage / (8*8) + + self.high = max(rangemax) + self.low = min(rangemin) + + return self.average, self.high, self.low From 83d06e7636f5ff23e6d1fd003adfa2a525d93a3b Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Mar 2022 15:01:50 -0500 Subject: [PATCH 35/82] fixes --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index a1aa387..488f753 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -9,7 +9,7 @@ from display import GenericDisplay -display = GenericDisplay() +device = GenericDisplay() # Load up the image library stuff to help draw bitmaps to push to the screen import PIL.ImageOps From 9811efb26910252bf754b96e497078c978dd30de Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Mar 2022 16:04:24 -0500 Subject: [PATCH 36/82] fixes --- lcars_clr.py | 2 +- lcars_clr_ili9341.py | 830 ------------------------------------------- 2 files changed, 1 insertion(+), 831 deletions(-) delete mode 100644 lcars_clr_ili9341.py diff --git a/lcars_clr.py b/lcars_clr.py index 488f753..1083751 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -959,7 +959,7 @@ def __init__(self): self.surface = TFT.draw() # instantiates an image and uses it in a draw object. - self.image = Image.open('assets/lcarsframe.png')#.convert('1') + self.image = Image.open('assets/lcarsframe.png') self.blankimage = Image.open('assets/lcarsframeblank.png') self.tbar = Image.open('assets/lcarssplitframe.png') self.burger = Image.open('assets/lcarsburgerframe.png') diff --git a/lcars_clr_ili9341.py b/lcars_clr_ili9341.py deleted file mode 100644 index fe13900..0000000 --- a/lcars_clr_ili9341.py +++ /dev/null @@ -1,830 +0,0 @@ -#!/usr/bin/env python -# This module controls the st7735 type screens -print("Loading Secondary Screen Module ili9341") -import math -import time - -# Load up the image library stuff to help draw bitmaps to push to the screen -import PIL.ImageOps -from PIL import Image -from PIL import ImageFont -from PIL import ImageDraw - -# load the module that draws graphs -from pilgraph import * -from amg8833_pil import * -from plars import * -from objects import * - - -# Details pulled from https://github.com/BehindTheSciences/ili9341_SPI_TouchScreen_LCD_Raspberry-Pi/blob/master/BTS-ili9341-touch-calibration.py -from lib_tft24T import TFT24T -import RPi.GPIO as GPIO -GPIO.setmode(GPIO.BCM) -GPIO.setwarnings(False) -import spidev -DC = 24 -RST = 25 -LED = 15 -PEN = 26 -TFT = TFT24T(spidev.SpiDev(), GPIO) -# Initialize display and touch. -TFT.initLCD(DC, RST, LED) - - -# Load default font. -font = ImageFont.truetype("assets/babs.otf",13) -titlefont = ImageFont.truetype("assets/babs.otf",16) -bigfont = ImageFont.truetype("assets/babs.otf",20) - -# Raspberry Pi hardware SPI config: -DC = 23 -RST = 24 -SPI_PORT = 0 -SPI_DEVICE = 0 - -TRANSITION = [False] - - - -# The following are for LCARS colours from LCARScom.net -lcars_orange = (255,153,0) -lcars_pink = (204,153,204) -lcars_blue = (153,153,204) -lcars_red = (204,102,102) -lcars_peach = (255,204,153) -lcars_bluer = (153,153,255) -lcars_orpeach = (255,153,102) -lcars_pinker = (204,102,153) - -theme1 = [lcars_orange,lcars_blue,lcars_pinker] - -fore_col = 0 -back_col = 1 - -# Controls text objects drawn to the LCD -class LabelObj(object): - def __init__(self,string,font, colour = lcars_blue): - self.font = font - #self.draw = draw - self.string = string - self.colour = colour - - def center(self,y,x,w,draw): - size = self.font.getsize(self.string) - xmid = x + w/2 - #ymid = y + h/2 - textposx = xmid - (size[0]/2) - #textposy = ymid - (size[1]/2) + self.scaler - self.push(textposx,y,draw) - - def r_align(self,x,y,draw): - size = self.font.getsize(self.string) - self.push(x-size[0],y,draw) - - # Draws the label onto the provided draw buffer. - def push(self,locx,locy,draw): - self.draw = draw - self.draw.text((locx, locy), self.string, font = self.font, fill= self.colour) - - def getsize(self): - size = self.draw.textsize(self.string, font=self.font) - return size - -class SelectableLabel(LabelObj): - - - def __init__(self,font,draw,oper,colour = lcars_blue, special = 0): - self.font = font - self.draw = draw - self.colour = colour - - # special determines the behaviour of the label for each type of oper - # the class is supplied. There may be multiple types of int or boolean based - # configuration parameters so this variable helps make new options - self.special = special - - # coordinates - self.x = 0 - self.y = 0 - - # basic graphical parameters - self.fontSize = 33 - - # self.myfont = pygame.font.Font(titleFont, self.fontSize) - # text = "Basic Item" - # self.size = self.myfont.size(text) - - self.scaler = 3 - self.selected = False - self.indicator = Image() - self.content = "default" - - # this variable is a reference to a list stored in "objects.py" - # containing either a boolean or an integer - self.oper = oper - - def update(self, content, fontSize, nx, ny, fontType, color): - self.x = nx - self.y = ny - self.content = content - self.fontSize = fontSize - self.myfont = pygame.font.Font(fontType, self.fontSize) - self.color = color - self.indicator.update(sliderb, nx - 23, ny+1) - - def toggle(self): - - # if the parameter supplied is a boolean - if isinstance(self.oper[0], bool): - #toggle its state - self.oper[0] = not self.oper[0] - - #if the parameter supplied is an integer - elif isinstance(self.oper[0], int): - - # increment the integer. - self.oper[0] += 1 - - # if the integer is larger than the pool - if self.special == 1 and self.oper[0] > configure.max_sensors[0]-1: - self.oper[0] = 0 - - if self.special == 2 and self.oper[0] > (len(themes) - 1): - self.oper[0] = 0 - - return self.oper[0] - - def draw(self, surface): - if self.selected: - self.indicator.draw(surface) - - label = self.myfont.render(self.content, 1, self.color) - - - status_text = "dummy" - if self.special == 0: - status_text = str(self.oper[0]) - elif self.special == 1: - status_text = configure.sensor_info[self.oper[0]][3] - elif self.special == 2: - status_text = themenames[self.oper[0]] - - pos = resolution[0] - (self.get_size(status_text) + 37) - state = self.myfont.render(status_text, 1, self.color) - - - surface.blit(label, (self.x, self.y)) - surface.blit(state, (pos, self.y)) - - -class SettingsFrame(object): - def __init__(self): - - self.pages = [["Sensor 1",configure.sensor1], ["Sensor 2", configure.sensor2], ["Sensor 3",configure.sensor3], ["Auto Range",configure.auto], ["LEDs", configure.sleep],["Power Off","poweroff"]] - - # Sets the topleft origin of the graph - self.graphx = 23 - self.graphy = 24 - - self.status_raised = False - - # Sets the x and y span of the graph - self.gspanx = 133 - self.gspany = 71 - - self.selection = 0 - - self.auto = configure.auto[0] - self.interval = timer() - self.interval.logtime() - #self.draw = draw - self.titlex = 25 - self.titley = 6 - self.labely = 102 - - self.graphcycle = 0 - self.decimal = 1 - - self.divider = 47 - self.labely = 102 - - - self.title = LabelObj("Settings",titlefont) - self.itemlabel = LabelObj("Item Label",titlefont,colour = lcars_peach) - self.A_Label = LabelObj("Next",font,colour = lcars_blue) - self.B_Label = LabelObj("Enter",font, colour = lcars_blue) - self.C_Label = LabelObj("Exit",font, colour = lcars_blue) - - self.item = LabelObj("No Data",bigfont,colour = lcars_pink) - - - # device needs to show multiple settings - # first the sensor palette configuration - - def toggle(self,oper): - - # if the parameter supplied is a boolean - if isinstance(oper[0], bool): - #toggle its state - oper[0] = not oper[0] - - #if the parameter supplied is an integer - elif isinstance(oper[0], int): - - # increment the integer. - oper[0] += 1 - - # if the integer is larger than the pool - if oper[0] > configure.max_sensors[0]-1: - oper[0] = 0 - - elif isinstance(oper, str): - #configure.last_status[0] = configure.status[0] - self.status_raised = True - configure.status[0] = oper - - - return oper - - - def push(self, draw): - - #draw the frame heading - self.title.push(self.titlex,self.titley,draw) - - - #draw the option item heading - self.itemlabel.string = str(self.pages[self.selection][0]) - self.itemlabel.push(self.titlex,self.titley+20,draw) - - - - self.A_Label.push(23,self.labely,draw) - self.B_Label.center(self.labely,23,135,draw) - self.C_Label.r_align(156,self.labely,draw) - - - #draw the 3 graph parameter items - if self.selection == 0 or self.selection == 1 or self.selection == 2: - - self.item.string = str(configure.sensor_info[self.pages[self.selection][1][0]][3]) - self.item.push(self.titlex,self.titley+40,draw) - else: - - if isinstance(self.pages[self.selection][1][0], bool): - self.item.string = str(self.pages[self.selection][1][0]) - self.item.push(self.titlex,self.titley+40,draw) - - - status = "settings" - - if configure.eventready[0]: - keys = configure.eventlist[0] - - if keys[0]: - self.selection = self.selection + 1 - if self.selection > (len(self.pages) - 1): - self.selection = 0 - - if keys[1]: - state = self.toggle(self.pages[self.selection][1]) - - if self.status_raised: - status = state - self.status_raised = False - - if keys[2]: - status = configure.last_status[0] - - configure.eventready[0] = False - - return status - -class PowerDown(object): - def __init__(self): - - # Sets the topleft origin of the graph - self.graphx = 23 - self.graphy = 24 - - self.status_raised = False - - # Sets the x and y span of the graph - self.gspanx = 133 - self.gspany = 71 - - self.selection = 0 - - - self.auto = configure.auto[0] - self.interval = timer() - self.interval.logtime() - #self.draw = draw - self.titlex = 25 - self.titley = 6 - self.labely = 102 - - self.graphcycle = 0 - self.decimal = 1 - - self.divider = 47 - self.labely = 102 - - - self.title = LabelObj("CAUTION",bigfont, colour = lcars_red) - self.itemlabel = LabelObj("Item Label",titlefont,colour = lcars_orange) - self.A_Label = LabelObj("Yes",font,colour = lcars_blue) - self.B_Label = LabelObj("Enter",font, colour = lcars_blue) - self.C_Label = LabelObj("No",font, colour = lcars_blue) - - self.item = LabelObj("No Data",bigfont,colour = lcars_orpeach) - # device needs to show multiple settings - # first the sensor palette configuration - - - def push(self, draw): - - #draw the frame heading - - self.title.center(self.titley,self.titlex,135,draw) - - - #draw the option item heading - #self.itemlabel.string = str(self.pages[self.selection][0]) - # self.itemlabel.push(self.titlex,self.titley+20,draw) - - - - self.A_Label.push(23,self.labely,draw) - - - #self.B_Label.center(self.labely,23,135,draw) - - - self.C_Label.r_align(156,self.labely,draw) - - - #draw the 3 graph parameter items - - self.item.string = "Power Down?" - self.item.center(self.titley+40, self.titlex, 135,draw) - - - status = "poweroff" - - - if configure.eventready[0]: - - keys = configure.eventlist[0] - - if keys[0]: - status = "shutdown" - - if keys[1]: - pass - - if keys[2]: - status = "settings" - - configure.eventready[0] = False - - - return status - - - -# Controls the LCARS frame, measures the label and makes sure the top frame bar has the right spacing. -class MultiFrame(object): - - def __init__(self): - - - - # Sets the topleft origin of the graph - self.graphx = 23 - self.graphy = 24 - - # Sets the x and y span of the graph - self.gspanx = 133 - self.gspany = 71 - - - self.marginleft = 23 - self.marginright= 133 - - # sets the background image for the display - self.back = Image.open('assets/lcarsframe.png') - - # sets the currently selected sensor to focus on - self.selection = 0 - - # ties the auto state to the global object - self.auto = configure.auto[0] - - # creates and interval timer for screen refresh. - self.interval = timer() - self.interval.logtime() - - # Sets the coordinates of onscreen labels. - self.titlex = 23 - self.titley = 6 - self.labely = 102 - - self.graphcycle = 0 - - self.decimal = 1 - - self.divider = 47 - - # create our graph_screen - self.A_Graph = graph_area(0,(self.graphx,self.graphy),(self.gspanx,self.gspany),self.graphcycle, theme1[0], width = 1) - - self.B_Graph = graph_area(1,(self.graphx,self.graphy),(self.gspanx,self.gspany),self.graphcycle, theme1[1], width = 1) - - self.C_Graph = graph_area(2,(self.graphx,self.graphy),(self.gspanx,self.gspany),self.graphcycle, theme1[2], width = 1) - - self.Graphs = [self.A_Graph, self.B_Graph, self.C_Graph] - - self.A_Label = LabelObj("a_string",font,colour = lcars_orange) - - self.B_Label = LabelObj("b_string",font, colour = lcars_blue) - - self.C_Label = LabelObj("c_string",font, colour = lcars_pinker) - - self.focus_Label = LabelObj("test",bigfont, colour = lcars_orpeach) - self.focus_high_Label = LabelObj("test",font, colour = lcars_peach) - self.focus_low_Label = LabelObj("test",font, colour = lcars_bluer) - self.focus_mean_Label = LabelObj("test",font, colour = lcars_pinker) - - self.title = LabelObj("Multi-Graph",titlefont, colour = lcars_peach) - - def get_x(self): - return self.gspanx - self.graphx - - # takes a value and sheds the second digit after the decimal place - def arrangelabel(self,data,range = ".0f"): - datareturn = format(float(data), range) - return datareturn - - # defines the labels for the screen - def labels(self): - - # depending on which number the "selection" variable takes on. - if self.selection == 0: - raw_a = str(self.A_Data) - adjusted_a = self.arrangelabel(raw_a) - a_string = adjusted_a + " " + configure.sensor_info[configure.sensor1[0]][4] - - raw_b = str(self.B_Data) - adjusted_b = self.arrangelabel(raw_b) - b_string = adjusted_b + " " + configure.sensor_info[configure.sensor2[0]][4] - - raw_c = str(self.C_Data) - adjusted_c = self.arrangelabel(raw_c) - c_string = adjusted_c + " " + configure.sensor_info[configure.sensor3[0]][4] - - self.A_Label.string = a_string - self.A_Label.push(23,self.labely,self.draw) - - self.B_Label.string = b_string - self.B_Label.center(self.labely,23,135,self.draw) - - self.C_Label.string = c_string - self.C_Label.r_align(156,self.labely,self.draw) - - # displays more details for whatever sensor is in focus - if self.selection != 0: - - carousel = [self.A_Data,self.B_Data,self.C_Data] - - this = self.selection - 1 - - this_bundle = self.Graphs[this] - - raw = str(carousel[this]) - - adjusted = self.arrangelabel(raw, '.2f') - self.focus_Label.string = adjusted - self.focus_Label.r_align(156,self.titley,self.draw) - - self.focus_high_Label.string = "max " + self.arrangelabel(str(this_bundle.get_high()), '.1f') - self.focus_high_Label.push(23,self.labely,self.draw) - - self.focus_low_Label.string = "min " + self.arrangelabel(str(this_bundle.get_low()), '.1f') - self.focus_low_Label.center(self.labely,23,135,self.draw) - - self.focus_mean_Label.string = "x- " + self.arrangelabel(str(this_bundle.get_average()), '.1f') - self.focus_mean_Label.r_align(156,self.labely,self.draw) - - - # push the image frame and contents to the draw object. - def push(self,draw): - - - - # returns mode_a to the main loop unless something causes state change - status = "mode_a" - - - if configure.eventready[0]: - keys = configure.eventlist[0] - - # if a key is registering as pressed increment or rollover the selection variable. - if keys[0]: - self.selection += 1 - if self.selection > 3: - self.selection = 0 - - if keys[1]: - status = "mode_b" - configure.eventready[0] = False - return status - - if keys[2]: - configure.last_status[0] = "mode_a" - status = "settings" - configure.eventready[0] = False - return status - - configure.eventready[0] = False - - - # passes the current bitmap buffer to the object incase someone else needs it. - self.draw = draw - - senseslice =[0,0,0] - - for i in range(3): - - dsc = configure.sensor_info[configure.sensors[i][0]][3] - dev = configure.sensor_info[configure.sensors[i][0]][5] - - item = plars.get_recent(dsc,dev,num = 1) - - senseslice[i] = item[0] - - - # Grabs the current sensor reading - self.A_Data = senseslice[0]#configure.sensor_data[configure.sensor1[0]][0] - self.B_Data = senseslice[1]#configure.sensor_data[configure.sensor2[0]][0] - self.C_Data = senseslice[2]#configure.sensor_data[configure.sensor3[0]][0] - - - - - # Draws the Title - if self.selection != 0: - this = self.selection - 1 - self.title.string = configure.sensor_info[configure.sensors[this][0]][3] - else: - self.title.string = "Multi-Graph" - - self.title.push(self.titlex,self.titley,draw) - - - - - # Updates the graphs with the new data. - self.A_Graph.update(self.A_Data) - self.B_Graph.update(self.B_Data) - self.C_Graph.update(self.C_Data) - - # turns each channel on individually - if self.selection == 0: - - self.C_Graph.render(self.draw) - self.B_Graph.render(self.draw) - self.A_Graph.render(self.draw) - - - - if self.selection == 1: - self.A_Graph.render(self.draw) - - if self.selection == 2: - self.B_Graph.render(self.draw) - - if self.selection == 3: - self.C_Graph.render(self.draw) - - - - self.labels() - - - - return status - - -class StartUp(object): - def __init__(self): - self.titlex = 0 - self.titley = 77 - self.labely = 102 - self.jump = 22 - - self.graphcycle = 0 - self.decimal = 1 - - self.divider = 47 - self.labely = 102 - - - self.title = LabelObj("PicorderOS " + configure.version,bigfont, colour = lcars_peach) - self.item = LabelObj(configure.boot_message,font,colour = lcars_peach) - - # creates and interval timer for screen refresh. - self.interval = timer() - self.interval.logtime() - - def push(self, draw): - - draw.bitmap((59,15),logo) - #draw the frame heading - self.title.center(self.titley,0,160,draw) - - #draw the title and version - self.item.center(self.titley+self.jump,0, 160,draw) - - - if self.interval.timelapsed() > configure.boot_delay and configure.sensor_ready[0]: - status = "mode_a" - else: - status = "startup" - - - return status - -class ThermalFrame(object): - def __init__(self): - # Sets the topleft origin of the graph - self.graphx = 23 - self.graphy = 24 - - # Sets the x and y span of the graph - self.gspanx = 133 - self.gspany = 71 - self.t_grid = ThermalGrid(23,24,133,71) - self.t_grid_full = ThermalGrid(23,8,133,109) - self.titlex = 23 - self.titley = 6 - - self.high = 0 - self.low = 0 - self.average = 0 - self.labely = 102 - - self.selection = 0 - - self.timed = timer() - self.timed.logtime() - - self.title = LabelObj("Thermal Array",titlefont) - - self.A_Label = LabelObj("No Data",font,colour = lcars_blue) - self.B_Label = LabelObj("No Data",font, colour = lcars_pinker) - self.C_Label = LabelObj("No Data",font, colour = lcars_orange) - - - # this function takes a value and sheds the second digit after the decimal place - def arrangelabel(self,data): - datareturn = format(float(data), '.0f') - return datareturn - - def labels(self): - - if self.selection == 0 or self.selection == 1: - raw_a = str(self.low) - adjusted_a = self.arrangelabel(raw_a) - a_string = "Low: " + adjusted_a - self.A_Label.string = a_string - self.A_Label.push(23,self.labely,self.draw) - - if self.selection == 0 or self.selection == 2: - raw_b = str(self.high) - adjusted_b = self.arrangelabel(raw_b) - self.B_Label.string = "High: " + adjusted_b - self.B_Label.center(self.labely,23,135, self.draw) - - if self.selection == 0 or self.selection == 3: - raw_c = str(self.average) - adjusted_c = self.arrangelabel(raw_c) - self.C_Label.string = "Avg: " + adjusted_c - self.C_Label.r_align(156,self.labely,self.draw) - - def push(self, draw): - - status = "mode_b" - - if configure.eventready[0]: - keys = configure.eventlist[0] - - - # ------------- Input handling -------------- # - if keys[0]: - status = "mode_a" - configure.eventready[0] = False - return status - - if keys[1]: - self.selection += 1 - if self.selection > 1: - self.selection = 0 - - if keys[2]: - status = "settings" - configure.last_status[0] = "mode_b" - configure.eventready[0] = False - return status - - configure.eventready[0] = False - - - self.draw = draw - self.labels() - - # Draw title - - self.title.push(self.titlex,self.titley, self.draw) - - - if self.selection == 0: - self.average,self.high,self.low = self.t_grid.update() - self.timed.logtime() - if self.selection == 1: - self.average,self.high,self.low = self.t_grid_full.update() - self.timed.logtime() - - if self.selection == 0: - self.t_grid.push(draw) - elif self.selection ==1: - self.t_grid_full.push(draw) - - return status - -class ColourScreen(object): - - def __init__(self): - self.surface = TFT.draw() - - # instantiates an image and uses it in a draw object. - self.image = Image.open('assets/lcarsframe.png') - self.blankimage = Image.open('assets/lcarsframeblank.png') - - self.status = "mode_a" - - # initializes all the modules - self.multi_frame = MultiFrame() - self.settings_frame = SettingsFrame() - self.thermal_frame = ThermalFrame() - self.powerdown_frame = PowerDown() - - - def start_up(self): - self.newimage = self.burgerfull.copy() - self.draw = ImageDraw.Draw(self.newimage) - self.status = self.startup_frame.push(self.draw) - - self.pixdrw() - - return self.status - - def get_size(self): - return self.multi_frame.get_x() - - def graph_screen(self): - self.newimage = self.image.copy() - self.draw = ImageDraw.Draw(self.newimage) - self.status = self.multi_frame.push(self.draw) - self.pixdrw() - return self.status - - def thermal_screen(self): - self.newimage = self.image.copy() - self.draw = ImageDraw.Draw(self.newimage) - self.status = self.thermal_frame.push(self.draw) - self.pixdrw() - return self.status - - def settings(self): - self.newimage = self.blankimage.copy() - self.draw = ImageDraw.Draw(self.newimage) - self.status = self.settings_frame.push(self.draw) - self.pixdrw() - return self.status - - def powerdown(self): - self.newimage = self.blankimage.copy() - self.draw = ImageDraw.Draw(self.newimage) - self.status = self.powerdown_frame.push(self.draw) - self.pixdrw() - return self.status - - def pixdrw(self): - thisimage = self.newimage.convert(mode = "RGB") - # Resize the image and rotate it so it's 240x320 pixels. - thisimage = self.newimage.rotate(90,0,1).resize((240, 320)) - # Draw the image on the display hardware. - self.surface.pasteimage(thisimage,(0,0)) - TFT.display() From 4e9849982afc1162e9db53dbab5f984d3bba7897 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 00:55:55 -0500 Subject: [PATCH 37/82] wifi band map --- lcars_clr.py | 35 ++++++++++++++++++++++++++++++++++- pilgraph.py | 4 +++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 1083751..9efbb67 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -569,7 +569,7 @@ def push(self, draw): self.signal_frequency.push(20,92,draw, string = info[3]) self.signal_mac.push(20,111, draw, string = info[6]) - if self.selection == 1: + if self.selection == 2: # list to hold the data labels list_for_labels = [] @@ -593,6 +593,39 @@ def push(self, draw): # assign each list element and its + # frequency intensity map + if self.selection == 1: + # returns the data necessary for freq_intensity map with EM. + # displays each SSID as a line segment. Its position along the x is + # determined by frequency. Its height by its signal strength. + + + #grab EM list + + #'ssid','signal','quality','frequency','encrypted','channel','dev','mode','dsc','timestamp' + + em_list = plars.get_recent_em_list() + items_list = [] + + for ssid in em_list: + name = str(ssid[0]) + strength = str(ssid[1]) + frequency = str(ssid[2]) + screenpos = translate(frequency, 2.412, 2.462, 14, 145) + lineheight = translate(strength, -60, 0, 103, 49) + this_ssid = (name,screenpos,lineheight) + items_list.append(this_ssid) + + #draw round rect background + draw.rounded_rectangle((6,43,153,103), outline = lcars_bluer) + + #for each item in item_list + for ssid in items_list: + cords = ((ssid[1],103),(ssid[1],ssid[2])) + draw.line(cords,lcars_bluer,1) + + + return status diff --git a/pilgraph.py b/pilgraph.py index c8e17e5..feec098 100644 --- a/pilgraph.py +++ b/pilgraph.py @@ -15,7 +15,7 @@ # - graphcoords: list containing the top left x,y coordinates # - graphspan: list containing the x and y span in pixels # - cycle: time per division of the graph (not working) -# - +# - from objects import * from PIL import Image @@ -195,6 +195,8 @@ def graphprep(self, datalist, ranger = None): return self.newlist + + def render(self, draw, auto = True, dot = True, ranger = None): self.auto = configure.auto[0] From b4e205d0e51b7e6b4342d8f4b7fbc151811fc06a Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 00:57:20 -0500 Subject: [PATCH 38/82] fix --- sensors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sensors.py b/sensors.py index 5614c29..1fd9df7 100644 --- a/sensors.py +++ b/sensors.py @@ -180,7 +180,7 @@ def __init__(self): self.bme_humi = Fragment(0,100,"Hygrometer", "%", "BME680") self.bme_press = Fragment(300,1100,"Barometer","hPa", "BME680") self.bme_voc = Fragment(300000,1100000,"VOC","KOhm", "BME680") - self.voc_procc = subprocess.Popen(['./bsec_bme680'], stdout=subprocess.PIPE) + #self.voc_procc = subprocess.Popen(['./bsec_bme680'], stdout=subprocess.PIPE) if configure.bme_bsec: self.bme_bsec = Fragment(-40,85,"Quality",self.deg_sym + "Q", "BME680") From d82d7515b5037bef31e43fff1f67373cee0245b8 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 00:58:03 -0500 Subject: [PATCH 39/82] fix --- sensors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sensors.py b/sensors.py index 1fd9df7..5a63be9 100644 --- a/sensors.py +++ b/sensors.py @@ -182,8 +182,8 @@ def __init__(self): self.bme_voc = Fragment(300000,1100000,"VOC","KOhm", "BME680") #self.voc_procc = subprocess.Popen(['./bsec_bme680'], stdout=subprocess.PIPE) - if configure.bme_bsec: - self.bme_bsec = Fragment(-40,85,"Quality",self.deg_sym + "Q", "BME680") + #if configure.bme_bsec: + # self.bme_bsec = Fragment(-40,85,"Quality",self.deg_sym + "Q", "BME680") if configure.pocket_geiger: self.radiat = Fragment(0.0, 10000.0, "Radiation", "urem/hr", "pocketgeiger") From 7d6d544ad4c5b4eada2c881f348f121f8148dc92 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:02:52 -0500 Subject: [PATCH 40/82] fix attempt --- lcars_clr.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 9efbb67..dd9b374 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -610,7 +610,9 @@ def push(self, draw): for ssid in em_list: name = str(ssid[0]) strength = str(ssid[1]) - frequency = str(ssid[2]) + frequency = ssid[2] + frequency = int(frequency.replace(' GHz', '')) + screenpos = translate(frequency, 2.412, 2.462, 14, 145) lineheight = translate(strength, -60, 0, 103, 49) this_ssid = (name,screenpos,lineheight) From 0c139c0dbd6fbe2b84f19c65014098b2f243b7b3 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:03:27 -0500 Subject: [PATCH 41/82] fix attempt --- lcars_clr.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lcars_clr.py b/lcars_clr.py index dd9b374..959a762 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -613,6 +613,7 @@ def push(self, draw): frequency = ssid[2] frequency = int(frequency.replace(' GHz', '')) + print(frequency,",",strength) screenpos = translate(frequency, 2.412, 2.462, 14, 145) lineheight = translate(strength, -60, 0, 103, 49) this_ssid = (name,screenpos,lineheight) From 8b2773a23c003ac7e86cb58709ecd1781309111d Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:04:41 -0500 Subject: [PATCH 42/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 959a762..30e0d5d 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -610,7 +610,7 @@ def push(self, draw): for ssid in em_list: name = str(ssid[0]) strength = str(ssid[1]) - frequency = ssid[2] + frequency = ssid[3] frequency = int(frequency.replace(' GHz', '')) print(frequency,",",strength) From ca7b4f9596ea4766b06d16c0650629ded7bb5fc0 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:05:47 -0500 Subject: [PATCH 43/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 30e0d5d..4e76116 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -611,7 +611,7 @@ def push(self, draw): name = str(ssid[0]) strength = str(ssid[1]) frequency = ssid[3] - frequency = int(frequency.replace(' GHz', '')) + frequency = float(frequency.replace(' GHz', '')) print(frequency,",",strength) screenpos = translate(frequency, 2.412, 2.462, 14, 145) From 902982db6962b7ee18d0146e5ccd06791c098cc6 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:07:08 -0500 Subject: [PATCH 44/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 4e76116..9dee9b8 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -609,7 +609,7 @@ def push(self, draw): for ssid in em_list: name = str(ssid[0]) - strength = str(ssid[1]) + strength = (ssid[1]) frequency = ssid[3] frequency = float(frequency.replace(' GHz', '')) From a326c4d2af059b31daafb532d94d2ac5277cf357 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:09:51 -0500 Subject: [PATCH 45/82] compromise --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 9dee9b8..8f04998 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -620,7 +620,7 @@ def push(self, draw): items_list.append(this_ssid) #draw round rect background - draw.rounded_rectangle((6,43,153,103), outline = lcars_bluer) + #draw.rounded_rectangle((6,43,153,103), outline = lcars_bluer) #for each item in item_list for ssid in items_list: From c114530a2b089c05faf1022fc2cf787b83baf6fc Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:15:51 -0500 Subject: [PATCH 46/82] fix --- lcars_clr.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 8f04998..480dd0e 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -12,6 +12,7 @@ device = GenericDisplay() # Load up the image library stuff to help draw bitmaps to push to the screen +import numpy import PIL.ImageOps from PIL import Image from PIL import ImageFont @@ -609,13 +610,14 @@ def push(self, draw): for ssid in em_list: name = str(ssid[0]) - strength = (ssid[1]) + strength = ssid[1] frequency = ssid[3] frequency = float(frequency.replace(' GHz', '')) print(frequency,",",strength) - screenpos = translate(frequency, 2.412, 2.462, 14, 145) - lineheight = translate(strength, -60, 0, 103, 49) + + screenpos = numpy.interp(frequency,(2.412, 2.462),(14, 145)) + lineheight = numpy.interp(strength, (-60, 0), (103, 49)) this_ssid = (name,screenpos,lineheight) items_list.append(this_ssid) From ef234807410d44dce6117fd7ec15b038613de911 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:19:36 -0500 Subject: [PATCH 47/82] fix --- lcars_clr.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 480dd0e..a2e560a 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -617,7 +617,7 @@ def push(self, draw): print(frequency,",",strength) screenpos = numpy.interp(frequency,(2.412, 2.462),(14, 145)) - lineheight = numpy.interp(strength, (-60, 0), (103, 49)) + lineheight = numpy.interp(strength, (-100, 0), (103, 49)) this_ssid = (name,screenpos,lineheight) items_list.append(this_ssid) @@ -625,8 +625,8 @@ def push(self, draw): #draw.rounded_rectangle((6,43,153,103), outline = lcars_bluer) #for each item in item_list - for ssid in items_list: - cords = ((ssid[1],103),(ssid[1],ssid[2])) + for item in items_list: + cords = ((item[1],103),(item[1],item[2])) draw.line(cords,lcars_bluer,1) From 990280cdc0232203db5cdbe547c961df6d1fe6f4 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:24:43 -0500 Subject: [PATCH 48/82] test --- lcars_clr.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index a2e560a..0924f8e 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -521,7 +521,7 @@ def __init__(self): self.list = Label_List(22,35, colour = lcars_peach) - + self.burgerfull = Image.open('assets/lcarsburgerframefull.png') def push(self, draw): @@ -600,6 +600,9 @@ def push(self, draw): # displays each SSID as a line segment. Its position along the x is # determined by frequency. Its height by its signal strength. + # change Background + + draw = ImageDraw.Draw(self.burgerfull) #grab EM list From fdbbc77ad4490ef143d470f382335ee7a1cfde19 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:28:15 -0500 Subject: [PATCH 49/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 0924f8e..f443f66 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -602,7 +602,7 @@ def push(self, draw): # change Background - draw = ImageDraw.Draw(self.burgerfull) + draw.pasteimage(self.burgerfull,(0,0)) #grab EM list From ed99601fc32c84507518dc40b06b424445d4ae83 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:29:59 -0500 Subject: [PATCH 50/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index f443f66..845c595 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -602,7 +602,7 @@ def push(self, draw): # change Background - draw.pasteimage(self.burgerfull,(0,0)) + draw.bitmap(self.burgerfull,(0,0)) #grab EM list From c390c143d6e8f4751b451e004e21116e7fcbe514 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:31:22 -0500 Subject: [PATCH 51/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 845c595..0e90382 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -602,7 +602,7 @@ def push(self, draw): # change Background - draw.bitmap(self.burgerfull,(0,0)) + draw.bitmap((0,0),self.burgerfull) #grab EM list From 164b55955f419b468830c9ec47cadf82939066d0 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:34:53 -0500 Subject: [PATCH 52/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 0e90382..8d0d448 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -601,7 +601,7 @@ def push(self, draw): # determined by frequency. Its height by its signal strength. # change Background - + draw.rectangle((0,0,320,240),(0,0,0)) draw.bitmap((0,0),self.burgerfull) #grab EM list From 268554f7e9d7381ef021ee7da094f86fa5be462d Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 01:36:31 -0500 Subject: [PATCH 53/82] fix --- lcars_clr.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 8d0d448..00ef355 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -541,7 +541,7 @@ def push(self, draw): if keys[1]: self.selection += 1 - if self.selection >= 2: + if self.selection >= 3: self.selection = 0 pass @@ -570,7 +570,7 @@ def push(self, draw): self.signal_frequency.push(20,92,draw, string = info[3]) self.signal_mac.push(20,111, draw, string = info[6]) - if self.selection == 2: + if self.selection == 1: # list to hold the data labels list_for_labels = [] @@ -595,7 +595,7 @@ def push(self, draw): # assign each list element and its # frequency intensity map - if self.selection == 1: + if self.selection == 2: # returns the data necessary for freq_intensity map with EM. # displays each SSID as a line segment. Its position along the x is # determined by frequency. Its height by its signal strength. @@ -617,7 +617,6 @@ def push(self, draw): frequency = ssid[3] frequency = float(frequency.replace(' GHz', '')) - print(frequency,",",strength) screenpos = numpy.interp(frequency,(2.412, 2.462),(14, 145)) lineheight = numpy.interp(strength, (-100, 0), (103, 49)) From 7056c7e725b15f5a4db24b679c0de17225923c2e Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 20:05:59 -0500 Subject: [PATCH 54/82] added dots --- lcars_clr.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 00ef355..fd35594 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -578,6 +578,7 @@ def push(self, draw): # grab EM list em_list = plars.get_recent_em_list() + #sort it so strongest is first sorted_em_list = sorted(em_list, key=itemgetter(1), reverse = True) # prepare a list of the data received for display @@ -607,8 +608,12 @@ def push(self, draw): #grab EM list #'ssid','signal','quality','frequency','encrypted','channel','dev','mode','dsc','timestamp' + unsorted_em_list = plars.get_recent_em_list() + + # sort it so strongest is first. + em_list = sorted(unsorted_em_list, key=itemgetter(1), reverse = True) + - em_list = plars.get_recent_em_list() items_list = [] for ssid in em_list: @@ -627,9 +632,22 @@ def push(self, draw): #draw.rounded_rectangle((6,43,153,103), outline = lcars_bluer) #for each item in item_list - for item in items_list: + for index, item in enumerate(item_list): cords = ((item[1],103),(item[1],item[2])) - draw.line(cords,lcars_bluer,1) + x1 = cords[2][0] - (6/2) + y1 = cords[2][1] - (6/2) + x2 = cords[2][0] + (6/2) + y2 = cords[2][1] + (6/2) + if index == 0: + draw.line(cords,lcars_peach,1) + draw.ellipse([x1,y1,x2,y2],lcars_peach) + self.signal_name.push(20,35,draw, string = item[0]) + + + else: + draw.line(cords,lcars_bluer,1) + draw.ellipse([x1,y1,x2,y2],lcars_bluer) + From 6f92182d53aed90c7b8dfb1c7607af7929e1ea9a Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 20:09:54 -0500 Subject: [PATCH 55/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index fd35594..f1ff493 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -632,7 +632,7 @@ def push(self, draw): #draw.rounded_rectangle((6,43,153,103), outline = lcars_bluer) #for each item in item_list - for index, item in enumerate(item_list): + for index, item in enumerate(items_list): cords = ((item[1],103),(item[1],item[2])) x1 = cords[2][0] - (6/2) y1 = cords[2][1] - (6/2) From c069beb4ae957afe8d3e674477d2b82823833b88 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 20:11:23 -0500 Subject: [PATCH 56/82] fix --- lcars_clr.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index f1ff493..5293e43 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -634,10 +634,10 @@ def push(self, draw): #for each item in item_list for index, item in enumerate(items_list): cords = ((item[1],103),(item[1],item[2])) - x1 = cords[2][0] - (6/2) - y1 = cords[2][1] - (6/2) - x2 = cords[2][0] + (6/2) - y2 = cords[2][1] + (6/2) + x1 = cords[1][0] - (6/2) + y1 = cords[1][1] - (6/2) + x2 = cords[1][0] + (6/2) + y2 = cords[1][1] + (6/2) if index == 0: draw.line(cords,lcars_peach,1) draw.ellipse([x1,y1,x2,y2],lcars_peach) From 4d4c813e4e9f23f0faf271f457a8b2d8cb0c4d70 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 23:23:08 -0500 Subject: [PATCH 57/82] wifi channel scan --- lcars_clr.py | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 5293e43..6d0b3ea 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -515,8 +515,13 @@ def __init__(self): self.title = LabelObj("Modulated EM Scan",titlefont, colour = lcars_orange) self.signal_name = LabelObj("SSID",bigfont, colour = lcars_peach) + self.signal_name_sm = LabelObj("SSID",font, colour = lcars_peach) + self.signal_strength = LabelObj("ST",giantfont, colour = lcars_peach) + self.signal_strength_sm = LabelObj("ST",font, colour = lcars_peach) + self.signal_frequency = LabelObj("FQ",titlefont, colour = lcars_orpeach) + self.signal_frequency_sm = LabelObj("FQ",font, colour = lcars_peach) self.signal_mac = LabelObj("MAC",font, colour = lcars_orpeach) self.list = Label_List(22,35, colour = lcars_peach) @@ -555,6 +560,7 @@ def push(self, draw): self.wifi.update_plars() + # details on strongest wifi network. if self.selection == 0: # grab EM data from plars @@ -564,12 +570,15 @@ def push(self, draw): self.Signal_Graph.render(draw) self.title.string = "Dominant Transciever" self.title.r_align(self.labelxr,self.titley,draw) + self.signal_name.push(20,35,draw, string = info[0]) + self.signal_strength.string = str(info[1]) + " DB" self.signal_strength.r_align(self.labelxr,92,draw) self.signal_frequency.push(20,92,draw, string = info[3]) self.signal_mac.push(20,111, draw, string = info[6]) + #list of all wifi ssids if self.selection == 1: # list to hold the data labels @@ -605,17 +614,23 @@ def push(self, draw): draw.rectangle((0,0,320,240),(0,0,0)) draw.bitmap((0,0),self.burgerfull) - #grab EM list + #draw round rect background + draw.rectangle((6,43,153,103), outline = lcars_blue) - #'ssid','signal','quality','frequency','encrypted','channel','dev','mode','dsc','timestamp' + #draw labels + self.title.string = "EM Channel Scan" + self.title.center(12,80,160,draw) + + #grab EM list unsorted_em_list = plars.get_recent_em_list() # sort it so strongest is first. em_list = sorted(unsorted_em_list, key=itemgetter(1), reverse = True) - + # create a list to hold just the info we need for the screen. items_list = [] + #filter info into items_list for ssid in em_list: name = str(ssid[0]) strength = ssid[1] @@ -625,11 +640,9 @@ def push(self, draw): screenpos = numpy.interp(frequency,(2.412, 2.462),(14, 145)) lineheight = numpy.interp(strength, (-100, 0), (103, 49)) - this_ssid = (name,screenpos,lineheight) + this_ssid = (name,screenpos,lineheight,strength,frequency) items_list.append(this_ssid) - #draw round rect background - #draw.rounded_rectangle((6,43,153,103), outline = lcars_bluer) #for each item in item_list for index, item in enumerate(items_list): @@ -641,9 +654,16 @@ def push(self, draw): if index == 0: draw.line(cords,lcars_peach,1) draw.ellipse([x1,y1,x2,y2],lcars_peach) - self.signal_name.push(20,35,draw, string = item[0]) + # draw the strongest signals name, top center + self.signal_name_sm.center(26,80,160,draw) + + # put strength at lower left + strength_string = str(info[1]) + " DB" + self.signal_strength_sm.push(6,107,draw,string = strength_string) + # put frequency at lower right + self.signal_frequency_sm.r_align(73,107,draw) else: draw.line(cords,lcars_bluer,1) draw.ellipse([x1,y1,x2,y2],lcars_bluer) From 161eb20f01b7c99076ad37a3121f6475afeb39f2 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 23:24:53 -0500 Subject: [PATCH 58/82] fix --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 6d0b3ea..e333e52 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -659,7 +659,7 @@ def push(self, draw): self.signal_name_sm.center(26,80,160,draw) # put strength at lower left - strength_string = str(info[1]) + " DB" + strength_string = str(item[1]) + " DB" self.signal_strength_sm.push(6,107,draw,string = strength_string) # put frequency at lower right From 42ad8d2a87de1a613b8c9d58fb2ebe70703de062 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 23:29:39 -0500 Subject: [PATCH 59/82] fixes --- lcars_clr.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index e333e52..7719d46 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -619,7 +619,7 @@ def push(self, draw): #draw labels self.title.string = "EM Channel Scan" - self.title.center(12,80,160,draw) + self.title.center(12,0,320,draw) #grab EM list unsorted_em_list = plars.get_recent_em_list() @@ -656,14 +656,15 @@ def push(self, draw): draw.ellipse([x1,y1,x2,y2],lcars_peach) # draw the strongest signals name, top center - self.signal_name_sm.center(26,80,160,draw) + self.signal_name_sm.center(26,0,320,draw) # put strength at lower left - strength_string = str(item[1]) + " DB" - self.signal_strength_sm.push(6,107,draw,string = strength_string) + strength_string = str(item[3]) + " DB" + self.signal_strength_sm.push(6,105,draw,string = strength_string) # put frequency at lower right - self.signal_frequency_sm.r_align(73,107,draw) + self.signal_frequency_sm.string = str(item[4]) + " DB" + self.signal_frequency_sm.r_align(153,105,draw) else: draw.line(cords,lcars_bluer,1) draw.ellipse([x1,y1,x2,y2],lcars_bluer) From 2ea9338d81f1908096f8706e407ca86399a3d29f Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 23:34:01 -0500 Subject: [PATCH 60/82] fixes --- lcars_clr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 7719d46..227463d 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -619,7 +619,7 @@ def push(self, draw): #draw labels self.title.string = "EM Channel Scan" - self.title.center(12,0,320,draw) + self.title.center(12,0,160,draw) #grab EM list unsorted_em_list = plars.get_recent_em_list() @@ -656,7 +656,7 @@ def push(self, draw): draw.ellipse([x1,y1,x2,y2],lcars_peach) # draw the strongest signals name, top center - self.signal_name_sm.center(26,0,320,draw) + self.signal_name_sm.center(26,0,160,draw) # put strength at lower left strength_string = str(item[3]) + " DB" From ef4552d250ec96c83ed7e00ab4e79aab0cfbe832 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 23:39:39 -0500 Subject: [PATCH 61/82] fixes --- lcars_clr.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 227463d..e3b18c3 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -619,7 +619,7 @@ def push(self, draw): #draw labels self.title.string = "EM Channel Scan" - self.title.center(12,0,160,draw) + self.title.center(11,0,160,draw) #grab EM list unsorted_em_list = plars.get_recent_em_list() @@ -656,15 +656,16 @@ def push(self, draw): draw.ellipse([x1,y1,x2,y2],lcars_peach) # draw the strongest signals name, top center - self.signal_name_sm.center(26,0,160,draw) + self.signal_name_sm.string = item[0] + self.signal_name_sm.center(27,0,160,draw) # put strength at lower left strength_string = str(item[3]) + " DB" - self.signal_strength_sm.push(6,105,draw,string = strength_string) + self.signal_strength_sm.push(6,104,draw,string = strength_string) # put frequency at lower right - self.signal_frequency_sm.string = str(item[4]) + " DB" - self.signal_frequency_sm.r_align(153,105,draw) + self.signal_frequency_sm.string = str(item[4]) + " GHZ" + self.signal_frequency_sm.r_align(153,104,draw) else: draw.line(cords,lcars_bluer,1) draw.ellipse([x1,y1,x2,y2],lcars_bluer) From 254a1739f9057d4ca70b542e32a79b0b99be9a27 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 2 Mar 2022 23:41:09 -0500 Subject: [PATCH 62/82] burger full background fix --- assets/lcarsburgerframefull.png | Bin 1155 -> 1371 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/assets/lcarsburgerframefull.png b/assets/lcarsburgerframefull.png index 7091c853c56092cce3c3b2cd5213f8720a819557..34dbfbcead55b6c1d7ab025ee707a492d3d01b00 100644 GIT binary patch literal 1371 zcmeAS@N?(olHy`uVBq!ia0vp^3xK$RgAGXbBqvD&DaPU;cPEB*=VV?2ITfi9o@u_m z3|c@o2LlVE6ayQL70(Y)*J~229_F67srqa#v3r+692IVbntyYdZz{#4n*x}Hhiq#sHiQbot-@ch!d{6ax zkG!nTJ^pwj*S`O5;Bro&Mw~` zouHHOj&Fx`zWR?vv2$Nnvj$BL%Dug7?YldSIw#J3-*=Lc^^e8|&E*%)S~Q#%)BBt} znU|}A_0a#l;&nUDH{9DS6L8=;)4lwIcJGbc8N(SG943e{EHJTu%y6V(3j@Q_pOWkf zY)e=fG|ry4U@%nBWpK!>JI2_-n90cC_1T!ufyaZJAz;@0LWU%VD29ehe|ne&m@hFg zOnH_r(;zWw)X)j5k2@c-6gY@}D$dIo>~&MvKgx$XH|{Worx v*Itk{5cqg+#)X^ns}ql0o)d6jKGS~2B+<^&yD{&lfC?#3S3j3^P6QL70(Y)*J~22IeK6E{-7;jBju3?+$U7 zVfZk!{I#p?nk!2Lv|TywiSBj{`NJG^L@BJPwds20bY(HKTQLjG#1waNiOFeRVr817 zaHG3xf8XbGPM#OMba*wZ^3|7VYGPdaWLRP*-rtNKPJ zLp^@OJgu$*gI3r7KBnvc-1#>xU*ti`=T{RWTJ9(D+~30fN_a-M!@8CGB1HDb*q431 zezP)89H`*by*;o0np9t~ZLAdUC{)QW*&S7xUdQYww|mDfj;+#_yJId%T@ZRP$6?p^ z4?n-m>Q$DO-*bzxnoTtR`Hs{)@eb`@S$l77|b=FT8e2L0;~6bk73~uP;h8qU}PF)5E%%cwFFk@T<`Cf`nD8haA2;EM)_J<+OjH4ogG_wE2!kWj^X2d{@UrV*>{=K0#&Uc9}#!oTC; z>Q(pGuGYEy;6Oq0n&{VCug$co$}E1fa&GR|t#`#wu>Nr0`sxf{#Qn`L%j_oem;KL< zC{*NnGQZ~fzdhxz*1x(N?OyOgK1+r}^Upp3$34a0Sw5ZnuCa&1+Rfelbk^1DtTWzU z{y})v&Fo`bD+%Z>FVdQ I&MBb@0IPX{{Qv*} From 6a0d72d05cbc5f29056caedb8f190daff858e282 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 00:00:34 -0500 Subject: [PATCH 63/82] pillow test --- lcars_clr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index e3b18c3..7b46bca 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -611,8 +611,9 @@ def push(self, draw): # determined by frequency. Its height by its signal strength. # change Background + draw._image = self.burgerfull draw.rectangle((0,0,320,240),(0,0,0)) - draw.bitmap((0,0),self.burgerfull) + #draw.bitmap((0,0), ) #draw round rect background draw.rectangle((6,43,153,103), outline = lcars_blue) From 4366883e938abf8786962e6d9d46ac58fba1a5f9 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 00:02:44 -0500 Subject: [PATCH 64/82] test2 --- lcars_clr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 7b46bca..b3ee460 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -611,8 +611,9 @@ def push(self, draw): # determined by frequency. Its height by its signal strength. # change Background + + #draw.rectangle((0,0,320,240),(0,0,0)) draw._image = self.burgerfull - draw.rectangle((0,0,320,240),(0,0,0)) #draw.bitmap((0,0), ) #draw round rect background From 00cfd5511f36a2d937234a6aae6c7545837397b4 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 11:35:10 -0500 Subject: [PATCH 65/82] tweaks to layout --- lcars_clr.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index b3ee460..97d8e11 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -617,11 +617,11 @@ def push(self, draw): #draw.bitmap((0,0), ) #draw round rect background - draw.rectangle((6,43,153,103), outline = lcars_blue) + draw.rectangle((17,49,158,109), outline = lcars_blue) #draw labels self.title.string = "EM Channel Scan" - self.title.center(11,0,160,draw) + self.title.r_align(self.labelxr,self.titley,draw) #grab EM list unsorted_em_list = plars.get_recent_em_list() @@ -640,8 +640,8 @@ def push(self, draw): frequency = float(frequency.replace(' GHz', '')) - screenpos = numpy.interp(frequency,(2.412, 2.462),(14, 145)) - lineheight = numpy.interp(strength, (-100, 0), (103, 49)) + screenpos = numpy.interp(frequency,(2.412, 2.462),(21, 154)) + lineheight = numpy.interp(strength, (-100, 0), (109, 58)) this_ssid = (name,screenpos,lineheight,strength,frequency) items_list.append(this_ssid) @@ -659,15 +659,15 @@ def push(self, draw): # draw the strongest signals name, top center self.signal_name_sm.string = item[0] - self.signal_name_sm.center(27,0,160,draw) + self.signal_name_sm.center(37,0,160,draw) # put strength at lower left strength_string = str(item[3]) + " DB" - self.signal_strength_sm.push(6,104,draw,string = strength_string) + self.signal_strength_sm.push(18,114,draw,string = strength_string) # put frequency at lower right self.signal_frequency_sm.string = str(item[4]) + " GHZ" - self.signal_frequency_sm.r_align(153,104,draw) + self.signal_frequency_sm.r_align(157,114,draw) else: draw.line(cords,lcars_bluer,1) draw.ellipse([x1,y1,x2,y2],lcars_bluer) From 2d942086fde027ceb51d9efa5befdd62608d071c Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 11:37:58 -0500 Subject: [PATCH 66/82] ui tweaks --- lcars_clr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 97d8e11..f69c82e 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -640,7 +640,7 @@ def push(self, draw): frequency = float(frequency.replace(' GHz', '')) - screenpos = numpy.interp(frequency,(2.412, 2.462),(21, 154)) + screenpos = numpy.interp(frequency,(2.412, 2.462),(23, 152)) lineheight = numpy.interp(strength, (-100, 0), (109, 58)) this_ssid = (name,screenpos,lineheight,strength,frequency) items_list.append(this_ssid) @@ -659,7 +659,7 @@ def push(self, draw): # draw the strongest signals name, top center self.signal_name_sm.string = item[0] - self.signal_name_sm.center(37,0,160,draw) + self.signal_name_sm.center(36,23,152,draw) # put strength at lower left strength_string = str(item[3]) + " DB" From 8b3de3c57c8fb8d0555f290470cd2f15c5d46b68 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 11:39:29 -0500 Subject: [PATCH 67/82] ui tweak --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index f69c82e..dbddd36 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -659,7 +659,7 @@ def push(self, draw): # draw the strongest signals name, top center self.signal_name_sm.string = item[0] - self.signal_name_sm.center(36,23,152,draw) + self.signal_name_sm.center(36,17,158,draw) # put strength at lower left strength_string = str(item[3]) + " DB" From bd403ead959fc80acb31e53ac81db0a68754fa6a Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 11:40:50 -0500 Subject: [PATCH 68/82] ui tweaks --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index dbddd36..053d363 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -659,7 +659,7 @@ def push(self, draw): # draw the strongest signals name, top center self.signal_name_sm.string = item[0] - self.signal_name_sm.center(36,17,158,draw) + self.signal_name_sm.center(36,17,141,draw) # put strength at lower left strength_string = str(item[3]) + " DB" From e2b2d1377ed4823eb2a15fd6a95877901b0a34aa Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 11:41:34 -0500 Subject: [PATCH 69/82] ui tweaks --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 053d363..738e6a0 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -641,7 +641,7 @@ def push(self, draw): screenpos = numpy.interp(frequency,(2.412, 2.462),(23, 152)) - lineheight = numpy.interp(strength, (-100, 0), (109, 58)) + lineheight = numpy.interp(strength, (-100, 0), (108, 58)) this_ssid = (name,screenpos,lineheight,strength,frequency) items_list.append(this_ssid) From 14a75e30168bd3285e3af7031b848a4763e5b218 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 11:42:56 -0500 Subject: [PATCH 70/82] ui tweaks --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 738e6a0..6f0cd3f 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -620,7 +620,7 @@ def push(self, draw): draw.rectangle((17,49,158,109), outline = lcars_blue) #draw labels - self.title.string = "EM Channel Scan" + self.title.string = "EM Channel Analysis" self.title.r_align(self.labelxr,self.titley,draw) #grab EM list From 03ffc4c7578ab873d4d352c3744f1c10d3a4a1bc Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 12:23:56 -0500 Subject: [PATCH 71/82] ui tweak --- lcars_clr.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 6f0cd3f..1eea981 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -617,7 +617,7 @@ def push(self, draw): #draw.bitmap((0,0), ) #draw round rect background - draw.rectangle((17,49,158,109), outline = lcars_blue) + draw.rectangle((18,49,158,109), outline = lcars_blue) #draw labels self.title.string = "EM Channel Analysis" @@ -640,7 +640,7 @@ def push(self, draw): frequency = float(frequency.replace(' GHz', '')) - screenpos = numpy.interp(frequency,(2.412, 2.462),(23, 152)) + screenpos = numpy.interp(frequency,(2.412, 2.462),(24, 152)) lineheight = numpy.interp(strength, (-100, 0), (108, 58)) this_ssid = (name,screenpos,lineheight,strength,frequency) items_list.append(this_ssid) @@ -663,7 +663,7 @@ def push(self, draw): # put strength at lower left strength_string = str(item[3]) + " DB" - self.signal_strength_sm.push(18,114,draw,string = strength_string) + self.signal_strength_sm.push(19,114,draw,string = strength_string) # put frequency at lower right self.signal_frequency_sm.string = str(item[4]) + " GHZ" From 82da9e2b246e623fca0c4027292274d951671532 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 12:40:02 -0500 Subject: [PATCH 72/82] layout tweaks --- lcars_clr.py | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 1eea981..715b071 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -617,7 +617,7 @@ def push(self, draw): #draw.bitmap((0,0), ) #draw round rect background - draw.rectangle((18,49,158,109), outline = lcars_blue) + draw.rectangle((18,49,158,126), outline = lcars_blue) #draw labels self.title.string = "EM Channel Analysis" @@ -639,35 +639,47 @@ def push(self, draw): frequency = ssid[3] frequency = float(frequency.replace(' GHz', '')) - + # determing x coordinate screenpos = numpy.interp(frequency,(2.412, 2.462),(24, 152)) - lineheight = numpy.interp(strength, (-100, 0), (108, 58)) + + # determine y coordinate + lineheight = numpy.interp(strength, (-100, 0), (129, 55)) + + # package into list this_ssid = (name,screenpos,lineheight,strength,frequency) items_list.append(this_ssid) #for each item in item_list for index, item in enumerate(items_list): + + # determine dot coordinates. cords = ((item[1],103),(item[1],item[2])) x1 = cords[1][0] - (6/2) y1 = cords[1][1] - (6/2) x2 = cords[1][0] + (6/2) y2 = cords[1][1] + (6/2) + + # if this is the strongest singal draw labels and change colour. if index == 0: draw.line(cords,lcars_peach,1) draw.ellipse([x1,y1,x2,y2],lcars_peach) + + name = item[0] + trunc_name = name[:16] + (name[16:] and '..') # draw the strongest signals name, top center - self.signal_name_sm.string = item[0] - self.signal_name_sm.center(36,17,141,draw) + self.signal_name_sm.push(19,35,draw,string = trunc_name) # put strength at lower left strength_string = str(item[3]) + " DB" - self.signal_strength_sm.push(19,114,draw,string = strength_string) + #self.signal_strength_sm.push(19,114,draw,string = strength_string) # put frequency at lower right - self.signal_frequency_sm.string = str(item[4]) + " GHZ" - self.signal_frequency_sm.r_align(157,114,draw) + self.signal_frequency_sm.string = str(item[4]) + " GHZ" + ", " + strength_string + self.signal_frequency_sm.r_align(157,36,draw) + + # otherwise just draw the line and dot in the usual color else: draw.line(cords,lcars_bluer,1) draw.ellipse([x1,y1,x2,y2],lcars_bluer) From b388883c4e19cff31061ada1ebdba1a8e80fc831 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 12:41:41 -0500 Subject: [PATCH 73/82] ui tweak --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 715b071..6bec531 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -654,7 +654,7 @@ def push(self, draw): for index, item in enumerate(items_list): # determine dot coordinates. - cords = ((item[1],103),(item[1],item[2])) + cords = ((item[1],129),(item[1],item[2])) x1 = cords[1][0] - (6/2) y1 = cords[1][1] - (6/2) x2 = cords[1][0] + (6/2) From 911d9e5a7dbcbd6335d6295e22e7773c00a1d97a Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 12:43:53 -0500 Subject: [PATCH 74/82] ui tweaks --- lcars_clr.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index 6bec531..a6c68eb 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -518,10 +518,10 @@ def __init__(self): self.signal_name_sm = LabelObj("SSID",font, colour = lcars_peach) self.signal_strength = LabelObj("ST",giantfont, colour = lcars_peach) - self.signal_strength_sm = LabelObj("ST",font, colour = lcars_peach) + self.signal_strength_sm = LabelObj("ST",littlefont, colour = lcars_peach) self.signal_frequency = LabelObj("FQ",titlefont, colour = lcars_orpeach) - self.signal_frequency_sm = LabelObj("FQ",font, colour = lcars_peach) + self.signal_frequency_sm = LabelObj("FQ",littlefont, colour = lcars_peach) self.signal_mac = LabelObj("MAC",font, colour = lcars_orpeach) self.list = Label_List(22,35, colour = lcars_peach) @@ -654,7 +654,7 @@ def push(self, draw): for index, item in enumerate(items_list): # determine dot coordinates. - cords = ((item[1],129),(item[1],item[2])) + cords = ((item[1],128),(item[1],item[2])) x1 = cords[1][0] - (6/2) y1 = cords[1][1] - (6/2) x2 = cords[1][0] + (6/2) From f0059a035cfa38deb3d39f649c5bd726d8182f96 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 12:48:06 -0500 Subject: [PATCH 75/82] ui tweaks --- lcars_clr.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index a6c68eb..eab9ab6 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -643,7 +643,7 @@ def push(self, draw): screenpos = numpy.interp(frequency,(2.412, 2.462),(24, 152)) # determine y coordinate - lineheight = numpy.interp(strength, (-100, 0), (129, 55)) + lineheight = numpy.interp(strength, (-100, 0), (127, 55)) # package into list this_ssid = (name,screenpos,lineheight,strength,frequency) @@ -654,7 +654,7 @@ def push(self, draw): for index, item in enumerate(items_list): # determine dot coordinates. - cords = ((item[1],128),(item[1],item[2])) + cords = ((item[1],127),(item[1],item[2])) x1 = cords[1][0] - (6/2) y1 = cords[1][1] - (6/2) x2 = cords[1][0] + (6/2) @@ -669,7 +669,7 @@ def push(self, draw): name = item[0] trunc_name = name[:16] + (name[16:] and '..') # draw the strongest signals name, top center - self.signal_name_sm.push(19,35,draw,string = trunc_name) + self.signal_name_sm.push(19,34,draw,string = trunc_name) # put strength at lower left strength_string = str(item[3]) + " DB" @@ -677,7 +677,7 @@ def push(self, draw): # put frequency at lower right self.signal_frequency_sm.string = str(item[4]) + " GHZ" + ", " + strength_string - self.signal_frequency_sm.r_align(157,36,draw) + self.signal_frequency_sm.r_align(157,37,draw) # otherwise just draw the line and dot in the usual color else: From 3a87754aec2ecf336a66ae11ca28cc6da578ee82 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 12:49:28 -0500 Subject: [PATCH 76/82] ui tweaks --- lcars_clr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lcars_clr.py b/lcars_clr.py index eab9ab6..5da393f 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -643,7 +643,7 @@ def push(self, draw): screenpos = numpy.interp(frequency,(2.412, 2.462),(24, 152)) # determine y coordinate - lineheight = numpy.interp(strength, (-100, 0), (127, 55)) + lineheight = numpy.interp(strength, (-100, 0), (126, 55)) # package into list this_ssid = (name,screenpos,lineheight,strength,frequency) @@ -654,7 +654,7 @@ def push(self, draw): for index, item in enumerate(items_list): # determine dot coordinates. - cords = ((item[1],127),(item[1],item[2])) + cords = ((item[1],126),(item[1],item[2])) x1 = cords[1][0] - (6/2) y1 = cords[1][1] - (6/2) x2 = cords[1][0] + (6/2) From 3373c520600b101475a9ed8457c5737796d76043 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 3 Mar 2022 12:51:10 -0500 Subject: [PATCH 77/82] ui tweaks --- lcars_clr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lcars_clr.py b/lcars_clr.py index 5da393f..da99cc8 100644 --- a/lcars_clr.py +++ b/lcars_clr.py @@ -640,7 +640,7 @@ def push(self, draw): frequency = float(frequency.replace(' GHz', '')) # determing x coordinate - screenpos = numpy.interp(frequency,(2.412, 2.462),(24, 152)) + screenpos = numpy.interp(frequency,(2.412, 2.462),(25, 151)) # determine y coordinate lineheight = numpy.interp(strength, (-100, 0), (126, 55)) From 4c2a13e5128617a287f2bf5388aa53ddc03bb676 Mon Sep 17 00:00:00 2001 From: "SCIFI.radio" Date: Sat, 12 Mar 2022 12:48:02 -1000 Subject: [PATCH 78/82] Added scaling settings for TR-108 mode_a graph screen to INI file config support --- objects.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/objects.py b/objects.py index f6f4c90..d545688 100644 --- a/objects.py +++ b/objects.py @@ -78,7 +78,8 @@ def createMissingINI(self,filepath): 'PG_NS':'21'} config['OUTPUT'] = {'display':'1', - 'LED_timer':'0.2'} + 'LED_timer':'0.2', + } config['GLOBALS'] = {'# Controls whether LEDs are active':None, 'leds':'yes', @@ -91,6 +92,10 @@ def createMissingINI(self,filepath): 'sleep':'yes', # If sleep is True the lights will respond to hall effect sensors '# Autoranging of graphs':None, 'autoranging':'yes', # Auto ranging of graphs + 'mode_a_graph_width':'280', # graph width for TR108 mode_a + 'mode_a_graph_height':'182', # graph height for TR108 mode_a\ + 'mode_a_x_offset':18, # x offset for TR108 mode_a + 'mode_a_y_offset':20, # y offset for TR108 mode_a '# Interpolate Temperature':None, 'interpolate':'yes', # Interpolate temperature 'samplerate':'0', @@ -234,6 +239,11 @@ def __init__(self): # controls auto ranging of graphs self.auto = [self.str2bool(config['GLOBALS']['autoranging'])] + # controls sizes and offsets for mode_a on TR108 + self.mode_a_graph_width = int(config['GLOBALS']['mode_a_graph_width']) + self.mode_a_graph_height = int(config['GLOBALS']['mode_a_graph_height']) + self.mode_a_x_offset = int(config['GLOBALS']['mode_a_x_offset']) + self.mode_a_y_offset = int(config['GLOBALS']['mode_a_y_offset']) # holds theme state for UI self.theme = [0] From f65c57e42fc081663d404100284cd3005f6be0de Mon Sep 17 00:00:00 2001 From: "SCIFI.radio" Date: Sat, 12 Mar 2022 12:49:51 -1000 Subject: [PATCH 79/82] Provides video pygame player support (see https://github.com/ree1261/pyvidplayer) --- pyvidplayer.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 pyvidplayer.py diff --git a/pyvidplayer.py b/pyvidplayer.py new file mode 100644 index 0000000..dad07dc --- /dev/null +++ b/pyvidplayer.py @@ -0,0 +1,87 @@ +import pygame +from pymediainfo import MediaInfo +from ffpyplayer.player import MediaPlayer +from os.path import exists, basename, splitext +from os import strerror +from errno import ENOENT + + +class Video: + def __init__(self, path): + self.path = path + + if exists(path): + self.video = MediaPlayer(path) + info = self.get_file_data() + + self.duration = info["duration"] + self.frames = 0 + self.frame_delay = 1 / info["frame rate"] + self.size = info["original size"] + self.image = pygame.Surface((0, 0)) + + self.active = True + else: + raise FileNotFoundError(ENOENT, strerror(ENOENT), path) + + def get_file_data(self): + info = MediaInfo.parse(self.path).video_tracks[0] + return {"path":self.path, + "name":splitext(basename(self.path))[0], + "frame rate":float(info.frame_rate), + "frame count":info.frame_count, + "duration":info.duration / 1000, + "original size":(info.width, info.height), + "original aspect ratio":info.other_display_aspect_ratio[0]} + + def get_playback_data(self): + return {"active":self.active, + "time":self.video.get_pts(), + "volume":self.video.get_volume(), + "paused":self.video.get_pause(), + "size":self.size} + + def restart(self): + self.video.seek(0, relative=False, accurate=False) + self.frames = 0 + self.active = True + + def close(self): + self.video.close_player() + self.active = False + + def set_size(self, size): + self.video.set_size(size[0], size[1]) + self.size = size + + def set_volume(self, volume): + self.video.set_volume(volume) + + def seek(self, seek_time, accurate=False): + vid_time = self.video.get_pts() + if vid_time + seek_time < self.duration and self.active: + self.video.seek(seek_time) + if seek_time < 0: + while (vid_time + seek_time < self.frames * self.frame_delay): + self.frames -= 1 + + def toggle_pause(self): + self.video.toggle_pause() + + def update(self): + updated = False + while self.video.get_pts() > self.frames * self.frame_delay: + frame, val = self.video.get_frame() + self.frames += 1 + updated = True + if updated: + if val == "eof": + self.active = False + elif frame != None: + self.image = pygame.image.frombuffer(frame[0].to_bytearray()[0], frame[0].get_size(), "RGB") + return updated + + def draw(self, surf, pos, force_draw=True): + if self.active: + if self.update() or force_draw: + surf.blit(self.image, pos) \ No newline at end of file From 31de8555006b9ef59b6da0e6393f2f29d8f5261d Mon Sep 17 00:00:00 2001 From: "SCIFI.radio" Date: Sat, 12 Mar 2022 12:55:24 -1000 Subject: [PATCH 80/82] Aesthetic adjustment to mode_a graph screen height limits for TR-108 --- objects.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/objects.py b/objects.py index d545688..cbd3a9d 100644 --- a/objects.py +++ b/objects.py @@ -93,9 +93,9 @@ def createMissingINI(self,filepath): '# Autoranging of graphs':None, 'autoranging':'yes', # Auto ranging of graphs 'mode_a_graph_width':'280', # graph width for TR108 mode_a - 'mode_a_graph_height':'182', # graph height for TR108 mode_a\ + 'mode_a_graph_height':'160', # graph height for TR108 mode_a\ 'mode_a_x_offset':18, # x offset for TR108 mode_a - 'mode_a_y_offset':20, # y offset for TR108 mode_a + 'mode_a_y_offset':31, # y offset for TR108 mode_a '# Interpolate Temperature':None, 'interpolate':'yes', # Interpolate temperature 'samplerate':'0', From e7d4395c4f78fcf8a1bab33bcc06b0a7551fddce Mon Sep 17 00:00:00 2001 From: "SCIFI.radio" Date: Sun, 13 Mar 2022 09:05:57 -0900 Subject: [PATCH 81/82] Added ffpyplayer=4.3.2 to requirements. The PyVidPlayer.py module needs this. --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9dd3974..468fb54 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,9 +7,10 @@ board==1.0 Cap1xxx==0.1.4 colour==0.1.5 envirophat==1.0.1 +ffpyplayer==4.3.2 luma.core==2.3.1 -luma.lcd==2.9.0 luma.emulator==1.4.0 +luma.lcd==2.9.0 numpy==1.21.4 pandas==1.3.4 Pillow==9.0.0 From 9b225fe4175918964f65556c16b186b26468e663 Mon Sep 17 00:00:00 2001 From: "SCIFI.radio" Date: Sun, 13 Mar 2022 12:54:37 -0900 Subject: [PATCH 82/82] Now plays Edith Keeler video on mode_c --- tos_display.py | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/tos_display.py b/tos_display.py index af9cd4b..07d5788 100644 --- a/tos_display.py +++ b/tos_display.py @@ -5,15 +5,19 @@ # styled tricorders. print("Loading 320x240 Duotronic Interface") # The following are some necessary modules for the Picorder. -import pygame -import time -import os +from asyncio import sleep +from pickle import FALSE +import pygame, time, os +from pyvidplayer import Video +os.environ["SDL_VIDEO_CENTERED"] = "1" +from pathlib import Path from plars import * from objects import * from input import * + if not configure.pc: if configure.tr108: import os @@ -21,10 +25,10 @@ #os.system('xset -display :0 -dpms') SAMPLE_SIZE = configure.samples -GRAPH_WIDTH = 280 -GRAPH_HEIGHT = 182 -GRAPH_X = 18 -GRAPH_Y = 20 +GRAPH_WIDTH = configure.mode_a_graph_width +GRAPH_HEIGHT = configure.mode_a_graph_height +GRAPH_X = configure.mode_a_x_offset +GRAPH_Y = configure.mode_a_y_offset GRAPH_X2 = GRAPH_X + GRAPH_WIDTH GRAPH_Y2 = GRAPH_Y + GRAPH_HEIGHT @@ -759,10 +763,20 @@ def __init__(self,surface): self.surface = surface self.videobg = Image() self.videobg.update(videobg, 0,0) - + self.running = False + self.paused = False + self.clock = pygame.time.Clock() def frame(self): self.status = "mode_c" + if not self.running: + self.running = True + self.clip = Video('assets/ekmd.mov') + self.clip.set_size(resolution) + pygame.mixer.quit() + + self.clock.tick(60) + if configure.eventready[0]: # The following code handles inputs and button presses. @@ -773,11 +787,21 @@ def frame(self): print("Button 1") self.status = "mode_b" configure.eventready[0] = False + self.running = False + self.clip.close() return self.status if keys[1]: self.status = "mode_c" - print("Button 2") + self.clip.toggle_pause() + if self.paused: + self.paused = False + print("Resume") + else: + self.paused = True + print("Paused") + # We would use this to set mode_d instead of + # toggling a pause were we to get a mode_d configure.eventready[0] = False return self.status @@ -786,15 +810,20 @@ def frame(self): configure.last_status[0] = "mode_c" print("Button 3") self.status = "settings" + self.running = False configure.eventready[0] = False + return self.status configure.eventready[0] = False #draws Background gridplane self.videobg.draw(self.surface) + self.clip.draw(self.surface,(0,0), force_draw=FALSE) #draws UI to frame buffer pygame.display.update() + if not self.clip.active: + self.clip.restart() return self.status