| | |
| | | using System.Collections.Generic; |
| | | using System; |
| | | using MQTTnet.Client; |
| | | using System.Text; |
| | | using System.Security.Cryptography; |
| | | using MQTTnet; |
| | | using MQTTnet.Client.Options; |
| | | using System.Net.Sockets; |
| | | using System.Threading.Tasks; |
| | | //using System.Net; |
| | | //using Newtonsoft.Json.Linq; |
| | | //using HDL_ON.DAL; |
| | | //using Newtonsoft.Json; |
| | | |
| | | namespace HDL_ON.DAL.Net |
| | | { |
| | | public static class MqttCommon |
| | | |
| | | public class RemoteRequestParameters |
| | | { |
| | | public string RequestVersion; |
| | | public int RequestSource; |
| | | public string LoginAccessToken; |
| | | public int RequestProtocolType; |
| | | |
| | | public int HdlGatewayGatewayType = 0; |
| | | public bool IsRedirectSelectEmqServer = false; |
| | | /// <summary> |
| | | /// MqttClient |
| | | /// 平台类型字符串 |
| | | /// </summary> |
| | | public static IMqttClient mqttClient_A; |
| | | public static string mqttClientIP; |
| | | public static string mqttGatewayMAC; |
| | | static bool remoteIsConnected; |
| | | |
| | | static bool onConnection = false; |
| | | |
| | | static MqttCommon() |
| | | { |
| | | InitMqtt(); |
| | | } |
| | | |
| | | /// <summary>
|
| | | /// 断开远程Mqtt的链接
|
| | | /// </summary> |
| | | public static async Task DisConnectRemoteMqttClient(string s = "")
|
| | | {
|
| | | try |
| | | {
|
| | | if (remoteIsConnected) |
| | | {
|
| | | remoteIsConnected = false;
|
| | | System.Console.WriteLine($"Remote主动断开_{s}");
|
| | | //await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
|
| | | await mqttClient_A.DisconnectAsync(); |
| | | }
|
| | | } |
| | | catch (Exception e) |
| | | { |
| | | Console.WriteLine($"Remote断开通讯连接出异常:{e.Message}");
|
| | | }
|
| | | } |
| | | |
| | | static bool isSubscribeSuccess; |
| | | static async Task SubscribeTopics() |
| | | { |
| | | if (remoteIsConnected && !isSubscribeSuccess) |
| | | { |
| | | try |
| | | { |
| | | var Topic1 = $"/BusGateWayToApp/{mqttGatewayMAC}/Common/Json"; |
| | | try |
| | | { |
| | | await mqttClient_A.SubscribeAsync(Topic1); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | await DisConnectRemoteMqttClient(ex.Message); |
| | | await StartMqtt(); |
| | | if (remoteIsConnected) |
| | | { |
| | | await mqttClient_A.SubscribeAsync(Topic1); |
| | | } |
| | | } |
| | | } |
| | | catch { } |
| | | } |
| | | } |
| | | |
| | | static void InitMqtt() |
| | | { |
| | | new System.Threading.Thread(async () => { |
| | | while (true) |
| | | { |
| | | try |
| | | { |
| | | System.Threading.Thread.Sleep(1000); |
| | | //if (!CommonPage.IsRemote) |
| | | // continue; |
| | | if (remoteIsConnected) |
| | | continue; |
| | | await StartMqtt(); |
| | | await SubscribeTopics(); |
| | | } |
| | | catch { } |
| | | } |
| | | }) |
| | | { IsBackground = true }.Start(); |
| | | } |
| | | |
| | | public string PlatformStr; |
| | | /// <summary> |
| | | /// 启动A协议Mqtt |
| | | /// 发布主题负载 |
| | | /// </summary> |
| | | public static async Task StartMqtt() |
| | | { |
| | | try |
| | | { |
| | | if (remoteIsConnected) |
| | | return; |
| | | if (onConnection) |
| | | return; |
| | | onConnection = true; |
| | | new System.Threading.Thread(async () => |
| | | { |
| | | if (remoteIsConnected) |
| | | return; |
| | | try |
| | | { |
| | | if (mqttClient_A == null) |
| | | { |
| | | mqttClient_A = new MqttFactory().CreateMqttClient(); |
| | | mqttClient_A.UseApplicationMessageReceivedHandler(async e => |
| | | { |
| | | var aesDecryptTopic = e.ApplicationMessage.Topic; |
| | | var aesDecryptPayload = e.ApplicationMessage.Payload; |
| | | MainPage.Log(aesDecryptTopic); |
| | | MainPage.Log($"Des Topic={aesDecryptTopic}"); |
| | | }); |
| | | public string PublishPayloadJsonStr; |
| | | |
| | | mqttClient_A.UseConnectedHandler(async (e) => { |
| | | MainPage.Log("mqtt connected !!"); |
| | | onConnection = false; |
| | | }); |
| | | } |
| | | try |
| | | { |
| | | int readCount = 0; |
| | | BusSocket.Stop(); |
| | | System.Threading.Thread.Sleep(1000); |
| | | BusSocket.Start(6688); |
| | | System.Threading.Thread.Sleep(1000); |
| | | Control.ReadGatewayIPAddress(); |
| | | while(true) |
| | | { |
| | | if (!string.IsNullOrEmpty(mqttClientIP)) |
| | | { |
| | | break; |
| | | } |
| | | else if (readCount > 10) |
| | | { |
| | | onConnection = false; |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | Control.ReadGatewayIPAddress(); |
| | | System.Threading.Thread.Sleep(200); |
| | | } |
| | | } |
| | | BusSocket.Stop(); |
| | | System.Threading.Thread.Sleep(1000); |
| | | BusSocket.Start(6000); |
| | | System.Threading.Thread.Sleep(1000); |
| | | |
| | | var options = new MqttClientOptionsBuilder()//MQTT连接参数填充 |
| | | .WithClientId(Guid.NewGuid().ToString().Substring(0, 5))//客户端ID |
| | | .WithTcpServer(mqttClientIP, 1883)//MQTTServerIP.Text, Int32.Parse(MQTTServerPort.Text.ToString()))//TCP服务端 1883 ,即MQTT服务端 |
| | | .WithCredentials("", "")//"", "")//凭证 帐号 密码 |
| | | .WithCommunicationTimeout(new TimeSpan(0, 0, 60)) //重连超时时间,默认5s |
| | | .WithKeepAlivePeriod(new TimeSpan(0, 0, 15)) //保持连接时间,默认5s,心跳包 |
| | | .Build(); |
| | | await mqttClient_A.ConnectAsync(options); |
| | | remoteIsConnected = true; |
| | | } |
| | | catch { } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | } |
| | | finally |
| | | { |
| | | onConnection = false; |
| | | } |
| | | }) |
| | | { IsBackground = true }.Start(); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | MainPage.Log("============>" + ex.Message); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="message">附加数据包</param> |
| | | /// <param name="optionType">操作类型:0=网关控制;1=订阅网关数据;2=订阅网关上线数据</param> |
| | | /// <returns></returns> |
| | | public static async Task MqttRemoteSend(byte[] message) |
| | | { |
| | | try |
| | | { |
| | | if (mqttClient_A == null || !mqttClient_A.IsConnected) |
| | | { |
| | | await StartMqtt(); |
| | | } |
| | | if (!mqttClient_A.IsConnected) |
| | | { |
| | | return; |
| | | } |
| | | var topicName = $"/AppToBusGateWay/{mqttGatewayMAC}/Common/Json"; |
| | | var m = new MqttApplicationMessage { Topic = topicName, Payload = message, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce }; |
| | | await mqttClient_A?.PublishAsync(m); |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | } |
| | | } |
| | | public string Mac = ""; |
| | | public string GroupName = ""; |
| | | } |
| | | } |
| | | |
| | | public class RemoteRequestParameters |
| | | { |
| | | public string RequestVersion; |
| | | public int RequestSource; |
| | | public string LoginAccessToken; |
| | | public int RequestProtocolType; |
| | | |
| | | public string Mac = ""; |
| | | public string GroupName = ""; |
| | | } |
| | | |
| | | public class MqttRemoteInfo |
| | | { |
| | | public List<RemoteMACInfo> pageData; |
| | | |
| | | public int pageIndex = 0; |
| | | public int pageSize = 10; |
| | | public int totalCount = 3; |
| | | public int totalPages = 1; |
| | | public bool hasPreviousPage = false; |
| | | public bool hasNextPage = false; |
| | | } |
| | | |
| | | public class MqttInfo |
| | | { |
| | | public string connEmqDomainPort; |
| | | public string connEmqClientId; |
| | | public string connEmqUserName; |
| | | public string connEmqPwd; |
| | | } |
| | | |
| | | public class RemoteMACInfo |
| | | { |
| | | public string mac; |
| | | public string macMark; |
| | | public string isValid; |
| | | public string aesKey; |
| | | public bool isNewBusproGateway; |
| | | public string groupName; |
| | | public string projectName; |
| | | public string userName; |
| | | |
| | | //app自定义数据 |
| | | public string md5_mac_string; |
| | | public string LoginAccessToken; |
| | | } |
| | | |
| | | namespace Shared.Securitys |
| | | { |
| | | public partial class EncryptionService |
| | | public class MqttRemoteInfo |
| | | { |
| | | public List<RemoteMACInfo> pageData; |
| | | |
| | | #region 加密 |
| | | /// <summary> |
| | | /// 加密主题为Base64 |
| | | /// </summary> |
| | | /// <param name="pToEncrypt"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static string AesEncryptTopic(string pToEncrypt, string key) |
| | | { |
| | | if (string.IsNullOrEmpty(pToEncrypt)) return null; |
| | | if (string.IsNullOrEmpty(key)) return pToEncrypt; |
| | | //需要加密内容的明文流 |
| | | Byte[] toEncryptArray = Encoding.UTF8.GetBytes(pToEncrypt); |
| | | public int pageIndex = 0; |
| | | public int pageSize = 10; |
| | | public int totalCount = 3; |
| | | public int totalPages = 1; |
| | | public bool hasPreviousPage = false; |
| | | public bool hasNextPage = false; |
| | | } |
| | | |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | RijndaelManaged rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | public class MqttInfo |
| | | { |
| | | public string connEmqDomainPort; |
| | | public string connEmqClientId; |
| | | public string connEmqUserName; |
| | | public string connEmqPwd; |
| | | |
| | | //创建AES加密器对象 |
| | | ICryptoTransform cTransform = rm.CreateEncryptor(); |
| | | |
| | | //使用AES将明文流转成密文字节数组 |
| | | Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | |
| | | //将AES生成的密文字节数组转成Base64字符串 |
| | | return Convert.ToBase64String(resultArray, 0, resultArray.Length); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 加密负载为二进制流 |
| | | /// </summary> |
| | | /// <param name="toEncryptArray"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static byte[] AesEncryptPayload(byte[] toEncryptArray, string key) |
| | | { |
| | | if (string.IsNullOrEmpty(key)) return toEncryptArray; |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | var rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES加密器对象 |
| | | var cTransform = rm.CreateEncryptor(); |
| | | //使用AES将明文流转成密文字节数组 |
| | | return cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | } |
| | | #endregion |
| | | |
| | | |
| | | #region 解密 |
| | | /// <summary> |
| | | /// 解密主题数据 |
| | | /// </summary> |
| | | /// <param name="pToDecrypt"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static string AesDecryptTopic(string pToDecrypt, string key) |
| | | { |
| | | //AES密文Base64转成字符串 |
| | | Byte[] toEncryptArray = Convert.FromBase64String(pToDecrypt); |
| | | |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | RijndaelManaged rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES解密器对象 |
| | | ICryptoTransform cTransform = rm.CreateDecryptor(); |
| | | |
| | | //使用AES将密文流转成明文的字节数组 |
| | | Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | |
| | | //转成字符串 |
| | | return Encoding.UTF8.GetString(resultArray); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 采用Aes解密负载数据 |
| | | /// </summary> |
| | | /// <param name="toEncryptArray"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static byte[] AesDecryptPayload(byte[] toEncryptArray, string key) |
| | | { |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | var rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES解密器对象 |
| | | var cTransform = rm.CreateDecryptor(); |
| | | |
| | | //使用AES将密文流转成明文的字节数组 |
| | | return cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | } |
| | | #endregion |
| | | |
| | | public List<RemoteMACInfo> AccountAllGateways; |
| | | |
| | | } |
| | | } |
| | | |
| | | public class RemoteMACInfo |
| | | { |
| | | public string mac; |
| | | public string macMark; |
| | | public string isValid; |
| | | public string aesKey; |
| | | public bool isNewBusproGateway; |
| | | public string groupName; |
| | | public string projectName; |
| | | public string userName; |
| | | |
| | | public string clientId; |
| | | |
| | | //app自定义数据 |
| | | public string md5_mac_string; |
| | | public string LoginAccessToken; |
| | | } |
| | | |
| | | namespace Shared.Securitys |
| | | { |
| | | public partial class EncryptionService |
| | | { |
| | | |
| | | #region 加密 |
| | | /// <summary> |
| | | /// 加密主题为Base64 |
| | | /// </summary> |
| | | /// <param name="pToEncrypt"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static string AesEncryptTopic(string pToEncrypt, string key) |
| | | { |
| | | if (string.IsNullOrEmpty(pToEncrypt)) return null; |
| | | if (string.IsNullOrEmpty(key)) return pToEncrypt; |
| | | //需要加密内容的明文流 |
| | | Byte[] toEncryptArray = Encoding.UTF8.GetBytes(pToEncrypt); |
| | | |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | RijndaelManaged rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES加密器对象 |
| | | ICryptoTransform cTransform = rm.CreateEncryptor(); |
| | | |
| | | //使用AES将明文流转成密文字节数组 |
| | | Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | |
| | | //将AES生成的密文字节数组转成Base64字符串 |
| | | return Convert.ToBase64String(resultArray, 0, resultArray.Length); |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// 加密负载为二进制流 |
| | | /// </summary> |
| | | /// <param name="toEncryptArray"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static byte[] AesEncryptPayload(byte[] toEncryptArray, string key) |
| | | { |
| | | if (string.IsNullOrEmpty(key)) return toEncryptArray; |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | var rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES加密器对象 |
| | | var cTransform = rm.CreateEncryptor(); |
| | | //使用AES将明文流转成密文字节数组 |
| | | return cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | } |
| | | #endregion |
| | | |
| | | |
| | | #region 解密 |
| | | /// <summary> |
| | | /// 解密主题数据 |
| | | /// </summary> |
| | | /// <param name="pToDecrypt"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static string AesDecryptTopic(string pToDecrypt, string key) |
| | | { |
| | | //AES密文Base64转成字符串 |
| | | Byte[] toEncryptArray = Convert.FromBase64String(pToDecrypt); |
| | | |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | RijndaelManaged rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES解密器对象 |
| | | ICryptoTransform cTransform = rm.CreateDecryptor(); |
| | | |
| | | //使用AES将密文流转成明文的字节数组 |
| | | Byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | |
| | | //转成字符串 |
| | | return Encoding.UTF8.GetString(resultArray); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 采用Aes解密负载数据 |
| | | /// </summary> |
| | | /// <param name="toEncryptArray"></param> |
| | | /// <param name="key"></param> |
| | | /// <returns></returns> |
| | | public static byte[] AesDecryptPayload(byte[] toEncryptArray, string key) |
| | | { |
| | | //配置AES加密Key(密钥、向量、模式、填充) |
| | | var rm = new RijndaelManaged |
| | | { |
| | | Key = Encoding.UTF8.GetBytes(key), |
| | | IV = Encoding.UTF8.GetBytes(key), |
| | | Mode = CipherMode.CBC, |
| | | Padding = PaddingMode.PKCS7 |
| | | }; |
| | | |
| | | //创建AES解密器对象 |
| | | var cTransform = rm.CreateDecryptor(); |
| | | |
| | | //使用AES将密文流转成明文的字节数组 |
| | | return cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); |
| | | } |
| | | #endregion |
| | | |
| | | |
| | | } |
| | | } |
| | | } |