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;
///
/// 手机标识
///
static Guid currentGuid = Guid.NewGuid();
///
/// 外网的MQTT是否正在连接
///
///
/// 远程MqttClient
///
///
/// 远程MqttClient
///
public static IMqttClient RemoteMqttClient = new MqttFactory().CreateMqttClient();
static bool thisShowTip = true;
//static string mqttRequestParToken="";
///
/// 推送标识
///
static string PushSignStr = System.DateTime.Now.Ticks.ToString();
///
/// 断开远程Mqtt的链接
///
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;
///
/// 外网的MQTT是否正在连接
///
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 { }
}
}
///
/// 启动远程Mqtt
///
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(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;
}
});
}
/////
///// 收到网关上线消息
/////
//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(gatewayListRequestResult.ResponseData.ToString());
// if (gatewayListRequestResult_Obj != null && gatewayListRequestResult_Obj.pageData.Count > 0)
// {
// CurRemoteMACInfo.aesKey = gatewayListRequestResult_Obj.pageData[0].aesKey;
// mqttEncryptKey = CurRemoteMACInfo.isNewBusproGateway ? CurRemoteMACInfo.aesKey : "";
// }
//}
///
/// 收到挤下线推送
///
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);
});
}
///
/// 收到CheckGateway主题
///
static void ReceiveCheckGateway(string mMes)
{
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject(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;
}
}
///
///
///
/// 附加数据包
/// 操作类型:0=网关控制;1=订阅网关数据;2=订阅网关上线数据
///
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");
}
}
}
///
/// SendCatch 后执行一次断开操作
///
static bool IsDisConnectingWithSendCatch = false;
}
}