Compare commits

...

24 Commits

Author SHA1 Message Date
Andrew Welker
0ee3e1d52b refactor: modify AddAction method to take the messenger 2024-02-29 13:27:02 -06:00
Andrew Welker
5084861067 feat: add IMobileControlAction interface 2024-02-29 12:36:50 -06:00
Andrew Welker
d6f896c4b2 feat: modify IMobileControl interface 2024-02-28 21:51:03 -06:00
Andrew Welker
7a5dc29946 refactor: remove MC bridge creation 2024-02-20 09:23:32 -06:00
Andrew Welker
812dd0e771 refactor: remove method
Moving all messenger creation to MC EPI.
2024-02-20 09:18:18 -06:00
Andrew Welker
08a4099842 refactor: change ApiOnline to BoolFeedback 2024-02-20 08:27:01 -06:00
Andrew Welker
a3c7d0c96a refactor: add online property for API 2024-02-20 08:13:46 -06:00
Andrew Welker
d7af57ba16 feat: add Properties to IMobileControl3 interface 2024-02-19 17:09:38 -06:00
Andrew Welker
6c2ef7b63b chore: update PepperDash Core version 2024-02-15 16:40:25 -06:00
Andrew Welker
06244b8a18 build: update PepperDash Core 2024-02-14 15:54:42 -06:00
Andrew Welker
b213262cdd refactor: use new method by default 2024-02-14 13:04:36 -06:00
Andrew Welker
e0e08ba22c feat: add methods to add routes to API 2024-02-14 13:02:09 -06:00
Andrew Welker
420ae8c7de refactor: add UpdateAppUrl method to RoomMessenger interface
Also renamed the interface to more accurately represent what it is for
2024-02-08 09:26:29 -06:00
Andrew Welker
f7cf854965 fix: remove incorrect using statement 2024-02-07 12:43:30 -06:00
Andrew Welker
5ce82f03b4 feat: move LightingBase to Devices Common 2024-02-07 12:43:13 -06:00
Andrew Welker
4d20cd7e80 chore: fix namespaces for room interfaces to be consistent 2024-02-07 12:32:59 -06:00
Andrew Welker
9e7239b219 chore: fix bad namespace
Namespaces were not correct

BREAKING_CHANGE: Namespaces changed
2024-02-07 12:32:45 -06:00
Andrew Welker
b689c847fb fix: invert interface to be custom instead of default
This way, existing rooms and devices will build messengers by default, while new plugins can implement their own messengers
2024-02-07 11:14:54 -06:00
Andrew Welker
4d608eef06 feat: refactor LoadRooms method
In order to facilitate using custom messengers, I added an interface, `IStandardMobileControl` that devices or rooms can implement if they should use the standard/existing MobileControl messengers. If a room or device wants to implement non-standard messengers, or is a new type of device that doesn't yet have a corresponding messenger in the Mobile Control plugin, do NOT implement this interface and MC won't attempt to build a messenger for it.
2024-02-07 08:44:58 -06:00
Andrew Welker
49b7faa400 chore: add back in config classes
Mobile Control (for the moment) relies on these classes, so they are necessary in Essentials until we determine a better solution.
2024-02-07 08:42:22 -06:00
Andrew Welker
8af0cf2702 chore: add room configs back in
At the moment, MC relies on some of these classes, so they are necessary
in Essentials for now. We can explore how to remove them at a later date
2024-02-07 07:46:16 -06:00
Andrew Welker
8d34b73cdf feat: add property to send ID to handlers for MC 2024-02-06 10:51:53 -06:00
Andrew Welker
5628042841 feat: move room aggregate interfaces back into Essentials 2024-02-06 10:51:25 -06:00
Andrew Welker
9f49a7faef feat: RKST-130 add missing event 2024-02-06 08:28:13 -06:00
29 changed files with 1064 additions and 105 deletions

View File

