2
头图

Recently, in response to the needs of the product manager, I needed to make an Android version of the host computer APP. For this reason, I bought a small Type-C to serial port device on a certain treasure, and then I started to toss. It took a few days to make the host computer APP, and then I made a small serial port debugging tool in my free time. The effect is as shown in the figure below.

串口调试

Create project

ionic start blank

Create a blank project

Install the serial port plug-in

To make a serial communication tool, you have to deal with the hardware. According to the official ionic document, I found a serial communication plug-in named cordovarduino . After trying, I found that this plug-in was out of repair for many years, although it can It is used, but it is always unable to receive the data completely when sending and receiving data. According to the code inspection, it is found that there is a usbseriallibrary.jar file in the lib directory. This should be the driver file of the USB serial port.

The plug-in that has been in disrepair for a long time is estimated to be a problem with the jar package. It should be updated. Therefore, through the usb-serial-for-android project, I repackaged a jar package. I tried it, and it was perfect, and there was no problem sending and receiving data. Therefore, I re-copy a project cordova-plugin-usbserialport cordovarduino project, so you only need to install the plug-in provided by me

Install the serial port plug-in

ionic cordova plugin add cordova-plugin-usbserialport

Install the local data storage plugin

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

Install the status bar plugin

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

Install device information plug-in

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

Install and get the version number plug-in

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

Install APP Minimization Plugin

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

Install background running plugin

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

Main code of serial port operation

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();
        }
    });
}

other

In order to be able to set the serial port baud rate, I also made a setting page, which is mainly used to set the baud rate, data bit, stop bit, as well as the background color switch and language switch of the sending and receiving data records.

The important codes are as follows:

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);
}

Summarize

Cordova is indeed too old. I feel that it has been abandoned by Apache. Cordova's update speed is also very slow. Even the current ionic has developed its own hybrid framework capacitor , and it is also compatible with Cordova plug-ins, but it is only in the face of react. -Native and flutter, ionic is currently in a more embarrassing scene, because react-native and flutter can crush ionic in terms of performance, but the advantage of ionic is that the apk takes up very little space after packaging.

In any case, compared to react-native and flutter, ionic allows front-end developers to quickly get started, and quickly develop and publish applications, with fewer pits and low learning costs. In addition, today’s ionic has completely relied on Cordova's mobile-side framework is transformed into a UI framework. You can use angular, vue, react and even native JavaScript for rapid development.

However, capacitor plug-ins are very few at present, and Cordova has many plug-ins, but many plug-ins are too old, and the update speed is too slow. You can use it with a learning attitude. Of course, if you choose ionic as a productivity framework, No big problem.

project address

APP project https://github.com/king2088/ionic-serial-port-app
cordova serial port plug-in project https://github.com/king2088/cordova-plugin-usbserialport


深夜徘徊
297 声望267 粉丝

博主是一个苦逼的80后IT奴,苦逼屌丝男。