Compare commits

..

1 Commits

Author SHA1 Message Date
Andrew Welker
4e8749b9da fix: update DMPS InputChange event handler
In some configurations, the InputChange handler can throw
a null reference exception due to a Feedback for
the input that triggered the event not existing. The
event handler now checks for the existence of a Feedback
for the input that triggered the event prior to attempting
to call the `FireUpdate` method. Addresses #1136
2023-09-25 15:21:42 -05:00
11 changed files with 65 additions and 94 deletions

View File

@@ -337,13 +337,12 @@ namespace PepperDash.Essentials
void Load() void Load()
{ {
LoadDevices(); LoadDevices();
LoadTieLines();
LoadRooms(); LoadRooms();
LoadLogoServer(); LoadLogoServer();
DeviceManager.ActivateAll(); DeviceManager.ActivateAll();
LoadTieLines();
var mobileControl = GetMobileControlDevice(); var mobileControl = GetMobileControlDevice();
if (mobileControl == null) return; if (mobileControl == null) return;

View File

@@ -334,7 +334,7 @@ namespace PepperDash.Essentials
/// route or commands /// route or commands
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
public virtual void RunRouteAction(string routeKey, Action successCallback) public void RunRouteAction(string routeKey, Action successCallback)
{ {
// Run this on a separate thread // Run this on a separate thread
new CTimer(o => new CTimer(o =>

View File

@@ -7,8 +7,7 @@ using PepperDash.Essentials.Room.Config;
namespace PepperDash.Essentials namespace PepperDash.Essentials
{ {
public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy, public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls
IEmergency, IMicrophonePrivacy
{ {
bool ExcludeFromGlobalFunctions { get; } bool ExcludeFromGlobalFunctions { get; }

View File

@@ -8,8 +8,7 @@ using PepperDash.Essentials.Devices.Common.AudioCodec;
namespace PepperDash.Essentials namespace PepperDash.Essentials
{ {
public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange,
IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback, IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback
IRoomOccupancy, IEmergency, IMicrophonePrivacy
{ {
EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; }

View File

@@ -81,15 +81,6 @@ namespace PepperDash.Essentials.Core
} }
case eControlMethod.Telnet: case eControlMethod.Telnet:
break; break;
case eControlMethod.SecureTcpIp:
{
var secureTcp = new GenericSecureTcpIpClient(deviceConfig.Key + "-secureTcp", c.Address, c.Port, c.BufferSize);
secureTcp.AutoReconnect = c.AutoReconnect;
if (secureTcp.AutoReconnect)
secureTcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
comm = secureTcp;
break;
}
default: default:
break; break;
} }

View File

@@ -72,10 +72,6 @@ namespace PepperDash.Essentials.Core
{ {
IBasicVolumeControls CurrentVolumeControls { get; } IBasicVolumeControls CurrentVolumeControls { get; }
event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange; event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
void SetDefaultLevels();
bool ZeroVolumeWhenSwtichingVolumeDevices { get; }
} }

View File

@@ -148,13 +148,9 @@ namespace PepperDash.Essentials.Core.Fusion
ReadGuidFile(guidFilePath); ReadGuidFile(guidFilePath);
} }
var occupancyRoom = Room as IRoomOccupancy; if (Room.RoomOccupancy != null)
if (occupancyRoom != null)
{ {
if (occupancyRoom.RoomOccupancy != null) if (Room.OccupancyStatusProviderIsRemote)
{
if (occupancyRoom.OccupancyStatusProviderIsRemote)
{ {
SetUpRemoteOccupancy(); SetUpRemoteOccupancy();
} }
@@ -163,7 +159,6 @@ namespace PepperDash.Essentials.Core.Fusion
SetUpLocalOccupancy(); SetUpLocalOccupancy();
} }
} }
}
AddPostActivationAction(() => PostActivate(guidFilePath)); AddPostActivationAction(() => PostActivate(guidFilePath));
@@ -1528,15 +1523,10 @@ namespace PepperDash.Essentials.Core.Fusion
// Tie to method on occupancy object // Tie to method on occupancy object
//occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b)); //occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b));
var occRoom = Room as IRoomOccupancy;
if (occRoom != null)
{
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig);
occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
}
RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString); RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString);
Room.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig);
Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig); RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig);
//} //}

View File

@@ -38,7 +38,7 @@ namespace PepperDash.Essentials.Core
ScheduledEventGroup FeatureEventGroup; ScheduledEventGroup FeatureEventGroup;
public IRoomOccupancy Room { get; private set; } public IEssentialsRoom Room { get; private set; }
private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom; private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom;
@@ -84,7 +84,7 @@ namespace PepperDash.Essentials.Core
/// </summary> /// </summary>
void SetUpDevice() void SetUpDevice()
{ {
Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IRoomOccupancy; Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IEssentialsRoom;
if (Room != null) if (Room != null)
{ {
@@ -235,25 +235,14 @@ namespace PepperDash.Essentials.Core
if (FeatureEnabled) if (FeatureEnabled)
{ {
var essentialsRoom = Room as IEssentialsRoom; // Check room power state first
if (!Room.OnFeedback.BoolValue)
if (essentialsRoom != null) {
if (!essentialsRoom.OnFeedback.BoolValue)
{ {
Debug.Console(1, this, "Powering Room on to default source"); Debug.Console(1, this, "Powering Room on to default source");
Room.RunDefaultPresentRoute();
var defaultRouteRoom = Room as IRunDefaultPresentRoute;
if (defaultRouteRoom != null)
{
defaultRouteRoom.RunDefaultPresentRoute();
} }
} }
} }
// Check room power state first
}
}
} }
void CreateEvent(ScheduledEvent schEvent, string name) void CreateEvent(ScheduledEvent schEvent, string name)

