Skip to content

Commit

Permalink
Merge pull request hollie#587 from jonwhitear/refactor_cbus
Browse files Browse the repository at this point in the history
Refactor Clipsal CBus support
  • Loading branch information
hollie committed Apr 14, 2016
2 parents 41d9841 + 5abc6d0 commit b2273ad
Show file tree
Hide file tree
Showing 9 changed files with 1,935 additions and 4 deletions.
13 changes: 13 additions & 0 deletions code/examples/cbus.mht
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# This file is an example MHT file for the Clipsal CBus module, providing
# just a definition of the CGate interface. When MisterHouse runs with a valid
# CGate definition, but no other CBus objects defined, it will query the
# CBus network for known objects and units, and write a corresponding
# MHT file including their definitions.

Format = A

#TYPE, Address, Name, GroupList, Other

CBUS_CGATE, CGATE


41 changes: 41 additions & 0 deletions code/examples/cbus.mht.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This file is an example MHT file for the Clipsal CBus module.
# Note that you should generate your own by defining only the
# CGate object, and letting MisterHouse generate the others. This
# example is provided purely to show the format.

Format = A

#TYPE, Address, Name, GroupList, Other

CBUS_CGATE, CGATE

# CBus trigger group addresses.

CBUS_TRIGGER, //HOME/254/202/1, Kitchen_Trigger_Group, All_CBus, Kitchen Trigger Group
CBUS_TRIGGER, //HOME/254/202/2, Bed_2_Fan_Speed, All_CBus|Bed_2, Bed 2 Fan Speed
CBUS_TRIGGER, //HOME/254/202/4, Bed_3_Fan_Speed, All_CBus|Bed_3, Bed 3 Fan Speed
CBUS_TRIGGER, //HOME/254/202/5, Master_Bed_Fan_Speed, All_CBus|Master_Bed, Master Bed Fan Speed

# CBus "lighting" group addresses.

CBUS_GROUP, //HOME/254/56/0, Study_Light, All_CBus|Study, Study Light
CBUS_GROUP, //HOME/254/56/1, Front_Entrance_Light, All_CBus|Lounge|Stairway, Front Entrance Light
CBUS_GROUP, //HOME/254/56/2, Outside_Front_Lights, All_CBus|Outside, Outside Front Lights
CBUS_GROUP, //HOME/254/56/3, Kitchen_Downlights, All_CBus|Kitchen, Kitchen Downlights
CBUS_GROUP, //HOME/254/56/4, Master_Bed_Fan, All_CBus|Master_Bed, Master Bed Fan
CBUS_GROUP, //HOME/254/56/5, Downstairs_Hallway_Spotlight, All_CBus|Kitchen|Lounge, Downstairs Hallway Spotlight
CBUS_GROUP, //HOME/254/56/6, Downstairs_Bathroom_Heatlamp_1, All_CBus|Downstairs_Bathroom, Downstairs Bathroom Heatlamp 1
CBUS_GROUP, //HOME/254/56/7, Downstairs_Bathroom_Heatlamp_2, All_CBus|Downstairs_Bathroom, Downstairs Bathroom Heatlamp 2
CBUS_GROUP, //HOME/254/56/8, Downstairs_Bathroom_Fan, All_CBus|Downstairs_Bathroom, Downstairs Bathroom Fan
CBUS_GROUP, //HOME/254/56/9, Guest_Bedroom_Cupboard_Light, All_CBus|Guest_Bedroom, Guest Bedroom Cupboard Light

# CBus Unit addresses.

