树莓派4 连接BLE设备,同步信息到阿里云IOT

本文通过树莓派的蓝牙连接nrf52的蓝牙BLE外设,将蓝牙采集的信息同步到阿里云,实现一个类似外设+网关+服务器的物联网平台
1 启用阿里云物联网服务
登陆 https://iot.console.aliyun.com/product/createProduct ,
创建产品,当前我选择一个心率设备,用于采集心率信息
在这里插入图片描述
定义设备属性字段名称,标识符,类型和范围,此处的标识符和类型需要记录Heartbeat int32
在这里插入图片描述
管理添加设备
这里选择刚才创建的产品心率计
在这里插入图片描述
通过查看设备信息获取三元码,阿里的iot设备都是通过三元码作为产品ID,记录这3个信息
在这里插入图片描述
到此,阿里云的一个简单的iot平台搭建完成,下面开始pi4 访问服务器的操作

2 启用配置树莓派4,连接到服务器,本文使用MQTT方式联机到IOT
代码里面有2部分组成
1 树莓派通过bluepy连接一个nrf52的心电设备,改心电设备1秒上传一次心率值
2 树莓接受到BLE的心率值上传到服务器端

# -*- coding: utf-8 -*-

from bluepy.btle import UUID, Peripheral, ADDR_TYPE_RANDOM, DefaultDelegate
import paho.mqtt.client as mqtt

from bluepy.btle import Scanner, DefaultDelegate
import binascii
import time
import hashlib
import hmac




def write_uint16(data, value, index):
    """ Write 16bit value into data string at index and return new string """
    data = data.decode('utf-8')  # This line is added to make sure both Python 2 and 3 works
    return '{}{:02x}{:02x}{}'.format(
                data[:index*4],
                value & 0xFF, value >> 8,
                data[index*4 + 4:])

def write_uint8(data, value, index):
    """ Write 8bit value into data string at index and return new string """
    data = data.decode('utf-8')  # This line is added to make sure both Python 2 and 3 works
    return '{}{:02x}{}'.format(
                data[:index*2],
                value,
                data[index*2 + 2:])

# Please see # Ref https://nordicsemiconductor.github.io/Nordic-Thingy52-FW/documentation
# for more information on the UUIDs of the Services and Characteristics that are being used
def Nordic_UUID(val):
    """ Adds base UUID and inserts value to return Nordic UUID """
    return UUID("EF68%04X-9B35-4933-9B10-52FFA9740042" % val)

# Definition of all UUID used by Thingy
CCCD_UUID = 0x2902


HEARTRATE_SERVICE_UUID = 0x180D
HEARTRATE_CHAR_UUID = 0x2A37

#此处的3个信息就是前面在阿里云的三元组
options = {
    'productKey':'a1loWX9eaVi',
    'deviceName':'heartbeat1',
    'deviceSecret':'bDIOOsJHWWyh40ZckZiDqbWxIBAA3geN',
    'regionId':'cn-shanghai'
}




HOST = options['productKey'] + '.iot-as-mqtt.'+options['regionId']+'.aliyuncs.com'
PORT = 1883
PUB_TOPIC = "/sys/" + options['productKey'] + "/" + options['deviceName'] + "/thing/event/property/post";

#此处是蓝牙相关的服务
class HeartRateService():
    """
    Environment service module. Instance the class and enable to get access to the Environment interface.
    """
    # serviceUUID =           Nordic_UUID(HEARTRATE_SERVICE_UUID)
    # heartrate_char_uuid = Nordic_UUID(HEARTRATE_CHAR_UUID)

    serviceUUID         = HEARTRATE_SERVICE_UUID
    heartrate_char_uuid = HEARTRATE_CHAR_UUID
    def __init__(self, periph):
        self.periph = periph
        self.heartrate_service = None
        self.heartrate_char = None
        self.heartrate_cccd = None
        self.config_char = None

    def enable(self):
        """ Enables the class by finding the service and its characteristics. """
        global e_heartrate_handle

        if self.heartrate_service is None:
            self.heartrate_service = self.periph.getServiceByUUID(self.serviceUUID)
        if self.heartrate_char is None:
            self.heartrate_char = self.heartrate_service.getCharacteristics(self.heartrate_char)[0]
            e_heartrate_handle = self.heartrate_char.getHandle()
            self.heartrate_cccd = self.heartrate_char.getDescriptors(forUUID=CCCD_UUID)[0]


    def set_heartrate_notification(self, state):
        if self.heartrate_cccd is not None:
            if state == True:
                self.heartrate_cccd.write(b"\x01\x00", True)
            else:
                self.heartrate_cccd.write(b"\x00\x00", True)


    def configure(self, heart_int=None):
        if heart_int is not None and self.config_char is not None:
            current_config = binascii.b2a_hex(self.config_char.read())
            new_config = write_uint16(current_config, heart_int, 0)
            self.config_char.write(binascii.a2b_hex(new_config), True)


    def disable(self):
        set_heartrate_notification(False)


