mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-08-31 19:08:29 +00:00
cleaned out framework files; added framework submodule; referneced p.core to reference in framework; moved essentials.sln; changed paths in sln to match; test build
This commit is contained in:
parent
058ea730ed
commit
0e9d1e4c35
413 changed files with 33026 additions and 71338 deletions
77
PepperDashEssentials/Audio/EssentialsVolumeLevelConfig.cs
Normal file
77
PepperDashEssentials/Audio/EssentialsVolumeLevelConfig.cs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Devices.Common.DSP;
|
||||
using PepperDash.Essentials.DM;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
/// <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()
|
||||
{
|
||||
// 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 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];
|
||||
}
|
||||
// No volume for some reason. We have failed as developers
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
881
PepperDashEssentials/ClassDiagram1.cd
Normal file
881
PepperDashEssentials/ClassDiagram1.cd
Normal file
|
|
@ -0,0 +1,881 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram MajorVersion="1" MinorVersion="1">
|
||||
<Class Name="PepperDash.Essentials.EssentialsRoomVolumesConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAQAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAIAgA=</HashCode>
|
||||
<FileName>Audio\EssentialsVolumeLevelConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsVolumeLevelConfig" Collapsed="true">
|
||||
<Position X="22.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAEAAAAAAAAAAAAAAAAIAAAAgBAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Audio\EssentialsVolumeLevelConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigReader" Collapsed="true">
|
||||
<Position X="26.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAIAAAAAAAABAAAACAAIAAAAQAAAAAAAAAAEAA=</HashCode>
|
||||
<FileName>Config\ConfigReader.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.DeviceFactory" Collapsed="true">
|
||||
<Position X="29.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Config\DeviceFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsConfig" Collapsed="true">
|
||||
<Position X="33.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAEAAAAAQAIAAAAAAAACAAAAAAAAAAAAAAEAAAA=</HashCode>
|
||||
<FileName>Config\EssentialsConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SystemTemplateConfigs" Collapsed="true">
|
||||
<Position X="33.25" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Config\EssentialsConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigTieLine" Collapsed="true">
|
||||
<Position X="31.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAgEAAAAAAEAAAAAAAAAAAAAAAAAAAAAEAIAIA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\ConfigTieLine.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Configuration" Collapsed="true">
|
||||
<Position X="33.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AEAAAAAAAAAAgQAAAAAAgAAAAAAAAAAAAAAgEDAADAQ=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigSourceList" Collapsed="true">
|
||||
<Position X="29.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAQAAACAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigSourceItem" Collapsed="true">
|
||||
<Position X="28" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAgAAAAAAAEAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ConfigInfo" Collapsed="true">
|
||||
<Position X="24.5" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>IQAAAAAEAAAAAAADAAACABQAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Configuration.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SourceListConfigProperties" Collapsed="true">
|
||||
<Position X="24.5" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAAAAIAAAAAgAAAIAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\ConfigurationHelpers.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.DmFactory" Collapsed="true">
|
||||
<Position X="31.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAQAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Factories\DmFactory.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.FactoryHelper" Collapsed="true">
|
||||
<Position X="26.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAEDAAKAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Factories\FactoryHelper.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.IrOutPortConfig" Collapsed="true">
|
||||
<Position X="31.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAABAAAA=</HashCode>
|
||||
<FileName>Configuration ORIGINAL\Factories\FactoryHelper.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.ControlSystem" Collapsed="true">
|
||||
<Position X="35" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAoAgAAIAEAACAAEAIEIBICAAAAAAABAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>ControlSystem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Amplifier" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="21" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA=</HashCode>
|
||||
<FileName>Devices\Amplifier.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaDdvc01RoomBridgePropertiesConfig" Collapsed="true">
|
||||
<Position X="22.75" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaSystemController" Collapsed="true">
|
||||
<Position X="24.5" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAAABAABAgACCAKGBIAAEyBAFAAACYSAgIAAAAJkAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaSystemController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaBridgeBase" Collapsed="true">
|
||||
<Position X="9.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQIQAAAAAAAAgAAAAAAQAAAAAAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaBridgeBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CotijaEssentialsHuddleSpaceRoomBridge" Collapsed="true">
|
||||
<Position X="8.25" Y="5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAAAAIABAAkgAABgIAAAAAAAAAEAAAAAAgBAAACA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SourceSelectMessageContent" Collapsed="true">
|
||||
<Position X="26.25" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddleSpaceRoom" Collapsed="true">
|
||||
<Position X="0.5" Y="9" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>iQFBQAIAAgAAgQAEQACAMABAAABAACAQUAAQAAgCgBA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsHuddleSpaceRoom.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddleVtc1Room" Collapsed="true">
|
||||
<Position X="2.75" Y="9" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>iQFBQAIAIgQMgQAEQAigMABAAABAADIwUACQAAgCgTE=</HashCode>
|
||||
<FileName>Room\Types\EssentialsHuddleVtc1Room.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsPresentationRoom" Collapsed="true">
|
||||
<Position X="5" Y="9" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>iQAEAAIACkAAAQAOQASgMAAJAABgAAAQQAAQAAgCgBA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsPresentationRoom.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsRoomBase" Collapsed="true">
|
||||
<Position X="2.75" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gQAAEAICECgCAQAEAAAUIwIyAAAAgACiAgAAAQECAgA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.CrestronTouchpanelPropertiesConfig" Collapsed="true">
|
||||
<Position X="26.25" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AICCIAAIGIAAAAAgCAAIAEAAAAAAAAAAAAEAIAAAAAA=</HashCode>
|
||||
<FileName>UI\CrestronTouchpanelPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UiSetupPropertiesConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UI\CrestronTouchpanelPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsTouchpanelController" Collapsed="true">
|
||||
<Position X="21" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAIAEAAAAAAAAAAAAAAAAEAAAAACKIBAAgACAAAAAA=</HashCode>
|
||||
<FileName>UI\EssentialsTouchpanelController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.HttpLogoServer" Collapsed="true">
|
||||
<Position X="19.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAACAAAAABAAAAAAAAAABAAAAAAAAAAkAAAAA=</HashCode>
|
||||
<FileName>UI\HttpLogoServer.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIBoolJoin" Collapsed="true">
|
||||
<Position X="35" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>j+jWCNqEIGzi4UTaTgyn37kpncQJK7L42VMLmMgTE5A=</HashCode>
|
||||
<FileName>UI\JoinConstants\UIBoolJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UISmartObjectJoin" Collapsed="true">
|
||||
<Position X="21" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BAggBIABCQAAGAAQAAAACAACAAAAAAAAAAIAAAAAAAA=</HashCode>
|
||||
<FileName>UI\JoinConstants\UISmartObjectJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIStringJoin" Collapsed="true">
|
||||
<Position X="22.75" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>BkBgIAgAAggOQAFGAYQIABACgCEBjkSQAUEAASIABCE=</HashCode>
|
||||
<FileName>UI\JoinConstants\UIStringlJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIUshortJoin" Collapsed="true">
|
||||
<Position X="24.5" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQAAAACAAAACAEAAIAAAAAAIABAIAAAABAAAEAAAAA=</HashCode>
|
||||
<FileName>UI\JoinConstants\UIUshortJoin.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SubpageReferenceListActivityItem" Collapsed="true">
|
||||
<Position X="28" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
|
||||
<FileName>UI\SubpageReferenceListActivityItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SubpageReferenceListButtonAndModeItem" Collapsed="true">
|
||||
<Position X="29.75" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
|
||||
<FileName>UI\SubpageReferenceListCallStagingItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SubpageReferenceListSourceItem" Collapsed="true">
|
||||
<Position X="31.5" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAABAAAAAAAAAAAAAAAAAAAAgAAAAACAAAAAABgAAA=</HashCode>
|
||||
<FileName>UI\SubpageReferenceListSourceItem.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.PanelDriverBase" Collapsed="true">
|
||||
<Position X="8.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>CAAIkAAAAAAQEAAAEAACAAAAAIAEABAAAgAACAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsPanelMainInterfaceDriver" Collapsed="true">
|
||||
<Position X="1" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>ABAAAAAAAhgAAAAAEAAAAAAAAIAEAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\Essentials\EssentialsPanelMainInterfaceDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsPresentationPanelAvFunctionsDriver" Collapsed="true">
|
||||
<Position X="3.25" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gTEAIIAiCggFNCQ4EA4AWBkAKJCEqAAOS4CKMAQQJQA=</HashCode>
|
||||
<FileName>UIDrivers\Essentials\EssentialsPresentationPanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddlePanelAvFunctionsDriver" Collapsed="true">
|
||||
<Position X="7.75" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gRQAIICuAghENHQpEA4IWCkBMJDEsEAEC4CAMARQIBA=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddle\EssentialsHuddlePanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.EssentialsHuddleVtc1PanelAvFunctionsDriver" Collapsed="true">
|
||||
<Position X="12.25" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>GRwAIYC+oghAeHStEDAIWCdBMADEsBAcDwCAMARYIBg=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.JoinedSigInterlock" Collapsed="true">
|
||||
<Position X="19.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQgAIAAAAAAAAAEAAAAAQAAAAEAAAAAAAAEAAAgAA=</HashCode>
|
||||
<FileName>UIDrivers\JoinedSigInterlock.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SingleSubpageModalAndBackDriver" Collapsed="true">
|
||||
<Position X="14.5" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAEAAAQAAABIAEAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SingleSubpageModalDriver" Collapsed="true">
|
||||
<Position X="16.75" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAEAAAAAAABAAEAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\Page Drivers\SingleSubpageModalDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SigInterlock" Collapsed="true">
|
||||
<Position X="19.25" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQAAIAAAAAAAAIEAAAAAAAAAAEAAAAAAAAEAAAgAA=</HashCode>
|
||||
<FileName>UIDrivers\SigInterlock.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SmartObjectRoomsList" Collapsed="true">
|
||||
<Position X="21" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAACAAACBAAAAAAAAAAAAAAAAAAAAIAAAAAAQA=</HashCode>
|
||||
<FileName>UIDrivers\SmartObjectRoomsList.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.SmartObjectRoomsListItem" Collapsed="true">
|
||||
<Position X="22.75" Y="7.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAAAAAAAAAABAAQAAAAAAAAAACAAEAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\SmartObjectRoomsList.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.VolumeDeviceChangeEventArgs" Collapsed="true">
|
||||
<Position X="26.25" Y="8.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAABAAAAAEAAAAAAAAAAAAAAAAAAAQAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase" Collapsed="true">
|
||||
<Position X="8.25" Y="9.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>IAGigRBpCgZwAIMSBBIbIgAAImAPtEBiAAgECpJgKQo=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionRoomExtensions" Collapsed="true">
|
||||
<Position X="31.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAACgAIQAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionStaticAssetExtensions" Collapsed="true">
|
||||
<Position X="35" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAQAAACAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.EssentialsHuddleVtc1FusionController" Collapsed="true">
|
||||
<Position X="8.25" Y="11" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AACAAAAAAgAAAIAAAAAAAAAgIBAQAAAAAAAAAAAAAQA=</HashCode>
|
||||
<FileName>OTHER\Fusion\EssentialsHuddleVtc1FusionController.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ScheduleChangeEventArgs" Collapsed="true">
|
||||
<Position X="33.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionEventHandlers.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.MeetingChangeEventArgs" Collapsed="true">
|
||||
<Position X="26.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionEventHandlers.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ProcessorProgReg" Collapsed="true">
|
||||
<Position X="19.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionProcessorQueries.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ProcessorProgramItem" Collapsed="true">
|
||||
<Position X="35" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAEAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionProcessorQueries.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionRoomGuids" Collapsed="true">
|
||||
<Position X="33.25" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAICAAAAAAAAAAAAAAAAAACAAAATQAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionOccupancySensorAsset" Collapsed="true">
|
||||
<Position X="29.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAQAAAAAAAAQAAAAAAQAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.FusionAsset" Collapsed="true">
|
||||
<Position X="28" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAQAQAAAAAAAAQAAAAAAQAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.RoomSchedule" Collapsed="true">
|
||||
<Position X="31.5" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.LocalTimeRequest" Collapsed="true">
|
||||
<Position X="24.5" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.RequestSchedule" Collapsed="true">
|
||||
<Position X="22.75" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACACAAAAQAAAAAAAAAAAAAAAAAAAACAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.RequestAction" Collapsed="true">
|
||||
<Position X="21" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACAAAgAAQAAAAAAAAAAAAAAAAAAIAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ActionResponse" Collapsed="true">
|
||||
<Position X="19.25" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAIAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Parameter" Collapsed="true">
|
||||
<Position X="33.25" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.ScheduleResponse" Collapsed="true">
|
||||
<Position X="35" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACAAAAAAQAAAAAAAAAAgAAAAAAAAAAABAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Event" Collapsed="true">
|
||||
<Position X="24.5" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AABCAAAAYEAAEBIBAIAAJAQAQKAYAAAIEAAAEAACCgg=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Resources" Collapsed="true">
|
||||
<Position X="26.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Rooms" Collapsed="true">
|
||||
<Position X="29.75" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Room" Collapsed="true">
|
||||
<Position X="28" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAQAAAAAAAAAAAAAAAAEAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Attendees" Collapsed="true">
|
||||
<Position X="22.75" Y="0.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Required" Collapsed="true">
|
||||
<Position X="24.5" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.Optional" Collapsed="true">
|
||||
<Position X="31.5" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.MeetingType" Collapsed="true">
|
||||
<Position X="28" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.MeetingTypes" Collapsed="true">
|
||||
<Position X="29.75" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.LiveMeeting" Collapsed="true">
|
||||
<Position X="21" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAQAAIAAAAAAACAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Fusion.LiveMeetingURL" Collapsed="true">
|
||||
<Position X="22.75" Y="5.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>OTHER\Fusion\FusionRviDataClasses.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.DDVC01RoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="5" Y="6.25" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAIAgAAQAAAAAAAAEAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\DDVC01RoomPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.DDVC01SpeedDial" Collapsed="true">
|
||||
<Position X="28" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAEAAAAQAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\DDVC01RoomPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHuddleRoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="2.75" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAACAAAAAABAAAAAAAAABA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsHuddleRoomPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHuddleVtc1PropertiesConfig" Collapsed="true">
|
||||
<Position X="5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAgAAAAAAAAAAACIAAAAABAAAAAAAAABA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsPresentationRoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="0.5" Y="4.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAACAIAAAAAAAAAAABAACAAAAAABAAAAAAAAABA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsPresentationPropertiesConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomConfig" Collapsed="true">
|
||||
<Position X="26.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAEAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomPropertiesConfig" Collapsed="true">
|
||||
<Position X="2.75" Y="3.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AABAEQAAAAEoAAEEAAQAAAACAAAAAAgggAAAAQAAAgA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsLightingPropertiesConfig" Collapsed="true">
|
||||
<Position X="19.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomMicrophonePrivacyConfig" Collapsed="true">
|
||||
<Position X="31.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAEAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsHelpPropertiesConfig" Collapsed="true">
|
||||
<Position X="35" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAgABAAAAAIAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsOneButtonMeetingPropertiesConfig" Collapsed="true">
|
||||
<Position X="22.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomAddressPropertiesConfig" Collapsed="true">
|
||||
<Position X="24.5" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAQAAAgAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsLogoPropertiesConfig" Collapsed="true">
|
||||
<Position X="21" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIACQAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomOccSensorConfig" Collapsed="true">
|
||||
<Position X="33.25" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AACAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomTechConfig" Collapsed="true">
|
||||
<Position X="35" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomEmergencyConfig" Collapsed="true">
|
||||
<Position X="28" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAABAACAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomEmergencyConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Config.EssentialsRoomEmergencyTriggerConfig" Collapsed="true">
|
||||
<Position X="29.75" Y="2.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAABQAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Config\EssentialsRoomEmergencyConfig.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.CotijaDdvc01DeviceBridge" Collapsed="true" BaseTypeListCollapsed="true">
|
||||
<Position X="21" Y="1.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AUAAAAgAAAACwAYAAAAAAAEAAAAAAAAAIcAAAEAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\CotijaDdvc01DeviceBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" Collapsed="true" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IChannelExtensions" Collapsed="true">
|
||||
<Position X="21" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IChannelExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IColorExtensions" Collapsed="true">
|
||||
<Position X="22.75" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IColorExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IDPadExtensions" Collapsed="true">
|
||||
<Position X="24.5" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IDvrExtensions" Collapsed="true">
|
||||
<Position X="26.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IDvrExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.INumericExtensions" Collapsed="true">
|
||||
<Position X="28" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\INumericExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.IPowerExtensions" Collapsed="true">
|
||||
<Position X="29.75" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\IPowerExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.ISetTopBoxControlsExtensions" Collapsed="true">
|
||||
<Position X="33.25" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.ITransportExtensions" Collapsed="true">
|
||||
<Position X="35" Y="4.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAACAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\DeviceTypeInterfaces\ITransportExtensions.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.Cotija.CotijaDdvc01RoomBridge" Collapsed="true">
|
||||
<Position X="10.5" Y="5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>gACIAAAAAAICAFAAAACAAAEIIAAAAAQAQAAAABAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaDdvc01RoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.EssentialsRoomEmergencyBase" Collapsed="true">
|
||||
<Position X="8.25" Y="6.5" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Emergency\EsentialsRoomEmergencyContactClosure.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
<Lollipop Position="0.2" />
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.Room.EssentialsRoomEmergencyContactClosure" Collapsed="true">
|
||||
<Position X="8.25" Y="7.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAASBAAAAAAAAAAAAAABAAAAAAAEAA=</HashCode>
|
||||
<FileName>Room\Emergency\EsentialsRoomEmergencyContactClosure.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIDrivers.EssentialsHuddleTechPageDriver" Collapsed="true">
|
||||
<Position X="5.5" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAQAAAAAiACDAAAGCAACgAIAABECBAgQAAAAQAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddle\EssentialsHuddleTechPageDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Class Name="PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver" Collapsed="true">
|
||||
<Position X="10" Y="1.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>XAASAoAiAagwAcBAGAUURWQEOHQFAKCmAABCNSSEDPA=</HashCode>
|
||||
<FileName>UIDrivers\VC\EssentialsVideoCodecUiDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Class>
|
||||
<Interface Name="PepperDash.Essentials.IHasCurrentSourceInfoChange" Collapsed="true">
|
||||
<Position X="22.75" Y="9.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.IAVDriver" Collapsed="true">
|
||||
<Position X="19.25" Y="9.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAgAAAAAAAAACBAAACAAAAIBAAAEAAAEAgAAAAAAIAA=</HashCode>
|
||||
<FileName>UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Interface Name="PepperDash.Essentials.Room.Cotija.IDelayedConfiguration" Collapsed="true">
|
||||
<Position X="21" Y="9.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\Interfaces.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Interface>
|
||||
<Enum Name="PepperDash.Essentials.eShutdownType" Collapsed="true">
|
||||
<Position X="29.75" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAQAAAAAAACAAAAAAAAAAAAAAAAAAAAAEACAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eVacancyMode" Collapsed="true">
|
||||
<Position X="31.5" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAACAAAAAAAAAAAAAAAAACAAAAAAAAAAEAAAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eWarmingCoolingMode" Collapsed="true">
|
||||
<Position X="33.25" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAIEAAAA=</HashCode>
|
||||
<FileName>Room\Types\EssentialsRoomBase.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eAvSubpageType" Collapsed="true">
|
||||
<Position X="24.5" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AIAAAAAAAAAAAAAAAhBAAAAAAAAAAACYAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eAvSourceSubpageType" Collapsed="true">
|
||||
<Position X="22.75" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAAACAAAEAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eCommonSubpageType" Collapsed="true">
|
||||
<Position X="28" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAEAAAAAAAAAIAAAAAAAAQAAAAQAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eAvSmartObjects" Collapsed="true">
|
||||
<Position X="21" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAABAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.eCommonSmartObjects" Collapsed="true">
|
||||
<Position X="26.25" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\enums and base.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Enum Name="PepperDash.Essentials.ChangeType" Collapsed="true">
|
||||
<Position X="19.25" Y="10.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAgCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Enum>
|
||||
<Delegate Name="PepperDash.Essentials.PressAndHoldAction" Collapsed="true">
|
||||
<Position X="19.25" Y="11.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
|
||||
<FileName>Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Delegate Name="PepperDash.Essentials.SourceInfoChangeHandler" Collapsed="true">
|
||||
<Position X="21" Y="11.75" Width="1.5" />
|
||||
<TypeIdentifier>
|
||||
<HashCode>AAAAAAAAAAAAACAAACAAAAAAAAAAAAAAAAAAACAAAAA=</HashCode>
|
||||
<FileName>UIDrivers\VolumeAndSourceChangeArgs.cs</FileName>
|
||||
</TypeIdentifier>
|
||||
</Delegate>
|
||||
<Font Name="Segoe UI" Size="9" />
|
||||
</ClassDiagram>
|
||||
188
PepperDashEssentials/Config/ConfigReader.cs
Normal file
188
PepperDashEssentials/Config/ConfigReader.cs
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads the ConfigObject from the file
|
||||
/// </summary>
|
||||
public class ConfigReader
|
||||
{
|
||||
public static EssentialsConfig ConfigObject { get; private set; }
|
||||
|
||||
public static bool LoadConfig2()
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loading unmerged system/template portal configuration file.");
|
||||
try
|
||||
{
|
||||
var filePath = Global.FilePathPrefix + "configurationFile.json";
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to load config file: '{0}'", filePath);
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error,
|
||||
"ERROR: Configuration file not present. Please load file to {0} and reset program", filePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
using (StreamReader fs = new StreamReader(filePath))
|
||||
{
|
||||
var doubleObj = JObject.Parse(fs.ReadToEnd());
|
||||
ConfigObject = MergeConfigs(doubleObj).ToObject<EssentialsConfig>();
|
||||
|
||||
// Extract SystemUrl and TemplateUrl into final config output
|
||||
|
||||
if (doubleObj["system_url"] != null)
|
||||
{
|
||||
ConfigObject.SystemUrl = doubleObj["system_url"].Value<string>();
|
||||
}
|
||||
|
||||
if (doubleObj["template_url"] != null)
|
||||
{
|
||||
ConfigObject.TemplateUrl= doubleObj["template_url"].Value<string>();
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Successfully Loaded Merged Config");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Config load failed: \r{0}", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static JObject MergeConfigs(JObject doubleConfig)
|
||||
{
|
||||
var system = JObject.FromObject(doubleConfig["system"]);
|
||||
var template = JObject.FromObject(doubleConfig["template"]);
|
||||
var merged = new JObject();
|
||||
|
||||
// Put together top-level objects
|
||||
// skip any objects that don't have template objects
|
||||
|
||||
if (system["info"] != null)
|
||||
merged.Add("info", Merge(template["info"], system["info"]));
|
||||
else
|
||||
merged.Add("info", template["info"]);
|
||||
|
||||
merged.Add("devices", MergeArraysOnTopLevelProperty(template["devices"] as JArray,
|
||||
system["devices"] as JArray, "uid"));
|
||||
|
||||
if (template["rooms"] != null)
|
||||
{
|
||||
if (system["rooms"] == null)
|
||||
merged.Add("rooms", template["rooms"]);
|
||||
else
|
||||
merged.Add("rooms", MergeArraysOnTopLevelProperty(template["rooms"] as JArray,
|
||||
system["rooms"] as JArray, "key"));
|
||||
}
|
||||
|
||||
if (template["sourceLists"] != null)
|
||||
{
|
||||
if (system["sourceLists"] == null)
|
||||
merged.Add("sourceLists", template["sourceLists"]);
|
||||
else
|
||||
merged.Add("sourceLists", Merge(template["sourceLists"], system["sourceLists"]));
|
||||
}
|
||||
|
||||
// Template tie lines take precdence. Config tool doesn't do them at system
|
||||
// level anyway...
|
||||
if (template["tieLines"] != null)
|
||||
merged.Add("tieLines", template["tieLines"]);
|
||||
//else if (system["tieLines"] != null)
|
||||
// merged.Add("tieLines", system["tieLines"]);
|
||||
//else
|
||||
// merged.Add("tieLines", new JArray());
|
||||
|
||||
Debug.Console(2, "MERGED CONFIG RESULT: \x0d\x0a{0}", merged);
|
||||
return merged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges the contents of a base and a delta array, matching the entries on a top-level property
|
||||
/// given by propertyName. Returns a merge of them. Items in the delta array that do not have
|
||||
/// a matched item in base array will not be merged.
|
||||
/// </summary>
|
||||
static JArray MergeArraysOnTopLevelProperty(JArray a1, JArray a2, string propertyName)
|
||||
{
|
||||
var result = new JArray();
|
||||
if (a2 == null)
|
||||
result = a1;
|
||||
else if (a1 != null)
|
||||
{
|
||||
for (int i = 0; i < a1.Count(); i++)
|
||||
{
|
||||
var a1Dev = a1[i];
|
||||
// Try to get a system device and if found, merge it onto template
|
||||
var a2Match = a2.FirstOrDefault(t => t[propertyName].Equals(a1Dev[propertyName]));// t.Value<int>("uid") == tmplDev.Value<int>("uid"));
|
||||
if (a2Match != null)
|
||||
{
|
||||
var mergedItem = Merge(a1Dev, a2Match);// Merge(JObject.FromObject(a1Dev), JObject.FromObject(a2Match));
|
||||
result.Add(mergedItem);
|
||||
}
|
||||
else
|
||||
result.Add(a1Dev);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper for using with JTokens. Converts to JObject
|
||||
/// </summary>
|
||||
static JObject Merge(JToken t1, JToken t2)
|
||||
{
|
||||
return Merge(JObject.FromObject(t1), JObject.FromObject(t2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merge b ONTO a
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <param name="b"></param>
|
||||
static JObject Merge(JObject o1, JObject o2)
|
||||
{
|
||||
foreach (var o2Prop in o2)
|
||||
{
|
||||
var o1Value = o1[o2Prop.Key];
|
||||
if (o1Value == null)
|
||||
o1.Add(o2Prop.Key, o2Prop.Value);
|
||||
else
|
||||
{
|
||||
JToken replacement = null;
|
||||
if (o2Prop.Value.HasValues && o1Value.HasValues) // Drill down
|
||||
replacement = Merge(JObject.FromObject(o1Value), JObject.FromObject(o2Prop.Value));
|
||||
else
|
||||
replacement = o2Prop.Value;
|
||||
o1[o2Prop.Key].Replace(replacement);
|
||||
}
|
||||
}
|
||||
return o1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the group for a given device key in config
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetGroupForDeviceKey(string key)
|
||||
{
|
||||
var dev = ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(key, StringComparison.OrdinalIgnoreCase));
|
||||
return dev == null ? null : dev.Group;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
67
PepperDashEssentials/Config/EssentialsConfig.cs
Normal file
67
PepperDashEssentials/Config/EssentialsConfig.cs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Loads the ConfigObject from the file
|
||||
/// </summary>
|
||||
public class EssentialsConfig : BasicConfig
|
||||
{
|
||||
[JsonProperty("system_url")]
|
||||
public string SystemUrl { get; set; }
|
||||
|
||||
[JsonProperty("template_url")]
|
||||
public string TemplateUrl { get; set; }
|
||||
|
||||
|
||||
//public CotijaConfig Cotija { get; private set; }
|
||||
|
||||
[JsonProperty("systemUuid")]
|
||||
public string SystemUuid
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Regex.Match(SystemUrl, @"https?:\/\/.*\/systems\/(.*)\/#.*");
|
||||
|
||||
string uuid = result.Groups[1].Value;
|
||||
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty("templateUuid")]
|
||||
public string TemplateUuid
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = Regex.Match(TemplateUrl, @"https?:\/\/.*\/templates\/(.*)\/#.*");
|
||||
|
||||
string uuid = result.Groups[1].Value;
|
||||
|
||||
return uuid;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty("rooms")]
|
||||
public List<EssentialsRoomConfig> Rooms { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class SystemTemplateConfigs
|
||||
{
|
||||
public EssentialsConfig System { get; set; }
|
||||
|
||||
public EssentialsConfig Template { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
|
||||
//public class TPConfig : DeviceConfig
|
||||
//{
|
||||
// new public TPConfigProperties Properties { get; set; }
|
||||
//}
|
||||
|
||||
//public class TPConfigProperties
|
||||
//{
|
||||
// /*
|
||||
// "properties": {
|
||||
// "ipId": "aa",
|
||||
// "defaultSystemKey": "system1",
|
||||
// "sgdPath": "\\NVRAM\\Program1\\Sgds\\PepperDash Essentials TSW1050_v0.9.sgd",
|
||||
// "usesSplashPage": true,
|
||||
// "showDate": true,
|
||||
// "showTime": false
|
||||
// }
|
||||
// */
|
||||
// public uint IpId { get; set; }
|
||||
// public string deafultSystemKey { get; set; }
|
||||
// public string SgdPath { get; set; }
|
||||
// public bool UsesSplashPage { get; set; }
|
||||
// public bool ShowDate { get; set; }
|
||||
// public bool ShowTime { get; set; }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// The gist of this converter: The comspec JSON comes in with normal values that need to be converted
|
||||
///// into enum names. This converter takes the value and applies the appropriate enum's name prefix to the value
|
||||
///// and then returns the enum value using Enum.Parse
|
||||
///// </summary>
|
||||
//public class TPPropertiesConverter : JsonConverter
|
||||
//{
|
||||
// public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
// {
|
||||
// return JObject.Load(reader);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// This will be hit with every value in the ComPortConfig class. We only need to
|
||||
// /// do custom conversion on the comspec items.
|
||||
// /// </summary>
|
||||
// public override bool CanConvert(Type objectType)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// public override bool CanRead { get { return true; } }
|
||||
// public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
82
PepperDashEssentials/Configuration Original/ConfigTieLine.cs
Normal file
82
PepperDashEssentials/Configuration Original/ConfigTieLine.cs
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class ConfigTieLine
|
||||
{
|
||||
[JsonProperty(Required=Required.Always)]
|
||||
public string SourceDeviceKey { get; set; }
|
||||
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string SourcePortKey { get; set; }
|
||||
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string DestinationDeviceKey { get; set; }
|
||||
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string DestinationPortKey { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("Tie line: [{0}]{1} --> [{2}]{3}", SourceDeviceKey, SourcePortKey, DestinationDeviceKey, DestinationPortKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a tie line if one can be constructed between the two devices and ports
|
||||
/// </summary>
|
||||
/// <returns>TieLine or null if devices or ports don't exist</returns>
|
||||
public TieLine GetTieLine()
|
||||
{
|
||||
var sourceDevice = (IRoutingOutputs)DeviceManager.GetDeviceForKey(SourceDeviceKey);
|
||||
var destinationDevice = (IRoutingInputs)DeviceManager.GetDeviceForKey(DestinationDeviceKey);
|
||||
|
||||
if (sourceDevice == null)
|
||||
{
|
||||
Debug.Console(0, " Cannot create TieLine. Source device '{0}' not found or does not have outputs",
|
||||
SourceDeviceKey);
|
||||
return null;
|
||||
}
|
||||
else if (destinationDevice == null)
|
||||
{
|
||||
Debug.Console(0, " Cannot create TieLine. Destination device '{0}' not found or does not have inputs",
|
||||
DestinationDeviceKey);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the ports by key name from the lists
|
||||
RoutingOutputPort sourcePort = sourceDevice.OutputPorts.FirstOrDefault(
|
||||
p => p.Key.Equals(SourcePortKey, System.StringComparison.OrdinalIgnoreCase));
|
||||
//RoutingOutputPort sourcePort = null;
|
||||
//sourceDevice.OutputPorts.TryGetValue(SourcePortKey, out sourcePort);
|
||||
if (sourcePort == null)
|
||||
{
|
||||
Debug.Console(0, " Cannot create TieLine {0}-->{1}. Source device does not have output port '{2}'",
|
||||
sourceDevice.Key, destinationDevice.Key, SourcePortKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
RoutingInputPort destinationPort = destinationDevice.InputPorts.FirstOrDefault(
|
||||
p => p.Key.Equals(DestinationPortKey, System.StringComparison.OrdinalIgnoreCase));
|
||||
//RoutingInputPort destinationPort = null;
|
||||
//destinationDevice.InputPorts.TryGetValue(DestinationPortKey, out destinationPort);
|
||||
if (destinationPort == null)
|
||||
{
|
||||
Debug.Console(0, " Cannot create TieLine {0}-->{1}. Destination device does not have input port '{2}'",
|
||||
sourceDevice.Key, destinationDevice.Key, DestinationPortKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
var tl = new TieLine(sourcePort, destinationPort);
|
||||
Debug.Console(1, " Created {0}", this);
|
||||
return tl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
287
PepperDashEssentials/Configuration Original/Configuration.cs
Normal file
287
PepperDashEssentials/Configuration Original/Configuration.cs
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using Crestron.SimplSharpPro.Diagnostics;
|
||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices;
|
||||
//using PepperDash.Essentials.Core.Devices.Dm;
|
||||
//using PepperDash.Essentials.Fusion;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public static class Configuration
|
||||
{
|
||||
|
||||
public static string LastPath { get; private set; }
|
||||
public static CrestronControlSystem ControlSystem { get; private set; }
|
||||
|
||||
public static void Initialize(CrestronControlSystem cs)
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand(ReloadFromConsole, "configreload", "Reloads configuration file",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
ControlSystem = cs;
|
||||
}
|
||||
|
||||
public static bool ReadConfiguration(string filePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Read file
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
LastPath = filePath;
|
||||
string json = File.ReadToEnd(filePath, System.Text.Encoding.ASCII);
|
||||
JObject jo = JObject.Parse(json);
|
||||
|
||||
var info = JsonConvert.DeserializeObject<ConfigInfo>(jo["info"].ToString());
|
||||
Debug.Console(0, "\r[Config] file read:");
|
||||
Debug.Console(0, " File: {0}", filePath);
|
||||
Debug.Console(0, " Name: {0}", info.Name);
|
||||
Debug.Console(0, " Type: {0}", info.SystemTemplateType);
|
||||
Debug.Console(0, " Date: {0}", info.EditDate);
|
||||
Debug.Console(0, " ConfigVersion: {0}", info.Version);
|
||||
Debug.Console(0, " EditedBy: {0}", info.EditedBy);
|
||||
Debug.Console(0, " Comment: {0}\r", info.Comment);
|
||||
|
||||
// Get the main config object
|
||||
var jConfig = jo["configuration"];
|
||||
|
||||
// Devices
|
||||
var jDevices = (JArray)jConfig["devices"];
|
||||
CreateDevices(jDevices);
|
||||
|
||||
// TieLines
|
||||
var jRouting = jConfig["routing"];
|
||||
CreateRouting(jRouting);
|
||||
|
||||
/// Parse the available source list(s)
|
||||
var jSourceLists = (JArray)jConfig["sourceLists"];
|
||||
var jSourceListJson = jSourceLists.ToString();
|
||||
List<ConfigSourceList> sourceLists = JsonConvert.DeserializeObject<List<ConfigSourceList>>(jSourceListJson);
|
||||
|
||||
// System
|
||||
var jSystems = (JArray)jConfig["systems"];
|
||||
CreateSystems(jSystems, sourceLists);
|
||||
|
||||
// Activate everything
|
||||
DeviceManager.ActivateAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, "[Config] file not found '{0}'", filePath);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, "Configuration read error: \r {0}", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CreateDevices(JArray jDevices)
|
||||
{
|
||||
//Debug.Console(0, " Creating {0} devices", jDevices.Count);
|
||||
//for (int i = 0; i < jDevices.Count; i++)
|
||||
//{
|
||||
// var jDev = jDevices[i];
|
||||
|
||||
// //var devConfig = JsonConvert.DeserializeObject<DeviceConfig>(jDev.ToString());
|
||||
// //Debug.Console(0, "++++++++++++{0}", devConfig);
|
||||
|
||||
|
||||
// var group = jDev["group"].Value<string>();
|
||||
// Debug.Console(0, " [{0}], creating {1}:{2}", jDev["key"].Value<string>(),
|
||||
// group, jDev["type"].Value<string>());
|
||||
|
||||
// Device dev = null;
|
||||
// if (group.Equals("Display", StringComparison.OrdinalIgnoreCase))
|
||||
// dev = DisplayFactory.CreateDisplay(jDev);
|
||||
// else if (group.Equals("DeviceMonitor", StringComparison.OrdinalIgnoreCase))
|
||||
// dev = DeviceManagerFactory.Create(jDev);
|
||||
// //else if (group.Equals("Pc", StringComparison.OrdinalIgnoreCase))
|
||||
// // dev = PcFactory.Create(jDev);
|
||||
// //else if (group.Equals("SetTopBox", StringComparison.OrdinalIgnoreCase))
|
||||
// // dev = SetTopBoxFactory.Create(jDev);
|
||||
// //else if (group.Equals("DiscPlayer", StringComparison.OrdinalIgnoreCase))
|
||||
// // dev = DiscPlayerFactory.Create(jDev);
|
||||
// //else if (group.Equals("Touchpanel", StringComparison.OrdinalIgnoreCase))
|
||||
// // dev = TouchpanelFactory.Create(jDev);
|
||||
// else if (group.Equals("dmEndpoint", StringComparison.OrdinalIgnoreCase)) // Add Transmitter and Receiver
|
||||
// dev = DmFactory.Create(jDev);
|
||||
// else if (group.Equals("dmChassic", StringComparison.OrdinalIgnoreCase))
|
||||
// dev = DmFactory.CreateChassis(jDev);
|
||||
// else if (group.Equals("processor", StringComparison.OrdinalIgnoreCase))
|
||||
// continue; // ignore it. Has no value right now.
|
||||
// //else if (group.Equals("remote", StringComparison.OrdinalIgnoreCase))
|
||||
// // dev = RemoteFactory.Create(jDev);
|
||||
// else
|
||||
// {
|
||||
// Debug.Console(0, " ERROR: Device [{0}] has unknown Group '{1}'. Skipping",
|
||||
// jDev["key"].Value<string>(), group);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// if (dev != null)
|
||||
// DeviceManager.AddDevice(dev);
|
||||
// else
|
||||
// Debug.Console(0, " ERROR: failed to create device {0}",
|
||||
// jDev["key"].Value<string>());
|
||||
//}
|
||||
}
|
||||
|
||||
static void CreateSystems(JArray jSystems, List<ConfigSourceList> sourceLists)
|
||||
{
|
||||
// // assuming one system
|
||||
// var jSystem = jSystems[0];
|
||||
// var name = jSystem.Value<string>("name");
|
||||
// var key = FactoryHelper.KeyOrConvertName(jSystem.Value<string>("key"), name);
|
||||
|
||||
// if (jSystem.Value<string>("type").Equals("EssentialsHuddleSpace", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
// var sys = new HuddleSpaceRoom(key, name);
|
||||
// var props = jSystem["properties"];
|
||||
// var displayKey = props["displayKey"].Value<string>();
|
||||
// if (displayKey != null)
|
||||
// sys.DefaultDisplay = (DisplayBase)DeviceManager.GetDeviceForKey(displayKey);
|
||||
|
||||
// // Add sources from passed in config list
|
||||
// var myList = sourceLists.FirstOrDefault(
|
||||
// l => l.Key.Equals(props.Value<string>("sourceListKey"), StringComparison.OrdinalIgnoreCase));
|
||||
// if (myList != null)
|
||||
// AddSourcesToSystem(sys, myList);
|
||||
|
||||
// DeviceManager.AddDevice(sys);
|
||||
|
||||
// //spin up a fusion thing too
|
||||
//#warning add this fusion connector back in later
|
||||
// //DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemController(sys, 0xf1));
|
||||
//}
|
||||
}
|
||||
|
||||
//static void AddSourcesToSystem(Room system, ConfigSourceList configList)
|
||||
//{
|
||||
//foreach (var configItem in configList.PresentationSources)
|
||||
//{
|
||||
// var src = (IPresentationSource)DeviceManager.GetDeviceForKey(configItem.SourceKey);
|
||||
// if (src != null)
|
||||
// system.Sources.Add(configItem.Number, src);
|
||||
// else
|
||||
// Debug.Console(0, system, "cannot find source '{0}' from list {1}",
|
||||
// configItem.SourceKey, configList.Name);
|
||||
//}
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Links up routing, creates tie lines
|
||||
/// </summary>
|
||||
/// <param name="jRouting">The "Routing" JArray from configuration</param>
|
||||
static void CreateRouting(JToken jRouting)
|
||||
{
|
||||
var jsonTieLines = jRouting["tieLines"].ToString();
|
||||
var tieLineConfigs = JsonConvert.DeserializeObject<List<ConfigTieLine>>(jsonTieLines);
|
||||
foreach (var c in tieLineConfigs)
|
||||
{
|
||||
var tl = c.GetTieLine();
|
||||
if (tl != null)
|
||||
TieLineCollection.Default.Add(tl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the IIROutputPorts device (control system, etc) that contains a given IR port
|
||||
/// </summary>
|
||||
/// <param name="propsToken"></param>
|
||||
static IROutputPort GetIrPort(JToken propsToken)
|
||||
{
|
||||
var portDevName = propsToken.Value<string>("IrPortDevice");
|
||||
var portNum = propsToken.Value<uint>("IrPortNumber");
|
||||
if (portDevName.Equals("controlSystem", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
IIROutputPorts irDev = ControlSystem;
|
||||
if (portNum <= irDev.NumberOfIROutputPorts)
|
||||
return ControlSystem.IROutputPorts[portNum];
|
||||
else
|
||||
Debug.Console(0, "[Config] ERROR: IR Port {0} out of range. Range 0-{1} on {2}", portNum,
|
||||
ControlSystem.IROutputPorts.Count, irDev.ToString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static void HandleUnknownType(JToken devToken, string type)
|
||||
{
|
||||
Debug.Console(0, "[Config] ERROR: Type '{0}' not found in group '{1}'", type,
|
||||
devToken.Value<string>("Group"));
|
||||
}
|
||||
|
||||
static void HandleDeviceCreationError(JToken devToken, Exception e)
|
||||
{
|
||||
Debug.Console(0, "[Config] ERROR creating device [{0}]: \r{1}",
|
||||
devToken["Key"].Value<string>(), e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Console helper to reload
|
||||
/// </summary>
|
||||
static void ReloadFromConsole(string s)
|
||||
{
|
||||
// Gotta tear down everything first!
|
||||
|
||||
if (!string.IsNullOrEmpty(LastPath))
|
||||
{
|
||||
ReadConfiguration(LastPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfigSourceList
|
||||
{
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string Key { get; set; }
|
||||
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public List<ConfigSourceItem> PresentationSources { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class ConfigSourceItem
|
||||
{
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public uint Number { get; set; }
|
||||
|
||||
[JsonProperty(Required = Required.Always)]
|
||||
public string SourceKey { get; set; }
|
||||
|
||||
public string AlternateName { get; set; }
|
||||
}
|
||||
|
||||
public class ConfigInfo
|
||||
{
|
||||
public string SystemTemplateType { get; set; }
|
||||
public string ProcessorType { get; set; }
|
||||
public string Name { get; set; }
|
||||
public uint ProgramSlotNumber { get; set; }
|
||||
public string Version { get; set; }
|
||||
public string EditedBy { get; set; }
|
||||
public string EditDate { get; set; }
|
||||
public string Comment { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class SourceListConfigProperties
|
||||
{
|
||||
[JsonProperty(Required= Required.Always)]
|
||||
public uint Number { get; set; }
|
||||
[JsonProperty(Required= Required.Always)]
|
||||
public string SourceKey { get; set; }
|
||||
public string AltName { get; set; }
|
||||
public string AltIcon { get; set; }
|
||||
|
||||
public SourceListConfigProperties()
|
||||
{
|
||||
AltName = "";
|
||||
AltIcon = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
//using System;
|
||||
//using Crestron.SimplSharpPro;
|
||||
|
||||
//using Newtonsoft.Json;
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Devices;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class CommFactory
|
||||
// {
|
||||
// public static IBasicCommunication CreateCommForDevice(JToken devToken)
|
||||
// {
|
||||
// var devKey = devToken.Value<string>("key");
|
||||
// IBasicCommunication comm = null;
|
||||
// try
|
||||
// {
|
||||
// var control = devToken["properties"]["control"];
|
||||
// var commMethod = control["method"].Value<string>();
|
||||
// if (commMethod == "com")
|
||||
// {
|
||||
// var comConfig = JsonConvert.DeserializeObject<ComPortConfig>(
|
||||
// control["comParams"].ToString(),
|
||||
// new JsonSerializerSettings
|
||||
// {
|
||||
// // Needs ObjectCreationHandling to make the ComSpec struct populate
|
||||
// ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||
// Converters = new JsonConverter[] { new ComSpecJsonConverter() }
|
||||
// });
|
||||
// comm = new ComPortController(devKey + "-com", comConfig.GetComPort(), comConfig.ComSpec);
|
||||
// }
|
||||
// else if (commMethod == "tcpIp")
|
||||
// {
|
||||
// var tcpConfig = JsonConvert.DeserializeObject<TcpIpConfig>(control["tcpParams"].ToString());
|
||||
// comm = new GenericTcpIpClient(devKey + "-tcp", tcpConfig.Address, tcpConfig.Port, tcpConfig.BufferSize);
|
||||
// }
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Debug.Console(0, "Cannot create communication from JSON:\r{0}\r\rException:\r{1}", devToken.ToString(), e);
|
||||
// }
|
||||
|
||||
// // put it in the device manager if it's the right flavor
|
||||
// var comDev = comm as Device;
|
||||
// if (comDev != null)
|
||||
// DeviceManager.AddDevice(comDev);
|
||||
|
||||
// return comm;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//using System;
|
||||
//using Crestron.SimplSharpPro;
|
||||
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Core.Devices;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class DeviceManagerFactory
|
||||
// {
|
||||
// public static Device Create(JToken devToken)
|
||||
// {
|
||||
// Device dev = null;
|
||||
// try
|
||||
// {
|
||||
// var devType = devToken.Value<string>("type");
|
||||
// var devKey = devToken.Value<string>("key");
|
||||
// var devName = devToken.Value<string>("name");
|
||||
// if (devType.Equals("DeviceMonitor", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
// var comm = CommFactory.CreateCommForDevice(devToken);
|
||||
// if (comm == null) return null;
|
||||
// dev = new GenericCommunicationMonitoredDevice(devKey, devName, comm, devToken["properties"]["pollString"].Value<string>());
|
||||
// }
|
||||
// else
|
||||
// FactoryHelper.HandleUnknownType(devToken, devType);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
// }
|
||||
// return dev;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
|
||||
//using Newtonsoft.Json;
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Devices;
|
||||
//using PepperDash.Essentials.Displays;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class DisplayFactory
|
||||
// {
|
||||
// public static DisplayBase CreateDisplay(JToken devToken)
|
||||
// {
|
||||
// DisplayBase dev = null;
|
||||
// try
|
||||
// {
|
||||
// var devType = devToken.Value<string>("type");
|
||||
// var devKey = devToken.Value<string>("key");
|
||||
// var devName = devToken.Value<string>("name");
|
||||
// var properties = devToken["properties"];
|
||||
|
||||
// if (devType.Equals("MockDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
// dev = new MockDisplay(devKey, devName);
|
||||
|
||||
// else if (devType.Equals("NecMPSX", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
// var comm = CommFactory.CreateCommForDevice(devToken);
|
||||
// if (comm == null) return null;
|
||||
// dev = new NecPSXMDisplayCom(devKey, devName, comm);
|
||||
|
||||
|
||||
|
||||
// //var commMethod = properties["control"]["method"].Value<string>();
|
||||
|
||||
// //// Helper-ize this?
|
||||
// //if(commMethod == "com")
|
||||
// //{
|
||||
// // // Move some of this up above???
|
||||
// // var comConfig = JsonConvert.DeserializeObject<ComPortConfig>(
|
||||
// // properties["control"]["comParams"].ToString(),
|
||||
// // new JsonSerializerSettings {
|
||||
// // // Needs ObjectCreationHandling to make the ComSpec struct populate
|
||||
// // ObjectCreationHandling = ObjectCreationHandling.Replace,
|
||||
// // Converters = new JsonConverter[] { new ComSpecJsonConverter() }
|
||||
// // });
|
||||
// // dev = new NecPSXMDisplayCom(devKey, devName, comConfig.GetComPort(), comConfig.ComSpec);
|
||||
// //}
|
||||
// //else if (commMethod == "tcpIp")
|
||||
// //{
|
||||
// // var spec = properties["control"]["tcpSpec"];
|
||||
// // var host = spec["address"].Value<string>();
|
||||
// // var port = spec["port"].Value<int>();
|
||||
// // dev = new NecPSXMDisplayCom(devKey, devName, host, port);
|
||||
// //}
|
||||
|
||||
|
||||
|
||||
// }
|
||||
|
||||
// else if (devType.Equals("NecNpPa550", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
// var proj = new NecPaSeriesProjector(devKey, devName);
|
||||
// var comm = CreateCommunicationFromPropertiesToken(
|
||||
// devKey + "-comm", properties, 3000);
|
||||
// proj.CommunicationMethod = comm;
|
||||
// dev = proj;
|
||||
// }
|
||||
// else
|
||||
// FactoryHelper.HandleUnknownType(devToken, devType);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
// }
|
||||
// return dev;
|
||||
// }
|
||||
|
||||
// public static IBasicCommunication CreateCommunicationFromPropertiesToken(
|
||||
// string commKey, JToken properties, int bufferSize)
|
||||
// {
|
||||
// Debug.Console(2, "Building port from: {0}", properties.ToString());
|
||||
|
||||
// var tcpToken = properties["TcpIp"];
|
||||
// if (tcpToken != null)
|
||||
// {
|
||||
// // Convert the Tcp property
|
||||
// var spec = JsonConvert.DeserializeObject<TcpIpConfig>(tcpToken.ToString());
|
||||
|
||||
// var tcp = new GenericTcpIpClient(commKey, spec.Address, spec.Port, bufferSize);
|
||||
// DeviceManager.AddDevice(tcp);
|
||||
// return tcp;
|
||||
// }
|
||||
|
||||
// var com = properties["Com"];
|
||||
// if (com != null)
|
||||
// {
|
||||
// // Make the interim config object
|
||||
// var comConfig = JsonConvert.DeserializeObject<ComPortConfig>(com.ToString(),
|
||||
// new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace });
|
||||
|
||||
// // Get the IComPorts hardware device from the Device or Control System
|
||||
// var comDev = comConfig.GetIComPortsDeviceFromManagedDevice();
|
||||
// if (comDev != null)
|
||||
// {
|
||||
// var controller = new ComPortController(commKey, comDev.ComPorts[comConfig.ComPortNumber], comConfig.ComSpec);
|
||||
// DeviceManager.AddDevice(controller);
|
||||
// return controller;
|
||||
// }
|
||||
// }
|
||||
// Debug.Console(0, "No Tcp or Com port information for port {0}", commKey);
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DM;
|
||||
using Crestron.SimplSharpPro.DM.Endpoints.Receivers;
|
||||
using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
|
||||
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices;
|
||||
//using PepperDash.Essentials.Devices.Dm;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class DmFactory
|
||||
{
|
||||
public static Device Create(JToken devToken)
|
||||
{
|
||||
Device dev = null;
|
||||
try
|
||||
{
|
||||
var devType = devToken.Value<string>("type");
|
||||
var devKey = devToken.Value<string>("key");
|
||||
var devName = devToken.Value<string>("name");
|
||||
// Catch all 200 series TX
|
||||
var devprops = devToken["properties"];
|
||||
var ipId = Convert.ToUInt32(devprops.Value<string>("ipId"), 16);
|
||||
var parent = devprops.Value<string>("parent");
|
||||
if (parent == null)
|
||||
parent = "controlSystem";
|
||||
|
||||
if (devType.StartsWith("DmTx2", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DmTx201C tx;
|
||||
if (parent.Equals("controlSystem", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
tx = new DmTx201C(ipId, Global.ControlSystem);
|
||||
//dev = new DmTx201SBasicController(devKey, devName, tx);
|
||||
}
|
||||
|
||||
}
|
||||
else if (devType.StartsWith("DmRmc", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
DmRmc100C rmc;
|
||||
if (parent.Equals("controlSystem", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
rmc = new DmRmc100C(ipId, Global.ControlSystem);
|
||||
//dev = new DmRmcBaseController(devKey, devName, rmc);
|
||||
}
|
||||
}
|
||||
else
|
||||
FactoryHelper.HandleUnknownType(devToken, devType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
public static Device CreateChassis(JToken devToken)
|
||||
{
|
||||
Device dev = null;
|
||||
try
|
||||
{
|
||||
var devType = devToken.Value<string>("type");
|
||||
var devKey = devToken.Value<string>("key");
|
||||
var devName = devToken.Value<string>("name");
|
||||
// Catch all 200 series TX
|
||||
var devprops = devToken["properties"];
|
||||
var ipId = Convert.ToUInt32(devprops.Value<string>("ipId"), 16);
|
||||
var parent = devprops.Value<string>("parent");
|
||||
if (parent == null)
|
||||
parent = "controlSystem";
|
||||
|
||||
if (devType.Equals("dmmd8x8", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var dm = new DmMd8x8(ipId, Global.ControlSystem);
|
||||
//dev = new DmChassisController(devKey, devName, dm);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public static class FactoryHelper
|
||||
{
|
||||
public static string IrDriverPathPrefix = Global.FilePathPrefix + "IR" + Global.DirectorySeparator;
|
||||
|
||||
public static void HandleUnknownType(JToken devToken, string type)
|
||||
{
|
||||
Debug.Console(0, "[Config] ERROR: Type '{0}' not found in group '{1}'", type,
|
||||
devToken.Value<string>("group"));
|
||||
}
|
||||
|
||||
public static void HandleDeviceCreationError(JToken devToken, Exception e)
|
||||
{
|
||||
Debug.Console(0, "[Config] ERROR creating device [{0}]: \r{1}",
|
||||
devToken["key"].Value<string>(), e);
|
||||
Debug.Console(0, "Relevant config:\r{0}", devToken.ToString(Newtonsoft.Json.Formatting.Indented));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds either the ControlSystem or a device controller that contains IR ports and
|
||||
/// returns a port from the hardware device
|
||||
/// </summary>
|
||||
/// <param name="propsToken"></param>
|
||||
/// <returns>Crestron IrPort or null if device doesn't have IR or is not found</returns>
|
||||
public static IrOutPortConfig GetIrPort(JToken propsToken)
|
||||
{
|
||||
var irSpec = propsToken["control"]["irSpec"];
|
||||
var portDevKey = irSpec.Value<string>("portDeviceKey");
|
||||
var portNum = irSpec.Value<uint>("portNumber");
|
||||
IIROutputPorts irDev = null;
|
||||
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|
||||
|| portDevKey.Equals("processor", StringComparison.OrdinalIgnoreCase))
|
||||
irDev = Global.ControlSystem;
|
||||
else
|
||||
irDev = DeviceManager.GetDeviceForKey(portDevKey) as IIROutputPorts;
|
||||
|
||||
if (irDev == null)
|
||||
{
|
||||
Debug.Console(0, "[Config] Error, device with IR ports '{0}' not found", portDevKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (portNum <= irDev.NumberOfIROutputPorts) // success!
|
||||
{
|
||||
var file = IrDriverPathPrefix + irSpec["file"].Value<string>();
|
||||
return new IrOutPortConfig { Port = irDev.IROutputPorts[portNum], FileName = file };
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, "[Config] Error, device '{0}' IR port {1} out of range",
|
||||
portDevKey, portNum);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Finds either the ControlSystem or a device controller that contains com ports and
|
||||
/// returns a port from the hardware device
|
||||
/// </summary>
|
||||
/// <param name="propsToken">The Properties token from the device's config</param>
|
||||
/// <returns>Crestron ComPort or null if device doesn't have IR or is not found</returns>
|
||||
public static ComPort GetComPort(JToken propsToken)
|
||||
{
|
||||
var portDevKey = propsToken.Value<string>("comPortDevice");
|
||||
var portNum = propsToken.Value<uint>("comPortNumber");
|
||||
IComPorts comDev = null;
|
||||
if (portDevKey.Equals("controlSystem", StringComparison.OrdinalIgnoreCase))
|
||||
comDev = Global.ControlSystem;
|
||||
else
|
||||
comDev = DeviceManager.GetDeviceForKey(portDevKey) as IComPorts;
|
||||
|
||||
if (comDev == null)
|
||||
{
|
||||
Debug.Console(0, "[Config] Error, device with com ports '{0}' not found", portDevKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (portNum <= comDev.NumberOfComPorts) // success!
|
||||
return comDev.ComPorts[portNum];
|
||||
else
|
||||
{
|
||||
Debug.Console(0, "[Config] Error, device '{0}' com port {1} out of range",
|
||||
portDevKey, portNum);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the key if it exists or converts the name into a key
|
||||
/// </summary>
|
||||
public static string KeyOrConvertName(string key, string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(key))
|
||||
return name.Replace(' ', '-');
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper to help in IR port creation
|
||||
/// </summary>
|
||||
public class IrOutPortConfig
|
||||
{
|
||||
public IROutputPort Port { get; set; }
|
||||
public string FileName { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
//using System;
|
||||
//using Crestron.SimplSharpPro;
|
||||
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Devices;
|
||||
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class SetTopBoxFactory
|
||||
// {
|
||||
// public static Device Create(JToken devToken)
|
||||
// {
|
||||
// Device dev = null;
|
||||
// try
|
||||
// {
|
||||
// var devType = devToken.Value<string>("type");
|
||||
// var devKey = devToken.Value<string>("key");
|
||||
// var devName = devToken.Value<string>("name");
|
||||
// var props = devToken["properties"];
|
||||
// var portConfig = FactoryHelper.GetIrPort(props);
|
||||
// if (portConfig != null)
|
||||
// {
|
||||
// if (devType.EndsWith("-generic"))
|
||||
// {
|
||||
// var stb = new IrSetTopBoxBase(devKey, devName, portConfig.Port, portConfig.FileName);
|
||||
// // Do this a better way?
|
||||
// stb.HasDpad = props["hasDpad"].Value<bool>();
|
||||
// stb.HasDvr = props["hasDvr"].Value<bool>();
|
||||
// stb.HasNumbers = props["hasNumbers"].Value<bool>();
|
||||
// stb.HasPreset = props["hasPresets"].Value<bool>();
|
||||
// dev = stb;
|
||||
// }
|
||||
// else
|
||||
// FactoryHelper.HandleUnknownType(devToken, devType);
|
||||
|
||||
// var preDev = dev as IHasSetTopBoxProperties;
|
||||
// if(preDev.HasPreset)
|
||||
// preDev.LoadPresets(props["presetListName"].Value<string>());
|
||||
// }
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
// }
|
||||
// return dev;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
//using System;
|
||||
//using Crestron.SimplSharpPro;
|
||||
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Devices;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class PcFactory
|
||||
// {
|
||||
// public static Device Create(JToken devToken)
|
||||
// {
|
||||
// Device dev = null;
|
||||
// //try
|
||||
// //{
|
||||
// // var devType = devToken.Value<string>("type");
|
||||
// // var devKey = devToken.Value<string>("key");
|
||||
// // var devName = devToken.Value<string>("name");
|
||||
// // if (devType.Equals("laptop", StringComparison.OrdinalIgnoreCase))
|
||||
// // dev = new Laptop(devKey, devName);
|
||||
// // else
|
||||
// // FactoryHelper.HandleUnknownType(devToken, devType);
|
||||
// //}
|
||||
// //catch (Exception e)
|
||||
// //{
|
||||
// // FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
// //}
|
||||
// return dev;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
//using System;
|
||||
//using Crestron.SimplSharpPro;
|
||||
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Devices;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class DiscPlayerFactory
|
||||
// {
|
||||
// public static Device Create(JToken devToken)
|
||||
// {
|
||||
// Device dev = null;
|
||||
// try
|
||||
// {
|
||||
// var devType = devToken.Value<string>("type");
|
||||
// var devKey = devToken.Value<string>("key");
|
||||
// var devName = devToken.Value<string>("name");
|
||||
|
||||
// // Filter out special (Pioneer
|
||||
// //(devType.Equals("genericIr", StringComparison.OrdinalIgnoreCase))
|
||||
|
||||
// var props = devToken["properties"];
|
||||
// var portConfig = FactoryHelper.GetIrPort(props);
|
||||
// if (portConfig != null)
|
||||
// {
|
||||
// if (devType.EndsWith("-generic"))
|
||||
// dev = new IrDvdBase(devKey, devName, portConfig.Port, portConfig.FileName);
|
||||
// else
|
||||
// FactoryHelper.HandleUnknownType(devToken, devType);
|
||||
// }
|
||||
|
||||
// // NO PORT ERROR HERE??
|
||||
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
// }
|
||||
// return dev;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.Remotes;
|
||||
//using Crestron.SimplSharpPro.UI;
|
||||
//using Newtonsoft.Json;
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Devices;
|
||||
////using PepperDash.Essentials.Remotes;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// //public class RemoteFactory
|
||||
// //{
|
||||
// // public static Device Create(JToken devToken)
|
||||
// // {
|
||||
// // Hr150Controller dev = null;
|
||||
// // try
|
||||
// // {
|
||||
// // var devType = devToken.Value<string>("type");
|
||||
// // var devKey = devToken.Value<string>("key");
|
||||
// // var devName = devToken.Value<string>("name");
|
||||
// // var props = devToken["properties"];
|
||||
|
||||
// // if (devType.Equals("hr150", StringComparison.OrdinalIgnoreCase))
|
||||
// // {
|
||||
// // uint id = Convert.ToUInt32(props.Value<string>("rfId"), 16);
|
||||
// // var parent = props.Value<string>("rfGateway");
|
||||
// // RFExGateway rf = GetGateway(parent);
|
||||
|
||||
// // var hw = new Hr150(id, rf);
|
||||
// // dev = new Hr150Controller(devKey, devName, hw);
|
||||
|
||||
// // // Have to add the buttons and default source after all devices are spun up
|
||||
// // dev.AddPostActivationAction(() =>
|
||||
// // {
|
||||
// // var defaultSystemKey = props.Value<string>("defaultSystemKey");
|
||||
// // dev.SetCurrentRoom((EssentialsRoom)DeviceManager.GetDeviceForKey(defaultSystemKey));
|
||||
|
||||
// // // Link custom buttons
|
||||
// // var buttonProps = JsonConvert.DeserializeObject<Dictionary<uint, string>>(props["buttons"].ToString());
|
||||
// // foreach (var kvp in buttonProps)
|
||||
// // {
|
||||
// // var split = kvp.Value.Split(':');
|
||||
// // if (split[0].Equals("source"))
|
||||
// // {
|
||||
// // var src = DeviceManager.GetDeviceForKey(split[1]) as IPresentationSource;
|
||||
// // if (src == null)
|
||||
// // {
|
||||
// // Debug.Console(0, dev, "Error: Cannot add source key '{0}'", split[1]);
|
||||
// // continue;
|
||||
// // }
|
||||
// // dev.SetCustomButtonAsSource(kvp.Key, src);
|
||||
// // }
|
||||
// // else if (split[0] == "room")
|
||||
// // {
|
||||
// // if (split[1] == "off")
|
||||
// // dev.SetCustomButtonAsRoomOff(kvp.Key);
|
||||
// // }
|
||||
// // }
|
||||
// // });
|
||||
// // }
|
||||
// // else if (devType.Equals("tsr302", StringComparison.OrdinalIgnoreCase))
|
||||
// // {
|
||||
// // uint id = Convert.ToUInt32(props.Value<string>("rfId"), 16);
|
||||
// // var parent = props.Value<string>("rfGateway");
|
||||
// // RFExGateway rf = GetGateway(parent);
|
||||
// // var sgd = props.Value<string>("sgdPath");
|
||||
|
||||
// // var hw = new Tsr302(id, rf);
|
||||
|
||||
// // //dev = new Hr150Controller(devKey, devName, hw);
|
||||
|
||||
// // //// Have to add the buttons and default source after all devices are spun up
|
||||
// // //dev.AddPostActivationAction(() =>
|
||||
// // //{
|
||||
// // // var defaultSystemKey = props.Value<string>("defaultSystemKey");
|
||||
// // // dev.SetCurrentRoom((EssentialsRoom)DeviceManager.GetDeviceForKey(defaultSystemKey));
|
||||
|
||||
// // // // Link custom buttons
|
||||
// // // var buttonProps = JsonConvert.DeserializeObject<Dictionary<uint, string>>(props["buttons"].ToString());
|
||||
// // // foreach (var kvp in buttonProps)
|
||||
// // // {
|
||||
// // // var split = kvp.Value.Split(':');
|
||||
// // // if (split[0].Equals("source"))
|
||||
// // // {
|
||||
// // // var src = DeviceManager.GetDeviceForKey(split[1]) as IPresentationSource;
|
||||
// // // if (src == null)
|
||||
// // // {
|
||||
// // // Debug.Console(0, dev, "Error: Cannot add source key '{0}'", split[1]);
|
||||
// // // continue;
|
||||
// // // }
|
||||
// // // dev.SetCustomButtonAsSource(kvp.Key, src);
|
||||
// // // }
|
||||
// // // else if (split[0] == "room")
|
||||
// // // {
|
||||
// // // if (split[1] == "off")
|
||||
// // // dev.SetCustomButtonAsRoomOff(kvp.Key);
|
||||
// // // }
|
||||
// // // }
|
||||
// // //});
|
||||
// // }
|
||||
// // }
|
||||
// // catch (Exception e)
|
||||
// // {
|
||||
// // FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
// // }
|
||||
// // return dev;
|
||||
// // }
|
||||
|
||||
// // public static RFExGateway GetGateway(string parent)
|
||||
// // {
|
||||
// // if (parent == null)
|
||||
// // parent = "controlSystem";
|
||||
// // RFExGateway rf = null;
|
||||
// // if (parent.Equals("controlSystem", StringComparison.OrdinalIgnoreCase)
|
||||
// // || parent.Equals("processor", StringComparison.OrdinalIgnoreCase))
|
||||
// // {
|
||||
// // rf = Global.ControlSystem.ControllerRFGatewayDevice;
|
||||
// // }
|
||||
// // return rf;
|
||||
// // }
|
||||
// //}
|
||||
//}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
//using System;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.UI;
|
||||
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Devices;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class TouchpanelFactory
|
||||
// {
|
||||
// public static Device Create(JToken devToken)
|
||||
// {
|
||||
// SmartGraphicsTouchpanelControllerBase dev = null;
|
||||
// try
|
||||
// {
|
||||
// var devType = devToken.Value<string>("type");
|
||||
// var devKey = devToken.Value<string>("key");
|
||||
// var devName = devToken.Value<string>("name");
|
||||
// var props = devToken["properties"];
|
||||
// if (devType.Equals("Tsw1052", StringComparison.OrdinalIgnoreCase))
|
||||
// {
|
||||
// uint ipId = Convert.ToUInt32(props.Value<string>("ipId"), 16);
|
||||
// var hw = new Tsw1052(ipId, Global.ControlSystem);
|
||||
// dev = TouchpanelControllerFactory.Create(devKey, devName, hw, props.Value<string>("sgdPath"));
|
||||
// dev.UsesSplashPage = props.Value<bool>("usesSplashPage");
|
||||
// dev.ShowDate = props.Value<bool>("showDate");
|
||||
// dev.ShowTime = props.Value<bool>("showTime");
|
||||
|
||||
// // This plugs the system key into the tp, but it won't be linked up until later
|
||||
// dev.AddPostActivationAction(() =>
|
||||
// {
|
||||
// var defaultSystemKey = props.Value<string>("defaultSystemKey");
|
||||
// dev.SetCurrentRoom((EssentialsRoom)DeviceManager.GetDeviceForKey(defaultSystemKey));
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// FactoryHelper.HandleDeviceCreationError(devToken, e);
|
||||
// }
|
||||
// return dev;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
359
PepperDashEssentials/ControlSystem.cs
Normal file
359
PepperDashEssentials/ControlSystem.cs
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common;
|
||||
using PepperDash.Essentials.DM;
|
||||
using PepperDash.Essentials.Fusion;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class ControlSystem : CrestronControlSystem
|
||||
{
|
||||
HttpLogoServer LogoServer;
|
||||
|
||||
public ControlSystem()
|
||||
: base()
|
||||
{
|
||||
Thread.MaxNumberOfUserThreads = 400;
|
||||
Global.ControlSystem = this;
|
||||
DeviceManager.Initialize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Git 'er goin'
|
||||
/// </summary>
|
||||
public override void InitializeSystem()
|
||||
{
|
||||
DeterminePlatform();
|
||||
|
||||
//CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads 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);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse
|
||||
("Current running configuration. This is the merged system and template configuration");
|
||||
CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject
|
||||
(ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented));
|
||||
}, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r" +
|
||||
"System URL: {0}\r" +
|
||||
"Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl);
|
||||
}, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
GoWithLoad();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the program is running on a processor (appliance) or server (XiO Edge).
|
||||
///
|
||||
/// Sets Global.FilePathPrefix based on platform
|
||||
/// </summary>
|
||||
public void DeterminePlatform()
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Determining Platform....");
|
||||
|
||||
string filePathPrefix;
|
||||
|
||||
var dirSeparator = Global.DirectorySeparator;
|
||||
|
||||
var version = Crestron.SimplSharp.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
var versionString = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
|
||||
string directoryPrefix;
|
||||
|
||||
//directoryPrefix = Crestron.SimplSharp.CrestronIO.Directory.GetApplicationRootDirectory();
|
||||
#warning ^ For use with beta Include4.dat for XiO Edge
|
||||
directoryPrefix = "";
|
||||
|
||||
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server)
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "NVRAM"
|
||||
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on 3-series Appliance", versionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on XiO Edge Server", versionString);
|
||||
}
|
||||
|
||||
Global.SetFilePathPrefix(filePathPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do it, yo
|
||||
/// </summary>
|
||||
public void GoWithLoad()
|
||||
{
|
||||
try
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand(EnablePortalSync, "portalsync", "Loads Portal Sync",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
//PortalSync = new PepperDashPortalSyncClient();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials load from configuration");
|
||||
|
||||
var filesReady = SetupFilesystem();
|
||||
if (filesReady)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Folder structure verified. Loading config...");
|
||||
if (!ConfigReader.LoadConfig2())
|
||||
return;
|
||||
|
||||
Load();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies filesystem is set up. IR, SGD, and program1 folders
|
||||
/// </summary>
|
||||
bool SetupFilesystem()
|
||||
{
|
||||
Debug.Console(0, "Verifying and/or creating folder structure");
|
||||
var configDir = Global.FilePathPrefix;
|
||||
var configExists = Directory.Exists(configDir);
|
||||
if (!configExists)
|
||||
Directory.Create(configDir);
|
||||
|
||||
var irDir = Global.FilePathPrefix + "ir";
|
||||
if (!Directory.Exists(irDir))
|
||||
Directory.Create(irDir);
|
||||
|
||||
var sgdDir = Global.FilePathPrefix + "sgd";
|
||||
if (!Directory.Exists(sgdDir))
|
||||
Directory.Create(sgdDir);
|
||||
|
||||
return configExists;
|
||||
}
|
||||
|
||||
public void EnablePortalSync(string s)
|
||||
{
|
||||
if (s.ToLower() == "enable")
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Portal Sync features enabled");
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void Load()
|
||||
{
|
||||
LoadDevices();
|
||||
LoadTieLines();
|
||||
LoadRooms();
|
||||
LoadLogoServer();
|
||||
|
||||
DeviceManager.ActivateAll();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads all devices from config and adds them to DeviceManager
|
||||
/// </summary>
|
||||
public void LoadDevices()
|
||||
{
|
||||
foreach (var devConf in ConfigReader.ConfigObject.Devices)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "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, Debug.ErrorLogLevel.Notice, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Creating device {0}. Skipping device. \r{1}", devConf.Key, e);
|
||||
}
|
||||
}
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Devices Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to load tie lines. This should run after devices have loaded
|
||||
/// </summary>
|
||||
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();
|
||||
if (ConfigReader.ConfigObject.TieLines == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines)
|
||||
{
|
||||
var newTL = tieLineConfig.GetTieLine();
|
||||
if (newTL != null)
|
||||
tlc.Add(newTL);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Tie Lines Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all rooms from config and adds them to DeviceManager
|
||||
/// </summary>
|
||||
public void LoadRooms()
|
||||
{
|
||||
if (ConfigReader.ConfigObject.Rooms == null)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Warning, "WARNING: Configuration contains no rooms");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
||||
{
|
||||
var room = roomConfig.GetRoomObject();
|
||||
if (room != null)
|
||||
{
|
||||
if (room is EssentialsHuddleSpaceRoom)
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemControllerBase((EssentialsHuddleSpaceRoom)room, 0xf1));
|
||||
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge...");
|
||||
// Cotija bridge
|
||||
var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom);
|
||||
AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
|
||||
DeviceManager.AddDevice(bridge);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Cotija Bridge Added...");
|
||||
}
|
||||
else if (room is EssentialsHuddleVtc1Room)
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsHuddleSpaceRoom, attempting to add to DeviceManager w/o Fusion");
|
||||
DeviceManager.AddDevice(room);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helps add the post activation steps that link bridges to main controller
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
void AddBridgePostActivationHelper(CotijaBridgeBase bridge)
|
||||
{
|
||||
bridge.AddPostActivationAction(() =>
|
||||
{
|
||||
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
||||
}
|
||||
Debug.Console(0, bridge, "Linking to parent controller");
|
||||
bridge.AddParent(parent);
|
||||
parent.AddBridge(bridge);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires up a logo server if not already running
|
||||
/// </summary>
|
||||
void LoadLogoServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogoServer = new HttpLogoServer(8080, Global.FilePathPrefix + "html" + Global.DirectorySeparator + "logo");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "NOTICE: Logo server cannot be started. Likely already running in another program");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
367
PepperDashEssentials/ControlSystem.cs.orig
Normal file
367
PepperDashEssentials/ControlSystem.cs.orig
Normal file
|
|
@ -0,0 +1,367 @@
|
|||
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;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class ControlSystem : CrestronControlSystem
|
||||
{
|
||||
PepperDashPortalSyncClient PortalSync;
|
||||
HttpLogoServer LogoServer;
|
||||
|
||||
public ControlSystem()
|
||||
: base()
|
||||
{
|
||||
Thread.MaxNumberOfUserThreads = 400;
|
||||
Global.ControlSystem = this;
|
||||
DeviceManager.Initialize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Git 'er goin'
|
||||
/// </summary>
|
||||
public override void InitializeSystem()
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
DeterminePlatform();
|
||||
|
||||
//CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
|
||||
// ConsoleAccessLevelEnum.AccessOperator);
|
||||
=======
|
||||
CrestronConsole.AddNewConsoleCommand(s => GoWithLoad(), "go", "Loads configuration file",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
>>>>>>> 600b9f11ff1bbc186f7c2a2945955731b3523b3c
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
foreach (var tl in TieLineCollection.Default)
|
||||
CrestronConsole.ConsoleCommandResponse(" {0}\r", tl);
|
||||
},
|
||||
"listtielines", "Prints out all tie lines", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse
|
||||
("Current running configuration. This is the merged system and template configuration");
|
||||
CrestronConsole.ConsoleCommandResponse(Newtonsoft.Json.JsonConvert.SerializeObject
|
||||
(ConfigReader.ConfigObject, Newtonsoft.Json.Formatting.Indented));
|
||||
}, "showconfig", "Shows the current running merged config", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("This system can be found at the following URLs:\r" +
|
||||
"System URL: {0}\r" +
|
||||
"Template URL: {1}", ConfigReader.ConfigObject.SystemUrl, ConfigReader.ConfigObject.TemplateUrl);
|
||||
}, "portalinfo", "Shows portal URLS from configuration", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
//GoWithLoad();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the program is running on a processor (appliance) or server (XiO Edge).
|
||||
///
|
||||
/// Sets Global.FilePathPrefix based on platform
|
||||
/// </summary>
|
||||
public void DeterminePlatform()
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Determining Platform....");
|
||||
|
||||
string filePathPrefix;
|
||||
|
||||
var dirSeparator = Global.DirectorySeparator;
|
||||
|
||||
var version = Crestron.SimplSharp.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
|
||||
|
||||
var versionString = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
|
||||
string directoryPrefix;
|
||||
|
||||
//directoryPrefix = Crestron.SimplSharp.CrestronIO.Directory.GetApplicationRootDirectory();
|
||||
#warning ^ For use with beta Include4.dat for XiO Edge
|
||||
directoryPrefix = "";
|
||||
|
||||
if (CrestronEnvironment.DevicePlatform != eDevicePlatform.Server)
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "NVRAM"
|
||||
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber) + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on 3-series Appliance", versionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
filePathPrefix = directoryPrefix + dirSeparator + "User" + dirSeparator;
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on XiO Edge Server", versionString);
|
||||
}
|
||||
|
||||
Global.SetFilePathPrefix(filePathPrefix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do it, yo
|
||||
/// </summary>
|
||||
public void GoWithLoad()
|
||||
{
|
||||
try
|
||||
{
|
||||
CrestronConsole.AddNewConsoleCommand(EnablePortalSync, "portalsync", "Loads Portal Sync",
|
||||
ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
//PortalSync = new PepperDashPortalSyncClient();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials load from configuration");
|
||||
|
||||
var filesReady = SetupFilesystem();
|
||||
if (filesReady)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Folder structure verified. Loading config...");
|
||||
if (!ConfigReader.LoadConfig2())
|
||||
return;
|
||||
|
||||
Load();
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies filesystem is set up. IR, SGD, and program1 folders
|
||||
/// </summary>
|
||||
bool SetupFilesystem()
|
||||
{
|
||||
Debug.Console(0, "Verifying and/or creating folder structure");
|
||||
var configDir = Global.FilePathPrefix;
|
||||
var configExists = Directory.Exists(configDir);
|
||||
if (!configExists)
|
||||
Directory.Create(configDir);
|
||||
|
||||
var irDir = Global.FilePathPrefix + "ir";
|
||||
if (!Directory.Exists(irDir))
|
||||
Directory.Create(irDir);
|
||||
|
||||
var sgdDir = Global.FilePathPrefix + "sgd";
|
||||
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");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void Load()
|
||||
{
|
||||
LoadDevices();
|
||||
LoadTieLines();
|
||||
LoadRooms();
|
||||
LoadLogoServer();
|
||||
|
||||
DeviceManager.ActivateAll();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads all devices from config and adds them to DeviceManager
|
||||
/// </summary>
|
||||
public void LoadDevices()
|
||||
{
|
||||
foreach (var devConf in ConfigReader.ConfigObject.Devices)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "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, Debug.ErrorLogLevel.Notice, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "ERROR: Creating device {0}. Skipping device. \r{1}", devConf.Key, e);
|
||||
}
|
||||
}
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Devices Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to load tie lines. This should run after devices have loaded
|
||||
/// </summary>
|
||||
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();
|
||||
if (ConfigReader.ConfigObject.TieLines == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var tieLineConfig in ConfigReader.ConfigObject.TieLines)
|
||||
{
|
||||
var newTL = tieLineConfig.GetTieLine();
|
||||
if (newTL != null)
|
||||
tlc.Add(newTL);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Tie Lines Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads all rooms from config and adds them to DeviceManager
|
||||
/// </summary>
|
||||
public void LoadRooms()
|
||||
{
|
||||
if (ConfigReader.ConfigObject.Rooms == null)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Warning, "WARNING: Configuration contains no rooms");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var roomConfig in ConfigReader.ConfigObject.Rooms)
|
||||
{
|
||||
var room = roomConfig.GetRoomObject();
|
||||
if (room != null)
|
||||
{
|
||||
if (room is EssentialsHuddleSpaceRoom)
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleSpaceRoom, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleSpaceFusionSystemControllerBase((EssentialsHuddleSpaceRoom)room, 0xf1));
|
||||
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Attempting to build Cotija Bridge...");
|
||||
// Cotija bridge
|
||||
var bridge = new CotijaEssentialsHuddleSpaceRoomBridge(room as EssentialsHuddleSpaceRoom);
|
||||
AddBridgePostActivationHelper(bridge); // Lets things happen later when all devices are present
|
||||
DeviceManager.AddDevice(bridge);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Cotija Bridge Added...");
|
||||
}
|
||||
else if (room is EssentialsHuddleVtc1Room)
|
||||
{
|
||||
DeviceManager.AddDevice(room);
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is EssentialsHuddleVtc1Room, attempting to add to DeviceManager with Fusion");
|
||||
DeviceManager.AddDevice(new EssentialsHuddleVtc1FusionController((EssentialsHuddleVtc1Room)room, 0xf1));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Room is NOT EssentialsHuddleSpaceRoom, attempting to add to DeviceManager w/o Fusion");
|
||||
DeviceManager.AddDevice(room);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create room from config, key '{0}'", roomConfig.Key);
|
||||
}
|
||||
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Rooms Loaded.");
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helps add the post activation steps that link bridges to main controller
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
void AddBridgePostActivationHelper(CotijaBridgeBase bridge)
|
||||
{
|
||||
bridge.AddPostActivationAction(() =>
|
||||
{
|
||||
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
||||
}
|
||||
Debug.Console(0, bridge, "Linking to parent controller");
|
||||
bridge.AddParent(parent);
|
||||
parent.AddBridge(bridge);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires up a logo server if not already running
|
||||
/// </summary>
|
||||
void LoadLogoServer()
|
||||
{
|
||||
try
|
||||
{
|
||||
LogoServer = new HttpLogoServer(8080, Global.FilePathPrefix + "html" + Global.DirectorySeparator + "logo");
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Debug.Console(0, Debug.ErrorLogLevel.Notice, "NOTICE: Logo server cannot be started. Likely already running in another program");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
PepperDashEssentials/Devices/Amplifier.cs
Normal file
31
PepperDashEssentials/Devices/Amplifier.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class Amplifier : Device, IRoutingSinkNoSwitching
|
||||
{
|
||||
public RoutingInputPort AudioIn { get; private set; }
|
||||
|
||||
public Amplifier(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
AudioIn = new RoutingInputPort(RoutingPortNames.AnyAudioIn, eRoutingSignalType.Audio,
|
||||
eRoutingPortConnectionType.None, null, this);
|
||||
InputPorts = new RoutingPortCollection<RoutingInputPort> { AudioIn };
|
||||
}
|
||||
|
||||
#region IRoutingInputs Members
|
||||
|
||||
public RoutingPortCollection<RoutingInputPort> InputPorts { get; private set; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
42
PepperDashEssentials/Devices/DiscPlayer/OppoExtendedBdp.cs
Normal file
42
PepperDashEssentials/Devices/DiscPlayer/OppoExtendedBdp.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Devices
|
||||
{
|
||||
///// <summary>
|
||||
///// This DVD class should cover most IR, one-way DVD and Bluray fuctions
|
||||
///// </summary>
|
||||
//public class OppoBluray : IrDvdBase, IDvdControls, IExtendedOutputs
|
||||
//{
|
||||
// public OppoBluray(string key, string name, IROutputPort port, string irDriverFilepath) : base(key, name, port, irDriverFilepath) { }
|
||||
|
||||
|
||||
|
||||
// public OutputsToTriListBridge GetExtendedOutputsToTriListBridge()
|
||||
// {
|
||||
// return new ExtendedDvdTriListBridge();
|
||||
// }
|
||||
|
||||
|
||||
//}
|
||||
|
||||
//public class ExtendedDvdTriListBridge : OutputsToTriListBridge
|
||||
//{
|
||||
|
||||
// public override void Link()
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
|
||||
// public override void UnLink()
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//}
|
||||
}
|
||||
45
PepperDashEssentials/Devices/NUMERIC AppleTV.cs
Normal file
45
PepperDashEssentials/Devices/NUMERIC AppleTV.cs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
|
||||
//namespace PepperDash.Essentials.Devices
|
||||
//{
|
||||
// public class AppleTV : Device, IHasCueActionList
|
||||
// {
|
||||
// public IrOutputPortController IrPort { get; private set; }
|
||||
|
||||
// public AppleTV(string key, string name, IROutputPort port, string irDriverFilepath)
|
||||
// : base(key, name)
|
||||
// {
|
||||
// IrPort = new IrOutputPortController("ir" + key, port, irDriverFilepath);
|
||||
// }
|
||||
|
||||
// #region IFunctionList Members
|
||||
// public List<CueActionPair> CueActionList
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// var numToIr = new Dictionary<Cue, string>
|
||||
// {
|
||||
// { CommonBoolCue.Menu, IROutputStandardCommands.IROut_MENU },
|
||||
// { CommonBoolCue.Up, IROutputStandardCommands.IROut_UP_ARROW },
|
||||
// { CommonBoolCue.Down, IROutputStandardCommands.IROut_DN_ARROW },
|
||||
// { CommonBoolCue.Left, IROutputStandardCommands.IROut_LEFT_ARROW },
|
||||
// { CommonBoolCue.Right, IROutputStandardCommands.IROut_RIGHT_ARROW },
|
||||
// { CommonBoolCue.Select, IROutputStandardCommands.IROut_ENTER }
|
||||
// };
|
||||
// var funcs = new List<CueActionPair>(numToIr.Count);
|
||||
|
||||
// foreach (var kvp in numToIr)
|
||||
// funcs.Add(new BoolCueActionPair(kvp.Key, b => IrPort.PressRelease(kvp.Value, b)));
|
||||
// return funcs;
|
||||
// }
|
||||
// }
|
||||
// #endregion
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
//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;
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Core.Presets;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// public abstract class DevicePageControllerBase
|
||||
// {
|
||||
|
||||
// protected BasicTriListWithSmartObject TriList;
|
||||
// protected List<BoolInputSig> FixedObjectSigs;
|
||||
|
||||
// public DevicePageControllerBase(BasicTriListWithSmartObject triList)
|
||||
// {
|
||||
// TriList = triList;
|
||||
// }
|
||||
|
||||
// public void SetVisible(bool state)
|
||||
// {
|
||||
// foreach (var sig in FixedObjectSigs)
|
||||
// {
|
||||
// Debug.Console(2, "set visible {0}={1}", sig.Number, state);
|
||||
// sig.BoolValue = state;
|
||||
// }
|
||||
// CustomSetVisible(state);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Add any specialized show/hide logic here - beyond FixedObjectSigs. Overriding
|
||||
// /// methods do not need to call this base method
|
||||
// /// </summary>
|
||||
// protected virtual void CustomSetVisible(bool state)
|
||||
// {
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,308 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
//using Crestron.SimplSharpPro.UI;
|
||||
|
||||
//using PepperDash.Core;
|
||||
|
||||
|
||||
//namespace PepperDash.Essentials.Core
|
||||
//{
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// public class LargeTouchpanelControllerBase : SmartGraphicsTouchpanelControllerBase
|
||||
// {
|
||||
// public string PresentationShareButtonInVideoText = "Share";
|
||||
// public string PresentationShareButtonNotInVideoText = "Presentation";
|
||||
|
||||
// SourceListSubpageReferenceList SourceSelectSRL;
|
||||
// DevicePageControllerBase CurrentPresentationSourcePageController;
|
||||
|
||||
// public LargeTouchpanelControllerBase(string key, string name,
|
||||
// BasicTriListWithSmartObject triList, string sgdFilePath)
|
||||
// : base(key, name, triList, sgdFilePath)
|
||||
// {
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Static factory method
|
||||
// /// </summary>
|
||||
// public static LargeTouchpanelControllerBase GetController(string key, string name,
|
||||
// string type, CrestronTswPropertiesConfig props)
|
||||
// {
|
||||
// var id = Convert.ToUInt32(props.IpId, 16);
|
||||
// type = type.ToLower();
|
||||
// Tswx52ButtonVoiceControl tsw = null;
|
||||
// if (type == "tsw752")
|
||||
// tsw = new Tsw752(id, Global.ControlSystem);
|
||||
// else if (type == "tsw1052")
|
||||
// tsw = new Tsw1052(id, Global.ControlSystem);
|
||||
// else
|
||||
// {
|
||||
// Debug.Console(0, "WARNING: Cannot create TSW controller with type '{0}'", type);
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// var sgdPath = string.Format(@"\NVRAM\Program{0}\SGD\{1}",
|
||||
// InitialParametersClass.ApplicationNumber, props.SgdFile);
|
||||
// var controller = new LargeTouchpanelControllerBase(key, name, tsw, sgdPath);
|
||||
// controller.UsesSplashPage = props.UsesSplashPage;
|
||||
|
||||
// // Get the room and add it after everthing is ready
|
||||
// var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey) as EssentialsRoom;
|
||||
// controller.AddPostActivationAction(() =>
|
||||
// {
|
||||
// controller.SetCurrentRoom(room);
|
||||
|
||||
// });
|
||||
|
||||
// return controller;
|
||||
// }
|
||||
|
||||
// public override bool CustomActivate()
|
||||
// {
|
||||
// var baseSuccess = base.CustomActivate();
|
||||
// if (!baseSuccess) return false;
|
||||
|
||||
// SourceSelectSRL = new SourceListSubpageReferenceList(this.TriList, n =>
|
||||
// { if (CurrentRoom != null) CurrentRoom.SelectSource(n); });
|
||||
|
||||
// var lm = Global.LicenseManager;
|
||||
// if (lm != null)
|
||||
// {
|
||||
// lm.LicenseIsValid.LinkInputSig(TriList.BooleanInput[UiCue.ShowLicensed.Number]);
|
||||
// //others
|
||||
// }
|
||||
|
||||
// // Wire up buttons
|
||||
// TriList.SetSigFalseAction(15003, () => SetMainMode(eMainModeType.Presentation));
|
||||
// TriList.SetSigFalseAction(15008, PowerOffWithConfirmPressed);
|
||||
// TriList.SetSigFalseAction(15101, () => SetMainMode(eMainModeType.Presentation));
|
||||
// TriList.SetSigFalseAction(15013, ShowHelp);
|
||||
// TriList.SetSigFalseAction(15014, () => SetMainMode(eMainModeType.Tech));
|
||||
|
||||
// // Temp things -----------------------------------------------------------------------
|
||||
// TriList.StringInput[UiCue.SplashMessage.Number].StringValue = SplashMessage;
|
||||
// //------------------------------------------------------------------------------------
|
||||
|
||||
// // Initialize initial view
|
||||
// ShowSplashOrMain();
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// In Essentials, this should NEVER be called, since it's a one-room solution
|
||||
// /// </summary>
|
||||
// protected override void HideRoomUI()
|
||||
// {
|
||||
// // UI Cleanup here????
|
||||
|
||||
// //SwapAudioDeviceControls(CurrentRoom.CurrentAudioDevice, null);
|
||||
// //CurrentRoom.AudioDeviceWillChange -= CurrentRoom_AudioDeviceWillChange;
|
||||
|
||||
// CurrentRoom.IsCoolingDownFeedback.OutputChange -= CurrentRoom_IsCoolingDown_OutputChange;
|
||||
// CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingUp_OutputChange;
|
||||
|
||||
// SourceSelectSRL.DetachFromCurrentRoom();
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Ties this panel controller to the Room and gets updates.
|
||||
// /// </summary>
|
||||
// protected override void ShowRoomUI()
|
||||
// {
|
||||
// Debug.Console(1, this, "connecting to system '{0}'", CurrentRoom.Key);
|
||||
|
||||
// TriList.StringInput[RoomCue.Name.Number].StringValue = CurrentRoom.Name;
|
||||
// TriList.StringInput[RoomCue.Description.Number].StringValue = CurrentRoom.Description;
|
||||
|
||||
// CurrentRoom.IsCoolingDownFeedback.OutputChange -= CurrentRoom_IsCoolingDown_OutputChange;
|
||||
// CurrentRoom.IsWarmingUpFeedback.OutputChange -= CurrentRoom_IsWarmingUp_OutputChange;
|
||||
// CurrentRoom.IsCoolingDownFeedback.OutputChange += CurrentRoom_IsCoolingDown_OutputChange;
|
||||
// CurrentRoom.IsWarmingUpFeedback.OutputChange += CurrentRoom_IsWarmingUp_OutputChange;
|
||||
|
||||
// SourceSelectSRL.AttachToRoom(CurrentRoom);
|
||||
// }
|
||||
|
||||
// void CurrentRoom_IsCoolingDown_OutputChange(object sender, EventArgs e)
|
||||
// {
|
||||
// Debug.Console(2, this, "Received room in cooldown={0}", CurrentRoom.IsCoolingDownFeedback.BoolValue);
|
||||
// if (CurrentRoom.IsCoolingDownFeedback.BoolValue) // When entering cooldown
|
||||
// {
|
||||
// // Do we need to check for an already-running cooldown - like in the case of room switches?
|
||||
// new ModalDialog(TriList).PresentModalTimerDialog(0, "Power Off", "Power", "Please wait, shutting down",
|
||||
// "", "", CurrentRoom.CooldownTime, true, b =>
|
||||
// {
|
||||
// ShowSplashOrMain();
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// void CurrentRoom_IsWarmingUp_OutputChange(object sender, EventArgs e)
|
||||
// {
|
||||
// Debug.Console(2, this, "Received room in warmup={0}", CurrentRoom.IsWarmingUpFeedback.BoolValue);
|
||||
// if (CurrentRoom.IsWarmingUpFeedback.BoolValue) // When entering warmup
|
||||
// {
|
||||
// // Do we need to check for an already-running cooldown - like in the case of room switches?
|
||||
// new ModalDialog(TriList).PresentModalTimerDialog(0, "Power On", "Power", "Please wait, powering on",
|
||||
// "", "", CurrentRoom.WarmupTime, false, b =>
|
||||
// {
|
||||
// // Reveal sources - or has already been done behind modal
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Handler for source change events.
|
||||
// void CurrentRoom_PresentationSourceChange(object sender, EssentialsRoomSourceChangeEventArgs args)
|
||||
// {
|
||||
// // Put away the old source and set up the new source.
|
||||
// Debug.Console(2, this, "Received source change={0}", args.NewSource != null ? args.NewSource.SourceKey : "none");
|
||||
|
||||
// // If we're in tech, don't switch screen modes. Add any other modes we may want to switch away from
|
||||
// // inside the if below.
|
||||
// if (MainMode == eMainModeType.Splash)
|
||||
// SetMainMode(eMainModeType.Presentation);
|
||||
// SetControlSource(args.NewSource);
|
||||
// }
|
||||
|
||||
// //***********************************************************************
|
||||
// //** UI Manipulation
|
||||
// //***********************************************************************
|
||||
|
||||
// /// <summary>
|
||||
// /// Shows the splash page or the main presentation page, depending on config setting
|
||||
// /// </summary>
|
||||
// void ShowSplashOrMain()
|
||||
// {
|
||||
// if (UsesSplashPage)
|
||||
// SetMainMode(eMainModeType.Splash);
|
||||
// else
|
||||
// SetMainMode(eMainModeType.Presentation);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Switches between main modes
|
||||
// /// </summary>
|
||||
// void SetMainMode(eMainModeType mode)
|
||||
// {
|
||||
// MainMode = mode;
|
||||
// switch (mode)
|
||||
// {
|
||||
// case eMainModeType.Presentation:
|
||||
// TriList.BooleanInput[UiCue.VisibleCommonFooter.Number].BoolValue = true;
|
||||
// TriList.BooleanInput[UiCue.VisibleCommonHeader.Number].BoolValue = true;
|
||||
// TriList.BooleanInput[UiCue.VisibleSplash.Number].BoolValue = false;
|
||||
// TriList.BooleanInput[UiCue.VisiblePresentationSourceList.Number].BoolValue = true;
|
||||
// ShowCurrentPresentationSourceUi();
|
||||
// break;
|
||||
// case eMainModeType.Splash:
|
||||
// TriList.BooleanInput[UiCue.VisibleCommonFooter.Number].BoolValue = false;
|
||||
// TriList.BooleanInput[UiCue.VisibleCommonHeader.Number].BoolValue = false;
|
||||
// TriList.BooleanInput[UiCue.VisiblePresentationSourceList.Number].BoolValue = false;
|
||||
// TriList.BooleanInput[UiCue.VisibleSplash.Number].BoolValue = true;
|
||||
// HideCurrentPresentationSourceUi();
|
||||
// break;
|
||||
// case eMainModeType.Tech:
|
||||
// new ModalDialog(TriList).PresentModalTimerDialog(1, "Tech page", "Info",
|
||||
// "Tech page will be here soon!<br>I promise",
|
||||
// "Bueno!", "", 0, false, null);
|
||||
// MainMode = eMainModeType.Presentation;
|
||||
// break;
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// void PowerOffWithConfirmPressed()
|
||||
// {
|
||||
// if (CurrentRoom == null)
|
||||
// return;
|
||||
// if (!CurrentRoom.RoomIsOnFeedback.BoolValue)
|
||||
// return;
|
||||
// // Timeout or button 1 press will shut down
|
||||
// var modal = new ModalDialog(TriList);
|
||||
// uint seconds = CurrentRoom.UnattendedShutdownTimeMs / 1000;
|
||||
// var message = string.Format("Meeting will end in {0} seconds", seconds);
|
||||
// modal.PresentModalTimerDialog(2, "End Meeting", "Info", message,
|
||||
// "End Meeting Now", "Cancel", CurrentRoom.UnattendedShutdownTimeMs, true,
|
||||
// but => { if (but != 2) CurrentRoom.RoomOff(); });
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Reveals the basic UI for the current device
|
||||
// /// </summary>
|
||||
// protected override void ShowCurrentPresentationSourceUi()
|
||||
// {
|
||||
// if (MainMode == eMainModeType.Splash && CurrentRoom.RoomIsOnFeedback.BoolValue)
|
||||
// SetMainMode(eMainModeType.Presentation);
|
||||
|
||||
// if (CurrentPresentationControlDevice == null)
|
||||
// {
|
||||
// // If system is off, do one thing
|
||||
|
||||
// // Otherwise, do something else - shouldn't be in this condition
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
// // If a controller is already loaded, use it
|
||||
// if (LoadedPageControllers.ContainsKey(CurrentPresentationControlDevice))
|
||||
// CurrentPresentationSourcePageController = LoadedPageControllers[CurrentPresentationControlDevice];
|
||||
// else
|
||||
// {
|
||||
// // This is by no means optimal, but for now....
|
||||
// if (CurrentPresentationControlDevice.Type == PresentationSourceType.SetTopBox
|
||||
// && CurrentPresentationControlDevice is ISetTopBoxControls)
|
||||
// CurrentPresentationSourcePageController = new PageControllerLargeSetTopBoxGeneric(TriList,
|
||||
// CurrentPresentationControlDevice as ISetTopBoxControls);
|
||||
|
||||
// else if (CurrentPresentationControlDevice.Type == PresentationSourceType.Laptop)
|
||||
// CurrentPresentationSourcePageController = new PageControllerLaptop(TriList);
|
||||
|
||||
// // separate these...
|
||||
// else if (CurrentPresentationControlDevice.Type == PresentationSourceType.Dvd)
|
||||
// CurrentPresentationSourcePageController =
|
||||
// new PageControllerLargeDvd(TriList, CurrentPresentationControlDevice as IDiscPlayerControls);
|
||||
|
||||
// else
|
||||
// CurrentPresentationSourcePageController = null;
|
||||
|
||||
// // Save it.
|
||||
// if (CurrentPresentationSourcePageController != null)
|
||||
// LoadedPageControllers[CurrentPresentationControlDevice] = CurrentPresentationSourcePageController;
|
||||
// }
|
||||
|
||||
// if (CurrentPresentationSourcePageController != null)
|
||||
// CurrentPresentationSourcePageController.SetVisible(true);
|
||||
// }
|
||||
|
||||
// protected override void HideCurrentPresentationSourceUi()
|
||||
// {
|
||||
// if (CurrentPresentationControlDevice != null && CurrentPresentationSourcePageController != null)
|
||||
// CurrentPresentationSourcePageController.SetVisible(false);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// void ShowHelp()
|
||||
// {
|
||||
// new ModalDialog(TriList).PresentModalTimerDialog(1, "Help", "Help", CurrentRoom.HelpMessage,
|
||||
// "OK", "", 0, false, null);
|
||||
// }
|
||||
|
||||
// protected void ListSmartObjects()
|
||||
// {
|
||||
// Debug.Console(0, this, "Smart objects IDs:");
|
||||
// var list = TriList.SmartObjects.OrderBy(s => s.Key);
|
||||
// foreach (var kvp in list)
|
||||
// Debug.Console(0, " {0}", kvp.Key);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//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;
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Core.Presets;
|
||||
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class PageControllerLaptop : DevicePageControllerBase
|
||||
// {
|
||||
// public PageControllerLaptop(BasicTriListWithSmartObject tl)
|
||||
// : base(tl)
|
||||
// {
|
||||
// FixedObjectSigs = new List<BoolInputSig>
|
||||
// {
|
||||
// tl.BooleanInput[10092], // well
|
||||
// tl.BooleanInput[11001] // Laptop info
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
//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;
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Core.Presets;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// public class PageControllerLargeDvd : DevicePageControllerBase
|
||||
// {
|
||||
// IDiscPlayerControls Device;
|
||||
|
||||
// public PageControllerLargeDvd(BasicTriListWithSmartObject tl, IDiscPlayerControls device)
|
||||
// : base(tl)
|
||||
// {
|
||||
|
||||
// Device = device;
|
||||
// FixedObjectSigs = new List<BoolInputSig>
|
||||
// {
|
||||
// tl.BooleanInput[10093], // well
|
||||
// tl.BooleanInput[10411], // DVD Dpad
|
||||
// tl.BooleanInput[10412] // everything else
|
||||
// };
|
||||
// }
|
||||
|
||||
// protected override void CustomSetVisible(bool state)
|
||||
// {
|
||||
// // Hook up smart objects if applicable
|
||||
// if (Device != null)
|
||||
// {
|
||||
//#warning rewire this
|
||||
// //var uos = (Device as IHasCueActionList).CueActionList;
|
||||
// //SmartObjectHelper.LinkDpadWithUserObjects(TriList, 10411, uos, state);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
//using PepperDash.Essentials.Core.Presets;
|
||||
|
||||
//using PepperDash.Core;
|
||||
//using PepperDash.Essentials.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
|
||||
// public class PageControllerLargeSetTopBoxGeneric : DevicePageControllerBase
|
||||
// {
|
||||
// // To-DO: Add properties for component subpage names. DpadPos1, DpadPos2...
|
||||
// // Derived classes can then insert special subpages for variations on given
|
||||
// // device types. Like DirecTV vs Comcast
|
||||
|
||||
// public uint DpadSmartObjectId { get; set; }
|
||||
// public uint NumberPadSmartObjectId { get; set; }
|
||||
// public uint PresetsSmartObjectId { get; set; }
|
||||
// public uint Position5TabsId { get; set; }
|
||||
|
||||
// ISetTopBoxControls Device;
|
||||
// DevicePresetsView PresetsView;
|
||||
|
||||
|
||||
// bool ShowPosition5Tabs;
|
||||
// uint CurrentVisiblePosition5Item = 1;
|
||||
// Dictionary<uint, uint> Position5SubpageJoins = new Dictionary<uint, uint>
|
||||
// {
|
||||
// { 1, 10053 },
|
||||
// { 2, 10054 }
|
||||
// };
|
||||
|
||||
// public PageControllerLargeSetTopBoxGeneric(BasicTriListWithSmartObject tl, ISetTopBoxControls device)
|
||||
// : base(tl)
|
||||
// {
|
||||
// Device = device;
|
||||
// DpadSmartObjectId = 10011;
|
||||
// NumberPadSmartObjectId = 10014;
|
||||
// PresetsSmartObjectId = 10012;
|
||||
// Position5TabsId = 10081;
|
||||
|
||||
// bool dpad = device is IDPad;
|
||||
// bool preset = device.HasPresets;
|
||||
// bool dvr = device.HasDvr;
|
||||
// bool numbers = device is INumericKeypad;
|
||||
// uint[] joins = null;
|
||||
|
||||
// if (dpad && !preset && !dvr && !numbers) joins = new uint[] { 10031, 10091 };
|
||||
// else if (!dpad && preset && !dvr && !numbers) joins = new uint[] { 10032, 10091 };
|
||||
// else if (!dpad && !preset && dvr && !numbers) joins = new uint[] { 10033, 10091 };
|
||||
// else if (!dpad && !preset && !dvr && numbers) joins = new uint[] { 10034, 10091 };
|
||||
|
||||
// else if (dpad && preset && !dvr && !numbers) joins = new uint[] { 10042, 10021, 10092 };
|
||||
// else if (dpad && !preset && dvr && !numbers) joins = new uint[] { 10043, 10021, 10092 };
|
||||
// else if (dpad && !preset && !dvr && numbers) joins = new uint[] { 10044, 10021, 10092 };
|
||||
// else if (!dpad && preset && dvr && !numbers) joins = new uint[] { 10043, 10022, 10092 };
|
||||
// else if (!dpad && preset && !dvr && numbers) joins = new uint[] { 10044, 10022, 10092 };
|
||||
// else if (!dpad && !preset && dvr && numbers) joins = new uint[] { 10044, 10023, 10092 };
|
||||
|
||||
// else if (dpad && preset && dvr && !numbers) joins = new uint[] { 10053, 10032, 10011, 10093 };
|
||||
// else if (dpad && preset && !dvr && numbers) joins = new uint[] { 10054, 10032, 10011, 10093 };
|
||||
// else if (dpad && !preset && dvr && numbers) joins = new uint[] { 10054, 10033, 10011, 10093 };
|
||||
// else if (!dpad && preset && dvr && numbers) joins = new uint[] { 10054, 10033, 10012, 10093 };
|
||||
|
||||
// else if (dpad && preset && dvr && numbers)
|
||||
// {
|
||||
// joins = new uint[] { 10081, 10032, 10011, 10093 }; // special case
|
||||
// ShowPosition5Tabs = true;
|
||||
// }
|
||||
// // Project the joins into corresponding sigs.
|
||||
// FixedObjectSigs = joins.Select(u => TriList.BooleanInput[u]).ToList();
|
||||
|
||||
// // Build presets
|
||||
// if (device.HasPresets)
|
||||
// {
|
||||
// PresetsView = new DevicePresetsView(tl, device.PresetsModel);
|
||||
// }
|
||||
// }
|
||||
|
||||
// protected override void CustomSetVisible(bool state)
|
||||
// {
|
||||
// if (ShowPosition5Tabs)
|
||||
// {
|
||||
// // Show selected tab
|
||||
// TriList.BooleanInput[Position5SubpageJoins[CurrentVisiblePosition5Item]].BoolValue = state;
|
||||
|
||||
// var tabSo = TriList.SmartObjects[Position5TabsId];
|
||||
// if (state) // Link up the tab object
|
||||
// {
|
||||
// tabSo.BooleanOutput["Tab Button 1 Press"].UserObject = new Action<bool>(b => ShowTab(1));
|
||||
// tabSo.BooleanOutput["Tab Button 2 Press"].UserObject = new Action<bool>(b => ShowTab(2));
|
||||
// }
|
||||
// else // Disco tab object
|
||||
// {
|
||||
// tabSo.BooleanOutput["Tab Button 1 Press"].UserObject = null;
|
||||
// tabSo.BooleanOutput["Tab Button 2 Press"].UserObject = null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Hook up smart objects if applicable
|
||||
//#warning hook these up
|
||||
// //if (Device is IHasCueActionList)
|
||||
// //{
|
||||
// // var uos = (Device as IHasCueActionList).CueActionList;
|
||||
// // SmartObjectHelper.LinkDpadWithUserObjects(TriList, DpadSmartObjectId, uos, state);
|
||||
// // SmartObjectHelper.LinkNumpadWithUserObjects(TriList, NumberPadSmartObjectId,
|
||||
// // uos, CommonBoolCue.Dash, CommonBoolCue.Last, state);
|
||||
// //}
|
||||
|
||||
|
||||
// // Link, unlink presets
|
||||
// if (Device.HasPresets && state)
|
||||
// PresetsView.Attach();
|
||||
// else if (Device.HasPresets && !state)
|
||||
// PresetsView.Detach();
|
||||
// }
|
||||
|
||||
// void ShowTab(uint number)
|
||||
// {
|
||||
// // Ignore re-presses
|
||||
// if (CurrentVisiblePosition5Item == number) return;
|
||||
// // Swap subpage
|
||||
// var bi = TriList.BooleanInput;
|
||||
// if (CurrentVisiblePosition5Item > 0)
|
||||
// bi[Position5SubpageJoins[CurrentVisiblePosition5Item]].BoolValue = false;
|
||||
// CurrentVisiblePosition5Item = number;
|
||||
// bi[Position5SubpageJoins[CurrentVisiblePosition5Item]].BoolValue = true;
|
||||
|
||||
// // Show feedback on buttons
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
43
PepperDashEssentials/FOR REFERENCE UI/Panels/REMOVE UiCue.cs
Normal file
43
PepperDashEssentials/FOR REFERENCE UI/Panels/REMOVE UiCue.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
|
||||
//namespace PepperDash.Essentials.Core
|
||||
//{
|
||||
// public class UiCue
|
||||
// {
|
||||
// public static readonly Cue VisibleSystemInit = Cue.BoolCue("VisibleSystemInit", 15001);
|
||||
// public static readonly Cue VisibleSplash = Cue.BoolCue("VisibleSplash", 15002);
|
||||
// public static readonly Cue PressSplash = Cue.BoolCue("PressSplash", 15003);
|
||||
// public static readonly Cue PressRoomOn = Cue.BoolCue("PressRoomOn", 15006);
|
||||
// public static readonly Cue PressRoomOff = Cue.BoolCue("PressRoomOff", 15007);
|
||||
// public static readonly Cue PressRoomOffWithConfirm = Cue.BoolCue("PressRoomOffWithConfirm", 15008);
|
||||
// public static readonly Cue VisibleCommonHeader = Cue.BoolCue("PressPowerOffConfirm", 15011);
|
||||
// public static readonly Cue VisibleCommonFooter = Cue.BoolCue("VisibleCommonFooter", 15012);
|
||||
// public static readonly Cue PressHelp = Cue.BoolCue("PressHelp", 15013);
|
||||
// public static readonly Cue PressSettings = Cue.BoolCue("PressSettings", 15014);
|
||||
|
||||
// public static readonly Cue ShowDate = Cue.BoolCue("PressSettings", 15015);
|
||||
// public static readonly Cue ShowTime = Cue.BoolCue("PressSettings", 15016);
|
||||
// public static readonly Cue ShowLicensed = Cue.BoolCue("PressSettings", 15017);
|
||||
// public static readonly Cue ShowUnLicensed = Cue.BoolCue("PressSettings", 15018);
|
||||
|
||||
// public static readonly Cue PressModePresentationShare = Cue.BoolCue("PressModePresentationShare", 15101);
|
||||
// public static readonly Cue PressModeVideoConf = Cue.BoolCue("PressModeVideoConf", 15102);
|
||||
// public static readonly Cue PressModeAudioConf = Cue.BoolCue("PressModeAudioConf", 15103);
|
||||
|
||||
// public static readonly Cue VisiblePresentationSourceList = Cue.BoolCue("VisiblePresentationSourceList", 15111);
|
||||
// public static readonly Cue VisibleSystemIsOff = Cue.BoolCue("VisibleSystemIsOff", 15112);
|
||||
|
||||
// public static readonly Cue VisibleAudioConfPopover = Cue.BoolCue("VisibleAudioConfPopover", 15201);
|
||||
|
||||
// public static readonly Cue VisibleVideoConfPopover = Cue.BoolCue("VisibleVideoConfPopover", 15251);
|
||||
|
||||
// public static readonly Cue TextRoomName = Cue.BoolCue("TextRoomName", 4001);
|
||||
// public static readonly Cue TextPresentationShareButton = Cue.BoolCue("TextPresentationShareButton", 4011);
|
||||
|
||||
// public static readonly Cue SplashMessage = Cue.StringCue("SplashMessage", 2101);
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
|
||||
//namespace PepperDash.Essentials.Core
|
||||
//{
|
||||
// public abstract class SmartGraphicsTouchpanelControllerBase : CrestronGenericBaseDevice
|
||||
// {
|
||||
// public BasicTriListWithSmartObject TriList { get; protected set; }
|
||||
// public bool UsesSplashPage { get; set; }
|
||||
// public string SplashMessage { get; set; }
|
||||
// public bool ShowDate
|
||||
// {
|
||||
// set { TriList.BooleanInput[UiCue.ShowDate.Number].BoolValue = value; }
|
||||
// }
|
||||
// public bool ShowTime
|
||||
// {
|
||||
// set { TriList.BooleanInput[UiCue.ShowTime.Number].BoolValue = value; }
|
||||
// }
|
||||
|
||||
// //public abstract List<CueActionPair> FunctionList { get; }
|
||||
|
||||
|
||||
// protected eMainModeType MainMode;
|
||||
// protected SourceListItem CurrentPresentationControlDevice;
|
||||
|
||||
// /// <summary>
|
||||
// /// Defines the signal offset for the presentation device. Defaults to 100
|
||||
// /// </summary>
|
||||
// public uint PresentationControlDeviceJoinOffset { get { return 100; } }
|
||||
|
||||
// public enum eMainModeType
|
||||
// {
|
||||
// Presentation, Splash, Tech
|
||||
// }
|
||||
|
||||
// protected string SgdFilePath;
|
||||
// public EssentialsRoom CurrentRoom { get; protected set; }
|
||||
// protected Dictionary<SourceListItem, DevicePageControllerBase> LoadedPageControllers
|
||||
// = new Dictionary<SourceListItem, DevicePageControllerBase>();
|
||||
|
||||
// static object RoomChangeLock = new object();
|
||||
|
||||
// /// <summary>
|
||||
// /// Constructor
|
||||
// /// </summary>
|
||||
// public SmartGraphicsTouchpanelControllerBase(string key, string name, BasicTriListWithSmartObject triList,
|
||||
// string sgdFilePath)
|
||||
// : base(key, name, triList)
|
||||
// {
|
||||
// TriList = triList;
|
||||
// if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key");
|
||||
// if (string.IsNullOrEmpty(sgdFilePath)) throw new ArgumentNullException("sgdFilePath");
|
||||
// SgdFilePath = sgdFilePath;
|
||||
// TriList.LoadSmartObjects(SgdFilePath);
|
||||
// UsesSplashPage = true;
|
||||
// SplashMessage = "Welcome";
|
||||
// TriList.SigChange += Tsw_AnySigChange;
|
||||
// foreach (var kvp in TriList.SmartObjects)
|
||||
// kvp.Value.SigChange += this.Tsw_AnySigChange;
|
||||
// }
|
||||
|
||||
//#warning wire UI manipulating presses up here, typically in child classes...
|
||||
// //public override bool CustomActivate()
|
||||
// //{
|
||||
// // var baseSuccess = base.CustomActivate();
|
||||
// // if (!baseSuccess) return false;
|
||||
|
||||
|
||||
// // // Wiring up the buttons with UOs
|
||||
// // foreach (var uo in this.FunctionList)
|
||||
// // {
|
||||
// // if (uo.Cue.Number == 0) continue;
|
||||
// // //if (uo is BoolCueActionPair)
|
||||
// // // TriList.BooleanOutput[uo.Cue.Number].UserObject = uo;
|
||||
// // //else if (uo is UShortCueActionPair)
|
||||
// // // TriList.UShortOutput[uo.Cue.Number].UserObject = uo;
|
||||
// // //else if (uo is StringCueActionPair)
|
||||
// // // TriList.StringOutput[uo.Cue.Number].UserObject = uo;
|
||||
// // }
|
||||
|
||||
// // return true;
|
||||
// //}
|
||||
|
||||
// //public void SetCurrentRoom(EssentialsRoom room)
|
||||
// //{
|
||||
// // if (CurrentRoom != null)
|
||||
// // HideRoomUI();
|
||||
// // CurrentRoom = room;
|
||||
// // ShowRoomUI();
|
||||
// //}
|
||||
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// /// <param name="room"></param>
|
||||
// public void SetCurrentRoom(EssentialsRoom room)
|
||||
// {
|
||||
// if (CurrentRoom == room) return;
|
||||
|
||||
// IBasicVolumeControls oldAudio = null;
|
||||
// //Disconnect current room and audio device
|
||||
// if (CurrentRoom != null)
|
||||
// {
|
||||
// HideRoomUI();
|
||||
// CurrentRoom.AudioDeviceWillChange -= CurrentRoom_AudioDeviceWillChange;
|
||||
// CurrentRoom.PresentationSourceChange -= CurrentRoom_PresentationSourceChange;
|
||||
// oldAudio = CurrentRoom.CurrentAudioDevice;
|
||||
// }
|
||||
|
||||
// CurrentRoom = room;
|
||||
// IBasicVolumeControls newAudio = null;
|
||||
// if (CurrentRoom != null)
|
||||
// {
|
||||
// CurrentRoom.AudioDeviceWillChange += this.CurrentRoom_AudioDeviceWillChange;
|
||||
// CurrentRoom.PresentationSourceChange += this.CurrentRoom_PresentationSourceChange;
|
||||
// SetControlSource(CurrentRoom.CurrentPresentationSourceInfo);
|
||||
// newAudio = CurrentRoom.CurrentAudioDevice;
|
||||
// ShowRoomUI();
|
||||
// }
|
||||
|
||||
// SwapAudioDeviceControls(oldAudio, newAudio);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Detaches and attaches an IVolumeFunctions device to the appropriate TP TriList signals.
|
||||
// /// This will also add IVolumeNumeric if the device implements it.
|
||||
// /// Overriding classes should call this. Overriding classes are responsible for
|
||||
// /// linking up to hard keys, etc.
|
||||
// /// </summary>
|
||||
// /// <param name="oldDev">May be null</param>
|
||||
// /// <param name="newDev">May be null</param>
|
||||
// protected virtual void SwapAudioDeviceControls(IBasicVolumeControls oldDev, IBasicVolumeControls newDev)
|
||||
// {
|
||||
// // Disconnect
|
||||
// if (oldDev != null)
|
||||
// {
|
||||
// TriList.BooleanOutput[CommonBoolCue.VolumeDown.Number].UserObject = null;
|
||||
// TriList.BooleanOutput[CommonBoolCue.VolumeUp.Number].UserObject = null;
|
||||
// TriList.BooleanOutput[CommonBoolCue.MuteToggle.Number].UserObject = null;
|
||||
// TriList.BooleanInput[CommonBoolCue.ShowVolumeButtons.Number].BoolValue = false;
|
||||
// TriList.BooleanInput[CommonBoolCue.ShowVolumeSlider.Number].BoolValue = false;
|
||||
// if (oldDev is IBasicVolumeWithFeedback)
|
||||
// {
|
||||
// var fbDev = oldDev as IBasicVolumeWithFeedback;
|
||||
// TriList.UShortOutput[401].UserObject = null;
|
||||
// fbDev.MuteFeedback.UnlinkInputSig(TriList.BooleanInput[403]);
|
||||
// fbDev.VolumeLevelFeedback.UnlinkInputSig(TriList.UShortInput[401]);
|
||||
// }
|
||||
// }
|
||||
// if (newDev != null)
|
||||
// {
|
||||
// TriList.BooleanInput[CommonBoolCue.ShowVolumeSlider.Number].BoolValue = true;
|
||||
// TriList.SetBoolSigAction(401, newDev.VolumeUp);
|
||||
// TriList.SetBoolSigAction(402, newDev.VolumeDown);
|
||||
// TriList.SetSigFalseAction(405, newDev.MuteToggle);
|
||||
|
||||
// if (newDev is IBasicVolumeWithFeedback) // Show slider
|
||||
// {
|
||||
// var fbDev = newDev as IBasicVolumeWithFeedback;
|
||||
// TriList.BooleanInput[406].BoolValue = false;
|
||||
// TriList.BooleanInput[407].BoolValue = true;
|
||||
// TriList.UShortOutput[401].UserObject = new Action<ushort>(fbDev.SetVolume);
|
||||
// fbDev.VolumeLevelFeedback.LinkInputSig(TriList.UShortInput[401]);
|
||||
// }
|
||||
// else // Show buttons only
|
||||
// {
|
||||
// TriList.BooleanInput[406].BoolValue = true;
|
||||
// TriList.BooleanInput[407].BoolValue = false;
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// Does nothing. Override to add functionality when calling SetCurrentRoom
|
||||
// /// </summary>
|
||||
// protected virtual void HideRoomUI() { }
|
||||
|
||||
// /// <summary>
|
||||
// /// Does nothing. Override to add functionality when calling SetCurrentRoom
|
||||
// /// </summary>
|
||||
// protected virtual void ShowRoomUI() { }
|
||||
|
||||
// /// <summary>
|
||||
// /// Sets up the current presentation device and updates statuses if the device is capable.
|
||||
// /// </summary>
|
||||
// protected void SetControlSource(SourceListItem newSource)
|
||||
// {
|
||||
// if (CurrentPresentationControlDevice != null)
|
||||
// {
|
||||
// HideCurrentPresentationSourceUi();
|
||||
//#warning Get button methods from RESI, and find a more-well-defined way to wire up feedbacks
|
||||
|
||||
// // Unhook presses and things
|
||||
// //if (CurrentPresentationControlDevice is IHasCueActionList)
|
||||
// //{
|
||||
// // foreach (var uo in (CurrentPresentationControlDevice as IHasCueActionList).CueActionList)
|
||||
// // {
|
||||
// // if (uo.Cue.Number == 0) continue;
|
||||
// // if (uo is BoolCueActionPair)
|
||||
// // {
|
||||
// // var bSig = TriList.BooleanOutput[uo.Cue.Number];
|
||||
// // // Disconnection should also clear bool sigs in case they are pressed and
|
||||
// // // might be orphaned
|
||||
// // if (bSig.BoolValue)
|
||||
// // (bSig.UserObject as BoolCueActionPair).Invoke(false);
|
||||
// // bSig.UserObject = null;
|
||||
// // }
|
||||
// // else if (uo is UShortCueActionPair)
|
||||
// // TriList.UShortOutput[uo.Cue.Number].UserObject = null;
|
||||
// // else if (uo is StringCueActionPair)
|
||||
// // TriList.StringOutput[uo.Cue.Number].UserObject = null;
|
||||
// // }
|
||||
// //}
|
||||
// // unhook outputs
|
||||
// if (CurrentPresentationControlDevice is IHasFeedback)
|
||||
// {
|
||||
// foreach (var fb in (CurrentPresentationControlDevice as IHasFeedback).Feedbacks)
|
||||
// {
|
||||
// if (fb.Cue.Number == 0) continue;
|
||||
// if (fb is BoolFeedback)
|
||||
// (fb as BoolFeedback).UnlinkInputSig(TriList.BooleanInput[fb.Cue.Number]);
|
||||
// else if (fb is IntFeedback)
|
||||
// (fb as IntFeedback).UnlinkInputSig(TriList.UShortInput[fb.Cue.Number]);
|
||||
// else if (fb is StringFeedback)
|
||||
// (fb as StringFeedback).UnlinkInputSig(TriList.StringInput[fb.Cue.Number]);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// CurrentPresentationControlDevice = newSource;
|
||||
// //connect presses and things
|
||||
// //if (newSource is IHasCueActionList) // This has functions, get 'em
|
||||
// //{
|
||||
// // foreach (var ao in (newSource as IHasCueActionList).CueActionList)
|
||||
// // {
|
||||
// // if (ao.Cue.Number == 0) continue;
|
||||
// // if (ao is BoolCueActionPair)
|
||||
// // TriList.BooleanOutput[ao.Cue.Number].UserObject = ao;
|
||||
// // else if (ao is UShortCueActionPair)
|
||||
// // TriList.UShortOutput[ao.Cue.Number].UserObject = ao;
|
||||
// // else if (ao is StringCueActionPair)
|
||||
// // TriList.StringOutput[ao.Cue.Number].UserObject = ao;
|
||||
// // }
|
||||
// //}
|
||||
// // connect outputs (addInputSig should update sig)
|
||||
// if (CurrentPresentationControlDevice is IHasFeedback)
|
||||
// {
|
||||
// foreach (var fb in (CurrentPresentationControlDevice as IHasFeedback).Feedbacks)
|
||||
// {
|
||||
// if (fb.Cue.Number == 0) continue;
|
||||
// if (fb is BoolFeedback)
|
||||
// (fb as BoolFeedback).LinkInputSig(TriList.BooleanInput[fb.Cue.Number]);
|
||||
// else if (fb is IntFeedback)
|
||||
// (fb as IntFeedback).LinkInputSig(TriList.UShortInput[fb.Cue.Number]);
|
||||
// else if (fb is StringFeedback)
|
||||
// (fb as StringFeedback).LinkInputSig(TriList.StringInput[fb.Cue.Number]);
|
||||
// }
|
||||
// }
|
||||
// ShowCurrentPresentationSourceUi();
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Reveals the basic UI for the current device
|
||||
// /// </summary>
|
||||
// protected virtual void ShowCurrentPresentationSourceUi()
|
||||
// {
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Hides the UI for the current device and calls for a feedback signal cleanup
|
||||
// /// </summary>
|
||||
// protected virtual void HideCurrentPresentationSourceUi()
|
||||
// {
|
||||
// }
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// void CurrentRoom_PresentationSourceChange(object sender, EssentialsRoomSourceChangeEventArgs args)
|
||||
// {
|
||||
// SetControlSource(args.NewSource);
|
||||
// }
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// void CurrentRoom_AudioDeviceWillChange(object sender, EssentialsRoomAudioDeviceChangeEventArgs e)
|
||||
// {
|
||||
// SwapAudioDeviceControls(e.OldDevice, e.NewDevice);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// Panel event handler
|
||||
// /// </summary>
|
||||
// void Tsw_AnySigChange(object currentDevice, SigEventArgs args)
|
||||
// {
|
||||
// // plugged in commands
|
||||
// object uo = args.Sig.UserObject;
|
||||
|
||||
// if (uo is Action<bool>)
|
||||
// (uo as Action<bool>)(args.Sig.BoolValue);
|
||||
// else if (uo is Action<ushort>)
|
||||
// (uo as Action<ushort>)(args.Sig.UShortValue);
|
||||
// else if (uo is Action<string>)
|
||||
// (uo as Action<string>)(args.Sig.StringValue);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
//using Crestron.SimplSharpPro.UI;
|
||||
|
||||
//using PepperDash.Core;
|
||||
//using PepperDash.Essentials.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
|
||||
// //*****************************************************************************
|
||||
// /// <summary>
|
||||
// /// Wrapper class for subpage reference list. Contains helpful methods to get at the various signal groupings
|
||||
// /// and to get individual signals using an index and a join.
|
||||
// /// </summary>
|
||||
// public class SourceListSubpageReferenceList : SubpageReferenceList
|
||||
// {
|
||||
// public const uint SmartObjectJoin = 3801;
|
||||
|
||||
// Action<uint> SourceSelectCallback;
|
||||
|
||||
// EssentialsRoom CurrentRoom;
|
||||
|
||||
// public SourceListSubpageReferenceList(BasicTriListWithSmartObject tl,
|
||||
// Action<uint> sourceSelectCallback)
|
||||
// : base(tl, SmartObjectJoin, 3, 1, 3)
|
||||
// {
|
||||
// SourceSelectCallback = sourceSelectCallback;
|
||||
// }
|
||||
|
||||
// void SetSourceList(Dictionary<uint, SourceListItem> dict)
|
||||
// {
|
||||
// // Iterate all positions, including ones missing from the dict.
|
||||
// var max = dict.Keys.Max();
|
||||
// for (uint i = 1; i <= max; i++)
|
||||
// {
|
||||
// // Add the source if it's in the dict
|
||||
// if (dict.ContainsKey(i))
|
||||
// {
|
||||
// Items.Add(new SourceListSubpageReferenceListItem(i, dict[i], this, SourceSelectCallback));
|
||||
// // Plug the callback function into the buttons
|
||||
// }
|
||||
// // Blank the line
|
||||
// else
|
||||
// Items.Add(new SourceListSubpageReferenceListItem(i, null,
|
||||
// this, SourceSelectCallback));
|
||||
// }
|
||||
// Count = (ushort)max;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Links the SRL to the Room's PresentationSourceChange event for updating of the UI
|
||||
// /// </summary>
|
||||
// /// <param name="room"></param>
|
||||
// public void AttachToRoom(EssentialsRoom room)
|
||||
// {
|
||||
// CurrentRoom = room;
|
||||
// SetSourceList(room.Sources);
|
||||
// CurrentRoom.PresentationSourceChange -= CurrentRoom_PresentationSourceChange;
|
||||
// CurrentRoom.PresentationSourceChange += CurrentRoom_PresentationSourceChange;
|
||||
// SetPresentationSourceFb(CurrentRoom.CurrentPresentationSource);
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Disconnects the SRL from a Room's PresentationSourceChange
|
||||
// /// </summary>
|
||||
// public void DetachFromCurrentRoom()
|
||||
// {
|
||||
// ClearPresentationSourceFb(CurrentRoom.CurrentPresentationSource);
|
||||
// if(CurrentRoom != null)
|
||||
// CurrentRoom.PresentationSourceChange -= CurrentRoom_PresentationSourceChange;
|
||||
// CurrentRoom = null;
|
||||
// }
|
||||
|
||||
// // Handler to route source changes into list feedback
|
||||
// void CurrentRoom_PresentationSourceChange(object sender, EssentialsRoomSourceChangeEventArgs args)
|
||||
// {
|
||||
// Debug.Console(2, "SRL received source change");
|
||||
// ClearPresentationSourceFb(args.OldSource);
|
||||
// SetPresentationSourceFb(args.NewSource);
|
||||
// }
|
||||
|
||||
// void ClearPresentationSourceFb(IPresentationSource source)
|
||||
// {
|
||||
// if (source == null) return;
|
||||
// var oldSourceItem = (SourceListSubpageReferenceListItem)Items.FirstOrDefault(
|
||||
// i => ((SourceListSubpageReferenceListItem)i).SourceDevice == source);
|
||||
// if (oldSourceItem != null)
|
||||
// oldSourceItem.ClearFeedback();
|
||||
// }
|
||||
|
||||
// void SetPresentationSourceFb(SourceListItem source)
|
||||
// {
|
||||
// if (source == null) return;
|
||||
// // Now set the new source to light up
|
||||
// var newSourceItem = (SourceListSubpageReferenceListItem)Items.FirstOrDefault(
|
||||
// i => ((SourceListSubpageReferenceListItem)i).SourceDevice == source);
|
||||
// if (newSourceItem != null)
|
||||
// newSourceItem.SetFeedback();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public class SourceListSubpageReferenceListItem : SubpageReferenceListItem
|
||||
// {
|
||||
// public readonly IPresentationSource SourceDevice;
|
||||
|
||||
// public const uint ButtonPressJoin = 1;
|
||||
// public const uint SelectedFeedbackJoin = 2;
|
||||
// public const uint ButtonTextJoin = 1;
|
||||
// public const uint IconNameJoin = 2;
|
||||
|
||||
// public SourceListSubpageReferenceListItem(uint index, SourceListItem srcDeviceItem,
|
||||
// SubpageReferenceList owner, Action<uint> sourceSelectCallback)
|
||||
// : base(index, owner)
|
||||
// {
|
||||
// if (srcDeviceItem == null) throw new ArgumentNullException("srcDeviceItem");
|
||||
// if (owner == null) throw new ArgumentNullException("owner");
|
||||
// if (sourceSelectCallback == null) throw new ArgumentNullException("sourceSelectCallback");
|
||||
|
||||
|
||||
// SourceDevice = srcDeviceItem;
|
||||
// var nameSig = owner.StringInputSig(index, ButtonTextJoin);
|
||||
// // Should be able to see if there is not enough buttons right here
|
||||
// if (nameSig == null)
|
||||
// {
|
||||
// Debug.Console(0, "ERROR: Item {0} does not exist on source list SRL", index);
|
||||
// return;
|
||||
// }
|
||||
// nameSig.StringValue = srcDeviceItem.Name;
|
||||
// owner.StringInputSig(index, IconNameJoin).StringValue = srcDeviceItem.Icon;
|
||||
|
||||
// // Assign a source selection action to the appropriate button's UserObject - on release
|
||||
// owner.GetBoolFeedbackSig(index, ButtonPressJoin).UserObject = new Action<bool>(b =>
|
||||
// { if (!b) sourceSelectCallback(index); });
|
||||
|
||||
// // hook up the video icon
|
||||
// var videoDev = srcDeviceItem as IAttachVideoStatus;
|
||||
// if (videoDev != null)
|
||||
// {
|
||||
// var status = videoDev.GetVideoStatuses();
|
||||
// if (status != null)
|
||||
// {
|
||||
// Debug.Console(1, "Linking {0} video status to SRL", videoDev.Key);
|
||||
// videoDev.GetVideoStatuses().VideoSyncFeedback.LinkInputSig(owner.BoolInputSig(index, 3));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void SetFeedback()
|
||||
// {
|
||||
// Owner.BoolInputSig(Index, SelectedFeedbackJoin).BoolValue = true;
|
||||
// }
|
||||
|
||||
// public void ClearFeedback()
|
||||
// {
|
||||
// Owner.BoolInputSig(Index, SelectedFeedbackJoin).BoolValue = false;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
92
PepperDashEssentials/Factory/DeviceFactory.cs
Normal file
92
PepperDashEssentials/Factory/DeviceFactory.cs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class DeviceFactory
|
||||
{
|
||||
public static IKeyed GetDevice(DeviceConfig dc)
|
||||
{
|
||||
var key = dc.Key;
|
||||
var name = dc.Name;
|
||||
var type = dc.Type;
|
||||
var properties = dc.Properties;
|
||||
|
||||
var typeName = dc.Type.ToLower();
|
||||
|
||||
if (typeName == "amplifier")
|
||||
{
|
||||
return new Amplifier(dc.Key, dc.Name);
|
||||
}
|
||||
else if (dc.Group.ToLower() == "touchpanel") // typeName.StartsWith("tsw"))
|
||||
{
|
||||
return UiDeviceFactory.GetUiDevice(dc);
|
||||
}
|
||||
|
||||
else if (typeName == "mockdisplay")
|
||||
{
|
||||
return new MockDisplay(key, name);
|
||||
}
|
||||
|
||||
else if (typeName == "generic")
|
||||
{
|
||||
return new Device(key, name);
|
||||
}
|
||||
|
||||
// MOVE into something else???
|
||||
else if (typeName == "basicirdisplay")
|
||||
{
|
||||
var ir = IRPortHelper.GetIrPort(properties);
|
||||
if (ir != null)
|
||||
return new BasicIrDisplay(key, name, ir.Port, ir.FileName);
|
||||
}
|
||||
|
||||
else if (typeName == "commmock")
|
||||
{
|
||||
var comm = CommFactory.CreateCommForDevice(dc);
|
||||
var props = JsonConvert.DeserializeObject<ConsoleCommMockDevicePropertiesConfig>(
|
||||
properties.ToString());
|
||||
return new ConsoleCommMockDevice(key, name, props, comm);
|
||||
}
|
||||
|
||||
else if (typeName == "appserver")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<CotijaConfig>(properties.ToString());
|
||||
return new CotijaSystemController(key, name, props);
|
||||
}
|
||||
|
||||
else if (typeName == "mobilecontrolbridge-ddvc01")
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
||||
|
||||
var bridge = new PepperDash.Essentials.Room.Cotija.CotijaDdvc01RoomBridge(key, name, comm.IpIdInt);
|
||||
bridge.AddPreActivationAction(() =>
|
||||
{
|
||||
var parent = DeviceManager.AllDevices.FirstOrDefault(d => d.Key == "appServer") as CotijaSystemController;
|
||||
if (parent == null)
|
||||
{
|
||||
Debug.Console(0, bridge, "ERROR: Cannot connect bridge. System controller not present");
|
||||
}
|
||||
Debug.Console(0, bridge, "Linking to parent controller");
|
||||
bridge.AddParent(parent);
|
||||
parent.AddBridge(bridge);
|
||||
});
|
||||
|
||||
return bridge;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
162
PepperDashEssentials/Factory/UiDeviceFactory.cs
Normal file
162
PepperDashEssentials/Factory/UiDeviceFactory.cs
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Core.PageManagers;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class UiDeviceFactory
|
||||
{
|
||||
public static IKeyed GetUiDevice(DeviceConfig config)
|
||||
{
|
||||
var comm = CommFactory.GetControlPropertiesConfig(config);
|
||||
|
||||
var props = JsonConvert.DeserializeObject<CrestronTouchpanelPropertiesConfig>(config.Properties.ToString());
|
||||
|
||||
EssentialsTouchpanelController panelController = new EssentialsTouchpanelController(config.Key, config.Name, config.Type, props, comm.IpIdInt);
|
||||
|
||||
panelController.AddPostActivationAction(() =>
|
||||
{
|
||||
var mainDriver = new EssentialsPanelMainInterfaceDriver(panelController.Panel, props);
|
||||
// Then the sub drivers
|
||||
|
||||
// spin up different room drivers depending on room type
|
||||
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
|
||||
if (room is EssentialsHuddleSpaceRoom)
|
||||
{
|
||||
|
||||
// Header Driver
|
||||
Debug.Console(0, panelController, "Adding header driver");
|
||||
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
|
||||
|
||||
// AV Driver
|
||||
Debug.Console(0, panelController, "Adding huddle space AV driver");
|
||||
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
|
||||
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
|
||||
// Environment Driver
|
||||
if (avDriver.CurrentRoom.Config.Environment != null && avDriver.CurrentRoom.Config.Environment.DeviceKeys.Count > 0)
|
||||
{
|
||||
Debug.Console(0, panelController, "Adding environment driver");
|
||||
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
||||
|
||||
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.Config.Environment);
|
||||
}
|
||||
|
||||
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
||||
|
||||
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
|
||||
|
||||
if (panelController.Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = panelController.Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
if(mainDriver.EnvironmentDriver != null)
|
||||
tsw.Lights.UserObject = new Action<bool>(b =>
|
||||
{
|
||||
if (!b)
|
||||
{
|
||||
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
|
||||
mainDriver.EnvironmentDriver.Toggle();
|
||||
}
|
||||
});
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
}
|
||||
}
|
||||
//else if (room is EssentialsPresentationRoom)
|
||||
//{
|
||||
// Debug.Console(0, panelController, "Adding presentation room driver");
|
||||
// var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
|
||||
// avDriver.CurrentRoom = room as EssentialsPresentationRoom;
|
||||
// avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
// mainDriver.AvDriver = avDriver ;
|
||||
// mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
|
||||
// panelController.LoadAndShowDriver(mainDriver);
|
||||
|
||||
// if (panelController.Panel is TswFt5ButtonSystem)
|
||||
// {
|
||||
// var tsw = panelController.Panel as TswFt5ButtonSystem;
|
||||
// // Wire up hard keys
|
||||
// tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
// //tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
// tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
// tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
// }
|
||||
//}
|
||||
else if (room is EssentialsHuddleVtc1Room)
|
||||
{
|
||||
Debug.Console(0, panelController, "Adding huddle space VTC AV driver");
|
||||
|
||||
// Header Driver
|
||||
mainDriver.HeaderDriver = new EssentialsHeaderDriver(mainDriver, props);
|
||||
|
||||
// AV Driver
|
||||
var avDriver = new EssentialsHuddleVtc1PanelAvFunctionsDriver(mainDriver, props);
|
||||
|
||||
var codecDriver = new PepperDash.Essentials.UIDrivers.VC.EssentialsVideoCodecUiDriver(panelController.Panel, avDriver,
|
||||
(room as EssentialsHuddleVtc1Room).VideoCodec, mainDriver.HeaderDriver);
|
||||
avDriver.SetVideoCodecDriver(codecDriver);
|
||||
avDriver.CurrentRoom = room as EssentialsHuddleVtc1Room;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
|
||||
// Environment Driver
|
||||
if (avDriver.CurrentRoom.Config.Environment != null && avDriver.CurrentRoom.Config.Environment.DeviceKeys.Count > 0)
|
||||
{
|
||||
Debug.Console(0, panelController, "Adding environment driver");
|
||||
mainDriver.EnvironmentDriver = new EssentialsEnvironmentDriver(mainDriver, props);
|
||||
|
||||
mainDriver.EnvironmentDriver.GetDevicesFromConfig(avDriver.CurrentRoom.Config.Environment);
|
||||
}
|
||||
|
||||
mainDriver.HeaderDriver.SetupHeaderButtons(avDriver, avDriver.CurrentRoom);
|
||||
|
||||
panelController.LoadAndShowDriver(mainDriver); // This is a little convoluted.
|
||||
|
||||
if (panelController.Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = panelController.Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.EndMeetingPress(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
if (mainDriver.EnvironmentDriver != null)
|
||||
tsw.Lights.UserObject = new Action<bool>(b =>
|
||||
{
|
||||
if (!b)
|
||||
{
|
||||
//mainDriver.AvDriver.PopupInterlock.ShowInterlockedWithToggle(mainDriver.EnvironmentDriver.BackgroundSubpageJoin);
|
||||
mainDriver.EnvironmentDriver.Toggle();
|
||||
}
|
||||
});
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, panelController, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
|
||||
}
|
||||
});
|
||||
|
||||
return panelController;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
266
PepperDashEssentials/HttpApiHandler.cs
Normal file
266
PepperDashEssentials/HttpApiHandler.cs
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharp.CrestronIO;
|
||||
//using Crestron.SimplSharp.Net.Http;
|
||||
|
||||
//using Newtonsoft.Json;
|
||||
//using Newtonsoft.Json.Linq;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Core.Http;
|
||||
//using PepperDash.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class EssentialsHttpApiHandler
|
||||
// {
|
||||
// string ConfigPath;
|
||||
// string PresetsPathPrefix;
|
||||
// EssentialsHttpServer Server;
|
||||
|
||||
// /// <summary>
|
||||
// ///
|
||||
// /// </summary>
|
||||
// /// <param name="server">HTTP server to attach to</param>
|
||||
// /// <param name="configPath">The full path to configuration file</param>
|
||||
// /// <param name="presetsListPath">The folder prefix for the presets path, eq "\HTML\presets\"</param>
|
||||
// public EssentialsHttpApiHandler(EssentialsHttpServer server, string configPath, string presetsPathPrefix)
|
||||
// {
|
||||
// if (server == null) throw new ArgumentNullException("server");
|
||||
// Server = server;
|
||||
// ConfigPath = configPath;
|
||||
// PresetsPathPrefix = presetsPathPrefix;
|
||||
// server.ApiRequest += Server_ApiRequest;
|
||||
// }
|
||||
|
||||
|
||||
// void Server_ApiRequest(object sender, Crestron.SimplSharp.Net.Http.OnHttpRequestArgs args)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// var path = args.Request.Path.ToLower();
|
||||
|
||||
// if (path == "/api/config")
|
||||
// HandleApiConfig(args);
|
||||
// else if (path.StartsWith("/api/presetslist/"))
|
||||
// HandleApiPresetsList(args);
|
||||
// else if (path == "/api/presetslists")
|
||||
// HandleApiGetPresetsLists(args.Request, args.Response);
|
||||
// else
|
||||
// {
|
||||
// args.Response.Code = 404;
|
||||
// return;
|
||||
// }
|
||||
// args.Response.Header.SetHeaderValue("Access-Control-Allow-Origin", "*");
|
||||
// args.Response.Header.SetHeaderValue("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// Debug.Console(1, "Uncaught HTTP server error: \n{0}", e);
|
||||
// args.Response.Code = 500;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// GET will return the running configuration. POST will attempt to take in a new config
|
||||
// /// and restart the program.
|
||||
// /// </summary>
|
||||
// void HandleApiConfig(OnHttpRequestArgs args)
|
||||
// {
|
||||
// var request = args.Request;
|
||||
// if (request.Header.RequestType == "GET")
|
||||
// {
|
||||
// if (File.Exists(ConfigPath))
|
||||
// {
|
||||
// Debug.Console(2, "Sending config:{0}", ConfigPath);
|
||||
// args.Response.Header.ContentType = EssentialsHttpServer.GetContentType(new FileInfo(ConfigPath).Extension);
|
||||
// args.Response.ContentStream = new FileStream(ConfigPath, FileMode.Open, FileAccess.Read);
|
||||
// }
|
||||
// }
|
||||
// else if (request.Header.RequestType == "POST")
|
||||
// {
|
||||
// Debug.Console(2, "Post type: '{0}'", request.Header.ContentType);
|
||||
|
||||
// // Make sure we're receiving at least good json
|
||||
// Debug.Console(1, "Receving new config");
|
||||
// if (GetContentStringJson(args) == null)
|
||||
// return;
|
||||
|
||||
// //---------------------------- try to move these into common method
|
||||
// // Move current file aside
|
||||
// var bakPath = ConfigPath + ".bak";
|
||||
// if (File.Exists(bakPath))
|
||||
// File.Delete(bakPath);
|
||||
// File.Move(ConfigPath, bakPath);
|
||||
|
||||
// // Write the file
|
||||
// using (FileStream fs = File.Open(ConfigPath, FileMode.OpenOrCreate))
|
||||
// using (StreamWriter sw = new StreamWriter(fs))
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// sw.Write(args.Request.ContentString);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// string err = string.Format("Error writing received config file:\r{0}", e);
|
||||
// CrestronConsole.PrintLine(err);
|
||||
// ErrorLog.Warn(err);
|
||||
// // Put file back
|
||||
// File.Move(ConfigPath + ".bak", ConfigPath);
|
||||
// args.Response.Code = 500;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // If client says "yeah, restart" and has a good token
|
||||
// // Restart program
|
||||
// string consoleResponse = null;
|
||||
// var restart = CrestronConsole.SendControlSystemCommand("progreset -p:" +
|
||||
// InitialParametersClass.ApplicationNumber, ref consoleResponse);
|
||||
// if (!restart) Debug.Console(0, "CAN'T DO THAT YO: {0}", consoleResponse);
|
||||
// }
|
||||
// }
|
||||
|
||||
// void HandleApiPresetsList(OnHttpRequestArgs args)
|
||||
// {
|
||||
// var listPath = PresetsPathPrefix + args.Request.Path.Remove(0, 17);
|
||||
// Debug.Console(2, "Checking for preset list '{0}'", listPath);
|
||||
|
||||
// if (args.Request.Header.RequestType == "GET")
|
||||
// {
|
||||
// if (File.Exists(listPath))
|
||||
// {
|
||||
// Debug.Console(2, "Sending presets file:{0}", listPath);
|
||||
// args.Response.Header.ContentType = EssentialsHttpServer.GetContentType(new FileInfo(listPath).Extension);
|
||||
// args.Response.ContentStream = new FileStream(listPath, FileMode.Open, FileAccess.Read);
|
||||
// }
|
||||
// }
|
||||
// else if (args.Request.Header.RequestType == "POST")
|
||||
// {
|
||||
// // Make sure we're receiving at least good json
|
||||
// Debug.Console(1, "Receving new presets");
|
||||
// if (GetContentStringJson(args) == null)
|
||||
// return;
|
||||
|
||||
// //---------------------------- try to move these into common method
|
||||
// // Move current file aside
|
||||
// var bakPath = listPath + ".new";
|
||||
// Debug.Console(2, "Moving presets file to {0}", bakPath);
|
||||
// if(File.Exists(bakPath))
|
||||
// File.Delete(bakPath);
|
||||
// File.Move(listPath, bakPath);
|
||||
|
||||
// Debug.Console(2, "Writing new file");
|
||||
// // Write the file
|
||||
// using (FileStream fs = File.OpenWrite(listPath))
|
||||
// using (StreamWriter sw = new StreamWriter(fs))
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// Debug.Console(2, "Writing {1}, {0} bytes", args.Request.ContentString.Length, listPath);
|
||||
// sw.Write(args.Request.ContentString);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// string err = string.Format("Error writing received presets file:\r{0}", e);
|
||||
// CrestronConsole.PrintLine(err);
|
||||
// ErrorLog.Warn(err);
|
||||
// // Put file back
|
||||
// File.Move(listPath + ".bak", listPath);
|
||||
// args.Response.Code = 500;
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// void HandleApiGetPresetsLists(HttpServerRequest request, HttpServerResponse response)
|
||||
// {
|
||||
// if (request.Header.RequestType != "GET")
|
||||
// {
|
||||
// response.Code = 404; // This should be a 405 with an allow header
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (Directory.Exists(PresetsPathPrefix))
|
||||
// {
|
||||
// //CrestronConsole.PrintLine("Parsing presets directory");
|
||||
// List<string> files = Directory.GetFiles(PresetsPathPrefix, "*.json")
|
||||
// .ToList().Select(f => Path.GetFileName(f)).ToList();
|
||||
// if (files.Count > 0)
|
||||
// files.Sort();
|
||||
// var json = JsonConvert.SerializeObject(files);
|
||||
// response.Header.ContentType = "application/json";
|
||||
// response.ContentString = json;
|
||||
// }
|
||||
|
||||
// // //CrestronConsole.PrintLine("Found {0} files", files.Count);
|
||||
// // JObject jo = new JObject();
|
||||
// // JArray ja = new JArray();
|
||||
|
||||
// // foreach (var filename in files)
|
||||
// // {
|
||||
// // try
|
||||
// // {
|
||||
// // using (StreamReader sr = new StreamReader(filename))
|
||||
// // {
|
||||
// // JObject tempJo = JObject.Parse(sr.ReadToEnd());
|
||||
// // if (tempJo.Value<string>("content").Equals("presetsList"))
|
||||
// // {
|
||||
// // var jItem = new JObject(); // make a new object
|
||||
// // jItem.Add("Name", tempJo["name"]);
|
||||
// // jItem.Add("File", filename);
|
||||
// // jItem.Add("Url", Uri.EscapeUriString(new Uri(
|
||||
// // filename.Replace("\\html", "")
|
||||
// // .Replace("\\HTML", "")
|
||||
// // .Replace('\\', '/'), UriKind.Relative).ToString()));
|
||||
// // ja.Add(jItem); // add to array
|
||||
// // }
|
||||
// // else
|
||||
// // CrestronConsole.PrintLine("Cannot use presets file '{0}'", filename);
|
||||
// // }
|
||||
// // }
|
||||
// // catch
|
||||
// // {
|
||||
// // // ignore failures - maybe delete them
|
||||
// // CrestronConsole.PrintLine("Unable to read presets file '{0}'", filename);
|
||||
// // }
|
||||
// // }
|
||||
// // jo.Add("PresetChannelLists", ja);
|
||||
// // //CrestronConsole.PrintLine(jo.ToString());
|
||||
// // response.Header.ContentType = "application/json";
|
||||
// // response.ContentString = jo.ToString();
|
||||
// //}
|
||||
// //else
|
||||
// // CrestronConsole.PrintLine("No presets files in directory");
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// Simply does what it says
|
||||
// /// </summary>
|
||||
// JObject GetContentStringJson(OnHttpRequestArgs args)
|
||||
// {
|
||||
// //var content = args.Request.ContentString;
|
||||
// //Debug.Console(1, "{0}", content);
|
||||
|
||||
// try
|
||||
// {
|
||||
// // just see if it parses properly
|
||||
// return JObject.Parse(args.Request.ContentString);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// string err = string.Format("JSON Error reading config file:\r{0}", e);
|
||||
// CrestronConsole.PrintLine(err);
|
||||
// ErrorLog.Warn(err);
|
||||
// args.Response.Code = 400; // Bad request
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,354 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.Fusion;
|
||||
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common;
|
||||
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||
|
||||
namespace PepperDash.Essentials.Fusion
|
||||
{
|
||||
public class EssentialsHuddleVtc1FusionController : EssentialsHuddleSpaceFusionSystemControllerBase
|
||||
{
|
||||
BooleanSigData CodecIsInCall;
|
||||
|
||||
public EssentialsHuddleVtc1FusionController(EssentialsHuddleVtc1Room room, uint ipId)
|
||||
: base(room, ipId)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called in base class constructor before RVI and GUID files are built
|
||||
/// </summary>
|
||||
protected override void ExecuteCustomSteps()
|
||||
{
|
||||
SetUpCodec();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a static asset for the codec and maps the joins to the main room symbol
|
||||
/// </summary>
|
||||
void SetUpCodec()
|
||||
{
|
||||
try
|
||||
{
|
||||
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
|
||||
|
||||
if (codec == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot link codec to Fusion because codec is null");
|
||||
return;
|
||||
}
|
||||
|
||||
codec.UsageTracker = new UsageTracking(codec);
|
||||
codec.UsageTracker.UsageIsTracked = true;
|
||||
codec.UsageTracker.DeviceUsageEnded += UsageTracker_DeviceUsageEnded;
|
||||
|
||||
var codecPowerOnAction = new Action<bool>(b => { if (!b) codec.StandbyDeactivate(); });
|
||||
var codecPowerOffAction = new Action<bool>(b => { if (!b) codec.StandbyActivate(); });
|
||||
|
||||
// Map FusionRoom Attributes:
|
||||
|
||||
// Codec volume
|
||||
var codecVolume = FusionRoom.CreateOffsetUshortSig(50, "Volume - Fader01", eSigIoMask.InputOutputSig);
|
||||
codecVolume.OutputSig.UserObject = new Action<ushort>(b => (codec as IBasicVolumeWithFeedback).SetVolume(b));
|
||||
(codec as IBasicVolumeWithFeedback).VolumeLevelFeedback.LinkInputSig(codecVolume.InputSig);
|
||||
|
||||
// In Call Status
|
||||
CodecIsInCall = FusionRoom.CreateOffsetBoolSig(69, "Conf - VC 1 In Call", eSigIoMask.InputSigOnly);
|
||||
codec.CallStatusChange += new EventHandler<PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
||||
|
||||
// Online status
|
||||
if (codec is ICommunicationMonitor)
|
||||
{
|
||||
var c = codec as ICommunicationMonitor;
|
||||
var codecOnline = FusionRoom.CreateOffsetBoolSig(122, "Online - VC 1", eSigIoMask.InputSigOnly);
|
||||
codecOnline.InputSig.BoolValue = c.CommunicationMonitor.Status == MonitorStatus.IsOk;
|
||||
c.CommunicationMonitor.StatusChange += (o, a) =>
|
||||
{
|
||||
codecOnline.InputSig.BoolValue = a.Status == MonitorStatus.IsOk;
|
||||
};
|
||||
Debug.Console(0, this, "Linking '{0}' communication monitor to Fusion '{1}'", codec.Key, "Online - VC 1");
|
||||
}
|
||||
|
||||
// Codec IP Address
|
||||
bool codecHasIpInfo = false;
|
||||
var codecComm = codec.Communication;
|
||||
|
||||
string codecIpAddress = string.Empty;
|
||||
int codecIpPort = 0;
|
||||
|
||||
StringSigData codecIpAddressSig;
|
||||
StringSigData codecIpPortSig;
|
||||
|
||||
if(codecComm is GenericSshClient)
|
||||
{
|
||||
codecIpAddress = (codecComm as GenericSshClient).Hostname;
|
||||
codecIpPort = (codecComm as GenericSshClient).Port;
|
||||
codecHasIpInfo = true;
|
||||
}
|
||||
else if (codecComm is GenericTcpIpClient)
|
||||
{
|
||||
codecIpAddress = (codecComm as GenericTcpIpClient).Hostname;
|
||||
codecIpPort = (codecComm as GenericTcpIpClient).Port;
|
||||
codecHasIpInfo = true;
|
||||
}
|
||||
|
||||
if (codecHasIpInfo)
|
||||
{
|
||||
codecIpAddressSig = FusionRoom.CreateOffsetStringSig(121, "IP Address - VC", eSigIoMask.InputSigOnly);
|
||||
codecIpAddressSig.InputSig.StringValue = codecIpAddress;
|
||||
|
||||
codecIpPortSig = FusionRoom.CreateOffsetStringSig(150, "IP Port - VC", eSigIoMask.InputSigOnly);
|
||||
codecIpPortSig.InputSig.StringValue = codecIpPort.ToString();
|
||||
}
|
||||
|
||||
var tempAsset = new FusionAsset();
|
||||
|
||||
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(c => c.Key.Equals(codec.Key));
|
||||
|
||||
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
|
||||
{
|
||||
tempAsset = FusionStaticAssets[deviceConfig.Uid];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new asset
|
||||
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), codec.Name, "Codec", "");
|
||||
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
|
||||
}
|
||||
|
||||
var codecAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
|
||||
codecAsset.PowerOn.OutputSig.UserObject = codecPowerOnAction;
|
||||
codecAsset.PowerOff.OutputSig.UserObject = codecPowerOffAction;
|
||||
codec.StandbyIsOnFeedback.LinkComplementInputSig(codecAsset.PowerOn.InputSig);
|
||||
|
||||
// TODO: Map relevant attributes on asset symbol
|
||||
|
||||
codecAsset.TrySetMakeModel(codec);
|
||||
codecAsset.TryLinkAssetErrorToCommunication(codec);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "Error setting up codec in Fusion: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
void codec_CallStatusChange(object sender, PepperDash.Essentials.Devices.Common.Codec.CodecCallStatusItemChangeEventArgs e)
|
||||
{
|
||||
var codec = (Room as EssentialsHuddleVtc1Room).VideoCodec;
|
||||
|
||||
CodecIsInCall.InputSig.BoolValue = codec.IsInCall;
|
||||
}
|
||||
|
||||
// These methods are overridden because they access the room class which is of a different type
|
||||
|
||||
protected override void CreateSymbolAndBasicSigs(uint ipId)
|
||||
{
|
||||
Debug.Console(1, this, "Creating Fusion Room symbol with GUID: {0}", RoomGuid);
|
||||
|
||||
FusionRoom = new FusionRoom(ipId, Global.ControlSystem, Room.Name, RoomGuid);
|
||||
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.Use();
|
||||
FusionRoom.ExtenderFusionRoomDataReservedSigs.Use();
|
||||
|
||||
FusionRoom.Register();
|
||||
|
||||
FusionRoom.FusionStateChange += FusionRoom_FusionStateChange;
|
||||
|
||||
FusionRoom.ExtenderRoomViewSchedulingDataReservedSigs.DeviceExtenderSigChange += FusionRoomSchedule_DeviceExtenderSigChange;
|
||||
FusionRoom.ExtenderFusionRoomDataReservedSigs.DeviceExtenderSigChange += ExtenderFusionRoomDataReservedSigs_DeviceExtenderSigChange;
|
||||
FusionRoom.OnlineStatusChange += FusionRoom_OnlineStatusChange;
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(RequestFullRoomSchedule, "FusReqRoomSchedule", "Requests schedule of the room for the next 24 hours", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(ModifyMeetingEndTimeConsoleHelper, "FusReqRoomSchMod", "Ends or extends a meeting by the specified time", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(CreateAsHocMeeting, "FusCreateMeeting", "Creates and Ad Hoc meeting for on hour or until the next meeting", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
// Room to fusion room
|
||||
Room.OnFeedback.LinkInputSig(FusionRoom.SystemPowerOn.InputSig);
|
||||
|
||||
// Moved to
|
||||
CurrentRoomSourceNameSig = FusionRoom.CreateOffsetStringSig(84, "Display 1 - Current Source", eSigIoMask.InputSigOnly);
|
||||
// Don't think we need to get current status of this as nothing should be alive yet.
|
||||
(Room as EssentialsHuddleVtc1Room).CurrentSingleSourceChange += Room_CurrentSourceInfoChange;
|
||||
|
||||
|
||||
FusionRoom.SystemPowerOn.OutputSig.SetSigFalseAction((Room as EssentialsHuddleVtc1Room).PowerOnToDefaultOrLastSource);
|
||||
FusionRoom.SystemPowerOff.OutputSig.SetSigFalseAction(() => (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"));
|
||||
// NO!! room.RoomIsOn.LinkComplementInputSig(FusionRoom.SystemPowerOff.InputSig);
|
||||
FusionRoom.ErrorMessage.InputSig.StringValue =
|
||||
"3: 7 Errors: This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;This is a really long error message;";
|
||||
|
||||
GetProcessorEthernetValues();
|
||||
|
||||
GetSystemInfo();
|
||||
|
||||
GetProcessorInfo();
|
||||
|
||||
CrestronEnvironment.EthernetEventHandler += CrestronEnvironment_EthernetEventHandler;
|
||||
}
|
||||
|
||||
protected override void SetUpSources()
|
||||
{
|
||||
// Sources
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey((Room as EssentialsHuddleVtc1Room).SourceListKey);
|
||||
if (dict != null)
|
||||
{
|
||||
// NEW PROCESS:
|
||||
// Make these lists and insert the fusion attributes by iterating these
|
||||
var setTopBoxes = dict.Where(d => d.Value.SourceDevice is ISetTopBoxControls);
|
||||
uint i = 1;
|
||||
foreach (var kvp in setTopBoxes)
|
||||
{
|
||||
TryAddRouteActionSigs("Display 1 - Source TV " + i, 188 + i, kvp.Key, kvp.Value.SourceDevice);
|
||||
i++;
|
||||
if (i > 5) // We only have five spots
|
||||
break;
|
||||
}
|
||||
|
||||
var discPlayers = dict.Where(d => d.Value.SourceDevice is IDiscPlayerControls);
|
||||
i = 1;
|
||||
foreach (var kvp in discPlayers)
|
||||
{
|
||||
TryAddRouteActionSigs("Display 1 - Source DVD " + i, 181 + i, kvp.Key, kvp.Value.SourceDevice);
|
||||
i++;
|
||||
if (i > 5) // We only have five spots
|
||||
break;
|
||||
}
|
||||
|
||||
var laptops = dict.Where(d => d.Value.SourceDevice is Laptop);
|
||||
i = 1;
|
||||
foreach (var kvp in laptops)
|
||||
{
|
||||
TryAddRouteActionSigs("Display 1 - Source Laptop " + i, 166 + i, kvp.Key, kvp.Value.SourceDevice);
|
||||
i++;
|
||||
if (i > 10) // We only have ten spots???
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (var kvp in dict)
|
||||
{
|
||||
var usageDevice = kvp.Value.SourceDevice as IUsageTracking;
|
||||
|
||||
if (usageDevice != null)
|
||||
{
|
||||
usageDevice.UsageTracker = new UsageTracking(usageDevice as Device);
|
||||
usageDevice.UsageTracker.UsageIsTracked = true;
|
||||
usageDevice.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found for room '{1}'",
|
||||
(Room as EssentialsHuddleVtc1Room).SourceListKey, Room.Key);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SetUpDisplay()
|
||||
{
|
||||
try
|
||||
{
|
||||
//Setup Display Usage Monitoring
|
||||
|
||||
var displays = DeviceManager.AllDevices.Where(d => d is DisplayBase);
|
||||
|
||||
// Consider updating this in multiple display systems
|
||||
|
||||
foreach (DisplayBase display in displays)
|
||||
{
|
||||
display.UsageTracker = new UsageTracking(display);
|
||||
display.UsageTracker.UsageIsTracked = true;
|
||||
display.UsageTracker.DeviceUsageEnded += new EventHandler<DeviceUsageEventArgs>(UsageTracker_DeviceUsageEnded);
|
||||
}
|
||||
|
||||
var defaultDisplay = (Room as EssentialsHuddleVtc1Room).DefaultDisplay as DisplayBase;
|
||||
if (defaultDisplay == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot link null display to Fusion because default display is null");
|
||||
return;
|
||||
}
|
||||
|
||||
var dispPowerOnAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOn(); });
|
||||
var dispPowerOffAction = new Action<bool>(b => { if (!b) defaultDisplay.PowerOff(); });
|
||||
|
||||
// Display to fusion room sigs
|
||||
FusionRoom.DisplayPowerOn.OutputSig.UserObject = dispPowerOnAction;
|
||||
FusionRoom.DisplayPowerOff.OutputSig.UserObject = dispPowerOffAction;
|
||||
defaultDisplay.PowerIsOnFeedback.LinkInputSig(FusionRoom.DisplayPowerOn.InputSig);
|
||||
if (defaultDisplay is IDisplayUsage)
|
||||
(defaultDisplay as IDisplayUsage).LampHours.LinkInputSig(FusionRoom.DisplayUsage.InputSig);
|
||||
|
||||
|
||||
|
||||
MapDisplayToRoomJoins(1, 158, defaultDisplay);
|
||||
|
||||
|
||||
var deviceConfig = ConfigReader.ConfigObject.Devices.FirstOrDefault(d => d.Key.Equals(defaultDisplay.Key));
|
||||
|
||||
//Check for existing asset in GUIDs collection
|
||||
|
||||
var tempAsset = new FusionAsset();
|
||||
|
||||
if (FusionStaticAssets.ContainsKey(deviceConfig.Uid))
|
||||
{
|
||||
tempAsset = FusionStaticAssets[deviceConfig.Uid];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a new asset
|
||||
tempAsset = new FusionAsset(FusionRoomGuids.GetNextAvailableAssetNumber(FusionRoom), defaultDisplay.Name, "Display", "");
|
||||
FusionStaticAssets.Add(deviceConfig.Uid, tempAsset);
|
||||
}
|
||||
|
||||
var dispAsset = FusionRoom.CreateStaticAsset(tempAsset.SlotNumber, tempAsset.Name, "Display", tempAsset.InstanceId);
|
||||
dispAsset.PowerOn.OutputSig.UserObject = dispPowerOnAction;
|
||||
dispAsset.PowerOff.OutputSig.UserObject = dispPowerOffAction;
|
||||
defaultDisplay.PowerIsOnFeedback.LinkInputSig(dispAsset.PowerOn.InputSig);
|
||||
// NO!! display.PowerIsOn.LinkComplementInputSig(dispAsset.PowerOff.InputSig);
|
||||
// Use extension methods
|
||||
dispAsset.TrySetMakeModel(defaultDisplay);
|
||||
dispAsset.TryLinkAssetErrorToCommunication(defaultDisplay);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "Error setting up display in Fusion: {0}", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected override void MapDisplayToRoomJoins(int displayIndex, int joinOffset, DisplayBase display)
|
||||
{
|
||||
string displayName = string.Format("Display {0} - ", displayIndex);
|
||||
|
||||
|
||||
if (display == (Room as EssentialsHuddleVtc1Room).DefaultDisplay)
|
||||
{
|
||||
// Power on
|
||||
var defaultDisplayPowerOn = FusionRoom.CreateOffsetBoolSig((uint)joinOffset, displayName + "Power On", eSigIoMask.InputOutputSig);
|
||||
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOn(); });
|
||||
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
|
||||
|
||||
// Power Off
|
||||
var defaultDisplayPowerOff = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 1, displayName + "Power Off", eSigIoMask.InputOutputSig);
|
||||
defaultDisplayPowerOn.OutputSig.UserObject = new Action<bool>(b => { if (!b) display.PowerOff(); }); ;
|
||||
display.PowerIsOnFeedback.LinkInputSig(defaultDisplayPowerOn.InputSig);
|
||||
|
||||
// Current Source
|
||||
var defaultDisplaySourceNone = FusionRoom.CreateOffsetBoolSig((uint)joinOffset + 8, displayName + "Source None", eSigIoMask.InputOutputSig);
|
||||
defaultDisplaySourceNone.OutputSig.UserObject = new Action<bool>(b => { if (!b) (Room as EssentialsHuddleVtc1Room).RunRouteAction("roomOff"); }); ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
PepperDashEssentials/OTHER/Fusion/FusionEventHandlers.cs
Normal file
18
PepperDashEssentials/OTHER/Fusion/FusionEventHandlers.cs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Fusion
|
||||
{
|
||||
public class ScheduleChangeEventArgs : EventArgs
|
||||
{
|
||||
public RoomSchedule Schedule { get; set; }
|
||||
}
|
||||
|
||||
public class MeetingChangeEventArgs : EventArgs
|
||||
{
|
||||
public Event Meeting { get; set; }
|
||||
}
|
||||
}
|
||||
63
PepperDashEssentials/OTHER/Fusion/FusionProcessorQueries.cs
Normal file
63
PepperDashEssentials/OTHER/Fusion/FusionProcessorQueries.cs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Fusion
|
||||
{
|
||||
/// <summary>
|
||||
/// When created, runs progcomments on every slot and stores the program names in a list
|
||||
/// </summary>
|
||||
public class ProcessorProgReg
|
||||
{
|
||||
//public static Dictionary<int, ProcessorProgramItem> Programs { get; private set; }
|
||||
|
||||
public static Dictionary<int, ProcessorProgramItem> GetProcessorProgReg()
|
||||
{
|
||||
var programs = new Dictionary<int, ProcessorProgramItem>();
|
||||
for (int i = 1; i <= Global.ControlSystem.NumProgramsSupported; i++)
|
||||
{
|
||||
string response = null;
|
||||
var success = CrestronConsole.SendControlSystemCommand("progcomments:" + i, ref response);
|
||||
var item = new ProcessorProgramItem();
|
||||
if (!success)
|
||||
item.Name = "Error: PROGCOMMENTS failed";
|
||||
else
|
||||
{
|
||||
if (response.ToLower().Contains("bad or incomplete"))
|
||||
item.Name = "";
|
||||
else
|
||||
{
|
||||
var startPos = response.IndexOf("Program File");
|
||||
var colonPos = response.IndexOf(":", startPos) + 1;
|
||||
var endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos);
|
||||
item.Name = response.Substring(colonPos, endPos - colonPos).Trim();
|
||||
item.Exists = true;
|
||||
if (item.Name.Contains(".dll"))
|
||||
{
|
||||
startPos = response.IndexOf("Compiler Revision");
|
||||
colonPos = response.IndexOf(":", startPos) + 1;
|
||||
endPos = response.IndexOf(CrestronEnvironment.NewLine, colonPos);
|
||||
item.Name = item.Name + "_v" + response.Substring(colonPos, endPos - colonPos).Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
programs[i] = item;
|
||||
Debug.Console(1, "Program {0}: {1}", i, item.Name);
|
||||
}
|
||||
return programs;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in ProcessorProgReg
|
||||
/// </summary>
|
||||
public class ProcessorProgramItem
|
||||
{
|
||||
public bool Exists { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
499
PepperDashEssentials/OTHER/Fusion/FusionRviDataClasses.cs
Normal file
499
PepperDashEssentials/OTHER/Fusion/FusionRviDataClasses.cs
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.Fusion;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Fusion
|
||||
{
|
||||
// Helper Classes for GUIDs
|
||||
|
||||
/// <summary>
|
||||
/// Stores GUIDs to be written to a file in NVRAM
|
||||
/// </summary>
|
||||
public class FusionRoomGuids
|
||||
{
|
||||
public string RoomName { get; set; }
|
||||
public uint IpId { get; set; }
|
||||
public string RoomGuid { get; set; }
|
||||
public FusionOccupancySensorAsset OccupancyAsset { get; set; }
|
||||
public Dictionary<int, FusionAsset> StaticAssets { get; set; }
|
||||
|
||||
public FusionRoomGuids()
|
||||
{
|
||||
StaticAssets = new Dictionary<int, FusionAsset>();
|
||||
OccupancyAsset = new FusionOccupancySensorAsset();
|
||||
}
|
||||
|
||||
public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary<int, FusionAsset> staticAssets)
|
||||
{
|
||||
RoomName = roomName;
|
||||
IpId = ipId;
|
||||
RoomGuid = roomGuid;
|
||||
|
||||
StaticAssets = staticAssets;
|
||||
OccupancyAsset = new FusionOccupancySensorAsset();
|
||||
}
|
||||
|
||||
public FusionRoomGuids(string roomName, uint ipId, string roomGuid, Dictionary<int, FusionAsset> staticAssets, FusionOccupancySensorAsset occAsset)
|
||||
{
|
||||
RoomName = roomName;
|
||||
IpId = ipId;
|
||||
RoomGuid = roomGuid;
|
||||
|
||||
StaticAssets = staticAssets;
|
||||
OccupancyAsset = occAsset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new room GUID prefixed by the program slot number and NIC MAC address
|
||||
/// </summary>
|
||||
/// <param name="progSlot"></param>
|
||||
/// <param name="mac"></param>
|
||||
public string GenerateNewRoomGuid(uint progSlot, string mac)
|
||||
{
|
||||
Guid roomGuid = Guid.NewGuid();
|
||||
|
||||
return string.Format("{0}-{1}-{2}", progSlot, mac, roomGuid.ToString());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds an asset to the StaticAssets collection and returns the new asset
|
||||
/// </summary>
|
||||
/// <param name="room"></param>
|
||||
/// <param name="uid"></param>
|
||||
/// <param name="assetName"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <param name="instanceId"></param>
|
||||
/// <returns></returns>
|
||||
public FusionAsset AddStaticAsset(FusionRoom room, int uid, string assetName, string type, string instanceId)
|
||||
{
|
||||
var slotNum = GetNextAvailableAssetNumber(room);
|
||||
|
||||
Debug.Console(2, "Adding Fusion Asset: {0} of Type: {1} at Slot Number: {2} with GUID: {3}", assetName, type, slotNum, instanceId);
|
||||
|
||||
var tempAsset = new FusionAsset(slotNum, assetName, type, instanceId);
|
||||
|
||||
StaticAssets.Add(uid, tempAsset);
|
||||
|
||||
return tempAsset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the next available slot number in the Fusion UserConfigurableAssetDetails collection
|
||||
/// </summary>
|
||||
/// <param name="room"></param>
|
||||
/// <returns></returns>
|
||||
public static uint GetNextAvailableAssetNumber(FusionRoom room)
|
||||
{
|
||||
uint slotNum = 0;
|
||||
|
||||
foreach (var item in room.UserConfigurableAssetDetails)
|
||||
{
|
||||
if(item.Number > slotNum)
|
||||
slotNum = item.Number;
|
||||
}
|
||||
|
||||
if (slotNum < 5)
|
||||
{
|
||||
slotNum = 5;
|
||||
}
|
||||
else
|
||||
slotNum = slotNum + 1;
|
||||
|
||||
Debug.Console(2, "#Next available fusion asset number is: {0}", slotNum);
|
||||
|
||||
return slotNum;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class FusionOccupancySensorAsset
|
||||
{
|
||||
// SlotNumber fixed at 4
|
||||
|
||||
public uint SlotNumber { get { return 4; } }
|
||||
public string Name { get { return "Occupancy Sensor"; } }
|
||||
public eAssetType Type { get; set; }
|
||||
public string InstanceId { get; set; }
|
||||
|
||||
public FusionOccupancySensorAsset()
|
||||
{
|
||||
}
|
||||
|
||||
public FusionOccupancySensorAsset(eAssetType type)
|
||||
{
|
||||
Type = type;
|
||||
|
||||
InstanceId = Guid.NewGuid().ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public class FusionAsset
|
||||
{
|
||||
public uint SlotNumber { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string InstanceId { get;set; }
|
||||
|
||||
public FusionAsset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public FusionAsset(uint slotNum, string assetName, string type, string instanceId)
|
||||
{
|
||||
SlotNumber = slotNum;
|
||||
Name = assetName;
|
||||
Type = type;
|
||||
if (string.IsNullOrEmpty(instanceId))
|
||||
{
|
||||
InstanceId = Guid.NewGuid().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
InstanceId = instanceId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//***************************************************************************************************
|
||||
|
||||
public class RoomSchedule
|
||||
{
|
||||
public List<Event> Meetings { get; set; }
|
||||
|
||||
public RoomSchedule()
|
||||
{
|
||||
Meetings = new List<Event>();
|
||||
}
|
||||
}
|
||||
|
||||
//****************************************************************************************************
|
||||
// Helper Classes for XML API
|
||||
|
||||
/// <summary>
|
||||
/// Data needed to request the local time from the Fusion server
|
||||
/// </summary>
|
||||
public class LocalTimeRequest
|
||||
{
|
||||
public string RequestID { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All the data needed for a full schedule request in a room
|
||||
/// </summary>
|
||||
/// //[XmlRoot(ElementName = "RequestSchedule")]
|
||||
public class RequestSchedule
|
||||
{
|
||||
//[XmlElement(ElementName = "RequestID")]
|
||||
public string RequestID { get; set; }
|
||||
//[XmlElement(ElementName = "RoomID")]
|
||||
public string RoomID { get; set; }
|
||||
//[XmlElement(ElementName = "Start")]
|
||||
public DateTime Start { get; set; }
|
||||
//[XmlElement(ElementName = "HourSpan")]
|
||||
public double HourSpan { get; set; }
|
||||
|
||||
public RequestSchedule(string requestID, string roomID)
|
||||
{
|
||||
RequestID = requestID;
|
||||
RoomID = roomID;
|
||||
Start = DateTime.Now;
|
||||
HourSpan = 24;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//[XmlRoot(ElementName = "RequestAction")]
|
||||
public class RequestAction
|
||||
{
|
||||
//[XmlElement(ElementName = "RequestID")]
|
||||
public string RequestID { get; set; }
|
||||
//[XmlElement(ElementName = "RoomID")]
|
||||
public string RoomID { get; set; }
|
||||
//[XmlElement(ElementName = "ActionID")]
|
||||
public string ActionID { get; set; }
|
||||
//[XmlElement(ElementName = "Parameters")]
|
||||
public List<Parameter> Parameters { get; set; }
|
||||
|
||||
public RequestAction(string roomID, string actionID, List<Parameter> parameters)
|
||||
{
|
||||
RoomID = roomID;
|
||||
ActionID = actionID;
|
||||
Parameters = parameters;
|
||||
}
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "ActionResponse")]
|
||||
public class ActionResponse
|
||||
{
|
||||
//[XmlElement(ElementName = "RequestID")]
|
||||
public string RequestID { get; set; }
|
||||
//[XmlElement(ElementName = "ActionID")]
|
||||
public string ActionID { get; set; }
|
||||
//[XmlElement(ElementName = "Parameters")]
|
||||
public List<Parameter> Parameters { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Parameter")]
|
||||
public class Parameter
|
||||
{
|
||||
//[XmlAttribute(AttributeName = "ID")]
|
||||
public string ID { get; set; }
|
||||
//[XmlAttribute(AttributeName = "Value")]
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
////[XmlRoot(ElementName = "Parameters")]
|
||||
//public class Parameters
|
||||
//{
|
||||
// //[XmlElement(ElementName = "Parameter")]
|
||||
// public List<Parameter> Parameter { get; set; }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Data structure for a ScheduleResponse from Fusion
|
||||
/// </summary>
|
||||
/// //[XmlRoot(ElementName = "ScheduleResponse")]
|
||||
public class ScheduleResponse
|
||||
{
|
||||
//[XmlElement(ElementName = "RequestID")]
|
||||
public string RequestID { get; set; }
|
||||
//[XmlElement(ElementName = "RoomID")]
|
||||
public string RoomID { get; set; }
|
||||
//[XmlElement(ElementName = "RoomName")]
|
||||
public string RoomName { get; set; }
|
||||
//[XmlElement("Event")]
|
||||
public List<Event> Events { get; set; }
|
||||
|
||||
public ScheduleResponse()
|
||||
{
|
||||
Events = new List<Event>();
|
||||
}
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Event")]
|
||||
public class Event
|
||||
{
|
||||
//[XmlElement(ElementName = "MeetingID")]
|
||||
public string MeetingID { get; set; }
|
||||
//[XmlElement(ElementName = "RVMeetingID")]
|
||||
public string RVMeetingID { get; set; }
|
||||
//[XmlElement(ElementName = "Recurring")]
|
||||
public string Recurring { get; set; }
|
||||
//[XmlElement(ElementName = "InstanceID")]
|
||||
public string InstanceID { get; set; }
|
||||
//[XmlElement(ElementName = "dtStart")]
|
||||
public DateTime dtStart { get; set; }
|
||||
//[XmlElement(ElementName = "dtEnd")]
|
||||
public DateTime dtEnd { get; set; }
|
||||
//[XmlElement(ElementName = "Organizer")]
|
||||
public string Organizer { get; set; }
|
||||
//[XmlElement(ElementName = "Attendees")]
|
||||
public Attendees Attendees { get; set; }
|
||||
//[XmlElement(ElementName = "Resources")]
|
||||
public Resources Resources { get; set; }
|
||||
//[XmlElement(ElementName = "IsEvent")]
|
||||
public string IsEvent { get; set; }
|
||||
//[XmlElement(ElementName = "IsRoomViewMeeting")]
|
||||
public string IsRoomViewMeeting { get; set; }
|
||||
//[XmlElement(ElementName = "IsPrivate")]
|
||||
public string IsPrivate { get; set; }
|
||||
//[XmlElement(ElementName = "IsExchangePrivate")]
|
||||
public string IsExchangePrivate { get; set; }
|
||||
//[XmlElement(ElementName = "MeetingTypes")]
|
||||
public MeetingTypes MeetingTypes { get; set; }
|
||||
//[XmlElement(ElementName = "ParticipantCode")]
|
||||
public string ParticipantCode { get; set; }
|
||||
//[XmlElement(ElementName = "PhoneNo")]
|
||||
public string PhoneNo { get; set; }
|
||||
//[XmlElement(ElementName = "WelcomeMsg")]
|
||||
public string WelcomeMsg { get; set; }
|
||||
//[XmlElement(ElementName = "Subject")]
|
||||
public string Subject { get; set; }
|
||||
//[XmlElement(ElementName = "LiveMeeting")]
|
||||
public LiveMeeting LiveMeeting { get; set; }
|
||||
//[XmlElement(ElementName = "ShareDocPath")]
|
||||
public string ShareDocPath { get; set; }
|
||||
//[XmlElement(ElementName = "HaveAttendees")]
|
||||
public string HaveAttendees { get; set; }
|
||||
//[XmlElement(ElementName = "HaveResources")]
|
||||
public string HaveResources { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the duration of the meeting
|
||||
/// </summary>
|
||||
public string DurationInMinutes
|
||||
{
|
||||
get
|
||||
{
|
||||
string duration;
|
||||
|
||||
var timeSpan = dtEnd.Subtract(dtStart);
|
||||
int hours = timeSpan.Hours;
|
||||
double minutes = timeSpan.Minutes;
|
||||
double roundedMinutes = Math.Round(minutes);
|
||||
if (hours > 0)
|
||||
{
|
||||
duration = string.Format("{0} hours {1} minutes", hours, roundedMinutes);
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = string.Format("{0} minutes", roundedMinutes);
|
||||
}
|
||||
|
||||
return duration;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the remaining time in the meeting. Returns null if the meeting is not currently in progress.
|
||||
/// </summary>
|
||||
public string RemainingTime
|
||||
{
|
||||
get
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
|
||||
string remainingTime;
|
||||
|
||||
if (GetInProgress())
|
||||
{
|
||||
var timeSpan = dtEnd.Subtract(now);
|
||||
int hours = timeSpan.Hours;
|
||||
double minutes = timeSpan.Minutes;
|
||||
double roundedMinutes = Math.Round(minutes);
|
||||
if (hours > 0)
|
||||
{
|
||||
remainingTime = string.Format("{0} hours {1} minutes", hours, roundedMinutes);
|
||||
}
|
||||
else
|
||||
{
|
||||
remainingTime = string.Format("{0} minutes", roundedMinutes);
|
||||
}
|
||||
|
||||
return remainingTime;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the meeting is in progress
|
||||
/// </summary>
|
||||
public bool isInProgress
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetInProgress();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the meeting is in progress
|
||||
/// </summary>
|
||||
/// <returns>Returns true if in progress</returns>
|
||||
bool GetInProgress()
|
||||
{
|
||||
var now = DateTime.Now;
|
||||
|
||||
if (now > dtStart && now < dtEnd)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Resources")]
|
||||
public class Resources
|
||||
{
|
||||
//[XmlElement(ElementName = "Rooms")]
|
||||
public Rooms Rooms { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Rooms")]
|
||||
public class Rooms
|
||||
{
|
||||
//[XmlElement(ElementName = "Room")]
|
||||
public List<Room> Room { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Room")]
|
||||
public class Room
|
||||
{
|
||||
//[XmlElement(ElementName = "Name")]
|
||||
public string Name { get; set; }
|
||||
//[XmlElement(ElementName = "ID")]
|
||||
public string ID { get; set; }
|
||||
//[XmlElement(ElementName = "MPType")]
|
||||
public string MPType { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Attendees")]
|
||||
public class Attendees
|
||||
{
|
||||
//[XmlElement(ElementName = "Required")]
|
||||
public Required Required { get; set; }
|
||||
//[XmlElement(ElementName = "Optional")]
|
||||
public Optional Optional { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Required")]
|
||||
public class Required
|
||||
{
|
||||
//[XmlElement(ElementName = "Attendee")]
|
||||
public List<string> Attendee { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "Optional")]
|
||||
public class Optional
|
||||
{
|
||||
//[XmlElement(ElementName = "Attendee")]
|
||||
public List<string> Attendee { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "MeetingType")]
|
||||
public class MeetingType
|
||||
{
|
||||
//[XmlAttribute(AttributeName = "ID")]
|
||||
public string ID { get; set; }
|
||||
//[XmlAttribute(AttributeName = "Value")]
|
||||
public string Value { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "MeetingTypes")]
|
||||
public class MeetingTypes
|
||||
{
|
||||
//[XmlElement(ElementName = "MeetingType")]
|
||||
public List<MeetingType> MeetingType { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "LiveMeeting")]
|
||||
public class LiveMeeting
|
||||
{
|
||||
//[XmlElement(ElementName = "URL")]
|
||||
public string URL { get; set; }
|
||||
//[XmlElement(ElementName = "ID")]
|
||||
public string ID { get; set; }
|
||||
//[XmlElement(ElementName = "Key")]
|
||||
public string Key { get; set; }
|
||||
//[XmlElement(ElementName = "Subject")]
|
||||
public string Subject { get; set; }
|
||||
}
|
||||
|
||||
//[XmlRoot(ElementName = "LiveMeetingURL")]
|
||||
public class LiveMeetingURL
|
||||
{
|
||||
//[XmlElement(ElementName = "LiveMeeting")]
|
||||
public LiveMeeting LiveMeeting { get; set; }
|
||||
}
|
||||
}
|
||||
1415
PepperDashEssentials/OTHER/Fusion/FusionSystemController.cs.orig
Normal file
1415
PepperDashEssentials/OTHER/Fusion/FusionSystemController.cs.orig
Normal file
File diff suppressed because it is too large
Load diff
19857
PepperDashEssentials/PepperDash Essentials TSW-760.sgd
Normal file
19857
PepperDashEssentials/PepperDash Essentials TSW-760.sgd
Normal file
File diff suppressed because it is too large
Load diff
20901
PepperDashEssentials/PepperDash Essentials iPad.sgd
Normal file
20901
PepperDashEssentials/PepperDash Essentials iPad.sgd
Normal file
File diff suppressed because it is too large
Load diff
227
PepperDashEssentials/PepperDashEssentials.csproj
Normal file
227
PepperDashEssentials/PepperDashEssentials.csproj
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{1BED5BA9-88C4-4365-9362-6F4B128071D3}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>PepperDash.Essentials</RootNamespace>
|
||||
<AssemblyName>PepperDashEssentials</AssemblyName>
|
||||
<ProjectTypeGuids>{0B4745B0-194B-4BB6-8E21-E9057CA92230};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<PlatformFamilyName>WindowsCE</PlatformFamilyName>
|
||||
<PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID>
|
||||
<OSVersion>5.0</OSVersion>
|
||||
<DeployDirSuffix>SmartDeviceProject1</DeployDirSuffix>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<NativePlatformName>Windows CE</NativePlatformName>
|
||||
<FormFactorID>
|
||||
</FormFactorID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\</OutputPath>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<NoStdLib>true</NoStdLib>
|
||||
<NoConfig>true</NoConfig>
|
||||
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Crestron.SimplSharpPro.DeviceSupport, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DeviceSupport.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.DM, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.DM.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.EthernetCommunications, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.EthernetCommunications.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.Fusion, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Fusion.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.Remotes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Remotes.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Crestron.SimplSharpPro.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="mscorlib" />
|
||||
<Reference Include="PepperDash_Core, Version=1.0.3.27452, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\essentials-framework\references\PepperDash_Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="PepperDash_Essentials_DM, Version=1.0.0.19343, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\essentials-framework\Essentials DM\Essentials_DM\bin\PepperDash_Essentials_DM.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpPro, Version=1.5.2.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpPro.exe</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Audio\EssentialsVolumeLevelConfig.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Builders\TPConfig.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Configuration.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\ConfigurationHelpers.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\ConfigTieLine.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\CommFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\RemoteFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\DeviceMonitorFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\DmFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\TouchpanelFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\PcFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\REMOVE DiscPlayerFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\MAYBE SetTopBoxFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\DisplayFactory.cs" />
|
||||
<Compile Include="Configuration ORIGINAL\Factories\FactoryHelper.cs" />
|
||||
<Compile Include="Config\ConfigReader.cs" />
|
||||
<Compile Include="Config\EssentialsConfig.cs" />
|
||||
<Compile Include="Factory\DeviceFactory.cs" />
|
||||
<Compile Include="Devices\Amplifier.cs" />
|
||||
<Compile Include="Devices\DiscPlayer\OppoExtendedBdp.cs" />
|
||||
<Compile Include="Devices\NUMERIC AppleTV.cs" />
|
||||
<Compile Include="ControlSystem.cs" />
|
||||
<Compile Include="Factory\UiDeviceFactory.cs" />
|
||||
<Compile Include="OTHER\Fusion\EssentialsHuddleVtc1FusionController.cs" />
|
||||
<Compile Include="OTHER\Fusion\FusionEventHandlers.cs" />
|
||||
<Compile Include="OTHER\Fusion\FusionProcessorQueries.cs" />
|
||||
<Compile Include="OTHER\Fusion\FusionRviDataClasses.cs" />
|
||||
<Compile Include="REMOVE EssentialsApp.cs" />
|
||||
<Compile Include="OTHER\Fusion\EssentialsHuddleSpaceFusionSystemControllerBase.cs" />
|
||||
<Compile Include="HttpApiHandler.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Room\Config\DDVC01RoomPropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsPresentationPropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
|
||||
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
|
||||
<Compile Include="Room\Cotija\CotijaConfig.cs" />
|
||||
<Compile Include="Room\Cotija\CotijaDdvc01DeviceBridge.cs" />
|
||||
<Compile Include="Room\Cotija\Interfaces.cs" />
|
||||
<Compile Include="Room\Cotija\RoomBridges\CotijaBridgeBase.cs" />
|
||||
<Compile Include="Room\Cotija\RoomBridges\CotijaDdvc01RoomBridge.cs" />
|
||||
<Compile Include="Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IChannelExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IColorExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDvrExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\INumericExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IPowerExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs" />
|
||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\ITransportExtensions.cs" />
|
||||
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
|
||||
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
|
||||
<Compile Include="Room\Types\EssentialsPresentationRoom.cs" />
|
||||
<Compile Include="Room\Types\EssentialsRoomBase.cs" />
|
||||
<Compile Include="Room\Config\EssentialsRoomConfig.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\PageControllers\DevicePageControllerBase.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\PageControllers\PageControllerLaptop.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\PageControllers\PageControllerLargeDvd.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\PageControllers\PageControllerLargeSetTopBoxGeneric.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\PageControllers\LargeTouchpanelControllerBase.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\Panels\SmartGraphicsTouchpanelControllerBase.cs" />
|
||||
<Compile Include="UIDrivers\Environment Drivers\EssentialsLightingDriver.cs" />
|
||||
<Compile Include="UIDrivers\Environment Drivers\EssentialsEnvironmentDriver.cs" />
|
||||
<Compile Include="UIDrivers\Environment Drivers\EssentialsShadeDriver.cs" />
|
||||
<Compile Include="UIDrivers\Essentials\EssentialsHeaderDriver.cs" />
|
||||
<Compile Include="UIDrivers\SigInterlock.cs" />
|
||||
<Compile Include="UIDrivers\EssentialsHuddleVTC\EssentialsHuddlePresentationUiDriver.cs" />
|
||||
<Compile Include="UIDrivers\EssentialsHuddle\EssentialsHuddleTechPageDriver.cs" />
|
||||
<Compile Include="UI\HttpLogoServer.cs" />
|
||||
<Compile Include="UI\SmartObjectHeaderButtonList.cs" />
|
||||
<Compile Include="UI\SubpageReferenceListCallStagingItem.cs" />
|
||||
<Compile Include="UIDrivers\VC\EssentialsVideoCodecUiDriver.cs" />
|
||||
<Compile Include="UIDrivers\JoinedSigInterlock.cs" />
|
||||
<Compile Include="UIDrivers\EssentialsHuddleVTC\EssentialsHuddleVtc1PanelAvFunctionsDriver.cs" />
|
||||
<Compile Include="UIDrivers\VolumeAndSourceChangeArgs.cs" />
|
||||
<Compile Include="UI\JoinConstants\UISmartObjectJoin.cs" />
|
||||
<Compile Include="UI\JoinConstants\UIStringlJoin.cs" />
|
||||
<Compile Include="UI\JoinConstants\UIUshortJoin.cs" />
|
||||
<Compile Include="UIDrivers\DualDisplayRouting.cs" />
|
||||
<Compile Include="UIDrivers\Essentials\EssentialsPresentationPanelAvFunctionsDriver.cs" />
|
||||
<Compile Include="UIDrivers\Page Drivers\SingleSubpageModalDriver.cs" />
|
||||
<Compile Include="UIDrivers\Essentials\EssentialsPanelMainInterfaceDriver.cs" />
|
||||
<Compile Include="UIDrivers\enums and base.cs" />
|
||||
<Compile Include="UIDrivers\EssentialsHuddle\EssentialsHuddlePanelAvFunctionsDriver.cs" />
|
||||
<Compile Include="UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs" />
|
||||
<Compile Include="UIDrivers\SmartObjectRoomsList.cs" />
|
||||
<Compile Include="UI\JoinConstants\UIBoolJoin.cs" />
|
||||
<Compile Include="Room\Cotija\CotijaSystemController.cs" />
|
||||
<Compile Include="UI\DualDisplaySourceSRLController.cs" />
|
||||
<Compile Include="UI\SubpageReferenceListActivityItem.cs" />
|
||||
<Compile Include="UI\CrestronTouchpanelPropertiesConfig.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\Panels\REMOVE UiCue.cs" />
|
||||
<Compile Include="FOR REFERENCE UI\SRL\SourceListSubpageReferenceList.cs" />
|
||||
<Compile Include="Room\Types\EssentialsHuddleSpaceRoom.cs" />
|
||||
<Compile Include="UI\EssentialsTouchpanelController.cs" />
|
||||
<Compile Include="UI\SubpageReferenceListSourceItem.cs" />
|
||||
<None Include="app.config" />
|
||||
<None Include="Properties\ControlSystem.cfg" />
|
||||
<EmbeddedResource Include="SGD\PepperDash Essentials iPad.sgd" />
|
||||
<EmbeddedResource Include="SGD\PepperDash Essentials TSW-560.sgd" />
|
||||
<EmbeddedResource Include="SGD\PepperDash Essentials TSW-760.sgd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\essentials-framework\Essentials Core\PepperDashEssentialsBase\PepperDash_Essentials_Core.csproj">
|
||||
<Project>{A49AD6C8-FC0A-4CC0-9089-DFB4CF92D2B5}</Project>
|
||||
<Name>PepperDash_Essentials_Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\essentials-framework\Essentials Devices Common\Essentials Devices Common\Essentials Devices Common.csproj">
|
||||
<Project>{892B761C-E479-44CE-BD74-243E9214AF13}</Project>
|
||||
<Name>Essentials Devices Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>rem S# Pro preparation will execute after these operations</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
8
PepperDashEssentials/Properties/AssemblyInfo.cs
Normal file
8
PepperDashEssentials/Properties/AssemblyInfo.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("PepperDashEssentials")]
|
||||
[assembly: AssemblyCompany("PepperDash Technology Corp")]
|
||||
[assembly: AssemblyProduct("PepperDashEssentials")]
|
||||
[assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")]
|
||||
[assembly: AssemblyVersion("1.2.0.*")]
|
||||
|
||||
12
PepperDashEssentials/Properties/AssemblyInfo.cs.orig
Normal file
12
PepperDashEssentials/Properties/AssemblyInfo.cs.orig
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyTitle("PepperDashEssentials")]
|
||||
[assembly: AssemblyCompany("PepperDash Technology Corp")]
|
||||
[assembly: AssemblyProduct("PepperDashEssentials")]
|
||||
[assembly: AssemblyCopyright("Copyright © PepperDash Technology Corp 2017")]
|
||||
<<<<<<< HEAD
|
||||
[assembly: AssemblyVersion("1.1.8.*")]
|
||||
=======
|
||||
[assembly: AssemblyVersion("1.3.0.*")]
|
||||
|
||||
>>>>>>> feature/ecs-684
|
||||
7
PepperDashEssentials/Properties/ControlSystem.cfg
Normal file
7
PepperDashEssentials/Properties/ControlSystem.cfg
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ControlSystem>
|
||||
<Name>Test RMC3</Name>
|
||||
<Address>auto 192.168.1.40</Address>
|
||||
<ProgramSlot>Program01</ProgramSlot>
|
||||
<Storage>Internal Flash</Storage>
|
||||
</ControlSystem>
|
||||
69
PepperDashEssentials/REMOVE EssentialsApp.cs
Normal file
69
PepperDashEssentials/REMOVE EssentialsApp.cs
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharp.CrestronIO;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
//using Crestron.SimplSharpPro.CrestronThread;
|
||||
//using Crestron.SimplSharpPro.Diagnostics;
|
||||
//using Crestron.SimplSharpPro.EthernetCommunication;
|
||||
//using Crestron.SimplSharpPro.UI;
|
||||
|
||||
//using Crestron.SimplSharpPro.DM;
|
||||
//using Crestron.SimplSharpPro.DM.Cards;
|
||||
//using Crestron.SimplSharpPro.DM.Endpoints.Transmitters;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
//using PepperDash.Essentials.Core.Devices;
|
||||
////using PepperDash.Essentials.Core.Devices.Dm;
|
||||
|
||||
//using PepperDash.Essentials.Displays;
|
||||
|
||||
////using PepperDash.Essentials.Core.Http;
|
||||
//using PepperDash.Core;
|
||||
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class EssentialsApp
|
||||
// {
|
||||
// public string ConfigPath { get; set; }
|
||||
|
||||
// public Dictionary<string, Room> Rooms { get; private set; }
|
||||
|
||||
// //EssentialsHttpApiHandler ApiHandler; // MOVE ???????????????????
|
||||
|
||||
// public EssentialsApp(CrestronControlSystem cs)
|
||||
// {
|
||||
// // Use a fake license manager for now
|
||||
// Global.LicenseManager = PepperDash.Essentials.License.MockEssentialsLicenseManager.Manager;
|
||||
|
||||
|
||||
// // ---------------------------------- Make this configurable
|
||||
// //var server = Global.HttpConfigServer;
|
||||
// //server.Start(8081, "HttpConfigServer");
|
||||
// //ConfigPath = string.Format(@"\NVRAM\Program{0}\EssentialsConfiguration.json",
|
||||
// // InitialParametersClass.ApplicationNumber);
|
||||
// //ApiHandler = new EssentialsHttpApiHandler(server, ConfigPath, @"\HTML\presets\lists\");
|
||||
|
||||
// Debug.Console(0, "\r\r--------------------CONFIG BEGIN--------------------\r");
|
||||
// Configuration.Initialize(cs);
|
||||
// Configuration.ReadConfiguration(ConfigPath);
|
||||
// Debug.Console(0, "\r--------------------CONFIG END----------------------\r\r");
|
||||
// }
|
||||
// }
|
||||
|
||||
// public class ResponseToken
|
||||
// {
|
||||
// public string Token { get; private set; }
|
||||
// public DateTime Expires { get; private set; }
|
||||
// public bool IsExpired { get { return Expires < DateTime.Now; } }
|
||||
|
||||
// public ResponseToken(int timeoutMinutes)
|
||||
// {
|
||||
// Expires = DateTime.Now.AddMinutes(timeoutMinutes);
|
||||
// Token = Guid.NewGuid().ToString();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,16 @@
|
|||
<ProgramInfo>
|
||||
<RequiredInfo>
|
||||
<FriendlyName>PepperDashEssentials</FriendlyName>
|
||||
<SystemName>PepperDashEssentialsBase</SystemName>
|
||||
<EntryPoint>PepperDashEssentialsBase</EntryPoint>
|
||||
<MinFirmwareVersion>1.009.0029</MinFirmwareVersion>
|
||||
<ProgramTool>SIMPL# Plugin</ProgramTool>
|
||||
<DesignToolId>5</DesignToolId>
|
||||
<ProgramToolId>5</ProgramToolId>
|
||||
<ArchiveName />
|
||||
</RequiredInfo>
|
||||
<OptionalInfo>
|
||||
<CompiledOn>1/8/2016 3:03:22 PM</CompiledOn>
|
||||
<CompilerRev>1.0.0.27100</CompilerRev>
|
||||
</OptionalInfo>
|
||||
</ProgramInfo>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,18 @@
|
|||
MainAssembly=PepperDashEssentialsBase.dll:5d68a993ab03b4b88d0f95478188a439
|
||||
MainAssemblyMinFirmwareVersion=1.009.0029
|
||||
ü
|
||||
DependencySource=Crestron.SimplSharpPro.DeviceSupport.dll:caae4b4259aaf619059f0ae34473bfd2
|
||||
DependencyPath=PepperDashEssentialsBase.cplz:Crestron.SimplSharpPro.DeviceSupport.dll
|
||||
DependencyMainAssembly=Crestron.SimplSharpPro.DeviceSupport.dll:caae4b4259aaf619059f0ae34473bfd2
|
||||
ü
|
||||
DependencySource=Crestron.SimplSharpPro.DM.dll:bdf5acfa80cc3bb87f21deb891128b1d
|
||||
DependencyPath=PepperDashEssentialsBase.cplz:Crestron.SimplSharpPro.DM.dll
|
||||
DependencyMainAssembly=Crestron.SimplSharpPro.DM.dll:bdf5acfa80cc3bb87f21deb891128b1d
|
||||
ü
|
||||
DependencySource=Crestron.SimplSharpPro.EthernetCommunications.dll:36e663497195140ee6f1b4ebc53f5ea7
|
||||
DependencyPath=PepperDashEssentialsBase.cplz:Crestron.SimplSharpPro.EthernetCommunications.dll
|
||||
DependencyMainAssembly=Crestron.SimplSharpPro.EthernetCommunications.dll:36e663497195140ee6f1b4ebc53f5ea7
|
||||
ü
|
||||
DependencySource=Crestron.SimplSharpPro.UI.dll:089312a0cb0b4537072d4eb234e71e0e
|
||||
DependencyPath=PepperDashEssentialsBase.cplz:Crestron.SimplSharpPro.UI.dll
|
||||
DependencyMainAssembly=Crestron.SimplSharpPro.UI.dll:089312a0cb0b4537072d4eb234e71e0e
|
||||
Binary file not shown.
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Config
|
||||
{
|
||||
public class DDVC01RoomPropertiesConfig : EssentialsHuddleVtc1PropertiesConfig
|
||||
{
|
||||
[JsonProperty("roomPhoneNumber")]
|
||||
public string RoomPhoneNumber { get; set; }
|
||||
[JsonProperty("roomURI")]
|
||||
public string RoomURI { get; set; }
|
||||
[JsonProperty("speedDials")]
|
||||
public List<DDVC01SpeedDial> SpeedDials { get; set; }
|
||||
[JsonProperty("volumeSliderNames")]
|
||||
public List<string> VolumeSliderNames { get; set; }
|
||||
}
|
||||
|
||||
public class DDVC01SpeedDial
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
[JsonProperty("number")]
|
||||
public string Number { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Config
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class EssentialsHuddleRoomPropertiesConfig : EssentialsRoomPropertiesConfig
|
||||
{
|
||||
public string DefaultDisplayKey { get; set; }
|
||||
public string DefaultAudioKey { get; set; }
|
||||
public string SourceListKey { get; set; }
|
||||
public string DefaultSourceItem { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Config
|
||||
{
|
||||
|
||||
public class EssentialsHuddleVtc1PropertiesConfig : EssentialsRoomPropertiesConfig
|
||||
{
|
||||
[JsonProperty("defaultDisplayKey")]
|
||||
public string DefaultDisplayKey { get; set; }
|
||||
[JsonProperty("defaultAudioKey")]
|
||||
public string DefaultAudioKey { get; set; }
|
||||
[JsonProperty("sourceListKey")]
|
||||
public string SourceListKey { get; set; }
|
||||
[JsonProperty("defaultSourceItem")]
|
||||
public string DefaultSourceItem { get; set; }
|
||||
[JsonProperty("videoCodecKey")]
|
||||
public string VideoCodecKey { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
334
PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
Normal file
334
PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Config
|
||||
{
|
||||
public class EssentialsRoomConfig : DeviceConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a room object from this config data
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Device GetRoomObject()
|
||||
{
|
||||
var typeName = Type.ToLower();
|
||||
if (typeName == "huddle")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<EssentialsHuddleRoomPropertiesConfig>
|
||||
(this.Properties.ToString());
|
||||
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;
|
||||
huddle.DefaultVolume = (ushort)(props.Volumes.Master.Level * 65535 / 100);
|
||||
return huddle;
|
||||
}
|
||||
else if (typeName == "presentation")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<EssentialsPresentationRoomPropertiesConfig>
|
||||
(this.Properties.ToString());
|
||||
var displaysDict = new Dictionary<uint, IRoutingSinkNoSwitching>();
|
||||
uint i = 1;
|
||||
foreach (var dispKey in props.DisplayKeys) // read in the ordered displays list
|
||||
{
|
||||
var disp = DeviceManager.GetDeviceForKey(dispKey) as IRoutingSinkWithSwitching;
|
||||
displaysDict.Add(i++, disp);
|
||||
}
|
||||
|
||||
// Get the master volume control
|
||||
IBasicVolumeWithFeedback masterVolumeControlDev = props.Volumes.Master.GetDevice();
|
||||
|
||||
|
||||
var presRoom = new EssentialsPresentationRoom(Key, Name, displaysDict, masterVolumeControlDev, props);
|
||||
return presRoom;
|
||||
}
|
||||
else if (typeName == "huddlevtc1")
|
||||
{
|
||||
var props = JsonConvert.DeserializeObject<EssentialsHuddleVtc1PropertiesConfig>
|
||||
(this.Properties.ToString());
|
||||
var disp = DeviceManager.GetDeviceForKey(props.DefaultDisplayKey) as IRoutingSinkWithSwitching;
|
||||
|
||||
var codec = DeviceManager.GetDeviceForKey(props.VideoCodecKey) as
|
||||
PepperDash.Essentials.Devices.Common.VideoCodec.VideoCodecBase;
|
||||
|
||||
var rm = new EssentialsHuddleVtc1Room(Key, Name, disp, codec, codec, props);
|
||||
// Add Occupancy object from config
|
||||
|
||||
if (props.Occupancy != null)
|
||||
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;
|
||||
rm.DefaultVolume = (ushort)(props.Volumes.Master.Level * 65535 / 100);
|
||||
|
||||
rm.MicrophonePrivacy = GetMicrophonePrivacy(props, rm); // Get Microphone Privacy object, if any
|
||||
|
||||
rm.Emergency = GetEmergency(props, rm); // Get emergency object, if any
|
||||
|
||||
return rm;
|
||||
}
|
||||
else if (typeName == "ddvc01Bridge")
|
||||
{
|
||||
return new Device(Key, Name); // placeholder device that does nothing.
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets and operating, standalone emergegncy object that can be plugged into a room.
|
||||
/// Returns null if there is no emergency defined
|
||||
/// </summary>
|
||||
EssentialsRoomEmergencyBase GetEmergency(EssentialsRoomPropertiesConfig props, EssentialsRoomBase 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>
|
||||
PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController GetMicrophonePrivacy(
|
||||
EssentialsRoomPropertiesConfig props, EssentialsHuddleVtc1Room room)
|
||||
{
|
||||
var microphonePrivacy = props.MicrophonePrivacy;
|
||||
if (microphonePrivacy == null)
|
||||
{
|
||||
Debug.Console(0, "ERROR: 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
|
||||
PepperDash.Essentials.Devices.Common.Microphones.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
|
||||
room.OnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (room.OnFeedback.BoolValue)
|
||||
mP.EnableLeds = true;
|
||||
else
|
||||
mP.EnableLeds = false;
|
||||
};
|
||||
|
||||
mP.EnableLeds = room.OnFeedback.BoolValue;
|
||||
}
|
||||
else if (behaviour == "trackcallstate")
|
||||
{
|
||||
// Tie LED enable to room power state
|
||||
room.InCallFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (room.InCallFeedback.BoolValue)
|
||||
mP.EnableLeds = true;
|
||||
else
|
||||
mP.EnableLeds = false;
|
||||
};
|
||||
|
||||
mP.EnableLeds = room.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; }
|
||||
|
||||
[JsonProperty("environment")]
|
||||
public EssentialsEnvironmentPropertiesConfig Environment { get; set; }
|
||||
|
||||
[JsonProperty("logo")]
|
||||
public EssentialsLogoPropertiesConfig Logo { 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("zeroVolumeWhenSwtichingVolumeDevices")]
|
||||
public bool ZeroVolumeWhenSwtichingVolumeDevices { 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 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 GetUrl()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents occupancy sensor(s) setup for a room
|
||||
/// </summary>
|
||||
public class EssentialsRoomOccSensorConfig
|
||||
{
|
||||
[JsonProperty("deviceKey")]
|
||||
public string DeviceKey { get; set; }
|
||||
|
||||
[JsonProperty("timoutMinutes")]
|
||||
public int TimoutMinutes { get; set; }
|
||||
}
|
||||
|
||||
public class EssentialsRoomTechConfig
|
||||
{
|
||||
[JsonProperty("password")]
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
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; }
|
||||
|
||||
}
|
||||
}
|
||||
33
PepperDashEssentials/Room/Cotija/CotijaConfig.cs
Normal file
33
PepperDashEssentials/Room/Cotija/CotijaConfig.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CotijaConfig
|
||||
{
|
||||
[JsonProperty("serverUrl")]
|
||||
public string ServerUrl { get; set; }
|
||||
|
||||
[JsonProperty("clientAppUrl")]
|
||||
public string ClientAppUrl { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class CotijaDdvc01RoomBridgePropertiesConfig
|
||||
{
|
||||
[JsonProperty("eiscId")]
|
||||
public string EiscId { get; set; }
|
||||
}
|
||||
}
|
||||
148
PepperDashEssentials/Room/Cotija/CotijaDdvc01DeviceBridge.cs
Normal file
148
PepperDashEssentials/Room/Cotija/CotijaDdvc01DeviceBridge.cs
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a generic device connection through to and EISC for DDVC01
|
||||
/// </summary>
|
||||
public class CotijaDdvc01DeviceBridge : Device, IChannel, INumericKeypad
|
||||
{
|
||||
/// <summary>
|
||||
/// EISC used to talk to Simpl
|
||||
/// </summary>
|
||||
ThreeSeriesTcpIpEthernetIntersystemCommunications EISC;
|
||||
|
||||
public CotijaDdvc01DeviceBridge(string key, string name, ThreeSeriesTcpIpEthernetIntersystemCommunications eisc)
|
||||
: base(key, name)
|
||||
{
|
||||
EISC = eisc;
|
||||
}
|
||||
|
||||
|
||||
#region IChannel Members
|
||||
|
||||
public void ChannelUp(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void ChannelDown(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void LastChannel(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Guide(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Info(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Exit(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INumericKeypad Members
|
||||
|
||||
public void Digit0(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit1(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit2(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit3(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit4(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit5(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit6(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit7(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit8(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public void Digit9(bool pressRelease)
|
||||
{
|
||||
EISC.SetBool(1111, pressRelease);
|
||||
}
|
||||
|
||||
public bool HasKeypadAccessoryButton1
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public string KeypadAccessoryButton1Label
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public void KeypadAccessoryButton1(bool pressRelease)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool HasKeypadAccessoryButton2
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public string KeypadAccessoryButton2Label
|
||||
{
|
||||
get { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
public void KeypadAccessoryButton2(bool pressRelease)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
690
PepperDashEssentials/Room/Cotija/CotijaSystemController.cs
Normal file
690
PepperDashEssentials/Room/Cotija/CotijaSystemController.cs
Normal file
|
|
@ -0,0 +1,690 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using Crestron.SimplSharp.CrestronWebSocketClient;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaSystemController : Device
|
||||
{
|
||||
WebSocketClient WSClient;
|
||||
|
||||
/// <summary>
|
||||
/// Prevents post operations from stomping on each other and getting lost
|
||||
/// </summary>
|
||||
CEvent PostLockEvent = new CEvent(true, true);
|
||||
|
||||
CEvent RegisterLockEvent = new CEvent(true, true);
|
||||
|
||||
public CotijaConfig Config { get; private set; }
|
||||
|
||||
Dictionary<string, Object> ActionDictionary = new Dictionary<string, Object>(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
Dictionary<string, CTimer> PushedActions = new Dictionary<string, CTimer>();
|
||||
|
||||
CTimer ServerHeartbeatCheckTimer;
|
||||
|
||||
long ServerHeartbeatInterval = 20000;
|
||||
|
||||
CTimer ServerReconnectTimer;
|
||||
|
||||
long ServerReconnectInterval = 5000;
|
||||
|
||||
string SystemUuid;
|
||||
|
||||
List<CotijaBridgeBase> RoomBridges = new List<CotijaBridgeBase>();
|
||||
|
||||
long ButtonHeartbeatInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Used for tracking HTTP debugging
|
||||
/// </summary>
|
||||
bool HttpDebugEnabled;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="config"></param>
|
||||
public CotijaSystemController(string key, string name, CotijaConfig config) : base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
Debug.Console(0, this, "Mobile UI controller initializing for server:{0}", config.ServerUrl);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
|
||||
"mobileauth", "Authorizes system to talk to cotija server", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => ShowInfo(),
|
||||
"mobileinfo", "Shows information for current mobile control session", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => {
|
||||
s = s.Trim();
|
||||
if(!string.IsNullOrEmpty(s))
|
||||
{
|
||||
HttpDebugEnabled = (s.Trim() != "0");
|
||||
}
|
||||
CrestronConsole.ConsoleCommandResponse("HTTP Debug {0}", HttpDebugEnabled ? "Enabled" : "Disabled");
|
||||
},
|
||||
"mobilehttpdebug", "1 enables more verbose HTTP response debugging", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
|
||||
"mobilehttprequest", "Tests an HTTP get to URL given", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an action to the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The path of the API command</param>
|
||||
/// <param name="action">The action to be triggered by the commmand</param>
|
||||
public void AddAction(string key, object action)
|
||||
{
|
||||
if (!ActionDictionary.ContainsKey(key))
|
||||
{
|
||||
ActionDictionary.Add(key, action);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary.", key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an action from the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public void RemoveAction(string key)
|
||||
{
|
||||
if (ActionDictionary.ContainsKey(key))
|
||||
ActionDictionary.Remove(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
public void AddBridge(CotijaBridgeBase bridge)
|
||||
{
|
||||
RoomBridges.Add(bridge);
|
||||
var b = bridge as IDelayedConfiguration;
|
||||
if (b != null)
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge with delayed configuration");
|
||||
b.ConfigurationIsReady += new EventHandler<EventArgs>(bridge_ConfigurationIsReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge and sending configuration");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void bridge_ConfigurationIsReady(object sender, EventArgs e)
|
||||
{
|
||||
Debug.Console(1, this, "Bridge ready. Registering");
|
||||
// send the configuration object to the server
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ReconnectToServerTimerCallback(object o)
|
||||
{
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies system connection with servers
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void AuthorizeSystem(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system");
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}/api/system/grantcode/{1}/{2}", Config.ServerUrl, code, SystemUuid);
|
||||
Debug.Console(0, this, "Authorizing to: {0}", url);
|
||||
|
||||
if (string.IsNullOrEmpty(Config.ServerUrl))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Config URL address is not set. Check portal configuration");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
req.Url.Parse(url);
|
||||
new HttpClient().DispatchAsync(req, (r, e) =>
|
||||
{
|
||||
CheckHttpDebug(r, e);
|
||||
if (e == HTTP_CALLBACK_ERROR.COMPLETED)
|
||||
{
|
||||
if (r.Code == 200)
|
||||
{
|
||||
Debug.Console(0, "System authorized, sending config.");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
else if (r.Code == 404)
|
||||
{
|
||||
if (r.ContentString.Contains("codeNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, code not found for system UUID {0}", SystemUuid);
|
||||
}
|
||||
else if (r.ContentString.Contains("uuidNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, uuid {0} not found. Check Essentials configuration is correct",
|
||||
SystemUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Debug.Console(0, this, "Error {0} in authorizing system", e);
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "Error in authorizing: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumps info in response to console command.
|
||||
/// </summary>
|
||||
void ShowInfo()
|
||||
{
|
||||
var url = Config != null ? Config.ServerUrl : "No config";
|
||||
string name;
|
||||
string code;
|
||||
if (RoomBridges != null && RoomBridges.Count > 0)
|
||||
{
|
||||
name = RoomBridges[0].RoomName;
|
||||
code = RoomBridges[0].UserCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "No config";
|
||||
code = "Not available";
|
||||
}
|
||||
var conn = WSClient == null ? "No client" : (WSClient.Connected ? "Yes" : "No");
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(@"Mobile Control Information:
|
||||
Server address: {0}
|
||||
System Name: {1}
|
||||
System UUID: {2}
|
||||
System User code: {3}
|
||||
Connected?: {4}", url, name, SystemUuid,
|
||||
code, conn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the room with the server
|
||||
/// </summary>
|
||||
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
|
||||
void RegisterSystemToServer()
|
||||
{
|
||||
var ready = RegisterLockEvent.Wait(20000);
|
||||
if (!ready)
|
||||
{
|
||||
Debug.Console(1, this, "RegisterSystemToServer failed to enter after 20 seconds. Ignoring");
|
||||
return;
|
||||
}
|
||||
RegisterLockEvent.Reset();
|
||||
|
||||
try
|
||||
{
|
||||
var confObject = ConfigReader.ConfigObject;
|
||||
confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
confObject.Info.RuntimeInfo.OsVersion = Crestron.SimplSharp.CrestronEnvironment.OSVersion.Firmware;
|
||||
|
||||
string postBody = JsonConvert.SerializeObject(confObject);
|
||||
SystemUuid = confObject.SystemUuid;
|
||||
|
||||
if (string.IsNullOrEmpty(postBody))
|
||||
{
|
||||
Debug.Console(1, this, "ERROR: Config body is empty. Cannot register with server.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var regClient = new HttpClient();
|
||||
regClient.Verbose = true;
|
||||
regClient.KeepAlive = true;
|
||||
|
||||
string url = string.Format("http://{0}/api/system/join/{1}", Config.ServerUrl, SystemUuid);
|
||||
Debug.Console(1, this, "Joining server at {0}", url);
|
||||
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
request.Url.Parse(url);
|
||||
request.RequestType = RequestType.Post;
|
||||
request.Header.SetHeaderValue("Content-Type", "application/json");
|
||||
request.ContentString = postBody;
|
||||
|
||||
var err = regClient.DispatchAsync(request, RegistrationConnectionCallback);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Initilizing Room: {0}", e);
|
||||
RegisterLockEvent.Set();
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message to the server from a room
|
||||
/// </summary>
|
||||
/// <param name="room">room from which the message originates</param>
|
||||
/// <param name="o">object to be serialized and sent in post body</param>
|
||||
public void SendMessageToServer(JObject o)
|
||||
{
|
||||
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
Debug.Console(1, this, "Message TX: {0}", message);
|
||||
var messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
|
||||
WSClient.Send(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
//WSClient.SendAsync(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the SSE Client and stops the heartbeat timer
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void DisconnectStreamClient(string command)
|
||||
{
|
||||
//if(SseClient != null)
|
||||
// SseClient.Disconnect();
|
||||
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
WSClient.Disconnect();
|
||||
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The callback that fires when we get a response from our registration attempt
|
||||
/// </summary>
|
||||
/// <param name="resp"></param>
|
||||
/// <param name="err"></param>
|
||||
void RegistrationConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err)
|
||||
{
|
||||
CheckHttpDebug(resp, err);
|
||||
Debug.Console(1, this, "RegistrationConnectionCallback: {0}", err);
|
||||
try
|
||||
{
|
||||
if (resp != null && resp.Code == 200)
|
||||
{
|
||||
if(ServerReconnectTimer != null)
|
||||
{
|
||||
ServerReconnectTimer.Stop();
|
||||
ServerReconnectTimer = null;
|
||||
}
|
||||
|
||||
// Success here!
|
||||
ConnectStreamClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resp != null)
|
||||
Debug.Console(1, this, "Response from server: {0}\n{1}", resp.Code, err);
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Null response received from server.");
|
||||
}
|
||||
StartReconnectTimer();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "Error Initializing Stream Client: {0}", e);
|
||||
StartReconnectTimer();
|
||||
}
|
||||
RegisterLockEvent.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
|
||||
/// </summary>
|
||||
/// <param name="o">For CTimer callback. Not used</param>
|
||||
void HeartbeatExpiredTimerCallback(object o)
|
||||
{
|
||||
Debug.Console(1, this, "Heartbeat Timer Expired.");
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void StartReconnectTimer()
|
||||
{
|
||||
// Start the reconnect timer
|
||||
if (ServerReconnectTimer == null)
|
||||
{
|
||||
ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, null, ServerReconnectInterval, ServerReconnectInterval);
|
||||
Debug.Console(1, this, "Reconnect Timer Started.");
|
||||
}
|
||||
ServerReconnectTimer.Reset(ServerReconnectInterval, ServerReconnectInterval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void ResetOrStartHearbeatTimer()
|
||||
{
|
||||
if (ServerHeartbeatCheckTimer == null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
|
||||
Debug.Console(1, this, "Heartbeat Timer Started.");
|
||||
}
|
||||
|
||||
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Connects the SSE Client
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ConnectStreamClient()
|
||||
{
|
||||
Debug.Console(0, this, "Initializing Stream client to server.");
|
||||
|
||||
if (WSClient == null)
|
||||
{
|
||||
WSClient = new WebSocketClient();
|
||||
}
|
||||
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
|
||||
WSClient.Connect();
|
||||
Debug.Console(0, this, "Websocket connected");
|
||||
WSClient.ReceiveCallBack = WebsocketReceiveCallback;
|
||||
//WSClient.SendCallBack = WebsocketSendCallback;
|
||||
WSClient.ReceiveAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets reconnect timer and updates usercode
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
void HandleHeartBeat(JToken content)
|
||||
{
|
||||
var code = content["userCode"];
|
||||
if(code != null)
|
||||
{
|
||||
foreach (var b in RoomBridges)
|
||||
{
|
||||
b.SetUserCode(code.Value<string>());
|
||||
}
|
||||
}
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs debug info when enabled
|
||||
/// </summary>
|
||||
/// <param name="req"></param>
|
||||
/// <param name="r"></param>
|
||||
/// <param name="e"></param>
|
||||
void CheckHttpDebug(HttpClientResponse r, HTTP_CALLBACK_ERROR e)
|
||||
{
|
||||
if (HttpDebugEnabled)
|
||||
{
|
||||
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
||||
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl.ToString());
|
||||
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
|
||||
Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
|
||||
Debug.Console(0, this, "HTTP Response content: \r{0}", r.ContentString);
|
||||
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="opcode"></param>
|
||||
/// <param name="err"></param>
|
||||
int WebsocketReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
|
||||
WebSocketClient.WEBSOCKET_RESULT_CODES err)
|
||||
{
|
||||
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
||||
if(rx.Length > 0)
|
||||
ParseStreamRx(rx);
|
||||
WSClient.ReceiveAsync();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback to catch possible errors in sending via the websocket
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
int WebsocketSendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
|
||||
{
|
||||
Debug.Console(1, this, "SendCallback result: {0}", result);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ParseStreamRx(string message)
|
||||
{
|
||||
if(string.IsNullOrEmpty(message))
|
||||
return;
|
||||
|
||||
Debug.Console(1, this, "Message RX: '{0}'", message);
|
||||
try
|
||||
{
|
||||
var messageObj = JObject.Parse(message);
|
||||
|
||||
var type = messageObj["type"].Value<string>();
|
||||
|
||||
if (type == "hello")
|
||||
{
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
else if (type == "/system/heartbeat")
|
||||
{
|
||||
HandleHeartBeat(messageObj["content"]);
|
||||
}
|
||||
else if (type == "close")
|
||||
{
|
||||
WSClient.Disconnect();
|
||||
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
// Start the reconnect timer
|
||||
StartReconnectTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check path against Action dictionary
|
||||
if (ActionDictionary.ContainsKey(type))
|
||||
{
|
||||
var action = ActionDictionary[type];
|
||||
|
||||
if (action is Action)
|
||||
{
|
||||
(action as Action)();
|
||||
}
|
||||
else if (action is PressAndHoldAction)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
// Look for a button press event
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
switch (stateString)
|
||||
{
|
||||
case "true":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions.Add(type, new CTimer(o =>
|
||||
{
|
||||
(action as PressAndHoldAction)(false);
|
||||
PushedActions.Remove(type);
|
||||
}, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval));
|
||||
}
|
||||
// Maybe add an else to reset the timer
|
||||
break;
|
||||
}
|
||||
case "held":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "false":
|
||||
{
|
||||
if (PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Stop();
|
||||
PushedActions.Remove(type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(action as PressAndHoldAction)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<bool>)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
(action as Action<bool>)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<ushort>)
|
||||
{
|
||||
(action as Action<ushort>)(messageObj["content"]["value"].Value<ushort>());
|
||||
}
|
||||
else if (action is Action<string>)
|
||||
{
|
||||
(action as Action<string>)(messageObj["content"]["value"].Value<string>());
|
||||
}
|
||||
else if (action is Action<SourceSelectMessageContent>)
|
||||
{
|
||||
(action as Action<SourceSelectMessageContent>)(messageObj["content"]
|
||||
.ToObject<SourceSelectMessageContent>());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
//Debug.Console(1, "SseMessageLengthBeforeFailureCount: {0}", SseMessageLengthBeforeFailureCount);
|
||||
//SseMessageLengthBeforeFailureCount = 0;
|
||||
Debug.Console(1, this, "Unable to parse message: {0}", err);
|
||||
}
|
||||
}
|
||||
|
||||
void TestHttpRequest(string s)
|
||||
{
|
||||
{
|
||||
s = s.Trim();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
var tokens = s.Split(' ');
|
||||
if (tokens.Length < 2)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Too few paramaters\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var url = tokens[1];
|
||||
if (tokens[0].ToLower() == "get")
|
||||
{
|
||||
var resp = new HttpClient().Get(url);
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
else if (tokens[0].ToLower() == "post")
|
||||
{
|
||||
var resp = new HttpClient().Post(url, new byte[] { });
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Only get or post supported\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
}
|
||||
}
|
||||
catch (HttpException e)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Exception in request:\r");
|
||||
CrestronConsole.ConsoleCommandResponse("Response URL: {0}\r", e.Response.ResponseUrl);
|
||||
CrestronConsole.ConsoleCommandResponse("Response Error Code: {0}\r", e.Response.Code);
|
||||
CrestronConsole.ConsoleCommandResponse("Response body: {0}\r", e.Response.ContentString);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTestHttpRequestUsage()
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Usage: mobilehttprequest:N get/post url\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
694
PepperDashEssentials/Room/Cotija/CotijaSystemController.cs.orig
Normal file
694
PepperDashEssentials/Room/Cotija/CotijaSystemController.cs.orig
Normal file
|
|
@ -0,0 +1,694 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharp.Reflection;
|
||||
using Crestron.SimplSharpPro.CrestronThread;
|
||||
using Crestron.SimplSharp.CrestronWebSocketClient;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaSystemController : Device
|
||||
{
|
||||
WebSocketClient WSClient;
|
||||
|
||||
/// <summary>
|
||||
/// Prevents post operations from stomping on each other and getting lost
|
||||
/// </summary>
|
||||
CEvent PostLockEvent = new CEvent(true, true);
|
||||
|
||||
CEvent RegisterLockEvent = new CEvent(true, true);
|
||||
|
||||
public CotijaConfig Config { get; private set; }
|
||||
|
||||
Dictionary<string, Object> ActionDictionary = new Dictionary<string, Object>(StringComparer.InvariantCultureIgnoreCase);
|
||||
|
||||
Dictionary<string, CTimer> PushedActions = new Dictionary<string, CTimer>();
|
||||
|
||||
CTimer ServerHeartbeatCheckTimer;
|
||||
|
||||
long ServerHeartbeatInterval = 20000;
|
||||
|
||||
CTimer ServerReconnectTimer;
|
||||
|
||||
long ServerReconnectInterval = 5000;
|
||||
|
||||
string SystemUuid;
|
||||
|
||||
List<CotijaBridgeBase> RoomBridges = new List<CotijaBridgeBase>();
|
||||
|
||||
long ButtonHeartbeatInterval = 1000;
|
||||
|
||||
/// <summary>
|
||||
/// Used for tracking HTTP debugging
|
||||
/// </summary>
|
||||
bool HttpDebugEnabled;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="config"></param>
|
||||
public CotijaSystemController(string key, string name, CotijaConfig config) : base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
Debug.Console(0, this, "Mobile UI controller initializing for server:{0}", config.ServerUrl);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
|
||||
"mobileauth", "Authorizes system to talk to cotija server", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => ShowInfo(),
|
||||
"mobileinfo", "Shows information for current mobile control session", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(s => {
|
||||
s = s.Trim();
|
||||
if(!string.IsNullOrEmpty(s))
|
||||
{
|
||||
HttpDebugEnabled = (s.Trim() != "0");
|
||||
}
|
||||
CrestronConsole.ConsoleCommandResponse("HTTP Debug {0}", HttpDebugEnabled ? "Enabled" : "Disabled");
|
||||
},
|
||||
"mobilehttpdebug", "1 enables more verbose HTTP response debugging", ConsoleAccessLevelEnum.AccessOperator);
|
||||
CrestronConsole.AddNewConsoleCommand(TestHttpRequest,
|
||||
"mobilehttprequest", "Tests an HTTP get to URL given", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an action to the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key">The path of the API command</param>
|
||||
/// <param name="action">The action to be triggered by the commmand</param>
|
||||
public void AddAction(string key, object action)
|
||||
{
|
||||
if (!ActionDictionary.ContainsKey(key))
|
||||
{
|
||||
ActionDictionary.Add(key, action);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Cannot add action with key '{0}' because key already exists in ActionDictionary.", key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an action from the dictionary
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public void RemoveAction(string key)
|
||||
{
|
||||
if (ActionDictionary.ContainsKey(key))
|
||||
ActionDictionary.Remove(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="bridge"></param>
|
||||
public void AddBridge(CotijaBridgeBase bridge)
|
||||
{
|
||||
RoomBridges.Add(bridge);
|
||||
var b = bridge as IDelayedConfiguration;
|
||||
if (b != null)
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge with delayed configuration");
|
||||
b.ConfigurationIsReady += new EventHandler<EventArgs>(bridge_ConfigurationIsReady);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "Adding room bridge and sending configuration");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void bridge_ConfigurationIsReady(object sender, EventArgs e)
|
||||
{
|
||||
Debug.Console(1, this, "Bridge ready. Registering");
|
||||
// send the configuration object to the server
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ReconnectToServerTimerCallback(object o)
|
||||
{
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies system connection with servers
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void AuthorizeSystem(string code)
|
||||
{
|
||||
if (string.IsNullOrEmpty(code))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Please enter a user code to authorize a system");
|
||||
return;
|
||||
}
|
||||
|
||||
var req = new HttpClientRequest();
|
||||
string url = string.Format("http://{0}/api/system/grantcode/{1}/{2}", Config.ServerUrl, code, SystemUuid);
|
||||
Debug.Console(0, this, "Authorizing to: {0}", url);
|
||||
|
||||
if (string.IsNullOrEmpty(Config.ServerUrl))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Config URL address is not set. Check portal configuration");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
req.Url.Parse(url);
|
||||
new HttpClient().DispatchAsync(req, (r, e) =>
|
||||
{
|
||||
CheckHttpDebug(r, e);
|
||||
if (e == HTTP_CALLBACK_ERROR.COMPLETED)
|
||||
{
|
||||
if (r.Code == 200)
|
||||
{
|
||||
Debug.Console(0, "System authorized, sending config.");
|
||||
RegisterSystemToServer();
|
||||
}
|
||||
else if (r.Code == 404)
|
||||
{
|
||||
if (r.ContentString.Contains("codeNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, code not found for system UUID {0}", SystemUuid);
|
||||
}
|
||||
else if (r.ContentString.Contains("uuidNotFound"))
|
||||
{
|
||||
Debug.Console(0, "Authorization failed, uuid {0} not found. Check Essentials configuration is correct",
|
||||
SystemUuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
Debug.Console(0, this, "Error {0} in authorizing system", e);
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "Error in authorizing: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumps info in response to console command.
|
||||
/// </summary>
|
||||
void ShowInfo()
|
||||
{
|
||||
var url = Config != null ? Config.ServerUrl : "No config";
|
||||
string name;
|
||||
string code;
|
||||
if (RoomBridges != null && RoomBridges.Count > 0)
|
||||
{
|
||||
name = RoomBridges[0].RoomName;
|
||||
code = RoomBridges[0].UserCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "No config";
|
||||
code = "Not available";
|
||||
}
|
||||
var conn = WSClient == null ? "No client" : (WSClient.Connected ? "Yes" : "No");
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(@"Mobile Control Information:
|
||||
Server address: {0}
|
||||
System Name: {1}
|
||||
System UUID: {2}
|
||||
System User code: {3}
|
||||
Connected?: {4}", url, name, SystemUuid,
|
||||
code, conn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the room with the server
|
||||
/// </summary>
|
||||
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
|
||||
void RegisterSystemToServer()
|
||||
{
|
||||
var ready = RegisterLockEvent.Wait(20000);
|
||||
if (!ready)
|
||||
{
|
||||
Debug.Console(1, this, "RegisterSystemToServer failed to enter after 20 seconds. Ignoring");
|
||||
return;
|
||||
}
|
||||
RegisterLockEvent.Reset();
|
||||
|
||||
try
|
||||
{
|
||||
var confObject = ConfigReader.ConfigObject;
|
||||
confObject.Info.RuntimeInfo.AppName = Assembly.GetExecutingAssembly().GetName().Name;
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
confObject.Info.RuntimeInfo.AssemblyVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
|
||||
confObject.Info.RuntimeInfo.OsVersion = Crestron.SimplSharp.CrestronEnvironment.OSVersion.Firmware;
|
||||
|
||||
string postBody = JsonConvert.SerializeObject(confObject);
|
||||
SystemUuid = confObject.SystemUuid;
|
||||
|
||||
if (string.IsNullOrEmpty(postBody))
|
||||
{
|
||||
Debug.Console(1, this, "ERROR: Config body is empty. Cannot register with server.");
|
||||
}
|
||||
else
|
||||
{
|
||||
var regClient = new HttpClient();
|
||||
regClient.Verbose = true;
|
||||
regClient.KeepAlive = true;
|
||||
|
||||
string url = string.Format("http://{0}/api/system/join/{1}", Config.ServerUrl, SystemUuid);
|
||||
Debug.Console(1, this, "Joining server at {0}", url);
|
||||
|
||||
HttpClientRequest request = new HttpClientRequest();
|
||||
request.Url.Parse(url);
|
||||
request.RequestType = RequestType.Post;
|
||||
request.Header.SetHeaderValue("Content-Type", "application/json");
|
||||
request.ContentString = postBody;
|
||||
|
||||
var err = regClient.DispatchAsync(request, RegistrationConnectionCallback);
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Initilizing Room: {0}", e);
|
||||
RegisterLockEvent.Set();
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a message to the server from a room
|
||||
/// </summary>
|
||||
/// <param name="room">room from which the message originates</param>
|
||||
/// <param name="o">object to be serialized and sent in post body</param>
|
||||
public void SendMessageToServer(JObject o)
|
||||
{
|
||||
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(o, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
Debug.Console(1, this, "Message TX: {0}", message);
|
||||
var messageBytes = System.Text.Encoding.UTF8.GetBytes(message);
|
||||
WSClient.Send(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
//WSClient.SendAsync(messageBytes, (uint)messageBytes.Length, WebSocketClient.WEBSOCKET_PACKET_TYPES.LWS_WS_OPCODE_07__TEXT_FRAME);
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
|
||||
>>>>>>> feature/ecs-684
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the SSE Client and stops the heartbeat timer
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
void DisconnectStreamClient(string command)
|
||||
{
|
||||
//if(SseClient != null)
|
||||
// SseClient.Disconnect();
|
||||
|
||||
if (WSClient != null && WSClient.Connected)
|
||||
WSClient.Disconnect();
|
||||
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The callback that fires when we get a response from our registration attempt
|
||||
/// </summary>
|
||||
/// <param name="resp"></param>
|
||||
/// <param name="err"></param>
|
||||
void RegistrationConnectionCallback(HttpClientResponse resp, HTTP_CALLBACK_ERROR err)
|
||||
{
|
||||
CheckHttpDebug(resp, err);
|
||||
Debug.Console(1, this, "RegistrationConnectionCallback: {0}", err);
|
||||
try
|
||||
{
|
||||
if (resp != null && resp.Code == 200)
|
||||
{
|
||||
if(ServerReconnectTimer != null)
|
||||
{
|
||||
ServerReconnectTimer.Stop();
|
||||
ServerReconnectTimer = null;
|
||||
}
|
||||
|
||||
// Success here!
|
||||
ConnectStreamClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (resp != null)
|
||||
Debug.Console(1, this, "Response from server: {0}\n{1}", resp.Code, err);
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Null response received from server.");
|
||||
}
|
||||
StartReconnectTimer();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "Error Initializing Stream Client: {0}", e);
|
||||
StartReconnectTimer();
|
||||
}
|
||||
RegisterLockEvent.Set();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes when we don't get a heartbeat message in time. Triggers reconnect.
|
||||
/// </summary>
|
||||
/// <param name="o">For CTimer callback. Not used</param>
|
||||
void HeartbeatExpiredTimerCallback(object o)
|
||||
{
|
||||
Debug.Console(1, this, "Heartbeat Timer Expired.");
|
||||
if (ServerHeartbeatCheckTimer != null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
ServerHeartbeatCheckTimer = null;
|
||||
}
|
||||
StartReconnectTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void StartReconnectTimer()
|
||||
{
|
||||
// Start the reconnect timer
|
||||
if (ServerReconnectTimer == null)
|
||||
{
|
||||
ServerReconnectTimer = new CTimer(ReconnectToServerTimerCallback, null, ServerReconnectInterval, ServerReconnectInterval);
|
||||
Debug.Console(1, this, "Reconnect Timer Started.");
|
||||
}
|
||||
ServerReconnectTimer.Reset(ServerReconnectInterval, ServerReconnectInterval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="dueTime"></param>
|
||||
/// <param name="repeatTime"></param>
|
||||
void ResetOrStartHearbeatTimer()
|
||||
{
|
||||
if (ServerHeartbeatCheckTimer == null)
|
||||
{
|
||||
ServerHeartbeatCheckTimer = new CTimer(HeartbeatExpiredTimerCallback, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
|
||||
Debug.Console(1, this, "Heartbeat Timer Started.");
|
||||
}
|
||||
|
||||
ServerHeartbeatCheckTimer.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Connects the SSE Client
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
void ConnectStreamClient()
|
||||
{
|
||||
Debug.Console(0, this, "Initializing Stream client to server.");
|
||||
|
||||
if (WSClient == null)
|
||||
{
|
||||
WSClient = new WebSocketClient();
|
||||
}
|
||||
WSClient.URL = string.Format("wss://{0}/system/join/{1}", Config.ServerUrl, this.SystemUuid);
|
||||
WSClient.Connect();
|
||||
Debug.Console(0, this, "Websocket connected");
|
||||
WSClient.ReceiveCallBack = WebsocketReceiveCallback;
|
||||
//WSClient.SendCallBack = WebsocketSendCallback;
|
||||
WSClient.ReceiveAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets reconnect timer and updates usercode
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
void HandleHeartBeat(JToken content)
|
||||
{
|
||||
var code = content["userCode"];
|
||||
if(code != null)
|
||||
{
|
||||
foreach (var b in RoomBridges)
|
||||
{
|
||||
b.SetUserCode(code.Value<string>());
|
||||
}
|
||||
}
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Outputs debug info when enabled
|
||||
/// </summary>
|
||||
/// <param name="req"></param>
|
||||
/// <param name="r"></param>
|
||||
/// <param name="e"></param>
|
||||
void CheckHttpDebug(HttpClientResponse r, HTTP_CALLBACK_ERROR e)
|
||||
{
|
||||
if (HttpDebugEnabled)
|
||||
{
|
||||
Debug.Console(0, this, "------ Begin HTTP Debug ---------------------------------------");
|
||||
Debug.Console(0, this, "HTTP Response URL: {0}", r.ResponseUrl.ToString());
|
||||
Debug.Console(0, this, "HTTP Response 'error' {0}", e);
|
||||
Debug.Console(0, this, "HTTP Response code: {0}", r.Code);
|
||||
Debug.Console(0, this, "HTTP Response content: \r{0}", r.ContentString);
|
||||
Debug.Console(0, this, "------ End HTTP Debug -----------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="length"></param>
|
||||
/// <param name="opcode"></param>
|
||||
/// <param name="err"></param>
|
||||
int WebsocketReceiveCallback(byte[] data, uint length, WebSocketClient.WEBSOCKET_PACKET_TYPES opcode,
|
||||
WebSocketClient.WEBSOCKET_RESULT_CODES err)
|
||||
{
|
||||
var rx = System.Text.Encoding.UTF8.GetString(data, 0, (int)length);
|
||||
if(rx.Length > 0)
|
||||
ParseStreamRx(rx);
|
||||
WSClient.ReceiveAsync();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback to catch possible errors in sending via the websocket
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
int WebsocketSendCallback(Crestron.SimplSharp.CrestronWebSocketClient.WebSocketClient.WEBSOCKET_RESULT_CODES result)
|
||||
{
|
||||
Debug.Console(1, this, "SendCallback result: {0}", result);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ParseStreamRx(string message)
|
||||
{
|
||||
if(string.IsNullOrEmpty(message))
|
||||
return;
|
||||
|
||||
Debug.Console(1, this, "Message RX: '{0}'", message);
|
||||
try
|
||||
{
|
||||
var messageObj = JObject.Parse(message);
|
||||
|
||||
var type = messageObj["type"].Value<string>();
|
||||
|
||||
if (type == "hello")
|
||||
{
|
||||
ResetOrStartHearbeatTimer();
|
||||
}
|
||||
else if (type == "/system/heartbeat")
|
||||
{
|
||||
HandleHeartBeat(messageObj["content"]);
|
||||
}
|
||||
else if (type == "close")
|
||||
{
|
||||
WSClient.Disconnect();
|
||||
|
||||
ServerHeartbeatCheckTimer.Stop();
|
||||
// Start the reconnect timer
|
||||
StartReconnectTimer();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check path against Action dictionary
|
||||
if (ActionDictionary.ContainsKey(type))
|
||||
{
|
||||
var action = ActionDictionary[type];
|
||||
|
||||
if (action is Action)
|
||||
{
|
||||
(action as Action)();
|
||||
}
|
||||
else if (action is PressAndHoldAction)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
// Look for a button press event
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
switch (stateString)
|
||||
{
|
||||
case "true":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions.Add(type, new CTimer(o =>
|
||||
{
|
||||
(action as PressAndHoldAction)(false);
|
||||
PushedActions.Remove(type);
|
||||
}, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval));
|
||||
}
|
||||
// Maybe add an else to reset the timer
|
||||
break;
|
||||
}
|
||||
case "held":
|
||||
{
|
||||
if (!PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Reset(ButtonHeartbeatInterval, ButtonHeartbeatInterval);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case "false":
|
||||
{
|
||||
if (PushedActions.ContainsKey(type))
|
||||
{
|
||||
PushedActions[type].Stop();
|
||||
PushedActions.Remove(type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
(action as PressAndHoldAction)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<bool>)
|
||||
{
|
||||
var stateString = messageObj["content"]["state"].Value<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(stateString))
|
||||
{
|
||||
(action as Action<bool>)(stateString == "true");
|
||||
}
|
||||
}
|
||||
else if (action is Action<ushort>)
|
||||
{
|
||||
(action as Action<ushort>)(messageObj["content"]["value"].Value<ushort>());
|
||||
}
|
||||
else if (action is Action<string>)
|
||||
{
|
||||
(action as Action<string>)(messageObj["content"]["value"].Value<string>());
|
||||
}
|
||||
else if (action is Action<SourceSelectMessageContent>)
|
||||
{
|
||||
(action as Action<SourceSelectMessageContent>)(messageObj["content"]
|
||||
.ToObject<SourceSelectMessageContent>());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception err)
|
||||
{
|
||||
//Debug.Console(1, "SseMessageLengthBeforeFailureCount: {0}", SseMessageLengthBeforeFailureCount);
|
||||
//SseMessageLengthBeforeFailureCount = 0;
|
||||
Debug.Console(1, this, "Unable to parse message: {0}", err);
|
||||
}
|
||||
}
|
||||
|
||||
void TestHttpRequest(string s)
|
||||
{
|
||||
{
|
||||
s = s.Trim();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
var tokens = s.Split(' ');
|
||||
if (tokens.Length < 2)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Too few paramaters\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var url = tokens[1];
|
||||
if (tokens[0].ToLower() == "get")
|
||||
{
|
||||
var resp = new HttpClient().Get(url);
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
else if (tokens[0].ToLower() == "post")
|
||||
{
|
||||
var resp = new HttpClient().Post(url, new byte[] { });
|
||||
CrestronConsole.ConsoleCommandResponse("RESPONSE:\r{0}\r\r", resp);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Only get or post supported\r");
|
||||
PrintTestHttpRequestUsage();
|
||||
}
|
||||
}
|
||||
catch (HttpException e)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Exception in request:\r");
|
||||
CrestronConsole.ConsoleCommandResponse("Response URL: {0}\r", e.Response.ResponseUrl);
|
||||
CrestronConsole.ConsoleCommandResponse("Response Error Code: {0}\r", e.Response.Code);
|
||||
CrestronConsole.ConsoleCommandResponse("Response body: {0}\r", e.Response.ContentString);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PrintTestHttpRequestUsage()
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("Usage: mobilehttprequest:N get/post url\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class IChannelExtensions
|
||||
{
|
||||
public static void LinkActions(this IChannel dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "chanup", new PressAndHoldAction(dev.ChannelUp));
|
||||
controller.AddAction(prefix + "chandown", new PressAndHoldAction(dev.ChannelDown));
|
||||
controller.AddAction(prefix + "lastchan", new PressAndHoldAction(dev.LastChannel));
|
||||
controller.AddAction(prefix + "guide", new PressAndHoldAction(dev.Guide));
|
||||
controller.AddAction(prefix + "info", new PressAndHoldAction(dev.Info));
|
||||
controller.AddAction(prefix + "exit", new PressAndHoldAction(dev.Exit));
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this IChannel dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "chanup");
|
||||
controller.RemoveAction(prefix + "chandown");
|
||||
controller.RemoveAction(prefix + "lastchan");
|
||||
controller.RemoveAction(prefix + "guide");
|
||||
controller.RemoveAction(prefix + "info");
|
||||
controller.RemoveAction(prefix + "exit");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class IColorExtensions
|
||||
{
|
||||
public static void LinkActions(this IColor dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "red", new PressAndHoldAction(dev.Red));
|
||||
controller.AddAction(prefix + "green", new PressAndHoldAction(dev.Green));
|
||||
controller.AddAction(prefix + "yellow", new PressAndHoldAction(dev.Yellow));
|
||||
controller.AddAction(prefix + "blue", new PressAndHoldAction(dev.Blue));
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this IColor dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "red");
|
||||
controller.RemoveAction(prefix + "green");
|
||||
controller.RemoveAction(prefix + "yellow");
|
||||
controller.RemoveAction(prefix + "blue");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class IDPadExtensions
|
||||
{
|
||||
public static void LinkActions(this IDPad dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "up", new PressAndHoldAction(dev.Up));
|
||||
controller.AddAction(prefix + "down", new PressAndHoldAction(dev.Down));
|
||||
controller.AddAction(prefix + "left", new PressAndHoldAction(dev.Left));
|
||||
controller.AddAction(prefix + "right", new PressAndHoldAction(dev.Right));
|
||||
controller.AddAction(prefix + "select", new PressAndHoldAction(dev.Select));
|
||||
controller.AddAction(prefix + "menu", new PressAndHoldAction(dev.Menu));
|
||||
controller.AddAction(prefix + "exit", new PressAndHoldAction(dev.Exit));
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this IDPad dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "up");
|
||||
controller.RemoveAction(prefix + "down");
|
||||
controller.RemoveAction(prefix + "left");
|
||||
controller.RemoveAction(prefix + "right");
|
||||
controller.RemoveAction(prefix + "select");
|
||||
controller.RemoveAction(prefix + "menu");
|
||||
controller.RemoveAction(prefix + "exit");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class IDvrExtensions
|
||||
{
|
||||
public static void LinkActions(this IDvr dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "dvrlist", new PressAndHoldAction(dev.DvrList));
|
||||
controller.AddAction(prefix + "record", new PressAndHoldAction(dev.Record));
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this IDvr dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "dvrlist");
|
||||
controller.RemoveAction(prefix + "record");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class INumericExtensions
|
||||
{
|
||||
public static void LinkActions(this INumericKeypad dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "num0", new PressAndHoldAction(dev.Digit0));
|
||||
controller.AddAction(prefix + "num1", new PressAndHoldAction(dev.Digit1));
|
||||
controller.AddAction(prefix + "num2", new PressAndHoldAction(dev.Digit2));
|
||||
controller.AddAction(prefix + "num3", new PressAndHoldAction(dev.Digit3));
|
||||
controller.AddAction(prefix + "num4", new PressAndHoldAction(dev.Digit4));
|
||||
controller.AddAction(prefix + "num5", new PressAndHoldAction(dev.Digit5));
|
||||
controller.AddAction(prefix + "num6", new PressAndHoldAction(dev.Digit6));
|
||||
controller.AddAction(prefix + "num7", new PressAndHoldAction(dev.Digit0));
|
||||
controller.AddAction(prefix + "num8", new PressAndHoldAction(dev.Digit0));
|
||||
controller.AddAction(prefix + "num9", new PressAndHoldAction(dev.Digit0));
|
||||
controller.AddAction(prefix + "dash", new PressAndHoldAction(dev.KeypadAccessoryButton1));
|
||||
controller.AddAction(prefix + "enter", new PressAndHoldAction(dev.KeypadAccessoryButton2));
|
||||
// Deal with the Accessory functions on the numpad later
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this INumericKeypad dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "num0");
|
||||
controller.RemoveAction(prefix + "num1");
|
||||
controller.RemoveAction(prefix + "num2");
|
||||
controller.RemoveAction(prefix + "num3");
|
||||
controller.RemoveAction(prefix + "num4");
|
||||
controller.RemoveAction(prefix + "num5");
|
||||
controller.RemoveAction(prefix + "num6");
|
||||
controller.RemoveAction(prefix + "num7");
|
||||
controller.RemoveAction(prefix + "num8");
|
||||
controller.RemoveAction(prefix + "num9");
|
||||
controller.RemoveAction(prefix + "dash");
|
||||
controller.RemoveAction(prefix + "enter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class IPowerExtensions
|
||||
{
|
||||
public static void LinkActions(this IPower dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "poweron", new Action(dev.PowerOn));
|
||||
controller.AddAction(prefix + "poweroff", new Action(dev.PowerOff));
|
||||
controller.AddAction(prefix + "powertoggle", new Action(dev.PowerToggle));
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this IPower dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "poweron");
|
||||
controller.RemoveAction(prefix + "poweroff");
|
||||
controller.RemoveAction(prefix + "powertoggle");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class ISetTopBoxControlsExtensions
|
||||
{
|
||||
public static void LinkActions(this ISetTopBoxControls dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "dvrlist", new PressAndHoldAction(dev.DvrList));
|
||||
controller.AddAction(prefix + "replay", new PressAndHoldAction(dev.Replay));
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this ISetTopBoxControls dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "dvrlist");
|
||||
controller.RemoveAction(prefix + "replay");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public static class ITransportExtensions
|
||||
{
|
||||
public static void LinkActions(this ITransport dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.AddAction(prefix + "play", new PressAndHoldAction(dev.Play));
|
||||
controller.AddAction(prefix + "pause", new PressAndHoldAction(dev.Pause));
|
||||
controller.AddAction(prefix + "stop", new PressAndHoldAction(dev.Stop));
|
||||
controller.AddAction(prefix + "prevtrack", new PressAndHoldAction(dev.ChapPlus));
|
||||
controller.AddAction(prefix + "nexttrack", new PressAndHoldAction(dev.ChapMinus));
|
||||
controller.AddAction(prefix + "rewind", new PressAndHoldAction(dev.Rewind));
|
||||
controller.AddAction(prefix + "ffwd", new PressAndHoldAction(dev.FFwd));
|
||||
controller.AddAction(prefix + "record", new PressAndHoldAction(dev.Record));
|
||||
}
|
||||
|
||||
public static void UnlinkActions(this ITransport dev, CotijaSystemController controller)
|
||||
{
|
||||
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
|
||||
|
||||
controller.RemoveAction(prefix + "play");
|
||||
controller.RemoveAction(prefix + "pause");
|
||||
controller.RemoveAction(prefix + "stop");
|
||||
controller.RemoveAction(prefix + "prevtrack");
|
||||
controller.RemoveAction(prefix + "nexttrack");
|
||||
controller.RemoveAction(prefix + "rewind");
|
||||
controller.RemoveAction(prefix + "ffwd");
|
||||
controller.RemoveAction(prefix + "record");
|
||||
}
|
||||
}
|
||||
}
|
||||
13
PepperDashEssentials/Room/Cotija/Interfaces.cs
Normal file
13
PepperDashEssentials/Room/Cotija/Interfaces.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public interface IDelayedConfiguration
|
||||
{
|
||||
event EventHandler<EventArgs> ConfigurationIsReady;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class CotijaBridgeBase: Device
|
||||
{
|
||||
public CotijaSystemController Parent { get; private set; }
|
||||
|
||||
public string UserCode { get; private set; }
|
||||
|
||||
public abstract string RoomName { get; }
|
||||
|
||||
public CotijaBridgeBase(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the parent. Does nothing else. Override to add functionality such
|
||||
/// as adding actions to parent
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
public virtual void AddParent(CotijaSystemController parent)
|
||||
{
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the UserCode on the bridge object. Called from controller. A changed code will
|
||||
/// fire method UserCodeChange. Override that to handle changes
|
||||
/// </summary>
|
||||
/// <param name="code"></param>
|
||||
public void SetUserCode(string code)
|
||||
{
|
||||
var changed = UserCode != code;
|
||||
UserCode = code;
|
||||
if (changed)
|
||||
{
|
||||
UserCodeChange();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Empty method in base class. Override this to add functionality
|
||||
/// when code changes
|
||||
/// </summary>
|
||||
protected virtual void UserCodeChange()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,607 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.EthernetCommunication;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Room.Cotija
|
||||
{
|
||||
public class CotijaDdvc01RoomBridge : CotijaBridgeBase, IDelayedConfiguration
|
||||
{
|
||||
public class BoolJoin
|
||||
{
|
||||
/// <summary>
|
||||
/// 301
|
||||
/// </summary>
|
||||
public const uint RoomIsOn = 301;
|
||||
|
||||
/// <summary>
|
||||
/// 51
|
||||
/// </summary>
|
||||
public const uint ActivitySharePress = 51;
|
||||
/// <summary>
|
||||
/// 52
|
||||
/// </summary>
|
||||
public const uint ActivityPhoneCallPress = 52;
|
||||
/// <summary>
|
||||
/// 53
|
||||
/// </summary>
|
||||
public const uint ActivityVideoCallPress = 53;
|
||||
|
||||
/// <summary>
|
||||
/// 1
|
||||
/// </summary>
|
||||
public const uint MasterVolumeIsMuted = 1;
|
||||
/// <summary>
|
||||
/// 1
|
||||
/// </summary>
|
||||
public const uint MasterVolumeMuteToggle = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 61
|
||||
/// </summary>
|
||||
public const uint ShutdownCancel = 61;
|
||||
/// <summary>
|
||||
/// 62
|
||||
/// </summary>
|
||||
public const uint ShutdownEnd = 62;
|
||||
/// <summary>
|
||||
/// 63
|
||||
/// </summary>
|
||||
public const uint ShutdownStart = 63;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 72
|
||||
/// </summary>
|
||||
public const uint SourceHasChanged = 72;
|
||||
/// <summary>
|
||||
/// 501
|
||||
/// </summary>
|
||||
public const uint ConfigIsReady = 501;
|
||||
}
|
||||
|
||||
public class UshortJoin
|
||||
{
|
||||
/// <summary>
|
||||
/// 1
|
||||
/// </summary>
|
||||
public const uint MasterVolumeLevel = 1;
|
||||
|
||||
/// <summary>
|
||||
/// 61
|
||||
/// </summary>
|
||||
public const uint ShutdownPromptDuration = 61;
|
||||
}
|
||||
|
||||
public class StringJoin
|
||||
{
|
||||
/// <summary>
|
||||
/// 71
|
||||
/// </summary>
|
||||
public const uint SelectedSourceKey = 71;
|
||||
|
||||
/// <summary>
|
||||
/// 501
|
||||
/// </summary>
|
||||
public const uint ConfigRoomName = 501;
|
||||
/// <summary>
|
||||
/// 502
|
||||
/// </summary>
|
||||
public const uint ConfigHelpMessage = 502;
|
||||
/// <summary>
|
||||
/// 503
|
||||
/// </summary>
|
||||
public const uint ConfigHelpNumber = 503;
|
||||
/// <summary>
|
||||
/// 504
|
||||
/// </summary>
|
||||
public const uint ConfigRoomPhoneNumber = 504;
|
||||
/// <summary>
|
||||
/// 505
|
||||
/// </summary>
|
||||
public const uint ConfigRoomURI = 505;
|
||||
/// <summary>
|
||||
/// 401
|
||||
/// </summary>
|
||||
public const uint UserCodeToSystem = 401;
|
||||
/// <summary>
|
||||
/// 402
|
||||
/// </summary>
|
||||
public const uint ServerUrl = 402;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires when config is ready to go
|
||||
/// </summary>
|
||||
public event EventHandler<EventArgs> ConfigurationIsReady;
|
||||
|
||||
public ThreeSeriesTcpIpEthernetIntersystemCommunications EISC { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool ConfigIsLoaded { get; private set; }
|
||||
|
||||
public override string RoomName
|
||||
{
|
||||
get {
|
||||
var name = EISC.StringOutput[StringJoin.ConfigRoomName].StringValue;
|
||||
return string.IsNullOrEmpty(name) ? "Not Loaded" : name;
|
||||
}
|
||||
}
|
||||
|
||||
CotijaDdvc01DeviceBridge SourceBridge;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
/// <param name="ipId"></param>
|
||||
public CotijaDdvc01RoomBridge(string key, string name, uint ipId)
|
||||
: base(key, name)
|
||||
{
|
||||
try
|
||||
{
|
||||
EISC = new ThreeSeriesTcpIpEthernetIntersystemCommunications(ipId, "127.0.0.2", Global.ControlSystem);
|
||||
var reg = EISC.Register();
|
||||
if (reg != Crestron.SimplSharpPro.eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
Debug.Console(0, this, "Cannot connect EISC at IPID {0}: \r{1}", ipId, reg);
|
||||
|
||||
SourceBridge = new CotijaDdvc01DeviceBridge(key + "-sourceBridge", "DDVC01 source bridge", EISC);
|
||||
DeviceManager.AddDevice(SourceBridge);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finish wiring up everything after all devices are created. The base class will hunt down the related
|
||||
/// parent controller and link them up.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override bool CustomActivate()
|
||||
{
|
||||
Debug.Console(0, this, "Final activation. Setting up actions and feedbacks");
|
||||
SetupFunctions();
|
||||
SetupFeedbacks();
|
||||
|
||||
EISC.SigChange += EISC_SigChange;
|
||||
EISC.OnlineStatusChange += (o, a) =>
|
||||
{
|
||||
Debug.Console(1, this, "DDVC EISC online={0}. Config is ready={1}", a.DeviceOnLine, EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue);
|
||||
if (a.DeviceOnLine && EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue)
|
||||
LoadConfigValues();
|
||||
};
|
||||
// load config if it's already there
|
||||
if (EISC.IsOnline && EISC.BooleanOutput[BoolJoin.ConfigIsReady].BoolValue) // || EISC.BooleanInput[BoolJoin.ConfigIsReady].BoolValue)
|
||||
LoadConfigValues();
|
||||
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s =>
|
||||
{
|
||||
for (uint i = 1; i < 1000; i++)
|
||||
{
|
||||
if (s.ToLower().Equals("b"))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("D{0,6} {1} - ", i, EISC.BooleanOutput[i].BoolValue);
|
||||
}
|
||||
else if (s.ToLower().Equals("u"))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse("U{0,6} {1,8} - ", i, EISC.UShortOutput[i].UShortValue);
|
||||
}
|
||||
else if (s.ToLower().Equals("s"))
|
||||
{
|
||||
var val = EISC.StringOutput[i].StringValue;
|
||||
if(!string.IsNullOrEmpty(val))
|
||||
CrestronConsole.ConsoleCommandResponse("S{0,6} {1}\r", i, EISC.StringOutput[i].StringValue);
|
||||
}
|
||||
|
||||
}
|
||||
}, "mobilebridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
CrestronConsole.AddNewConsoleCommand(s => LoadConfigValues(), "loadddvc", "", ConsoleAccessLevelEnum.AccessOperator);
|
||||
|
||||
return base.CustomActivate();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Setup the actions to take place on various incoming API calls
|
||||
/// </summary>
|
||||
void SetupFunctions()
|
||||
{
|
||||
|
||||
Parent.AddAction(@"/room/room1/status", new Action(SendFullStatus));
|
||||
|
||||
Parent.AddAction(@"/room/room1/source", new Action<SourceSelectMessageContent>(c =>
|
||||
{
|
||||
EISC.SetString(StringJoin.SelectedSourceKey, c.SourceListItem);
|
||||
EISC.PulseBool(BoolJoin.SourceHasChanged);
|
||||
}));
|
||||
|
||||
#warning CHANGE to activityshare. Perhaps
|
||||
Parent.AddAction(@"/room/room1/defaultsource", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ActivitySharePress)));
|
||||
|
||||
Parent.AddAction(@"/room/room1/masterVolumeLevel", new Action<ushort>(u =>
|
||||
EISC.SetUshort(UshortJoin.MasterVolumeLevel, u)));
|
||||
Parent.AddAction(@"/room/room1/masterVolumeMuteToggle", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.MasterVolumeIsMuted)));
|
||||
|
||||
Parent.AddAction(@"/room/room1/shutdownStart", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ShutdownStart)));
|
||||
Parent.AddAction(@"/room/room1/shutdownEnd", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ShutdownEnd)));
|
||||
Parent.AddAction(@"/room/room1/shutdownCancel", new Action(() =>
|
||||
EISC.PulseBool(BoolJoin.ShutdownCancel)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Links feedbacks to whatever is gonna happen!
|
||||
/// </summary>
|
||||
void SetupFeedbacks()
|
||||
{
|
||||
// Power
|
||||
EISC.SetBoolSigAction(BoolJoin.RoomIsOn, b =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
isOn = b
|
||||
}));
|
||||
|
||||
// Source change things
|
||||
EISC.SetSigTrueAction(BoolJoin.SourceHasChanged, () =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue
|
||||
}));
|
||||
|
||||
// Volume things
|
||||
EISC.SetUShortSigAction(UshortJoin.MasterVolumeLevel, u =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
masterVolumeLevel = u
|
||||
}));
|
||||
|
||||
EISC.SetBoolSigAction(BoolJoin.MasterVolumeIsMuted, b =>
|
||||
PostStatusMessage(new
|
||||
{
|
||||
masterVolumeMuteState = b
|
||||
}));
|
||||
|
||||
// shutdown things
|
||||
EISC.SetSigTrueAction(BoolJoin.ShutdownCancel, new Action(() =>
|
||||
PostMessage("/room/shutdown/", new
|
||||
{
|
||||
state = "wasCancelled"
|
||||
})));
|
||||
EISC.SetSigTrueAction(BoolJoin.ShutdownEnd, new Action(() =>
|
||||
PostMessage("/room/shutdown/", new
|
||||
{
|
||||
state = "hasFinished"
|
||||
})));
|
||||
EISC.SetSigTrueAction(BoolJoin.ShutdownStart, new Action(() =>
|
||||
PostMessage("/room/shutdown/", new
|
||||
{
|
||||
state = "hasStarted",
|
||||
duration = EISC.UShortOutput[UshortJoin.ShutdownPromptDuration].UShortValue
|
||||
})));
|
||||
|
||||
// Config things
|
||||
EISC.SetSigTrueAction(BoolJoin.ConfigIsReady, LoadConfigValues);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads in config values when the Simpl program is ready
|
||||
/// </summary>
|
||||
void LoadConfigValues()
|
||||
{
|
||||
Debug.Console(1, this, "Loading configuration from DDVC01 EISC bridge");
|
||||
ConfigIsLoaded = false;
|
||||
|
||||
var co = ConfigReader.ConfigObject;
|
||||
|
||||
//Room
|
||||
if (co.Rooms == null)
|
||||
co.Rooms = new List<EssentialsRoomConfig>();
|
||||
var rm = new EssentialsRoomConfig();
|
||||
if (co.Rooms.Count == 0)
|
||||
{
|
||||
Debug.Console(0, this, "Adding room to config");
|
||||
co.Rooms.Add(rm);
|
||||
}
|
||||
rm.Name = EISC.StringOutput[501].StringValue;
|
||||
rm.Key = "room1";
|
||||
rm.Type = "ddvc01";
|
||||
|
||||
DDVC01RoomPropertiesConfig rmProps;
|
||||
if (rm.Properties == null)
|
||||
rmProps = new DDVC01RoomPropertiesConfig();
|
||||
else
|
||||
rmProps = JsonConvert.DeserializeObject<DDVC01RoomPropertiesConfig>(rm.Properties.ToString());
|
||||
|
||||
rmProps.Help = new EssentialsHelpPropertiesConfig();
|
||||
rmProps.Help.CallButtonText = EISC.StringOutput[503].StringValue;
|
||||
rmProps.Help.Message = EISC.StringOutput[502].StringValue;
|
||||
|
||||
rmProps.Environment = new EssentialsEnvironmentPropertiesConfig(); // enabled defaults to false
|
||||
|
||||
rmProps.RoomPhoneNumber = EISC.StringOutput[504].StringValue;
|
||||
rmProps.RoomURI = EISC.StringOutput[505].StringValue;
|
||||
rmProps.SpeedDials = new List<DDVC01SpeedDial>();
|
||||
// add speed dials as long as there are more - up to 4
|
||||
for (uint i = 512; i <= 519; i = i + 2)
|
||||
{
|
||||
var num = EISC.StringOutput[i].StringValue;
|
||||
if (string.IsNullOrEmpty(num))
|
||||
break;
|
||||
var name = EISC.StringOutput[i + 1].StringValue;
|
||||
rmProps.SpeedDials.Add(new DDVC01SpeedDial { Number = num, Name = name});
|
||||
}
|
||||
// volume control names
|
||||
var volCount = EISC.UShortOutput[701].UShortValue;
|
||||
|
||||
// use Volumes object or?
|
||||
rmProps.VolumeSliderNames = new List<string>();
|
||||
for(uint i = 701; i <= 700 + volCount; i++)
|
||||
{
|
||||
rmProps.VolumeSliderNames.Add(EISC.StringInput[i].StringValue);
|
||||
}
|
||||
|
||||
// There should be cotija devices in here, I think...
|
||||
if(co.Devices == null)
|
||||
co.Devices = new List<DeviceConfig>();
|
||||
|
||||
// clear out previous DDVC devices
|
||||
co.Devices.RemoveAll(d => d.Key.StartsWith("source-", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
rmProps.SourceListKey = "default";
|
||||
rm.Properties = JToken.FromObject(rmProps);
|
||||
|
||||
// Source list! This might be brutal!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
var groupMap = GetSourceGroupDictionary();
|
||||
|
||||
co.SourceLists = new Dictionary<string,Dictionary<string,SourceListItem>>();
|
||||
var newSl = new Dictionary<string, SourceListItem>();
|
||||
// add sources...
|
||||
for (uint i = 0; i<= 19; i++)
|
||||
{
|
||||
var name = EISC.StringOutput[601 + i].StringValue;
|
||||
if(string.IsNullOrEmpty(name))
|
||||
break;
|
||||
var icon = EISC.StringOutput[651 + i].StringValue;
|
||||
var key = EISC.StringOutput[671 + i].StringValue;
|
||||
var type = EISC.StringOutput[701 + i].StringValue;
|
||||
|
||||
Debug.Console(0, this, "Adding source {0} '{1}'", key, name);
|
||||
var newSLI = new SourceListItem{
|
||||
Icon = icon,
|
||||
Name = name,
|
||||
Order = (int)i + 1,
|
||||
SourceKey = key,
|
||||
};
|
||||
newSl.Add(key, newSLI);
|
||||
|
||||
string group = "genericsource";
|
||||
if (groupMap.ContainsKey(type))
|
||||
{
|
||||
group = groupMap[type];
|
||||
}
|
||||
|
||||
// add dev to devices list
|
||||
var devConf = new DeviceConfig {
|
||||
Group = group,
|
||||
Key = key,
|
||||
Name = name,
|
||||
Type = type
|
||||
};
|
||||
co.Devices.Add(devConf);
|
||||
}
|
||||
|
||||
co.SourceLists.Add("default", newSl);
|
||||
|
||||
Debug.Console(0, this, "******* CONFIG FROM DDVC: \r{0}", JsonConvert.SerializeObject(ConfigReader.ConfigObject, Formatting.Indented));
|
||||
|
||||
var handler = ConfigurationIsReady;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new EventArgs());
|
||||
}
|
||||
|
||||
ConfigIsLoaded = true;
|
||||
}
|
||||
|
||||
void SendFullStatus()
|
||||
{
|
||||
if (ConfigIsLoaded)
|
||||
{
|
||||
PostStatusMessage(new
|
||||
{
|
||||
isOn = EISC.BooleanOutput[BoolJoin.RoomIsOn].BoolValue,
|
||||
selectedSourceKey = EISC.StringOutput[StringJoin.SelectedSourceKey].StringValue,
|
||||
masterVolumeLevel = EISC.UShortOutput[UshortJoin.MasterVolumeLevel].UShortValue,
|
||||
masterVolumeMuteState = EISC.BooleanOutput[BoolJoin.MasterVolumeIsMuted].BoolValue
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
PostStatusMessage(new
|
||||
{
|
||||
error = "systemNotReady"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Helper for posting status message
|
||||
/// </summary>
|
||||
/// <param name="contentObject">The contents of the content object</param>
|
||||
void PostStatusMessage(object contentObject)
|
||||
{
|
||||
Parent.SendMessageToServer(JObject.FromObject(new
|
||||
{
|
||||
type = "/room/status/",
|
||||
content = contentObject
|
||||
}));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="messageType"></param>
|
||||
/// <param name="contentObject"></param>
|
||||
void PostMessage(string messageType, object contentObject)
|
||||
{
|
||||
Parent.SendMessageToServer(JObject.FromObject(new
|
||||
{
|
||||
type = messageType,
|
||||
content = contentObject
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="currentDevice"></param>
|
||||
/// <param name="args"></param>
|
||||
void EISC_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
|
||||
{
|
||||
if (Debug.Level >= 1)
|
||||
Debug.Console(1, this, "DDVC EISC change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
||||
var uo = args.Sig.UserObject;
|
||||
if (uo is Action<bool>)
|
||||
(uo as Action<bool>)(args.Sig.BoolValue);
|
||||
else if (uo is Action<ushort>)
|
||||
(uo as Action<ushort>)(args.Sig.UShortValue);
|
||||
else if (uo is Action<string>)
|
||||
(uo as Action<string>)(args.Sig.StringValue);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the mapping of types to groups, for setting up devices.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Dictionary<string, string> GetSourceGroupDictionary()
|
||||
{
|
||||
//type, group
|
||||
var d = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "laptop", "pc" },
|
||||
{ "wireless", "genericsource" },
|
||||
{ "iptv", "settopbox" }
|
||||
|
||||
};
|
||||
return d;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// updates the usercode from server
|
||||
/// </summary>
|
||||
protected override void UserCodeChange()
|
||||
{
|
||||
Debug.Console(1, this, "Server user code changed: {0}", UserCode);
|
||||
EISC.StringInput[StringJoin.UserCodeToSystem].StringValue = UserCode;
|
||||
EISC.StringInput[StringJoin.ServerUrl].StringValue = Parent.Config.ClientAppUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="oldKey"></param>
|
||||
/// <param name="newKey"></param>
|
||||
void SourceChange(string oldKey, string newKey)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
}
|
||||
}
|
||||
*/
|
||||
//if (type == ChangeType.WillChange)
|
||||
//{
|
||||
// // Disconnect from previous source
|
||||
|
||||
// if (info != null)
|
||||
// {
|
||||
// var previousDev = info.SourceDevice;
|
||||
|
||||
// // device type interfaces
|
||||
// if (previousDev is ISetTopBoxControls)
|
||||
// (previousDev as ISetTopBoxControls).UnlinkActions(Parent);
|
||||
// // common interfaces
|
||||
// if (previousDev is IChannel)
|
||||
// (previousDev as IChannel).UnlinkActions(Parent);
|
||||
// if (previousDev is IColor)
|
||||
// (previousDev as IColor).UnlinkActions(Parent);
|
||||
// if (previousDev is IDPad)
|
||||
// (previousDev as IDPad).UnlinkActions(Parent);
|
||||
// if (previousDev is IDvr)
|
||||
// (previousDev as IDvr).UnlinkActions(Parent);
|
||||
// if (previousDev is INumericKeypad)
|
||||
// (previousDev as INumericKeypad).UnlinkActions(Parent);
|
||||
// if (previousDev is IPower)
|
||||
// (previousDev as IPower).UnlinkActions(Parent);
|
||||
// if (previousDev is ITransport)
|
||||
// (previousDev as ITransport).UnlinkActions(Parent);
|
||||
// }
|
||||
|
||||
|
||||
// var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
// JObject roomStatus = new JObject();
|
||||
// roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
// JObject message = new JObject();
|
||||
|
||||
// message.Add("type", "/room/status/");
|
||||
// message.Add("content", roomStatus);
|
||||
|
||||
// Parent.PostToServer(message);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// if (info != null)
|
||||
// {
|
||||
// var dev = info.SourceDevice;
|
||||
|
||||
// if (dev is ISetTopBoxControls)
|
||||
// (dev as ISetTopBoxControls).LinkActions(Parent);
|
||||
// if (dev is IChannel)
|
||||
// (dev as IChannel).LinkActions(Parent);
|
||||
// if (dev is IColor)
|
||||
// (dev as IColor).LinkActions(Parent);
|
||||
// if (dev is IDPad)
|
||||
// (dev as IDPad).LinkActions(Parent);
|
||||
// if (dev is IDvr)
|
||||
// (dev as IDvr).LinkActions(Parent);
|
||||
// if (dev is INumericKeypad)
|
||||
// (dev as INumericKeypad).LinkActions(Parent);
|
||||
// if (dev is IPower)
|
||||
// (dev as IPower).LinkActions(Parent);
|
||||
// if (dev is ITransport)
|
||||
// (dev as ITransport).LinkActions(Parent);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,379 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Cotija;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CotijaEssentialsHuddleSpaceRoomBridge : CotijaBridgeBase
|
||||
{
|
||||
|
||||
public EssentialsHuddleSpaceRoom Room { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override string RoomName
|
||||
{
|
||||
get
|
||||
{
|
||||
return Room.Name;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
/// <param name="room"></param>
|
||||
public CotijaEssentialsHuddleSpaceRoomBridge(EssentialsHuddleSpaceRoom room):
|
||||
base("mobileControlBridge-essentialsHuddle", "Essentials Mobile Control Bridge-Huddle")
|
||||
{
|
||||
Room = room;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override of base: calls base to add parent and then registers actions and events.
|
||||
/// </summary>
|
||||
/// <param name="parent"></param>
|
||||
public override void AddParent(CotijaSystemController parent)
|
||||
{
|
||||
base.AddParent(parent);
|
||||
|
||||
// we add actions to the messaging system with a path, and a related action. Custom action
|
||||
// content objects can be handled in the controller's LineReceived method - and perhaps other
|
||||
// sub-controller parsing could be attached to these classes, so that the systemController
|
||||
// doesn't need to know about everything.
|
||||
|
||||
// Source Changes and room off
|
||||
Parent.AddAction(string.Format(@"/room/{0}/status", Room.Key), new Action(() => Room_RoomFullStatus(Room)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/source", Room.Key), new Action<SourceSelectMessageContent>(c => Room.RunRouteAction(c.SourceListItem)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/defaultsource", Room.Key), new Action(Room.RunDefaultRoute));
|
||||
|
||||
Parent.AddAction(string.Format(@"/room/{0}/masterVolumeLevel", Room.Key), new Action<ushort>(u =>
|
||||
(Room.CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(u)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/masterVolumeMuteToggle", Room.Key), new Action(() => Room.CurrentVolumeControls.MuteToggle()));
|
||||
|
||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownStart", Room.Key), new Action(() => Room.StartShutdown(eShutdownType.Manual)));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownEnd", Room.Key), new Action(() => Room.ShutdownPromptTimer.Finish()));
|
||||
Parent.AddAction(string.Format(@"/room/{0}/shutdownCancel", Room.Key), new Action(() => Room.ShutdownPromptTimer.Cancel()));
|
||||
|
||||
Room.CurrentSingleSourceChange += new SourceInfoChangeHandler(Room_CurrentSingleSourceChange);
|
||||
|
||||
Room.CurrentVolumeDeviceChange += new EventHandler<VolumeDeviceChangeEventArgs>(Room_CurrentVolumeDeviceChange);
|
||||
|
||||
Room.OnFeedback.OutputChange += OnFeedback_OutputChange;
|
||||
Room.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange;
|
||||
Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
|
||||
|
||||
Room.ShutdownPromptTimer.HasStarted += ShutdownPromptTimer_HasStarted;
|
||||
Room.ShutdownPromptTimer.HasFinished += ShutdownPromptTimer_HasFinished;
|
||||
Room.ShutdownPromptTimer.WasCancelled += ShutdownPromptTimer_WasCancelled;
|
||||
|
||||
// Registers for initial volume events, if possible
|
||||
var currentVolumeDevice = Room.CurrentVolumeControls;
|
||||
|
||||
if (currentVolumeDevice != null)
|
||||
{
|
||||
if (currentVolumeDevice is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var newDev = currentVolumeDevice as IBasicVolumeWithFeedback;
|
||||
|
||||
newDev.MuteFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||
newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for cancelled shutdown
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ShutdownPromptTimer_WasCancelled(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("state", "wasCancelled");
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/shutdown/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for when shutdown finishes
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ShutdownPromptTimer_HasFinished(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("state", "hasFinished");
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/shutdown/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler for when shutdown starts
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void ShutdownPromptTimer_HasStarted(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("state", "hasStarted");
|
||||
roomStatus.Add("duration", Room.ShutdownPromptTimer.SecondsToCount);
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/shutdown/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
// equivalent JS message:
|
||||
// Post( { type: '/room/status/', content: { shutdown: 'hasStarted', duration: Room.ShutdownPromptTimer.SecondsToCount })
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void IsWarmingUpFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("isWarmingUp", (sender as BoolFeedback).BoolValue);
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void IsCoolingDownFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("isCoolingDown", (sender as BoolFeedback).BoolValue);
|
||||
JObject message = new JObject();
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void OnFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"isOn": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
roomStatus.Add("isOn", (sender as BoolFeedback).BoolValue);
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
|
||||
void Room_CurrentVolumeDeviceChange(object sender, VolumeDeviceChangeEventArgs e)
|
||||
{
|
||||
if (e.OldDev is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var oldDev = e.OldDev as IBasicVolumeWithFeedback;
|
||||
|
||||
oldDev.MuteFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
||||
oldDev.VolumeLevelFeedback.OutputChange -= VolumeLevelFeedback_OutputChange;
|
||||
}
|
||||
|
||||
if (e.NewDev is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var newDev = e.NewDev as IBasicVolumeWithFeedback;
|
||||
|
||||
newDev.MuteFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||
newDev.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||
}
|
||||
}
|
||||
|
||||
void VolumeLevelFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"masterVolumeLevel": 12345,
|
||||
"masterVolumeMuteState": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
var huddleRoom = Room as EssentialsHuddleSpaceRoom;
|
||||
|
||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
if (huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
||||
}
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
}
|
||||
|
||||
void Room_CurrentSingleSourceChange(EssentialsRoomBase room, PepperDash.Essentials.Core.SourceListItem info, ChangeType type)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (type == ChangeType.WillChange)
|
||||
{
|
||||
// Disconnect from previous source
|
||||
|
||||
if (info != null)
|
||||
{
|
||||
var previousDev = info.SourceDevice;
|
||||
|
||||
// device type interfaces
|
||||
if (previousDev is ISetTopBoxControls)
|
||||
(previousDev as ISetTopBoxControls).UnlinkActions(Parent);
|
||||
// common interfaces
|
||||
if (previousDev is IChannel)
|
||||
(previousDev as IChannel).UnlinkActions(Parent);
|
||||
if (previousDev is IColor)
|
||||
(previousDev as IColor).UnlinkActions(Parent);
|
||||
if (previousDev is IDPad)
|
||||
(previousDev as IDPad).UnlinkActions(Parent);
|
||||
if (previousDev is IDvr)
|
||||
(previousDev as IDvr).UnlinkActions(Parent);
|
||||
if (previousDev is INumericKeypad)
|
||||
(previousDev as INumericKeypad).UnlinkActions(Parent);
|
||||
if (previousDev is IPower)
|
||||
(previousDev as IPower).UnlinkActions(Parent);
|
||||
if (previousDev is ITransport)
|
||||
(previousDev as ITransport).UnlinkActions(Parent);
|
||||
}
|
||||
}
|
||||
else // did change
|
||||
{
|
||||
if (info != null)
|
||||
{
|
||||
var dev = info.SourceDevice;
|
||||
|
||||
if (dev is ISetTopBoxControls)
|
||||
(dev as ISetTopBoxControls).LinkActions(Parent);
|
||||
if (dev is IChannel)
|
||||
(dev as IChannel).LinkActions(Parent);
|
||||
if (dev is IColor)
|
||||
(dev as IColor).LinkActions(Parent);
|
||||
if (dev is IDPad)
|
||||
(dev as IDPad).LinkActions(Parent);
|
||||
if (dev is IDvr)
|
||||
(dev as IDvr).LinkActions(Parent);
|
||||
if (dev is INumericKeypad)
|
||||
(dev as INumericKeypad).LinkActions(Parent);
|
||||
if (dev is IPower)
|
||||
(dev as IPower).LinkActions(Parent);
|
||||
if (dev is ITransport)
|
||||
(dev as ITransport).LinkActions(Parent);
|
||||
|
||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
JObject roomStatus = new JObject();
|
||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Posts the full status of the room to the server
|
||||
/// </summary>
|
||||
/// <param name="room"></param>
|
||||
void Room_RoomFullStatus(EssentialsRoomBase room)
|
||||
{
|
||||
/* Example message
|
||||
* {
|
||||
"type":"/room/status",
|
||||
"content": {
|
||||
"selectedSourceKey": "off",
|
||||
"isOn": false,
|
||||
"masterVolumeLevel": 50,
|
||||
"masterVolumeMuteState": false
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
JObject roomStatus = new JObject();
|
||||
|
||||
var huddleRoom = room as EssentialsHuddleSpaceRoom;
|
||||
roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue);
|
||||
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
|
||||
|
||||
|
||||
if(huddleRoom.CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var currentVolumeConstrols = huddleRoom.CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
roomStatus.Add("masterVolumeLevel", currentVolumeConstrols.VolumeLevelFeedback.IntValue);
|
||||
roomStatus.Add("masterVolumeMuteState", currentVolumeConstrols.MuteFeedback.BoolValue);
|
||||
}
|
||||
|
||||
JObject message = new JObject();
|
||||
|
||||
message.Add("type", "/room/status/");
|
||||
message.Add("content", roomStatus);
|
||||
|
||||
Parent.SendMessageToServer(message);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SourceSelectMessageContent
|
||||
{
|
||||
public string SourceListItem { get; set; }
|
||||
//public string Destination { get; set; }
|
||||
//public string SourceSelect { get; set; }
|
||||
}
|
||||
|
||||
public delegate void PressAndHoldAction(bool b);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
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;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
namespace PepperDash.Essentials.Room
|
||||
{
|
||||
public abstract class EssentialsRoomEmergencyBase : IKeyed
|
||||
{
|
||||
public string Key { get; private set; }
|
||||
|
||||
public EssentialsRoomEmergencyBase(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class EssentialsRoomEmergencyContactClosure : EssentialsRoomEmergencyBase
|
||||
{
|
||||
EssentialsRoomBase Room;
|
||||
string Behavior;
|
||||
bool TriggerOnClose;
|
||||
|
||||
public EssentialsRoomEmergencyContactClosure(string key, EssentialsRoomEmergencyConfig config, EssentialsRoomBase 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
462
PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
Normal file
462
PepperDashEssentials/Room/Types/EssentialsHuddleSpaceRoom.cs
Normal file
|
|
@ -0,0 +1,462 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
|
||||
protected override Func<bool> OnFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
var val = CurrentSourceInfo != null
|
||||
&& CurrentSourceInfo.Type == eSourceListItemType.Route
|
||||
&& disp != null;
|
||||
//&& disp.PowerIsOnFeedback.BoolValue;
|
||||
return val;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsWarmingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsWarmingUpFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsCoolingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsCoolingDownFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsRoomPropertiesConfig Config { get; private set; }
|
||||
|
||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||
|
||||
public bool ExcludeFromGlobalFunctions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The config name of the source list
|
||||
/// </summary>
|
||||
public string SourceListKey { get; set; }
|
||||
|
||||
public string DefaultSourceItem { get; set; }
|
||||
|
||||
public ushort DefaultVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If room is off, enables power on to last source. Default true
|
||||
/// </summary>
|
||||
public bool EnablePowerOnToLastSource { get; set; }
|
||||
string LastSourceKey;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
get { return _CurrentAudioDevice; }
|
||||
set
|
||||
{
|
||||
if (value == _CurrentAudioDevice) return;
|
||||
|
||||
var oldDev = _CurrentAudioDevice;
|
||||
// derigister this room from the device, if it can
|
||||
if (oldDev is IInUseTracking)
|
||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||
var handler = CurrentVolumeDeviceChange;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||
_CurrentAudioDevice = value;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||
// register this room with new device, if it can
|
||||
if (_CurrentAudioDevice is IInUseTracking)
|
||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||
}
|
||||
}
|
||||
IBasicVolumeControls _CurrentAudioDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The SourceListItem last run - containing names and icons
|
||||
/// </summary>
|
||||
public SourceListItem CurrentSourceInfo
|
||||
{
|
||||
get { return _CurrentSourceInfo; }
|
||||
private set
|
||||
{
|
||||
if (value == _CurrentSourceInfo) return;
|
||||
|
||||
var handler = CurrentSingleSourceChange;
|
||||
// remove from in-use tracker, if so equipped
|
||||
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
|
||||
|
||||
_CurrentSourceInfo = value;
|
||||
|
||||
// add to in-use tracking
|
||||
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _CurrentSourceInfo;
|
||||
|
||||
public string CurrentSourceInfoKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
||||
IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
|
||||
: base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
DefaultDisplay = defaultDisplay;
|
||||
DefaultAudioDevice = defaultAudio;
|
||||
if (defaultAudio is IBasicVolumeControls)
|
||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||
else if (defaultAudio is IHasVolumeDevice)
|
||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
CurrentVolumeControls = DefaultVolumeControls;
|
||||
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
{
|
||||
// Link power, warming, cooling to display
|
||||
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
|
||||
{
|
||||
if (!disp.PowerIsOnFeedback.BoolValue)
|
||||
CurrentSourceInfo = null;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
if (!IsWarmingUpFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
};
|
||||
}
|
||||
|
||||
SourceListKey = "default";
|
||||
EnablePowerOnToLastSource = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override void EndShutdown()
|
||||
{
|
||||
SetDefaultLevels();
|
||||
|
||||
RunDefaultRoute();
|
||||
|
||||
CrestronEnvironment.Sleep(1000);
|
||||
|
||||
RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes the default source item, if any
|
||||
/// </summary>
|
||||
public void RunDefaultRoute()
|
||||
{
|
||||
//if (DefaultSourceItem != null && !OnFeedback.BoolValue)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="routeKey"></param>
|
||||
public void RunRouteAction(string routeKey)
|
||||
{
|
||||
RunRouteAction(routeKey, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||
/// route or commands
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RunRouteAction(string routeKey, Action successCallback)
|
||||
{
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
Debug.Console(1, this, "Run route action '{0}'", routeKey);
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||
if(dict == null)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the list item by it's string key
|
||||
if (!dict.ContainsKey(routeKey))
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||
routeKey, SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
var item = dict[routeKey];
|
||||
//Debug.Console(2, this, "Action {0} has {1} steps",
|
||||
// item.SourceKey, item.RouteList.Count);
|
||||
|
||||
// End usage timer on last source
|
||||
if (!string.IsNullOrEmpty(LastSourceKey))
|
||||
{
|
||||
var lastSource = dict[LastSourceKey].SourceDevice;
|
||||
|
||||
try
|
||||
{
|
||||
if (lastSource != null && lastSource is IUsageTracking)
|
||||
(lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's run it
|
||||
if (routeKey.ToLower() != "roomoff")
|
||||
{
|
||||
LastSourceKey = routeKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentSourceInfoKey = null;
|
||||
}
|
||||
|
||||
foreach (var route in item.RouteList)
|
||||
{
|
||||
// if there is a $defaultAll on route, run two separate
|
||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Going to assume a single-path route for now
|
||||
var tempVideo = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultDisplay",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Video
|
||||
};
|
||||
DoRoute(tempVideo);
|
||||
|
||||
//var tempAudio = new SourceRouteListItem
|
||||
//{
|
||||
// DestinationKey = "$defaultAudio",
|
||||
// SourceKey = route.SourceKey,
|
||||
// Type = eRoutingSignalType.Audio
|
||||
//};
|
||||
//DoRoute(tempAudio);
|
||||
//continue; -- not sure why this was here
|
||||
}
|
||||
else
|
||||
DoRoute(route);
|
||||
}
|
||||
|
||||
// Start usage timer on routed source
|
||||
if (item.SourceDevice is IUsageTracking)
|
||||
{
|
||||
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Set volume control, using default if non provided
|
||||
IBasicVolumeControls volDev = null;
|
||||
// Handle special cases for volume control
|
||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultVolumeControls;
|
||||
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultDisplay as IBasicVolumeControls;
|
||||
// Or a specific device, probably rarely used.
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
||||
if (dev is IBasicVolumeControls)
|
||||
volDev = dev as IBasicVolumeControls;
|
||||
else if (dev is IHasVolumeDevice)
|
||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||
}
|
||||
|
||||
if (volDev != CurrentVolumeControls)
|
||||
{
|
||||
// zero the volume on the device we are leaving.
|
||||
// Set the volume to default on device we are entering
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
|
||||
vd.SetVolume(0);
|
||||
}
|
||||
CurrentVolumeControls = volDev;
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
|
||||
vd.SetVolume(vol);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = null;
|
||||
}
|
||||
else if (item.SourceKey != null)
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = item;
|
||||
}
|
||||
// And finally, set the "control". This will trigger event
|
||||
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
|
||||
|
||||
OnFeedback.FireUpdate();
|
||||
|
||||
// report back when done
|
||||
if (successCallback != null)
|
||||
successCallback();
|
||||
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will power the room on with the last-used source
|
||||
/// </summary>
|
||||
public void PowerOnToDefaultOrLastSource()
|
||||
{
|
||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||
return;
|
||||
RunRouteAction(LastSourceKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does what it says
|
||||
/// </summary>
|
||||
public override void SetDefaultLevels()
|
||||
{
|
||||
Debug.Console(1, this, "Restoring default levels");
|
||||
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
if (vc != null)
|
||||
vc.SetVolume(DefaultVolume);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <returns></returns>
|
||||
bool DoRoute(SourceRouteListItem route)
|
||||
{
|
||||
IRoutingSinkNoSwitching dest = null;
|
||||
|
||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultAudioDevice;
|
||||
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultDisplay;
|
||||
else
|
||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void RoomVacatedForTimeoutPeriod(object o)
|
||||
{
|
||||
//Implement this
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
|
||||
/// </summary>
|
||||
public static void AllRoomsOff()
|
||||
{
|
||||
var allRooms = DeviceManager.AllDevices.Where(d =>
|
||||
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
|
||||
foreach (var room in allRooms)
|
||||
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,850 @@
|
|||
<<<<<<< HEAD
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
|
||||
protected override Func<bool> OnFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
var val = CurrentSourceInfo != null
|
||||
&& CurrentSourceInfo.Type == eSourceListItemType.Route
|
||||
&& disp != null
|
||||
&& disp.PowerIsOnFeedback.BoolValue;
|
||||
return val;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsWarmingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsWarmingUpFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsCoolingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsCoolingDownFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsRoomPropertiesConfig Config { get; private set; }
|
||||
|
||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||
|
||||
public bool ExcludeFromGlobalFunctions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The config name of the source list
|
||||
/// </summary>
|
||||
public string SourceListKey { get; set; }
|
||||
|
||||
public string DefaultSourceItem { get; set; }
|
||||
|
||||
public ushort DefaultVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If room is off, enables power on to last source. Default true
|
||||
/// </summary>
|
||||
public bool EnablePowerOnToLastSource { get; set; }
|
||||
string LastSourceKey;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
get { return _CurrentAudioDevice; }
|
||||
set
|
||||
{
|
||||
if (value == _CurrentAudioDevice) return;
|
||||
|
||||
var oldDev = _CurrentAudioDevice;
|
||||
// derigister this room from the device, if it can
|
||||
if (oldDev is IInUseTracking)
|
||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||
var handler = CurrentVolumeDeviceChange;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||
_CurrentAudioDevice = value;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||
// register this room with new device, if it can
|
||||
if (_CurrentAudioDevice is IInUseTracking)
|
||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||
}
|
||||
}
|
||||
IBasicVolumeControls _CurrentAudioDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The SourceListItem last run - containing names and icons
|
||||
/// </summary>
|
||||
public SourceListItem CurrentSourceInfo
|
||||
{
|
||||
get { return _CurrentSourceInfo; }
|
||||
private set
|
||||
{
|
||||
if (value == _CurrentSourceInfo) return;
|
||||
|
||||
var handler = CurrentSingleSourceChange;
|
||||
// remove from in-use tracker, if so equipped
|
||||
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
|
||||
|
||||
_CurrentSourceInfo = value;
|
||||
|
||||
// add to in-use tracking
|
||||
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _CurrentSourceInfo;
|
||||
|
||||
public string CurrentSourceInfoKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
||||
IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
|
||||
: base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
DefaultDisplay = defaultDisplay;
|
||||
DefaultAudioDevice = defaultAudio;
|
||||
if (defaultAudio is IBasicVolumeControls)
|
||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||
else if (defaultAudio is IHasVolumeDevice)
|
||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
CurrentVolumeControls = DefaultVolumeControls;
|
||||
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
{
|
||||
// Link power, warming, cooling to display
|
||||
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
|
||||
{
|
||||
if (!disp.PowerIsOnFeedback.BoolValue)
|
||||
CurrentSourceInfo = null;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
if (!IsWarmingUpFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
if (IsCoolingDownFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
}
|
||||
|
||||
SourceListKey = "default";
|
||||
EnablePowerOnToLastSource = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override void Shutdown()
|
||||
{
|
||||
RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes the default source item, if any
|
||||
/// </summary>
|
||||
public void RunDefaultRoute()
|
||||
{
|
||||
if (DefaultSourceItem != null)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="routeKey"></param>
|
||||
public void RunRouteAction(string routeKey)
|
||||
{
|
||||
RunRouteAction(routeKey, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||
/// route or commands
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RunRouteAction(string routeKey, Action successCallback)
|
||||
{
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
Debug.Console(1, this, "Run route action '{0}'", routeKey);
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||
if(dict == null)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the list item by it's string key
|
||||
if (!dict.ContainsKey(routeKey))
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||
routeKey, SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
var item = dict[routeKey];
|
||||
//Debug.Console(2, this, "Action {0} has {1} steps",
|
||||
// item.SourceKey, item.RouteList.Count);
|
||||
|
||||
// End usage timer on last source
|
||||
if (!string.IsNullOrEmpty(LastSourceKey))
|
||||
{
|
||||
var lastSource = dict[LastSourceKey].SourceDevice;
|
||||
|
||||
try
|
||||
{
|
||||
if (lastSource != null && lastSource is IUsageTracking)
|
||||
(lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's run it
|
||||
if (routeKey.ToLower() != "roomoff")
|
||||
{
|
||||
LastSourceKey = routeKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentSourceInfoKey = null;
|
||||
}
|
||||
|
||||
foreach (var route in item.RouteList)
|
||||
{
|
||||
// if there is a $defaultAll on route, run two separate
|
||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Going to assume a single-path route for now
|
||||
var tempVideo = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultDisplay",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Video
|
||||
};
|
||||
DoRoute(tempVideo);
|
||||
|
||||
//var tempAudio = new SourceRouteListItem
|
||||
//{
|
||||
// DestinationKey = "$defaultAudio",
|
||||
// SourceKey = route.SourceKey,
|
||||
// Type = eRoutingSignalType.Audio
|
||||
//};
|
||||
//DoRoute(tempAudio);
|
||||
//continue; -- not sure why this was here
|
||||
}
|
||||
else
|
||||
DoRoute(route);
|
||||
}
|
||||
|
||||
// Start usage timer on routed source
|
||||
if (item.SourceDevice is IUsageTracking)
|
||||
{
|
||||
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
|
||||
}
|
||||
|
||||
|
||||
// Set volume control on room, using default if non provided
|
||||
IBasicVolumeControls volDev = null;
|
||||
// Handle special cases for volume control
|
||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultVolumeControls;
|
||||
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultDisplay as IBasicVolumeControls;
|
||||
// Or a specific device, probably rarely used.
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
||||
if (dev is IBasicVolumeControls)
|
||||
volDev = dev as IBasicVolumeControls;
|
||||
else if (dev is IHasVolumeDevice)
|
||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||
}
|
||||
CurrentVolumeControls = volDev;
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = null;
|
||||
}
|
||||
else if (item.SourceKey != null)
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = item;
|
||||
}
|
||||
// And finally, set the "control". This will trigger event
|
||||
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
|
||||
|
||||
OnFeedback.FireUpdate();
|
||||
|
||||
// report back when done
|
||||
if (successCallback != null)
|
||||
successCallback();
|
||||
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will power the room on with the last-used source
|
||||
/// </summary>
|
||||
public void PowerOnToDefaultOrLastSource()
|
||||
{
|
||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||
return;
|
||||
RunRouteAction(LastSourceKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does what it says
|
||||
/// </summary>
|
||||
public override void SetDefaultLevels()
|
||||
{
|
||||
Debug.Console(0, this, "SetDefaultLevels not implemented");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <returns></returns>
|
||||
bool DoRoute(SourceRouteListItem route)
|
||||
{
|
||||
IRoutingSinkNoSwitching dest = null;
|
||||
|
||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultAudioDevice;
|
||||
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultDisplay;
|
||||
else
|
||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
||||
}
|
||||
return true;
|
||||
=======
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
|
||||
protected override Func<bool> OnFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
var val = CurrentSourceInfo != null
|
||||
&& CurrentSourceInfo.Type == eSourceListItemType.Route
|
||||
&& disp != null
|
||||
&& disp.PowerIsOnFeedback.BoolValue;
|
||||
return val;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsWarmingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsWarmingUpFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsCoolingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsCoolingDownFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsRoomPropertiesConfig Config { get; private set; }
|
||||
|
||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||
|
||||
public bool ExcludeFromGlobalFunctions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The config name of the source list
|
||||
/// </summary>
|
||||
public string SourceListKey { get; set; }
|
||||
|
||||
public string DefaultSourceItem { get; set; }
|
||||
|
||||
public ushort DefaultVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If room is off, enables power on to last source. Default true
|
||||
/// </summary>
|
||||
public bool EnablePowerOnToLastSource { get; set; }
|
||||
string LastSourceKey;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
get { return _CurrentAudioDevice; }
|
||||
set
|
||||
{
|
||||
if (value == _CurrentAudioDevice) return;
|
||||
|
||||
var oldDev = _CurrentAudioDevice;
|
||||
// derigister this room from the device, if it can
|
||||
if (oldDev is IInUseTracking)
|
||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||
var handler = CurrentVolumeDeviceChange;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||
_CurrentAudioDevice = value;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||
// register this room with new device, if it can
|
||||
if (_CurrentAudioDevice is IInUseTracking)
|
||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||
}
|
||||
}
|
||||
IBasicVolumeControls _CurrentAudioDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The SourceListItem last run - containing names and icons
|
||||
/// </summary>
|
||||
public SourceListItem CurrentSourceInfo
|
||||
{
|
||||
get { return _CurrentSourceInfo; }
|
||||
private set
|
||||
{
|
||||
if (value == _CurrentSourceInfo) return;
|
||||
|
||||
var handler = CurrentSingleSourceChange;
|
||||
// remove from in-use tracker, if so equipped
|
||||
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
|
||||
|
||||
_CurrentSourceInfo = value;
|
||||
|
||||
// add to in-use tracking
|
||||
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _CurrentSourceInfo;
|
||||
|
||||
public string CurrentSourceInfoKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
||||
IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
|
||||
: base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
DefaultDisplay = defaultDisplay;
|
||||
DefaultAudioDevice = defaultAudio;
|
||||
if (defaultAudio is IBasicVolumeControls)
|
||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||
else if (defaultAudio is IHasVolumeDevice)
|
||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
CurrentVolumeControls = DefaultVolumeControls;
|
||||
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
{
|
||||
// Link power, warming, cooling to display
|
||||
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
|
||||
{
|
||||
if (!disp.PowerIsOnFeedback.BoolValue)
|
||||
CurrentSourceInfo = null;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
};
|
||||
|
||||
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
if (!IsWarmingUpFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
if (IsCoolingDownFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
}
|
||||
|
||||
SourceListKey = "default";
|
||||
EnablePowerOnToLastSource = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override void EndShutdown()
|
||||
{
|
||||
RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes the default source item, if any
|
||||
/// </summary>
|
||||
public void RunDefaultRoute()
|
||||
{
|
||||
if (DefaultSourceItem != null)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="routeKey"></param>
|
||||
public void RunRouteAction(string routeKey)
|
||||
{
|
||||
RunRouteAction(routeKey, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||
/// route or commands
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RunRouteAction(string routeKey, Action successCallback)
|
||||
{
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
Debug.Console(1, this, "Run route action '{0}'", routeKey);
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||
if(dict == null)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the list item by it's string key
|
||||
if (!dict.ContainsKey(routeKey))
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||
routeKey, SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
var item = dict[routeKey];
|
||||
//Debug.Console(2, this, "Action {0} has {1} steps",
|
||||
// item.SourceKey, item.RouteList.Count);
|
||||
|
||||
// End usage timer on last source
|
||||
if (!string.IsNullOrEmpty(LastSourceKey))
|
||||
{
|
||||
var lastSource = dict[LastSourceKey].SourceDevice;
|
||||
|
||||
try
|
||||
{
|
||||
if (lastSource != null && lastSource is IUsageTracking)
|
||||
(lastSource as IUsageTracking).UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking (257):\r{0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Let's run it
|
||||
if (routeKey.ToLower() != "roomoff")
|
||||
{
|
||||
LastSourceKey = routeKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentSourceInfoKey = null;
|
||||
}
|
||||
|
||||
foreach (var route in item.RouteList)
|
||||
{
|
||||
// if there is a $defaultAll on route, run two separate
|
||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Going to assume a single-path route for now
|
||||
var tempVideo = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultDisplay",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Video
|
||||
};
|
||||
DoRoute(tempVideo);
|
||||
|
||||
//var tempAudio = new SourceRouteListItem
|
||||
//{
|
||||
// DestinationKey = "$defaultAudio",
|
||||
// SourceKey = route.SourceKey,
|
||||
// Type = eRoutingSignalType.Audio
|
||||
//};
|
||||
//DoRoute(tempAudio);
|
||||
//continue; -- not sure why this was here
|
||||
}
|
||||
else
|
||||
DoRoute(route);
|
||||
}
|
||||
|
||||
// Start usage timer on routed source
|
||||
if (item.SourceDevice is IUsageTracking)
|
||||
{
|
||||
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
|
||||
}
|
||||
|
||||
|
||||
// Set volume control on room, using default if non provided
|
||||
IBasicVolumeControls volDev = null;
|
||||
// Handle special cases for volume control
|
||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultVolumeControls;
|
||||
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultDisplay as IBasicVolumeControls;
|
||||
// Or a specific device, probably rarely used.
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
||||
if (dev is IBasicVolumeControls)
|
||||
volDev = dev as IBasicVolumeControls;
|
||||
else if (dev is IHasVolumeDevice)
|
||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||
}
|
||||
CurrentVolumeControls = volDev;
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = null;
|
||||
}
|
||||
else if (item.SourceKey != null)
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = item;
|
||||
}
|
||||
// And finally, set the "control". This will trigger event
|
||||
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
|
||||
|
||||
OnFeedback.FireUpdate();
|
||||
|
||||
// report back when done
|
||||
if (successCallback != null)
|
||||
successCallback();
|
||||
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will power the room on with the last-used source
|
||||
/// </summary>
|
||||
public void PowerOnToDefaultOrLastSource()
|
||||
{
|
||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||
return;
|
||||
RunRouteAction(LastSourceKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does what it says
|
||||
/// </summary>
|
||||
public override void SetDefaultLevels()
|
||||
{
|
||||
Debug.Console(0, this, "SetDefaultLevels not implemented");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <returns></returns>
|
||||
bool DoRoute(SourceRouteListItem route)
|
||||
{
|
||||
IRoutingSinkNoSwitching dest = null;
|
||||
|
||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultAudioDevice;
|
||||
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultDisplay;
|
||||
else
|
||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
||||
}
|
||||
return true;
|
||||
>>>>>>> origin/feature/ecs-342
|
||||
}
|
||||
|
||||
public override void RoomVacatedForTimeoutPeriod(object o)
|
||||
{
|
||||
//Implement this
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
|
||||
/// </summary>
|
||||
public static void AllRoomsOff()
|
||||
{
|
||||
var allRooms = DeviceManager.AllDevices.Where(d =>
|
||||
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
|
||||
foreach (var room in allRooms)
|
||||
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
|
||||
}
|
||||
}
|
||||
}
|
||||
572
PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
Normal file
572
PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs
Normal file
|
|
@ -0,0 +1,572 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, IPrivacy, IHasCurrentVolumeControls
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
|
||||
|
||||
//************************
|
||||
// Call-related stuff
|
||||
|
||||
public BoolFeedback InCallFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Make this more specific
|
||||
/// </summary>
|
||||
public List<CodecActiveCallItem> ActiveCalls { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
|
||||
/// </summary>
|
||||
public IntFeedback CallTypeFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// When something in the room is sharing with the far end or through other means
|
||||
/// </summary>
|
||||
public BoolFeedback IsSharingFeedback { get; private set; }
|
||||
|
||||
//************************
|
||||
|
||||
|
||||
protected override Func<bool> OnFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
var val = CurrentSourceInfo != null
|
||||
&& CurrentSourceInfo.Type == eSourceListItemType.Route
|
||||
&& disp != null;
|
||||
//&& disp.PowerIsOnFeedback.BoolValue;
|
||||
return val;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsWarmingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsWarmingUpFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsCoolingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsCoolingDownFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsHuddleVtc1PropertiesConfig Config { get; private set; }
|
||||
|
||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
|
||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||
|
||||
public VideoCodecBase VideoCodec { get; private set; }
|
||||
|
||||
public bool ExcludeFromGlobalFunctions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The config name of the source list
|
||||
/// </summary>
|
||||
public string SourceListKey { get; set; }
|
||||
|
||||
public string DefaultSourceItem { get; set; }
|
||||
|
||||
public ushort DefaultVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If room is off, enables power on to last source. Default true
|
||||
/// </summary>
|
||||
public bool EnablePowerOnToLastSource { get; set; }
|
||||
string LastSourceKey;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the volume control device, and attaches/removes InUseTrackers with "audio"
|
||||
/// tag to device.
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
get { return _CurrentAudioDevice; }
|
||||
set
|
||||
{
|
||||
if (value == _CurrentAudioDevice) return;
|
||||
|
||||
var oldDev = _CurrentAudioDevice;
|
||||
// derigister this room from the device, if it can
|
||||
if (oldDev is IInUseTracking)
|
||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||
var handler = CurrentVolumeDeviceChange;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||
_CurrentAudioDevice = value;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||
// register this room with new device, if it can
|
||||
if (_CurrentAudioDevice is IInUseTracking)
|
||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||
}
|
||||
}
|
||||
IBasicVolumeControls _CurrentAudioDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The SourceListItem last run - containing names and icons
|
||||
/// </summary>
|
||||
public SourceListItem CurrentSourceInfo
|
||||
{
|
||||
get { return _CurrentSourceInfo; }
|
||||
private set
|
||||
{
|
||||
if (value == _CurrentSourceInfo) return;
|
||||
|
||||
var handler = CurrentSingleSourceChange;
|
||||
// remove from in-use tracker, if so equipped
|
||||
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
|
||||
|
||||
_CurrentSourceInfo = value;
|
||||
|
||||
// add to in-use tracking
|
||||
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _CurrentSourceInfo;
|
||||
|
||||
public string CurrentSourceInfoKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// "codecOsd"
|
||||
/// </summary>
|
||||
public string DefaultCodecRouteString { get { return "codecOsd"; } }
|
||||
|
||||
/// <summary>
|
||||
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
|
||||
/// always returns the VideoCodec if it is capable
|
||||
/// </summary>
|
||||
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
|
||||
|
||||
CCriticalSection SourceSelectLock = new CCriticalSection();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsHuddleVtc1Room(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
||||
IBasicVolumeControls defaultAudio, VideoCodecBase codec, EssentialsHuddleVtc1PropertiesConfig config)
|
||||
: base(key, name)
|
||||
{
|
||||
if (codec == null)
|
||||
throw new ArgumentNullException("codec cannot be null");
|
||||
Config = config;
|
||||
DefaultDisplay = defaultDisplay;
|
||||
VideoCodec = codec;
|
||||
DefaultAudioDevice = defaultAudio;
|
||||
|
||||
if (defaultAudio is IBasicVolumeControls)
|
||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||
else if (defaultAudio is IHasVolumeDevice)
|
||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
CurrentVolumeControls = DefaultVolumeControls;
|
||||
|
||||
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
{
|
||||
// Link power, warming, cooling to display
|
||||
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
|
||||
{
|
||||
if (!disp.PowerIsOnFeedback.BoolValue)
|
||||
CurrentSourceInfo = null;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
if (disp.PowerIsOnFeedback.BoolValue)
|
||||
{
|
||||
SetDefaultLevels();
|
||||
}
|
||||
};
|
||||
|
||||
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
if (!IsWarmingUpFeedback.BoolValue)
|
||||
(CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
};
|
||||
}
|
||||
|
||||
InCallFeedback = new BoolFeedback(() => VideoCodec.IsInCall);
|
||||
VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate();
|
||||
|
||||
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue);
|
||||
VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate();
|
||||
|
||||
// link privacy to VC (for now?)
|
||||
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
|
||||
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
|
||||
|
||||
CallTypeFeedback = new IntFeedback(() => 0);
|
||||
|
||||
SourceListKey = "default";
|
||||
EnablePowerOnToLastSource = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override void EndShutdown()
|
||||
{
|
||||
VideoCodec.EndAllCalls();
|
||||
|
||||
SetDefaultLevels();
|
||||
|
||||
RunDefaultPresentRoute();
|
||||
|
||||
CrestronEnvironment.Sleep(1000);
|
||||
|
||||
RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes the default source item, if any. Returns true when default route exists
|
||||
/// </summary>
|
||||
public bool RunDefaultPresentRoute()
|
||||
{
|
||||
//if (DefaultSourceItem != null)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
return DefaultSourceItem != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the room when started into call mode without presenting a source
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool RunDefaultCallRoute()
|
||||
{
|
||||
RunRouteAction(DefaultCodecRouteString);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="routeKey"></param>
|
||||
public void RunRouteAction(string routeKey)
|
||||
{
|
||||
RunRouteAction(routeKey, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||
/// route or commands
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RunRouteAction(string routeKey, Action successCallback)
|
||||
{
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
// try to prevent multiple simultaneous selections
|
||||
SourceSelectLock.TryEnter();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
Debug.Console(1, this, "Run route action '{0}'", routeKey);
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||
if (dict == null)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the list item by it's string key
|
||||
if (!dict.ContainsKey(routeKey))
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||
routeKey, SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// End usage timer on last source
|
||||
if (!string.IsNullOrEmpty(LastSourceKey))
|
||||
{
|
||||
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
|
||||
if (usageLastSource != null && usageLastSource.UsageTracker != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// There MAY have been failures in here. Protect
|
||||
usageLastSource.UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let's run it
|
||||
var item = dict[routeKey];
|
||||
if (routeKey.ToLower() != "roomoff")
|
||||
{
|
||||
|
||||
LastSourceKey = routeKey;
|
||||
}
|
||||
else
|
||||
CurrentSourceInfoKey = null;
|
||||
|
||||
// hand off the individual routes to this helper
|
||||
foreach (var route in item.RouteList)
|
||||
DoRouteItem(route);
|
||||
|
||||
// Start usage timer on routed source
|
||||
var usageNewSource = item.SourceDevice as IUsageTracking;
|
||||
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
|
||||
{
|
||||
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
|
||||
}
|
||||
|
||||
// See if this can be moved into common, base-class method -------------
|
||||
|
||||
|
||||
// Set volume control, using default if non provided
|
||||
IBasicVolumeControls volDev = null;
|
||||
// Handle special cases for volume control
|
||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultVolumeControls;
|
||||
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultDisplay as IBasicVolumeControls;
|
||||
// Or a specific device, probably rarely used.
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
||||
if (dev is IBasicVolumeControls)
|
||||
volDev = dev as IBasicVolumeControls;
|
||||
else if (dev is IHasVolumeDevice)
|
||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||
}
|
||||
|
||||
if (volDev != CurrentVolumeControls)
|
||||
{
|
||||
// zero the volume on the device we are leaving.
|
||||
// Set the volume to default on device we are entering
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
SavedVolumeLevels[vd] = (uint)vd.VolumeLevelFeedback.IntValue;
|
||||
vd.SetVolume(0);
|
||||
}
|
||||
|
||||
CurrentVolumeControls = volDev;
|
||||
if (ZeroVolumeWhenSwtichingVolumeDevices && CurrentVolumeControls is IBasicVolumeWithFeedback)
|
||||
{
|
||||
var vd = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
ushort vol = (SavedVolumeLevels.ContainsKey(vd) ? (ushort)SavedVolumeLevels[vd] : DefaultVolume);
|
||||
vd.SetVolume(vol);
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = null;
|
||||
}
|
||||
else if (item.SourceKey != null)
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = item;
|
||||
}
|
||||
|
||||
OnFeedback.FireUpdate();
|
||||
|
||||
// report back when done
|
||||
if (successCallback != null)
|
||||
successCallback();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "ERROR in routing: {0}", e);
|
||||
}
|
||||
|
||||
SourceSelectLock.Leave();
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
void DoRouteItem(SourceRouteListItem route)
|
||||
{
|
||||
// if there is a $defaultAll on route, run two separate
|
||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Going to assume a single-path route for now
|
||||
var tempVideo = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultDisplay",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Video
|
||||
};
|
||||
DoRoute(tempVideo);
|
||||
}
|
||||
else
|
||||
DoRoute(route);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <returns></returns>
|
||||
bool DoRoute(SourceRouteListItem route)
|
||||
{
|
||||
IRoutingSinkNoSwitching dest = null;
|
||||
|
||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultAudioDevice as IRoutingSinkNoSwitching;
|
||||
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultDisplay;
|
||||
else
|
||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void RoomVacatedForTimeoutPeriod(object o)
|
||||
{
|
||||
//Implement this
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does what it says
|
||||
/// </summary>
|
||||
public override void SetDefaultLevels()
|
||||
{
|
||||
Debug.Console(1, this, "Restoring default levels");
|
||||
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
if (vc != null)
|
||||
vc.SetVolume(DefaultVolume);
|
||||
}
|
||||
/// <summary>
|
||||
/// Will power the room on with the last-used source
|
||||
/// </summary>
|
||||
public void PowerOnToDefaultOrLastSource()
|
||||
{
|
||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||
return;
|
||||
RunRouteAction(LastSourceKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
|
||||
/// </summary>
|
||||
public static void AllRoomsOff()
|
||||
{
|
||||
var allRooms = DeviceManager.AllDevices.Where(d =>
|
||||
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
|
||||
foreach (var room in allRooms)
|
||||
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
#region IPrivacy Members
|
||||
|
||||
|
||||
public void PrivacyModeOff()
|
||||
{
|
||||
VideoCodec.PrivacyModeOff();
|
||||
}
|
||||
|
||||
public void PrivacyModeOn()
|
||||
{
|
||||
VideoCodec.PrivacyModeOn();
|
||||
}
|
||||
|
||||
public void PrivacyModeToggle()
|
||||
{
|
||||
VideoCodec.PrivacyModeToggle();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
967
PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs.orig
Normal file
967
PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs.orig
Normal file
|
|
@ -0,0 +1,967 @@
|
|||
<<<<<<< HEAD
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, IPrivacy
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
|
||||
|
||||
//************************
|
||||
// Call-related stuff
|
||||
|
||||
public BoolFeedback InCallFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Make this more specific
|
||||
/// </summary>
|
||||
public List<CodecActiveCallItem> ActiveCalls { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
|
||||
/// </summary>
|
||||
public IntFeedback CallTypeFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// When something in the room is sharing with the far end or through other means
|
||||
/// </summary>
|
||||
public BoolFeedback IsSharingFeedback { get; private set; }
|
||||
|
||||
//************************
|
||||
|
||||
|
||||
protected override Func<bool> OnFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
var val = CurrentSourceInfo != null
|
||||
&& CurrentSourceInfo.Type == eSourceListItemType.Route
|
||||
&& disp != null
|
||||
&& disp.PowerIsOnFeedback.BoolValue;
|
||||
return val;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsWarmingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsWarmingUpFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsCoolingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsCoolingDownFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsHuddleVtc1PropertiesConfig Config { get; private set; }
|
||||
|
||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
|
||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||
|
||||
public VideoCodecBase VideoCodec { get; private set; }
|
||||
|
||||
public bool ExcludeFromGlobalFunctions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The config name of the source list
|
||||
/// </summary>
|
||||
public string SourceListKey { get; set; }
|
||||
|
||||
public string DefaultSourceItem { get; set; }
|
||||
|
||||
public ushort DefaultVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If room is off, enables power on to last source. Default true
|
||||
/// </summary>
|
||||
public bool EnablePowerOnToLastSource { get; set; }
|
||||
string LastSourceKey;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
get { return _CurrentAudioDevice; }
|
||||
set
|
||||
{
|
||||
if (value == _CurrentAudioDevice) return;
|
||||
|
||||
var oldDev = _CurrentAudioDevice;
|
||||
// derigister this room from the device, if it can
|
||||
if (oldDev is IInUseTracking)
|
||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||
var handler = CurrentVolumeDeviceChange;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||
_CurrentAudioDevice = value;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||
// register this room with new device, if it can
|
||||
if (_CurrentAudioDevice is IInUseTracking)
|
||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||
}
|
||||
}
|
||||
IBasicVolumeControls _CurrentAudioDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The SourceListItem last run - containing names and icons
|
||||
/// </summary>
|
||||
public SourceListItem CurrentSourceInfo
|
||||
{
|
||||
get { return _CurrentSourceInfo; }
|
||||
private set
|
||||
{
|
||||
if (value == _CurrentSourceInfo) return;
|
||||
|
||||
var handler = CurrentSingleSourceChange;
|
||||
// remove from in-use tracker, if so equipped
|
||||
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
|
||||
|
||||
_CurrentSourceInfo = value;
|
||||
|
||||
// add to in-use tracking
|
||||
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _CurrentSourceInfo;
|
||||
|
||||
public string CurrentSourceInfoKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// "codecOsd"
|
||||
/// </summary>
|
||||
public string DefaultCodecRouteString { get { return "codecOsd"; } }
|
||||
|
||||
/// <summary>
|
||||
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
|
||||
/// always returns the VideoCodec if it is capable
|
||||
/// </summary>
|
||||
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsHuddleVtc1Room(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
||||
IBasicVolumeControls defaultAudio, VideoCodecBase codec, EssentialsHuddleVtc1PropertiesConfig config)
|
||||
: base(key, name)
|
||||
{
|
||||
if (codec == null)
|
||||
throw new ArgumentNullException("codec cannot be null");
|
||||
Config = config;
|
||||
DefaultDisplay = defaultDisplay;
|
||||
VideoCodec = codec;
|
||||
DefaultAudioDevice = defaultAudio;
|
||||
|
||||
if (defaultAudio is IBasicVolumeControls)
|
||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||
else if (defaultAudio is IHasVolumeDevice)
|
||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
CurrentVolumeControls = DefaultVolumeControls;
|
||||
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
{
|
||||
// Link power, warming, cooling to display
|
||||
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
|
||||
{
|
||||
if (!disp.PowerIsOnFeedback.BoolValue)
|
||||
CurrentSourceInfo = null;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
if (disp.PowerIsOnFeedback.BoolValue)
|
||||
{
|
||||
SetDefaultLevels();
|
||||
}
|
||||
};
|
||||
|
||||
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
if (!IsWarmingUpFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
if (IsCoolingDownFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
}
|
||||
|
||||
InCallFeedback = new BoolFeedback(() => VideoCodec.IsInCall);
|
||||
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingSourceFeedback.StringValue != null);
|
||||
|
||||
// link privacy to VC (for now?)
|
||||
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
|
||||
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
|
||||
|
||||
CallTypeFeedback = new IntFeedback(() => 0);
|
||||
|
||||
SourceListKey = "default";
|
||||
EnablePowerOnToLastSource = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override void Shutdown()
|
||||
{
|
||||
RunRouteAction("roomOff");
|
||||
VideoCodec.EndAllCalls();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes the default source item, if any. Returns true when default route exists
|
||||
/// </summary>
|
||||
public bool RunDefaultPresentRoute()
|
||||
{
|
||||
if (DefaultSourceItem != null)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
return DefaultSourceItem != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the room when started into call mode without presenting a source
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool RunDefaultCallRoute()
|
||||
{
|
||||
RunRouteAction(DefaultCodecRouteString);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="routeKey"></param>
|
||||
public void RunRouteAction(string routeKey)
|
||||
{
|
||||
RunRouteAction(routeKey, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||
/// route or commands
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RunRouteAction(string routeKey, Action successCallback)
|
||||
{
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Debug.Console(1, this, "Run route action '{0}'", routeKey);
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||
if (dict == null)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the list item by it's string key
|
||||
if (!dict.ContainsKey(routeKey))
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||
routeKey, SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// End usage timer on last source
|
||||
if (!string.IsNullOrEmpty(LastSourceKey))
|
||||
{
|
||||
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
|
||||
if (usageLastSource != null && usageLastSource.UsageTracker != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// There MAY have been failures in here. Protect
|
||||
usageLastSource.UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let's run it
|
||||
var item = dict[routeKey];
|
||||
if (routeKey.ToLower() != "roomoff")
|
||||
{
|
||||
|
||||
LastSourceKey = routeKey;
|
||||
}
|
||||
else
|
||||
CurrentSourceInfoKey = null;
|
||||
|
||||
// hand off the individual routes to this helper
|
||||
foreach (var route in item.RouteList)
|
||||
DoRouteItem(route);
|
||||
|
||||
// Start usage timer on routed source
|
||||
var usageNewSource = item.SourceDevice as IUsageTracking;
|
||||
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
|
||||
{
|
||||
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
|
||||
}
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = null;
|
||||
}
|
||||
else if (item.SourceKey != null)
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = item;
|
||||
}
|
||||
|
||||
OnFeedback.FireUpdate();
|
||||
|
||||
// report back when done
|
||||
if (successCallback != null)
|
||||
successCallback();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "ERROR in routing: {0}", e);
|
||||
}
|
||||
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
void DoRouteItem(SourceRouteListItem route)
|
||||
{
|
||||
// if there is a $defaultAll on route, run two separate
|
||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Going to assume a single-path route for now
|
||||
var tempVideo = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultDisplay",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Video
|
||||
};
|
||||
DoRoute(tempVideo);
|
||||
}
|
||||
else
|
||||
DoRoute(route);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <returns></returns>
|
||||
bool DoRoute(SourceRouteListItem route)
|
||||
{
|
||||
IRoutingSinkNoSwitching dest = null;
|
||||
|
||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultAudioDevice as IRoutingSinkNoSwitching;
|
||||
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultDisplay;
|
||||
else
|
||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
||||
}
|
||||
return true;
|
||||
=======
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
using PepperDash.Essentials.Devices.Common.Codec;
|
||||
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IHasCurrentSourceInfoChange, IPrivacy
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
|
||||
|
||||
//************************
|
||||
// Call-related stuff
|
||||
|
||||
public BoolFeedback InCallFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Make this more specific
|
||||
/// </summary>
|
||||
public List<CodecActiveCallItem> ActiveCalls { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// States: 0 for on hook, 1 for video, 2 for audio, 3 for telekenesis
|
||||
/// </summary>
|
||||
public IntFeedback CallTypeFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BoolFeedback PrivacyModeIsOnFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// When something in the room is sharing with the far end or through other means
|
||||
/// </summary>
|
||||
public BoolFeedback IsSharingFeedback { get; private set; }
|
||||
|
||||
//************************
|
||||
|
||||
|
||||
protected override Func<bool> OnFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
var val = CurrentSourceInfo != null
|
||||
&& CurrentSourceInfo.Type == eSourceListItemType.Route
|
||||
&& disp != null
|
||||
&& disp.PowerIsOnFeedback.BoolValue;
|
||||
return val;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsWarmingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsWarmingUpFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override Func<bool> IsCoolingFeedbackFunc
|
||||
{
|
||||
get
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
return disp.IsCoolingDownFeedback.BoolValue;
|
||||
else
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public EssentialsHuddleVtc1PropertiesConfig Config { get; private set; }
|
||||
|
||||
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
|
||||
public IBasicVolumeControls DefaultAudioDevice { get; private set; }
|
||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||
|
||||
public VideoCodecBase VideoCodec { get; private set; }
|
||||
|
||||
public bool ExcludeFromGlobalFunctions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The config name of the source list
|
||||
/// </summary>
|
||||
public string SourceListKey { get; set; }
|
||||
|
||||
public string DefaultSourceItem { get; set; }
|
||||
|
||||
public ushort DefaultVolume { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If room is off, enables power on to last source. Default true
|
||||
/// </summary>
|
||||
public bool EnablePowerOnToLastSource { get; set; }
|
||||
string LastSourceKey;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
get { return _CurrentAudioDevice; }
|
||||
set
|
||||
{
|
||||
if (value == _CurrentAudioDevice) return;
|
||||
|
||||
var oldDev = _CurrentAudioDevice;
|
||||
// derigister this room from the device, if it can
|
||||
if (oldDev is IInUseTracking)
|
||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||
var handler = CurrentVolumeDeviceChange;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||
_CurrentAudioDevice = value;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||
// register this room with new device, if it can
|
||||
if (_CurrentAudioDevice is IInUseTracking)
|
||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||
}
|
||||
}
|
||||
IBasicVolumeControls _CurrentAudioDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The SourceListItem last run - containing names and icons
|
||||
/// </summary>
|
||||
public SourceListItem CurrentSourceInfo
|
||||
{
|
||||
get { return _CurrentSourceInfo; }
|
||||
private set
|
||||
{
|
||||
if (value == _CurrentSourceInfo) return;
|
||||
|
||||
var handler = CurrentSingleSourceChange;
|
||||
// remove from in-use tracker, if so equipped
|
||||
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
|
||||
|
||||
_CurrentSourceInfo = value;
|
||||
|
||||
// add to in-use tracking
|
||||
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _CurrentSourceInfo;
|
||||
|
||||
public string CurrentSourceInfoKey { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// "codecOsd"
|
||||
/// </summary>
|
||||
public string DefaultCodecRouteString { get { return "codecOsd"; } }
|
||||
|
||||
/// <summary>
|
||||
/// Temporary implementation. Returns the schedule-ready object or null if none. Fow now,
|
||||
/// always returns the VideoCodec if it is capable
|
||||
/// </summary>
|
||||
public IHasScheduleAwareness ScheduleSource { get { return VideoCodec as IHasScheduleAwareness; } }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsHuddleVtc1Room(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
|
||||
IBasicVolumeControls defaultAudio, VideoCodecBase codec, EssentialsHuddleVtc1PropertiesConfig config)
|
||||
: base(key, name)
|
||||
{
|
||||
if (codec == null)
|
||||
throw new ArgumentNullException("codec cannot be null");
|
||||
Config = config;
|
||||
DefaultDisplay = defaultDisplay;
|
||||
VideoCodec = codec;
|
||||
DefaultAudioDevice = defaultAudio;
|
||||
|
||||
if (defaultAudio is IBasicVolumeControls)
|
||||
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||
else if (defaultAudio is IHasVolumeDevice)
|
||||
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
CurrentVolumeControls = DefaultVolumeControls;
|
||||
|
||||
var disp = DefaultDisplay as DisplayBase;
|
||||
if (disp != null)
|
||||
{
|
||||
// Link power, warming, cooling to display
|
||||
disp.PowerIsOnFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (disp.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue)
|
||||
{
|
||||
if (!disp.PowerIsOnFeedback.BoolValue)
|
||||
CurrentSourceInfo = null;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
if (disp.PowerIsOnFeedback.BoolValue)
|
||||
{
|
||||
SetDefaultLevels();
|
||||
}
|
||||
};
|
||||
|
||||
disp.IsWarmingUpFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsWarmingUpFeedback.FireUpdate();
|
||||
if (!IsWarmingUpFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
disp.IsCoolingDownFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
IsCoolingDownFeedback.FireUpdate();
|
||||
if (IsCoolingDownFeedback.BoolValue)
|
||||
(DefaultDisplay as IBasicVolumeWithFeedback).SetVolume(DefaultVolume);
|
||||
};
|
||||
}
|
||||
|
||||
InCallFeedback = new BoolFeedback(() => VideoCodec.IsInCall);
|
||||
IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingSourceFeedback.StringValue != null);
|
||||
|
||||
// link privacy to VC (for now?)
|
||||
PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue);
|
||||
VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate();
|
||||
|
||||
CallTypeFeedback = new IntFeedback(() => 0);
|
||||
|
||||
SourceListKey = "default";
|
||||
EnablePowerOnToLastSource = true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override void EndShutdown()
|
||||
{
|
||||
RunRouteAction("roomOff");
|
||||
VideoCodec.EndAllCalls();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Routes the default source item, if any. Returns true when default route exists
|
||||
/// </summary>
|
||||
public bool RunDefaultPresentRoute()
|
||||
{
|
||||
if (DefaultSourceItem != null)
|
||||
RunRouteAction(DefaultSourceItem);
|
||||
return DefaultSourceItem != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up the room when started into call mode without presenting a source
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool RunDefaultCallRoute()
|
||||
{
|
||||
RunRouteAction(DefaultCodecRouteString);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="routeKey"></param>
|
||||
public void RunRouteAction(string routeKey)
|
||||
{
|
||||
RunRouteAction(routeKey, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||
/// route or commands
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RunRouteAction(string routeKey, Action successCallback)
|
||||
{
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
Debug.Console(1, this, "Run route action '{0}'", routeKey);
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||
if (dict == null)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the list item by it's string key
|
||||
if (!dict.ContainsKey(routeKey))
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||
routeKey, SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// End usage timer on last source
|
||||
if (!string.IsNullOrEmpty(LastSourceKey))
|
||||
{
|
||||
var usageLastSource = dict[LastSourceKey].SourceDevice as IUsageTracking;
|
||||
if (usageLastSource != null && usageLastSource.UsageTracker != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// There MAY have been failures in here. Protect
|
||||
usageLastSource.UsageTracker.EndDeviceUsage();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "*#* EXCEPTION in end usage tracking:\r{0}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let's run it
|
||||
var item = dict[routeKey];
|
||||
if (routeKey.ToLower() != "roomoff")
|
||||
{
|
||||
|
||||
LastSourceKey = routeKey;
|
||||
}
|
||||
else
|
||||
CurrentSourceInfoKey = null;
|
||||
|
||||
// hand off the individual routes to this helper
|
||||
foreach (var route in item.RouteList)
|
||||
DoRouteItem(route);
|
||||
|
||||
// Start usage timer on routed source
|
||||
var usageNewSource = item.SourceDevice as IUsageTracking;
|
||||
if (usageNewSource != null && usageNewSource.UsageTracker != null) // Have to make sure there is a usage tracker!
|
||||
{
|
||||
(item.SourceDevice as IUsageTracking).UsageTracker.StartDeviceUsage();
|
||||
}
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey == "$off")
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = null;
|
||||
}
|
||||
else if (item.SourceKey != null)
|
||||
{
|
||||
CurrentSourceInfoKey = routeKey;
|
||||
CurrentSourceInfo = item;
|
||||
}
|
||||
|
||||
OnFeedback.FireUpdate();
|
||||
|
||||
// report back when done
|
||||
if (successCallback != null)
|
||||
successCallback();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(1, this, "ERROR in routing: {0}", e);
|
||||
}
|
||||
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
void DoRouteItem(SourceRouteListItem route)
|
||||
{
|
||||
// if there is a $defaultAll on route, run two separate
|
||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Going to assume a single-path route for now
|
||||
var tempVideo = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultDisplay",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Video
|
||||
};
|
||||
DoRoute(tempVideo);
|
||||
}
|
||||
else
|
||||
DoRoute(route);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <returns></returns>
|
||||
bool DoRoute(SourceRouteListItem route)
|
||||
{
|
||||
IRoutingSinkNoSwitching dest = null;
|
||||
|
||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultAudioDevice as IRoutingSinkNoSwitching;
|
||||
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultDisplay;
|
||||
else
|
||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
||||
}
|
||||
return true;
|
||||
>>>>>>> origin/feature/ecs-342
|
||||
}
|
||||
|
||||
public override void RoomVacatedForTimeoutPeriod(object o)
|
||||
{
|
||||
//Implement this
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does what it says
|
||||
/// </summary>
|
||||
public override void SetDefaultLevels()
|
||||
{
|
||||
Debug.Console(1, this, "Restoring default levels");
|
||||
var vc = CurrentVolumeControls as IBasicVolumeWithFeedback;
|
||||
if (vc != null)
|
||||
vc.SetVolume(DefaultVolume);
|
||||
}
|
||||
/// <summary>
|
||||
/// Will power the room on with the last-used source
|
||||
/// </summary>
|
||||
public void PowerOnToDefaultOrLastSource()
|
||||
{
|
||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||
return;
|
||||
RunRouteAction(LastSourceKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
|
||||
/// </summary>
|
||||
public static void AllRoomsOff()
|
||||
{
|
||||
var allRooms = DeviceManager.AllDevices.Where(d =>
|
||||
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
|
||||
foreach (var room in allRooms)
|
||||
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
|
||||
}
|
||||
|
||||
#region IPrivacy Members
|
||||
|
||||
|
||||
public void PrivacyModeOff()
|
||||
{
|
||||
VideoCodec.PrivacyModeOff();
|
||||
}
|
||||
|
||||
public void PrivacyModeOn()
|
||||
{
|
||||
VideoCodec.PrivacyModeOn();
|
||||
}
|
||||
|
||||
public void PrivacyModeToggle()
|
||||
{
|
||||
VideoCodec.PrivacyModeToggle();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
437
PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs
Normal file
437
PepperDashEssentials/Room/Types/EssentialsPresentationRoom.cs
Normal file
|
|
@ -0,0 +1,437 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Room.Config;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsPresentationRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
|
||||
{
|
||||
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
|
||||
public event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
public event SourceInfoChangeHandler CurrentDisplay1SourceChange;
|
||||
public event SourceInfoChangeHandler CurrentDisplay2SourceChange;
|
||||
|
||||
protected override Func<bool> OnFeedbackFunc { get {
|
||||
return () => (CurrentSingleSourceInfo != null
|
||||
&& CurrentSingleSourceInfo.Type != eSourceListItemType.Off)
|
||||
|| (Display1SourceInfo != null
|
||||
&& Display1SourceInfo.Type != eSourceListItemType.Off)
|
||||
|| (Display2SourceInfo != null
|
||||
&& Display2SourceInfo.Type != eSourceListItemType.Off); } }
|
||||
|
||||
protected override Func<bool> IsWarmingFeedbackFunc { get { return () =>false;; } }
|
||||
protected override Func<bool> IsCoolingFeedbackFunc { get { return () => false; } }
|
||||
|
||||
public EssentialsPresentationRoomPropertiesConfig Config { get; private set; }
|
||||
|
||||
public Dictionary<uint, IRoutingSinkNoSwitching> Displays { get; private set; }
|
||||
|
||||
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
|
||||
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The config name of the source list
|
||||
/// </summary>
|
||||
public string SourceListKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If room is off, enables power on to last source. Default true
|
||||
/// </summary>
|
||||
public bool EnablePowerOnToLastSource { get; set; }
|
||||
string LastSourceKey;
|
||||
|
||||
public enum eVideoRoutingMode
|
||||
{
|
||||
SelectSourceSelectDisplay, SourceToAllDisplays
|
||||
}
|
||||
|
||||
public eVideoRoutingMode VideoRoutingMode { get; set; }
|
||||
|
||||
public enum eAudioRoutingMode
|
||||
{
|
||||
AudioFollowsLastVideo, SelectAudioFromDisplay
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public IBasicVolumeControls CurrentVolumeControls
|
||||
{
|
||||
get { return _CurrentAudioDevice; }
|
||||
set
|
||||
{
|
||||
if (value == _CurrentAudioDevice) return;
|
||||
|
||||
var oldDev = _CurrentAudioDevice;
|
||||
// derigister this room from the device, if it can
|
||||
if (oldDev is IInUseTracking)
|
||||
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
|
||||
var handler = CurrentVolumeDeviceChange;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
|
||||
_CurrentAudioDevice = value;
|
||||
if (handler != null)
|
||||
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
|
||||
// register this room with new device, if it can
|
||||
if (_CurrentAudioDevice is IInUseTracking)
|
||||
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
|
||||
}
|
||||
}
|
||||
IBasicVolumeControls _CurrentAudioDevice;
|
||||
|
||||
/// <summary>
|
||||
/// The SourceListItem last run - containing names and icons. The complex setter is
|
||||
/// to add/remove this room to the source's InUseTracking, if it is capable
|
||||
/// </summary>
|
||||
public SourceListItem CurrentSingleSourceInfo
|
||||
{
|
||||
get { return _CurrentSingleSourceInfo; }
|
||||
private set
|
||||
{
|
||||
if (value == _CurrentSingleSourceInfo) return;
|
||||
|
||||
var handler = CurrentSingleSourceChange;
|
||||
// remove from in-use tracker, if so equipped
|
||||
if(_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSingleSourceInfo, ChangeType.WillChange);
|
||||
|
||||
_CurrentSingleSourceInfo = value;
|
||||
|
||||
// add to in-use tracking
|
||||
if (_CurrentSingleSourceInfo != null && _CurrentSingleSourceInfo.SourceDevice is IInUseTracking)
|
||||
(_CurrentSingleSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
|
||||
if (handler != null)
|
||||
handler(this, _CurrentSingleSourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _CurrentSingleSourceInfo;
|
||||
|
||||
public SourceListItem Display1SourceInfo
|
||||
{
|
||||
get { return _Display1SourceInfo; }
|
||||
set
|
||||
{
|
||||
if (value == _Display1SourceInfo) return;
|
||||
|
||||
var handler = CurrentDisplay1SourceChange;
|
||||
if (handler != null)
|
||||
handler(this, _Display1SourceInfo, ChangeType.WillChange);
|
||||
|
||||
_Display1SourceInfo = value;
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _Display1SourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _Display1SourceInfo;
|
||||
|
||||
public SourceListItem Display2SourceInfo
|
||||
{
|
||||
get { return _Display2SourceInfo; }
|
||||
set
|
||||
{
|
||||
if (value == _Display2SourceInfo) return;
|
||||
|
||||
var handler = CurrentDisplay2SourceChange;
|
||||
if (handler != null)
|
||||
handler(this, _Display2SourceInfo, ChangeType.WillChange);
|
||||
|
||||
_Display2SourceInfo = value;
|
||||
|
||||
if (handler != null)
|
||||
handler(this, _Display2SourceInfo, ChangeType.DidChange);
|
||||
}
|
||||
}
|
||||
SourceListItem _Display2SourceInfo;
|
||||
|
||||
/// <summary>
|
||||
/// If an audio dialer is available for this room
|
||||
/// </summary>
|
||||
public bool HasAudioDialer { get { return false; } }
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsPresentationRoom(string key, string name,
|
||||
Dictionary<uint, IRoutingSinkNoSwitching> displays,
|
||||
IBasicVolumeWithFeedback defaultVolume, EssentialsPresentationRoomPropertiesConfig config)
|
||||
: base(key, name)
|
||||
{
|
||||
Config = config;
|
||||
Displays = displays;
|
||||
|
||||
DefaultVolumeControls = defaultVolume;
|
||||
CurrentVolumeControls = defaultVolume;
|
||||
|
||||
//DefaultAudioDevice = defaultAudio;
|
||||
//if (defaultAudio is IBasicVolumeControls)
|
||||
// DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
|
||||
//else if (defaultAudio is IHasVolumeDevice)
|
||||
// DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
|
||||
|
||||
|
||||
SourceListKey = "default";
|
||||
EnablePowerOnToLastSource = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Run the same source to all destinations
|
||||
/// </summary>
|
||||
/// <param name="sourceItem"></param>
|
||||
public void RouteSourceToAllDestinations(SourceListItem sourceItem)
|
||||
{
|
||||
if (Config.Volumes.Master != null)
|
||||
{
|
||||
var audioDev = DeviceManager.GetDeviceForKey(Config.Volumes.Master.DeviceKey);
|
||||
if (audioDev is IBasicVolumeWithFeedback)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var display in Displays.Values)
|
||||
{
|
||||
if (sourceItem != null)
|
||||
DoVideoRoute(sourceItem.SourceKey, display.Key);
|
||||
else
|
||||
DoVideoRoute("$off", display.Key);
|
||||
}
|
||||
Display1SourceInfo = sourceItem;
|
||||
Display2SourceInfo = sourceItem;
|
||||
CurrentSingleSourceInfo = sourceItem;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
public void SourceToDisplay1(SourceListItem sourceItem)
|
||||
{
|
||||
DoVideoRoute(sourceItem.SourceKey, Displays[1].Key);
|
||||
Display1SourceInfo = sourceItem;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
public void SourceToDisplay2(SourceListItem sourceItem)
|
||||
{
|
||||
DoVideoRoute(sourceItem.SourceKey, Displays[2].Key);
|
||||
Display2SourceInfo = sourceItem;
|
||||
OnFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Basic source -> destination routing
|
||||
/// </summary>
|
||||
void DoVideoRoute(string sourceKey, string destinationKey)
|
||||
{
|
||||
new CTimer(o =>
|
||||
{
|
||||
var dest = DeviceManager.GetDeviceForKey(destinationKey) as IRoutingSinkNoSwitching;
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route. Destination '{0}' not found", destinationKey);
|
||||
return;
|
||||
}
|
||||
// off is special case
|
||||
if (sourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
return;
|
||||
}
|
||||
|
||||
var source = DeviceManager.GetDeviceForKey(sourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route. Source '{0}' not found", sourceKey);
|
||||
return;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, eRoutingSignalType.Video);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected override void EndShutdown()
|
||||
{
|
||||
RunRouteAction("roomoff");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="routeKey"></param>
|
||||
public void RunRouteAction(string routeKey)
|
||||
{
|
||||
RunRouteAction(routeKey, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a source from config list SourceListKey and dynamically build and executes the
|
||||
/// route or commands
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public void RunRouteAction(string routeKey, Action successCallback)
|
||||
{
|
||||
// Run this on a separate thread
|
||||
new CTimer(o =>
|
||||
{
|
||||
Debug.Console(1, this, "Run room action '{0}'", routeKey);
|
||||
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
|
||||
if(dict == null)
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the list item by it's string key
|
||||
if (!dict.ContainsKey(routeKey))
|
||||
{
|
||||
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
|
||||
routeKey, SourceListKey);
|
||||
return;
|
||||
}
|
||||
|
||||
var item = dict[routeKey];
|
||||
//Debug.Console(2, this, "Action {0} has {1} steps",
|
||||
// item.SourceKey, item.RouteList.Count);
|
||||
|
||||
// Let's run it
|
||||
if (routeKey.ToLower() != "roomoff")
|
||||
LastSourceKey = routeKey;
|
||||
|
||||
foreach (var route in item.RouteList)
|
||||
{
|
||||
// if there is a $defaultAll on route, run two separate
|
||||
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var tempAudio = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultDisplay",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Video
|
||||
};
|
||||
DoRoute(tempAudio);
|
||||
|
||||
var tempVideo = new SourceRouteListItem
|
||||
{
|
||||
DestinationKey = "$defaultAudio",
|
||||
SourceKey = route.SourceKey,
|
||||
Type = eRoutingSignalType.Audio
|
||||
};
|
||||
DoRoute(tempVideo);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
DoRoute(route);
|
||||
}
|
||||
|
||||
// Set volume control on room, using default if non provided
|
||||
IBasicVolumeControls volDev = null;
|
||||
// Handle special cases for volume control
|
||||
if (string.IsNullOrEmpty(item.VolumeControlKey)
|
||||
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
|
||||
volDev = DefaultVolumeControls;
|
||||
//else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
// volDev = DefaultDisplay as IBasicVolumeControls;
|
||||
// Or a specific device, probably rarely used.
|
||||
else
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
|
||||
if (dev is IBasicVolumeControls)
|
||||
volDev = dev as IBasicVolumeControls;
|
||||
else if (dev is IHasVolumeDevice)
|
||||
volDev = (dev as IHasVolumeDevice).VolumeDevice;
|
||||
}
|
||||
CurrentVolumeControls = volDev;
|
||||
|
||||
// store the name and UI info for routes
|
||||
if (item.SourceKey != null)
|
||||
CurrentSingleSourceInfo = item;
|
||||
// And finally, set the "control". This will trigger event
|
||||
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
|
||||
|
||||
OnFeedback.FireUpdate();
|
||||
|
||||
// report back when done
|
||||
if (successCallback != null)
|
||||
successCallback();
|
||||
}, 0); // end of CTimer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Will power the room on with the last-used source
|
||||
/// </summary>
|
||||
public void PowerOnToDefaultOrLastSource()
|
||||
{
|
||||
if (!EnablePowerOnToLastSource || LastSourceKey == null)
|
||||
return;
|
||||
RunRouteAction(LastSourceKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does what it says
|
||||
/// </summary>
|
||||
public override void SetDefaultLevels()
|
||||
{
|
||||
Debug.Console(0, this, "SetDefaultLevels not implemented");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="route"></param>
|
||||
/// <returns></returns>
|
||||
bool DoRoute(SourceRouteListItem route)
|
||||
{
|
||||
IRoutingSinkNoSwitching dest = null;
|
||||
|
||||
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
|
||||
dest = DefaultAudioDevice;
|
||||
//else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
|
||||
// dest = DefaultDisplay;
|
||||
else
|
||||
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
|
||||
|
||||
if (dest == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
dest.ReleaseRoute();
|
||||
if (dest is IPower)
|
||||
(dest as IPower).PowerOff();
|
||||
}
|
||||
else
|
||||
{
|
||||
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
|
||||
if (source == null)
|
||||
{
|
||||
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
|
||||
return false;
|
||||
}
|
||||
dest.ReleaseAndMakeRoute(source, route.Type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void RoomVacatedForTimeoutPeriod(object o)
|
||||
{
|
||||
//Implement this
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
272
PepperDashEssentials/Room/Types/EssentialsRoomBase.cs
Normal file
272
PepperDashEssentials/Room/Types/EssentialsRoomBase.cs
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Devices.Common.Occupancy;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public interface IHasCurrentSourceInfoChange
|
||||
{
|
||||
event SourceInfoChangeHandler CurrentSingleSourceChange;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class EssentialsRoomBase : Device
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public BoolFeedback OnFeedback { get; private set; }
|
||||
|
||||
public BoolFeedback IsWarmingUpFeedback { get; private set; }
|
||||
public BoolFeedback IsCoolingDownFeedback { get; private set; }
|
||||
|
||||
public IOccupancyStatusProvider RoomOccupancy { get; private set; }
|
||||
|
||||
public bool OccupancyStatusProviderIsRemote { get; private set; }
|
||||
|
||||
protected abstract Func<bool> IsWarmingFeedbackFunc { get; }
|
||||
protected abstract Func<bool> IsCoolingFeedbackFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Timer used for informing the UIs of a shutdown
|
||||
/// </summary>
|
||||
public SecondsCountdownTimer ShutdownPromptTimer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int ShutdownPromptSeconds { get; set; }
|
||||
public int ShutdownVacancySeconds { get; set; }
|
||||
public eShutdownType ShutdownType { get; private set; }
|
||||
|
||||
public PepperDash.Essentials.Room.EssentialsRoomEmergencyBase Emergency { get; set; }
|
||||
|
||||
public PepperDash.Essentials.Devices.Common.Microphones.MicrophonePrivacyController MicrophonePrivacy { get; set; }
|
||||
|
||||
public string LogoUrl { get; set; }
|
||||
|
||||
protected SecondsCountdownTimer RoomVacancyShutdownTimer { get; private set; }
|
||||
|
||||
public eVacancyMode VacancyMode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Seconds after vacancy prompt is displayed until shutdown
|
||||
/// </summary>
|
||||
protected int RoomVacancyShutdownSeconds;
|
||||
|
||||
/// <summary>
|
||||
/// Seconds after vacancy detected until prompt is displayed
|
||||
/// </summary>
|
||||
protected int RoomVacancyShutdownPromptSeconds;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected abstract Func<bool> OnFeedbackFunc { get; }
|
||||
|
||||
protected Dictionary<IBasicVolumeWithFeedback, uint> SavedVolumeLevels = new Dictionary<IBasicVolumeWithFeedback, uint>();
|
||||
|
||||
/// <summary>
|
||||
/// When volume control devices change, should we zero the one that we are leaving?
|
||||
/// </summary>
|
||||
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="name"></param>
|
||||
public EssentialsRoomBase(string key, string name) : base(key, name)
|
||||
{
|
||||
// Setup the ShutdownPromptTimer
|
||||
ShutdownPromptTimer = new SecondsCountdownTimer(Key + "-offTimer");
|
||||
ShutdownPromptTimer.IsRunningFeedback.OutputChange += (o, a) =>
|
||||
{
|
||||
if (!ShutdownPromptTimer.IsRunningFeedback.BoolValue)
|
||||
ShutdownType = eShutdownType.None;
|
||||
};
|
||||
ShutdownPromptTimer.HasFinished += (o, a) => Shutdown(); // Shutdown is triggered
|
||||
|
||||
ShutdownPromptSeconds = 60;
|
||||
ShutdownVacancySeconds = 120;
|
||||
ShutdownType = eShutdownType.None;
|
||||
|
||||
RoomVacancyShutdownTimer = new SecondsCountdownTimer(Key + "-vacancyOffTimer");
|
||||
//RoomVacancyShutdownTimer.IsRunningFeedback.OutputChange += (o, a) =>
|
||||
//{
|
||||
// if (!RoomVacancyShutdownTimer.IsRunningFeedback.BoolValue)
|
||||
// ShutdownType = ShutdownType.Vacancy;
|
||||
//};
|
||||
RoomVacancyShutdownTimer.HasFinished += new EventHandler<EventArgs>(RoomVacancyShutdownPromptTimer_HasFinished); // Shutdown is triggered
|
||||
|
||||
RoomVacancyShutdownPromptSeconds = 1500; // 25 min to prompt warning
|
||||
RoomVacancyShutdownSeconds = 240; // 4 min after prompt will trigger shutdown prompt
|
||||
VacancyMode = eVacancyMode.None;
|
||||
|
||||
OnFeedback = new BoolFeedback(OnFeedbackFunc);
|
||||
|
||||
IsWarmingUpFeedback = new BoolFeedback(IsWarmingFeedbackFunc);
|
||||
IsCoolingDownFeedback = new BoolFeedback(IsCoolingFeedbackFunc);
|
||||
}
|
||||
|
||||
void RoomVacancyShutdownPromptTimer_HasFinished(object sender, EventArgs e)
|
||||
{
|
||||
switch (VacancyMode)
|
||||
{
|
||||
case eVacancyMode.None:
|
||||
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
|
||||
break;
|
||||
case eVacancyMode.InInitialVacancy:
|
||||
StartRoomVacancyTimer(eVacancyMode.InShutdownWarning);
|
||||
break;
|
||||
case eVacancyMode.InShutdownWarning:
|
||||
{
|
||||
StartShutdown(eShutdownType.Vacancy);
|
||||
Debug.Console(0, this, "Shutting Down due to vacancy.");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
public void StartShutdown(eShutdownType type)
|
||||
{
|
||||
// Check for shutdowns running. Manual should override other shutdowns
|
||||
|
||||
if (type == eShutdownType.Manual)
|
||||
ShutdownPromptTimer.SecondsToCount = ShutdownPromptSeconds;
|
||||
else if (type == eShutdownType.Vacancy)
|
||||
ShutdownPromptTimer.SecondsToCount = ShutdownVacancySeconds;
|
||||
ShutdownType = type;
|
||||
ShutdownPromptTimer.Start();
|
||||
}
|
||||
|
||||
public void StartRoomVacancyTimer(eVacancyMode mode)
|
||||
{
|
||||
if (mode == eVacancyMode.None)
|
||||
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownPromptSeconds;
|
||||
else if (mode == eVacancyMode.InInitialVacancy)
|
||||
RoomVacancyShutdownTimer.SecondsToCount = RoomVacancyShutdownSeconds;
|
||||
VacancyMode = mode;
|
||||
RoomVacancyShutdownTimer.Start();
|
||||
|
||||
Debug.Console(0, this, "Vacancy Timer Started.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the vacancy mode and shutsdwon the room
|
||||
/// </summary>
|
||||
public void Shutdown()
|
||||
{
|
||||
VacancyMode = eVacancyMode.None;
|
||||
EndShutdown();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method is for the derived class to define it's specific shutdown
|
||||
/// requirements but should not be called directly. It is called by Shutdown()
|
||||
/// </summary>
|
||||
protected abstract void EndShutdown();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Override this to implement a default volume level(s) method
|
||||
/// </summary>
|
||||
public abstract void SetDefaultLevels();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the object to be used as the IOccupancyStatusProvider for the room. Can be an Occupancy Aggregator or a specific device
|
||||
/// </summary>
|
||||
/// <param name="statusProvider"></param>
|
||||
public void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes)
|
||||
{
|
||||
if (statusProvider == null)
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Occupancy sensor device is null");
|
||||
return;
|
||||
}
|
||||
|
||||
// If status provider is fusion, set flag to remote
|
||||
if (statusProvider is PepperDash.Essentials.Fusion.EssentialsHuddleSpaceFusionSystemControllerBase)
|
||||
OccupancyStatusProviderIsRemote = true;
|
||||
|
||||
if(timeoutMinutes > 0)
|
||||
RoomVacancyShutdownSeconds = timeoutMinutes * 60;
|
||||
|
||||
RoomOccupancy = statusProvider;
|
||||
|
||||
RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange;
|
||||
}
|
||||
|
||||
void RoomIsOccupiedFeedback_OutputChange(object sender, EventArgs e)
|
||||
{
|
||||
if (RoomOccupancy.RoomIsOccupiedFeedback.BoolValue == false)
|
||||
{
|
||||
Debug.Console(1, this, "Notice: Vacancy Detected");
|
||||
// Trigger the timer when the room is vacant
|
||||
StartRoomVacancyTimer(eVacancyMode.InInitialVacancy);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(1, this, "Notice: Occupancy Detected");
|
||||
// Reset the timer when the room is occupied
|
||||
|
||||
RoomVacancyShutdownTimer.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
//void SwapVolumeDevices(IBasicVolumeControls currentDevice, IBasicVolumeControls newDevice)
|
||||
//{
|
||||
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Executes when RoomVacancyShutdownTimer expires. Used to trigger specific room actions as needed. Must nullify the timer object when executed
|
||||
/// </summary>
|
||||
/// <param name="o"></param>
|
||||
public abstract void RoomVacatedForTimeoutPeriod(object o);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// To describe the various ways a room may be shutting down
|
||||
/// </summary>
|
||||
public enum eShutdownType
|
||||
{
|
||||
None = 0,
|
||||
External,
|
||||
Manual,
|
||||
Vacancy
|
||||
}
|
||||
|
||||
public enum eVacancyMode
|
||||
{
|
||||
None = 0,
|
||||
InInitialVacancy,
|
||||
InShutdownWarning
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public enum eWarmingCoolingMode
|
||||
{
|
||||
None,
|
||||
Warming,
|
||||
Cooling
|
||||
}
|
||||
}
|
||||
19813
PepperDashEssentials/SGD/PepperDash Essentials TSW-560.sgd
Normal file
19813
PepperDashEssentials/SGD/PepperDash Essentials TSW-560.sgd
Normal file
File diff suppressed because it is too large
Load diff
16137
PepperDashEssentials/SGD/PepperDash Essentials TSW-760.sgd
Normal file
16137
PepperDashEssentials/SGD/PepperDash Essentials TSW-760.sgd
Normal file
File diff suppressed because it is too large
Load diff
20901
PepperDashEssentials/SGD/PepperDash Essentials iPad.sgd
Normal file
20901
PepperDashEssentials/SGD/PepperDash Essentials iPad.sgd
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,33 @@
|
|||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CrestronTouchpanelPropertiesConfig
|
||||
{
|
||||
public string IpId { get; set; }
|
||||
public string DefaultRoomKey { get; set; }
|
||||
public string RoomListKey { get; set; }
|
||||
public string SgdFile { get; set; }
|
||||
public string ProjectName { get; set; }
|
||||
public bool ShowVolumeGauge { get; set; }
|
||||
public bool UsesSplashPage { get; set; }
|
||||
public bool ShowDate { get; set; }
|
||||
public bool ShowTime { get; set; }
|
||||
public UiSetupPropertiesConfig Setup { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The count of sources that will trigger the "additional" arrows to show on the SRL.
|
||||
/// Defaults to 5
|
||||
/// </summary>
|
||||
public int SourcesOverflowCount { get; set; }
|
||||
|
||||
public CrestronTouchpanelPropertiesConfig()
|
||||
{
|
||||
SourcesOverflowCount = 5;
|
||||
}
|
||||
}
|
||||
|
||||
public class UiSetupPropertiesConfig
|
||||
{
|
||||
public bool IsVisible { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
//using Crestron.SimplSharpPro.UI;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class DualDisplaySourceSRLController : SubpageReferenceList
|
||||
// {
|
||||
// public DualDisplaySourceSRLController(BasicTriListWithSmartObject triList,
|
||||
// uint smartObjectId, EssentialsPresentationRoom room)
|
||||
// : base(triList, smartObjectId, 3, 3, 3)
|
||||
// {
|
||||
// var srcList = room.s items.Values.ToList().OrderBy(s => s.Order);
|
||||
// foreach (var item in srcList)
|
||||
// {
|
||||
// GetBoolFeedbackSig(index, 1).UserObject = new Action<bool>(routeAction);
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.PageManagers;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsTouchpanelController : Device
|
||||
{
|
||||
public BasicTriListWithSmartObject Panel { get; private set; }
|
||||
|
||||
public PanelDriverBase PanelDriver { get; private set; }
|
||||
|
||||
CTimer BacklightTransitionedOnTimer;
|
||||
|
||||
public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw,
|
||||
string projectName, string sgdPath)
|
||||
: base(key, name)
|
||||
{
|
||||
Panel = tsw;
|
||||
tsw.LoadSmartObjects(sgdPath);
|
||||
tsw.SigChange += new Crestron.SimplSharpPro.DeviceSupport.SigEventHandler(Tsw_SigChange);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Config constructor
|
||||
/// </summary>
|
||||
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
|
||||
: base(key, name)
|
||||
{
|
||||
AddPostActivationAction(() =>
|
||||
{
|
||||
Debug.Console(0, this, "post-activation linking");
|
||||
type = type.ToLower();
|
||||
try
|
||||
{
|
||||
if (type == "crestronapp")
|
||||
{
|
||||
var app = new CrestronApp(id, Global.ControlSystem);
|
||||
app.ParameterProjectName.Value = props.ProjectName;
|
||||
Panel = app;
|
||||
}
|
||||
else if (type == "tsw560")
|
||||
Panel = new Tsw560(id, Global.ControlSystem);
|
||||
else if (type == "tsw752")
|
||||
Panel = new Tsw752(id, Global.ControlSystem);
|
||||
else if (type == "tsw1052")
|
||||
Panel = new Tsw1052(id, Global.ControlSystem);
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "WARNING: Cannot create TSW controller with type '{0}'", type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reserved sigs
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
tsw.ExtenderSystemReservedSigs.Use();
|
||||
tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
|
||||
+= ExtenderSystemReservedSigs_DeviceExtenderSigChange;
|
||||
}
|
||||
|
||||
new CTimer(o =>
|
||||
{
|
||||
var regSuccess = Panel.Register();
|
||||
if (regSuccess != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
Debug.Console(0, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", regSuccess);
|
||||
|
||||
// Give up cleanly if SGD is not present.
|
||||
var sgdName = @"\NVRAM\Program" + InitialParametersClass.ApplicationNumber
|
||||
+ @"\sgd\" + props.SgdFile;
|
||||
if (!File.Exists(sgdName))
|
||||
{
|
||||
Debug.Console(0, this, "WARNING: Smart object file '{0}' not present. Exiting TSW load", sgdName);
|
||||
return;
|
||||
}
|
||||
|
||||
Panel.LoadSmartObjects(sgdName);
|
||||
Panel.SigChange += Tsw_SigChange;
|
||||
|
||||
var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, props);
|
||||
// Then the AV driver
|
||||
|
||||
// spin up different room drivers depending on room type
|
||||
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
|
||||
if (room is EssentialsHuddleSpaceRoom)
|
||||
{
|
||||
Debug.Console(0, this, "Adding huddle space driver");
|
||||
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
|
||||
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
LoadAndShowDriver(mainDriver); // This is a little convoluted.
|
||||
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
|
||||
}
|
||||
}
|
||||
else if (room is EssentialsPresentationRoom)
|
||||
{
|
||||
Debug.Console(0, this, "Adding presentation room driver");
|
||||
var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
|
||||
avDriver.CurrentRoom = room as EssentialsPresentationRoom;
|
||||
avDriver.DefaultRoomKey = props.DefaultRoomKey;
|
||||
mainDriver.AvDriver = avDriver;
|
||||
LoadAndShowDriver(mainDriver);
|
||||
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
// Wire up hard keys
|
||||
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
|
||||
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
|
||||
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
|
||||
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
|
||||
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
|
||||
}
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
public void LoadAndShowDriver(PanelDriverBase driver)
|
||||
{
|
||||
PanelDriver = driver;
|
||||
driver.Show();
|
||||
}
|
||||
|
||||
void HomePressed()
|
||||
{
|
||||
if (BacklightTransitionedOnTimer == null)
|
||||
PanelDriver.BackButtonPressed();
|
||||
}
|
||||
|
||||
|
||||
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
|
||||
{
|
||||
// If the sig is transitioning on, mark it in case it was home button that transitioned it
|
||||
var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback;
|
||||
if (args.Sig == blOnSig && blOnSig.BoolValue)
|
||||
{
|
||||
BacklightTransitionedOnTimer = new CTimer(o =>
|
||||
{
|
||||
BacklightTransitionedOnTimer = null;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
public void PulseBool(uint join)
|
||||
{
|
||||
var act = Panel.BooleanInput[join].UserObject as Action<bool>;
|
||||
if (act != null)
|
||||
{
|
||||
act(true);
|
||||
act(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBoolSig(uint join, bool value)
|
||||
{
|
||||
var act = Panel.BooleanInput[join].UserObject as Action<bool>;
|
||||
if (act != null)
|
||||
act(value);
|
||||
}
|
||||
|
||||
public void SetIntSig(uint join, ushort value)
|
||||
{
|
||||
var act = Panel.BooleanInput[join].UserObject as Action<ushort>;
|
||||
if (act != null)
|
||||
{
|
||||
act(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Tsw_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
||||
var uo = args.Sig.UserObject;
|
||||
if (uo is Action<bool>)
|
||||
(uo as Action<bool>)(args.Sig.BoolValue);
|
||||
else if (uo is Action<ushort>)
|
||||
(uo as Action<ushort>)(args.Sig.UShortValue);
|
||||
else if (uo is Action<string>)
|
||||
(uo as Action<string>)(args.Sig.StringValue);
|
||||
}
|
||||
|
||||
void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
|
||||
{
|
||||
var uo = args.Button.UserObject;
|
||||
if(uo is Action<bool>)
|
||||
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class SubpageReferenceListActivityItem : SubpageReferenceListItem
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="owner"></param>
|
||||
/// <param name="buttonMode">0=Share, 1=Phone Call, 2=Video Call, 3=End Meeting</param>
|
||||
/// <param name="pressAction"></param>
|
||||
public SubpageReferenceListActivityItem(uint index, SubpageReferenceList owner,
|
||||
ushort buttonMode, Action<bool> pressAction)
|
||||
: base(index, owner)
|
||||
{
|
||||
Owner.GetBoolFeedbackSig(Index, 1).UserObject = pressAction;
|
||||
Owner.UShortInputSig(Index, 1).UShortValue = buttonMode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by SRL to release all referenced objects
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
Owner.BoolInputSig(Index, 1).UserObject = null;
|
||||
Owner.UShortInputSig(Index, 1).UShortValue = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class SubpageReferenceListSourceItem : SubpageReferenceListItem
|
||||
{
|
||||
public SourceListItem SourceItem { get; private set; }
|
||||
|
||||
public SubpageReferenceListSourceItem(uint index, SubpageReferenceList owner,
|
||||
SourceListItem sourceItem, Action<bool> routeAction)
|
||||
: base(index, owner)
|
||||
{
|
||||
SourceItem = sourceItem;
|
||||
owner.GetBoolFeedbackSig(index, 1).UserObject = new Action<bool>(routeAction);
|
||||
owner.StringInputSig(index, 1).StringValue = SourceItem.PreferredName;
|
||||
}
|
||||
|
||||
public void RegisterForSourceChange(IHasCurrentSourceInfoChange room)
|
||||
{
|
||||
room.CurrentSingleSourceChange -= room_CurrentSourceInfoChange;
|
||||
room.CurrentSingleSourceChange += room_CurrentSourceInfoChange;
|
||||
}
|
||||
|
||||
void room_CurrentSourceInfoChange(EssentialsRoomBase room, SourceListItem info, ChangeType type)
|
||||
{
|
||||
if (type == ChangeType.WillChange && info == SourceItem)
|
||||
ClearFeedback();
|
||||
else if (type == ChangeType.DidChange && info == SourceItem)
|
||||
SetFeedback();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by SRL to release all referenced objects
|
||||
/// </summary>
|
||||
public override void Clear()
|
||||
{
|
||||
Owner.BoolInputSig(Index, 1).UserObject = null;
|
||||
Owner.StringInputSig(Index, 1).StringValue = "";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the selected feedback on the button
|
||||
/// </summary>
|
||||
public void SetFeedback()
|
||||
{
|
||||
Owner.BoolInputSig(Index, 1).BoolValue = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the selected feedback on the button
|
||||
/// </summary>
|
||||
public void ClearFeedback()
|
||||
{
|
||||
Owner.BoolInputSig(Index, 1).BoolValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class CrestronTouchpanelPropertiesConfig
|
||||
{
|
||||
public string IpId { get; set; }
|
||||
public string DefaultRoomKey { get; set; }
|
||||
public string RoomListKey { get; set; }
|
||||
public string SgdFile { get; set; }
|
||||
public string ProjectName { get; set; }
|
||||
public bool ShowVolumeGauge { get; set; }
|
||||
public bool UsesSplashPage { get; set; }
|
||||
public bool ShowDate { get; set; }
|
||||
public bool ShowTime { get; set; }
|
||||
public UiSetupPropertiesConfig Setup { get; set; }
|
||||
public string HeaderStyle { get; set; }
|
||||
public bool IncludeInFusionRoomHealth { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The count of sources that will trigger the "additional" arrows to show on the SRL.
|
||||
/// Defaults to 5
|
||||
/// </summary>
|
||||
public int SourcesOverflowCount { get; set; }
|
||||
|
||||
public CrestronTouchpanelPropertiesConfig()
|
||||
{
|
||||
SourcesOverflowCount = 5;
|
||||
HeaderStyle = CrestronTouchpanelPropertiesConfig.Habanero;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "habanero"
|
||||
/// </summary>
|
||||
public const string Habanero = "habanero";
|
||||
/// <summary>
|
||||
/// "verbose"
|
||||
/// </summary>
|
||||
public const string Verbose = "verbose";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class UiSetupPropertiesConfig
|
||||
{
|
||||
public bool IsVisible { get; set; }
|
||||
}
|
||||
}
|
||||
28
PepperDashEssentials/UI/DualDisplaySourceSRLController.cs
Normal file
28
PepperDashEssentials/UI/DualDisplaySourceSRLController.cs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Text;
|
||||
//using Crestron.SimplSharp;
|
||||
//using Crestron.SimplSharpPro;
|
||||
//using Crestron.SimplSharpPro.DeviceSupport;
|
||||
//using Crestron.SimplSharpPro.UI;
|
||||
|
||||
//using PepperDash.Essentials.Core;
|
||||
|
||||
//namespace PepperDash.Essentials
|
||||
//{
|
||||
// public class DualDisplaySourceSRLController : SubpageReferenceList
|
||||
// {
|
||||
// public DualDisplaySourceSRLController(BasicTriListWithSmartObject triList,
|
||||
// uint smartObjectId, EssentialsPresentationRoom room)
|
||||
// : base(triList, smartObjectId, 3, 3, 3)
|
||||
// {
|
||||
// var srcList = room.s items.Values.ToList().OrderBy(s => s.Order);
|
||||
// foreach (var item in srcList)
|
||||
// {
|
||||
// GetBoolFeedbackSig(index, 1).UserObject = new Action<bool>(routeAction);
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
181
PepperDashEssentials/UI/EssentialsTouchpanelController.cs
Normal file
181
PepperDashEssentials/UI/EssentialsTouchpanelController.cs
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.PageManagers;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class EssentialsTouchpanelController : Device
|
||||
{
|
||||
public BasicTriListWithSmartObject Panel { get; private set; }
|
||||
|
||||
public PanelDriverBase PanelDriver { get; private set; }
|
||||
|
||||
CTimer BacklightTransitionedOnTimer;
|
||||
|
||||
public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw,
|
||||
string projectName, string sgdPath)
|
||||
: base(key, name)
|
||||
{
|
||||
Panel = tsw;
|
||||
tsw.LoadSmartObjects(sgdPath);
|
||||
tsw.SigChange += new Crestron.SimplSharpPro.DeviceSupport.SigEventHandler(Tsw_SigChange);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Config constructor
|
||||
/// </summary>
|
||||
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
|
||||
: base(key, name)
|
||||
{
|
||||
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Creating touchpanel hardware...");
|
||||
type = type.ToLower();
|
||||
try
|
||||
{
|
||||
if (type == "crestronapp")
|
||||
{
|
||||
var app = new CrestronApp(id, Global.ControlSystem);
|
||||
app.ParameterProjectName.Value = props.ProjectName;
|
||||
Panel = app;
|
||||
}
|
||||
else if (type == "tsw550")
|
||||
Panel = new Tsw550(id, Global.ControlSystem);
|
||||
else if (type == "tsw552")
|
||||
Panel = new Tsw552(id, Global.ControlSystem);
|
||||
else if (type == "tsw560")
|
||||
Panel = new Tsw560(id, Global.ControlSystem);
|
||||
else if (type == "tsw750")
|
||||
Panel = new Tsw750(id, Global.ControlSystem);
|
||||
else if (type == "tsw752")
|
||||
Panel = new Tsw752(id, Global.ControlSystem);
|
||||
else if (type == "tsw760")
|
||||
Panel = new Tsw760(id, Global.ControlSystem);
|
||||
else if (type == "tsw1050")
|
||||
Panel = new Tsw1050(id, Global.ControlSystem);
|
||||
else if (type == "tsw1052")
|
||||
Panel = new Tsw1052(id, Global.ControlSystem);
|
||||
else if (type == "tsw1060")
|
||||
Panel = new Tsw1060(id, Global.ControlSystem);
|
||||
else
|
||||
{
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW controller with type '{0}'", type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reserved sigs
|
||||
if (Panel is TswFt5ButtonSystem)
|
||||
{
|
||||
var tsw = Panel as TswFt5ButtonSystem;
|
||||
tsw.ExtenderSystemReservedSigs.Use();
|
||||
tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
|
||||
+= ExtenderSystemReservedSigs_DeviceExtenderSigChange;
|
||||
|
||||
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
|
||||
|
||||
}
|
||||
|
||||
if (Panel.Register() != eDeviceRegistrationUnRegistrationResponse.Success)
|
||||
Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "WARNING: Registration failed. Continuing, but panel may not function: {0}", Panel.RegistrationFailureReason);
|
||||
|
||||
// Give up cleanly if SGD is not present.
|
||||
var sgdName = Global.FilePathPrefix
|
||||
+ Global.DirectorySeparator + "sgd" + Global.DirectorySeparator + props.SgdFile;
|
||||
if (!File.Exists(sgdName))
|
||||
{
|
||||
Debug.Console(0, this, "ERROR: Smart object file '{0}' not present. Exiting TSW load", sgdName);
|
||||
return;
|
||||
}
|
||||
|
||||
Panel.LoadSmartObjects(sgdName);
|
||||
Panel.SigChange += Tsw_SigChange;
|
||||
|
||||
}
|
||||
|
||||
public void LoadAndShowDriver(PanelDriverBase driver)
|
||||
{
|
||||
PanelDriver = driver;
|
||||
driver.Show();
|
||||
}
|
||||
|
||||
void HomePressed()
|
||||
{
|
||||
if (BacklightTransitionedOnTimer == null)
|
||||
PanelDriver.BackButtonPressed();
|
||||
}
|
||||
|
||||
|
||||
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
|
||||
{
|
||||
// If the sig is transitioning on, mark it in case it was home button that transitioned it
|
||||
var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback;
|
||||
if (args.Sig == blOnSig && blOnSig.BoolValue)
|
||||
{
|
||||
BacklightTransitionedOnTimer = new CTimer(o =>
|
||||
{
|
||||
BacklightTransitionedOnTimer = null;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
public void PulseBool(uint join)
|
||||
{
|
||||
var act = Panel.BooleanInput[join].UserObject as Action<bool>;
|
||||
if (act != null)
|
||||
{
|
||||
act(true);
|
||||
act(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetBoolSig(uint join, bool value)
|
||||
{
|
||||
var act = Panel.BooleanInput[join].UserObject as Action<bool>;
|
||||
if (act != null)
|
||||
act(value);
|
||||
}
|
||||
|
||||
public void SetIntSig(uint join, ushort value)
|
||||
{
|
||||
var act = Panel.BooleanInput[join].UserObject as Action<ushort>;
|
||||
if (act != null)
|
||||
{
|
||||
act(value);
|
||||
}
|
||||
}
|
||||
|
||||
void Tsw_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
|
||||
{
|
||||
if (Debug.Level == 2)
|
||||
Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
|
||||
var uo = args.Sig.UserObject;
|
||||
if (uo is Action<bool>)
|
||||
(uo as Action<bool>)(args.Sig.BoolValue);
|
||||
else if (uo is Action<ushort>)
|
||||
(uo as Action<ushort>)(args.Sig.UShortValue);
|
||||
else if (uo is Action<string>)
|
||||
(uo as Action<string>)(args.Sig.StringValue);
|
||||
}
|
||||
|
||||
void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
|
||||
{
|
||||
var uo = args.Button.UserObject;
|
||||
if(uo is Action<bool>)
|
||||
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
108
PepperDashEssentials/UI/HttpLogoServer.cs
Normal file
108
PepperDashEssentials/UI/HttpLogoServer.cs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
|
||||
using PepperDash.Core;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class HttpLogoServer
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
HttpServer Server;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
string FileDirectory;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public static Dictionary<string, string> ExtensionContentTypes;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
/// <param name="directory"></param>
|
||||
public HttpLogoServer(int port, string directory)
|
||||
{
|
||||
ExtensionContentTypes = new Dictionary<string, string>
|
||||
{
|
||||
//{ ".css", "text/css" },
|
||||
//{ ".htm", "text/html" },
|
||||
//{ ".html", "text/html" },
|
||||
{ ".jpg", "image/jpeg" },
|
||||
{ ".jpeg", "image/jpeg" },
|
||||
//{ ".js", "application/javascript" },
|
||||
//{ ".json", "application/json" },
|
||||
//{ ".map", "application/x-navimap" },
|
||||
{ ".pdf", "application.pdf" },
|
||||
{ ".png", "image/png" },
|
||||
//{ ".txt", "text/plain" },
|
||||
};
|
||||
|
||||
Server = new HttpServer();
|
||||
Server.Port = port;
|
||||
FileDirectory = directory;
|
||||
Server.OnHttpRequest += new OnHttpRequestHandler(Server_OnHttpRequest);
|
||||
Server.Open();
|
||||
|
||||
CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void Server_OnHttpRequest(object sender, OnHttpRequestArgs args)
|
||||
{
|
||||
var path = args.Request.Path;
|
||||
if (File.Exists(FileDirectory + @"\" + path))
|
||||
{
|
||||
string filePath = path.Replace('/', '\\');
|
||||
string localPath = string.Format(@"{0}{1}", FileDirectory, filePath);
|
||||
if (File.Exists(localPath))
|
||||
{
|
||||
args.Response.Header.ContentType = GetContentType(new FileInfo(localPath).Extension);
|
||||
args.Response.ContentStream = new FileStream(localPath, FileMode.Open, FileAccess.Read);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Response.ContentString = string.Format("Not found: '{0}'", filePath);
|
||||
args.Response.Code = 404;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
|
||||
{
|
||||
if (programEventType == eProgramStatusEventType.Stopping)
|
||||
Server.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="extension"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetContentType(string extension)
|
||||
{
|
||||
string type;
|
||||
if (ExtensionContentTypes.ContainsKey(extension))
|
||||
type = ExtensionContentTypes[extension];
|
||||
else
|
||||
type = "text/plain";
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
813
PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
Normal file
813
PepperDashEssentials/UI/JoinConstants/UIBoolJoin.cs
Normal file
|
|
@ -0,0 +1,813 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
{
|
||||
/// <summary>
|
||||
/// Where all UI element common joins are defined
|
||||
/// </summary>
|
||||
public class UIBoolJoin
|
||||
{
|
||||
/// <summary>
|
||||
/// 901
|
||||
/// </summary>
|
||||
public const uint VolumeUpPress = 901;
|
||||
/// <summary>
|
||||
/// 902
|
||||
/// </summary>
|
||||
public const uint VolumeDownPress = 902;
|
||||
|
||||
//****************************************************
|
||||
// Codec General
|
||||
|
||||
/// <summary>
|
||||
/// 1001
|
||||
/// </summary>
|
||||
public const uint CallEndPress = 1001;
|
||||
/// <summary>
|
||||
/// 1002
|
||||
/// </summary>
|
||||
public const uint CallEndAllConfirmPress = 1002;
|
||||
/// <summary>
|
||||
/// 1003 - For tapping the text field to reveal the keyboard
|
||||
/// </summary>
|
||||
public const uint CodecDirectorySearchTextPress = 1003;
|
||||
/// <summary>
|
||||
/// 1004
|
||||
/// </summary>
|
||||
public const uint CallStopSharingPress = 1004;
|
||||
/// <summary>
|
||||
/// 1005
|
||||
/// </summary>
|
||||
public const uint CallSharedSourceInfoVisible = 1005;
|
||||
/// <summary>
|
||||
/// 1006
|
||||
/// </summary>
|
||||
public const uint CallEndAllConfirmVisible = 1006;
|
||||
|
||||
|
||||
|
||||
// Audio Conference
|
||||
/// <summary>
|
||||
/// 1101
|
||||
/// </summary>
|
||||
public const uint ACKeypadVisible = 1101;
|
||||
/// <summary>
|
||||
/// 1102
|
||||
/// </summary>
|
||||
public const uint ACStagingPopoverVisible = 1102;
|
||||
/// <summary>
|
||||
/// 1111
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial1Press = 1111;
|
||||
/// <summary>
|
||||
/// 1112
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial2Press = 1112;
|
||||
/// <summary>
|
||||
/// 1113
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial3Press = 1113;
|
||||
/// <summary>
|
||||
/// 1114
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial4Press = 1114;
|
||||
/// <summary>
|
||||
/// 1121
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial1Visible = 1121;
|
||||
/// <summary>
|
||||
/// 1122
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial2Visible = 1122;
|
||||
/// <summary>
|
||||
/// 1123
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial3Visible = 1123;
|
||||
/// <summary>
|
||||
/// 1124
|
||||
/// </summary>
|
||||
public const uint ACSpeedDial4Visible = 1124;
|
||||
|
||||
//******************************************************
|
||||
// Video Conference
|
||||
/// <summary>
|
||||
/// 1201
|
||||
/// </summary>
|
||||
public const uint VCKeypadWithFavoritesVisible = 1201;
|
||||
/// <summary>
|
||||
/// 1202
|
||||
/// </summary>
|
||||
public const uint VCStagingInactivePopoverVisible = 1202;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public const uint VCStagingActivePopoverVisible = 1203;
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public const uint VCKeypadVisible = 1204;
|
||||
/// <summary>
|
||||
/// 1205
|
||||
/// </summary>
|
||||
public const uint VCDirectoryVisible = 1205;
|
||||
/// <summary>
|
||||
/// 1206
|
||||
/// </summary>
|
||||
public const uint VCRecentsVisible = 1206;
|
||||
/// <summary>
|
||||
/// 1207
|
||||
/// </summary>
|
||||
public const uint VCCameraVisible = 1207;
|
||||
/// <summary>
|
||||
/// 1208
|
||||
/// </summary>
|
||||
public const uint VCSelfViewLayoutVisible = 1208;
|
||||
/// <summary>
|
||||
/// 1211 - 1215
|
||||
/// </summary>
|
||||
public const uint VCFavoritePressStart = 1211;
|
||||
// RANGE IN USE
|
||||
public const uint VCFavoritePressEnd = 1215;
|
||||
/// <summary>
|
||||
/// 1221 - 1225
|
||||
/// </summary>
|
||||
public const uint VCFavoriteVisibleStart = 1221;
|
||||
// RANGE IN USE
|
||||
public const uint VCFavoriteVisibleEnd = 1225;
|
||||
/// <summary>
|
||||
/// 1231
|
||||
/// </summary>
|
||||
public const uint VCStagingRecentsPress = 1231;
|
||||
/// <summary>
|
||||
/// 1232
|
||||
/// </summary>
|
||||
public const uint VCStagingDirectoryPress = 1232;
|
||||
/// <summary>
|
||||
/// 1233
|
||||
/// </summary>
|
||||
public const uint VCStagingKeypadPress = 1233;
|
||||
/// <summary>
|
||||
/// 1234
|
||||
/// </summary>
|
||||
public const uint VCStagingConnectPress = 1234;
|
||||
/// <summary>
|
||||
/// 1235
|
||||
/// </summary>
|
||||
public const uint VCStagingCameraPress = 1235;
|
||||
/// <summary>
|
||||
/// 1236
|
||||
/// </summary>
|
||||
public const uint VCStagingConnectEnable = 1236;
|
||||
/// <summary>
|
||||
/// 1237 - When the user touches the text field, should trigger keyboard
|
||||
/// </summary>
|
||||
public const uint VCKeypadTextPress = 1237;
|
||||
/// <summary>
|
||||
/// 1238
|
||||
/// </summary>
|
||||
public const uint VCKeypadBackspacePress = 1238;
|
||||
/// <summary>
|
||||
/// 1239
|
||||
/// </summary>
|
||||
public const uint VCKeypadBackspaceVisible = 1239;
|
||||
/// <summary>
|
||||
/// 1240
|
||||
/// </summary>
|
||||
public const uint VCDirectoryBackPress = 1240;
|
||||
/// <summary>
|
||||
/// 1241 For touching the text area to bring up keyboard
|
||||
/// </summary>
|
||||
public const uint VCDirectorySearchTextPress = 1241;
|
||||
/// <summary>
|
||||
/// 1242
|
||||
/// </summary>
|
||||
public const uint VCStagingSelfViewLayoutPress = 1242;
|
||||
/// <summary>
|
||||
/// 1243
|
||||
/// </summary>
|
||||
public const uint VCDirectoryBackVisible = 1243;
|
||||
/// <summary>
|
||||
/// 1244
|
||||
/// </summary>
|
||||
public const uint VCDirectoryBackspacePress = 1244;
|
||||
/// <summary>
|
||||
/// 1245
|
||||
/// </summary>
|
||||
public const uint VCDirectoryBackspaceVisible = 1245;
|
||||
/// <summary>
|
||||
/// 1251
|
||||
/// </summary>
|
||||
public const uint VCSelfViewTogglePress = 1251;
|
||||
/// <summary>
|
||||
/// 1252
|
||||
/// </summary>
|
||||
public const uint VCLayoutTogglePress = 1252;
|
||||
/// <summary>
|
||||
/// 1253
|
||||
/// </summary>
|
||||
public const uint VCSelfViewPipTogglePress = 1253;
|
||||
/// <summary>
|
||||
/// 1254
|
||||
/// </summary>
|
||||
public const uint VCLayoutToggleEnable = 1254;
|
||||
/// <summary>
|
||||
/// 1255
|
||||
/// </summary>
|
||||
public const uint VCMinMaxPress = 1255;
|
||||
/// <summary>
|
||||
/// 1256
|
||||
/// </summary>
|
||||
public const uint VCMinMaxEnable = 1256;
|
||||
|
||||
// Letter joins start at 2921;
|
||||
|
||||
//******************************************************
|
||||
|
||||
// Environment Joins
|
||||
|
||||
// Popup Container
|
||||
|
||||
/// <summary>
|
||||
/// 2001 - 2004
|
||||
/// </summary>
|
||||
public const uint EnvironmentBackgroundSubpageVisibleBase = 2000;
|
||||
|
||||
|
||||
// ColumnOne
|
||||
|
||||
/// <summary>
|
||||
/// 2011 - 2015
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneLightingTypeVisibleBase = 2010;
|
||||
|
||||
/// <summary>
|
||||
/// 2016 - 2020
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneShadingTypeVisibleBase = 2015;
|
||||
|
||||
// ColumnTwo
|
||||
|
||||
/// <summary>
|
||||
/// 2021 - 2025
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoLightingTypeVisibleBase = 2020;
|
||||
|
||||
/// <summary>
|
||||
/// 2026 - 2030
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoShadingTypeVisibleBase = 2025;
|
||||
|
||||
// ColumnThree
|
||||
|
||||
/// <summary>
|
||||
/// 2031 - 2035
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeLightingTypeVisibleBase = 2030;
|
||||
|
||||
/// <summary>
|
||||
/// 2036 - 2040
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeShadingTypeVisibleBase = 2035;
|
||||
|
||||
// ColumnFour
|
||||
|
||||
/// <summary>
|
||||
/// 2041 - 2045
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourLightingTypeVisibleBase = 2040;
|
||||
|
||||
/// <summary>
|
||||
/// 2046 - 2050
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourShadingTypeVisibleBase = 2045;
|
||||
|
||||
// Button press
|
||||
|
||||
/// <summary>
|
||||
/// 2051 - 2060
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneButtonPressBase = 2050;
|
||||
|
||||
/// <summary>
|
||||
/// 2061 - 2070
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoButtonPressBase = 2060;
|
||||
|
||||
/// <summary>
|
||||
/// 2071 - 2080
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeButtonPressBase = 2070;
|
||||
|
||||
/// <summary>
|
||||
/// 2081 - 2090
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourButtonPressBase = 2080;
|
||||
|
||||
// Button visibility
|
||||
|
||||
/// <summary>
|
||||
/// 2151 - 2160
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnOneButtonVisibleBase = 2150;
|
||||
|
||||
/// <summary>
|
||||
/// 2161 - 2170
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnTwoButtonVisibleBase = 2160;
|
||||
|
||||
/// <summary>
|
||||
/// 2171 - 2180
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnThreeButtonVisibleBase = 2170;
|
||||
|
||||
/// <summary>
|
||||
/// 2181 - 2190
|
||||
/// </summary>
|
||||
public const uint EnvironmentColumnFourButtonVisibleBase = 2180;
|
||||
|
||||
|
||||
//******************************************************
|
||||
|
||||
/// <summary>
|
||||
/// 3101
|
||||
/// </summary>
|
||||
public const uint TechExitButton = 3101;
|
||||
/// <summary>
|
||||
/// 3106
|
||||
/// </summary>
|
||||
public const uint TechCommonItemsVisbible = 3106;
|
||||
/// <summary>
|
||||
/// 3107
|
||||
/// </summary>
|
||||
public const uint TechSystemStatusVisible = 3107;
|
||||
/// <summary>
|
||||
/// 3108
|
||||
/// </summary>
|
||||
public const uint TechDisplayControlsVisible = 3108;
|
||||
/// <summary>
|
||||
/// 3109
|
||||
/// </summary>
|
||||
public const uint TechPanelSetupVisible = 3109;
|
||||
/// <summary>
|
||||
/// 3110
|
||||
/// </summary>
|
||||
public const uint TechAdvancedVolumeVisible = 3110;
|
||||
/// <summary>
|
||||
/// 3111
|
||||
/// </summary>
|
||||
public const uint TechAboutVisible = 3111;
|
||||
/// <summary>
|
||||
/// 3112
|
||||
/// </summary>
|
||||
public const uint TechSchedulerVisible = 3112;
|
||||
|
||||
//*****************************************************
|
||||
/// <summary>
|
||||
/// 3811
|
||||
/// </summary>
|
||||
public const uint VolumeSingleMute1Visible = 3811;
|
||||
/// <summary>
|
||||
/// 3812
|
||||
/// </summary>
|
||||
public const uint VolumeSlider1Press = 3812;
|
||||
/// <summary>
|
||||
/// 3813
|
||||
/// </summary>
|
||||
public const uint Volume1ProgramMutePressAndFB = 3813;
|
||||
/// <summary>
|
||||
/// 3821
|
||||
/// </summary>
|
||||
public const uint Volume2Visible = 3821;
|
||||
/// <summary>
|
||||
/// 3822
|
||||
/// </summary>
|
||||
public const uint VolumeSlider2Press = 3822;
|
||||
/// <summary>
|
||||
/// 3823
|
||||
/// </summary>
|
||||
public const uint Volume2MutePressAndFB = 3823;
|
||||
/// <summary>
|
||||
/// 3831
|
||||
/// </summary>
|
||||
public const uint Volume3Visible = 3831;
|
||||
/// <summary>
|
||||
/// 3832
|
||||
/// </summary>
|
||||
public const uint VolumeSlider3Press = 3832;
|
||||
/// <summary>
|
||||
/// 3833
|
||||
/// </summary>
|
||||
public const uint Volume3MutePressAndFB = 3833;
|
||||
/// <summary>
|
||||
/// 3841
|
||||
/// </summary>
|
||||
public const uint Volume4Visible = 3841;
|
||||
/// <summary>
|
||||
/// 3842
|
||||
/// </summary>
|
||||
public const uint VolumeSlider4Press = 3842;
|
||||
/// <summary>
|
||||
/// 3843
|
||||
/// </summary>
|
||||
public const uint Volume4MutePressAndFB = 3843;
|
||||
/// <summary>
|
||||
/// 3851
|
||||
/// </summary>
|
||||
public const uint Volume5Visible = 3851;
|
||||
/// <summary>
|
||||
/// 3852
|
||||
/// </summary>
|
||||
public const uint VolumeSlider5Press = 3852;
|
||||
/// <summary>
|
||||
/// 3853
|
||||
/// </summary>
|
||||
public const uint Volume5MutePressAndFB = 3853;
|
||||
/// <summary>
|
||||
/// 3861
|
||||
/// </summary>
|
||||
public const uint Volume6Visible = 3861;
|
||||
/// <summary>
|
||||
/// 3862
|
||||
/// </summary>
|
||||
public const uint VolumeSlider6Press = 3862;
|
||||
/// <summary>
|
||||
/// 3863
|
||||
/// </summary>
|
||||
public const uint Volume6MutePressAndFB = 3863;
|
||||
|
||||
/// <summary>
|
||||
/// 3869 - when the system is off and the gear is pressed
|
||||
/// </summary>
|
||||
public const uint VolumesPagePowerOffVisible = 3869;
|
||||
/// <summary>
|
||||
/// 3870
|
||||
/// </summary>
|
||||
public const uint VolumesPageVisible = 3870;
|
||||
/// <summary>
|
||||
/// 3871
|
||||
/// </summary>
|
||||
public const uint VolumeDualMute1Visible = 3871;
|
||||
/// <summary>
|
||||
/// 3874
|
||||
/// </summary>
|
||||
public const uint Volume1SpeechMutePressAndFB = 3874;
|
||||
/// <summary>
|
||||
/// 3875
|
||||
/// </summary>
|
||||
public const uint Volume1BackerVisibility = 3875;
|
||||
/// <summary>
|
||||
/// 3891
|
||||
/// </summary>
|
||||
public const uint VolumeDefaultPress = 3891;
|
||||
/// <summary>
|
||||
/// 3951
|
||||
/// </summary
|
||||
|
||||
public const uint HeaderIcon1Press = 3951;
|
||||
/// <summary>
|
||||
/// 3952
|
||||
/// </summary>
|
||||
public const uint HeaderIcon2Press = 3952;
|
||||
/// <summary>
|
||||
/// 3953
|
||||
/// </summary>
|
||||
public const uint HeaderIcon3Press = 3953;
|
||||
/// <summary>
|
||||
/// 3954
|
||||
/// </summary>
|
||||
public const uint HeaderIcon4Press = 3954;
|
||||
/// <summary>
|
||||
/// 3955
|
||||
/// </summary>
|
||||
public const uint HeaderIcon5Press = 3955;
|
||||
|
||||
/// <summary>
|
||||
/// 3999
|
||||
/// </summary>
|
||||
public const uint GenericModalVisible = 3999;
|
||||
/// <summary>
|
||||
/// 12345
|
||||
/// </summary>
|
||||
public const uint AvNoControlsSubVisible = 12345;
|
||||
|
||||
// 10000 - 14999 are general "source" pages
|
||||
|
||||
/// <summary>
|
||||
/// 15001
|
||||
/// </summary>
|
||||
public const uint StartPageVisible = 15001;
|
||||
/// <summary>
|
||||
/// 15002 Shows the start page in the source controls area of the screen
|
||||
/// </summary>
|
||||
public const uint TapToBeginVisible = 15002;
|
||||
/// <summary>
|
||||
/// 15003 Message text when no source is showing
|
||||
/// </summary>
|
||||
public const uint SelectASourceVisible = 15003;
|
||||
/// <summary>
|
||||
/// 15004
|
||||
/// </summary>
|
||||
public const uint RoomIsOn = 15004;
|
||||
/// <summary>
|
||||
/// 15005 Shows always-on volume control subpage with only audio mute
|
||||
/// </summary>
|
||||
public const uint VolumeControlsSingleMuteVisible = 15005;
|
||||
/// <summary>
|
||||
/// 15006 Shows always-on volume control subpage with mic and audio mutes
|
||||
/// </summary>
|
||||
public const uint VolumeControlsDualMuteVisible = 15006;
|
||||
/// <summary>
|
||||
/// 15010
|
||||
/// </summary>
|
||||
public const uint ShowPanelSetupPress = 15010;
|
||||
/// <summary>
|
||||
/// 15011 - Top bar with room name and button that pops up dialog with room data
|
||||
/// </summary>
|
||||
public const uint TopBarHabaneroVisible = 15011;
|
||||
/// <summary>
|
||||
/// 15012
|
||||
/// </summary>
|
||||
public const uint SourceStagingBarVisible = 15012;
|
||||
/// <summary>
|
||||
/// 15013
|
||||
/// </summary>
|
||||
public const uint PowerOffStep1Visible = 15013;
|
||||
/// <summary>
|
||||
/// 15014
|
||||
/// </summary>
|
||||
public const uint PowerOffStep2Visible = 15014;
|
||||
/// <summary>
|
||||
/// 15015
|
||||
/// </summary>
|
||||
public const uint ShowPowerOffPress = 15015;
|
||||
/// <summary>
|
||||
/// 15016
|
||||
/// </summary>
|
||||
public const uint PowerOffMorePress = 15016;
|
||||
/// <summary>
|
||||
/// 15017
|
||||
/// </summary>
|
||||
public const uint StagingPageAdditionalArrowsVisible = 15017;
|
||||
/// <summary>
|
||||
/// 15018 The Header with dynamic buttons
|
||||
/// </summary>
|
||||
public const uint TopBarHabaneroDynamicVisible = 15018;
|
||||
/// <summary>
|
||||
/// 15019 Shown when system is starting and not ready for use
|
||||
/// </summary>
|
||||
public const uint SystemInitializingVisible = 15019;
|
||||
/// <summary>
|
||||
/// 15020
|
||||
/// </summary>
|
||||
public const uint PanelSetupVisible = 15020;
|
||||
/// <summary>
|
||||
/// 15021
|
||||
/// </summary>
|
||||
public const uint SourceWaitOverlayVisible = 15021;
|
||||
/// <summary>
|
||||
/// 15022
|
||||
/// </summary>
|
||||
public const uint ActivityFooterVisible = 15022;
|
||||
/// <summary>
|
||||
/// 15024
|
||||
/// </summary>
|
||||
public const uint HeaderCallStatusLeftPositionVisible = 15024;
|
||||
/// <summary>
|
||||
/// 15025
|
||||
/// </summary>
|
||||
public const uint HeaderCallStatusRightPositionVisible = 15025;
|
||||
/// <summary>
|
||||
/// 15027
|
||||
/// </summary>
|
||||
public const uint HeaderCallStatusLabelPress = 15027;
|
||||
/// <summary>
|
||||
/// 15028 The gear button in header
|
||||
/// </summary>
|
||||
public const uint FIXFIX_HeaderGearButtonPress_FIXFIX = 15028;
|
||||
/// <summary>
|
||||
/// 15029 the room button in header
|
||||
/// </summary>
|
||||
public const uint HeaderRoomButtonPress = 15029;
|
||||
/// <summary>
|
||||
/// 15030 Visibility for room data popup
|
||||
/// </summary>
|
||||
public const uint RoomHeaderPageVisible = 15030;
|
||||
/// <summary>
|
||||
/// 15031
|
||||
/// </summary>
|
||||
public const uint AllRoomsOffPress = 15031;
|
||||
/// <summary>
|
||||
/// 15032
|
||||
/// </summary>
|
||||
public const uint DisplayPowerTogglePress = 15032;
|
||||
/// <summary>
|
||||
/// 15033
|
||||
/// </summary>
|
||||
public const uint PowerOffCancelPress = 15033;
|
||||
/// <summary>
|
||||
/// 15034
|
||||
/// </summary>
|
||||
public const uint PowerOffConfirmPress = 15034;
|
||||
/// <summary>
|
||||
/// 15035
|
||||
/// </summary>
|
||||
public const uint VolumeButtonPopupPress = 15035;
|
||||
/// <summary>
|
||||
/// 15035
|
||||
/// </summary>
|
||||
public const uint VolumeButtonPopupVisible = 15035;
|
||||
/// <summary>
|
||||
/// 15036
|
||||
/// </summary>
|
||||
public const uint VolumeGaugePopupVisible = 15036;
|
||||
/// <summary>
|
||||
/// 15037
|
||||
/// </summary>
|
||||
public const uint GearButtonVisible = 15037;
|
||||
/// <summary>
|
||||
/// 15038
|
||||
/// </summary>
|
||||
public const uint CalendarHeaderButtonVisible = 15038;
|
||||
/// <summary>
|
||||
/// 15039
|
||||
/// </summary>
|
||||
public const uint CalendarHeaderButtonPress = 15039;
|
||||
/// <summary>
|
||||
/// 15040
|
||||
/// </summary>
|
||||
public const uint CallStatusPageVisible = 15040;
|
||||
/// <summary>
|
||||
/// 15041
|
||||
/// </summary>
|
||||
public const uint LightsPageVisible = 15041;
|
||||
/// <summary>
|
||||
/// 15042 Closes whichever interlocked modal is open
|
||||
/// </summary>
|
||||
public const uint InterlockedModalClosePress = 15042;
|
||||
/// <summary>
|
||||
/// 15043 Vis for modal backer for full-screen source
|
||||
/// </summary>
|
||||
public const uint SourceBackgroundOverlayVisible = 15043;
|
||||
/// <summary>
|
||||
/// 15044 Close button for source modal overlay
|
||||
/// </summary>
|
||||
public const uint SourceBackgroundOverlayClosePress = 15044;
|
||||
/// <summary>
|
||||
/// 15045 - Visibility for the bar containing call navigation button list
|
||||
/// </summary>
|
||||
public const uint CallStagingBarVisible = 15045;
|
||||
/// <summary>
|
||||
/// 15046
|
||||
/// </summary>
|
||||
public const uint MeetingsOrContacMethodsListVisible = 15046;
|
||||
/// <summary>
|
||||
/// 15047 The "Join" button on the next meeting ribbon
|
||||
/// </summary>
|
||||
public const uint NextMeetingJoinPress = 15047;
|
||||
/// <summary>
|
||||
/// 15048 Dismisses the ribbon
|
||||
/// </summary>
|
||||
public const uint NextMeetingModalClosePress = 15048;
|
||||
/// <summary>
|
||||
/// 15049
|
||||
/// </summary>
|
||||
public const uint NextMeetingModalVisible = 15049;
|
||||
/// <summary>
|
||||
/// 15051
|
||||
/// </summary>
|
||||
public const uint Display1SelectPressAndFb = 15051;
|
||||
/// <summary>
|
||||
/// 15052
|
||||
/// </summary>
|
||||
public const uint Display1ControlButtonEnable = 15052;
|
||||
/// <summary>
|
||||
/// 15053
|
||||
/// </summary>
|
||||
public const uint Display1ControlButtonPress = 15053;
|
||||
/// <summary>
|
||||
/// 15054
|
||||
/// </summary>
|
||||
public const uint Display1AudioButtonEnable = 15054;
|
||||
/// <summary>
|
||||
/// 15055
|
||||
/// </summary>
|
||||
public const uint Display1AudioButtonPressAndFb = 15055;
|
||||
/// <summary>
|
||||
/// 15056
|
||||
/// </summary>
|
||||
public const uint Display2SelectPressAndFb = 15056;
|
||||
/// <summary>
|
||||
/// 15057
|
||||
/// </summary>
|
||||
public const uint Display2ControlButtonEnable = 15057;
|
||||
/// <summary>
|
||||
/// 15058
|
||||
/// </summary>
|
||||
public const uint Display2ControlButtonPress = 15058;
|
||||
/// <summary>
|
||||
/// 15059
|
||||
/// </summary>
|
||||
public const uint Display2AudioButtonEnable = 15059;
|
||||
/// <summary>
|
||||
/// 15060
|
||||
/// </summary>
|
||||
public const uint Display2AudioButtonPressAndFb = 15060;
|
||||
/// <summary>
|
||||
/// 15061 Reveals the dual-display subpage
|
||||
/// </summary>
|
||||
public const uint DualDisplayPageVisible = 15061;
|
||||
/// <summary>
|
||||
/// 15062 Reveals the toggle switch for the sharing mode
|
||||
/// </summary>
|
||||
public const uint ToggleSharingModeVisible = 15062;
|
||||
/// <summary>
|
||||
/// 15063 Press for the toggle mode switch
|
||||
/// </summary>
|
||||
public const uint ToggleSharingModePress = 15063;
|
||||
/// <summary>
|
||||
/// 15064
|
||||
/// </summary>
|
||||
public const uint LogoDefaultVisible = 15064;
|
||||
/// <summary>
|
||||
/// 15065
|
||||
/// </summary>
|
||||
public const uint LogoUrlVisible = 15065;
|
||||
/// <summary>
|
||||
/// 15066 - Reveals the active calls header item
|
||||
/// </summary>
|
||||
public const uint HeaderActiveCallsListVisible = 15066;
|
||||
/// <summary>
|
||||
/// 15067
|
||||
/// </summary>
|
||||
public const uint NotificationRibbonVisible = 15067;
|
||||
/// <summary>
|
||||
/// 15083 - Press for Call help desk on AC/VC
|
||||
/// </summary>
|
||||
public const uint HelpPageShowCallButtonPress = 15083;
|
||||
/// <summary>
|
||||
/// 15084 - Show the "call help desk" button on help page
|
||||
/// </summary>
|
||||
public const uint HelpPageShowCallButtonVisible = 15084;
|
||||
/// <summary>
|
||||
/// 15085 Visibility join for help subpage
|
||||
/// </summary>
|
||||
public const uint HelpPageVisible = 15085;
|
||||
/// <summary>
|
||||
/// 15086 Press for help header button
|
||||
/// </summary>
|
||||
public const uint HelpPress = 15086;
|
||||
/// <summary>
|
||||
/// 15088
|
||||
/// </summary>
|
||||
public const uint DateOnlyVisible = 15088;
|
||||
/// <summary>
|
||||
/// 15089
|
||||
/// </summary>
|
||||
public const uint TimeOnlyVisible = 15089;
|
||||
/// <summary>
|
||||
/// 15090
|
||||
/// </summary>
|
||||
public const uint DateAndTimeVisible = 15090;
|
||||
/// <summary>
|
||||
/// 15091
|
||||
/// </summary>
|
||||
public const uint SetupFullDistrib = 15091;
|
||||
|
||||
// PIN dialogs ************************************
|
||||
|
||||
/// <summary>
|
||||
/// 15201
|
||||
/// </summary>
|
||||
public const uint PinDialog4DigitVisible = 15201;
|
||||
/// <summary>
|
||||
/// 15206
|
||||
/// </summary>
|
||||
public const uint PinDialogCancelPress = 15206;
|
||||
/// <summary>
|
||||
/// 15207
|
||||
/// </summary>
|
||||
public const uint PinDialogErrorVisible = 15207;
|
||||
/// <summary>
|
||||
/// 15211
|
||||
/// </summary>
|
||||
public const uint PinDialogDot1 = 15211;
|
||||
/// <summary>
|
||||
/// 15212
|
||||
/// </summary>
|
||||
public const uint PinDialogDot2 = 15212;
|
||||
/// <summary>
|
||||
/// 15213
|
||||
/// </summary>
|
||||
public const uint PinDialogDot3 = 15213;
|
||||
/// <summary>
|
||||
/// 15214
|
||||
/// </summary>
|
||||
public const uint PinDialogDot4 = 15214;
|
||||
}
|
||||
}
|
||||
73
PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs
Normal file
73
PepperDashEssentials/UI/JoinConstants/UISmartObjectJoin.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
namespace PepperDash.Essentials
|
||||
{
|
||||
public class UISmartObjectJoin
|
||||
{
|
||||
//******************************************************
|
||||
// Conference
|
||||
/// <summary>
|
||||
/// 1001 - The list that reveals in header to show calls
|
||||
/// </summary>
|
||||
public const uint CodecActiveCallsHeaderList = 1001;
|
||||
|
||||
// Video Conference
|
||||
|
||||
/// <summary>
|
||||
/// 1201
|
||||
/// </summary>
|
||||
public const uint VCDialKeypad = 1201;
|
||||
|
||||
/// <summary>
|
||||
/// 1202
|
||||
/// </summary>
|
||||
public const uint VCDirectoryList = 1202;
|
||||
/// <summary>
|
||||
/// 1203
|
||||
/// </summary>
|
||||
public const uint VCRecentsList = 1203;
|
||||
/// <summary>
|
||||
/// 1204
|
||||
/// </summary>
|
||||
public const uint VCFavoritesList = 1204;
|
||||
/// <summary>
|
||||
/// 1205 Layout buttons dynamic list
|
||||
/// </summary>
|
||||
public const uint VCLayoutsList = 1205;
|
||||
|
||||
|
||||
//******************************************************
|
||||
// General
|
||||
|
||||
/// <summary>
|
||||
/// 3200 The staging, source-select list
|
||||
/// </summary>
|
||||
public const uint SourceStagingSRL = 3200;
|
||||
/// <summary>
|
||||
/// 3901 The Tech page menu list
|
||||
/// </summary>
|
||||
public const uint TechMenuList = 3901;
|
||||
/// <summary>
|
||||
/// 3902 Tech page statuses
|
||||
/// </summary>
|
||||
public const uint TechStatusList = 3902;
|
||||
/// <summary>
|
||||
/// 3903
|
||||
/// </summary>
|
||||
public const uint TechPinDialogKeypad = 3903;
|
||||
/// <summary>
|
||||
/// 3904 - Display controls on the tech page
|
||||
/// </summary>
|
||||
public const uint TechDisplayControlsList = 3904;
|
||||
/// <summary>
|
||||
/// 15018
|
||||
/// </summary>
|
||||
public const uint HeaderButtonList = 15018;
|
||||
/// <summary>
|
||||
/// 15022 The main activity footer
|
||||
/// </summary>
|
||||
public const uint ActivityFooterSRL = 15022;
|
||||
/// <summary>
|
||||
/// 15023 - The header meetings SRL
|
||||
/// </summary>
|
||||
public const uint MeetingListSRL = 15023;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue