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