class MyDelegate(DefaultDelegate):

    def handleNotification(self, hnd, data):
        # Debug print repr(data)
        if (hnd == e_heartrate_handle):
            heartheart = binascii.b2a_hex(data)
            print('Notification: heartheart received:  {}.{}'.format(
                self._str_to_int(heartheart[:-2]), int(heartheart[-2:], 16)))

            payload_json = {
                'id': int(time.time()),
                #这里的信息是阿里云上的
                'params': {
                    'Heartbeat': int(heartheart[-2:], 16),
                },
                'method': "thing.event.property.post"
            }
            print('send data to iot server: ' + str(payload_json))

            client.publish(PUB_TOPIC,payload=str(payload_json),qos=1)
        else:
            teptep = binascii.b2a_hex(data)
            print('Notification: UNKOWN: hnd {}, data {}'.format(hnd, teptep))

    def _str_to_int(self, s):
        """ Transform hex str into int. """
        i = int(s, 16)
        if i >= 2 ** 7:
            i -= 2 ** 8
        return i



class HeartRate(Peripheral):
    """
    Thingy:52 module. Instance the class and enable to get access to the Thingy:52 Sensors.
    The addr of your device has to be know, or can be found by using the hcitool command line
    tool, for example. Call "> sudo hcitool lescan" and your Thingy's address should show up.
    """
    def __init__(self, addr):
        Peripheral.__init__(self, addr)

        self.m_Heart = HeartRateService(self)
        # DFU Service not implemented


# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    # client.subscribe("the/topic")

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    print(msg.topic+" "+str(msg.payload))

def hmacsha1(key, msg):
    return hmac.new(key.encode(), msg.encode(), hashlib.sha1).hexdigest()

def getAliyunIoTClient():
    timestamp = str(int(time.time()))
    CLIENT_ID = "paho.py|securemode=3,signmethod=hmacsha1,timestamp="+timestamp+"|"
    CONTENT_STR_FORMAT = "clientIdpaho.pydeviceName"+options['deviceName']+"productKey"+options['productKey']+"timestamp"+timestamp
    # set username/password.
    USER_NAME = options['deviceName']+"&"+options['productKey']
    PWD = hmacsha1(options['deviceSecret'],CONTENT_STR_FORMAT)
    client = mqtt.Client(client_id=CLIENT_ID, clean_session=False)
    client.username_pw_set(USER_NAME, PWD)
    return client



class ScanDelegate(DefaultDelegate):
    def __init__(self):
        DefaultDelegate.__init__(self)

    def handleDiscovery(self, dev, isNewDev, isNewData):
        if isNewDev:
            print ("Discovered device %s" % (dev.addr))
        elif isNewData:
            print ("Received new data from %s" % (dev.addr))

if __name__ == '__main__':

    client = getAliyunIoTClient()
    client.on_connect = on_connect
    client.on_message = on_message

    client.connect(HOST, 1883, 300)
    client.loop_start()


    scanner = Scanner().withDelegate(ScanDelegate())
    devices = scanner.scan(5.0)
    device_msg = [0,0]
    found = 0

    for dev in devices:
        print ("Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi))
        for (adtype, desc, value) in dev.getScanData():
            print ("  %s = %s" % (desc, value))

        for (adtype, desc, value) in dev.getScanData():
            res = value.find("blehr_sensor")
            if res < 0:
                None
            else:
                found = 1
                device_msg[1] = dev.addrType
                device_msg[0] = dev.addr
                print("%s %s %s" % (device_msg[0], value, device_msg[1]))
                break
        if found:
            break

    if found:
        print('Connecting to ' + device_msg[0])
        heart = HeartRate(device_msg[0])
        print('Connected...')
        heart.setDelegate(MyDelegate())

        try:
            print('Enabling selected HeartRate...')
            heart.m_Heart.enable()
            heart.m_Heart.configure(heart_int=1000)
            heart.m_Heart.set_heartrate_notification(True)

            time.sleep(1.0)

            # counter=1
            while True:
                heart.waitForNotifications(0)

        finally:
            heart.disconnect()
            print('DisConnected...')

            # del heart

这里是代码执行的过程
每一秒树莓派接受到BLE心电的数据(这里模拟的是一个每秒递增1的数据),并上传到服务器
看下服务器的接收数据

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值