DDVC bridge

This commit is contained in:
Heath Volmer
2018-02-13 17:42:28 -07:00
parent 17c448e309
commit 2a4ed67bee
10 changed files with 286 additions and 104 deletions

View File

@@ -23,6 +23,7 @@ namespace PepperDash.Essentials.Core
/// </summary>
public class SourceListItem
{
[JsonProperty("sourceKey")]
public string SourceKey { get; set; }
/// <summary>
/// Returns the source Device for this, if it exists in DeviceManager
@@ -43,6 +44,7 @@ namespace PepperDash.Essentials.Core
/// Gets either the source's Name or this AlternateName property, if
/// defined. If source doesn't exist, returns "Missing source"
/// </summary>
[JsonProperty("preferredName")]
public string PreferredName
{
get
@@ -60,15 +62,34 @@ namespace PepperDash.Essentials.Core
/// <summary>
/// A name that will override the source's name on the UI
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("icon")]
public string Icon { get; set; }
[JsonProperty("altIcon")]
public string AltIcon { get; set; }
[JsonProperty("includeInSourceList")]
public bool IncludeInSourceList { get; set; }
public int Order { get; set; }
[JsonProperty("order")]
public int Order { get; set; }
[JsonProperty("volumeControlKey")]
public string VolumeControlKey { get; set; }
[JsonProperty("type")]
public eSourceListItemType Type { get; set; }
[JsonProperty("routeList")]
public List<SourceRouteListItem> RouteList { get; set; }
[JsonProperty("disableCodecSharing")]
public bool DisableCodecSharing { get; set; }
[JsonProperty("disableRoutedSharing")]
public bool DisableRoutedSharing { get; set; }
public SourceListItem()

View File

@@ -83,7 +83,7 @@ namespace PepperDash.Essentials
}
Debug.Console(0, bridge, "Linking to parent controller");
bridge.AddParent(parent);
parent.CotijaRooms.Add(bridge);
parent.AddBridge(bridge);
});
return bridge;

View File

@@ -283,7 +283,7 @@ namespace PepperDash.Essentials
}
Debug.Console(0, bridge, "Linking to parent controller");
bridge.AddParent(parent);
parent.CotijaRooms.Add(bridge);
parent.AddBridge(bridge);
});
}

View File

@@ -4,19 +4,27 @@ 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; }
}
}

View File

@@ -3,16 +3,22 @@ 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
{
public string DefaultDisplayKey { get; set; }
public string DefaultAudioKey { get; set; }
public string SourceListKey { get; set; }
public string DefaultSourceItem { get; set; }
public string VideoCodecKey { get; set; }
[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; }
}
}

View File

@@ -179,26 +179,56 @@ namespace PepperDash.Essentials.Room.Config
/// </summary>
public class EssentialsRoomPropertiesConfig
{
public EssentialsRoomEmergencyConfig Emergency { get; set; }
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy {get; set;}
[JsonProperty("emergency")]
public EssentialsRoomEmergencyConfig Emergency { get; set; }
[JsonProperty("microphonePrivacy")]
public EssentialsRoomMicrophonePrivacyConfig MicrophonePrivacy { get; set; }
[JsonProperty("helpMessage")]
public string HelpMessage { get; set; }
public string Description { get; set; }
public int ShutdownVacancySeconds { get; set; }
public int ShutdownPromptSeconds { get; set; }
public EssentialsHelpPropertiesConfig Help { get; set; }
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
public EssentialsLogoPropertiesConfig Logo { get; set; }
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("shutdownVacancySeconds")]
public int ShutdownVacancySeconds { get; set; }
[JsonProperty("shutdownPromptSeconds")]
public int ShutdownPromptSeconds { get; set; }
[JsonProperty("help")]
public EssentialsHelpPropertiesConfig Help { get; set; }
[JsonProperty("oneButtonMeeting")]
public EssentialsOneButtonMeetingPropertiesConfig OneButtonMeeting { get; set; }
[JsonProperty("addresses")]
public EssentialsRoomAddressPropertiesConfig Addresses { get; set; }
[JsonProperty("occupancy")]
public EssentialsRoomOccSensorConfig Occupancy { get; set; }
[JsonProperty("logo")]
public EssentialsLogoPropertiesConfig Logo { get; set; }
[JsonProperty("tech")]
public EssentialsRoomTechConfig Tech { get; set; }
public EssentialsRoomVolumesConfig Volumes { get; set; }
[JsonProperty("volumes")]
public EssentialsRoomVolumesConfig Volumes { get; set; }
[JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")]
public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; }
}
public class EssentialsRoomMicrophonePrivacyConfig
{
public string DeviceKey { get; set; }
public string Behaviour { get; set; }
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("behaviour")]
public string Behaviour { get; set; }
}
/// <summary>
@@ -206,12 +236,17 @@ namespace PepperDash.Essentials.Room.Config
/// </summary>
public class EssentialsHelpPropertiesConfig
{
public string Message { get; set; }
public bool ShowCallButton { get; set; }
/// <summary>
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("showCallButton")]
public bool ShowCallButton { get; set; }
/// <summary>
/// Defaults to "Call Help Desk"
/// </summary>
public string CallButtonText { get; set; }
[JsonProperty("callButtonText")]
public string CallButtonText { get; set; }
public EssentialsHelpPropertiesConfig()
{
@@ -224,13 +259,17 @@ namespace PepperDash.Essentials.Room.Config
/// </summary>
public class EssentialsOneButtonMeetingPropertiesConfig
{
public bool Enable { get; set; }
[JsonProperty("enable")]
public bool Enable { get; set; }
}
public class EssentialsRoomAddressPropertiesConfig
{
public string PhoneNumber { get; set; }
public string SipAddress { get; set; }
[JsonProperty("phoneNumber")]
public string PhoneNumber { get; set; }
[JsonProperty("sipAddress")]
public string SipAddress { get; set; }
}
@@ -239,8 +278,11 @@ namespace PepperDash.Essentials.Room.Config
/// </summary>
public class EssentialsLogoPropertiesConfig
{
public string Type { get; set; }
public string Url { get; set; }
[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>
@@ -260,13 +302,16 @@ namespace PepperDash.Essentials.Room.Config
/// </summary>
public class EssentialsRoomOccSensorConfig
{
public string DeviceKey { get; set; }
public int TimoutMinutes { get; set; }
[JsonProperty("deviceKey")]
public string DeviceKey { get; set; }
[JsonProperty("timoutMinutes")]
public int TimoutMinutes { get; set; }
}
public class EssentialsRoomTechConfig
{
[JsonProperty("password")]
public string Password { get; set; }
}
}

View File

@@ -10,8 +10,10 @@ 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
{
@@ -19,8 +21,6 @@ namespace PepperDash.Essentials
{
GenericHttpSseClient SseClient;
//CCriticalSection FileLock;
/// <summary>
/// Prevents post operations from stomping on each other and getting lost
/// </summary>
@@ -44,7 +44,7 @@ namespace PepperDash.Essentials
string SystemUuid;
public List<CotijaBridgeBase> CotijaRooms { get; private set; }
List<CotijaBridgeBase> RoomBridges = new List<CotijaBridgeBase>();
long ButtonHeartbeatInterval = 1000;
@@ -54,23 +54,24 @@ namespace PepperDash.Essentials
/// Used to count retries in PostToServer
/// </summary>
int RetryCounter;
/// <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);
CotijaRooms = new List<CotijaBridgeBase>();
//CrestronConsole.AddNewConsoleCommand(s => RegisterSystemToServer(),
// "CotiInitializeHttpClient", "Initializes a new HTTP client connection to a specified URL", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(DisconnectSseClient,
"CloseHttpClient", "Closes the active HTTP client", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(AuthorizeSystem,
"cotijaauth", "Authorizes system to talk to cotija server", ConsoleAccessLevelEnum.AccessOperator);
AddPostActivationAction(() => RegisterSystemToServer());
//AddPostActivationAction(() => RegisterSystemToServer());
}
/// <summary>
@@ -100,6 +101,40 @@ namespace PepperDash.Essentials
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)
{
b.ConfigurationIsReady += new EventHandler<EventArgs>(bridge_ConfigurationIsReady);
}
else
{
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();
@@ -153,42 +188,19 @@ namespace PepperDash.Essentials
/// <param name="url">URL of the server, including the port number, if not 80. Format: "serverUrlOrIp:port"</param>
void RegisterSystemToServer()
{
#warning THIS SHOULD NOT GO until the config is ready - in cases of config populated from elsewhere (DDVC)
try
{
string filePath = string.Format(@"\NVRAM\Program{0}\configurationFile.json", Global.ControlSystem.ProgramNumber);
var confObject = ConfigReader.ConfigObject;
string postBody = JsonConvert.SerializeObject(confObject);
SystemUuid = confObject.SystemUuid;
//if (string.IsNullOrEmpty(filePath))
//{
// Debug.Console(0, this, "Error reading file. No path specified.");
// return;
//}
// FileLock = new CCriticalSection();
//#warning NEIL I think we need to review this usage. Don't think it ever blocks
// if (FileLock.TryEnter())
// {
// Debug.Console(1, this, "Reading configuration file to extract system UUID...");
// postBody = File.ReadToEnd(filePath, Encoding.ASCII);
// Debug.Console(2, this, "{0}", postBody);
// FileLock.Leave();
// }
if (string.IsNullOrEmpty(postBody))
{
Debug.Console(1, this, "ERROR: Config post body is empty. Cannot register with server.");
}
else
{
if(Client == null || NeedNewClient)
Client = new HttpClient();
Client = new HttpClient();
Client.Verbose = true;
Client.KeepAlive = true;
@@ -221,6 +233,11 @@ namespace PepperDash.Essentials
{
CrestronInvoke.BeginInvoke(oo =>
{
if (string.IsNullOrEmpty(SystemUuid))
{
Debug.Console(1, this, "Status post attempt before UUID is set. Ignoring.");
return;
}
var ready = PostLockEvent.Wait(2000);
if (!ready)
{
@@ -546,9 +563,7 @@ namespace PepperDash.Essentials
{
Debug.Console(1, this, "-- Warning: Incoming message has no registered handler");
}
}
}
catch (Exception err)
{
@@ -557,6 +572,4 @@ namespace PepperDash.Essentials
}
}
}
}

View File

@@ -21,7 +21,7 @@ namespace PepperDash.Essentials.Room.Cotija
public class BoolJoin
{
/// <summary>
/// 2
/// 301
/// </summary>
public const uint RoomIsOn = 301;
@@ -39,11 +39,11 @@ namespace PepperDash.Essentials.Room.Cotija
public const uint ActivityVideoCallPress = 53;
/// <summary>
/// 4
/// 1
/// </summary>
public const uint MasterVolumeIsMuted = 1;
/// <summary>
/// 4
/// 1
/// </summary>
public const uint MasterVolumeMuteToggle = 1;
@@ -63,7 +63,7 @@ namespace PepperDash.Essentials.Room.Cotija
/// <summary>
/// 71
/// 72
/// </summary>
public const uint SourceHasChanged = 72;
/// <summary>
@@ -75,19 +75,22 @@ namespace PepperDash.Essentials.Room.Cotija
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 = 3;
public const uint SelectedSourceKey = 71;
/// <summary>
/// 501
@@ -112,7 +115,7 @@ namespace PepperDash.Essentials.Room.Cotija
}
/// <summary>
/// Fires when the config is ready, to be used by the controller class to forward config to server
/// Fires when config is ready to go
/// </summary>
public event EventHandler<EventArgs> ConfigurationIsReady;
@@ -153,17 +156,49 @@ namespace PepperDash.Essentials.Room.Cotija
/// <returns></returns>
public override bool CustomActivate()
{
Debug.Console(0, this, "Final activation. Setting up actions and feedbacks");
SetupFunctions();
SetupFeedbacks();
//**** RE-ADD THESE WHEN IT MAKES SENSE
EISC.SigChange += EISC_SigChange;
EISC.OnlineStatusChange += (o, a) =>
{
if (a.DeviceOnLine)
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.BooleanInput[BoolJoin.ConfigIsReady].BoolValue)
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);
}
}
}, "cotijabridgedump", "Dumps DDVC01 bridge EISC data b,u,s", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => LoadConfigValues(), "loadddvc", "", ConsoleAccessLevelEnum.AccessOperator);
return base.CustomActivate();
}
@@ -173,6 +208,7 @@ namespace PepperDash.Essentials.Room.Cotija
/// </summary>
void SetupFunctions()
{
Parent.AddAction(@"/room/room1/status", new Action(SendFullStatus));
Parent.AddAction(@"/room/room1/source", new Action<SourceSelectMessageContent>(c =>
@@ -181,7 +217,8 @@ namespace PepperDash.Essentials.Room.Cotija
EISC.PulseBool(BoolJoin.SourceHasChanged);
}));
Parent.AddAction(@"/room/room1/activityshare", new Action(() =>
#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 =>
@@ -231,17 +268,17 @@ namespace PepperDash.Essentials.Room.Cotija
// shutdown things
EISC.SetSigTrueAction(BoolJoin.ShutdownCancel, new Action(() =>
PostStatusMessage(new
PostMessage("/room/shutdown/", new
{
state = "wasCancelled"
})));
EISC.SetSigTrueAction(BoolJoin.ShutdownEnd, new Action(() =>
PostStatusMessage(new
PostMessage("/room/shutdown/", new
{
state = "hasFinished"
})));
EISC.SetSigTrueAction(BoolJoin.ShutdownStart, new Action(() =>
PostStatusMessage(new
PostMessage("/room/shutdown/", new
{
state = "hasStarted",
duration = EISC.UShortOutput[UshortJoin.ShutdownPromptDuration].UShortValue
@@ -256,7 +293,6 @@ namespace PepperDash.Essentials.Room.Cotija
/// </summary>
void LoadConfigValues()
{
Debug.Console(1, this, "Loading configuration from DDVC01 EISC bridge");
ConfigIsLoaded = false;
@@ -265,10 +301,13 @@ namespace PepperDash.Essentials.Room.Cotija
//Room
if (co.Rooms == null)
co.Rooms = new List<EssentialsRoomConfig>();
var rm = new EssentialsRoomConfig();
if (co.Rooms.Count == 0)
co.Rooms.Add(new EssentialsRoomConfig());
var rm = co.Rooms[0];
rm.Name = EISC.StringInput[501].StringValue;
{
Debug.Console(0, this, "Adding room to config");
co.Rooms.Add(rm);
}
rm.Name = EISC.StringOutput[501].StringValue;
rm.Key = "room1";
rm.Type = "ddvc01";
@@ -279,22 +318,22 @@ namespace PepperDash.Essentials.Room.Cotija
rmProps = JsonConvert.DeserializeObject<DDVC01RoomPropertiesConfig>(rm.Properties.ToString());
rmProps.Help = new EssentialsHelpPropertiesConfig();
rmProps.Help.Message = EISC.StringInput[502].StringValue;
rmProps.Help.CallButtonText = EISC.StringInput[503].StringValue;
rmProps.RoomPhoneNumber = EISC.StringInput[504].StringValue;
rmProps.RoomURI = EISC.StringInput[505].StringValue;
rmProps.Help.Message = EISC.StringOutput[502].StringValue;
rmProps.Help.CallButtonText = EISC.StringOutput[503].StringValue;
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.StringInput[i].StringValue;
var num = EISC.StringOutput[i].StringValue;
if (string.IsNullOrEmpty(num))
break;
var name = EISC.StringInput[i + 1].StringValue;
var name = EISC.StringOutput[i + 1].StringValue;
rmProps.SpeedDials.Add(new DDVC01SpeedDial { Number = num, Name = name});
}
// volume control names
var volCount = EISC.UShortInput[701].UShortValue;
var volCount = EISC.UShortOutput[701].UShortValue;
rmProps.VolumeSliderNames = new List<string>();
for(uint i = 701; i <= 700 + volCount; i++)
{
@@ -305,29 +344,43 @@ namespace PepperDash.Essentials.Room.Cotija
if(co.Devices == null)
co.Devices = new List<DeviceConfig>();
// Source list! This might be brutal!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
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.StringInput[601 + i].StringValue;
var name = EISC.StringOutput[601 + i].StringValue;
if(string.IsNullOrEmpty(name))
break;
var icon = EISC.StringInput[651 + i].StringValue;
var key = EISC.StringInput[671 + i].StringValue;
var type = EISC.StringInput[701 + i].StringValue;
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 = "ddvc01",
Group = group,
Key = key,
Name = name,
Type = type
@@ -339,9 +392,13 @@ namespace PepperDash.Essentials.Room.Cotija
Debug.Console(0, this, "******* CONFIG FROM DDVC: \r{0}", JsonConvert.SerializeObject(ConfigReader.ConfigObject, Formatting.Indented));
ConfigIsLoaded = true;
var handler = ConfigurationIsReady;
if (handler != null)
{
handler(this, new EventArgs());
}
// send config changed status???
ConfigIsLoaded = true;
}
void SendFullStatus()
@@ -380,6 +437,20 @@ namespace PepperDash.Essentials.Room.Cotija
}));
}
/// <summary>
///
/// </summary>
/// <param name="messageType"></param>
/// <param name="contentObject"></param>
void PostMessage(string messageType, object contentObject)
{
Parent.PostToServer(JObject.FromObject(new
{
type = messageType,
content = contentObject
}));
}
/// <summary>
///
@@ -398,5 +469,23 @@ namespace PepperDash.Essentials.Room.Cotija
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;
}
}
}