See the corresponding blog post here.
The main objective here is to write a
sendToServer function that is an example of an operation that hypothetically takes 3 steps to complete: powering on the modem, connecting to the server, and sending the data. In the spirit of writing non-blocking, single-threaded code, this uses callbacks to trigger the next step when the previous completes.
The example is not fully comprehensive. For example, it doesn't include error checking or timeouts. It doesn't check if the modem is powered on, but just powers it on each time (it also doesn't power it off). But it's easy to imagine how
modem.powerOn() could be changed to
if (alreadyPoweredOn) ... , etc.
The example code here is structured into 4 layers:
main.mjsis just an example usage of the
send-to-server.mjsis the implementation of
sendToServer, basically the same as what was shown in the blog post.
events.mjsis an example event system to translate events from the host firmware into callback calls. This is not specific to the modem code but could underly all events (there is no mention of "modem" in event.mjs).
(in this gist I've prefixed the filenames with numbers just to keep them in order of these 4 layers)
The key point to notice in this example is that the implementation of
modem.powerOn (and the other methods) do not block while the modem powers on. Instead, it starts off the process using
startModemPowerOn and then waits for call from the host firmware to say when the modem is on. During this waiting, the VM is idle and the VM call stack is freed.
When the host firmware calls the JS method
eventReceivedFromHost('modem-powered-on') then the VM wakes up, allocates the call stack, and triggers the next thing to be done
modem.connectTocalls the host firmware function
- Then the VM goes idle again until the next event.
The main intention of this example is to communicate how easy it is to write the high-level, single-threaded, non-blocking logic such as that in
sendToServer, compared with doing the same thing in C.