服务端的TigerApi 框架,基于.NET6 2024 版本
Rodney Chen
2024-04-12 646ce5990fb03908a0371fc4ca8416905b27a4d1
移除Rhea中MQTT的前准备
已修改11个文件
已重命名3个文件
已添加2个文件
422 ■■■■ 文件已修改
Tiger.Api.sln 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Api/Controllers/Test/TestController.R.cs 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Api/Startup.cs 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Api/Tiger.Api.csproj 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Api/TigerApi6Text64.ico 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Api/注册Windows服务.txt 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Business/Services/Base/InterfaceService.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Business/Services/Base/InterfaceServiceNew.cs 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Business/Tiger.Business.csproj 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.IBusiness/Core/ApiConfig.cs 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.IBusiness/Core/Logger.cs 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.IBusiness/Core/MQTTHelper.cs 270 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.IBusiness/Core/UpgradeFileSystem.cs 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.IBusiness/Tiger.IBusiness.csproj 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Model.Net/Tiger.Model.Net.csproj 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Model.Net/packages.config 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
Tiger.Api.sln
@@ -22,7 +22,7 @@
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tiger.Business", "Tiger.Business\Tiger.Business.csproj", "{60FA322B-9B03-4380-803C-63B1F240E453}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05-框架方法", "05-框架方法", "{CF29B377-FE5A-488A-AF99-DF9D9C6FCA95}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "05-单元测试", "05-单元测试", "{CF29B377-FE5A-488A-AF99-DF9D9C6FCA95}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
Tiger.Api/Controllers/Test/TestController.R.cs
@@ -231,46 +231,6 @@
            return Ok($"设置{param}成功");
        }
        /// <summary>
        /// SendMQTTAsync
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> SendMQTTAsync([FromBody] ApiAction action)
        {
            string msg = "";
            await Task.Run(() =>
            {
                msg = action.ID;
                MQTTHelper.Send("TestSendMQTT001", new MQTTMessage()
                {
                    Type = "TestSendMQTT001",
                    Content = "TestSendMQTT001,测试消息!",
                    Data = "",
                    DataType = typeof(String).Name,
                    IsSuccessed = true,
                });
            });
            return Ok(MQTTHelper.Send(action.GetResponse(msg)));
        }
        /// <summary>
        /// DeleteMQTTTopicAsync
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> DeleteMQTTTopicAsync([FromBody] ApiAction action)
        {
            string msg = "";
            await Task.Run(() =>
            {
                msg = MQTTHelper.DeleteTopic(action.ID) ? "删除Topic成功" : "删除Topic失败";
            });
            return Ok(action.GetResponse(msg));
        }
        [HttpPost]
        public async Task<IActionResult> TestTask([FromBody] ApiAction action)
        {
@@ -320,7 +280,6 @@
    [Route("api/[controller]/[action]")]
    public partial class _TestController : ControllerBase
    {
        [HttpGet]
        public async Task<IActionResult> DoSomething(int duration)
        {
@@ -335,5 +294,53 @@
            Logger.Default.Info($"{begin:mmssfff} completed");
            return Ok($"{begin:mmssfff} completed");
        }
        [HttpGet]
        public async Task<IActionResult> DoSomething1(int duration)
        {
            var begin = DateTime.Now;
            return Ok($"{begin:mmssfff} completed");
        }
        /// <summary>
        /// SendMQTTAsync
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> SendMQTTAsync([FromBody] ApiAction action)
        {
            string msg = "";
            await Task.Run(() =>
            {
                msg = action.ID;
                MQTTHelper.Send("TestSendMQTT001", new MQTTMessage()
                {
                    Type = "TestSendMQTT001",
                    Content = "TestSendMQTT001,测试消息!",
                    Data = "",
                    DataType = typeof(String).Name,
                    IsSuccessed = true,
                });
            });
            return Ok(MQTTHelper.Send(action.GetResponse(msg)));
        }
        /// <summary>
        /// DeleteMQTTTopicAsync
        /// </summary>
        /// <param name="action"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> DeleteMQTTTopicAsync([FromBody] ApiAction action)
        {
            string msg = "";
            await Task.Run(() =>
            {
                msg = MQTTHelper.DeleteTopic(action.ID) ? "删除Topic成功" : "删除Topic失败";
            });
            return Ok(action.GetResponse(msg));
        }
    }
}
Tiger.Api/Startup.cs
@@ -73,7 +73,7 @@
            });
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc(version, new OpenApiInfo { Title = "Share API", Version = version });
                c.SwaggerDoc(version, new OpenApiInfo { Title = "Tiger API", Version = version });
                var basePath = AppDomain.CurrentDomain.BaseDirectory;
                var xmlPath = Path.Combine(basePath, "Tiger.Api.xml");
                c.IncludeXmlComments(xmlPath);
