Pixelblaze-client: Python 3 library for Pixelblaze

@zranger1 you have my permission and support :slight_smile:

BTW I think the naming thread was just for the the package name in PyPi (mentioned by @vutang50). But if you do want to rename the repo, GitHub made it easy, no re-create necessary.

1 Like

Thanks @wizard!
LOL, just habit from years in the world of extremely large software, where renaming or moving anything generates an instant flood of support traffic. What I’m doing is this:

  • Create and test new repository, leaving the old one in place
  • Once the new one is working, empty out the old one, leave just the readme with a pointer to the new repository, and an apology for Disturbing The Force by renaming and/or moving things.
2 Likes

pixelblaze-client is now up on github. I’ll work out the namespace and setup issues and see if I can get us published on PyPi in the next few days. It’ll (eventually) simpler for users.

3 Likes

I think some form of finding units on a network is still key. A likely use is setting up an installation somewhere and the units IPs will not be known.

It’s coming… requires a little messing about with threading and a datagram listener. I’ll do detection and Firestorm style time synchronization (though probably not the pattern cloning) with this set of tools too. It’ll be a separate class for which I have not yet thought of a good name – PixelblazeDetector? ArmyofPixelblazes?

People in this part of the country come up with place names like “Big Balanced Rock”, and “Numerous Potholes”. The lack of imagination may have finally gotten to me.

3 Likes

Yeah, pattern cloning is not really needed.

Excellent! I appreciate the addition of getColorControlName() as that made the integration code much cleaner. This suits my needs as I don’t want to have to think about an arbitrary number of color pickers as I only want to focus on 1, but its incredible how flexible and dynamic the Pixelblaze UI and controls can be.

Next steps is to automate with HASS and Node-Red so that when my media players play a song, I can switch to a sound pattern.

2 Likes

Just updated to v0.9, which includes the new PixelblazeEnumerator class. It listens continuously for Pixelblaze beacon packets, maintains a list of Pixelblazes visible on the network and supports synchronizing time on multiple Pixelblazes. The essential API looks like this:

  • PixelblazeEnumerator(bind_ip=“0.0.0.0”) - Create an object that will listen for Pixelblazes on IP address bind_ip, or all available interfaces if bind_ip is not specified.
  • getPixelblazeList() - Return a list of the IP addresses of Pixelblazes that are currently visible on the network
  • synchronize() - Set the time on all currently visible Pixelblazes to match time on the sending computer.

plus several more methods to control timouts, automatic synchronization, shutdown, etc. Documentation and sample code are in the repository.

Unless we find a showstopping bug, or a necessary feature that got left out, the pixelblaze-client library is now feature complete. I’m going to move ahead with getting it published on PyPi this week. Hope lots of people use this, and have fun making amazing things!

2 Likes

Hi @zranger1,
Awesome!

For timesync stuff, the reply should go out right as soon as the beacon is heard. The latency should be as low as possible and as consistent as possible. Pixelblaze uses many of these over time to figure out the round trip time and half the median RTT is used to get it stable within a few ms. Similar to NTP’s clock sync algorithm.

So think of it more of a mode than a one time sync. Should it reply or not?

Only one node should reply on a network. I don’t yet have an election process to prevent multiple replies (or from handling multiple replies), and if there are things can get glitchy. Right now it’s assumed that either there will be only one Firestorm / pixeblaze-client w/ timesync mode on, or that a PB in AP mode can reply.

It looked like NTP, but in testing here, the 5 second interval didn’t seem to make much difference, so I left it that way to control wifi traffic. In retrospect, that’s because in my particular situation – doh! around 1ms RTT, no appreciable jitter on the LAN.

I’ll get rid of the explicit synchronize() API, and set it up so that enabling synchronization responds to every beacon packet. I didn’t see any election-like traffic, so I just “borrowed” firestorm’s ID, assuming that it was always the one in charge.

Is it worth watching for other timesync packets, and deferring to any other time source that’s already sending? At this stage, this is all easy stuff to implement.

It uses the time since beacon to timesync to determine the offset, so I would expect that if you booted a handful of PB at different intervals, and were sending timesync every 5s to everything, the’d get weird offsets like 0-2.5s depending on how that lined up.

There isn’t anything special about Firestorm’s ID, other than it’s Firestorm’s ID. Feel free to pick a random 32 bit number, or choose a favorite number. It would be good to choose a different one than Firestorm for network debugging purposes.

