Open alaeddinezaghdoud opened 3 years ago
I spent all day on this problem - to no avail. From my POV this plugin is broken and needs to be fixed.
Every time, no matter if I use "read" function or registering callback in registerReadCallback I get empty object (no data).
Example code:
const serialConnect = async () => {
return serial
.requestPermission()
.then(() => {
setData({ ...data, status: "connecting" });
return (
serial
.open({ baudRate: 1200, dataBits: 8, stopBits: 1, parity: 0, dtr: true, rts: true, sleepOnPause: true })
.then(async () => {
const observable = serial.registerReadCallback();
observable.subscribe({
next(x) {
if (x instanceof ArrayBuffer) {
const typedArray = new Uint8Array(x);
const array = Array.from(typedArray);
alert("arraybuffer " + JSON.stringify(array)); // empty data
} else {
alert("object: " + JSON.stringify(x)); // Callback registered successfully
}
},
error(err) {
setData({ ...data, status: "disconnected" });
},
complete() {
setData({ ...data, status: "disconnected" });
},
});
await serial
.writeHex(toHexString([0x11, 0x22, 0x33]))
.catch((e) => {
setData({ ...data, status: "disconnected" });
});
setData({ ...data, status: "connected" });
// serial.read().then((data) => {
// // data also is empty
// });
return "ok";
})
.catch((error: any) => {
setData({ ...data, status: "disconnected" });
return error;
})
);
})
.catch((e) => e);
};
Today I used cordova-plugin-serial@0.0.3
https://www.npmjs.com/package/cordova-plugin-serial
I wrote a simple wrapper:
interface PortOptions {
baudRate?: number; // default 9600
dataBits?: number; // default 8
stopBits?: number; // default 1
parity?: number; // default 0
dtr?: boolean; // default true
rts?: boolean; // default true
sleepOnPause?: boolean; // default false
}
type ReadCallback = (data: ArrayBuffer) => void;
const serial = (window as any).serial;
const SerialPort = {
requestPermission: async () => {
return new Promise((resolve: any, reject: any) => {
serial.requestPermission(
function success(successMessage: string) {
resolve(successMessage);
},
function error(error: string) {
reject(error);
},
);
});
},
open: async (portOptions: PortOptions) => {
const _portOptions: PortOptions = {
...{ baudRate: 9600, dataBits: 8, stopBits: 1, parity: 0, dtr: true, rts: true, sleepOnPause: false },
...portOptions,
};
return new Promise((resolve: any, reject: any) => {
serial.open(
_portOptions,
function (successMessage: string) {
resolve(successMessage);
},
function (openError: string) {
if (openError === "Already open") { // ugly code, but it solves the problem if the user just pulls out the USB cable.
serial.close(
() => {
serial.open(
_portOptions,
function (successMessage: string) {
resolve(successMessage);
},
function (openError: string) {
reject(openError);
},
);
},
() => {
serial.open(
{ baudRate: 1200 },
function (successMessage: string) {
resolve(successMessage);
},
function (openError: string) {
reject(openError);
},
);
},
);
} else {
reject(openError);
}
},
);
});
},
write: async (data: string) => {
return new Promise((resolve: any, reject: any) => {
serial.write(
data,
function (successMessage: string) {
resolve(successMessage);
},
function (writeError: string) {
reject(writeError);
},
);
});
},
writeHex: async (data: string) => {
return new Promise((resolve: any, reject: any) => {
serial.writeHex(
data,
function (successMessage: string) {
resolve(successMessage);
},
function (writeError: string) {
reject(writeError);
},
);
});
},
read: async (): Promise<ArrayBuffer> => {
return new Promise((resolve: any, reject: any) => {
serial.read(
function (buffer: ArrayBuffer) {
resolve(buffer);
},
function (readError: string) {
reject(readError);
},
);
});
},
close: async (): Promise<void> => {
return new Promise((resolve: any, reject: any) => {
serial.close(
function () {
resolve();
},
function (closeError: string) {
reject(closeError);
},
);
});
},
registerReadCallback: async (callbackForRegister: ReadCallback): Promise<void> => {
return serial.registerReadCallback(callbackForRegister, function (registerCallbackError: string) {
throw new Error(registerCallbackError);
});
},
};
export { SerialPort };
and this is the example code:
const serialConnect = async () => {
try {
await SerialPort.requestPermission();
await SerialPort.open({ baudRate: 1200 });
await SerialPort.registerReadCallback((data: ArrayBuffer) => {
const view = new Uint8Array(data);
alert("Incomming data: " + JSON.stringify(view));
});
await SerialPort.writeHex(toHexString([0x11, 0x22, 0x33]));
setData({ ...data, status: "connected" });
return "ok";
} catch (error) {
setData({ ...data, status: "disconnected" });
return error;
}
};
It seems to work fine. All the data is incoming correctly!
As far as I know, cordovarduino is based on cordova-plugin-serial
but why doesn't it work?
Thank you for your reply.
I am trying to use your solution. But I need your help.
I have installed cordova-plugin-serial@0.0.3 in my ionic project using npm i cordova-plugin-serial.
I tried to use your wrapper but I cannot find the correct declaration for serial in this line : const serial = (window as any).serial;
Can you please explain how to properly install the plugin in my ionic project in order to use the wrapper?
@alaeddinezaghdoud
I am using capacitor.js to build an android application. I removed cordovarduino from package.json dependencies.
Then:
$ rm -rf node_modules
$ npm i
$ npm i cordova-plugin-serial
$ ionic cap sync
$ ionic cap run android -l --external
And that's it. I don't know if there is a .d.ts file for this library, but it is available in the global "window" object. So I just cast it to type "any" and used it according to the examples in JavaScript
@mkopa
These are the steps I have done.
I installed cordova-plugin-serial in a new blank ionic project.
Then I tried your code. I think my problem is that i still dont get the correct declaration of serial.
The plugin is installed and I can see it under plugins.
But I have a problem to find the declaration in this line(eq serial has multiple declarations and none of them is referring to : cordova-plugin-serial) : const serial = (window as any).serial;
Can you help?
@alaeddinezaghdoud
That's why I wrote the wrapper. I don't create applications in Ionic on a daily basis, but I needed to write an application to support some device.
I didn't spend too much time looking for the best solution and mine is definitely not it.
cordovaduino
did not work for me according to the documentation, so I made this hack - maybe someone will find it useful as a temporary solution to the problem that you and I had.
Thank you for your help.
I have tried your solution but I still have the same problem : when I read the incoming data all I get is an array full with 0.
Do you have any idea?
Hi, I am using the serial plugin for serial communication in ionic : https://ionicframework.com/docs/v3/native/serial/
I could open a connection between the app and my embedded device. But when I try to read incoming values, the ReadCallback() is succesfull but I receive an ArrayBuffer with 0 values.
Here is my code : I have succesfully established the connection using Putty(terminal) and it works fine : the embedded device is always sending its status multiple times per second and every message starts with #.
Can anyone help me?
@alaeddinezaghdoud Hi, My skill aren't really advance, so maybe i'm not doing it in the right way. Nevertheless, i've tested this plugin successfully in a ionic/vue project like this :
Serial.registerReadCallback(
data => {
console.log("incoming data : " + data.byteLength) // in order to debug if there is incoming data
var view = new Uint8Array(data);
if(view.length >= 1) {
[....]
}
},
() => {
new Error("Failed to register read callback");
}).subscribe();
So in my code, the "reading" process isn't in the "subscribe" method but directly in the success callback of "registerReadCallback" (once again, maybe i'm not doing it in the right way). One thing that really help me is debugging with android studio and adb wifi. In this way you can track serial I/O between the 2 devices. I hope this could help you
Christophe
I strongly do not recommend using the Cordovarduino library for the following reasons:
Because of the restriction no. 1 we are deprived of updates in the project https://github.com/mik3y/usb-serial-for-android on which the Cordovarduino library is based. Because of this, adapters based on Qinheng CH340, CH341A chips do not support baud rate 1200 (the patch made by me contains the update and baud rate 1200 works correctly: https://github.com/mkopa/cordovarduino ). There are many more updates in the last 5 years.
@Cricrikris that's exactly what you need to do
@mkopa your comment is exactly why I don't care anymore about this lib. There's always a random dude willing to say shit about the open source work that I did and never contribute back the few lines he wrote. The open source community owe you a big thanks!
LOL NOPE
@xseignard please don't get so upset. This library is listed as official on the Ionic framework project website https://ionicframework.com/docs/native/serial). The libraries that the author ignores are really detrimental to the Ionic project.
Many people find it annoying that a simple library needs so much effort to work, and in the end it turns out to be outdated and not working as it should.
Thank you very much for finally writing that you are NO LONGER DEVELOPING this library. Be good enough and mark it in the README.md main file.
I strongly do not recommend using the Cordovarduino library for the following reasons:
- for incomprehensible reasons the author uses a statically linked library "usb-serial-for-android" (instead of adding it as a dependency in plugin.xml)
- restriction to use only one serial port.
Because of the restriction no. 1 we are deprived of updates in the project https://github.com/mik3y/usb-serial-for-android on which the Cordovarduino library is based. Because of this, adapters based on Qinheng CH340, CH341A chips do not support baud rate 1200 (the patch made by me contains the update and baud rate 1200 works correctly: https://github.com/mkopa/cordovarduino ). There are many more updates in the last 5 years.
@mkopa , I wasn't expecting working with ionic serial would be so painful; I was testing usb serial connectivity with raspberry pi zero with CDC driver and getting always 0 as size. Your solution made my day; btw, is there any plan of making the version 0.0.11 of cordovarduino available at npm?
@mkopa I'm a beginner and I'm using ionic with capacitor, in the ionic native docs they just install the cordova package with npm install, now instead of writing cordovarduino i installed the npm package from ur github repo, but now I get an
Could not find com.github.mik3y:usb-serial-for-android:3.3.3.
error, do you know by chance how to fix this or how to install the package properly?
Hi @filipppp it should work identical to the documentation, with a small change if you want to use my fork:
$ npm install mkopa/cordovarduino
$ npm install @ionic-native/serial
$ ionic cap sync
You can also try doing a full reinstall of node_modules:
$ npm ci
edit: Is possible that you just need to rebuild the project in Android Studio
okay now it works, dont know what I changed since I installed it like that, but I guess the reinstall "npm ci" did it, but sadly I still cant get the Serial Connection to work since the registerReadCallback doesn't return anything :/
thanks for the help tho!!
Moreover, this library doesnt let you pick a USB Port, what if I have multiple USB Devices on my Phone?
Unfortunately, the first recognized device will be selected. https://github.com/xseignard/cordovarduino/blob/2bbdc45e339d676b7a3267f75ed9ac43d9fcfbef/src/android/fr/drangies/cordova/serial/Serial.java#L230
You can try to use "Serial.java" file as a template and write your code to support multiple USB devices. The library that this project uses is very good quality! https://github.com/mik3y/usb-serial-for-android Good luck!
That could be it, since I've done lsusb on my mobile phone in the shell and getting all kinds of busses and devices, will try editing the Serial.java file
Well, I'm gonna need more time since I cant debug anything since I cant find a way to print stuff, or get autocompletion or anything out of that plugin, that codeline should work for my specific case, but I don't know how to apply this:
List<UsbSerialPort> ports = driver.getPorts();
for (UsbSerialPort p : ports) {
if (p..getDriver().getDevice().getVendorId() == 0x1A86) {
port = p;
break;
}
}
EDIT: got it working now, editing the java file from the node package and ionic cap sync didn't work for me, there are suddenly two Serial.java, one is "ty.cordova.serial" and one is "fr.drangies.cordova.serial", it seems the second one is the real one and I edited the file directly and verified it with logcat. Thing is now I for sure know that the arduino serial port is targetted, but it still doesn't give me any Serial data from it, so yeah
@mkopa Sorry for bothering you for the last time, but I get this error when using your fork:
Execution failed for task ':app:mergeDebugResources'.
> Could not resolve all files for configuration ':app:debugRuntimeClasspath'.
> Could not find com.github.mik3y:usb-serial-for-android:3.3.3.
Searched in the following locations:
- https://repo.maven.apache.org/maven2/com/github/mik3y/usb-serial-for-android/3.3.3/usb-serial-for-android-3.3.3.pom
- https://dl.google.com/dl/android/maven2/com/github/mik3y/usb-serial-for-android/3.3.3/usb-serial-for-android-3.3.3.pom
- https://jcenter.bintray.com/com/github/mik3y/usb-serial-for-android/3.3.3/usb-serial-for-android-3.3.3.pom
Required by:
project :app
Any ideas?
EDIT: Silly me, just read the README from the mik3y/usb-serial-for-android repo, now my Serial Connection works with ur fork @mkopa ! Big thanks to u!!
I am still fetch same issue serial.registerReadCallback() receives ArrayBuffer with 0 values using cordova angular
Can you please help me on this
Hi, I am using the serial plugin for serial communication in ionic : https://ionicframework.com/docs/v3/native/serial/
I could open a connection between the app and my embedded device. But when I try to read incoming values, the ReadCallback() is succesfull but I receive an ArrayBuffer with 0 values.
Here is my code :
this.serial.requestPermission({ vid: '2323', pid: '1111', driver: 'CdcAcmSerialDriver' } ).then(() => { this.serial.open({ baudRate: 9600, dataBits: 8, stopBits: 1, parity: 0, dtr: true, rts: true, sleepOnPause: true }) .then((x) => { this.apiService.showToast('Serial connection opened'); this.serial.registerReadCallback().subscribe((data) => { const view = new Uint8Array(data); if (view.length >= 1) { for (let i = 0; i < view.length; i++) { // if we received a \n, the message is complete, display it if (view[i] === 23) { const value = parseInt(str, 2); str = ''; this.apiService.showToast('value' + value); } // if not, concatenate with the begening of the message else { const tempstr = String.fromCharCode(view[i]); const stresc = escape(tempstr); str += unescape(stresc); } } } }); }).catch((error: any) => { this.apiService.showToast('[Serial] open error' + error); }); }).catch((err) => { this.apiService.showToast(JSON.stringify(err)); });
I have succesfully established the connection using Putty(terminal) and it works fine : the embedded device is always sending its status multiple times per second and every message starts with #.
Can anyone help me?