以下のような、csv に似たデータをシリアル通信で受け取る。
b'@-114,6,6 304 451 10097 505\r\n'
末尾は CRLF。頭に@がついて、7つのフィールド間のデミリタはカンマまたはスペース。
環境
- Python 3.9.2
- RaspberryPi OS Raspbian GNU/Linux 11 \n \l
作戦
バイト列としてシリアル通信で受信する。
以下のことに注意して処理する。
- readline() で一行受け取るので \r\n がくっついてくる
- 数値は符号付き整数
- 4,5,6番目のフィールドは小数点以下1位の固定小数で "257" と送られてきたのは "25.7"を意味している
- 7つのフィールド間のデミリタは1バイトのカンマまたは1バイトのスペース
- 頭に @ がついていることをチェック
- 通信エラーで異常文字列が来ること前提
正規表現を使う
↓↓↓↓↓↓↓ あなたの記事の内容
───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
result=( re.match( rb'^@([-0-9]*)' # 行頭の@に続く符号付整数
+b',([-0-9]*)' # ,で区切られた符号付き整数
+b',([-0-9]*)' # ,で区切られた符号付き整数
+b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き整数
+b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き固定小数
+b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き固定小数
+b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き整数
, onerecord))
パースした値を取り出す
↓↓↓↓↓↓↓ あなたの記事の内容
───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
result.group(n)
としてn番目のフィールドがバイト文字列で取り出せる。
取り出した値の変換
これを utf8 文字列にするには
↓↓↓↓↓↓↓ あなたの記事の内容
───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
result.group(n).decode('utf-8')
整数型にするには
↓↓↓↓↓↓↓ あなたの記事の内容
───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
int(result.group(n))
固定小数フィールドを float にするには
↓↓↓↓↓↓↓ あなたの記事の内容
───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
float(result.group(n))/10
サンプルプログラム
↓↓↓↓↓↓↓ あなたの記事の内容
───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
import serial
import pymysql.cursors
import time
import re
ser = serial.Serial("/dev/ttyS0",115200)
while 1:
oneline = ser.readline()
result=( re.match( rb'^@([-0-9]*)'
+b',([-0-9]*)'
+b'[ ,]([-0-9]*)'
+b'[ ,]([-0-9]*)'
+b'[ ,]([-0-9]*)'
+b'[ ,]([-0-9]*)'
+b'[ ,]([-0-9]*)'
, onerecord))
rssi=int(result.group(1))
node1=int(result.group(2))
node2=int(result.group(3))
temp=float(result.group(4))/10
humi=float(result.group(5))/10
pressure=float(result.group(6))/10
co2=int(result.group(7))
db=pymysql.connect(host="localhost", user="hogehoge", password="hagehage" , cursorclass=pymysql.cursors.DictCursor)
cursor=db.cursor()
cursor.execute("USE hokan")
db.commit()
sql=('insert into hokandata (recvtime,node,rssi,recv,temp,humi,pressure,co2) values (now(),"%s","%s","%s","%s","%s","%s","%s");')
cursor.execute(sql,(node1,rssi,result2,temp,humi,pressure,co2))
db.commit()
db.close()
temp=float(result.group(4))/10
temp=float(result.group(4).decode('utf-8'))/10