CBUS_UNIT, 0, USB_PC_Interface,
CBUS_UNIT, 3, Downstairs_Relay_1,
CBUS_UNIT, 4, Upstairs_Relay_1,
CBUS_UNIT, 5, Upstairs_Dimmer_1,
CBUS_UNIT, 6, Upstairs_Hallway_Sensor,
CBUS_UNIT, 7, Bed_3_Switch,
CBUS_UNIT, 8, Bed_2_Switch,
CBUS_UNIT, 9, Master_Bed_Switch,
9 changes: 9 additions & 0 deletions code/public/cbus.pl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
# Copyright 2002: Richard Morgan omegaATbigpondDOTnetDOT.au
# Copyright 2008: Andrew McCallum, Mandoon Technologies andyATmandoonDOTcomDOTau
#
# IMPORTANT NOTICE - Clipsal CBus support is now provided by Clipsal_CBus.pm
#
#
# $Id$
#
# Ensure XML::Simple is installed:
Expand Down Expand Up @@ -98,6 +101,10 @@
# V3.0.3 2013-11-28
# Test debug flag for logging statements.
#
# V4.0 2016-03-25
# Refactor cbus.pl to make CBus support more MisterHouse "native".
# See lib/Clipsal_CBus.pm for more information.
#
# How Cgate integrates with MH
#
# All Cbus objects are defined in a standard XML file (cbus.xml), this file is
Expand Down Expand Up @@ -175,6 +182,8 @@

use XML::Simple qw(:strict);

print_log "IMPORTANT NOTICE - Clipsal CBus support is now provided by Clipsal_CBus.pm"

#
# Define Defaults
#
Expand Down
295 changes: 295 additions & 0 deletions lib/Clipsal_CBus.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@

=head1 B<Clipsal CBus>
=head2 SYNOPSIS
Clipsal_CBus.pm - support for Clipsal CBus.
=head2 DESCRIPTION
This module adds support for Clipsal CBus automation systems, and is a refactor of the original cbus.pl code by Richard Morgan and Andrew McCallum.
******* IMPORTANT *******
***
*** You must change the C-Gate configuration files found under the 'config' directory.
***
*** In C-GateConfig.txt: Change global-event-level from 5 to 7, the new line will be:
*** "global-event-level=7"
***
*** In access.txt: Add a new line with your subnet,
*** eg. if your IP address is 192.168.72.42, then add the following line:
*** "interface 192.168.72.255 Program"
***
******* IMPORTANT *******
=head3 How CGate integrates with MH
All CBus objects (i.e. the CGate interface, groups and units) are defined in a standard mht
file. Misterhouse creates objects from the mht file at $Reload, and subsequently creates corresponding voice command
objects on the next $Reload. As the MH obects are created, their details (e.g. address, name) are added
to a hash oh hashes (one each for Groups and Units) which is used to map a received CBus message back to an MH object.
On $Relaod, this module checks to see if there is a hash of group objects. If not, presumablt we haven't defined any group objects in
mht file, so we walk the tree of objects in CBus, and output to results to a generated mht file. So, all that's needed to get going is
to:
1) Create an mht file with just a CGate object defined. There is an example in the code directory.
2) Define the CBus settings in the ini file (see below)
3) Run MH to generate an mht file (typically called cbus.mht.generated)
4) Rename the generated mht file to make it valid (e.g. cbus.mht)
5) Edit the mht file as required, e.g. to add group objects to MH groups
6) reload
7) Enjoy (and report bugs)
The $object_vs are all voice commands, and in this version they are NOT used to control
a Cbus device from the web. Each CBus group object has it's own set() method which
ensures that any actions are reflected both in MH and on the CBus. Therefore, any changes to CBus are reflected
in the web interface in real time.
Each $v_object is tied to its respective $object. In program control (testing the state of an $object, or setting a $object) are all
performed against the $object, although you can set the $v_object, its state will not
reflect any updates from the actual CBus.
Remember, the CBus is interactive, it can receive as well as issue commands.
So, you should always use the $object in your code, as it has it's own set() method. Notice how the last 'set_by'
directive was also passed, this is to ensure that we do not create endless message loops.
When the set() sub is called the actual CBus device is set to that state
assuming it was not the CBus that actually initiated this set in the first place. For example, in user code,
you might use something like this:-
if (time_now "$Time_Sunset") {
speak "I just turned the entry light on at $Time_Now";
$Front_Entrance_Light->set('on','user code');
}
CGate itself repeats all commands received back to MH via the CBus monitor. Therefore MH listens for these
commands and then sets the appropriate $object, but this is ignored if MH was in fact the source of the set.
When MH starts up, the cbus code will automatically attempt to sync MH to the current
state of CGate. CGate of course, will reflect the physical state of the CBus network.
When the sync is complete, the $CBus_Sync will be set ON.
mh.private.ini Settings
===============
Category = CBus
cbus_project_name = CARLYLE
cgate_mon_address = 192.168.1.180:20024
cgate_talk_address = 192.168.1.180:20023
cbus_dat_file = cbus.xml #deprecated from original cbus.pl code
cbus_mht_file = cbus.mht.generated
cbus_category_prefix = cbus_ #deprecated from original cbus.pl code
cbus_ramp_speed = 0
=cut

package Clipsal_CBus;

use strict;

%Clipsal_CBus::Groups = ();
%Clipsal_CBus::Units = ();
$Clipsal_CBus::Command_Counter = 0;
$Clipsal_CBus::Command_Counter_Max = 100;

$Clipsal_CBus::Talker =
new Socket_Item( undef, undef, $::config_parms{cgate_talk_address} );
$Clipsal_CBus::Monitor =
new Socket_Item( undef, undef, $::config_parms{cgate_mon_address} );

$Clipsal_CBus::Talker_last_sent = "N/A";

=head2 FUNCTIONS
=over
=item C<debug ( $message, $level )>
Provides a standard logging function for the CBus packages.
=cut

#log levels
my $warn = 1;
my $notice = 2;
my $info = 3;
my $debug = 4;
my $trace = 5;

&::print_log("[Clipsal CBus] CBus logging at level $::Debug{cbus}");

sub debug {
my ( $self, $message, $level ) = @_;
$level = $info if $level eq '';
my $line = '';
my @caller = caller(0);
if ( $::Debug{cbus} >= $level || $level == 0 ) {
$line = " at line " . $caller[2]
if $::Debug{cbus} >= $trace;
&::print_log( "[" . $caller[0] . "] " . $message . $line );
}
}

=item C<generate_voice_commands ()>
Generates voice commands correspnding to the CBus group objects. When a new CGate object is instantiated, it
adds a post reload hook into &main to run this function.
=cut

sub generate_voice_commands {

&::print_log(
"[Clipsal CBus] Generating Voice commands for all CBus group objects");

my $object_string;
for my $object (&main::list_all_objects) {
next unless ref $object;
next unless $object->isa('Clipsal_CBus::Group');

#get object name to use as part of variable in voice command
my $object_name = $object->get_object_name;
my $object_name_v = $object_name . '_v';
$object_string .= "use vars '${object_name}_v';\n";
my $command = $object->{label};

#Get list of all voice commands from the object
my $voice_cmds = $object->get_voice_cmds();

#Initialize the voice command with all of the possible device commands
$object_string .= "$object_name_v = new Voice_Cmd '$command ["
. join( ",", sort keys %$voice_cmds ) . "]';\n";

#Tie the proper routine to each voice command
foreach ( keys %$voice_cmds ) {
$object_string .=
"$object_name_v -> tie_event('"
. $voice_cmds->{$_}
. "', '$_');\n\n";
}

#Add this object to the list of CBus Voice Commands on the Web Interface
$object_string .= ::store_object_data(
$object_name_v, 'Voice_Cmd',
'Clipsal CBus', 'Clipsal_CBus_commands'
);
}

#Evaluate the resulting object generating string
package main;

eval $object_string;
print_log("Error in cbus_item_commands: $@\n") if $@;

use vars '$CBus_Talker_v';
$CBus_Talker_v = new Voice_Cmd("cbus talker [Status,Scan]");
&main::register_object_by_name( '$CBus_Talker_v', $CBus_Talker_v );
$CBus_Talker_v->{category} = "Clipsal CBus";
$CBus_Talker_v->{filename} = "Clipsal_CBus_commands";
$CBus_Talker_v->{object_name} = '$CBus_Talker_v';

use vars '$CBus_Monitor_v';
$CBus_Monitor_v = new Voice_Cmd("cbus monitor [Status]");
&main::register_object_by_name( '$CBus_Monitor_v', $CBus_Monitor_v );
$CBus_Monitor_v->{category} = "Clipsal CBus";
$CBus_Monitor_v->{filename} = "Clipsal_CBus_commands";
$CBus_Monitor_v->{object_name} = '$CBus_Monitor_v';

package Clipsal_CBus;
}

