Skip to content

Instantly share code, notes, and snippets.

@oesolberg
Created December 6, 2017 09:34
Show Gist options
  • Save oesolberg/95450ea4b3807c5bfac31546d33880f2 to your computer and use it in GitHub Desktop.
Save oesolberg/95450ea4b3807c5bfac31546d33880f2 to your computer and use it in GitHub Desktop.
Homeseer device handling
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using HomeSeerAPI;
using RfLinkSeer.Common;
using RfLinkSeer.Common.Interfaces;
using Scheduler;
namespace RfLinkSeer.DeviceHandling
{
public class RfLinkDeviceHandling
{
private readonly IHSApplication _hs;
private readonly ILogging _log;
public RfLinkDeviceHandling(HomeSeerAPI.IHSApplication hs, ILogging log)
{
_hs = hs;
_log = log;
}
/// <param name="name">The name of the device</param>
/// <remarks>By Moskus and http://www.homeseer.com/support/homeseer/HS3/HS3Help/scripting_devices_deviceclass1.htm </remarks>
public virtual int CreateBasicDevice(string name, string location, string location2)
{
try
{
//Creating a brand new device, and get the actual device from the device reference
var fullName = location2 + Utility.HsNameSeparator + location + Utility.HsNameSeparator + name;
Scheduler.Classes.DeviceClass dv = (Scheduler.Classes.DeviceClass)_hs.GetDeviceByRef(_hs.NewDeviceRef(fullName));
int dvRef = dv.get_Ref(_hs);
//Setting the type to plugin device
DeviceTypeInfo_m.DeviceTypeInfo typeInfo = new DeviceTypeInfo_m.DeviceTypeInfo();
typeInfo.Device_Type = (int)DeviceTypeInfo_m.DeviceTypeInfo.eDeviceAPI.Plug_In;
dv.set_DeviceType_Set(_hs, typeInfo);
dv.set_Interface(_hs, Utility.PluginName); //Don't change this, or the device won't be associated with your plugin
dv.set_InterfaceInstance(_hs, Utility.PluginInstanceName); //Don't change this, or the device won't be associated with that particular instance
dv.set_Device_Type_String(_hs, name);
dv.set_Can_Dim(_hs, false);
//Setting the name and locations
dv.set_Name(_hs, name);
dv.set_Location(_hs, location);
dv.set_Location2(_hs, location2);
//Misc options
dv.set_Status_Support(_hs, false); //Set to True if the devices can be polled, False if not. (See PollDevice in hspi.vb)
dv.MISC_Set(_hs, Enums.dvMISC.SHOW_VALUES); //If not set, device control options will not be displayed.
dv.MISC_Set(_hs, Enums.dvMISC.NO_LOG); //As default, we don't want to Log every device value change to the Log
//Committing to the database, clear value-status-pairs and graphic-status pairs
_hs.SaveEventsDevices();
_hs.DeviceVSP_ClearAll(dvRef, true);
_hs.DeviceVGP_ClearAll(dvRef, true);
return dvRef; //Return the reference
}
catch (Exception ex)
{
throw new Exception("Error creating basic device: " + ex.Message, ex);
}
}
public virtual int CreateRootDevice(string rootDeviceName, string location, string location2)
{
try
{
//Creating a brand new device, and get the actual device from the device reference
Scheduler.Classes.DeviceClass rootDevice = (Scheduler.Classes.DeviceClass)_hs.GetDeviceByRef(CreateBasicDevice(rootDeviceName, location, location2));
rootDevice.set_Device_Type_String(_hs, rootDeviceName + Utility.HsNameSeparator + "root");
rootDevice.set_Relationship(_hs, HomeSeerAPI.Enums.eRelationship.Parent_Root);
int dvRef = rootDevice.get_Ref(_hs);
//Committing to the database, clear value-status-pairs and graphic-status pairs
_hs.SaveEventsDevices();
return dvRef; //Return the reference
}
catch (Exception ex)
{
throw new Exception("Error creating root device: " + ex.Message, ex);
}
}
public virtual int CreateChildDevice(string ChildDeviceName, string location, string location2, Scheduler.Classes.DeviceClass rootDevice)
{
try
{
//Creating a brand new device, and get the actual device from the device reference
Scheduler.Classes.DeviceClass childDevice = (Scheduler.Classes.DeviceClass)_hs.GetDeviceByRef(CreateBasicDevice(ChildDeviceName, location, location2));
childDevice.set_Device_Type_String(_hs, ChildDeviceName + Utility.HsNameSeparator+"child");
childDevice.set_Relationship(_hs, HomeSeerAPI.Enums.eRelationship.Child);
int dvRef = childDevice.get_Ref(_hs);
rootDevice.AssociatedDevice_Add(_hs, dvRef); //Then associated that child reference with the root.
//Committing to the database, clear value-status-pairs and graphic-status pairs
_hs.SaveEventsDevices();
return dvRef; //Return the reference
}
catch (Exception ex)
{
throw new Exception("Error creating child device: " + ex.Message, ex);
}
}
public virtual int GetDeviceId(string name, string location, string location2)
{
string fullName;
if (String.IsNullOrEmpty(location2))
{
fullName = location + " " + name;
}
else
{
fullName = location2 + " " + location + " " + name;
}
var devices = GetHomeseerDevices();
var foundDevices = devices.Where(x => x.get_Device_Type_String(_hs).Contains(name)).ToList();
if (foundDevices.Any())
{
//foreach (var dev in foundDevices)
//{
// _hs.SetDeviceValueByRef(dev.get_Ref(_hs), 999, true);
// _hs.SetDeviceString(dev.get_Ref(_hs), $"Last random value: {DateTime.Now.Second}", false);
//}
var rootDevice = devices.FirstOrDefault(x => x.get_Device_Type_String(_hs).Contains(name) && x.get_Device_Type_String(_hs).Contains("root"));
if (rootDevice != null) return rootDevice.get_Ref(_hs);
}
//int dvRef = _hs.GetDeviceRefByName(name);
return -1;
}
private List<Scheduler.Classes.DeviceClass> GetHomeseerDevices()
{
var deviceList = new List<Scheduler.Classes.DeviceClass>();
var deviceEnumerator = (Scheduler.Classes.clsDeviceEnumeration)_hs.GetDeviceEnumerator();
while (!deviceEnumerator.Finished)
{
var foundDevice = deviceEnumerator.GetNext();
deviceList.Add(foundDevice);
}
//== Where d.Interface(hs) = Me.Name
return deviceList.Where(x => x.get_Interface(_hs) == Utility.PluginName).ToList();
}
public virtual bool DeviceExists(string name, string location, string location2)
{
if (GetDeviceId(name, location, location2) > 0) return true;
return false;
}
public List<Scheduler.Classes.DeviceClass> GetChildrenByHomeseerRefId(int refId)
{
var rootDevice = (Scheduler.Classes.DeviceClass)_hs.GetDeviceByRef(refId);
if (rootDevice.get_AssociatedDevices_Count(_hs) < 1) return null;
var childIds = rootDevice.get_AssociatedDevices(_hs);
var childList = new List<Scheduler.Classes.DeviceClass>();
foreach (var childId in childIds)
{
childList.Add((Scheduler.Classes.DeviceClass)_hs.GetDeviceByRef(childId));
}
return childList;
}
public Scheduler.Classes.DeviceClass GetDeviceByRefId(int refId)
{
var foundDevice = (Scheduler.Classes.DeviceClass)_hs.GetDeviceByRef(refId);
return foundDevice;
}
public List<object> GetAllUnitsFromHomeseer()
{
var devicesInHomeseerList = GetHomeseerDevices();
if (devicesInHomeseerList != null && devicesInHomeseerList.Any())
{
foreach (var deviceClass in devicesInHomeseerList)
{
Console.WriteLine($"found one {deviceClass.get_Address(_hs)}");
}
}
return null;
}
public void UpdateOrAddUnitInHomeseer(ParsedRfLinkData rfLinkUnit)
{
//Check if the unit already exists
var unitId = GetUnitId(rfLinkUnit.UnitId, Utility.PluginName, Utility.PluginName);
if (unitId > 0)
{
UpdateHomeseerWithUnitData(rfLinkUnit, unitId);
}
//else
//{
// CreateUnitInHomeseer(rfLinkUnit);
//}
}
private int GetUnitId(string name, string location, string location2)
{
return GetDeviceId(name, location, location2);
}
private void UpdateHomeseerWithUnitData(ParsedRfLinkData linkUnit, int refId)
{
var rootDevice = GetDeviceByRefId(refId);
var children = GetChildrenByHomeseerRefId(refId);
if (children != null)
{
//update all subitems
foreach (var rfLinkDataInfo in linkUnit.DataInfoList)
{
var deviceToUpdate = children.FirstOrDefault(x => x.get_Device_Type_String(_hs).Contains($"{linkUnit.UnitId} {rfLinkDataInfo.DataType}"));
if (deviceToUpdate != null)
{
UpdateHomeSeerDevice(rfLinkDataInfo, deviceToUpdate);
}
}
//Check if the root value should be updated
}
var rootData = linkUnit.DataInfoList.FirstOrDefault(x => rootDevice.get_Device_Type_String(_hs).Contains(x.DataType));
if (rootData != null)
{
UpdateHomeSeerDevice(rootData, rootDevice);
}
}
private void UpdateHomeSeerDevice(RfLinkBaseDataInfo rfLinkDataInfo, Scheduler.Classes.DeviceClass deviceToUpdate)
{
_hs.SetDeviceValueByRef(deviceToUpdate.get_Ref(_hs), rfLinkDataInfo.RfValue, true);
_hs.SetDeviceString(deviceToUpdate.get_Ref(_hs), $"{rfLinkDataInfo.DataType}: {rfLinkDataInfo.RfValue}", false);
}
public void CreateNewDevice(ParsedRfLinkData rfUnit)
{
var rootTuple = CreateRootDevice(rfUnit);
if (rootTuple == null) return;
var root = (Scheduler.Classes.DeviceClass)_hs.GetDeviceByRef(rootTuple.Item2);
foreach (var dataInfo in rfUnit.DataInfoList)
{
if (dataInfo.DataType != rootTuple.Item1)
{
var childUnitDeviceId = CreateChildDevice($"{rfUnit.UnitId} {dataInfo.DataType}", Utility.PluginName, Utility.PluginName, root);
root.AssociatedDevice_Add(_hs, childUnitDeviceId);
}
}
}
private Tuple<string, int> CreateRootDevice(ParsedRfLinkData rfLinkUnit)
{
var rootDevice = rfLinkUnit.DataInfoList.FirstOrDefault(x => x.DataType == "TEMP");
if (rootDevice == null) rootDevice = rfLinkUnit.DataInfoList.FirstOrDefault();
//Return null if the unit already exists
if (DeviceExists($"{rfLinkUnit.UnitId} {rootDevice.DataType}", Utility.PluginName, Utility.PluginName))
{
_log.LogDebug($"Unit already exists: '{rfLinkUnit.UnitId} {rootDevice.DataType}' ");
return null;
}
var rootId = CreateRootDevice($"{rfLinkUnit.UnitId};{rootDevice.DataType}", Utility.PluginName, Utility.PluginName);
return new Tuple<string, int>(rootDevice.DataType, rootId);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment