diff --git a/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs b/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs index e71fa3b2..167b86cd 100644 --- a/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs +++ b/Essentials Core/PepperDashEssentialsBase/Crestron IO/IOPortConfig.cs @@ -10,6 +10,6 @@ namespace PepperDash.Essentials.Core.CrestronIO { public string PortDeviceKey { get; set; } public uint PortNumber { get; set; } + public bool DisablePullUpResistor { get; set; } } - } \ No newline at end of file diff --git a/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs b/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs index 749957b9..37f978a1 100644 --- a/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs +++ b/Essentials Core/PepperDashEssentialsBase/Crestron IO/Inputs/GenericVersiportInputDevice.cs @@ -12,7 +12,7 @@ namespace PepperDash.Essentials.Core.CrestronIO /// /// Represents a generic digital input deviced tied to a versiport /// - public class GenericVersiportInputDevice : Device, IDigitalInput + public class GenericVersiportDigitalInputDevice : Device, IDigitalInput { public Versiport InputPort { get; private set; } @@ -26,25 +26,25 @@ namespace PepperDash.Essentials.Core.CrestronIO } } - public GenericVersiportInputDevice(string key, Versiport inputPort): + public GenericVersiportDigitalInputDevice(string key, Versiport inputPort, IOPortConfig props): base(key) { InputStateFeedback = new BoolFeedback(InputStateFeedbackFunc); InputPort = inputPort; - InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); + InputPort.SetVersiportConfiguration(eVersiportConfiguration.DigitalInput); + if (props.DisablePullUpResistor) + InputPort.DisablePullUpResistor = true; InputPort.VersiportChange += new VersiportEventHandler(InputPort_VersiportChange); + + Debug.Console(1, this, "Created GenericVersiportDigitalInputDevice on port '{0}'. DisablePullUpResistor: '{1}'", props.PortNumber, InputPort.DisablePullUpResistor); } void InputPort_VersiportChange(Versiport port, VersiportEventArgs args) { Debug.Console(1, this, "Versiport change: {0}", args.Event); - InputStateFeedback.FireUpdate(); + + if(args.Event == eVersiportEvent.DigitalInChange) + InputStateFeedback.FireUpdate(); } } - - public class GenericVersiportInputDeviceConfigProperties - { - - } - } \ No newline at end of file diff --git a/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs b/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs index 04ccf5c3..ac88f0d7 100644 --- a/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs +++ b/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs @@ -42,9 +42,9 @@ namespace PepperDash.Essentials.Core var response = Hardware.RegisterWithLogging(Key); if (response != eDeviceRegistrationUnRegistrationResponse.Success) { - Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); - return false; - } + Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); + return false; + } Hardware.OnlineStatusChange += new OnlineStatusChangeEventHandler(Hardware_OnlineStatusChange); CommunicationMonitor.Start(); diff --git a/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs.orig b/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs.orig new file mode 100644 index 00000000..416cc553 --- /dev/null +++ b/Essentials Core/PepperDashEssentialsBase/Crestron/CrestronGenericBaseDevice.cs.orig @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; + +using PepperDash.Core; + +namespace PepperDash.Essentials.Core +{ + /// + /// A bridge class to cover the basic features of GenericBase hardware + /// + public class CrestronGenericBaseDevice : Device, IOnline, IHasFeedback, ICommunicationMonitor, IUsageTracking + { + public virtual GenericBase Hardware { get; protected set; } + + public BoolFeedback IsOnline { get; private set; } + public BoolFeedback IsRegistered { get; private set; } + public StringFeedback IpConnectionsText { get; private set; } + + public CrestronGenericBaseDevice(string key, string name, GenericBase hardware) + : base(key, name) + { + Hardware = hardware; + IsOnline = new BoolFeedback(CommonBoolCue.IsOnlineFeedback, () => Hardware.IsOnline); + IsRegistered = new BoolFeedback(new Cue("IsRegistered", 0, eCueType.Bool), () => Hardware.Registered); + IpConnectionsText = new StringFeedback(CommonStringCue.IpConnectionsText, () => + string.Join(",", Hardware.ConnectedIpList.Select(cip => cip.DeviceIpAddress).ToArray())); + CommunicationMonitor = new CrestronGenericBaseCommunicationMonitor(this, hardware, 120000, 300000); + } + + /// + /// Make sure that overriding classes call this! + /// Registers the Crestron device, connects up to the base events, starts communication monitor + /// + public override bool CustomActivate() + { + Debug.Console(0, this, "Activating"); + var response = Hardware.RegisterWithLogging(Key); + if (response != eDeviceRegistrationUnRegistrationResponse.Success) + { +<<<<<<< HEAD + Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); + return false; + } +======= + Debug.Console(0, this, "ERROR: Cannot register Crestron device: {0}", response); + return false; + } +>>>>>>> origin/feature/ecs-342-neil + Hardware.OnlineStatusChange += new OnlineStatusChangeEventHandler(Hardware_OnlineStatusChange); + CommunicationMonitor.Start(); + + return true; + } + + /// + /// This disconnects events and unregisters the base hardware device. + /// + /// + public override bool Deactivate() + { + CommunicationMonitor.Stop(); + Hardware.OnlineStatusChange -= Hardware_OnlineStatusChange; + + return Hardware.UnRegister() == eDeviceRegistrationUnRegistrationResponse.Success; + } + + /// + /// Returns a list containing the Outputs that we want to expose. + /// + public virtual List Feedbacks + { + get + { + return new List + { + IsOnline, + IsRegistered, + IpConnectionsText + }; + } + } + + void Hardware_OnlineStatusChange(GenericBase currentDevice, OnlineOfflineEventArgs args) + { + IsOnline.FireUpdate(); + } + + #region IStatusMonitor Members + + public StatusMonitorBase CommunicationMonitor { get; private set; } + #endregion + + #region IUsageTracking Members + + public UsageTracking UsageTracker { get; set; } + + #endregion + } + + //*********************************************************************************** + public class CrestronGenericBaseDeviceEventIds + { + public const uint IsOnline = 1; + public const uint IpConnectionsText =2; + } + + /// + /// Adds logging to Register() failure + /// + public static class GenericBaseExtensions + { + public static eDeviceRegistrationUnRegistrationResponse RegisterWithLogging(this GenericBase device, string key) + { + var result = device.Register(); + if (result != eDeviceRegistrationUnRegistrationResponse.Success) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, "Cannot register device '{0}': {1}", key, result); + } + return result; + } + + } +} \ No newline at end of file diff --git a/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs.orig b/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs.orig new file mode 100644 index 00000000..e768807b --- /dev/null +++ b/Essentials Core/PepperDashEssentialsBase/Devices/DeviceManager.cs.orig @@ -0,0 +1,253 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.EthernetCommunication; +using Crestron.SimplSharpPro.UI; +using Crestron.SimplSharp.Reflection; + +using PepperDash.Core; + + +namespace PepperDash.Essentials.Core +{ + public static class DeviceManager + { + //public static List Devices { get { return _Devices; } } + //static List _Devices = new List(); + + static Dictionary Devices = new Dictionary(StringComparer.OrdinalIgnoreCase); + + /// + /// Returns a copy of all the devices in a list + /// + public static List AllDevices { get { return new List(Devices.Values); } } + + public static void Initialize(CrestronControlSystem cs) + { + CrestronConsole.AddNewConsoleCommand(ListDeviceCommStatuses, "devcommstatus", "Lists the communication status of all devices", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ListDeviceFeedbacks, "devfb", "Lists current feedbacks", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(ListDevices, "devlist", "Lists current managed devices", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(DeviceJsonApi.DoDeviceActionWithJson, "devjson", "", + ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + { + CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetProperties(s)); + }, "devprops", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + { + CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetMethods(s)); + }, "devmethods", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + { + CrestronConsole.ConsoleCommandResponse(DeviceJsonApi.GetApiMethods(s)); + }, "apimethods", "", ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(SimulateComReceiveOnDevice, "devsimreceive", + "Simulates incoming data on a com device", ConsoleAccessLevelEnum.AccessOperator); + } + + /// + /// Calls activate on all Device class items + /// + public static void ActivateAll() + { + foreach (var d in Devices.Values) +<<<<<<< HEAD + { + try + { + if (d is Device) + (d as Device).Activate(); + } + catch (Exception e) + { + Debug.Console(0, d, "ERROR: Device activation failure:\r{0}", e); + } + } +======= + { + try + { + if (d is Device) + (d as Device).Activate(); + } + catch (Exception e) + { + Debug.Console(0, d, "ERROR: Device activation failure:\r{0}", e); + } + } +>>>>>>> origin/feature/ecs-342-neil + } + + /// + /// Calls activate on all Device class items + /// + public static void DeactivateAll() + { + foreach (var d in Devices.Values) + { + if (d is Device) + (d as Device).Deactivate(); + } + } + + //static void ListMethods(string devKey) + //{ + // var dev = GetDeviceForKey(devKey); + // if(dev != null) + // { + // var type = dev.GetType().GetCType(); + // var methods = type.GetMethods(BindingFlags.Public|BindingFlags.Instance); + // var sb = new StringBuilder(); + // sb.AppendLine(string.Format("{2} methods on [{0}] ({1}):", dev.Key, type.Name, methods.Length)); + // foreach (var m in methods) + // { + // sb.Append(string.Format("{0}(", m.Name)); + // var pars = m.GetParameters(); + // foreach (var p in pars) + // sb.Append(string.Format("({1}){0} ", p.Name, p.ParameterType.Name)); + // sb.AppendLine(")"); + // } + // CrestronConsole.ConsoleCommandResponse(sb.ToString()); + // } + //} + + static void ListDevices(string s) + { + Debug.Console(0, "{0} Devices registered with Device Mangager:",Devices.Count); + var sorted = Devices.Values.ToList(); + sorted.Sort((a, b) => a.Key.CompareTo(b.Key)); + + foreach (var d in sorted) + { + var name = d is IKeyName ? (d as IKeyName).Name : "---"; + Debug.Console(0, " [{0}] {1}", d.Key, name); + } + } + + static void ListDeviceFeedbacks(string devKey) + { + var dev = GetDeviceForKey(devKey); + if(dev == null) + { + Debug.Console(0, "Device '{0}' not found", devKey); + return; + } + var statusDev = dev as IHasFeedback; + if(statusDev == null) + { + Debug.Console(0, "Device '{0}' does not have visible feedbacks", devKey); + return; + } + statusDev.DumpFeedbacksToConsole(true); + } + + //static void ListDeviceCommands(string devKey) + //{ + // var dev = GetDeviceForKey(devKey); + // if (dev == null) + // { + // Debug.Console(0, "Device '{0}' not found", devKey); + // return; + // } + // Debug.Console(0, "This needs to be reworked. Stay tuned.", devKey); + //} + + static void ListDeviceCommStatuses(string input) + { + var sb = new StringBuilder(); + foreach (var dev in Devices.Values) + { + if (dev is ICommunicationMonitor) + sb.Append(string.Format("{0}: {1}\r", dev.Key, (dev as ICommunicationMonitor).CommunicationMonitor.Status)); + } + CrestronConsole.ConsoleCommandResponse(sb.ToString()); + } + + + //static void DoDeviceCommand(string command) + //{ + // Debug.Console(0, "Not yet implemented. Stay tuned"); + //} + + public static void AddDevice(IKeyed newDev) + { + // Check for device with same key + //var existingDevice = _Devices.FirstOrDefault(d => d.Key.Equals(newDev.Key, StringComparison.OrdinalIgnoreCase)); + ////// If it exists, remove or warn?? + //if (existingDevice != null) + if(Devices.ContainsKey(newDev.Key)) + { + Debug.Console(0, newDev, "WARNING: A device with this key already exists. Not added to manager"); + return; + } + Devices.Add(newDev.Key, newDev); + //if (!(_Devices.Contains(newDev))) + // _Devices.Add(newDev); + } + + public static void RemoveDevice(IKeyed newDev) + { + if(newDev == null) + return; + if (Devices.ContainsKey(newDev.Key)) + Devices.Remove(newDev.Key); + //if (_Devices.Contains(newDev)) + // _Devices.Remove(newDev); + else + Debug.Console(0, "Device manager: Device '{0}' does not exist in manager. Cannot remove", newDev.Key); + } + + public static IEnumerable GetDeviceKeys() + { + //return _Devices.Select(d => d.Key).ToList(); + return Devices.Keys; + } + + public static IEnumerable GetDevices() + { + //return _Devices.Select(d => d.Key).ToList(); + return Devices.Values; + } + + public static IKeyed GetDeviceForKey(string key) + { + //return _Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); + if (key != null && Devices.ContainsKey(key)) + return Devices[key]; + + return null; + } + + /// + /// Console handler that simulates com port data receive + /// + /// + public static void SimulateComReceiveOnDevice(string s) + { + // devcomsim:1 xyzabc + var match = Regex.Match(s, @"(\S*)\s*(.*)"); + if (match.Groups.Count < 3) + { + CrestronConsole.ConsoleCommandResponse(" Format: devsimreceive:P "); + return; + } + //Debug.Console(2, "**** {0} - {1} ****", match.Groups[1].Value, match.Groups[2].Value); + + ComPortController com = GetDeviceForKey(match.Groups[1].Value) as ComPortController; + if (com == null) + { + CrestronConsole.ConsoleCommandResponse("'{0}' is not a comm port device", match.Groups[1].Value); + return; + } + com.SimulateReceive(match.Groups[2].Value); + } + } +} \ No newline at end of file diff --git a/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs b/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs index 3d9b4316..74bb76c2 100644 --- a/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs +++ b/Essentials Devices Common/Essentials Devices Common/Factory/DeviceFactory.cs @@ -177,28 +177,10 @@ namespace PepperDash.Essentials.Devices.Common return null; } - if (cs.SupportsDigitalInput) + if (cs.SupportsVersiport) { - if (props.PortNumber > cs.NumberOfDigitalInputPorts) - { - Debug.Console(0, "WARNING: Cannot register DIO port {0} on {1}. Out of range", - props.PortNumber, props.PortDeviceKey); - return null; - } + Debug.Console(1, "Attempting to add Digital Input device to Versiport port '{0}'", props.PortNumber); - DigitalInput digitalInput = cs.DigitalInputPorts[props.PortNumber]; - - if (!digitalInput.Registered) - { - if (digitalInput.Register() == eDeviceRegistrationUnRegistrationResponse.Success) - return new GenericDigitalInputDevice(key, digitalInput); - else - Debug.Console(0, "WARNING: Attempt to register digital input {0} on device with key '{1}' failed.", - props.PortNumber, props.PortDeviceKey); - } - } - else if (cs.SupportsVersiport) - { if (props.PortNumber > cs.NumberOfVersiPorts) { Debug.Console(0, "WARNING: Cannot add Vesiport {0} on {1}. Out of range", @@ -212,8 +194,9 @@ namespace PepperDash.Essentials.Devices.Common { var regSuccess = vp.Register(); if (regSuccess == eDeviceRegistrationUnRegistrationResponse.Success) - { - return new GenericVersiportInputDevice(key, vp); + { + Debug.Console(1, "Successfully Created Digital Input Device on Versiport"); + return new GenericVersiportDigitalInputDevice(key, vp, props); } else { @@ -223,6 +206,31 @@ namespace PepperDash.Essentials.Devices.Common } } } + else if (cs.SupportsDigitalInput) + { + Debug.Console(1, "Attempting to add Digital Input device to Digital Input port '{0}'", props.PortNumber); + + if (props.PortNumber > cs.NumberOfDigitalInputPorts) + { + Debug.Console(0, "WARNING: Cannot register DIO port {0} on {1}. Out of range", + props.PortNumber, props.PortDeviceKey); + return null; + } + + DigitalInput digitalInput = cs.DigitalInputPorts[props.PortNumber]; + + if (!digitalInput.Registered) + { + if (digitalInput.Register() == eDeviceRegistrationUnRegistrationResponse.Success) + { + Debug.Console(1, "Successfully Created Digital Input Device on Digital Input"); + return new GenericDigitalInputDevice(key, digitalInput); + } + else + Debug.Console(0, "WARNING: Attempt to register digital input {0} on device with key '{1}' failed.", + props.PortNumber, props.PortDeviceKey); + } + } } } @@ -243,14 +251,14 @@ namespace PepperDash.Essentials.Devices.Common { var cs = (portDevice as CrestronControlSystem); - if(cs != null) + if (cs != null) if (cs.SupportsRelay && props.PortNumber <= cs.NumberOfRelayPorts) { Relay relay = cs.RelayPorts[props.PortNumber]; if (!relay.Registered) { - if(relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success) + if (relay.Register() == eDeviceRegistrationUnRegistrationResponse.Success) return new GenericRelayDevice(key, relay); else Debug.Console(0, "Attempt to register relay {0} on device with key '{1}' failed.", props.PortNumber, props.PortDeviceKey); @@ -290,7 +298,7 @@ namespace PepperDash.Essentials.Devices.Common else if (typeName == "occsensor") { var props = JsonConvert.DeserializeObject(properties.ToString()); - + uint id = 0x00; GlsOccupancySensorBase occSensor = null; diff --git a/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs b/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs index 86daf926..05425970 100644 --- a/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs +++ b/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs @@ -16,18 +16,16 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy public BoolFeedback RoomIsOccupiedFeedback { get; private set; } - /// - /// Set by debugging functions - /// - public bool InMockMode { get; private set; } + // Debug properties + public bool InTestMode { get; private set; } - public bool MockRoomIsOccupiedFeedback { get; private set; } + public bool TestRoomIsOccupiedFeedback { get; private set; } public Func RoomIsOccupiedFeedbackFunc { get { - return () => InMockMode ? MockRoomIsOccupiedFeedback : OccSensor.OccupancyDetectedFeedback.BoolValue; + return () => InTestMode ? TestRoomIsOccupiedFeedback : OccSensor.OccupancyDetectedFeedback.BoolValue; } } @@ -44,6 +42,25 @@ namespace PepperDash.Essentials.Devices.Common.Occupancy { RoomIsOccupiedFeedback.FireUpdate(); } + + public void SetTestMode(bool mode) + { + InTestMode = mode; + + Debug.Console(1, this, "In Mock Mode: '{0}'", InTestMode); + } + + public void SetTestOccupiedState(bool state) + { + if (!InTestMode) + Debug.Console(1, "Mock mode not enabled"); + else + { + TestRoomIsOccupiedFeedback = state; + + RoomIsOccupiedFeedback.FireUpdate(); + } + } } /// diff --git a/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs.orig b/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs.orig new file mode 100644 index 00000000..f65e1b37 --- /dev/null +++ b/Essentials Devices Common/Essentials Devices Common/Occupancy/EssentialsGlsOccupancySensorBaseController.cs.orig @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro.GeneralIO; + +using PepperDash.Core; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Devices.Common.Occupancy +{ + public class EssentialsGlsOccupancySensorBaseController : CrestronGenericBaseDevice, IOccupancyStatusProvider + { + public GlsOccupancySensorBase OccSensor { get; private set; } + + public BoolFeedback RoomIsOccupiedFeedback { get; private set; } + +<<<<<<< HEAD + /// + /// Set by debugging functions + /// + public bool InMockMode { get; private set; } + + public bool MockRoomIsOccupiedFeedback { get; private set; } +======= + // Debug properties + public bool InTestMode { get; private set; } + + public bool TestRoomIsOccupiedFeedback { get; private set; } +>>>>>>> origin/feature/ecs-342-neil + + public Func RoomIsOccupiedFeedbackFunc + { + get + { +<<<<<<< HEAD + return () => InMockMode ? MockRoomIsOccupiedFeedback : OccSensor.OccupancyDetectedFeedback.BoolValue; +======= + return () => InTestMode ? TestRoomIsOccupiedFeedback : OccSensor.OccupancyDetectedFeedback.BoolValue; +>>>>>>> origin/feature/ecs-342-neil + } + } + + public EssentialsGlsOccupancySensorBaseController(string key, string name, GlsOccupancySensorBase sensor, GlsOccupancySensorConfigurationProperties props) + : base(key, name, sensor) + { + OccSensor = sensor; + RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc); + + OccSensor.GlsOccupancySensorChange += new GlsOccupancySensorChangeEventHandler(sensor_GlsOccupancySensorChange); + } + + void sensor_GlsOccupancySensorChange(GlsOccupancySensorBase device, GlsOccupancySensorChangeEventArgs args) + { + RoomIsOccupiedFeedback.FireUpdate(); + } + + public void SetTestMode(bool mode) + { + InTestMode = mode; + + Debug.Console(1, this, "In Mock Mode: '{0}'", InTestMode); + } + + public void SetTestOccupiedState(bool state) + { + if (!InTestMode) + Debug.Console(1, "Mock mode not enabled"); + else + { + TestRoomIsOccupiedFeedback = state; + + RoomIsOccupiedFeedback.FireUpdate(); + } + } + } + + /// + /// + /// + public class GlsOccupancySensorConfigurationProperties + { + public string CresnetId { get; set; } + public string Model { get; set; } + } +} \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/ControlSystem.cs b/Essentials/PepperDashEssentials/ControlSystem.cs index 57c10aba..dc549ece 100644 --- a/Essentials/PepperDashEssentials/ControlSystem.cs +++ b/Essentials/PepperDashEssentials/ControlSystem.cs @@ -32,7 +32,7 @@ namespace PepperDash.Essentials public override void InitializeSystem() { //CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Reloads configuration file", - // ConsoleAccessLevelEnum.AccessOperator); + //ConsoleAccessLevelEnum.AccessOperator); //CrestronConsole.AddNewConsoleCommand(s => TearDown(), "ungo", "Unloads configuration file", // ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => diff --git a/Essentials/PepperDashEssentials/ControlSystem.cs.orig b/Essentials/PepperDashEssentials/ControlSystem.cs.orig new file mode 100644 index 00000000..b35f6e47 --- /dev/null +++ b/Essentials/PepperDashEssentials/ControlSystem.cs.orig @@ -0,0 +1,276 @@ +using System; +using System.Linq; +using Crestron.SimplSharp; +using Crestron.SimplSharp.CrestronIO; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.CrestronThread; +using PepperDash.Core; +using PepperDash.Core.PortalSync; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Devices.Common; +using PepperDash.Essentials.DM; +using PepperDash.Essentials.Fusion; + +namespace PepperDash.Essentials +{ + public class ControlSystem : CrestronControlSystem + { + PepperDashPortalSyncClient PortalSync; + HttpLogoServer LogoServer; + + public ControlSystem() + : base() + { + Thread.MaxNumberOfUserThreads = 400; + Global.ControlSystem = this; + DeviceManager.Initialize(this); + } + + /// + /// Git 'er goin' + /// + public override void InitializeSystem() + { + //CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Reloads configuration file", + //ConsoleAccessLevelEnum.AccessOperator); + //CrestronConsole.AddNewConsoleCommand(s => TearDown(), "ungo", "Unloads configuration file", + // ConsoleAccessLevelEnum.AccessOperator); + CrestronConsole.AddNewConsoleCommand(s => + { + foreach (var tl in TieLineCollection.Default) + CrestronConsole.ConsoleCommandResponse(" {0}\r", tl); + }, + "listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator); + + GoWithLoad(); + } + + /// + /// Do it, yo + /// + public void GoWithLoad() + { + try + { + CrestronConsole.AddNewConsoleCommand(EnablePortalSync, "portalsync", "Loads Portal Sync", + ConsoleAccessLevelEnum.AccessOperator); + + //PortalSync = new PepperDashPortalSyncClient(); + + Debug.Console(0, "Starting Essentials load from configuration"); + + var filesReady = SetupFilesystem(); + if (filesReady) + { + Debug.Console(0, "Folder structure verified. Loading config..."); + if (!ConfigReader.LoadConfig2()) + return; + + Load(); +<<<<<<< HEAD +======= + +>>>>>>> origin/feature/ecs-342-neil + Debug.Console(0, "Essentials load complete\r" + + "-------------------------------------------------------------"); + } + else + { + Debug.Console(0, + "------------------------------------------------\r" + + "------------------------------------------------\r" + + "------------------------------------------------\r" + + "Essentials file structure setup completed.\r" + + "Please load config, sgd and ir files and\r" + + "restart program.\r" + + "------------------------------------------------\r" + + "------------------------------------------------\r" + + "------------------------------------------------"); + } + } + catch (Exception e) + { + Debug.Console(0, "FATAL INITIALIZE ERROR. System is in an inconsistent state:\r{0}", e); + } + + } + + /// + /// Verifies filesystem is set up. IR, SGD, and program1 folders + /// + bool SetupFilesystem() + { + Debug.Console(0, "Verifying and/or creating folder structure"); + var appNum = InitialParametersClass.ApplicationNumber; + var configDir = @"\NVRAM\Program" + appNum; + var configExists = Directory.Exists(configDir); + if (!configExists) + Directory.Create(configDir); + + var irDir = string.Format(@"\NVRAM\Program{0}\ir", appNum); + if (!Directory.Exists(irDir)) + Directory.Create(irDir); + + var sgdDir = string.Format(@"\NVRAM\Program{0}\sgd", appNum); + if (!Directory.Exists(sgdDir)) + Directory.Create(sgdDir); + + return configExists; + } + + public void EnablePortalSync(string s) + { + if (s.ToLower() == "enable") + { + CrestronConsole.ConsoleCommandResponse("Portal Sync features enabled"); + PortalSync = new PepperDashPortalSyncClient(); + } + } + + public void TearDown() + { + Debug.Console(0, "Tearing down existing system"); + DeviceManager.DeactivateAll(); + + TieLineCollection.Default.Clear(); + + foreach (var key in DeviceManager.GetDevices()) + DeviceManager.RemoveDevice(key); + + Debug.Console(0, "Tear down COMPLETE"); + } + + /// + /// + /// + void Load() + { + LoadDevices(); + LoadTieLines(); + LoadRooms(); + LoadLogoServer(); + +<<<<<<< HEAD + DeviceManager.ActivateAll(); +======= + DeviceManager.ActivateAll(); +>>>>>>> origin/feature/ecs-342-neil + } + + + /// + /// Reads all devices from config and adds them to DeviceManager + /// + public void LoadDevices() + { + foreach (var devConf in ConfigReader.ConfigObject.Devices) + { + + try + { + Debug.Console(0, "Creating device '{0}'", devConf.Key); + // Skip this to prevent unnecessary warnings + if (devConf.Key == "processor") + continue; + + // Try local factory first + var newDev = DeviceFactory.GetDevice(devConf); + + // Then associated library factories + if (newDev == null) + newDev = PepperDash.Essentials.Devices.Common.DeviceFactory.GetDevice(devConf); + if (newDev == null) + newDev = PepperDash.Essentials.DM.DeviceFactory.GetDevice(devConf); + if (newDev == null) + newDev = PepperDash.Essentials.Devices.Displays.DisplayDeviceFactory.GetDevice(devConf); + + if (newDev != null) + DeviceManager.AddDevice(newDev); + else + Debug.Console(0, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key); + } + catch (Exception e) + { + Debug.Console(0, "ERROR: Creating device {0}. Skipping device. \r{1}", devConf.Key, e); + } + } + } + + /// + /// Helper method to load tie lines. This should run after devices have loaded + /// + public void LoadTieLines() + { + // In the future, we can't necessarily just clear here because devices + // might be making their own internal sources/tie lines + + var tlc = TieLineCollection.Default; + //tlc.Clear(); + foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines) + { + var newTL = tieLineConfig.GetTieLine(); + if (newTL != null) + tlc.Add(newTL); + } + } + + /// + /// Reads all rooms from config and adds them to DeviceManager + /// + public void LoadRooms() + { + foreach (var roomConfig in ConfigReader.ConfigObject.Rooms) + { + var room = roomConfig.GetRoomObject(); + if (room != null) + { + if (room is EssentialsHuddleSpaceRoom) + { + DeviceManager.AddDevice(room); + + Debug.Console(1, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion"); + DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemControllerBase((EssentialsHuddleSpaceRoom)room, 0xf1)); + + var cotija = DeviceManager.GetDeviceForKey("cotijaServer") as CotijaSystemController; + + if (cotija != null) + { + cotija.CotijaRooms.Add(new CotijaEssentialsHuddleSpaceRoomBridge(cotija, room as EssentialsHuddleSpaceRoom)); + } + } + else if (room is EssentialsHuddleVtc1Room) + { + DeviceManager.AddDevice(room); + + Debug.Console(1, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion"); + DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1)); + } + else + { + Debug.Console(1, "Room is NOT EssentialsHuddleSpaceRoom, attempting to add to DeviceManager w/o Fusion"); + DeviceManager.AddDevice(room); + } + + } + else + Debug.Console(0, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key); + } + } + + /// + /// Fires up a logo server if not already running + /// + void LoadLogoServer() + { + + try + { + LogoServer = new HttpLogoServer(8080, @"\html\logo"); + } + catch (Exception) + { + Debug.Console(0, "NOTICE: Logo server cannot be started. Likely already running in another program"); + } + } + } +} diff --git a/Essentials/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs b/Essentials/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs index b2c9eac0..ce70e381 100644 --- a/Essentials/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs +++ b/Essentials/PepperDashEssentials/OTHER/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs @@ -1208,14 +1208,23 @@ namespace PepperDash.Essentials.Fusion { RoomIsOccupiedFeedback = new BoolFeedback(RoomIsOccupiedFeedbackFunc); + FusionRoom.FusionAssetStateChange += new FusionAssetStateEventHandler(FusionRoom_FusionAssetStateChange); + // Build Occupancy Asset? // Link sigs? - Room.SetRoomOccupancy(this); + //Room.SetRoomOccupancy(this as IOccupancyStatusProvider, 0); } + void FusionRoom_FusionAssetStateChange(FusionBase device, FusionAssetStateEventArgs args) + { + if (args.EventId == FusionAssetEventId.RoomOccupiedReceivedEventId || args.EventId == FusionAssetEventId.RoomUnoccupiedReceivedEventId) + RoomIsOccupiedFeedback.FireUpdate(); + + } + /// /// Sets up remote occupancy that will relay the occupancy status determined by local system devices to Fusion /// diff --git a/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs b/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs index c1a0c2de..bb3fc49d 100644 --- a/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs +++ b/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs @@ -4,5 +4,5 @@ [assembly: AssemblyCompany("PepperDash Technology Corp")] [assembly: AssemblyProduct("PepperDashEssentials")] [assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")] -[assembly: AssemblyVersion("1.0.31.*")] +[assembly: AssemblyVersion("1.0.33.*")] diff --git a/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs.orig b/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs.orig index 880729f5..3f9c87ad 100644 --- a/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs.orig +++ b/Essentials/PepperDashEssentials/Properties/AssemblyInfo.cs.orig @@ -5,8 +5,8 @@ [assembly: AssemblyProduct("PepperDashEssentials")] [assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")] <<<<<<< HEAD -[assembly: AssemblyVersion("1.0.8.*")] +[assembly: AssemblyVersion("1.0.31.*")] ======= -[assembly: AssemblyVersion("1.0.10.*")] ->>>>>>> development +[assembly: AssemblyVersion("1.0.33.*")] +>>>>>>> origin/feature/ecs-342-neil diff --git a/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index cce57191..54f5a959 100644 --- a/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/Essentials/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -29,6 +29,10 @@ namespace PepperDash.Essentials.Room.Config var disp = DeviceManager.GetDeviceForKey(props.DefaultDisplayKey) as IRoutingSinkWithSwitching; var audio = DeviceManager.GetDeviceForKey(props.DefaultAudioKey) as IRoutingSinkNoSwitching; var huddle = new EssentialsHuddleSpaceRoom(Key, Name, disp, audio, props); + + if (props.Occupancy != null) + huddle.SetRoomOccupancy(DeviceManager.GetDeviceForKey(props.Occupancy.DeviceKey) as + PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider, props.Occupancy.TimoutMinutes); huddle.LogoUrl = props.Logo.GetUrl(); huddle.SourceListKey = props.SourceListKey; huddle.DefaultSourceItem = props.DefaultSourceItem; @@ -67,8 +71,8 @@ namespace PepperDash.Essentials.Room.Config // Add Occupancy object from config if (props.Occupancy != null) - rm.SetRoomOccupancy(DeviceManager.GetDeviceForKey(props.Occupancy.DeviceKey) as - PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider); + rm.SetRoomOccupancy(DeviceManager.GetDeviceForKey(props.Occupancy.DeviceKey) as + PepperDash.Essentials.Devices.Common.Occupancy.IOccupancyStatusProvider, props.Occupancy.TimoutMinutes); rm.LogoUrl = props.Logo.GetUrl(); rm.SourceListKey = props.SourceListKey; rm.DefaultSourceItem = props.DefaultSourceItem; @@ -252,7 +256,7 @@ namespace PepperDash.Essentials.Room.Config public class EssentialsRoomOccSensorConfig { public string DeviceKey { get; set; } - public string TimoutMinutes { get; set; } + public int TimoutMinutes { get; set; } } public class EssentialsRoomTechConfig diff --git a/Essentials/PepperDashEssentials/Room/Types/EssentialsRoomBase.cs b/Essentials/PepperDashEssentials/Room/Types/EssentialsRoomBase.cs index 0814bddb..7e18f55b 100644 --- a/Essentials/PepperDashEssentials/Room/Types/EssentialsRoomBase.cs +++ b/Essentials/PepperDashEssentials/Room/Types/EssentialsRoomBase.cs @@ -186,7 +186,7 @@ namespace PepperDash.Essentials /// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device /// /// - public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider) + public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes) { if (statusProvider == null) { @@ -198,6 +198,9 @@ namespace PepperDash.Essentials if (statusProvider is PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase) OccupancyStatusProviderIsRemote = true; + if(timeoutMinutes > 0) + RoomVacancyShutdownSeconds = timeoutMinutes * 60; + RoomOccupancy = statusProvider; RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += new EventHandler(RoomIsOccupiedFeedback_OutputChange); @@ -205,15 +208,15 @@ namespace PepperDash.Essentials void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e) { - if ((sender as IOccupancyStatusProvider).RoomIsOccupiedFeedback.BoolValue == false) + if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false) { - Debug.Console(0, this, "Vacancy Detected"); + Debug.Console(1, this, "Notice: Vacancy Detected"); // Trigger the timer when the room is vacant StartRoomVacancyTimer(eVacancyMode.InInitialVacancy); } else { - Debug.Console(0, this, "Occupancy Detected"); + Debug.Console(1, this, "Notice: Occupancy Detected"); // Reset the timer when the room is occupied RoomVacancyShutdownTimer.Cancel(); diff --git a/devjson commands.json b/devjson commands.json index 952601e7..67ee4df4 100644 --- a/devjson commands.json +++ b/devjson commands.json @@ -27,4 +27,5 @@ devjson:1 {"deviceKey":"room1-emergency", "methodName":"RunEmergencyBehavior"} devjson:1 {"deviceKey":"microphonePrivacyController-1", "methodName":"TogglePrivacyMute"} devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"SetTestValue", "params": [ true ]} + devjson:1 {"deviceKey":"room1.InCallFeedback","methodName":"ClearTestValue", "params": []}