Closing App and all other Python Threads

19 views
Skip to first unread message

Yuri Klebanov

unread,
Mar 10, 2018, 5:30:14 AM3/10/18
to Kivy users support
Hi All,
I'm really new to kivy and still not getting all it's logic completely,
I'm trying to create an app (on Linux) that reads multiple sensor (an eyetracker and a lux sensor) data via the serial+zmq
And presents it on a live graph.

I'm not sure I'm doing it the right way but my script runs a thread which reads the sensor data outside the Kivy App and then using a global variable to pass the data to Kivy and display it in the graph.

I basically have 2 questions:
  1. I this the right way to do it?
    My guess it's not and all threads should be running within Kivy, but i didn't manage to Implement my get_data thread inside Kivy app.
  2. If I leave the app as is (as it works well at the moment), what would be the right way to make the "QUIT" button to close the get_data thread and not only the Kivy app / window.


Here is my code:



Enter code here...import kivy
kivy
.require('1.10.0')
from kivy.app import App
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.garden.graph import MeshLinePlot
from kivy.clock import Clock
from kivy.logger import Logger
from threading import Thread
import zmq, msgpack
from zmq_tools import Msg_Receiver
import csv
import serial

recLength
= 500
pupil_values
= []


def get_data():

   
print("Getting Data")

   
global pupil_values

   
while True:

        pupilSize
= 0
        luxValue
= 0

       
try:
           
if (ser != 0 and ser.inWaiting() > 0):
                line
= ser.readline().strip()
                luxValue
= float(line)
               
print('Lux Value: %s'%(luxValue))

           
# receiver is a Msg_Receiver, that returns a topic/payload tuple on recv()
            topic
, payload = receiver.recv()
            pupilSize
= payload.get('diameter_3d')
           
print('Pupil Size: %s'%(pupilSize))

       
except:
           
print("oops cant parse data")


        val
= pupilSize
       
if len(pupil_values) >= recLength:
            pupil_values
= []

        pupil_values
.append(val)


class Logic(BoxLayout):

   
def __init__(self,):
       
super(Logic, self).__init__()
       
self.plot_pupil = MeshLinePlot(color=[1, 0, 0, 1])
       
self.data_graph.xmax = recLength

   
def start(self):
       
self.data_graph.add_plot(self.plot_pupil)
       
Clock.schedule_interval(self.get_value, 0.001)

   
def stop(self):
       
Clock.unschedule(self.get_value)

   
def quit_app(self):
       
App.get_running_app().stop()
       
Window.close()

   
def get_value(self, dt):
       
self.plot_pupil.points = [(i, j) for i, j in enumerate(pupil_values)]


class RecorderApp(App):
   
   
def on_stop(self):
       
Logger.critical('Closing App')


   
def build(self):
       
return Logic()

if __name__ == "__main__":

   
#Connect to Lux Sensor on Adafruit feather runing CircuitPython via
   
try:
        ser
= serial.Serial('/dev/ttyACM1', 115200, timeout=2)
       
print("connected to: " + ser.name)
   
except:
       
print("No Serial Found")
        ser
= 0    


   
# Setup ZMQ to get pupil data
    ctx
= zmq.Context()
    ip
= 'localhost' #If you talk to a different machine use its IP.
    port
= 50020 #The port defaults to 50020 but can be set in the GUI of Pupil Capture.

   
# open Pupil Remote socket
    requester
= ctx.socket(zmq.REQ)
    requester
.connect('tcp://%s:%s'%(ip,port))
    requester
.send_string('SUB_PORT')
    ipc_sub_port
= requester.recv_string()

   
# setup message receiver
    sub_url
= 'tcp://%s:%s'%(ip,ipc_sub_port)
    receiver
= Msg_Receiver(ctx, sub_url, topics=('pupil.0',))

   
# init data reading thread    
    get_data_thread
= Thread(target = get_data)
    get_data_thread
.daemon = True
    get_data_thread
.start()
   
   
# run app interface
   
RecorderApp().run()


Many thanks in advance!



Reply all
Reply to author
Forward
0 new messages