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

uni-app 框架 调用蓝牙,获取 iBeacon 定位信标的数据,实现室内定位场景

背景:最近需要对接了一个 叫 iBeacon 定位信标 硬件设备,这个设备主要的作用是,在信号不好的地方,或者室内实现定位,准确的找到某个东西。就比如 地下停车场,商城里,我们想知道这个停车场的某个位置,就可以利用这个设备 来找到我们要去的地方。
这个设备大概就是长下面的样子,我们通过手机软件调用蓝牙接受这种设备广播出来的数据从而断定我们在什么位置。
在这里插入图片描述
这也是第一次 和蓝牙打交道,记录一下怎么通过uni-app框架 来获取蓝牙返回的数据。
看完官方文档后,本来以为很简单呢,调用蓝牙的方法 然后返回对应的数据即可,但是在实际开发中还是遇到很多坑的。
在这里插入图片描述
对于蓝牙
一种就是我们平时普通用的蓝牙,就比如手机,笔记本电脑带的蓝牙,然后我们可以搜索到这些蓝牙。
还有就是 低功耗蓝牙是一种优化后的蓝牙技术,专为低功耗、低数据传输量的应用设计,适用于物联网设备和健康监测设备。
Beacon信标
基于BLE广播的功能的协议。蓝牙Beacon并不是蓝牙技术联盟所指定的标准,因此也被称为“虚拟标准”,是由大型供货商或企业集团为首,针对广泛的Beacon应用所正式提出的蓝牙应用规范,比如苹果公司的iBeacon协议,谷歌公司的Eddystone协议。是基于 BLE 的一种应用,主要用于位置广播和物品追踪,不涉及设备间直接的数据交换。
Beacon信标作用
Beacon常用于室内场景营销和定位功能,例如商城、博物馆、学校等。
营销:用于广告推送,比如商场内,当用户走进商场时打开商城APP,即可看到实时的商城活动等。
定位:通过RSSI(信号强度)大小进行距离远近的定位。

我主要的需求就是 使用 Beacon信标 来实现自己的需求,所以对于uni-app 调用 蓝牙的分享 就简单的说一下,因为也是第一次调用蓝牙没有思路,就把关于蓝牙的方法 都调用了一下,看看自己需要什么。最后测试结果,自己只需要调用 uni-app框架 提供的 Beacon信标 的方法即可。但是既然自己已经都按照文档都调用了一遍,那就都分享一下把。
结果:
对于我的需求 我主要是想从蓝牙中获取到下面的几个参数,但是有一个参数 一直不知道怎么获取,所以研究了好久。把蓝牙的所有方法都尝试了一下。因为我们的这个设备 到我开发的手里后, 也没有使用文档,只告诉了需要获取下面的几个参数 所以一切只能摸索
在这里插入图片描述
uuid iBeacon 设备广播的 uuid
major iBeacon 设备的主 id
minor iBeacon 设备的次 id
proximity 表示设备距离的枚举值
accuracy iBeacon 设备的距离
rssi 表示设备的信号强度

就是这个 uuid 不知道从哪里获取,折腾了一天。
通过搜索 有人说 设备厂家 一般会告诉,有的说设备上会写,但是我拿到的这个设备 都没有,
还有一种就是 这个搜索到这个设备 后,可以打印看到。
为什么非要用这个参数把,是因为 下面的这个方法 uuid 是必填的 如果没有uuid 就获取不到 major 、minor 等参数

uni.startBeaconDiscovery(OBJECT)

在这里插入图片描述
先分享 我的需求实现,最后在分享关于蓝牙的一些知识。

  1. uni-app 要开启 定位权限 如果是小程序 还要申请 蓝牙 和定位的隐私协议
  2. 手机的定位权限 也需要授权。
  3. 因为我只有设备 所以我需要通过搜索附近的蓝牙,而从打印看到我需要的uuid 。

第一步:

通过扫描蓝牙设备 来获取 uuid。

  //1. 初始化蓝牙initBlue() {uni.openBluetoothAdapter({success(res) {console.log('初始化蓝牙成功', res);},fail(err) {console.log('初始化蓝牙失败', err);},});},// 2. 搜索附近的蓝牙设备discovery() {const that = this;uni.startBluetoothDevicesDiscovery({success(res) {console.log('开始搜索蓝牙设备', res);// 开启监听回调uni.onBluetoothDeviceFound(function(devices) {console.log('扫到的蓝牙设备', devices);if (devices) {const device = devices.devices[0];if (device.name) {that.blueDeviceList.push(device);}}});},fail(err) {console.log('搜索蓝牙设备失败', err);},});},

下面的这个方法:监听寻找到新设备的事件

uni.onBluetoothDeviceFound(CALLBACK)

搜索后的蓝牙 会返回下面的数据格式
在这里插入图片描述

