sde1000 / python-dali Goto Github PK
View Code? Open in Web Editor NEWLibrary for controlling DALI lighting systems
License: Other
Library for controlling DALI lighting systems
License: Other
Since there's some drive about DALI drivers at the moment i want to place my latest finding here as well
https://git.unipi.technology/UniPi/unipi-python-lighting/blob/master/UnipiDali/unipidali.py
maybe it ends up in the driver collection somewhen
Hi,
would you mind license this package under LGPL, MIT, APACHE or similar license?
Regards
The collection of device drivers isn't really "plug-and-play" at the moment. All the example code imports the author's favourite driver and needs to be edited before being run to work with the others. This has caused problems for people picking up the library for the first time (eg. #42, #44) and in any case is a bit tedious!
We need some kind of driver registry and device discovery module, so that simple scripts that just work with a single DALI device can call to get a suitable driver with the API they need. Where multiple devices are present, or the device being used isn't automatically discoverable, the device to use could be specified by environment variable or on the command line. More complex code that works with multiple devices at once also needs a way of naming devices (eg. in its config file or on the command line), so we need a way to go from a string description of a driver/device to a driver instance.
Comments originally from @rnixx in #68:
Hi Stephen,
I still don't think there's a "winner" amongst the several driver APIs
I don't think we should talk about a "winning" API. Actually we have 2 approaches. The "old style" implementation in dali.driver.base
, with straight forward sync API and async implementation with callbacks. And the asyncio based implementation which uses the "modern" way of life. Both have their value and usecases. And finally there's the daliserver module which needs to be refactored to one kind of a driver or another, or both.
What we have in the driver package is some kind of a mess. Here are some thoughts from my side:
This is what the hid module may be split up to:
driver
asyncio
backend.py
hid
tridonic.py
tridonic
hasseb.py
hasseb
...
I always felt you do not like the driver API I wrote very much. Maybe I'm wrong, either way I'm totally fine with this. I am not able to switch over to asyncio based main loop anytime soon, and I think other people also will or cannot use asyncio for one reason or another. Therefor we should just cleanup the package and document what's there and why.
AS it turned out here, we'll need to specify interfaces to create cummunitation protocols and drivers with it - here.
Just wondering, do you have plans to include dali groups to be added?
At the moment only lamps are supported, not groups, right?
What is considered a "connection" here. A DaliServer instance? Because the socket connection gets opened and closed each enter/exit cycle if this flag is set to True, which is the opposite of multiple frames per (socket) connection in my understanding.
Hi,
I've found this raspberry shield https://www.shop.atxled.com/products/dali-hat-for-raspberry-pi-b-and-b?variant=18469832884339
Is this supported?
In alternative any suggestion on a cheap DALI2 to USB adapter is really appreciated.
Thanks, BR
Hello! I found the Commissioning
sequence, and I would like to invoke it from my code. Thing is, I already instantiate some SyncHassebDALIUSBDriver
objects, and I could only find examples of the sequence being run from a hid
-type object.
My question is, how would I go about this? It doesn't seem that the driver class has an accessible hid
(or hasseb
) member - do I need to instantiate a hasseb
object, or is there something in the SyncHassebDALIUSBDriver
class that can run sequences?
Thanks in advance!
Running tests like so:
~/workspace/python-dali$ ./bin/python -m dali.test_command
....
----------------------------------------------------------------------
Ran 4 tests in 85.095s
There's no USB DALI adapter connected while running the tests, so this might be a problem but then it would be better to have a backend mock for these tests.
Leaving this question here because the issue has just come up in the pull request for command sequences:
Is anyone still using this library on python-3.5?
f-strings were introduced in python-3.6 and I'm so used to them now it seems odd to have to work around their absence!
Is it now reasonable to drop support for python-3.5?
Does anybody still care about python 2 compatibility for python-dali?
The next lot of code I plan to commit is python 3.5+ only, because it's based on asyncio. Committing it won't break python 2 compatibility for existing code, but I'm just wondering about opportunities for clean-up.
Hello again :)
First and to be completely honnest, I am 100% new to DALI and DALI connection, so, please indulge me for my ignorance.
I have a LED connected to my OSRAM OPTOTRONIC 15/220-240-1A0 LT2 and I connected DA 3 and DA 4 to one of my Tridonic DALI port: https://ibb.co/jQasPd
And now I want to control the LED. Are my connections OK?
I really feel dumb asking that but I would like to avoid killing my devices :)
Anyway, thank you
There's a metaclass that collects the known commands. Is there any method to access this and instantitate any class form it?
I'm aiming to implement two features from it:
DAPC bcast 0x80
and the corresponding object has to be made, and sent.I'd implement these, and push my variations, if you could give me some hints how to do it properly to fit into the project.
Note: Is there any way to classify this ticket as Enhancement?
I'm going to make a lighting controller application as to control illumination level in a high-by indoor environment having daylight contribution form a semi-transparent roof.
Would anybody recommend me a dali illumination sensor for this purpose?
Thanks in advance.
As described in https://github.com/onitake/daliserver -> 4. Communication protocol, Requests are always 4 bytes long, thus the set-scene.py example fails (daliserver logs [2015-08-18 12:50:46] INFO Short read on connection 18, only got 2 bytes).
I digged around a little bit and added a hack to transmit protocol version and request type as expected here rnixx@27fa7f1
Am i missing any basic configuration for the Tridonic adapter or is this a bug?
When running this module I get the following error:
TypeError: unsupported operand type(s) for >>: 'float' and 'int'
It appears that :
low = 0
high = 0xffffff
if response.value is True:
midpoint = (low + high) / 2
results in a value of 838607.5 (float)
Whats the fix?
There's another possible USB2DALI device from Philips which I haven't yet been able to get working (with official software which requires key activation):
New USB device found, idVendor=0471, idProduct=0003, bcdDevice= 1.00
New USB device strings: Mfr=1, Product=2, SerialNumber=3
Product: Philips USB to DALI
Manufacturer: Philips Lighting
SerialNumber: XXX
USB HID descriptor:
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
0x09, 0x01, // Usage (0x01)
0xA1, 0x01, // Collection (Application)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x40, // Report Count (64)
0x09, 0x01, // Usage (0x01)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0x95, 0x40, // Report Count (64)
0x09, 0x01, // Usage (0x01)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x95, 0x01, // Report Count (1)
0x09, 0x01, // Usage (0x01)
0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0, // End Collection
I tried to run examples/find_ballasts.py which ended up in an error.
I added print (command, result)
before https://github.com/sde1000/python-dali/blob/master/dali/interface.py#L64
This is the output:
~/workspace/python-dali$ ./bin/python examples/find_ballasts.py
Usage: find-ballasts.py [host] [port]
Looking for ballast devices at localhost:55825
<dali.gear.general.Terminate object at 0x7f49f6cb3810> �
<dali.gear.general.Initialise object at 0x7f49f6cb3810> �
<dali.gear.general.Randomise object at 0x7f49f6cb3810> �
Searching from 0 to 16777215...
<dali.gear.general.SearchaddrH object at 0x7f49f6cb3810> �
<dali.gear.general.SearchaddrM object at 0x7f49f6cb3810> �
<dali.gear.general.SearchaddrL object at 0x7f49f6cb3810> �
<dali.gear.general.Compare object at 0x7f49f6cb3810> ���
(<type 'exceptions.TypeError'>, TypeError(u'Response must be passed None or a BackwardFrame',), <traceback object at 0x7f49f6cc8d88>)
Traceback (most recent call last):
File "examples/find_ballasts.py", line 83, in <module>
ballasts = find_ballasts(d)
File "examples/find_ballasts.py", line 60, in find_ballasts
low = find_next(i, low, high)
File "examples/find_ballasts.py", line 41, in find_next
response = i.send(Compare())
File "/.../workspace/python-dali/local/lib/python2.7/site-packages/dali/interface.py", line 65, in send
response = self.unpack_response(command, result)
File "/.../workspace/python-dali/local/lib/python2.7/site-packages/dali/interface.py", line 90, in unpack_response
response = command._response(rval)
File "/.../workspace/python-dali/local/lib/python2.7/site-packages/dali/command.py", line 57, in __init__
raise TypeError("Response must be passed None or a BackwardFrame")
TypeError: Response must be passed None or a BackwardFrame
Any chance of doing:
https://packaging.python.org/distributing/#uploading-your-project-to-pypi ?
Can help if need
Having a metaclass to keep track of all class types, is not working. We'll have to find an other way to do it.
Not entirely sure but I believe this is due to something changed in Python 3:
File "/home/.../python-dali/dali/driver/tridonic.py", line 258, in send
sn = struct.unpack('B', data[1])[0]
TypeError: a bytes-like object is required, not 'int'
i.e. using subscription notation on struct.Struct seems to return the byte value as int
(I'm pretty sure this issue is on the device side of the USB-wire, but maybe someone knows something)
I've been developing with the Hasseb DALI device because ... well it was available and I want to control some lights in the house.
I can't get actual adressing to work, so all my commands are DAPC(Broadcast(), <value>)
and Off(Broadcast())
based. This shouldn't matter.
After implementing with an actual light, and generating some input for it, I noticed sometimes - even with seconds of 'nothing' around it - Python throws:
d.send(cmd)
File "/usr/local/lib/python3.5/site-packages/python_dali-0.6-py3.5.egg/dali/driver/hasseb.py", line 85, in send
self.backend.write(self.construct(command))
File "/usr/local/lib/python3.5/site-packages/python_dali-0.6-py3.5.egg/dali/driver/base.py", line 189, in write
return self._ep_write.write(data)
File "/usr/local/lib/python3.5/site-packages/usb/core.py", line 387, in write
return self.device.write(self, data, timeout)
File "/usr/local/lib/python3.5/site-packages/usb/core.py", line 948, in write
self.__get_timeout(timeout)
File "/usr/local/lib/python3.5/site-packages/usb/backend/libusb1.py", line 842, in intr_write
timeout)
File "/usr/local/lib/python3.5/site-packages/usb/backend/libusb1.py", line 920, in __write
_check(retval)
File "/usr/local/lib/python3.5/site-packages/usb/backend/libusb1.py", line 595, in _check
raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 110] Operation timed out
Does anybody know why this is? As far as I can check the line is 'free', no other stuff is using it, etc (how do I debug this?).
The hardware I'm working on is a Raspberry Pi Zero W, directly attached via USB to the Hasseb DALI device.
First let me thank you for the great work you have done with this project 👍 . The setup I am planning would not have been possible without it.
I am conducting accelerated life tests of commercial LED drivers as part of my PhD and I want to record the data from the DiiA extended memory banks (e.g. primary side power, secondary side power) during these tests. As my test setup is running on Python I plan on using this library to read those memory banks. I have also build my own (quad) DALI-USB-interface and I will add a driver for that as well.
My question is: what would be a good place to add the support for the extended memory banks? As a new type of gear? I am not certain right now if the extensions only affect LED drivers or other types of drivers as well.
At the moment, dali.frame.Frame
raises exceptions in the following circumstances:
Frame()
and pass a sequence to initialise it, and one or more of the elements of the sequence is less than 0 or greater than 255, it will raise TypeError
pack_len()
on an instance of Frame
and the length you specify won't accommodate the frame (eg. passing length 2 for a 24-bit frame) it will raise ValueError
The first case isn't covered by the test suite; the second case is.
I'm looking at using int.from_bytes()
and int.to_bytes()
in the implementations of these, for a minor speedup. They've been available since Python 3.2. (The frame code was originally written for Python 2.7. Using the native methods gives about a 5% speedup running the tests on my machine.)
These native methods raise ValueError
in the first case, and OverflowError
in the second case.
The question is: is anybody relying on the current behaviour? I can catch the exceptions raised by the native methods and reproduce the current behaviour, but the choice of exceptions in the native methods does seem more appropriate.
@sde1000 as you mentioned in another post, dali.driver.tridonic.DaliUSB is meant as a daliserver
replacement, with restriction that the DALI interface is not controllable via network any longer, but requires physical access to the underlying USB bus.
I plan to implement such a driver as Twisted based Protocol (twisted.internet.protocol.Protocol). A protocol has a transport
property, where some can write data to and a dataReceived
function, which gets called whenever data is received.
Some questions appear.
Thanks for you patience :)
At some point it would be useful to drop support for Python 3.6, for two main reasons:
But when? Security support for Python 3.6 ends in December 2021, five years after its initial release; there's an argument that says support can be dropped after that. However, some distributions (eg. Ubuntu 18.04) will continue supporting Python 3.6 for longer; support for Ubuntu 18.04 ends in April 2023, for example.
Current distribution Python versions are:
I would like to pick a date between 23rd December 2021 and end of April 2023!
Hi, I get a 0 as response when I querying a scene with has the value 255.
dali_driver = SyncHassebDALIUSBDriver()
a = address.Short(1)
b = gear.QuerySceneLevel(a, 8)
c = dali_driver.send(b)
d = c.value
print(d)
=> 0
This is a log from a Lunatone interface.
I tried to search the bug in the code, but I could not find it.
Can python-dali be used to commission this device ?
https://www.lunatone.com/wp-content/uploads/2018/03/86458507-4L_DALI_MC4L_EN_D0032-1.pdf
Hi,
This library project seems to be really interesting, but now I'm looking at hardware:
http://it.farnell.com/nxp/om13046-598/eval-dali-master-usb2dali/dp/2249920
is there anyone that have tried this board?
Are there any recommended usb2dali device?
Thanks, BR
Any chance of expanding the README / making a wiki with some "Getting started" scenarios? I am unsure how the library discovers connected DALI systems. :)
Hello,
I am currently trying to use the library in order to control my DALI ballast but I am in my very first steps.
I have a tridonic dali - usb adapter that is connected to my mac (macOS Sierra) and the adapter is not connected to any ballast yet as I want to make sure my environment is OK.
I adapted the find-ballast.py script in order to use the SyncTridonicDALIUSBDriver instead of Daliserver (although I am also trying to install and use Daliserver as a back-up solution if the native tridonic library does not work properly) but I get the following error when I execute it:
$ sudo python3 find-ballast.py
Password:
Traceback (most recent call last):
File "find-ballast.py", line 75, in <module>
with SyncTridonicDALIUSBDriver() as d:
File "/usr/local/lib/python3.6/site-packages/python_dali-0.6.dev0-py3.6.egg/dali/driver/tridonic.py", line 221, in __init__
File "/usr/local/lib/python3.6/site-packages/python_dali-0.6.dev0-py3.6.egg/dali/driver/base.py", line 164, in __init__
File "/usr/local/lib/python3.6/site-packages/usb/util.py", line 205, in claim_interface
device._ctx.managed_claim_interface(device, interface)
File "/usr/local/lib/python3.6/site-packages/usb/core.py", line 102, in wrapper
return f(self, *args, **kwargs)
File "/usr/local/lib/python3.6/site-packages/usb/core.py", line 167, in managed_claim_interface
self.backend.claim_interface(self.handle, i)
File "/usr/local/lib/python3.6/site-packages/usb/backend/libusb1.py", line 811, in claim_interface
_check(self.lib.libusb_claim_interface(dev_handle.handle, intf))
File "/usr/local/lib/python3.6/site-packages/usb/backend/libusb1.py", line 595, in _check
raise USBError(_strerror(ret), ret, _libusb_errno[ret])
usb.core.USBError: [Errno 13] Access denied (insufficient permissions)
So I wonder if anyone has already experienced this and/or could help me with it.
One last weird thing is that even if my tridonic USB is connected to one of my few usb port, I cannot see any tty.USB in /dev/
Anyway, thank you for the help ;)
Hello, I am new to the DALI protocoll, and I was hoping someone could help me with some ideas.
I want to controll a system that is made of 24 drivers from a PC (linux or windows). Each driver has 4 individually addressable channels, (so in total 96 addressable channels). I am planning to use the Tridonic or Hasseb DALI master.
How can I overcome the 64 adresses limitation? I though of 2 solutions:
Is there a better workaround?
Thanks
Is there any way to create async callbacks, e.g., that the function provided to register()
is async? Or is callbacks always sync?
cc @fredriklj
Whenever I try to run one of the examples, I get :
Traceback (most recent call last):
File "find_ballasts.py", line 14, in
from dali.interface import DaliServer
ImportError: No module named interface
Any ideas ?
I'm very interested in this project but i'm not exactly sure what i can do with this.
When i buy a hasseb usb adapter, can i use this to assign an adress to new balasts (i guess i can do this with the hasseb software) and then switch / dim these?
How can i interface with the library (node-red, home-assistant)?
Is anyone using this with home-assistant or any other software to control their lighting?
Create an intrface class to make different drivers with it. (Sucha as tridonic USB, UART, DaliServer... etc) I've created one, but it made a merge conflict due I couldn't catch up the recent changes.
interface.py
in a base classinterface.py
for contain interface for various drivers.
I've seen vou've created a new branch for serial communication, but I had my own here as a feature branch.
I have downloaded and installed the library from the source and tried to run a test script "set_single.py" from examples. But after making all the changes and debugging some errors, the execution stops at send command and raises the error that the socket is unable to communicate to driver. The following error was shown. Will appreciate if someone can help me in debugging.
File "/usr/lib/python3.8/socket.py", line 796, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
I do have a custom contorller, which is able to communicate through (virtual) serial port with dali devices. It would nice to have a driver which is able to do that.
I've started to add support for different frame sizes to the code. Check out the 'frameclass' branch in my repo and let me know what you think. In particular, I'd like to know whether this approach will work with what you've been doing in your own code.
Assuming you think this is OK, I plan to start going through IEC 62386-103 and adding 24-bit control device commands and events to the library. There are also some more 16-bit commands in IEC 62386-102 to add, and some cleaning up to do to fix assumptions I made when I only had access to IEC 60929 annex E.
Is there a specific reason why you use plain distutils in setup.py instead of setuptools?
I'd create tickets to handle several things, we've been discussed - or started to - under the previous pull request
I'll paste here your plan:
Is this object experimental? legacy? The DaliServer class in dali.interface communicates with daliserver which actually does all the communication properly, so i am wondering if this class can go into a dedicated sandbox place if it's not supposed to end up as official API?
We haven't published a new version in a while, maybe we can do 0.7 ?
I'm in the process of implementing a new driver (as mentioned in #59) and I stumbled over the device type issue. The CommandTracker (see #3) only stores these as far as I can see. hid.py automatically deals with _devicetype, but the other drivers don't.
If drivers are supposed to be handling the _devicetype attribute, it should be marked as public not protected.
If not, how should application logic handle it, e.g. interact with the CommandTracker?
Hi,
I found this googling for a DALI Logger i could run on a Raspberry Pi
I'm a lighting controls integrator based in Canberra Australia, and we're having trouble with a job that has issues with lights being triggered at odd times with no obvious explanation.
I have very little coding experience, especially not with python. Could anyone help me to build an image I could load onto a Raspberry Pi and connect using a Tridonic DALI USB to the Dali line? even better if it could monitor multiple DALI-USBs and record to files. Thats all i really want it to do, just record the traffic and store to a text file that i can pull out later.
I noticed someone mentioned they were short of hardware to further develop this, I have a whole bunch of surplus/older hardware I'm happy to post if someone is interested in helping me out.
I've been looking at making a new release (upload to pypi, and generate Debian packages) and I've run into a couple of blockers.
When I try to build the Debian packages with current debhelper, I get:
dh_auto_test -O--buildsystem=pybuild
I: pybuild base:217: python3.8 setup.py test
running test
WARNING: Testing via this command is deprecated and will be removed in a future version. Users looking for a generic test entry point independent of test runner are encouraged to use tox.
error: the `allow-hosts` option is not supported when using pip to install requirements.
E: pybuild pybuild:341: test: plugin distutils failed with: exit code=1: python3.8 setup.py test
What's happening here is that debhelper is deliberately setting up the environment to prevent setuptools from fetching build or test dependencies. Furthermore, reading around the issue, I've found that setup.py test
is deprecated: see pypa/setuptools#1684 — the reasoning appears to be that, amongst other things, fetching and installing test requirements is out of scope for setuptools.
Currently in setup.py
we have:
test_suite='dali.tests',
install_requires=['pyusb', 'pymodbus'],
tests_require=['mock'],
This works well enough for the current Travis CI integration, but is obviously going to be problematic in the future. There are a couple of things to talk about:
If I remove those three lines from setup.py
then debhelper builds the packages without running any tests. If I add dali.tests
to the packages
list then debhelper runs all the tests using python3 -m unittest discover
— which fails on the unipi driver tests which require mock and pymodbus.
So what should we do? I'm not sure, but things I'm considering include:
dali.driver
, and arrange that they are not run by default by python3 -m unittest discover
(but are run by Travis CI)Any other suggestions? Python packaging seems to be a bit of a minefield at the moment!
I've used this library as glue between my lighting and other home automation and now that I have couple of tunable white dt8 devices I want to add colour control into the play.
I acquired a copy of the part 209 and I'm currently working on writing colour
module. For most of the things this looks quite straightforward, but there's a couple of things I'd like to evaluate my thoughts first. For instance, query colour value command takes parameter that defines which of the 50+ values is to be queried - would I rather define this as class (int, Enum)
or just as constants?
Do you mind if i format the code according to PEP8?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.