=head1 AUTHOR
Richard Morgan, omegaATbigpondDOTnetDOTau
Andrew McCallum, Mandoon Technologies, andyATmandoonDOTcomDOTau
Jon Whitear, jonATwhitearDOTorg
=head1 VERSION HOSTORY
03-12-2001
Modified to support c-gate 1.5
23-06-2002
Monitor: Source name now works, and shows 'MH' is source 0
05-07-2002
Modified for cbus_dat.csv input file support
Added groups and set_info support
06-07-2002
Minor changes to support new cbus_builder
Modified to support global %cbus_data hash
removed make_cbus_file(), replaced with cbus_builder.pl
11-07-2002
Added announce flag to cbus_dat.csv, and conditional speak flag $announce
19-09-2002
Fixed bug in cbus_set() that prevented dimming numeric % set values
being accepted. Dimming now works.
21-09-2002
Modified cbus_groups and cbus_catagories to read from input file
rather than hard coded
Put in config item cbus_category_prefix
Comments in input file now allowed
Fixed some other minor things
22-09-2002 V2.0
Collapsed cbus_talker.pl, cbus_builder.pl and cbus_monitor.pl
into one new file, cbus.pl. Now issued as V2.0.
V2.1 Fixed up some menu uglies.
Improved coding in monitor loop
Fixed up code labels, docs etc
V2.2 Changed all speak() calls to say 'C-Bus' rather than 'CBus', so the diction is correct
V2.2.1 Fixed minor bug in cbus monitor start voice command
V2.2.2 Implemented;
oneshot device type
cbus_oneshot_log config param
V2.2.3 Made the dump_cbus_data format pretty HTML tables
V3.0 2008-02-04
Fixed to work with C-Gate Version: v2.6.1 (build 2236)
Latest version as of June 2008
Now reports the name of the source unit that modified a group level.
Added ability to scan CGate for groups and output to config file.
*** Configuration only requires running Builder to scan cgate and
*** build XML file, then commanding MH to "reload code". Job Done.
*** Customisation if wanted can be done through the config file.
Changed config file to XML format.
Builder command auto scans CGate if no config file exists.
Fixed interpretation of dimming commands.
PROD is the default state. In PROD, no option to stop comms.
Changed DEV to DEBUG for commonality.
Monitor and Talker attempt to always run unless in DEBUG state.
V3.0.1 2013-11-22
Fixed to work with C-Gate Version: v2.9.7 (build 2569), which returns
cbus addresses in the form NETWORK/APPLICATION/GROUP rather than
//PROJECT/NETWORK/APPLICATION/GROUP.
Add logging to aid debugging cbus_builder
Contributed by Jon Whitear <jonATwhitearDOTorg>
V3.0.2 2013-11-25
Add support for both formats of return code, i.e. NETWORK/APPLICATION/GROUP
and //PROJECT/NETWORK/APPLICATION/GROUP.
V3.0.3 2013-11-28
Test debug flag for logging statements.
V4.0 2016-03-25
Refactor cbus.pl into Clipsal_CBus.pm, CGate.pm, Group.pm, and Unit.pm, and
make CBus support more MisterHouse "native".
=head1 LICENSE
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
=cut

1;
Loading

0 comments on commit b2273ad

Please sign in to comment.