Por que o / dev / rfcomm0 está dando problemas ao PySerial?

1

Estou conectando minha caixa do Ubuntu a uma configuração de leitura sem fio via Bluetooth. Eu escrevi um script Python para enviar a informação serial através de / dev / rfcomm0. O script se conecta bem e funciona por alguns minutos, mas o Python começa a usar 100% da CPU e as mensagens param de fluir.

Eu posso abrir o rfcomm0 em um terminal serial e me comunicar através dele manualmente. Quando abro através de um terminal, parece funcionar indefinidamente. Além disso, posso trocar o receptor Bluetooth por um cabo USB e mudar a porta para / dev / ttyUSB0 e não obtenho nenhum problema com o tempo.

Parece que estou fazendo algo errado com o rfcomm0 ou PySerial não lida bem com isso.

Aqui está o script:

import psutil
import serial
import string
import time

sampleTime = 1
numSamples = 5
lastTemp = 0

TEMP_CHAR = 't'
USAGE_CHAR = 'u'
SENSOR_NAME = 'TC0D'

gauges = serial.Serial()
gauges.port = '/dev/rfcomm0'
gauges.baudrate = 9600
gauges.parity = 'N'
gauges.writeTimeout = 0
gauges.open()

print("Connected to " + gauges.portstr)

filename = '/sys/bus/platform/devices/applesmc.768/temp2_input'

def parseSensorsOutputLinux(output):
    return int(round(float(output) / 1000))

while(1):
    usage = psutil.cpu_percent(interval=sampleTime)
    gauges.write(USAGE_CHAR)
    gauges.write(chr(int(usage))) #write the first byte
    #print("Wrote usage: " + str(int(usage)))

    sensorFile = open(filename)
    temp = parseSensorsOutputLinux(sensorFile.read())
    gauges.write(TEMP_CHAR)
    gauges.write(chr(temp))
    #print("Wrote temp: " + str(temp))

Alguma opinião?

Obrigado.

EDIT: Aqui está o código revisado, usando Python-BlueZ em vez de PySerial:

import psutil
import serial
import string
import time
import bluetooth

sampleTime = 1
numSamples = 5
lastTemp = 0

TEMP_CHAR = 't'
USAGE_CHAR = 'u'
SENSOR_NAME = 'TC0D'

#gauges = serial.Serial()
#gauges.port = '/dev/rfcomm0'
#gauges.baudrate = 9600
#gauges.parity = 'N'
#gauges.writeTimeout = 0
#gauges.open()

gaugeSocket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
gaugeSocket.connect(('00:06:66:42:22:96', 1))

filename = '/sys/bus/platform/devices/applesmc.768/temp2_input'

def parseSensorsOutputLinux(output):
    return int(round(float(output) / 1000))

while(1):
    usage = psutil.cpu_percent(interval=sampleTime)
    #gauges.write(USAGE_CHAR)
    gaugeSocket.send(USAGE_CHAR)
    #gauges.write(chr(int(usage))) #write the first byte
    gaugeSocket.send(chr(int(usage)))
    #print("Wrote usage: " + str(int(usage)))

    sensorFile = open(filename)
    temp = parseSensorsOutputLinux(sensorFile.read())
    #gauges.write(TEMP_CHAR)
    gaugeSocket.send(TEMP_CHAR)
    #gauges.write(chr(temp))
    gaugeSocket.send(chr(temp))
    #print("Wrote temp: " + str(temp))

Parece que o Ubuntu deve estar fechando / dev / rfcomm0 depois de um certo tempo ou meu receptor Bluetooth está bagunçando as coisas. Mesmo quando surge o erro BluetoothE, a luz "conectada" no receptor permanece acesa, e não é até que eu ligue e volte para o receptor que eu possa reconectar.

Não sei como abordar esse problema. É estranho que a conexão funcione bem por alguns minutos (aparentemente um período de tempo aleatório) e, em seguida, confunda.

Caso isso ajude, o receptor Bluetooth é um BlueSmirf Silver da Sparkfun. Preciso estar tentando manter a conexão do lado do receptor ou algo assim?

    
por Travis G. 19.03.2012 / 04:57

1 resposta

2

Acontece que o buffer Bluetooth no PC estava transbordando porque eu nunca estava chamando recv () no script Python.

O acessório Bluetooth estava enviando caracteres para o PC, que o script ignorou e que inevitavelmente levou a um estouro de buffer. Esse estouro aparentemente faz com que o canal rfcomm bloqueie até que o buffer seja lido.

Aqui está o script de trabalho, para referência futura:

import psutil
import serial
import string
import time
import bluetooth

sampleTime = 1
numSamples = 5
lastTemp = 0

TEMP_CHAR = 't'
USAGE_CHAR = 'u'
SENSOR_NAME = 'TC0D'

filename = '/sys/bus/platform/devices/applesmc.768/temp2_input'


def parseSensorsOutputLinux(output):
    return int(round(float(output) / 1000))

def connect():
    while(True):    
        try:
            gaugeSocket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
            gaugeSocket.connect(('00:06:66:42:22:96', 1))
            break;
        except bluetooth.btcommon.BluetoothError as error:
            gaugeSocket.close()
            print "Could not connect: ", error, "; Retrying in 10s..."
            time.sleep(10)
    return gaugeSocket;

gaugeSocket = connect()
while(True):
    usage = psutil.cpu_percent(interval=sampleTime)
    sensorFile = open(filename)
    temp = parseSensorsOutputLinux(sensorFile.read())
    try:
        gaugeSocket.send(USAGE_CHAR)
        gaugeSocket.send(chr(int(usage)))
        #print("Wrote usage: " + str(int(usage)))

        gaugeSocket.send(TEMP_CHAR)
        gaugeSocket.send(chr(temp))
        print gaugeSocket.recv(1024)
        #print("Wrote temp: " + str(temp))
    except bluetooth.btcommon.BluetoothError as error:
        print "Caught BluetoothError: ", error
        time.sleep(5)
        gaugeSocket = connect()
        pass

gaugeSocket.close()

A mudança da chave está na adição da linha

gaugeSocket.recv(1024)

que limpa o buffer das mensagens "OK" enviadas de volta do dispositivo remoto.

    
por Travis G. 22.03.2012 / 05:58