• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2023-2023 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
16import wifi from '@ohos.wifi';
17import P2PUtils from './utils/P2pUtils';
18import CheckEmptyUtils, { Log, PrinterCapability, PrinterInfo, IPP_CONNECT_ERROR } from '@ohos/common';
19import type { PrintServiceAdapter } from './PrintServiceAdapter';
20import type { LocalDiscoverySession } from './LocalDiscoverySession';
21import type DiscoveredPrinter from './discovery/DiscoveredPrinter';
22import LocalPrinterCapabilities from './napi/LocalPrinterCapabilities';
23import type ConnectionListener from './connect/ConnectionListener';
24import P2PPrinterConnection from './connect/P2pPrinterConnection';
25import type { CapabilitiesCache, OnLocalPrinterCapabilities } from './ipp/CapabilitiesCache';
26import { print } from '@kit.BasicServicesKit';
27
28const TAG = 'LocalPrinter';
29
30export default class LocalPrinter implements ConnectionListener, OnLocalPrinterCapabilities {
31  private static readonly p2pDiscoveryProtocol: string = 'wifi_direct';
32  private static readonly descriptionSplit: string = '&&';
33  private static readonly maxRetryTimes: number = 2;
34  private readonly mPrintServiceAdapter: PrintServiceAdapter;
35  private readonly mSession: LocalDiscoverySession;
36  private readonly mPrinterId: string; // number类型
37
38  private mTracking: boolean = false; //是否正在执行连接
39  private mCapabilities: PrinterCapability;
40  private mDiscoveredPrinter: DiscoveredPrinter;
41  private mP2pPrinterConnection: P2PPrinterConnection;
42  private getCapsFailedTimes: number = 0;
43
44  constructor(printServiceAdapter: PrintServiceAdapter, session: LocalDiscoverySession,
45              discoveredPrinter: DiscoveredPrinter) {
46    this.mPrintServiceAdapter = printServiceAdapter;
47    this.mSession = session;
48    this.mDiscoveredPrinter = discoveredPrinter;
49    this.mPrinterId = discoveredPrinter.getId();
50  }
51
52  /**
53   * get capabilities
54   *
55   * @return Return capabilities or null if not present
56   */
57  getCapabilities(): void {
58    if (CheckEmptyUtils.isEmpty(this.mDiscoveredPrinter)) {
59      Log.error(TAG, 'discovery printer is undefined');
60      return;
61    }
62    Log.info(TAG, 'caps is empty, now to request');
63    let capabilitiesCache: CapabilitiesCache = this.mPrintServiceAdapter.capabilitiesCache;
64    capabilitiesCache.requestCapabilities(this.mDiscoveredPrinter, this);
65  }
66
67  /**
68   * Create a PrinterInfo from this record or null if not possible
69   *
70   * @param knownGood boolean
71   * @return PrinterInfo or null
72   */
73  createPrinterInfo(): PrinterInfo {
74    //创建PrinterInfo对象 返回给打印框架
75    let printerInfo: PrinterInfo = new PrinterInfo(this.mPrinterId, this.mDiscoveredPrinter.getDeviceName(), print.PrinterState.PRINTER_ADDED);
76    if (!CheckEmptyUtils.isEmpty(this.mCapabilities)) {
77      let printerCapability: PrinterCapability = new PrinterCapability();
78      LocalPrinterCapabilities.buildPrinterCapability(printerCapability, this.mCapabilities);
79      printerInfo.capability = printerCapability;
80      printerInfo.description = LocalPrinter.p2pDiscoveryProtocol +
81      LocalPrinter.descriptionSplit +
82      this.mDiscoveredPrinter.getUri().host;
83      let options: string = LocalPrinterCapabilities.buildExtraCaps(this.mCapabilities, this.mDiscoveredPrinter.getUri().toString());
84      printerInfo.options = options;
85    }
86    return printerInfo;
87  }
88
89
90  /**
91   * 开始连接打印机
92   */
93  public startTracking(): void {
94    Log.debug(TAG, 'start connect to printer, track is: ' + this.mTracking);
95    if (!P2PUtils.isP2p(this.mDiscoveredPrinter)) {
96      Log.debug(TAG, 'mdns printer');
97      this.getCapabilities();
98      return;
99    }
100    if (this.mTracking) {
101      Log.error(TAG, 'ERROR: isTracking: ' + this.mTracking);
102      return;
103    }
104    this.mTracking = true;
105    Log.debug(TAG, 'p2p printer');
106    if (!CheckEmptyUtils.isEmpty(this.mP2pPrinterConnection)) {
107      Log.error(TAG, 'ERROR: connection in progress');
108      this.mP2pPrinterConnection = undefined;
109      return;
110    }
111    this.mSession.addConnectingId(<string> this.mDiscoveredPrinter.getId());
112    this.mP2pPrinterConnection = new P2PPrinterConnection(this.mPrintServiceAdapter, this.mDiscoveredPrinter, this);
113    this.mP2pPrinterConnection.connectToPeer();
114  }
115
116  /**
117   * 停止连接打印机
118   */
119  public stopTracking(): void {
120    if (!P2PUtils.isP2p(this.mDiscoveredPrinter)) {
121      Log.debug(TAG, 'mdns printer, no need stop tracking');
122      return;
123    }
124    if (this.mP2pPrinterConnection !== undefined) {
125      Log.info(TAG, 'printer is connecting, close');
126      this.mSession.removeConnectedId(this.mPrinterId);
127      this.mP2pPrinterConnection.close();
128    } else {
129      Log.info(TAG, 'mP2pPrinterConnection is undefined, remove p2p group');
130      this.mPrintServiceAdapter.wifiModel.getP2pLinkInfo().then((linkInfo: wifi.WifiP2pLinkedInfo) => {
131        if (linkInfo.connectState === wifi.P2pConnectState.CONNECTED) {
132          this.mPrintServiceAdapter.wifiModel.disconnectToPrinter();
133        } else {
134          Log.info(TAG, 'p2p is not connected');
135          this.mPrintServiceAdapter.wifiModel.stopConnection();
136        }
137      });
138    }
139    this.mP2pPrinterConnection = undefined;
140    this.mTracking = false;
141  }
142
143  /**
144   * get printerId
145   *
146   * @return PrinterId
147   */
148  public getPrinterId(): string {
149    return this.mPrinterId;
150  }
151
152  public setDiscoveryPrinter(printer: DiscoveredPrinter): void {
153    this.mDiscoveredPrinter = printer;
154  }
155
156  public getDiscoveryPrinter(): DiscoveredPrinter {
157    Log.debug(TAG, 'getDiscoveryPrinter: ' + this.mDiscoveredPrinter.toString());
158    return this.mDiscoveredPrinter;
159  }
160
161
162  /**
163   * 获取打印机能力成功的回调
164   *
165   * @param printerCaps
166   */
167  onCapabilities(printerCaps: PrinterCapability): void {
168    if (!CheckEmptyUtils.isEmpty(printerCaps)) {
169      this.mCapabilities = printerCaps;
170      this.getCapsFailedTimes = 0;
171      // 上报打印机获取能力成功的回调
172      let printerInfo: PrinterInfo = this.createPrinterInfo();
173      print.updatePrinters([printerInfo]).catch((error) => {
174        Log.error(TAG, 'update error: ' + JSON.stringify(error));
175      });
176    } else {
177      if (this.getCapsFailedTimes < LocalPrinter.maxRetryTimes) {
178        Log.error(TAG, `getCapabilities failed, retry ${this.getCapsFailedTimes} times`);
179        this.getCapsFailedTimes++;
180        this.getCapabilities();
181      } else {
182        Log.error(TAG, 'printerCaps is null');
183        this.getCapsFailedTimes = 0;
184        print.updateExtensionInfo(JSON.stringify(IPP_CONNECT_ERROR));
185      }
186    }
187  }
188
189
190  /**
191   * 打印机连接成功回调
192   * @param printer
193   */
194  onConnectionComplete(printer: DiscoveredPrinter): void {
195    this.mTracking = false;
196    this.mP2pPrinterConnection = undefined;
197    if (CheckEmptyUtils.isEmpty(printer)) {
198      Log.error(TAG, 'connect failed');
199      return;
200    }
201    this.mDiscoveredPrinter = printer;
202    this.mSession.updateLocalPrinter(printer);
203    // 上报打印机机连接成功的状态
204    // @ts-ignore
205    print.updatePrinterState(this.mPrinterId, PrinterState.PRINTER_CONNECTED);
206    this.mSession.removeConnectedId(this.mPrinterId);
207
208    //连接成功获取打印机能力
209    if (CheckEmptyUtils.isEmpty(this.mCapabilities)) {
210      this.getCapabilities();
211    } else {
212      this.onCapabilities(this.mCapabilities);
213    }
214  }
215
216  /**
217   * 打印机连接超时回调
218   * @param delayed
219   */
220  onConnectionDelayed(): void {
221    this.mTracking = false;
222    this.mP2pPrinterConnection = undefined;
223    // 通知打印框架连接失败
224    Log.error(TAG, 'connect delay');
225    print.updatePrinterState(this.mPrinterId, print.PrinterState.PRINTER_DISCONNECTED);
226    this.mSession.removeConnectedId(this.mPrinterId);
227  }
228}