GithubHelp home page GithubHelp logo

python-elgato-streamdeck's Introduction

Python Elgato Stream Deck Library

Example Deck

This is an open source Python 3 library to control an Elgato Stream Deck directly, without the official software. This can allow you to create your own custom front-ends, such as a custom control front-end for home automation software.


PyPi Project Entry - Online Documentation - Source Code

Project Status:

Working - you can enumerate devices, set the brightness of the panel(s), set the images shown on each button, and read the current button states.

Currently the following StreamDeck products are supported in multiple hardware variants:

  • StreamDeck Original
  • StreamDeck Mini
  • StreamDeck XL
  • StreamDeck Pedal
  • StreamDeck Plus

Package Installation:

Install the library via pip:

pip install streamdeck

Alternatively, manually clone the project repository:

git clone https://github.com/abcminiuser/python-elgato-streamdeck.git

For detailed installation instructions, refer to the prebuilt online documentation, or build the documentation yourself locally by running make html from the docs directory.

Credits:

I've used the reverse engineering notes from this GitHub repository to implement this library. Thanks Alex Van Camp!

Thank you to the following contributors, large and small, for helping with the development and maintenance of this library:

If you've contributed in some manner, but I've accidentally missed you in the list above, please let me know.

License:

Released under the MIT license.

python-elgato-streamdeck's People

Contributors

abcminiuser avatar aetherdyne avatar benedikt-bartscher avatar brimston3 avatar core447 avatar dirkk0 avatar dodgyrabbit avatar jakobbuis avatar jmudge14 avatar lewiscowles1986 avatar matrixinius avatar phillco avatar shanna avatar spidererrol avatar theslimshaney avatar tjemg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-elgato-streamdeck's Issues

Issue with devicemanager

Hi,

I tried to use the examples but I get an error (see below). I checked the installation of both streamdeckapi and the libusb.
Can anyone give some advise?

Traceback (most recent call last):
File "C:\Users\Techniek\OneDrive - PKN Gouda\test\src\example_basic.py", line 110, in
streamdecks = DeviceManager().enumerate()
File "C:\Users\Techniek\OneDrive - PKN Gouda\test\src\StreamDeck\DeviceManager.py", line 88, in init
self.transport = self._get_transport(transport)
File "C:\Users\Techniek\OneDrive - PKN Gouda\test\src\StreamDeck\DeviceManager.py", line 80, in _get_transport
raise ProbeError("Probe failed to find any functional HID backend.", probe_errors)
StreamDeck.DeviceManager.ProbeError: ('Probe failed to find any functional HID backend.', {'libusb': TransportError("No suitable LibUSB HIDAPI library found on this system. Is the 'hidapi.dll' library installed?")})

reboot

Hi,

thanks for the lib, works like a charm!

I needed to reboot my Pi, otherwise the streamdeck couldn't be accessed. I am pretty sure there is a better way to solve this, so I didn't create a pull request.

Cheers, Dirk

Reading 32 bytes instead of 17 on StreamDeckXL for Serial Number

Describe the bug
In Devices/StreamDeckXL.py the serial number is read over 32 bytes. On my system, it reports bad chars containing \0 (not stripped, because of a \1 at the rightmost position).:

(Pdb) p serial
b'\x06\x0cCL35J1A01471\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'


(Pdb) p serial
b'\x06\x0cCL35J1A01471\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
(Pdb) s
--Call--
> /home/adrien/.cache/pypoetry/virtualenvs/streamdeck-ui-68pX5nCk-py3.7/lib/python3.7/site-packages/StreamDeck/Devices/StreamDeck.py(92)_extract_string()
-> def _extract_string(self, data):
(Pdb) s
> /home/adrien/.cache/pypoetry/virtualenvs/streamdeck-ui-68pX5nCk-py3.7/lib/python3.7/site-packages/StreamDeck/Devices/StreamDeck.py(98)_extract_string()
-> return str(bytes(data), 'ascii', 'replace').rstrip(' \0')
(Pdb) s
--Return--
> /home/adrien/.cache/pypoetry/virtualenvs/streamdeck-ui-68pX5nCk-py3.7/lib/python3.7/site-packages/StreamDeck/Devices/StreamDeck.py(98)_extract_string()->'CL35J1A01471...0\x00\x00\x01'

As other libraries are reading 17 bytes instead of 32, I guess there's an overflow there:

$ grep 'serial =' StreamDeck/Devices/StreamDeck*.py
StreamDeck/Devices/StreamDeckMini.py:        serial = self.device.read_feature(0x03, 17)
StreamDeck/Devices/StreamDeckOriginal.py:        serial = self.device.read_feature(0x03, 17)
StreamDeck/Devices/StreamDeckOriginalV2.py:        serial = self.device.read_feature(0x06, 32)
StreamDeck/Devices/StreamDeckXL.py:        serial = self.device.read_feature(0x06, 32)

To Reproduce
Show raw output of serial = self.device.read_feature(0x06, 32)

StreamDeck Information
StreamDeckXL

System Information
UI from Streamdeck_ui, streamdeck library v0.8.2

Race condition when closing device, causing core dump

Describe the bug
When calling close() there is a race condition that can cause and invalid handle to be accessed.

To Reproduce
Please see this issue for details.

We are using version 0.8.3

The problem we saw is inside the read method of LibUSBHIDAPI.py (line 301)

def read(self, handle, length):
    if not handle:
        raise TransportError("No HID device.")

    data = ctypes.create_string_buffer(length)
            
    with self.mutex:
        result = self.hidapi.hid_read(handle, data, len(data))

The core problem is specifically that this line can run, with handle already invalid:

result = self.hidapi.hid_read(handle, data, len(data))

From the python trace output, we can see the following flow. I've colored the two threads blue (my application thread) and red (the key polling thread) to make it more obvious what I believe is going on:

image

In summary:

  • The application is calling close() on the streamdeck.
  • The handle is closed (line 195 blue) by the thread calling close(). Note the device_handle is not set to None yet.
  • They _read loop calls into _read_key_states() which calls into read() (line 436 red).
  • However, since self.device_handle is not set to None yet, it passes the stale handle as an argument to read().
  • The check inside read() passes (it is not None). Since this is a parameter, it can't change even if the other thread sets it.
  • The blue thread - now sets device_handle to None (doesn't really matter at this point, the red one can't observe it anyway).
  • The red thread calls self.hidapi.hid_read(handle, data, len(data)) on a handle that is invalid.
  • The read fails, exception is thrown.
    Core dumped

It's not clear to me exactly what causes the core dump. Is it the read on an invalid handle, or is it the error handling or something.

No support for StreamDeck XL

Currently no support for StreamDeck XL. Tinkered a bit, looks like the XL has some large differences in the protocol. You'd have expected Elgato to have kept it mostly the same, but nope.

