1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16// [Start gatt_server_manage] 17import { ble } from '@kit.ConnectivityKit'; 18import { constant } from '@kit.ConnectivityKit'; 19import { BusinessError } from '@kit.BasicServicesKit'; 20import { ToastReport } from '../common/ToastReport' 21 22const TAG: string = 'GattServerManager'; 23 24export class GattServerManager { 25 public gattServer: ble.GattServer = ble.createGattServer(); 26 public connectState: ble.ProfileConnectionState = constant.ProfileConnectionState.STATE_DISCONNECTED; 27 public myServiceUuid: string = '00001810-0000-1000-8000-00805F9B34FB'; 28 public myCharacteristicUuid: string = '00001820-0000-1000-8000-00805F9B34FB'; 29 public myFirstDescriptorUuid: string = '00002902-0000-1000-8000-00805F9B34FB'; // 2902一般用于notification或者indication 30 public mySecondDescriptorUuid: string = '00002903-0000-1000-8000-00805F9B34FB'; 31 public toastReport: ToastReport = new ToastReport(); 32 33 // 构造BLEDescriptor 34 private initDescriptor(des: string, value: ArrayBuffer): ble.BLEDescriptor { 35 let descriptor: ble.BLEDescriptor = { 36 serviceUuid: this.myServiceUuid, 37 characteristicUuid: this.myCharacteristicUuid, 38 descriptorUuid: des, 39 descriptorValue: value 40 }; 41 return descriptor; 42 } 43 44 // 构造BLECharacteristic 45 private initCharacteristic(): ble.BLECharacteristic { 46 let descriptors: ble.BLEDescriptor[] = []; 47 let descBuffer = new ArrayBuffer(2); 48 let descValue = new Uint8Array(descBuffer); 49 descValue[0] = 31; 50 descValue[1] = 32; 51 descriptors[0] = this.initDescriptor(this.myFirstDescriptorUuid, new ArrayBuffer(2)); 52 descriptors[1] = this.initDescriptor(this.mySecondDescriptorUuid, descBuffer); 53 let charBuffer = new ArrayBuffer(2); 54 let charValue = new Uint8Array(charBuffer); 55 charValue[0] = 21; 56 charValue[1] = 22; 57 let characteristic: ble.BLECharacteristic = { 58 serviceUuid: this.myServiceUuid, 59 characteristicUuid: this.myCharacteristicUuid, 60 characteristicValue: charBuffer, 61 descriptors: descriptors 62 }; 63 return characteristic; 64 } 65 66 // 1. 订阅连接状态变化事件 67 public onGattServerStateChange() { 68 if (!this.gattServer) { 69 console.error(TAG, 'no gattServer'); 70 return; 71 } 72 try { 73 this.gattServer.on('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { 74 let state = ''; 75 switch (stateInfo.state) { 76 case 0: 77 state = 'DISCONNECTED'; 78 break; 79 case 1: 80 state = 'CONNECTING'; 81 break; 82 case 2: 83 state = 'CONNECTED'; 84 break; 85 case 3: 86 state = 'DISCONNECTING'; 87 break; 88 default: 89 state = 'undefined'; 90 break; 91 } 92 console.info(TAG, 'onGattServerStateChange: device=' + stateInfo.deviceId + ', state=' + state); 93 }); 94 } catch (err) { 95 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 96 } 97 } 98 99 // 2. server端注册服务时调用 100 public registerServer() { 101 let characteristics: ble.BLECharacteristic[] = []; 102 let characteristic = this.initCharacteristic(); 103 characteristics.push(characteristic); 104 let gattService: ble.GattService = { 105 serviceUuid: this.myServiceUuid, 106 isPrimary: true, 107 characteristics: characteristics 108 }; 109 110 console.info(TAG, 'registerServer ' + this.myServiceUuid); 111 try { 112 // this.gattServer = ble.createGattServer(); 初始化时已经构造,去除报错// 2.1 构造gattServer,后续的交互都需要使用该实例 113 this.onGattServerStateChange(); // 2.2 订阅连接状态 114 this.gattServer.addService(gattService); 115 this.toastReport.showResult('registerServer success'); 116 } catch (err) { 117 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 118 this.toastReport.showResult('registerServer failed'); 119 } 120 } 121 122 // 3. 订阅来自gattClient的读取特征值请求时调用 123 public onCharacteristicRead() { 124 if (!this.gattServer) { 125 console.error(TAG, 'no gattServer'); 126 return; 127 } 128 129 console.info(TAG, 'onCharacteristicRead'); 130 try { 131 this.gattServer.on('characteristicRead', (charReq: ble.CharacteristicReadRequest) => { 132 let deviceId: string = charReq.deviceId; 133 let transId: number = charReq.transId; 134 let offset: number = charReq.offset; 135 console.info(TAG, 'receive characteristicRead'); 136 let rspBuffer = new ArrayBuffer(2); 137 let rspValue = new Uint8Array(rspBuffer); 138 rspValue[0] = 21; 139 rspValue[1] = 22; 140 let serverResponse: ble.ServerResponse = { 141 deviceId: deviceId, 142 transId: transId, 143 status: 0, // 0表示成功 144 offset: offset, 145 value: rspBuffer 146 }; 147 148 try { 149 this.gattServer.sendResponse(serverResponse); 150 } catch (err) { 151 console.error(TAG, 152 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 153 } 154 }); 155 } catch (err) { 156 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 157 } 158 } 159 160 // 4. 订阅来自gattClient的写入特征值请求时调用 161 public onCharacteristicWrite() { 162 if (!this.gattServer) { 163 console.error(TAG, 'no gattServer'); 164 return; 165 } 166 167 console.info(TAG, 'onCharacteristicWrite'); 168 try { 169 this.gattServer.on('characteristicWrite', (charReq: ble.CharacteristicWriteRequest) => { 170 let deviceId: string = charReq.deviceId; 171 let transId: number = charReq.transId; 172 let offset: number = charReq.offset; 173 console.info(TAG, 'receive characteristicWrite: needRsp=' + charReq.needRsp); 174 if (!charReq.needRsp) { 175 return; 176 } 177 let rspBuffer = new ArrayBuffer(0); 178 let serverResponse: ble.ServerResponse = { 179 deviceId: deviceId, 180 transId: transId, 181 status: 0, // 0表示成功 182 offset: offset, 183 value: rspBuffer 184 }; 185 186 try { 187 this.gattServer.sendResponse(serverResponse); 188 } catch (err) { 189 console.error(TAG, 190 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 191 } 192 }); 193 } catch (err) { 194 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 195 } 196 } 197 198 // 5. 订阅来自gattClient的读取描述符请求时调用 199 public onDescriptorRead() { 200 if (!this.gattServer) { 201 console.error(TAG, 'no gattServer'); 202 return; 203 } 204 205 console.info(TAG, 'onDescriptorRead'); 206 try { 207 this.gattServer.on('descriptorRead', (desReq: ble.DescriptorReadRequest) => { 208 let deviceId: string = desReq.deviceId; 209 let transId: number = desReq.transId; 210 let offset: number = desReq.offset; 211 console.info(TAG, 'receive descriptorRead'); 212 let rspBuffer = new ArrayBuffer(2); 213 let rspValue = new Uint8Array(rspBuffer); 214 rspValue[0] = 31; 215 rspValue[1] = 32; 216 let serverResponse: ble.ServerResponse = { 217 deviceId: deviceId, 218 transId: transId, 219 status: 0, // 0表示成功 220 offset: offset, 221 value: rspBuffer 222 }; 223 224 try { 225 this.gattServer.sendResponse(serverResponse); 226 } catch (err) { 227 console.error(TAG, 228 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 229 } 230 }); 231 } catch (err) { 232 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 233 } 234 } 235 236 // 6. 订阅来自gattClient的写入描述符请求时调用 237 public onDescriptorWrite() { 238 if (!this.gattServer) { 239 console.error(TAG, 'no gattServer'); 240 return; 241 } 242 243 console.info(TAG, 'onDescriptorWrite'); 244 try { 245 this.gattServer.on('descriptorWrite', (desReq: ble.DescriptorWriteRequest) => { 246 let deviceId: string = desReq.deviceId; 247 let transId: number = desReq.transId; 248 let offset: number = desReq.offset; 249 console.info(TAG, 'receive descriptorWrite: needRsp=' + desReq.needRsp); 250 if (!desReq.needRsp) { 251 return; 252 } 253 let rspBuffer = new ArrayBuffer(0); 254 let serverResponse: ble.ServerResponse = { 255 deviceId: deviceId, 256 transId: transId, 257 status: 0, // 0表示成功 258 offset: offset, 259 value: rspBuffer 260 }; 261 262 try { 263 this.gattServer.sendResponse(serverResponse); 264 } catch (err) { 265 console.error(TAG, 266 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 267 } 268 }); 269 } catch (err) { 270 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 271 } 272 } 273 274 // 7. server端删除服务,不再使用时调用 275 public unRegisterServer() { 276 if (!this.gattServer) { 277 console.error(TAG, 'no gattServer'); 278 return; 279 } 280 281 console.info(TAG, 'unRegisterServer ' + this.myServiceUuid); 282 try { 283 this.gattServer.removeService(this.myServiceUuid); // 7.1 删除服务 284 this.gattServer.off('connectionStateChange', (stateInfo: ble.BLEConnectionChangeState) => { // 7.2 取消订阅连接状态 285 }); 286 this.gattServer.close() // 7.3 如果不再使用此gattServer,则需要close 287 this.toastReport.showResult('unRegisterServer'); 288 } catch (err) { 289 console.error(TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message); 290 } 291 } 292} 293 294let gattServerManager = new GattServerManager(); 295 296export default gattServerManager as GattServerManager; 297// [End gatt_server_manage]