{ "info": { "author": "Dave Hocker", "author_email": "AtHomeX10@gmail.com", "bugtrack_url": null, "classifiers": [ "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "# Programming the Anyma uDMX interface (and clones) Using Python and PyUSB\nCopyright \u00a9 2016 by Dave Hocker (AtHomeX10@gmail.com)\n\n## Overview\n\nThe purpose of this repo is to share what I have learned about programming the\nAnyma uDMX interface using Python and PyUSB on the Raspberry Pi (RPi). Th Anyma uDMX\ninterface is relatively inexpensive and there are a large number of clones available \nfrom sites like eBay. However, there seems to be a dearth of information available for\nprogramming this interface under Linux (Raspbian Jessie in this case).\n\nMany thanks go out to Markus Baertschi and the work he did on the uDMX-linux utility\n(see https://github.com/markusb/uDMX-linux). His C++ based uDMX utility served as the basis\nfor the majority of my learning exercise. \n\n## License\n\nThe work presented here is licensed under the GNU General Public License v3 as published by the \nFree Software Foundation, Inc.. See the LICENSE file for the full text of the license.\n\n## Source Code\n\nThe full source is maintained on [GitHub](https://www.github.com/dhocker/uDMX-pyusb).\n\n## Development Environment\n### Virtual Environment\n\nThis work was originally written in Python 2.7 but has been adapted for both Python 2 and Python 3.\nVersion 1.1.0 works on Python 2. Version 2.0.0 and above works on Python 3.5+.\nA suitable development environment would use virtualenv and virtualenvwrapper to create a working virtual environment.\nThe **requirements.txt** file can be used with pip to create the required virtual environment with all dependencies.\n\nHere are some references for setting up virtualenv and virtualenvwrapper.\n\n* [virtualenv and virtualenvwrapper](http://docs.python-guide.org/en/latest/dev/virtualenvs/)\n* [virtualenv and virtualenvwrapper on Linux](http://nayon.net/install-virtualenv-and-virtualenvwrapper-on-ubuntu/)\n* [pip and virtualenv on Windows](http://programwithus.com/learn-to-code/Pip-and-virtualenv-on-Windows/)\n* [virtualenvwrapper on Windows](https://pypi.org/project/virtualenvwrapper-win/)\n* [virtualenv and virtualenvwrapper on macOS](http://exponential.io/blog/2015/02/10/install-virtualenv-and-virtualenvwrapper-on-mac-os-x/)\n\nA quick Internet search will reveal many articles on how to install and setup virtualenv/virtualenvwrapper on\nmost any OS.\n\n### PyUSB\nPyUSB requires one of the following: libusb 1.0, libusb 0.1 or OpenUSB. See [5](#5). libusb 1.0 is part of the \nRaspbian Jessie image available from [raspberrypi.org](https://www.raspberrypi.org/downloads/raspbian/). How to\ninstall libusb on [Windows](#windows) and [macOS](#macos) is covered below.\n\n### Operating Systems\n#### Raspbian\nThe main purpose of this project was to learn about using the uDMX interface on an RPi. And, this is the\nprimary environment where the author deploys the code.\n#### macOS \nHowever, enough of the work\nwas done on OS X 10.11.3 to conclude that this code will work or can be made to work on both OSes. If you want to\ntry it on OS X, use brew to install libusb (it will install libusb 1.0).\n#### Windows\nThe code has also been tested on Windows 10. To get this to work, you must install a Windows version of libusb. \nThere are likely a number of ways to get a libusb installed.\nHowever, the following libusb version has been successfully tested:\n[libusb-win32](https://sourceforge.net/projects/libusb-win32/) using this \n[installer](https://sourceforge.net/projects/libusb-win32/files/libusbK-release/libusbK-3.0.7.0-setup-chk.exe/download).\nThe key is to follow the instructions for the \"Driver Install Creator Wizard\". You need to create a driver for the\nuDMX interface.\n\n## Programs and Modules\n\n### tryusb.py Program\nThis was my first learning tool. It does the following:\n\n* Locates the uDMX interface.\n* Prints some information about the interface.\n* Sends some basic commands to a Venue ThinPar64 demonstrating how to manipulate the light via DMX.\n\nIt also helped me resolve some issues with [permissions](#Permissions) on the RPi. To run this app:\n\n python tryusb.py\n\n### uDMX.py Program\nThis program functions pretty much like the C++ based uDMX utility from Markus Baertschi. To get help, try\n\n ./uDMX --help\n or\n python uDMX.py --help\n\nFor each invocation, this program does the following:\n\n* Loads the uDMX.conf file from /etc/uDMX.conf.\n* Activates the virtualenv defined in the conf file IF PyUSB is not found in the current environment.\n* Loads the .uDMXrc file defined in the conf file.\n* Locates the uDMX interface based on vendor ID and product ID.\n* Sends the DMX message defined by the command line arguments.\n\nuDMX.py uses the pyudmx.py module.\n\n### pyudmx.py Module\nThe pyudmx.py module provides a simple, easy to use module for talking to the uDMX interface. Essentially,\nit is a uDMX specific adapter on top of the pyusb module. If you want to write a uDMX oriented application\nconsider starting with pyudmx.py.\n\nSimple usage example:\n\n dev = pyudmx.uDMXDevice()\n dev.open()\n dev.send_single_value(1, 255) # sends the value 255 to DMX channel 1\n dev.close()\n\nIn this example, the open() method will default to opening the first uDMX interface \nwith vendor ID 0x16c0 and product ID 0x05dc.\n\nA more complete programming example can be found in the **example.py** file.\n\n## Learning Notes\nHere are some notes from this learning exercise using Raspbian Jessie on an Rpi. The lessons learned\nhere apply to most Linux systems, but probably do not apply to Windows or macOS.\n\n### Finding the uDMX Interface\nAs there is no kernel driver for the uDMX, it does not show up under /dev like /dev/tty.\n\nYou can locate it this way:\n\n ~/rpi/uDMX-pyusb $ lsusb\n\n Bus 001 Device 005: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb\n Bus 001 Device 004: ID 1a40:0201 Terminus Technology Inc. FE 2.1 7-port Hub\n Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter\n Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. \n Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub\n\n\nThe uDMX is the first device at Bus 001, Device 005 with ID 16c0:05dc. The 16c0 is the vendor ID and\nthe 05dc is the product ID. The uDMX can be found at /dev/bus/usb/001/005.\n\n## Permissions \nIf you want to program the uDMX on a raspberry pi without always running sudo, you\nmust do something with the default permissions of the uDMX device.\n\n ~/rpi/uDMX-pyusb $ ls -al /dev/bus/usb/001/005\n crw-rw-r-- 1 root root 189, 4 Feb 25 15:30 /dev/bus/usb/001/005\n\nNotice the permissions are: 664. Only root and members of the \nroot group have write permission. This is why sudo is required for the current user (usually pi).\nYou can fix this issue by changing the permissions on the uDMX to: 666.\n\n sudo chmod 666 /dev/bus/usb/001/005\n\nNow check the permissions.\n\n ~/rpi/uDMX-pyusb $ ls -al /dev/bus/usb/001/005\n crw-rw-rw- 1 root root 189, 4 Feb 25 15:30 /dev/bus/usb/001/005\n\nUnfortunately, this is only a temporary fix. On the next reboot the permissions will revert\nback to their default 664. One way to permanently fix this problem is to write a \nudev rule that sets the permissions to 666 when the device is plugged in. Here's the\nrule.\n\n SUBSYSTEM==\"usb\", ATTR{idVendor}==\"16c0\", ATTR{idProduct}==\"05dc\", MODE=\"0666\"\n\nYou can take this solution by editing the [98-uDMX-usb.rules](https://github.com/dhocker/uDMX-pyusb/blob/master/98-uDMX.rules) \nfile and uncommenting the line that contains this rule. Copy the edited file to /etc/udev/rules.d.\n\n sudo cp 98-uDMX-usb.rules /etc/udev/rules.d\n\nTo make sure the rule is used, pull the uDMX and replug it.\n\nThere is an obvious down side to this solution. It gives all users read/write access to the uDMX. We\ncan limit read/write access to members of the pi group by changing the rule to:\n\n SUBSYSTEM==\"usb\", ATTR{idVendor}==\"16c0\", ATTR{idProduct}==\"05dc\", GROUP=\"pi\"\n\nThis rule leaves the permissions set to 664 while changing the ownership to root:pi.\nOverall, this is probably more desirable. The root user owns the device, members of the \npi group (which includes pi) have read/write access and all other users have read-only access.\n\n ~/rpi/uDMX-pyusb $ ll /dev/bus/usb/001/005\n crw-rw-r-- 1 root pi 189, 4 Feb 26 10:05 /dev/bus/usb/001/005\n\nYou can choose this rule by editing 98-uDMX-usb.rules file and uncommenting\nthe line that contains this rule.\n\n## Symlinks\nYou can use a udev rule to create a symlink for a uDMX device.\n\n SUBSYSTEM==\"usb\", ATTR{idVendor}==\"16c0\", ATTR{idProduct}==\"05dc\", GROUP=\"pi\", SYMLINK+=\"uDMXusb%n\"\n\nThis rule will produce a symlink for each uDMX device found.\n\n ~/rpi/uDMX-pyusb $ ll /dev/uDMXusb*\n lrwxrwxrwx 1 root root 15 Mar 21 16:29 /dev/uDMXusb2 -> bus/usb/001/005\n\nLooking at these permissions you might think that there is open access to the uDMX.\nHowever, that is not the case. The permissions of the the symlink target prevail.\nThe symlink simply allows all access to the symlink itself.\n\n ~/rpi/uDMX-pyusb $ ll /dev/bus/usb/001/005\n crw-rw-r-- 1 root pi 189, 15 Mar 21 16:29 /dev/bus/usb/001/005\n\nThanks to [muzzol](https://github.com/muzzol) for this tip.\n\n## udev Rules\nFor more on udev rules see [Writing udev rules](http://www.reactivated.net/writing_udev_rules.html).\n\n## Reboot Issues\nThis is an observation. On a warm reboot, the uDMX interface is not always found. \nYou might have to replug the device to get Raspbian to find it. Why this happens is unclear.\n\n## Multiple uDMX Issues\nIt is possible to run multiple uDMX devices on one system, but it can be difficult. Most uDMX interfaces\nand clones do not have unique serial numbers. This makes identification of each interface problematic.\n\nGiven the detailed USB information shown below, the following is available to identify\na uDMX.\n\n* Vendor ID\n* Product ID\n* Manufacturer\n* Product\n* Serial\n* Bus number\n* Device number\n\nBased on limited research it appears that only the Bus and Device numbers uniquely identify a\ngiven uDMX interace. The other values are likely to be the same for all uDMX interfaces based on the \nAnyma design and firmware. Unfortunately, the Bus and Device number cannot be used reliably because simply moving \na uDMX to another USB port will change one or both of those values.\n\nIf you want to use multiple uDMX interfaces, you need to plug them in one at a time and use the lsusb command\nto determine the Bus and Device number for each one. And, after that you can't move them around.\n\nThe pyudmx.uDMXDevice.open() method will accept a bus number and device address if you need to manage multiple\nuDMX interfaces.\n\nUnless otherwise indicated, the programs in this repo will work with the first uDMX interface they find.\n\n## Detailed USB Information\nHere is a dump of innformation a uDMX clone. Most of the information in the dump seems to refer to\nthe firmware manufacturer not the hardware manufacturer. The firmware is open source.\n\n ~/rpi/uDMX-pyusb $ lsusb -v\n\n Bus 001 Device 005: ID 16c0:05dc Van Ooijen Technische Informatica shared ID for use with libusb\n Device Descriptor:\n bLength 18\n bDescriptorType 1\n bcdUSB 1.01\n bDeviceClass 255 Vendor Specific Class\n bDeviceSubClass 0 \n bDeviceProtocol 0 \n bMaxPacketSize0 8\n idVendor 0x16c0 Van Ooijen Technische Informatica\n idProduct 0x05dc shared ID for use with libusb\n bcdDevice 1.02\n iManufacturer 1 www.anyma.ch\n iProduct 2 uDMX\n iSerial 3 ilLUTZminator001\n bNumConfigurations 1\n Configuration Descriptor:\n bLength 9\n bDescriptorType 2\n wTotalLength 18\n bNumInterfaces 1\n bConfigurationValue 1\n iConfiguration 0 \n bmAttributes 0x80\n (Bus Powered)\n MaxPower 500mA\n Interface Descriptor:\n bLength 9\n bDescriptorType 4\n bInterfaceNumber 0\n bAlternateSetting 0\n bNumEndpoints 0\n bInterfaceClass 0 (Defined at Interface level)\n bInterfaceSubClass 0 \n bInterfaceProtocol 0 \n iInterface 0 \n Device Status: 0x0000\n (Bus Powered)\n\n## References\n1. [uDMX - tiny bus powered USB-DMX interface - Anyma](http://www.anyma.ch/research/udmx/)\n2. [illutzminator](http://www.illutzminator.de/udmx.html?&L=1)\n3. [Markus Baertschi uDMX Utility](https://github.com/markusb/uDMX-linux)\n4. [Writing udev rules](http://www.reactivated.net/writing_udev_rules.html)\n5. [PyUSB](https://github.com/walac/pyusb)\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://www.github.com/dhocker/udmx-pyusb", "keywords": "", "license": "GPLv3. See LICENSE file.", "maintainer": "", "maintainer_email": "", "name": "udmx-pyusb", "package_url": "https://pypi.org/project/udmx-pyusb/", "platform": "", "project_url": "https://pypi.org/project/udmx-pyusb/", "project_urls": { "Homepage": "https://www.github.com/dhocker/udmx-pyusb" }, "release_url": "https://pypi.org/project/udmx-pyusb/2.0.0/", "requires_dist": [ "pyusb (>=1.0.2)" ], "requires_python": "", "summary": "uDMX Interface Library", "version": "2.0.0" }, "last_serial": 4261937, "releases": { "1.1.1": [ { "comment_text": "", "digests": { "md5": "3c453b4ea8a1b441d5d1615cda44997d", "sha256": "b7c683a7866d21c4f369a40535e98925ba5346377d3f3ad846ea645038fc6dd0" }, "downloads": -1, "filename": "udmx_pyusb-1.1.1-py2-none-any.whl", "has_sig": false, "md5_digest": "3c453b4ea8a1b441d5d1615cda44997d", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 8865, "upload_time": "2018-09-11T15:47:55", "url": "https://files.pythonhosted.org/packages/98/7e/0b78a731ead60aba44d71de8bad2668a7a285a736da315a1f8b5f63249fa/udmx_pyusb-1.1.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d49bfa55ba89f929a9aa9b9549f5f66c", "sha256": "267aff281cc76cb3e9c348179f0d001186e6dba2f71c4c894a790f8b04daef68" }, "downloads": -1, "filename": "udmx-pyusb-1.1.1.tar.gz", "has_sig": false, "md5_digest": "d49bfa55ba89f929a9aa9b9549f5f66c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22137, "upload_time": "2018-09-11T15:47:56", "url": "https://files.pythonhosted.org/packages/5c/20/1fd2d9837004379fc85ec5ca583e15d51a256fe934d62a3b61d0f319d1c8/udmx-pyusb-1.1.1.tar.gz" } ], "2.0.0": [ { "comment_text": "", "digests": { "md5": "106b338f572e7dfc03930a85cadaef2c", "sha256": "3d0bdb5acbfd7eb2f6ac4f3d13d08b89260454d4c9a97088db13819e9e5391a8" }, "downloads": -1, "filename": "udmx_pyusb-2.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "106b338f572e7dfc03930a85cadaef2c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8979, "upload_time": "2018-09-11T16:23:55", "url": "https://files.pythonhosted.org/packages/4a/1d/c19a32186ef78ee67180cc01ad57264d3ddd7da2c675947b0451317adbc8/udmx_pyusb-2.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "20d2cbea27e92aeab41df00d26ee6e86", "sha256": "3ed45facbbab6c49d6218a04eb44377b21022415f79cce9e271d489ed6d7c263" }, "downloads": -1, "filename": "udmx-pyusb-2.0.0.tar.gz", "has_sig": false, "md5_digest": "20d2cbea27e92aeab41df00d26ee6e86", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22284, "upload_time": "2018-09-11T16:23:56", "url": "https://files.pythonhosted.org/packages/81/b2/e392e233b6b798b5fa4cd717d7adff1d24bda52302673215abd844ecf4fe/udmx-pyusb-2.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "106b338f572e7dfc03930a85cadaef2c", "sha256": "3d0bdb5acbfd7eb2f6ac4f3d13d08b89260454d4c9a97088db13819e9e5391a8" }, "downloads": -1, "filename": "udmx_pyusb-2.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "106b338f572e7dfc03930a85cadaef2c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8979, "upload_time": "2018-09-11T16:23:55", "url": "https://files.pythonhosted.org/packages/4a/1d/c19a32186ef78ee67180cc01ad57264d3ddd7da2c675947b0451317adbc8/udmx_pyusb-2.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "20d2cbea27e92aeab41df00d26ee6e86", "sha256": "3ed45facbbab6c49d6218a04eb44377b21022415f79cce9e271d489ed6d7c263" }, "downloads": -1, "filename": "udmx-pyusb-2.0.0.tar.gz", "has_sig": false, "md5_digest": "20d2cbea27e92aeab41df00d26ee6e86", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 22284, "upload_time": "2018-09-11T16:23:56", "url": "https://files.pythonhosted.org/packages/81/b2/e392e233b6b798b5fa4cd717d7adff1d24bda52302673215abd844ecf4fe/udmx-pyusb-2.0.0.tar.gz" } ] }