Initiating a backround JS code from SNAP!

I tried posting this into the existing topic Call block from Javascript?, but I think it is closed and did not work.

Anyway, here is what I need help with:

I have a Javascipt code that runs async and talks to the USB port using the WEB Serial Interface of Chrome. It receives and sends data on an interrupt fashion, using promise / awaits. I initiate this by opening the Developer console and pasting and running my code. I have added Jen's SNAP API items in it and could communiate to my SNAP project without a problem.

What I want to do is initiate the running of that code from within the SNAP project without going to the dev console. I tried the JS block, and of course that does not work in my case, since the exit terminates the link to it.

So, is there a way I can initiate this JS code from within SNAP and have it run in the background continuously, while I interact with it from SNAP and vice versa?

I am not a strong JS person, so please be gentle with the suggestions.

proc.evaluate(
    <block>, //put the variable that has the block here
    new List(), //args
    true //is command
);

I do not know how to deal with your answer.
Is this supposed to go into the JS block?

Yes, and include an extra argument named "proc".

I think I will need more help in populating the JS block based on your answer.
What is block, new List(), and true ?

The comments explain it.

If you start async function with IIFE

(async function() {

...
      code here
e.g.
      setup_WEB_Serial(); 
        while (true) {
            const { value, done } = await reader.read();
            Snap broadcast ("received", value);
...

})();

return true;

Javascript async loop will be still running (in the background) after returning to :snap: .

Thx dardoro, I will try this and report.

'cause I deleted my other message, this one needed addt'l sentence for the editor to accept it.

dardoro, once I have the JS code running in the background, can I use the same technique to communicate to the running JS code, meaning execute its functions from SNAP using further JS blocks?

OK, I am a bit puzzled; but that's normal !
It worked ! It executes in the background and updates the SNAP vars without a problem.
However, when I try to execute addt'l JS blocks, trying to conjure the functions in the code, they do not work. (This is also the answer to my previous question, I guess.)

Also, after the background execution starts running, if I go into the Dev Tools from the SNAP window and try to reach any of the code's variables or functions, they all return UNDEFINED...

So I am wondering where the executing code is and how I can reach it again ?

But thanks anyway for getting me over the intital hurdle.
I have a lot more to learn to be fully successful.

Used this way communication is mostly one-direction.
Read-loop can submit data to :snap: with broadcast or global variables.
There is other pattern. Inside async function global object can be created to store API.

(async function() {

window.myAPI = new mySerAPI(...

})();
return true;

Then accessed with

window.myAPI.write(..
window.myAPI.readloop(...
window.myAPI.readBuffer

Changed the post group.
Thanks for the answers.
I will try the new method and see how far I get.

hi dardoro,
I could not make the global object version work.
I think I am making some syntax error in trying to encapsulate my code within the (...)

If you can assist, it will be great.
If not, I will seek some other assistance.
Thx.

I planned to make a WEB USB/Serial blocks for :snap: to directly interact with the Arduino board. Maybe it will be useful for Your needs.

How can i help?

Hi dardoro,

Thanks for your interest and offer to help.
tguneysu@msn.com - I am located in Cappadocia, Turkey GMT+3.

As a background, I am a participant in the MicroBlocks development efforts, working with John Maloney and Bernat Romagosa. The functionality I was trying to achieve has to do with being able to interface to the devices supported by the MicroBlocks at the VM level. By exchanging VM micro codes over USB connectivity, in both directions, it is possible to achieve a tightly integrated control functionality with these devices.

I have done some initial work on the APP Inventor environment and gotten great results. Now I want to apply this experience to the SNAP environment. The lack of Serial interface in SNAP necessitated this WebSerial experiment. Unfortunately, I am not a JS proficient person; just enough to get by. But in this instance, even that was obviously not enough !

My needs are about reading and writing to the USB port on a per byte / multiple byte basis, meaning not delimited by any newLine or carriage return requirements found in some serial IO routines.

I initially put together a read routine from the WebSerial docs and was able to make it work from the Console interface, and then made it a background function initiated from SNAP with your initial assistance. But as you pointed out, it was only good for reading from the port. I was not able to call the write functions in my code from SNAP to output to the USB port.

I guess, the simple way to define the functionality would be:

  • kick off a background USB Serial IO routine from SNAP, it keeps running in the background.
  • then issue read and write requests to it from SNAP, potentially using SNAP variables as carriers and deposit destinations for the data.
  • USB speed of 115200 is the only one I am interested in, but for more general use, it might be useful to support baud settings.
  • I read that Web USB has a 1024 byte buffer capability. That is more than enough for my interests.
  • The encoding of the data is not crucial for me; SNAP has enough functionality to convert byte data to dec / hex / bin formats. I guess a basic UTF-8 support would be good starting point.
  • There is the complication of "waiting for the event to complete" issue:
    For me this is not a big deal, as every write request will be followed by an immediate response (read) from the remote device I am interested in. As such, it is not a requirement for the "SNAP stream to NOT be locked on waiting" in my case. But for more general use, I can see that eg: for continuous data collection type activities, a more callback driven implementation could be useful for others.

That is all I can think of for now. I am sure further exchanges might generate other mods.

Thanks again.

Hi,
I'm from Szczecin@Poland, CEST, GMT+2.

This is a "proof of concept" of WEB Serial API for Snap!
It's slightly biased to my preferences. Only the port instance is shared and, after every read/write operation, consistent state is restored (at least I hope so).

Tested with simple Arduino "echo" sketch

void setup() {
  Serial.setTimeout (100);
  Serial.begin( 115200);
  Serial.println( "Hello from Arduino@WEB Serial");
}

void loop() {
  if( Serial.available() > 0){
    Serial.write( Serial.read());
  } 
}

Hi dardoro,
This is very promising ! Works good.

Question:
does the timeout happen when there is no data coming in ?
OR
it reads the port for timeout ms and then returns whatever it got?

The reason I am asking is, I keep getting partial data buffers spread across the in list variable. And I know that all the data I am expecting is coming out as one continuous stream.

Thanks to clarify.
TG

Timeout is for waiting on Promise completion.
Read can return:

  1. data returned by completed Promise
  2. "" for timed-out read
  3. Error object which is translated into Snap! exception

Did You see a data lost or just empty responses ("gaps")?
How "continuos" is the data stream? Didn't it overrun a hardware capability? I'll try to emulate such stream, to see what happens.

BTW: Asynchronous blocks cannot be run in "warp". Concurrent execution in the Snap!/JS is only "simulated" by cooperative effort...

Updated project to comply with a simulated stream of 4000 bytes + EOF(255) marker.
Arduino stream sketch

void setup() {
  Serial.setTimeout (100);
  Serial.begin( 115200);
  while (!Serial) {
     delay(1); // wait for serial port to connect. Needed for native USB
  }
  Serial.print( "Hello from Arduino@WEB Serial");
}

int frame = 0;
void loop() {
  if( Serial.available()){
    if( frame <4000){
      Serial.write( (frame % 100)+1);
      frame++;
      Serial.flush();
      if( frame==4000){ Serial.write( 255);}
    }
  }
}

Maybe I used the wrong term with "continuous stream".
It was meant to be: data comes out in various length chunks, but always as complete units.
In my case, response lengths can vary from 6 bytes minimum to several hundred bytes, never exceeding 1000 bytes.
I will play with your Arduino example to get a better understanding of the exchange details.

My question on the timeout was to understand:

  • if the timeout is short, but the Serial has data to receive, will it keep receiving it beyond timeout limits and complete the incoming data chunks?
    OR
    cut them up into separate buffers depending on the length of data and timeout interaction?