UART-controlled 7-segment display with Python GUI

This project uses this 7-segment display. It is based on Arduino. Display shows current gasoline price in Tampere, Finland. Gasoline price is middle price for 95E10 and it’s downloaded from www.polttoaine.net with Python code.

GUI (graphical user interface) is made with wxPython and wxFormBuilder. Update interval and serial port is user selectable.

Python code:

#! /usr/bin/python
# -*- coding: utf-8 -*-

import wx, wx.xrc
import threading
import serial
import urllib
from lxml.html import fromstring

class MyApp(wx.App):

    delay = 0
    runTime = 0

    def OnInit(self):
        self.res = wx.xrc.XmlResource("gui.xrc")
        self.frame = self.res.LoadFrame(None, "MyFrame1")
        self.text1 = wx.xrc.XRCCTRL(self.frame, "m_textCtrl1")
        self.text2 = wx.xrc.XRCCTRL(self.frame, "m_textCtrl2")
        self.slider1 = wx.xrc.XRCCTRL(self.frame, "m_slider1")
        self.frame.Bind(wx.EVT_BUTTON, self.on_evt_button, id=wx.xrc.XRCID("m_button1"))

        self.SetTopWindow(self.frame)
        self.frame.Show()
        
        self.delay = self.slider1.GetValue()*60
        self.updatePrice()
        self.thread = threading.Thread(target=self.delayTimer)
        self.thread.daemon = True
        self.thread.start()
        return True

    def on_evt_button(self, evt):
        self.delay = self.slider1.GetValue()*60

    def updatePrice(self):
        fopen = urllib.urlopen("https://www.polttoaine.net/Tampere")
        content = fopen.read()
        doc = fromstring(content)
        price = doc.find_class("Hinnat")[3].text_content()
        self.text1.SetValue(price)

        try:
            with serial.Serial(self.text2.GetValue(), 9600, timeout=1) as ser:
                time.sleep(5)
                ser.write(price+"\r")
        except IOError:
            print("Port cannot be opened")

    def delayTimer(self):
        self.runTime += 1
        if self.runTime >= self.delay:
            self.runTime = 0
            self.updatePrice()
        self.thread = threading.Timer(1,self.delayTimer)
        self.thread.daemon = True
        self.thread.start()       

app = MyApp(False)
app.MainLoop()

XRC layout file generated from wxFormBuilder:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<resource xmlns="http://www.wxwindows.org/wxxrc" version="2.3.0.1">
  <object class="wxFrame" name="MyFrame1">
    <style>wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL</style>
    <size>380,165</size>
    <title>95E10 Gasoline Price Display</title>
    <centered>1</centered>
    <aui_managed>0</aui_managed>
    <object class="wxFlexGridSizer">
      <rows>3</rows>
      <cols>3</cols>
      <minsize>380,165</minsize>
      <vgap>0</vgap>
      <hgap>0</hgap>
      <growablecols></growablecols>
      <growablerows></growablerows>
      <object class="sizeritem">
        <option>0</option>
        <flag>wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL</flag>
        <border>5</border>
        <object class="wxStaticText" name="m_staticText1">
          <label>Current output</label>
          <wrap>-1</wrap>
        </object>
      </object>
      <object class="sizeritem">
        <option>0</option>
        <flag>wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL</flag>
        <border>5</border>
        <object class="wxTextCtrl" name="m_textCtrl1">
          <style>wxTE_READONLY</style>
          <value></value>
        </object>
      </object>
      <object class="spacer">
        <option>1</option>
        <flag>wxEXPAND</flag>
        <border>5</border>
        <size>0,0</size>
      </object>
      <object class="sizeritem">
        <option>0</option>
        <flag>wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL</flag>
        <border>5</border>
        <object class="wxStaticText" name="m_staticText2">
          <label>Update interval (minutes)</label>
          <wrap>-1</wrap>
        </object>
      </object>
      <object class="sizeritem">
        <option>0</option>
        <flag>wxALL|wxALIGN_BOTTOM|wxALIGN_CENTER_HORIZONTAL</flag>
        <border>5</border>
        <object class="wxSlider" name="m_slider1">
          <style>wxSL_HORIZONTAL|wxSL_LABELS</style>
          <size>100,-1</size>
          <value>30</value>
          <min>10</min>
          <max>120</max>
        </object>
      </object>
      <object class="sizeritem">
        <option>0</option>
        <flag>wxALL|wxALIGN_CENTER_VERTICAL</flag>
        <border>5</border>
        <object class="wxButton" name="m_button1">
          <label>Save settings</label>
          <default>0</default>
        </object>
      </object>
      <object class="sizeritem">
        <option>0</option>
        <flag>wxALL|wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL</flag>
        <border>5</border>
        <object class="wxStaticText" name="m_staticText3">
          <label>Serial port</label>
          <wrap>-1</wrap>
        </object>
      </object>
      <object class="sizeritem">
        <option>0</option>
        <flag>wxALL|wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL</flag>
        <border>5</border>
        <object class="wxTextCtrl" name="m_textCtrl2">
          <value>/dev/ttyUSB0</value>
        </object>
      </object>
    </object>
  </object>
</resource>