Example #1
0
def led_matrix_options(args):
  options = RGBMatrixOptions()

  if args.led_gpio_mapping != None:
    options.hardware_mapping = args.led_gpio_mapping

  options.rows = args.led_rows
  options.cols = args.led_cols
  options.chain_length = args.led_chain
  options.parallel = args.led_parallel
  options.row_address_type = args.led_row_addr_type
  options.multiplexing = args.led_multiplexing
  options.pwm_bits = args.led_pwm_bits
  options.brightness = args.led_brightness
  options.pwm_lsb_nanoseconds = args.led_pwm_lsb_nanoseconds
  options.led_rgb_sequence = args.led_rgb_sequence
  try:
    options.pixel_mapper_config = args.led_pixel_mapper
  except AttributeError:
    debug.warning("Your compiled RGB Matrix Library is out of date.")
    debug.warning("The --led-pixel-mapper argument will not work until it is updated.")

  if args.led_show_refresh:
    options.show_refresh_rate = 1

  if args.led_slowdown_gpio != None:
    options.gpio_slowdown = args.led_slowdown_gpio

  if args.led_no_hardware_pulse:
    options.disable_hardware_pulsing = True

  return options
Example #2
0
def led_matrix_options(args):
  options = RGBMatrixOptions()

  if args.led_gpio_mapping != None:
    options.hardware_mapping = args.led_gpio_mapping

  options.rows = args.led_rows
  options.cols = args.led_cols
  options.chain_length = args.led_chain
  options.parallel = args.led_parallel
  options.row_address_type = args.led_row_addr_type
  options.multiplexing = args.led_multiplexing
  options.pwm_bits = args.led_pwm_bits
  options.brightness = args.led_brightness
  options.pwm_lsb_nanoseconds = args.led_pwm_lsb_nanoseconds
  options.led_rgb_sequence = args.led_rgb_sequence

  if args.led_show_refresh:
    options.show_refresh_rate = 1

  if args.led_slowdown_gpio != None:
    options.gpio_slowdown = args.led_slowdown_gpio

  if args.led_no_hardware_pulse:
    options.disable_hardware_pulsing = True

  return options
    def process(self):
        self.args = self.parser.parse_args()

        options = RGBMatrixOptions()

        if self.args.led_gpio_mapping != None:
          options.hardware_mapping = self.args.led_gpio_mapping
        options.rows = self.args.led_rows
        options.chain_length = self.args.led_chain
        options.parallel = self.args.led_parallel
        options.pwm_bits = self.args.led_pwm_bits
        options.brightness = self.args.led_brightness
        options.pwm_lsb_nanoseconds = self.args.led_pwm_lsb_nanoseconds
        if self.args.led_show_refresh:
          options.show_refresh_rate = 1

        if self.args.led_slowdown_gpio != None:
            options.gpio_slowdown = self.args.led_slowdown_gpio
        if self.args.led_no_hardware_pulse:
          options.disable_hardware_pulsing = True

        self.matrix = RGBMatrix(options = options)

        try:
            # Start loop
            print("Press CTRL-C to stop sample")
            self.run()
        except KeyboardInterrupt:
            print("Exiting\n")
            sys.exit(0)

        return True
Example #4
0
    def __init__(self, LEDFormat):
        logging.info('Initialising LEDMatrix')

        options = RGBMatrixOptions()

        options.hardware_mapping = LEDFormat['matrixDriver']
        options.rows = LEDFormat['matrixRows']
        options.cols = LEDFormat['matrixCols']
        options.chain_length = LEDFormat['matrixCount']
        options.pixel_mapper_config = LEDFormat['matrixMapper']

        options.row_address_type = 0
        options.multiplexing = 0
        options.pwm_bits = 11
        options.brightness = 100
        options.pwm_lsb_nanoseconds = 130
        options.led_rgb_sequence = "RGB"
        options.show_refresh_rate = 0

        self.__MatrixID = RGBMatrix(options = options)
        
        self.__MatrixID.Clear()

        xsize = self.__MatrixID.width
        ysize = self.__MatrixID.height

        self.__LEDXSize = xsize
        self.__LEDYSize = ysize

        self.__LEDXMax = xsize - 1
        self.__LEDYMax = ysize - 1

        self.__DrawOnMatrix = True

        self.__MatrixCanvas = Canvas((self.__LEDXSize, self.__LEDYSize))
        self.__FadeMatrixCanvas = Canvas((self.__LEDXSize, self.__LEDYSize))

        self.__MatrixBuffer = self.__MatrixID.CreateFrameCanvas()
Example #5
0
    def setup(self):
        config = configparser.ConfigParser()
        config.read("weatherPanel.cfg")

        #
        # LED section
        #
        options = RGBMatrixOptions()
        if "LED" in config:
            ledOptions = config["LED"]
            options.cols = int(ledOptions.get("cols", 64))
            options.rows = int(ledOptions.get("rows", 32))
            options.chain_length = int(ledOptions.get("chain_length", 4))
            options.parallel = int(ledOptions.get("parallel", 1))
            options.hardware_mapping = ledOptions.get(
                "hardware_mapping", "adafruit-hat"
            )
            options.pixel_mapper_config = ledOptions.get(
                "pixel_mapper_config", "U-mapper"
            )
            self.matrix = RGBMatrix(options=options)
        else:
            self.handleOptionsError("LED", "")

        #
        # WEATHER section
        #
        if "WEATHER" in config:
            weatherOptions = config["WEATHER"]
            if "lat" in weatherOptions:
                lat = weatherOptions.get("lat")
            else:
                self.handleOptionsError("WEATHER", "lat")
            if "lon" in weatherOptions:
                lon = weatherOptions.get("lon")
            else:
                self.handleOptionsError("WEATHER", "lon")
            if "units" in weatherOptions:
                units = weatherOptions.get("units", "imperial")
            if "appid" in weatherOptions:
                appid = weatherOptions["appid"]
            else:
                self.handleOptionsError("WEATHER", "appid")
        else:
            self.handleOptionsError("WEATHER", "")
        self.weatherUri = "https://api.openweathermap.org/data/2.5/onecall"
        self.params = (
            "lat=" + lat + "&lon=" + lon + "&appid=" + appid + "&units=" + units
        )

        #
        # RSS section
        #
        self.feedArray = []
        if "RSS" in config:
            rssOptions = config["RSS"]
            if "feed" in rssOptions:
                self.feedArray = rssOptions.get("feed", "").split("\n")
                self.rssApp.url = self.feedArray[0]

        #
        # MISC section
        #
        if "MISC" in config:
            miscOptions = config["MISC"]
            self.weatherTimeOut = int(miscOptions.get("weatherTimeOut", 8 * 60 * 10))
            self.rssTimeOut = int(miscOptions.get("rssTimeOut", 8 * 60 * 30))
            self.rssApp.verbose = self.verbose = miscOptions.get("verbose", False)
        else:
            self.weatherTimeOut = 8 * 60 * 10
            self.rssTimeOut = 8 * 60 * 30
            self.rssApp.verbose = self.verbose = False

        self.offscreen_canvas = self.matrix.CreateFrameCanvas()
        self.font = graphics.Font()
        self.font.LoadFont("./fonts/7x13.bdf")
        self.fontB = graphics.Font()
        self.fontB.LoadFont("./fonts/7x13B.bdf")
        self.fontMed = graphics.Font()
        self.fontMed.LoadFont("./fonts/6x9.bdf")
        self.fontSmall = graphics.Font()
        self.fontSmall.LoadFont("./fonts/5x8.bdf")
        self.textColor = graphics.Color(0, 0, 128)
        self.xpos = 0
        self.lineSpacing = 1

        self.degreeSign = "\u00B0"

        self.alertArray = []
        self.weatherIcon = None
        self.feedNo = 0
Example #6
0
    def __init__(self):
        p = psutil.Process()
        p.cpu_affinity([3])

        with open('../config-clock.json') as f:
            s = f.read()
            self.config = json.loads(s)

        self.map = collections.OrderedDict()

        if self.config['mqtt']['enabled']:
            self.mqcl = mqtt.Client("led-clock")
            self.mqcl.enable_logger()
            self.mqcl.on_connect = self.mqtt_connect
            self.mqcl.on_message = self.mqtt_message
            self.mqcl.connect(self.config['mqtt']['host'],
                              self.config['mqtt']['port'], 60)

        self.icons = {}
        self.ledW = 64
        self.ledH = 32
        self.delay = 0.05

        self.clockPos = [0, 14]
        self.tempPos = [46, 7]
        self.co2Pos = [1, 31]
        self.humPos = [1, 23]
        self.windSpPos = [25, 23]
        self.forecastPos = [41, 23]

        self.fontReg = graphics.Font()
        self.fontReg.LoadFont("./fonts/10x20.bdf")
        self.fontRegW = 8
        self.fontRegH = 14
        self.fontSm = graphics.Font()
        self.fontSm.LoadFont("./fonts/5x8.bdf")
        self.fontSmW = 5
        self.fontSmH = 7
        self.fontSmm = graphics.Font()
        self.fontSmm.LoadFont("./fonts/4x6.bdf")
        self.fontSmmW = 4

        self.imgW = 8
        self.imgH = 7

        self.userBrightness = None
        self.bri = 1
        self.prevBri = None
        self.initColors()
        self.snow = []
        self.snowTimer = time.time()

        options = RGBMatrixOptions()
        options.rows = self.ledH
        options.cols = self.ledW
        options.chain_length = 1
        options.parallel = 1
        options.multiplexing = 0
        options.pwm_bits = 11
        options.pwm_lsb_nanoseconds = 130
        options.gpio_slowdown = 2
        options.disable_hardware_pulsing = False
        options.hardware_mapping = 'regular'
        options.row_address_type = 0
        options.brightness = 100
        options.show_refresh_rate = False

        self.matrix = RGBMatrix(options=options)
        self.canvas = self.matrix.CreateFrameCanvas()

        self.metricsUpdated = 0
        self.metrics = None
Example #7
0
# this is the size of ONE of our matrixes.
matrix_rows = 32
matrix_columns = 32

# how many matrixes stacked horizontally and vertically
matrix_horizontal = 5
matrix_vertical = 3

total_rows = matrix_rows * matrix_vertical
total_columns = matrix_columns * matrix_horizontal

options = RGBMatrixOptions()
options.rows = matrix_rows
options.cols = matrix_columns
options.chain_length = matrix_horizontal
options.parallel = matrix_vertical
options.hardware_mapping = 'regular'
options.gpio_slowdown = 2

matrix = RGBMatrix(options=options)


def display_jpg():
    global matrix

    image = Image.open("temp.jpg").convert('RGB')
    image = image.resize((total_columns, total_rows))
    image = image.transpose(Image.FLIP_LEFT_RIGHT)
    matrix.SetImage(image, 0, 0)
Example #8
0
parser.add_argument("--led-show-refresh", action="store_true", help="Shows the current refresh rate of the LED panel")
parser.add_argument("--led-slowdown-gpio", action="store", help="Slow down writing to GPIO. Range: 1..100. Default: 1", choices=range(3), type=int)
parser.add_argument("--led-no-hardware-pulse", action="store", help="Don't use hardware pin-pulse generation")
parser.add_argument("--led-rgb-sequence", action="store", help="Switch if your matrix has led colors swapped. Default: RGB", default="RGB", type=str)
parser.add_argument("--led-pixel-mapper", action="store", help="Apply pixel mappers. e.g \"Rotate:90\"", default="", type=str)
parser.add_argument("--led-row-addr-type", action="store", help="0 = default; 1=AB-addressed panels;2=row direct", default=0, type=int, choices=[0, 1, 2])
parser.add_argument("--led-multiplexing", action="store", help="Multiplexing type: 0=direct; 1=strip; 2=checker; 3=spiral; 4=ZStripe; 5=ZnMirrorZStripe; 6=coreman; 7=Kaler2Scan; 8=ZStripeUneven (Default: 0)", default=0, type=int)

args = parser.parse_args()

options = RGBMatrixOptions()
if args.led_gpio_mapping is not None:
    options.hardware_mapping = args.led_gpio_mapping
options.rows = args.led_rows
options.cols = args.led_cols
options.chain_length = args.led_chain
options.parallel = args.led_parallel
options.row_address_type = args.led_row_addr_type
options.multiplexing = args.led_multiplexing
options.pwm_bits = args.led_pwm_bits
options.brightness = args.led_brightness
options.pwm_lsb_nanoseconds = args.led_pwm_lsb_nanoseconds
options.led_rgb_sequence = args.led_rgb_sequence
options.pixel_mapper_config = args.led_pixel_mapper
if args.led_show_refresh:
    options.show_refresh_rate = 1
if args.led_slowdown_gpio is not None:
    options.gpio_slowdown = args.led_slowdown_gpio
if args.led_no_hardware_pulse:
    options.disable_hardware_pulsing = True
options.daemon = args.daemon
Example #9
0
"""
Do not modify this section
"""
from random import randint
from rgbmatrix import RGBMatrix, RGBMatrixOptions

# Configuration for the matrix
options = RGBMatrixOptions()
options.rows = 64
options.chain_length = 4
options.parallel = 1
options.hardware_mapping = 'adafruit-hat'
options.led_rgb_sequence = "RBG"

matrix = RGBMatrix(options=options)
Example #10
0
import time
import sys
import os

import socket

from rgbmatrix import RGBMatrix, RGBMatrixOptions
from rgbmatrix import graphics

options = RGBMatrixOptions()

# This chain is mapped as a 64*2 x 32 grid.

options.rows = 32  # 32 rows per display
options.cols = 64  # 64 rows per display (64x32)
options.chain_length = 2  # 2 displays per chain (128x32)
options.parallel = 1  # 3 (128x96)

matrix = RGBMatrix(options=options)


def draw_graphic(x, y, data, color, canvas):
    data = data.replace(' ', '').replace('\n', '')
    pos = 0
    for j in range(12):
        for i in range(12):
            if data[pos] == '*':
                canvas.SetPixel(x + i, y + j, 100, 255, 255)
            pos += 1

Example #11
0
def main():
    """
    from samplebase.py
    """

    sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/..'))

    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-r",
        "--led-rows",
        action="store",
        help="Display rows. 16 for 16x32, 32 for 32x32. Default: 32",
        default=32,
        type=int)
    parser.add_argument(
        "--led-cols",
        action="store",
        help="Panel columns. Typically 32 or 64. (Default: 32)",
        default=32,
        type=int)
    parser.add_argument("-c",
                        "--led-chain",
                        action="store",
                        help="Daisy-chained boards. Default: 1.",
                        default=1,
                        type=int)
    parser.add_argument(
        "-P",
        "--led-parallel",
        action="store",
        help="For Plus-models or RPi2: parallel chains. 1..3. Default: 1",
        default=1,
        type=int)
    parser.add_argument(
        "-p",
        "--led-pwm-bits",
        action="store",
        help="Bits used for PWM. Something between 1..11. Default: 11",
        default=11,
        type=int)
    parser.add_argument(
        "-b",
        "--led-brightness",
        action="store",
        help="Sets brightness level. Default: 100. Range: 1..100",
        default=100,
        type=int)
    parser.add_argument(
        "-m",
        "--led-gpio-mapping",
        help="Hardware Mapping: regular, adafruit-hat, adafruit-hat-pwm",
        choices=['regular', 'adafruit-hat', 'adafruit-hat-pwm'],
        type=str)
    parser.add_argument(
        "--led-scan-mode",
        action="store",
        help=
        "Progressive or interlaced scan. 0 Progressive, 1 Interlaced (default)",
        default=1,
        choices=range(2),
        type=int)
    parser.add_argument(
        "--led-pwm-lsb-nanoseconds",
        action="store",
        help=
        "Base time-unit for the on-time in the lowest significant bit in nanoseconds. Default: 130",
        default=130,
        type=int)
    parser.add_argument("--led-show-refresh",
                        action="store_true",
                        help="Shows the current refresh rate of the LED panel")
    parser.add_argument(
        "--led-slowdown-gpio",
        action="store",
        help="Slow down writing to GPIO. Range: 1..100. Default: 1",
        choices=range(3),
        type=int)
    parser.add_argument("--led-no-hardware-pulse",
                        action="store",
                        help="Don't use hardware pin-pulse generation")
    parser.add_argument(
        "--led-rgb-sequence",
        action="store",
        help="Switch if your matrix has led colors swapped. Default: RGB",
        default="RGB",
        type=str)
    parser.add_argument("--led-pixel-mapper",
                        action="store",
                        help="Apply pixel mappers. e.g \"Rotate:90\"",
                        default="",
                        type=str)
    parser.add_argument("--led-row-addr-type",
                        action="store",
                        help="0 = default; 1=AB-addressed panels;2=row direct",
                        default=0,
                        type=int,
                        choices=[0, 1, 2])
    parser.add_argument(
        "--led-multiplexing",
        action="store",
        help=
        "Multiplexing type: 0=direct; 1=strip; 2=checker; 3=spiral; 4=ZStripe; 5=ZnMirrorZStripe; 6=coreman; 7=Kaler2Scan; 8=ZStripeUneven (Default: 0)",
        default=0,
        type=int)

    args = parser.parse_args()

    options = RGBMatrixOptions()

    if args.led_gpio_mapping != None:
        options.hardware_mapping = args.led_gpio_mapping

    options.rows = args.led_rows
    options.cols = args.led_cols
    options.chain_length = args.led_chain
    options.parallel = args.led_parallel
    options.row_address_type = args.led_row_addr_type
    options.multiplexing = args.led_multiplexing
    options.pwm_bits = args.led_pwm_bits
    options.brightness = args.led_brightness
    options.pwm_lsb_nanoseconds = args.led_pwm_lsb_nanoseconds
    options.led_rgb_sequence = args.led_rgb_sequence
    options.pixel_mapper_config = args.led_pixel_mapper

    if args.led_show_refresh:
        options.show_refresh_rate = 1

    if args.led_slowdown_gpio != None:
        options.gpio_slowdown = args.led_slowdown_gpio

    if args.led_no_hardware_pulse:
        options.disable_hardware_pulsing = True

    matrix = RGBMatrix(options=options)

    try:
        # Start loop
        print('(C) 2020-2021 MSRoth')
        print(
            'LED clock on 64x32 LED matrix with weather, market, and news updates.'
        )
        print('See config.py for details. Press CTRL-C to stop clock.')
        print('Loading data...\n\n')

        run(matrix)
    except KeyboardInterrupt:
        print("Exiting\n")
        tl.stop()
        sys.exit(0)
toMatrixBuffer = Image.new("RGB", (128, 16), "black")

dataFile = open("/home/pi/kristallradarlite/started.txt", "r")
countStart = int(dataFile.readline())
dataFile.close()

countStart += 1

dataFile = open("/home/pi/kristallradarlite/started.txt", "w")
dataFile.write(str(countStart))
dataFile.close()

matrix_options = RGBMatrixOptions()
matrix_options.rows = 16
matrix_options.cols = 32
matrix_options.chain_length = 4
matrix_options.parallel = 1
matrix_options.multiplexing = 4
matrix_options.hardware_mapping = 'adafruit-hat'
matrix_options.gpio_slowdown = 2
matrix_options.pwm_bits = 1
#matrix_options.pwm_dither_bits = 1
matrix_options.brightness = 100
matrix_options.pwm_lsb_nanoseconds = 350
matrix = RGBMatrix(options=matrix_options)
matrix.SetImage(buffer, 0, 0)

while 1:
    for i in range(200):
        speedValue = i
        time.sleep(1)
Example #13
0
def main():

    if len(sys.argv) < 2:
        sys.exit("require a command argument")
    else:
        image_set = sys.argv[1]

    random = False

    if image_set is "random":
        random = True

    sets = {
        "broccoli_test": ["broccoli.png", "broccoli_black.png"],
        "snorunt":
        8,
        "fireworks":
        23,
        "uc_broccoli": [
            "uc.png", "uc.png", "uc.png", "broccoli.png", "broccoli.png",
            "broccoli.png"
        ],
        "schwifty":
        22,
        "engineer":
        16,
        "ea": ["ea.png", "ea.png"],
        "meche": ["meche.png", "meche2.png"]
    }

    random_keys = ["snorunt", "fireworks", "uc_broccoli", "ea", "meche"]

    image_path = "images/"

    if random:
        image_set = random.choice(random_keys)

    if isinstance(sets[image_set], (int, long)):
        slides = []
        for i in range(sets[image_set]):
            slides.append(str(i) + ".gif")
    else:
        slides = sets[image_set]

    options = RGBMatrixOptions()
    options.rows = 32
    options.cols = 32
    options.chain_length = 4
    options.parallel = 1
    options.hardware_mapping = 'adafruit-hat'

    matrix = RGBMatrix(options=options)

    try:
        print("Press CTRL-C to stop")
        index = 0
        start_time = time.time()
        while True:

            if random:
                if time.time() > (start_time + 30):
                    start_time = time.time()
                    index = 0
                    image_set = random.choice(random_keys)

                    if isinstance(sets[image_set], (int, long)):
                        slides = []
                        for i in range(sets[image_set]):
                            slides.append(str(i) + ".gif")
                    else:
                        slides = sets[image_set]

            if index == len(slides):
                index = 0
            print index
            image_file = image_path + image_set + '/' + slides[index]
            image = Image.open(image_file)
            display_image_to_matrix(image, matrix)
            index = index + 1
            time.sleep(0.1)

    except KeyboardInterrupt:
        sys.exit(0)
Example #14
0
    os.environ.get("LOGFILE", "/var/log/matrix.log"))
formatter = logging.Formatter(logging.BASIC_FORMAT)
handler.setFormatter(formatter)
root = logging.getLogger()
root.setLevel(os.environ.get("LOGLEVEL", "INFO"))
root.addHandler(handler)
config = configparser.ConfigParser()
config.read('config.ini')

####
# Configuration for the matrix
####
options = RGBMatrixOptions()
options.rows = int(config['MATRIX']['ROWS'])
options.cols = int(config['MATRIX']['COLS'])
options.chain_length =  int(config['MATRIX']['CHAIN_LENGTH'])
options.hardware_mapping = config['MATRIX']['HARDWARE_MAPPING']
options.brightness = int(config['MATRIX']['BRIGHTNESS'])
####
# Configuration for Gmaps
####
gmaps = googlemaps.Client(key=config['LOCATION']['GOOGLE_API'])

####
# Variables
####
my_zip = config['LOCATION']['ZIP']   # US Zip Code used in the weather module
origin = config['LOCATION']['HOME']
destination = config['LOCATION']['WORK']
ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.93 Safari/537.36'
bustime_api_key = config['MUNI']['API_KEY']
Example #15
0
def main():
    parser = argparse.ArgumentParser()

    # arguments from the RGBMatrix library
    parser.add_argument(
        "-r",
        "--led-rows",
        action="store",
        help="Display rows. 16 for 16x32, 32 for 32x32. Default: 32",
        default=32,
        type=int,
    )
    parser.add_argument(
        "--led-cols",
        action="store",
        help="Panel columns. Typically 32 or 64. (Default: 32)",
        default=32,
        type=int,
    )
    parser.add_argument(
        "-c",
        "--led-chain",
        action="store",
        help="Daisy-chained boards. Default: 1.",
        default=1,
        type=int,
    )
    parser.add_argument(
        "-P",
        "--led-parallel",
        action="store",
        help="For Plus-models or RPi2: parallel chains. 1..3. Default: 1",
        default=1,
        type=int,
    )
    parser.add_argument(
        "-p",
        "--led-pwm-bits",
        action="store",
        help="Bits used for PWM. Something between 1..11. Default: 11",
        default=11,
        type=int,
    )
    parser.add_argument(
        "-b",
        "--led-brightness",
        action="store",
        help="Sets brightness level. Default: 100. Range: 1..100",
        default=100,
        type=int,
    )
    parser.add_argument(
        "-m",
        "--led-gpio-mapping",
        help="Hardware Mapping: regular, adafruit-hat, adafruit-hat-pwm",
        choices=["regular", "adafruit-hat", "adafruit-hat-pwm"],
        type=str,
    )
    parser.add_argument(
        "--led-scan-mode",
        action="store",
        help=
        "Progressive or interlaced scan. 0 Progressive, 1 Interlaced (default)",
        default=1,
        choices=range(2),
        type=int,
    )
    parser.add_argument(
        "--led-pwm-lsb-nanoseconds",
        action="store",
        help=
        "Base time-unit for the on-time in the lowest significant bit in nanoseconds. Default: 130",
        default=130,
        type=int,
    )
    parser.add_argument(
        "--led-show-refresh",
        action="store_true",
        help="Shows the current refresh rate of the LED panel",
    )
    parser.add_argument(
        "--led-slowdown-gpio",
        action="store",
        help="Slow down writing to GPIO. Range: 0..4. Default: 1",
        default=1,
        type=int,
    )
    parser.add_argument(
        "--led-no-hardware-pulse",
        action="store",
        help="Don't use hardware pin-pulse generation",
    )
    parser.add_argument(
        "--led-rgb-sequence",
        action="store",
        help="Switch if your matrix has led colors swapped. Default: RGB",
        default="RGB",
        type=str,
    )
    parser.add_argument(
        "--led-pixel-mapper",
        action="store",
        help='Apply pixel mappers. e.g "Rotate:90"',
        default="",
        type=str,
    )
    parser.add_argument(
        "--led-row-addr-type",
        action="store",
        help="0 = default; 1=AB-addressed panels;2=row direct",
        default=0,
        type=int,
        choices=[0, 1, 2],
    )
    parser.add_argument(
        "--led-multiplexing",
        action="store",
        help=
        "Multiplexing type: 0=direct; 1=strip; 2=checker; 3=spiral; 4=ZStripe; 5=ZnMirrorZStripe; 6=coreman; 7=Kaler2Scan; 8=ZStripeUneven (Default: 0)",
        default=0,
        type=int,
    )

    args = parser.parse_args()

    options = RGBMatrixOptions()

    if args.led_gpio_mapping != None:
        options.hardware_mapping = args.led_gpio_mapping

    options.rows = args.led_rows
    options.cols = args.led_cols
    options.chain_length = args.led_chain
    options.parallel = args.led_parallel
    options.row_address_type = args.led_row_addr_type
    options.multiplexing = args.led_multiplexing
    options.pwm_bits = args.led_pwm_bits
    options.brightness = args.led_brightness
    options.pwm_lsb_nanoseconds = args.led_pwm_lsb_nanoseconds
    options.led_rgb_sequence = args.led_rgb_sequence
    options.pixel_mapper_config = args.led_pixel_mapper

    if args.led_show_refresh:
        options.show_refresh_rate = 1

    if args.led_slowdown_gpio != None:
        options.gpio_slowdown = args.led_slowdown_gpio

    if args.led_no_hardware_pulse:
        options.disable_hardware_pulsing = True

    try:
        print("Press CTRL-C to stop the clock")
        run(options)
    except KeyboardInterrupt:
        print("Exiting\n")
        sys.exit(0)
