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 16 17// @ts-ignore 18import print from '@ohos.print'; 19import commonEvent from '@ohos.commonEvent'; 20import { 21 AppCommonEvent, 22 PrintErrorCode, 23 AppStorageKeyName 24} from '@ohos/common'; 25import AppStorageHelper from '../Common/Adapter/AppStorageHelper'; 26import { GlobalThisHelper, GlobalThisStorageKey } from '@ohos/common'; 27import WifiP2pHelper from '../Common/Adapter/WifiP2pHelper'; 28import { Log } from '@ohos/common'; 29import { PrinterDiscModel } from '../Model/PrinterDiscModel'; 30import emitter from '@ohos.events.emitter'; 31import { StringUtil } from '@ohos/common'; 32import { requestPermission, checkPermission } from '@ohos/common'; 33import { PrintJob, PrinterCapability, PrinterInfo, PrinterState } from '@ohos/common'; 34 35const TAG = '[PrinterDiscController]:'; 36 37/** 38 * PrinterDiscController 39 */ 40export class PrinterDiscController { 41 private mPrinterDiscModel: PrinterDiscModel = new PrinterDiscModel(); 42 private eventSubscriber = null; 43 44 /** 45 * create print Job 46 * 47 * @param jobId printJob id 48 * @return job state 49 */ 50 public init(): void { 51 Log.info(TAG, 'PrinterDiscController init'); 52 AppStorageHelper.createValue<Array<PrinterInfo>>(this.getModel().mPrinters, AppStorageKeyName.PRINTER_QUEUE_NAME); 53 this.registerPrinterCallback(); 54 this.subscribeCommonEvent(); 55 } 56 57 /** 58 * on destroy 59 */ 60 public destroy(): void { 61 Log.info(TAG, 'PrinterDiscController destroy'); 62 this.unregisterPrinterCallback(); 63 } 64 65 /** 66 * start discovery 67 * 68 * @param jobId job id 69 * @param extensionList extension list 70 */ 71 public startDiscovery(jobId: string, extensionList: Array<string>): void { 72 Log.info(TAG, 'startDiscovery, jobId = ' + JSON.stringify(jobId) + ', extensionList ' + JSON.stringify(extensionList)); 73 this.mPrinterDiscModel.reset(); 74 print.queryAllPrinterExtensionInfos().then((extensionInfos: object[]) => { 75 Log.info(TAG, 'queryExtensionAbilityInfos success : ' + JSON.stringify(extensionInfos)); 76 print.startDiscoverPrinter(extensionList).then((data) => { 77 Log.info(TAG, 'start Discovery success data : ' + JSON.stringify(data)); 78 }).catch((err) => { 79 Log.error(TAG, 'failed to start Discovery because : ' + JSON.stringify(err)); 80 }); 81 checkPermission().then((result) => { 82 if (!result) { 83 let context = GlobalThisHelper.getValue(GlobalThisStorageKey.KEY_MAIN_ABILITY_CONTEXT); 84 requestPermission(context, () => { 85 print.startDiscoverPrinter(extensionList).then((data) => { 86 Log.info(TAG, 'requestPermission, start Discovery success data : ' + JSON.stringify(data)); 87 }).catch((err) => { 88 Log.error(TAG, 'failed to start Discovery because : ' + JSON.stringify(err)); 89 }); 90 }); 91 } else { 92 Log.error(TAG, 'has permission, ignore'); 93 } 94 }); 95 }).catch((error) => { 96 Log.error(TAG, 'start discovery fail because :' + JSON.stringify(error)); 97 }); 98 } 99 100 /** 101 * register printer callback 102 */ 103 private registerPrinterCallback(): void { 104 Log.info(TAG, 'registerPrinterCallback'); 105 print.on('printerStateChange', this.onPrinterStateChanged); 106 } 107 108 /** 109 * printer state change callback 110 * 111 * @param state printer state 112 * @param info printer info 113 */ 114 private onPrinterStateChanged = (state, info): void => { 115 if (state === null || info === null) { 116 Log.error(TAG, 'printer state changed state is null or info is null'); 117 return; 118 } 119 120 Log.info(TAG, 'on printer state changed, state = ' + JSON.stringify(state)); 121 info.toJSON = function (): JSON { 122 return { 123 // @ts-ignore 124 'printerId': StringUtil.splitMac(<string> this.printerId), 125 'printerName': StringUtil.encodeCommonString(<string> this.printerName), 126 'printerIcon': this.printerIcon, 127 'printerState': this.printerState 128 }; 129 }; 130 Log.info(TAG, 'on printer state changed, info = ' + JSON.stringify(info)); 131 switch (state) { 132 case PrinterState.PRINTER_ADDED: 133 this.onPrinterFound(info); 134 break; 135 case PrinterState.PRINTER_REMOVED: 136 this.onPrinterOffline(info); 137 break; 138 case PrinterState.PRINTER_UPDATE_CAP: 139 this.onPrinterUpdateCapability(info); 140 break; 141 case PrinterState.PRINTER_CONNECTED: 142 case PrinterState.PRINTER_DISCONNECTED: 143 case PrinterState.PRINTER_RUNNING: 144 this.onPrinterStateChange(info); 145 break; 146 default: 147 break; 148 } 149 }; 150 151 /** 152 * deal printer offline 153 * 154 * @param info printer info 155 */ 156 private onPrinterOffline(info: print.PrinterInfo): void { 157 if (info === null) { 158 Log.error(TAG, 'onPrinterOffline for null info'); 159 return; 160 } 161 Log.info(TAG, 'on printer offline, printer = ' + StringUtil.splitMac(<string> info.printerId)); 162 this.mPrinterDiscModel.removePrinter(<string> info.printerId); 163 } 164 165 /** 166 * deal printer find 167 * 168 * @param info printer info 169 */ 170 private onPrinterFound(info: print.PrinterInfo): void { 171 Log.info(TAG, 'enter onPrinterFound'); 172 if (info === null) { 173 Log.error(TAG, 'onPrinterFound for null data'); 174 return; 175 } 176 let newPrinter = new PrinterInfo(); 177 newPrinter.printerId = info.printerId; 178 newPrinter.printerName = info.printerName; 179 newPrinter.printerState = info.printerState; 180 newPrinter.printerIcon = info.printerIcon; 181 newPrinter.description = info.description; 182 newPrinter.capability = info.capability; 183 // @ts-ignore 184 newPrinter.option = info.options; 185 let added = this.mPrinterDiscModel.addPrinter(newPrinter); 186 Log.info(TAG, 'foundPrinter = ' + StringUtil.encodeCommonString(<string> info.printerName)); 187 } 188 189 /** 190 * find printer 191 * 192 * @param printerId printerId 193 */ 194 public findPrinter(printerId: string): boolean { 195 Log.debug(TAG, 'findPrinter = ' + StringUtil.splitMac(printerId)); 196 let res: boolean = this.mPrinterDiscModel.findPrinter(printerId); 197 return <boolean> res; 198 } 199 200 /** 201 * deal printer state change 202 * 203 * @param info printer info 204 */ 205 private onPrinterStateChange(info: print.PrinterInfo): void { 206 Log.error(TAG, 'onPrinterStateChange, info = ' + JSON.stringify(info)); 207 if (info === null) { 208 Log.error(TAG, 'onPrinterStateChange for null data'); 209 return; 210 } 211 this.mPrinterDiscModel.printerStateChange(<string> info.printerId, <number> info.printerState); 212 } 213 214 /** 215 * deal printer capability update 216 * 217 * @param info printer info 218 */ 219 private onPrinterUpdateCapability(info: print.PrinterInfo): void { 220 Log.info(TAG, 'onPrinterUpdateCapability, info = ' + JSON.stringify(info)); 221 if (info === null) { 222 Log.error(TAG, 'onPrinterUpdateCapability for null data'); 223 return; 224 } 225 this.mPrinterDiscModel.printerUpdateCapability(<string> info.printerId, <PrinterCapability> info.capability, 226// @ts-ignore 227 <string> info.option, <string> info.description); 228 } 229 230 /** 231 * stop discovery 232 * 233 * @param jobId job id 234 */ 235 public stopDiscovery(jobId: string): void { 236 Log.info(TAG, 'stopDiscovery'); 237 print.stopDiscoverPrinter().then((data) => { 238 Log.info(TAG, 'stop Discovery success data : ' + JSON.stringify(data)); 239 }).catch((err) => { 240 Log.error(TAG, 'failed to stop Discovery because ' + JSON.stringify(err)); 241 }); 242 } 243 244 /** 245 * register printer callback 246 */ 247 private unregisterPrinterCallback(): void { 248 Log.info(TAG, 'unregisterPrinterCallback'); 249 print.off('printerStateChange', (data) => { 250 console.info('off printerStateChange data : ' + JSON.stringify(data)); 251 }); 252 } 253 254 /** 255 * connect Printer 256 * 257 * @param printerId printer id 258 */ 259 public connectPrinter(printer: PrinterInfo): void { 260 let printerId: string = printer.printerId; 261 Log.debug(TAG, 'connectPrinter printerId = ' + StringUtil.splitMac(printerId)); 262 print.connectPrinter(printerId).then((data) => { 263 Log.debug(TAG, 'start connect Printer success data : ' + JSON.stringify(data)); 264 }).catch((err) => { 265 Log.error(TAG, 'failed to connect Printer because ' + JSON.stringify(err)); 266 if (err === PrintErrorCode.E_PRINT_INVALID_PRINTER) { 267 let innerEvent = { 268 eventId: AppCommonEvent.PRINTER_INVALID_EVENT, 269 priority: emitter.EventPriority.HIGH 270 }; 271 let eventData = { 272 data: { 273 'printerId': printerId 274 } 275 }; 276 emitter.emit(innerEvent, eventData); 277 Log.error(TAG, 'delete invalid printer printerId = ' + JSON.stringify(printerId)); 278 this.mPrinterDiscModel.removePrinter(printerId); 279 this.startDiscovery('', []); 280 } 281 }); 282 } 283 284 /** 285 * disconnect Printer 286 * 287 * @param printerId printer id 288 */ 289 public async disconnectPrinter(printerId: string): Promise<void> { 290 Log.info(TAG, 'disconnectPrinter'); 291 await print.disconnectPrinter(printerId).then((data) => { 292 Log.info(TAG, 'start disconnect Printer success data : ' + JSON.stringify(data)); 293 }).catch((err) => { 294 Log.error(TAG, 'failed to disconnect Printer because ' + JSON.stringify(err)); 295 }); 296 } 297 298 /** 299 * query Printer Capability 300 * 301 * @param printerId printer id 302 * @return printer capability 303 */ 304 public async queryPrinterCapability(printerId: string): Promise<void> { 305 Log.info(TAG, 'queryPrinterCapability'); 306 print.queryPrinterCapability(printerId); 307 } 308 309 /** 310 * get model 311 * 312 * @return PrinterDiscModel 313 */ 314 public getModel(): PrinterDiscModel { 315 return this.mPrinterDiscModel; 316 } 317 318 /** 319 * subscribe CommonEvent 320 */ 321 public subscribeCommonEvent(): void { 322 Log.info(TAG, 'subscribeCommonEvent'); 323 let subscribeInfo = { 324 events: [commonEvent.Support.COMMON_EVENT_WIFI_POWER_STATE], 325 }; 326 commonEvent.createSubscriber(subscribeInfo).then((subscriber) => { 327 Log.info(TAG, 'start createSubscriber subscriber : ' + JSON.stringify(subscriber)); 328 this.eventSubscriber = subscriber; 329 commonEvent.subscribe(this.eventSubscriber, (err, commonEventData) => { 330 Log.error(TAG, 'subscribe callback : ' + JSON.stringify(commonEventData)); 331 if (commonEventData.event === commonEvent.Support.COMMON_EVENT_WIFI_POWER_STATE) { 332 if (!WifiP2pHelper.checkWifiActive()) { 333 Log.error(TAG, 'wifi inactive '); 334 this.mPrinterDiscModel.reset(); 335 let innerEvent = { 336 eventId: AppCommonEvent.WLAN_INACTIVE_EVENT, 337 priority: emitter.EventPriority.HIGH 338 }; 339 emitter.emit(innerEvent); 340 } else { 341 let innerEvent = { 342 eventId: AppCommonEvent.WLAN_ACTIVE_EVENT, 343 priority: emitter.EventPriority.HIGH 344 }; 345 emitter.emit(innerEvent); 346 } 347 } 348 }); 349 }).catch((err) => { 350 Log.error(TAG, 'failed createSubscriber because ' + JSON.stringify(err)); 351 }); 352 } 353}