Overriding UART?

Posted on
  • What I would like to do is have a function I call that allows me to attach my own handler to the BLE UART RX/TX and basically disable the espruino interface until the device disconnects.

    Is this possible?

    Being able to send JavaScript over UART is convenient, but it’s not ideal if you’re sending binary data back and forth.

    I’ve somewhat implemented what I want, but it doesn’t actually use the UART, but rather alternative characteristics that behave similarly

    Ideally I would just keep UART and add my two additional characteristics with advertisement, but as things are now, I have to change out the services

  • Yes - you just use:

    Bluetooth.on("data", ...)

    The trick is really the E.setConsole(null, {force:true}); which moves the console away from Bluetooth so you can use it as you want. Just remember that when that is done you won't be able to use the console until you do Bluetooth.setConsole again

  • In the Bluetooth.on callback, would it be safe to assume that the data received event will be called in order of being received?

    If I have a callback that takes longer, will the firmware wait to call the callback for the next chunk of data, or is there a chance that multiple instances of the same callback could be running at the same time?

    If I sent 572 bytes of data in 28 characteristic updates, would it cache all 28 updates, or would you risk having some lost?

    Sorry for all the questions.

  • Hi - it all happens in order, so you're fine. You would probably also find that the bangle negotiates a higher payload length so you don't get just 20 byte packets, but a few that are much larger.

    On Bangle.js 2 I think you have about a 2kB input buffer (and Puck/others are around 1k) so you'll be ok there - if there ever is a problem and data gets lost, you'll get a FIFO_FULL error flag that you can handle too

  • Is there a way to force the buffers to immediately flush?

    Sometimes I want to send just a specific chunk of data as a uart update.

    On the other end, I have a function called from an on data callback that adds another temporary listener to combine the output of multiple packets into one buffer. The issue is that the initial packet sent to the first callback is still in the buffer by the time I run the code, so it becomes part of the start of the combined buffer.

    There’s a workaround I’ve found to wrap it in a timeout of 0, but that’s not the cleanest to deal with

  • I think when you send data on the UART it'll be sent as fast as possible, but there's no way to force a 'flush' right now - interestingly this is the first time it's been requested.

    When I'm using Espruino to do stuff like Modbus (I think?) where you have to force a transmit and then open the line up to receive when transmitting is finished, I work out how long the transmit will take (usually string.length*10/baudrate) and set a timeout for that.

  • Well, I was referring to the BLE UART, not a physical serial connection.

    Flushing the transmit buffer isn’t a huge deal, I currently just set a timeout, but if there was a way to pause js execution until the last BLE UART packet has been sent, it could definitely simplify things and eliminate guessing.

    I only really have one situation where I don’t want the buffer combined with previous repl output, but that’s just when I move it to Serial1 and send a string to let other end know I’m ready.

    The receive buffer has the workaround mentioned above, although one thing that might be helpful is a way to tell espruino to not fire the next on(data) event until so many bytes have been received, with the option of a timeout.

    Maybe something like this to receive 500 bytes with a max timeout of 100ms between rx events Bluetooth.receive(500, 100, dataReceived, rxTimeout)

    My project might not be typical, but I chose to forego the REPL console on Bluetooth for the additional speed of sending data.

    An example of an exchange is

    -> 0x03 0x01
    <- 0x03 0x01
    -> (572 bytes)
    <- 0x03 0x01

  • Ahh, right... Well, I can do a flush function - although busy-waiting in JavaScript is generally not a great idea as it relies on the idle handler firing reasonably often to work properly.

    a way to tell espruino to not fire the next on(data) event until so many bytes have been received, with the option of a timeout.

    I think this is probably overkill to implement in Espruino, and extremely niche. I'd have thought it would be reasonably easy to just create a JS function that would handle that though.

    Personally, I think really to do this reliably you probably need to handle framing yourself rather than relying on forcing it to send in packets - you might always get some chunk of data split up when it shouldn't be - or maybe some data gets sent over bluetooth but then the send fails and has to be retried or something like that.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Overriding UART?

Posted by Avatar for DanTheMan827 @DanTheMan827