Stream Deck XL only shows black empty keys.

Hi, First of all thank you for a very useful library.

I have cloned version 0.5.1 from the github repository and have without any problems been using it with a Stream Deck Original on a Raspberry PI CM3+ module. The baseboard for the CM3+ is my own design. (USB 2.0)

I have now bought a Stream Deck XL and it is not working correctly. I have tested this on the CM3+ (USB2.0 Capable of delivering 1 ampere to the USB port), a Raspberry Pi 4 (USB3.0) and Ubuntu in VMware Fusion and the result is the same.

When I connect the Stream Deck XL I can control the backlight and read key states but calling update_key_image(deck, key, False) in example_basic.py causes a delay for about 3 seconds and the key stays black before trying to update the the next key.
Investigating a little further it looks like def set_key_image(self, key, image): in StreamDeckXL.py calls self.device.write(payload) three times to transmit all data and the function def write(self, payload): in HIDAPI.py returns -1 and not the transferred byte count.
When Disconnecting the XL and reconnecting the Stream Deck Original to the Raspberry Pi 4, example_basic.py works as expected.

I have tested the NodeJS library mentioned in another post (https://github.com/bitfocus/elgato-stream-deck-clean-xl/blob/master/index.js) and it does change the key colours.

The Raspberry Pi 4 is running a fresh install of 2019-09-26-raspbian-buster.
Below are the version information of the system.

Any help is greatly appreciated.

Best regards,
Brian.

Versions:
Raspbian: 2019-09-26-raspbian-buster
Python: 3.7.3
Pillow: 5.4.1
HIDAPI: 0.7.99.post21
StreamDeck Library: 0.5.1

"example_deckinfo.py" returns the following information for the XL and the Original.

Deck 0 - Stream Deck XL.
         - ID: b'0001:0009:00'
         - Serial: 'CL30I1A03593'
         - Firmware Version: '1.00.006'
         - Key Count: 32 (4x8 grid)
         - Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically

Deck 0 - Stream Deck (Original).
         - ID: b'0001:000a:00'
         - Serial: 'AL25I1C0682'
         - Firmware Version: '1.0.170133'
         - Key Count: 15 (3x5 grid)
         - Key Images: 72x72 pixels, BMP format, rotated 0 degrees, mirrored horizontally/vertically

LSUSB on the Raspberry Pi 4 returns:
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 011: ID 0fd9:006c Elgato Systems GmbH
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

lsusb -v -s 1:12
Bus 001 Device 012: ID 0fd9:006c Elgato Systems GmbH
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  idVendor           0x0fd9 Elgato Systems GmbH
  idProduct          0x006c
  bcdDevice            2.00
  iManufacturer           1 Elgato
  iProduct                2 Stream Deck XL
  iSerial                 3 CL30I1A03593
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x0029
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0xa0
      (Bus Powered)
      Remote Wakeup
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0
      bInterfaceProtocol      0
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     177
          Report Descriptor: (length is 177)
            Item(Global): Usage Page, data= [ 0x0c ] 12
                            Consumer
            Item(Local ): Usage, data= [ 0x01 ] 1
                            Consumer Control
            Item(Main  ): Collection, data= [ 0x01 ] 1
                            Application
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0xff 0x03 ] 1023
            Item(Global): Report ID, data= [ 0x02 ] 2
            Item(Main  ): Output, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0xff 0x01 ] 511
            Item(Global): Report ID, data= [ 0x01 ] 1
            Item(Main  ): Input, data= [ 0x02 ] 2
                            Data Variable Absolute No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x03 ] 3
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x07 ] 7
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x05 ] 5
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x04 ] 4
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x06 ] 6
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x08 ] 8
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x09 ] 9
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Local ): Usage, data= [ 0x00 0xff ] 65280
                            (null)
            Item(Global): Logical Minimum, data= [ 0x00 ] 0
            Item(Global): Logical Maximum, data= [ 0xff 0x00 ] 255
            Item(Global): Report Size, data= [ 0x08 ] 8
            Item(Global): Report Count, data= [ 0x1f 0x00 ] 31
            Item(Global): Report ID, data= [ 0x0a ] 10
            Item(Main  ): Feature, data= [ 0x04 ] 4
                            Data Array Relative No_Wrap Linear
                            Preferred_State No_Null_Position Non_Volatile Bitfield
            Item(Main  ): End Collection, data=none
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0200  1x 512 bytes
        bInterval               1
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x02  EP 2 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0400  1x 1024 bytes
        bInterval               1
Device Qualifier (for other device speed):
  bLength                10
  bDescriptorType         6
  bcdUSB               2.00
  bDeviceClass            0
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        64
  bNumConfigurations      1
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)

Proposal: Button generator -- already implemented

Hi @abcminiuser / Dean, thank you for the library -- it's very nice to be able to have such control over a streamdeck. I've previously heard of you via LUFA so I was pleasantly surprised to learn you'd also made this library.

For my own use I've implemented a button generator with the following features:

  • Fully automatic alignment, no scaling
  • Google Material Icon support, by name
  • Text, up to 3 lines, centred and properly line wrapped (icon reduced in size for 3 lines)
  • Background colour (palette generator)
  • Text/icon is automatically black or white depending on lightness value (background is converted to HLS colour space)
  • Status indicator: either not there, on or off

Here's an example set of (randomly) generated icons:

image

On my streamdeck XL:

image

The library uses pillow to do all this, as well as the icon font version (TTF) of google material fonts, 4.0 which is GPL.

Is this something you'd like me to do a PR for? I was thinking it could be an ImageHelper.

Caveats:

  • I've only tested on my XL, 96x96 so far. Will probably work fine on the other stream decks with 72x72px, maybe we'd need to change the font sizes though
  • Code is commented but no sphinx style docblocks yet
  • No tests yet

This can be fixed in the PR or post-merge though I trust.

DeviceManager().enumerate() takes very long

Hi,
This issue happened suddenly after a system upgrade, so it's hard to pinpoint the culprit here. What I found is that DeviceManager().enumerate() takes a very long time, over a minute. That was not the case before and makes now streamdeck-ui unusable.
So, I reinstalled all streamdeck python packages and the necessary libraries — still the same issues. Any ideas what causes that behavior?

I'm on Linux Mint 20 and use the 5.8.5-xanmod1 kernel.

Thanks,
Sandro

RPI: No HID Backend found

I followed the Raspberry Installation Manual:

pi@raspberrypi:~/Desktop/New folder $ python3 ./DeviceInformation.py3
Traceback (most recent call last):
  File "./DeviceInformation.py3", line 44, in <module>
    streamdecks = DeviceManager().enumerate()
  File "/home/pi/.local/lib/python3.7/site-packages/StreamDeck/DeviceManager.py", line 90, in __init__
    self.transport = self._get_transport(transport)
  File "/home/pi/.local/lib/python3.7/site-packages/StreamDeck/DeviceManager.py", line 82, in _get_transport
    raise ProbeError("Probe failed to find any functional HID backend.", probe_errors)
StreamDeck.DeviceManager.ProbeError: ('Probe failed to find any functional HID backend.', {'hid': OSError('The libhidapi-hidraw0 backend is currently blacklisted for StreamDeck devices.'), 'hidapi': TypeError("enumerate() got an unexpected keyword argument 'vendor_id'")})

Can't Open Streamdeck

Describe the bug
Please give a clear and concise description of what the bug is.
Streamdeck give error that won't allow me to open it on linux chromebook
To Reproduce
Please list the steps to reproduce the behavior.
use stream deck in command prompt on Linux Chromebook
StreamDeck Information
List the model of StreamDeck(s) you are using here.
Streamdeck original
System Information
List details about your operating system and hardware setup here, including OS name and version, and the version of any library dependencies you are using.
Chrome OS, Version 87.0.4280.109 (Official Build) (64-bit)
You should also include the version(s) of the library you are using - if not using a tagged release, list the commit hash you are testing here.
I don't know

Stream Deck Mini low FPS

New issue, as requested here

Animated example on my mini has a very low FPS, as shown in the animated example video here or in the album if the first link doesn't work.

Python version: 3.7.2
Pillow version: 5.4.1
hidapi: 0.7.99.post21

Running on a Windows 7 machine with 8 GB and an AMD Phenom II X6 1100T Black. (Yep, it's quite old.)

Error on deck open

Thank you so much for creating this library.
I am running the latest 0.6.1
I have the mini, original, and XL version of the stream deck.

With the latest update, the mini seems to be working just fine. When I try the original or the XL then with the deck.open() the follow error occurs:

Found 1 Stream Deck(s).

Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/StreamDeck/Transport/HID.py", line 157, in write
return self.hid.write(payload)
File "/usr/local/lib/python3.7/dist-packages/hid/init.py", line 149, in write
return self.__hidcall(hidapi.hid_write, self.__dev, data, len(data))
File "/usr/local/lib/python3.7/dist-packages/hid/init.py", line 140, in __hidcall
raise HIDException(err)
hid.HIDException: None

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/pi/Documents/StreamDeck/Streamdeck.py", line 99, in
deck.open()
File "/usr/local/lib/python3.7/dist-packages/StreamDeck/Devices/StreamDeck.py", line 116, in open
self._reset_key_stream()
File "/usr/local/lib/python3.7/dist-packages/StreamDeck/Devices/StreamDeckOriginal.py", line 79, in _reset_key_stream
self.device.write(payload)
File "/usr/local/lib/python3.7/dist-packages/StreamDeck/Transport/HID.py", line 159, in write
raise IOError(e)
OSError: None

Any ideas on what the issue could be?

Thanks again.

Stream Deck Mini "caches" Keys after running animated example

This issue might be related to #13, but shows a different behaviour.

The first 2 keypresses are registered to the previous key. For example, if I run example_basic.py and press key #3 for 4 times with a registered press on #1 before:

Deck b'0001:0059:00' Key 1 = True
Deck b'0001:0059:00' Key 1 = False
Deck b'0001:0059:00' Key 1 = True
Deck b'0001:0059:00' Key 1 = False
Deck b'0001:0059:00' Key 3 = True
Deck b'0001:0059:00' Key 3 = False

Note that the first 2 presses on #3 are registered as #1. This can be repeated and it is always the first 2 presses that are being registered incorrectly.

On the first press after launching example_basic.py, it looks like a random "previous" key is chosen.

In addition to the above issue, the deck sometimes registers random key presses inbetween correct ones or does not register presses at all. From my experiments, this applies to keys #4 and #5 (the last two keys) more often than to the first 4 keys.

Here's the deck info:

Deck 0 - Stream Deck Mini.
	 - ID: b'0001:0059:00'
	 - Serial: BL44H1B15985
	 - Firmware Version: 3.00.000
	 - Key Count: 6 (2x3 grid)
	 - Key Image Format: 80x80 pixels, BGR order, rotated 90 degrees, not mirrored

Stream Deck XL Performance

I wanted to see if anybody else is seeing a performance issue with the XL. I have the XL connected to a raspberry pi 3, and it is working fine. There are no errors I can see being thrown. I have 3 "page" buttons that will toggle between pages of keys, so when a page button is pressed I highlight that button (load a new image) and then refresh about 20 of the keys to reflect the items in that page. Most of the time the refresh happens very quickly with no problems, but every so many times a page button is pressed the XL seems to "freeze" for a moment and then will eventually load the new buttons without a problem.

It would make sense if the page switches were fast or slow every time, but the inconsistency is what is driving me crazy. I have tried to do something to optimize the process by rendering all the buttons and storing them in memory and then just calling the set_key_image and passing it the rendered image. I have also done things like only update buttons that are different. It may have helped a little bit on the page flips, but didn't solve the "freezing" problem. I can even hit the page buttons in rapid sequence and it will work many times and then all of the sudden freeze. I can also switch the pages slowly and same problem. I can't seem to find the root of the freeze and why it seems to happen randomly.

Any ideas on the best way to troubleshoot the root cause?

Companion crash when using buttons for Epiphan Pearl

Describe the bug
Created a new instance for Epiphan Pearl. All good, and Status OK and green. Created a new regular button, and selected Down action from list as PEARL2: Start/stop streaming. Selected correct Channel Publisher and 'Start' action to start Pearl streaming. Companion immediately reported a problem when button pressed, and displayed error message - see attached screen shot.
Thanks :-)
To Reproduce
See above - happens everytime.

StreamDeck Information
Stream Deck 32 button

System Information
MacBook 15" 2017 model. OS is High Sierra 10.13.6.

You should also include the version(s) of the library you are using - if not using a tagged release, list the commit hash you are testing here.
Bitfocus Companion
2.0.0 (2.0.0-d8475a4-1977)
Screen Shot 2021-05-10 at 15 41 54

OSX: sudo python3 example_deckinfo.py => OSError: open failed

System Version: macOS 10.14.4 (18E226)
Kernel Version: Darwin 18.5.0

$ sudo python3 example_deckinfo.py 
Found 1 Stream Deck(s).

Traceback (most recent call last):
  File "example_deckinfo.py", line 48, in <module>
    deck.open()
  File "/Users/arnold/projects/python-elgato-streamdeck/src/StreamDeck/Devices/StreamDeck.py", line 105, in open
    self.device.open()
  File "/Users/arnold/projects/python-elgato-streamdeck/src/StreamDeck/Transport/HIDAPI.py", line 51, in open
    self.hid.open_path(self.hid_info['path'])
  File "hid.pyx", line 72, in hid.device.open_path
OSError: open failed

I have not done the equivalent of setting up udev.
I had the same problem in linux and setting up the udev solved my issue there.

FR: Add Key class to the library

Playing around with this, I wanted to treat keys as individual objects rather than needing to put the code for all the different keys into one function based on style/callback (use key.get_style() rather than get_key_style()). I tried playing around with the project examples in my repo, and got to a point where I'm fairly happy with it (at least Key and its subclasses, the rest of my code is still a mess). Specifically in basic.py, key.py, emoji_key.py, and exit_key.py.

It seems to make sense to me that Key would be its own class related to the deck, and users would be able to assign functionality/styles by key class rather than all in one callback function, but I'm not terribly familiar with this project yet. Is there any reason not to do it that way, or reasons that that would be a terrifically difficult change?

StreamDeckXL.get_serial_number sometimes returning wrong results

Description
Normally, self.device.read_feature(0x06, 32) will return

b'\x06\x0cAAAAAAAAAAAA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

But sometimes, it will return

b'\x06\x0cAAAAAAAAAAAA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'

I'm not sure exactly what causes to get into this 'sometimes \x01' state, but I have noticed it a few times after fiddling around with things. Maybe an improper abort is causing it? I can try to find out but will have to see.

I just recently started using this program, so I can't speak to any prior behavior. But I check a recent commit 1 month ago, before it would be returning

b'\x06\x0cAAAAAAAAAAAA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

But due to c047eb7#diff-8fce19ef15b0c8c1aa404b2a80f62eecR237-R238, we're now sometimes getting this extra \x01 byte at the end, which is breaking normal behavior of

def get_serial_number(self):
"""
Gets the serial number of the attached StreamDeck.
:rtype: str
:return: String containing the serial number of the attached device.
"""
serial = self.device.read_feature(0x06, 32)
return self._extract_string(serial[2:])

def _extract_string(self, data):
"""
Extracts out a human-readable string from a collection of raw bytes,
removing any trailing whitespace or NUL bytes.
"""
return str(bytes(data), 'ascii', 'replace').rstrip(' \0')

To Reproduce
I don't know exactly how to get the device into the state so that it returns the \x01 byte at the end, but don't think that's too important for this issue.

Possible fix
I'm not familiar with device APIs like this at all, so just guessing here, but adding a check to see if the last byte is \x01 fixes the issue for me. But I'm not sure if it's ever okay for this byte to be \x01, so maybe since the comment only mentions Mac, there could be an OS check here. Or we should check for a long sequence of 'x00\x00\...\x01' to remove possible false positive? Other ideas is maybe the read_feature() call or _extract_string function can be adjusted in StreamDeckXL.
I will make a PR for option 1 in case that solution is fine. But let me know if you want it tweaked, otherwise I will just leave it up you.

StreamDeck Information
StreamDeckXL

System Information
Linux, hidapi 0.9.0-2, python-elgato-streamdeck 0.8.2
I also have this plugged into a KVM switch USB hub, in case that's relevant.

UnicodeDecodeError

I get an error: UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte when I try to run the example from the docs.

(.env) 38f9d35bacfd:StreamDeck rhboyd$ python ./app/discover.py 
Found 1 Stream Deck(s).

Deck 0 - Stream Deck Original (V2).
	 - ID: b'IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/RP05@1C,4/IOPP/UPSB@0/IOPP/DSB1@1/IOPP/UPS0@0/IOPP/pci-bridge@1/IOPP/pci1b73,1100@0/AppleUSBXHCIFL1100@01000000/AppleUSB20XHCIPort@01100000/Stream Deck@01100000/IOUSBHostInterface@0/IOUSBHostHIDDevice@01100000,0'
	 - Serial: '
                    AL47I2C05642'
Traceback (most recent call last):
  File "./app/discover.py", line 52, in <module>
    print_deck_info(index, deck)
  File "./app/discover.py", line 30, in print_deck_info
    print("\t - Firmware Version: '{}'".format(deck.get_firmware_version()))
  File "/Users/rhboyd/dev/StreamDeck/.env/lib/python3.7/site-packages/StreamDeck/Devices/StreamDeckOriginalV2.py", line 151, in get_firmware_version
    return self._extract_string(version[6:])
  File "/Users/rhboyd/dev/StreamDeck/.env/lib/python3.7/site-packages/StreamDeck/Devices/StreamDeck.py", line 100, in _extract_string
    return data.decode("utf-8").rstrip('\0')
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte

Changing this line to

return str(bytes(data), 'utf-8', 'ignore').rstrip(' \0')

ignores decode errors and appears to work correctly. Is this something I should submit a PR for or am I just being dumb?

(.env) 38f9d35bacfd:StreamDeck rhboyd$ python ./app/discover.py 
Found 1 Stream Deck(s).

Deck 0 - Stream Deck Original (V2).
	 - ID: b'IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/RP05@1C,4/IOPP/UPSB@0/IOPP/DSB1@1/IOPP/UPS0@0/IOPP/pci-bridge@1/IOPP/pci1b73,1100@0/AppleUSBXHCIFL1100@01000000/AppleUSB20XHCIPort@01100000/Stream Deck@01100000/IOUSBHostInterface@0/IOUSBHostHIDDevice@01100000,0'
	 - Serial: '
                    AL47I2C05642'
	 - Firmware Version: '1.02.004'
	 - Key Count: 15 (3x5 grid)
	 - Key Images: 72x72 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically

Using Python3.7 on MacOS Mojave

OSX Catalina trouble with HID

Hi,

I am trying to use the library under my MBP running Catalina. But I am not able to run because of Exception from HID.
I am almost sure it's a security of Catalina who do not allow accessing the device. I try running the script with sudo but same issue.
I also convert my script to an executable app with pyinstaller, and try to force allowing access but still same issue.

Any suggestion how I can make the library working with Catalina?

Thanks

> python3 streamdecktest.py
Found 1 Stream Deck(s).
Device 0 : <StreamDeck.Devices.StreamDeckXL.StreamDeckXL object at 0x108daf690>
Traceback (most recent call last):
  File "streamdecktest.py", line 115, in <module>
    deck.open()
  File "/usr/local/lib/python3.7/site-packages/StreamDeck/Devices/StreamDeck.py", line 122, in open
    self.device.open()
  File "/usr/local/lib/python3.7/site-packages/StreamDeck/Transport/HID.py", line 48, in open
    self.hid = hid.Device(path=self.hid_info['path'])
  File "/usr/local/lib/python3.7/site-packages/hid/__init__.py", line 130, in __init__
    raise HIDException('unable to open device')
hid.HIDException: unable to open device

StreamDeck mini confused after pressing multiple keys simultaneously

If pressing just one key at a time, it works just fine using the example_basic.py example
If pressing several keys simultaneously, it becomes confused. Pressing one key at a time after that, makes other buttons react. Restarting example_basic.py does not fix it, but restarting the computer does.

I have a StreamDeck Mini.
I use Ubuntu Bionic on a Nvidia Jetson TX1.
It has libhidapi-libusb0/bionic,now 0.8.0~rc1+git20140818.d17db57+dfsg-2 arm64

Unable to start streamdeck after install

After following all instructions to install this in POP_OS ( a fork of Ubuntu) and installing all dependencies as needed, the command "streamdeck" does not start the program. All I get is "command not found" in terminal.

I did get a warning that a file needed added to "PATH" and tried to do that, but could still never get "streamdeck" to work. Also there are no instructions or link to instructions on howw to add it to auto start as suggested...

I am stuck and dont know what to try next, as I am a new (ish) user on linux.

(now for the obligatory "dis is broke, fix nao") XD

any help would be greatly appreciated!

TransportError

I'm getting this error after Version 0.8.2 install: "StreamDeck.Transport.Transport.TransportError: Could not open HID device"
Used to work fine so wonder if it has anything to do with the latest update and the "Updated LibUSB transport backend so that device paths are returned as UTF-8 strings, not raw bytes"?

No suitable LibUSB HIDAPI library found on this system

Hello,

I am trying to get it to work, but I receive always the same error message.

StreamDeck.DeviceManager.ProbeError: ('Probe failed to find any functional HID backend.', {'libusb': TransportError("No suitable LibUSB HIDAPI library found on this system. Is the 'libhidapi-libusb.so' library installed?")})

I don't know why I get this exception. I checked for the error but all the dependencies are installed.

Does anyone know how to fix this?
Thank you very much.

Here are some Details about my system.

StreamDeck Information
I am using the StreamDeck Original

System Information
I use Linux Mint 20.
Fallowing Libhidapi packages are installed

libhidapi-dev/focal,now 0.9.0+dfsg-1 amd64 [installed]
libhidapi-hidraw0/focal,now 0.9.0+dfsg-1 amd64 [installed]
libhidapi-libusb0/focal,now 0.9.0+dfsg-1 amd64 [installed]

.print_deck_info() doesn't populate Serial or Firmware Version on Stream Deck XL

Running example_deckinfo.py on a new Stream Deck XL (just arrived this week), I get:

Deck 0 - Stream Deck XL.
- ID: b'\\?\hid#vid_0fd9&pid_006c#7&a8de7c&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}'
- Serial: ''
- Firmware Version: ''
- Key Count: 32 (8x4 grid)
- Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically

Udev rules and TransportError

Describe the bug

On my Debian machine with a backport-kernel (5.9.15) the udev-rule

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0fd9", GROUP="users"

suggested here: https://github.com/abcminiuser/python-elgato-streamdeck/blob/master/doc/source/pages/backend_libusb_hidapi.rst

produces to a TransportError

raise TransportError("Could not open HID device.")

It turns out that on none of my debian machines my user was part of the users group. However, all of these machines were upgraded from earlier versions (this also applies to a raspbian rpi4 - here only the pi user is part of users, not additional users added with adduser).