@@ -1,6 +1,6 @@
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_Core.Bridges.JoinMaps
namespace PepperDash.Essentials.Core.Bridges.JoinMaps
{
public sealed class GenericIrControllerJoinMap : JoinMapBaseAdvanced
{

View File

@@ -1,7 +1,7 @@
using System;
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_Core.Bridges
namespace PepperDash.Essentials.Core.Bridges
{
public class HdPsXxxControllerJoinMap : JoinMapBaseAdvanced
{

View File

@@ -6,6 +6,13 @@ using PepperDash.Core;
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
{
/// <summary>
/// Use this interface on a device or room if it uses custom Mobile Control messengers
/// </summary>
public interface ICustomMobileControl : IKeyed
{
}
/*/// <summary>
/// Describes a MobileControlSystemController
/// </summary>
public interface IMobileControl : IKeyed
@@ -13,16 +20,24 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
void CreateMobileControlRoomBridge(IEssentialsRoom room, IMobileControl parent);
void LinkSystemMonitorToAppServer();
}
}*/
/// <summary>
/// Describes a MobileSystemController that accepts IEssentialsRoom
/// </summary>
public interface IMobileControl3 : IMobileControl
{
public interface IMobileControl : IKeyed
{
string Host { get; }
string ClientAppUrl { get; }
string SystemUuid { get; }
BoolFeedback ApiOnlineAndAuthorized { get;}
void SendMessageObject(IMobileControlMessage o);
void AddAction(string key, Action<JToken> action);
void AddAction(IMobileControlMessenger messenger, Action<string, string, JToken> action);
void RemoveAction(string key);
@@ -36,9 +51,11 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// </summary>
public interface IMobileControlMessenger: IKeyed
{
IMobileControl3 AppServerController { get; }
IMobileControl AppServerController { get; }
string MessagePath { get; }
void RegisterWithAppServer(IMobileControl3 appServerController);
string DeviceKey { get; }
void RegisterWithAppServer(IMobileControl appServerController);
}
public interface IMobileControlMessage
@@ -57,7 +74,7 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
/// <summary>
/// Describes a MobileControl Room Bridge
/// </summary>
public interface IMobileControlRoomBridge : IKeyed
public interface IMobileControlRoomMessenger : IKeyed
{
event EventHandler<EventArgs> UserCodeChanged;
@@ -78,5 +95,15 @@ namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
string RoomName { get; }
string AppUrl { get; }
void UpdateAppUrl(string url);
}
public interface IMobileControlAction
{
IMobileControlMessenger Messenger { get; }
Action<string,string, JToken> Action { get; }
}
}

View File

@@ -48,6 +48,20 @@ namespace PepperDash.Essentials.Core
}
});
}
public override bool CustomActivate()
{
CreateMobileControlMessengers();
return base.CustomActivate();
}
/// <summary>
/// Override this method to build and create custom Mobile Control Messengers during the Activation phase
/// </summary>
protected virtual void CreateMobileControlMessengers() {
}
}
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]

View File