Yeah, deferring to another source is one way to elect a leader. If all timesync sources used the same algorithm, like defer to lower ID sources if heard within 10s or something. I planed to read up a bit more on election algorithms before doing anything like that just to make sure I’m not falling into some known traps.

I could also make PBs smarter, so they focus on a specific source, but it’s still better to have fewer packets flying around.

Cool… I’ll make all these changes and get it checked in. At this point, I’ll have it defer to any other time source. Will just leave a note in the code that at some point we might want to compare IDs and give lower numbered sources priority.

I did browsemaster election for NetBIOS/SMB networks a very long time ago. It was (and still is) pretty hairy. If things are working as they are, not much reason to add complication at the moment.

1 Like

Done!
PixelblazeEnumerator now responds with timesync packets on every beacon as quickly as possible. The old “synchronize(),enable/disable autosync” API gone, the new one is just:

  • enableTimesync() - start synchronization
  • disableTimesync() - stop synchronization

Synchronization is off by default. The user must call enableTimesync() to start it. Once started, if it detects another time source on the network, it will automatically defer. The default senderID for pixelblaze-client is now 890 - if there’s an eventual lower-id–has-priority scheme, it’s 1 level below Firestorm.

… back to working on outdoor lights for me! …

4 Likes

Ok! The pixelblaze-client package is now available on pypi. To install, just
pip install pixelblaze-client
and use
import pixelblaze
or
from pixelblaze import *
in your programs.

Sample code is in the “examples” directory in the repository, and API documentation is still in README.md

First time publishing anything there – my main use of Python to date has been for short one-off data analysis scripts. So:

  • Yay, it worked! It’s up there and available to the general public!
  • Let me know if you encounter any problems.
  • Have fun making cool things!
5 Likes

Just posted a minor update to pixelblaze-cllient. It’s available on pypi now.

This version adds support for the new sequencer features in the latest Pixelblaze firmware. Specifically:

startSequencer() now takes a “mode” parameter, which sets the sequencer’s operating mode: 1 - Shuffle, 2 - Playlist. You still have to use the Web UI to set up your playlist (for now).

I’ve added methods to pause and restart the sequencer without losing your place in the current shuffle or playlist. They are:
pauseSequencer() and playSequencer()

stopSequencer() still stops and disables the sequencer, regardless of mode.

Full documentation is available on pypi, or from the repository’s readme. I’ve been meaning to get this checked in for a while, but it’s just been the Season of Way Too Many Projects…

3 Likes

I’ve updated the pixelblaze-client library to v0.9.4. It’s available on Github and pypi now.

This is the “small step now before we take a huge step later” release. There are bug fixes, performance improvements, a few new commands and some behavior changes aimed at reducing unneeded writes to flash memory.

Here are the details:

  • Documented getPixelCount/setPixelCount(), which lets you get and set the number of LEDs attached to your Pixelblaze.
  • added the pause() and unpause() commands.
  • getPatternList() is now cached, for greatly improved performance. The cache timeout can be set by calling setCacheRefreshTime(seconds). The default is 600 seconds, or 10 minutes.
  • Reduced unneccessary flash writes - setActivePattern(), setActivePatternId() and setBrightness() now take
    an optional saveFlash parameter, which is False by default, and uses the enable_flash_save() safety
    mechanism (described in the API documentation) to prevent inadvertent flash saves.

If you’re a Python user, try this out and let me know how it works for you!

4 Likes

Pull request: If you change the signature of ws_recv to:

    def ws_recv(self, wantBinary=False, packetType=0x07):

and the test for binary packets to:

                elif (wantBinary is True) and (result[0] == packetType):  # binary pattern list packet

then your library can be used to read other things besides the pattern list (I’m redoing my animated previews code to take advantage of the increased number of preview pixels in v3.24, but they’re only in the websocket packets – the preview jpeg saved inside the pattern EPE is still limited to 100 wide by 150 tall).

3 Likes

Thanks! Will get this in this afternoon, and into pypi asap!

If you’ve got a github account, pm me with your github name and I’ll add you as a collaborator on the python client repo so you can check things like this in as you encounter them.

1 Like

Ok - @pixie’s improvement is in! pixelblaze-client v0.9.5 is updated in the repo and available for download on pypi.

2 Likes