【问题标题】:Parse data from arduino serial using python使用 python 解析来自 arduino 串行的数据
【发布时间】:2021-03-29 19:58:13
【问题描述】:

我正在尝试使用 pySerial 解析来自 arduino 的数据,以便将每个值归因于 tKinter GUI 应用程序的变量使用。

为此,我试图从 arduino 获取数据并将每个解析的值归因于浮点或复杂(文本 + num)变量。为此,我的第一个测试是对每种数据类型使用 if 条件,但我不知道它是否经过调整,我的代码这样的代码不起作用。

# Get value from the data serial arduino braud 9600
ser = serial.Serial('/dev/cu.usbmodem14201', 9600, timeout=3, writeTimeout=0)
data = ser.read_all()

Analog value=0.0
Voltage=0 # int
temp=0.0
EC=0.0
TemperatureB=0.0
HumidityB=0.0
pHvalue=0.0
extractorstatement="NULL"
lightstatement="NULL"
intractorstatement="NULL"
FANstatement="NULL"
date="NULL" # as sting

def DataReaderThread():
    while True:
        currentLineRead = ser.readline()
        print(currentLineRead)
        currentLineReadName=reading.split(":",0)
        currentLineReadValue=reading.split(":",1)
        if currentLineReadName="b\'Analog value":
            analogValue=currentLineReadValue
        elif currentLineReadName="b\'Voltage":
            VoltageEcSensor=currentLineReadValue
        elif currentLineReadName="b\'temp":
            tempWaterSensor=currentLineReadValue
        elif currentLineReadName="b\'EC":
            if currentLineReadValue="No solution!\r\n\'":
                EcSensorValue=0.0
            else:
                EcSensorValue=currentLineReadValue
        elif currentLineReadName="b\'TemperatureB":
            TemperatureB=currentLineReadValue
        elif currentLineReadName="b\'HumidityB":
            HumidityB=currentLineReadValue
        elif currentLineReadName="b\'pHvalue":
            pHvalue=currentLineReadValue
        elif currentLineReadName="b\'extractorstatement":
            extractorStatement=currentLineReadValue
        elif currentLineReadName="b\'lightstatement":
            ligthStatement=currentLineReadValue
        elif currentLineReadName="b\'intractorstatement":
            intractorStatement=currentLineReadValue
        else currentLineReadName="b'FANstatement":
            fanStatement=currentLineReadValue
        return(analogValue, VoltageEcSensor, tempWaterSensor, EcSensorValue, TemperatureB, HumidityB, pHvalue, extractorStatement, ligthStatement, intractorStatement, fanStatement)

