mirror of
https://github.com/excaliburpartners/OmniLinkBridge
synced 2024-12-22 18:52:24 +00:00
1.1.5 - Update readme, fix thermostat logging interval, and cleanup code
This commit is contained in:
parent
cb24322bef
commit
336e02e8e8
|
@ -12,17 +12,17 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
public class LoggerModule : IModule
|
public class LoggerModule : IModule
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private OmniLinkII omnilink;
|
private readonly OmniLinkII omnilink;
|
||||||
private List<string> alarms = new List<string>();
|
private readonly List<string> alarms = new List<string>();
|
||||||
|
|
||||||
// mySQL Database
|
// mySQL Database
|
||||||
private OdbcConnection mysql_conn = null;
|
private OdbcConnection mysql_conn = null;
|
||||||
private DateTime mysql_retry = DateTime.MinValue;
|
private DateTime mysql_retry = DateTime.MinValue;
|
||||||
private OdbcCommand mysql_command = null;
|
private OdbcCommand mysql_command = null;
|
||||||
private Queue<string> mysql_queue = new Queue<string>();
|
private readonly Queue<string> mysql_queue = new Queue<string>();
|
||||||
private object mysql_lock = new object();
|
private readonly object mysql_lock = new object();
|
||||||
|
|
||||||
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
@ -221,18 +221,14 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
private void Omnilink_OnThermostatStatus(object sender, ThermostatStatusEventArgs e)
|
private void Omnilink_OnThermostatStatus(object sender, ThermostatStatusEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.EventTimer)
|
int.TryParse(e.Thermostat.TempText(), out int temp);
|
||||||
return;
|
int.TryParse(e.Thermostat.HeatSetpointText(), out int heat);
|
||||||
|
int.TryParse(e.Thermostat.CoolSetpointText(), out int cool);
|
||||||
int temp, heat, cool, humidity, humidify, dehumidify;
|
int.TryParse(e.Thermostat.HumidityText(), out int humidity);
|
||||||
|
int.TryParse(e.Thermostat.HumidifySetpointText(), out int humidify);
|
||||||
Int32.TryParse(e.Thermostat.TempText(), out temp);
|
int.TryParse(e.Thermostat.DehumidifySetpointText(), out int dehumidify);
|
||||||
Int32.TryParse(e.Thermostat.HeatSetpointText(), out heat);
|
|
||||||
Int32.TryParse(e.Thermostat.CoolSetpointText(), out cool);
|
|
||||||
Int32.TryParse(e.Thermostat.HumidityText(), out humidity);
|
|
||||||
Int32.TryParse(e.Thermostat.HumidifySetpointText(), out humidify);
|
|
||||||
Int32.TryParse(e.Thermostat.DehumidifySetpointText(), out dehumidify);
|
|
||||||
|
|
||||||
|
// Log all events including thermostat polling
|
||||||
DBQueue(@"
|
DBQueue(@"
|
||||||
INSERT INTO log_thermostats (timestamp, id, name,
|
INSERT INTO log_thermostats (timestamp, id, name,
|
||||||
status, temp, heat, cool,
|
status, temp, heat, cool,
|
||||||
|
@ -243,7 +239,8 @@ namespace OmniLinkBridge.Modules
|
||||||
humidity + "','" + humidify + "','" + dehumidify + "','" +
|
humidity + "','" + humidify + "','" + dehumidify + "','" +
|
||||||
e.Thermostat.ModeText() + "','" + e.Thermostat.FanModeText() + "','" + e.Thermostat.HoldStatusText() + "')");
|
e.Thermostat.ModeText() + "','" + e.Thermostat.FanModeText() + "','" + e.Thermostat.HoldStatusText() + "')");
|
||||||
|
|
||||||
if (Global.verbose_thermostat)
|
// Ignore events fired by thermostat polling
|
||||||
|
if (!e.EventTimer && Global.verbose_thermostat)
|
||||||
log.Debug("ThermostatStatus " + e.ID + " " + e.Thermostat.Name +
|
log.Debug("ThermostatStatus " + e.ID + " " + e.Thermostat.Name +
|
||||||
", Status: " + e.Thermostat.TempText() + " " + e.Thermostat.HorC_StatusText() +
|
", Status: " + e.Thermostat.TempText() + " " + e.Thermostat.HorC_StatusText() +
|
||||||
", Heat: " + e.Thermostat.HeatSetpointText() +
|
", Heat: " + e.Thermostat.HeatSetpointText() +
|
||||||
|
|
|
@ -18,14 +18,13 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
public class MQTTModule : IModule
|
public class MQTTModule : IModule
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public static DeviceRegistry MqttDeviceRegistry { get; set; }
|
public static DeviceRegistry MqttDeviceRegistry { get; set; }
|
||||||
|
|
||||||
private OmniLinkII OmniLink { get; set; }
|
private OmniLinkII OmniLink { get; set; }
|
||||||
private IManagedMqttClient MqttClient { get; set; }
|
private IManagedMqttClient MqttClient { get; set; }
|
||||||
private bool ControllerConnected { get; set; }
|
private bool ControllerConnected { get; set; }
|
||||||
|
|
||||||
private MessageProcessor MessageProcessor { get; set; }
|
private MessageProcessor MessageProcessor { get; set; }
|
||||||
|
|
||||||
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
||||||
|
@ -371,9 +370,8 @@ namespace OmniLinkBridge.Modules
|
||||||
if (!MqttClient.IsConnected)
|
if (!MqttClient.IsConnected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Ignore events fired by thermostat polling and when temperature is invalid
|
// Ignore events fired by thermostat polling
|
||||||
// An invalid temperature can occur when a Zigbee thermostat is unreachable
|
if (!e.EventTimer)
|
||||||
if (!e.EventTimer && e.Thermostat.Temp > 0)
|
|
||||||
PublishThermostatState(e.Thermostat);
|
PublishThermostatState(e.Thermostat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,16 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
public class OmniLinkII : IModule, IOmniLinkII
|
public class OmniLinkII : IModule, IOmniLinkII
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
// OmniLink Controller
|
// OmniLink Controller
|
||||||
public clsHAC Controller { get; private set; }
|
public clsHAC Controller { get; private set; }
|
||||||
private DateTime retry = DateTime.MinValue;
|
private DateTime retry = DateTime.MinValue;
|
||||||
|
|
||||||
// Thermostats
|
// Thermostats
|
||||||
private Dictionary<ushort, DateTime> tstats = new Dictionary<ushort, DateTime>();
|
private readonly Dictionary<ushort, DateTime> tstats = new Dictionary<ushort, DateTime>();
|
||||||
private System.Timers.Timer tstat_timer = new System.Timers.Timer();
|
private readonly System.Timers.Timer tstat_timer = new System.Timers.Timer();
|
||||||
private object tstat_lock = new object();
|
private readonly object tstat_lock = new object();
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
public event EventHandler<EventArgs> OnConnect;
|
public event EventHandler<EventArgs> OnConnect;
|
||||||
|
@ -382,13 +382,15 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
private void GetNextNamed(enuObjectType type, int ix)
|
private void GetNextNamed(enuObjectType type, int ix)
|
||||||
{
|
{
|
||||||
clsOL2MsgRequestProperties MSG = new clsOL2MsgRequestProperties(Controller.Connection);
|
clsOL2MsgRequestProperties MSG = new clsOL2MsgRequestProperties(Controller.Connection)
|
||||||
MSG.ObjectType = type;
|
{
|
||||||
MSG.IndexNumber = (UInt16)ix;
|
ObjectType = type,
|
||||||
MSG.RelativeDirection = 1; // next object after IndexNumber
|
IndexNumber = (UInt16)ix,
|
||||||
MSG.Filter1 = 1; // (0=Named or Unnamed, 1=Named, 2=Unnamed).
|
RelativeDirection = 1, // next object after IndexNumber
|
||||||
MSG.Filter2 = 0; // Any Area
|
Filter1 = 1, // (0=Named or Unnamed, 1=Named, 2=Unnamed).
|
||||||
MSG.Filter3 = 0; // Any Room
|
Filter2 = 0, // Any Area
|
||||||
|
Filter3 = 0 // Any Room
|
||||||
|
};
|
||||||
Controller.Connection.Send(MSG, HandleNamedPropertiesResponse);
|
Controller.Connection.Send(MSG, HandleNamedPropertiesResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,12 +726,19 @@ namespace OmniLinkBridge.Modules
|
||||||
lock (tstat_lock)
|
lock (tstat_lock)
|
||||||
{
|
{
|
||||||
Controller.Thermostats[MSG.ObjectNumber(i)].CopyExtendedStatus(MSG, i);
|
Controller.Thermostats[MSG.ObjectNumber(i)].CopyExtendedStatus(MSG, i);
|
||||||
|
|
||||||
|
// Don't fire event when invalid temperature of 0 is sometimes received
|
||||||
|
if (Controller.Thermostats[MSG.ObjectNumber(i)].Temp > 0)
|
||||||
|
{
|
||||||
OnThermostatStatus?.Invoke(this, new ThermostatStatusEventArgs()
|
OnThermostatStatus?.Invoke(this, new ThermostatStatusEventArgs()
|
||||||
{
|
{
|
||||||
ID = MSG.ObjectNumber(i),
|
ID = MSG.ObjectNumber(i),
|
||||||
Thermostat = Controller.Thermostats[MSG.ObjectNumber(i)],
|
Thermostat = Controller.Thermostats[MSG.ObjectNumber(i)],
|
||||||
EventTimer = false
|
EventTimer = false
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
else if (Global.verbose_thermostat_timer)
|
||||||
|
log.Warn("Ignoring unsolicited unknown temp for Thermostat " + Controller.Thermostats[MSG.ObjectNumber(i)].Name);
|
||||||
|
|
||||||
if (!tstats.ContainsKey(MSG.ObjectNumber(i)))
|
if (!tstats.ContainsKey(MSG.ObjectNumber(i)))
|
||||||
tstats.Add(MSG.ObjectNumber(i), DateTime.Now);
|
tstats.Add(MSG.ObjectNumber(i), DateTime.Now);
|
||||||
|
@ -809,6 +818,7 @@ namespace OmniLinkBridge.Modules
|
||||||
(Controller.Connection.ConnectionState == enuOmniLinkConnectionState.Online ||
|
(Controller.Connection.ConnectionState == enuOmniLinkConnectionState.Online ||
|
||||||
Controller.Connection.ConnectionState == enuOmniLinkConnectionState.OnlineSecure))
|
Controller.Connection.ConnectionState == enuOmniLinkConnectionState.OnlineSecure))
|
||||||
{
|
{
|
||||||
|
// Don't fire event when invalid temperature of 0 is sometimes received
|
||||||
if (Controller.Thermostats[tstat.Key].Temp > 0)
|
if (Controller.Thermostats[tstat.Key].Temp > 0)
|
||||||
{
|
{
|
||||||
OnThermostatStatus?.Invoke(this, new ThermostatStatusEventArgs()
|
OnThermostatStatus?.Invoke(this, new ThermostatStatusEventArgs()
|
||||||
|
@ -819,7 +829,7 @@ namespace OmniLinkBridge.Modules
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (Global.verbose_thermostat_timer)
|
else if (Global.verbose_thermostat_timer)
|
||||||
log.Warn("Not logging unknown temp for Thermostat " + Controller.Thermostats[tstat.Key].Name);
|
log.Warn("Ignoring unknown temp for Thermostat " + Controller.Thermostats[tstat.Key].Name);
|
||||||
}
|
}
|
||||||
else if (Global.verbose_thermostat_timer)
|
else if (Global.verbose_thermostat_timer)
|
||||||
log.Warn("Not logging out of date status for Thermostat " + Controller.Thermostats[tstat.Key].Name);
|
log.Warn("Not logging out of date status for Thermostat " + Controller.Thermostats[tstat.Key].Name);
|
||||||
|
|
|
@ -8,11 +8,11 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
public class TimeSyncModule : IModule
|
public class TimeSyncModule : IModule
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private OmniLinkII OmniLink { get; set; }
|
private OmniLinkII OmniLink { get; set; }
|
||||||
|
|
||||||
private System.Timers.Timer tsync_timer = new System.Timers.Timer();
|
private readonly System.Timers.Timer tsync_timer = new System.Timers.Timer();
|
||||||
private DateTime tsync_check = DateTime.MinValue;
|
private DateTime tsync_check = DateTime.MinValue;
|
||||||
|
|
||||||
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
private readonly AutoResetEvent trigger = new AutoResetEvent(false);
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace OmniLinkBridge
|
||||||
{
|
{
|
||||||
public class WebServiceModule : IModule
|
public class WebServiceModule : IModule
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public static OmniLinkII OmniLink { get; private set; }
|
public static OmniLinkII OmniLink { get; private set; }
|
||||||
|
|
||||||
|
|
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.1.4.0")]
|
[assembly: AssemblyVersion("1.1.5.0")]
|
||||||
[assembly: AssemblyFileVersion("1.1.4.0")]
|
[assembly: AssemblyFileVersion("1.1.5.0")]
|
||||||
|
|
|
@ -13,7 +13,7 @@ namespace OmniLinkBridge
|
||||||
{
|
{
|
||||||
public static class Settings
|
public static class Settings
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public static void LoadSettings()
|
public static void LoadSettings()
|
||||||
{
|
{
|
||||||
|
@ -60,7 +60,7 @@ namespace OmniLinkBridge
|
||||||
Global.mqtt_discovery_name_prefix = settings["mqtt_discovery_name_prefix"] ?? string.Empty;
|
Global.mqtt_discovery_name_prefix = settings["mqtt_discovery_name_prefix"] ?? string.Empty;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(Global.mqtt_discovery_name_prefix))
|
if (!string.IsNullOrEmpty(Global.mqtt_discovery_name_prefix))
|
||||||
Global.mqtt_discovery_name_prefix = Global.mqtt_discovery_name_prefix + " ";
|
Global.mqtt_discovery_name_prefix += " ";
|
||||||
|
|
||||||
Global.mqtt_discovery_ignore_zones = ValidateRange(settings, "mqtt_discovery_ignore_zones");
|
Global.mqtt_discovery_ignore_zones = ValidateRange(settings, "mqtt_discovery_ignore_zones");
|
||||||
Global.mqtt_discovery_ignore_units = ValidateRange(settings, "mqtt_discovery_ignore_units");
|
Global.mqtt_discovery_ignore_units = ValidateRange(settings, "mqtt_discovery_ignore_units");
|
||||||
|
@ -103,7 +103,7 @@ namespace OmniLinkBridge
|
||||||
.Select(s => s.Split('='))
|
.Select(s => s.Split('='))
|
||||||
.ToDictionary(a => a[0].Trim(), a => a[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
|
.ToDictionary(a => a[0].Trim(), a => a[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
|
||||||
|
|
||||||
if (!attributes.ContainsKey("id") || !Int32.TryParse(attributes["id"], out int attrib_id))
|
if (!attributes.ContainsKey("id") || !int.TryParse(attributes["id"], out int attrib_id))
|
||||||
throw new Exception("Missing or invalid id attribute");
|
throw new Exception("Missing or invalid id attribute");
|
||||||
|
|
||||||
T override_zone = new T();
|
T override_zone = new T();
|
||||||
|
@ -139,7 +139,7 @@ namespace OmniLinkBridge
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return Int32.Parse(settings[section]);
|
return int.Parse(settings[section]);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -165,7 +165,7 @@ namespace OmniLinkBridge
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int port = Int32.Parse(settings[section]);
|
int port = int.Parse(settings[section]);
|
||||||
|
|
||||||
if (port < 1 || port > 65534)
|
if (port < 1 || port > 65534)
|
||||||
throw new Exception();
|
throw new Exception();
|
||||||
|
@ -179,54 +179,6 @@ namespace OmniLinkBridge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool ValidateBool(NameValueCollection settings, string section)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Boolean.Parse(settings[section]);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
log.Error("Invalid bool specified for " + section);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IPAddress ValidateIP(NameValueCollection settings, string section)
|
|
||||||
{
|
|
||||||
if (settings[section] == "*")
|
|
||||||
return IPAddress.Any;
|
|
||||||
|
|
||||||
if (settings[section] == "")
|
|
||||||
return IPAddress.None;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return IPAddress.Parse(section);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
log.Error("Invalid IP specified for " + section);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string ValidateDirectory(NameValueCollection settings, string section)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(settings[section]))
|
|
||||||
Directory.CreateDirectory(settings[section]);
|
|
||||||
|
|
||||||
return settings[section];
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
log.Error("Invalid directory specified for " + section);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static MailAddress ValidateMailFrom(NameValueCollection settings, string section)
|
private static MailAddress ValidateMailFrom(NameValueCollection settings, string section)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace OmniLinkBridge.WebAPI
|
||||||
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
|
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
|
||||||
public class OmniLinkService : IOmniLinkService
|
public class OmniLinkService : IOmniLinkService
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
public void Subscribe(SubscribeContract contract)
|
public void Subscribe(SubscribeContract contract)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,10 +10,10 @@ namespace OmniLinkBridge.WebAPI
|
||||||
{
|
{
|
||||||
static class WebNotification
|
static class WebNotification
|
||||||
{
|
{
|
||||||
private static ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
private static List<string> subscriptions = new List<string>();
|
private static List<string> subscriptions = new List<string>();
|
||||||
private static object subscriptions_lock = new object();
|
private static readonly object subscriptions_lock = new object();
|
||||||
|
|
||||||
public static void AddSubscription(string callback)
|
public static void AddSubscription(string callback)
|
||||||
{
|
{
|
||||||
|
|
125
README.md
125
README.md
|
@ -1,25 +1,59 @@
|
||||||
# OmniLink Bridge
|
# OmniLink Bridge
|
||||||
Provides MQTT bridge, web service API, time sync, and logging for [HAI/Leviton OmniPro II controllers](https://www.leviton.com/en/products/brands/omni-security-automation). Provides integration with [Samsung SmarthThings via web service API](https://github.com/excaliburpartners/SmartThings-OmniPro) and [Home Assistant via MQTT](https://www.home-assistant.io/components/mqtt/).
|
Provides MQTT bridge, web service API, time sync, and logging for [HAI/Leviton OmniPro II controllers](https://www.leviton.com/en/products/brands/omni-security-automation). Provides integration with [Samsung SmartThings via web service API](https://github.com/excaliburpartners/SmartThings-OmniPro) and [Home Assistant via MQTT](https://www.home-assistant.io/components/mqtt/).
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
You can use docker to build an image from git or download the [binary here](http://www.excalibur-partners.com/downloads/OmniLinkBridge_1_1_4.zip).
|
You can use docker to build an image from git or download the [binary here](https://github.com/excaliburpartners/OmniLinkBridge/releases/latest/download/OmniLinkBridge.zip).
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
- [Docker](https://www.docker.com/)
|
- [Docker](https://www.docker.com/)
|
||||||
- .NET Framework 4.5.2 (or Mono equivalent)
|
- .NET Framework 4.5.2 (or Mono equivalent)
|
||||||
|
|
||||||
## Operation
|
## Operation
|
||||||
- Area, Messages, Units, and Zones are logged to mySQL when status changes
|
OmniLinkBridge is divided into the following modules
|
||||||
- Thermostats are logged to mySQL once per minute
|
|
||||||
- If no notifications are received within 4 minutes a request is issued
|
|
||||||
- After 5 minutes of no updates a warning will be logged and mySQL will not be updated
|
|
||||||
- If the temp is 0 a warning will be logged and mySQL will not be updated
|
|
||||||
- Controller time is checked and compared to the local computer time disregarding time zones
|
|
||||||
|
|
||||||
## Notifications
|
- OmniLinkII
|
||||||
- Supports email, prowl, and pushover
|
- Settings: controller_
|
||||||
|
- Maintains connection to the OmniLink controller
|
||||||
|
- Thermostats
|
||||||
|
- If no status update has been received after 4 minutes a request is issued
|
||||||
|
- A status update containing a temperature of 0 is ignored
|
||||||
|
- This can occur when a ZigBee thermostat has lost communication
|
||||||
|
- Logger
|
||||||
|
- Console output
|
||||||
|
- Settings: verbose_
|
||||||
|
- Thermostats (verbose_thermostat_timer)
|
||||||
|
- After 5 minutes of no status updates a warning will be logged
|
||||||
|
- When a current temperature of 0 is received a warning will be logged
|
||||||
|
- MySQL logging
|
||||||
|
- Settings: mysql_
|
||||||
|
- Thermostats are logged every minute and when an event is received
|
||||||
|
- Push notifications
|
||||||
|
- Settings: notify_
|
||||||
- Always sent for area alarms and critical system events
|
- Always sent for area alarms and critical system events
|
||||||
- Optionally enable for area status changes and console messages
|
- Optionally enable for area status changes and console messages
|
||||||
|
- Email
|
||||||
|
- Settings: mail_
|
||||||
|
- Prowl
|
||||||
|
- Settings: prowl_
|
||||||
|
- Pushover
|
||||||
|
- Settings: pushover_
|
||||||
|
- Time Sync
|
||||||
|
- Settings: time_
|
||||||
|
- Controller time is checked and compared to the local computer time disregarding time zones
|
||||||
|
- Web API
|
||||||
|
- Settings: webapi_
|
||||||
|
- Provides integration with [Samsung SmartThings](https://github.com/excaliburpartners/SmartThings-OmniPro)
|
||||||
|
- Allows an application to subscribe to receive POST notifications status updates are received from the OmniLinkII module
|
||||||
|
- On failure to POST to callback URL subscription is removed
|
||||||
|
- Recommended for application to send subscribe reqeusts every few minutes
|
||||||
|
- Requests to GET endpoints return status from the OmniLinkII module
|
||||||
|
- Requests to POST endpoints send commands to the OmniLinkII module
|
||||||
|
- MQTT
|
||||||
|
- Settings: mqtt_
|
||||||
|
- Maintains connection to the MQTT broker
|
||||||
|
- Publishes discovery topics for [Home Assistant](https://www.home-assistant.io/components/mqtt/) to auto configure devices
|
||||||
|
- Publishes topics for status received from the OmniLinkII module
|
||||||
|
- Subscribes to command topics and sends commands to the OmniLinkII module
|
||||||
|
|
||||||
## Docker Hub (preferred)
|
## Docker Hub (preferred)
|
||||||
1. Configure at a minimum the controller IP and encryptions keys. The web service port must be 8000.
|
1. Configure at a minimum the controller IP and encryptions keys. The web service port must be 8000.
|
||||||
|
@ -62,7 +96,7 @@ docker logs omnilink-bridge
|
||||||
## Installation Windows
|
## Installation Windows
|
||||||
1. Copy files to your desired location like C:\OmniLinkBridge
|
1. Copy files to your desired location like C:\OmniLinkBridge
|
||||||
2. Edit OmniLinkBridge.ini and define at a minimum the controller IP and encryptions keys
|
2. Edit OmniLinkBridge.ini and define at a minimum the controller IP and encryptions keys
|
||||||
3. Run OmniLinkBridge.exe to verify connectivity
|
3. Run OmniLinkBridge.exe from the command prompt to verify connectivity
|
||||||
4. Add Windows service
|
4. Add Windows service
|
||||||
```
|
```
|
||||||
sc create OmniLinkBridge binpath=C:\OmniLinkBridge\OmniLinkBridge.exe
|
sc create OmniLinkBridge binpath=C:\OmniLinkBridge\OmniLinkBridge.exe
|
||||||
|
@ -95,7 +129,6 @@ systemctl start omnilinkbridge.service
|
||||||
```
|
```
|
||||||
|
|
||||||
## MQTT
|
## MQTT
|
||||||
This module will also publish discovery topics for Home Assistant to auto configure devices.
|
|
||||||
|
|
||||||
### Areas
|
### Areas
|
||||||
```
|
```
|
||||||
|
@ -183,16 +216,69 @@ PUB omnilink/buttonX/command
|
||||||
string ON
|
string ON
|
||||||
```
|
```
|
||||||
|
|
||||||
## Web Service API
|
## Web API
|
||||||
To test the API you can use your browser to view a page or PowerShell (see below) to change a value.
|
To test the web service API you can use your browser to view a page or PowerShell (see below) to change a value.
|
||||||
|
|
||||||
- http://localhost:8000/ListUnits
|
|
||||||
- http://localhost:8000/GetUnit?id=1
|
|
||||||
|
|
||||||
```
|
```
|
||||||
Invoke-WebRequest -Uri "http://localhost:8000/SetUnit" -Method POST -ContentType "application/json" -Body (convertto-json -InputObject @{"id"=1;"value"=100}) -UseBasicParsing
|
Invoke-WebRequest -Uri "http://localhost:8000/SetUnit" -Method POST -ContentType "application/json" -Body (convertto-json -InputObject @{"id"=1;"value"=100}) -UseBasicParsing
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Subscription
|
||||||
|
```
|
||||||
|
POST /Subscribe
|
||||||
|
{ "callback": url }
|
||||||
|
Callback is a POST request with Type header added and json body identical to the related /Get
|
||||||
|
Type: area, contact, motion, water, smoke, co, temp, unit, thermostat
|
||||||
|
```
|
||||||
|
|
||||||
|
### Areas
|
||||||
|
```
|
||||||
|
GET /ListAreas
|
||||||
|
GET /GetArea?id=X
|
||||||
|
```
|
||||||
|
|
||||||
|
### Zones
|
||||||
|
```
|
||||||
|
GET /ListZonesContact
|
||||||
|
GET /ListZonesMotion
|
||||||
|
GET /ListZonesWater
|
||||||
|
GET /ListZonesSmoke
|
||||||
|
GET /ListZonesCO
|
||||||
|
GET /ListZonesTemp
|
||||||
|
GET /GetZone?id=X
|
||||||
|
```
|
||||||
|
|
||||||
|
### Units
|
||||||
|
```
|
||||||
|
GET /ListUnits
|
||||||
|
GET /GetZone?id=X
|
||||||
|
POST /SetUnit
|
||||||
|
POST /SetUnitKeypadPress
|
||||||
|
{ "id":X, "value":0-100 }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Thermostats
|
||||||
|
```
|
||||||
|
GET /ListThermostats
|
||||||
|
GET /GetThermostat?id=X
|
||||||
|
POST /SetThermostatCoolSetpoint
|
||||||
|
POST /SetThermostatHeatSetpoint
|
||||||
|
POST /SetThermostatMode
|
||||||
|
POST /SetThermostatFanMode
|
||||||
|
POST /SetThermostatHold
|
||||||
|
{ "id":X, "value": }
|
||||||
|
int mode 0=off, 1=heat, 2=cool, 3=auto, 4=emergency heat
|
||||||
|
int fanmode 0=auto, 1=on, 2=circulate
|
||||||
|
int hold 0=off, 1=on
|
||||||
|
```
|
||||||
|
|
||||||
|
### Thermostats
|
||||||
|
```
|
||||||
|
GET /ListButtons
|
||||||
|
POST /PushButton
|
||||||
|
{ "id":X, "value":1 }
|
||||||
|
```
|
||||||
|
|
||||||
## MySQL Setup
|
## MySQL Setup
|
||||||
You will want to install the MySQL Community Server, Workbench, and ODBC Connector. The Workbench software provides a graphical interface to administer the MySQL server. The OmniLink Bridge uses ODBC to communicate with the database. The MySQL ODBC Connector library is needed for Windows ODBC to communicate with MySQL.
|
You will want to install the MySQL Community Server, Workbench, and ODBC Connector. The Workbench software provides a graphical interface to administer the MySQL server. The OmniLink Bridge uses ODBC to communicate with the database. The MySQL ODBC Connector library is needed for Windows ODBC to communicate with MySQL.
|
||||||
|
|
||||||
|
@ -215,6 +301,11 @@ mysql_connection = DRIVER={MySQL};SERVER=localhost;DATABASE=OmniLinkBridge;USER=
|
||||||
```
|
```
|
||||||
|
|
||||||
## Change Log
|
## Change Log
|
||||||
|
Version 1.1.5 - 2019-12-14
|
||||||
|
- Fix SQL logging for areas, units, and thermostats
|
||||||
|
- Refactor MQTT parser and add unit tests
|
||||||
|
- Update readme, fix thermostat logging interval, and cleanup code
|
||||||
|
|
||||||
Version 1.1.4 - 2019-11-22
|
Version 1.1.4 - 2019-11-22
|
||||||
- Utilize controller temperature format
|
- Utilize controller temperature format
|
||||||
- Don't publish invalid thermostat temperatures
|
- Don't publish invalid thermostat temperatures
|
||||||
|
|
Loading…
Reference in a new issue