Is Espruino right for my project?

Posted on
Page
of 3
Prev
/ 3
Next
  • Yes you are correct it talks to a php script that sits on my amazon aws server. This script actually makes the calls to the network rail LDBWS api and receives the data. I then rip out the parts I want and convert it to an json object and this is what is returned.

    I am using a naughty header('Access-Control-Allow-Origin: *'); to allow the javascript to talk to my php while developing from my local machine.

    My html literally just creates a canvas this is because the project was always aimed to just be run on hardware but people in the office liked it so much and use it for there trains I decided to try and keep it cross platform so they can still use it in the browser.

    If I am reading what you are saying correctly. You would be able to convert this to run on espruino but have a module that draws it onto your lcd. And I would then replace with a module that just sends the canvas data to my DMD board using i2c instead. I am still a little bit worried about about memory? all the little temporary canvas's will use up to much ram? If you could help me with this project I would really appreciate it :)

  • Naughty header... ts...ts...ts... glad that you did not get found by some phisher... ;)... Do you need a key or account to access the network rail LDBWS api? - and what is the request / response format? rest/jason, soap/xml (or worse)? I see no issue why not go directly to the api than through your server (except you have a 'hidden agenda'/additional intentions - such as... of course a good one, I assume ;-).

  • hehe yes just for development lol I will remove once complete lol

    This is the api
    http://www.livedepartureboards.co.uk/ldb­ws/

    Yes you have your own private key which is in the php file. Also some one made a php example of how to receive the data using SOAP so I just copied this and converted to json. That's all the php script does really :)

    You could talk directly from the javascript I guess but I have no idea how plus your key would be reviled.

  • Now comes you php into place... because I'm sure that you can use it only so frequently before you run into terms and conditions that ask for money... :(... like with maps services with Google. Your server could make it easy to get a key and the key would be transparent... a user registers with the server and this gets the user a key, which will then be used for further reads by that user. Of course, this needs only be done when you run into the volume challenge.

  • Yup I get 5 million requests to the api a month which when its just me and a few friends using it is ok :)

  • Let's move back to the tech things. This are my thoughts: First step is to set the CORS definition in the index.html, make the access from any place to your server and later to the api, and scrub the response in the client. That means, the php would for the beginning just enhance and forward the request with the key and forward the response like a straight forward proxy. A url parm can keep the coexistency... &go=proxy and &go=api would be my suggestion for the new functionality. 2nd step wold be the separation of DOM oriented stuff in the code vs plain js stuff - we may end up with some more files - no problem. 3rd step is making classes (placing the variables and functions that belong together into a class definition or singleton). 4th step is moving onto require. These steps are all to refactor for cross platform enablement... And when you have an Espruino and the LED panel and processor, it will be ready. I for my part will make on my Espruino a Canvas that uses the Espruino Graphics and the IL9143 library.

  • 5M - this will go a long way...

  • Ah another reason for the php is if you have multiple destination states the php has to make multiple calls to the networkrail api it also has to make a separate request to collect the calling at stations data (forgot about this lol) then packages it all up in one friendly json response.

    If it is written to use require (to load the js files) does this still run inside a browser? I will do some research on this and try and implement it :)

    I have included the php file in this reply so you can see what it is doing. I guess it is doing quite a lot and saves the js from making multiple requests and just hides/removes all the train api crap from it which it doesn't really care about. It just wants to make one request and get back just the data it needs :) (way I see it hehe)

    Its not 100% finished I still need to sort out the station service messages.


    1 Attachment

  • Is https://github.com/railalefan/phpOpenLDB­WS/blob/master/OpenLDBWS.php this the library/module you use in ldbwsService.php?

  • Ah yes that is the file I have included in my php :)

    Almost converted html canvas to my own custom byte canvas just need to write the copyCanvas function now :)

    Spent ages trying to figure out why my chars where being clipped off. eventually found out that javascript bitwise shift right does not wrap??? and just fills with 0's useless! hehe.

    My led panels turned up today but one was damaged in the post :( hoping it still works but will see once driver board turns up hehe (embedded adventures says they will replace if not working 100%) which is good.

  • @russd, got it running local accessing your ip for the data. Began the separation of concerns work... and at the same time grow the inner workings of the DepartureBoard.js... a bit a challenge since it is all global function calling... said that, I could must put all JS code into one single file and it would still work... ;-).

    Question: what is the particular reason to use a JS written JSON parser and not the native JSON object as provided by the JS environment?

    I use the the JSON.parse() with a responseText of yours, and it works just fine...


    1 Attachment

    • departureBoardLocal.png
  • In Espruino's console, I made some initial memory tests.

    I set the

    to what the server delivers as JSON string. This used 137 variable elements of 2250 total.
    
    Then I set the responseObect to the JSON parsed responseText:
    

    var responseObj = JSON.parse(responseText);```
    This used another 240 variable elements of 2250 total.

    No code (except the variable references) - just the response string and response JS object use 377 variable elements of 2250, leaving 1837 for all the other things.

    A variable element is a number of bytes and is also a garbage collection entity (btw, strings are chained memory elements... so not contiguous memory bytes by definition, and therefore concatenation is quite 'simple' and effective) - Espruino has separate Web pages about implementation, performance, memory usage.

    This is from Espruino's Web IDE console:

    >process.memory();
    ={ "free": 2219, "usage": 31, "total": 2250, "history": 21,
      "stackEndAddress": 536909756, "flash_start": 134217728, "flash_binary_end": 207484, "flash_code_start": 134443008, "flash_length": 262144 }
    >var responseText='{"generatedAt":"2015-01-11­T21:29:18.7728461+00:00","locationName":­"Reading","crs":"RDG","platformAvailable­":true,"nrccMessages":"","trainServices"­:[{"origin":{"locationName":"Bristol Temple Meads","crs":"BRI"},"destination":{"loca­tionName":"London Paddington","crs":"PAD"},"std":"21:20","­etd":"21:28","platform":"15","serviceID"­:"r9ccnXCZphVkCGddcS7usw==","subsequentC­allingPoints":[{"locationName":"London Paddington","st":"22:05","et":"On time"}],"operator":"First Great Western","operatorCode":"GW"},{"origin":­{"locationName":"Didcot Parkway","crs":"DID"},"destination":{"lo­cationName":"London Paddington","crs":"PAD"},"std":"21:27","­etd":"21:32","platform":"15","serviceID"­:"Gy57d\/+itMP4lsK2ot8HAQ==","subsequent­CallingPoints":"","operator":"First Great Western","operatorCode":"GW"},{"origin":­{"locationName":"London Paddington","crs":"PAD"},"destination":{­"locationName":"Didcot Parkway","crs":"DID"},"std":"21:27","etd­":"On time","platform":"12","serviceID":"ew4Mk­Xo5cIVDvxHkrFnaYw==","subsequentCallingP­oints":"","operator":"First Great Western","operatorCode":"GW"},{"origin":­{"locationName":"London Paddington","crs":"PAD"},"destination":{­"locationName":"Exeter St Davids","crs":"EXD"},"std":"21:31","etd"­:"On time","platform":"7","serviceID":"vil6sU­ouIa4aG4JGvcCtmA==","subsequentCallingPo­ints":"","operator":"First Great Western","operatorCode":"GW"}]}';
    ="{\"generatedAt\":\"2" ... "atorCode\":\"GW\"}]}"
    >process.memory();
    ={ "free": 2102, "usage": 148, "total": 2250, "history": 143,
      "stackEndAddress": 536909756, "flash_start": 134217728, "flash_binary_end": 207484, "flash_code_start": 134443008, "flash_length": 262144 }
    >var responseObj = JSON.parse(responseText);
    ={
      "generatedAt": "2015-01-11T21:29:18.7728461+00:00",
      "locationName": "Reading",
      "crs": "RDG",
      "platformAvailable": true,
      "nrccMessages": "",
      "trainServices": [
        {
          "origin": {
    "locationName": "Bristol Temple Meads",
    "crs": "BRI"
           },
          "destination": {
    "locationName": "London Paddington",
    "crs": "PAD"
           },
          "std": "21:20",
          "etd": "21:28",
          "platform": "15",
          "serviceID": "r9ccnXCZphVkCGddcS7usw==",
          "subsequentCallingPoints": [
    {
      "locationName": "London Paddington",
      "st": "22:05",
      "et": "On time"
     }
           ],
          "operator": "First Great Western",
          "operatorCode": "GW"
         },
        {
          "origin": {
    "locationName": "Didcot Parkway",
    "crs": "DID"
           },
          "destination": {
    "locationName": "London Paddington",
    "crs": "PAD"
           },
          "std": "21:27",
          "etd": "21:32",
          "platform": "15",
          "serviceID": "Gy57d/+itMP4lsK2ot8HAQ==",
          "subsequentCallingPoints": "",
          "operator": "First Great Western",
          "operatorCode": "GW"
         },
        {
          "origin": {
    "locationName": "London Paddington",
    "crs": "PAD"
           },
          "destination": {
    "locationName": "Didcot Parkway",
    "crs": "DID"
           },
          "std": "21:27",
          "etd": "On time",
          "platform": "12",
          "serviceID": "ew4MkXo5cIVDvxHkrFnaYw==",
          "subsequentCallingPoints": "",
          "operator": "First Great Western",
          "operatorCode": "GW"
         },
        {
          "origin": {
    "locationName": "London Paddington",
    "crs": "PAD"
           },
          "destination": {
    "locationName": "Exeter St Davids",
    "crs": "EXD"
           },
          "std": "21:31",
          "etd": "On time",
          "platform": "7",
          "serviceID": "vil6sUouIa4aG4JGvcCtmA==",
          "subsequentCallingPoints": "",
          "operator": "First Great Western",
          "operatorCode": "GW"
         }
       ]
     }
    >process.memory();
    ={ "free": 1873, "usage": 377, "total": 2250, "history": 149,
      "stackEndAddress": 536909756, "flash_start": 134217728, "flash_binary_end": 207484, "flash_code_start": 134443008, "flash_length": 262144 }
    > 
    

    1 Attachment

    • depBoardRespTxtObjMemoryInConsole.png
  • Hey

    Wow that's pretty cool to see it running on the web ide :)

    Regards to the json parser I did not actually know there was a native one! I will definitely use it know I know it exists :) (I did come across it in node js and just assumed it was a node js thing did not know it was a standard javascript method hehe)

    I have almost got it working with the removed html canvas :) still working on that canvasCopy method (not quite working right lol) Hopefully finish it off tomorrow in work. But it still all runs fast and is looking good and is using pure byte arrays now :D not relying on html canvas which is nice if I ever wanted to port this to another language.

  • Great to hear... what I though think is that the array/buffer part should be in a separate class. The way the code works now, is preparing everything in a buffer on bit level - actually rendering the characters - and then all that data - bit image buffer - is sent to the display system (Canvas). This may get short handed on memory, because the setup is not taking advantage of the display controller's buffer / memory and processing and function power (the controller implements quite powerful render operations, including scrolling).

    Refactoring the bit to buffer code into its own class enables it to be easily replaced with the display's buffer and code.. If the controller has not the desirable font(s) and no way to upload them, one character is rendered at a time and then shipped as a bit image... I know for sure that with a display with 16 bits of color (actually 24 bits when going through the Espruino Graphics interface) per bit and a much higher dot density than a LED panel, it is becoming a lot of bits... just as @Gordon mentioned (The display I have is a 2.8" diagonal TFT LCD with 320x240 pixels, a pixel density of about 138 dpi, where as with 5mm LEDs on the panel you end up with 5 dpi. Even with the adjustment of the viewing distance, dpi ratio is still between 3..5 to 1 for LCD vs. LED.)

    The display controller's buffer can be seen as the (or canvas / context) which understands most importantly text drawing commands: just sending the ASCII string together with foreground and background color information, font size information, and may be font type id, and position is sufficient. I know already for sure that I cannot have 3 bytes per bit in buffers if I want to run simultaneously also other code and and data in the main processor's memory.

  • After some wifi connectivity skirmishes with the CC3000 module - see - I'n now ready to read data... this is the code I'm using:

    var SSID = "MySSID";
    var WPA2Key = "MyWPA2Key";
    
    var log = function(s,e) { 
      var p = "" + (Math.round((getTime() - t0) * 1000) / 1000) + "000";
      var d = p.indexOf("."); console.log(((e) ? "E: " : "-: ") + ((p < 0) ? 
        p.substr(p.length - 3) + ".000" : p.substr(0,d + 4)) + ": "+ s);
    };
    
    var t0 = getTime();
    log("Connecting to CC3000...");
    var wlan = require("CC3000").connect();
    if (wlan) {
      log("Connecting to wifi access point...");
      wlan.connect( SSID, WPA2Key, function (s) {
        log("Connected with " + s);
        if (s == "dhcp") {
          require("http").get("http://54.148.129.1­0/ldbwsService.php", function(res) {
            var str = "";
            res.on('data', function(data) {
              log(">" + data);
              str += data;
            });
            res.on('close', function() {
              log("str: " + str);
              var obj = JSON.parse(str);
              log("obj: "); console.log(obj);
              var mem = process.memory();
              log("Memory free: " + mem.free + "  -  usage: " + mem.usage);
              wlan.disconnect();
              log('CC3000 disconnected.');
            });
          });
        }
      });
    } else {
      log("Did not get wlan object / not connected to CC3000.",1);
    }
    

    And this is the expected response - so far in the console... is:

    1. response fragments (>)
    2. response string - a JSON string, all of it (str: ....)
    3. JSON parsed object (obj: ...)

    The time is in [s].[ms] to give a feeling about the speed behavior:

    • about 20[s] for to connect
    • about 1.5[s] for sending the request, get the response, and parse it into an object.

            |_| http://espruino.com
      1v71 Copyright 2014 G.Williams
      >echo(0);
      -: 0.001: Connecting to CC3000...
      -: 2.629: Connecting to wifi access point...
      =undefined
      -: 9.079: Connected with connect
      -: 19.227: Connected with dhcp
      -: 19.229: Sending request
      -: 20.418: >{"generatedA
      -: 20.423: >t":"2015-01-12T07:36:00.9734935+00:00",­"locationName":"Reading",
      -: 20.429: >"crs":"RDG","platformAvailable":true,"n­rccMessages":"","trainSer
      -: 20.435: >vices":[{"origin":{"locationName":"Read­ing","crs":"RDG"},"destin
      -: 20.441: >ation":{"locationName":"London Paddington","crs":"PAD"},"std":"0
      -: 20.447: >7:34","etd":"07:36","platform":"14","se­rviceID":"9yEl2b7IcoQGhuh
      -: 20.452: >J7UqicA==","subsequentCallingPoints":[{­"locationName":"Twyford",
      -: 20.458: >"st":"07:41","et":"On time"},{"locationName":"Maidenhead","st"­:"
      -: 20.464: >07:49","et":"On time"},{"locationName":"Taplow","st":"07­:53","et
      -: 20.470: >":"On time"},{"locationName":"Burnham","st":"0­7:56","et":"On tim
      -: 20.476: >e"},{"locationName":"Slough","st":"08:0­1","et":"On time"},{"loca
      -: 20.482: >tionName":"Langley","st":"08:06","et":"­On time"},{"locationName"
      -: 20.487: >:"West Drayton","st":"08:11","et":"On time"},{"locationName":"Ha
      -: 20.493: >yes & Harlington","st":"08:16","et":"On time"},{"locationName":"
      -: 20.499: >Southall","st":"08:20","et":"On time"},{"locationName":"Ealing B
      -: 20.505: >roadway","st":"08:25","et":"On time"},{"locationName":"London Pa
      -: 20.511: >ddington","st":"08:38","et":"On time"}],"operator":"First Great
      -: 20.517: >Western","operatorCode":"GW"},{"origin"­:{"locationName":"Worcest
      -: 20.523: >er Shrub Hill","crs":"WOS"},"destination":{"locat­ionName":"Londo
      -: 20.529: >n Paddington","crs":"PAD"},"std":"07:35","­etd":"On time","platfo
      -: 20.535: >rm":"11","serviceID":"vUUvejQm7x3F4dRM+­SqC1g==","subsequentCalli
      -: 20.540: >ngPoints":"","operator":"First Great Western","operatorCode":"GW
      -: 20.546: >"},{"origin":{"locationName":"Reading",­"crs":"RDG"},"destination
      -: 20.552: >":{"locationName":"Basingstoke","crs":"­BSK"},"std":"07:37","etd"
      -: 20.558: >:"On time","platform":"2","serviceID":"I25K29­2y51sCtA1NaP7\/Gg==
      -: 20.564: >","subsequentCallingPoints":"","operato­r":"First Great Western",
      -: 20.570: >"operatorCode":"GW"},{"origin":{"locati­onName":"Frome","crs":"FR
      -: 20.576: >O"},"destination":{"locationName":"Lond­on Paddington","crs":"PAD
      -: 20.582: >"},"std":"07:39","etd":"On time","platform":"8","serviceID":"qcq
      -: 20.588: >riRjZax87JaIWts3i6g==","subsequentCalli­ngPoints":"","operator":"
      -: 20.594: >First Great Western","operatorCode":"GW"}]}
      -: 20.641: str: {"generatedAt":"2015-01-12T07:36:00.9734­935+00:00","locationName":"Reading","crs­":"RDG","platformAvailable":true,"nrccMe­ssages":"","trainServices":[{"origin":{"­locationName":"Reading","crs":"RDG"},"de­stination":{"locationName":"London Paddington","crs":"PAD"},"std":"07:34","­etd":"07:36","platform":"14","serviceID"­:"9yEl2b7IcoQGhuhJ7UqicA==","subsequentC­allingPoints":[{"locationName":"Twyford"­,"st":"07:41","et":"On time"},{"locationName":"Maidenhead","st"­:"07:49","et":"On time"},{"locationName":"Taplow","st":"07­:53","et":"On time"},{"locationName":"Burnham","st":"0­7:56","et":"On time"},{"locationName":"Slough","st":"08­:01","et":"On time"},{"locationName":"Langley","st":"0­8:06","et":"On time"},{"locationName":"West Drayton","st":"08:11","et":"On time"},{"locationName":"Hayes & Harlington","st":"08:16","et":"On time"},{"locationName":"Southall","st":"­08:20","et":"On time"},{"locationName":"Ealing Broadway","st":"08:25","et":"On time"},{"locationName":"London Paddington","st":"08:38","et":"On time"}],"operator":"First Great Western","operatorCode":"GW"},{"origin":­{"locationName":"Worcester Shrub Hill","crs":"WOS"},"destination":{"locat­ionName":"London Paddington","crs":"PAD"},"std":"07:35","­etd":"On time","platform":"11","serviceID":"vUUve­jQm7x3F4dRM+SqC1g==","subsequentCallingP­oints":"","operator":"First Great Western","operatorCode":"GW"},{"origin":­{"locationName":"Reading","crs":"RDG"},"­destination":{"locationName":"Basingstok­e","crs":"BSK"},"std":"07:37","etd":"On time","platform":"2","serviceID":"I25K29­2y51sCtA1NaP7\/Gg==","subsequentCallingP­oints":"","operator":"First Great Western","operatorCode":"GW"},{"origin":­{"locationName":"Frome","crs":"FRO"},"de­stination":{"locationName":"London Paddington","crs":"PAD"},"std":"07:39","­etd":"On time","platform":"8","serviceID":"qcqriR­jZax87JaIWts3i6g==","subsequentCallingPo­ints":"","operator":"First Great Western","operatorCode":"GW"}]}
      -: 20.667: obj:
      {
      "generatedAt": "2015-01-12T07:36:00.9734935+00:00",
      "locationName": "Reading",
      "crs": "RDG",
      "platformAvailable": true,
      "nrccMessages": "",
      "trainServices": [
      {
        "origin": {
      "locationName": "Reading",
      "crs": "RDG"
         },
        "destination": {
      "locationName": "London Paddington",
      "crs": "PAD"
         },
        "std": "07:34",
        "etd": "07:36",
        "platform": "14",
        "serviceID": "9yEl2b7IcoQGhuhJ7UqicA==",
        "subsequentCallingPoints": [
      {
      "locationName": "Twyford",
      "st": "07:41",
      "et": "On time"
      },
      {
      "locationName": "Maidenhead",
      "st": "07:49",
      "et": "On time"
      },
      {
      "locationName": "Taplow",
      "st": "07:53",
      "et": "On time"
      },
      {
      "locationName": "Burnham",
      "st": "07:56",
      "et": "On time"
      },
      {
      "locationName": "Slough",
      "st": "08:01",
      "et": "On time"
      },
      {
      "locationName": "Langley",
      "st": "08:06",
      "et": "On time"
      },
      {
      "locationName": "West Drayton",
      "st": "08:11",
      "et": "On time"
      },
      {
      "locationName": "Hayes & Harlington",
      "st": "08:16",
      "et": "On time"
      },
      {
      "locationName": "Southall",
      "st": "08:20",
      "et": "On time"
      },
      {
      "locationName": "Ealing Broadway",
      "st": "08:25",
      "et": "On time"
      },
      {
      "locationNa e": "London Paddington",
      "st": "08:38",
      "et": "On time"
      }
         ],
        "operator": "First Great Western",
        "operatorCode": "GW"
       },
      {
        "origin": {
      "locationName": "Worcester Shrub Hill",
      "crs": "WOS"
         },
        "destination": {
      "locationName": "London Paddington",
      "crs": "PAD"
         },
        "std": "07:35",
        "etd": "On time",
        "platform": "11",
        "serviceID": "vUUvejQm7x3F4dRM+SqC1g==",
        "subsequentCallingPoints": "",
        "operator": "First Great Western",
        "operatorCode": "GW"
       },
      {
        "origin": {
      "locationName": "Reading",
      "crs": "RDG"
         },
        "destination": {
      "locationName": "Basingstoke",
      "crs": "BSK"
         },
        "std": "07:37",
        "etd": "On time",
        "platform": "2",
        "serviceID": "I25K292y51sCtA1NaP7/Gg==",
        "subsequentCallingPoints": "",
        "operator": "First Great Western",
        "operatorCode": "GW"
       },
      {
        "origin": {
      "locationName": "Frome",
      "crs": "FRO"
         },
        "destination": {
      "locationName": "London Paddington",
      "crs": "PAD"
         },
        "std": "07:39",
        "etd": "On time",
        "platform": "8",
        "serviceID": "qcqriRjZax87JaIWts3i6g==",
        "subsequentCallingPoints": "",
        "operator": "First Great Western",
        "operatorCode": "GW"
       }
      ]
      }
      -: 20.724: Memory free: 1469  -  usage: 781
      -: 20.727: CC3000 disconnected.
      > 
      

    The very very first request brought the response string in on shot. I then added the JASON.parse to the simple sample code as described in Clienbt paragraph on CC3000 Module page. In great anticipation... nope: all following requests brought only a very tiny fragment containing: {requestedA. That was all. Some more reading - notably from the overall Internet (HTTP) page - lead back to working code again. Even though it is only a single shot at data, I'm satisfied for now. More later.

  • I'm afraid I don't have time to read through all of this right now - but in short:

    • You don't need to mess around with canvasses, you just need to create a special 'arraybuffer' graphics - see here
    • I'd really advise against writing all your own graphics library (unless it's done just to make the PC look like Espruino). Espruino graphics is quite fast because it's done in native C code internally, but as soon as you start writing to pixels by hand in Espruino you'll find that everything runs too slowly.
  • If I use the the custom espruino graphics canvas how will it work when running in a browser?

    Also if I draw directly to the dmd controller board canvas how will this work inside the browser? I had a look at what that board supports and i dont think it supports enough to do what I need. (would need a new font for a start!)(and can you draw fonts half off the canvas?)

    Using my own (very simple) byte array canvas (it only supports drawText and copyCanvas) and will work in the browser and on a micro controller (I am thinking of using the stmf4? which definitely has enough ram for all my little byte array canvas's)

    Another reason is if i do decide to just straight port this and run in c on a micro controller I can pretty much copy and paste all my logic and canvas code I am not relying on a certain os canvas library.

    I spoke to embedded adventures and they say I can either bump up the uart or use the i2c (need to write bit of code my self) to send the frame data to the dmd controller board. Which is my preferred method.

    Its cool to see the espruino making and parsing the networkrail request though using that wireless board. One step closer :D

  • If I use the the custom espruino graphics canvas how will it work when running in a browser?

    You'd have to write your own version of 'drawString' just for the browser - but you've basically done that all already.

    Using my own (very simple) byte array canvas will work in the browser and on a micro controller

    It will, yes - but chances are it'll run too slowly to get the 24fps update you want on Espruino - unless you run it on something like a Raspberry Pi, or you re-write everything in C.

  • Ah

    Even on Espruino running on a STMF4?

    I still like the raspberry pi idea.

  • Yes, even on the F4. It's possible you could get something but it'd be a real struggle.

  • Ah

    To be totally honest I have no idea what is actually happening under the hood when running javascript on a microcontroller.

    if you have a simple for loop in javascript is that not converting to a simple for loop in c? why does it run so much slower when written in javascript?

  • Well, JavaScript is an interpreted language, rather than a compiled language. It means that no work is done 'up front' by a compiler. The way there's no type checking makes compilation quite difficult.

    On a PC, with something like Chrome and V8, it cheats - and when the webpage is loaded V8 does a lot of clever stuff and basically 'compiles' the JavaScript to native code every time a webpage is loaded. On other (often older) JS interpreters they compile the code to an intermediate form (like a bytecode).

    On Espruino there just aren't the resources to do that on the chip, so it actually executes the text strings your wrote directly - which makes it a lot slower.

    I'm actually doing some work on partially compiling the JS code up front using the Web IDE, but that's still some way off being useful.

    At the end of the day, it can still all be done, and can be done really easily using the built in Graphics class... but if you want to write your own new Graphics class then you're probably better off using something else like a Pi with node.js.

  • I had a different thought... why not use the interface that the context of a html canvas has... the application talks in JS the same way to this interface whether running in a browser or in a dedicated micro controller.

    Based on that idea - but with the give Graphics library and the given's of @russdx's lcd panel controller api - I was thinking of an adapter that has on one side - the application side - the context api of the browser canvas and on the other side it speaks to the Espruino Graphics lib or the LED panel controller interface. For example: how much can the api for drawing a line (in a 2D context) be semantically different between any of the environments? Lets wrap the setting of fonts in an api as well that requires only to pass an ID and let the dedicated implementations - which are loaded with ID matching profiles - do the settings. Yes, it adds layers, but @russdx would like to run the very same (high) level application code on just any platform... @Gordon, no adversary thoughts here, just a question: could you imagine the Espruino graphics have the same api as the 2D context of an html canvas?

  • could you imagine the Espruino graphics have the same api as the 2D context of an html canvas?

    For drawing text, yes - for lines etc, it's possible but not without a lot of overhead (as the HTML5 Canvas lets you define a path, and then 'stroke' or 'fill' it afterwards).

    It'd be a lot easier to do as you say, but the other way around: Create an Espruino-style graphics object but on the PC (where you have enough resources for the adaptor).

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

Is Espruino right for my project?

Posted by Avatar for russdx @russdx

Actions