Author Topic: Plugin for cm15a/cm19a X10 Controllers /w Mochad Linux Daemon (full send/recv)  (Read 60483 times)

Offline radarengineer

  • Sr. Member
  • ****
  • Posts: 402
  • Karma: +4/-0
Hi!

I have been working on a plug on that interfaces Vera to Mochad, which is a "mochad is a Linux TCP gateway daemon for the X10 CM15A RF (radio frequency) and PL (power line) controller and the CM19A RF controller."

http://sourceforge.net/projects/mochad/

This will give you full send and receive control to X10 PL, RF, and RFSEC devices.

You have to have a usb cm15a or cm19a controller plugged into a linux computer running the mochad daemon. I have run mochad on a pc, an openwrt router, and most recently a Pogoplug plug computer. I recommend the Pogoplug if you don't have a linux box already running 24/7 because it is <5watts. It makes a good Vera extender!

Right now I support:

binary lights (this could also be an appliance module)
dimmable lights (both old and new 'softstart', although you have to tell my plugin which)
motion sensors that use housecodes (ms14a/ms16a)

I do not support RFSEC devices yet. (ds10a, ms10a, etc). I will but I just haven't done it yet!

I just started the plugin earlier this week and it needs a bit of tweaking.

I am successfully dimming a lamp module and watching a couple of motion sensors. :)

X10 sensors are dirt cheap which is one of the benefits of this plugin. ds10a door/window sensors are 9 for $30, ms14a PIR motion sensors are 6 for $35, and ms10a (bigger/nicer/RFSEC PIR motion sensors) are 7 for $50. Combine that with 20% off and free shipping... lets just say I bought a lot of these before I found vera. People do a lot of cool things with ds10a sensors especially, and for ~$3 each why not?

Plus I am assuming that like me you have a bunch of this x10 crap sitting around that you would like to use while you move to z-wave. ;)

Please don't install this yet unless you are familiar with luup as I am experiencing a few issues still!

Hopefully some luup experts can set me straight?

EDIT: Attachments removed. New code is now up at code.mios.com
« Last Edit: August 22, 2011, 10:08:30 am by radarengineer »

Offline radarengineer

  • Sr. Member
  • ****
  • Posts: 402
  • Karma: +4/-0
Please excuse me for replying to myself, I didn't want to clutter up the first announcement post with this issue. Sometimes when dimming a light Luup crashes! I must be doing something dumb ??? Most of the time it works great.

I think the problem is in this function:

   ------------------------------------------------------------
   local function sendCommand(command)
        if luup.io.write(command)==false then
            luup.log("cannot send: " .. tostring(command),1)
            luup.set_failure(true)
            return false
        else
            luup.log('Wrote: ' .. command);
            return true
        end
   end

It seems like sometimes luup.log isn't valid? But only rarely?

Here is my log:

02   08/17/11 20:56:46.354   UPnPCallbackEventHandler 4 start PIDLOG2 28376 <0x240a>
02   08/17/11 20:56:46.352   UPnPCallbackEventHandler 4 start PIDLOG2 28375 <0x2009>
08   08/17/11 20:56:50.374   JobHandler_LuaUPnP::HandleActionRequest device: 57 service: urn:upnp-org:serviceId:Dimming1 action: SetLoadLevelTarget <0x4808>
08   08/17/11 20:56:50.375   JobHandler_LuaUPnP::HandleActionRequest argument DeviceNum=57 <0x4808>
08   08/17/11 20:56:50.376   JobHandler_LuaUPnP::HandleActionRequest argument serviceId=urn:upnp-org:serviceId:Dimming1 <0x4808>
08   08/17/11 20:56:50.376   JobHandler_LuaUPnP::HandleActionRequest argument action=SetLoadLevelTarget <0x4808>
08   08/17/11 20:56:50.377   JobHandler_LuaUPnP::HandleActionRequest argument newLoadlevelTarget=100 <0x4808>
08   08/17/11 20:56:50.377   JobHandler_LuaUPnP::HandleActionRequest argument rand=0.18467210094632092 <0x4808>
06   08/17/11 20:56:50.380   Device_Variable::m_szValue_set device: 57 service: urn:upnp-org:serviceId:Dimming1 variable: LoadLevelStatus was: 0 now: 100 #hooks: 0 upnp: 0 v:0x801348/NONE duplicate:0 <0x4808>
01   08/17/11 20:56:50.407   LuaInterface::CallFunction-1 device 57 function SDimming1_Dimming1_SetLoadLevelTarget_run failed [string "..."]:41: attempt to call field 'log' (a number value) <0x4808>
08   08/17/11 20:56:52.039   JobHandler_LuaUPnP::HandleActionRequest device: 57 service: urn:upnp-org:serviceId:Dimming1 action: SetLoadLevelTarget <0x4808>
08   08/17/11 20:56:52.040   JobHandler_LuaUPnP::HandleActionRequest argument DeviceNum=57 <0x4808>
08   08/17/11 20:56:52.041   JobHandler_LuaUPnP::HandleActionRequest argument serviceId=urn:upnp-org:serviceId:Dimming1 <0x4808>
08   08/17/11 20:56:52.041   JobHandler_LuaUPnP::HandleActionRequest argument action=SetLoadLevelTarget <0x4808>
08   08/17/11 20:56:52.042   JobHandler_LuaUPnP::HandleActionRequest argument newLoadlevelTarget=0 <0x4808>
08   08/17/11 20:56:52.043   JobHandler_LuaUPnP::HandleActionRequest argument rand=0.32482261823748493 <0x4808>
06   08/17/11 20:56:52.044   Device_Variable::m_szValue_set device: 57 service: urn:upnp-org:serviceId:Dimming1 variable: LoadLevelStatus was: 100 now: 0 #hooks: 0 upnp: 0 v:0x801348/NONE duplicate:0 <0x4808>
50   08/17/11 20:56:52.062   luup_log:56: Wrote: pl A1 xdim 0 <0x4808>
02   08/17/11 20:56:53.394   UPnPCallbackEventHandler 4 start PIDLOG2 28376 <0x240a>

Offline dfad1469

  • Jr. Member
  • **
  • Posts: 77
  • Karma: +0/-0
Why do you have a ,1 as an argument to luup.log?


Offline guessed

  • Master Member
  • *******
  • Posts: 5293
  • Karma: +90/-22
  • Release compat is not a bolted-on afterthought
A few comments:

D_Mochad1.xml...
a) protocol element has a value of "cf".
I think you wanted "crlf" or "cr".  It's working at the moment, as the defn in the I_xxxx.xml file is overriding this declaration.

I_Mochad1.xml...
a) For log/debug convenience fns, use the newer ones
Something like this:
    http://code.mios.com/trac/mios_brultech-power-monitor/browser/trunk/L_BrultechMeter1.lua#L25
as it passes the parameters for logging levels, and you can use that in your code if needed for printing info level stuff (etc)

b) dev_id:sub(3, string.len(dev_id)) is a convenience in Lua for string.sub(dev_id, 3, string.len(dev_id))
Also the default is to run through the end of the string, so you can shorten it further to dev_id:sub(3)

c) You have the convenience function log(...) but in some cases you directly use luup.log still.
Seems like you might as well cut them all over to just use log(...) instead of luup.log(...).  One of these is in sendCommand, for example.

d) In split_deliminated_string, "nil" is mis-spelt.
In Lua, this should have one L, not 2.

e) If you're going to read/write Variables off of the Parent device, you should also have a S_xxxx.xml file.
It's not required, but it's a great way to document what the variables are, and what they do/store (format, etc)

f) is_motion() assumes the existence/validity of a global variable lul_device.
These are typically done as input parameters to <startup>, <incoming> etc, but aren't documented to exist elsewhere (even if they may do, in some cases).

Might be better to store this during the <startup> code, into a named Global variable of your own, and then use that throughout the code.

This code also checks for "nill" instead of "nil", so you'll want to change that also.

g) In lug_startup, return a string indicating the error.
Specifically, return a "tuple" like:

     return false, "Mochad", "Cannot connect to Mochad on " .. ipAddress

This will then get displayed in the startup/dialog on the dash when the plugin fails, letting the user know without having to read the log files.

btw, what's the difference between an X-A01 and an D-A01?

h) <incoming> block needs a little parameter checking.
You may find cases where the incoming IO gets mangled.  I've seen this a few times with Zibgee Serial devices (etc).  Anyhow, in these cases the data may not come in the format you're expecting, may be missing checksums (etc), so it might pay to do some basic validation on it before "acting" on the resulting data.

i) Declare all the service Id strings at the top, as you've done for SECURITY_SID.
You have others like HaDevice1, SwitchPower1, Dimming1 etc that could all benefit from that for code readability.


Offline guessed

  • Master Member
  • *******
  • Posts: 5293
  • Karma: +90/-22
  • Release compat is not a bolted-on afterthought
Sometimes when dimming a light Luup crashes! I must be doing something dumb ??? Most of the time it works great.
...

It seems like sometimes luup.log isn't valid? But only rarely?
When I've seen this, it's because two [MiOS] threads are trying to do something concurrently with Lua.  That's not permitted, since the Lua context isn't t-safe.

In the case where I've seen it, it's concurrent <startup> and <incoming> code, but the same possibility it true for <action> and <incoming>.

I believe this is the problem you're experiencing, but I was expecting to see log lines starting with "51" or "52" indicating the IO, but perhaps you don't have verbose Logging enabled.

Anyhow this problem is currently being worked on by MCV.  The symptom will be what you're seeing, or occasionally SEGV'd (signal 11 detected) on the LuaUPnP process.

Offline radarengineer

  • Sr. Member
  • ****
  • Posts: 402
  • Karma: +4/-0
@dfad1469 and @guessed,

Thank you very much for the comments! Those are *very* helpful!

I think my crash was probably caused by two concurrent threads. I have been reloading this plugin a great deal, and also stress testing the lights... I had one browser window open with UI4 to reload the file and one I was testing it in.

@guessed, I have learned a great deal from reading your other code. I still have a lot to learn though! I will try to implement all the code improvements you mention.

As for X-A01 and D-A01, there are two types of X10 dimmer units. Older X10 dimmers need a different command than newer ones. My understanding is that newer modules are called "extended dim" or "soft-start" modules. I am using the different prefixes to distinguish between units and tell what command set to use.

An old dimmer needs "pl a1 dim <dims>" where dims is from 0 to 31
A new dimmer needs "pl a1 xdim <dims>" where dims is from 0 to 63

There might be a better way of differentiating between these in the code, and I'm certainly open to it.

Offline radarengineer

  • Sr. Member
  • ****
  • Posts: 402
  • Karma: +4/-0
Here are some instructions on putting mochad on a pogoplug. I pick up at the end of the installation instructions found on the Archlinuxarm site. For the Pink Pogoplug v2 those are found here:

http://archlinuxarm.org/platforms/armv5/pogoplug-v2-pinkgray (and click on "installation").

When you first are done installing Archlinux on your pogoplug you might want to update some things first. Archlinux uses a package manager called 'pacman'. You will use pacman to install and remove programs. You can see a comprehensive guide here:

https://wiki.archlinux.org/index.php/Pacman

If you are following this guide and pacman asks you if you want to update pacman or install other packages, it is a good idea to say yes. If you get a prompt that asks you to update pacman and you do, you might have to rerun the installation command you were trying to run. Start this guide by ssh'ing into your newly installed Pogoplug. You should see a prompt like this:

[root@alarm ~]#

The first think I am going to do on my new system is sync the package managers repository databases. This way my pogoplug knows what version of packages to install.

pacman -Sy

Now I am going to install a network time protocol client so I can update my pogoplug's clock. The pogoplug doesn't have a hardware clock so it doesn't know what time it is. If you reboot the pogoplug it will go back to thinking it is 1970!

pacman -S ntp

Now that this is installed I am going to fix my pogoplug's time:

ntpdate pool.ntp.org

Now if I run the date command it should show the right time! You can set up the pogoplug to do this on boot, but I'm not going to go into that here. Now to install mochad I need the make command:

pacman -S make

Now I am going to get my compiled mooched package. I am hosting this precompiled version on my website so you don't have to get install gcc and build it yourself. If you want to though it isn't hard, I didn't do anything special.

wget http://naething.com/mochad_compiled.tar.gz

And now extra the archive:

tar -xzf mochad_compiled.tar.gz

Enter the new directory:

cd mochad-0.1.12

Install mochad:

make install

Now mochad is installed! You are done! But lets make sure it is working. Install nc.openbsd to test mochad (the build in nc is broken on archlinuxarm)

pacman -S openbsd-netcat

Plug in a cm15a or cm19a and see if it works:

nc.openbsd localhost 1099

And type in a mochad command:

rf a1 on

You should get something like:

08/19 21:11:08 Tx RF HouseUnit: A1 Func: On

You can also watch to see if mochad is hearing your motion sensors or other RF devices. The cm15a/cm19a have fairly crappy antennas so you might have to do an antenna mod to hear the little keychain remotes well. When you are done you can leave the netcat session with "CTRL-C".  :)

EDIT:

I uploaded a newer binary version of mochad, instructions are the same

http://naething.com/mochad-0.1.14_pogo.tar.gz

« Last Edit: February 10, 2012, 07:10:13 pm by radarengineer »

Offline Intrepid

  • Hero Member
  • *****
  • Posts: 536
  • Karma: +4/-0
Radar, awesome instructions. 

My new pogo is up and running with my CM19a and mochad.  Command line control works, and it does 'see' my palmpad commands.   

Great work!





Offline Intrepid

  • Hero Member
  • *****
  • Posts: 536
  • Karma: +4/-0
Radar, amazing work!

Here's how my test units work.

CM19A interface with pogoplug





MS12A motion sensor D4:  working

This works perfectly!




DS10A 6B:D0:80 -- not working

The virtual device shows up but does not toggle.  Mochad does see the sensor changes.

01/02 18:00:53 Rx RFSEC Addr: 6B:D0:80 Func: Contact_normal_max_low_DS10A
01/02 18:00:54 Rx RFSEC Addr: 6B:D0:80 Func: Contact_alert_max_low_DS10A

Vera log seems to see the DS10a activity:
08/23/11 6:58:19.295   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:17 Rx RFSEC Addr: 6B:D0:80 Func: Contact_normal_max_DS10A <0x380f>
01   08/23/11 6:58:19.297   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>
01   08/23/11 6:58:20.935   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:18 Rx RFSEC Addr: 6B:D0:80 Func: Contact_alert_max_DS10A <0x380f>
01   08/23/11 6:58:20.936   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>
01   08/23/11 6:58:21.920   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:19 Rx RFSEC Addr: 6B:D0:80 Func: Contact_normal_max_DS10A <0x380f>
01   08/23/11 6:58:21.921   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>
01   08/23/11 6:58:22.528   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:20 Rx RFSEC Addr: 6B:D0:80 Func: Contact_alert_max_DS10A <0x380f>
01   08/23/11 6:58:22.529   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>
01   08/23/11 6:58:23.144   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:21 Rx RFSEC Addr: 6B:D0:80 Func: Contact_normal_max_DS10A <0x380f>
01   08/23/11 6:58:23.145   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>
02   08/23/11 6:58:26.469   UPnPCallbackEventHandler 4 start PIDLOG2 17635 <0x240a>
02   08/23/11 6:58:26.569   UPnPCallbackEventHandler 4 start PIDLOG2 17634 <0x2009>
02   08/23/11 6:58:26.670   UPnPCallbackEventHandler 4 start PIDLOG2 17635 <0x240a>
02   08/23/11 6:58:26.770   UPnPCallbackEventHandler 4 start PIDLOG2 17634 <0x2009>
01   08/23/11 6:58:29.985   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:28 Rx RFSEC Addr: 6B:D0:80 Func: Contact_alert_max_DS10A <0x380f>
01   08/23/11 6:58:29.986   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>
01   08/23/11 6:58:30.599   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:28 Rx RFSEC Addr: 6B:D0:80 Func: Contact_normal_max_DS10A <0x380f>
01   08/23/11 6:58:30.601   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>
01   08/23/11 6:58:31.216   luup_log:71: MOCHAD: MOCHAD: Recieved 01/02 19:10:29 Rx RFSEC Addr: 6B:D0:80 Func: Contact_alert_max_DS10A <0x380f>
01   08/23/11 6:58:31.217   luup_variable_get interface 0xb6e0a0 no (null)/urn:micasaverde-com:serviceId:mochad1 <0x380f>


X10 appliance module A2: working for UI control, does not sense RF control changes

If set this a A2 in 'dimmable modules', I can control it via Vera UI.  However, Vera does not see changes made via an RF palmpad (status never changes).  

If I set up A2 as a 'binary module', I cannot control via Vera UI.  Also, RF palmpad changes are not seen by Vera.

edit:  I guess an RF remote like the palmpad will need to be added to the plugin before vera can see commands from it?
« Last Edit: August 23, 2011, 08:00:12 am by Intrepid »

