通过蓝牙读取攀藤G5传感器的代码
攀藤G5传感器通过串口访问,通过USB2TTY线连接即可
最简单的代码
#!/usr/bin/python
import serial
import time
import struct
port = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3)
while True:
chs = port.read(32)
frame = struct.unpack(">HHHHHHHHHHHHHHHH",chs)
print("US PM1.0 %d PM2.5 %d PM10 %d"%(frame[2],frame[3],frame[4]))
print("CN PM1.0 %d PM2.5 %d PM10 %d"%(frame[5],frame[6],frame[7]))
print("---------------------------------")
为了通过远程访问,需要把攀藤G5传感器和HC05蓝牙串口进行连接。同时把传感器的使能端和HC05的使能端进行连接,这样只有进行蓝牙连接的时候才启动传感器,避免持续工作从而有效延长使用寿命,并可以降低功耗。
然后在树莓派上接了一个USB蓝牙适配器,用于跟HC05进行通讯。 当然,手机也可以直接跟HC05通讯。
下面是树莓派通过蓝牙适配器连接HC05的脚本,98:D3:31:xx:xx:xx是HC05的地址,使用cron定时执行pm25-statsd.py
蓝牙配对,只需手动执行一次
$ bluetooth-agent 1234 98:D3:31:xx:xx:xx
or
$ sudo bluetoothctl
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# scan on
[bluetooth]# pair 98:D3:31:xx:xx:xx
[bluetooth]# exit
下面这行,添加到/etc/rc.local
rfcomm bind /dev/rfcomm0 98:D3:31:xx:xx:xx 1
数据读取后发送到Statsd服务器,用于记录。同时增加了容错处理,并且会跳过前面一段数据,以等传感器数据平稳(因蓝牙连接后才会启动传感器)。
pm25-statsd.py
import serial
import time
import struct
from socket import *
while True:
port = serial.Serial("/dev/rfcomm0", baudrate=9600, timeout=10)
chs = port.read(32)
frame = struct.unpack(">HHHHHHHHHHHHHHHH",chs)
if frame[0] != 0x424d:
port.close()
time.sleep(1)
continue
skip = 60
while skip > 0:
chs = port.read(32)
skip -= 1
port.close()
frame = struct.unpack(">HHHHHHHHHHHHHHHH",chs)
print(time.ctime())
print("CN PM1.0 %d PM2.5 %d PM10 %d"%(frame[5],frame[6],frame[7]))
print("----------------------------------------------------")
s = socket(AF_INET, SOCK_DGRAM)
s.sendto("home.pm25.indoor:"+str(frame[6])+"|g", ("statsd-server", 8125))
s.sendto("home.pm10.indoor:"+str(frame[7])+"|g", ("statsd-server", 8125))
break
Android手机连接HC05,需要先配对,然后通过下面的代码连接并创建串口服务即可
BluetoothSocket s;
protected void connect(){
//BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
//BluetoothAdapter adapter = manager.getAdapter();
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = adapter.getRemoteDevice("98:D3:31:xx:xx:xx");
try {
//s = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Method m = device.getClass().getMethod("createRfcommSocket",new Class[]{int.class});
s =(BluetoothSocket) m.invoke(device,1);
if(s == null)
throw new IOException();
new AsyncTask<BluetoothSocket, Integer, Boolean>(
) {
@Override
protected Boolean doInBackground(BluetoothSocket... s) {
try {
s[0].connect();
InputStream input = s[0].getInputStream();
if(input == null){
return false;
}
DataInputStream reader = new DataInputStream(input);
while (true){
if(reader.readShort() != 0x424d)
continue;
if(reader.readShort() != 28)
throw new RuntimeException("data error");
//skip us data
reader.skipBytes(6);
//skip pm1.0
reader.skipBytes(2);
int pm25 = (int)reader.readShort();
int pm10 = (int)reader.readShort();
publishProgress(pm25, pm10);
//skip rest data
reader.skipBytes(16);
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
protected void onProgressUpdate(Integer... progress) {
updatePm25(progress[0], progress[1]); //换成你的代码!!!
}
@Override
protected void onPostExecute(Boolean result){
if(!result)
Toast.makeText(getApplicationContext(), "Connect device fail!", Toast.LENGTH_LONG).show();
}
}.execute(s);
} catch (IOException e) {
Toast.makeText(this, "read data from device fail!", Toast.LENGTH_LONG).show();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
今年的空气还不错!