【HarmonyOS】鸿蒙应用蓝牙功能实现 (三)

news2024/9/23 15:52:06

【HarmonyOS】鸿蒙应用蓝牙功能实现 (三)

前言

今天整理蓝牙Demo代码,查看官网时发现自己帐号没有登录,竟然也可以访问最新的API文档,真是喜大奔普。看来华为已经开始对外开放最新的API文档,不再有白名单限制了。

在这里插入图片描述

HarmonyOS NEXTDeveloper Beta5

接下来讲解蓝牙配对流程。低功耗蓝牙BLE模式将在下面章节讲解。

蓝牙配对业务流程

1‌.设备进入可被发现模式‌:
首先,设备需要进入可被发现模式,这样周围的蓝牙设备才能识别到它。一方设备(如手机)会主动搜索附近的蓝牙设备,并列出所有可用的配对选项。

2‌.选择并触发配对请求‌:
用户从列表中选择想要连接的设备,并触发配对请求。此时,双方设备会交换一系列的身份验证信息,以确保彼此的身份安全无误。在这个过程中,可能会要求用户输入配对码(如PIN码)或在设备上确认配对请求。

3‌.身份验证和加密‌:
一旦身份验证通过,设备间就会建立安全的连接通道,这一过程称为“配对成功”。配对完成后,设备之间的连接就建立了,它们可以开始传输数据。

4‌.数据传输‌:
设备间通过蓝牙进行数据传输,可以传输音频、文件等多种类型的数据。

5‌.断开连接‌:
当数据传输完成后,蓝牙设备可以断开连接。断开连接的操作可以通过设备上的按钮或者软件来实现。

蓝牙配对通常是一次性的,即一旦设备成功配对,它们会在后续的连接中自动识别并连接,无需再次进行配对过程(除非设备被重置或用户手动取消配对)

以下是传统的蓝牙配对流程图仅供参考:
在这里插入图片描述

常规蓝牙配对Demo

在这里插入图片描述

Demo包括以下内容:
1.蓝牙权限开启
2.蓝牙开启/关闭
3.蓝牙扫描开启/关闭
4.蓝牙配对
5.蓝牙code协议确认

蓝牙UI交互类

import { access } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { BlueToothMgr } from '../manager/BlueToothMgr';
import { abilityAccessCtrl, common } from '@kit.AbilityKit';
import { connection } from '@kit.ConnectivityKit';
import { map } from '@kit.ConnectivityKit';
import { pbap } from '@kit.ConnectivityKit';
import { HashMap } from '@kit.ArkTS';
import { DeviceInfo } from '../info/DeviceInfo';
import { promptAction } from '@kit.ArkUI';



struct Index {

  private TAG: string = "BlueToothTest";

  // 扫描状态定时器
  private mNumInterval: number = -1;
  // 当前设备蓝牙名
   mCurrentDeviceName: string = "";
  // 蓝牙状态
   ('onChangeBlueTooth') isStartBlueTooth: boolean = false;
  // 蓝牙扫描状态
   ('onChangeBlueTooth') isStartScan: boolean = false;
  // 当前蓝牙权限
   userGrant: boolean = false;
  // 扫描到设备名
   mMapDevice: HashMap<string, DeviceInfo> = new HashMap();
  // ui展现的设备列表
   mListDeviceInfo: Array<DeviceInfo> = new Array();

  async aboutToAppear() {
    await this.requestBlueToothPermission();

    let state = access.getState();
    console.log(this.TAG, "getState state: " + state);
    if(state == 2){
      this.isStartBlueTooth = true;
      console.log(this.TAG, "getState isStartBlueTooth: " + this.isStartBlueTooth);
    }else{
      this.isStartBlueTooth = false;
      console.log(this.TAG, "getState isStartBlueTooth: " + this.isStartBlueTooth);
    }
  }

  private onChangeBlueTooth(){
    if(!this.isStartBlueTooth){
      this.mMapDevice = new HashMap();
      return;
    }

    this.mCurrentDeviceName = BlueToothMgr.Ins().getCurrentDeviceName();
  }

  // 用户申请权限
  async reqPermissionsFromUser(): Promise<number[]> {
    let context = getContext() as common.UIAbilityContext;
    let atManager = abilityAccessCtrl.createAtManager();
    let grantStatus = await atManager.requestPermissionsFromUser(context, ['ohos.permission.ACCESS_BLUETOOTH']);
    return grantStatus.authResults;
  }

  // 用户申请蓝牙权限
  async requestBlueToothPermission() {
    let grantStatus = await this.reqPermissionsFromUser();
    for (let i = 0; i < grantStatus.length; i++) {
      if (grantStatus[i] === 0) {
        // 用户授权,可以继续访问目标操作
        this.userGrant = true;
        promptAction.showToast({ message: "蓝牙授权成功!"});
      }else{
        promptAction.showToast({ message: "蓝牙授权失败!"});
      }
    }
  }

  setBlueToothScan = ()=>{
    if(!this.isStartScan){
      promptAction.showToast({ message: "开启扫描!"});
      BlueToothMgr.Ins().startScanDevice((data: Array<string>)=>{
        let deviceId: string = data[0];
        if(this.mMapDevice.hasKey(deviceId)){
          // 重复设备,丢弃不处理
        }else{
          // 添加到表中
          let deviceInfo: DeviceInfo = new DeviceInfo();
          deviceInfo.deviceId = deviceId;
          deviceInfo.deviceName = BlueToothMgr.Ins().getDeviceName(deviceId);
          deviceInfo.deviceClass = BlueToothMgr.Ins().getDeviceClass(deviceId);
          this.mMapDevice.set(deviceId, deviceInfo);
          this.mListDeviceInfo = this.mListDeviceInfo.concat(deviceInfo);
        }
      });
      this.mMapDevice.clear();
      this.mListDeviceInfo = [];
      // 开启定时器
      this.mNumInterval = setInterval(()=>{
        let discovering = BlueToothMgr.Ins().isCurrentDiscovering();
        if(!discovering){
          this.closeScanDevice();
        }
      }, 1000);
      this.isStartScan = true;
    }else{
      promptAction.showToast({ message: "关闭扫描!"});
      BlueToothMgr.Ins().stopScanDevice();
      this.closeScanDevice();
    }
  }

  private closeScanDevice(){
    clearInterval(this.mNumInterval);
    this.isStartScan = false;
  }

  setBlueToothState = ()=>{
    try {
      if(!this.isStartBlueTooth){
        // 开启蓝牙
        BlueToothMgr.Ins().setBlueToothAccess(true, (state: access.BluetoothState) => {
          console.log(this.TAG, "getState setBlueToothAccessTrue: " + state);
          if(state == access.BluetoothState.STATE_ON){
            this.isStartBlueTooth = true;
            promptAction.showToast({ message: "开启蓝牙!"});
            console.log(this.TAG, "getState isStartBlueTooth: " + this.isStartBlueTooth);
          }
        });
      }else{
        BlueToothMgr.Ins().setBlueToothAccess(false, (state: access.BluetoothState) => {
          console.log(this.TAG, "getState setBlueToothAccessFalse: " + state);
          if(state == access.BluetoothState.STATE_OFF){
            this.isStartBlueTooth = false;
            promptAction.showToast({ message: "关闭蓝牙!"});
            console.log(this.TAG, "getState isStartBlueTooth: " + this.isStartBlueTooth);
          }
        });
      }
    } catch (err) {
      console.error(this.TAG,'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  private isLog(){
    console.log(this.TAG, "isLog isStartBlueTooth: " + this.isStartBlueTooth);
    return true;
  }

  build() {
    Column() {
      if(this.userGrant){
        if(this.isLog()){
          Text("当前蓝牙设备信息:\n " + this.mCurrentDeviceName)
            .fontSize(px2fp(80))
            .margin({ top: px2vp(100) })
            .fontWeight(FontWeight.Bold)

          Text(this.isStartBlueTooth ? "蓝牙状态: 开启" : "蓝牙状态: 关闭")
            .fontSize(px2fp(80))
            .margin({ top: px2vp(100) })
            .fontWeight(FontWeight.Bold)
            .onClick(this.setBlueToothState)

          Text(this.isStartScan ? "蓝牙扫描: 开启ing" : "蓝牙扫描: 关闭")
            .margin({ top: px2vp(100) })
            .fontSize(px2fp(80))
            .fontWeight(FontWeight.Bold)
            .onClick(this.setBlueToothScan)

          this.ListView()
        }
      }
    }
    .justifyContent(FlexAlign.Center)
    .height('100%')
    .width('100%')
  }

   ListView(){
    List() {
      ForEach(this.mListDeviceInfo, (item: DeviceInfo, index: number) => {
        ListItem() {
          Column(){
            Row() {
              Text("设备ID: " + item.deviceId).fontSize(px2fp(42)).fontColor(Color.Black)
              Blank()
              Text("设备名: " + item.deviceName).fontSize(px2fp(42)).fontColor(Color.Black)
            }
            .width('100%')
            Text(item.deviceClass).fontSize(px2fp(42)).fontColor(Color.Black)
          }
          .width('100%')
          .height(px2vp(200))
          .justifyContent(FlexAlign.Start)
          .onClick(()=>{
            // 点击选择处理配对
            AlertDialog.show({
              title:"选择配对",
              message:"是否选择该设备进行蓝牙配对?",
              autoCancel: true,
              primaryButton: {
                value:"确定",
                action:()=>{
                  promptAction.showToast({ message: item.deviceName + "配对ing!"});
                  BlueToothMgr.Ins().pairDevice(item.deviceId);
                }
              },
              secondaryButton: {
                value:"取消",
                action:()=>{
                  promptAction.showToast({ message: "取消!"});
                }
              },
              cancel:()=>{
                promptAction.showToast({ message: "取消!"});
              }
            })
          })
        }
      }, (item: string, index: number) => JSON.stringify(item) + index)
    }
    .width('100%')
  }
}

蓝牙管理类

import { access, ble } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { connection } from '@kit.ConnectivityKit';

export class BlueToothMgr {

  private TAG: string = "BlueToothTest";

  private static mBlueToothMgr: BlueToothMgr | undefined = undefined;

  private advHandle: number = 0xFF; // default invalid value

  private mDeviceDiscoverArr: Array<string> = new Array<string>();

  public static Ins(){
    if(!BlueToothMgr.mBlueToothMgr){
      BlueToothMgr.mBlueToothMgr = new BlueToothMgr();
      BlueToothMgr.init();
    }
    return BlueToothMgr.mBlueToothMgr;
  }

  private static init(){
    try {
      connection.on('pinRequired', (data: connection.PinRequiredParam) =>{
        // data为配对请求参数
        console.info("BlueToothTest",'pinRequired pin required = '+ JSON.stringify(data));
      });
    } catch (err) {
      console.error("BlueToothTest", 'pinRequired errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  /**
   * 当前设备蓝牙设备名称
   */
  public getCurrentDeviceName(){
    let localName: string = "";
    try {
      localName = connection.getLocalName();
      console.info(this.TAG, 'getCurrentDeviceName localName: ' + localName);
    } catch (err) {
      console.error(this.TAG, 'getCurrentDeviceName errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
    return localName;
  }

  /**
   * 当前设备蓝牙可发现状态
   */
  public isCurrentDiscovering(){
    let res: boolean = false;
    try {
      res = connection.isBluetoothDiscovering();
      console.info(this.TAG, 'isCurrentDiscovering isBluetoothDiscovering: ' + res);
    } catch (err) {
      console.error(this.TAG, 'isCurrentDiscovering errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
    return res;
  }

  // STATE_OFF	0	表示蓝牙已关闭。
  // STATE_TURNING_ON	1	表示蓝牙正在打开。
  // STATE_ON	2	表示蓝牙已打开。
  // STATE_TURNING_OFF	3	表示蓝牙正在关闭。
  // STATE_BLE_TURNING_ON	4	表示蓝牙正在打开LE-only模式。
  // STATE_BLE_ON	5	表示蓝牙正处于LE-only模式。
  // STATE_BLE_TURNING_OFF	6	表示蓝牙正在关闭LE-only模式。

  public getBlueToothState(): access.BluetoothState {
    let state = access.getState();
    return state;
  }

  /**
   * 设置蓝牙访问(开关状态)
   * @param isAccess true: 打开蓝牙
   */
  setBlueToothAccess(isAccess: boolean, callbackBluetoothState: Callback<access.BluetoothState>){
    try {
      if(isAccess){
        console.info(this.TAG, 'bluetooth enableBluetooth 1');
        access.enableBluetooth();
        console.info(this.TAG, 'bluetooth enableBluetooth 2');
        access.on('stateChange', (data: access.BluetoothState) => {
          let btStateMessage = this.switchState(data);
          if (btStateMessage == 'STATE_ON') {
            access.off('stateChange');
          }
          console.info(this.TAG, 'bluetooth statues: ' + btStateMessage);
          callbackBluetoothState(data);
        })
      }else{
        console.info(this.TAG, 'bluetooth disableBluetooth 1');
        access.disableBluetooth();
        console.info(this.TAG, 'bluetooth disableBluetooth 2');
        access.on('stateChange', (data: access.BluetoothState) => {
          let btStateMessage = this.switchState(data);
          if (btStateMessage == 'STATE_OFF') {
            access.off('stateChange');
          }
          console.info(this.TAG, "bluetooth statues: " + btStateMessage);
          callbackBluetoothState(data);
        })
      }
    } catch (err) {
      console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  private switchState(data: access.BluetoothState){
    let btStateMessage = '';
    switch (data) {
      case 0:
        btStateMessage += 'STATE_OFF';
        break;
      case 1:
        btStateMessage += 'STATE_TURNING_ON';
        break;
      case 2:
        btStateMessage += 'STATE_ON';
        break;
      case 3:
        btStateMessage += 'STATE_TURNING_OFF';
        break;
      case 4:
        btStateMessage += 'STATE_BLE_TURNING_ON';
        break;
      case 5:
        btStateMessage += 'STATE_BLE_ON';
        break;
      case 6:
        btStateMessage += 'STATE_BLE_TURNING_OFF';
        break;
      default:
        btStateMessage += 'unknown status';
        break;
    }
    return btStateMessage;
  }

  /**
   * 主播蓝牙广播
   */
  public registerBroadcast(){
    try {
      ble.on('advertisingStateChange', (data: ble.AdvertisingStateChangeInfo) => {
        console.info(this.TAG, 'bluetooth advertising state = ' + JSON.stringify(data));
        AppStorage.setOrCreate('advertiserState', data.state);
      });
    } catch (err) {
      console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  /**
   * 开启蓝牙广播
   */
  public async startBroadcast(valueBuffer: Uint8Array){

    // 表示发送广播的相关参数。
    let setting: ble.AdvertiseSetting = {
      // 表示广播间隔,最小值设置160个slot表示100ms,最大值设置16384个slot,默认值设置为1600个slot表示1s。
      interval: 160,
      // 表示发送功率,最小值设置-127,最大值设置1,默认值设置-7,单位dbm。推荐值:高档(1),中档(-7),低档(-15)。
      txPower: 0,
      // 表示是否是可连接广播,默认值设置为true,表示可连接,false表示不可连接。
      connectable: true
    };

    // BLE广播数据包的内容。
    let manufactureDataUnit: ble.ManufactureData = {
      // 表示制造商的ID,由蓝牙SIG分配。
      manufactureId: 4567,
      manufactureValue: valueBuffer.buffer
    };

    let serviceValueBuffer = new Uint8Array(4);
    serviceValueBuffer[0] = 5;
    serviceValueBuffer[1] = 6;
    serviceValueBuffer[2] = 7;
    serviceValueBuffer[3] = 8;

    // 广播包中服务数据内容。
    let serviceDataUnit: ble.ServiceData = {
      serviceUuid: "00001888-0000-1000-8000-00805f9b34fb",
      serviceValue: serviceValueBuffer.buffer
    };

    // 表示广播的数据包内容。
    let advData: ble.AdvertiseData = {
      serviceUuids: ["00001888-0000-1000-8000-00805f9b34fb"],
      manufactureData: [manufactureDataUnit],
      serviceData: [serviceDataUnit],
      includeDeviceName: false // 表示是否携带设备名,可选参数。注意带上设备名时广播包长度不能超出31个字节。
    };

    // 表示回复扫描请求的响应内容。
    let advResponse: ble.AdvertiseData = {
      serviceUuids: ["00001888-0000-1000-8000-00805f9b34fb"],
      manufactureData: [manufactureDataUnit],
      serviceData: [serviceDataUnit]
    };

    // 首次启动广播设置的参数。
    let advertisingParams: ble.AdvertisingParams = {
      advertisingSettings: setting,
      advertisingData: advData,
      advertisingResponse: advResponse,
      // 	表示发送广播持续的时间。单位为10ms,有效范围为1(10ms)到65535(655350ms),如果未指定此参数或者将其设置为0,则会连续发送广播。
      duration: 0 // 可选参数,若大于0,则广播发送一段时间后,则会临时停止,可重新启动发送
    }

    // 首次启动广播,且获取所启动广播的标识ID
    try {
      this.registerBroadcast();
      this.advHandle = await ble.startAdvertising(advertisingParams);
    } catch (err) {
      console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  /**
   * 开始蓝牙扫描
   */
  public startScanDevice(callback: Callback<Array<string>>){
    try {
      connection.on('bluetoothDeviceFind', (data: Array<string>)=>{
        // 随机MAC地址
        console.info(this.TAG, 'bluetooth device bluetoothDeviceFind = '+ JSON.stringify(data));
        callback(data);
      });
      connection.startBluetoothDiscovery();
    } catch (err) {
      console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  /**
   * 停止蓝牙扫描
   */
  public stopScanDevice(){
    try {
      connection.off('bluetoothDeviceFind');
      connection.stopBluetoothDiscovery();
    } catch (err) {
      console.error(this.TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

  public getDeviceName(deviceID: string){
    let remoteDeviceName: string = "";
    try {
      remoteDeviceName = connection.getRemoteDeviceName(deviceID);
      console.info(this.TAG, 'getDeviceName device = '+ JSON.stringify(remoteDeviceName));
    } catch (err) {
      console.error(this.TAG, 'getDeviceName errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
    return remoteDeviceName;
  }

  public getDeviceClass(deviceID: string){
    let remoteDeviceClass: string = "";
    try {
      let classObj = connection.getRemoteDeviceClass(deviceID);
      remoteDeviceClass = JSON.stringify(classObj);
    } catch (err) {
      console.error(this.TAG, 'getDeviceName errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
    return remoteDeviceClass;
  }

  // BondState
  // BOND_STATE_INVALID	0	无效的配对。
  // BOND_STATE_BONDING	1	正在配对。
  // BOND_STATE_BONDED	2	已配对。

  /**
   * 发起配对蓝牙
   */
  public pairDevice(deviceID: string){
    try {
      connection.on('bondStateChange', (data: connection.BondStateParam) =>{
        console.info(this.TAG, 'pairDevice pair state = '+ JSON.stringify(data));
        // 当蓝牙配对类型PinType为PIN_TYPE_ENTER_PIN_CODE或PIN_TYPE_PIN_16_DIGITS时调用此接口,请求用户输入PIN码。
      });
      connection.pairDevice(deviceID, (err: BusinessError) => {
        console.info(this.TAG, 'pairDevice device name err:' + JSON.stringify(err));
      });
    } catch (err) {
      console.error(this.TAG, 'pairDevice errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
    }
  }

}

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/fda00352f394401cbc3a6b884469f6ce.png在这里插入图片描述

DEMO完成示例资源下载链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2074335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode每日刷题之面试题01.06字符串压缩(C++)

1.题目解析 本题的目的是遍历一个字符串&#xff0c;将重复的字符串以该字符出现次数进行压缩&#xff0c;最终返回压缩后的字符串即可 题目来源&#xff1a;面试题01.06.字符串压缩 2.算法原理 我们从左往右遍历字符串&#xff0c;用 ch 记录当前要压缩的字符&#xff0c;cnt …

交叉编译Qt5.12.8附带编译opengl

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、重要说明二、准备环境1.下载qt5.12.8源代码2.配置系统环境3.安装必要工具4.解压qt5源代码5.开始配置编译6.配置qtcreator 三、编译opengl总结 前言 最近有…

zdppy+vue3+onlyoffice文档管理系统实战 20240825上课笔记 zdppy_cache框架增加resize清理缓存的方法

遗留问题 设置缓存&#xff0c;已完成获取缓存&#xff0c;已实现删除缓存&#xff0c;已实现查询所有key&#xff0c;带查询参数&#xff1a;active只查激活的&#xff0c;value包含value默认只获取key查询缓存大小清空缓存判断是否为管理员 实现删除缓存的接口 async def …

[C语言]一、C语言基础

G:\Cpp\C语言精讲 1. C语言入门 1.1 初识计算机语言 计算机编程语言&#xff0c;就是人与计算机交流的方式。人们可以使用编程语言对计算机下达命令&#xff0c;让计算机完成人们需要的功能。 计算机语言有很多种。如&#xff1a;C 、C、Java、Go、JavaScript、Python&#x…

音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息

通过FFprobe命令可以显示WAV音频文件每个packet&#xff08;也称为数据包或多媒体包&#xff09;的信息&#xff1a; ffprobe -of json -show_packets XXX.wav 输出如下&#xff1a; 其中&#xff1a; 1.codec_type&#xff1a;packet类型&#xff0c;表示该路流是视频还是音…

【CSS】使用 CSS 自定义属性(变量)-- var()

自定义属性&#xff08;有时候也被称作CSS 变量或者级联变量&#xff09;是由 CSS 作者定义的&#xff0c;它包含的值可以在整个文档中重复使用。由自定义属性标记设定值&#xff08;比如&#xff1a; --main-color: black;&#xff09;&#xff0c;由 var() 函数来获取值&…

一台电脑配置两个Git账号(github和gitlab),不同仓库使用不同的git

我们工作时一般都是使用gitlab&#xff0c;工作电脑也一般配置的 git 是连接 gitlab 的&#xff0c;那么当我们如果想用同一个电脑实现不同仓库根据自己的需要到底是推送代码到github还是 gitlab&#xff0c;以及使用哪个账号&#xff0c;(比如如果想用工作电脑维护自己的 gith…

C语言学习,Turbo C 开发环境回顾

&#xff08;1&#xff09;Turbo C 集成开发环境&#xff1a; &#xff08;2&#xff09;按AltF&#xff0c;进入File菜单&#xff1a; &#xff08;3&#xff09;按AltR&#xff0c;进入Run菜单&#xff1a; &#xff08;4&#xff09;按AltC&#xff0c;进入Compile菜单&…

Java 入门指南:Java 泛型(generics)

Java 泛型概要 Java 泛型&#xff08;generics&#xff09; 是 JDK 5 中引入的一个新特性。泛型的本质是参数化类型&#xff0c;也就是所操作的数据类型被指定为一个参数&#xff08;可以称之为类型形参&#xff0c;然后在使用/调用时传入具体的类型。&#xff09; 使用 Java …

【机器学习】特征工程的基本概念以及LASSO回归和主成分分析优化方法

引言 特征工程是机器学习中的一个关键步骤&#xff0c;它涉及到从原始数据中提取和构造新的特征&#xff0c;以提高模型的性能和预测能力LASSO&#xff08;Least Absolute Shrinkage and Selection Operator&#xff09;回归是一种用于回归分析的线性模型&#xff0c;它通过引入…

字节跳动-生活服务-java后端-一面

基础题 计算机网络 1.tcp三次握手和四次挥手&#xff1f;tcp的第三次握手可以传输应用层数据嘛&#xff1f; 4.1 TCP 三次握手与四次挥手面试题 | 小林coding (xiaolincoding.com) 2.描述一下打开百度首页后发生的网络过程&#xff1f; 计算机网络面试题 | 小林coding (xi…

linux-基础知识1

简单命令 init 0 关机 int 6 重启 pwd 查看当前所在目录&#xff0c; cd切换目录 ls 列出目录下的内容 clear 清屏 date 查看时间 路径 linux表示硬件设备的文件在dev目录 /tmp是临时目录&#xff0c;可以创建目录和文件&#xff0c;但不能保证安全 df查看文件系统…

数据仓库系列 1:什么是数据仓库,它与传统数据库有什么不同?

想象一下,你正站在一座巨大的仓库前。这座仓库不是用来存放普通商品的,而是存储着海量的数据 - 这就是数据仓库。在大数据时代,数据仓库已经成为企业数据管理的核心。但它究竟是什么?又为什么如此重要?让我们一起揭开数据仓库的神秘面纱,探索它与我们熟知的传统数据库有何不同…

IDEA2023的激活与安装

前言 开始了java的学习之旅&#xff0c;当然少不了IDEA这个得力的开发工具软件。但是IDEA是付费的&#xff0c;免费版功能有太少&#xff0c;怎么使用上正式版呢&#xff01;当然还是激活啦 第一步&#xff1a;官网下载安装包 安装步骤就不展现了&#xff0c;无脑下一步就可以…

【学习笔记】技术分析-华为智驾控制器MDC Pro 610分析

华为的智能驾驶控制器一直在迭代&#xff0c;和网络上广泛披露的早期MDC 610相比&#xff0c;华为 MDC Pro 610 智能驾驶控制器&#xff0c;现在的样品设计采用了海思的双系统级芯片 (SoC) 提高了处理能力&#xff0c;三星的存储模块为无缝数据处理提供了充足的内存&#xff0c…

高并发业务下的无损技术方案设计

0 前言 秒杀&#xff0c;既有需求真实且迫切的用户&#xff0c;也有试图牟利的黄牛。系统挑战&#xff0c;就是相较于以往千倍万倍的用户规模&#xff0c;可能是真人可能是机器人&#xff0c;在同一瞬间对系统发起冲击&#xff0c;需要海量的计算资源才能支撑。 秒杀系统的设计…

Long Short-Term Memory

这篇论文总结的太抽象了&#xff0c;只是翻译了一遍。 &#xff08;我太笨了&#xff0c;如果把这个当我的入门读物&#xff0c;我觉着会把我折磨坏&#xff09; 递归神经网络的一个重要优点是它们在映射输入和输出序列时使用上下文信息的能力。不幸的是&#xff0c;对于标准的…

51单片机——按键控制

1、按键介绍 轻触按键&#xff1a;相当于是一种电子开关&#xff0c;按下时开关接通&#xff0c;松开时开关断开&#xff0c;实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。 2、按键的抖动 对于机械开关&#xff0c;当机械触点断开、闭合时&#xff0c;由于…

基于SpringBoot+Vue的家教管理系统

文章目录 前言1.项目类型2.技术栈介绍1.客户端技术栈介绍2.服务端技术栈介绍 3.功能介绍1.客户端功能2.服务单功能 4.项目亮点5.适用场景6.项目展示1.客户端展示2.服务端展示 7.诚邀参与 前言 大家好&#xff0c;我是执手天涯&#xff0c;今天非常荣幸地向大家介绍一款基于Spr…

关于ssrf的实现

ssrf漏洞形成 SSRF(Server-Side Request Forgery:服务器端请求伪造)漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求的内容的URL参数&#xff0c;并且未对客户端所传输过来的URL参数进行过滤 ssrf实现 本次ssrf于Pikachu靶场上实现 我们可以先拉取镜像 docker …