I was able to fix the issue by modifying the udev rule based on randomly found similar issues for other projects (e.g.. https://wiki.archlinux.org/index.php/Talk:Udev or stapelberg/openhantek@b02d417 )

# does not work on my Debian 10 machine
# SUBSYSTEMS=="usb", ATTRS{idVendor}=="0fd9", GROUP="users"
# works
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0fd9", GROUP="users", TAG+="uaccess", TAG+="udev-acl"
# works
# SUBSYSTEMS=="usb", ATTRS{idVendor}=="0fd9", GROUP="users", TAG+="udev-acl"
# # works
# SUBSYSTEMS=="usb", ATTRS{idVendor}=="0fd9", GROUP="users", TAG+="uaccess"
# does not work on my machine
# SUBSYSTEMS=="usb", ATTRS{idVendor}=="0fd9", GROUP="users", MODE="0660"

Unfortunately my knowledge of udev-internals is very limited and therefore I cannot propose a "correct" fix (if this is actually an issue). However, my understanding of the uaccess tag is that it grants access rights to every logged-in user, which seems reasonable for the use of the streamdeck.

To Reproduce

Use and apply the udev rules a proposed in the manual.

StreamDeck Information
List the model of StreamDeck(s) you are using here.

System Information

Debian 10.7 (buster)
Linux nathan 5.9.0-0.bpo.5-amd64 #1 SMP Debian 5.9.15-1~bpo10+1 (2020-12-31) x86_64 GNU/Linux
steamdeck library installed in fresh virtualenv from pypi (0.8.2, python 3.7)

"deckinfo" example: error at exit when executed in a function

Describe the bug

When running code of "deckinfo" example in a function (instead of just in if __name__ == "__main__"), the code runs well BUT at the end, an error is displayed:

$ ./deckinfo.py 
Found 1 Stream Deck(s).

Deck 0 - Stream Deck XL.
	 - ID: 0001:0003:00
	 - Serial: 'REDACTED'
	 - Firmware Version: '1.00.007'
	 - Key Count: 32 (in a 4x8 grid)
	 - Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically
Exception ignored in: <function StreamDeck.__del__ at 0x7fe3a0db0a60>
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/dist-packages/StreamDeck/Devices/StreamDeck.py", line 47, in __del__

And sometimes, with a core dump:

$ ./deckinfo.py
Found 1 Stream Deck(s).

Deck 0 - Stream Deck XL.
	 - ID: 0001:0003:00
	 - Serial: 'REDACTED'
	 - Firmware Version: '1.00.007'
	 - Key Count: 32 (in a 4x8 grid)
	 - Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically
Exception ignored in: <function StreamDeck.__del__ at 0x7f02010f5a60>
Traceback (most recent call last):
Fatal Python error: _enter_buffered_busy: could not acquire lock for <_io.BufferedWriter name='<stderr>'> at interpreter shutdown, possibly due to daemon threads
Python runtime state: finalizing (tstate=0x195dfe0)

Current thread 0x00007f02021ae740 (most recent call first):
<no Python frame>
Aborted (core dumped)

Note that when running the example unmodified, there is no error:

$ ./deckinfo.py 
Found 1 Stream Deck(s).

Deck 0 - Stream Deck XL.
	 - ID: 0001:0003:00
	 - Serial: 'REDACTED'
	 - Firmware Version: '1.00.007'
	 - Key Count: 32 (in a 4x8 grid)
	 - Key Images: 96x96 pixels, JPEG format, rotated 0 degrees, mirrored horizontally/vertically

Also note than:

  • it does not depend on the time passed between two executions of the program
  • no threads seems to be left on the system

To Reproduce

Instead of running the code directly in if __name__ == "__main__":, call a function with the code in it:

In the deckinfo example, replace:

if __name__ == "__main__":
    streamdecks = DeviceManager().enumerate()

    print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

    for index, deck in enumerate(streamdecks):
        deck.open()
        deck.reset()

        print_deck_info(index, deck)

        deck.close()

by

def main():
    streamdecks = DeviceManager().enumerate()

    print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

    for index, deck in enumerate(streamdecks):
        deck.open()
        deck.reset()

        print_deck_info(index, deck)

        deck.close()

if __name__ == "__main__":
    main()
Full code
#!/usr/bin/env python3

#         Python Stream Deck Library
#      Released under the MIT license
#
#   dean [at] fourwalledcubicle [dot] com
#         www.fourwalledcubicle.com
#

# Example script that prints out information about any discovered StreamDeck
# devices to the console.

from StreamDeck.DeviceManager import DeviceManager


# Prints diagnostic information about a given StreamDeck.
def print_deck_info(index, deck):
    image_format = deck.key_image_format()

    flip_description = {
        (False, False): "not mirrored",
        (True, False): "mirrored horizontally",
        (False, True): "mirrored vertically",
        (True, True): "mirrored horizontally/vertically",
    }

    print("Deck {} - {}.".format(index, deck.deck_type()))
    print("\t - ID: {}".format(deck.id()))
    print("\t - Serial: '{}'".format(deck.get_serial_number()))
    print("\t - Firmware Version: '{}'".format(deck.get_firmware_version()))
    print("\t - Key Count: {} (in a {}x{} grid)".format(
        deck.key_count(),
        deck.key_layout()[0],
        deck.key_layout()[1]))
    print("\t - Key Images: {}x{} pixels, {} format, rotated {} degrees, {}".format(
        image_format['size'][0],
        image_format['size'][1],
        image_format['format'],
        image_format['rotation'],
        flip_description[image_format['flip']]))

def main():
    streamdecks = DeviceManager().enumerate()

    print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

    for index, deck in enumerate(streamdecks):
        deck.open()
        deck.reset()

        print_deck_info(index, deck)

        deck.close()

if __name__ == "__main__":
    main()

StreamDeck Information
Stream Deck XL (Firmware Version: '1.00.007')

System Information
CPU: AMD threadripper
OS: Ubuntu 21.04
Python: 3.9.4
python-elgato-streamdeck : 0.8.4 (installed via pip install streamdeck)

$ dpkg -l | grep libhidapi
ii  libhidapi-hidraw0:amd64                    0.10.1+dfsg-1                                                        amd64        Multi-Platform library for communication with HID devices (hidraw backend)
ii  libhidapi-libusb0:amd64                    0.10.1+dfsg-1                                                        amd64        Multi-Platform library for communication with HID devices (libusb backend)

Not picking up hidapi.dll on Windows 10.

Did a 'pip install hid' followed by 'pip install streamdeck', and dropped the precompiled 0.9.0 dll from https://github.com/libusb/hidapi/releases into the same directory as the python script. The script is the "Basic Usage" example from the docs.

Every time it is run, however, it fails with:

    raise ProbeError("Probe failed to find any functional HID backend.", probe_errors)
StreamDeck.DeviceManager.ProbeError: ('Probe failed to find any functional HID backend.', {'hid': ImportError('Unable to load any of the following libraries:libhidapi-hidraw.so libhidapi-hidraw.so.0 libhidapi-libusb.so libhidapi-libusb.so.0 libhidapi-iohidmanager.so libhidapi-iohidmanager.so.0 libhidapi.dylib hidapi.dll libhidapi-0.dll'), 'hidapi': ImportError('Unable to load any of the following libraries:libhidapi-hidraw.so libhidapi-hidraw.so.0 libhidapi-libusb.so libhidapi-libusb.so.0 libhidapi-iohidmanager.so libhidapi-iohidmanager.so.0 libhidapi.dylib hidapi.dll libhidapi-0.dll')})

Moving hidapi.dll to other directories (windows/system, system32, etc) does not seem to make a difference, it just isn't seeing it somehow.

Is there some other step I'm missing to get it to work?

Windows 10 hidapi.dll Error

This is definitely not a bug. I'm sure it's all due to my ignorance, and I appreciate any help you can provide. I'm anxious to use this library!

I downloaded the hidapi.dll and hidapi.lib from the libUSB GitHub project as directed. Not knowing where the process would look, I placed these files into c:\Windows\System32, into the Python executable directory, and the directory of where my script resides. However, I keep getting the error...

StreamDeck.DeviceManager.ProbeError: ('Probe failed to find any functional HID backend.', {'libusb': TransportError("No suitable LibUSB HIDAPI library found on this system. Is the 'hidapi.dll' library installed?",)})

Can you point me in the right direction? I'm on a Windows 10 box.

Thanks,
Ray.

Image quality could easily be better for (at least) original V2

Hello,

first off, thank you very much for this library – very easy to use, yet powerful.

I noticed, however, that the image quality on my StreamDeck original V2 is quite poor. This is especially noticable when having intense colors, e.g. red text on black background.

I quickly found that the image format for this device is defined to be JPEG in the code, and the poor quality I'm seeing are in fact compression artifacts. Specifying "quality = 100" as additional parameter to image.save() already improves the quality. However, I also noticed that the device seems to accept BMP just fine (although the image needs to be flipped vertically). The image quality is perfect then.

Is there a particular reason to use JPEG on this device?

ProbeError when running under Manjaro

Hi,

I'm trying to use the streamdeck library under Manjaro 18.1.1 but I'm getting an error related with the HID backends.

Traceback (most recent call last):
  File "streamdeck.py", line 377, in <module>
    streamdecks = DeviceManager().enumerate()
  File "/usr/lib/python3.7/site-packages/StreamDeck/DeviceManager.py", line 83, in __init__
    self.transport = self._get_transport(transport)
  File "/usr/lib/python3.7/site-packages/StreamDeck/DeviceManager.py", line 75, in _get_transport
    raise ProbeError("Probe failed to find any functional HID backend.", probe_errors)
StreamDeck.DeviceManager.ProbeError: ('Probe failed to find any functional HID backend.', {'hid': TypeError("enumerate() got an unexpected keyword argument 'vid'"), 'hidapi': TypeError("enumerate() got an unexpected keyword argument 'vid'")})

The same script was working previously under Debian Buster.

I'm not sure about what additional info to provide to you here, so feel free to request any additional info that you need.

HID library cannot select which Linux backend is to be used if multiple are present

Documenting here so I don't forget.

Currently on Linux the hid wrapper Python library I use supports two possible low level HID backends, HIDAPI and libUSB. The former is incompatible with the Original StreamDeck as it has a fixed 4KB maximum report size compiled into it by default, while the Original needs around 8KB for image data. The libUSB backend works.

I've added an explicit blacklist in 88fbc5c to ensure only the working backend is chosen by the HID library, but this forces the user to uninstall the HIDAPI backend that other applications might depend on.

A proper fix is to either patch the hid python library with a way to explicitly select which is to be used, or incorporate a HID wrapper into this library that only selects libUSB.

Random crashes with nothing in logs

OS: Win 10
Using HID API

When set key images onto StreamDeck buttons, the script will crash randomly. There is no pattern to this. With logger on debug on, no crash relevant output is displayed. No exceptions are raised (this can by seen by surrounding set_key_image call in try/except) and the entire script instantly exits.

Possible to account for "bezels" between keys when tiling the image across entire Stream Deck?

I was poking at the streamdeck_ui package but was looking for a little inspiration as to what was possible, so I came over here and found the example scripts, but when using the example_tileimage.py it becomes pretty evident when looking at the mini vs V2 vs XL that the bezels aren't accounted for. The human brain is actually wired to "fill in the gaps", so it would be much less jarring if it were possible to just drop xx number of pixels on the edges of each tile to make the image more seamless.

A really good example of this done well is in the StreamDeckSharp repo in their "video playback" example, your brain can pretty quickly get past the fact that the image is playing on a matrix of screens, much like when looking at a video wall at a conference or sporting event.

https://www.youtube.com/watch?v=tNwUG0sPmKw

deck.connected() throwing error in LibUSBHIDAPI.py

deck.connect() is throwing an error when called.

Operating System: Manjaro Linux
KDE Plasma Version: 5.18.4
KDE Frameworks Version: 5.69.0
Qt Version: 5.14.2
Kernel Version: 5.6.4-1-MANJARO
OS Type: 64-bit

Error:

Found 1 Stream Deck(s).

Traceback (most recent call last):
  File "test.py", line 52, in <module>
    print_deck_info(index, deck)
  File "test.py", line 26, in print_deck_info
    print(deck.connected())
  File "/home/david/.local/lib/python3.8/site-packages/StreamDeck/Devices/StreamDeck.py", line 148, in connected
    return self.device.connected()
  File "/home/david/.local/lib/python3.8/site-packages/StreamDeck/Transport/LibUSBHIDAPI.py", line 321, in connected
    return any([d['path'] == self.hid_info['path'] for d in self.hidapi.enumerate()])
  File "/home/david/.local/lib/python3.8/site-packages/StreamDeck/Transport/LibUSBHIDAPI.py", line 147, in enumerate
    'path': current_device.path,
AttributeError: 'LP_hid_device_info' object has no attribute 'path'
Segmentation fault (core dumped)

Code:


#         Python Stream Deck Library
#      Released under the MIT license
#
#   dean [at] fourwalledcubicle [dot] com
#         www.fourwalledcubicle.com
#

# Example script that prints out information about any discovered StreamDeck
# devices to the console.

from StreamDeck.DeviceManager import DeviceManager


# Prints diagnostic information about a given StreamDeck.
def print_deck_info(index, deck):
    image_format = deck.key_image_format()

    flip_description = {
        (False, False): "not mirrored",
        (True, False): "mirrored horizontally",
        (False, True): "mirrored vertically",
        (True, True): "mirrored horizontally/vertically",
    }
    print(deck.connected())
    print("Deck {} - {}.".format(index, deck.deck_type()))
    print("\t - ID: {}".format(deck.id()))
    print("\t - Serial: '{}'".format(deck.get_serial_number()))
    print("\t - Firmware Version: '{}'".format(deck.get_firmware_version()))
    print("\t - Key Count: {} ({}x{} grid)".format(
        deck.key_count(),
        deck.key_layout()[0],
        deck.key_layout()[1]))
    print("\t - Key Images: {}x{} pixels, {} format, rotated {} degrees, {}".format(
        image_format['size'][0],
        image_format['size'][1],
        image_format['format'],
        image_format['rotation'],
        flip_description[image_format['flip']]))


if __name__ == "__main__":
    streamdecks = DeviceManager().enumerate()

    print("Found {} Stream Deck(s).\n".format(len(streamdecks)))

    for index, deck in enumerate(streamdecks):
        deck.open()
        deck.reset()

        print_deck_info(index, deck)

        deck.close()

I was messing with using streamdeck_ui with 0.7.2 and was running into this error so I took one of the example scripts and added print(deck.connected()) to see if it was the UI code or this, and it seems to be this. If I comment api.ensure_decks_connected() in the sync function for the UI which uses connected to check and reset the device if it is disconnected, it works fine except if the stream deck disconnects and reconnects you have to restart the UI.

Other then that it seems to be working fine on Manjaro and the HIDraw blacklist issue seems to be fixed!

debian - get_serial_number missing last digit

debian buster (10)
Stream Deck Mini (2 of)
When executing get_serial_number, I get the first 11 digits of the serial only. When run previously on my Mac I would get all 12 digits.
Happy to provide more info

New Original StreamDeck hardware variant unsupported

When I do lsusb on my laptop with arch where I have my stream deck plugged into, I get a stream deck with this info Bus 001 Device 025: ID 0fd9:006d Elgato Systems GmbH USB2.0 Hub When I look into the code, the stream deck is supposed to have 0060 as a idProduct… so by this I'm curious if anyone else have experienced this. I've tried to edit the code so that it says 006d instead of 0060 with not much luck.

Unable to open HID device

Describe the bug
Unable to open HID device. I followed the libhidapi-libusb0 setup here, but when I run src/example_basic.py, I see this:

Found 1 Stream Deck(s).

Traceback (most recent call last):
  File "/home/cmccandless/repos/sandbox/python-elgato-streamdeck/src/example_basic.py", line 113, in <module>
    deck.open()
  File "/home/cmccandless/repos/sandbox/python-elgato-streamdeck/src/StreamDeck/Devices/StreamDeck.py", line 148, in open
    self.device.open()
  File "/home/cmccandless/repos/sandbox/python-elgato-streamdeck/src/StreamDeck/Transport/LibUSBHIDAPI.py", line 348, in open
    self.device_handle = self.hidapi.open_device(self.device_info['path'])
  File "/home/cmccandless/repos/sandbox/python-elgato-streamdeck/src/StreamDeck/Transport/LibUSBHIDAPI.py", line 181, in open_device
    raise TransportError("Could not open HID device.")
StreamDeck.Transport.Transport.TransportError: Could not open HID device.

To Reproduce
Follow all installation steps, the run python3 src/example_basic.py

StreamDeck Information
StreamDeck v2 (15 keys)

System Information
Ubuntu 20.04
Linux 5.4.0-65-generic #73-Ubuntu SMP Mon Jan 18 17:25:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

I'm using the latest from Github (f48a401)

Top half of image is shifted right on Original StreamDeck V1

Was trying to figure out why I couldn't draw text with Pillow at (0, 0), discovered this.
Seems shifted right by about 16 pixels. Unfortunately I need this real-estate.

I have a fuzzy picture (phone camera lacks drivers), you can see the top, cyan text is shifted right, and the green text in the center is effectively sliced in half.

sd

Library doesn't work in Python 3.8 or 3.9 on Windows

Describe the bug
When trying to use the library on Windows 10 using either Python 3.8 or 3.9, the library raises an exception when trying to enumerate the Stream Decks attached to the computer. The exception raised is 'ProbeError' and the message is ''Probe failed to find any functional HID backend.'

The hidapi.dll and hidapi.lib files are installed in the same directory as python.exe. The version of Python in both cases is the 32 bit version. With the same setup in Python 3.7, the example scripts run correctly.

To Reproduce
Install the 32 bit version of either Python 3.8 or 3.9. Download (or build) the hidapi.dll and hidapi.lib files and place them in the same directory as the python.exe. Run the example scripts provided in the source tree for python-elgato-streamdeck.

StreamDeck Information
The StreamDeck version is the StreamDeck XL.

System Information
Window 10, Build 2004, Ryzen 7 2700X, 3.70 GHz

Library version 0.8.2

How to rotate a button on StreamDeck Original?

Hi all,

first of all, thank you very much for your work. I have a StreamDeck Original mounted on edge and would like to rotate the buttons 90°. Unfortunately I can only find the rotation value in the StreamDeck class in the documentation. Do I have to do this via Pillow?

Many thanks in advance.

Libraries for CentOS7.7

Hi,

does anyone have the correct libraries needed for CentOS 7.7?
I’ve found a couple different one, but I’m not sure which one are correct..

Any help would be greatly appreciated.

lee

Sent with GitHawk

Probe failed to find any functional HID backend on Raspberry Pi

We've tried to use HIDAPI for our streamdeck on the Raspberry Pi. With HIDAPI, the streamdeck works normal for a couple of minutes. After some time, the software do not receive any key input.

Now we were trying to remove the HIDAPI python package and use HID, but it throws the following error on starting our program:

Traceback (most recent call last): File "streamdeck.py", line 180, in <module> main() File "streamdeck.py", line 162, in main streamdeck() File "streamdeck.py", line 139, in streamdeck streamdecks = DeviceManager().enumerate() File "/home/pi/.local/lib/python3.7/site-packages/StreamDeck/DeviceManager.py", line 90, in __init__ self.transport = self._get_transport(transport) File "/home/pi/.local/lib/python3.7/site-packages/StreamDeck/DeviceManager.py", line 82, in _get_transport raise ProbeError("Probe failed to find any functional HID backend.", probe_errors) StreamDeck.DeviceManager.ProbeError: ('Probe failed to find any functional HID backend.', {'hid': ImportError('Unable to load any of the following libraries:libhidapi-hidraw.so libhidapi-hidraw.so.0 libhidapi-libusb.so libhidapi-libusb.so.0 libhidapi-iohidmanager.so libhidapi-iohidmanager.so.0 libhidapi.dylib hidapi.dll libhidapi-0.dll'), 'hidapi': ImportError('Unable to load any of the foll

Has someone experience with this?

Thonny can't find StreamDeck Package

Hi,

Thanks so much for this library. I am having difficulty getting it to be recognized by Thonny. I am running Raspbian GNU/Linux 10 (buster). I followed the raspberry pi installation instructions (including the pip3 install streamdeck). Everything installed correctly and without errors. I also installed the package from within Thonny (Tools->Manage Packages). I did reboot the raspberry pi (Rpi 4B) after the install. When trying to run the example python app, I am getting the following error:
Traceback (most recent call last):
File "/home/pi/Desktop/StreamDeck/StreamDeck.py", line 16, in
from StreamDeck.DeviceManager import DeviceManager
File "/home/pi/Desktop/StreamDeck/StreamDeck.py", line 16, in
from StreamDeck.DeviceManager import DeviceManager
ModuleNotFoundError: No module named 'StreamDeck.DeviceManager'; 'StreamDeck' is not a package

Any help would be greatly appreciated!

Stream Deck mini updates the keys twice

The streamdeck mini repeats the last image before updating to a new one. So if I update key0 and sometime later for example key5 then key5 first shows the image that has been sent to key0 for 0.1 or 0.2 sec then shows the image that is actually sent to it. The included basic example also has this issue.

get_firmware_version() call leads to streamdeck XL ignoring top 3 row presses

Strange behaviour encountered today where the top 3 rows of an XL get ignored until reset() or similar

Here's a tiny working illustration. Pressing key(0) makes the call and the top 3 rows stop working then. Pressing key(31) runs reset() then all kets work again.

import threading
from StreamDeck.DeviceManager import DeviceManager

def _cbKeyPressed(deck, key, state):
    print("Got a press on {}".format(key))
    if state:
        return
    if key == 0:
        print("Running get_firmware_version()!")
        deck.get_firmware_version()
    elif key == 31:
        print("restoring")
        deck.reset()
        
def setup(deck):
    deck.open()
    deck.reset()
    deck.set_key_callback(_cbKeyPressed)

deck = DeviceManager().enumerate()[0]
setup(deck)

for t in threading.enumerate():
    if t is threading.currentThread():
        continue
    
    if t.is_alive():
            t.join()

streamdeck 0.6.3
hidapi 0.9.0.post2
Mac OS 10.15.2 (Catalina)

Seen same on Linux with hid (referenced in #29)

PILHelper has no attribute 'create_scaled_image'

Describe the bug
AttributeError: module 'StreamDeck.ImageHelpers.PILHelper' has no attribute 'create_scaled_image'

  File "/home/xlaits/Documents/Programming/Python/Streamdeck/Streamdeck.py", line 102, in <module>
    create_animation_frames(deck, "Legion-StreamDeckIcon-Firefox-256x256.gif"),
  File "/home/xlaits/Documents/Programming/Python/Streamdeck/Streamdeck.py", line 58, in create_animation_frames
    frame_image = PILHelper.create_scaled_image(deck, frame)
AttributeError: module 'StreamDeck.ImageHelpers.PILHelper' has no attribute 'create_scaled_image'

To Reproduce
See error above.

StreamDeck Information
Streamdeck v2 15 key.

System Information
2021-02-19-133428_814x520_scrot

streamdeck in ./.local/lib/python3.9/site-packages (0.6.3) (Pulled from pip)

.set_key_image() doesn't scale correctly on Stream Deck XL

Hi - first of all amazing job with this library. I haven't found anything to compare with it for Python and it's really opening some creative doors for us, thank you.

Small thing - I noticed that images don't scale correctly on our Stream Deck XL (4x8 buttons) though. Please see attached images as example input and output:

Input
globe portrait

Output
20190930_233839

As you can see the image seems to be repeated on the deck itself, with the right hand image curiously a bit larger than the left hand one.

All the best,
Peter

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.