@@ -8,7 +8,7 @@ using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash_Essentials_Core.Bridges.JoinMaps;
using PepperDash.Essentials.Core.Bridges.JoinMaps;
namespace PepperDash.Essentials.Core.Devices
{

View File

@@ -4,12 +4,11 @@ using Crestron.SimplSharp;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash_Essentials_Core.Devices
namespace PepperDash.Essentials.Core.Devices
{
/// <summary>
/// Interface for any device that is able to control it'spower and has a configurable reboot time
/// </summary>
[Obsolete("PepperDash_Essentials_Core.Devices is Deprecated - use PepperDash.Essentials.Core")]
/// </summary>
public interface IHasPowerCycle : IKeyName, IHasPowerControlWithFeedback
{
/// <summary>
@@ -25,8 +24,7 @@ namespace PepperDash_Essentials_Core.Devices
/// <summary>
/// Interface for any device that contains a collection of IHasPowerReboot Devices
/// </summary>
[Obsolete("PepperDash_Essentials_Core.Devices is Deprecated - use PepperDash.Essentials.Core")]
/// </summary>
public interface IHasControlledPowerOutlets : IKeyName
{
/// <summary>

View File

@@ -23,7 +23,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.42" />
<PackageReference Include="PepperDashCore" Version="2.0.0-beta-385" />
<PackageReference Include="PepperDashCore" Version="2.0.0-beta-389" />
</ItemGroup>
<ItemGroup>
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />

View File

@@ -0,0 +1,8 @@
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsDualDisplayRoomPropertiesConfig : EssentialsNDisplayRoomPropertiesConfig
{
}
}

View File

@@ -0,0 +1,34 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
/// <summary>
/// The key of the default display device
/// </summary>
[JsonProperty("defaultDisplayKey")]
public string DefaultDisplayKey { get; set; }
/// <summary>
/// The key of the default audio device
/// </summary>
[JsonProperty("defaultAudioKey")]
public string DefaultAudioKey { get; set; }
/// <summary>
/// The key of the source list for the room
/// </summary>
[JsonProperty("sourceListKey")]
public string SourceListKey { get; set; }
/// <summary>
/// The key of the default source item from the source list
/// </summary>
[JsonProperty("defaultSourceItem")]
public string DefaultSourceItem { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsHuddleVtc1PropertiesConfig : EssentialsConferenceRoomPropertiesConfig
{
[JsonProperty("defaultDisplayKey")]
public string DefaultDisplayKey { get; set; }
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsNDisplayRoomPropertiesConfig : EssentialsConferenceRoomPropertiesConfig
{
[JsonProperty("defaultAudioBehavior")]
public string DefaultAudioBehavior { get; set; }
[JsonProperty("defaultVideoBehavior")]
public string DefaultVideoBehavior { get; set; }
[JsonProperty("displays")]
public Dictionary<eSourceListItemDestinationTypes, DisplayItem> Displays { get; set; }
public EssentialsNDisplayRoomPropertiesConfig()
{
Displays = new Dictionary<eSourceListItemDestinationTypes, DisplayItem>();
}
}
public class DisplayItem : IKeyName
{
public string Key { get; set; }
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsPresentationRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
public string DefaultAudioBehavior { get; set; }
public string DefaultAudioKey { get; set; }
public string DefaultVideoBehavior { get; set; }
public List<string> DisplayKeys { get; set; }
public string SourceListKey { get; set; }
public bool HasDsp { get; set; }
public EssentialsPresentationRoomPropertiesConfig()
{
DisplayKeys = new List<string>();
}
}
}

View File

@@ -0,0 +1,364 @@
using System;
using System.Collections.Generic;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Privacy;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsRoomConfigHelper
{
/// <summary>
/// Gets and operating, standalone emergegncy object that can be plugged into a room.
/// Returns null if there is no emergency defined
/// </summary>
public static EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, IEssentialsRoom room)
{
// This emergency
var emergency = props.Emergency;
if (emergency != null)
{
//switch on emergency type here. Right now only contact and shutdown
var e = new EssentialsRoomEmergencyContactClosure(room.Key + "-emergency", props.Emergency, room);
DeviceManager.AddDevice(e);
}
return null;
}
/// <summary>
///
/// </summary>
/// <param name="props"></param>
/// <param name="room"></param>
/// <returns></returns>
public static MicrophonePrivacyController GetMicrophonePrivacy(
EssentialsRoomPropertiesConfig props, IPrivacy room)
{
var microphonePrivacy = props.MicrophonePrivacy;
if (microphonePrivacy == null)
{
Debug.Console(0, "Cannot create microphone privacy with null properties");
return null;
}
// Get the MicrophonePrivacy device from the device manager
var mP = (DeviceManager.GetDeviceForKey(props.MicrophonePrivacy.DeviceKey) as MicrophonePrivacyController);
// Set this room as the IPrivacy device
if (mP == null)
{
Debug.Console(0, "ERROR: Selected device {0} is not MicrophonePrivacyController", props.MicrophonePrivacy.DeviceKey);
return null;
}
mP.SetPrivacyDevice(room);
var behaviour = props.MicrophonePrivacy.Behaviour.ToLower();
if (behaviour == null)
{
Debug.Console(0, "WARNING: No behaviour defined for MicrophonePrivacyController");
return null;
}
if (behaviour == "trackroomstate")
{
// Tie LED enable to room power state
var essRoom = room as IEssentialsRoom;
essRoom.OnFeedback.OutputChange += (o, a) =>
{
if (essRoom.OnFeedback.BoolValue)
mP.EnableLeds = true;
else
mP.EnableLeds = false;
};
mP.EnableLeds = essRoom.OnFeedback.BoolValue;
}
else if (behaviour == "trackcallstate")
{
// Tie LED enable to room power state
var inCallRoom = room as IHasInCallFeedback;
inCallRoom.InCallFeedback.OutputChange += (o, a) =>
{
if (inCallRoom.InCallFeedback.BoolValue)
mP.EnableLeds = true;
else
mP.EnableLeds = false;
};
mP.EnableLeds = inCallRoom.InCallFeedback.BoolValue;
}
return mP;
}
}
/// <summary>
///
/// </summary>
public class EssentialsRoomPropertiesConfig
{
[JsonProperty("addresses")]
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("emergency")]
public EssentialsRoomEmergencyConfig Emergency { get; set; }
[JsonProperty("help")]
public EssentialsHelpPropertiesConfig Help { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
/// <summary>
/// Read this value to get the help message. It checks for the old and new config format.
/// </summary>
public string HelpMessageForDisplay
{
get
{
if(Help != null && !string.IsNullOrEmpty(Help.Message))
{
return Help.Message;
}
else
{
return HelpMessage;
}
}
}
[JsonProperty("environment")]
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
[JsonProperty("logo")]
public EssentialsLogoPropertiesConfig LogoLight { get; set; }
[JsonProperty("logoDark")]
public EssentialsLogoPropertiesConfig LogoDark { get; set; }
[JsonProperty("microphonePrivacy")]
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
[JsonProperty("occupancy")]
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
[JsonProperty("oneButtonMeeting")]
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
[JsonProperty("shutdownVacancySeconds")]
public int ShutdownVacancySeconds { get; set; }
[JsonProperty("shutdownPromptSeconds")]
public int ShutdownPromptSeconds { get; set; }
[JsonProperty("tech")]
public EssentialsRoomTechConfig Tech { get; set; }
[JsonProperty("volumes")]
public EssentialsRoomVolumesConfig Volumes { get; set; }
[JsonProperty("fusion")]
public EssentialsRoomFusionConfig Fusion { get; set; }
[JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)]
public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
/// <summary>
/// Indicates if this room represents a combination of other rooms
/// </summary>
[JsonProperty("isRoomCombinationScenario")]
public bool IsRoomCombinationScenario { get; set; }
public EssentialsRoomPropertiesConfig()
{
LogoLight = new EssentialsLogoPropertiesConfig();
LogoDark = new EssentialsLogoPropertiesConfig();
}
}
public class EssentialsRoomUiBehaviorConfig
{
[JsonProperty("disableActivityButtonsWhileWarmingCooling")]
public bool DisableActivityButtonsWhileWarmingCooling { get; set; }
}
public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig
{
[JsonProperty("defaultAudioKey")]
public string DefaultAudioKey { get; set; }
[JsonProperty("sourceListKey")]
public string SourceListKey { get; set; }
[JsonProperty("destinationListKey")]
public string DestinationListKey { get; set; }
[JsonProperty("defaultSourceItem")]
public string DefaultSourceItem { get; set; }
/// <summary>
/// Indicates if the room supports advanced sharing
/// </summary>
[JsonProperty("supportsAdvancedSharing")]
public bool SupportsAdvancedSharing { get; set; }
/// <summary>
/// Indicates if non-tech users can change the share mode
/// </summary>
[JsonProperty("userCanChangeShareMode")]
public bool UserCanChangeShareMode { get; set; }
}
public class EssentialsConferenceRoomPropertiesConfig : EssentialsAvRoomPropertiesConfig
{
[JsonProperty("videoCodecKey")]
public string VideoCodecKey { get; set; }
[JsonProperty("audioCodecKey")]
public string AudioCodecKey { get; set; }
}
public class EssentialsEnvironmentPropertiesConfig
{
public bool Enabled { get; set; }
[JsonProperty("deviceKeys")]
public List<string> DeviceKeys { get; set; }
public EssentialsEnvironmentPropertiesConfig()
{
DeviceKeys = new List<string>();
}
}
public class EssentialsRoomFusionConfig
{
public uint IpIdInt
{
get
{
try
{
return Convert.ToUInt32(IpId, 16);
}
catch (Exception)
{
throw new FormatException(string.Format("ERROR:Unable to convert IP ID: {0} to hex. Error:\n{1}", IpId));
}
}
}
[JsonProperty("ipId")]
public string IpId { get; set; }
[JsonProperty("joinMapKey")]
public string JoinMapKey { get; set; }
}
public class EssentialsRoomMicrophonePrivacyConfig
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("behaviour")]
public string Behaviour { get; set; }
}
/// <summary>
/// Properties for the help text box
/// </summary>
public class EssentialsHelpPropertiesConfig
{
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("showCallButton")]
public bool ShowCallButton { get; set; }
/// <summary>
/// Defaults to "Call Help Desk"
/// </summary>
[JsonProperty("callButtonText")]
public string CallButtonText { get; set; }
public EssentialsHelpPropertiesConfig()
{
CallButtonText = "Call Help Desk";
}
}
/// <summary>
///
/// </summary>
public class EssentialsOneButtonMeetingPropertiesConfig
{
[JsonProperty("enable")]
public bool Enable { get; set; }
}
public class EssentialsRoomAddressPropertiesConfig
{
[JsonProperty("phoneNumber")]
public string PhoneNumber { get; set; }
[JsonProperty("sipAddress")]
public string SipAddress { get; set; }
}
/// <summary>
/// Properties for the room's logo on panels
/// </summary>
public class EssentialsLogoPropertiesConfig
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("url")]
public string Url { get; set; }
/// <summary>
/// Gets either the custom URL, a local-to-processor URL, or null if it's a default logo
/// </summary>
public string GetLogoUrlLight()
{
if (Type == "url")
return Url;
if (Type == "system")
return string.Format("http://{0}:8080/logo.png",
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
return null;
}
public string GetLogoUrlDark()
{
if (Type == "url")
return Url;
if (Type == "system")
return string.Format("http://{0}:8080/logo-dark.png",
CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0));
return null;
}
}
/// <summary>
/// Represents occupancy sensor(s) setup for a room
/// </summary>
public class EssentialsRoomOccSensorConfig
{
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("timeoutMinutes")]
public int TimeoutMinutes { get; set; }
}
public class EssentialsRoomTechConfig
{
[JsonProperty("password")]
public string Password { get; set; }
}
}

