商丘关键词优化推广/南昌seo营销
Uni APP的学习
官方文档
uni-app官网 (dcloud.net.cn)
任何的博客都不如官方文档
一、快速复习
文件结构
main.js
- 功能:项目的入口文件,初始化 Vue 实例。
App.vue
- 功能:根组件,包含应用的基本结构和全局样式。
manifest.json
- 功能:应用的全局配置文件,包含应用名称、图标、平台特定配置等信息。
pages.json
- 功能:配置应用的页面路由、导航栏、选项卡等信息。
uni.scss
- 功能:全局的 SCSS 样式文件,可以在整个项目中使用。
components/
- 功能:用于存放项目中的可复用组件。
pages/
- 功能:用于存放项目的页面,每个页面通常有一个独立的目录和对应的
.vue
文件。
static/
- 功能:用于存放项目中的静态资源,如图片、字体等。
uni_modules/
- 功能:用于存放 UniApp 插件模块。
store/
- 功能:用于存放 Vuex 状态管理的相关文件。
utils/
- 功能:用于存放工具函数和公共方法。
unpackage/
- 功能:用于存放编译后的文件和生成的包。包含生成的各个平台的编译文件,是项目发布和运行的产物目录
为什么每个页面都使用template包围
每个页面都是一个组件:
- 在 UniApp 中,一个页面本质上是一个独立的 Vue 组件。它包含了自己的
<template>
、<script>
和<style>
,因此可以独立运行。 - 由于 Vue 组件的特性,这些页面也可以在其他地方被当作子组件使用。
组件复用: - 你可以将一个页面或组件嵌套在另一个页面或组件中,复用其内容和逻辑。例如,你可以在一个主页面中引入一个通用的头部或底部组件。
- 通过在不同页面之间复用组件,你可以保持代码的简洁,并减少重复劳动。
组件之间的通信: - 当你将一个页面作为组件嵌套在另一个页面中时,你可以通过
props
传递数据,或者通过事件$emit
和$on
来实现父子组件之间的通信。 - 这使得页面之间可以互相传递数据,形成一个有机的整体。
view标签
<view>
标签在 UniApp 中是一个非常重要且常用的标签。它在 UniApp 中起到了类似于 HTML 中 <div>
标签的作用,用于构建页面的基本布局和结构。下面是对 <view>
标签的详细讲解:
1. 基本功能
<view>
标签是 UniApp 中的一个容器元素,用来包含其他的视图元素或者组件。- 你可以将
<view>
标签理解为一个通用的布局容器,类似于 HTML 中的<div>
标签。
2. 属性
<view>
标签支持很多属性,下面是一些常见的属性:
- class: 用于为
<view>
添加样式类,通过 CSS 进行样式控制。 - style: 直接内联样式设置,例如
style="margin:10px; padding:5px;"
。 - id: 为
<view>
指定唯一标识符,用于在 JS 代码中进行操作。 - hover-class: 当用户触摸时会给
<view>
添加的样式类。 - hover-start-time: 按住时长达到多少毫秒才显示 hover 状态,默认 50 毫秒。
- hover-stay-time: 手指松开后,保留 hover 状态的时长,默认 400 毫秒。
3. 使用示例
下面是一个简单的示例,展示如何使用 <view>
标签来构建一个页面的布局:
<template><!-- 页面根容器,使用 Flex 布局来组织页面结构 --><view class="container"><!-- 头部区域 --><view class="header" <!-- 应用样式类 "header" -->hover-class="hover-effect" <!-- 用户触摸时,应用 "hover-effect" 样式 -->><text>这是头部(带有hover效果)</text> <!-- 显示在头部的文本内容 --></view><!-- 主要内容区域,带有点击事件 --><view class="content" <!-- 应用样式类 "content" -->@click="handleClick" <!-- 点击时触发 handleClick 方法 -->hover-class="hover-effect" <!-- 用户触摸时,应用 "hover-effect" 样式 -->hover-start-time="100" <!-- 用户触摸 100 毫秒后,开始显示 hover 效果 -->hover-stay-time="300" <!-- 松开触摸后,hover 效果持续 300 毫秒 -->id="main-content" <!-- 设置唯一标识符为 "main-content" -->><text>点击这里触发事件</text> <!-- 显示在内容区域的文本内容 --></view><!-- 底部区域,使用动态内联样式 --><view class="footer" <!-- 应用样式类 "footer" -->style="background-color: #00aaff;" <!-- 内联样式,设置背景颜色为蓝色 -->:style="{ height: dynamicHeight + 'px' }" <!-- 动态设置高度,使用 Vue 的绑定语法 -->><text>这是底部(背景颜色通过style设置)</text> <!-- 显示在底部的文本内容 --></view></view>
</template><script>
export default {data() {return {dynamicHeight: 50 // 动态设置底部区域的高度为 50 像素};},methods: {handleClick() {// 点击事件的处理逻辑console.log('内容区域被点击');}}
};
</script><style>
/* 容器的样式:设置为 Flex 布局,子元素按垂直方向排列,容器高度占满页面 */
.container {display: flex; /* 启用弹性布局 */flex-direction: column; /* 子元素垂直排列(从上到下) */height: 100%; /* 容器高度占满父容器或视口 */
}/* 头部的样式 */
.header {background-color: #f8f8f8; /* 设置背景颜色为浅灰色 */padding: 10px; /* 内边距为 10 像素 */text-align: center; /* 文本居中对齐 */
}/* 内容区域的样式 */
.content {flex: 1; /* 占据容器中剩余的所有空间 */background-color: #ffffff; /* 设置背景颜色为白色 */padding: 20px; /* 内边距为 20 像素 */
}/* 底部的样式 */
.footer {padding: 10px; /* 内边距为 10 像素 */text-align: center; /* 文本居中对齐 */
}/* 用户触摸时的 hover 效果样式 */
.hover-effect {background-color: #e0e0e0; /* 设置触摸时的背景颜色为浅灰色 */
}
</style>
在这个例子中:
hover-class
:- 作用:为
<view>
组件添加一个在用户触摸时显示的样式类。通常用于按钮或可点击的区域,提供视觉反馈。 - 示例:
hover-class="hover-effect"
,当用户点击或触摸时,hover-effect
样式会被应用。
hover-start-time
: - 作用:设置用户触摸多少毫秒后,开始显示
hover-class
。 - 示例:
hover-start-time="100"
,用户触摸 100 毫秒后,开始显示hover-class
的效果。
hover-stay-time
: - 作用:设置用户松开触摸后,
hover-class
的效果持续多久(毫秒)。 - 示例:
hover-stay-time="300"
,在用户松开触摸后,hover-class
的效果会持续 300 毫秒。
id
: - 作用:为
<view>
组件设置唯一的标识符,可以用于在 JS 中进行 DOM 操作。 - 示例:
id="main-content"
,你可以通过this.$refs['main-content']
来引用这个元素。
style
: - 作用:内联样式直接应用于
<view>
元素,用于设置动态样式。 - 示例:
style="background-color: #00aaff;"
为<view>
设置了蓝色背景。:style="{ height: dynamicHeight + 'px' }"
使用 Vue 的动态绑定来设置高度。
@click
: - 作用:绑定点击事件,当
<view>
被点击时触发对应的事件处理函数。 - 示例:
@click="handleClick"
,点击content
区域时,将调用handleClick
方法。
class
: - 作用:应用定义在
<style>
中的样式类,用于控制<view>
的外观和布局。 - 示例:
class="header"
应用了.header
中定义的样式。
- 作用:为
4. 为什么使用 <view>
而不是 <div>
?
- 跨平台支持:
<view>
标签在所有 UniApp 支持的平台上都可以正常使用,而<div>
是 HTML 元素,不适用于小程序、App 等其他平台。 - 性能优化: UniApp 对
<view>
标签做了许多平台优化,可以更好地适应移动端设备,提供更流畅的用户体验。 - 样式控制:
<view>
标签内的样式和布局在不同平台之间更一致,使用<view>
可以减少跨平台开发时的样式兼容性问题。
5. 常见的使用场景
- 布局容器: 创建页面的基础结构和布局。
- 点击区域: 配合
hover-class
等属性,实现点击效果。 - 数据展示: 包裹和组织其他元素,如文本、图片、列表等.
flex布局
1. 基础概念
- Flex 容器(Flex Container): 包含子元素(Flex 项目)的父容器,通常通过设置
display: flex;
来定义。 - Flex 项目(Flex Items): 容器内的所有直接子元素,它们将自动成为弹性布局的一部分,可以自由地根据容器的规则进行排列和对齐。
2. 基本属性
在 Flexbox 布局中,最重要的属性主要有以下几类:
2.1. 容器属性(应用于 Flex 容器)
- display: flex;
- 将一个元素定义为 Flex 容器,容器内的子元素将变成 Flex 项目。
- flex-direction
- 决定 Flex 项目的排列方向。
row
: 默认值,从左到右水平排列。row-reverse
: 从右到左水平排列。column
: 从上到下垂直排列。column-reverse
: 从下到上垂直排列。
- 决定 Flex 项目的排列方向。
- justify-content
- 控制 Flex 项目在主轴(flex-direction 方向)的对齐方式。
flex-start
: 靠主轴的起点对齐。flex-end
: 靠主轴的终点对齐。center
: 居中对齐。space-between
: 项目之间的间距相等,首尾项目与容器边缘对齐。space-around
: 项目之间的间距相等,项目和容器边缘之间留有一半的间距。
- 控制 Flex 项目在主轴(flex-direction 方向)的对齐方式。
- align-items
- 控制 Flex 项目在交叉轴(与主轴垂直的方向)的对齐方式。
stretch
: 默认值,项目在交叉轴方向上拉伸以填充容器。flex-start
: 靠交叉轴的起点对齐。flex-end
: 靠交叉轴的终点对齐。center
: 在交叉轴方向居中对齐。baseline
: 项目基线对齐。
- 控制 Flex 项目在交叉轴(与主轴垂直的方向)的对齐方式。
- flex-wrap
- 决定如果容器空间不足,Flex 项目是否换行。
nowrap
: 默认值,不换行。wrap
: 换行,项目在多行中排列。wrap-reverse
: 反向换行。
- 决定如果容器空间不足,Flex 项目是否换行。
2.2. 项目属性(应用于 Flex 项目)
- flex
- 简写属性,用于指定 Flex 项目的可伸缩性。
flex: 1;
表示项目将占据容器的所有可用空间,多个项目之间将按比例分配空间。
- 简写属性,用于指定 Flex 项目的可伸缩性。
- align-self
- 允许单个项目对齐方式与容器的
align-items
属性不同。
- 允许单个项目对齐方式与容器的
- order
- 控制项目的排列顺序,数值越小的项目会排在前面,默认值为
0
- 控制项目的排列顺序,数值越小的项目会排在前面,默认值为
二、websocket的连接
函数介绍
1. connect
- 功能:建立 WebSocket 连接,并设置各种事件回调来处理连接成功、收到消息、连接关闭和连接出错的情况。
- 核心操作:通过
uni.connectSocket
方法创建 WebSocket 连接,成功后发送初始数据。
2. sendMessage
- 功能:通过 WebSocket 连接向服务器发送文本消息。
- 核心操作
- 检查 WebSocket 连接是否处于打开状态。
- 构造要发送的消息(包含目标客户端 ID 和消息内容)。
- 通过
socketTask.send
方法发送消息。
3. handleFileChange
- 功能:处理用户选择的音频文件,并将文件保存在组件的状态中,以便稍后发送。
- 核心操作
- 捕获用户选择的文件,并将其存储在
audioFile
变量中。
- 捕获用户选择的文件,并将其存储在
4. sendAudio
- 功能:将选择的音频文件通过 WebSocket 连接发送给服务器。
- 核心操作
- 使用
FileReader
读取音频文件的内容,并转换为ArrayBuffer
格式。
- 使用
- 通过
socketTask.send
方法逐块发送音频数据,并在发送结束后发送"EOF"
标志表示文件传输结束。
详细功能介绍
1. connect
- 功能:启动 WebSocket 连接,是整个应用程序的核心功能。它确保了客户端能够与服务器通信,并在连接成功后立即向服务器发送客户端的身份信息(即
uniqueId
和mateUniqueId
)。 - 使用场景:当用户想要连接到服务器进行实时通信时,点击“Connect”按钮触发。
2. sendMessage
- 功能:允许用户通过 WebSocket 连接向特定的客户端发送消息。这是聊天应用或任何需要发送点对点消息的应用程序的核心功能。
- 使用场景:当用户输入目标客户端 ID 和消息内容后,点击“Send”按钮发送消息。
3. handleFileChange
- 功能:捕获用户选择的音频文件,并为后续的音频传输做准备。这个函数确保了音频文件能够正确读取并保存在组件的状态中。
- 使用场景:当用户选择音频文件时,这个函数被触发,准备好文件以便稍后发送。
4. sendAudio
- 功能:将音频文件通过 WebSocket 连接发送到服务器。这个函数负责处理音频文件的分块传输,并确保传输的完整性。
- 使用场景:当用户选择了音频文件并点击“Send Audio”按钮时,触发这个函数开始传输音频数据。
连接函数
connect() {// 创建一个 WebSocket 连接,保存到 socketTask 变量中this.socketTask = uni.connectSocket({url: "wss://erroright.cn/ws", // WebSocket 服务器的地址success: () => {// 如果 WebSocket 连接创建成功,输出成功日志console.log("WebSocket connection created.");},fail: (error) => {// 如果 WebSocket 连接创建失败,输出错误信息console.error("Failed to create WebSocket connection:", error);}});// 当 WebSocket 连接成功时触发的事件回调this.socketTask.onOpen(() => {// 输出调试信息,表示已经成功连接到 WebSocket 服务器console.log("Connected to WebSocket server.");// 构造发送给服务器的初始数据,包含客户端的唯一 ID 和配对客户端的唯一 IDlet data = {send_id: this.uniqueId, // 客户端的唯一 IDreceive_id: this.mateUniqueId // 配对客户端的唯一 ID};// 输出调试信息,显示即将发送的初始数据console.log("Sending initial data:", data);// 通过 WebSocket 连接发送初始数据this.socketTask.send({data: JSON.stringify(data), // 将数据转换为 JSON 字符串格式发送fail: (error) => {// 如果发送初始数据失败,输出错误信息console.error("Failed to send initial data:", error);}});});// 当从服务器接收到消息时触发的事件回调this.socketTask.onMessage((event) => {// 输出调试信息,显示接收到的消息内容console.log("Received message from server:", event.data);// 将接收到的消息添加到 messages 数组中,以便在页面中显示this.messages.push(event.data);});// 当 WebSocket 连接关闭时触发的事件回调this.socketTask.onClose(() => {// 输出调试信息,表示 WebSocket 连接已关闭console.log("Disconnected from WebSocket server.");});// 当 WebSocket 连接出错时触发的事件回调this.socketTask.onError((error) => {// 输出调试信息,显示具体的错误内容console.error("WebSocket error occurred:", error);});
}
发送信息
sendMessage() {// 检查 WebSocket 连接是否存在并且处于打开状态if (this.socketTask && this.socketTask.readyState === WebSocket.OPEN) {// 构造要发送的消息对象,包含目标客户端 ID 和消息内容let message = JSON.stringify({content: this.messageText // 要发送的消息内容});// 输出调试信息,显示即将发送的消息内容console.log("Sending message:", message);// 通过 WebSocket 连接发送消息this.socketTask.send({data: message, // 发送的消息数据success: () => {// 发送成功后清空消息输入框this.messageText = '';},fail: (error) => {// 如果消息发送失败,输出错误信息console.error("Failed to send message:", error);}});} else {// 如果 WebSocket 未连接或状态不正确,输出错误信息console.error("WebSocket is not connected or is in an invalid state.");}},
捕获音频文件,为后续音频传输做准备
handleFileChange(event) {// 从事件对象 event 中获取用户选择的文件// event.target.files 是一个 FileList 对象,包含了用户选择的所有文件// [0] 代表获取第一个文件对象,因为通常用户只选择一个文件this.audioFile = event.target.files[0];// 输出调试信息,显示用户选择的文件的名称// 通过 this.audioFile.name 获取文件的名称,确认用户选择的文件正确无误console.log("Selected audio file:", this.audioFile.name);
}
发送音频文件给服务器
sendAudio() {// 检查是否选择了音频文件if (!this.audioFile) {// 如果没有选择音频文件,提示用户先选择文件uni.showToast({title: 'Please select an audio file first', // 显示的提示信息icon: 'none' // 不显示图标});return; // 结束函数执行}// 创建一个 FileReader 对象,用于读取文件内容let reader = new FileReader();// 定义 FileReader 的 onload 回调,当文件读取完成时触发reader.onload = (event) => {// 获取读取的文件内容,作为 ArrayBuffer 对象let arrayBuffer = event.target.result;// 将 ArrayBuffer 转换为 Uint8Array,这样可以逐字节处理数据let bytes = new Uint8Array(arrayBuffer);// 输出调试信息,显示即将发送的音频数据console.log("Sending audio data:", bytes);// 通过 WebSocket 发送音频数据this.socketTask.send({data: bytes.buffer, // 将 Uint8Array 的缓冲区发送success: () => {// 音频数据发送成功后,再发送一个 "EOF" 标志,表示传输结束this.socketTask.send({data: "EOF", // 发送 "EOF" 表示文件传输结束success: () => {console.log("EOF sent."); // 输出 "EOF" 发送成功的日志},fail: (error) => {console.error("Failed to send EOF:", error); // 输出 "EOF" 发送失败的错误信息}});},fail: (error) => {console.error("Failed to send audio data:", error); // 输出音频数据发送失败的错误信息}});};// 开始异步读取音频文件的内容,并将其转换为 ArrayBuffer 格式reader.readAsArrayBuffer(this.audioFile);
}
三、蓝牙
1. initBlue
- 功能:初始化蓝牙模块。
- 操作
- 调用
uni.openBluetoothAdapter
打开蓝牙适配器。
- 调用
- 如果初始化成功,调用
startBluetoothDevicesDiscovery
开始搜索蓝牙设备。
2. startBluetoothDevicesDiscovery
- 功能:启动蓝牙设备的搜索。
- 操作
- 调用
uni.startBluetoothDevicesDiscovery
开始搜索蓝牙设备。
- 调用
- 如果搜索成功,设置蓝牙设备发现的回调函数
onBluetoothDeviceFound
。
3. onBluetoothDeviceFound
- 功能:处理发现的蓝牙设备。
- 操作
- 当发现蓝牙设备时,检查设备名称是否与
deviceName
匹配。
- 当发现蓝牙设备时,检查设备名称是否与
- 如果匹配,保存设备的
deviceId
并调用createBLEConnection
尝试连接设备。
4. createBLEConnection
- 功能:创建蓝牙低功耗设备 (BLE) 的连接。
- 操作
- 调用
uni.createBLEConnection
连接到指定的蓝牙设备。 - 如果连接成功,更新连接状态为已连接 (
isConnected: true
)。 - 延迟 3 秒后调用
getBLEDeviceServices
获取设备的服务列表。
- 调用
5. getBLEDeviceServices
- 功能:获取连接设备的服务列表。
- 操作
- 调用
uni.getBLEDeviceServices
获取设备的服务。 - 如果成功,遍历服务列表并检查是否包含指定的服务 UUID (
SERVICE_UUID
)。 - 如果找到匹配的服务,调用
getBLEDeviceCharacteristics
获取该服务的特性。 - 如果获取服务失败或服务列表为空,最多重试三次。
- 调用
6. getBLEDeviceCharacteristics
- 功能:获取指定服务的特性。
- 操作
- 调用
uni.getBLEDeviceCharacteristics
获取服务的特性列表。 - 如果成功,检查特性是否支持写操作,并将其 UUID 保存到
CHARACTERISTIC_UUID
。 - 如果没有找到支持写操作的特性,输出错误信息。
- 调用
7. sendDataToBluetooth
- 功能:发送数据到蓝牙设备。
- 操作
- 首先检查是否已连接到蓝牙设备。
- 如果连接正常,调用
sendDataInChunks
将数据分块发送到蓝牙设备。
8. sendDataInChunks
- 功能:将数据分块发送到蓝牙设备。
- 操作
- 根据设备的 MTU 大小(这里假设为 517 字节)将数据分块。
- 对每个数据块,创建
ArrayBuffer
并转换为字节数据后,通过uni.writeBLECharacteristicValue
发送给设备。
9. action
- 功能:发送 “over” 命令到蓝牙设备,表示数据传输完成或其他特定操作。
- 操作
- 类似于
sendDataToBluetooth
,但是这里发送的是 “over” 字符串。
- 类似于
<template><view class="container"><view class="intro">蓝牙消息发送示例。</view><button @click="initBlue">连接蓝牙</button><button @click="sendDataToBluetooth">发送数据</button><button @click="action">开始运行</button></view>
</template><script>export default {data() {return {deviceName: "MiniBay", // 要连接的设备名称deviceId: null, // 设备 IDSERVICE_UUID: "4FAFC201-1FB5-459E-8FCC-C5C9C331914B", // 服务的 UUID (大写)CHARACTERISTIC_UUID: "BEB5483E-36E1-4688-B7F5-EA07361B26A8", // 特性的 UUID (大写)dataToSend:"{10, 10, 200},{20, 10, 200},{10, 20, 200},{30, 10, 200},{25, 25, 100},{10, 30, 200},{20, 20, 100},{30, 30, 100},{35, 35, 100},{40, 40, 100},{45, 45, 100},{50, 50, 100},{55, 55, 100},{60, 60, 100},{65, 65, 100},{70, 70, 100},{75, 75, 100},{80, 80, 100},{85, 85, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{95, 95, 200},{90, 90, 200},{45, 45, 200},{0, 0, 0}",isConnected: false // 用于跟踪蓝牙是否已连接}},methods: {initBlue() {uni.openBluetoothAdapter({success: res => {console.log('初始化蓝牙成功');this.startBluetoothDevicesDiscovery();},fail: err => {console.log('初始化蓝牙失败');console.error(err);}});},startBluetoothDevicesDiscovery() {uni.startBluetoothDevicesDiscovery({success: res => {console.log('开始搜索设备...');this.onBluetoothDeviceFound();},fail: err => {console.log('搜索设备失败');console.error(err);}});},onBluetoothDeviceFound() {uni.onBluetoothDeviceFound(devices => {devices.devices.forEach(device => {if (device.name === this.deviceName) {console.log('找到设备:', device);this.deviceId = device.deviceId;this.createBLEConnection();}});});},createBLEConnection() {if (this.deviceId) {uni.createBLEConnection({deviceId: this.deviceId,success: res => {console.log('连接设备成功');this.isConnected = true; // 更新连接状态// 延迟以确保设备服务准备就绪setTimeout(() => {this.getBLEDeviceServices();}, 3000);},fail: err => {console.log('连接设备失败');this.isConnected = false; // 确保连接失败时状态更新console.error(err);}});}},getBLEDeviceServices(retryCount = 0) {uni.getBLEDeviceServices({deviceId: this.deviceId,success: res => {if (res.services && res.services.length > 0) {console.log('获取服务成功:', res.services);res.services.forEach((service, index) => {console.log(`服务 ${index + 1}: UUID = ${service.uuid}`);});// 检查是否找到特定的服务const service = res.services.find(s => s.uuid === this.SERVICE_UUID);if (service) {this.getBLEDeviceCharacteristics(service.uuid);} else {console.error('未找到指定的服务');}} else {console.error('服务列表为空或未找到服务');if (retryCount < 3) { // 尝试重试三次console.log(`重试获取服务 (${retryCount + 1}/3)`);setTimeout(() => {this.getBLEDeviceServices(retryCount + 1);}, 3000); // 每次延迟3秒再重试}}},fail: err => {console.log('获取服务失败');console.error(err);}});},getBLEDeviceCharacteristics(serviceId) {uni.getBLEDeviceCharacteristics({deviceId: this.deviceId,serviceId: serviceId,success: res => {console.log('获取特性成功:', res.characteristics);// 检查特性是否支持写操作const writableCharacteristic = res.characteristics.find(char => char.properties.write);if (writableCharacteristic) {this.CHARACTERISTIC_UUID = writableCharacteristic.uuid;} else {console.error('未找到支持写操作的特性');}},fail: err => {console.log('获取特性失败');console.error(err);}});},sendDataToBluetooth() {if (!this.isConnected) {console.error('未连接到蓝牙设备');return;}const data = this.dataToSend;this.sendDataInChunks(data);},sendDataInChunks(data) {const maxChunkSize = 517; // 依据设备的 MTU,20 是默认蓝牙包大小for (let i = 0; i < data.length; i += maxChunkSize) {const chunk = data.slice(i, i + maxChunkSize);const buffer = new ArrayBuffer(chunk.length);const dataView = new DataView(buffer);for (let j = 0; j < chunk.length; j++) {dataView.setUint8(j, chunk.charCodeAt(j));}uni.writeBLECharacteristicValue({deviceId: this.deviceId,serviceId: this.SERVICE_UUID,characteristicId: this.CHARACTERISTIC_UUID,value: buffer,success: res => {console.log('数据发送成功:', chunk);},fail: err => {console.log('数据发送失败');console.error(err);}});}},action() {if (!this.isConnected) {console.error('未连接到蓝牙设备');return;}const formattedData = "over";const buffer = new ArrayBuffer(formattedData.length);const dataView = new DataView(buffer);for (let i = 0; i < formattedData.length; i++) {dataView.setUint8(i, formattedData.charCodeAt(i));}uni.writeBLECharacteristicValue({deviceId: this.deviceId,serviceId: this.SERVICE_UUID,characteristicId: this.CHARACTERISTIC_UUID,value: buffer,success: res => {console.log('数据发送成功:', formattedData);},fail: err => {console.log('数据发送失败');console.error(err);}});}}}
</script><style>.container {padding: 20px;font-size: 14px;line-height: 24px;}
</style>
相关文章:

uniapp快速回顾,新学websocket连接和BLE连接
Uni APP的学习 官方文档 uni-app官网 (dcloud.net.cn) 任何的博客都不如官方文档 一、快速复习 文件结构 main.js 功能:项目的入口文件,初始化 Vue 实例。 App.vue功能:根组件,包含应用的基本结构和全局样式。 manifest.js…...

激光测距传感器
系列文章目录 1.元件基础 2.电路设计 3.PCB设计 4.元件焊接 5.板子调试 6.程序设计 7.算法学习 8.编写exe 9.检测标准 10.项目举例 11.职业规划 文章目录 前言一、产品原理:二、产品介绍:三、应用特点四、应用案例:1.冶金钢铁板卷材开卷工…...

从数据分析到智能生产:AI在工业中的应用与未来
导语 | 人工智能技术的迅猛发展,正在引领第四次工业革命悄然而至。尽管 AI 技术在工业领域的部署仍有诸多难题亟待解决,但这并不能阻挡历史趋势的车轮滚滚向前,AI 正在为工业领域带来新的变革。今天,我们特邀了上海腾展长融董事 &…...

讲讲android art虚拟机的内存
Android 的 ART(Android Runtime)虚拟机的内存管理是一个复杂但重要的部分。 ART 虚拟机的内存主要包括以下几个关键区域: Java 堆(Java Heap): 这是存储 Java 对象实例的主要区域。堆内存被进一步划分为不…...

构建高效社群生态:探索社群系统的力量与未来
在数字化时代的大潮中,社群系统作为连接人与人、促进信息交流与资源共享的重要平台,正日益成为企业、组织乃至个人不可或缺的一部分。它不仅为成员提供了展示自我、学习成长的舞台,更为社群管理者创造了高效管理、精准运营的工具。今天&#…...

数据结构——排序(3):交换排序(续)
目录 一、快速排序 (1)hoare版本 ①思路 ②过程图示 ③思考 ④代码实现 ⑤代码解释 (2)挖坑法 ①思路 ②过程图示 ③思考 ④代码实现 ⑤代码解释 (3)lomuto前后指针 ①思路 ②过程图示 ③思考 ④代码实现 ⑤代…...

2024最新版本Python安装及开发环境配置(vscodepython)
python安装 去Python官网下载最新版本: 接下来请一步步按照图片操作: 这样子就安装完成了 测试Python安装是否成功 先打开终端 右键Windows徽标,点击终端 然后输入python,如果如下图所示,就说明安装成功࿰…...

机器学习的定义
机器学习 机器学习的定义 机器学习是人工智能的一个分支,它使计算机系统能够从经验中学习并改进,而无需进行明确的编程。机器学习算法分析和解释数据,然后使用该数据来做出预测或决策,随着时间的推移,它们会变得更加准…...

2024-08-05升级问题:Android中ScrollView嵌套listview并解决listview显示问题
问题: 当ScrollView嵌套ListView时,ListView的高度设置为wrap_content时出现ListView的高度不能完全展开,而只显示的第一个Item。 解决方法: 按item的个数乘以高度计算出listview的总高度,并在数据变化时直接设置lis…...

【热度文章】Java设计模式之中介者模 式
ava 中的中介者模式 中介者模式(Mediator Pattern)是一种行为型设计模式,它通过一个中介对象来封装一系列对象之间的交互,使这些对象之间不需要显式地相互引用,从而降低了对象之间的耦合度。 中介者模式的主要角色&…...

【3.0】vue3语法
【3】vue3语法 【一】vue前提 【1】定义变量 # 1 const是常量--》不允许变的 # 2 咱们用 ref包裹后,是个对象,虽然对象是常量,对象不能变,对象.value可以变化 # 3 之所以定义成const原因是,后期不能修改对象 【对象.…...

Navicat Monitor 荣获 2024 年 DBTA “最佳数据库性能解决方案”读者选择奖
近期,Navicat 以其卓越的服务器监控与深度分析能力在众多杰出竞争者中脱颖而出,其监控产品 Navicat Monitor 荣获了 2024 年度 DBTA 读者选择奖中的“最佳数据库性能解决方案”殊荣。该奖项不仅是对 Navicat Monitor 在数据库监控与分析领域非凡实力的权…...

[论文笔记]ZeRO: Memory Optimizations Toward Training Trillion Parameter Models
引言 今天带来ZeRO: Memory Optimizations Toward Training Trillion Parameter Models的论文笔记。 大型深度模型提供了显著的准确性提升,但训练数十亿到数万亿个参数是具有挑战性的。现有的解决方案,如数据并行和模型并行,存在基本的局限…...

shuashuashua
CVE-2023-2130 靶标介绍: 在SourceCodester采购订单管理系统1.0中发现了一项被分类为关键的漏洞。受影响的是组件GET参数处理器的文件/admin/suppliers/view_details.php中的一个未知函数。对参数id的操纵导致了SQL注入。可以远程发起攻击。 通过标靶介绍可以知道…...

k8s之HPA
目录 1.HPA 2.部署 metrics-server 3.部署 HPA 4.总结 1.HPA HPA(Horizontal Pod Autoscaling)Pod 水平自动伸缩,Kubernetes 有一个 HPA 的资源,HPA 可以根据 CPU 利用率自动伸缩一个 Replication Controller、 Deployment 或…...

fun状态上传,并可手动控制
文章目录 引言上传原因:矛盾点:基础工程源码: 代码实操fun状态上传fun状态下发控制 引言 上传原因: 续上一节, 我们把fun像小灯一样, 加入了预警工程, 但是我们fun其实还有其他用处, 比如我们人工手动开风扇, 排风, 所以我们需要把fun的状态上传, 然后也可以通过服务器手动控制…...

【Canvas与艺术】四扇叶结
注意:此是一个看起来简单,实际上需要细细计算调整的拓扑图。 【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head&…...

基于DVWA-Brute Force(LowMedium)的渗透测试
Brute force主要是通过爆破达到渗透目的: Low 查看源代码: <?phpif( isset( $_GET[ Login ] ) ) {// Get username$user $_GET[ username ];// Get password$pass $_GET[ password ];$pass md5( $pass );// Check the database$query "SE…...

水库大坝安全预警系统的作用
“汛情就是命令,防汛就是责任”,为了防治和减轻洪涝带来的危害,需要一种以预警为先导的临灾位移监测系统--水库大坝安全预警系统,对可能会出现的灾害进行实时远程监控,尽可能做到隐患早发现、早决策、早治理࿰…...

容器化部署ES集群
文章目录 一、ElasticSearch基本概念1、索引(Index)2、文档(Document)3、分片和副本4、映射(Mapping) 二、容器部署ElasticSearch集群三、容器部署ElasticSearch伪集群 一、ElasticSearch基本概念 1、索引(Index) 在ElasticSearch中,索引是文档的集合,类…...

使用排名前三的华为解锁工具来绕过忘记的华为锁屏密码
如果您在未使用“设置”应用的情况下将华为手机恢复出厂设置,同时启用了出厂重置保护 (FRP) 安全功能,您的华为设备将卡在帐户验证界面。您可以使用帐户凭据轻松绕过此锁定。但是,假设您无法回忆起旧的帐户信息。在这种情况下,您应…...

战神之父和前暴雪总裁都很期待《黑神话》:太酷想玩
近日《战神》之父David Jaffe在油管上发布视频,分享了他对《黑神话:悟空》的看法。他表示自己一直很关注这款游戏,该作的最终预告画面让他惊讶。而战斗部分更是让他大呼:“OMG”。 David Jaffe表示:“我必须要购买《黑…...

用户体验的优化:观测云在用户行为分析中的应用
在数字化商业环境中,用户体验的质量直接影响到品牌形象和客户忠诚度。观测云平台,作为一款专业的数据监控和分析工具,为企业提供了一个全面的解决方案,以深入分析用户行为并优化用户体验。 观测云的核心优势在于其能够实时处理和…...

ModelScope 部署 Flux 模型
Flux 文生图模型,是 Black Forest Labs 最近发布的模型,图片生成清晰度很高,模型可以在 ModelScope 上进行下载,本文将在本地环境中部署 Flex。使用环境如下 2080 TI 22GUbuntu 22Amd R7 2700 / 128G 启动 Model Scope 容器 Mo…...

ArkTs基础语法-声明式UI-基本概念
声明式UI语法 基本概念声明式UI描述创建组件无参数有参数 配置属性配置事件 配置子组件 基本概念 装饰器:用于装饰类、结构、方法及变量,并赋予其特殊的含义。 例如: Entry 有该装饰器的自定义组件,可以在UIAbility中使用…...

Day26 线程学习
线程相关知识总结 在多线程编程中,线程的管理和控制是非常重要的部分。本文将对线程的创建、取消、资源回收、竞争及顺序等方面进行详细总结。 一、线程的基本操作 pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*…...

eNSP 华为三层交换机实现VLAN间通信
华为三层交换机实现VLAN间通信 三层交换机: <Huawei>sys [Huawei]sys SW-3 [SW-3]vlan batch 10 20 [SW-3]int vlan 10 [SW-3-Vlanif10]ip address 192.168.10.254 24 [SW-3-Vlanif10]int vlan 20 [SW-3-Vlanif20]ip add 192.168.20.254 24 [SW-3-Vlanif20]in…...

【多模态大模型】LLaMA in arXiv 2023
一、引言 论文: LLaMA: Open and Efficient Foundation Language Models 作者: Meta AI 代码: LLaMA 特点: 该方法在Transformer的基础上增加了Pre-normalization (RMSNorm)、SwiGLU activation function (SwiGLU)、Rotary Embed…...

(转)java中restful接口和普通接口的区别
RESTful接口是一种遵循REST(Representational State Transfer)架构风格的网络接口,设计上更倾向于资源的表述,通过HTTP方法(如GET、POST、PUT、DELETE)直接操作资源,使得接口更简洁、易于理解和维护。 与普通接口相比…...

灵办AI免费ChatGPT4人工智能浏览器插件快速便捷(多功能)
灵办AI就是您所需的最佳助手!我们为您带来了一款多功能AI工具,不仅能为您提供精准翻译,还能满足您的对话需求、智能续写、AI搜索、文档阅读、代码生成与修正等多种需求。灵办 AI,真正让工作和学习变得轻松高效! 推荐使…...