@@ -0,0 +1,61 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Threading.Tasks; | |||
using System.Web; | |||
using Microsoft.AspNetCore.Mvc; | |||
using MQTTnet.Server.Mqtt; | |||
using MQTTnet.Server.Status; | |||
namespace MQTTnet.Server.Controllers | |||
{ | |||
[ApiController] | |||
public class ClientsController : ControllerBase | |||
{ | |||
private readonly MqttServerService _mqttServerService; | |||
public ClientsController(MqttServerService mqttServerService) | |||
{ | |||
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService)); | |||
} | |||
[Route("api/v1/clients")] | |||
[HttpGet] | |||
public async Task<ActionResult<IList<IMqttClientStatus>>> GetClients() | |||
{ | |||
return new ObjectResult(await _mqttServerService.GetClientStatusAsync()); | |||
} | |||
[Route("api/v1/clients/{clientId}")] | |||
[HttpGet] | |||
public async Task<ActionResult<IMqttClientStatus>> GetClient(string clientId) | |||
{ | |||
clientId = HttpUtility.UrlDecode(clientId); | |||
var client = (await _mqttServerService.GetClientStatusAsync()).FirstOrDefault(c => c.ClientId == clientId); | |||
if (client == null) | |||
{ | |||
return new StatusCodeResult((int)HttpStatusCode.NotFound); | |||
} | |||
return new ObjectResult(client); | |||
} | |||
[Route("api/v1/clients/{clientId}")] | |||
[HttpDelete] | |||
public async Task<ActionResult> DeleteClient(string clientId) | |||
{ | |||
clientId = HttpUtility.UrlDecode(clientId); | |||
var client = (await _mqttServerService.GetClientStatusAsync()).FirstOrDefault(c => c.ClientId == clientId); | |||
if (client == null) | |||
{ | |||
return new StatusCodeResult((int)HttpStatusCode.NotFound); | |||
} | |||
await client.DisconnectAsync(); | |||
return StatusCode((int)HttpStatusCode.NoContent); | |||
} | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Threading.Tasks; | |||
using System.Web; | |||
using Microsoft.AspNetCore.Mvc; | |||
using MQTTnet.Server.Mqtt; | |||
namespace MQTTnet.Server.Controllers | |||
{ | |||
[ApiController] | |||
public class RetainedApplicationMessagesController : ControllerBase | |||
{ | |||
private readonly MqttServerService _mqttServerService; | |||
public RetainedApplicationMessagesController(MqttServerService mqttServerService) | |||
{ | |||
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService)); | |||
} | |||
[Route("api/v1/retainedApplicationMessages")] | |||
[HttpGet] | |||
public async Task<ActionResult<IList<MqttApplicationMessage>>> GetRetainedApplicationMessages() | |||
{ | |||
return new ObjectResult(await _mqttServerService.GetRetainedApplicationMessagesAsync()); | |||
} | |||
[Route("api/v1/retainedApplicationMessages/{topic}")] | |||
[HttpGet] | |||
public async Task<ActionResult<MqttApplicationMessage>> GetRetainedApplicationMessage(string topic) | |||
{ | |||
topic = HttpUtility.UrlDecode(topic); | |||
var applicationMessage = (await _mqttServerService.GetRetainedApplicationMessagesAsync()).FirstOrDefault(c => c.Topic == topic); | |||
if (applicationMessage == null) | |||
{ | |||
return new StatusCodeResult((int)HttpStatusCode.NotFound); | |||
} | |||
return new ObjectResult(applicationMessage); | |||
} | |||
[Route("api/v1/retainedApplicationMessages")] | |||
[HttpDelete] | |||
public async Task<ActionResult> DeleteRetainedApplicationMessages() | |||
{ | |||
await _mqttServerService.ClearRetainedApplicationMessagesAsync(); | |||
return StatusCode((int)HttpStatusCode.NoContent); | |||
} | |||
[Route("api/v1/retainedApplicationMessages/{topic}")] | |||
[HttpDelete] | |||
public async Task<ActionResult> DeleteRetainedApplicationMessage(string topic) | |||
{ | |||
topic = HttpUtility.UrlDecode(topic); | |||
await _mqttServerService.PublishAsync(new MqttApplicationMessageBuilder().WithTopic(topic).WithRetainFlag().Build()); | |||
return StatusCode((int)HttpStatusCode.NoContent); | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace MQTTnet.Server.Controllers | |||
{ | |||
public class ScriptsController | |||
{ | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Net; | |||
using System.Threading.Tasks; | |||
using System.Web; | |||
using Microsoft.AspNetCore.Mvc; | |||
using MQTTnet.Server.Mqtt; | |||
using MQTTnet.Server.Status; | |||
namespace MQTTnet.Server.Controllers | |||
{ | |||
[ApiController] | |||
public class SessionsController : ControllerBase | |||
{ | |||
private readonly MqttServerService _mqttServerService; | |||
public SessionsController(MqttServerService mqttServerService) | |||
{ | |||
_mqttServerService = mqttServerService ?? throw new ArgumentNullException(nameof(mqttServerService)); | |||
} | |||
[Route("api/v1/sessions")] | |||
[HttpGet] | |||
public async Task<ActionResult<IList<IMqttSessionStatus>>> GetSessions() | |||
{ | |||
return new ObjectResult(await _mqttServerService.GetSessionStatusAsync()); | |||
} | |||
[Route("api/v1/sessions/{clientId}")] | |||
[HttpGet] | |||
public async Task<ActionResult<IMqttClientStatus>> GetSession(string clientId) | |||
{ | |||
clientId = HttpUtility.UrlDecode(clientId); | |||
var session = (await _mqttServerService.GetSessionStatusAsync()).FirstOrDefault(c => c.ClientId == clientId); | |||
if (session == null) | |||
{ | |||
return new StatusCodeResult((int)HttpStatusCode.NotFound); | |||
} | |||
return new ObjectResult(session); | |||
} | |||
[Route("api/v1/sessions/{clientId}")] | |||
[HttpDelete] | |||
public async Task<ActionResult> DeleteSession(string clientId) | |||
{ | |||
clientId = HttpUtility.UrlDecode(clientId); | |||
var session = (await _mqttServerService.GetSessionStatusAsync()).FirstOrDefault(c => c.ClientId == clientId); | |||
if (session == null) | |||
{ | |||
return new StatusCodeResult((int)HttpStatusCode.NotFound); | |||
} | |||
await session.DeleteAsync(); | |||
return StatusCode((int)HttpStatusCode.NoContent); | |||
} | |||
[Route("api/v1/sessions/{clientId}/pendingApplicationMessages")] | |||
[HttpDelete] | |||
public async Task<ActionResult> DeletePendingApplicationMessages(string clientId) | |||
{ | |||
clientId = HttpUtility.UrlDecode(clientId); | |||
var session = (await _mqttServerService.GetSessionStatusAsync()).FirstOrDefault(c => c.ClientId == clientId); | |||
if (session == null) | |||
{ | |||
return new StatusCodeResult((int)HttpStatusCode.NotFound); | |||
} | |||
await session.ClearPendingApplicationMessagesAsync(); | |||
return StatusCode((int)HttpStatusCode.NoContent); | |||
} | |||
} | |||
} |
@@ -1,42 +0,0 @@ | |||
using System.Collections.Generic; | |||
using Microsoft.AspNetCore.Mvc; | |||
namespace MQTTnet.Server.Controllers | |||
{ | |||
[Route("api/[controller]")] | |||
[ApiController] | |||
public class ValuesController : ControllerBase | |||
{ | |||
// GET api/values | |||
[HttpGet] | |||
public ActionResult<IEnumerable<string>> Get() | |||
{ | |||
return new string[] { "value1", "value2" }; | |||
} | |||
// GET api/values/5 | |||
[HttpGet("{id}")] | |||
public ActionResult<string> Get(int id) | |||
{ | |||
return "value"; | |||
} | |||
// POST api/values | |||
[HttpPost] | |||
public void Post([FromBody] string value) | |||
{ | |||
} | |||
// PUT api/values/5 | |||
[HttpPut("{id}")] | |||
public void Put(int id, [FromBody] string value) | |||
{ | |||
} | |||
// DELETE api/values/5 | |||
[HttpDelete("{id}")] | |||
public void Delete(int id) | |||
{ | |||
} | |||
} | |||
} |
@@ -40,8 +40,8 @@ | |||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" /> | |||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.2.0" /> | |||
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" /> | |||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="4.0.1" /> | |||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="4.0.1" /> | |||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="5.0.0-rc2" /> | |||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.0.0-rc2" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
@@ -10,10 +10,12 @@ using Microsoft.AspNetCore.Http; | |||
using Microsoft.Extensions.Logging; | |||
using MQTTnet.Adapter; | |||
using MQTTnet.AspNetCore; | |||
using MQTTnet.Client.Publishing; | |||
using MQTTnet.Implementations; | |||
using MQTTnet.Protocol; | |||
using MQTTnet.Server.Configuration; | |||
using MQTTnet.Server.Scripting; | |||
using MQTTnet.Server.Status; | |||
namespace MQTTnet.Server.Mqtt | |||
{ | |||
@@ -92,6 +94,33 @@ namespace MQTTnet.Server.Mqtt | |||
return _webSocketServerAdapter.RunWebSocketConnectionAsync(webSocket, httpContext); | |||
} | |||
public Task<IList<IMqttClientStatus>> GetClientStatusAsync() | |||
{ | |||
return _mqttServer.GetClientStatusAsync(); | |||
} | |||
public Task<IList<IMqttSessionStatus>> GetSessionStatusAsync() | |||
{ | |||
return _mqttServer.GetSessionStatusAsync(); | |||
} | |||
public Task ClearRetainedApplicationMessagesAsync() | |||
{ | |||
return _mqttServer.ClearRetainedApplicationMessagesAsync(); | |||
} | |||
public Task<IList<MqttApplicationMessage>> GetRetainedApplicationMessagesAsync() | |||
{ | |||
return _mqttServer.GetRetainedApplicationMessagesAsync(); | |||
} | |||
public Task<MqttClientPublishResult> PublishAsync(MqttApplicationMessage applicationMessage) | |||
{ | |||
if (applicationMessage == null) throw new ArgumentNullException(nameof(applicationMessage)); | |||
return _mqttServer.PublishAsync(applicationMessage); | |||
} | |||
private void Publish(PythonDictionary parameters) | |||
{ | |||
try | |||
@@ -5,12 +5,14 @@ using Microsoft.AspNetCore.Mvc; | |||
using Microsoft.EntityFrameworkCore.Internal; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.OpenApi.Models; | |||
using Microsoft.Scripting.Utils; | |||
using MQTTnet.Server.Configuration; | |||
using MQTTnet.Server.Logging; | |||
using MQTTnet.Server.Mqtt; | |||
using MQTTnet.Server.Scripting; | |||
using MQTTnet.Server.Scripting.DataSharing; | |||
using Swashbuckle.AspNetCore.SwaggerUI; | |||
namespace MQTTnet.Server | |||
{ | |||
@@ -55,11 +57,28 @@ namespace MQTTnet.Server | |||
pythonScriptHostService.Configure(); | |||
mqttServerService.Configure(); | |||
application.UseSwagger(o => o.RouteTemplate = "/api/{documentName}/swagger.json"); | |||
application.UseSwaggerUI(o => | |||
{ | |||
o.RoutePrefix = "api"; | |||
o.DocumentTitle = "MQTTnet.Server API"; | |||
o.SwaggerEndpoint("/api/v1/swagger.json", "MQTTnet.Server API v1"); | |||
o.DisplayRequestDuration(); | |||
o.DocExpansion(DocExpansion.List); | |||
o.DefaultModelRendering(ModelRendering.Model); | |||
}); | |||
} | |||
public void ConfigureServices(IServiceCollection services) | |||
{ | |||
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); | |||
services.AddMvc() | |||
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2) | |||
.AddJsonOptions(options => | |||
{ | |||
options.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter()); | |||
}); | |||
services.AddSingleton(ReadSettings()); | |||
@@ -79,6 +98,28 @@ namespace MQTTnet.Server | |||
services.AddSingleton<MqttConnectionValidator>(); | |||
services.AddSingleton<MqttSubscriptionInterceptor>(); | |||
services.AddSingleton<MqttApplicationMessageInterceptor>(); | |||
services.AddSwaggerGen(c => | |||
{ | |||
c.DescribeAllEnumsAsStrings(); | |||
c.SwaggerDoc("v1", new OpenApiInfo | |||
{ | |||
Title = "MQTTnet.Server API", | |||
Version = "v1", | |||
Description = "The public API for the MQTT broker MQTTnet.Server.", | |||
License = new OpenApiLicense | |||
{ | |||
Name = "MIT", | |||
Url = new Uri("https://github.com/chkr1011/MQTTnet/blob/master/README.md") | |||
}, | |||
Contact = new OpenApiContact | |||
{ | |||
Name = "MQTTnet.Server", | |||
Email = string.Empty, | |||
Url = new Uri("https://github.com/chkr1011/MQTTnet") | |||
}, | |||
}); | |||
}); | |||
} | |||
private SettingsModel ReadSettings() | |||