URC Macro Integration Guide v1.0
URC Macro Integration Guide v1.0
0
Revision History
Date Ver. Changes
06/12/2019 1.0 Initial release.
1
Table of Contents
Introduction ........................................................................................... 3
Overview ................................................................................................ 4
Device Events ..........................................................................................................................4
Commands ..............................................................................................................................4
The XML Generator Tool ........................................................................ 5
Overview.................................................................................................................................6
Creating the Events XML .........................................................................................................8
Creating the Commands XML................................................................................................16
Accelerator Setup ................................................................................. 17
Events ...................................................................................................................................18
Commands ............................................................................................................................23
Writing The Code.................................................................................. 29
Events ...................................................................................................................................30
Commands ............................................................................................................................32
Running The Demo ............................................................................... 34
2
Introduction
A great UI can be the cornerstone of a solid third-party integration. But alone, it can leave much to be desired
automation-wise. Adding Macro Integration capability to your two-way module offers the potential to transform
it into a highly dynamic and powerful automation solution. There are many different facets of automation that are
covered by URC macro integration. However, for a two-way module, there are essentially two that apply. They
are Device Events and Commands.
It is highly recommended that you understand the fundamentals of automation macro creation
in the URC Accelerator software before continuing with this guide. If you do not, or need a
refresher on this material, there are resources available on the URC Dealer Portal web site under
the Support and Training tabs.
You can find them in the Downloads section of the Two-Way Module SDK page on the Dealer Portal.
3
Overview
Device Events
A Device Event is a trackable event that occurs on a host device. The two-way module controlling that device can
then “report” that event to the URC base station’s firmware, allowing it to perform virtually any programmed URC
macro as an effect of the event triggering.
So, for example, let’s say you have a module that’s controlling a network of battery-powered window shades. You
want the customer to know well ahead of time when one of their shades is nearing depletion. So, you might solve
this by creating a device event that triggers when a shade reports a “low battery” status to the module. You can
then make use of this event tracking by integrating it into a macro that sends a URC push notification to the
customer’s phone upon the event’s occurence, alerting them of the battery status.
As you can see, being able to track virtually any change that occurs on a device and then perform anything an
Accelerator macro is capable of as a result of that change, creates a nearly unlimited potential for automation.
Commands
A Command, in the context of macro integration, is simply a query sent to a host device with the purpose of either
controlling a property of, or requesting a property value from, the device.
Let’s use shades again for an example. Say our shades module is a fully featured two-way module with a nice,
intuitive user interface. We know that it alone will provide the end user with an enjoyable experience. After all,
people love interacting with beautifully-designed UIs. But, we also know that a truly impressive and convenient
experience will require a higher level of control than that. We want to be able to provide some of that great UI
control outside of the module’s UI. This is where commands come into play. With command functionality, we can
create a macro that includes shade control. For example, we might make a macro called “Movie Time” that:
So, because we decided to implement command macro integration in our shades module, we’ve boosted the
automation capability of any URC system that utilizes it. Hopefully, once you’ve completed this guide and
familiarized yourself with the process, you will see that macro integration provides a significant increase in
capability with a relatively small amount of extra effort in implementation. Depending on your application, you
may even find that macro integration alone provides sufficient functionality. If that is the case, skipping UI
implementation may greatly reduce the total development time needed for your project.
4
The XML Generator Tool
5
Overview
For version 2.0 of the URC SDK, we’ve made some significant changes to the way device event and command
support is implemented in a module, both in the way the event data is constructed and in the way it is handled in a
module’s code. The functionality has not been modified, however. The goal of these changes was simply to make
the development process a little more streamlined and take some of the burden off the developer, while also
reducing the amount of problems that could potentially occur due to human error.
If you’ve been developing URC two-way modules since version 1.0 of the SDK, you’re probably familiar with the old
way of constructing the device event and command data. This is done by manually building an xml file, following
specific formatting rules to ensure the xml can be read successfully by the URC Accelerator software. This process
is, at the least, a little confusing and undoubtedly prone to error. So, we’ve created a wizard-like desktop tool to
assist you with the creation of the xml file.
! The XML Generator tool requires the Java Runtime Environment (JRE) to be installed on your computer.
If it isn’t, you may be prompted by the tool to download and install it.
Upon executing the program, you’ll see a title screen giving you two options: Create New XML File or
Import Existing XML File:
6
Select Create New XML File.
The Import Existing XML File option will allow you to import an xml file that you previously generated
with this tool, edit it as needed and then re-export it to back to xml.
You will be prompted to select the type of XML you want to create: Events or Commands.
7
Creating the Events XML
After selecting OK, you will be prompted to choose whether to include the DZI (Dynamic Zone Interface) attribute
in the XML. That is for modules of device type Dynamic Interface + Core. We’ll explain the need for this in more
detail later. But, for this example, we’re going to say this is for a General device type and choose “No”. You
should now see the main editing screen.
Before we delve into construction, let’s first break down what we’re seeing on-screen. First, notice how the main
editing area is broken up into two sections: Rule and it’s sub-section, Parameter:
8
A rule is analogous to an “event type” and is the main building block of the xml. A parameter is a child property of
a rule.
It is important to distinguish between an event rule and an actual event. The goal here is not to create
the actual events for your module. That is the installer’s job. The goal here is to provide the resources
needed for the installer to create events for your module in Accelerator. The rules contain these
resources.
So, what does that actually mean? Let’s say we’ve created a thermostat module. We want to give the installer the
ability to create an event in Accelerator that says:
"Trigger this macro when the indoor temperature is less than/greater than/equal to temperature XX."
So, let’s break down that verbalization. There are two key components to this rule. These key components are the
rule’s parameters.
"Trigger this macro when the indoor temperature is less than/greater than/equal to temperature XX."
Now that the composition of a rule is a bit clearer, we’re ready to apply this knowledge to effectively use the tool.
For simplicity’s sake, we’re going to create only two rules for our sample xml file. Let’s begin with the rule above
since we’ve already broken it down.
9
Step 1) Add the Rule ID and Name
A good rule of thumb is to always start with ID 0. So, we’ll add that as the ID. For the Name, we’ll call it Indoor
Temperature Event.
That’s it for the Rule info. We won’t need to touch the Rule fields again until we move on to the next rule. Don’t
click the “Add Rule” button just yet. The rule is essentially empty right now. We need to add its parameters first.
The first parameter for this rule is going to be the comparison operator. So, once again, we’ll start with ID 0 and
give the parameter a Label of Comparison Operator.
Now we need to select the Type. We have the choice of label, num or string. The comparison operator is going to
be of type string. When you select string, you’ll notice that the Value(s) field disappears and a checkbox labeled
Dropdown appears. If we leave the checkbox unchecked, the installer will be able to specify any value to use for
the comparison operator. We don’t want that for this type of parameter. We want them to choose from a pre-
defined set of acceptable comparison operators. So, we’ll check that checkbox. The Value(s) field will re-appear,
allowing us to specify the set of comparison operators we want the installer to be able to choose from. These
values will show up in Accelerator in a “dropdown” menu. Each value needs to be separated with a vertical bar “|”
in order to display properly in Accelerator. So, we’re going to add the string <|>|= to the Value(s) field. Your
screen should now look like this:
10
Click Add Param. You should see a new window pop up next to your main window. This is the Preview window:
The Preview window allows you to view a rule’s parameters, as well as the entire list of rules that you’ve added.
You can switch between viewing a rule’s parameter list and viewing the list of rules by toggling between the two
radio buttons Param View and Rule View. If you were to toggle Rule View right now, you would see a blank list
since we haven’t added our first rule yet.
11
Take a look at the column headers in Param View. Notice how they correspond to the parameter fields on the
editing screen. You may be wondering where the “min” and “max” column headers came from. Those apply only
to parameters of type num, which you’ll see soon.
Ok…We’ve got our first parameter added. The second parameter is going to be the temperature to compare the
current indoor temperature against. So, go ahead and add another parameter with the following properties:
ID 1
Label Comparison Temperature
Type num
The Value(s) field should disappear when you select num and the Min Val and Max Val fields should now be
visible. Min Val is the minimum value that Accelerator will accept as valid input for this parameter. Any integer
value may be entered in this field. A Min Val of 0 and Max Val of 100 should be more than enough of a range for
an indoor temperature. Specifying an appropriate value for Min Val and Max Val is not particularly important for
this parameter since it is simply a number to compare against and there are no negative consequences whether
the user puts a normal indoor temperature (like 70°) or not (like 1560°). The significance of having strict min/vax
values will vary depending on the parameter. The underlying goal of specifying a range though is simple: to
prevent bad user input from ever entering the module’s code.
So, here’s what your editing screen should currently look like:
Click Add Param. You should now see the new parameter in the Param View of your Preview window.
12
We’ve finished adding the essential parameters needed to make our rule useable. Let’s add one optional
parameter to serve as a description of the rule, so that it is clear to the installer what it’s for.
ID 2
Label Description
Type label
Value(s) This event will trigger when the indoor
temperature is greater than/less
than/equal to the comparison
temperature specified above.
Notice the difference between a string type parameter and a label type parameter. A string type is used
to accept input from the installer. It will appear in Accelerator as an editable textfield (or dropdown
menu). A label type is used when we want to convey info to the installer. It will appear in Accelerator as
an uneditable text field.
Our parameter info is complete and we’re now ready to add the rule. Click Add Rule. A confirmation message will
be displayed. After clicking “Yes”, you will notice that all the fields on the editing screen have been wiped clean.
You may also notice that your Preview window has switched from Param View to Rule View and that you now have
a rule in the list. Your screen should look something like this:
13
Editing and Deleting Rules & Parameters
If at any time you want to edit a rule’s Name, single-click the rule in the rule list. You will see the ID and Name
values populate on the editing screen. Simply modify the name and then click Add Rule again to re-add it. You
may also modify the rule’s ID. However, be aware that doing so will not overwrite the rule. It will create a
duplicate of the rule, except with a new ID.
To delete a rule, select it in the rule list and hit the Delete button on your keyboard.
To modify the parameters of a rule, simply double-click the rule in the rule list. The Preview window will switch
to Param View and you will see all the parameters for the selected rule. Click on a parameter and the parameter
section of the editor screen will populate with its values.
To delete a parameter, select it in the parameter list and hit the Delete button on your keyboard.
Be aware when making modifications to a rule’s parameters that, in order for them to be saved, you will need to
click Add Rule to re-add the rule after making your changes.
We’re halfway done. The second rule is going to be for an “HVAC State” event. This rule will be for tracking events
in which the operating state of the HVAC system changes (i.e. from “Off” to “Cooling”). So, we’ll start by adding
the Rule ID and Name for this new rule. The Rule ID will be 1 and the Rule Name will be HVAC State Event.
14
Param # ID Label Type Dropdown Value(s) Min Val Max Val
1 0 Comparison HVAC string true Heating|Cooling|Off N/A N/A
State
2 1 Description label N/A This event will trigger N/A N/A
when the operating
state of the HVAC is
equal to the state
specified above.
Once you’ve input the information above into the tool and added the new rule, you should see two rules in Rule
View.
We’re now ready for the final step of using the tool - Generating the xml file.
Click on the Generate XML button and then select “Yes” when prompted to proceed. A save dialog window will
pop up, allowing you to choose where in your file system you want to save the file. Notice, the “File name” field is
already pre-populated with a default: sys_DeviceEvent.xml. You may modify it if you want for test purposes or any
other reason, but it will not be valid for use in your Tcl Tool project if it has any name other than the default. A
good place to save the file would be in your project’s root directory, as that is where it ultimately needs to be
placed before generating the module’s .tcm2 file in Tcl Tool:
You now have your events xml file ready to go! You don’t need to add it anywhere, as there is already one in the
source folder for this project. But, check the one you created against it to make sure you got everything right.
15
Creating the Commands XML
The process for creating the xml for commands is almost identical to that of creating the events xml. So, we’ll keep
this brief and skip the screenshots….
For our example module, we’re going to allow the ability to issue two types of commands:
So first, on the main screen of the generator tool, select Create New XML File. Select Commands from the drop-
down menu. Select No when prompted to include the “DZI” attribute.
Next, you’re going to create two rules with the following properties:
Rule ID = 0
Rule Name = Set Heat Setpoint
Return = num
Rule ID = 1
Rule Name = Get Fan Mode
Return = string
Once you’ve added these two rules and generated the XML, you should have a sys_TwoWayCmd.xml file. Once
again, there is no need to add your file anywhere. Just check it against the pre-generated file in the source folder
for verification.
Now, before we get into the code portion of this tutorial, let’s configure the Accelerator file for the demo. This
whole process has been a bit abstract so far, so seeing how what you’ve created with the tool transfers to
Accelerator should help make things clearer.
16
Accelerator Setup
17
Events
Once you’ve imported the .tcm2 file, configure the basics of your Accelerator project. Make sure to add at least
one user interface (any interface is fine). You won’t need it for the events demo, but you will for the commands
demo.
Next, go to Step 6 and configure all of your devices. Make sure to provide a “dummy” IP address for the module
(use 0.0.0.1 for this module). Even though the module will not be connecting to an actual IP device, specifying an
IP address will be necessary for debugging later on (see section titled “Running The Demo” for details on why).
Proceed to Step 12 and click the Add Macro button. We’re going to make this a macro that will trigger when the
indoor temperature falls below 60°, so a good name will be “Indoor Temp < 60”:
18
In the Available Devices dropdown menu, you should see the Macro Integration Demo module. Select it and the
menu under Available Event should populate with the event rules we created using the tool:
Select Indoor Temperature Event. You should see the Parameters section populate with the parameter info we
specified for this event. In the dropdown menu under Comparison Operator, you will see the three operators (<,
>, =) with the default set to “<”. Leave that as-is.
19
Under Comparison Temperature, enter the value “60”.
Note the contents of the Description field. This field can only show two lines of text at at a time. To see additional
text that is cut off, you will need to scroll down inside the field. Keep this in mind when adding your descriptions in
the tool. Try to make them as brief as possible while still getting the idea across clearly.
Click “OK” once you’re done. You now have your device event macro! Except….it doesn’t do anything. We need
to add some actions to this macro.
You’ll notice that the macro appears with red text. This is to indicate that it’s empty:
To keep things simple, we’re just going to add a pair of relay commands to the macro, so that we get a convenient
audible confirmation (“Click-click”) when the macro has been triggered:
20
Your finished macro should look like this:
Ok, our first macro is done. Go ahead and create another one for the event “HVAC State = Cooling”. When you’re
done, your screen should look something like this:
21
That’s it for events setup. Next, we’ll add commands.
22
Commands
Under Step 12, select the tab Edit Special Macros. We’re going to make these universal macros, so in the drop-
down menu under Select Type of Special Macro, select Universal Macros. Click the Add Macro button, add a
macro with the name “Set Heat Setpoint to 70” and click “OK”:
Configure your command for setting the heat setpoint to 70 and click “OK” when done:
23
Ok, our first macro is done. Go ahead and create another one called “Get Fan Mode”. We’re going to utilize the
Result section this time since we’re retrieving data and want to save it. So, check the box next to Save the result:
24
25
Next, create a variable to save the result to. Make it an Ascii String and give it a default value:
Click “OK” to create the variable and close the Add Variable window. Notice the new variable in the Variable field:
Click “OK” to finish adding the command. Now, we just need a way to verify that this variable is indeed being set
by our module. So, after the command that retrieves the value, create an IF-ELSE statement that checks if
fanMode is equal to “auto” and if so, triggers a relay on/off and then resets its value back to “unknown”:
26
You’ve now finished creating your macros. Now, you just need to add a couple of buttons to the UI that will
execute the macros when pressed. So, go back to Step 10 (Edit User Interfaces) and add two macro buttons to the
UI called “Set Heat to 70” and “Get Fan Mode”:
Accelerate, and then return to Step 12. Under the Edit Macro By Room tab, select Universal Macros from the
dropdown under Connected Devices and drag the two-way commands that you created into the macro-recording
area:
27
You’ll notice that the text for the macro buttons on the left will change from red to black once you’ve added the
commands.
Ok, that’s it! We’ve finished configuring our Accelerator file for this demo. Now, before downloading it to the
base station and running it, let’s look at the backend code that’s going to make all of this actually do what it’s
supposed to…
28
Writing The Code
29
Events
Implementing event macro functionality in a module’s code is essentially the task of adding the code to evaluate
any type of event that can potentially be created for the module and then making calls to that evaluation
procedure wherever needed.
In our example, we need to be able to handle indoor temperature events and HVAC state events. So, our goal is to
write an evaluation procedure that can determine if an indoor temperature or HVAC state event’s conditions have
been met and, if they have, send a command to the base station’s firmware to execute the associated macro.
Take a look at main.tcl. This is our module’s master script. It will serve as the primary point of execution. So,
since it is the master script, it contains some preliminary setup code at the top.
Please take a moment to review this code and refer to the URC Tcl API Reference if there is anything that you’re
unclear about.
Next, inside our main namespace, you’ll see the indoorTemp and hvacState variables, which we’ll use to store
the current values of those two properties.
Since we’re not going to be communicating with an actual thermostat, our module will (very loosely) simulate a
thermostat’s changes. So, we have variable simulationRuntime to determine how long the simulation will run.
It’s set to 120000 milliseconds (2 minutes) by default, but feel free to change that if you’d like.
Moving on to procedures, we have intialize, which sets up everything necessary to start the demo and run it to
completion. Notice the line:
This is important. In this line, we’re retrieving the event data from the API and storing it locally. We’ll get to the
contents soon…
simulateTempChange and simulateHvacStateChange will randomly generate a value for the indoor
temperature and HVAC state respectively. The value will then be stored and passed to the evaluateEvent
procedure located in events.tcl, where it will be determined whether the appropriate conditions have been met to
trigger a macro. The evaluateEvent procedure is where all the real action happens…
After some intial checks to make sure the events dict is not empty and that the value of the thermostat property
being evaluated has indeed changed, we get to the core of the procedure - a foreach loop where we search
through the rules to see if the conditions for any of them have been met by the event we’re evaluating. Please
take some time now to analyze and understand exactly what is going on in this code. It will help if you can also
reference the structure of eventsDict, so that you can visualize what is being parsed. The dict is printed out
during ::main::initialize.
You will notice that if an event meets any potential conditions defined by a rule, the following code will be called:
This is what triggers the macro associated with that event. That’s all there is to it!
30
! It is important to keep in mind the effect that event evaluation can have on a module’s performance.
With regards to resource utilization (CPU/memory), this demo is very low-intensity compared to the
average real-world module. So, when implementing this functionality in your own module, it is crucial to
consider factors like:
A large module with 20 different types of events has the potential to weigh heavily on a system if this
functionality is implemented without any concern for optimization. So, while this document provides a
general evaluation method that can be used, we urge you to keep this information in mind, so that you
make it a habit to refine this method and prioritize its efficiency, rather than considering efficiency as an
after-thought or not considering it at all.
31
Commands
The purpose of the code for the Commands side of macro integration is to simply handle commands forwarded to
the module by the base station’s firmware and then perform the tasks interpreted from parsing these commands.
Open the file commands.tcl. The first thing you’ll probably notice is how simple it is. Inside the ::commands
namespace, we have a single procedure onReceiveTwoWay. This procedure will be called when the end user
invokes a macro containing a two-way command for this module.
By default, the firmware will try to call a global handler with the name ::onReceiveTwoWay. The way
we get it to call ::commands::onReceiveTwoWay instead is by utilizing the procedure
URC::Macro::Command::Wrap. From main.tcl:
When this macro invocation occurs, a dict containing the parameters of the command wil be passed in. It will be in
the format:
So, whenever you implement the onReceiveTwoWay proc (or whatever you decide to call it), your goal is to
analyze this incoming parameter data and take the appropriate action based on it. In our implementation, there
are two possible command types, Set Heat Setpoint Temperature and Get Fan Mode. We know that they have
rule IDs 0 and 1 respectively. So, we have a simple switch statement based on the rule ID.
Here is an actual sample of the incoming parameter data from the command we set up in our Accelerator file to
set the heat setpoint temperature to 70:
ruleID 0 eventID {} zoneID -1 paramDict {0 70 1 {Sets the heat setpoint temperature on the thermostat.
(Permitted Values: 50-95)}}
32
You can ignore zoneID and its value of -1. Had we made this a Dynamic Interface + Core module type and chosen
to include the DZI attribute in the XML generator tool, this parameter would have an actual value instead of -1.
You can also ignore index 1 of paramDict, which is the description. This info was simply for display in Accelerator
and we don’t need to do anything with it in the code.
Moving on to the second condition in that switch statement (when ruleID = 1) you’ll see that instead of setting a
variable in the module or sending a command to the host device, we’re simply returning the value of one of the
module’s variables: ::main::fanMode. Remember when we created a variable in Accelerator and checked that
“Save the result” box? That variable is where this returned value will get saved to.
That’s it for commands! We’ve done the work. Now, let’s enjoy the demo…
33
Running The Demo
34
Go ahead and download to your base station if you haven’t already done so. Then, get a debugging session
running in Tcl Tool, so you can view the log.
! When debugging in Tcl Tool, make sure that when you use the Restart Server feature, the Device IP
address you specify matches the IP address used for the module in Step 6 of Accelerator. In this case, it
would be 0.0.0.1. Failing to do this will result in the commands portion of the module failing. If this
module had a GUI, it would also cause that to fail when launched.
Also, be sure the specify the Events File, which is an xml file that Accelerator generates from the event
macros you create in Step 12 and then sends to the base station during the final Download step. It will be
in the path /remote/Store/data/TwoWay and its name will be a hexadecimal value, like “2.xml” for
example. You can verify the name of the file by FTPing into the base station and looking for it in
/data/TwoWay.
Since the events portion of the demo is based on our “simulation” and will only run for two minutes, we’ll give our
attention to that first. The module will continue to execute in the background once the simulation has ended, so
you can still send macro commands any time after that. So, hopefully during the simulation, you will hear your
relays “clicking” on and off at least a few times. Every time you hear that, you know an event has triggered.
Included with the source code is a sample log file that you can compare yours to.
Now, let’s move on to commands. First, press the button on your UI that is tied to the “Set Heat to 70” macro.
The main firmware will send the command data to our ::commands::onReceiveTwoWay procedure, and the
TRACE log statements within it should produce output that looks something like this:
cmdDict = ruleID 0 eventID {} zoneID -1 paramDict {0 70 1 {Sets the heat setpoint temperature on the
thermostat. (Permitted Values: 50-95)}}
ruleID = 0
paramDict = 0 70 1 {Sets the heat setpoint temperature on the thermostat. (Permitted Values: 50-95)}
heatSetpoint = 70
35
So, we’ve confirmed that works as expected. Now, try pressing the “Get Fan Mode” button on your UI. Based on
the logic in that IF-ELSE statement we created in Accelerator, you should hear the relay click every time you press
the button.
Congratulations! You’ve completed the Macro Integration guide. You should now be familiar
enough with this feature to begin adding it to your own modules. Be creative and good luck!
36