mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-19 15:35:00 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e43565c1a | ||
|
|
97e157b5b6 | ||
|
|
3411fe0cf3 | ||
|
|
6713ea53f2 | ||
|
|
607f6084de | ||
|
|
1625cbe6de | ||
|
|
63e6829a03 | ||
|
|
d3719ee505 | ||
|
|
041059210c | ||
|
|
1a45ef5d0f | ||
|
|
65a0743dac | ||
|
|
32e090648c | ||
|
|
bb045ba06b | ||
|
|
474b2eb647 | ||
|
|
e6cf2794bc | ||
|
|
2c28b57806 | ||
|
|
8762f84548 | ||
|
|
b0a68f38f5 | ||
|
|
46887579e4 | ||
|
|
b095d926d2 | ||
|
|
7cebf861cc | ||
|
|
2e0b003118 | ||
|
|
bada7e3a25 | ||
|
|
67a7422cd0 |
@@ -60,4 +60,4 @@ For detailed documentation, see the [Wiki](https://github.com/PepperDash/Essenti
|
||||
|
||||
## How-To (Getting Started)
|
||||
|
||||
See [Getting Started](https://github.com/PepperDash/Essentials/wiki/Get-started#how-to-get-started)
|
||||
See [Getting Started](https://github.com/PepperDash/Essentials/wiki/Get-started#how-to-get-started)
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PepperDash.Essentials.Core.DeviceTypeInterfaces
|
||||
{
|
||||
public interface IHasWebView
|
||||
{
|
||||
bool WebviewIsVisible { get; }
|
||||
void ShowWebView(string url, string mode, string title, string target);
|
||||
void HideWebView();
|
||||
}
|
||||
}
|
||||
@@ -144,17 +144,17 @@ namespace PepperDash.Essentials.Core.Web
|
||||
Name = "GetJoinMapsForDeviceKey",
|
||||
RouteHandler = new GetJoinMapForDeviceKeyRequestHandler()
|
||||
},
|
||||
new HttpCwsRoute("debugSession")
|
||||
{
|
||||
Name = "DebugSession",
|
||||
RouteHandler = new DebugSessionRequestHandler()
|
||||
},
|
||||
new HttpCwsRoute("doNotLoadConfigOnNextBoot")
|
||||
{
|
||||
Name = "DoNotLoadConfigOnNextBoot",
|
||||
RouteHandler = new DoNotLoadConfigOnNextBootRequestHandler()
|
||||
},
|
||||
new HttpCwsRoute("restartProgram")
|
||||
new HttpCwsRoute("debugSession")
|
||||
{
|
||||
Name = "DebugSession",
|
||||
RouteHandler = new DebugSessionRequestHandler()
|
||||
},
|
||||
new HttpCwsRoute("doNotLoadConfigOnNextBoot")
|
||||
{
|
||||
Name = "DoNotLoadConfigOnNextBoot",
|
||||
RouteHandler = new DoNotLoadConfigOnNextBootRequestHandler()
|
||||
},
|
||||
new HttpCwsRoute("restartProgram")
|
||||
{
|
||||
Name = "Restart Program",
|
||||
RouteHandler = new RestartProgramRequestHandler()
|
||||
@@ -164,12 +164,16 @@ namespace PepperDash.Essentials.Core.Web
|
||||
Name = "Load Config",
|
||||
RouteHandler = new LoadConfigRequestHandler()
|
||||
},
|
||||
new HttpCwsRoute("getTielines")
|
||||
new HttpCwsRoute("tielines")
|
||||
{
|
||||
Name = "Get TieLines",
|
||||
RouteHandler = new GetTieLinesRequestHandler()
|
||||
}
|
||||
|
||||
},
|
||||
new HttpCwsRoute("device/{deviceKey}/routingPorts")
|
||||
{
|
||||
Name = "Get Routing Ports for a device",
|
||||
RouteHandler = new GetRoutingPortsHandler()
|
||||
},
|
||||
};
|
||||
|
||||
AddRoute(routes);
|
||||
@@ -196,13 +200,18 @@ namespace PepperDash.Essentials.Core.Web
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the CWS class
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
/// <summary>
|
||||
/// Initializes the CWS class
|
||||
/// </summary>
|
||||
public override void Initialize()
|
||||
{
|
||||
// If running on an appliance
|
||||
if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance)
|
||||
AddRoute(new HttpCwsRoute("apiPaths") {
|
||||
Name = "GetPaths",
|
||||
RouteHandler = new GetRoutesHandler(_server.GetRouteCollection(), BasePath)
|
||||
});
|
||||
|
||||
// If running on an appliance
|
||||
if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance)
|
||||
{
|
||||
/*
|
||||
WEBSERVER [ON | OFF | TIMEOUT <VALUE IN SECONDS> | MAXSESSIONSPERUSER <Number of sessions>]
|
||||
@@ -247,8 +256,8 @@ namespace PepperDash.Essentials.Core.Web
|
||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
|
||||
|
||||
var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server
|
||||
? $"http(s)://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{BasePath}"
|
||||
: $"http(s)://{currentIp}/cws{BasePath}";
|
||||
? $"https://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{BasePath}"
|
||||
: $"https://{currentIp}/cws{BasePath}";
|
||||
|
||||
Debug.LogMessage(LogEventLevel.Information, this, "Server:{path:l}", path);
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core.Web.RequestHandlers;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
||||
{
|
||||
public class GetRoutesHandler:WebApiBaseRequestHandler
|
||||
{
|
||||
private HttpCwsRouteCollection routeCollection;
|
||||
private string basePath;
|
||||
|
||||
public GetRoutesHandler(HttpCwsRouteCollection routeCollection, string basePath) {
|
||||
this.routeCollection = routeCollection;
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
protected override void HandleGet(HttpCwsContext context)
|
||||
{
|
||||
var currentIp = CrestronEthernetHelper.GetEthernetParameter(
|
||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, 0);
|
||||
|
||||
var hostname = CrestronEthernetHelper.GetEthernetParameter(
|
||||
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, 0);
|
||||
|
||||
var path = CrestronEnvironment.DevicePlatform == eDevicePlatform.Server
|
||||
? $"https://{hostname}/VirtualControl/Rooms/{InitialParametersClass.RoomId}/cws{basePath}"
|
||||
: $"https://{currentIp}/cws{basePath}";
|
||||
|
||||
var response = JsonConvert.SerializeObject(new RoutesResponseObject()
|
||||
{
|
||||
Url = path,
|
||||
Routes = routeCollection
|
||||
});
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.ContentType = "application/json";
|
||||
context.Response.Headers.Add("Content-Type", "application/json");
|
||||
context.Response.Write(response, false);
|
||||
context.Response.End();
|
||||
}
|
||||
}
|
||||
|
||||
public class RoutesResponseObject
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { set; get; }
|
||||
|
||||
[JsonProperty("routes")]
|
||||
public HttpCwsRouteCollection Routes { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core.Web.RequestHandlers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Web.RequestHandlers
|
||||
{
|
||||
public class GetRoutingPortsHandler : WebApiBaseRequestHandler
|
||||
{
|
||||
public GetRoutingPortsHandler() : base(true) { }
|
||||
|
||||
protected override void HandleGet(HttpCwsContext context)
|
||||
{
|
||||
var routeData = context.Request.RouteData;
|
||||
|
||||
if (routeData == null)
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
context.Response.StatusDescription = "Bad Request";
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!routeData.Values.TryGetValue("deviceKey", out var deviceKey))
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
context.Response.StatusDescription = "Bad Request";
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
var device = DeviceManager.GetDeviceForKey(deviceKey.ToString());
|
||||
|
||||
if (device == null)
|
||||
{
|
||||
context.Response.StatusCode = 404;
|
||||
context.Response.StatusDescription = "Device Not Found";
|
||||
context.Response.End();
|
||||
return;
|
||||
}
|
||||
|
||||
var inputPorts = (device as IRoutingInputs)?.InputPorts;
|
||||
var outputPorts = (device as IRoutingOutputs)?.OutputPorts;
|
||||
|
||||
var response = JsonConvert.SerializeObject( new ReturnValue
|
||||
{
|
||||
InputPorts = inputPorts?.Select(p => p.Key).ToList(),
|
||||
OutputPorts = outputPorts?.Select(p => p.Key).ToList()
|
||||
});
|
||||
|
||||
context.Response.StatusCode = 200;
|
||||
context.Response.StatusDescription = "OK";
|
||||
context.Response.ContentType = "application/json";
|
||||
context.Response.ContentEncoding = Encoding.UTF8;
|
||||
context.Response.Write(response, false);
|
||||
context.Response.End();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal class ReturnValue {
|
||||
[JsonProperty("inputPorts", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<string> InputPorts { get; set; }
|
||||
|
||||
[JsonProperty("outputPorts", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<string> OutputPorts { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||
protected override void RegisterActions()
|
||||
|
||||
{
|
||||
AddAction("/presets/fullStatus", (id, content) =>
|
||||
AddAction("/fullStatus", (id, content) =>
|
||||
{
|
||||
this.LogInformation("getting full status for client {id}", id);
|
||||
try
|
||||
@@ -56,7 +56,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||
}
|
||||
});
|
||||
|
||||
AddAction("/presets/recall", (id, content) =>
|
||||
AddAction("/recall", (id, content) =>
|
||||
{
|
||||
var p = content.ToObject<PresetChannelMessage>();
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||
RecallPreset(dev, p.Preset.Channel);
|
||||
});
|
||||
|
||||
AddAction("/presets/save", (id, content) =>
|
||||
AddAction("/save", (id, content) =>
|
||||
{
|
||||
var presets = content.ToObject<List<PresetChannel>>();
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
@@ -56,10 +59,32 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||
|
||||
private void SendFullStatus()
|
||||
{
|
||||
var stateObject = new JObject();
|
||||
stateObject[_propName] = JToken.FromObject(itemDevice, serializer);
|
||||
PostStatusMessage(stateObject);
|
||||
try
|
||||
{
|
||||
this.LogInformation("Sending full status");
|
||||
|
||||
var stateObject = new ISelectableItemsStateMessage<TKey>
|
||||
{
|
||||
Items = itemDevice.Items,
|
||||
CurrentItem = itemDevice.CurrentItem
|
||||
};
|
||||
|
||||
PostStatusMessage(stateObject);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
this.LogError("Error sending full status: {0}", e.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ISelectableItemsStateMessage<TKey> : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("items")]
|
||||
public Dictionary<TKey, ISelectableItem> Items { get; set; }
|
||||
|
||||
[JsonProperty("currentItem")]
|
||||
public TKey CurrentItem { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1133,7 +1133,11 @@ namespace PepperDash.Essentials
|
||||
|
||||
_messengers.Add(messenger.Key, messenger);
|
||||
|
||||
messenger.RegisterWithAppServer(this);
|
||||
if (_initialized)
|
||||
{
|
||||
this.LogDebug("Registering messenger {messengerKey} AFTER initialization", messenger.Key);
|
||||
messenger.RegisterWithAppServer(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddDefaultDeviceMessenger(IMobileControlMessenger messenger)
|
||||
@@ -2230,16 +2234,14 @@ Mobile Control Direct Server Infromation:
|
||||
// /room/roomAB
|
||||
|
||||
// Can't do direct comparison because it will match /room/roomA with /room/roomA/xxx instead of /room/roomAB/xxx
|
||||
var handlersKv = _actionDictionary.FirstOrDefault(kv => message.Type.StartsWith(kv.Key + "/")); // adds trailing slash to ensure above case is handled
|
||||
var handlers = _actionDictionary.Where(kv => message.Type.StartsWith(kv.Key + "/")).SelectMany(kv => kv.Value).ToList(); // adds trailing slash to ensure above case is handled
|
||||
|
||||
|
||||
if (handlersKv.Key == null)
|
||||
if (handlers.Count == 0)
|
||||
{
|
||||
this.LogInformation("-- Warning: Incoming message has no registered handler {type}", message.Type);
|
||||
break;
|
||||
}
|
||||
|
||||
var handlers = handlersKv.Value;
|
||||
}
|
||||
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
|
||||
@@ -116,64 +116,6 @@ namespace PepperDash.Essentials.RoomBridges
|
||||
if (Room is IRunDefaultPresentRoute defaultRoom)
|
||||
AddAction("/defaultsource", (id, content) => defaultRoom.RunDefaultPresentRoute());
|
||||
|
||||
if (Room is IHasCurrentVolumeControls volumeRoom)
|
||||
{
|
||||
volumeRoom.CurrentVolumeDeviceChange += Room_CurrentVolumeDeviceChange;
|
||||
|
||||
if (volumeRoom.CurrentVolumeControls == null) return;
|
||||
|
||||
AddAction("/volumes/master/level", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<ushort>>();
|
||||
|
||||
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
basicVolumeWithFeedback.SetVolume(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/volumes/master/muteToggle", (id, content) => volumeRoom.CurrentVolumeControls.MuteToggle());
|
||||
|
||||
AddAction("/volumes/master/muteOn", (id, content) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
basicVolumeWithFeedback.MuteOn();
|
||||
});
|
||||
|
||||
AddAction("/volumes/master/muteOff", (id, content) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
basicVolumeWithFeedback.MuteOff();
|
||||
});
|
||||
|
||||
AddAction("/volumes/master/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
{
|
||||
basicVolumeWithFeedback.VolumeUp(b);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
AddAction("/volumes/master/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
{
|
||||
basicVolumeWithFeedback.VolumeDown(b);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
// Registers for initial volume events, if possible
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback currentVolumeDevice)
|
||||
{
|
||||
this.LogVerbose("Registering for volume feedback events");
|
||||
|
||||
currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
|
||||
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||
}
|
||||
}
|
||||
|
||||
if (Room is IHasCurrentSourceInfoChange sscRoom)
|
||||
sscRoom.CurrentSourceChange += Room_CurrentSingleSourceChange;
|
||||
|
||||
@@ -212,6 +154,63 @@ namespace PepperDash.Essentials.RoomBridges
|
||||
Room.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange;
|
||||
|
||||
AddTechRoomActions();
|
||||
|
||||
if (Room is IHasCurrentVolumeControls volumeRoom)
|
||||
{
|
||||
volumeRoom.CurrentVolumeDeviceChange += Room_CurrentVolumeDeviceChange;
|
||||
|
||||
if (volumeRoom.CurrentVolumeControls == null) return;
|
||||
|
||||
AddAction("/volumes/master/level", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<ushort>>();
|
||||
|
||||
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
basicVolumeWithFeedback.SetVolume(msg.Value);
|
||||
});
|
||||
|
||||
AddAction("/volumes/master/muteToggle", (id, content) => volumeRoom.CurrentVolumeControls.MuteToggle());
|
||||
|
||||
AddAction("/volumes/master/muteOn", (id, content) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
basicVolumeWithFeedback.MuteOn();
|
||||
});
|
||||
|
||||
AddAction("/volumes/master/muteOff", (id, content) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
basicVolumeWithFeedback.MuteOff();
|
||||
});
|
||||
|
||||
AddAction("/volumes/master/volumeUp", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
{
|
||||
basicVolumeWithFeedback.VolumeUp(b);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
AddAction("/volumes/master/volumeDown", (id, content) => PressAndHoldHandler.HandlePressAndHold(DeviceKey, content, (b) =>
|
||||
{
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback basicVolumeWithFeedback)
|
||||
{
|
||||
basicVolumeWithFeedback.VolumeDown(b);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
// Registers for initial volume events, if possible
|
||||
if (volumeRoom.CurrentVolumeControls is IBasicVolumeWithFeedback currentVolumeDevice)
|
||||
{
|
||||
this.LogVerbose("Registering for volume feedback events");
|
||||
|
||||
currentVolumeDevice.MuteFeedback.OutputChange += MuteFeedback_OutputChange;
|
||||
currentVolumeDevice.VolumeLevelFeedback.OutputChange += VolumeLevelFeedback_OutputChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTouchPanelsUpdated(JToken content)
|
||||
|
||||
@@ -483,11 +483,13 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
var room = Core.DeviceFactory.GetDevice(roomConfig);
|
||||
|
||||
DeviceManager.AddDevice(room);
|
||||
if (room is ICustomMobileControl)
|
||||
if(room == null)
|
||||
{
|
||||
Debug.LogWarning("ERROR: Cannot load unknown room type '{roomType:l}', key '{roomKey:l}'.", roomConfig.Type, roomConfig.Key);
|
||||
continue;
|
||||
}
|
||||
|
||||
DeviceManager.AddDevice(room);
|
||||
} catch (Exception ex)
|
||||
{
|
||||
Debug.LogMessage(ex, "Exception loading room {roomKey}:{roomType}", null, roomConfig.Key, roomConfig.Type);
|
||||
|
||||
Reference in New Issue
Block a user