Offline radarengineer

  • Sr. Member
  • ****
  • Posts: 402
  • Karma: +4/-0
@Intrepid, thank for the feedback. Sounds like there are a few bugs I need to fix! So I guess it is time for a confession. I couldn't find my box of ds10a modules until last night, so I didn't actually test that portion of the code!

Right now I don't monitor for RF commands (e.g from a palmpad) that are changing modules. This is a simple fix and I'll get that added.

Not sure about the appliance module... but I will figure it out!

As for adding a palmpad into the plugin, that is probably a good idea. I can get changes made by the palmpad to show up in the gui without adding specific support *if* the commands are targeted at a module that is programmed into vera.

However, I know some people like to have their palmpads set to house/unit codes with no modules on them. That way the commands can be picked up by their software. One way to handle this is just to add dummy module units to vera. However, maybe it would be better to actually add support for a palmpad? I'm open to suggestions on this!

Offline Intrepid

  • Hero Member
  • *****
  • Posts: 536
  • Karma: +4/-0
Quote
However, I know some people like to have their palmpads set to house/unit codes with no modules on them. That way the commands can be picked up by their software. One way to handle this is just to add dummy module units to vera. However, maybe it would be better to actually add support for a palmpad? I'm open to suggestions on this!

If you can make any RF commands be sensed, and any virtual devices be subsequently controlled, there's probably no reason to add the remote as a device in the plugin?

Palmpads, stickaswitches, keyfobs....whatever the rf remote source, if a signal is received let it control installed virtual devices.

Oh man, this thing is opening all kinds of possibilities.  Awesome job.  Thanks for your work on this!!

Offline radarengineer

  • Sr. Member
  • ****
  • Posts: 402
  • Karma: +4/-0
I just uploaded a new version of mochad and updated the link to the zip file in the installation instructions. Only the I_Mochad1.xml file changed.

I fixed three things:

1. ds10a sensors should now work (this was a dumb mistake, just missing a couple quotes in the previous code version  ::) )

2. I now monitor for RF signals for things other than motion sensors. This might need to be tweaked a little because of how X10 sends RF dim/bright commands. Only a house code is sent, not a unit code, and the last device controlled on that house code is modified. I have it pretty close, but I might need to play around with a dimmable module and a remote for a while to see if the Vera is matching the behavior.

3. Binary modules should now work

Please keep the bug reports coming! Some features I am not (yet) supporting:

1. monitoring for PL commands
2. camera control
3. arm/disarm for the x10 security devices (e.g., DS7000, SH624). This might wait until there is a request!

I also need to make the code a little more readable. Lua is very nice but I keep forgetting it has things like first class functions :)

Offline Intrepid

  • Hero Member
  • *****
  • Posts: 536
  • Karma: +4/-0
Bravo, Radar!

Appliance module now works as a binary module.  Perfect, quick control.

When I hit 'D2 ON' on my palmpad, the appliance module turns on, so PL listening is working!

DS10a works.  Perfect, quick status updates.

MS12a still works.  Perfect, quick status updates.

Amazing work.  All of the basics seem to be working perfectly!  This plugin truly opens up the entire world of X10 RF to interface with Vera!  

All those places that I may want to monitor an open/closed status but didn't want to spend $40-$50 for a z-wave switch, I'll use a DS10a.  Crawlspace, shed....even monitor my squirrel trap for those pesky tree rats that had been trying to get back into my attic.

I'll feel comfortable using outdoor eagle eye MS12a motion sensors all around the exterior perimeter.  At $3/each, this is awesome.

The most powerful function to me is the RF remotes.  I've got a box full of them, and these will make cheap/free scene controllers.  Assign a house/unit code, add to the plugin, run any vera scene.  Couldn't be simpler.

You are amazing.  Thank you so much.

edit.  nerdgasm while I sit here controlling my z-wave lamp with a palmpad.   ;D ;D ;D

« Last Edit: August 24, 2011, 07:13:29 am by Intrepid »

Offline Intrepid

  • Hero Member
  • *****
  • Posts: 536
  • Karma: +4/-0
Power cycle on mochad computer:

It seems that if power is cycled off/on on the pogo, mochad starts automatically.

But when this happens, Vera loses communication with mochad.  A reload/save button on the UI brings communication back.

Does this seem right?  Any methods to handle this situation?