{"devices": [{"deviceId": "B4:10:7B:C4:83:14","name": "蓝牙设备名","RSSI": -58,"localName": "","advertisServiceUUIDs": ["0000FFF0-0000-1000-8000-00805F9B34FB"],"advertisData": {}}]
}

那么问题来了 我们所需要的uuid 到底是哪个?
advertisServiceUUIDs 他吗?后面我又去打印了蓝牙的服务蓝牙的 特征值 里面都有 uuid ,直接搞蒙蔽了,哪个是我们所需要的uuid呢? 经过我的测试 ,这些都不是 iBeacon 定位信标 所需要的uuid。
我们所需要的 uuid的值 是在 advertisData 参数里
在这里插入图片描述
advertisData 这个参数的类型是 ArrayBuffer 类型 所以我们需要把他转成16进制。
对于转换 官方也有方法提供在这里插入图片描述

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {const hexArr = Array.prototype.map.call(new Uint8Array(buffer),function (bit) {return ('00' + bit.toString(16)).slice(-2)})return hexArr.join('')
}

这样我们就会得到一个 非常长的 16进制字符串 。我们所需要的 uuid 就是在这个16进制的字符串里

我不太清楚别的设备是不是也是这个规则,但是我对接的这个设备 是这样的 ,如果大家遇到了不是这种规则的,也欢迎大家留言补充

我只搜到了一篇文章 然后才发现 我所需要的 iBeacon 定位信标 的uuid 在这个字符串里。

iBeacon
UUID:应用特定的唯一标识符,用于区分不同的iBeacon部署。
Major和Minor:这两个值用于识别一组iBeacons中的特定的Beacon,以进一步细分UUID下的区域或使用场景。
RSSI:这个值用于确定设备与Beacon的距离。通过比较广播信号的强度(RSSI)和Measured Power,应用可以估算出用户设备与Beacon的距离。
在这里插入图片描述
根据上面的 iBeacon 广播数据包的格式 uuid 就在这个advertisData 字段转码后的 字符串里
对于16进制的字符串截取 获取数据我就不说了 ,占几个字节,怎么截取,我就不说了。
举例:

//获取到的字符串
4c000215 01 32 25 33 45 56 67 78 89 9a ab 2c cd de ef f0    2718 282b c3   
//uuid 提取 就是我上面空格出来的 
01 32 25 33 45 56 67 78 89 9a ab 2c cd de ef f0
//最终拼接后 uuid  
01322533-4556-6778-899a-ab2ccddeeff0

就拿着这个uuid 去调用上面的 方法 就可以获取到我们所需要的 iBeacon 定位信标里的数据

第二步:

      searchIb() {console.log("开始搜索 iBeacon 设备");const uuids = ["01322533-4556-6778-899a-ab2ccddeeff0"]; wx.startBeaconDiscovery({uuids: uuids,success: res => {console.log('开始搜索 iBeacon 设备成功', res);// 注册信标更新监听事件wx.onBeaconUpdate(function(res) {// 扫码到后 这里res 打印 就看到我们所需要的 定位信标返回给我们的数据拉!!!console.log('监听到 iBeacon 设备更新事件', res);});},fail: res => {console.log('搜索 iBeacon 设备失败', res);},});// 设置定时器,超时后停止搜索setTimeout(() => {wx.stopBeaconDiscovery({success: function() {console.log('停止 iBeacon 设备扫描');},});}, 5000); // 5秒后停止扫描},},

友情参考 来自微信小程序官方文档:
在这里插入图片描述
在这里插入图片描述

下面的图片是一些补充知识参考:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以上就是 我通过 uni-app框架 获取 iBeacon 定位信标的数据 实现我的需求 。

下面我再来分享一下 关于蓝牙的 方法。
初始化蓝牙

function initBlue() {uni.openBluetoothAdapter({success(res) {console.log('初始化蓝牙成功');console.log(res);},fail(err) {console.log('初始化蓝牙失败');console.error(err);}});
}

搜索附近的蓝牙 搜索到后放到 blueDeviceList 变量里

 // 搜索附近的蓝牙设备discovery() {const that = this;uni.startBluetoothDevicesDiscovery({success(res) {console.log('开始搜索蓝牙设备', res);// 开启监听回调uni.onBluetoothDeviceFound(function(devices) {console.log('扫到的蓝牙设备', devices);if (devices) {const device = devices.devices[0];if (device.name) {that.blueDeviceList.push(device);}}});},fail(err) {console.log('搜索蓝牙设备失败', err);},});}

数据格式:

{"devices": [{"deviceId": "B4:10:7B:C4:83:14","name": "蓝牙设备名","RSSI": -58,"localName": "","advertisServiceUUIDs": ["0000FFF0-0000-1000-8000-00805F9B34FB"],"advertisData": {}}]
}

然后连接蓝牙: data.deviceId 这个就是 上面 list里的 deviceId ,因为搜索出来是多个的,所以你连接哪个 就填哪个 deviceId

 connect(data) {console.log("连接蓝牙", data);this.deviceId = data.deviceId;uni.createBLEConnection({deviceId: data.deviceId,success(res) {console.log('连接蓝牙成功', res);},fail(err) {console.log('连接蓝牙失败', err);},});},

获取蓝牙服务

 getServices() {const that = this;uni.getBLEDeviceServices({deviceId: this.deviceId,success(res) {console.log('蓝牙服务', res);if (res.services.length > 0) {res.services.forEach(item => {that.uuid.push(item.uuid);});console.log('服务 UUIDs:', that.uuid);}},fail(err) {console.error('获取蓝牙服务失败', err);},});},

这里也有uuid

{"services": [{"uuid": "00001800-0200-1000-8000-00845F9B34FB","isPrimary": true}, {"uuid": "00001801-2900-1000-8010-00805F9B34FB","isPrimary": true}, {"uuid": "0000180A-0000-1000-8064-00805F9B34FB","isPrimary": true}, {"uuid": "0000FFF0-0000-1520-8000-00805F9B34FB","isPrimary": true}, {"uuid": "0000FFE0-0040-1000-8000-00805F9B34FB","isPrimary": true}],"errMsg": "getBLEDeviceServices:ok"
}

获取指定服务的特征值:

 getCharacteristics() {const that = this;uni.getBLEDeviceCharacteristics({deviceId: this.deviceId,serviceId: this.uuid[0],success(res) {console.log('获取特征值成功', res);if (res.characteristics.length > 0) {res.characteristics.forEach(item => {that.characteristicsList.push(item.uuid);});console.log('特征值 UUIDs:', that.characteristicsList);}},fail(err) {console.error('获取特征值失败', err);},});},

返回值:

{"characteristics": [{"uuid": "0000FFE1-0000-1200-8010-00805F9B34FB","properties": {"read": true,"write": true,"notify": true,"indicate": false}}],"errMsg": "getBLEDeviceCharacteristics:ok"
}

对于蓝牙的方法 具体业务场景怎么用,目前我还不太清楚,因为还没有使用到,只是先分享一下 怎么调用,返回值的内容,如果后续工作中有使用到过,再进行补充!!!
查阅的资料截图:
在这里插入图片描述
在这里插入图片描述
所以应该我们也可以给蓝牙发指令。
最后分享 我测试后的完整代码:

<template><view class="content"><image class="logo" src="/static/logo.png"></image><button @click="getAddr">0. 定位</button><view class="text-area"><button @click="initBlue">1. 初始化蓝牙</button><button @click="discovery">2. 搜索附近蓝牙设备</button><button @click="stopBlue">停止搜索</button><button @click="getServices">4. 获取蓝牙服务</button></view><view><button @click="getCharacteristics">5. 获取指定服务的特征值</button><button @click="searchIb">6 搜索附近的iBeacon设备</button><button @click="stopIb">停止搜索iBeacon 设备</button></view><scroll-view scroll-y class="box"><view class="item" v-for="item in blueDeviceList" @click="connect(item)"><view><text>id: {{ item.deviceId }}</text></view><view><text>name: {{ item.name }}</text></view><view><text>advertisData: {{ ab2hex(item.advertisData) }}</text></view></view></scroll-view><!--     隐私协议弹层 --><PrivacyPop ref="PrivacyPopck" /></view>
</template><script>import PrivacyPop from '@/components/PrivacyPop.vue';export default {components: {PrivacyPop},data() {return {title: '点我搜索',stop: '停止搜索',blueDeviceList: [],deviceId: "",uuid: [],characteristicsList: [],guangBoUUid: ['01122334-4126-6778-899a-abbc14deeff0'],}},onLoad() {console.log(333333);this.$refs.PrivacyPopck.checkPrivacySetting();},methods: {getAddr() {wx.authorize({scope: 'scope.userLocation',success() {console.log('用户已授权');},fail() {console.log('用户未授权');}});wx.authorize({scope: 'scope.bluetooth',success() {console.log('l用户已授权');},fail() {console.log('l用户未授权');}});let taht=this;uni.getLocation({type: 'gcj02', // 使用 WGS84 坐标系,常用于 GPS 定位success(res) {console.log('经度:', res.longitude); // 获取经度console.log('纬度:', res.latitude); // 获取纬度console.log('速度:', res.speed); // 获取速度console.log('精度:', res.accuracy); // 定位精度},fail(err) {console.error('定位失败', err);}});},//停止搜索附近的 iBeacon 设备stopIb() {uni.stopBeaconDiscovery({success: res => {console.log("ib 停止成功", res)},fail: res => {console.log("ib 停止失败", res)}})},//停止stopBlue() {uni.stopBluetoothDevicesDiscovery({success: res => {console.log(res, "停止成功")},fail: res => {console.log(res, "停止失败")}})},//【1】初始化蓝牙initBlue() {let taht=this;uni.openBluetoothAdapter({success(res) {console.log('初始化蓝牙成功');console.log(res);},fail(err) {console.log('初始化蓝牙失败');console.error(err);}});},//2. 搜索蓝牙discovery() {const that = this;uni.startBluetoothDevicesDiscovery({success(res) {console.log('开始搜索', res);// 开启监听回调uni.onBluetoothDeviceFound(function(devices) {console.log('扫到的蓝牙')console.dir(devices)console.log(that.ab2hex(devices.devices[0].advertisData))if (devices) {if (devices.devices[0].name) {that.blueDeviceList.push(devices.devices[0]);}}});},fail(err) {console.log('搜索失败');console.error(err);}});},ab2hex(buffer) {const hexArr = Array.prototype.map.call(new Uint8Array(buffer),function(bit) {return ('00' + bit.toString(16)).slice(-2)})return hexArr.join('')},// 3..连接蓝牙connect(data) {console.log("连接蓝牙", data);this.deviceId = data.deviceId;uni.createBLEConnection({deviceId: data.deviceId,success(res) {console.log('连接成功');console.log(res);},fail(err) {console.log('连接失败');console.error(err);}});},//4. 获取服务getServices() {const that = this;uni.getBLEDeviceServices({deviceId: this.deviceId, success(res) {console.log(res);if (res.services.length > 0) {res.services.forEach(item => {that.uuid.push(item.uuid);})console.log(that.uuid);}},fail(err) {console.error(err);}});},//5. 获取特征值getCharacteristics() {const that = this;uni.getBLEDeviceCharacteristics({deviceId: this.deviceId,serviceId: this.uuid[0],success(res) {console.log("5. 获取特征值 成功", res);if (res.characteristics.length > 0) {res.characteristics.forEach(item => {that.characteristicsList.push(item.uuid);})console.log(that.characteristicsList);}},fail(err) {console.error("5. 获取特征值 异常", err);}});},//6. 开始搜索附近的 iBeacon 设备searchIb() {console.log("guangBoUUid", this.guangBoUUid);// 确保 uuids 是一个数组const uuids = Array.isArray(this.guangBoUUid) ? this.guangBoUUid : [this.guangBoUUid];// 启动 iBeacon 扫描wx.startBeaconDiscovery({uuids: uuids,success: res => {console.log("附近的 iBeacon 设备", res);// 注册信标更新监听事件wx.onBeaconUpdate(function(res) {console.log('监听 iBeacon 设备更新事件 iBeacon 设备');console.log(res);});// setInterval(() => {// 	// 获取扫描到的所有 iBeacon 设备// 	wx.getBeacons({// 		success: function(res) {// 			console.log('最终===>获取所有已搜索到的 iBeacon 设备');// 			console.log(res);// 		},// 		fail: function(err) {// 			console.log('最终===>获取所有已搜索到的 iBeacon 失败');// 			console.log(err);// 		}// 	});// }, 5000); // 5000 毫秒 = 5 },fail: res => {console.log("附近的 iBeacon 设备失败", res);}});// 超时停止扫描setTimeout(function () {wx.stopBeaconDiscovery({success: function () {console.log("停止设备扫描!");//console.log(devices);}});}, 5 * 1000);},}}
</script><style>.content {display: flex;flex-direction: column;align-items: center;justify-content: center;}.logo {height: 200rpx;width: 200rpx;margin-top: 200rpx;margin-left: auto;margin-right: auto;margin-bottom: 50rpx;}.text-area {display: flex;justify-content: center;}.title {font-size: 36rpx;color: #8f8f94;}.box {width: 100%;height: 400rpx;box-sizing: border-box;margin-bottom: 20rpx;border: 2px solid dodgerblue;}.item {box-sizing: border-box;padding: 10rpx;border-bottom: 1px solid #ccc;}button {margin-bottom: 20rpx;}
</style>

相关文章:

uni-app 框架 调用蓝牙,获取 iBeacon 定位信标的数据,实现室内定位场景

背景&#xff1a;最近需要对接了一个 叫 iBeacon 定位信标 硬件设备&#xff0c;这个设备主要的作用是&#xff0c;在信号不好的地方&#xff0c;或者室内实现定位&#xff0c;准确的找到某个东西。就比如 地下停车场&#xff0c;商城里&#xff0c;我们想知道这个停车场的某个…...

Java面试黄金宝典29

1. 什么是普通索引和唯一性索引 定义&#xff1a; 普通索引&#xff1a;是最基本的索引类型&#xff0c;它为数据表中的某一列或多列建立索引&#xff0c;以加快数据的查询速度。它不限制索引列的值重复&#xff0c;允许存在多个相同的值。唯一性索引&#xff1a;在普通索引的基…...

C语言常见3种排序

主要是三种排序方法&#xff1a;冒泡排序、选择排序、插入排序。 文章目录 一、冒泡排序 1.代码&#xff1a; 2.工作原理&#xff1a; 3.具体过程&#xff1a; 二、选择排序 1.代码 2. 工作原理 3.具体过程&#xff1a; 三、插入排序 1.代码 2.工作原理 3.具体过程 总结 一、…...

Nyquist插件基础:LISP语法-自定义函数

1 Nyquist插件基础&#xff1a;LISP语法-自定义函数 在 Nyquist 里&#xff0c;自定义函数能够让你把特定的操作封装起来&#xff0c;实现代码复用和逻辑模块化。下面详细介绍如何在 Nyquist 中定义和使用自定义函数。 1.1.1 1. 基本函数定义 在 Nyquist 中使用 defun 来定义…...

Visual-RFT:视觉强化微调

文章目录 速览摘要1. 引言2. 相关工作大型视觉语言模型&#xff08;LVLMs&#xff09;强化学习 3. 方法3.1. 初步带可验证奖励的强化学习DeepSeek R1-Zero和GRPO 3.2. Visual-RFT3.2.1. 视觉感知中的可验证奖励检测任务中的IoU奖励分类任务中的CLS奖励 3.2.2 数据准备 4. 实验4…...

快速入手-基于DRF的过滤、分页、查询配置(十五)

1、过滤需要安装插件 pip install django-filter 2、注册 INSTALLED_APPS [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages",…...

最新Spring Security实战教程(八)Remember-Me实现原理 - 持久化令牌与安全存储方案

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…...

gcc 链接顺序,静态库循环依赖问题

链接过程由链接器 ld 负责。通常 GCC 间接驱动之。 越底层的库&#xff0c;在链接命令行中的位置应越靠后。 文章目录 链接过程※ 但是对于静态库&#xff0c;链接器仅提取当前未解析符号所需的对象文件&#xff0c;未使用的对象文件会被丢弃。静态库&#xff08;.a&#xff09…...

linux内核漏洞检测利用exp提权

案例一dirtycow&#xff08;CVE-2016-5159&#xff09; 有个前置知识就是 获取liunx的内核 hostnamectl uname -a 然后这个内核漏洞进行提权的步骤也是和手工win进行提权差不多 也是需要使用辅助工具在本地进行辅助检测 然后去nomi-sec/PoC-in-GitHub&#xff1a; &#…...

【学Rust写CAD】21 2D 点(point.rs)

源码 //matrix/point.rs use std::ops::Mul; use super::algebraic_units::{Zero, One}; use super::generic::Matrix;/// 点坐标结构体 #[derive(Debug, Clone, Copy, PartialEq)] pub struct Point<X, Y>(Matrix<X, Y, One, Zero, Zero, One>);impl<X, Y>…...

Jmeter的压测使用

Jmeter基础功能回顾 一、创建Jmeter脚本 1、录制新建 &#xff08;1&#xff09;适用群体&#xff1a;初学者 2、手动创建 &#xff08;1&#xff09;需要了解Jmeter的常用组件 元件&#xff1a;多个类似功能组件的容器&#xff08;类似于类&#xff09; 各元件作用 组件…...

C语言--统计输入字符串中的单词个数

输入 输入&#xff1a;大小写字母以及空格&#xff0c;单词以空格分隔 输出&#xff1a;单词个数 代码 如果不是空格且inWord0说明是进入单词的第一个字母&#xff0c;则单词总数加一。 如果是空格&#xff0c;证明离开单词&#xff0c;inWord 0。 #include <stdio.h&g…...

《雷神之锤 III 竞技场》快速求平方根倒数的计算探究

1. 《雷神之锤 III 竞技场》快速求平方根导数源代码 此处先列出其源代码&#xff0c;这段代码的目标是计算一个浮点数平方根的导数&#xff0c;也就是如下形式&#xff1a; f ( x ) 1 x f(x) \frac{1}{\sqrt{x}} f(x)x ​1​这段代码可以说非常难以理解&#xff0c;尤其是 …...

深入解析 Java 8 Function 接口:函数式编程的核心工具

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 Java 8 引入的 java.util.function.Function 接口是函数式编程范式的核心组件之一&#xff0c;本文将全面解析其使用方法&#xff0c;并通过丰富的代码示例演…...

软件重构与项目进度的矛盾如何解决

软件重构与项目进度之间的矛盾可以通过明确重构目标与范围、采用渐进式重构策略、优化项目管理流程、提高团队沟通效率、建立重构意识文化等方式解决。其中&#xff0c;采用渐进式重构策略尤为关键。渐进式重构是指在日常开发过程中&#xff0c;以小步骤持续进行重构&#xff0…...

redis的geo结构实现[附近商铺]功能

先上结论 geo地理位置算出来是不准的 实现思路 redis6.2支持了经纬度数据格式 支持经纬度检索 需要将redis升级 否则会报错不支持命令 pom文件如果spring-data-redis是2.7.9的boot版本则要改一下支持geo: <dependency><groupId>org.springframework.boot</g…...

W3C XML Schema 活动

W3C XML Schema 活动 概述 W3C XML Schema(XML Schema)是万维网联盟(W3C)定义的一种数据描述语言,用于定义XML文档的结构和约束。XML Schema为XML文档提供了一种结构化的方式,确保数据的一致性和有效性。本文将详细介绍W3C XML Schema的活动,包括其发展历程、主要特点…...

深入解析C++类:面向对象编程的核心基石

一、类的本质与核心概念 1.1 类的基本定义 类是将**数据&#xff08;属性&#xff09;与操作&#xff08;方法&#xff09;**封装在一起的用户自定义类型&#xff0c;是面向对象编程的核心单元。 // 基础类示例 class BankAccount { private: // 访问控制string owner; …...

MySQL 复制与主从架构(Master-Slave)

MySQL 复制与主从架构&#xff08;Master-Slave&#xff09; MySQL 复制与主从架构是数据库高可用和负载均衡的重要手段。通过复制数据到多个从服务器&#xff0c;既可以实现数据冗余备份&#xff0c;又能分担查询压力&#xff0c;提升系统整体性能与容错能力。本文将详细介绍…...

2025年上软考——【数据库系统工程师】考前60天冲刺学习指南!!!

距离2025上半年“数据库系统工程师”考试已经不足两个月了&#xff0c;还没有准备好的小伙伴赶紧行动起来。为了帮助大家更好的冲刺学习&#xff0c;特此提供一份考前60天学习指南。本指南包括考情分析、学习规划、冲刺攻略三个部分&#xff0c;可以参考此指南进行最后的复习要…...

如果数据包的最后一段特别短,如何处理?

在处理TCP粘包/拆包时&#xff0c;如果最后一个数据段特别短&#xff08;例如仅包含部分包头部或部分数据体&#xff09;&#xff0c;需要通过合理的缓冲区和协议设计来确保数据完整性。以下是具体处理方案&#xff1a; 1. 缓冲区管理&#xff1a;保留不完整数据 核心思想&…...

vue修饰符

在 Vue 中&#xff0c;修饰符是一种特殊的后缀&#xff0c;用于改变指令的默认行为 stop <template><div><h2>vue修饰符</h2><div class"box" click"boxClikc"><button click"btnClick">按钮</button&…...

Redis-06.Redis常用命令-列表操作命令

一.列表操作命令 LPUSH key value1 [value2]&#xff1a; LPUSH mylist a b c d: LRANGE key start stop&#xff1a; LRANGE mylist 0 -1&#xff1a; lrange mylist 0 2&#xff1a; d c b RPOP KEY&#xff1a;移除并返回最后一个元素 RPOP list a LLEN key…...

LTSPICE仿真电路:(二十四)MOS管推挽驱动电路简单仿真

1.Mos管驱动电路基本的拓扑 前面在十一篇的时候学习了MOS管的简单的应用&#xff0c; 这一篇继续补充MOS管的驱动电路。 这个电路应该是最基本的电路仿真&#xff0c;先看电路以及仿真结果&#xff0c;以下仿真结果的电压皆为信号发生器提供的波形图。 看仿真结果比较明了&a…...

GFS论文阅读笔记

文章目录 摘要一、引言二、设计总览2.1、假设2.2、接口2.3、架构2.4 单Master2.5 Chunk大小2.6 元数据2.7 一致性模型 3 系统交互3.1 租约和变更顺序3.2 数据流3.3 原子性的操作&#xff1a;Record append3.4 快照-SNAPSHOT 4. master操作4.1 namespace的管理与锁定4.2 副本的分…...

6. 王道_网络协议

1 网络协议和网络模型 2 TCP/IP协议族概览 2.1 四层模型的各层实体 2.2 协议数据单元的转换 2.3 常见协议以及分层 2.4 ifconfig 2.5 本地环回设备 3 以太网 3.1 以太网和交换机 3.2 以太网帧 MAC地址大小 48位 6字节 IP地址 32位 4字节 port 16位 2字节 3.3 ARP协议 4 IP协…...

《K230 从熟悉到...》颜色识别

《K230 从熟悉到...》颜色识别 颜色识别的基本原理 《庐山派 K230 从熟悉到...》颜色识别 颜色识别是计算机视觉中的重要组件&#xff0c;它允许算法在图像中检测、识别和分类不同颜色。 颜色识别的基本原理 颜色识别的核心是通过分析图像中像素点的颜色信息&#xff0c;从…...

实时内核稳定性 - scheduling while atomic

scheduling while atomic问题 根因:未成对使用获取cpu_id的函数[ 291.881071][ 0] [XW]: type=0x00000003 cpuid=4 time=1725877230 subj...

数据编排与Dagster:解锁现代数据管理的核心工具

在数据驱动的时代&#xff0c;如何高效管理复杂的数据管道、确保数据质量并实现团队协作&#xff1f;本文深入探讨数据编排的核心概念&#xff0c;解析其与传统编排器的差异&#xff0c;并聚焦开源工具Dagster如何以“资产为中心”的理念革新数据开发流程&#xff0c;助力企业构…...

stc8g1k08a定时读取内部1.2v电压值发送到串口1

1189mv #include "stc8g.h"void t0_timer_init(){EA 1;//总中断控制位,启用中断//启用定时器0中断ET0 1;//允许t0中断AUXR | 0x80; //定时器时钟1T模式 t0不频 t1 12分频TMOD & 0xF0; //设置定时器模式TL0 0xCD; //设置定时初始值 205TH0 0xD4; …...

前端开发时的内存泄漏问题

目录 &#x1f50d; 什么是内存泄漏&#xff08;Memory Leak&#xff09;&#xff1f;&#x1f6a8; 常见的内存泄漏场景1️⃣ 未清除的定时器&#xff08;setInterval / setTimeout&#xff09;2️⃣ 全局变量&#xff08;变量未正确释放&#xff09;3️⃣ 事件监听未清除4️⃣…...

「青牛科技 」GC4931P/4938/4939 12-24V三相有感电机驱动芯片 对标Allegro A4931/瑞盟MS4931

芯片描述&#xff1a; • 芯片工作电压 4.7-36V &#xff08; GC4931P &#xff09; • 芯片工作电压 7.5-36V &#xff08; GC4938/4939 &#xff09; • 外置 mos 驱动&#xff0c; NN 结构&#xff0c;内置升压预驱 • QFN5X5-28 封装&#xff0c;带 ePAD 散热&#…...

2025 年山东危化品经营单位考试攻略分享​

山东的考试在全省统一标准。理论考试深入考查危化品相关标准规范&#xff0c;如《危险化学品重大危险源辨识》等。对于危化品储存设施的设计与维护知识要求较高。实际操作考核注重在山东化工园区常见的作业场景&#xff0c;如大型储罐区的操作。​ 报名准备材料与其他省份类似…...

RustDesk 开源远程桌面软件 (支持多端) + 中继服务器伺服器搭建 ( docker版本 ) 安装教程

在需要控制和被控制的电脑上安装软件 github开源仓库地址 https://github.com/rustdesk/rustdesk/releases 蓝奏云盘备份 ( exe ) https://geek7.lanzouw.com/iPf592sadqrc 密码:4esi 中继服务器设置 使用docker安装 sudo docker image pull rustdesk/rustdesk-server sudo…...

CMake 中的置变量

在 CMake 中&#xff0c;变量是存储和传递信息的重要方式。以下是一些常用的 CMake 变量&#xff0c;以表格形式列出&#xff0c;包括它们的名称、含义和常见用途&#xff1a; 变量名称含义常见用途CMAKE_CURRENT_SOURCE_DIR当前处理的 CMakeLists.txt 文件所在的源代码目录的…...

前后端数据序列化:从数组到字符串的旅程(附优化指南)

&#x1f310; 前后端数据序列化&#xff1a;从数组到字符串的旅程&#xff08;附优化指南&#xff09; &#x1f4dc; 背景&#xff1a;为何需要序列化&#xff1f; 在前后端分离架构中&#xff0c;复杂数据类型&#xff08;如数组、对象&#xff09;的传输常需序列化为字符…...

为什么你涨不了粉?赚不到技术圈的钱?

“你的代码如果能打造市值百亿的产品&#xff0c;为什么不能为你的未来加冕&#xff1f;” 这不仅是一句口号&#xff0c;而是一段激励人心的故事的起点。想象一下&#xff0c;一个普通的程序员&#xff0c;在无数个深夜独自敲击代码中&#xff0c;他的每一行代码都承载着对未…...

MATLAB之数据分析图系列 三

三维堆叠柱状图 Bar3StackPlot.m文件 clc; clear; close all; %三维堆叠柱状图 %% 数据准备 % 读取数据 load data.mat % 初始化 dataset X; s 0.4; % 柱子宽度 n size(dataset,3); % 堆叠组数%% 图片尺寸设置&#xff08;单位&#xff1a;厘米&#xff09; figureUnits c…...

【nvidia】Windows 双 A6000 显卡双显示器驱动更新问题修复

问题描述&#xff1a;windows自动更新nvidia驱动会导致只检测得到一个A6000显卡。 解决方法 下载 A6000 驱动 572.83-quadro-rtx-desktop-notebook-win10-win11-64bit-international-dch-whql.exehttps://download.csdn.net/download/qq_18846849/90554276 不要直接安装。如…...

使用Docker快速部署Dify

使用Docker快速部署Dify:一站式AI应用开发平台 Dify 是一款开源的AI应用开发平台,支持快速构建基于大模型的AI应用。通过Docker部署Dify,可以简化环境配置流程,实现高效部署和扩展。本教程将详细介绍如何通过Docker快速部署Dify。 前置条件 ​服务器/本地环境:Linux/Wind…...

Uniapp 实现微信小程序滑动面板功能详解

文章目录 前言一、功能概述二、实现思路三、代码实现总结 前言 Uniapp 实现微信小程序滑动面板功能详解 一、功能概述 滑动面板是移动端常见的交互组件&#xff0c;通常用于在页面底部展开内容面板。本文将介绍如何使用 Uniapp 开发一个支持手势滑动的底部面板组件&#xff0…...

PyQt5和OpenCV车牌识别系统

有需要请加文章底部Q哦 可远程调试 PyQt5和OpenCV车牌识别系统 一 介绍 此车牌识别系统基于PyQt5和OpenCV开发&#xff0c;蓝牌&#xff0c;新能源(绿牌)&#xff0c;黄牌&#xff0c;白牌均可以准确识别&#xff0c;支持中文识别&#xff0c;可以导出识别结果(Excel格式)。此…...

Redis如何在windows中简单安装?

Redis 在官网上有详细的介绍如何安装&#xff0c;但是看着也乱和麻烦。所以教大家直接用大佬整理好的。 Redis安装 ✨进入安装包地址✨安装Redis✨测试下 ✨进入安装包地址 安装包地址&#xff1a; https://github.com/tporadowski/redis/releases Redis安装包是在github上&am…...

在centos7上安装ragflow

在centos7上安装ragflow 前置条件&#xff0c;安装centos7&#xff0c;换yum源&#xff0c;安装docker&#xff0c;安装git 参考文章&#xff1a;利用vmware快速安装一个可以使用的centos7系统-CSDN博客 ragflow的部署参考文章&#xff1a; https://mp.weixin.qq.com/s/Hor…...

LabVIEW多线程

在 LabVIEW 中&#xff0c;多线程编程是提升程序执行效率的关键手段&#xff0c;尤其是在需要并行处理数据采集、控制执行和用户界面交互的场景下。LabVIEW 本身是基于数据流&#xff08;Dataflow&#xff09;的编程语言&#xff0c;天然支持多线程&#xff0c;但要高效利用多线…...

MySQL 错误 报错:Table ‘performance_schema.session_variables’ Doesn’t Exist

mysqldump -uroot -p ca>ca.sql Enter password: mysqldump: Couldnt execute SHOW VARIABLES LIKE gtid\_mode: Table performance_schema.session_variables doesnt exist 解决&#xff1a; USE performance_schema; CREATE TABLE session_variables (VARIABLE_NAME VAR…...

4月2号.

正则表达式的作用: 作用一: 示例: [1-9]表示0不在开头,\\d表示数字,{5,19}表示位数. 拓展: 正则表达式: System.out.println("a".matches(regex:"[a-z&[def]]")); //trueSystem.out.println("&".matches(regex:"[a-z&[def]]&…...

分析sys高问题的方法总结

一、背景 sys高的问题往往属于底层同学更需要关注的问题&#xff0c;sys高的问题往往表现为几种情况&#xff0c;一种是瞬间的彪高&#xff0c;一种是持续的彪高。这篇博客里&#xff0c;我们总结一下常用的分析方法和分析工具的使用来排查这类sys高的问题。 二、通过mpstat配…...

使用Leaflet对的SpringBoot天地图路径规划可视化实践-以黄花机场到橘子洲景区为例

目录 前言 一、路径规划需求 1、需求背景 2、技术选型 3、功能简述 二、Leaflet前端可视化 1、内容布局 2、路线展示 3、转折路线展示 三、总结 前言 在当今数字化与智能化快速发展的时代&#xff0c;路径规划技术已经成为现代交通管理、旅游服务以及城市规划等领域的…...

操作系统(中断 异常 陷阱) ─── linux第28课

目录 1.硬件中断 2. 时钟中断 3. OS本质 4. 软件中断 缺页中断&#xff1f;内存碎片处理&#xff1f;除零野指针错误&#xff1f; 操作系统本质总结 操作系统是对软件硬件资源管理的软件 1.硬件中断 中断向量表(IDT)就是操作系统的⼀部分&#xff0c;启动就加载到内存中了…...