1.1.6 - Add support for environment variables

This commit is contained in:
Ryan Wagoner 2019-12-23 21:23:43 -05:00
parent 792355dd0a
commit 9a966225b6
5 changed files with 76 additions and 137 deletions

View file

@ -22,6 +22,7 @@ RUN apt-get update && \
COPY --from=build /usr/lib/odbc /usr/lib/odbc COPY --from=build /usr/lib/odbc /usr/lib/odbc
COPY --from=build /etc/odbcinst.ini /etc/odbcinst.ini COPY --from=build /etc/odbcinst.ini /etc/odbcinst.ini
COPY --from=build /app/OmniLinkBridge.ini /config/OmniLinkBridge.ini
EXPOSE 8000/tcp EXPOSE 8000/tcp
VOLUME /config VOLUME /config

View file

@ -9,7 +9,7 @@ controller_name = OmniLinkBridge
# Controller Time Sync (yes/no) # Controller Time Sync (yes/no)
# time_interval is interval in minutes to check controller time # time_interval is interval in minutes to check controller time
# time_drift is the drift in seconds to allow before an adjustment is made # time_drift is the drift in seconds to allow before an adjustment is made
time_sync = yes time_sync = no
time_interval = 60 time_interval = 60
time_drift = 10 time_drift = 10
@ -29,7 +29,7 @@ mysql_connection = DRIVER={MySQL};SERVER=localhost;DATABASE=OmniLinkBridge;USER=
# Web Service (yes/no) # Web Service (yes/no)
# Can be used for integration with Samsung SmartThings # Can be used for integration with Samsung SmartThings
webapi_enabled = yes webapi_enabled = no
webapi_port = 8000 webapi_port = 8000
# device_type must be contact, motion, water, smoke, or co # device_type must be contact, motion, water, smoke, or co
#webapi_override_zone = id=20;device_type=motion #webapi_override_zone = id=20;device_type=motion

View file

@ -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.5.0")] [assembly: AssemblyVersion("1.1.6.0")]
[assembly: AssemblyFileVersion("1.1.5.0")] [assembly: AssemblyFileVersion("1.1.6.0")]

View file

