首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程在Telepot中保存串行连接(Python)

线程在Telepot中保存串行连接(Python)
EN

Stack Overflow用户
提问于 2018-11-08 14:25:43
回答 1查看 335关注 0票数 0

我有一个串行设备(Arduino)定期输出日志数据,这些日志数据应该写在日志文件中。此外,该设备通过串行接收自发的命令。我通过电报将命令发送给Raspberry,由Telepot处理并发送给arduino,后者在一个单独的线程中运行。

我怎样才能确保这两个过程相互配合?

我完全是多线程的初学者。以下是“我的代码”的简写版本:

代码语言:javascript
复制
import time
import datetime
import telepot
import os
import serial
from time import sleep

ser = None
bot = None


def log(data):
    with open('logfile', 'w') as f:
        file.write("Timestamp" + data)

#The handle Function is called by the telepot thread, 
#whenever a message is received from Telegram
def handle(msg):
        chat_id = msg['chat']['id']
        command = msg['text']
        print( 'Command Received: %s' % command)
        if command = '/start':
            bot.sendMessage(chat_id, 'welcome')
        elif command == 'close_door':
            #This serial write could possibly happen while a 
            #ser.readline() is executed, which would crash my program. 
            ser.write("Close Door")
        elif command == 'LOG':
            #Here i should make sure that nothing 
            #is waiting from the Arduino
            #so that the next two Serial lines are the Arduinos 
            #respoonce to the "LOG" command.
            #and that hanlde is the only 
            #function talking to the Serial port now.
            ser.write("LOG")
            response = ser.readline()
            response += "\0000000A" + ser.readline()
            #The Arduinos response is now saved as one string 
            #and sent to the User.
            bot.sendMessage(chat_id, response)

        print("Command Processed.")


bot = telepot.Bot('BOT TOKEN')
bot.message_loop(handle)


ser = serial.Serial("Arduino Serial Port", 9600)
print( 'I am listening ...')

while True:
    #anything to make it not run at full speed (Recommendations welcome)
    #The log updates are only once an hour. 
    sleep(10)

    #here i need to make sure it does not collide with the other thread.
    while ser.in_waiting > 0:
        data = ser.readline()
        log(data)

这段代码不是我的实际代码,但它应该代表我想要做的事情。

我的最后一招是将串行代码放入线程循环函数中,但这将要求我更改丑陋的libary。

我在Asincio中查找了一些关于队列的内容,以及锁定函数。不过,我真的不明白该如何应用它。另外,我也不使用异步传送器。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-08 16:00:54

在阅读了更多关于锁定和线程的内容之后,我在这个问题中提供的链接的帮助下找到了一个答案:Locking a method in Python?经常被推荐使用队列,但是我不知道如何使用。

我的解决方案(代码可能有错误,但原理有效)

代码语言:javascript
复制
import time
import random
import datetime
import telepot
import os
import serial
from time import sleep
#we need to import the Lock from threading
from threading import Lock

ser = None
bot = None



def log(data):
    with open('logfile', 'w') as f:
        file.write("Timestamp" + data)


#create a lock:
ser_lock = Lock()


#The handle Function is called by the telepot thread, 
#whenever a message is received from Telegram
def handle(msg):
    #let the handle function use the same lock:
    global ser_lock

    chat_id = msg['chat']['id']
    command = msg['text']
    print( 'Command Received: %s' % command)
    if command == '/start':
        bot.sendMessage(chat_id, 'welcome')
    elif command == 'close_door':
        #This serial write could possibly happen while a 
        #ser.readline() is executed, which would crash my program.
        with ser_lock:
            ser.write("Close Door")
    elif command == 'LOG':
        #Here i should make sure that nothing 
        #is waiting from the Arduino
        #so that the next two Serial lines are the Arduinos 
        #respoonce to the "LOG" command.
        #and that hanlde is the only 
        #function talking to the Serial port now.

        #the lock will only be open when no other thread is using the port.
        #This thread will wait untill it's open.
        with ser_lock:
            while ser.in_waiting > 0:
                data = ser.readline()
                log(data)
                #Should there be any old data, just write it to a file
            #now i can safely execute serial writes and reads.
            ser.write("LOG")
            response = ser.readline()
            response += "\0000000A" + ser.readline()
        #The Arduinos response is now saved as one string 
        #and sent to the User.
        bot.sendMessage(chat_id, response)

    print("Command Processed.")


bot = telepot.Bot('BOT TOKEN')
bot.message_loop(handle)


ser = serial.Serial("Arduino Serial Port", 9600)
print( 'I am listening ...')

while True:
    #anything to make it not run at full speed (Recommendations welcome)
    #The log updates are only once a 
    sleep(10)

    #here i need to make sure it does not collide with the other thread.
    with ser_lock:
        while ser.in_waiting > 0:
            data = ser.readline()
            log(data)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53209733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档