• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023 Fujian Newland Auto-ID Tech.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 */
15import { InputDeviceInfo } from '../model/InputDeviceInfo'
16import { logger } from '@ohos/common'
17import inputDevice from '@ohos.multimodalInput.inputDevice'
18
19const TAG: string = '[Sample_InputDeviceUtil]'
20
21/**
22 *  获取设备列表
23 * @param callback 回调
24 */
25export function getDeviceList(callback: (data: InputDeviceInfo[]) => void) {
26  // 获取所有输入设备ID列表
27  try {
28    inputDevice.getDeviceList().then(async (ids) => {
29      logger.info(`${TAG} Device id list: ${JSON.stringify(ids)}`)
30      if (!ids || ids.length <= 0) {
31        return
32      }
33      // 根据设备ID获取设备信息
34      try {
35        let devices: InputDeviceInfo[] = []
36        for (const item of ids) {
37          logger.info(`${TAG} get device info, id: ${item}`)
38          let deviceData: InputDeviceInfo | null = await getDeviceInfo(item);
39          if (deviceData !== null && devices.indexOf(deviceData) === -1) {
40            logger.info(`${TAG} add device, deviceId: ${deviceData.id}`)
41            devices.push(deviceData)
42          }
43        }
44        callback(devices)
45      } catch (error) {
46        logger.error(`${TAG} Failed to get device info, error: ${JSON.stringify(error, [`code`, `message`])}`)
47      }
48    })
49  } catch (error) {
50    logger.error(`${TAG} Failed to get device id list, error: ${JSON.stringify(error, [`code`, `message`])}`)
51  }
52}
53
54/**
55 * 获取设备信息
56 * @param deviceId 设备ID
57 */
58export async function getDeviceInfo(deviceId: number): Promise<InputDeviceInfo | null> {
59
60  try {
61    let deviceData: InputDeviceInfo;
62    let inputDeviceData: inputDevice.InputDeviceData = await inputDevice.getDeviceInfo(deviceId)
63    logger.info(`${TAG} get device info ${JSON.stringify(inputDeviceData)}`)
64    deviceData = {
65      id: inputDeviceData.id,
66      name: inputDeviceData.name,
67      sources: inputDeviceData.sources,
68      axisRanges: inputDeviceData.axisRanges,
69      bus: inputDeviceData.bus,
70      product: inputDeviceData.product,
71      vendor: inputDeviceData.vendor,
72      version: inputDeviceData.version,
73      phys: inputDeviceData.phys,
74      uniq: inputDeviceData.uniq,
75      icon_source: getDeviceIcon(inputDeviceData.sources),
76      connect: false
77    }
78    return deviceData;
79  } catch (error) {
80    logger.error(`${TAG} Failed to get device info, error: ${JSON.stringify(error, [`code`, `message`])}`)
81  }
82
83  return null;
84}
85
86/**
87 * 获取设备的图标
88 * @param sources 输入设备支持的源类型
89 */
90function getDeviceIcon(sources: string[]): Resource {
91  logger.info(`${TAG} getDeviceIcon: ${sources}`)
92  if (!sources || sources.length <= 0) {
93    return $r('app.media.icon_input_device_default')
94  }
95  let res: Resource
96  let sourceType = sources[0]
97  if (sourceType === 'keyboard') {
98    res = $r('app.media.icon_keyboard')
99  } else if (sourceType === 'mouse') {
100    res = $r('app.media.icon_mouse')
101  } else if (sourceType === 'touchpad') {
102    res = $r('app.media.icon_touchpad')
103  } else if (sourceType === 'touchscreen') {
104    res = $r('app.media.icon_touchscreen')
105  } else if (sourceType === 'joystick') {
106    res = $r('app.media.icon_joystick')
107  } else if (sourceType === 'trackball') {
108    res = $r('app.media.icon_trackball')
109  } else {
110    res = $r('app.media.icon_input_device_default')
111  }
112  return res
113}
114
115class InputDevice {
116  private callback: Function | null = null;
117  private deviceList: InputDeviceInfo[] = []
118
119  public registerChange(callback: Function): void {
120    logger.info(`${TAG} registerChange`)
121    try {
122      this.callback = callback
123      inputDevice.on('change', (data: inputDevice.DeviceListener) => this.onChangeCallback(data));
124    } catch (error) {
125      logger.error(`${TAG} Listen device event failed, error: ${JSON.stringify(error, [`code`, `message`])}`)
126    }
127  }
128
129  public unregisterChange(): void {
130    try {
131      inputDevice.off('change')
132      this.deviceList = []
133      if (this.callback && this.callback !== null) {
134        this.callback(this.deviceList)
135        this.callback = null
136      }
137      logger.info(`${TAG} Monitor off success`)
138    } catch (error) {
139      logger.error(`${TAG} Cancel listening device event failed, error: ${JSON.stringify(error, [`code`, `message`])}`)
140    }
141
142  }
143
144  private async onChangeCallback(data: inputDevice.DeviceListener) {
145    logger.info(`${TAG} onChangeCallback event: ${JSON.stringify(data)}`)
146    // 获取设备信息
147    let deviceId: number = data.deviceId
148    let deviceInfo: InputDeviceInfo | null = null;
149    let curIndex: number = -1
150    let tempIndex: number = -1
151    let delCount: number = 0
152    if (this.deviceList && this.deviceList.length > 0) {
153      for (const element of this.deviceList) {
154        tempIndex++
155        if (element.id === deviceId) {
156          deviceInfo = element
157          curIndex = tempIndex
158          delCount = 1
159          break
160        }
161      }
162    }
163
164    if (deviceInfo == null) {
165      deviceInfo = await getDeviceInfo(deviceId)
166    }
167    // 根据状态修改
168    let type: inputDevice.ChangedType = data.type
169    if (type === 'add' && deviceInfo !== null && deviceInfo !== undefined) {
170      // 连接
171      deviceInfo.connect = true
172    } else if (type === 'remove' && deviceInfo !== null && deviceInfo !== undefined) {
173      // 断开
174      deviceInfo.connect = false
175    }
176
177    if (deviceInfo !== null) {
178      this.deviceList.splice(curIndex, delCount, deviceInfo);
179    }
180    logger.info(`${TAG} get device info deviceId count:${this.deviceList.length}}`)
181    // fixme xjs 当前OH 3.2 release系统存在应用多次启动后出现回调多次,所以这里进行数据去重处理
182    this.deviceList = this.removeDuplicate(this.deviceList)
183    logger.info(`${TAG} get device info deviceId: ${deviceId} deviceInfo: ${JSON.stringify(deviceInfo)} count:${this.deviceList.length}}`)
184
185    if (this.callback && this.callback !== null) {
186      this.callback(this.deviceList)
187    }
188  }
189
190  /**
191   * 列表对象去重
192   * @param arr 列表
193   */
194  private removeDuplicate(arr: InputDeviceInfo[]): InputDeviceInfo[] {
195    const newArr: InputDeviceInfo[] = [];
196    for (const item of arr) {
197      // 检查缓存中是否已经存在
198      if (newArr.find((cur: InputDeviceInfo) =>
199      cur.id === item.id &&
200        cur.name === item.name &&
201        cur.connect === item.connect)
202      ) {
203        // 已经存在说明以前记录过,现在这个就是多余的,直接忽略
204        continue;
205      }
206      // 不存在就说明以前没遇到过,把它记录下来
207      newArr.push(item)
208    }
209    // 记录结果就是过滤后的结果
210    return newArr
211  }
212}
213
214export default new InputDevice()