Skip to content
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Crestron.SimplSharp.SDK.ProgramLibrary" Version="2.21.90" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup>
<ItemGroup>
<None Include="Crestron\CrestronGenericBaseDevice.cs.orig" />
Expand Down
193 changes: 193 additions & 0 deletions src/PepperDash.Essentials.Core/Web/Attributes/OpenApiAttributes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
using System;
using System.ComponentModel;

namespace PepperDash.Essentials.Core.Web.Attributes
{
/// <summary>
/// Base class for HTTP method attributes
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public abstract class HttpMethodAttribute : Attribute
{
public string Method { get; }

protected HttpMethodAttribute(string method)
{
Method = method;
}
}

/// <summary>
/// Indicates that a request handler supports HTTP GET operations
/// </summary>
public class HttpGetAttribute : HttpMethodAttribute
{
public HttpGetAttribute() : base("GET") { }
}

/// <summary>
/// Indicates that a request handler supports HTTP POST operations
/// </summary>
public class HttpPostAttribute : HttpMethodAttribute
{
public HttpPostAttribute() : base("POST") { }
}

/// <summary>
/// Indicates that a request handler supports HTTP PUT operations
/// </summary>
public class HttpPutAttribute : HttpMethodAttribute
{
public HttpPutAttribute() : base("PUT") { }
}

/// <summary>
/// Indicates that a request handler supports HTTP DELETE operations
/// </summary>
public class HttpDeleteAttribute : HttpMethodAttribute
{
public HttpDeleteAttribute() : base("DELETE") { }
}

/// <summary>
/// Provides OpenAPI operation metadata for a request handler
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class OpenApiOperationAttribute : Attribute
{
/// <summary>
/// A brief summary of what the operation does
/// </summary>
public string Summary { get; set; }

/// <summary>
/// A verbose explanation of the operation behavior
/// </summary>
public string Description { get; set; }

/// <summary>
/// Unique string used to identify the operation
/// </summary>
public string OperationId { get; set; }

/// <summary>
/// A list of tags for API documentation control
/// </summary>
public string[] Tags { get; set; }

public OpenApiOperationAttribute()
{
}
}

/// <summary>
/// Describes a response from an API operation
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class OpenApiResponseAttribute : Attribute
{
/// <summary>
/// The HTTP status code
/// </summary>
public int StatusCode { get; }

/// <summary>
/// A short description of the response
/// </summary>
public string Description { get; set; }

/// <summary>
/// The content type of the response
/// </summary>
public string ContentType { get; set; } = "application/json";

/// <summary>
/// The type that represents the response schema
/// </summary>
public Type Type { get; set; }

public OpenApiResponseAttribute(int statusCode)
{
StatusCode = statusCode;
}
}

/// <summary>
/// Indicates that an operation requires a request body
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class OpenApiRequestBodyAttribute : Attribute
{
/// <summary>
/// Determines if the request body is required
/// </summary>
public bool Required { get; set; } = true;

/// <summary>
/// The content type of the request body
/// </summary>
public string ContentType { get; set; } = "application/json";

/// <summary>
/// The type that represents the request body schema
/// </summary>
public Type Type { get; set; }

/// <summary>
/// Description of the request body
/// </summary>
public string Description { get; set; }

public OpenApiRequestBodyAttribute()
{
}
}

/// <summary>
/// Describes a parameter for the operation
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public class OpenApiParameterAttribute : Attribute
{
/// <summary>
/// The name of the parameter
/// </summary>
public string Name { get; }

/// <summary>
/// The location of the parameter
/// </summary>
public ParameterLocation In { get; set; } = ParameterLocation.Path;

/// <summary>
/// Determines whether this parameter is mandatory
/// </summary>
public bool Required { get; set; } = true;

/// <summary>
/// A brief description of the parameter
/// </summary>
public string Description { get; set; }

/// <summary>
/// The type of the parameter
/// </summary>
public Type Type { get; set; } = typeof(string);

public OpenApiParameterAttribute(string name)
{
Name = name;
}
}

/// <summary>
/// The location of the parameter
/// </summary>
public enum ParameterLocation
{
Query,
Header,
Path,
Cookie
}
}
5 changes: 5 additions & 0 deletions src/PepperDash.Essentials.Core/Web/EssentialsWebApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ public override void Initialize()
RouteHandler = new GetRoutesHandler(_server.GetRouteCollection(), BasePath)
});

AddRoute(new HttpCwsRoute("swagger") {
Name = "OpenAPI Documentation",
RouteHandler = new SwaggerHandler(_server.GetRouteCollection(), BasePath)
});

