2012-04-19 12 views
7

मेरे पास एक धारावाहिक डिवाइस है जिसे मैं इनपुट पढ़ने की कोशिश कर रहा हूं। मैंने इसे एक स्ट्रिंग "आईडी \ आर" भेजा, और यह "आईडी एक्सएक्स \ आर" लौटाता है (जहां \ r एक ASCII कैरिज रिटर्न, हेक्स 0x0d है)।लाइन buffered धारावाहिक इनपुट

सीरियल.readline पर ईओएल विकल्प अब समर्थित नहीं है, इसलिए मैं धारावाहिक बंदरगाह से पढ़ने के लिए TextIOWrapper का उपयोग कर रहा हूं और एक समय में एक लाइन लौटाता हूं।

मेरी समस्या यह है कि जैसे ही यह कैरिज रिटर्न देखता है, मेरी स्ट्रिंग को वापस करने की बजाय, यह तब तक इंतजार कर रहा है जब मैंने धारावाहिक बंदरगाह खोला था। मैं इसे पूरी तरह से स्ट्रिंग वापस लौटना चाहूंगा जैसे ही यह पूरी लाइन पढ़ता है क्योंकि मेरे पास डिवाइस पर भेजने के लिए इनमें से सैकड़ों कमांड हो सकते हैं और मैं हर बार टाइमआउट का इंतजार नहीं करना चाहता हूं। अगर मैं 0 पर टाइमआउट सेट करता हूं, तो मुझे बिल्कुल आउटपुट नहीं मिलता है (संभवतः क्योंकि मेरी स्क्रिप्ट डिवाइस को कुछ भी आउटपुट करने का मौका देने से पहले प्रतीक्षा कर रही है), और यदि मैं टाइमआउट को किसी को भी सेट नहीं करता हूं, तो स्क्रिप्ट हमेशा के लिए ब्लॉक करता है।

import serial 
import io 
import time 

ser = serial.Serial("/dev/ttyUSB0", baudrate=9600, 
        bytesize=8, parity='N', stopbits=1, 
        xonxoff=0, rtscts=1, timeout=5) 

sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser), 
         newline=None) 


sio.write(unicode("ID\r")) 
sio.flush() 

print "reading..." 

x = sio.readline() 

print len(x) 
print x 

स्क्रिप्ट हमेशा समय यह कहता है 'समझ' जब ​​तक यह "आईडी XX" स्ट्रिंग है कि यह सीरियल पोर्ट से पढ़ा प्रिंट से 10 सेकंड लेता है:

यहाँ एक सरल परीक्षण स्क्रिप्ट है।

मुझे विश्वास है कि इस उपकरण गाड़ी वापसी outputting है कर रहा हूँ, जैसा कि मैंने strace का उपयोग किया है देखने के लिए कहता है:

select(4, [3], [], [], {5, 0})   = 1 (in [3], left {4, 991704}) 
read(3, "I", 8192)      = 1 
select(4, [3], [], [], {5, 0})   = 1 (in [3], left {4, 999267}) 
read(3, "D", 8191)      = 1 
select(4, [3], [], [], {5, 0})   = 1 (in [3], left {4, 999420}) 
read(3, " ", 8190)      = 1 
select(4, [3], [], [], {5, 0})   = 1 (in [3], left {4, 999321}) 
read(3, "X", 8189)      = 1 
select(4, [3], [], [], {5, 0})   = 1 (in [3], left {4, 999355}) 
read(3, "X", 8188)      = 1 
select(4, [3], [], [], {5, 0})   = 1 (in [3], left {4, 999171}) 
read(3, "\r", 8187)      = 1 
select(4, [3], [], [], {5, 0})   = 0 (Timeout) 
select(4, [3], [], [], {5, 0})   = 0 (Timeout) 

आप 2 का चयन करें() समय समाप्ति है कि 10 सेकंड की देरी दे देख सकते हैं , लेकिन आप कैरिज रिटर्न को पढ़ते हुए भी स्पष्ट रूप से देख सकते हैं। मैंने 'none' और '' (जिसे स्वचालित रूप से \ r, \ n, और \ r \ n), और '\ r' को अनुमति देने के लिए न्यूलाइन पैरामीटर सेट करने का प्रयास किया है, लेकिन प्रत्येक बार एक ही परिणाम के साथ।

मैंने BufferedRWPair() में buffer_size को बफरिंग इनपुट से रखने के लिए '1' पर कॉल करने का भी प्रयास किया है, लेकिन इससे कोई फर्क नहीं पड़ता।

कोई विचार क्या मैं गलत कर रहा हूं?

यदि मैं यह काम नहीं कर पा रहा हूं, तो मेरा अगला कदम एक समय में एक चरित्र को पढ़ने के लिए serial.read() का उपयोग करना होगा और अपनी लाइन बफरिंग करना होगा, लेकिन मैं इसे "सही करने की कोशिश करना चाहता था "पहले textiowrapper के साथ रास्ता।

+0

सेट करने के अलावा, यह भी करना था, क्या आप निश्चित रूप से प्रिंट स्टेटमेंट आउटपुट बफरिंग ट्रिगर नहीं कर रहा है? इसे चलाने की कोशिश करें -u –

उत्तर

0

वास्तव में इसे देखने के बिना इसे डीबग करना मुश्किल होगा। लेकिन देखें कि क्या आप मेरे टीटी मॉड्यूल का उपयोग कर सकते हैं।

http://code.google.com/p/pycopia/source/browse/trunk/aid/pycopia/tty.py

वहाँ में serialport वस्तु का प्रयास करें। मैंने सीरियल उपकरणों के साथ बातचीत करने के लिए सफलतापूर्वक इसका उपयोग किया है, जहां "आपके अन्य धारावाहिक मॉड्यूल" में आपके द्वारा वर्णित की गई कई समस्याएं थीं। यह आपको यह भी बता सकता है कि आपके पास फीफो में डेटा है या नहीं।

अब मुझे यह कैसे चल रहा है।

0

कोड कीथ के लिए धन्यवाद, लेकिन मैं इस कोड को कुछ पोर्टेबल रखना चाहता था, इसलिए मैं डिफ़ॉल्ट "धारावाहिक" पैकेज के साथ रहना चाहता हूं।

प्लस, चूंकि मैं अभी भी पाइथन सीख रहा हूं, मैं सीखने की कोशिश करना चाहता था कि जिस तरह से इसका उद्देश्य टेक्स्टआईओपरपर का उपयोग करना है।

मैंने serial.readline() काम करने की कोशिश छोड़ दी, इसलिए अब मैं एक समय में एक चरित्र को पढ़ने और कैरिज रिटर्न टर्मिनेटर की तलाश करने के लिए एक साधारण "रीडलाइन" फ़ंक्शन का उपयोग करूंगा। हालांकि अगर मैं अधिक धारावाहिक quirkyness में भाग लेता हूं, तो मैं आपके कोड का उपयोग कर फिर से देख सकता हूं।

धन्यवाद!

def readLine(ser): 
    str = "" 
    while 1: 
     ch = ser.read() 
     if(ch == '\r' or ch == ''): 
      break 
     str += ch 

    #"print "str = " + str 

    return str 
6

आज इस पर कुछ घंटों बर्बाद हो गए। यह पता चला कि io.BufferedReader पढ़ता है जब तक कि यह अपना बफर भर नहीं जाता है और फिर बफर को io.TextIOWrapper पर भेजता है। डिफ़ॉल्ट बफर आकार 8192 है, इसलिए आपके डिवाइस के आधार पर इसमें कुछ समय लग सकता है।

सही उदाहरण कोड होना चाहिए:

# buffer size is 1 byte, so directly passed to TextIOWrapper 
sio = io.TextIOWrapper(io.BufferedRWPair(ser, ser, 1), encoding='ascii') 
print sio.readline()[:-1] 
2

चेतावनी: मैं किसी Mac अजगर 3.4 का उपयोग कर रहा तो अपने लाभ, भिन्न हो सकते हैं, हालांकि मैं अजगर 2.7, अजगर 2.7 में स्थिति (बैकपोर्टेड TextIOWrapper साथ विश्वास करते हैं और अन्य ओएस) अनिवार्य रूप से वही होंगे जैसा कि मैंने नीचे वर्णित किया है।