View File

@@ -0,0 +1,30 @@
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsRoomEmergencyConfig
{
public EssentialsRoomEmergencyTriggerConfig Trigger { get; set; }
public string Behavior { get; set; }
}
/// <summary>
///
/// </summary>
public class EssentialsRoomEmergencyTriggerConfig
{
/// <summary>
/// contact,
/// </summary>
public string Type { get; set; }
/// <summary>
/// Input number if contact
/// </summary>
public int Number { get; set; }
public bool TriggerOnClose { get; set; }
}
}

View File

@@ -0,0 +1,77 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Room.Config
{
public class EssentialsTechRoomConfig
{
/// <summary>
/// The key of the dummy device used to enable routing
/// </summary>
[JsonProperty("dummySourceKey")]
public string DummySourceKey { get; set; }
/// <summary>
/// The keys of the displays assigned to this room
/// </summary>
[JsonProperty("displays")]
public List<string> Displays { get; set; }
/// <summary>
/// The keys of the tuners assinged to this room
/// </summary>
[JsonProperty("tuners")]
public List<string> Tuners { get; set; }
/// <summary>
/// PIN to access the room as a normal user
/// </summary>
[JsonProperty("userPin")]
public string UserPin { get; set; }
/// <summary>
/// PIN to access the room as a tech user
/// </summary>
[JsonProperty("techPin")]
public string TechPin { get; set; }
/// <summary>
/// Name of the presets file. Path prefix is assumed to be /html/presets/lists/
/// </summary>
[JsonProperty("presetsFileName")]
public string PresetsFileName { get; set; }
[JsonProperty("scheduledEvents")]
public List<ScheduledEventConfig> ScheduledEvents { get; set; }
/// <summary>
/// Indicates that the room is the primary when true
/// </summary>
[JsonProperty("isPrimary")]
public bool IsPrimary { get; set; }
/// <summary>
/// Indicates which tuners should mirror preset recall when two rooms are configured in a primary->secondary scenario
/// </summary>
[JsonProperty("mirroredTuners")]
public Dictionary<uint, string> MirroredTuners { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
/// <summary>
/// Indicates the room
/// </summary>
[JsonProperty("isTvPresetsProvider")]
public bool IsTvPresetsProvider;
public EssentialsTechRoomConfig()
{
Displays = new List<string>();
Tuners = new List<string>();
ScheduledEvents = new List<ScheduledEventConfig>();
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Room.Config
{
/// <summary>
///
/// </summary>
public class EssentialsRoomVolumesConfig
{
public EssentialsVolumeLevelConfig Master { get; set; }
public EssentialsVolumeLevelConfig Program { get; set; }
public EssentialsVolumeLevelConfig AudioCallRx { get; set; }
public EssentialsVolumeLevelConfig AudioCallTx { get; set; }
}
/// <summary>
///
/// </summary>
public class EssentialsVolumeLevelConfig
{
public string DeviceKey { get; set; }
public string Label { get; set; }
public int Level { get; set; }
/// <summary>
/// Helper to get the device associated with key - one timer.
/// </summary>
public IBasicVolumeWithFeedback GetDevice()
{
throw new NotImplementedException("This method references DM CHASSIS Directly");
/*
// DM output card format: deviceKey--output~number, dm8x8-1--output~4
var match = Regex.Match(DeviceKey, @"([-_\w]+)--(\w+)~(\d+)");
if (match.Success)
{
var devKey = match.Groups[1].Value;
var chassis = DeviceManager.GetDeviceForKey(devKey) as DmChassisController;
if (chassis != null)
{
var outputNum = Convert.ToUInt32(match.Groups[3].Value);
if (chassis.VolumeControls.ContainsKey(outputNum)) // should always...
return chassis.VolumeControls[outputNum];
}
// No volume for some reason. We have failed as developers
return null;
}
// DSP/DMPS format: deviceKey--levelName, biampTesira-1--master
match = Regex.Match(DeviceKey, @"([-_\w]+)--(.+)");
if (match.Success)
{
var devKey = match.Groups[1].Value;
var dsp = DeviceManager.GetDeviceForKey(devKey) as BiampTesiraForteDsp;
if (dsp != null)
{
var levelTag = match.Groups[2].Value;
if (dsp.LevelControlPoints.ContainsKey(levelTag)) // should always...
return dsp.LevelControlPoints[levelTag];
}
var dmps = DeviceManager.GetDeviceForKey(devKey) as DmpsAudioOutputController;
if (dmps != null)
{
var levelTag = match.Groups[2].Value;
switch (levelTag)
{
case "master":
return dmps.MasterVolumeLevel;
case "source":
return dmps.SourceVolumeLevel;
case "micsmaster":
return dmps.MicsMasterVolumeLevel;
case "codec1":
return dmps.Codec1VolumeLevel;
case "codec2":
return dmps.Codec2VolumeLevel;
default:
return dmps.MasterVolumeLevel;
}
}
// No volume for some reason. We have failed as developers
return null;
}
return null;
}
* */
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace PepperDash.Essentials.Room.Config
{
public class SimplRoomPropertiesConfig : EssentialsHuddleVtc1PropertiesConfig
{
[JsonProperty("roomPhoneNumber")]
public string RoomPhoneNumber { get; set; }
[JsonProperty("roomURI")]
public string RoomURI { get; set; }
[JsonProperty("speedDials")]
public List<SimplSpeedDial> SpeedDials { get; set; }
[JsonProperty("volumeSliderNames")]
public List<string> VolumeSliderNames { get; set; }
}
public class SimplSpeedDial
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("number")]
public string Number { get; set; }
}
}

View File

@@ -0,0 +1,47 @@
using System;
using Crestron.SimplSharpPro;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Core
{
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase
{
IEssentialsRoom Room;
string Behavior;
bool TriggerOnClose;
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, IEssentialsRoom room) :
base(key)
{
Room = room;
var cs = Global.ControlSystem;
if (config.Trigger.Type.Equals("contact", StringComparison.OrdinalIgnoreCase))
{
var portNum = (uint)config.Trigger.Number;
if (portNum <= cs.NumberOfDigitalInputPorts)
{
cs.DigitalInputPorts[portNum].Register();
cs.DigitalInputPorts[portNum].StateChange += EsentialsRoomEmergencyContactClosure_StateChange;
}
}
Behavior = config.Behavior;
TriggerOnClose = config.Trigger.TriggerOnClose;
}
void EsentialsRoomEmergencyContactClosure_StateChange(DigitalInput digitalInput, DigitalInputEventArgs args)
{
if (args.State && TriggerOnClose || !args.State && !TriggerOnClose)
RunEmergencyBehavior();
}
/// <summary>
///
/// </summary>
public void RunEmergencyBehavior()
{
if (Behavior.Equals("shutdown"))
Room.Shutdown();
}
}
}

View File

@@ -58,7 +58,7 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// The bridge for this room if Mobile Control is enabled
/// </summary>
public IMobileControlRoomBridge MobileControlRoomBridge { get; private set; }
public IMobileControlRoomMessenger MobileControlRoomBridge { get; private set; }
/// <summary>
/// The config name of the source list
@@ -209,7 +209,7 @@ namespace PepperDash.Essentials.Core
}
else
{
MobileControlRoomBridge = mcBridge as IMobileControlRoomBridge;
MobileControlRoomBridge = mcBridge as IMobileControlRoomMessenger;
Debug.Console(1, this, "*********************Mobile Control Bridge found and enabled for this room");
IsMobileControlEnabled = true;
}

View File

@@ -23,7 +23,7 @@ namespace PepperDash.Essentials.Core
BoolFeedback IsCoolingDownFeedback { get; }
bool IsMobileControlEnabled { get; }
IMobileControlRoomBridge MobileControlRoomBridge { get; }
IMobileControlRoomMessenger MobileControlRoomBridge { get; }
string SourceListKey { get; }

View File

@@ -1,4 +1,5 @@
using PepperDash.Essentials.Room.Config;
using System;
using System.Collections.Generic;
namespace PepperDash.Essentials.Core
@@ -8,5 +9,12 @@ namespace PepperDash.Essentials.Core
void AddOrUpdateScheduledEvent(ScheduledEventConfig eventConfig);
List<ScheduledEventConfig> GetScheduledEvents();
event EventHandler<ScheduledEventEventArgs> ScheduledEventsChanged;
}
public class ScheduledEventEventArgs : EventArgs
{
public List<ScheduledEventConfig> ScheduledEvents;
}
}

View File

@@ -11,7 +11,7 @@ namespace PepperDash.Essentials.Core.Web
{
public class EssentialsWebApi : EssentialsDevice
{
private readonly WebApiServer _server;
private readonly WebApiServer _server;
///<example>
/// http(s)://{ipaddress}/cws/{basePath}
@@ -67,8 +67,6 @@ namespace PepperDash.Essentials.Core.Web
_server = new WebApiServer(Key, Name, BasePath);
SetupRoutes();
Initialize();
}
private void SetupRoutes()
@@ -168,10 +166,27 @@ namespace PepperDash.Essentials.Core.Web
};
foreach (var route in routes.Where(route => route != null))
AddRoute(routes);
}
/// <summary>
/// Add a single route to the API. MUST be done during the activation phase
/// </summary>
/// <param name="route"></param>
public void AddRoute(HttpCwsRoute route)
{
_server.AddRoute(route);
}
/// <summary>
/// Add a collection of routes to the API. MUST be done during the activation phase
/// </summary>
/// <param name="routes"></param>
public void AddRoute(List<HttpCwsRoute> routes)
{
foreach (var route in routes)
{
var r = route;
_server.AddRoute(r);
AddRoute(route);
}
}

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Lighting;
namespace PepperDash.Essentials.Devices.Common.Lighting
{
[Obsolete("Please use PepperDash.Essentials.Devices.Common, this will be removed in 2.1")]
public abstract class LightingBase : EssentialsBridgeableDevice, ILightingScenes
{
#region ILightingScenes Members
public event EventHandler<LightingSceneChangeEventArgs> LightingSceneChange;
public List<LightingScene> LightingScenes { get; protected set; }
public LightingScene CurrentLightingScene { get; protected set; }
public IntFeedback CurrentLightingSceneFeedback { get; protected set; }
#endregion
protected LightingBase(string key, string name)
: base(key, name)
{
LightingScenes = new List<LightingScene>();
CurrentLightingScene = new LightingScene();
//CurrentLightingSceneFeedback = new IntFeedback(() => { return int.Parse(this.CurrentLightingScene.ID); });
}
public abstract void SelectScene(LightingScene scene);
public void SimulateSceneSelect(string sceneName)
{
Debug.Console(1, this, "Simulating selection of scene '{0}'", sceneName);
var scene = LightingScenes.FirstOrDefault(s => s.Name.Equals(sceneName));
if (scene != null)
{
CurrentLightingScene = scene;
OnLightingSceneChange();
}
}
/// <summary>
/// Sets the IsActive property on each scene and fires the LightingSceneChange event
/// </summary>
protected void OnLightingSceneChange()
{
foreach (var scene in LightingScenes)
{
if (scene == CurrentLightingScene)
scene.IsActive = true;
else
scene.IsActive = false;
}
var handler = LightingSceneChange;
if (handler != null)
{
handler(this, new LightingSceneChangeEventArgs(CurrentLightingScene));
}
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, uint joinStart,
string joinMapKey, EiscApiAdvanced bridge)
{
var joinMap = new GenericLightingJoinMap(joinStart);
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
if (!string.IsNullOrEmpty(joinMapSerialized))
joinMap = JsonConvert.DeserializeObject<GenericLightingJoinMap>(joinMapSerialized);
if (bridge != null)
{
bridge.AddJoinMap(Key, joinMap);
}
else
{
Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
}
return LinkLightingToApi(lightingDevice, trilist, joinMap);
}
protected GenericLightingJoinMap LinkLightingToApi(LightingBase lightingDevice, BasicTriList trilist, GenericLightingJoinMap joinMap)
{
Debug.Console(1, "Linking to Trilist '{0}'", trilist.ID.ToString("X"));
Debug.Console(0, "Linking to Lighting Type {0}", lightingDevice.GetType().Name.ToString());
// GenericLighitng Actions & FeedBack
trilist.SetUShortSigAction(joinMap.SelectScene.JoinNumber, u => lightingDevice.SelectScene(lightingDevice.LightingScenes[u]));
var sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.SetSigTrueAction((uint)(joinMap.SelectSceneDirect.JoinNumber + index), () => lightingDevice.SelectScene(lightingDevice.LightingScenes[index]));
scene.IsActiveFeedback.LinkInputSig(trilist.BooleanInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)]);
trilist.StringInput[(uint)(joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint)(joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
sceneIndex++;
}
trilist.OnlineStatusChange += (sender, args) =>
{
if (!args.DeviceOnLine) return;
sceneIndex = 0;
foreach (var scene in lightingDevice.LightingScenes)
{
var index = sceneIndex;
trilist.StringInput[(uint) (joinMap.SelectSceneDirect.JoinNumber + index)].StringValue = scene.Name;
trilist.BooleanInput[(uint) (joinMap.ButtonVisibility.JoinNumber + index)].BoolValue = true;
scene.IsActiveFeedback.FireUpdate();
sceneIndex++;
}
};
return joinMap;
}
}
}

View File

@@ -27,6 +27,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.20.42" />
<PackageReference Include="PepperDashCore" Version="2.0.0-beta-385" />
<PackageReference Include="PepperDashCore" Version="2.0.0-beta-389" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,15 @@
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Devices.Common.Room
{
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy,
IEmergency, IMicrophonePrivacy
{
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
EssentialsHuddleRoomPropertiesConfig PropertiesConfig { get; }
}
}

View File

@@ -0,0 +1,26 @@
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Devices.Common.AudioCodec;
using PepperDash.Essentials.Devices.Common.Codec;
using PepperDash.Essentials.Devices.Common.VideoCodec;
using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials.Devices.Common.Room
{
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback,
IRoomOccupancy, IEmergency, IMicrophonePrivacy
{
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }
bool ExcludeFromGlobalFunctions { get; }
void RunRouteAction(string routeKey);
IHasScheduleAwareness ScheduleSource { get; }
new BoolFeedback InCallFeedback { get; }
new BoolFeedback PrivacyModeIsOnFeedback { get; }
string DefaultCodecRouteString { get; }
}
}

View File

@@ -0,0 +1,22 @@
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Room.Config;
using System.Collections.Generic;
using TwoWayDisplayBase = PepperDash.Essentials.Devices.Common.Displays.TwoWayDisplayBase;
namespace PepperDash.Essentials.Devices.Common.Room
{
public interface IEssentialsTechRoom:IEssentialsRoom, ITvPresetsProvider,IBridgeAdvanced,IRunDirectRouteAction
{
EssentialsTechRoomConfig PropertiesConfig { get; }
Dictionary<string, IRSetTopBoxBase> Tuners { get; }
Dictionary<string, TwoWayDisplayBase> Displays { get; }
void RoomPowerOn();
void RoomPowerOff();
}
}

View File

@@ -11,6 +11,8 @@ using PepperDash.Essentials.Core.Bridges;
using PepperDash.Essentials.Core.Config;
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
using PepperDash.Essentials.Core.Web;
using PepperDash.Essentials.Devices.Common.Room;
using PepperDash.Essentials.Room.Config;
using System;
using System.Linq;
@@ -364,11 +366,11 @@ namespace PepperDash.Essentials
LoadTieLines();
var mobileControl = GetMobileControlDevice();
/*var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return;
mobileControl.LinkSystemMonitorToAppServer();
mobileControl.LinkSystemMonitorToAppServer();*/
}
@@ -468,103 +470,48 @@ namespace PepperDash.Essentials
return;
}
// uint fusionIpId = 0xf1;
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
{
/*
var room = EssentialsRoomConfigHelper.GetRoomObject(roomConfig) as IEssentialsRoom;
if (room != null)
{
// default to no join map key
string fusionJoinMapKey = string.Empty;
var room = Core.DeviceFactory.GetDevice(roomConfig);
if (room.Config.Properties["fusion"] != null)
{
Debug.Console(2, "Custom Fusion config found. Using custom values");
DeviceManager.AddDevice(room);
if (room is ICustomMobileControl)
{
continue;
}
var fusionConfig = room.Config.Properties["fusion"].ToObject<EssentialsRoomFusionConfig>();
if (fusionConfig != null)
{
fusionIpId = fusionConfig.IpIdInt;
fusionJoinMapKey = fusionConfig.JoinMapKey;
}
}
AddRoomAndBuildMC(room);
if (room is IEssentialsHuddleSpaceRoom)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new Core.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase(room, fusionIpId, fusionJoinMapKey));
}
else if (room is IEssentialsHuddleVtc1Room)
{
if (!(room is EssentialsCombinedHuddleVtc1Room))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((IEssentialsHuddleVtc1Room)room, fusionIpId, fusionJoinMapKey));
}
}
else if (room is EssentialsTechRoom)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice,
"Room is EssentialsTechRoom, Attempting to add to DeviceManager with Fusion with IP-ID {0:X2}", fusionIpId);
DeviceManager.AddDevice(new EssentialsTechRoomFusionSystemController((EssentialsTechRoom)room, fusionIpId, fusionJoinMapKey));
}
fusionIpId += 1;
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Notice: Cannot create room from config, key '{0}' - Is this intentional? This may be a valid configuration.", roomConfig.Key);
}
*/
// BuildMC(room as IEssentialsRoom);
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");
}
private static void AddRoomAndBuildMC(IEssentialsRoom room)
{
DeviceManager.AddDevice(room);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Mobile Control Bridge");
/*private static void BuildMC(IEssentialsRoom room)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, $"Attempting to build Mobile Control Bridge for {room?.Key}");
CreateMobileControlBridge(room);
}
private static void CreateMobileControlBridge(object room)
private static void CreateMobileControlBridge(IEssentialsRoom room)
{
if(room == null)
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, $"Room does not implement IEssentialsRoom");
return;
}
var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return;
var mobileControl3 = mobileControl as IMobileControl3;
if (mobileControl3 != null)
{
mobileControl3.CreateMobileControlRoomBridge(room as IEssentialsRoom, mobileControl);
}
else
{
mobileControl.CreateMobileControlRoomBridge(room as EssentialsRoomBase, mobileControl);
}
mobileControl?.CreateMobileControlRoomBridge(room, mobileControl);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control Bridge Added...");
}
private static IMobileControl GetMobileControlDevice()
private static IMobileControl3 GetMobileControlDevice()
{
var mobileControlList = DeviceManager.AllDevices.OfType<IMobileControl>().ToList();
var mobileControlList = DeviceManager.AllDevices.OfType<IMobileControl3>().ToList();
if (mobileControlList.Count > 1)
{
@@ -581,7 +528,7 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Mobile Control not enabled for this system");
return null;
}
}*/
/// <summary>
/// Fires up a logo server if not already running

View File

@@ -47,7 +47,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.20.42" />
<PackageReference Include="PepperDashCore" Version="2.0.0-beta-385" />
<PackageReference Include="PepperDashCore" Version="2.0.0-beta-389" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PepperDash.Essentials.Core\PepperDash.Essentials.Core.csproj" />