Sending binary files to bangle.js Storage

Posted on
  • Hi,

    I have a bunch of binary files that I need to transfer to bangle.js Storage. There are about 30 small sound files, roughly 2-3K bytes each.

    Is there a way to copy arbitrary files to Storage, say through a command-line tool? I managed to do the job through the Web IDE, but it was pretty time consuming, and now I'd like to tweak my data I'm looking for a better way. Can "espruino --storage" be used to do this? Its unclear from the documentation exactly what this does.

  • Found this a few minutes ago, not sure if it does what you want
    https://github.com/espruino/EspruinoTools

    I Installed it on my Mac and it works as commandline for the Bangle using BLE.

    iMac19-9:~ gerard$ espruino
    Espruino Command-line Tool 0.1.31
    -----------------------------------
    
    Using first port, {"path":"f3-2c-dc-06-01-95","description":"Bangle.js 0195","type":"bluetooth"}
    Connecting to 'f3-2c-dc-06-01-95'
    
    >Connected
    
    >help
    Uncaught ReferenceError: "help" is not defined
     at line 1 col 1
    help
    ^
    >process.env
    ={ 
      VERSION: "2v06", 
      GIT_COMMIT: "21168a2b", 
      BOARD: "BANGLEJS", 
      FLASH: 524288, SPIFLASH: 4194304, STORAGE: 4194304, RAM: 65536, 
      SERIAL: "2e5db521-5511cd11", 
      CONSOLE: "Bluetooth", 
      MODULES: "Flash,Storage,hea" ... "tensorflow,locale", 
      EXPTR: 536882556 }
    >1+1
    =2
    >
    
  • Hi,

    Right now the command-line tool you two found won't actually do uploads to arbitrary Storage files. The --storage option is (confusingly) used when creating a hex file (for firmware updates to other devices).

    However there is https://github.com/espruino/BangleApps/blob/master/bin/apploader.js which allows you to upload apps just as you would have done with the App Loader (just from the command line).

    If you added your files to apps.json as an app then you could just use that (or in fact the app loader website itself)

  • @Gordon
    Thanks for the tip, will have look at `apploader.js';

    In the meantime I found out that you could use the espruino commandline tool for uploading Espruino code that writes text to a textfile on the Bangle.

    You feed the 'espruino' tool with an Espruino program to write a file, something like this:

    var Storage = require("Storage");
    var f = Storage.open("messages.txt","w");
    f.write(`
    Peter:How are you?
    Paul:Arrive 5 minutes later!
    Mary:Love you xxx
    `
    );
    

    Ofcourse you could the same with the left part of the Espruino WebIDE.

    My "use case" is that I want to feed a Bangle app with data residing on my Raspberry every few minutes, without manual intervention.

    Will see if apploader.js is the solution for me.

    Thanks.

  • Thanks @Gordon, that works well.

    Is there away to remove an app via the App Loader? Seems that "install" will overwrite an existing install, so if files are renamed or removed from the app, there will be orphaned files in the device Storage that are not in the app's ".info" file. Would be good the old files could be removed first.

  • OK, looks like its easy to do an App remove like this:

    Storage = require("Storage");
    Storage.list("myAppName").forEach(Storage.erase)
    
  • It'd be good to add some remove functionality - however this was created because someone on the forum complained that they couldn't develop "on the command-line". It's not meant to be a CLI App Loader replacement - it's just a way to develop quickly.

    Actually pushing data that way via the Espruino CLI sounds like good idea though - nice and easy.

  • FYI

    For sending simple commands to Bangle using Noble/BluePy/Gattool there is an extensive description with examples here: http://www.espruino.com/Interfacing#python

    The BluePy example code can be modified to send a file with Espruino commands in it to Bangle for execution by replacing

    command = "\x03\x10clearInterval()\n\x10setInterval(function() {LED.toggle()}, 500);\n\x10print('Hello World')\n"
    

    with something like

    f = open(sys.argv[2], "r")
    command = f.read()
    

    The BluePy example code can be changed to send a text file to Bangle Storage by replacing

    command = "\x03\x10clearInterval()\n\x10setInterval(function() {LED.toggle()}, 500);\n\x10print('Hello World')\n"
    

    with something like

    f = open(sys.argv[2], "r")
    command = f.read()
    command = 'var Storage = require("Storage");var f = Storage.open("' + sys.argv[2] + '","w");f.write(`' + command + '`);\n'
    
    

    Maybe it's for use for someone.

  • That's great, thanks! Only thing to watch out for is that because you're putting the command into a templated string without quoting, some thing can fail - for instance uploading:

    print("Hello\nWorld")
    

    Won't have the desired effect, because it'll actually turn into:

    f.write(`print("Hello
    World")`);
    

    It's easy enough to solve that using the Python JSON library to 'stringify' the command first though: https://docs.python.org/3/library/json.html

  • Thanks for the tip. Until now the data I have sent was "simple text". If the text would contain newlines, single or double quotes, backticks, etc I'm sure that I'm in trouble.

    I am searching for a reliable way to provide a Bangle app with data from "the internet", and wanted to try this.

    My current code sends 4 short textfiles to the Bangle, every minute via a crontab. Added a short delay after each 20-byte chunk, without it I ran into several "FIFO FULL" errors.

    Work reasonable reliable, during a 1 hour test I had no fails.

    But sometimes:

    • I get a "connection failed"
    • while transferring data something goes wrong. data is garbled, and the Bangle gets confused because it does not recognise valid commands anymore. And the picture on the Bangle screen is shifted 50% to the left. Looks like a memory error of some sort. Maybe the 0.05 second delay is too small, and causes a memory error.

    So I'm not out of the woods yet, but had fun learning.

    Thanks for this wonderfull project!

  • Ahh - the actual IDE/app loader implements XON/XOFF flow control (which isn't in the Python code) - but adding a few delays is an easy way to work around that.

    I think sometimes you will get a connection failed and will have to try again - radio is not 100% reliable. You just have to try again.

    However what can happen is half the command gets left on the 'input line' and then next time you connect it gets messed up.

    That's easy enough to fix - you'll note the original command that was sent starts with command = "\x03\x10 - if you make sure that's also in your code it should really help you.

    • \x03 - char code 3 is Ctrl-C - it'll clear the input line, removing any previous half-commands that might be on it
    • \x10 - char code 16 - is a special code for Espruino that means 'echo off for line'. The rest of that input line is then not repeated out to the console (usually you type a character and it is echoed back to you). That should really help with your upload too as you're halving the amount of data that gets transferred
  • Hi,

    Had a look at the App Loader (in a hurry) as a solution for me, but had trouble getting it working, surely my mistake. Now I know it has XON/XOFF it's again on the "candidate" list.

    I getting used to the fact that a BLE connection is not 100% reliable, so I have to adapt my code for that.

    Yes, saw the \x03\x010 in your original code:

    • for testing purposes I removed the \x10 so I could monitor the response from the Bangle, when I saw it returning =undefined I knew that my transfer was succesfull.
    • I was uncertain about the purpose of the \x03 and removed it also

    So next steps for me:

    • Will put the '\x03\x10` back in and see how that goes.
    • will change my code to allocate for a failed connection.

    Thanks for your help!

  • Update on my previous post.

    • added the \x03\x10 back in
    • increased the delay between 20-byte chunks to 0.1 second

    The update Python code on RPi code has been running now for 3.5 hours.

    It transfers 4 small text textfiles (20-30 textlines each) every minute to Bangle storage, so that is 3.5*60*4 = 840 separate BLE connections

    • no more catastrofic errors like "garbled data" or "bangle screen shifted right 50%" or "FIFO FULL", my Bangle App keeps running flawless
    • appr. 88 times the BLE connection has failed, that's like 10%

    So it seems likes the suggestions are working :-)

    Next steps:

    • let it run overnight and look at the behaviour and the numbers
    • add code for reconnection if connect fails
    • think of a way to check whether the transfer was successful. That's a challenge considering the \x10 switches response from the Bangle OFF ;-)

    All in all, making progress.

  • That's great!

    think of a way to check whether the transfer was successful.

    I tend to add Bluetooth.println("OK") to the end of the line of text that's sent to the device - that way it'll print OK if the whole line was received and executed without causing an exception

  • The Bluetooth.println("OK") looks like a good solution, provided the \x10 does not suppress it.

    Added a try and except around the code for connection, so that connection errors are trapped in the code, that works OK. Is the basis for adding a retry mechanism.

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

Sending binary files to bangle.js Storage

Posted by Avatar for stewartg @stewartg

Actions