Mqtt blocks

hmm-- well, "MQTT is data-agnostic so it's possible to send images, texts in any encoding, encrypted data, and virtually every type of data in binary format." (1). So, conceivably yes something like this could be done. Practically, though, I'm not sure that would be very effective.

(The block idea you posted should be an mqtt_pub block: the mqtt_sub block subscribes to a topic and only takes one argument. Instead, we'd use the mqtt_pub block to publish a message to a topic...)

The example you presented publishes this message:
snapmqtttest: Context >> a CommandBlockMorph ("move %n steps...") a VariableFrame {}

Really, what messages to send and receive is completely up to you-- what is done on the receiving end is dependent on how you parse out and respond to the received message!

Mike

You can do anything with JSFunction. The trick is, you have to read the source code to figure out how. So for example, I know that the implementation of command blocks is generally called doWhatever(), so I searched through the src directory for "doSetVar" and sure enough I found Process.prototype,doSetVar(name, value) in threads.js. Unfortunately, "this" in a JSFunction block is a sprite, not a process, so you have to know that JSFunction calls your function with an extra argument, the current process. So:


I haven't carefully debugged this; for example, I should make sure it does the right thing with script variables.

I am not a Snap! internals wizard. "Duct-tape coding" is a pretty good description of all my efforts to contribute code to Snap!. (Jens yells at me a lot about my code, correctly.) I knew how to find the process in a JSFunction because Jens explained it once in a forum post. I should really make Jens write a Program Logic Manual, When Things Slow Down™.

I also found a "Process.prototype.doBroadcast" in threads.js, so I wrote this:


I know, you want to call these from Javascript, not from Snap!. So I'm guessing you have to create a new Process to carry out the computation in. But that's as far down this rabbit hole as I have time for...

Thanks, Brian. I've got things working kind-of the way I like by just using a "forever" loop to poll for incoming messages... I guess, as I think about it more, I prefer having Snap! in change of message processing rather than a javascript block, at this point.

Have done some tweaking today. My current version is here.

Have solved my problem of needing to "init" twice by breaking down the "init" and "connect" into two steps-- adding a moment between them allows the external javascript to get loaded and enabled.

Have added a "poll for incoming messages" block which does a broadcast, and have added a broadcast receiver as an example of how one might parse incoming messages.

Interesting to ponder: if multiple people are running this Snap! app at the same time and are connected to the same mqtt broker and are subscribed and publishing to the same channels-- things could be done in Snap! simultaneously on all of those machines... In other words, if you and I are both connected at the same time running this program as it is, and one of use sends a "move" command-- both of us will see our sprites move at the same time... (Works across multiple browser tabs, too... : )

Mike

1 Like

Interesting. Do you know about NetsBlox (https://editor.netsblox.org/)? They added a feature to let two people edit the same project at the same time. Maybe you should compare notes.

Nice! I recall seeing NetsBlox at one point a year or two ago. Certainly a different model and tool than mqtt, but-- powerful stuff!

Great progress :slight_smile:

I've used your framework to make a simple cheerlights display

Woot! That's awesome!

I've found a limitation: on my machine, when I subscribe to a really busy topic like "#" (all topics) on test.mosquitto.org, the messagequeue buffer fills faster than Snap can process the queue. Eventually, the mqtt connection was closed (apparently due to some kind of error)... So, there's that...

Also, I selected "&&" as a delimiter between topic and payload for when the JavaScript function returns a message to Snap. I don't know if it's possible for an mqtt topic to contain '&&', so I don't know if this is a safe delimiter. I'll do some digging in this...

Mike

Cute application... We really should queue events so that you can rely on a hat block. It's on the list...

fwiw, found this good article on mqtt topic naming best practices... There aren't really any forbidden characters per se in mqtt parlance. However, there are a couple of wildcards ("#" and "+") that can be used when subscribing, but therefore could never be part of a topic name. So, I think I'll switch that delimiter to "###" instead...

The article also mentions that-- it's not recommended to subscribe to the "#" topic of busy servers because most clients would be overwhelmed... So, this isn't a "Snap" issue... : )

Moving forward,as I tweak and adjust this-- I'll use this sketch as the "master"...

Mike

I always feel like "wait 1 secs" as a synchronization mechanism is a sign of a missing feature. The Scratch way to do this would be a "broadcast and wait." But I guess what you're waiting on isn't another script, but an external event, so... Ah, we're back at the discussion of using Snap! scripts as callbacks in JS code.

See my feature request

Javascript can return a List so no need to assemble and then disasemble :slight_smile:

if (messagequeue.length > 0) {
  thismessage = messagequeue.shift();
  console.log("retreived queued message= "+thismessage.destinationName+": "+thismessage.payloadString);
} else {
  console.log("No messages in queue");
}
thismessagedest=thismessage.destinationName;
thismessagepayload=thismessage.payloadString;
return new List([thismessagedest,thismessagepayload]);

image

Awesome! Returning the list object is perfect! Have updated the "master"... : )

Mike

1 Like

I also realized that my logic for determining when to broadcast "newmessagereceived" was flawed: it ignores multiple sequential mqtt messages that are the same, which could be a legitimate situation (for example, if a sensor is reporting temperature every few minutes, it's likely that many readings in a row would be the same. However, if I wanted to gather and graph that data, I'd want each reading even if it is that same!)

So, I've changed the underlying messagequeue processor to add a "new message" flag that's passed up to Snap... Is all still contained in the poll_for_mqtt_messages block.

The "master" has been updated...

Mike

I just read the Snap!Con schedule and saw that someone is doing a talk on #MQTT for Snap! - looking forward to that very much :slight_smile:

In the past few weeks I've been playing around with @mikep345678 project - I wanted to try and not have to poll in a loop from Snap! and thanks to the new JS API - I managed to do that (please remember I am the world's wort JS programmer)

So, I'm just publishing my efforts here just for posterity and looking forward to what comes from the conference

My project only reads cheerlight #MQTT info and contains a lot of debugging info but I'm leaving it all in in case it helps any other JS muggles like myself :slight_smile:

image

Awesome! Glad to see there's growing and ongoing interest in MQTT and Snap! I haven't touched my mqtt project since early last year, but did successfully utilize it without modification earlier this spring (pre-COVID) with a bunch of students for a couple of short robotics sessions...

Looks like there are actually two MQTT sessions scheduled at Snap!Con... Am registering now! : )

Mike

Latest tweak
The underlying JS code only sends a broadcast back up to Snap! when a flag variable (mqtt_queueFlag) is set to true.

This is to try and make sure that no messages are lost

They should now be added to in the queue in the JS and broadcast only sent if Snap! signals that its finished dealing with previous messages in the queue

Don't think I'm quite there yet with how to interact properly from a JS long running background prog but its fun playing and learning :slight_smile:

image

will we have this feature in the future

That's a good question. We'd entertain the submission of a proposed library. Dunno that any of us have time to do the development, though.

There is an extension named MQTT4Snap! (GitHub - pixavier/mqtt4snap: MQTT for Snap!)

:slight_smile:

I know :slight_smile:

It is what I use now :slight_smile:

My SnapCon21 talk will mention it :slight_smile: