mirror of
https://github.com/excaliburpartners/OmniLinkBridge
synced 2024-12-22 18:52:24 +00:00
1.1.14 - Improve MQTT unit, output and flag capabilities
This commit is contained in:
parent
a016e1cd64
commit
495ce74149
|
@ -1,5 +1,4 @@
|
||||||
using OmniLinkBridge.MQTT;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
@ -24,39 +23,6 @@ namespace OmniLinkBridge
|
||||||
{
|
{
|
||||||
return (b & (1 << pos)) != 0;
|
return (b & (1 << pos)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AreaCommandCode ToCommandCode(this string payload, bool supportValidate = false)
|
|
||||||
{
|
|
||||||
string[] payloads = payload.Split(',');
|
|
||||||
int code = 0;
|
|
||||||
|
|
||||||
AreaCommandCode ret = new AreaCommandCode()
|
|
||||||
{
|
|
||||||
Command = payloads[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
if (payload.Length == 1)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if (payloads.Length == 2)
|
|
||||||
{
|
|
||||||
ret.Success = int.TryParse(payloads[1], out code);
|
|
||||||
}
|
|
||||||
else if (supportValidate && payloads.Length == 3)
|
|
||||||
{
|
|
||||||
if (string.Compare(payloads[1], "validate", true) == 0)
|
|
||||||
{
|
|
||||||
ret.Validate = true;
|
|
||||||
ret.Success = int.TryParse(payloads[2], out code);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret.Success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.Code = code;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string ToSpaceTitleCase(this string phrase)
|
public static string ToSpaceTitleCase(this string phrase)
|
||||||
{
|
{
|
||||||
return Regex.Replace(phrase, "(\\B[A-Z])", " $1");
|
return Regex.Replace(phrase, "(\\B[A-Z])", " $1");
|
||||||
|
|
|
@ -55,6 +55,7 @@ namespace OmniLinkBridge
|
||||||
public static HashSet<int> mqtt_discovery_ignore_units;
|
public static HashSet<int> mqtt_discovery_ignore_units;
|
||||||
public static HashSet<int> mqtt_discovery_area_code_required;
|
public static HashSet<int> mqtt_discovery_area_code_required;
|
||||||
public static ConcurrentDictionary<int, MQTT.OverrideZone> mqtt_discovery_override_zone;
|
public static ConcurrentDictionary<int, MQTT.OverrideZone> mqtt_discovery_override_zone;
|
||||||
|
public static ConcurrentDictionary<int, MQTT.OverrideUnit> mqtt_discovery_override_unit;
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
public static bool notify_area;
|
public static bool notify_area;
|
||||||
|
|
65
OmniLinkBridge/MQTT/Extensions.cs
Normal file
65
OmniLinkBridge/MQTT/Extensions.cs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
using HAI_Shared;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace OmniLinkBridge.MQTT
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static AreaCommandCode ToCommandCode(this string payload, bool supportValidate = false)
|
||||||
|
{
|
||||||
|
string[] payloads = payload.Split(',');
|
||||||
|
int code = 0;
|
||||||
|
|
||||||
|
AreaCommandCode ret = new AreaCommandCode()
|
||||||
|
{
|
||||||
|
Command = payloads[0]
|
||||||
|
};
|
||||||
|
|
||||||
|
if (payload.Length == 1)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (payloads.Length == 2)
|
||||||
|
{
|
||||||
|
ret.Success = int.TryParse(payloads[1], out code);
|
||||||
|
}
|
||||||
|
else if (supportValidate && payloads.Length == 3)
|
||||||
|
{
|
||||||
|
if (string.Compare(payloads[1], "validate", true) == 0)
|
||||||
|
{
|
||||||
|
ret.Validate = true;
|
||||||
|
ret.Success = int.TryParse(payloads[2], out code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret.Success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.Code = code;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnitType ToUnitType(this clsUnit unit)
|
||||||
|
{
|
||||||
|
Global.mqtt_discovery_override_unit.TryGetValue(unit.Number, out OverrideUnit override_unit);
|
||||||
|
|
||||||
|
if (unit.Type == enuOL2UnitType.Output)
|
||||||
|
return UnitType.@switch;
|
||||||
|
|
||||||
|
if (unit.Type == enuOL2UnitType.Flag)
|
||||||
|
{
|
||||||
|
if (override_unit != null && override_unit.type == UnitType.number)
|
||||||
|
return UnitType.number;
|
||||||
|
|
||||||
|
return UnitType.@switch;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (override_unit != null && override_unit.type == UnitType.@switch)
|
||||||
|
return UnitType.@switch;
|
||||||
|
|
||||||
|
return UnitType.light;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class Alarm : Device
|
public class Alarm : Device
|
||||||
{
|
{
|
|
@ -1,7 +1,7 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class BinarySensor : Device
|
public class BinarySensor : Device
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class Climate : Device
|
public class Climate : Device
|
||||||
{
|
{
|
|
@ -3,7 +3,7 @@ using Newtonsoft.Json.Converters;
|
||||||
using OmniLinkBridge.Modules;
|
using OmniLinkBridge.Modules;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class Device
|
public class Device
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class DeviceRegistry
|
public class DeviceRegistry
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class Light : Device
|
public class Light : Device
|
||||||
{
|
{
|
18
OmniLinkBridge/MQTT/HomeAssistant/Number.cs
Normal file
18
OmniLinkBridge/MQTT/HomeAssistant/Number.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
|
{
|
||||||
|
public class Number : Device
|
||||||
|
{
|
||||||
|
public string command_topic { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public string icon { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public int? min { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||||
|
public int? max { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Converters;
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class Sensor : Device
|
public class Sensor : Device
|
||||||
{
|
{
|
|
@ -1,6 +1,6 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.HomeAssistant
|
||||||
{
|
{
|
||||||
public class Switch : Device
|
public class Switch : Device
|
||||||
{
|
{
|
|
@ -1,6 +1,8 @@
|
||||||
using HAI_Shared;
|
using HAI_Shared;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using OmniLinkBridge.MQTT.HomeAssistant;
|
||||||
|
using OmniLinkBridge.MQTT.Parser;
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT
|
||||||
{
|
{
|
||||||
|
@ -399,6 +401,20 @@ namespace OmniLinkBridge.MQTT
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Number ToConfigNumber(this clsUnit unit)
|
||||||
|
{
|
||||||
|
Number ret = new Number
|
||||||
|
{
|
||||||
|
unique_id = $"{Global.mqtt_prefix}unit{unit.Number}number",
|
||||||
|
name = Global.mqtt_discovery_name_prefix + unit.Name,
|
||||||
|
state_topic = unit.ToTopic(Topic.flag_state),
|
||||||
|
command_topic = unit.ToTopic(Topic.flag_command),
|
||||||
|
min = 0,
|
||||||
|
max = 255
|
||||||
|
};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public static string ToState(this clsUnit unit)
|
public static string ToState(this clsUnit unit)
|
||||||
{
|
{
|
||||||
return unit.Status == 0 || unit.Status == 100 ? UnitCommands.OFF.ToString() : UnitCommands.ON.ToString();
|
return unit.Status == 0 || unit.Status == 100 ? UnitCommands.OFF.ToString() : UnitCommands.ON.ToString();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using HAI_Shared;
|
using HAI_Shared;
|
||||||
|
using OmniLinkBridge.MQTT.Parser;
|
||||||
using OmniLinkBridge.OmniLink;
|
using OmniLinkBridge.OmniLink;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
using System;
|
||||||
|
@ -167,10 +168,16 @@ namespace OmniLinkBridge.MQTT
|
||||||
OmniLink.SendCommand(UnitMapping[cmd], 0, (ushort)unit.Number);
|
OmniLink.SendCommand(UnitMapping[cmd], 0, (ushort)unit.Number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (command == Topic.brightness_command && int.TryParse(payload, out int unitValue))
|
else if (unit.Type == enuOL2UnitType.Flag &&
|
||||||
|
command == Topic.flag_command && int.TryParse(payload, out int flagValue))
|
||||||
|
{
|
||||||
|
log.Debug("SetUnit: {id} to {value}", unit.Number, payload);
|
||||||
|
OmniLink.SendCommand(enuUnitCommand.Set, BitConverter.GetBytes(flagValue)[0], (ushort)unit.Number);
|
||||||
|
}
|
||||||
|
else if (unit.Type != enuOL2UnitType.Output &&
|
||||||
|
command == Topic.brightness_command && int.TryParse(payload, out int unitValue))
|
||||||
{
|
{
|
||||||
log.Debug("SetUnit: {id} to {value}%", unit.Number, payload);
|
log.Debug("SetUnit: {id} to {value}%", unit.Number, payload);
|
||||||
|
|
||||||
OmniLink.SendCommand(enuUnitCommand.Level, BitConverter.GetBytes(unitValue)[0], (ushort)unit.Number);
|
OmniLink.SendCommand(enuUnitCommand.Level, BitConverter.GetBytes(unitValue)[0], (ushort)unit.Number);
|
||||||
|
|
||||||
// Force status change instead of waiting on controller to update
|
// Force status change instead of waiting on controller to update
|
||||||
|
@ -178,10 +185,10 @@ namespace OmniLinkBridge.MQTT
|
||||||
// which will cause light to go to 100% brightness
|
// which will cause light to go to 100% brightness
|
||||||
unit.Status = (byte)(100 + unitValue);
|
unit.Status = (byte)(100 + unitValue);
|
||||||
}
|
}
|
||||||
else if (command == Topic.scene_command && char.TryParse(payload, out char scene))
|
else if (unit.Type != enuOL2UnitType.Output &&
|
||||||
|
command == Topic.scene_command && char.TryParse(payload, out char scene))
|
||||||
{
|
{
|
||||||
log.Debug("SetUnit: {id} to {value}", unit.Number, payload);
|
log.Debug("SetUnit: {id} to {value}", unit.Number, payload);
|
||||||
|
|
||||||
OmniLink.SendCommand(enuUnitCommand.Compose, (byte)(scene - 63), (ushort)unit.Number);
|
OmniLink.SendCommand(enuUnitCommand.Compose, (byte)(scene - 63), (ushort)unit.Number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace OmniLinkBridge.MQTT
|
|
||||||
{
|
|
||||||
public class Number : Device
|
|
||||||
{
|
|
||||||
public string command_topic { get; set; }
|
|
||||||
|
|
||||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
|
||||||
public string icon { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
7
OmniLinkBridge/MQTT/OverrideUnit.cs
Normal file
7
OmniLinkBridge/MQTT/OverrideUnit.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace OmniLinkBridge.MQTT
|
||||||
|
{
|
||||||
|
public class OverrideUnit
|
||||||
|
{
|
||||||
|
public UnitType type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
using OmniLinkBridge.MQTT.HomeAssistant;
|
||||||
|
|
||||||
|
namespace OmniLinkBridge.MQTT
|
||||||
{
|
{
|
||||||
public class OverrideZone
|
public class OverrideZone
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.Parser
|
||||||
{
|
{
|
||||||
enum AlarmCommands
|
enum AlarmCommands
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.Parser
|
||||||
{
|
{
|
||||||
enum AreaCommands
|
enum AreaCommands
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.Parser
|
||||||
{
|
{
|
||||||
enum CommandTypes
|
enum CommandTypes
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.Parser
|
||||||
{
|
{
|
||||||
enum MessageCommands
|
enum MessageCommands
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.Parser
|
||||||
{
|
{
|
||||||
public enum Topic
|
public enum Topic
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,8 @@
|
||||||
json_state,
|
json_state,
|
||||||
brightness_state,
|
brightness_state,
|
||||||
brightness_command,
|
brightness_command,
|
||||||
|
flag_state,
|
||||||
|
flag_command,
|
||||||
scene_state,
|
scene_state,
|
||||||
scene_command,
|
scene_command,
|
||||||
current_operation,
|
current_operation,
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.Parser
|
||||||
{
|
{
|
||||||
enum UnitCommands
|
enum UnitCommands
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace OmniLinkBridge.MQTT
|
namespace OmniLinkBridge.MQTT.Parser
|
||||||
{
|
{
|
||||||
enum ZoneCommands
|
enum ZoneCommands
|
||||||
{
|
{
|
9
OmniLinkBridge/MQTT/UnitType.cs
Normal file
9
OmniLinkBridge/MQTT/UnitType.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace OmniLinkBridge.MQTT
|
||||||
|
{
|
||||||
|
public enum UnitType
|
||||||
|
{
|
||||||
|
@switch,
|
||||||
|
light,
|
||||||
|
number
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using OmniLinkBridge.Notifications;
|
using OmniLinkBridge.Notifications;
|
||||||
using OmniLinkBridge.OmniLink;
|
using OmniLinkBridge.OmniLink;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Serilog.Context;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
|
@ -125,8 +126,7 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
private void Omnilink_OnConnect(object sender, EventArgs e)
|
private void Omnilink_OnConnect(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (Global.verbose_area)
|
ushort areaUsage = 0;
|
||||||
{
|
|
||||||
for (ushort i = 1; i <= omnilink.Controller.Areas.Count; i++)
|
for (ushort i = 1; i <= omnilink.Controller.Areas.Count; i++)
|
||||||
{
|
{
|
||||||
clsArea area = omnilink.Controller.Areas[i];
|
clsArea area = omnilink.Controller.Areas[i];
|
||||||
|
@ -134,6 +134,10 @@ namespace OmniLinkBridge.Modules
|
||||||
if (i > 1 && area.DefaultProperties == true)
|
if (i > 1 && area.DefaultProperties == true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
areaUsage++;
|
||||||
|
|
||||||
|
if (Global.verbose_area)
|
||||||
|
{
|
||||||
string status = area.ModeText();
|
string status = area.ModeText();
|
||||||
|
|
||||||
if (area.ExitTimer > 0)
|
if (area.ExitTimer > 0)
|
||||||
|
@ -146,8 +150,7 @@ namespace OmniLinkBridge.Modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Global.verbose_zone)
|
ushort zoneUsage = 0;
|
||||||
{
|
|
||||||
for (ushort i = 1; i <= omnilink.Controller.Zones.Count; i++)
|
for (ushort i = 1; i <= omnilink.Controller.Zones.Count; i++)
|
||||||
{
|
{
|
||||||
clsZone zone = omnilink.Controller.Zones[i];
|
clsZone zone = omnilink.Controller.Zones[i];
|
||||||
|
@ -155,12 +158,51 @@ namespace OmniLinkBridge.Modules
|
||||||
if (zone.DefaultProperties == true)
|
if (zone.DefaultProperties == true)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
zoneUsage++;
|
||||||
|
|
||||||
|
if (Global.verbose_zone)
|
||||||
|
{
|
||||||
if (zone.IsTemperatureZone())
|
if (zone.IsTemperatureZone())
|
||||||
log.Verbose("Initial ZoneStatus {id} {name}, Temp: {temp}", i, zone.Name, zone.TempText());
|
log.Verbose("Initial ZoneStatus {id} {name}, Temp: {temp}", i, zone.Name, zone.TempText());
|
||||||
else
|
else
|
||||||
log.Verbose("Initial ZoneStatus {id} {name}, Status: {status}", i, zone.Name, zone.StatusText());
|
log.Verbose("Initial ZoneStatus {id} {name}, Status: {status}", i, zone.Name, zone.StatusText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ushort unitUsage = 0, outputUsage = 0, flagUsage = 0;
|
||||||
|
for (ushort i = 1; i <= omnilink.Controller.Units.Count; i++)
|
||||||
|
{
|
||||||
|
clsUnit unit = omnilink.Controller.Units[i];
|
||||||
|
|
||||||
|
if (unit.DefaultProperties == true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (unit.Type == enuOL2UnitType.Output)
|
||||||
|
outputUsage++;
|
||||||
|
else if (unit.Type == enuOL2UnitType.Flag)
|
||||||
|
flagUsage++;
|
||||||
|
else
|
||||||
|
unitUsage++;
|
||||||
|
|
||||||
|
if (Global.verbose_unit)
|
||||||
|
log.Verbose("Initial UnitStatus {id} {name}, Status: {status}", i, unit.Name, unit.StatusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
ushort thermostatUsage = 0;
|
||||||
|
for (ushort i = 1; i <= omnilink.Controller.Thermostats.Count; i++)
|
||||||
|
{
|
||||||
|
clsThermostat thermostat = omnilink.Controller.Thermostats[i];
|
||||||
|
|
||||||
|
if (thermostat.DefaultProperties == true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
thermostatUsage++;
|
||||||
|
}
|
||||||
|
|
||||||
|
using (LogContext.PushProperty("Telemetry", "ControllerUsage"))
|
||||||
|
log.Debug("Controller has {AreaUsage} areas, {ZoneUsage} zones, {UnitUsage} units, " +
|
||||||
|
"{OutputUsage} outputs, {FlagUsage} flags, {ThermostatUsage} thermostats",
|
||||||
|
areaUsage, zoneUsage, unitUsage, outputUsage, flagUsage, thermostatUsage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Omnilink_OnAreaStatus(object sender, AreaStatusEventArgs e)
|
private void Omnilink_OnAreaStatus(object sender, AreaStatusEventArgs e)
|
||||||
|
|
|
@ -9,10 +9,13 @@ using MQTTnet.Extensions.ManagedClient;
|
||||||
using MQTTnet.Protocol;
|
using MQTTnet.Protocol;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using OmniLinkBridge.MQTT;
|
using OmniLinkBridge.MQTT;
|
||||||
|
using OmniLinkBridge.MQTT.HomeAssistant;
|
||||||
|
using OmniLinkBridge.MQTT.Parser;
|
||||||
using OmniLinkBridge.OmniLink;
|
using OmniLinkBridge.OmniLink;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
@ -108,6 +111,7 @@ namespace OmniLinkBridge.Modules
|
||||||
Topic.command,
|
Topic.command,
|
||||||
Topic.alarm_command,
|
Topic.alarm_command,
|
||||||
Topic.brightness_command,
|
Topic.brightness_command,
|
||||||
|
Topic.flag_command,
|
||||||
Topic.scene_command,
|
Topic.scene_command,
|
||||||
Topic.temperature_heat_command,
|
Topic.temperature_heat_command,
|
||||||
Topic.temperature_cool_command,
|
Topic.temperature_cool_command,
|
||||||
|
@ -216,8 +220,8 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
clsArea area = OmniLink.Controller.Areas[i];
|
clsArea area = OmniLink.Controller.Areas[i];
|
||||||
|
|
||||||
// PC Access doesn't let you customize the area name for the Omni LTe or Omni IIe
|
// PC Access doesn't let you customize the area name when configured for one area.
|
||||||
// (configured for 1 area). To workaround ignore default properties for the first area.
|
// Ignore default properties for the first area.
|
||||||
if (i > 1 && area.DefaultProperties == true)
|
if (i > 1 && area.DefaultProperties == true)
|
||||||
{
|
{
|
||||||
PublishAsync(area.ToTopic(Topic.name), null);
|
PublishAsync(area.ToTopic(Topic.name), null);
|
||||||
|
@ -308,6 +312,7 @@ namespace OmniLinkBridge.Modules
|
||||||
for (ushort i = 1; i <= OmniLink.Controller.Units.Count; i++)
|
for (ushort i = 1; i <= OmniLink.Controller.Units.Count; i++)
|
||||||
{
|
{
|
||||||
clsUnit unit = OmniLink.Controller.Units[i];
|
clsUnit unit = OmniLink.Controller.Units[i];
|
||||||
|
UnitType unitType = unit.ToUnitType();
|
||||||
|
|
||||||
if (unit.DefaultProperties == true)
|
if (unit.DefaultProperties == true)
|
||||||
{
|
{
|
||||||
|
@ -321,17 +326,26 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
if (unit.DefaultProperties == true || Global.mqtt_discovery_ignore_units.Contains(unit.Number))
|
if (unit.DefaultProperties == true || Global.mqtt_discovery_ignore_units.Contains(unit.Number))
|
||||||
{
|
{
|
||||||
string type = i < 385 ? "light" : "switch";
|
foreach(UnitType entry in Enum.GetValues(typeof(UnitType)))
|
||||||
PublishAsync($"{Global.mqtt_discovery_prefix}/{type}/{Global.mqtt_prefix}/unit{i}/config", null);
|
PublishAsync($"{Global.mqtt_discovery_prefix}/{entry}/{Global.mqtt_prefix}/unit{i}/config", null);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < 385)
|
foreach (UnitType entry in Enum.GetValues(typeof(UnitType)).Cast<UnitType>().Where(x => x != unitType))
|
||||||
PublishAsync($"{Global.mqtt_discovery_prefix}/light/{Global.mqtt_prefix}/unit{i}/config",
|
PublishAsync($"{Global.mqtt_discovery_prefix}/{entry}/{Global.mqtt_prefix}/unit{i}/config", null);
|
||||||
JsonConvert.SerializeObject(unit.ToConfig()));
|
|
||||||
else
|
log.Verbose("Publishing {type} {id} {name} as {unitType}", "units", i, unit.Name, unitType);
|
||||||
PublishAsync($"{Global.mqtt_discovery_prefix}/switch/{Global.mqtt_prefix}/unit{i}/config",
|
|
||||||
|
if (unitType == UnitType.@switch)
|
||||||
|
PublishAsync($"{Global.mqtt_discovery_prefix}/{unitType}/{Global.mqtt_prefix}/unit{i}/config",
|
||||||
JsonConvert.SerializeObject(unit.ToConfigSwitch()));
|
JsonConvert.SerializeObject(unit.ToConfigSwitch()));
|
||||||
|
else if (unitType == UnitType.light)
|
||||||
|
PublishAsync($"{Global.mqtt_discovery_prefix}/{unitType}/{Global.mqtt_prefix}/unit{i}/config",
|
||||||
|
JsonConvert.SerializeObject(unit.ToConfig()));
|
||||||
|
else if (unitType == UnitType.number)
|
||||||
|
PublishAsync($"{Global.mqtt_discovery_prefix}/{unitType}/{Global.mqtt_prefix}/unit{i}/config",
|
||||||
|
JsonConvert.SerializeObject(unit.ToConfigNumber()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,7 +551,11 @@ namespace OmniLinkBridge.Modules
|
||||||
{
|
{
|
||||||
PublishAsync(unit.ToTopic(Topic.state), unit.ToState());
|
PublishAsync(unit.ToTopic(Topic.state), unit.ToState());
|
||||||
|
|
||||||
if (unit.Number < 385)
|
if (unit.Type == enuOL2UnitType.Flag)
|
||||||
|
{
|
||||||
|
PublishAsync(unit.ToTopic(Topic.flag_state), ((ushort)unit.Status).ToString());
|
||||||
|
}
|
||||||
|
else if(unit.Type != enuOL2UnitType.Output)
|
||||||
{
|
{
|
||||||
PublishAsync(unit.ToTopic(Topic.brightness_state), unit.ToBrightnessState().ToString());
|
PublishAsync(unit.ToTopic(Topic.brightness_state), unit.ToBrightnessState().ToString());
|
||||||
PublishAsync(unit.ToTopic(Topic.scene_state), unit.ToSceneState());
|
PublishAsync(unit.ToTopic(Topic.scene_state), unit.ToSceneState());
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace OmniLinkBridge.Modules
|
||||||
|
|
||||||
Controller.Connection.NetworkAddress = address;
|
Controller.Connection.NetworkAddress = address;
|
||||||
Controller.Connection.NetworkPort = (ushort)port;
|
Controller.Connection.NetworkPort = (ushort)port;
|
||||||
Controller.Connection.ControllerKey = clsUtil.HexString2ByteArray(String.Concat(key1, key2));
|
Controller.Connection.ControllerKey = clsUtil.HexString2ByteArray(string.Concat(key1, key2));
|
||||||
|
|
||||||
Controller.PreferredNetworkProtocol = clsHAC.enuPreferredNetworkProtocol.TCP;
|
Controller.PreferredNetworkProtocol = clsHAC.enuPreferredNetworkProtocol.TCP;
|
||||||
Controller.Connection.ConnectionType = enuOmniLinkConnectionType.Network_TCP;
|
Controller.Connection.ConnectionType = enuOmniLinkConnectionType.Network_TCP;
|
||||||
|
@ -316,7 +316,8 @@ namespace OmniLinkBridge.Modules
|
||||||
Controller.Zones.CopyProperties(MSG);
|
Controller.Zones.CopyProperties(MSG);
|
||||||
|
|
||||||
if (Controller.Zones[MSG.ObjectNumber].IsTemperatureZone() || Controller.Zones[MSG.ObjectNumber].IsHumidityZone())
|
if (Controller.Zones[MSG.ObjectNumber].IsTemperatureZone() || Controller.Zones[MSG.ObjectNumber].IsHumidityZone())
|
||||||
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection, enuObjectType.Auxillary, MSG.ObjectNumber, MSG.ObjectNumber), HandleRequestAuxillaryStatus);
|
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection,
|
||||||
|
enuObjectType.Auxillary, MSG.ObjectNumber, MSG.ObjectNumber), HandleRequestAuxillaryStatus);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case enuObjectType.Thermostat:
|
case enuObjectType.Thermostat:
|
||||||
|
@ -327,7 +328,8 @@ namespace OmniLinkBridge.Modules
|
||||||
else
|
else
|
||||||
tstats[MSG.ObjectNumber] = DateTime.MinValue;
|
tstats[MSG.ObjectNumber] = DateTime.MinValue;
|
||||||
|
|
||||||
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection, enuObjectType.Thermostat, MSG.ObjectNumber, MSG.ObjectNumber), HandleRequestThermostatStatus);
|
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection,
|
||||||
|
enuObjectType.Thermostat, MSG.ObjectNumber, MSG.ObjectNumber), HandleRequestThermostatStatus);
|
||||||
log.Debug("Added thermostat to watch list {thermostatName}",
|
log.Debug("Added thermostat to watch list {thermostatName}",
|
||||||
Controller.Thermostats[MSG.ObjectNumber].Name);
|
Controller.Thermostats[MSG.ObjectNumber].Name);
|
||||||
break;
|
break;
|
||||||
|
@ -714,7 +716,8 @@ namespace OmniLinkBridge.Modules
|
||||||
(Controller.Connection.ConnectionState == enuOmniLinkConnectionState.Online ||
|
(Controller.Connection.ConnectionState == enuOmniLinkConnectionState.Online ||
|
||||||
Controller.Connection.ConnectionState == enuOmniLinkConnectionState.OnlineSecure))
|
Controller.Connection.ConnectionState == enuOmniLinkConnectionState.OnlineSecure))
|
||||||
{
|
{
|
||||||
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection, enuObjectType.Thermostat, tstat.Key, tstat.Key), HandleRequestThermostatStatus);
|
Controller.Connection.Send(new clsOL2MsgRequestExtendedStatus(Controller.Connection,
|
||||||
|
enuObjectType.Thermostat, tstat.Key, tstat.Key), HandleRequestThermostatStatus);
|
||||||
|
|
||||||
if (Global.verbose_thermostat_timer)
|
if (Global.verbose_thermostat_timer)
|
||||||
log.Debug("Polling status for Thermostat {thermostatName}",
|
log.Debug("Polling status for Thermostat {thermostatName}",
|
||||||
|
|
|
@ -74,14 +74,15 @@ namespace OmniLinkBridge.Modules
|
||||||
// Extract the 2 digit prefix to use when parsing the time
|
// Extract the 2 digit prefix to use when parsing the time
|
||||||
int year = DateTime.Now.Year / 100;
|
int year = DateTime.Now.Year / 100;
|
||||||
|
|
||||||
time = new DateTime((int)MSG.Year + (year * 100), (int)MSG.Month, (int)MSG.Day, (int)MSG.Hour, (int)MSG.Minute, (int)MSG.Second);
|
time = new DateTime(MSG.Year + (year * 100), MSG.Month, MSG.Day, MSG.Hour, MSG.Minute, MSG.Second);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
log.Warning("Controller time could not be parsed");
|
log.Warning("Controller time could not be parsed");
|
||||||
|
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.Now;
|
||||||
OmniLink.Controller.Connection.Send(new clsOL2MsgSetTime(OmniLink.Controller.Connection, (byte)(now.Year % 100), (byte)now.Month, (byte)now.Day, (byte)now.DayOfWeek,
|
OmniLink.Controller.Connection.Send(new clsOL2MsgSetTime(OmniLink.Controller.Connection,
|
||||||
|
(byte)(now.Year % 100), (byte)now.Month, (byte)now.Day, (byte)now.DayOfWeek,
|
||||||
(byte)now.Hour, (byte)now.Minute, (byte)(now.IsDaylightSavingTime() ? 1 : 0)), HandleSetTime);
|
(byte)now.Hour, (byte)now.Minute, (byte)(now.IsDaylightSavingTime() ? 1 : 0)), HandleSetTime);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -95,7 +96,8 @@ namespace OmniLinkBridge.Modules
|
||||||
time.ToString("MM/dd/yyyy HH:mm:ss"), adj);
|
time.ToString("MM/dd/yyyy HH:mm:ss"), adj);
|
||||||
|
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.Now;
|
||||||
OmniLink.Controller.Connection.Send(new clsOL2MsgSetTime(OmniLink.Controller.Connection, (byte)(now.Year % 100), (byte)now.Month, (byte)now.Day, (byte)now.DayOfWeek,
|
OmniLink.Controller.Connection.Send(new clsOL2MsgSetTime(OmniLink.Controller.Connection,
|
||||||
|
(byte)(now.Year % 100), (byte)now.Month, (byte)now.Day, (byte)now.DayOfWeek,
|
||||||
(byte)now.Hour, (byte)now.Minute, (byte)(now.IsDaylightSavingTime() ? 1 : 0)), HandleSetTime);
|
(byte)now.Hour, (byte)now.Minute, (byte)(now.IsDaylightSavingTime() ? 1 : 0)), HandleSetTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,28 +82,31 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="CoreServer.cs" />
|
<Compile Include="CoreServer.cs" />
|
||||||
<Compile Include="Modules\TimeSyncModule.cs" />
|
<Compile Include="Modules\TimeSyncModule.cs" />
|
||||||
<Compile Include="MQTT\Alarm.cs" />
|
<Compile Include="MQTT\HomeAssistant\Alarm.cs" />
|
||||||
<Compile Include="MQTT\AlarmCommands.cs" />
|
<Compile Include="MQTT\OverrideUnit.cs" />
|
||||||
|
<Compile Include="MQTT\Parser\AlarmCommands.cs" />
|
||||||
<Compile Include="MQTT\AreaCommandCode.cs" />
|
<Compile Include="MQTT\AreaCommandCode.cs" />
|
||||||
<Compile Include="MQTT\AreaCommands.cs" />
|
<Compile Include="MQTT\Parser\AreaCommands.cs" />
|
||||||
<Compile Include="MQTT\AreaState.cs" />
|
<Compile Include="MQTT\AreaState.cs" />
|
||||||
<Compile Include="MQTT\Availability.cs" />
|
<Compile Include="MQTT\Availability.cs" />
|
||||||
<Compile Include="MQTT\BinarySensor.cs" />
|
<Compile Include="MQTT\HomeAssistant\BinarySensor.cs" />
|
||||||
<Compile Include="MQTT\CommandTypes.cs" />
|
<Compile Include="MQTT\Parser\CommandTypes.cs" />
|
||||||
<Compile Include="MQTT\Device.cs" />
|
<Compile Include="MQTT\HomeAssistant\Device.cs" />
|
||||||
<Compile Include="MQTT\Climate.cs" />
|
<Compile Include="MQTT\HomeAssistant\Climate.cs" />
|
||||||
<Compile Include="MQTT\DeviceRegistry.cs" />
|
<Compile Include="MQTT\HomeAssistant\DeviceRegistry.cs" />
|
||||||
<Compile Include="MQTT\MessageCommands.cs" />
|
<Compile Include="MQTT\Extensions.cs" />
|
||||||
|
<Compile Include="MQTT\Parser\MessageCommands.cs" />
|
||||||
<Compile Include="MQTT\MessageProcessor.cs" />
|
<Compile Include="MQTT\MessageProcessor.cs" />
|
||||||
<Compile Include="MQTT\Number.cs" />
|
<Compile Include="MQTT\HomeAssistant\Number.cs" />
|
||||||
<Compile Include="MQTT\OverrideZone.cs" />
|
<Compile Include="MQTT\OverrideZone.cs" />
|
||||||
<Compile Include="MQTT\Switch.cs" />
|
<Compile Include="MQTT\HomeAssistant\Switch.cs" />
|
||||||
<Compile Include="MQTT\Light.cs" />
|
<Compile Include="MQTT\HomeAssistant\Light.cs" />
|
||||||
<Compile Include="MQTT\MappingExtensions.cs" />
|
<Compile Include="MQTT\MappingExtensions.cs" />
|
||||||
<Compile Include="MQTT\Sensor.cs" />
|
<Compile Include="MQTT\HomeAssistant\Sensor.cs" />
|
||||||
<Compile Include="MQTT\Topic.cs" />
|
<Compile Include="MQTT\Parser\Topic.cs" />
|
||||||
<Compile Include="MQTT\UnitCommands.cs" />
|
<Compile Include="MQTT\Parser\UnitCommands.cs" />
|
||||||
<Compile Include="MQTT\ZoneCommands.cs" />
|
<Compile Include="MQTT\Parser\ZoneCommands.cs" />
|
||||||
|
<Compile Include="MQTT\UnitType.cs" />
|
||||||
<Compile Include="Notifications\EmailNotification.cs" />
|
<Compile Include="Notifications\EmailNotification.cs" />
|
||||||
<Compile Include="Notifications\INotification.cs" />
|
<Compile Include="Notifications\INotification.cs" />
|
||||||
<Compile Include="Notifications\Notification.cs" />
|
<Compile Include="Notifications\Notification.cs" />
|
||||||
|
|
|
@ -4,4 +4,7 @@
|
||||||
<StartArguments>
|
<StartArguments>
|
||||||
</StartArguments>
|
</StartArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ProjectView>ProjectFiles</ProjectView>
|
||||||
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -49,13 +49,24 @@ mqtt_prefix = omnilink
|
||||||
mqtt_discovery_prefix = homeassistant
|
mqtt_discovery_prefix = homeassistant
|
||||||
# Prefix for Home Assistant entity names
|
# Prefix for Home Assistant entity names
|
||||||
mqtt_discovery_name_prefix =
|
mqtt_discovery_name_prefix =
|
||||||
# Specify a range of numbers like 1,2,3,5-10
|
# Skip publishing Home Assistant discovery topics for zones/units
|
||||||
|
# Specify a range of numbers 1,2,3,5-10
|
||||||
mqtt_discovery_ignore_zones =
|
mqtt_discovery_ignore_zones =
|
||||||
mqtt_discovery_ignore_units =
|
mqtt_discovery_ignore_units =
|
||||||
|
# Require Home Assistant to prompt for user code when arming/disarming area
|
||||||
|
# Specify a range of numbers 1,2,3,5-10
|
||||||
mqtt_discovery_area_code_required =
|
mqtt_discovery_area_code_required =
|
||||||
# device_class must be battery, door, garage_door, gas, moisture, motion, problem, smoke, or window
|
# Override the zone Home Assistant binary sensor device_class
|
||||||
|
# device_class: must be battery, cold, door, garage_door, gas,
|
||||||
|
# heat, moisture, motion, problem, safety, smoke, or window
|
||||||
#mqtt_discovery_override_zone = id=5;device_class=garage_door
|
#mqtt_discovery_override_zone = id=5;device_class=garage_door
|
||||||
#mqtt_discovery_override_zone = id=6;device_class=garage_door
|
#mqtt_discovery_override_zone = id=6;device_class=garage_door
|
||||||
|
# Override the unit Home Assistant device type
|
||||||
|
# type:
|
||||||
|
# Units (LTe 1-32, IIe 1-64, Pro 1-256) light or switch, defaults to light
|
||||||
|
# Flags (LTe 41-88, IIe 73-128, Pro 393-511) switch or number, defaults to switch
|
||||||
|
#mqtt_discovery_override_unit = id=1;type=switch
|
||||||
|
#mqtt_discovery_override_unit = id=395;type=number
|
||||||
|
|
||||||
# Notifications (yes/no)
|
# Notifications (yes/no)
|
||||||
# Always sent for area alarms and critical system events
|
# Always sent for area alarms and critical system events
|
||||||
|
|
|
@ -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.13.0")]
|
[assembly: AssemblyVersion("1.1.14.0")]
|
||||||
[assembly: AssemblyFileVersion("1.1.13.0")]
|
[assembly: AssemblyFileVersion("1.1.14.0")]
|
||||||
|
|
|
@ -7,7 +7,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Mail;
|
using System.Net.Mail;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using ha = OmniLinkBridge.MQTT.HomeAssistant;
|
||||||
|
|
||||||
namespace OmniLinkBridge
|
namespace OmniLinkBridge
|
||||||
{
|
{
|
||||||
|
@ -86,6 +86,7 @@ namespace OmniLinkBridge
|
||||||
Global.mqtt_discovery_ignore_units = settings.ValidateRange("mqtt_discovery_ignore_units");
|
Global.mqtt_discovery_ignore_units = settings.ValidateRange("mqtt_discovery_ignore_units");
|
||||||
Global.mqtt_discovery_area_code_required = settings.ValidateRange("mqtt_discovery_area_code_required");
|
Global.mqtt_discovery_area_code_required = settings.ValidateRange("mqtt_discovery_area_code_required");
|
||||||
Global.mqtt_discovery_override_zone = settings.LoadOverrideZone<MQTT.OverrideZone>("mqtt_discovery_override_zone");
|
Global.mqtt_discovery_override_zone = settings.LoadOverrideZone<MQTT.OverrideZone>("mqtt_discovery_override_zone");
|
||||||
|
Global.mqtt_discovery_override_unit = settings.LoadOverrideUnit<MQTT.OverrideUnit>("mqtt_discovery_override_unit");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
|
@ -157,7 +158,7 @@ namespace OmniLinkBridge
|
||||||
}
|
}
|
||||||
else if (override_zone is MQTT.OverrideZone mqtt_zone)
|
else if (override_zone is MQTT.OverrideZone mqtt_zone)
|
||||||
{
|
{
|
||||||
if (!attributes.ContainsKey("device_class") || !Enum.TryParse(attributes["device_class"], out MQTT.BinarySensor.DeviceClass attrib_device_class))
|
if (!attributes.ContainsKey("device_class") || !Enum.TryParse(attributes["device_class"], out ha.BinarySensor.DeviceClass attrib_device_class))
|
||||||
throw new Exception("Missing or invalid device_class attribute");
|
throw new Exception("Missing or invalid device_class attribute");
|
||||||
|
|
||||||
mqtt_zone.device_class = attrib_device_class;
|
mqtt_zone.device_class = attrib_device_class;
|
||||||
|
@ -175,6 +176,50 @@ namespace OmniLinkBridge
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ConcurrentDictionary<int, T> LoadOverrideUnit<T>(this NameValueCollection settings, string section) where T : new()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ConcurrentDictionary<int, T> ret = new ConcurrentDictionary<int, T>();
|
||||||
|
|
||||||
|
string value = settings.CheckEnv(section);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
string[] ids = value.Split(',');
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.Length; i++)
|
||||||
|
{
|
||||||
|
Dictionary<string, string> attributes = ids[i].TrimEnd(new char[] { ';' }).Split(';')
|
||||||
|
.Select(s => s.Split('='))
|
||||||
|
.ToDictionary(a => a[0].Trim(), a => a[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
|
||||||
|
|
||||||
|
if (!attributes.ContainsKey("id") || !int.TryParse(attributes["id"], out int attrib_id))
|
||||||
|
throw new Exception("Missing or invalid id attribute");
|
||||||
|
|
||||||
|
T override_unit = new T();
|
||||||
|
|
||||||
|
if (override_unit is MQTT.OverrideUnit mqtt_unit)
|
||||||
|
{
|
||||||
|
if (!attributes.ContainsKey("type") || !Enum.TryParse(attributes["type"], out MQTT.UnitType attrib_type))
|
||||||
|
throw new Exception("Missing or invalid type attribute");
|
||||||
|
|
||||||
|
mqtt_unit.type = attrib_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.TryAdd(attrib_id, override_unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
log.Error(ex, "Invalid override unit specified for {section}", section);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static string ValidateHasValue(this NameValueCollection settings, string section)
|
private static string ValidateHasValue(this NameValueCollection settings, string section)
|
||||||
{
|
{
|
||||||
string value = settings.CheckEnv(section);
|
string value = settings.CheckEnv(section);
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using System.Text;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using OmniLinkBridge;
|
using OmniLinkBridge;
|
||||||
using OmniLinkBridge.MQTT;
|
using OmniLinkBridge.MQTT;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace OmniLinkBridgeTest
|
namespace OmniLinkBridgeTest
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
using System;
|
using HAI_Shared;
|
||||||
using System.Text;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using HAI_Shared;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
using OmniLinkBridge;
|
||||||
using OmniLinkBridge.MQTT;
|
using OmniLinkBridge.MQTT;
|
||||||
using OmniLinkBridgeTest.Mock;
|
using OmniLinkBridgeTest.Mock;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
|
||||||
namespace OmniLinkBridgeTest
|
namespace OmniLinkBridgeTest
|
||||||
{
|
{
|
||||||
|
@ -19,6 +18,8 @@ namespace OmniLinkBridgeTest
|
||||||
{
|
{
|
||||||
omniLink = new MockOmniLinkII();
|
omniLink = new MockOmniLinkII();
|
||||||
messageProcessor = new MessageProcessor(omniLink);
|
messageProcessor = new MessageProcessor(omniLink);
|
||||||
|
|
||||||
|
omniLink.Controller.Units[395].Type = enuOL2UnitType.Flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
@ -134,6 +135,28 @@ namespace OmniLinkBridgeTest
|
||||||
check(2, "on", enuUnitCommand.On);
|
check(2, "on", enuUnitCommand.On);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void UnitFlagCommand()
|
||||||
|
{
|
||||||
|
void check(ushort id, string payload, enuUnitCommand command, int value)
|
||||||
|
{
|
||||||
|
SendCommandEventArgs actual = null;
|
||||||
|
omniLink.OnSendCommand += (sender, e) => { actual = e; };
|
||||||
|
messageProcessor.Process($"omnilink/unit{id}/flag_command", payload);
|
||||||
|
SendCommandEventArgs expected = new SendCommandEventArgs()
|
||||||
|
{
|
||||||
|
Cmd = command,
|
||||||
|
Par = (byte)value,
|
||||||
|
Pr2 = id
|
||||||
|
};
|
||||||
|
Assert.AreEqual(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
check(395, "0", enuUnitCommand.Set, 0);
|
||||||
|
check(395, "1", enuUnitCommand.Set, 1);
|
||||||
|
check(395, "255", enuUnitCommand.Set, 255);
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void UnitLevelCommand()
|
public void UnitLevelCommand()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
using HAI_Shared;
|
using HAI_Shared;
|
||||||
using OmniLinkBridge.OmniLink;
|
using OmniLinkBridge.OmniLink;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace OmniLinkBridgeTest.Mock
|
namespace OmniLinkBridgeTest.Mock
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
using HAI_Shared;
|
using HAI_Shared;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace OmniLinkBridgeTest.Mock
|
namespace OmniLinkBridgeTest.Mock
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
using System;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using System.Text;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using OmniLinkBridge.Notifications;
|
|
||||||
using OmniLinkBridge;
|
using OmniLinkBridge;
|
||||||
|
using OmniLinkBridge.Notifications;
|
||||||
using System.Net.Mail;
|
using System.Net.Mail;
|
||||||
|
|
||||||
namespace OmniLinkBridgeTest
|
namespace OmniLinkBridgeTest
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
using System;
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
using System.Text;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
||||||
using OmniLinkBridge;
|
using OmniLinkBridge;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ha = OmniLinkBridge.MQTT.HomeAssistant;
|
||||||
|
|
||||||
namespace OmniLinkBridgeTest
|
namespace OmniLinkBridgeTest
|
||||||
{
|
{
|
||||||
|
@ -156,8 +155,11 @@ namespace OmniLinkBridgeTest
|
||||||
"mqtt_discovery_name_prefix = mynameprefix",
|
"mqtt_discovery_name_prefix = mynameprefix",
|
||||||
"mqtt_discovery_ignore_zones = 1,2-3,4",
|
"mqtt_discovery_ignore_zones = 1,2-3,4",
|
||||||
"mqtt_discovery_ignore_units = 2-5,7",
|
"mqtt_discovery_ignore_units = 2-5,7",
|
||||||
|
"mqtt_discovery_area_code_required = 1",
|
||||||
"mqtt_discovery_override_zone = id=5;device_class=garage_door",
|
"mqtt_discovery_override_zone = id=5;device_class=garage_door",
|
||||||
"mqtt_discovery_override_zone = id=7;device_class=motion",
|
"mqtt_discovery_override_zone = id=7;device_class=motion",
|
||||||
|
"mqtt_discovery_override_unit = id=1;type=switch",
|
||||||
|
"mqtt_discovery_override_unit = id=395;type=light",
|
||||||
});
|
});
|
||||||
Settings.LoadSettings(lines.ToArray());
|
Settings.LoadSettings(lines.ToArray());
|
||||||
Assert.AreEqual("myuser", Global.mqtt_username);
|
Assert.AreEqual("myuser", Global.mqtt_username);
|
||||||
|
@ -167,11 +169,12 @@ namespace OmniLinkBridgeTest
|
||||||
Assert.AreEqual("mynameprefix ", Global.mqtt_discovery_name_prefix);
|
Assert.AreEqual("mynameprefix ", Global.mqtt_discovery_name_prefix);
|
||||||
Assert.IsTrue(Global.mqtt_discovery_ignore_zones.SetEquals(new int[] { 1, 2, 3, 4 }));
|
Assert.IsTrue(Global.mqtt_discovery_ignore_zones.SetEquals(new int[] { 1, 2, 3, 4 }));
|
||||||
Assert.IsTrue(Global.mqtt_discovery_ignore_units.SetEquals(new int[] { 2, 3, 4, 5, 7 }));
|
Assert.IsTrue(Global.mqtt_discovery_ignore_units.SetEquals(new int[] { 2, 3, 4, 5, 7 }));
|
||||||
|
Assert.IsTrue(Global.mqtt_discovery_area_code_required.SetEquals(new int[] { 1 }));
|
||||||
|
|
||||||
Dictionary<int, OmniLinkBridge.MQTT.OverrideZone> override_zone = new Dictionary<int, OmniLinkBridge.MQTT.OverrideZone>()
|
Dictionary<int, OmniLinkBridge.MQTT.OverrideZone> override_zone = new Dictionary<int, OmniLinkBridge.MQTT.OverrideZone>()
|
||||||
{
|
{
|
||||||
{ 5, new OmniLinkBridge.MQTT.OverrideZone { device_class = OmniLinkBridge.MQTT.BinarySensor.DeviceClass.garage_door }},
|
{ 5, new OmniLinkBridge.MQTT.OverrideZone { device_class = ha.BinarySensor.DeviceClass.garage_door }},
|
||||||
{ 7, new OmniLinkBridge.MQTT.OverrideZone { device_class = OmniLinkBridge.MQTT.BinarySensor.DeviceClass.motion }}
|
{ 7, new OmniLinkBridge.MQTT.OverrideZone { device_class = ha.BinarySensor.DeviceClass.motion }}
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.AreEqual(override_zone.Count, Global.mqtt_discovery_override_zone.Count);
|
Assert.AreEqual(override_zone.Count, Global.mqtt_discovery_override_zone.Count);
|
||||||
|
@ -180,6 +183,19 @@ namespace OmniLinkBridgeTest
|
||||||
Global.mqtt_discovery_override_zone.TryGetValue(pair.Key, out OmniLinkBridge.MQTT.OverrideZone value);
|
Global.mqtt_discovery_override_zone.TryGetValue(pair.Key, out OmniLinkBridge.MQTT.OverrideZone value);
|
||||||
Assert.AreEqual(override_zone[pair.Key].device_class, value.device_class);
|
Assert.AreEqual(override_zone[pair.Key].device_class, value.device_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dictionary<int, OmniLinkBridge.MQTT.OverrideUnit> override_unit = new Dictionary<int, OmniLinkBridge.MQTT.OverrideUnit>()
|
||||||
|
{
|
||||||
|
{ 1, new OmniLinkBridge.MQTT.OverrideUnit { type = OmniLinkBridge.MQTT.UnitType.@switch }},
|
||||||
|
{ 395, new OmniLinkBridge.MQTT.OverrideUnit { type = OmniLinkBridge.MQTT.UnitType.light }}
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.AreEqual(override_unit.Count, Global.mqtt_discovery_override_unit.Count);
|
||||||
|
foreach (KeyValuePair<int, OmniLinkBridge.MQTT.OverrideUnit> pair in override_unit)
|
||||||
|
{
|
||||||
|
Global.mqtt_discovery_override_unit.TryGetValue(pair.Key, out OmniLinkBridge.MQTT.OverrideUnit value);
|
||||||
|
Assert.AreEqual(override_unit[pair.Key].type, value.type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
|
|
@ -9,7 +9,7 @@ You can use docker to build an image from git or download the [binary here](http
|
||||||
- .NET Framework 4.7.2 (or Mono equivalent)
|
- .NET Framework 4.7.2 (or Mono equivalent)
|
||||||
|
|
||||||
## Operation
|
## Operation
|
||||||
OmniLink Bridge is divided into the following modules and configurable settings. Configuration settings can also be set as environment variables by using their name in uppercase. Refer to [OmniLinkBridge.ini](https://github.com/excaliburpartners/OmniLinkBridge/blob/master/OmniLinkBridge/OmniLinkBridge.ini) for specifics.
|
OmniLink Bridge is divided into the following modules and configurable settings. Configuration settings can also be set as environment variables by using their name in uppercase. Refer to [OmniLinkBridge.ini](OmniLinkBridge/OmniLinkBridge.ini) for specifics.
|
||||||
|
|
||||||
- OmniLinkII: controller_
|
- OmniLinkII: controller_
|
||||||
- Maintains connection to the OmniLink controller
|
- Maintains connection to the OmniLink controller
|
||||||
|
@ -232,6 +232,10 @@ SUB omnilink/unitX/brightness_state
|
||||||
PUB omnilink/unitX/brightness_command
|
PUB omnilink/unitX/brightness_command
|
||||||
int Level from 0 to 100 percent
|
int Level from 0 to 100 percent
|
||||||
|
|
||||||
|
SUB omnilink/unitX/flag_state
|
||||||
|
PUB omnilink/unitX/flag_command
|
||||||
|
int Level from 0 to 255
|
||||||
|
|
||||||
SUB omnilink/unitX/scene_state
|
SUB omnilink/unitX/scene_state
|
||||||
PUB omnilink/unitX/scene_command
|
PUB omnilink/unitX/scene_command
|
||||||
string A-L
|
string A-L
|
||||||
|
|
Loading…
Reference in a new issue