• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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]