mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-16 05:05:00 +00:00
Moved cotija classes into appserver folder; adding VideoCodecBaseMessenger class
This commit is contained in:
@@ -42,8 +42,8 @@ namespace PepperDash.Essentials.Room.Cotija
|
|||||||
controller.RemoveAction(prefix + "num6");
|
controller.RemoveAction(prefix + "num6");
|
||||||
controller.RemoveAction(prefix + "num7");
|
controller.RemoveAction(prefix + "num7");
|
||||||
controller.RemoveAction(prefix + "num8");
|
controller.RemoveAction(prefix + "num8");
|
||||||
controller.RemoveAction(prefix + "num9");
|
controller.RemoveAction(prefix + "num9");
|
||||||
controller.RemoveAction(prefix + "numDash");
|
controller.RemoveAction(prefix + "numDash");
|
||||||
controller.RemoveAction(prefix + "numEnter");
|
controller.RemoveAction(prefix + "numEnter");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
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.Devices.Common.Codec;
|
||||||
|
using PepperDash.Essentials.Devices.Common.VideoCodec;
|
||||||
|
|
||||||
|
namespace PepperDash.Essentials.AppServer.Messengers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides a messaging bridge for a VideoCodecBase
|
||||||
|
/// </summary>
|
||||||
|
public class VideoCodecBaseMessenger
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public VideoCodecBase Codec { get; private set; }
|
||||||
|
|
||||||
|
public CotijaSystemController AppServerController { get; private set; }
|
||||||
|
|
||||||
|
public string MessagePath { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="codec"></param>
|
||||||
|
public VideoCodecBaseMessenger(VideoCodecBase codec, string messagePath)
|
||||||
|
{
|
||||||
|
if (codec == null)
|
||||||
|
throw new ArgumentNullException("codec");
|
||||||
|
if (string.IsNullOrEmpty(messagePath))
|
||||||
|
throw new ArgumentException("messagePath must not be empty or null");
|
||||||
|
|
||||||
|
MessagePath = messagePath;
|
||||||
|
Codec = codec;
|
||||||
|
codec.CallStatusChange += new EventHandler<CodecCallStatusItemChangeEventArgs>(codec_CallStatusChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers this codec's messaging with an app server controller
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="appServerController"></param>
|
||||||
|
public void RegisterWithAppServer(CotijaSystemController appServerController)
|
||||||
|
{
|
||||||
|
if (appServerController == null)
|
||||||
|
throw new ArgumentNullException("appServerController");
|
||||||
|
|
||||||
|
AppServerController = appServerController;
|
||||||
|
|
||||||
|
appServerController.AddAction("/device/videoCodec/dial", new Action<string>(s => Codec.Dial(s)));
|
||||||
|
appServerController.AddAction("/device/videoCodec/endCallById", new Action<string>(s =>
|
||||||
|
{
|
||||||
|
var call = GetCallWithId(s);
|
||||||
|
if (call != null)
|
||||||
|
Codec.EndCall(call);
|
||||||
|
}));
|
||||||
|
appServerController.AddAction(MessagePath + "/endAllCalls", new Action(() => Codec.EndAllCalls()));
|
||||||
|
appServerController.AddAction(MessagePath + "/dtmf", new Action<string>(s => Codec.SendDtmf(s)));
|
||||||
|
appServerController.AddAction(MessagePath + "/rejectById", new Action<string>(s =>
|
||||||
|
{
|
||||||
|
var call = GetCallWithId(s);
|
||||||
|
if (call != null)
|
||||||
|
Codec.RejectCall(call);
|
||||||
|
}));
|
||||||
|
appServerController.AddAction(MessagePath + "/acceptById", new Action<string>(s =>
|
||||||
|
{
|
||||||
|
var call = GetCallWithId(s);
|
||||||
|
if (call != null)
|
||||||
|
Codec.AcceptCall(call);
|
||||||
|
}));
|
||||||
|
appServerController.AddAction(MessagePath + "/privacyModeOn", new Action(() => Codec.PrivacyModeOn()));
|
||||||
|
appServerController.AddAction(MessagePath + "/privacyModeOff", new Action(() => Codec.PrivacyModeOff()));
|
||||||
|
appServerController.AddAction(MessagePath + "/privacyModeToggle", new Action(() => Codec.PrivacyModeToggle()));
|
||||||
|
appServerController.AddAction(MessagePath + "/sharingStart", new Action(() => Codec.StartSharing()));
|
||||||
|
appServerController.AddAction(MessagePath + "/sharingStop", new Action(() => Codec.StopSharing()));
|
||||||
|
appServerController.AddAction(MessagePath + "/standbyOn", new Action(() => Codec.StandbyActivate()));
|
||||||
|
appServerController.AddAction(MessagePath + "/standbyOff", new Action(() => Codec.StandbyDeactivate()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper to grab a call with string ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
CodecActiveCallItem GetCallWithId(string id)
|
||||||
|
{
|
||||||
|
return Codec.ActiveCalls.FirstOrDefault(c => c.Id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handler for codec changes
|
||||||
|
/// </summary>
|
||||||
|
void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
|
||||||
|
{
|
||||||
|
PostStatusMessage(new
|
||||||
|
{
|
||||||
|
vtc = GetVtcCallsMessageObject()
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to build call status for vtc
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
object GetVtcCallsMessageObject()
|
||||||
|
{
|
||||||
|
var info = Codec.CodecInfo;
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
isInCall = Codec.IsInCall,
|
||||||
|
isReady = Codec.IsReady,
|
||||||
|
privacyModeIsOn = Codec.PrivacyModeIsOnFeedback.BoolValue,
|
||||||
|
sharingContentIsOn = Codec.SharingContentIsOnFeedback.BoolValue,
|
||||||
|
sharingSource = Codec.SharingSourceFeedback.StringValue,
|
||||||
|
standbyIsOn = Codec.StandbyIsOnFeedback.StringValue,
|
||||||
|
calls = Codec.ActiveCalls,
|
||||||
|
info = new
|
||||||
|
{
|
||||||
|
autoAnswerEnabled = info.AutoAnswerEnabled,
|
||||||
|
e164Alias = info.E164Alias,
|
||||||
|
h323Id = info.H323Id,
|
||||||
|
ipAddress = info.IpAddress,
|
||||||
|
multiSiteEnabled = info.MultiSiteOptionIsEnabled,
|
||||||
|
sipPhoneNumber = info.SipPhoneNumber,
|
||||||
|
sipURI = info.SipUri
|
||||||
|
},
|
||||||
|
showSelfViewByDefault = Codec.ShowSelfViewByDefault
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper for posting status message
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="contentObject">The contents of the content object</param>
|
||||||
|
void PostStatusMessage(object contentObject)
|
||||||
|
{
|
||||||
|
AppServerController.SendMessageToServer(JObject.FromObject(new
|
||||||
|
{
|
||||||
|
type = MessagePath,
|
||||||
|
content = contentObject
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -160,7 +160,6 @@ namespace PepperDash.Essentials
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
|
void codec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e)
|
||||||
{
|
{
|
||||||
var codec = sender as VideoCodecBase;
|
|
||||||
PostStatusMessage(new
|
PostStatusMessage(new
|
||||||
{
|
{
|
||||||
calls = GetCallsMessageObject(),
|
calls = GetCallsMessageObject(),
|
||||||
@@ -1,104 +1,104 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Crestron.SimplSharp;
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Room.Cotija
|
namespace PepperDash.Essentials.Room.Cotija
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains all of the default joins that map to API funtions
|
/// Contains all of the default joins that map to API funtions
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SourceDeviceMapDictionary : Dictionary<string, uint>
|
public class SourceDeviceMapDictionary : Dictionary<string, uint>
|
||||||
{
|
{
|
||||||
|
|
||||||
public SourceDeviceMapDictionary(): base()
|
public SourceDeviceMapDictionary(): base()
|
||||||
{
|
{
|
||||||
var dictionary = new Dictionary<string, uint>
|
var dictionary = new Dictionary<string, uint>
|
||||||
{
|
{
|
||||||
{"preset01", 101},
|
{"preset01", 101},
|
||||||
{"preset02", 102},
|
{"preset02", 102},
|
||||||
{"preset03", 103},
|
{"preset03", 103},
|
||||||
{"preset04", 104},
|
{"preset04", 104},
|
||||||
{"preset05", 105},
|
{"preset05", 105},
|
||||||
{"preset06", 106},
|
{"preset06", 106},
|
||||||
{"preset07", 107},
|
{"preset07", 107},
|
||||||
{"preset08", 108},
|
{"preset08", 108},
|
||||||
{"preset09", 109},
|
{"preset09", 109},
|
||||||
{"preset10", 110},
|
{"preset10", 110},
|
||||||
{"preset11", 111},
|
{"preset11", 111},
|
||||||
{"preset12", 112},
|
{"preset12", 112},
|
||||||
{"preset13", 113},
|
{"preset13", 113},
|
||||||
{"preset14", 114},
|
{"preset14", 114},
|
||||||
{"preset15", 115},
|
{"preset15", 115},
|
||||||
{"preset16", 116},
|
{"preset16", 116},
|
||||||
{"preset17", 117},
|
{"preset17", 117},
|
||||||
{"preset18", 118},
|
{"preset18", 118},
|
||||||
{"preset19", 119},
|
{"preset19", 119},
|
||||||
{"preset20", 120},
|
{"preset20", 120},
|
||||||
{"preset21", 121},
|
{"preset21", 121},
|
||||||
{"preset22", 122},
|
{"preset22", 122},
|
||||||
{"preset23", 123},
|
{"preset23", 123},
|
||||||
{"preset24", 124},
|
{"preset24", 124},
|
||||||
|
|
||||||
{"num0", 130},
|
{"num0", 130},
|
||||||
{"num1", 131},
|
{"num1", 131},
|
||||||
{"num2", 132},
|
{"num2", 132},
|
||||||
{"num3", 133},
|
{"num3", 133},
|
||||||
{"num4", 134},
|
{"num4", 134},
|
||||||
{"num5", 135},
|
{"num5", 135},
|
||||||
{"num6", 136},
|
{"num6", 136},
|
||||||
{"num7", 137},
|
{"num7", 137},
|
||||||
{"num8", 138},
|
{"num8", 138},
|
||||||
{"num9", 139},
|
{"num9", 139},
|
||||||
{"numDash", 140},
|
{"numDash", 140},
|
||||||
{"numEnter", 141},
|
{"numEnter", 141},
|
||||||
{"chanUp", 142},
|
{"chanUp", 142},
|
||||||
{"chanDown", 143},
|
{"chanDown", 143},
|
||||||
{"lastChan", 144},
|
{"lastChan", 144},
|
||||||
{"exit", 145},
|
{"exit", 145},
|
||||||
{"powerToggle", 146},
|
{"powerToggle", 146},
|
||||||
{"red", 147},
|
{"red", 147},
|
||||||
{"green", 148},
|
{"green", 148},
|
||||||
{"yellow", 149},
|
{"yellow", 149},
|
||||||
{"blue", 150},
|
{"blue", 150},
|
||||||
{"video", 151},
|
{"video", 151},
|
||||||
{"previous", 152},
|
{"previous", 152},
|
||||||
{"next", 153},
|
{"next", 153},
|
||||||
{"rewind", 154},
|
{"rewind", 154},
|
||||||
{"ffwd", 155},
|
{"ffwd", 155},
|
||||||
{"closedCaption", 156},
|
{"closedCaption", 156},
|
||||||
{"stop", 157},
|
{"stop", 157},
|
||||||
{"pause", 158},
|
{"pause", 158},
|
||||||
{"up", 159},
|
{"up", 159},
|
||||||
{"down", 160},
|
{"down", 160},
|
||||||
{"left", 161},
|
{"left", 161},
|
||||||
{"right", 162},
|
{"right", 162},
|
||||||
{"settings", 163},
|
{"settings", 163},
|
||||||
{"info", 164},
|
{"info", 164},
|
||||||
{"return", 165},
|
{"return", 165},
|
||||||
{"guide", 166},
|
{"guide", 166},
|
||||||
{"reboot", 167},
|
{"reboot", 167},
|
||||||
{"dvrList", 168},
|
{"dvrList", 168},
|
||||||
{"replay", 169},
|
{"replay", 169},
|
||||||
{"play", 170},
|
{"play", 170},
|
||||||
{"select", 171},
|
{"select", 171},
|
||||||
{"record", 172},
|
{"record", 172},
|
||||||
{"menu", 173},
|
{"menu", 173},
|
||||||
{"topMenu", 174},
|
{"topMenu", 174},
|
||||||
{"prevTrack", 175},
|
{"prevTrack", 175},
|
||||||
{"nextTrack", 176},
|
{"nextTrack", 176},
|
||||||
{"powerOn", 177},
|
{"powerOn", 177},
|
||||||
{"powerOff", 178},
|
{"powerOff", 178},
|
||||||
{"dot", 179}
|
{"dot", 179}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
foreach (var item in dictionary)
|
foreach (var item in dictionary)
|
||||||
{
|
{
|
||||||
this.Add(item.Key, item.Value);
|
this.Add(item.Key, item.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,6 +104,7 @@
|
|||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="AppServer\Messengers\VideoCodecBaseMessenger.cs" />
|
||||||
<Compile Include="Audio\EssentialsVolumeLevelConfig.cs" />
|
<Compile Include="Audio\EssentialsVolumeLevelConfig.cs" />
|
||||||
<Compile Include="Bridges\BridgeBase.cs" />
|
<Compile Include="Bridges\BridgeBase.cs" />
|
||||||
<Compile Include="Bridges\BridgeFactory.cs" />
|
<Compile Include="Bridges\BridgeFactory.cs" />
|
||||||
@@ -142,22 +143,22 @@
|
|||||||
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
|
<Compile Include="Room\Config\EssentialsHuddleRoomPropertiesConfig.cs" />
|
||||||
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
|
<Compile Include="Room\Config\EssentialsHuddleVtc1PropertiesConfig.cs" />
|
||||||
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
|
<Compile Include="Room\Config\EssentialsRoomEmergencyConfig.cs" />
|
||||||
<Compile Include="Room\Cotija\CotijaConfig.cs" />
|
<Compile Include="AppServer\CotijaConfig.cs" />
|
||||||
<Compile Include="Room\Cotija\CotijaDdvc01DeviceBridge.cs" />
|
<Compile Include="AppServer\CotijaDdvc01DeviceBridge.cs" />
|
||||||
<Compile Include="Room\Cotija\Interfaces.cs" />
|
<Compile Include="AppServer\Interfaces.cs" />
|
||||||
<Compile Include="Room\Cotija\RoomBridges\CotijaBridgeBase.cs" />
|
<Compile Include="AppServer\RoomBridges\CotijaBridgeBase.cs" />
|
||||||
<Compile Include="Room\Cotija\RoomBridges\CotijaDdvc01RoomBridge.cs" />
|
<Compile Include="AppServer\RoomBridges\CotijaDdvc01RoomBridge.cs" />
|
||||||
<Compile Include="Room\Cotija\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs" />
|
<Compile Include="AppServer\RoomBridges\CotijaEssentialsHuddleSpaceRoomBridge.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IChannelExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IChannelExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IColorExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IColorExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IDPadExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDvrExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IDvrExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\INumericExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\INumericExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IPowerExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\IPowerExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\ISetTopBoxControlsExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\DeviceTypeInterfaces\ITransportExtensions.cs" />
|
<Compile Include="AppServer\DeviceTypeInterfaces\ITransportExtensions.cs" />
|
||||||
<Compile Include="Room\Cotija\RoomBridges\SourceDeviceMapDictionary.cs" />
|
<Compile Include="AppServer\RoomBridges\SourceDeviceMapDictionary.cs" />
|
||||||
<Compile Include="Room\Cotija\Volumes.cs" />
|
<Compile Include="AppServer\Volumes.cs" />
|
||||||
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
|
<Compile Include="Room\Emergency\EsentialsRoomEmergencyContactClosure.cs" />
|
||||||
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
|
<Compile Include="Room\Types\EssentialsHuddleVtc1Room.cs" />
|
||||||
<Compile Include="Room\Types\EssentialsPresentationRoom.cs" />
|
<Compile Include="Room\Types\EssentialsPresentationRoom.cs" />
|
||||||
@@ -195,7 +196,7 @@
|
|||||||
<Compile Include="UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs" />
|
<Compile Include="UIDrivers\Page Drivers\SingleSubpageModalAndBackDriver.cs" />
|
||||||
<Compile Include="UIDrivers\SmartObjectRoomsList.cs" />
|
<Compile Include="UIDrivers\SmartObjectRoomsList.cs" />
|
||||||
<Compile Include="UI\JoinConstants\UIBoolJoin.cs" />
|
<Compile Include="UI\JoinConstants\UIBoolJoin.cs" />
|
||||||
<Compile Include="Room\Cotija\CotijaSystemController.cs" />
|
<Compile Include="AppServer\CotijaSystemController.cs" />
|
||||||
<Compile Include="UI\DualDisplaySourceSRLController.cs" />
|
<Compile Include="UI\DualDisplaySourceSRLController.cs" />
|
||||||
<Compile Include="UI\SubpageReferenceListActivityItem.cs" />
|
<Compile Include="UI\SubpageReferenceListActivityItem.cs" />
|
||||||
<Compile Include="UI\CrestronTouchpanelPropertiesConfig.cs" />
|
<Compile Include="UI\CrestronTouchpanelPropertiesConfig.cs" />
|
||||||
|
|||||||
@@ -1,694 +0,0 @@
|
|||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user