为什么Pyserial readline输出未从触发事件更新Kivy标签?

问题描述 投票:0回答:1

我正在使用Pyserial从比例尺获得输出。因此,我决定将所有输出读取到Kivy Label,以使程序更易于使用。最初,最小的示例足够好,用户只需单击一个按钮即可以20个计数器间隔查看输出。但是现在有必要通过首先接收输出,然后触发一个辅助事件来自动化整个过程,该事件在更新Sqlite数据库之前将检查输出是否稳定。但是发生了一个问题:1]标签不会随着刻度输出的变化而更新。这源于serial.readline()方法,由于某种原因它也不会更新。我的一些Python代码:

import kivy

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import StringProperty, ObjectProperty,BooleanProperty,NumericProperty
from kivy.clock import Clock
from kivy.core.window import Window

import serial, re, time, string, random
import plyer

Builder.load_string("""
#:set cereal None
<CerealOutput>:
    Label:
        text: root.portname
        pos_hint: {'top': 0.79, 'right': 0.8}
        size_hint: [0.6, 0.19]
        color: (1,1,1,1)
    Label:
        id: milk
        text: root.scale_output if root.scale_output != "" else "Scale Output"
        pos_hint: {'top': 0.6, 'right': 0.8}
        size_hint: [0.6, 0.2]
        color: (1,1,1,1)
        canvas.before:
            Color:
                rgb: (0.43, 0.43, 0.43, 1)
            Rectangle:
                pos: self.pos
                size: self.size
    Button:
        text: "Exit"
        pos_hint: {'top': 0.2, 'right': 0.98}
        size_hint: [0.17, 0.18]
        on_release: root.weigh_tick.cancel() if root.weigh_tick != None else ""
    Button:
        text: "Get Serial"
        pos_hint: {'top': 0.3, 'right': 0.8}
        size_hint: [0.6, 0.2]
        on_press:
            cereal = root.ccereal
            root.GetCereal() if cereal == None or cereal.isOpen() == False else root.weight_ticker()
""")

class CerealOutput(FloatLayout):
    portname = StringProperty('')
    the = ObjectProperty(None)  # App object
    ccereal = ObjectProperty(None)
    mythread = ObjectProperty(None)
    bowl = ObjectProperty(None)
    go = BooleanProperty(True)
    weigh_tick = ObjectProperty(None)
    weigh_tme = NumericProperty()  # Weigh time numerical
    scale_output = StringProperty('')
    is_shift = BooleanProperty(False)
    def __init__(self, **kwargs):
        super(CerealOutput, self).__init__(**kwargs)
        self.the = App.get_running_app()
        self.bowl = self.ids.milk
    def GetCereal(self):
        ser = serial.Serial(port='/dev/ttyUSB0',baudrate=9600,bytesize=serial.EIGHTBITS)
        self.ccereal = ser
        if self.ccereal.isOpen():
            self.portname = self.ccereal.name
        else:
            self.ccereal.open()
        self.portname = self.ccereal.name
        self.weight_ticker()
    def GetOutput(self, cereal):
        if cereal.isOpen() and cereal != None:
            if self.weigh_tme > 0:
                try:
                    bb = cereal.readline()
                    t = ''.join(random.choice(string.ascii_letters) for x in range(5))
                    self.scale_output = re.sub('[GSTUkg,\s]', '', bb.decode('latin-1'))
                    #Q only gets text after each read is finished.  Why?
                    #S Threading; Interval read; Other
                    #UI imbed visible progress on each read
                    #Errors, Test if port exists, Unicode byte read error:  How to solve
                    print(self.scale_output, bb, t)
                    self.weigh_tick()
                    self.weigh_tme -= 1
                except serial.SerialException:
                    self.weigh_tme = 0
                    print("Port not open")
            else:
                self.weigh_tick.cancel()  # cancel event
                print("Finished")
        else:
            self.GetCereal()

    def weight_ticker(self):
        self.weigh_tme = 1000
        self.weigh_tick = Clock.create_trigger(lambda dt: self.GetOutput(self.ccereal), 1)
        self.weigh_tick()

class PorridgeApp(App):
    def build(self):
        return CerealOutput()
    def on_stop(self):
        if App.get_running_app().root.ccereal != None:
            App.get_running_app().root.ccereal.close()

    def on_pause(self):
        if App.get_running_app().root.ccereal != None:
            App.get_running_app().root.ccereal.close()
        pass

if __name__=='__main__':
    PorridgeApp().run()

我已经尝试将输出绑定到Label对象的文本。那并没有改变。

有人可以告诉我为什么readline方法没有随着刻度输出的变化而更新吗?

python python-3.x kivy pyserial kivy-language
1个回答
0
投票

因此,我决定将解决方案发布到更新的GetOutput函数中。解决方法是使用PySerial方法内置的serial.reset_input_buffer()重置输入缓冲区。从文档中:

刷新输入缓冲区,丢弃其所有内容。在版本3.0中更改:从flushInput()重命名

代码:

    def GetOutput(self):
        if self.ccereal.isOpen() and self.ccereal != None:
            if self.weigh_tme > 0:
                try:
                    self.stable = self.ccereal.readline().decode('latin-1')[:2]
                    self.scale_output = re.sub('[GSTUkg,\s]', '',self.ccereal.readline().decode('latin-1'))

                    self.ccereal.reset_input_buffer() #flush the input buffer
                    self.weigh_tme -= 1
                    self.weigh_tick()
                except serial.SerialException as e:
                    self.weigh_tme = 0
                    print("Port not open","Unicode errror")
                except TypeError as e:
                    self.ccereal.close()
                except UnicodeDecodeError as e:
                    print("Unicode error")
                else:
                    print(self.scale_output)

            else:
                #self.weigh_tick.cancel()  # cancel event
                self.weight_ticker()
                print("Finished")
        else:
            self.GetCereal()
© www.soinside.com 2019 - 2024. All rights reserved.