当前位置: 首页 > news >正文

3.28 haas506 2.0开发教程-example-蓝牙多设备扫描(仅支持M320,HD1)

haas506 2.0开发教程-example-蓝牙多设备扫描

  • 案例说明
  • 蓝牙信息克隆
      • 1.手机蓝牙改名
      • 信息克隆
  • 代码
  • 测试

案例说明

  • 开发板扫描蓝牙设备,获取并打印蓝牙设备mac地址。mac地址每个设备不同,且不能更改。
  • 本案例仅适用于M320开发板和HD1-RTU。
  • 案例使用手机与iBeacon作为从机。开发板根据设备名称进行连接,要同时扫描到2个设备,手机的蓝牙名称需要改成与iBeacon相同的名称。

蓝牙信息克隆

使用手机克隆iBeacon的名字信息。

1.手机蓝牙改名

手机下载nRF connect蓝牙调试工具。
在这里插入图片描述
iBeacon设备名称,将手机蓝牙改成一样的名字
在这里插入图片描述

选择ADVERTISER后点击图标改名
在这里插入图片描述

在这里插入图片描述

信息克隆

点开iBeacon设备后,点击CLONE
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这样就得到了2个同名的设备。

代码

  • 注意更改代码中的设备名称

main.py

# This example finds and connects to a BLE temperature sensor (e.g. the one in ble_temperature.py).# from ast import While
# from logging.config import valid_ident
# from multiprocessing.sharedctypes import Value
# from sys import platlibdir
# from this import d
# from traceback import print_list
import bluetooth
from bluetooth import BLE
from bluetooth import UUID
# import random
import ustruct#import time
import micropythonimport utime as time#from ble_advertising import decode_services, decode_namefrom micropython import const_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
_IRQ_GATTS_READ_REQUEST = const(4)
_IRQ_SCAN_RESULT = const(5)
_IRQ_SCAN_DONE = const(6)
_IRQ_PERIPHERAL_CONNECT = const(7)
_IRQ_PERIPHERAL_DISCONNECT = const(8)
_IRQ_GATTC_SERVICE_RESULT = const(9)
_IRQ_GATTC_SERVICE_DONE = const(10)
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(11)
_IRQ_GATTC_CHARACTERISTIC_DONE = const(12)
_IRQ_GATTC_DESCRIPTOR_RESULT = const(13)
_IRQ_GATTC_DESCRIPTOR_DONE = const(14)
_IRQ_GATTC_READ_RESULT = const(15)
_IRQ_GATTC_READ_DONE = const(16)
_IRQ_GATTC_WRITE_DONE = const(17)
_IRQ_GATTC_NOTIFY = const(18)
_IRQ_GATTC_INDICATE = const(19)_ADV_IND = const(0x00)
_ADV_DIRECT_IND = const(0x01)  
_ADV_SCAN_IND = const(0x02)
_ADV_NONCONN_IND = const(0x03)# org.bluetooth.service.environmental_sensing
# _ENV_SENSE_UUID = bluetooth.UUID(0x30AF)
_ENV_SENSE_UUID = bluetooth.UUID("FDA50693-A4E2-4FB1-AFCF-C6EB07647825")
# org.bluetooth.characteristic.temperature
_TEMP_UUID = bluetooth.UUID(0x2A6E)
_TEMP_CHAR = (_TEMP_UUID,bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
)
_ENV_SENSE_SERVICE = (_ENV_SENSE_UUID,(_TEMP_CHAR,),
)_UART_SERVICE_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA77")
_UART_RX_CHAR_UUID = bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA77")
_UART_TX_CHAR_UUID = bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA77")_MY_SERVICE_UUID = bluetooth.UUID(0x181A)# org.bluetooth.characteristic.gap.appearance.xml
_ADV_APPEARANCE_GENERIC_THERMOMETER = const(768)_ADV_TYPE_FLAGS = const(0x01)
_ADV_TYPE_NAME = const(0x09)
_ADV_TYPE_UUID16_COMPLETE = const(0x3)
_ADV_TYPE_UUID32_COMPLETE = const(0x5)
_ADV_TYPE_UUID128_COMPLETE = const(0x7)
_ADV_TYPE_UUID16_MORE = const(0x2)
_ADV_TYPE_UUID32_MORE = const(0x4)
_ADV_TYPE_UUID128_MORE = const(0x6)
_ADV_TYPE_APPEARANCE = const(0x19)def decode_field(payload, adv_type):i = 0result = []while i + 1 < len(payload):if payload[i + 1] == adv_type:result.append(payload[i + 2 : i + payload[i] + 1])i += 1 + payload[i]return resultdef decode_name(payload):n = decode_field(payload, _ADV_TYPE_NAME)# print("n:",n)return str(n[0], "utf-8") if n else ""def decode_mac(addr):if isinstance(addr, memoryview):addr = bytes(addr)assert isinstance(addr,bytes) and len(addr) == 6,ValueError("mac address value error")return ":".join(['%02X' % byte for byte in addr])def print_hex(bytes):l = [hex(int(i)) for i in bytes]return " ".join(l)def decode_services(payload):services = []for u in decode_field(payload, _ADV_TYPE_UUID16_COMPLETE):services.append(bluetooth.UUID(ustruct.unpack("<h", u)[0]))for u in decode_field(payload, _ADV_TYPE_UUID32_COMPLETE):services.append(bluetooth.UUID(ustruct.unpack("<d", u)[0]))for u in decode_field(payload, _ADV_TYPE_UUID128_COMPLETE):services.append(bluetooth.UUID(u))return servicesclass BLETemperatureCentral:def __init__(self, ble):self._ble = bleself._ble.gap_scan_name('X622080084')self._ble.gattc_set_uuids(0xFFF2, 0xFFF1)self._ble.active(True)time.sleep_ms(3000)self._ble.irq(self._irq)self._reset()def _reset(self):# Cached name and address from a successful scan.self._name = Noneself._addr_type = Noneself._addr = Noneself._mac = Noneself._adv_data = None# Cached value (if we have one)self._value = None# Callbacks for completion of various operations.# These reset back to None after being invoked.self._scan_callback = Noneself._conn_callback = Noneself._read_callback = None# Persistent callback for when new data is notified from the device.self._notify_callback = None# Connected device.self._conn_handle = Noneself._start_handle = Noneself._end_handle = Noneself._value_handle = Nonedef _irq(self, event, data):if event == _IRQ_SCAN_RESULT:# time.sleep_ms(1)addr_type, addr, adv_type, rssi, adv_data = data# print("ble data:{}".format(adv_data))# if adv_type in (_ADV_IND, _ADV_DIRECT_IND) and _ENV_SENSE_UUID in decode_services(adv_data):if adv_type in (_ADV_IND, _ADV_DIRECT_IND):# if adv_type in (_ADV_DIRECT_IND): #ibeacon的类型# Found a potential device, remember it and stop scanning.self._addr_type = addr_typeself._addr = bytes(addr)  # Note: addr buffer is owned by caller so need to copy it.self._name = decode_name(adv_data)self._mac = decode_mac(addr)# self._adv_data = bytes(#     adv_data# )  # Note: addr buffer is owned by caller so need to copy it.# self._name = decode_name(adv_data) or "?"# print("ble addr:",self._mac )# print("ble data:",data )elif event == _IRQ_SCAN_DONE:#time.sleep_ms(1000)self._ble.gap_scan(None)#print("##### scan done #####")val = 1if self._scan_callback:if self._addr:# Found a device during the scan (and the scan was explicitly stopped).self._scan_callback(self._addr_type, self._addr, self._name)self._scan_callback = Noneelse:# Scan timed out.self._scan_callback(None, None, None)elif event == _IRQ_PERIPHERAL_CONNECT:print('connect')elif event == _IRQ_PERIPHERAL_DISCONNECT:print('disconnect')elif event == _IRQ_GATTC_SERVICE_RESULT:# Connected device returned a service.conn_handle, start_handle, end_handle, uuid = dataif conn_handle == self._conn_handle and uuid == _ENV_SENSE_UUID:self._start_handle, self._end_handle = start_handle, end_handleelif event == _IRQ_GATTC_SERVICE_DONE:# Service query complete.if self._start_handle and self._end_handle:self._ble.gattc_discover_characteristics(self._conn_handle, self._start_handle, self._end_handle)else:print("Failed to find environmental sensing service.")elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:# Connected device returned a characteristic.conn_handle, def_handle, value_handle, properties, uuid = dataif conn_handle == self._conn_handle and uuid == _TEMP_UUID:self._value_handle = value_handleelif event == _IRQ_GATTC_CHARACTERISTIC_DONE:# Characteristic query complete.if self._value_handle:# We've finished connecting and discovering device, fire the connect callback.if self._conn_callback:self._conn_callback()else:print("Failed to find temperature characteristic.")elif event == _IRQ_GATTC_READ_RESULT:buffer = self._ble.gattc_read(0,0)print('recv data:',buffer)elif event == _IRQ_GATTC_READ_DONE:# Read completed (no-op).conn_handle, value_handle, status = dataelif event == _IRQ_GATTC_NOTIFY:# The ble_temperature.py demo periodically notifies its value.conn_handle, value_handle, notify_data = dataif conn_handle == self._conn_handle and value_handle == self._value_handle:self._update_value(notify_data)if self._notify_callback:self._notify_callback(self._value)elif event == _IRQ_GATTC_WRITE_DONE:conn_handle, value_handle, status = dataprint("TX complete")# Returns true if we've successfully connected and discovered characteristics.def is_connected(self):return self._conn_handle is not None and self._value_handle is not None# Find a device advertising the environmental sensor service.def scan(self, callback=None):self._addr_type = Noneself._addr = Noneself._scan_callback = callbackself._ble.gap_scan(4000, 6000, 6000)# Connect to the specified device (otherwise use cached address from a scan).def connect(self, addr_type=None, addr=None, callback=None):self._addr_type = addr_type or self._addr_typeself._addr = addr or self._addrself._conn_callback = callbackif self._addr_type is None or self._addr is None:return Falseself._ble.gap_connect(self._addr_type, self._addr)return True# Disconnect from current device.def disconnect(self):if not self._conn_handle:returnself._ble.gap_disconnect(self._conn_handle)self._reset()# Issues an (asynchronous) read, will invoke callback with data.def read(self, callback):if not self.is_connected():returnself._read_callback = callbackself._ble.gattc_read(self._conn_handle, self._value_handle)# Sets a callback to be invoked when the device notifies us.def on_notify(self, callback):self._notify_callback = callbackdef _update_value(self, data):# Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius.self._value = ustruct.unpack("<h", data)[0] / 100return self._valuedef value(self):return self._valuedef write(self, v, response=False):# if not self.is_connected():#     returnself._ble.gattc_write(0, 0, v, 1 if response else 0)print("data_send:", v)global v
def demo():time.sleep_ms(2000)ble = bluetooth.BLE()central = BLETemperatureCentral(ble)time.sleep_ms(2000)not_found = Falsedef on_scan(addr_type, addr, name):if addr_type is not None:print("Found sensor addr_type:", addr_type)print("Found sensor addr:", print_hex(addr))print("Found sensor name:", name)global vv = 1else:nonlocal not_foundnot_found = Trueprint("No sensor found.")while True :central.scan(callback=on_scan)time.sleep_ms(2000)# if v == 1:#     central.connect()# while True:#     ble.gattc_notify(1, 1)#     # central.write('123', False)#     time.sleep_ms(1000)if __name__ == "__main__":demo()

测试

Haas506可以搜索到2个不同mac地址的设备,并将mac地址打印。
在这里插入图片描述

相关文章:

3.28 haas506 2.0开发教程-example-蓝牙多设备扫描(仅支持M320,HD1)

haas506 2.0开发教程-example-蓝牙多设备扫描案例说明蓝牙信息克隆1.手机蓝牙改名信息克隆代码测试案例说明 开发板扫描蓝牙设备&#xff0c;获取并打印蓝牙设备mac地址。mac地址每个设备不同&#xff0c;且不能更改。本案例仅适用于M320开发板和HD1-RTU。案例使用手机与iBeac…...

C语言经典编程题100例(41~60)

目录41、习题4-4 特殊a串数列求和42、习题4-6 水仙花数43、习题4-7 最大公约数和最小公倍数44、习题7-5 找鞍点45、练习5-1 求m到n之和46、练习5-2 找两个数中最大者47、练习5-3 数字金字塔48、习题5-1 符号函数49、习题5-2 使用函数求奇数和50、习题5-3 使用函数计算两点间的距…...

git日常使用命令

实习这段时间使用了很多git指令来提交代码&#xff0c;简单记录一下日常使用的指令&#xff1a; 提交代码通常顺序&#xff1a; 1.git status 查看本地修改项 2.git add . 提交全部文件 &#xff08;这个 .是全部文件&#xff09;到暂存区 3.git commit -m ‘本次提交的说明’…...