这里有来自 arduino 的输出,调用 'currentLineRead'(多行的视觉:

b'
b'
b'Analog value:30\r\n'
b'Voltage:146\r\n'
b'temp:24.25\r\n'
b'EC:No solution!\r\n'
b'TemperatureB:23.60\r\n'
b'HumidityB:35.70\r\n'
b'pHvalue:14.68\r\n'
b'extractorstatement:1\r\n'
b'lightstatement:0\r\n'
b'intractorstatement:0\r\n'
b'FANstatement:10:0:0 1/1/0 Day_of_week:1\r\n'
b'
b'
b'Analog value:30\r\n'
b'Voltage:146\r\n'
b'temp:24.25\r\n'
b'EC:No solution!\r\n'
b'TemperatureB:23.60\r\n'
b'HumidityB:35.70\r\n'
b'pHvalue:14.68\r\n'
b'extractorstatement:1\r\n'
b'lightstatement:0\r\n'
b'intractorstatement:0\r\n'
b'FANstatement:10:0:0 1/1/0 Day_of_week:1\r\n

我想将每个值归因于上面设置的变量。例如:b'TemperatureB:23.60\r\n',我只想要数值。请问最好的方法是什么?

谢谢!

【问题讨论】:

  • 请从intro tour 重复on topichow to ask。 “告诉我如何解决这个编码问题”不是堆栈溢出问题。我们希望您做出诚实的尝试,然后然后就您的算法或技术提出一个具体的问题。 Stack Overflow 并不打算取代现有的文档和教程。这是使用字符串函数从输入中提取所需信息的问题。查找如何在两个文本标签之间查找文本。
  • “我想将每个值都归入变量”到底是什么意思?什么变量?
  • 你可以在reading上调用.strip()来删除尾随的换行符,然后使用.split(":",1)获取键/值对。
  • @Prune 抱歉,我已经更正了我的帖子。
  • @acw1668 感谢您的回复

标签: python tkinter arduino pyserial


【解决方案1】:

您实际上可以使用 json 包和一些我发现 here 的片段来“放松”语法,不需要在键周围加上“”引号,(因为 ArduinoJson 发送具有该标准化的字符串以在传输过程中节省一些字节)

将您的 json 行反序列化为 python 字典对象,可能是最好的方法。 它允许您:

  • 通过名称轻松获取键的值
  • 测试密钥是否存在

所有这一切只需调用 .get("key_name") 方法,如果您的字典中没有名称为 "key_name" 的键,则默认返回 None

这里是sn-p:

类和对象声明

import re
import json
from parsec import (
    sepBy,
    regex,
    string,
    generate,
    many
)

whitespace = regex(r'\s*', re.MULTILINE)

lexeme = lambda p: p << whitespace

lbrace = lexeme(string('{'))
rbrace = lexeme(string('}'))
lbrack = lexeme(string('['))
rbrack = lexeme(string(']'))
colon = lexeme(string(':'))
comma = lexeme(string(','))
true = lexeme(string('true')).result(True)
false = lexeme(string('false')).result(False)
null = lexeme(string('null')).result(None)
quote = string('"') | string("'")

def number():
    return lexeme(
        regex(r'-?(0|[1-9][0-9]*)([.][0-9]+)?([eE][+-]?[0-9]+)?')
    ).parsecmap(float)


def charseq():
    def string_part():
        return regex(r'[^"\'\\]+')

    def string_esc():
        return string('\\') >> (
            string('\\')
            | string('/')
            | string('b').result('\b')
            | string('f').result('\f')
            | string('n').result('\n')
            | string('r').result('\r')
            | string('t').result('\t')
            | regex(r'u[0-9a-fA-F]{4}').parsecmap(lambda s: chr(int(s[1:], 16)))
            | quote
        )
    return string_part() | string_esc()

class StopGenerator(StopIteration):
    def __init__(self, value):
        self.value = value

@lexeme
@generate
def quoted():
    yield quote
    body = yield many(charseq())
    yield quote
    raise StopGenerator(''.join(body))

@generate
def array():
    yield lbrack
    elements = yield sepBy(value, comma)
    yield rbrack
    raise StopGenerator(elements)


@generate
def object_pair():
    key = yield regex(r'[a-zA-Z][a-zA-Z0-9]*') | quoted
    yield colon
    val = yield value
    raise StopGenerator((key, val))


@generate
def json_object():
    yield lbrace
    pairs = yield sepBy(object_pair, comma)
    yield rbrace
    raise StopGenerator(dict(pairs))
    
value = quoted | number() | json_object | array | true | false | null
relaxed_json = whitespace >> json_object

这是轻松使用它的方法:

input_byte = b'{test:157}' # Placeholder for a line you recieved as bytes 
input_dict = relaxed_json.parse(input_byte.decode()) #decode to a string
# then parse it with json package to get a dictionnary

print(input_dict) # here is it's content printed
print(type(input_dict)) # it is a dictionnary
print(input_dict.get("test",None)) # You can get the value of a key...
print(input_dict.get("toast",None)) # and test if it exists with one same method
if input_dict.get("toast",None) is not None: #if it exists you can use it
    print("Toast key has value :",input_dict.get("toast"))
else : #if it doesn't exist in your dict, in that case .get() methods returns None, and you can do something else
    print("No key named toast here")

输出:

{'test': 157.0}
<class 'dict'>
157.0
None
No key named toast here

【讨论】:

  • 非常感谢您的回复。我已经以其他形式解析了来自 arduino 输出的数据以便能够使用它。但是你的方式似乎和我一样有用。我会试试的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多