Example #16
0
    def run(self):

        options = RGBMatrixOptions()
        options.rows = 32
        options.cols = 64
        options.chain_length = 4
        options.parallel = 1
        options.hardware_mapping = "adafruit-hat-pwm"
        options.pixel_mapper_config = "U-mapper"
        options.row_address_type = 0
        options.multiplexing = 0
        options.pwm_bits = 6
        options.brightness = 100
        options.pwm_lsb_nanoseconds = 130
        options.limit_refresh_rate_hz = 200
        options.led_rgb_sequence = "RBG"
        options.show_refresh_rate = 0
        options.gpio_slowdown = 1
        self.matrix = RGBMatrix(options=options)

        white = graphics.Color(255, 255, 255)
        gray = graphics.Color(127, 127, 127)
        green = graphics.Color(0, 150, 0)
        yellow = graphics.Color(127, 127, 0)
        red = graphics.Color(150, 0, 0)
        blue = graphics.Color(0, 0, 150)
        magenta = graphics.Color(127, 0, 127)
        cyan = graphics.Color(0, 127, 127)
        dim = graphics.Color(10, 10, 10)

        offscreen_canvas = self.matrix.CreateFrameCanvas()
        font = graphics.Font()

        #main_dir = os.getcwd()
        main_dir = "/home/pi/nhlscoreboard"

        width = 128
        height = 64
        font_medium = graphics.Font()
        font_medium.LoadFont("/home/pi/rpi-rgb-led-matrix/fonts/7x13.bdf")
        font_small = graphics.Font()
        font_small.LoadFont("/home/pi/rpi-rgb-led-matrix/fonts/6x10.bdf")
        font_big = graphics.Font()
        font_big.LoadFont("/home/pi/rpi-rgb-led-matrix/fonts/9x15.bdf")

        fontYoffset = 8
        fontYoffset2 = 8
        x_offset = -64

        gameday = False
        season = False
        home_roster = {}
        away_roster = {}
        home_score = 0
        home_score_old = 0
        away_score = 0
        away_score_old = 0
        home_team = ""
        away_team = ""
        live_stats_link = ""
        x = 0
        y = 10
        home_score_color = ""
        away_score_color = ""
        do_once = 1
        ignore_first_score_change = 1

        random.seed()
        choice = 1

        teams = {
            1: "NJD",
            2: "NYI",
            3: "NYR",
            4: "PHI",
            5: "PIT",
            6: "BOS",
            7: "BUF",
            8: "MTL",
            9: "OTT",
            10: "TOR",
            12: "CAR",
            13: "FLA",
            14: "TBL",
            15: "WSH",
            16: "CHI",
            17: "DET",
            18: "NSH",
            19: "STL",
            20: "CGY",
            21: "COL",
            22: "EDM",
            23: "VAN",
            24: "ANA",
            25: "DAL",
            26: "LAK",
            28: "SJS",
            29: "CBJ",
            30: "MIN",
            52: "WPG",
            53: "ARI",
            54: "VGK"
        }
        team_id, delay = self.setup_nhl()

        #image = Image.open("/home/pi/nhlscoreboard/images/goal.png")
        #self.matrix.SetImage(image.convert('RGB'))
        #time.sleep(5)

        try:

            while (True):

                time.sleep(2)

                # check if in season
                season = nhl.check_season()
                season = 1
                if season:

                    # check game
                    gameday = nhl.check_if_game(team_id)

                    if gameday:
                        # check end of game
                        game_end = nhl.check_game_end(team_id)

                        if not game_end:
                            try:
                                # get score, teams, and live stats link
                                home_score, home_team, away_score, away_team, live_stats_link = nhl.fetch_game(
                                    team_id)
                            except TypeError:
                                continue

                            # get stats from the game
                            current_period, home_sog, away_sog, home_powerplay, away_powerplay, time_remaining = nhl.fetch_live_stats(
                                live_stats_link)

                            if current_period > 0:

                                # get the rosters just once at the start
                                if do_once:
                                    while ((len(home_roster) < 5)
                                           or (len(away_roster) < 5)):
                                        home_roster, away_roster = nhl.fetch_rosters(
                                            live_stats_link)
                                    do_once = 0

                                # get the players on ice
                                home_on_ice, away_on_ice = nhl.players_on_ice(
                                    live_stats_link)
                                # build a list like so for each team
                                # jersey_number lastname
                                home_ice_list = []
                                away_ice_list = []
                                home_goalie_id, away_goalie_id = nhl.fetch_goalies(
                                    live_stats_link)
                                for the_id in home_on_ice:
                                    try:
                                        jersey_number = (
                                            home_roster['ID' + str(the_id)]
                                            ['jerseyNumber']).encode("ascii")
                                    except:
                                        jersey_number = "0"
                                    if int(jersey_number) < 10:
                                        try:
                                            jersey_number = jersey_number.decode(
                                                "utf-8") + ' '
                                        except:
                                            jersey_number = '00'
                                    else:
                                        try:
                                            jersey_number = jersey_number.decode(
                                                "utf-8")
                                        except:
                                            jersey_number = '00'

                                    try:
                                        last_name = ((
                                            (home_roster['ID' + str(the_id)]
                                             ['person']['fullName']).split(
                                                 ' ', 1))[1]
                                                     ).encode('utf-8').strip()
                                    except UnicodeEncodeError:
                                        last_name = ' '

                                    try:
                                        temp_thing = jersey_number + ' ' + (
                                            last_name[0:7].upper()
                                        ).decode("utf-8")
                                    except TypeError:
                                        temp_thing = ' '
                                    home_ice_list.append(temp_thing)
                                for the_id in away_on_ice:
                                    try:
                                        jersey_number = (
                                            away_roster['ID' + str(the_id)]
                                            ['jerseyNumber']).encode("ascii")
                                    except:
                                        jersey_number = '00'
                                    if int(jersey_number) < 10:
                                        try:
                                            jersey_number = jersey_number.decode(
                                                "ascii") + ' '
                                        except TypeError:
                                            jersey_number = 0
                                    else:
                                        jersey_number = jersey_number.decode(
                                            "utf-8")
                                    try:
                                        last_name = ((
                                            (away_roster['ID' + str(the_id)]
                                             ['person']['fullName']).split(
                                                 ' ', 1))[1]
                                                     ).encode('utf-8').strip()
                                    except TypeError:
                                        last_name = ' '
                                    try:
                                        temp_thing = jersey_number + ' ' + (
                                            last_name[0:7].upper()
                                        ).decode("utf-8")
                                    except TypeError:
                                        temp_thing = ' '
                                    away_ice_list.append(temp_thing)

                                # determine score colors
                                if home_score > away_score:
                                    home_score_color = red
                                    away_score_color = green
                                elif away_score > home_score:
                                    home_score_color = green
                                    away_score_color = red
                                else:
                                    home_score_color = green
                                    away_score_color = green

                                # determine team colors
                                if home_powerplay == 1:
                                    home_team_color = yellow
                                else:
                                    home_team_color = gray
                                if away_powerplay == 1:
                                    away_team_color = yellow
                                else:
                                    away_team_color = gray

                                # reset x and y
                                x = 0
                                y = 0

                                # clear the offscreen canvas
                                offscreen_canvas.Clear()

                                # teams
                                # away on left
                                # home on right
                                # 3-letter team, score, sog
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  0, y + fontYoffset,
                                                  away_team_color,
                                                  teams[away_team])
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  28, y + fontYoffset,
                                                  away_score_color,
                                                  str(away_score))
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  49, y + fontYoffset, yellow,
                                                  str(away_sog))
                                y += 8
                                # players on ice
                                for line in away_ice_list:
                                    graphics.DrawText(offscreen_canvas,
                                                      font_small, 0,
                                                      y + fontYoffset, gray,
                                                      line)
                                    y += 8

                                # away on left
                                y = 0
                                # 3-letter team, score, sog
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  64, y + fontYoffset,
                                                  home_team_color,
                                                  teams[home_team])
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  92, y + fontYoffset,
                                                  home_score_color,
                                                  str(home_score))
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  113, y + fontYoffset, yellow,
                                                  str(home_sog))
                                y += 8
                                # players on ice
                                for line in home_ice_list:
                                    graphics.DrawText(offscreen_canvas,
                                                      font_small, 64,
                                                      y + fontYoffset, gray,
                                                      line)
                                    y += 8

                                y = 64
                                status, time_remaining = nhl.intermission_status(
                                    live_stats_link)
                                if status == False:
                                    graphics.DrawText(
                                        offscreen_canvas, font_small, 35, y,
                                        cyan, "PERIOD " + str(current_period))
                                else:
                                    m, s = divmod(time_remaining, 60)
                                    graphics.DrawText(
                                        offscreen_canvas, font_small, 0, y,
                                        cyan, "INTERMISSION " +
                                        '{:02d}:{:02d}'.format(m, s))
                                # blit it to the screen
                                offscreen_canvas = self.matrix.SwapOnVSync(
                                    offscreen_canvas)

                                # If score change...
                                if home_score > home_score_old:
                                    home_score_old = home_score
                                    choice = random.randint(1, 3)
                                    if ignore_first_score_change == 0:
                                        if home_team == int(team_id):
                                            time.sleep(delay)
                                            image = Image.open(
                                                "/home/pi/nhlscoreboard/images/goal.png"
                                            )
                                            self.matrix.SetImage(
                                                image.convert('RGB'))
                                            time.sleep(5)
                                        else:
                                            time.sleep(delay)
                                            image = Image.open(
                                                "/home/pi/nhlscoreboard/images/sad-rod.gif"
                                            )
                                            self.matrix.SetImage(
                                                image.convert('RGB'))
                                            time.sleep(5)
                                    else:
                                        ignore_first_score_change = 0
                                else:
                                    home_score_old = home_score

                                # If score change...
                                if away_score > away_score_old:
                                    away_score_old = away_score
                                    choice = random.randint(1, 3)
                                    if ignore_first_score_change == 0:
                                        if away_team == int(team_id):
                                            time.sleep(delay)
                                            image = Image.open(
                                                "/home/pi/nhlscoreboard/images/goal.png"
                                            )
                                            self.matrix.SetImage(
                                                image.convert('RGB'))
                                            time.sleep(5)
                                        else:
                                            time.sleep(delay)
                                            image = Image.open(
                                                "/home/pi/nhlscoreboard/images/sad-rod.gif"
                                            )
                                            self.matrix.SetImage(
                                                image.convert('RGB'))
                                            time.sleep(5)
                                    else:
                                        ignore_first_score_change = 0

                                else:
                                    away_score_old = away_score

                                ignore_first_score_change = 0

                            if current_period == 0:
                                offscreen_canvas.Clear()
                                y = 7
                                x_offset = x_offset + 1
                                if x_offset > 128:
                                    x_offset = -128
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  x + x_offset, y, blue,
                                                  "GAME TODAY!")
                                y += fontYoffset2
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  x + 10 + x_offset, y, green,
                                                  "GAME TODAY!")
                                y += fontYoffset2
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  x + 20 + x_offset, y, red,
                                                  "GAME TODAY!")
                                y += fontYoffset2
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  x + 30 + x_offset, y, yellow,
                                                  "GAME TODAY!")
                                y += fontYoffset2
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  x + 40 + x_offset, y,
                                                  magenta, "GAME TODAY!")
                                y += fontYoffset2
                                graphics.DrawText(offscreen_canvas, font_small,
                                                  x + 50 + x_offset, y, cyan,
                                                  "GAME TODAY!")
                                y += fontYoffset2
                                temptime = datetime.datetime.now()
                                graphics.DrawText(
                                    offscreen_canvas, font_small, 0, y, gray,
                                    temptime.strftime("%m/%d/%y %H:%M"))
                                y += fontYoffset2
                                game_start_time = nhl.fetch_game_start_time(
                                    live_stats_link)
                                graphics.DrawText(
                                    offscreen_canvas, font_small, 0, y, gray,
                                    "GAMETIME: " + game_start_time)
                                offscreen_canvas = self.matrix.SwapOnVSync(
                                    offscreen_canvas)

                        else:
                            home_roster.clear()
                            away_roster.clear()
                            old_score = 0  # Reset for new game
                            current_period = 0
                            self.matrix.Clear()
                            offscreen_canvas.Clear()
                            do_once = 1
                            self.sleep("day")  # sleep till tomorrow
                    else:
                        print("No Game Today!")
                        self.sleep("day")  # sleep till tomorrow
                else:
                    print("OFF SEASON!")
                    self.sleep("season")  # sleep till next season

        except KeyboardInterrupt:
            print("\nCtrl-C pressed")
Example #17
0
def draw_board():
    """Draw components of LaLiga game.

    Firstly, creates a canvas for the LED matrix using various configurations.
    Requests games for the day for La Liga and draws various components of the game such as team logos, scores, period, and time.

    Also, draws "SCORE!!!" animation for the game if there is an update in the score.

    If button is pressed during the execution, it will load the next game. If the game is the last one for the day in La Liga, then it will
    go to the next league.

    Returns:
        int: Return -1 if no favorite game.
    """

    # Configuration for the matrix
    options = RGBMatrixOptions()
    options.rows = ROWS
    options.cols = COLS
    options.chain_length = 1
    options.parallel = 1
    options.brightness = BRIGHTNESS
    options.hardware_mapping = 'adafruit-hat'

    image_size = ROWS if ROWS < COLS else COLS
    matrix = RGBMatrix(options=options)

    canvas = matrix.CreateFrameCanvas()
    font = graphics.Font()
    font.LoadFont("./fonts/tom-thumb.bdf")
    anifont = graphics.Font()
    anifont.LoadFont("./fonts/cherry-10-b.bdf")
    textColor = graphics.Color(225, 225, 0)

    height_first_row = 9
    height_second_row = 18
    height_third_row = 27

    # Control button
    button = Button(GPIO_CONTROL)

    it = 0
    wait = 0

    # Loading La Liga
    canvas.Clear()
    graphics.DrawText(canvas, font,
                      10,
                      height_second_row, textColor, 'Loading LaL')
    canvas = matrix.SwapOnVSync(canvas)

    games = Scores.get_scores()
    if len(games) == 0:
        # Print no games scheduled
        canvas.Clear()
        graphics.DrawText(canvas, font,
                          4,
                          height_second_row, textColor, 'LaL - no games')
        canvas = matrix.SwapOnVSync(canvas)
        # Handle control button and wait
        button.wait_for_press(15)
        return -1

    while it < len(games):
        canvas.Clear()

        score_len = 20
        if 'score' in games[it]:
            # Chagne score len if 2 digit score
            score_len = 28 if games[it]['score'][3] == '-' else 20

        # Get x coords for logos
        image_space = (COLS - score_len - 4) / 2
        x_away = -ROWS + image_space - 2
        x_home = image_space + score_len + 2

        # Get logos as thumbnails; home is flipped for right
        image_away = Image.open(f"logos/LaLiga/{games[it]['away']}_logo.png")
        image_away.thumbnail((image_size, image_size), Image.ANTIALIAS)

        image_home = Image.open(f"logos/LaLiga/{games[it]['home']}_logo.png")
        image_home.thumbnail((image_size, image_size), Image.ANTIALIAS)

        # Print logos
        canvas.SetImage(image_away.convert('RGB'), x_away, 0)
        canvas.SetImage(image_home.convert('RGB'), x_home, 0)

        # Print score final or live
        score_len = len(games[it]['score'])*4

        if games[it]['stage'] == 'Scheduled':
            # If planned game, print @ and time
            clock_len = len(games[it]['clock'])*4
            graphics.DrawText(canvas, font,
                              int((COLS - 8) / 2),
                              height_first_row, textColor, "AT")
            graphics.DrawText(canvas, font,
                              int((COLS - clock_len) / 2),
                              height_second_row, textColor, games[it]['clock'])
            graphics.DrawText(canvas, font,
                              int((COLS - 12) / 2),
                              height_third_row, textColor, 'GMT')
        elif games[it]['stage'] == 'Full Time':
            # Else print 'fin' to indicate final score
            graphics.DrawText(canvas, font,
                              int((COLS - 12) / 2),
                              height_first_row, textColor, "FIN")
            graphics.DrawText(canvas, font,
                              int((COLS - score_len) / 2),
                              height_second_row, textColor, games[it]['score'])
        else:
            # If game is in progress, print period
            # and time left in the period
            period_len = len(games[it]['period'])*4
            clock_len = len(games[it]['clock'])*4
            graphics.DrawText(canvas, font,
                              int((COLS - period_len) / 2),
                              height_first_row, textColor,
                              games[it]['period'])
            graphics.DrawText(canvas, font,
                              int((COLS - score_len) / 2),
                              height_second_row, textColor, games[it]['score'])
            graphics.DrawText(canvas, font,
                              int((COLS - clock_len) / 2),
                              height_third_row, textColor, games[it]['clock'])

        # Handle control button and wait
        is_button_pressed = button.wait_for_press(5)

        # Increment iterator if button was pressed
        if is_button_pressed:
            it += 1
            time.sleep(1)

        # Mention to the user that they should wait after pressing the button
        # for about 5-10 seconds as it takes a while to fetch score
        wait += 1
        if wait > 12 and it < len(games):
            wait = 0
            tmp = Scores.get_scores()

            # Check if new fixes
            if games[it]['away'] != games[it]['away'] and \
                    tmp[it]['home'] != tmp[it]['home']:
                it = 0
            elif (games[it]['stage'] != 'Scheduled' and games[it]['stage'] == 'Full Time') \
                    and games[it]['score'] != tmp[it]['score']:
                # check for score update
                pos = ROWS
                rounds = 0
                while True:
                    canvas.Clear()
                    l = graphics.DrawText(
                        canvas, anifont, pos, height_second_row, textColor, 'GOAL!!!')
                    pos -= 1
                    if (pos + l < 0):
                        pos = ROWS
                        rounds += 1
                        if rounds > 3:
                            break

                    time.sleep(0.05)
                    canvas = matrix.SwapOnVSync(canvas)

            games = tmp

        canvas = matrix.SwapOnVSync(canvas)