@@ -108,7 +108,7 @@
            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"Share API {version}");
                c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"Tiger API {version}");
            });
            app.UseRouting();
Tiger.Api/Tiger.Api.csproj
@@ -10,7 +10,7 @@
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ApplicationIcon>ShareApi6.ico</ApplicationIcon>
    <ApplicationIcon>TigerApi6Text64.ico</ApplicationIcon>
    <OutputType>Exe</OutputType>
    <AssemblyName>TigerApiHost</AssemblyName>
    <UserSecretsId>63e1c730-ccbc-4208-a72d-3e6460877d4d</UserSecretsId>
@@ -58,12 +58,12 @@
  <ItemGroup>
    <Content Include="ShareApi6.ico" />
    <Content Include="TigerApi6Text64.ico" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Autofac" Version="7.1.0" />
    <PackageReference Include="Autofac" Version="8.0.0" />
    <PackageReference Include="Autofac.Configuration" Version="6.0.0" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="6.0.14" />
    <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
Tiger.Api/TigerApi6Text64.ico
Tiger.Api/×¢²áWindows·þÎñ.txt
@@ -1,15 +1,15 @@
添加Windows服务
sc create ShareApi_IF binPath= "D:\WMS\Api\Api_IF\TigerApiHost.exe" start= auto displayname= "Share Api Host - Interface"
sc create ShareApi_BS binPath= "D:\WMS\Api\Api_BS\TigerApiHost.exe" start= auto displayname= "Share Api Host - BS"
sc create ShareApi_CS binPath= "D:\WMS\Api\Api_CS\TigerApiHost.exe" start= auto displayname= "Share Api Host - CS"
sc create ShareApi_PDA binPath= "D:\WMS\Api\Api_PDA\TigerApiHost.exe" start= auto displayname= "Share Api Host - PDA"
sc create ShareApi_Test binPath= "D:\WMS\Api\Api_Test\TigerApiHost.exe" start= auto displayname= "Share Api Host - Test"
sc create ShareApi_KB binPath= "D:\WMS\Api\Api_KB\TigerApiHost.exe" start= auto displayname= "Share Api Host - Kanban"
sc create TigerApi_IF binPath= "D:\WMS\Api\Api_IF\TigerApiHost.exe" start= auto displayname= "Tiger Api Host - Interface"
sc create TigerApi_BS binPath= "D:\WMS\Api\Api_BS\TigerApiHost.exe" start= auto displayname= "Tiger Api Host - BS"
sc create TigerApi_CS binPath= "D:\WMS\Api\Api_CS\TigerApiHost.exe" start= auto displayname= "Tiger Api Host - CS"
sc create TigerApi_PDA binPath= "D:\WMS\Api\Api_PDA\TigerApiHost.exe" start= auto displayname= "Tiger Api Host - PDA"
sc create TigerApi_Test binPath= "D:\WMS\Api\Api_Test\TigerApiHost.exe" start= auto displayname= "Tiger Api Host - Test"
sc create TigerApi_KB binPath= "D:\WMS\Api\Api_KB\TigerApiHost.exe" start= auto displayname= "Tiger Api Host - Kanban"
sc create TigerApi binPath= "D:\Projects\TigerClouds\TigerApi\Api\Tiger.Api\bin\Debug\net5.0\TigerApiHost.exe" start= auto displayname= "Tiger Api Host"
启动Windows服务
net start ShareApi
net start TigerApi
停止Windows服务
net stop ShareApi
net stop TigerApi
删除Windows服务
sc delete ShareApi_DashBoard
sc delete TigerApi_DashBoard
sc delete TigerApi
Tiger.Business/Services/Base/InterfaceService.cs
@@ -114,7 +114,8 @@
        public void StartJob(string jobname)
        {
            // å¸¦è¿”回值
            var scheduleResult = _schedulerFactory.TryRunJob(jobname);
            IScheduler scheduler;
            var scheduleResult = _schedulerFactory.TryRunJob(jobname, out scheduler);
        }
        /// <summary>