View File

@@ -19,9 +19,14 @@ namespace PepperDash.Essentials.Core
{ {
BoolFeedback OnFeedback { get; } BoolFeedback OnFeedback { get; }
event EventHandler<EventArgs> RoomOccupancyIsSet;
BoolFeedback IsWarmingUpFeedback { get; } BoolFeedback IsWarmingUpFeedback { get; }
BoolFeedback IsCoolingDownFeedback { get; } BoolFeedback IsCoolingDownFeedback { get; }
IOccupancyStatusProvider RoomOccupancy { get; }
bool OccupancyStatusProviderIsRemote { get; }
bool IsMobileControlEnabled { get; } bool IsMobileControlEnabled { get; }
IMobileControlRoomBridge MobileControlRoomBridge { get; } IMobileControlRoomBridge MobileControlRoomBridge { get; }
@@ -32,14 +37,29 @@ namespace PepperDash.Essentials.Core
int ShutdownVacancySeconds { get; } int ShutdownVacancySeconds { get; }
eShutdownType ShutdownType { get; } eShutdownType ShutdownType { get; }
EssentialsRoomEmergencyBase Emergency { get; }
Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; }
string LogoUrlLightBkgnd { get; } string LogoUrlLightBkgnd { get; }
string LogoUrlDarkBkgnd { get; } string LogoUrlDarkBkgnd { get; }
eVacancyMode VacancyMode { get; }
bool ZeroVolumeWhenSwtichingVolumeDevices { get; }
void StartShutdown(eShutdownType type); void StartShutdown(eShutdownType type);
void StartRoomVacancyTimer(eVacancyMode mode);
void Shutdown(); void Shutdown();
void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes);
void PowerOnToDefaultOrLastSource(); void PowerOnToDefaultOrLastSource();
void SetDefaultLevels();
void RoomVacatedForTimeoutPeriod(object o);
} }
} }

View File

@@ -41,6 +41,7 @@ namespace PepperDash.Essentials.Core
void RunRouteAction(string routeKey, string sourceListKey); void RunRouteAction(string routeKey, string sourceListKey);
void RunRouteAction(string routeKey, string sourceListKey, Action successCallback); void RunRouteAction(string routeKey, string sourceListKey, Action successCallback);
} }
/// <summary> /// <summary>
@@ -77,30 +78,4 @@ namespace PepperDash.Essentials.Core
bool HasEnvironmentalControlDevices { get; } bool HasEnvironmentalControlDevices { get; }
} }
public interface IRoomOccupancy:IKeyed
{
IOccupancyStatusProvider RoomOccupancy { get; }
bool OccupancyStatusProviderIsRemote { get; }
void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes);
void RoomVacatedForTimeoutPeriod(object o);
void StartRoomVacancyTimer(eVacancyMode mode);
eVacancyMode VacancyMode { get; }
event EventHandler<EventArgs> RoomOccupancyIsSet;
}
public interface IEmergency
{
EssentialsRoomEmergencyBase Emergency { get; }
}
public interface IMicrophonePrivacy
{
Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; }
}
} }

View File

@@ -991,28 +991,41 @@ namespace PepperDash.Essentials.DM
case (DMInputEventIds.OnlineFeedbackEventId): case (DMInputEventIds.OnlineFeedbackEventId):
{ {
Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); Debug.Console(2, this, "DM Input OnlineFeedbackEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback);
if(!InputEndpointOnlineFeedbacks.ContainsKey(args.Number)){
break;
}
InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); InputEndpointOnlineFeedbacks[args.Number].FireUpdate();
break; break;
} }
case (DMInputEventIds.EndpointOnlineEventId): case (DMInputEventIds.EndpointOnlineEventId):
{ {
Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback); Debug.Console(2, this, "DM Input EndpointOnlineEventId for input: {0}. State: {1}", args.Number, device.Inputs[args.Number].EndpointOnlineFeedback);
if(!InputEndpointOnlineFeedbacks.ContainsKey(args.Number)){
break;
}
InputEndpointOnlineFeedbacks[args.Number].FireUpdate(); InputEndpointOnlineFeedbacks[args.Number].FireUpdate();
break; break;
} }
case (DMInputEventIds.VideoDetectedEventId): case (DMInputEventIds.VideoDetectedEventId):
{ {
Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number); Debug.Console(2, this, "DM Input {0} VideoDetectedEventId", args.Number);
if(!VideoInputSyncFeedbacks.ContainsKey(args.Number)){
break;
}
VideoInputSyncFeedbacks[args.Number].FireUpdate(); VideoInputSyncFeedbacks[args.Number].FireUpdate();
break; break;
} }
case (DMInputEventIds.InputNameEventId): case (DMInputEventIds.InputNameEventId):
{ {
Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number); Debug.Console(2, this, "DM Input {0} NameFeedbackEventId", args.Number);
if(InputNameFeedbacks.ContainsKey(args.Number)) if(!InputNameFeedbacks.ContainsKey(args.Number))
{ {
InputNameFeedbacks[args.Number].FireUpdate(); break;
} }
InputNameFeedbacks[args.Number].FireUpdate();
break; break;
} }
} }