电子商务网站建设需要的语言,出行南宁app软件下载,网站的域名做邮箱吗,爱凡客一#xff0c;简介
蓝牙4.0以下称为传统蓝牙#xff0c;4.0以上是低功耗蓝牙#xff0c;5.0开始主打物联网
5.0协议蓝牙最重要的技术就是Mesh组网#xff0c;实现1对多#xff0c;多对多的无线通信。即从点对点传输发展为网络拓扑结构#xff0c;主要领域如灯光控制等简介
蓝牙4.0以下称为传统蓝牙4.0以上是低功耗蓝牙5.0开始主打物联网
5.0协议蓝牙最重要的技术就是Mesh组网实现1对多多对多的无线通信。即从点对点传输发展为网络拓扑结构主要领域如灯光控制等可以同时控制一组内的多个设备。
如下模型把灯具分组就可以同时控制一组或者多组内的多台设备 二 蓝牙组网步骤
2.1 扫描还是用BluetoothAdapter adapter BluetoothAdapter.getDefaultAdapter()
/*** Start scanning for Bluetooth devices.** param filterUuid UUID to filter scan results with*/
public void startScan(final UUID filterUuid, boolean auto) {mFilterUuid filterUuid;Log.e(TAG, mScannerStateLiveData: 6 );if (mScannerStateLiveData.isScanning()) {return;}if (mFilterUuid.equals(BleMeshManager.MESH_PROXY_UUID)) {final MeshNetwork network mMeshManagerApi.getMeshNetwork();if (network ! null) {if (!network.getNetKeys().isEmpty()) {mNetworkId mMeshManagerApi.generateNetworkId(network.getNetKeys().get(0).getKey());}}}Log.e(TAG, mScannerStateLiveData: 7 );mScannerStateLiveData.scanningStarted();//Scanning settingsfinal ScanSettings settings new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)// Refresh the devices list every second.setReportDelay(0)// Hardware filtering has some issues on selected devices.setUseHardwareFilteringIfSupported(false)// Samsung S6 and S6 Edge report equal value of RSSI for all devices. In this app we ignore the RSSI./*.setUseHardwareBatchingIfSupported(false)*/.build();//Lets use the filter to scan only for unprovisioned mesh nodes.final ListScanFilter filters new ArrayList();filters.add(new ScanFilter.Builder().setServiceUuid(new ParcelUuid((filterUuid))).build());final BluetoothLeScannerCompat scanner BluetoothLeScannerCompat.getScanner();Log.e(TAG, startScan: 开始扫描 );scanner.startScan(filters, settings, mScanCallbacks);
}
2.2 扫描到设备后连接并获取地址
SuppressLint(RestrictedApi)
private void connect(final ExtendedBluetoothDevice extendedBluetoothDevice) {/*** 蓝牙 --根据UUID中的型号ID* DMX --根据品牌-系列-模式* 2.4G --单色温双色温全彩*/String uuid ((UnprovisionedBeacon) selectedBluetoothDevice.getBeacon()).getUuid().toString().replace(-, );String[] stringArray OrderUtils.hexStringToStringArray(uuid);//型号byte 10 ~ 12 表示型号String modelFileName stringArray[10] stringArray[11] stringArray[12];Log.e(TAG, modelFileName: modelFileName);dataJson dataJsonCommonDaoUtils.queryBykey(modelFileName);if (dataJson null) {ConfirmDialog confirmDialog new ConfirmDialog(mContext, R.style.dialog, 没有该型号的配置文件:\n modelFileName, getResources().getString(R.string.account_confirm));confirmDialog.show();hideCustomProgress();cancleHandlerProvisioning();return;}if (fromType 1 || fromType 2) {String json dataJson.getDataJson();if (!json.contains(FUNCTION)) {ConfirmDialog confirmDialog new ConfirmDialog(mContext, R.style.dialog, 请添加控制盒类型的配置文件\n, getResources().getString(R.string.account_confirm));confirmDialog.show();hideCustomProgress();cancleHandlerProvisioning();return;}}nextChBlue getNextCHBlue();if (nextChBlue -1) {//如果nextChBlue-1说明蓝牙地址1-512已将占完直接return;cancleHandlerProvisioning();return;}showCustomProgress(getResources().getString(R.string.ble_provisioning) (addIndex 1) / mSelectCommonList.size());scannerViewModel.getScannerRepository().stopScan();provisioningViewModel.connect(this, extendedBluetoothDevice, false);//监听连接状态provisioningViewModel.getConnectionState().observe(this, new ObserverString() {Overridepublic void onChanged(Nullable String s) {Log.e(TAG, getConnectionState: s);}});//监听是否连接provisioningViewModel.isConnected().observe(this, connected - {final boolean isComplete provisioningViewModel.isProvisioningComplete();if (isComplete) {return;}if (connected ! null) {if (connected) {Log.e(TAG, isConnected: 连接成功);handlerProvisioning.sendEmptyMessageDelayed(1, 4000);} else {Log.e(TAG, isConnected: 连接失败);}} else {Log.e(TAG, isConnected: 未连接);}});//监听设备信息provisioningViewModel.isDeviceReady().observe(this, deviceReady - {if (provisioningViewModel.getBleMeshManager().isDeviceReady()) {Log.e(TAG, isDeviceReady);final boolean isComplete provisioningViewModel.isProvisioningComplete();if (isComplete) {setupProvisionerStateObservers();return;}}});//监听重连provisioningViewModel.isReconnecting().observe(this, isReconnecting - {Log.e(TAG, isReconnecting);if (isReconnecting ! null isReconnecting) {provisioningViewModel.getUnprovisionedMeshNode().removeObservers(this);} else {setResultIntent();}});//监听keyprovisioningViewModel.getNetworkLiveData().observe(this, meshNetworkLiveData - {final ApplicationKey applicationKey meshNetworkLiveData.getSelectedAppKey();Log.e(TAG, getNetworkLiveData:Key: MeshParserUtils.bytesToHex(applicationKey.getKey(), false));Log.e(TAG, getNetworkLiveData: Address: getString(R.string.ble_hex_format, String.format(Locale.US, %04X, meshNetworkLiveData.getMeshNetwork().getUnicastAddress())));// 获取已选择的app key//appKeyView.setText(MeshParserUtils.bytesToHex(applicationKey.getKey(), false));
// Log.e(TAG, onCreate: MeshParserUtils.bytesToHex(applicationKey.getKey(), false) );// unicastAddressView.setText(getString(R.string.ble_hex_format,
// String.format(Locale.US, %04X, meshNetworkLiveData.getMeshNetwork().getUnicastAddress())));});//监听设备识别provisioningViewModel.getUnprovisionedMeshNode().observe(this, meshNode - {Log.e(TAG, getUnprovisionedMeshNode:meshNode (meshNode null));if (meshNode ! null) {final ProvisioningCapabilities capabilities meshNode.getProvisioningCapabilities();Log.e(TAG, getUnprovisionedMeshNode:capabilities (capabilities null));if (capabilities ! null) {final MeshNetwork network provisioningViewModel.getNetworkLiveData().getMeshNetwork();if (network ! null) {try {final int elementCount capabilities.getNumberOfElements();final Provisioner provisioner network.getSelectedProvisioner();final int unicast network.nextAvailableUnicastAddress(elementCount, provisioner);network.assignUnicastAddress(unicast);} catch (IllegalArgumentException ex) {ToastUtil.showToast(mContext, ex.getMessage());}}}}});
}
2.3 选择模型和节点
//选择节点
public ProvisionedMeshNode setSelectNode(String controlAddress) {MeshNetwork network Consts.sharedViewModel.getNetworkLiveData().getMeshNetwork();ProvisionedMeshNode node network.getNode(Integer.parseInt(controlAddress));if (node ! null) {Consts.sharedViewModel.setSelectedMeshNode(node);mElements.clear();mElements.addAll(node.getElements().values());tag2:for (int i 0; i mElements.size(); i) {ListMeshModel models new ArrayList(mElements.get(i).getMeshModels().values());tag1:for (int j 0; j models.size(); j) {if (models.get(j) instanceof VendorModel) {Consts.modelConfigurationViewModel.setSelectedElement(mElements.get(i));Consts.modelConfigurationViewModel.setSelectedModel(models.get(j));break tag2;}}}}return node;
}
2.4 配置入网
//入网
SuppressLint(RestrictedApi)
public void provisionClick() {final UnprovisionedMeshNode node provisioningViewModel.getUnprovisionedMeshNode().getValue();Log.e(TAG, isConnected: ((((((((((((( (node null));if (node null) {Log.e(TAG, isConnected: provisioningViewModel.getNetworkLiveData().getNodeName());provisioningViewModel.getNrfMeshRepository().identifyNode(selectedBluetoothDevice);return;}//配置入网if (node.getProvisioningCapabilities() ! null) {Log.e(TAG, onCreate: (node.getProvisioningCapabilities().getAvailableOOBTypes().size() 1 node.getProvisioningCapabilities().getAvailableOOBTypes().get(0) AuthenticationOOBMethods.NO_OOB_AUTHENTICATION));if (node.getProvisioningCapabilities().getAvailableOOBTypes().size() 1 node.getProvisioningCapabilities().getAvailableOOBTypes().get(0) AuthenticationOOBMethods.NO_OOB_AUTHENTICATION) {onNoOOBSelected();} else {
// final DialogFragmentSelectOOBType fragmentSelectOOBType DialogFragmentSelectOOBType.newInstance(meshNode.getProvisioningCapabilities());
// fragmentSelectOOBType.show(getSupportFragmentManager(), null);}}
}SuppressLint(RestrictedApi)
public void setupProvisionerStateObservers() {provisioningViewModel.getProvisioningStatus().observe(this, provisioningStateLiveData - {if (provisioningStateLiveData ! null) {final ProvisionerProgress provisionerProgress provisioningStateLiveData.getProvisionerProgress();provisioningStateLiveData.getStateList();if (provisionerProgress ! null) {final ProvisionerStates state provisionerProgress.getState();Log.e(TAG, setupProvisionerStateObservers: state: state);switch (state) {case PROVISIONING_CAPABILITIES:Log.e(TAG, PROVISIONING_CAPABILITIES: provisioningViewModel.getNetworkLiveData().getMeshNetwork().getUnicastAddress());String address String.format(Locale.US, %04X, provisioningViewModel.getNetworkLiveData().getMeshNetwork().getUnicastAddress());addressMap.put(selectedBluetoothDevice.getAddress(), address);break;case PROVISIONING_FAILED://失败
// if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_PROVISIONING_FAILED) null) {
// final String statusMessage ProvisioningFailedState.parseProvisioningFailure(getApplicationContext(), provisionerProgress.getStatusReceived());
// DialogFragmentProvisioningFailedError message DialogFragmentProvisioningFailedError.newInstance(getString(R.string.ble_title_error_provisioning_failed), statusMessage);
// message.show(getSupportFragmentManager(), DIALOG_FRAGMENT_PROVISIONING_FAILED);
// }break;case PROVISIONING_AUTHENTICATION_STATIC_OOB_WAITING:case PROVISIONING_AUTHENTICATION_OUTPUT_OOB_WAITING:case PROVISIONING_AUTHENTICATION_INPUT_OOB_WAITING:
// if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_AUTH_INPUT_TAG) null) {
// DialogFragmentAuthenticationInput dialogFragmentAuthenticationInput DialogFragmentAuthenticationInput.
// newInstance(mViewModel.getUnprovisionedMeshNode().getValue());
// dialogFragmentAuthenticationInput.show(getSupportFragmentManager(), DIALOG_FRAGMENT_AUTH_INPUT_TAG);
// }break;case PROVISIONING_AUTHENTICATION_INPUT_ENTERED:
// final DialogFragmentAuthenticationInput fragment (DialogFragmentAuthenticationInput) getSupportFragmentManager().
// findFragmentByTag(DIALOG_FRAGMENT_AUTH_INPUT_TAG);
// if (fragment ! null) {
// fragment.dismiss();
// }break;case PROVISIONING_COMPLETE:case NETWORK_TRANSMIT_STATUS_RECEIVED:
// if (getSupportFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_CONFIGURATION_STATUS) null) {
// DialogFragmentConfigurationComplete fragmentConfigComplete DialogFragmentConfigurationComplete.
// newInstance(getString(R.string.title_configuration_compete), getString(R.string.configuration_complete_summary));
// fragmentConfigComplete.show(getSupportFragmentManager(), DIALOG_FRAGMENT_CONFIGURATION_STATUS);
// }Log.e(TAG, setupProvisionerStateObservers: PROVISIONING_COMPLETE);handlerProvisioning.sendEmptyMessageDelayed(3, 3000);break;case PROVISIONER_UNASSIGNED:setResultIntent();break;default:break;}}}});}public void onNoOOBSelected() {final UnprovisionedMeshNode node provisioningViewModel.getUnprovisionedMeshNode().getValue();if (node ! null) {try {node.setNodeName(provisioningViewModel.getNetworkLiveData().getNodeName());setupProvisionerStateObservers();provisioningViewModel.getMeshManagerApi().startProvisioning(node);} catch (IllegalArgumentException ex) {ToastUtil.showToast(mContext, ex.getMessage());}}}
2.5 发送消息
/*** Send vendor model acknowledged message** param opcode opcode of the message* param parameters parameters of the message*/
public void sendVendorModelMessage(final int opcode, final byte[] parameters, final boolean acknowledged) {final Element element Consts.modelConfigurationViewModel.getSelectedElement().getValue();if (element ! null) {final VendorModel model (VendorModel) Consts.modelConfigurationViewModel.getSelectedModel().getValue();if (model ! null) {final int appKeyIndex Consts.modelConfigurationViewModel.getMeshManagerApi().getMeshNetwork().getAppKey(0).getKeyIndex();// final int appKeyIndex model.getBoundAppKeyIndexes().get(0);final ApplicationKey appKey Consts.modelConfigurationViewModel.getNetworkLiveData().getMeshNetwork().getAppKey(appKeyIndex);final MeshMessage message;if (acknowledged) {message new VendorModelMessageAcked(appKey, model.getModelId(), model.getCompanyIdentifier(), opcode, parameters);int address element.getElementAddress();if (lightEquipmentGroup ! null lightEquipmentGroup.getConnectMethod() 0) {address Consts.sharedViewModel.getSelectedGroup().getValue().getAddress();}sendMessage(address, message);} else {message new VendorModelMessageUnacked(appKey, model.getModelId(), model.getCompanyIdentifier(), opcode, parameters);int address element.getElementAddress();if (lightEquipmentGroup ! null lightEquipmentGroup.getConnectMethod() 0) {address Consts.sharedViewModel.getSelectedGroup().getValue().getAddress();}sendMessage(address, message);}}}
}protected void sendMessage(final int address, NonNull final MeshMessage meshMessage) {try {Log.e(TAG, sendMessage: checkConnectivity());if (!checkConnectivity())return;Consts.modelConfigurationViewModel.getMeshManagerApi().createMeshPdu(address, meshMessage);} catch (IllegalArgumentException ex) {ToastUtil.showToast(mContext, getString(R.string.ble_title_error));}
}
2.6 订阅网络群组
//订阅网络群组public void subscribe() {final ProvisionedMeshNode meshNode modelConfigurationViewModel.getSelectedMeshNode().getValue();Log.e(TAG, meshNodeIsnull: (meshNode null));if (meshNode ! null) {final Element element modelConfigurationViewModel.getSelectedElement().getValue();Log.e(TAG, elementIsnull: (element null));if (element ! null) {final int elementAddress element.getElementAddress();final MeshModel model modelConfigurationViewModel.getSelectedModel().getValue();Log.e(TAG, modelIsnull: (model null));if (model ! null) {final int modelIdentifier model.getModelId();final MeshMessage configModelSubscriptionAdd;Log.e(TAG, group.getAddressLabel(): (group.getAddressLabel() null));if (group.getAddressLabel() null) {configModelSubscriptionAdd new ConfigModelSubscriptionAdd(elementAddress, group.getAddress(), modelIdentifier);} else {configModelSubscriptionAdd new ConfigModelSubscriptionVirtualAddressAdd(elementAddress, group.getAddressLabel(), modelIdentifier);}sendMessage(meshNode.getUnicastAddress(), configModelSubscriptionAdd);handlerCheckIsConnectIndexaddIndex;handlerCheckIsConnect.removeCallbacksAndMessages(0);handlerCheckIsConnect.sendEmptyMessageDelayed(1,3000);}}}} 2.7 接收消息
public void onMeshMessageReceived(final int src, NonNull final MeshMessage meshMessage) {final ProvisionedMeshNode node mMeshNetwork.getNode(src);if (node ! null)if (meshMessage instanceof ProxyConfigFilterStatus) {mProvisionedMeshNode node;setSelectedMeshNode(node);final ProxyConfigFilterStatus status (ProxyConfigFilterStatus) meshMessage;final int unicastAddress status.getSrc();Log.v(TAG, Proxy configuration source: MeshAddress.formatAddress(status.getSrc(), false));mConnectedProxyAddress.postValue(unicastAddress);mMeshMessageLiveData.postValue(status);} else if (meshMessage instanceof ConfigCompositionDataStatus) {final ConfigCompositionDataStatus status (ConfigCompositionDataStatus) meshMessage;if (mSetupProvisionedNode) {mIsCompositionDataReceived true;mProvisionedMeshNodeLiveData.postValue(node);mConnectedProxyAddress.postValue(node.getUnicastAddress());mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.COMPOSITION_DATA_STATUS_RECEIVED);mHandler.postDelayed(() - {Log.e(TAG, onMeshMessageReceived: 500 );final ConfigDefaultTtlGet configDefaultTtlGet new ConfigDefaultTtlGet();Log.e(TAG, onMeshMessageReceived: 3 );mMeshManagerApi.createMeshPdu(node.getUnicastAddress(), configDefaultTtlGet);//}, 500);}, 0);} else {updateNode(node);}} else if (meshMessage instanceof ConfigDefaultTtlStatus) {final ConfigDefaultTtlStatus status (ConfigDefaultTtlStatus) meshMessage;if (mSetupProvisionedNode) {mIsDefaultTtlReceived true;mProvisionedMeshNodeLiveData.postValue(node);mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.DEFAULT_TTL_STATUS_RECEIVED);mHandler.postDelayed(() - {Log.e(TAG, onMeshMessageReceived: 1500 );final ApplicationKey appKey mMeshNetworkLiveData.getSelectedAppKey();SuppressLint(RestrictedApi) final int index node.getAddedNetKeys().get(0).getIndex();final NetworkKey networkKey mMeshNetwork.getNetKeys().get(index);final ConfigAppKeyAdd configAppKeyAdd new ConfigAppKeyAdd(networkKey, appKey);Log.e(TAG, onMeshMessageReceived: 2 );mMeshManagerApi.createMeshPdu(node.getUnicastAddress(), configAppKeyAdd);//}, 1500);}, 0);} else {updateNode(node);mMeshMessageLiveData.postValue(status);}} else if (meshMessage instanceof ConfigAppKeyStatus) {final ConfigAppKeyStatus status (ConfigAppKeyStatus) meshMessage;if (mSetupProvisionedNode) {if (status.isSuccessful()) {mIsAppKeyAddCompleted true;mProvisionedMeshNodeLiveData.postValue(node);mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.APP_KEY_STATUS_RECEIVED);mHandler.postDelayed(() - {final ConfigNetworkTransmitSet networkTransmitSet new ConfigNetworkTransmitSet(2, 1);Log.e(TAG, onMeshMessageReceived: 1 );mMeshManagerApi.createMeshPdu(node.getUnicastAddress(), networkTransmitSet);// }, 1500);}, 0);}} else {updateNode(node);mMeshMessageLiveData.postValue(status);}} else if (meshMessage instanceof ConfigNetworkTransmitStatus) {if (mSetupProvisionedNode) {mSetupProvisionedNode false;mIsNetworkRetransmitSetCompleted true;mProvisioningStateLiveData.onMeshNodeStateUpdated(ProvisionerStates.NETWORK_TRANSMIT_STATUS_RECEIVED);} else {updateNode(node);final ConfigNetworkTransmitStatus status (ConfigNetworkTransmitStatus) meshMessage;mMeshMessageLiveData.postValue(status);}} else if (meshMessage instanceof ConfigModelAppStatus) {if (updateNode(node)) {final ConfigModelAppStatus status (ConfigModelAppStatus) meshMessage;final Element element node.getElements().get(status.getElementAddress());if (node.getElements().containsKey(status.getElementAddress())) {mSelectedElement.postValue(element);final MeshModel model element.getMeshModels().get(status.getModelIdentifier());mSelectedModel.postValue(model);}}} else if (meshMessage instanceof ConfigModelPublicationStatus) {if (updateNode(node)) {final ConfigModelPublicationStatus status (ConfigModelPublicationStatus) meshMessage;if (node.getElements().containsKey(status.getElementAddress())) {final Element element node.getElements().get(status.getElementAddress());mSelectedElement.postValue(element);final MeshModel model element.getMeshModels().get(status.getModelIdentifier());Log.e(TAG, onMeshMessageReceived: **************************** );mSelectedModel.postValue(model);}}} else if (meshMessage instanceof ConfigModelSubscriptionStatus) {if (updateNode(node)) {final ConfigModelSubscriptionStatus status (ConfigModelSubscriptionStatus) meshMessage;if (node.getElements().containsKey(status.getElementAddress())) {final Element element node.getElements().get(status.getElementAddress());mSelectedElement.postValue(element);final MeshModel model element.getMeshModels().get(status.getModelIdentifier());mSelectedModel.postValue(model);}}} else if (meshMessage instanceof ConfigNodeResetStatus) {mBleMeshManager.setClearCacheRequired();final ConfigNodeResetStatus status (ConfigNodeResetStatus) meshMessage;mExtendedMeshNode.postValue(null);Log.e(TAG, onMeshMessageReceived: 2 );loadNodes();mMeshMessageLiveData.postValue(status);} else if (meshMessage instanceof ConfigRelayStatus) {if (updateNode(node)) {final ConfigRelayStatus status (ConfigRelayStatus) meshMessage;mMeshMessageLiveData.postValue(status);}} else if (meshMessage instanceof ConfigProxyStatus) {if (updateNode(node)) {final ConfigProxyStatus status (ConfigProxyStatus) meshMessage;mMeshMessageLiveData.postValue(status);}} else if (meshMessage instanceof GenericOnOffStatus) {if (updateNode(node)) {final GenericOnOffStatus status (GenericOnOffStatus) meshMessage;if (node.getElements().containsKey(status.getSrcAddress())) {final Element element node.getElements().get(status.getSrcAddress());mSelectedElement.postValue(element);final MeshModel model element.getMeshModels().get((int) SigModelParser.GENERIC_ON_OFF_SERVER);mSelectedModel.postValue(model);}}} else if (meshMessage instanceof GenericLevelStatus) {if (updateNode(node)) {final GenericLevelStatus status (GenericLevelStatus) meshMessage;if (node.getElements().containsKey(status.getSrcAddress())) {final Element element node.getElements().get(status.getSrcAddress());mSelectedElement.postValue(element);final MeshModel model element.getMeshModels().get((int) SigModelParser.GENERIC_LEVEL_SERVER);mSelectedModel.postValue(model);}}} else if (meshMessage instanceof VendorModelMessageStatus) {if (updateNode(node)) {final VendorModelMessageStatus status (VendorModelMessageStatus) meshMessage;if (node.getElements().containsKey(status.getSrcAddress())) {final Element element node.getElements().get(status.getSrcAddress());mSelectedElement.postValue(element);final MeshModel model element.getMeshModels().get(status.getModelIdentifier());mSelectedModel.postValue(model);}}}if (mMeshMessageLiveData.hasActiveObservers()) {mMeshMessageLiveData.postValue(meshMessage);}//Refresh mesh network live datamMeshNetworkLiveData.refresh(mMeshManagerApi.getMeshNetwork());}
2.9 字节数据的转换8位二进制一个字节
public static String hexStringFormatNormal1(CmdNormal cmdNormal) {if (cmdNormal null) {return ;}/*** 功能码8位二进制组成功能byte* Bit[0] : 0-不需要从机返回信息 / 1-需要从机返回信息* Bit[1] : 0-发送 / 1-返回* Bit[3] : 0-快捷指令 / 1-常规指令* Bit[4:3] : 0-蓝牙灯具 / 1-2.4G灯具 / 2-DMX灯具* Bit[6:5] : 未使用保持0* Bit[7] : 0-独立一帧 / 1-多帧数据*/StringBuffer stringBufferFunction new StringBuffer();CmdFunction cmdFunction cmdNormal.getCmdFunction();stringBufferFunction.append(cmdFunction.getIsMultiFrame());//7位0-独立一帧 / 1-多帧数据stringBufferFunction.append(0);//6位保持0stringBufferFunction.append(cmdFunction.getIsSetting());//5 0-查询 / 1-设置//stringBufferFunction.append(0);//3位保持0stringBufferFunction.append(OrderUtils.numToBinary(cmdFunction.getIsDeviceType(),2));//3,4位0-蓝牙灯具 / 1-2.4G灯具 / 2-DMX灯具stringBufferFunction.append(cmdFunction.getIsFunctionNormal());//2位 (0-快捷指令 / 1-常规指令)stringBufferFunction.append(cmdFunction.getIsFunctionBack());//1位0-发送 / 1-返回stringBufferFunction.append(cmdFunction.getIsMachineBack());//0位0-不需要从机返回信息 / 1-需要从机返回信息//功能码二进制转10进制int functionTen Integer.parseInt(stringBufferFunction.toString(), 2);StringBuffer stringBuffer new StringBuffer();stringBuffer.append(bytesToHexString(cmdNormal.getRollCode()));//滚码stringBuffer.append(bytesToHexString(functionTen));//功能码//地址码int addresscmdNormal.getAddress();stringBuffer.append(bytesToHexString(address 8 0xff));stringBuffer.append(bytesToHexString(address 0xff));//当前帧stringBuffer.append(bytesToHexString(cmdNormal.getCurrentFrame()));//总帧stringBuffer.append(bytesToHexString(cmdNormal.getTotalFrame()));//数据模式stringBuffer.append(bytesToHexString(cmdNormal.getModeType()));CmdNormal.AllDataMode allDataModecmdNormal.getAllDataMode();for(CmdCode cmdCode:allDataMode.getCmdCodeList()){if(cmdCode.getLenth()1){stringBuffer.append(bytesToHexString(cmdCode.getValue()));}else if(cmdCode.getLenth()2){stringBuffer.append(bytesToHexString(cmdCode.getValue() 8 0xff));//高8位stringBuffer.append(bytesToHexString(cmdCode.getValue() 0xff));//低8位}else if(cmdCode.getLenth()4){stringBuffer.append(bytesToHexString(cmdCode.getValue() 24 0xff));//高24位stringBuffer.append(bytesToHexString(cmdCode.getValue() 16 0xff));//高16位stringBuffer.append(bytesToHexString(cmdCode.getValue() 8 0xff));//高8位stringBuffer.append(bytesToHexString(cmdCode.getValue() 0xff));//低8位}else if(cmdCode.getLenth()6){stringBuffer.append(bytesToHexString(cmdCode.getValue() 40 0xff));//高40位stringBuffer.append(bytesToHexString(cmdCode.getValue() 32 0xff));//高32位stringBuffer.append(bytesToHexString(cmdCode.getValue() 24 0xff));//高24位stringBuffer.append(bytesToHexString(cmdCode.getValue() 16 0xff));//高16位stringBuffer.append(bytesToHexString(cmdCode.getValue() 8 0xff));//高8位stringBuffer.append(bytesToHexString(cmdCode.getValue() 0xff));//低8位}}return stringBuffer.toString();} 三总结
3.1 整个Mesh通信拓扑的实现还是比较复杂的所以开源的可能不好找我也是基于收费厂家的一套Mesh方案实现的组网的步骤有兴趣的可以了解下组网的概念和组网的流程。
3.2 组网步骤总结
第一步肯定还是扫描设备毕竟这是蓝牙最基本功能 Mesh节点在网络内发送数据不会像普通BLE广播需要等一个固定的广播间隔而是延迟一小段随机时间后发送所以为了数据不丢失节点会启用100%占空比来扫描广播信道扫描窗口时间扫描间隔 第二步检测key连接设备 mesh对传输的数据进行分层次加密网络层Network Layer数据通过网络密钥Network Key加密应用密钥App Key用于加密接入层Access Layer数据配置模型Configuration Model的数据则采用设备密钥Device Key进行加密 第三步选择节点 mesh里面还给每个节点有一些额外的四种可选的特性(Features)。分别是中继Relay,代理Proxy,朋友Friend和 低功耗Low Power features。节点可以在某个时间点选择不支持或者支持多个Feature。 中继Relay支持中继的节点可以帮忙转发收到的消息。因为有了RelayMesh网络就可以实现多跳(Hops)。 低功耗和朋友Low Power Nodes and Friend Nodes 这是搭配来用的。我们先说Low power节点类似于对功耗有要求的设备例如温度传感器。这种类型的设备为了节约功耗很大的时间都是在休眠的。也就是意味着他们收不到网络中发过来的消息。Friend节点能帮LP节点暂存消息。当LP节点需要的时候可以发消息给Friend节点 问问有没有“waiting message”。如果有就会一条条的发给LP节点。简而言之Friend节点就像是门卫的张大爷你Low power node想起来的时候去门卫拿你要的信就好了。这种方式和zigbee里面的enddevice向父节点拿数据的方式类似 第四步配置入网 所谓配网就是将未配网的设备变为配网的节点一般需要一个配网器与末配网设备进行配网交互、验证然后通过后将一些密钥交给对方的一个过程。 一般过程有5个阶段 1. 信标Beaconing阶段 2.邀请 (Invitation阶段 3. 交换公钥 (Exchange Public Keys)阶段 4. 身份认证 CAuthentication阶段 5. 分发配网数据 (Distribution Of Provisioning Data阶段 第五步分配地址 单播地址分配给节点中的元素地址地址范围0x0001~0x7FFF 未分配地址即无效地址固定为0x0000地址的初始值常用于屏蔽一个设备 组播地址用于表示一个或多个节点的多个元素地址范围0xC000~0xFFFF其中包含256个固定组播地址 虚拟地址用于表示一个或多个节点的多个元素每一个虚拟地址逻辑上对应一个128-bit的Label UUID通过对该Label UUID作哈希运算得出虚拟地址的低14位数值虚拟地址的范围为0x8000~0xBFFF 第六步选择模型 模型(Model)定义了节点基本功能的最小单位模型包含实现这个功能所必需的状态和操作状态的消息及其他一些行为 在蓝牙mesh模型里消息通信基于客户端-服务器的架构对外提供状态访问接口的叫做服务器Server而访问服务器状态的叫做客户端模型分为三种 服务器模型服务器模型包含了一个或多个元素上的一种或多种状态比如灯泡上包含有通用开关服务器模型Generic OfOff Server和灯泡亮度服务器模型Light Lightneww Server 客户端模型客户端模型定义了一系列的消息用于客户端去请求、设置服务端的状态比如开关中含有通用开关客户端模型(Generic OnOff Client)以及灯亮度客户端模型(Light Lightness Client)客户端模型不含有状态 控制模型控制模型可以包含一个或多个客户端模型用来和其他节点的服务端模型通信也可以包含一个或多个服务端模型用于响应其他节点客户端模型发来的消息 蓝牙技术联盟定义的模型被称为标准模型SIG Adopted Model16bit标识目前SIG定义好的模型包括Generic、Sensors、Time and Scenes、Lighting由厂商定义的模型称为厂商模型Vendor Model,32bit标识。 第七步发布和订阅 在蓝牙mesh里面发消息的动作我们叫做发布Publish。光从字面意思理解大家基本上就能看懂了。我想告诉别人什么事情发生或者做什么事情就叫做发布。谁对某些消息感兴趣就可以订阅这些内容。节点发布消息到单播地址组播地址或者虚拟地址。节点有兴趣接收这些数据的可以订阅这些地址。 第八步发送消息 蓝牙Mesh采用了消息缓存队列和TTL的优化方案来避免消息的无限制转发。 消息缓存 Message cache设备都会缓存收到消息的关键信息以确定是否已经转发过此消息如果是就忽略此消息。Message cache至少需要能缓存两条消息 Time to Live(TTL) 每个消息都会包含一个Time to Live(TTL)的值来限制中继的次数最大可以中继126次。消息每转发一次TTL的值就减1TTL值为1就不再转发