Example #18
0
                        filename='spotipy.log',
                        level=logging.INFO)
    logger = logging.getLogger('spotipy_logger')

    # automatically deletes logs more than 2000 bytes
    handler = RotatingFileHandler('spotipy.log', maxBytes=2000, backupCount=3)
    logger.addHandler(handler)

    # Configuration for the matrix
    config = configparser.ConfigParser()
    config.read(filename)

    options = RGBMatrixOptions()
    options.rows = int(config['DEFAULT']['rows'])
    options.cols = int(config['DEFAULT']['columns'])
    options.chain_length = int(config['DEFAULT']['chain_length'])
    options.parallel = int(config['DEFAULT']['parallel'])
    options.hardware_mapping = config['DEFAULT']['hardware_mapping']
    options.gpio_slowdown = int(config['DEFAULT']['gpio_slowdown'])
    options.brightness = int(config['DEFAULT']['brightness'])

    default_image = os.path.join(dir, config['DEFAULT']['default_image'])
    print(default_image)
    matrix = RGBMatrix(options=options)

    try:
        while True:
            try:
                imageURL = getSongInfo(username, token_path)[1]
                response = requests.get(imageURL)
                image = Image.open(BytesIO(response.content))
import sys

from rgbmatrix import RGBMatrix, RGBMatrixOptions
from PIL import Image