// If running on an appliance
if (CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,22 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;
using System;
using Serilog.Events;
using Newtonsoft.Json.Converters;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpGet]
[HttpPost]
[OpenApiOperation(
Summary = "AppDebug",
Description = "Get or set application debug level settings",
OperationId = "appDebug")]
[OpenApiRequestBody(Description = "Debug level configuration")]
[OpenApiResponse(200, Description = "Successful response", ContentType = "application/json")]
[OpenApiResponse(400, Description = "Bad Request")]
public class AppDebugRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;
using Serilog.Events;
using System;
using System.Collections.Generic;
Expand All @@ -13,7 +14,15 @@

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
public class DebugSessionRequestHandler : WebApiBaseRequestHandler
[HttpGet]
[HttpPost]
[OpenApiOperation(
Summary = "DebugSession",
Description = "Start or stop a WebSocket debug session",
OperationId = "debugSession")]
[OpenApiResponse(200, Description = "Successful response", ContentType = "application/json")]
[OpenApiResponse(400, Description = "Bad Request")]
public class DebugSessionRequestHandler : WebApiBaseRequestHandler
{
public DebugSessionRequestHandler()
: base(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,20 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;
using Serilog.Events;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpPost]
[OpenApiOperation(
Summary = "DevJson",
Description = "Send a command to a specific device",
OperationId = "sendDeviceCommand")]
[OpenApiParameter("deviceKey", Description = "The key of the device to send the command to")]
[OpenApiRequestBody(Description = "Device command data")]
[OpenApiResponse(200, Description = "Command executed successfully")]
[OpenApiResponse(400, Description = "Bad Request")]
public class DevJsonRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@
using Crestron.SimplSharp.WebScripting;
using Newtonsoft.Json;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpGet]
[OpenApiOperation(
Summary = "DevList",
Description = "Retrieve a list of all devices in the system",
OperationId = "getDevices")]
[OpenApiResponse(200, Description = "Successful response", ContentType = "application/json")]
[OpenApiResponse(404, Description = "Not Found")]
public class DevListRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,19 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpGet]
[OpenApiOperation(
Summary = "DevMethods",
Description = "Retrieve available methods for a specific device",
OperationId = "getDeviceMethods")]
[OpenApiParameter("deviceKey", Description = "The key of the device")]
[OpenApiResponse(200, Description = "Successful response", ContentType = "application/json")]
[OpenApiResponse(400, Description = "Bad Request")]
[OpenApiResponse(404, Description = "Device not found")]
public class DevMethodsRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@
using Crestron.SimplSharp.WebScripting;
using Newtonsoft.Json;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpGet]
[OpenApiOperation(
Summary = "DevProps",
Description = "Retrieve properties for a specific device",
OperationId = "getDeviceProperties")]
[OpenApiParameter("deviceKey", Description = "The key of the device")]
[OpenApiResponse(200, Description = "Successful response", ContentType = "application/json")]
[OpenApiResponse(400, Description = "Bad Request")]
[OpenApiResponse(404, Description = "Device not found")]
public class DevPropsRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
using Crestron.SimplSharp.WebScripting;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpPost]
[OpenApiOperation(
Summary = "DisableAllStreamDebug",
Description = "Disable stream debugging for all devices",
OperationId = "disableAllStreamDebug")]
[OpenApiResponse(200, Description = "Successful response")]
public class DisableAllStreamDebugRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpGet]
[HttpPost]
[OpenApiOperation(
Summary = "DoNotLoadConfigOnNextBoot",
Description = "Get or set flag to prevent configuration loading on next boot",
OperationId = "doNotLoadConfigOnNextBoot")]
[OpenApiRequestBody(Description = "Configuration loading flag")]
[OpenApiResponse(200, Description = "Successful response", ContentType = "application/json")]
[OpenApiResponse(400, Description = "Bad Request")]
public class DoNotLoadConfigOnNextBootRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@
using Crestron.SimplSharp.WebScripting;
using Newtonsoft.Json;
using PepperDash.Core.Web.RequestHandlers;
using PepperDash.Essentials.Core.Web.Attributes;

namespace PepperDash.Essentials.Core.Web.RequestHandlers
{
[HttpGet]
[OpenApiOperation(
Summary = "GetFeedbacksForDeviceKey",
Description = "Get feedback values from a specific device",
OperationId = "getDeviceFeedbacks")]
[OpenApiParameter("deviceKey", Description = "The key of the device to get feedbacks from")]
[OpenApiResponse(200, Description = "Device feedback values")]
[OpenApiResponse(400, Description = "Bad Request")]
[OpenApiResponse(404, Description = "Device not found")]
public class GetFeedbacksForDeviceRequestHandler : WebApiBaseRequestHandler
{
/// <summary>
Expand Down
Loading