123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- using Edge.Core.UniversalApi;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Microsoft.AspNetCore.Hosting;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Hosting;
- using Microsoft.AspNetCore;
- using MQTTnet.AspNetCore;
- using Edge.Core.Processor;
- using Edge.Core.Configuration;
- using Microsoft.Extensions.Logging;
- using Edge.Core;
- using Edge.Core.Processor.Dispatcher;
- namespace Edge.WebHost
- {
- public class AspNetCoreWebApiCommunicatorProvider : ICommunicationProvider
- {
- public static UniversalApiHub UniversalApiHub { get; private set; }
- private bool isWebHostStarted = false;
- private IHost webHost;
- private IServiceProvider appServices;
- private IEnumerable<IProcessor> processors;
- public AspNetCoreWebApiCommunicatorProvider(IServiceProvider appServices)
- {
- this.appServices = appServices;
- }
- public void Dispose()
- {
- this.webHost?.Dispose();
- this.webHost?.StopAsync().Wait();
- }
- public IEnumerable<UniversalApiInfoDoc> GetApiDocuments()
- {
- var pDescriptors = this.processors.Select(p => p.ProcessorDescriptor())
- .Where(d => d.UniversalApiInfos != null && d.UniversalApiInfos.Any());
- return pDescriptors.SelectMany(pd => pd.UniversalApiInfos).Select(apiInfo =>
- {
- var doc = new UniversalApiInfoDoc()
- {
- ProviderType = apiInfo.Processor.ProcessorDescriptor().DeviceHandlerOrApp.GetType().FullName
- //+ ", " + apiInfo.Processor.MetaConfigName
- ,
- BaseCategory = apiInfo.ServiceApiInfo == null ?
- (apiInfo.PropertyApiInfo == null ? "Event" : "Property") : "Service",
- ProviderConfigName = apiInfo.Processor.MetaConfigName,
- Description = apiInfo.ApiAttribute.Description,
- InputParametersExampleJson = apiInfo.ApiAttribute.InputParametersExampleJson,
- //InputParameters = apiInfo.ServiceApiInfo == null ?
- // // for event, providing the EventDataType
- // (apiInfo.PropertyApiInfo == null ?
- // (apiInfo.EventApiInfo?.EventDataType?.ToString() ?? "")
- // : apiInfo.PropertyApiInfo.PropertyType.ToString()) :
- // // for service, providing the parameter list
- // apiInfo.ServiceApiInfo.GetParameters()?.Select(p => p.ParameterType.Name + " " + (p.Name ?? ""))?.Aggregate("", (acc, n) => (string.IsNullOrEmpty(acc) ? "" : (acc + ", ")) + n) ?? "",
- };
- var rawTags = new Type[] { apiInfo.Processor.ProcessorDescriptor().DeviceHandlerOrApp.GetType() }.ExtractProcessorMetaDescriptor(true).FirstOrDefault()?.Tags;
- if (rawTags != null)
- {
- var localizedTags = new List<string>();
- foreach (var t in rawTags)
- localizedTags.Add(t.LocalizedContent("en"));
- doc.ProviderTags = localizedTags.ToArray();
- }
- string apiName = null;
- string path = null;
- string[] inputParametersJsonSchemaStrings = null;
- string outputParameterJsonSchema = null;
- if (apiInfo.ServiceApiInfo != null)
- {
- apiName = apiInfo.ServiceApiInfo.Name;
- path = $"/u/?apitype=service&an={apiName}&pn={apiInfo.Processor.MetaConfigName}&en={apiInfo.Processor.ProcessorDescriptor().DeviceHandlerOrApp.GetType().FullName}";
- inputParametersJsonSchemaStrings = apiInfo.ServiceApiInfo.ResolveParamsJsonSchemas().ToArray();
- outputParameterJsonSchema = apiInfo.ServiceApiInfo.ReturnType.GetGenericArguments().FirstOrDefault()?.ResolveParamsJsonSchema();
- }
- else if (apiInfo.PropertyApiInfo != null)
- {
- apiName = apiInfo.PropertyApiInfo.Name;
- path = $"/u/?apitype=property&an={apiName}&pn={apiInfo.Processor.MetaConfigName}&en={apiInfo.Processor.ProcessorDescriptor().DeviceHandlerOrApp.GetType().FullName}";
- if (!apiInfo.PropertyApiInfo.CanWrite
- || apiInfo.PropertyApiInfo.SetMethod == null
- || (apiInfo.PropertyApiInfo.SetMethod?.IsPrivate ?? false))
- {
- // indicates this Property is read-only
- inputParametersJsonSchemaStrings = null;
- }
- else
- inputParametersJsonSchemaStrings = new string[] { apiInfo.PropertyApiInfo.ResolveParamsJsonSchemas() };
- outputParameterJsonSchema = apiInfo.PropertyApiInfo.ResolveParamsJsonSchemas();
- }
- else if (apiInfo.EventApiInfo != null)
- {
- outputParameterJsonSchema = apiInfo.EventApiInfo.EventDataType?.ResolveParamsJsonSchema();
- }
- doc.ApiName = apiName;
- doc.Path = path;
- doc.InputParametersJsonSchemaStrings = inputParametersJsonSchemaStrings;
- doc.InputParametersExampleJson = doc.InputParametersExampleJson ?? inputParametersJsonSchemaStrings?.GenerateParametersJsonSample();
- doc.OutputParametersJsonSchema = outputParameterJsonSchema;
- doc.OutputParametersExampleJson = doc.OutputParametersExampleJson ?? outputParameterJsonSchema?.GenerateParameterJsonSample();
- return doc;
- });
- return Enumerable.Empty<UniversalApiInfoDoc>();
- //throw new NotImplementedException();
- }
- public Task<bool> RouteEventAsync(IProcessor eventSource, EventDescriptor eventDescriptor)
- {
- //does not support event yet.
- return Task.FromResult(false);
- }
- public async Task SetupAsync(IEnumerable<IProcessor> processors)
- {
- UniversalApiHub = this.appServices.GetRequiredService<UniversalApiHub>();
- this.processors = processors;
- if (this.isWebHostStarted) return;
- var configurator = this.appServices.GetService<Configurator>();
- var httpListeningIp = configurator.MetaConfiguration.Parameter?.FirstOrDefault(p => p.Name == "WebHostHttpListeningIp")?.Value ?? "*";
- var httpListeningPort = configurator.MetaConfiguration.Parameter?.FirstOrDefault(p => p.Name == "WebHostHttpListeningPort")?.Value ?? "8384";
- var mqttServerTcpListeningIp = configurator.MetaConfiguration.Parameter?.FirstOrDefault(p => p.Name == "MqttServerTcpListeningIp")?.Value ?? "*";
- var mqttServerTcpListeningPort = configurator.MetaConfiguration.Parameter?.FirstOrDefault(p => p.Name == "MqttServerTcpListeningPort")?.Value ?? "8388";
- this.webHost = CreateHostBuilder(
- new string[] { "%LAUNCHER_ARGS%" },
- httpListeningIp,
- int.Parse(httpListeningPort),
- mqttServerTcpListeningIp,
- int.Parse(mqttServerTcpListeningPort)).Build();
- await this.webHost.StartAsync();
- this.isWebHostStarted = true;
- }
- private IHostBuilder CreateHostBuilder(string[] args,
- string httpListeningIp, int httpListeningPort,
- string mqttServerTcpListeningIp,
- int mqttServerTcpListeningPort
- ) =>
- Host.CreateDefaultBuilder(args)
- .ConfigureServices((hostBuilderContext, aspNetCoreServices) =>
- {
- aspNetCoreServices.Configure<HostOptions>(option =>
- {
- option.ShutdownTimeout = TimeSpan.FromSeconds(60);
- });
- Func<IEnumerable<IProcessor>> pFactory = () => processors;
- aspNetCoreServices.AddSingleton(pFactory);
- aspNetCoreServices.AddSingleton(this.appServices.GetRequiredService<UniversalApiHub>());
- aspNetCoreServices.AddSingleton(this.appServices.GetRequiredService<UniversalApiInvoker>());
- aspNetCoreServices.AddSingleton(this.appServices.GetService<IProcessorMetaConfigAccessor>());
- })
- //.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Error))
- .ConfigureWebHostDefaults(webBuilder =>
- {
- webBuilder.ConfigureKestrel(o =>
- {
- if (mqttServerTcpListeningIp == "*")
- o.ListenAnyIP(mqttServerTcpListeningPort, l => l.UseMqtt()); // MQTT pipeline
- else
- o.Listen(System.Net.IPAddress.Parse(mqttServerTcpListeningIp), mqttServerTcpListeningPort, l => l.UseMqtt()); // MQTT pipeline
- if (httpListeningIp == "*")
- o.ListenAnyIP(httpListeningPort);// Default HTTP pipeline
- else
- o.Listen(System.Net.IPAddress.Parse(httpListeningIp), httpListeningPort);// Default HTTP pipeline
- });
- webBuilder.UseStartup<Startup>();
- //webBuilder.UseUrls(url);
- });
- }
- }
|