Tiger.Business/Services/Base/InterfaceServiceNew.cs
@@ -143,7 +143,8 @@
        public void StartJob(string jobname)
        {
            // å¸¦è¿”回值
            var scheduleResult = _schedulerFactory.TryRunJob(jobname);
            IScheduler scheduler;
            var scheduleResult = _schedulerFactory.TryRunJob(jobname, out scheduler);
        }
        /// <summary>
Tiger.Business/Tiger.Business.csproj
@@ -101,11 +101,11 @@
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="MailKit" Version="4.3.0" />
    <PackageReference Include="MailKit" Version="4.4.0" />
    <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.2.5" />
    <PackageReference Include="NLog" Version="5.2.6" />
    <PackageReference Include="NLog.Database" Version="5.2.6" />
    <PackageReference Include="NLog" Version="5.2.8" />
    <PackageReference Include="NLog.Database" Version="5.2.8" />
    <PackageReference Include="Rhea.Common" Version="6.1.5.1351" />
  </ItemGroup>
Tiger.IBusiness/Core/ApiConfig.cs
Tiger.IBusiness/Core/Logger.cs
Tiger.IBusiness/Core/MQTTHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,270 @@
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Protocol;
using MQTTnet.Server;
using Newtonsoft.Json;
using Rhea.Common;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
namespace Tiger.IBusiness.Utility
{
    /// <summary>
    /// EMQX å¸®åŠ©ç±»
    /// </summary>
    public class EMQX : IDisposable
    {
        public EMQX(string address, string username, string password)
        {
            Address = address;
            Username = username;
            Password = password;
        }
        public EMQX(string address, int port, string username, string password)
        {
            Address = address;
            Port = port;
            Username = username;
            Password = password;
        }
        public string Address { get; set; }
        public int Port { get; set; } = 1883;
        public string ClientId { get; set; } = $"{Environment.MachineName}-Client-{Guid.NewGuid():N}";
        public string Username { get; set; }
        public string Password { get; set; }
        public int ApiPort { get; set; } = 18083;
        public string ApiKey { get; set; }
        public string ApiSecretKey { get; set; }
        public string ApiCredentials => Convert.ToBase64String(Encoding.ASCII.GetBytes($"{ApiKey}:{ApiSecretKey}"));
        /// <summary>
        /// MQTT客户端
        /// </summary>
        public IMqttClient Client = new MqttFactory().CreateMqttClient();
        private List<string> TopicList = new();
        public Result<IMqttClient> Connect(string clientId = null)
        {
            Result<IMqttClient> result = new();
            if (!Address.IsNullOrEmpty())
            {
                ClientId = clientId.IsNullOrEmpty(ClientId);
                var options = new MqttClientOptionsBuilder()
                    .WithTcpServer(Address, Port) // MQTT broker address and port
                    .WithCredentials(Username, Password) // Set username and password
                    .WithClientId(ClientId)
                    .WithCleanSession()
                    .Build();
                var connectResult = Client.ConnectAsync(options).Result;
                if (connectResult.ResultCode == MqttClientConnectResultCode.Success)
                {
                    result.Flag = Result.Flags.Success;
                    result.Data = Client;
                    result.Message = "Connect to MQTT server success.";
                }
                else
                {
                    result.Flag = Result.Flags.Failed;
                    result.Data = null;
                    result.Message = $"Failed to connect to MQTT server: {connectResult.ResultCode}";
                }
            }
            else
            {
                result.Flag = Result.Flags.Failed;
                result.Data = null;
                result.Message = $"Failed to connect to MQTT server: no server address.";
            }
            return result;
        }
        public void Disconnect()
        {
            foreach (var topic in TopicList)
            {
                Client.UnsubscribeAsync(topic).Wait();
            }
            Client.DisconnectAsync().Wait();
        }
        public void Dispose()
        {
            Disconnect();
        }
        public bool Subscribe(string topic, Action<MqttApplicationMessageReceivedEventArgs> onReceive, MqttQualityOfServiceLevel QoS = MqttQualityOfServiceLevel.AtMostOnce)
        {
            if (TopicList.Contains(topic))
            {
                return true;
            }
            else
            {
                try
                {
                    if (!Client.IsConnected)
                    {
                        Client.ReconnectAsync().Wait();
                    }
                    // Subscribe to a topic
                    Client.SubscribeAsync(topic, QoS).Wait();
                    TopicList.Add(topic);
                    // Callback function when a message is received
                    Client.ApplicationMessageReceivedAsync += e =>
                    {
                        onReceive.Invoke(e);
                        return Task.CompletedTask;
                    };
                    return true;
                }
                catch (System.Exception ex)
                {
                    return false;
                }
            }
        }
        public void Unsubscribe(string topic)
        {
            // Unsubscribe
            Client.UnsubscribeAsync(topic).Wait();
            TopicList.Remove(topic);
        }
        /// <summary>
        /// å‘送一个MQ消息
        /// </summary>
        /// <param name="msg">消息</param>
        /// <param name="topic">消息的Topic,移动端根据这个Topic来接收消息<param>
        public async Task<bool> SendAsync(string topic, string msg, MqttQualityOfServiceLevel QoS)
        {
            bool isFinish = false;
            int doTimes = 0;
            do
            {
                doTimes++;
                try
                {
                    if (!Client.IsConnected)
                    {
                        await Client.ReconnectAsync();
                    }
                    // Publish a message
                    await Client.PublishAsync(new MqttApplicationMessageBuilder()
                        .WithTopic(topic)
                        .WithPayload(msg)
                        .WithQualityOfServiceLevel(QoS)
                        .WithRetainFlag()
                        .Build());
                    isFinish = true;
                }
                catch (System.Exception ex)
                {
                    //Logger.Console.Fatal(ex, $"Send MQTT Message[{sessionId}] Exception(Text: {msg})");
                }
            } while (!isFinish && doTimes < 3);
            return isFinish;
        }
        /// <summary>
        /// å‘送一个内容是ApiAction的MQ消息,以ApiAction的ID作为消息的Topic
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="action"></param>
        /// <returns></returns>
        public ApiAction<T> Send<T>(ApiAction<T> action, MqttQualityOfServiceLevel QoS = MqttQualityOfServiceLevel.AtLeastOnce)
        {
            MQTTMessage message = new MQTTMessage();
            message.IsVoice = !action.IsSuccessed;
            message.IsSuccessed = action.IsSuccessed;
            message.Content = action.Message;
            message.Color = action.IsSuccessed ? "#878787" : "#880000";
            SendAsync(JsonConvert.SerializeObject(message), action.ID, QoS).Wait();
            return action;
        }
        public bool Send<T>(string topic, Result<T> result, string msgTitle, MqttQualityOfServiceLevel QoS = MqttQualityOfServiceLevel.AtLeastOnce)
        {
            try
            {
                MQTTMessage message = new MQTTMessage();
                message.IsVoice = !result.IsSuccessed;
                message.IsSuccessed = result.IsSuccessed;
                message.Content = msgTitle + ":" + result.Message;
                message.Color = result.IsSuccessed ? "#878787" : "#880000";
                return SendAsync(topic, JsonConvert.SerializeObject(message), QoS).Result;
            }
            catch (System.Exception ex)
            {
                return false;
            }
        }
        public bool Send(string topic, MQTTMessage msg, MqttQualityOfServiceLevel QoS = MqttQualityOfServiceLevel.AtLeastOnce)
        {
            try
            {
                return SendAsync(topic, JsonConvert.SerializeObject(msg), QoS).Result;
            }
            catch (System.Exception ex)
            {
                return false;
            }
        }
        public HttpResponseMessage GetTopicList(string topic = "")
        {
            //var content = new StringContent(json);
            //content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            //var client = new HttpClient();
            //var response = client.PostAsync(url, content).Result;
            ApiKey = "ee26b0dd4af7e749";
            ApiSecretKey = "XHOUC9BQSoa0j0jRINQEkQanIR1nzDQUY8GnYtaktEQJ";
            string credentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{ApiKey}:{ApiSecretKey}"));
            var client = new HttpClient();
            client.DefaultRequestHeaders.Add("Content-Type", "application/json");
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", ApiCredentials);// æ·»åŠ åŸºæœ¬è®¤è¯å¤´
            string url = $"http://{Address}:{ApiPort}/api/v5/topics/";
            var response = client.GetAsync(url).Result;
            return response;
        }
        public bool DeleteTopic(string sessionId)
        {
            int doTimes = 0;
            bool isFinish = false;
            do
            {
                doTimes++;
                try
                {
                    isFinish = true;
                }
                catch (Exception ex)
                {
                    //Logger.Console.Fatal(ex, $"Delete MQTT Topic[{sessionId}] Exception");
                }
            } while (!isFinish && doTimes < 3);
            return isFinish;
        }
    }
}
Tiger.IBusiness/Core/UpgradeFileSystem.cs
Tiger.IBusiness/Tiger.IBusiness.csproj
@@ -11,15 +11,16 @@
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Autofac" Version="7.1.0" />
    <PackageReference Include="Autofac" Version="8.0.0" />
    <PackageReference Include="Autofac.Configuration" Version="6.0.0" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
    <PackageReference Include="MailKit" Version="4.3.0" />
    <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
    <PackageReference Include="MailKit" Version="4.4.0" />
    <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
    <PackageReference Include="NLog" Version="5.2.6" />
    <PackageReference Include="NLog.Database" Version="5.2.6" />
    <PackageReference Include="MQTTnet" Version="4.3.3.952" />
    <PackageReference Include="NLog" Version="5.2.8" />
    <PackageReference Include="NLog.Database" Version="5.2.8" />
    <PackageReference Include="Rhea.Common" Version="6.1.5.1351" />
    <PackageReference Include="Sundial" Version="2.28.0" />
    <PackageReference Include="Sundial" Version="2.45.0" />
  </ItemGroup>
  <ItemGroup>
Tiger.Model.Net/Tiger.Model.Net.csproj
@@ -54,8 +54,8 @@
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="SqlSugar, Version=5.1.4.94, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\SqlSugar.5.1.4.95\lib\SqlSugar.dll</HintPath>
    <Reference Include="SqlSugar, Version=5.1.4.152, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\SqlSugar.5.1.4.152\lib\SqlSugar.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.ComponentModel.DataAnnotations" />
Tiger.Model.Net/packages.config
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net452" />
  <package id="SqlSugar" version="5.1.4.95" targetFramework="net48" />
  <package id="SqlSugar" version="5.1.4.152" targetFramework="net48" />
</packages>