繁体   English   中英

为什么 Pyserial readline output 没有从 Triggerred 事件更新 Kivy Label?

[英]Why is Pyserial readline output not updating Kivy Label from Triggerred event?

我正在使用 Pyserial 从规模上得到 output。 所以我决定阅读所有 output 到 Kivy Label 以使程序更加用户友好。 起初,最小的例子已经足够好了,用户只需单击一个按钮,就可以在 20 个计数器间隔内查看 output。 但是现在有必要通过首先接收 Output 来自动化整个过程,然后在更新 Sqlite db 之前触发检查稳定的 Output 的辅助事件。 但是出现了一个问题:

1] Label 不会随着刻度 output 的变化而更新。 这源于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()

我尝试将 output 绑定到 Label object 的文本。 这并没有什么不同。

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

所以我决定用解决方案发布我更新的GetOutput function。
解决方案是使用PySerial内置的 serial.reset_input_buffer 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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM