使用python解析arduino序列中的数据

2024-10-03 04:35:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图使用pySerial解析arduino中的数据,以便将每个值属性化为tKinter GUI应用程序使用的变量

为此,我尝试从arduino获取数据,并将每个解析的值属性化为float或complex(text+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',我只想要数值。请问最好的方法是什么

谢谢


Tags: valuenulltemparduinoecelifvoltageanalog
1条回答
网友
1楼 · 发布于 2024-10-03 04:35:19

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

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

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

如果字典中没有名为"key_name"的键,那么只需调用默认返回None.get("key_name")方法即可

以下是片段:

类和对象声明

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

相关问题 更多 >