if len(sys.argv) < 2:
    sys.exit("Require an image argument")
else:
    image_file = sys.argv[1]

image = Image.open(image_file)

# Configuration for the matrix
options = RGBMatrixOptions()
options.rows = 32
options.chain_length = 1
options.parallel = 1
options.hardware_mapping = 'regular'  # If you have an Adafruit HAT: 'adafruit-hat'

matrix = RGBMatrix(options = options)

# Make image fit our screen.
image.thumbnail((matrix.width, matrix.height), Image.ANTIALIAS)

matrix.SetImage(image.convert('RGB'))

try:
    print("Press CTRL-C to stop.")
    while True:
        time.sleep(100)
except KeyboardInterrupt:
Example #20
0
def main(args):
    device_lat = args.device_lat
    device_long = args.device_long
    feeder_url = args.fr24_feeder_host
    fonts_home = args.fonts_home

    # Configuration for the LED matrix
    options = RGBMatrixOptions()
    options.cols = 64
    options.rows = 32
    options.chain_length = 1
    options.brightness = 40
    options.pwm_dither_bits = 1
    options.pwm_lsb_nanoseconds = 50
    options.parallel = 1
    options.gpio_slowdown = 2  # reduces flicker
    #options.hardware_mapping = 'regular'  # If you have an Adafruit HAT: 'adafruit-hat'

    matrix = RGBMatrix(options=options)
    font = graphics.Font()
    font.LoadFont(f'{fonts_home}/5x7.bdf')
    font2 = graphics.Font()
    font2.LoadFont(f'{fonts_home}/6x10.bdf')

    green = graphics.Color(0, 255, 0)
    graphics.DrawText(matrix, font, 0, 7, green, 'No aircraft')
    graphics.DrawText(matrix, font, 0, 14, green, 'found')

    try:
        print('Press CTRL-C to stop.')
        while True:
            t = threading.Thread(target=get_aircraft(feeder_url))
            t.run()
            if aircraft_change:
                logger.info('Refreshing aircraft list')
                matrix.Clear()
                index = 1
                if len(aircraft_map.keys()) > 0:
                    for aircraft in aircraft_map.keys():
                        matrix.Clear()
                        aircraft_mode_s_transponder = aircraft_map.get(aircraft)[0]
                        aircraft_lat = aircraft_map.get(aircraft)[1]
                        aircraft_long = aircraft_map.get(aircraft)[2]
                        aircraft_ground_speed = aircraft_map.get(aircraft)[5]
                        aircraft_squawk = aircraft_map.get(aircraft)[6]
                        aircraft_callsign = aircraft_map.get(aircraft)[-1]

                        # Draw ADS-B Mode S transponder code
                        graphics.DrawText(matrix, font, 0, index * 7, green, f'ModeS: {aircraft_mode_s_transponder}')

                        # Draw aircraft callsign
                        if aircraft_callsign:
                            graphics.DrawText(matrix, font, 0, (index + 1) * 7, green, f'Sign:  {aircraft_callsign}')
                        else:
                            graphics.DrawText(matrix, font, 0, (index + 1) * 7, green, f'Sign: unknown')

                        if aircraft_lat and aircraft_long:
                            geodesic_dict = Geodesic.WGS84.Inverse(float(device_lat), float(device_long), aircraft_lat,
                                                                   aircraft_long)
                            azimuth = geodesic_dict['azi1']
                            distance_meters = geodesic_dict['s12']
                            distance_miles = 0.000621371 * distance_meters
                            heading = float(azimuth)
                            logger.info(f'heading: {heading:.3f}')

                            # Correct for negative headings
                            if heading < 0:
                                heading = heading + 360
                                logger.info(f'corrected heading: {heading:.3f}')

                            cardinal_direction = get_direction_from_heading(heading)
                            logger.info(f'cardinal direction: {cardinal_direction}')

                            # adjust heading from display orientation
                            display_heading = 240.0
                            adjusted_heading = 360 - display_heading + heading
                            logger.info(f'adjusted heading: {adjusted_heading:.3f}°')
                            # correct for heading over 360°
                            if adjusted_heading > 360:
                                adjusted_heading = adjusted_heading - 360
                                logger.info(f'adjusted heading (corrected): {adjusted_heading:.3f}°')
                            arrow_direction = get_direction_from_heading(adjusted_heading)

                            # Draw cardinal direction and arrow
                            graphics.DrawText(matrix, font2, 0, ((index + 2) * 7) + 1, green, cardinal_direction)
                            graphics.DrawText(matrix, font2, 0, ((index + 3) * 7) + 2, green, cardinal_arrows_map[
                                arrow_direction])
                            graphics.DrawText(matrix, font2, 22, ((index + 3) * 7) + 2, green, f'{distance_miles:.2f} mi')
                        else:
                            graphics.DrawText(matrix, font2, 0, ((index + 2) * 7) + 1, green, '?')
                            graphics.DrawText(matrix, font2, 0, ((index + 3) * 7) + 2, green, '?')
                        if aircraft_ground_speed:
                            graphics.DrawText(matrix, font2, 22, ((index + 2) * 7) + 1, green, f'{aircraft_ground_speed} kts')
                        time.sleep(10)
                else:
                    graphics.DrawText(matrix, font, 0, 7, green, "No aircraft")
                    graphics.DrawText(matrix, font, 0, 14, green, "found")

            time.sleep(60)
    except KeyboardInterrupt:
        sys.exit(0)