123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- using Edge.Core.Processor;
- using Edge.Core.UniversalApi;
- using Microsoft.AspNetCore.Mvc;
- using Microsoft.Extensions.Logging;
- using Microsoft.Net.Http.Headers;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Reflection;
- using System.Text.Json;
- using System.Text.Json.Serialization;
- using System.Threading.Tasks;
- using Microsoft.Extensions.DependencyInjection;
- using Edge.WebHost.Models;
- using Edge.Core.Processor.Dispatcher;
- using System.Diagnostics.CodeAnalysis;
- using Edge.Core.UniversalApi.Auditing;
- using Edge.Core.Processor.Dispatcher.Attributes;
- using Edge.Core;
- namespace Edge.WebHost.Controllers
- {
- public class HomeController : Controller
- {
- public const string UniversalWebApiHandlerRoute = "u";
- //private readonly ILogger<HomeController> _logger;
- private readonly Func<IEnumerable<IProcessor>> processorFactory;
- private UniversalApiHub universalApiHub;
- private UniversalApiInvoker universalApiInvoker;
- private IProcessorMetaConfigAccessor processorMetaConfigAccessor;
- private static JsonSerializerOptions jsonSerializerOptions;
- static HomeController()
- {
- jsonSerializerOptions = new JsonSerializerOptions()
- {
- WriteIndented = true,
- PropertyNameCaseInsensitive = true,
- };
- jsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
- }
- public HomeController(
- Func<IEnumerable<IProcessor>> processorFactory,
- UniversalApiHub universalApiHub, UniversalApiInvoker universalApiInvoker,
- IProcessorMetaConfigAccessor processorMetaConfigAccessor)
- {
- this.processorFactory = processorFactory;
- this.universalApiHub = universalApiHub;
- this.universalApiInvoker = universalApiInvoker;
- this.processorMetaConfigAccessor = processorMetaConfigAccessor;
- }
- [HttpGet]
- public IActionResult Index()
- {
- var clientAcceptFormatStr = Request.Headers[HeaderNames.Accept].FirstOrDefault();
- var processorCompoundInfos = this.processorFactory().Select(p =>
- {
- var pDesc = p.ProcessorDescriptor();
- return new Tuple<ProcessorDescriptor, MetaPartsDescriptor>(pDesc,
- pDesc.DeviceHandlerOrApp.GetType().GetCustomAttributes<MetaPartsDescriptor>().FirstOrDefault());
- });
- if (string.IsNullOrEmpty(clientAcceptFormatStr))
- return View("~/Views/Home/Index.cshtml", processorCompoundInfos);
- else if (clientAcceptFormatStr.Contains("text/html"))
- return View("~/Views/Home/Index.cshtml", processorCompoundInfos);
- else if (clientAcceptFormatStr.Contains("application/json"))
- return Ok(processorCompoundInfos);
- else if (clientAcceptFormatStr.Contains("application/xml"))
- return Ok(processorCompoundInfos);
- return View("~/Views/Home/Index.cshtml", processorCompoundInfos);
- }
- [HttpGet]
- public async Task<IActionResult> GetProcessorMetaConfigSchema(string simpleSourceEndpointTypeStr, string configSubSection, string format)
- {
- if (this.processorMetaConfigAccessor == null) return Content("");
- var metaConfigs = await this.processorMetaConfigAccessor.GetMetaConfigAsync(null);
- var configs = metaConfigs.Where(c => c.SourceEndpointFullTypeStr.Contains(simpleSourceEndpointTypeStr));
- if (!(configs?.Any() ?? false)) return Content("");
- //sample: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
- var clientAcceptLanguageStr = Request.Headers[HeaderNames.AcceptLanguage].FirstOrDefault()?.Split(',')[0] ?? "en-us";
- #region FdcServerHostApp
- if (simpleSourceEndpointTypeStr.Contains("FdcServerHostApp", StringComparison.OrdinalIgnoreCase))
- {
- if (configSubSection == "Pump")
- {
- var pumpJsElements = JsonDocument.Parse(configs.FirstOrDefault().Parts.FirstOrDefault().ParametersJsonArrayStr).RootElement.EnumerateArray().First().GetProperty("PumpConfigs").EnumerateArray().ToArray();
- var productElements = JsonDocument.Parse(configs.FirstOrDefault().Parts.FirstOrDefault().ParametersJsonArrayStr).RootElement.EnumerateArray().First().GetProperty("ProductConfigs").EnumerateArray().ToArray();
- var siteLevelNozzleIds = new List<int>();
- var siteLevelNozzleDisplayStrings = new List<string>();
- foreach (var pumpJsEle in pumpJsElements)
- {
- var pumpId = pumpJsEle.GetProperty("PumpId").GetInt32();
- var nzJsEles = pumpJsEle.GetProperty("NozzleConfigs").EnumerateArray().ToArray();
- foreach (var nzJsEle in nzJsEles)
- {
- int nozzleLogicalId;
- if (!nzJsEle.GetProperty("NozzleLogicalId").TryGetInt32(out nozzleLogicalId))
- nozzleLogicalId = -1;
- int siteLvlNozzleId;
- if (!nzJsEle.GetProperty("SiteLevelNozzleId").TryGetInt32(out siteLvlNozzleId))
- siteLvlNozzleId = -1;
- int tankNumber;
- if (!nzJsEle.GetProperty("TankNumber").TryGetInt32(out tankNumber))
- tankNumber = -1;
- var productCode = nzJsEle.GetProperty("ProductCode").GetInt32();
- var productName = productElements.Where(p => p.GetProperty("ProductCode").GetInt32() == productCode).FirstOrDefault().GetProperty("ProductName").GetString();
- siteLevelNozzleIds.Add(siteLvlNozzleId);
- if (string.IsNullOrEmpty(format))
- siteLevelNozzleDisplayStrings.Add(
- $"lang-en-us:SiteLevelNozzleId: {siteLvlNozzleId}, pumpId: {pumpId}, nozzleLogicalId: {nozzleLogicalId}, productName: {productName}(code: {productCode }), tankNo.:{ tankNumber}lang-zh-cn:站级枪号: {siteLvlNozzleId}, 加油点号: {pumpId}, 逻辑枪号: {nozzleLogicalId}, 油品名: {productName}(代码: {productCode }), 油罐号.: { tankNumber}"
- .LocalizedContent(clientAcceptLanguageStr));
- else if (format == "simple")
- {
- siteLevelNozzleDisplayStrings.Add(
- $"lang-en-us:SiteLevelNozzleId: {siteLvlNozzleId}, productName: {productName}(code: {productCode })lang-zh-cn:站级枪号: {siteLvlNozzleId}, 油品名: {productName}(代码: {productCode })"
- .LocalizedContent(clientAcceptLanguageStr));
- }
- }
- }
- var dynamicPumpSchema = "{" +
- "\"$schema\": \"http://json-schema.org/draft-04/schema\"," +
- "\"type\": \"integer\"," +
- "\"enum\": [ " +
- siteLevelNozzleIds.Select(i => i.ToString()).Aggregate((acc, n) => acc + "," + n) + " ]," +
- " \"options\": {" +
- " \"enum_titles\": [ " +
- siteLevelNozzleDisplayStrings.Select(s => "\"" + s + "\"").Aggregate((acc, n) => acc + "," + n) + " ]" +
- " }" +
- "}";
- return Content(dynamicPumpSchema);
- }
- }
- #endregion
- return Content("");
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="apiType">localmqtt, remotemqtt, webapi</param>
- /// <param name="tags">, split tag string</param>
- /// <param name="format"></param>
- /// <returns></returns>
- [HttpGet]
- public IActionResult ShowMeApi(string apiType, string tags, string format)
- {
- var communicationProvider =
- this.universalApiHub.CommunicationProviders?.Where(p => p.GetType().Name.Contains(apiType, StringComparison.OrdinalIgnoreCase))?.FirstOrDefault();
- var docs = communicationProvider?.GetApiDocuments()?.FilterByTags(tags?.Replace(" ", "")?.Split(",")) ?? Enumerable.Empty<UniversalApiInfoDoc>();
- if (format == "data")
- return Ok(docs);
- else if (format == "pretty")
- return View("~/Views/Home/MqttApiDocPretty.cshtml", docs);
- return Redirect("/swagger");
- }
- public async Task<IActionResult> ProcessorMetaDescriptor(int startIndex = 0, int count = 10, string q = "")
- {
- var clientAcceptFormatStr = Request.Headers[HeaderNames.Accept].FirstOrDefault();
- //sample: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
- var clientAcceptLanguageStr = Request.Headers[HeaderNames.AcceptLanguage].FirstOrDefault()?.Split(',')[0] ?? "en-us";
- IEnumerable<ProcessorMetaDescriptor> pMetaDescriptors = null;
- if (!string.IsNullOrEmpty(q))
- {
- pMetaDescriptors = ObjectInstanceCreator.CurrentDomainProcessorEndPointTypes.ExtractProcessorMetaDescriptor()
- .Where(d => d.SourceEndpointFullTypeStr.Contains(q.Trim(), StringComparison.OrdinalIgnoreCase));
- }
- else
- {
- pMetaDescriptors = ObjectInstanceCreator.CurrentDomainProcessorEndPointTypes.ExtractProcessorMetaDescriptor().Skip(startIndex).Take(count);
- }
- ReplaceWithLocalizedContent(pMetaDescriptors, clientAcceptLanguageStr);
- if (string.IsNullOrEmpty(clientAcceptFormatStr))
- return View(pMetaDescriptors);
- else if (clientAcceptFormatStr.Contains("text/html"))
- return View(pMetaDescriptors);
- else if (clientAcceptFormatStr.Contains("application/json"))
- return Ok(pMetaDescriptors);
- else if (clientAcceptFormatStr.Contains("application/xml"))
- return Ok(pMetaDescriptors);
- return View(pMetaDescriptors);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="source"></param>
- /// <param name="clientAcceptLanguageStr">sample: en-US or zh-CN</param>
- static void ReplaceWithLocalizedContent(IEnumerable<ProcessorMetaDescriptor> source, string clientAcceptLanguageStr)
- {
- foreach (var pDescriptor in source)
- {
- pDescriptor.Description = pDescriptor?.Description?.LocalizedContent(clientAcceptLanguageStr);
- if (pDescriptor.Tags != null)
- {
- var localizedTags = new List<string>();
- foreach (var t in pDescriptor.Tags)
- {
- var compoundTag = new
- {
- TagKey = t.LocalizedContent("en"),
- LocalizedTagName = t.LocalizedContent(clientAcceptLanguageStr)
- };
- localizedTags.Add(System.Text.Json.JsonSerializer.Serialize(compoundTag));
- }
- pDescriptor.Tags = localizedTags.ToArray();
- }
- if (string.IsNullOrEmpty(pDescriptor.DisplayName))
- {
- //SourceEndpointFullTypeStr sample: Edge.Core.Processor.Dispatcher.DefaultDispatcher, Edge.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
- pDescriptor.DisplayName = pDescriptor.SourceEndpointFullTypeStr.Substring(0, pDescriptor.SourceEndpointFullTypeStr.IndexOf(", Version="));
- }
- else
- pDescriptor.DisplayName = pDescriptor.DisplayName.LocalizedContent(clientAcceptLanguageStr);
- foreach (var mpGroup in pDescriptor.MetaPartsGroupDescriptors)
- {
- foreach (var mpDescriptor in mpGroup.MetaPartsDescriptors)
- {
- mpDescriptor.Description = mpDescriptor?.Description?.LocalizedContent(clientAcceptLanguageStr);
- if (string.IsNullOrEmpty(mpDescriptor.DisplayName))
- {
- mpDescriptor.DisplayName = mpDescriptor.TypeString;
- }
- else
- mpDescriptor.DisplayName = mpDescriptor.DisplayName.LocalizedContent(clientAcceptLanguageStr);
- foreach (var pJsons in mpDescriptor.ParametersJsonSchemaStrings)
- {
- for (int i = 0; i < pJsons.Count; i++)
- {
- pJsons[i] = pJsons[i].LocalizedJsonSchema(clientAcceptLanguageStr);
- }
- }
- }
- }
- }
- }
- [HttpGet]
- [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
- public IActionResult Error()
- {
- return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
- }
- //public async Task<IActionResult> Processors()
- //{
- // return View(this.processors);
- //}
- /// <summary>
- /// all calls to every single processor will be routed here
- /// </summary>
- /// <param name="apiType">service, or property</param>
- /// <param name="targetApiName">service, or property name</param>
- /// <param name="targetProcessorName"></param>
- /// <param name="endpointName"></param>
- /// <param name="inputParameter"></param>
- /// <returns></returns>
- //[ApiExplorerSettings(IgnoreApi = true)]
- [HttpPost]
- [Route(UniversalWebApiHandlerRoute)]
- public async Task<IActionResult> UniversalWebApiHandler(
- [FromQuery(Name = "apitype")] string apiType,
- [FromQuery(Name = "an")] string targetApiName,
- [FromQuery(Name = "pn")] string targetProcessorName,
- [FromQuery(Name = "en")] string endpointName,
- [FromBody] JsonElement inputParameter)
- {
- try
- {
- /* empty post body will treat inputParameters==null, no content json array '[]' will treat inputParameters.Length==0*/
- JsonElement[] inputParameters = null;
- if (inputParameter.ValueKind == JsonValueKind.Array)
- inputParameters = inputParameter.EnumerateArray().ToArray();
- else if (inputParameter.ValueKind == JsonValueKind.Object)
- inputParameters = new JsonElement[] { inputParameter };
- else if (inputParameter.ValueKind == JsonValueKind.Undefined)
- { }
- else
- inputParameters = new JsonElement[] { inputParameter };
- var p = this.processorFactory().FirstOrDefault(p => p.MetaConfigName == targetProcessorName);
- if (p == null) return BadRequest("Could not find processor with name: " + targetProcessorName);
- if (string.IsNullOrEmpty(apiType) || string.IsNullOrEmpty(targetApiName))
- return BadRequest("Must provide apiType and targetApiName in query");
- var requestContext = new RequestContext(Request);
- if (apiType.ToLower() == "service")
- {
- var apiCallResult = await this.universalApiInvoker.InvokeUniversalApiServiceAsync(p, targetApiName, inputParameters, requestContext);
- return Json(apiCallResult, jsonSerializerOptions);
- }
- else if (apiType.ToLower() == "property")
- {
- object apiCallResult;
- if (inputParameters == null)
- {
- /*call 'get'*/
- apiCallResult = this.universalApiInvoker.InvokeUniversalApiPropertyGet(p, targetApiName, requestContext);
- }
- else
- {
- /*call 'set'*/
- JsonElement? setValue = null;
- if (inputParameters.Length == 0)
- {
- }
- else if (inputParameters.Length >= 2)
- {
- return BadRequest("Unexpected too many parameters passed in. when calling for set value for a Property, Either post a single JsonObject, or a JsonArray with single element of JsonObject");
- }
- else
- setValue = inputParameters[0];
- apiCallResult = this.universalApiInvoker.InvokeUniversalApiPropertySet(p, targetApiName, setValue, requestContext);
- }
- return Json(apiCallResult, jsonSerializerOptions);
- }
- return BadRequest();
- }
- catch (Exception exx)
- {
- return StatusCode(500, exx.ToString());
- }
- }
- public IActionResult Configure()
- {
- //return all descriptor
- IEnumerable<ProcessorMetaDescriptor> descriptors = null;
- descriptors = ObjectInstanceCreator.CurrentDomainProcessorEndPointTypes.ExtractProcessorMetaDescriptor().Skip(0);
- //sample: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7
- var clientAcceptLanguageStr = Request.Headers[HeaderNames.AcceptLanguage].FirstOrDefault()?.Split(',')[0] ?? "en-us";
- ReplaceWithLocalizedContent(descriptors, clientAcceptLanguageStr);
- return View(descriptors);
- }
- ///// <summary>
- /////
- ///// </summary>
- ///// <param name="appOrHandlerFullName">like Applications.FDC.FdcServerHostApp, or Wayne_Pump_Dart.PumpGroupHandler</param>
- ///// <param name="input"></param>
- ///// <returns></returns>
- //[HttpPost]
- //public async Task<IActionResult> UniversalWebConsoleHandler(
- // [FromQuery(Name = "epn")] string appOrHandlerFullName,
- // [FromBody]ApiData input)
- //{
- // return View("~/Home/WebConsoles/VeederRoot_ATG_Console_Handler");
- //}
- }
- }
|