Wednesday, August 19, 2009

Python driver v0.11 for CM19a X10 Transceiver

Now updated to version 0.11. Just a few bug fixes plus it now saves any error messages to an object attribute so these can be accessed externally (such as via a user interface app).

Here's my first attempt at a Python driver for the CM19a wireless (USB, Firecracker) transceiver.
This is a user space driver so a kernel driver for the CM19a does not need to be installed.

Functionality
- Use the CM19a to send any X10 on/off command (eg A1OFF, C16ON) wirelessly to a lamp or appliance module (requires an X10 receiver module).
- Use the CM19a to automatically receive and log to a queue any command received from an X10 remote control.

Click here for the Python code(version 0.11)

Click here for the X10 protocol file

Andrew

Example Output
Configuring...
CM19a found and opened
Vendor ID (dev.idVendor): 3015 (0bc7 hex)
Product ID (dev.idProduct): 2 (0002 hex)
Device Version: 01.00
usbVersion: 01.10
Number of Configurations: 1
Turning ON A1...
Waiting 5 seconds...
Turning OFF A1...
Press one or more keys on the x10 remote within the next 30 seconds
Command A3OFF received via cm19a
Command A3ON received via cm19a
Command A3ON received via cm19a
Command A4OFF received via cm19a
Command A3OFF received via cm19a
Command A1OFF received via cm19a
Receive Queue: ['A3OFF', 'A3ON', 'A3ON', 'A4OFF', 'A3OFF', 'A1OFF']
Press one or more keys on the x10 remote within the next 30 seconds
Command A1ON received via cm19a
Command A2ON received via cm19a
Command A2ON received via cm19a
Command A3ON received via cm19a
Command A4ON received via cm19a
Receive Queue (since the last time we requested the queue): ['A1ON', 'A2ON', 'A2ON', 'A3ON', 'A4ON']
Tests complete.

24 comments:

  1. AnonymousOct 10, 2009 01:09 PM
    Thank you very much for posting this code. I have it working in Ubuntu 9.04, though I had to blacklist the following two modules in /etc/modprobe.d/blacklist

    lirc_atiusb
    ati_remote

    I am doing some home automation with some X10s, and am now adding a 1-Wire network for sensors. My first use of your code will be to activate a blower on a wood stove depending on the temperature in our loft bedroom.

    Thanks again
    Michael, Corning, NY, US
    ReplyDelete
  2. AndrewOct 18, 2009 03:32 AM
    Great, thanks for the post Michael.

    I think I had probably already blacklisted those modules.

    If you find any bugs please let me know so I can update my code.
    ReplyDelete
  3. Chris CombsDec 7, 2009 06:33 PM
    Ah, this is excellent! Thank you. I'm using it to recover data from a sporadically-working hard drive via a shell script using ddrescue... when the usb device disappears, it gets its power reset via X10. Very helpful.
    ReplyDelete
  4. Tim MeushawDec 8, 2009 04:10 AM
    Thank you very much for writing this! I just purchased a CM19A to replace my working CM17A, since I may be moving to a server soon that doesn't have serial ports. I too had to rmmod ati_remote (the other module hadn't loaded) in order for this script to work.

    How are you doing regarding a user interface? :-) It would also be nice to maybe have this run as a daemon; that way, a shell-based client can receive commands from the user to send, while a background thread is reading input from remote commands and logging all X10 commands that fly around my house.
    ReplyDelete
  5. AndrewDec 11, 2009 12:25 PM
    I was amazed that when I bought my CM19a that most of the software and drivers out there did not support it - the focus still seems to be on the RS232 serial versions rather than USB.
    ReplyDelete
  6. AndrewDec 11, 2009 12:34 PM
    I haven't thought about a user interface yet. The intent was to be a back end.

    I have though about running as a daemon but this is well beyond my Python knowledge (Are there any good tutorials/examples out there?).

    Currently I use this driver in my own automation program that I automatically load on startup. It runs a continuous loop that checks for events on my network (eg PS3 is turned on) and responds by turning on the TV (infrared) and a lamp(X10). I also have a intranet site that I use to control my AV equipment using this program and my ipod touch and the remote.
    ReplyDelete
  7. Tim MeushawDec 12, 2009 04:46 PM
    Pretty much everything is beyond my Python knowledge; I can make my way through with Perl, but Python just confuses me. :-) For my environment, I really only use my CM17a simply to turn lights on and off via cron. But I don't know enough Python to, say, take your script and write a wrapper that simply takes "a1 on" as command line arguments and passes them to the appropriate function. Maybe I can find a quick tutorial, or bribe one of my Python-knowing friends....

    I was mostly thinking about a daemon since it'd be nice to only initialize the device once, instead of every time the script gets run; but that'd be more a wishlist kind of thing.

    I remember when looking at the serial port devices, it was really annoying to write scripts that both listened to incoming signals while sending user-driver outbound signals in the same script, since one of the routines would lock out access to the port so the other couldn't use it. I wonder if USB devices work the same way....
    ReplyDelete
  8. HackeronJun 5, 2010 04:49 PM
    Any updates? - i.e. does bright/dim work yet? :)
    ReplyDelete
  9. AndrewJun 6, 2010 03:57 PM
    Hi Hackeron
    I haven't looked at bright/dim for some time. I'll see if I can find some time over the next few weeks.

    I have been working on server version that enables the the connected devices to be controlled remotely via xml-rpc calls. That means you'll be able to control a device using any prog or scripting language that supports xml-rpc (Perl, Ruby, Python etc). And the controlling script doesn't need to be on the same PC as the X10 devices.
    ReplyDelete
  10. Dan AbdinoorJul 21, 2010 03:38 PM
    I was psyched to find this driver but unfortunately I just cannot get it to work. Every time I run the script I get:
    "Resource busy
    Unable to open the CM19a."
    I can't figure out why the device would be busy. When I unplug it, the script correctly detects that the device is unplugged, so I assume that libusb is working correctly.

    Any suggestions?
    ReplyDelete
  11. AndrewJul 24, 2010 10:33 PM
    Dan. It sounds like another driver has taken ownership of the device. If you are using Ubuntu you will need to blacklist a couple of drivers (See below). I'm not sure whether you need to do this on other Linux distributions.
    Let me know if this does not work.

    1. Edit the blacklist file
    sudo nano /etc/modprobe.d/blacklist

    2. Add in the follow text and save
    # To enable CM19a X10 Transceiver to work
    blacklist lirc_atiusb
    blacklist ati_remote

    3. Reboot so this all takes effect.
    ReplyDelete
  12. David MerrickAug 14, 2010 04:20 PM
    Thanks for writing this, Andrew--it worked great for me on an Ubuntu 9.10 server!

    @Dan: I ran into the same issue as because I'd tried to run the script twice. Try "ps ax | grep cm" and if the script is running, kill it with "kill ." Then try running it again.
    ReplyDelete
  13. David MerrickAug 14, 2010 04:21 PM
    *my comment above got stripped of a few tags. Dan-- kill the process with "kill [process id number]."
    ReplyDelete
  14. AnonymousSep 16, 2010 09:01 AM
    I know this is more of a general python question, but I'm trying to get this working and I get "ImportError: No module named logger". I've searched UbuntuForums and Google and I can't seem to find anyone else with this issue. I was able to get python-usb installed so I figured it was some basic thing I am missing. Any ideas?

    I see info about something called "Logging", but that's not "Logger". So there are web pages that describe "import logging". I tried changing "import logger" to "import logging" but as expected that fails:

    File "CM19a_X10_USB.py", line 479, in
    log = logger.start_logging("CM19a_X10_USB", LOGFILE)
    NameError: name 'logger' is not defined

    Thanks for any advice you can give!

    -Greg
    ReplyDelete
  15. AnonymousSep 16, 2010 09:05 AM
    Just realized I posted this in the wrong page; I am trying to use version .20! Sorry about that, maybe I'll try .11 as I see in the changelog that you added logging in .20 and that seems to be what is failing for me.

    -Greg
    ReplyDelete
  16. AnonymousSep 16, 2010 10:01 AM
    Version .11 works great for me - you can delete my comments, thank you!

    -Greg
    ReplyDelete
  17. AndrewSep 20, 2010 03:30 PM
    The logging problem is my fault - I left out a file called logger.py from the archive file. The latest version 2 driver should now work. You can find it here: http://ubuntuone.com/p/GtG/
    ReplyDelete
  18. DougOct 2, 2010 09:33 PM
    I wanted to run this as a command line module to send (not receive) commands to the Cm19. The command line code works fine but now I want to use an existing Perl script to call it. Something like -

    system("/usr/bin/python /usr/local/bin/x10python/CM19a_X10_USB.py $x10command\r\n");

    When I do this it complains about not finding many of the Python modules it needs. errors like -

    Sat 02 Oct 2010 23:33:44, ERROR, Error loading libusb 1.0 backend
    Traceback (most recent call last):
    File "/usr/local/lib/python2.7/site-packages/usb/backend/libusb10.py", line 588, in get_backend
    _lib = _load_library()

    Not being a Python programmer I am not sure why this is happening. Any help would be appreciated.
    ReplyDelete
  19. AndrewOct 4, 2010 03:17 AM
    Hi Doug
    This is a libusb problem. It looks like it is trying to load the libusb1.0 backend. Try installing libusb0.1 and see if it works (this is the original libusb library.

    Also, try running the Python script on it's own to see if you get any error messages when you are not calling it from your Perl script.

    Let me know if you still have problems.
    ReplyDelete
  20. DougOct 4, 2010 06:31 AM
    Andrew,

    Thanks. The code does work standalone when running the module directly from the console and sending commands to the CM19. This only happens when I call it from this Perl script.

    Can the .1 and 1.0 USB libs both be loaded? Would this interfere with anything or would they clash with each other?
    ReplyDelete
  21. DougOct 4, 2010 06:28 PM
    Just posting again to tell you the progress I made on this. I gave up on the Perl system call to Python. A call from a BASH script or crontab seems to work fine. So I just took the code from the Perl script and recreated it in the CM19 Python script. It works fine and crontab is controlling my automation.

    The original Perl script had mapped the house and unit coeds to a single number. I say '2 on' or '18 off' and it is mapped to the house and unit code. I also send the command three time with a 1 second delay between sends. This is all now done in the python module which is call by a simple BASH script that in turn is called by cron.

    If anyone can answer why the Perl call did not work I would be interested to know. I spend a lot of time trying to get it to work. I should have just written it in Python to begin with. Python is nice once you get to know it.
    ReplyDelete
  22. DougOct 7, 2010 07:46 AM
    The only problem is that I get messages like this:

    kernel: usb 5-2: usbfs: interface 0 claimed by usbfs while 'python' sets config #1

    if I try to send multiple commands with cron at the same time. This is similar to what I got with the kernel /dev/cm19 driver. So I guess there might be an issue, at least on my system, sending multiple commands to the USB??? I can live with it because there is nothing that has to have simultaneous commands. I just spread them out. But I do wonder why this is happening and if it is just on my system.
    ReplyDelete
  23. AnonymousDec 7, 2011 09:21 PM
    Hello everyone,

    I am running on Ubuntu 11.10; I installed this driver, after, I blacklisted these
    blacklist lirc_atiusb
    blacklist ati_remote
    then Reboot.
    then I try to run the driver as follow:

    /CM19A$ sudo ./CM19aDriver.py A1 ON
    [sudo] password for carlos:
    Traceback (most recent call last):
    File "./CM19aDriver.py", line 106, in
    import usb
    ImportError: No module named usb

    What can I do?

    Thanks in advance,
    Carlos Gonzalez
    ReplyDelete
  24. AndrewDec 9, 2011 03:28 PM
    Hi Carlos

    You need to install pyUSB. You can install it from the Ubuntu Software centre or from the command line:
    sudo apt-get install python-usb

    Andrew
    ReplyDelete

Recent Comments