mirror of
https://github.com/excaliburpartners/OmniLinkBridge
synced 2024-12-22 18:52:24 +00:00
1.0.8 - 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
This commit is contained in:
parent
0d83ded2a4
commit
039f7d023c
|
@ -3,7 +3,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Data.Odbc;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
@ -44,14 +43,6 @@ namespace HAILogger
|
|||
|
||||
private void Server()
|
||||
{
|
||||
Global.event_log = "EventLog.txt";
|
||||
Global.event_source = "HAI Logger";
|
||||
|
||||
if (string.IsNullOrEmpty(Global.dir_config))
|
||||
Global.dir_config = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
|
||||
Settings.LoadSettings();
|
||||
|
||||
Event.WriteInfo("CoreServer", "Starting up server " +
|
||||
Assembly.GetExecutingAssembly().GetName().Version.ToString());
|
||||
|
||||
|
@ -784,10 +775,13 @@ namespace HAILogger
|
|||
case enuZoneType.X2EntryDelay:
|
||||
case enuZoneType.X4EntryDelay:
|
||||
case enuZoneType.Perimeter:
|
||||
case enuZoneType.Tamper:
|
||||
case enuZoneType.Auxiliary:
|
||||
WebNotification.Send("contact", Helper.Serialize<ZoneContract>(Helper.ConvertZone(
|
||||
MSG.ObjectNumber(i), HAC.Zones[MSG.ObjectNumber(i)])));
|
||||
break;
|
||||
case enuZoneType.AwayInt:
|
||||
case enuZoneType.NightInt:
|
||||
WebNotification.Send("motion", Helper.Serialize<ZoneContract>(Helper.ConvertZone(
|
||||
MSG.ObjectNumber(i), HAC.Zones[MSG.ObjectNumber(i)])));
|
||||
break;
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace HAILogger
|
|||
|
||||
try
|
||||
{
|
||||
FileStream fs = new FileStream(Global.dir_config + "\\" + Global.event_log, FileMode.Append, FileAccess.Write);
|
||||
FileStream fs = new FileStream(Global.log_file, FileMode.Append, FileAccess.Write);
|
||||
StreamWriter sw = new StreamWriter(fs);
|
||||
|
||||
sw.WriteLine(DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss ") + source + ": " + value);
|
||||
|
|
|
@ -4,12 +4,12 @@ namespace HAILogger
|
|||
{
|
||||
public abstract class Global
|
||||
{
|
||||
// Events Preset
|
||||
public static string event_log;
|
||||
// Events
|
||||
public static string event_source;
|
||||
|
||||
// Directories
|
||||
public static string dir_config;
|
||||
// Files
|
||||
public static string config_file;
|
||||
public static string log_file;
|
||||
|
||||
// HAI Controller
|
||||
public static string hai_address;
|
||||
|
|
|
@ -53,7 +53,9 @@ namespace HAILogger
|
|||
if ((zone.ZoneType == enuZoneType.EntryExit ||
|
||||
zone.ZoneType == enuZoneType.X2EntryDelay ||
|
||||
zone.ZoneType == enuZoneType.X4EntryDelay ||
|
||||
zone.ZoneType == enuZoneType.Perimeter) && zone.DefaultProperties == false)
|
||||
zone.ZoneType == enuZoneType.Perimeter ||
|
||||
zone.ZoneType == enuZoneType.Tamper ||
|
||||
zone.ZoneType == enuZoneType.Auxiliary) && zone.DefaultProperties == false)
|
||||
names.Add(new NameContract() { id = i, name = zone.Name });
|
||||
}
|
||||
return names;
|
||||
|
@ -68,7 +70,8 @@ namespace HAILogger
|
|||
{
|
||||
clsZone zone = WebService.HAC.Zones[i];
|
||||
|
||||
if (zone.ZoneType == enuZoneType.AwayInt && zone.DefaultProperties == false)
|
||||
if ((zone.ZoneType == enuZoneType.AwayInt ||
|
||||
zone.ZoneType == enuZoneType.NightInt) && zone.DefaultProperties == false)
|
||||
names.Add(new NameContract() { id = i, name = zone.Name });
|
||||
}
|
||||
return names;
|
||||
|
@ -152,9 +155,12 @@ namespace HAILogger
|
|||
case enuZoneType.X2EntryDelay:
|
||||
case enuZoneType.X4EntryDelay:
|
||||
case enuZoneType.Perimeter:
|
||||
case enuZoneType.Tamper:
|
||||
case enuZoneType.Auxiliary:
|
||||
ctx.OutgoingResponse.Headers.Add("type", "contact");
|
||||
break;
|
||||
case enuZoneType.AwayInt:
|
||||
case enuZoneType.NightInt:
|
||||
ctx.OutgoingResponse.Headers.Add("type", "motion");
|
||||
break;
|
||||
case enuZoneType.Water:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.ServiceProcess;
|
||||
|
||||
namespace HAILogger
|
||||
|
@ -22,7 +24,10 @@ namespace HAILogger
|
|||
ShowHelp();
|
||||
return;
|
||||
case "-c":
|
||||
Global.dir_config = args[++i];
|
||||
Global.config_file = args[++i];
|
||||
break;
|
||||
case "-l":
|
||||
Global.config_file = args[++i];
|
||||
break;
|
||||
case "-i":
|
||||
interactive = true;
|
||||
|
@ -30,6 +35,26 @@ namespace HAILogger
|
|||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(Global.log_file))
|
||||
Global.log_file = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) +
|
||||
Path.DirectorySeparatorChar + "EventLog.txt";
|
||||
|
||||
if (string.IsNullOrEmpty(Global.config_file))
|
||||
Global.config_file = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) +
|
||||
Path.DirectorySeparatorChar + "HAILogger.ini";
|
||||
|
||||
Global.event_source = "HAI Logger";
|
||||
|
||||
try
|
||||
{
|
||||
Settings.LoadSettings();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Errors are logged in LoadSettings();
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
if (Environment.UserInteractive || interactive)
|
||||
{
|
||||
Console.TreatControlCAsInput = false;
|
||||
|
@ -64,9 +89,10 @@ namespace HAILogger
|
|||
static void ShowHelp()
|
||||
{
|
||||
Console.WriteLine(
|
||||
AppDomain.CurrentDomain.FriendlyName + " [-c config_file] [-i]\n" +
|
||||
"\t-c Specifies the name of the config file. Default is HAILogger.ini.\n" +
|
||||
"\t-i Run in interactive mode.");
|
||||
AppDomain.CurrentDomain.FriendlyName + " [-c config_file] [-l log_file] [-i]\n" +
|
||||
"\t-c Specifies the name of the config file. Default is HAILogger.ini\n" +
|
||||
"\t-l Specifies the name of the log file. Default is EventLog.txt\n" +
|
||||
"\t-i Run in interactive mode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.7.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.7.0")]
|
||||
[assembly: AssemblyVersion("1.0.8.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.8.0")]
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace HAILogger
|
|||
{
|
||||
public static void LoadSettings()
|
||||
{
|
||||
NameValueCollection settings = LoadCollection(Global.dir_config + Path.DirectorySeparatorChar + "HAILogger.ini");
|
||||
NameValueCollection settings = LoadCollection(Global.config_file);
|
||||
|
||||
// HAI Controller
|
||||
Global.hai_address = settings["hai_address"];
|
||||
|
@ -62,10 +62,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid integer specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidateInt shouldn't reach here");
|
||||
}
|
||||
|
||||
private static int ValidatePort(NameValueCollection settings, string section)
|
||||
|
@ -82,10 +80,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid port specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidatePort shouldn't reach here");
|
||||
}
|
||||
|
||||
private static bool ValidateBool(NameValueCollection settings, string section)
|
||||
|
@ -97,10 +93,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid bool specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidateBool shouldn't reach here");
|
||||
}
|
||||
|
||||
private static IPAddress ValidateIP(NameValueCollection settings, string section)
|
||||
|
@ -118,10 +112,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid IP specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidateIP shouldn't reach here");
|
||||
}
|
||||
|
||||
private static string ValidateDirectory(NameValueCollection settings, string section)
|
||||
|
@ -136,10 +128,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid directory specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidateDirectory shouldn't reach here");
|
||||
}
|
||||
|
||||
private static MailAddress ValidateMailFrom(NameValueCollection settings, string section)
|
||||
|
@ -151,10 +141,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid email specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidateMailFrom shouldn't reach here");
|
||||
}
|
||||
|
||||
private static MailAddress[] ValidateMailTo(NameValueCollection settings, string section)
|
||||
|
@ -175,10 +163,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid email specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidateMailTo shouldn't reach here");
|
||||
}
|
||||
|
||||
private static string[] ValidateMultipleStrings(NameValueCollection settings, string section)
|
||||
|
@ -193,10 +179,8 @@ namespace HAILogger
|
|||
catch
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid string specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
throw new Exception("ValidateMultipleStrings shouldn't reach here");
|
||||
}
|
||||
|
||||
private static bool ValidateYesNo (NameValueCollection settings, string section)
|
||||
|
@ -210,10 +194,8 @@ namespace HAILogger
|
|||
else
|
||||
{
|
||||
Event.WriteError("Settings", "Invalid yes/no specified for " + section);
|
||||
Environment.Exit(1);
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
throw new Exception("ValidateYesNo shouldn't reach here");
|
||||
}
|
||||
|
||||
private static NameValueCollection LoadCollection(string sFile)
|
||||
|
@ -235,13 +217,15 @@ namespace HAILogger
|
|||
if (line.StartsWith("#"))
|
||||
continue;
|
||||
|
||||
string[] split = line.Split('=');
|
||||
int pos = line.IndexOf('=', 0);
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
split[i] = split[i].Trim();
|
||||
if (pos == -1)
|
||||
continue;
|
||||
|
||||
if (split.Length == 2)
|
||||
settings.Add(split[0], split[1]);
|
||||
string key = line.Substring(0, pos).Trim();
|
||||
string value = line.Substring(pos + 1).Trim();
|
||||
|
||||
settings.Add(key, value);
|
||||
}
|
||||
|
||||
sr.Close();
|
||||
|
@ -250,7 +234,7 @@ namespace HAILogger
|
|||
catch (FileNotFoundException)
|
||||
{
|
||||
Event.WriteError("Settings", "Unable to parse settings file " + sFile);
|
||||
Environment.Exit(1);
|
||||
throw;
|
||||
}
|
||||
|
||||
return settings;
|
||||
|
|
|
@ -7,25 +7,33 @@ namespace HAILogger
|
|||
static class WebNotification
|
||||
{
|
||||
private static List<string> subscriptions = new List<string>();
|
||||
private static object subscriptions_lock = new object();
|
||||
|
||||
public static void AddSubscription(string callback)
|
||||
{
|
||||
if (!subscriptions.Contains(callback))
|
||||
lock (subscriptions_lock)
|
||||
{
|
||||
Event.WriteVerbose("WebRequest", "Adding subscription to " + callback);
|
||||
subscriptions.Add(callback);
|
||||
if (!subscriptions.Contains(callback))
|
||||
{
|
||||
Event.WriteVerbose("WebNotification", "Adding subscription to " + callback);
|
||||
subscriptions.Add(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Send(string type, string body)
|
||||
{
|
||||
WebClient client = new WebClient();
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
client.Headers.Add("type", type);
|
||||
client.UploadStringCompleted += client_UploadStringCompleted;
|
||||
string[] send;
|
||||
lock (subscriptions_lock)
|
||||
send = subscriptions.ToArray();
|
||||
|
||||
foreach (string subscription in subscriptions)
|
||||
foreach (string subscription in send)
|
||||
{
|
||||
WebClient client = new WebClient();
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
client.Headers.Add("type", type);
|
||||
client.UploadStringCompleted += client_UploadStringCompleted;
|
||||
|
||||
try
|
||||
{
|
||||
client.UploadStringAsync(new Uri(subscription), "POST", body, subscription);
|
||||
|
@ -43,7 +51,9 @@ namespace HAILogger
|
|||
if (e.Error != null)
|
||||
{
|
||||
Event.WriteError("WebNotification", "An error occurred sending notification to " + e.UserState.ToString() + "\r\n" + e.Error.Message);
|
||||
subscriptions.Remove(e.UserState.ToString());
|
||||
|
||||
lock (subscriptions_lock)
|
||||
subscriptions.Remove(e.UserState.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
34
README.md
34
README.md
|
@ -2,7 +2,7 @@
|
|||
Provides logging and web service API for HAI/Leviton OmniPro II controllers
|
||||
|
||||
##Download
|
||||
You can download the [binary here](http://www.excalibur-partners.com/downloads/HAILogger_1_0_7.zip)
|
||||
You can download the [binary here](http://www.excalibur-partners.com/downloads/HAILogger_1_0_8.zip)
|
||||
|
||||
##Requirements
|
||||
- .NET Framework 4.0
|
||||
|
@ -20,12 +20,25 @@ You can download the [binary here](http://www.excalibur-partners.com/downloads/H
|
|||
- Emails are sent to mail_alarm_to when an area status changes
|
||||
- Prowl notifications are sent when an areas status changes
|
||||
|
||||
##Installation
|
||||
1. Copy files to your desiered location like C:\HAILogger
|
||||
2. Create mySQL database and import HAILogger.sql
|
||||
3. Update HAILogger.ini with settings
|
||||
4. Run HAILogger.exe and verify everything is working
|
||||
5. For Windows Service run install.bat / uninstall.bat
|
||||
##Installation Windows
|
||||
1. Copy files to your desired location like C:\HAILogger
|
||||
2. Edit HAILogger.ini and define at a minimum the controller IP and encryptions keys
|
||||
3. Run HAILogger.exe to verify connectivity
|
||||
4. For Windows Service run install.bat / uninstall.bat
|
||||
5. Start service from Administrative Tools -> Services
|
||||
|
||||
##Installation Linux
|
||||
1. Copy files to your desired location like /opt/HAILogger
|
||||
2. Configure at a minimum the controller IP and encryptions keys
|
||||
- vim HAILogger.ini
|
||||
3. Run as interactive to verify connectivity
|
||||
- ./HAILogger.exe -i
|
||||
4. Add systemd file and configure ExecStart path
|
||||
- cp hailogger.service /etc/systemd/system/
|
||||
- vim /etc/systemd/system/hailogger.service
|
||||
5. Enable at boot and start service
|
||||
- systemctl enable hailogger.service
|
||||
- systemctl start hailogger.service
|
||||
|
||||
##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 HAI Logger uses ODBC to communicate with the database. The MySQL ODBC Connector library is needed for Windows ODBC to communicate with MySQL. Make sure you install version 5.1 of the MySQL ODBC Connector provided in the link below.
|
||||
|
@ -37,7 +50,9 @@ http://dev.mysql.com/downloads/connector/odbc/5.1.html
|
|||
After installing MySQL server it should have asked you to setup an instance. One of the steps of the instance wizard was to create a root password. Assuming you installed the HAI Logger on the same computer you will want to use the below settings in HAILogger.ini.
|
||||
|
||||
mysql_server = localhost
|
||||
|
||||
mysql_user = root
|
||||
|
||||
mysql_password = password you set in the wizard
|
||||
|
||||
At this point we need to open MySQL Workbench to create the database (called a schema in the Workbench GUI) for HAILogger to use.
|
||||
|
@ -58,6 +73,11 @@ To test the API you can use your browser to view a page or PowerShell (see below
|
|||
- Invoke-WebRequest -Uri "http://localhost:8000/SetUnit" -Method POST -ContentType "application/json" -Body (convertto-json -InputObject @{"id"=1;"value"=100}) -UseBasicParsing
|
||||
|
||||
##Change Log
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue