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>