using System;
|
using MQTTnet.Client;
|
using System.Threading.Tasks;
|
using Shared;
|
using MQTTnet;
|
using System.Text;
|
using HDL_ON.Entity;
|
|
namespace HDL_ON.DAL.Net
|
{
|
public static class Mqtt_Cloud
|
{
|
static string mqttEncryptKey = "";
|
static string checkGatewayTopicBase64 = "";
|
static RemoteMACInfo CurRemoteMACInfo = null;
|
|
/// <summary>
|
/// 手机标识
|
/// </summary>
|
static Guid currentGuid = Guid.NewGuid();
|
|
/// <summary>
|
/// 外网的MQTT是否正在连接
|
/// </summary>
|
/// <summary>
|
/// 远程MqttClient
|
/// </summary>
|
/// <summary>
|
/// 远程MqttClient
|
/// </summary>
|
public static IMqttClient RemoteMqttClient = new MqttFactory().CreateMqttClient();
|
|
static bool thisShowTip = true;
|
//static string mqttRequestParToken="";
|
/// <summary>
|
/// 推送标识
|
/// </summary>
|
static string PushSignStr = System.DateTime.Now.Ticks.ToString();
|
|
/// <summary>
|
/// 断开远程Mqtt的链接
|
/// </summary>
|
public static async Task DisConnectRemoteMqttClient(string s = "")
|
{
|
try
|
{
|
if (remoteIsConnected)
|
{
|
remoteIsConnected = false;
|
MainPage.Log($"Remote主动断开_{s}");
|
//await RemoteMqttClient.DisconnectAsync(new MQTTnet.Client.Disconnecting.MqttClientDisconnectOptions { }, CancellationToken.None);
|
await RemoteMqttClient.DisconnectAsync();
|
}
|
}
|
catch (Exception e)
|
{
|
System.Console.WriteLine($"Remote断开通讯连接出异常:{e.Message}");
|
}
|
}
|
static DateTime dateTime = DateTime.MinValue;
|
/// <summary>
|
/// 外网的MQTT是否正在连接
|
/// </summary>
|
static bool remoteMqttIsConnecting;
|
static bool remoteIsConnected;
|
|
static Mqtt_Cloud()
|
{
|
InitMqtt();
|
}
|
|
public static bool IsInitMqtt = false;
|
|
static void InitMqtt()
|
{
|
new System.Threading.Thread(async () => {
|
while (true)
|
{
|
try
|
{
|
System.Threading.Thread.Sleep(1000);
|
if (!MainPage.IsRemote) continue;
|
|
await StartCloudMqtt();
|
await SubscribeTopics();
|
}
|
catch { }
|
}
|
})
|
{ IsBackground = true }.Start();
|
}
|
|
static bool isSubscribeSuccess;
|
static async Task SubscribeTopics()
|
{
|
if (remoteIsConnected && !isSubscribeSuccess)
|
{
|
try
|
{
|
var topicFilter1 = new TopicFilter { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange" };
|
var topicFilter2 = new TopicFilter { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce, Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/#" };
|
var topicFilter3 = new TopicFilter { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.ExactlyOnce, Topic = $"/BusGateWayToClient/{CurRemoteMACInfo.clientId}/Push/NotifySqueeze" };
|
var result = await RemoteMqttClient.SubscribeAsync(new TopicFilter[] { topicFilter1, topicFilter2, topicFilter3 });
|
if (result.Items[0].ResultCode == MQTTnet.Client.Subscribing.MqttClientSubscribeResultCode.GrantedQoS2)
|
{
|
isSubscribeSuccess = true;
|
}
|
}
|
catch { }
|
}
|
}
|
/// <summary>
|
/// 启动远程Mqtt
|
/// </summary>
|
public static async Task StartCloudMqtt()
|
{
|
//追加:没有远程连接的权限
|
if (remoteMqttIsConnecting
|
|| remoteIsConnected || !MainPage.LoginUser.IsLogin)
|
{
|
return;
|
}
|
|
await Task.Factory.StartNew(async () => {
|
//try {
|
lock (RemoteMqttClient)
|
{
|
//表示后面将进行连接
|
remoteMqttIsConnecting = true;
|
|
#region 初始化远程Mqtt
|
//(3)当[连接云端的Mqtt成功后]或者[以及后面App通过云端Mqtt转发数据给网关成功后],处理接收到云端数据包响应时在mqttServerClient_ApplicationMessageReceived这个方法处理
|
if (RemoteMqttClient.ApplicationMessageReceivedHandler == null)
|
{
|
RemoteMqttClient.UseApplicationMessageReceivedHandler((e) => {
|
try
|
{
|
var topic = e.ApplicationMessage.Topic;
|
//Console.WriteLine ("回复Topic={0}", topic);
|
if (topic == $"/BusGateWayToClient/{CurRemoteMACInfo.clientId}/Push/NotifySqueeze")
|
{
|
var mMes = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
//收到挤下线主题
|
ReceiveNotifySqueezeAsync(mMes);
|
}
|
else if (topic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/NotifyBusGateWayInfoChange")
|
{
|
//网关上线,需要更新aeskey
|
//收到网关上线消息主题
|
//ReceiveNotifyBusGateWayInfoChange();
|
}
|
else if (topic == $"/BusGateWayToClient/{CurRemoteMACInfo.macMark}/Common/CheckGateway")
|
{
|
var ss = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
ReceiveCheckGateway(ss);
|
}
|
else
|
{
|
var packet = new Packet();
|
|
if (!string.IsNullOrEmpty(mqttEncryptKey))
|
{
|
packet.Bytes = Shared.Securitys.EncryptionService.AesDecryptPayload(e.ApplicationMessage.Payload, mqttEncryptKey);
|
}
|
else
|
{
|
packet.Bytes = e.ApplicationMessage.Payload;
|
}
|
packet.Manager();
|
}
|
}
|
catch { }
|
});
|
}
|
|
if (RemoteMqttClient.DisconnectedHandler == null)
|
{
|
RemoteMqttClient.UseDisconnectedHandler(async (e) => {
|
System.Console.WriteLine($"远程连接断开");
|
isSubscribeSuccess = false;
|
await DisConnectRemoteMqttClient("StartRemoteMqtt.DisconnectedHandler");
|
if (MainPage.IsRemote)
|
{
|
Application.RunOnMainThread(() => {
|
//远程连接成功
|
});
|
}
|
});
|
}
|
if (RemoteMqttClient.ConnectedHandler == null)
|
{
|
RemoteMqttClient.UseConnectedHandler(async (e) => {
|
System.Console.WriteLine($"远程连接成功");
|
MainPage.IsRemote = true;
|
Application.RunOnMainThread(() => {
|
//远程连接成功
|
MainPage.IsRemote = true;
|
});
|
//刷新状态
|
if (CurRemoteMACInfo != null)
|
{
|
if (CurRemoteMACInfo.isValid == "InValid")
|
{
|
//远程失败
|
MainPage.IsRemote = false;
|
}
|
else
|
{
|
MqttRemoteSend(new byte[] { 0 }, 3);
|
}
|
}
|
});
|
}
|
#endregion
|
}
|
|
try
|
{
|
|
//--第一步:获取mqtt链接参数 提交MAC 服务器自动判断是否为新网关,返回是否需要自动切换远程连接的服务器
|
var mqttInfoRequestPar = new RemoteRequestParameters()
|
{
|
PlatformStr = "ON",
|
LoginAccessToken = MainPage.LoginUser.loginTokenString,
|
RequestVersion = MainPage.VersionString,
|
RequestProtocolType = 0,
|
RequestSource = 1,
|
HdlGatewayGatewayType = 0,
|
PublishPayloadJsonStr = PushSignStr,
|
Mac = HDL_ON.Entity.DB_ResidenceData.residenceData.residenceGatewayMAC,
|
};
|
var jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(mqttInfoRequestPar);
|
var mqttInfoRequestResult = new HDL_ON.DAL.Server.HttpServerRequest().RequestMqttInfo(jsonString);
|
|
if (mqttInfoRequestResult != null && mqttInfoRequestResult.ResponseData != null)
|
{
|
try
|
{
|
var mqttInfoRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttInfo>(mqttInfoRequestResult.ResponseData.ToString());
|
|
if (mqttInfoRequestResult_Obj != null)
|
{
|
string url = mqttInfoRequestResult_Obj.connEmqDomainPort;
|
string clientId = mqttInfoRequestResult_Obj.connEmqClientId;
|
string username = mqttInfoRequestResult_Obj.connEmqUserName;
|
string passwordRemote = mqttInfoRequestResult_Obj.connEmqPwd;
|
if (mqttInfoRequestResult_Obj.AccountAllGateways != null && mqttInfoRequestResult_Obj.AccountAllGateways.Count > 0)
|
{
|
//----第二步找出是否存在匹配当前住宅的mac,存在再进行远程。
|
foreach (var curRegionMac in DB_ResidenceData.residenceData.residecenInfo.homeGateways)
|
{
|
CurRemoteMACInfo = mqttInfoRequestResult_Obj.AccountAllGateways.Find((obj) => obj.mac == curRegionMac.GatewayUniqueId);
|
if (CurRemoteMACInfo != null)
|
{
|
break;
|
}
|
}
|
if (CurRemoteMACInfo != null)
|
{
|
CurRemoteMACInfo.LoginAccessToken = MainPage.LoginUser.loginTokenString;
|
CurRemoteMACInfo.clientId = clientId;
|
mqttEncryptKey = CurRemoteMACInfo.isNewBusproGateway ? CurRemoteMACInfo.aesKey : "";
|
|
var options1 = new MQTTnet.Client.Options.MqttClientOptionsBuilder()
|
.WithClientId(clientId)
|
.WithTcpServer(url.Split(':')[1].Substring("//".Length), int.Parse(url.Split(':')[2]))
|
.WithCredentials(username, passwordRemote)
|
.WithCleanSession()
|
.WithCommunicationTimeout(new TimeSpan(0, 0, 20))
|
.Build();
|
|
await DisConnectRemoteMqttClient("StartRemoteMqtt");
|
await RemoteMqttClient.ConnectAsync(options1);
|
remoteIsConnected = true;
|
IsDisConnectingWithSendCatch = false;
|
|
}
|
}
|
|
}
|
}
|
catch { }
|
}
|
|
}
|
catch (Exception e)
|
{
|
|
}
|
finally
|
{
|
//最终要释放连接状态
|
remoteMqttIsConnecting = false;
|
}
|
|
});
|
}
|
|
|
|
///// <summary>
|
///// 收到网关上线消息
|
///// </summary>
|
//static void ReceiveNotifyBusGateWayInfoChange()
|
//{
|
// var gatewayListUrl = @"https://developer.hdlcontrol.com/Center/Center/GetGatewayPagger"; //App、Buspro软件登录后获取网关列表 http 请求
|
// var gatewayListRequestPar = new RemoteRequestParameters() { Mac = CurRemoteMACInfo.mac, LoginAccessToken = MainPage.LoginUser.loginTokenString, RequestVersion = "RequestVersion1", RequestProtocolType = 0, RequestSource = 1 };
|
// var gatewayListRequestResult = MainPage.RequestHttps("", Newtonsoft.Json.JsonConvert.SerializeObject(gatewayListRequestPar), false, false, gatewayListUrl);
|
// var gatewayListRequestResult_Obj = Newtonsoft.Json.JsonConvert.DeserializeObject<MqttRemoteInfo>(gatewayListRequestResult.ResponseData.ToString());
|
// if (gatewayListRequestResult_Obj != null && gatewayListRequestResult_Obj.pageData.Count > 0)
|
// {
|
// CurRemoteMACInfo.aesKey = gatewayListRequestResult_Obj.pageData[0].aesKey;
|
// mqttEncryptKey = CurRemoteMACInfo.isNewBusproGateway ? CurRemoteMACInfo.aesKey : "";
|
// }
|
//}
|
|
/// <summary>
|
/// 收到挤下线推送
|
/// </summary>
|
static void ReceiveNotifySqueezeAsync(string mMes)
|
{
|
if (mMes == PushSignStr) return;//是自己的登录推送不处理
|
//断开远程连接
|
MainPage.IsRemote = false;
|
if (!MainPage.LoginUser.IsLogin)
|
{
|
return;
|
}
|
MainPage.LoginUser.lastTime = DateTime.MinValue;
|
MainPage.LoginUser.SaveUserInfo();
|
|
string oldRegionRootPath = FileUtils.CreateRegionBackup(DB_ResidenceData.residenceData.CurReginID.ToString());
|
new System.Threading.Thread(() =>
|
{
|
try
|
{
|
var backuplist = FileUtils.ReadFiles();
|
FileUtils.DeleteRegionFiles(oldRegionRootPath);
|
//移动文件
|
foreach (var fileName in backuplist)
|
{
|
System.IO.FileInfo fileInfo = new System.IO.FileInfo(FileUtils.RootPath + fileName);
|
if (fileName == "headImage.png")
|
{
|
continue;
|
}
|
if (fileInfo.Exists)
|
{
|
fileInfo.MoveTo(oldRegionRootPath + fileName);
|
MainPage.Log("move file : " + fileName);
|
}
|
}
|
//删除本地文件
|
foreach (var fileName in backuplist)
|
{
|
if (fileName == "headImage.png")
|
{
|
continue;
|
}
|
FileUtils.DeleteFile(fileName);
|
}
|
}
|
catch (Exception ex)
|
{
|
MainPage.Log(ex.Message);
|
}
|
finally
|
{
|
}
|
})
|
{ IsBackground = true }.Start();
|
|
|
//删除推送数据
|
DisConnectRemoteMqttClient("挤下线");
|
Application.RunOnMainThread(() =>
|
{
|
MainPage.GoLoginPage(MainPage.LoginUser);
|
});
|
}
|
|
/// <summary>
|
/// 收到CheckGateway主题
|
/// </summary>
|
static void ReceiveCheckGateway(string mMes)
|
{
|
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponsePack>(mMes);
|
if (obj == null)
|
{
|
return;
|
}
|
switch (obj.StateCode)
|
{
|
case "HDLUdpDataForwardServerMqttClientNoOnLine":
|
case "NoOnline":
|
case "NetworkAnomaly"://不在线
|
Application.RunOnMainThread(() =>
|
{
|
new HDL_ON.UI.PublicAssmebly().TipMsgAutoClose(Language.StringByID(StringId.RemoteFailedGatewayOffline), true);
|
});
|
break;
|
case "NoRecord"://MAC不正确
|
Application.RunOnMainThread(() => {
|
new HDL_ON.UI.PublicAssmebly().TipMsgAutoClose(Language.StringByID(StringId.MACError), true);
|
});
|
break;
|
case "Success":
|
break;
|
default:
|
Application.RunOnMainThread(() => {
|
new HDL_ON.UI.PublicAssmebly().TipMsgAutoClose(Language.StringByID(StringId.LinkLoser), true);
|
});
|
break;
|
}
|
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="message">附加数据包</param>
|
/// <param name="optionType">操作类型:0=网关控制;1=订阅网关数据;2=订阅网关上线数据</param>
|
/// <returns></returns>
|
public static async Task MqttRemoteSend(byte[] message, int optionType = 0)
|
{
|
try
|
{
|
string topicName;
|
switch (optionType)
|
{
|
case 0:
|
topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/ON";
|
if (!string.IsNullOrEmpty(mqttEncryptKey))
|
{
|
message = Shared.Securitys.EncryptionService.AesEncryptPayload(message, mqttEncryptKey);
|
}
|
await RemoteMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topicName, Payload = message, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce });
|
break;
|
case 3:
|
topicName = $"/ClientToBusGateWay/{CurRemoteMACInfo.macMark}/Common/CheckGateway";
|
Console.WriteLine("CheckGateway");
|
await RemoteMqttClient.PublishAsync(new MqttApplicationMessage { Topic = topicName, Retain = false, QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce });
|
break;
|
}
|
}
|
catch (Exception e)
|
{
|
//System.Console.WriteLine ($"============>Mqtt MqttRemoteSend catch");
|
if (!IsDisConnectingWithSendCatch)
|
{
|
IsDisConnectingWithSendCatch = true;
|
await DisConnectRemoteMqttClient("SendCatch");
|
}
|
}
|
}
|
/// <summary>
|
/// SendCatch 后执行一次断开操作
|
/// </summary>
|
static bool IsDisConnectingWithSendCatch = false;
|
|
}
|
}
|