关于ionic:我用ionic撸了一个USB转串口的调试工具

38次阅读

共计 6498 个字符,预计需要花费 17 分钟才能阅读完成。

因为最近应产品经理的需要,须要做一个 Android 版的上位机 APP,为此专门到某宝上购买了一个 Type- C 转串口的小设施,而后就开始折腾了。花了几天的工夫就把上位机 APP 做进去了,起初在闲暇工夫又做了一个串口调试的小工具,成果如下图

创立我的项目

ionic start blank

创立一个空白我的项目

装置串口插件

要做一个串口通信的工具,那就得和硬件打交道,正好依据 ionic 官网文档,我找到了一个串口通信的插件,名为 cordovarduino,通过尝试之后,发现此插件因为久年失修,尽管能够应用,然而在收发数据的时候总是无奈残缺接管到数据。依据对其代码查看,发现其中 lib 目录下有一个 usbseriallibrary.jar 文件,这个应该就是 USB 串口的驱动文件了吧。

久年失修的插件,预计就是这个 jar 包有问题,应该更新一下这个 jar 包就能够了,因而,通过 usb-serial-for-android 这个我的项目的介绍我从新打包了一个 jar 包,实现后尝试了一下,的确很完满,并且收发数据也没有任何问题了。因而,本人依据 cordovarduino 我的项目从新 copy 了一个我的项目 cordova-plugin-usbserialport,因而你只须要装置我提供的插件即可

装置串口插件

ionic cordova plugin add cordova-plugin-usbserialport

装置本地数据存储插件

ionic cordova plugin add cordova-plugin-nativestorage
npm install @ionic-native/native-storage

装置状态栏插件

ionic cordova plugin add cordova-plugin-statusbar
npm install @ionic-native/status-bar

装置设施信息插件

ionic cordova plugin add cordova-plugin-device
npm install @ionic-native/device

装置获取版本号插件

ionic cordova plugin add cordova-plugin-app-version
npm install @ionic-native/app-version

装置 APP 最小化插件

ionic cordova plugin add cordova-plugin-appminimize
npm install @ionic-native/app-minimize

装置后盾运行插件

ionic cordova plugin add cordova-plugin-background-mode
npm install @ionic-native/background-mode

串口操作次要代码

declare let usbSerialPort: any; // 引入串口插件 
// 关上串口
async openSerialPort() {const config = await this.nativeStorage.getItem('config');
    // First request permission
    usbSerialPort.requestPermission(() => {console.log('get permission success.');
        usbSerialPort.getDevice(data => {this.title = data.name;});
        // open serial
        usbSerialPort.open(config, () => {console.log('Serial connection opened');
            // get open status
            this.isOpen();
            // read listener
            usbSerialPort.readListener(data => {clearTimeout(this.timer);
                const view = new Uint8Array(data);
                console.log(this.utils.bytes2HexString(view));
                this.receiveDataArray.push(view);
                this.timer = setTimeout(() => {const now = new Date();
                    const dateMs = now.getMilliseconds();
                    this.zone.run(() => {const date = `<span style="color: #2fdf75">${this.utils.formatDate(now, 'hh:mm:ss')}.${dateMs} > </span>`;
                        const resultUint8Array = this.utils.concatUint(Uint8Array, ...this.receiveDataArray);
                        if (!this.utils.bytes2HexString(resultUint8Array)) {return;}
                        this.receiveData += `
<div style="
-webkit-user-select: auto;
-moz-user-select: auto;
-ms-user-select: auto;
user-select: auto;">
${date}${this.utils.strDivision(this.utils.bytes2HexString(resultUint8Array), 2)}
</div>
`;
                        this.receiveData += `<div style="margin-top:8px"></div>`;
                        this.receiveLength = this.utils.bytes2HexString(resultUint8Array).length / 2;
                        this.scrollToBottom();});
                }, 500);
            }, err => {console.log(`Read listener error: ${err}`);
            });
        });
    }, err => {console.log(`Get permission error: ${err}`);
        if (this.openStatus) {this.zone.run(() => {
                this.openStatus = false;
                this.title = this.translate.instant('SERIAL_DEVICE_TITLE');
            });
        }
        this.presentToast(this.translate.instant('NO_DEVICE_CONNECTED'));
    });
}
// 串口写入
writerSerial() {if (!this.openStatus) {if (this.pack) {this.presentAlert();
        }
        return;
    }
    this.receiveDataArray = [];
    const now = new Date();
    const dateMs = now.getMilliseconds();
    if (this.isWriterHex) {usbSerialPort.writeHex(this.pack, (res: any) => {console.log('writer res:', res);
            const date = `<span style="color:#3880ff">${this.utils.formatDate(now, 'hh:mm:ss')}.${dateMs} < </span>`;
            this.receiveData += `<div>${date}${this.utils.strDivision(this.pack, 2)}</div>`;
            this.sendLength = this.pack.length / 2;
        }, err => {console.log('writer hex err:', err);
            this.presentToast();
            this.closeSerial();});
    } else {usbSerialPort.write(this.pack, (res: any) => {console.log('writer res:', res);
            const date = `<span style="color:#3880ff">${this.utils.formatDate(now, 'hh:mm:ss')}.${dateMs} < </span>`;
            this.receiveData += `<div>
${date}${this.utils.strDivision(this.utils.bufToHex(this.utils.stringToBytes(this.pack)), 2)}
</div>`;
            this.sendLength = this.utils.getStringByteLength(this.pack);
        }, err => {console.log('writer string err:', err);
            this.presentToast();
            this.closeSerial();});
    }
}
// 串口开启状态
isOpen() {
    usbSerialPort.isOpen(status => {console.log(`Serial open status: ${status}`);
        this.zone.run(() => {this.openStatus = status;});
    });
}
// 敞开串口
closeSerial(isOpenSerial?: boolean) {usbSerialPort.close(() => {this.isOpen();
        this.receiveDataArray = [];
        if (isOpenSerial) {this.openSerialPort();
        }
    });
}

