meeting-clock/MeetingClockManager.cs
Zechert, Frank (EXTERN: Capgemini) a8bd6c1e91 tried to avoid blocking by SEP
2020-12-20 15:35:05 +01:00

480 lines
13 KiB
C#

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO.Ports;
using System.Text;
using System.Timers;
using System.Windows.Forms;
namespace MeetingClock
{
public class MeetingClockManager
{
private const string MTC = "MTC";
public enum MeetingClockState
{
NotInitialized,
NoComPort,
Disconnected,
Connected
}
public MeetingClockState State { get; private set; } = MeetingClockState.NotInitialized;
public string Version { get; private set; }
public string Port {
get
{
if (this.serialPort != null && this.serialPort.IsOpen)
{
return this.serialPort.PortName;
}
return "";
}
}
public delegate void MeetingClockStateChangeHandler(MeetingClockManager manager, MeetingClockState oldState, MeetingClockState newState);
public event MeetingClockStateChangeHandler StateChanged;
private System.Timers.Timer startTimer;
private System.Timers.Timer checkTimer;
private BluetoothManager bluetoothManager;
private SerialPort serialPort;
public MeetingClockManager(BluetoothManager bluetoothManager)
{
this.NewSerialPort();
this.startTimer = new System.Timers.Timer(1000);
this.startTimer.AutoReset = false;
this.startTimer.Elapsed += ConnectTimer_Elapsed;
this.checkTimer = new System.Timers.Timer(30000);
this.checkTimer.AutoReset = false;
this.checkTimer.Elapsed += CheckTimer_Elapsed;
this.checkTimer.Start();
this.bluetoothManager = bluetoothManager;
this.bluetoothManager.StateChanged += BluetoothManager_StateChanged;
}
private void NewSerialPort() {
lock (this) {
if (this.serialPort != null)
{
try
{
this.serialPort.Close();
}
catch (Exception)
{
// ignored
}
}
this.serialPort = new SerialPort();
this.serialPort.BaudRate = 9600;
this.serialPort.Parity = Parity.None;
this.serialPort.DataBits = 8;
this.serialPort.StopBits = StopBits.One;
this.serialPort.Encoding = Encoding.GetEncoding("iso8859-1");
this.serialPort.ReadTimeout = 5000;
this.serialPort.WriteTimeout = 5000;
}
}
private void BluetoothManager_StateChanged(BluetoothManager manager, BluetoothManager.BluetoothState oldState, BluetoothManager.BluetoothState newState)
{
switch (newState)
{
case BluetoothManager.BluetoothState.On:
this.startTimer.Start();
break;
default:
this.Disconnect();
break;
}
}
private void ConnectTimer_Elapsed(object sender, ElapsedEventArgs e)
{
this.Connect();
}
private void Connect()
{
lock (this)
{
if (this.State == MeetingClockState.Connected && this.serialPort.IsOpen)
{
Debug.WriteLine("Meeting clock already connected. Not trying to connect again.");
return;
}
string[] portNames = SerialPort.GetPortNames();
if (portNames.Length == 0)
{
Debug.WriteLine("No COM ports are available at the moment.");
this.ChangeState(MeetingClockState.NoComPort);
return;
}
this.ChangeState(MeetingClockState.Disconnected);
this.NewSerialPort();
foreach (string portName in portNames)
{
Debug.WriteLine(String.Format("Trying to connect to {0}", portName));
try
{
this.serialPort.PortName = portName;
this.serialPort.Open();
if (this.Handshake())
{
Debug.WriteLine(String.Format("Successfully connected to meeting clock {0} on port {1}", this.Version, portName));
this.Adjust();
this.ScrollText("");
this.NextDate(DateTime.Now.AddMinutes(-5));
this.ChangeState(MeetingClockState.Connected);
return;
}
else
{
Debug.WriteLine(String.Format("Failed to connect to meeting clock on port {0}. Invalid Handshake.", portName));
}
}
catch (Exception exception)
{
Debug.WriteLine(String.Format("Failed to connect to meeting clock on port {0}. {1}", portName, exception.Message));
}
this.Disconnect();
}
}
}
private void Disconnect()
{
lock (this)
{
if (this.serialPort.IsOpen)
{
Debug.WriteLine(String.Format("Closing connection on port {0}", this.serialPort.PortName));
try
{
this.serialPort.Close();
}
catch (Exception)
{
// ignored
}
}
this.ChangeState(MeetingClockState.Disconnected);
this.NewSerialPort();
}
}
private bool Handshake()
{
string rx = this.SendAndReceive(MTC);
if (rx == null)
{
return false;
}
if (rx.StartsWith(MTC))
{
this.Version = rx.Substring(MTC.Length).Trim();
return true;
}
return false;
}
public void Adjust()
{
this.SendAndReceive(String.Format("ADJ {0}", DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss")));
}
private string SendAndReceive(string tx)
{
lock (this)
{
try
{
if (this.serialPort.IsOpen)
{
Debug.WriteLine(String.Format(">>> {0}", tx));
this.serialPort.WriteLine(tx);
string rx = this.serialPort.ReadLine().Trim();
Debug.WriteLine(String.Format("<<< {0}", rx));
return rx;
}
}
catch (Exception exception)
{
Debug.WriteLine(String.Format("Failed to send/receiv on port {0}. {1}", this.serialPort.PortName, exception.Message));
this.Disconnect();
}
return null;
}
}
private void ChangeState(MeetingClockState newState)
{
MeetingClockState oldState = this.State;
this.State = newState;
if (newState != oldState)
{
Debug.WriteLine("Meeting Clock state change detected. Old state: {0}, new state {1}.", oldState, newState);
if (this.StateChanged != null)
{
this.StateChanged(this, oldState, newState);
}
}
}
private void CheckTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (this.serialPort.IsOpen)
{
if (!this.Handshake())
{
this.Disconnect();
}
}
else if (this.bluetoothManager.State == BluetoothManager.BluetoothState.On)
{
this.Connect();
}
this.checkTimer.Start();
}
public void Stop()
{
this.Disconnect();
this.checkTimer.Stop();
this.startTimer.Stop();
}
public int? GetTimeInterval()
{
try
{
string rx = this.SendAndReceive("GET TI").Substring(7);
return int.Parse(rx);
}
catch (Exception)
{
return null;
}
}
public void SetTimeInterval(int value)
{
try
{
this.SendAndReceive("SET TI " + value);
}
catch (Exception)
{
}
}
public int? GetDateInterval()
{
try
{
string rx = this.SendAndReceive("GET DI").Substring(7);
return int.Parse(rx);
}
catch (Exception)
{
return null;
}
}
public void SetDateInterval(int value)
{
try
{
this.SendAndReceive("SET DI " + value);
}
catch (Exception)
{
}
}
public int? GetTemperatureInterval()
{
try
{
string rx = this.SendAndReceive("GET CI").Substring(7);
return int.Parse(rx);
}
catch (Exception)
{
return null;
}
}
public void SetTemperatureInterval(int value)
{
try
{
this.SendAndReceive("SET CI " + value);
}
catch (Exception)
{
}
}
public int? GetBrightness()
{
try
{
string rx = this.SendAndReceive("GET IN").Substring(7);
return int.Parse(rx);
}
catch (Exception)
{
return null;
}
}
public int? GetScrollSpeed()
{
try
{
string rx = this.SendAndReceive("GET SS").Substring(7);
return int.Parse(rx);
}
catch (Exception)
{
return null;
}
}
public int? GetScrollWait()
{
try
{
string rx = this.SendAndReceive("GET SW").Substring(7);
return int.Parse(rx);
}
catch (Exception)
{
return null;
}
}
public void SetBrightness(int value)
{
try
{
this.SendAndReceive("SET IN " + value);
}
catch (Exception)
{
}
}
public void SetScrollSpeed(int value)
{
try
{
this.SendAndReceive("SET SS " + value);
}
catch (Exception)
{
}
}
public void SetScrollWait(int value)
{
try
{
this.SendAndReceive("SET SW " + value);
}
catch (Exception)
{
}
}
public void ScrollText(string value)
{
try
{
this.SendAndReceive("SCR " + value);
}
catch (Exception)
{
}
}
public bool? GetDateEnabled()
{
try
{
string rx = this.SendAndReceive("GET DE").Substring(7);
return int.Parse(rx) > 0;
}
catch (Exception)
{
return null;
}
}
public void SetDateEnabled(bool value)
{
try
{
this.SendAndReceive("SET DE " + (value ? "1" : "0"));
}
catch (Exception)
{
}
}
public bool? GetTemperatureEnabled()
{
try
{
string rx = this.SendAndReceive("GET CE").Substring(7);
return int.Parse(rx) > 0;
}
catch (Exception)
{
return null;
}
}
public void SetTemperatureEnabled(bool value)
{
try
{
this.SendAndReceive("SET CE " + (value ? "1" : "0"));
}
catch (Exception)
{
}
}
internal void NextDate(DateTime value)
{
try
{
this.SendAndReceive("NXT " + value.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss"));
}
catch (Exception)
{
}
}
}
}