tenWare Software

C# Scripting with HomeSeer Version 4

Extending HomeSeer

There are two primary ways to extend HomeSeer functionality:  plugins and scripting.  Plugins are separate programs that run in there own address space (on the HomeSeer server or on another computer) and communicate with HS using TCP and .Net Remoting.  Plugins create and manage HS Devices and provide Event processing for these Devices.

Scripts are user written code using either Visual Basic or C#.  The script statements are placed into individual text files residing in the \HomeSeer HS4\scripts\ folder.  VB script files must have a suffix of .vb and C# script files must have a suffix of .cs.  These scripts can be executed by user-created Events.  When an Event calls for HS to run a script, the source statements from the script file must be compiled, and then executed, providing the script with the object instances necesarry to access HS functionality (hs and hs4.) 

 

HomeSeer C# Implementation

HS uses a third party library CS-Script to compile C# script statements. CS-Script documentation can be found here. This site describes current versions of CS-Script, but is not totally applicable to the old 3.7.2.0 version used by HS. CS-Script in turn invokes either the CodeDom or Mono compilers provided by Microsoft, I have been unable to ascertain which because the documentation for the older versions is not available.

 

Writing C# Scripts for HS

An HS C# script is a text file with an extension of .cs located in the \HomeSeer HS4\scripts\ folder.  The script consists of single subroutine Main defined this way:

public void Main(object parm)

   {

       hs.WriteLog("Test Script","Start");

       hs.WaitSecs(5);

       hs.WriteLog("Test Script", "End");

   }

This simple example shows the exact way to define the Main routine. The C# script text file can be created by any text editor, but I recommend that you take a look at tenScripting to code and test your scripts if you intend to do any serious script development.

 

How HS Compiles and Runs a C# Script

The script that you create consists of a single routine that must be called Main as shown above. HS creates the text statements for a class called Script that contains your Main routine by adding statements that reside before your routine. The added statements consist of the class definition for Script, using statements for the system and HS libraries needed by your script, declaration of the hs and hs4 object variables, and a routine called InitHS to instantiate these objects.  HS then calls a CS-Script method to compile the newly created text statements resulting in an instance of the Script class.  It then calls the InitHS routine of Script to instantiate hs and hs4, and then calls Main to run your script.

This approach has implications to how you code your scripts.  Since you code will be included within a class definition, you would not be able to include your own using statements at the front of your script. HS will attempt to move any using statements in your code to before the Script class definition.  Any error messages you recieve in the HS log from compilation will contain line numbers from the complete text as built by HS, so the line numbers reported will always be greater than the line numbers of your script text.  The C# compiler used by HS is a fairly old version, so newer C# syntax will result in an error.  As you can see, a lot of trial and error will be needed to get started with serious C# script development.

 

External Library (dll) References

You may want to use methods from .NET libraries that are not made available to your script by HS.  There are several ways to create references to external libraries that then can be used by your script.

The preferred way (and the only way I have been able to get to work) is to add an entry to the ScriptingReferences key within the Config\settings.ini HS configuration file that tells HS to load the library and namespace specified before it calls your script.  Existing HS documentation still states that the ScriptingReferences entries are only used for VB scripts and do nothing for C# scripts, but since HS version 4.2.11, this is not longer correct. An example:

 ScriptingReferences=tenGlobalMethods;tenGlobalMethods.dll,System.Data.SQLite;bin\homeseer\System.Data.SQLite.dll

 Note:  If running HS4 as a service, there appears to be issues with default directories, and you may need to fully qualify the location of the dll file, see here.

The CS-Script documentation describes two additional ways to reference external libraries.  Explicityly using the //css_reference directive and CS-Script will also attempt to load any namespace reference in the C# using directive.  I have not been able to make these work, which might be due to the older release of CS-Script used by HS.  See here for details.

 

Tips in Converting From VB

Besides the obvious coding syntax differences, there are some things to be aware of when coding in C# for HS4 for the first time, especially if you have experience in coding scripts in VB.

C# is Case Sensitive

While VB is NOT case sensitive, C# is.  You must use the proper case when referencing HS4 and other functions.  The HS4 documentation does not always describe the proper case for some functions.  This is where tenScripting can really help in that it provides syntax prompting, including for HS4 methods and properties.

C# Requires Explicit Type Conversions

This is valid in VB:

Dim d as Double

d = hs4.GetPropertyByRef(2148, HomeSeer.PluginSdk.Devices.EProperty.Value)

 

C# must be coded like this:

double d;

d = (double)hs4.GetPropertyByRef(2148, HomeSeer.PluginSdk.Devices.EProperty.Value);

C# Requires Fully-Qualified Method References

In VB:

Dim Pair as VSPair

In C#:

HomeSeerAPI.VSVGPairs.VSPair Pair;

HS4 Method Calls Can Require Explicit Get/Set methods

The HS4 documentation describes the Methods and Properties that are available to scripts, but the calling sequence may be different for C# than VB, requiring explicit use of GET or SET methods.

In VB:

s = hs.GetDeviceByRef(2148).Location2(hs)

In C#:

s = ((Scheduler.Classes.DeviceClass)hs.GetDeviceByRef(2148)).get_Location2(hs);

You might find tenScriptAid4 helpful in constructing common C# HS4 method references.