@ -19,11 +19,11 @@ namespace OmniLinkBridge
NameValueCollection settings = LoadCollection(Global.config_file); NameValueCollection settings = LoadCollection(Global.config_file);
// HAI / Leviton Omni Controller // HAI / Leviton Omni Controller
Global.controller_address = settings["controller_address"]; Global.controller_address = settings.CheckEnv("controller_address");
Global.controller_port = ValidatePort(settings, "controller_port"); Global.controller_port = ValidatePort(settings, "controller_port");
Global.controller_key1 = settings["controller_key1"]; Global.controller_key1 = settings.CheckEnv("controller_key1");
Global.controller_key2 = settings["controller_key2"]; Global.controller_key2 = settings.CheckEnv("controller_key2");
Global.controller_name = settings["controller_name"] ?? "OmniLinkBridge"; Global.controller_name = settings.CheckEnv("controller_name") ?? "OmniLinkBridge";
// Controller Time Sync // Controller Time Sync
Global.time_sync = ValidateYesNo(settings, "time_sync"); Global.time_sync = ValidateYesNo(settings, "time_sync");
@ -42,7 +42,7 @@ namespace OmniLinkBridge
// mySQL Logging // mySQL Logging
Global.mysql_logging = ValidateYesNo(settings, "mysql_logging"); Global.mysql_logging = ValidateYesNo(settings, "mysql_logging");
Global.mysql_connection = settings["mysql_connection"]; Global.mysql_connection = settings.CheckEnv("mysql_connection");
// Web Service // Web Service
Global.webapi_enabled = ValidateYesNo(settings, "webapi_enabled"); Global.webapi_enabled = ValidateYesNo(settings, "webapi_enabled");
@ -51,13 +51,13 @@ namespace OmniLinkBridge
// MQTT // MQTT
Global.mqtt_enabled = ValidateYesNo(settings, "mqtt_enabled"); Global.mqtt_enabled = ValidateYesNo(settings, "mqtt_enabled");
Global.mqtt_server = settings["mqtt_server"]; Global.mqtt_server = settings.CheckEnv("mqtt_server");
Global.mqtt_port = ValidatePort(settings, "mqtt_port"); Global.mqtt_port = ValidatePort(settings, "mqtt_port");
Global.mqtt_username = settings["mqtt_username"]; Global.mqtt_username = settings.CheckEnv("mqtt_username");
Global.mqtt_password = settings["mqtt_password"]; Global.mqtt_password = settings.CheckEnv("mqtt_password");
Global.mqtt_prefix = settings["mqtt_prefix"] ?? "omnilink"; Global.mqtt_prefix = settings.CheckEnv("mqtt_prefix") ?? "omnilink";
Global.mqtt_discovery_prefix = settings["mqtt_discovery_prefix"] ?? "homeassistant"; Global.mqtt_discovery_prefix = settings.CheckEnv("mqtt_discovery_prefix") ?? "homeassistant";
Global.mqtt_discovery_name_prefix = settings["mqtt_discovery_name_prefix"] ?? string.Empty; Global.mqtt_discovery_name_prefix = settings.CheckEnv("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 += " ";
@ -71,11 +71,11 @@ namespace OmniLinkBridge
Global.notify_message = ValidateYesNo(settings, "notify_message"); Global.notify_message = ValidateYesNo(settings, "notify_message");
// Email Notifications // Email Notifications
Global.mail_server = settings["mail_server"]; Global.mail_server = settings.CheckEnv("mail_server");
Global.mail_tls = ValidateYesNo(settings, "mail_tls"); Global.mail_tls = ValidateYesNo(settings, "mail_tls");
Global.mail_port = ValidatePort(settings, "mail_port"); Global.mail_port = ValidatePort(settings, "mail_port");
Global.mail_username = settings["mail_username"]; Global.mail_username = settings.CheckEnv("mail_username");
Global.mail_password = settings["mail_password"]; Global.mail_password = settings.CheckEnv("mail_password");
Global.mail_from = ValidateMailFrom(settings, "mail_from"); Global.mail_from = ValidateMailFrom(settings, "mail_from");
Global.mail_to = ValidateMailTo(settings, "mail_to"); Global.mail_to = ValidateMailTo(settings, "mail_to");
@ -83,20 +83,26 @@ namespace OmniLinkBridge
Global.prowl_key = ValidateMultipleStrings(settings, "prowl_key"); Global.prowl_key = ValidateMultipleStrings(settings, "prowl_key");
// Pushover Notifications // Pushover Notifications
Global.pushover_token = settings["pushover_token"]; Global.pushover_token = settings.CheckEnv("pushover_token");
Global.pushover_user = ValidateMultipleStrings(settings, "pushover_user"); Global.pushover_user = ValidateMultipleStrings(settings, "pushover_user");
} }
private static string CheckEnv(this NameValueCollection settings, string name)
{
string env = Environment.GetEnvironmentVariable(name.ToUpper());
return !string.IsNullOrEmpty(env) ? env : settings[name];
}
private static ConcurrentDictionary<int, T> LoadOverrideZone<T>(NameValueCollection settings, string section) where T : new() private static ConcurrentDictionary<int, T> LoadOverrideZone<T>(NameValueCollection settings, string section) where T : new()
{ {
try try
{ {
ConcurrentDictionary<int, T> ret = new ConcurrentDictionary<int, T>(); ConcurrentDictionary<int, T> ret = new ConcurrentDictionary<int, T>();
if (settings[section] == null) if (settings.CheckEnv(section) == null)
return ret; return ret;
string[] ids = settings[section].Split(','); string[] ids = settings.CheckEnv(section).Split(',');
for (int i = 0; i < ids.Length; i++) for (int i = 0; i < ids.Length; i++)
{ {
@ -140,7 +146,7 @@ namespace OmniLinkBridge
{ {
try try
{ {
return int.Parse(settings[section]); return int.Parse(settings.CheckEnv(section));
} }
catch catch
{ {
@ -153,7 +159,7 @@ namespace OmniLinkBridge
{ {
try try
{ {
return new HashSet<int>(settings[section].ParseRanges()); return new HashSet<int>(settings.CheckEnv(section).ParseRanges());
} }
catch catch
{ {
@ -166,7 +172,7 @@ namespace OmniLinkBridge
{ {
try try
{ {
int port = int.Parse(settings[section]); int port = int.Parse(settings.CheckEnv(section));
if (port < 1 || port > 65534) if (port < 1 || port > 65534)
throw new Exception(); throw new Exception();
@ -184,7 +190,7 @@ namespace OmniLinkBridge
{ {
try try
{ {
return new MailAddress(settings[section]); return new MailAddress(settings.CheckEnv(section));
} }
catch catch
{ {
@ -197,10 +203,10 @@ namespace OmniLinkBridge
{ {
try try
{ {
if(settings[section] == null) if(settings.CheckEnv(section) == null)
return new MailAddress[] {}; return new MailAddress[] {};
string[] emails = settings[section].Split(','); string[] emails = settings.CheckEnv(section).Split(',');
MailAddress[] addresses = new MailAddress[emails.Length]; MailAddress[] addresses = new MailAddress[emails.Length];
for(int i=0; i < emails.Length; i++) for(int i=0; i < emails.Length; i++)
@ -219,10 +225,10 @@ namespace OmniLinkBridge
{ {
try try
{ {
if (settings[section] == null) if (settings.CheckEnv(section) == null)
return new string[] { }; return new string[] { };
return settings[section].Split(','); return settings.CheckEnv(section).Split(',');
} }
catch catch
{ {
@ -233,11 +239,13 @@ namespace OmniLinkBridge
private static bool ValidateYesNo (NameValueCollection settings, string section) private static bool ValidateYesNo (NameValueCollection settings, string section)
{ {
if (settings[section] == null) string value = settings.CheckEnv(section);
if (value == null)
return false; return false;
if (string.Compare(settings[section], "yes", true) == 0) if (string.Compare(value, "yes", true) == 0)
return true; return true;
else if (string.Compare(settings[section], "no", true) == 0) else if (string.Compare(value, "no", true) == 0)
return false; return false;
else else
{ {

140
README.md
View file

@ -9,7 +9,7 @@ You can use docker to build an image from git or download the [binary here](http
- .NET Framework 4.5.2 (or Mono equivalent) - .NET Framework 4.5.2 (or Mono equivalent)
## Operation ## Operation
OmniLinkBridge is divided into the following modules and configurable settings. OmniLinkBridge 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.
- OmniLinkII: controller_ - OmniLinkII: controller_
- Maintains connection to the OmniLink controller - Maintains connection to the OmniLink controller
@ -33,6 +33,7 @@ OmniLinkBridge is divided into the following modules and configurable settings.
- Requests to POST endpoints send commands to the OmniLinkII module - Requests to POST endpoints send commands to the OmniLinkII module
- Logger - Logger
- Console output: verbose_ - Console output: verbose_
- Enabled by default
- Thermostats (verbose_thermostat_timer) - Thermostats (verbose_thermostat_timer)
- After 5 minutes of no status updates a warning will be logged - 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 - When a current temperature of 0 is received a warning will be logged
@ -45,8 +46,34 @@ OmniLinkBridge is divided into the following modules and configurable settings.
- Prowl: prowl_ - Prowl: prowl_
- Pushover: pushover_ - Pushover: pushover_
## Docker Hub (preferred) ## Docker Hub Quickstart
1. Configure at a minimum the controller IP and encryptions keys. The web service port must be 8000. Quickly get started with console logging by specifying the controller address and encryption keys.
```
docker run --name="omnilink-bridge" \
-v /etc/localtime:/etc/localtime:ro \
-e CONTROLLER_ADDRESS='' \
-e CONTROLLER_KEY1='00-00-00-00-00-00-00-00' \
-e CONTROLLER_KEY2='00-00-00-00-00-00-00-00' \
--net=host excaliburpartners/omnilink-bridge
```
Or start in the background with time sync and MQTT modules enabled.
```
docker run -d --name="omnilink-bridge" --restart always \
-v /etc/localtime:/etc/localtime:ro \
-e CONTROLLER_ADDRESS='' \
-e CONTROLLER_KEY1='00-00-00-00-00-00-00-00' \
-e CONTROLLER_KEY2='00-00-00-00-00-00-00-00' \
-e TIME_SYNC='yes' \
-e MQTT_ENABLED='yes' \
-e MQTT_SERVER='' \
-e MQTT_USERNAME='' \
-e MQTT_PASSWORD='' \
--net=host excaliburpartners/omnilink-bridge
```
## Docker Hub with Configuration File
1. Configure at a minimum the controller IP and encryptions keys.
``` ```
mkdir /opt/omnilink-bridge mkdir /opt/omnilink-bridge
curl https://raw.githubusercontent.com/excaliburpartners/OmniLinkBridge/master/OmniLinkBridge/OmniLinkBridge.ini -o /opt/omnilink-bridge/OmniLinkBridge.ini curl https://raw.githubusercontent.com/excaliburpartners/OmniLinkBridge/master/OmniLinkBridge/OmniLinkBridge.ini -o /opt/omnilink-bridge/OmniLinkBridge.ini
@ -61,7 +88,7 @@ docker run -d --name="omnilink-bridge" -v /opt/omnilink-bridge:/config -v /etc/l
docker logs omnilink-bridge docker logs omnilink-bridge
``` ```
## Docker (for developers) ## Docker for Developers
1. Clone git repo and build docker image 1. Clone git repo and build docker image
``` ```
git clone https://github.com/excaliburpartners/OmniLinkBridge.git git clone https://github.com/excaliburpartners/OmniLinkBridge.git
@ -296,107 +323,10 @@ POST /PushButton
{ "id":X, "value":1 } { "id":X, "value":1 }
``` ```
## MySQL Setup ## 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. The [MySQL ODBC Connector](http://dev.mysql.com/downloads/connector/odbc/) is required for MySQL logging. The docker image comes with the MySQL ODBC connector installed. For Windows and Linux you will need to download and install it.
http://dev.mysql.com/downloads/mysql/
http://dev.mysql.com/downloads/tools/workbench/
http://dev.mysql.com/downloads/connector/odbc/
At this point we need to open MySQL Workbench to create the database (called a schema in the Workbench GUI) for OmniLinkBridge to use.
1. After opening the program double-click on "Local instance MySQL" and enter the password you set in the wizard.
2. On the toolbar click the "Create a new schema" button, provide a name, and click apply.
3. On the left side right-click on the schema you created and click "Set as default schema".
4. In the middle section under Query1 click the open file icon and select the OmniLinkBridge.sql file.
5. Click the Execute lighting bolt to run the query, which will create the tables.
Lastly in OmniLinkBridge.ini set mysql_connection. This should get you up and running. The MySQL Workbench can also be used to view the data that OmniLink Bridge inserts into the tables.
Configure mysql_connection in OmniLinkBridge.ini. For Windows change DRIVER={MySQL} to name of the driver shown in the ODBC Data Source Administrator.
``` ```
mysql_connection = DRIVER={MySQL};SERVER=localhost;DATABASE=OmniLinkBridge;USER=root;PASSWORD=myPassword;OPTION=3; mysql_connection = DRIVER={MySQL};SERVER=localhost;DATABASE=OmniLinkBridge;USER=root;PASSWORD=myPassword;OPTION=3;
``` ```
## 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
- Utilize controller temperature format
- Don't publish invalid thermostat temperatures
- Always enable first area to support Omni LTe and Omni IIe
- Fix MQTT id validation and add notice for publishing to area 0
- Fix missing last area, zone, unit, thermostat, and button
- Fix compatibility with Home Assistant 0.95.4 MQTT extra keys
- Add Home Assistant MQTT device registry support
- Add MQTT messages for controller disconnect and last will
- Shutdown cleanly on linux or docker
Version 1.1.3 - 2019-02-10
- Publish config when reconnecting to MQTT
- Update readme documentation
- Add override zone type for web service
- Add area json status and climate temp sensor
- Fix compatibility with Home Assistant 0.87 MQTT strict config
Version 1.1.2 - 2018-10-23
- Add min and max climate temperatures
- Update docker run command to use local time zone
- Improve area and zone MQTT support
- Add option to change MQTT prefix to support multiple instances
- Add detailed zone sensor and thermostat humidity sensor
- Add prefix for MQTT discovery entity name
- Request zone status update on area status change
Version 1.1.1 - 2018-10-18
- Added docker support
- Save subscriptions on change
Version 1.1.0 - 2018-10-13
- Renamed to OmniLinkBridge
- Restructured code to be event based with modules
- Added MQTT module for Home Assistant
- Added pushover notifications
- Added web service API subscriptions file to persist subscriptions
Version 1.0.8 - 2016-11-28
- Fixed web service threading when multiple subscriptions exist
- Added additional zone types to contact and motion web service API
- Split command line options for config and log files
Version 1.0.7 - 2016-11-25
- Use previous area state when area is arming for web service API
- Add interactive command line option and use path separator for Mono compatibility
Version 1.0.6 - 2016-11-20
- Added thermostat status and auxiliary temp to web service API
Version 1.0.5 - 2016-11-15
- Added web service API for Samsung SmartThings integration
Version 1.0.4 - 2014-05-08
- Merged HAILogger.exe and HAILoggerService.exe
- Added immediate time sync after controller reconnect
Version 1.0.3 - 2013-01-06
- Added setting for prowl console message notification
- Added settings for verbose output control
- Added setting to enable mySQL logging
- Added queue to mySQL logging
- Changed mySQL log time from mySQL NOW() to computer time
- Changed prowl notifications to be asynchronous
- Fixed crash when prowl api down
- Fixed setting yes/no parsing so no setting works
- Fixed incorrect thermostat out of date status warning
Version 1.0.2 - 2012-12-30
- Fixed thermostat invalid mySQL logging error
Version 1.0.1 - 2012-12-30
- Added setting to adjust time sync interval
- Fixed crash when controller time not initially set
Version 1.0.0 - 2012-12-29
- Initial release