Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trying to read answer from CdcAcmSerialDriver on a slow command returns 0 #607

Open
StanislavStamatov opened this issue Oct 31, 2024 · 3 comments

Comments

@StanislavStamatov
Copy link

StanislavStamatov commented Oct 31, 2024

I am sending a command that typically returns answer slower than other commands. Interesting thing is that if i am in debug and i stop for 5 minutes before trying to read and then i read, the answer is returned as expected, but if i start reading in a loop immediately the answer never comes even if i wait for 10 or 15 minutes. If i put tread.sleep for 5 minutes before the read() again answer never comes. If i use SerialInputOutputManager for event-driven read again the answer never comes. I tried different baudrates but the result is the same. I downloaded the UsbSerialExample project and there the command takes some time and then return answer as expected. The expected answer is 908 bytes.

Here is the code i am using. If i send a command that returns answer faster there is no problem.
Code example.txt

` public byte[] SeekUSBDeviceAndSendCommand(boolean fiscal)
{
UsbManager manager = (UsbManager) App.currentActivity.getSystemService(Context.USB_SERVICE);

    if (manager != null) {
        HashMap<String, UsbDevice> deviceList = manager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = deviceList.values().iterator();
        while (deviceIterator.hasNext()) {
            UsbDevice device = deviceIterator.next();
            if (DaisyCommunicationUSB.checkUSBDeviceVID_PID(device, fiscal))
            {
                HashMap<String, Object> params = new HashMap<String, Object>();

                params.put("id", 2);
                params.put("jsonrpc", "2.0");
                params.put("method", "ReadDayInfo");
                params.put("params", 245);

                String jsonCommand = new Gson().toJson(params);
                
                UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
                UsbSerialPort port = driver.getPorts().get(0); // Most devices have just one port (port 0)
                UsbDeviceConnection connection = manager.openDevice(driver.getDevice());

                if (connection == null && !manager.hasPermission(device)) {
                    int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_MUTABLE : 0;
                    Intent intent = new Intent(BuildConfig.APPLICATION_ID + ".GRANT_USB");
                    intent.setPackage(App.currentActivity.getPackageName());
                    PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(App.currentActivity, 0, intent, flags);
                    manager.requestPermission(driver.getDevice(), usbPermissionIntent);
                }

	    byte[] readBuffer = new byte[8192];

                try {
                    port.open(connection);
                    port.setParameters(19200, UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);

                    //SerialInputOutputManager usbIoManager = new SerialInputOutputManager(port, this);
                    //usbIoManager.start(); // todo with ioManager with event driven read

                    port.write(jsonCommand.getBytes(), 2000);

                    int len = -1;

                    while (len <= 0) {
                        len = port.read(readBuffer, 2000);

                        if (len <= 0) {
                            try {
                                Thread.sleep(500);
                            } catch (InterruptedException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }

                    } catch (IOException e) {
                          throw new RuntimeException(e);
                    }

                return readBuffer;
            }
        }
    }

return null;
} `

@StanislavStamatov
Copy link
Author

Update: The problem was that in my project there is sdk that internally uses UsbSerialForAndroid with the SerialInputOutputManager and every time i send command to the serial device the sdk reads the answer before i read it and when i try to read there is no answer anymore because the SerialInputOutoputManager already read it. The solution was to stop the sdk if i am going to send commands, but i wonder what if i need the sdk to be working along with my part of the code sending commands to other serial devices (the sdk works for card payment devices and my part of the code for fiscal printers). I was thinking maybe if such situation occurs i can use reflection to access the SerialInputOutputManager in the sdk and stop it before i send command and start it again when i read the answer for the sent command.

@kai-morich
Copy link
Collaborator

The SerialInputOutputManager class has to be instantiated with a concrete UsbSerialPort.
Probably the SDK simply tried all UsbSerialPort, so it received data before your app.

@StanislavStamatov
Copy link
Author

Maybe if i can somehow deny the access for the port where my device is connected for for everybody except for me and than only i will send commands and receive answers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants