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