ES6对象展开运算符浅拷贝or深拷贝

ES6中提出的对象展开运算符“…”就是用来展开元素的。有了它就不用代码循环遍历了&#xff0c;偷懒专用。 1. 合并数组 展开原有数组中的所有元素&#xff0c;可以合并成一个新的数组。 var a[1,2,3]; var b[4,5,6]; var c[...a,...b]; console.log(c) // 输出&#xff1a;…...

leaflet 上传包含shp的zip文件,在map上解析显示图形(059)

第059个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中本地上传包含shp的zip文件,利用shapefile读取shp数据,并在地图上显示图形。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果 文章目录 示例效果加载shapefile.js方式安装引用jszip(…...

CAN总线详细介绍

1.1 CAN是什么&#xff1f; CAN 最终成为国际标准 &#xff08; ISO11898(高速应用)和 ISO11519&#xff08;低速应用&#xff09;&#xff09;&#xff0c;是国际上应用最广泛的现场总线之一。 1.2 CAN总线特点 多主方式: 可以多主方式工作&#xff0c;网络上任意一个节点…...

python如何完成对 Excel文件的解密后读取?

通常为了防止重要的Excel文件数据内容的泄露&#xff0c;需要对文件整体进行加密与解密的操作。 对于文件的加解密过程&#xff0c;python也有很多非标准库来帮助我们完成操作&#xff0c;这里主要说明如何完成对Excel文件的解密与读取操作。 这里我们使用到的是msoffcrypto-…...

微服务实战--高级篇:RabbitMQ高级

服务异步通信-高级篇 消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1.消息可靠性 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一步都可能导致消息丢失&#xff0c;常见的丢失原因包括&#xff1a; 发送…...

autoCAD2022 - 设置新的原点

文章目录autoCAD2022 - 设置新的原点概述笔记UCS原点设置功能的菜单位置ENDautoCAD2022 - 设置新的原点 概述 上次整板子的dxf时, 原来的原点不合适, 想调整一下. 当时整完了, 没记录. 这次用的时候, 又找半天… 设置新原点的功能, 不在顶部菜单中, 而是在视图右上角的UCS图标…...

spring boot 配置 mybatis-plus多数据源

简介Mybatis-puls 多数据源的使用&#xff0c;采用的是官方提供的dynamic-datasource-spring-boot-starter包的 DS 注解&#xff0c;具体可以参考官网&#xff1a;https://gitee.com/baomidou/dynamic-datasource-spring-boot-starterpom.xml文件引入如下依赖主要引入dynamic-d…...

独立产品灵感周刊 DecoHack #047 - 安卓手机上最有用的APP

本周刊记录有趣好玩的独立产品设计开发相关内容&#xff0c;每周发布&#xff0c;往期内容同样精彩&#xff0c;感兴趣的伙伴可以点击订阅我的周刊。为保证每期都能收到&#xff0c;建议邮件订阅。欢迎通过 Twitter 私信推荐或投稿。&#x1f4bb; 产品推荐 1. Bouncer Tempor…...

【面试题】JavaScript中递归的理解

大厂面试题分享 面试题库后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★地址&#xff1a;前端面试题库递归 RecursionTo iterate is human, to recurse, divine. 理解迭代&#xff0c;神理解递归。本文会以 JavaScript为主、有部分 Rust 举例说明。…...

PyTorch学习笔记

PyTorch学习笔记&#xff08;一&#xff09;&#xff1a;PyTorch环境安装 往期学习资料推荐&#xff1a; 1.Pytorch实战笔记_GoAI的博客-CSDN博客 2.Pytorch入门教程_GoAI的博客-CSDN博客 安装参考&#xff1a; 1.视频教程&#xff1a;3分钟深度学习【环境搭建】CUDA Anacon…...

SpringBoot2知识点记录

SpringBoot2知识点记录1.SpringBoot2基础入门1.1 环境要求1.1.1 maven设置1.2 第一个程序 HelloWorld1.2.1 创建maven工程1.2.2 引入依赖1.2.3 创建主程序1.2.4 编写业务1.2.5 测试1.2.6 简化配置1.2.7 简化部署1.3 自动装配1.3.1 SpringBoot特点1.3.1.1 依赖管理1.3.1.2 自动装…...

Mysql

1 Sql编写 count(*) //是对行数目进行计数 count(column_name) //是对列中不为空的行进行计数 SELECT COUNT( DISTINCT id ) FROM tablename; //计算表中id不同的记录有多少条 SELECT DISTINCT id, type FROM tablename; //返回表中id与type同时不同的结果 X.1 连表子查询 sel…...

Q4营收利润增长背后估值持续偏低,全球支付巨头PayPal前景如何?

作为国际版的“支付宝”&#xff0c;全球第三方支付巨头PayPal的业务横跨欧美市场&#xff0c;覆盖了全球200多个国家和地区。同时&#xff0c;PayPal也是首家进军中国支付市场的外资机构&#xff0c;实力强劲。然而&#xff0c;近两年&#xff0c;PayPal的市值一路从3000亿跌至…...

【自然语言处理】【大模型】BLOOM:一个176B参数且可开放获取的多语言模型

BLOOM&#xff1a;一个176B参数且可开放获取的多语言模型《BLOOM: A 176B-Parameter Open-Access Multilingual Language Model》论文地址&#xff1a;https://arxiv.org/pdf/2211.05100.pdf 相关博客 【自然语言处理】【大模型】用于大型Transformer的8-bit矩阵乘法介绍 【自然…...

小红书穿搭博主推广费用是多少?

小红书作为一个种草属性非常强的平台&#xff0c;商业价值是有目共睹的。很多爱美的女性都会在小红书上被种草某个商品&#xff0c;所以很多服装品牌都会在小红书上布局推广。 穿搭作为小红书的顶梁柱类目&#xff0c;刷小红书就能总是看到好看的穿搭博主分享美美的衣服&#…...

网络安全-PHPstudy环境搭建

网络安全-PHPstudy环境搭建 网络搭建我是专家&#xff0c;安全我懂的不多&#xff0c;所以可能很基础。。因为我自己都不懂&#xff0c;都是跟着课程学的 PHPstudy 这个东东是一个在windwos下可以快速部署的web开发环境&#xff0c;安装了就能用&#xff0c;也支持iis和ngin…...

operator的两种用法(重载和隐式类型转换)

文章目录重载隐式类型转换构造函数的隐式类型转换补充operator算子的隐式类型转换重载 略 隐式类型转换 构造函数的隐式类型转换 利用operator进行的隐式类型转换成为operator算子的隐式类型转换&#xff0c;讲这个之前先了解构造函数的隐式类型转换&#xff0c;请看以下代…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...