其余

为了可能对串口波特率进行设置,我还做了一个设置页面,次要用于设置波特率、数据位、进行位、以及收发数据记录的背景色彩切换、语言切换等性能。

重要代码如下:

version: any = '';
config: any = {};
// eslint-disable-next-line @typescript-eslint/ban-types
configTemp: object = {};
// 色彩列表
colorList: any[] = [
    'color-white',
    'color-red',
    'color-blue',
    'color-cyan',
    'color-yellow',
    'color-green',
    'color-black',
    'color-cornsilk',
    'color-darkviolet',
    'color-gainsboro',
    'color-maroon',
    'color-pink',
];
lang: any;
constructor(
    private appVersion: AppVersion,
    private nativeStorage: NativeStorage,
    private modalController: ModalController,
    private translate: TranslateService,
    private zone: NgZone
) { }

ionViewWillEnter() {this.initBackgroundColor();
    this.getVersion();
    this.getSerialPortConfig();
    this.getLanguage();}

async initBackgroundColor() {const backgroundClass = await this.nativeStorage.getItem('backgroundClass');
    console.log('settings backagroun class', backgroundClass);

    const activeClass = 'color-active';
    this.colorList.forEach((item, index) => {if (item === backgroundClass) {console.log('have same');
            this.zone.run(() => {this.colorList[index] = `${item} ${activeClass}`;
            });
        }
    });
    console.log('color list', this.colorList);

}

/**
 * get App version
 *
 * @memberof SettingsPage
 */
async getVersion() {this.version = await this.appVersion.getVersionNumber();
}

/**
 * Get serial port config
 *
 * @memberof SettingsPage
 */
async getSerialPortConfig() {this.config = await this.nativeStorage.getItem('config');
    this.configTemp = Object.assign({}, this.config);
    console.log('config', this.config);
}

async setSerialPortConfig() {await this.nativeStorage.setItem('config', this.config);
    const configIsCHange = JSON.stringify(this.configTemp) !== JSON.stringify(this.config);
    this.modalController.dismiss({configIsChange: configIsCHange});
}

async setBackgroundColor(className: string) {await this.nativeStorage.setItem('backgroundClass', className);
    this.modalController.dismiss();}

async getLanguage() {this.lang = await this.nativeStorage.getItem('locale');
}

async setLanguage() {await this.nativeStorage.setItem('locale', this.lang);
    this.translate.setDefaultLang(this.lang);
    this.translate.use(this.lang);
}

总结

Cordova 的确太老了,感觉都快曾经被 Apache 摈弃了,Cordova 的更新速度也很慢,就连目前的 ionic 都开发了本人的混合框架 capacitor,而且也兼容 Cordova 插件,只不过面对 react-native 以及 flutter 来说,ionic 目前处于一个比拟难堪的局面,因为 react-native 与 flutter 从性能上都能够碾压 ionic,不过 ionic 的长处就是打包后 apk 占用空间是极小的。

不论如何,ionic 绝对于 react-native 和 flutter 来说,能够让前端开发人员疾速上手,并且疾速开发与公布利用,其中坑较少,学习成本低,再加上现在的 ionic 曾经齐全从一个依赖于 Cordova 的挪动端框架转变为了 UI 框架,你能够应用 angular、vue、react 甚至是原生 JavaScript 进行疾速开发。

不过 capacitor 的插件目前少之又少,而 Cordova 的插件尽管多,然而太旧很多插件更新速度太慢,大家就抱着学习的态度去应用就能够了,当然如果抉择 ionic 来作为生产力框架的话也没多大问题。

我的项目地址

APP 我的项目 https://github.com/king2088/i…
cordova 串口插件我的项目 https://github.com/king2088/c…

正文完
 0