मुख्य मुद्दा यह है कि io.TextIOWrapper स्वयं एक बफरिंग तंत्र का उपयोग करता है, जिसे अनियंत्रित _CHUNK_SIZE विशेषता द्वारा नियंत्रित किया जाता है। यह बहुत अप्रिय है। तो आपके पास दो विकल्प हैं:

  1. आपके द्वारा प्रयास किए जाने पर एक टाइमआउट का उपयोग करें। यह pyserial प्रलेखन पृष्ठ पर readline के प्रलेखन में संकेत दिया गया है। हालांकि, यदि आप एक बड़े मूल्य का उपयोग करते हैं (जैसा आपने किया था), जब TextIOWrapper के बफर को भरने के लिए पर्याप्त डेटा नहीं है, तो आपका कोड टाइमआउट तक पहुंचने तक अवरुद्ध हो जाएगा। यह वही है जो आप अनिवार्य रूप से अनुभव कर रहे हैं (मुझे टाइमआउट मूल्य को दोगुना करने का इंतजार क्यों नहीं किया गया है, लेकिन मुझे लगता है कि इसे TextIOWrapper के कार्यान्वयन को देखकर हल किया जा सकता है और अंततः आपके प्रश्न के लिए अप्रासंगिक है)।
  2. दूसरी पसंद 1. _CHUNK_SIZE बदलने के लिए अपनी स्थिति में, बस सही होने के बाद आप Sio प्रारंभ अपने कोड में लाइन

    sio._CHUNK_SIZE = 1 
    

    जोड़ने है। इसका शायद अप्रिय प्रभाव है कि TextIowrapper के भीतर बफरिंग बंद कर दी जाएगी (यह इनपुट के वृद्धिशील डिकोडिंग के लिए उपयोग की जाती है)। यदि प्रदर्शन कोई मुद्दा नहीं है, तो यह सबसे आसान समाधान है। यदि प्रदर्शन एक मुद्दा है, तो आप _CHUNK_SIZE को स्पर्श नहीं करते समय टाइमआउट का कम मान सेट कर सकते हैं। हालांकि, इस मामले में रीडलाइन() से खाली स्ट्रिंग प्राप्त करने के लिए तैयार रहें (यदि डिवाइस आपको खाली रेखा भेजता है, जो '\ n' के माध्यम से आ जाएगा, तो इसे खाली स्ट्रिंग से अलग किया जा सकता है जब आपको मिलेगा आवंटित समय से पढ़ा जाता है)।

अपने कोड के साथ एक और समस्या है: जब Sio हटा दिया जाएगा, सेवा की समाप्ति विधि दो बार बुलाया जाएगा, जो एक अपवाद में परिणाम होगा जब अपने कार्यक्रम के बारे में समाप्त करने के लिए किया जाएगा (कम से कम यह है अगर मैं अपने कंप्यूटर पर अपना कोड आज़माता हूं तो क्या होगा)। आपको सीरियल के उदाहरणों के लिए (ऐसा लगता है) बनाना चाहिए और उन लोगों को पास करें जिन्हें BufferedRWPair में पास किया गया है।

मैंने टेक्स्टआईओप्रैपर पर आधारित एक रैपर क्लास भी बनाया है, जो कि अगर दिलचस्पी हो तो मैं पोस्ट भी कर सकता हूं, बस मैं कुछ अतिरिक्त कोड के साथ प्रतिक्रिया प्रतिक्रिया नहीं देना चाहता था, जो सख्ती से बोलने की ज़रूरत नहीं है।

पीएस: इस बीच, मैंने उबंटू पर कोड के साथ प्रयोग किया है। मेरे मैक पर, मुझे उबंटू पर io.BufferedRWPair के बफर आकार को सेट करने की आवश्यकता नहीं दिखाई दे रही थी, मुझे _CHUNK_SIZE से 1.

संबंधित मुद्दे