Real time connections with the Spark

I’ve been doing some thinking about the Spark core and Cloud API in general. While the cloud is very fast, is there a way to establish a websocket with it? I’d like to avoid the additional overhead from connectivity in rapid HTTP calls. My example is controlling relays with the spark core and having it turn on/off lights to Christmas music. I don’t want to store the algorithm for every single song in memory on the core but rather I’d like to pass data to it in real-time so it can process that and act accordingly. This type of real-time connection would be a serious step forward (if it doesn’t exist already.)

Also, for things like home automation and Christmas light synchronization, I could avoid this extra bandwidth by using a local websocket so I never have to go out into the real world.

Is this doable? If not, how can we make it so? If so, you’ve made my day :slight_smile:

1 Like

Maybe you could try to implement your own TCP server? Instead of web sockets, you might be able to implement a simpler telnet-like interface.

That is a very interesting idea. Like a TCP Server that cuts out additional stuff and streamlined for fast communications. I’m gonna think about this a little more.

For real time data streaming, you would use a UDP client. Currently it’s partially implemented? … but not documented. The trade off for speed is that some packets may be dropped, but if you want to keep in sync… you will likely not miss any dropped packets for something like christmas lights.

How many packets would be dropped though? I don’t use UDP much but I know it’s used a lot in games.

Also, in the absence of UDP implementation: keeping a socket open to the TCP Server and sending packets back and forth would still be much faster and reduce overhead from HTTP connections, no?

There is no such thing as “realtime” TCP/IP or UDP/IP. The IP protocol stack, your wireless router, the cloud servers, etc do not guarantee deterministic packet delivery times.

UDP is more “predictable” than TCP because delivery of stream data is not blocked if a packet is lost to ensure in-order delivery. With UDP either a packet is received after some normally distributed delay, or its never delivered. But again, delivery times are not ensured or deterministic.

For your application its much easier to download the relay sequence ahead of time and rely on some STM32 hardware to synchronize the start of sequence to an external source.

As far as UDP reliability goes, it’s reliable enough. Most multiplayer games use UDP, and it’s pretty reliable when you need to react fast in a first-person shooter video game (instagib at 200% speed anyone?). Where you will see most of your packet loss is on a wireless connection. Your standard wifi router setup at home or in the office is probably pretty reliable as long as you have good signal strength. However, it is possible for things like old microwaves, crappy fluorescent lighting ballasts, and even noise in your home electricity to cause signal interference, but those are more like exceptions rather than the rule. A cell phone data connection is more likely to have noticeable packet loss, but even the 4G networks are now good enough for voice-quality VOIP.

I think the basic summary is that if you need 100% perfect accuracy, you’ll need to use TCP. If speed is more important than accuracy, use UDP. If you aren’t sure, you might just have to test both.

However, if you implement a basic TCP server, you can skip the HTTP overhead of all of the headers being sent back and forth between the server and client (which can be a lot of overhead data compared to the important bits that you’re really interested in). Another caveat with a TCP server on the core is that if you want to keep an always-open connection (a la telnet), the Spark may have issues if the sketch blocks the every-15-second cloud check.

Thanks for clarifying guys! @mattande I use “real time” in a loose sense… it’s close enough that you wouldn’t perceive a delay for xmas lights synchronized to music, but is lagging the music by networking and processing propagation delays.

@carldanley I bet TCP would be fast enough for your light data… you could pack all of the control for your lights into one 16-bit integer actually… 16 outlets, on/off for each one. Creating the table of synchronized lights to music timing is a different story though. I suppose you could add a 32-bit int for a timecode in milliseconds from the start of the song. You almost need to build a 4 x 4 style button controller that you could use as your light controller composer… then just keep recording over and over and filling in bits and patterns with the song. As you play the time code gets stamped to memory from your controller, and dumped to a file when done. If you could set the BPM for the song, and sync it… you could group your recorded lighting decisions into perfect timing… a la autorhythm. Node.js would be good for this I think, or maybe even Processing. There’s probably an application out there that could do all of this easily though like Ableton, Fruity Loops etc…, and use a standard Midi Controller.

That limited data over a local network with UDP or TCP should be plenty fast!

[EDIT: I initially assumed were having the spark stream the audio, as well as the lighting codes, but re-reading your post, it seems that you’re sending the audio somewhere else. Either way, sending timecodes with the lighting signals, and pre-buffering is the way to avoid the network latency issues.]

If you’re syncing lights to music, surely you’d be sending timecodes or lighting instructions along with the audio? As others have said, TCP might be perfectly fine, but if you do choose UDP the odd dropped packet won’t make a difference- the lights and audio will always be in sync.

You might consider using some RAM and the external flash memory as a buffer to help smooth out any dropouts. The main issue with flash memory is wear. A circular buffer in flash memory would wear each 4k page equally. Given that there’s 1.5MB of free space, that’s the equivalent of about 2 minutes of uncompressed 44.1kHz 16-bit stereo audio. With expected lifetime of 100k writes, that’s about 3300 hours or 132 days of continuous playback.

More elaborate schemes can detect if the buffer is needed and only activate when there have been sufficient network delays or dropouts in the last few minutes to make it worthwhile.

There’s also mp3 decoder software library available for the STM32 -

Here is my two bits on the near real time spark core connection bit

The core intercepts a normal http GET request. Activates D7 on the core and then shuts down the connection returning nothing to the calling web page. Not perfect but faster than the cloud.