蓝牙单点技术实现路径介绍
本文主要介绍蓝牙设备与手机一对一相连的 蓝牙单点 技术。
准备工作
- 系统要求:蓝牙使用需要安卓 4.3 以及以上版本,智能生活 App SDK 从安卓 4.4 开始支持。
- Manifest 权限:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
- 蓝牙权限检测:每次扫描和连接前,都要进行检测,否则 App 无法正常使用蓝牙。
- App 在使用蓝牙连接或者扫描操作前,需要检查 App 定位权限是否被允许。
- 检查蓝牙状态是否为开启。
说明:该部分检查逻辑,智能生活 SDK 未提供 API,您可自行检测。
扫描设备
开始扫描
待配网的蓝牙设备会向周围发送蓝牙广播包,SDK 会根据协议对广播包进行解析发现周围的涂鸦蓝牙单点设备和双模设备等。
⚠️注意:蓝牙设备扫描前需要进行权限检测,只有具备权限才能正常扫描:
- 蓝牙是否打开。
- 应用是否具有定位权限。
接口说明
void startLeScan(LeScanSetting setting, TyBleScanResponse response);
参数说明
参数 | 类型 | 说明 |
---|---|---|
setting | LeScanSetting | 扫描的设置 |
response | TyBleScanResponse | 扫描结果的回调,不能为空 |
构建类说明
LeScanSetting.Builder
用于构建需要扫描设备的设置。
方法名 | 参数 | 说明 | 是否必需 |
---|---|---|---|
setTimeout() | long | 设置超时时间 默认:40000;单位:毫秒 | 可选 |
addScanType() | ScanType |
| 必需 |
setRepeatFilter() | boolean | 重复过滤,默认:true | 可选 |
示例代码
LeScanSetting scanSetting = new LeScanSetting.Builder().setTimeout(60000) // 扫描的超时时间:ms.addScanType(ScanType.SINGLE) // 若需要扫描蓝牙设备,则只需要添加 ScanType.SINGLE// .addScanType(ScanType.SIG_MESH) 可同时添加其他类型设备.build();// 开始扫描
TuyaHomeSdk.getBleOperator().startLeScan(scanSetting, new TyBleScanResponse() {@Overridepublic void onResult(ScanDeviceBean bean) {// 回调扫描的结果 TODO}
});
回调说明
ScanDeviceBean
说明
属性 | 类型 | 说明 |
---|---|---|
id | String | 扫描 ID 通常由 UUID 组成,可以唯一区别设备 |
name | String | 扫描到的蓝牙名称,一般为空 |
providerName | String | 取值为 SingleBleProvider 则表示只开发单点设备,您无需关注该字段 |
data | byte[] | 原始数据 |
configType | String |
|
productId | String | 产品 ID |
uuid | String | 设备 UUID,设备唯一码 |
mac | String | 设备 Mac,不可作为唯一码 |
isbind | boolean | 设备是否被绑定,能回调的均为未配网的设备 |
flag | int |
|
address | String | 设备地址 |
deviceType | int | 设备类型,用于区分不同协议的设备,您无需关注该字段 |
deviceType
表示待配网设备类型,若带有 Wi-Fi
的双模设备见 双模配网,蓝牙设备见 蓝牙配网。
deviceType 值 | configType | 设备类型 |
---|---|---|
200 | config_type_single | 蓝牙设备 |
300 | config_type_single | 蓝牙设备 |
301 | config_type_wifi | Wi-Fi + 蓝牙双模设备 |
304 | config_type_wifi | Wi-Fi + 蓝牙双模设备(支持蓝牙兜底配网) |
400 | config_type_single | 蓝牙设备 |
401 | config_type_wifi | Wi-Fi + 蓝牙双模设备 |
404 | config_type_wifi | Wi-Fi + 蓝牙双模设备(支持蓝牙兜底配网) |
查询设备名称
扫描到目标设备以后,可以通过查询显示产品配置的名称和图标。
接口说明
void getActivatorDeviceInfo(String productId, String uuid, String mac, ITuyaDataCallback<ConfigProductInfoBean> callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
productId | String | ScanDeviceBean.getProductId |
uuid | String | ScanDeviceBean.getUuid |
mac | String | ScanDeviceBean.getMac 该值一般设备为 null ,只有某些品类有值 |
示例代码
TuyaHomeSdk.getActivatorInstance().getActivatorDeviceInfo(scanDeviceBean.getProductId(),scanDeviceBean.getUuid(),scanDeviceBean.getMac(),new ITuyaDataCallback<ConfigProductInfoBean>() {@Overridepublic void onSuccess(ConfigProductInfoBean result) {}@Overridepublic void onError(String errorCode, String errorMessage) {}
});
回调说明
ConfigProductInfoBean
说明
属性 | 类型 | 说明 |
---|---|---|
name | String | 产品名称,云端配置,一般是用户首次创建产品时的名称 |
icon | String | 产品图标 |
停止扫描
当退出配网页面或者在执行设备入网时,建议停止设备扫描,以防止扫描影响到配网过程。
接口说明
void stopLeScan();
代码示例
TuyaHomeSdk.getBleOperator().stopLeScan();
单点设备配网
开始单点设备入网
扫描到的设备的 configType
属性取值为 config_type_single
表示单点蓝牙设备,config_type_wifi
为双模设备。
接口说明
void startActivator(BleActivatorBean bleActivatorBean, IBleActivatorListener listener);
参数说明
参数 | 类型 | 说明 |
---|---|---|
bleActivatorBean | BleActivatorBean | 需要连接的设备的参数集合 |
listener | IBleActivatorListener | 配网结果的回调 |
BleActivatorBean
用于存放需要配网设备的参数以及设置。
属性 | 类型 | 说明 | 是否必需 |
---|---|---|---|
homeId | long | 当前家庭 ID | 必需 |
uuid | String | 设备 UUID,通过扫描可以查询 | 必需 |
address | String | 设备地址,通过扫描可以查询 | 可选 |
productId | String | 产品 ID,通过扫描可以查询 | 可选 |
deviceType | Integer | 设备类型,通过扫描可以查询 | 必需 |
isShare | boolean | 是否为共享设备,通过扫描可以查询,默认为 false | 可选 |
timeout | long | 配网总超时,配网超时失败以该参数为准。 单位:毫秒,默认:60000 | 可选 |
代码示例
BleActivatorBean bleActivatorBean = new BleActivatorBean();// mScanDeviceBean 来自于扫描回调的 ScanDeviceBean
bleActivatorBean.homeId = 123456; // homeId
bleActivatorBean.address = mScanDeviceBean.getAddress(); // 设备地址
bleActivatorBean.deviceType = mScanDeviceBean.getDeviceType(); // 设备类型
bleActivatorBean.uuid = mScanDeviceBean.getUuid(); // UUID
bleActivatorBean.productId = mScanDeviceBean.getProductId(); // 产品 ID
bleActivatorBean.isShare = (mScanDeviceBean.getFlag() >> 2) & 0x01 == 1; // 设备是否为共享类型的标志// 开始配网
TuyaHomeSdk.getActivator().newBleActivator().startActivator(bleActivatorBean, new IBleActivatorListener() {@Overridepublic void onSuccess(DeviceBean deviceBean) {// 配网成功}@Overridepublic void onFailure(int code, String msg, Object handle) {// 配网失败}
});
取消单点设备入网
配网过程中终止配网。
接口说明
void stopActivator(String uuid);
参数说明
参数 | 类型 | 说明 |
---|---|---|
uuid | String | 扫描到的设备的 UUID,即 ScanDeviceBean.uuid |
示例代码
TuyaHomeSdk.getBleManager().stopBleConfig("uuid");
双模设备配网
双模设备入网
双模设备扫描到后,可以进行入网激活扫描到的设备。configType
属性取值为 config_type_single
表示单点蓝牙设备,config_type_wifi
为双模设备。
接口说明
void startActivator(MultiModeActivatorBean multiModeActivatorBean, IMultiModeActivatorListener listener);
参数说明
参数 | 类型 | 说明 |
---|---|---|
multiModeActivatorBean | MultiModeActivatorBean | 需要配网的双模设备参数集合 |
listener | IMultiModeActivatorListener | 配网结果回调 |
MultiModeActivatorBean
说明
属性 | 类型 | 说明 |
---|---|---|
deviceType | Integer | 设备类型,通过扫描可以查询 |
uuid | String | 设备 UUID,通过扫描可以查询 |
address | String | 设备地址,通过扫描可以查询 |
mac | String | 设备 Mac,通过扫描可以查询 |
ssid | String | Wi-Fi SSID |
pwd | String | Wi-Fi 密码 |
token | String | 配网 Token,获取 Token 的方式与 Wi-Fi 设备配网一致。 |
homeId | long | 当前家庭的 ID |
timeout | long | 配网总超时,配网超时失败以该参数为准,单位为毫秒 |
说明:若未说明,一般设备只支持 2.4G 频段 Wi-Fi 配网,部分设备支持 5G,可以根据
ScanDeviceBean.flag
进行判定。
代码示例
MultiModeActivatorBean multiModeActivatorBean = new MultiModeActivatorBean();// mScanDeviceBean 来自于扫描回调的 ScanDeviceBean
multiModeActivatorBean.deviceType = mScanDeviceBean.getDeviceType(); // 设备类型
multiModeActivatorBean.uuid = mScanDeviceBean.getUuid(); // 设备 uuid
multiModeActivatorBean.address = mScanDeviceBean.getAddress(); // 设备地址
multiModeActivatorBean.mac = mScanDeviceBean.getMac(); // 设备 mac
multiModeActivatorBean.ssid = "WIFI_2.4G"; // Wi-Fi SSID
multiModeActivatorBean.pwd = "WIFI_PASSWORD"; // Wi-Fi 密码
multiModeActivatorBean.token = "abcd1234"; // 获取的 Token
multiModeActivatorBean.homeId = ; // 当前家庭 homeId
multiModeActivatorBean.timeout = 120000; // 超时时间// 开始配网
TuyaHomeSdk.getActivator().newMultiModeActivator().startActivator(multiModeActivatorBean, new IMultiModeActivatorListener() {@Overridepublic void onSuccess(DeviceBean deviceBean) {// 配网成功}@Overridepublic void onFailure(int code, String msg, Object handle) {// 配网失败}
});
回调说明
-
DeviceBean
:表示设备信息数据类型。 -
Object handle
:handle 返回类型是实体对象ConfigErrorBean
,参数说明如下:参数 类型 说明 name String 设备名称 errorCode String 错误码 devId String 设备 ID iconUrl String 设备图标 errorMsg String 错误信息
取消双模设备配网
说明:如果在配网过程中终止了配网,若设备已经进行到云端激活阶段,虽取消设备配网,但可能会配网成功。
接口说明
TuyaHomeSdk.getActivator().newMultiModeActivator().stopActivator(uuid);
参数说明
参数 | 类型 | 说明 |
---|---|---|
devUuid | String | 扫描到的设备的 UUID |
示例代码
TuyaHomeSdk.getActivator().newMultiModeActivator().stopActivator("uuidxxxx");
双模设备蓝牙兜底配网
部分双模设备拥有蓝牙兜底配网能力。用户使用 App 通过手机蓝牙,将设备连云所需信息传输给待配网设备,设备会尝试连接 Wi-Fi。若激活云端链路失败,会启动本地连接模式,使用手机蓝牙直接与设备通信。
说明:判断扫描到的设备是否拥有蓝牙兜底配网能力,可以通过
ScanDeviceBean
的getDeviceType()
方法查询。返回值为404
或304
,则表示该设备拥有蓝牙兜底配网能力。其它结果则表示没有该能力。
接口说明
void startActivator(MultiModeActivatorBean multiModeActivatorBean, IMultiModeActivatorListener listener);
MultiModeActivatorBean
说明
参数 | 类型 | 说明 |
---|---|---|
homeId | long | 将设备添加到指定 ID 的家庭中 |
uuid | String | 需要配网的设备 UUID |
deviceType | int | 设备类型 |
address | String | 设备地址 |
timeout | long | 设备配网超时总时长,单位为 ms |
phase1Timeout | long | 设备连云激活配网超时时长,默认:60000,单位:ms |
ssid | String | 需要连接的 Wi-Fi SSID |
pwd | String | 需要连接的 Wi-Fi 密码,若无密码则传空字符串 |
token | String | 从云端查询的账号身份认证信息,获取 Token 的方式与 Wi-Fi 设备配网一致 |
mac | String | 设备 Mac 地址 |
说明:若未说明,一般设备只支持 2.4G 频段 Wi-Fi 配网,部分设备支持 5G。可以根据
ScanDeviceBean.flag
进行判定。
代码示例
// scanDeviceBean 为蓝牙扫描到的设备信息回调
MultiModeActivatorBean multiModeActivatorBean = new MultiModeActivatorBean();
// 设置 Wi-Fi 的 SSID
multiModeActivatorBean.ssid = "SSID_xxx";
// 设置 Wi-Fi 的密码
multiModeActivatorBean.pwd = "pwd_xxx";
// 设置设备 UUID
multiModeActivatorBean.uuid = scanDeviceBean.getUuid();
// 设置设备类型
multiModeActivatorBean.deviceType = scanDeviceBean.getDeviceType();
// 设置设备 Mac 地址
multiModeActivatorBean.mac = scanDeviceBean.getMac();
// 设置设备地址
multiModeActivatorBean.address = scanDeviceBean.getAddress();
// 设置 HomeID
multiModeActivatorBean.homeId = "homeId_xxx";
// 设置获取到的 Token
multiModeActivatorBean.token = "token_xxx";
// 设置配网总超时,单位:ms
multiModeActivatorBean.timeout = 120 * 1000L;
// 设置仅 Wi-Fi 连接的超时,单位:ms
multiModeActivatorBean.phase1Timeout = 60 * 1000L;// 配网结果回调
IMultiModeActivatorListener listener = new IMultiModeActivatorListener() {@Overridepublic void onSuccess(DeviceBean deviceBean) {// 配网成功}@Overridepublic void onFailure(int code, String error, Object handle) {// 配网失败}
};// 开始配网
TuyaHomeSdk.getActivator().newMultiModeActivator().startActivator(multiModeActivatorBean, listener);
说明:
开启连云激活需要确保设备当前处于蓝牙链路激活状态,即通过蓝牙将连云激活的信息传输给设备。调用
DeviceBean
实例的getCommunicationOnline(CommunicationEnum.BLE)
方法,可以查询当前设备蓝牙连接状态。只有返回值为true
时,才能调用开启连云激活的方法。如果需要判断云端链路是否激活,可以通过
deviceBean.getMeta().get("wifiEnable")
方法,查询设备是否连接 Wi-Fi。结果为true
,则表示云端链路已激活。
蓝牙兜底双模设备连云
上述蓝牙兜底配网设备如果 Wi-Fi 激活失败,会进入蓝牙本地连接进行操作。此时,若想重新尝试让设备连接 Wi-Fi 进行云端激活,可以调用如下接口,调用时需要确保设备处于本地蓝牙连接状态且云端链路未激活:
-
通过
DeviceBean
的getCommunicationOnline(CommunicationEnum.BLE)
方法,查询本地蓝牙链路是否激活。 -
使用
deviceBean.getMeta().get("wifiEnable")
查询设备是否激活云端链路。
接口说明
void startWifiEnable(MultiModeActivatorBean multiModeActivatorBean, IMultiModeActivatorListener listener);
参数说明
参数 | 类型 | 说明 |
---|---|---|
multiModeActivatorBean | MultiModeActivatorBean | 需要重连 Wi-Fi 的设备参数集合 |
listener | IMultiModeActivatorListener | 重连 Wi-Fi 结果的回调 |
MultiModeActivatorBean
说明
参数 | 类型 | 说明 |
---|---|---|
timeout | long | 设备重连 Wi-Fi 云端激活超时时长,单位为 ms |
ssid | String | 需要连接的 Wi-Fi SSID |
pwd | String | 需要连接的 Wi-Fi 密码,若无密码则传空字符串 |
devId | Long | 需要开启 Wi-Fi 使能的设备 ID |
代码示例
MultiModeActivatorBean multiModeActivatorBean = new MultiModeActivatorBean();
multiModeActivatorBean.devId = "devId_xxx"; // 设备 devId
multiModeActivatorBean.ssid = "ssid_xxx"; // 需要连接的 Wi-Fi ssid
multiModeActivatorBean.pwd = "pwd_xxx"; // 需要连接的 Wi-Fi 密码
multiModeActivatorBean.timeout = 120 * 1000L; // 超时时长,单位:ms// Wi-Fi 重新配网结果回调
IMultiModeActivatorListener listener = new IMultiModeActivatorListener() {@Overridepublic void onSuccess(DeviceBean deviceBean) {// 激活 Wi-Fi ,连接云端成功}@Overridepublic void onFailure(int code, String msg, Object handle) {// 激活 Wi-Fi ,连接云端失败}
};// 开始重新连接 Wi-Fi 并云端激活
TuyaHomeSdk.getActivator().newMultiModeActivator().startWifiEnable(multiModeActivatorBean, listener);
设备操作
本章节介绍已配网的单点设备,如何进行状态检测、连接、解绑等。
判断设备在线状态
-
方式一:通过通用方式查询。方法与 Wi-Fi 设备一致。查询的结果是综合状态,若蓝牙设备添加到网关下面,则蓝牙设备可云端在线。
TuyaHomeSdk.getDataInstance().getDeviceBean(devId).getIsOnline();
-
方式二:查询设备蓝牙是否本地连接。通常情况下蓝牙只需要考虑本地状态即可。只有加入蓝牙网关下的蓝牙设备才需要考虑是否云端在线。
TuyaHomeSdk.getBleManager().isBleLocalOnline(devId);
连接离线设备
⚠️注意:连接方法需要在主线程中调用。
接口说明
void connectBleDevice(List<BleConnectBuilder> builderList);
参数说明
参数 | 类型 | 说明 |
---|---|---|
builderList | List | BleConnectBuilder 集合,用于构建需要连接设备的设置 |
BleConnectBuilder
说明
方法名 | 参数 | 说明 |
---|---|---|
setDirectConnect() | boolean |
|
setDevId() | String | 需要连接的设备 ID |
setScanTimeout() | Integer | 扫描超时时长,单位为毫秒 |
setLevel() | BleConnectBuilder.Level |
NORMAL |
示例代码
List<BleConnectBuilder> builderList = new ArrayList<>();BleConnectBuilder bleConnectBuilder1 = new BleConnectBuilder();
BleConnectBuilder bleConnectBuilder2 = new BleConnectBuilder();bleConnectBuilder1.setDevId(devId1); // 设备 1 的 devId
bleConnectBuilder2.setDevId(devId2); // 设备 2 的 devIdbuilderList.add(bleConnectBuilder1); // 添加设备 1
builderList.add(bleConnectBuilder2); // 添加设备 2TuyaHomeSdk.getBleManager().connectBleDevice(builderList); // 开始连接
断开连接设备
⚠️注意:需要在主线程中调用。
接口说明
void disconnectBleDevice(List<BleConnectBuilder> builderList);
参数说明
参数 | 类型 | 说明 |
---|---|---|
builderList | List | BleConnectBuilder 集合,用于构建需要断开设备的设置 |
BleConnectBuilder
说明
方法名 | 参数 | 说明 |
---|---|---|
setDevId() | String | 需要断开的设备 ID |
示例代码
List<BleConnectBuilder> builderList = new ArrayList<>();builderList.add(new BleConnectBuilder().setDevId(devId1)); // 设备 1 的 devId
builderList.add(new BleConnectBuilder().setDevId(devId2)); // 设备 2 的 devIdTuyaHomeSdk.getBleManager().disconnectBleDevice(builderList); // 断开连接
设备管理操作
大家可以通过设备的操作类进行监听设备状态。该部分与 Wi-Fi 逻辑类似,以下操作均与 Wi-Fi 设备的指令下发一致:
-
设备信息查询
-
初始化设备控制
-
注册设备监听
-
取消设备监听
-
设备功能说明
-
设备重命名
-
移除设备
说明:蓝牙设备的解绑与 Wi-Fi 使用方式一致,都是调用
TuyaHomeSdk.newDeviceInstance("devId").removeDevice()
或者resetFactory()
。但是,有以下区别:- 蓝牙设备除了进行云端移除之外,若设备此时本地连接状态,则会自动移除设备。若此时设备离线,则只会云端移除,设备会仍处于绑定状态。
- 下次想要继续重新绑定设备,用户需要将设备手动置为配网状态。
- SDK 在扫描时,若发现设备处于绑定状态但是云端已解绑,也会进行自动重置。
-
回收设备资源
固件升级
固件 OTA 升级前,需要先检查固件信息,然后进行升级。
检查固件信息
接口说明
void requestUpgradeInfo(String devId, IRequestUpgradeInfoCallback callback);
参数说明
参数 | 类型 | 说明 |
---|---|---|
devId | String | 需要升级的设备 ID |
callback | IRequestUpgradeInfoCallback | 检查回调 |
示例代码
TuyaHomeSdk.getMeshInstance().requestUpgradeInfo(mDevID, new IRequestUpgradeInfoCallback() {@Overridepublic void onSuccess(ArrayList<BLEUpgradeBean> bleUpgradeBeans) {}@Overridepublic void onError(String errorCode, String errorMsg) {}
});
BLEUpgradeBean
返回固件升级的信息,提供以下信息:
字段 | 类型 | 描述 |
---|---|---|
upgradeStatus | Integer | 升级状态:
|
version | String | 最新版本 |
currentVersion | String | 当前版本 |
timeout | Integer | 超时时间,单位:秒 |
upgradeType | Integer |
|
type | Integer | 固件来源:
|
typeDesc | String | 来源描述 |
lastUpgradeTime | long | 上次升级时间,单位:毫秒 |
url | String | 新固件下载地址,type 取值为 1 或 9 时有值 |
fileSize | long | 新固件大小 |
md5 | String | 新固件 MD5 值 |
OTA 升级
将检查到的新固件下载到本地后,进行 OTA 升级。
接口说明
void startBleOta(String uuid, int type, String version, String binPackagePath, OnBleUpgradeListener listener);
参数说明
参数 | 类型 | 说明 |
---|---|---|
uuid | String | 需要升级的设备 UUID,可通过 deviceBean.getUuid() 查询 |
type | int |
|
version | String | 新固件版本号 |
binPackagePath | String | 下载到本地的固件的路径 |
listener | OnBleUpgradeListener | 升级进度回调 |
TuyaHomeSdk.getBleManager().startBleOta(uuid, type, version, binPackagePath, new OnBleUpgradeListener() {@Overridepublic void onUpgrade(int percent) {// 升级进度,单位为百分比}@Overridepublic void onSuccess() {// 升级成功}@Overridepublic void onFail(String errorCode, String errorMsg) {// 升级失败}
});
错误码
错误码 | 说明 |
---|---|
1 | 设备接收的数据包格式错误 |
2 | 设备找不到路由器 |
3 | Wi-Fi 密码错误 |
4 | 设备连不上路由器 |
5 | 设备 DHCP 失败 |
6 | 设备连云失败 |
100 | 用户取消配网 |
101 | 蓝牙连接错误 |
102 | 发现蓝牙服务错误 |
103 | 打开蓝牙通讯通道失败 |
104 | 蓝牙查询设备信息失败 |
105 | 蓝牙配对失败 |
106 | 配网超时 |
107 | Wi-Fi 信息发送失败 |
108 | Token 失效 |
109 | 查询蓝牙加密密钥失败 |
110 | 设备不存在 |
111 | 设备云端注册失败 |
112 | 设备云端激活失败 |
113 | 云端设备已被绑定 |
114 | 主动断开 |
115 | 云端查询设备信息失败 |
116 | 设备此时正被其他方式配网 |
117 | OTA 升级失败 |
118 | OTA 升级超时 |
119 | Wi-Fi 配网传参校验失败 |
相关文章:
蓝牙单点技术实现路径介绍
本文主要介绍蓝牙设备与手机一对一相连的 蓝牙单点 技术。 准备工作 系统要求:蓝牙使用需要安卓 4.3 以及以上版本,智能生活 App SDK 从安卓 4.4 开始支持。Manifest 权限: <uses-permission android:name"android.permission.ACCE…...
Ubuntu22.04 用 `hwclock` 或 `timedatectl` 来设置RTC硬件时钟为本地时区
Ubuntu22.04用 hwclock 或 timedatectl 来设置硬件时区为本地时区 可以用hwclock命令 sudo hwclock --localtime --systohc👆效果等同👇 , --localtime的简写是-l ; --systohc的简写是-w sudo hwclock -l -w也可以用timedatectl命令 👆效果…...
Node=>Express路由 学习2
1.概念 Express路由指的是客户端的请求与服务器处理函数之间的映射关系 Express路由由三部分组成 请求类型 请求URL地址 处理函数 app.METHOD ( PATH , HANDLER )根据定义的先后顺序进行匹配 请求类型和请求的URl同时匹配成功才会调用相应的处理函数 简单用法 2.模块化路由 为了…...
Android 面试三部曲——你做到了几点?
今天的干货来点轻松一点的,这次的分享是《面试需要哪些准备?》,主要分为三个部分: 面试前。面试中。面试后。 面试前 1、『工作经验中的职位要层层递进:初、中、高、资深级』🍒 2.投简历 你的简历必须要…...
windeployqt实现一键打包
每次发布QT程序前,都必须要在命令行环境下运行windeployqt 工具进行打包,加载相关的lib文件,才能正常运行。但是在命令行模式下,每次都要手动输入windeployqt的目录,和应用程序的位置目录,效率非常低,见下图: 那QT有没有什么好用的工具可以避免这个问题呢,认真找了一下…...
ESP32S3系列--SPI主机驱动详解(二)
一、目的 在上一篇《ESP32S3系列--SPI主机驱动详解(一)》我们介绍了ESP32S3的SPI外设的基本情况以及主机驱动的一些知识点,包括主机驱动的特点、总线的初始化、从设备的加入、传输模式分类等等。 本篇我们将从代码角度帮助大家进一步理解传输接口的一些细节问题。 二、实战 …...
51单片机15单片机 时钟芯片DS1302【更新中】
前言 现在流行的串行时钟电路很多,如DS1302、 DS1307、PCF8485等。这些电路的接口简单、价格低廉、使用方便,被广泛地采用。 本文介绍的实时时钟电路DS1302是DALLAS公司的一种具有涓细电流充电能力的电路主要特点是采用串行数据传输,可为掉电…...
SaleSmartly(ss客服)带你了解:缩短B2B销售周期的秘诀
缩短B2B销售周期的秘诀:即时聊天 关键词:B2B 销售;即时沟通;SaleSmartly(ss客服) 在B2B销售中,时间就是一切。在某些情况下,买家正在积极寻找即时解决方案,潜在客户以多种…...
九龙证券|A股苏州板块迎来“200+”里程碑
2月10日,跟着裕太微登陆科创板,A股“姑苏板块”正式迎来第201位成员。姑苏也成为继京、沪、深、杭之后,第5个具有A股上市公司总数超越200家的城市。 现在,姑苏不仅生长为位居全国前列的“制作之都”,更成为资本市场高地…...
vcruntime140_1.dll无法继续执行代码,怎么解决这种问题?
经常使用电脑的人,可能对于这个弹出框应该不陌生,“vcruntime140_1.dll无法继续执行代码”,其实会出现这种情况,主要是因为缺少一个动态链接库 (DLL) 文件导致的。这个文件是 Visual C 2015 库的一部分,某些程序需要这…...
正大国际期货:外盘震荡行情的特征及突破信号的确立
投机市场上,趋势交易应该是交易操作理念的灵魂和核心;能够顺应大的趋势,交易将变得简单,也更容易赚到钱。下面正大IxxxuanI详细来给大家讲讲 投资市场是由千万个交易个体所组成的复杂系统,走势具有不确定性࿰…...
【ESP 保姆级教程】玩转emqx数据集成篇④ ——数据桥接之HTTP服务
忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-02-10 ❤️❤️ 本篇更新记录 2023-02-10 ❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请…...
蓝桥杯算法训练合集十三 1.P06022.P07033.逗志芃的危机4.唯一的小可爱5.JOE的矩阵
目录 1.P0602 2.P0703 3.逗志芃的危机 4.唯一的傻子 5.JOE的矩阵 1.P0602 问题描述 编写一个程序,输入一个4位的自然数,将组成该数的各位数字重新排列,形成一个最大数和一个最小数,之后用最大数减去最小数,得到一…...
切换分支报错:Untracked Files Prevent Checkout
切换分支报错:Untracked Files Prevent Checkoutgit分支切换 Untracked Files Prevent Checkout本人解决办法:git分支切换 Untracked Files Prevent Checkout 新起的项目在切换master分支到工作分支时,出现下图的问题: Untracked…...
endo-BCN-PEG4-Palmitic,环丙烷环辛炔四聚乙二醇-Palmitic包装灵活
endo-BCN-PEG4-Palmitic,endo环丙烷环辛炔四聚乙二醇-Palmitic反应特点:endo-BCN-PEG4-Palmitic 酯在其末端含有一个 Palmitic基和一个 BCN 基。对点击试剂来说同样会通过不同的小分子PEG进行连接,BCN-PEG-acid、BCN-PEG-NHS ester、BCN-PEG-…...
多传感器融合定位十一-基于滤波的融合方法Ⅱ
多传感器融合定位十一-基于滤波的融合方法Ⅱ1. 编码器运动模型及标定1.1 编码器基础知识1.2 编码器运动模型1.2.1 旋转半径求解1.2.2 角速度求解1.2.3 线速度求解1.2.4 位姿求解1.3 编码器的标定1.3.1 轮子半径标定1.3.2 轮子与底盘中心距离标定2. 融合编码器的滤波方法2.1 核心…...
JAVA使用poi解析execl解决数值被转为科学计数法(如:手机号、身份证号、电话、等)解决方法
1、原由 大家都知道数字在EXCEL表格中存储时有两种表现形式。1.数字作为数值存储。当数字作为数值存储时,单元格中的数字可以参与数学运算。2.数字作为文本存储。当数字作为文本存储时,单元格中的数值不能够参与数学运算。 数字作为文本存储时,如果没有更…...
hive中substring_index()的使用
substring_index(str,delim,count)str:要处理的字符串delim:分隔符count:计数例子:strwww.wikibt.comsubstring_index(str,.,1)结果是:wwwsubstring_index(str,.,2)结果是:www.wikibt如果count是正数,那么就是从左往右数ÿ…...
LocalDateTime设置时间的年、月、日、时、分、秒、纳秒
如何把String/Date转成LocalDateTime参考String、Date与LocalDate、LocalTime、LocalDateTime之间互转 String、Date、LocalDateTime、Calendar与时间戳之间互相转化参考String、Date、LocalDateTime、Calendar与时间戳之间互相转化 方法介绍 withYear(int year) 指定日期的…...
C语言rand和srand用法详解
在实际编程中,我们经常需要生成随机数,例如,贪吃蛇游戏中在随机的位置出现食物,扑克牌游戏中随机发牌。在C语言中,我们一般使用 <stdlib.h> 头文件中的 rand() 函数来生成随机数,它的用法为ÿ…...
安装作业
1、安装方法 mysql安装常见的方法有四种 序号安装方式说明1yum\rpm简单、快速,不能定制参数2二进制解压,简单配置就可使用 免安装 mysql-a.b.c-linux2.x-x86_64.tar.gz3源码编译可以定制参数,安装时间长 mysql-a.b.c.tar.gz4源码制成rpm包把…...
电压放大器在非共线混频方法检测混凝土中的应用
实验名称:电压放大器在非共线混频方法检测混凝土中的应用研究方向:无损检测测试目的:无损检测是在不损伤或不干扰待测物体的结构材料的情况下,对其内部损伤进行探测的方法。传统无损检测法在仪器携带,操作程序…...
二十四、Gtk4-GtkExpression
GtkExpression是一种基本类型。它不是GObject的后代。GtkExpression提供了一种描述对值的引用的方法。GtkExpression需要求值才能获得值。 它类似于算术计算。 1 2 3 12是一个表达式。给出了计算的方法。3是来自表达式的值。求值是计算表达式并得到值。 GtkExpression是一种…...
Oracle Dataguard(主库为 Oracle rac 集群)配置教程(02)—— Oracle RAC 主库的相关操作
Oracle Dataguard(主库为 Oracle rac 集群)配置教程(02)—— Oracle RAC 主库的相关操作 / 本专栏详细讲解 Oracle Dataguard(Oracle 版本为11g,主库为双节点 Oracle rac 集群)的配置过程。主要…...
midjournery AI绘画使用指南
midjournery AI绘画使用指南 基于Discord的Midjournery配置: https://www.bilibili.com/video/BV16d4y1A7Zq/?spm_id_from333.337.search-card.all.click&vd_source9c3ca9555620bed64bdee27ae49d37cf 使用原则 使用midjournery绘画的原则是给出对脑海中某个…...
iptables防火墙SNAT和DNAT
iptables防火墙SNAT和DNAT一、SNAT原理和应用1、SNAT原理2、SNAT应用环境3、SNAT转换前提条件二、SNAT案列1、实验需求2、实验环境3、实验目的三、DNAT原理和应用1、DNAT原理2、DNAT 应用环境3、DNAT转换的前提条件四、DNAT案列总结一、SNAT原理和应用 1、SNAT原理 SNAT原理:…...
python | 第二章考试题和练习题
一、考试题 1、turtle八边形绘制 问题描述: 使用turtle库,绘制一个八边形。 参考代码: import turtle as t t.pensize(2) for i in range(8):t.fd(100)t.left(45) 2、turtle八角图形绘制 问题描述: 使用turtle库,…...
Mysql 存储引擎设计:xa协议相关接口功能及实现
需要对接的接口以及每个接口的实现 recovery 阶段 此阶段由 xa.cc 文件中的 xarecover_handlerton() 函数完成,它通过三个接口实现与存储引擎的沟通:recover(),commit_by_xid() ,rollback_by_xid()。其流程如下: 此…...
字符串常量池
1.创建对象的思考下面两种创建字符串的方式一样吗?public static void main(String[] args) {//两者一样吗String s1 "hello";String s2 "hello";String s3 new String("hello");String s4 new String("hello");System…...
让技术更有温度,腾讯Light 点亮公益之光
蓝天白云,远处是广东最长跨海大桥——南澳大桥,一艘小船在海面驶过,近处一头中华白海豚露出水面。在第三届腾讯Light技术公益创造营上,海南智渔可持续发展研究中心科学总监郑锐强为我们展现这样一幅人与自然和平相处的美好画面。随…...
网站建设技术支持有什么/一手项目对接app平台
击上方蓝色字体,选择“标星公众号”优质文章,第一时间送达 大家好,我是燕子!Sentinel是阿里巴巴开源的限流器熔断器,并且带有可视化操作界面。在日常开发中,限流功能时常被使用,用于对某些接口…...
wordpress畅言插件/自媒体怎么入门
小程序赛道要逆天了,继微信小程序,百度小程序,支付宝小程序,头条小程序,360PC小程序之后,中国移动宣布也将进入小程序赛道,推出短信小程序,覆盖生活吃穿住行所有场景! 了解到&#x…...
网站建设 力洋网络/广州百度关键词推广
场景 使用docker进行前端项目构建时报错,但是本地构建正常。 完整报错信息The build failed because the process exited too early. This probably means the system ran out of memory or someone called kill -9 on the process. 参考过程 从 create-react-ap…...
南宁网站建设公司哪家专业/中国新冠疫情最新消息
✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 目 录你是怎么理解乐观锁和悲观锁的,具体怎么实现呢? 悲观锁认为多个线程访问同一个共享变量冲突的概率较大, 会在每次访问共享变量之前都去真正加锁. 乐观…...
网站的站外推广手段/如何进行市场推广
之前看过Makefile,只记住了一些基本语法,细节没掌握太多,上手基本写不出来。用时只能搬砖,导致很简单的脚本要画很长时间来磨。 1. 粘贴过来的脚本,注意其每行的空格, 尤其是输出时候看到很诡异的错误&…...
网站建设公司做前端/网站建站在线制作
/** 【需求】服务端接收客户端发送过来的数据,并打印在控制台上。* * 建立TCP服务端的思路:* * 1.创建服务端Socket服务,通过ServerSocket。* * 2.服务端必须对外提供一个端口,否则客户端无法连接。* (连接服务器&…...