using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Shared.Common;
using ZigBee.Device;
namespace ZigBee.Common
{
public static class Application
{
public static bool isInited;
static bool isEncry;
///
/// 是否正在搜索网关
///
public static bool IsSearchingGateway = false;
///
/// 新发现的网关通知
///
public static Action NewGateWayAction;
///
/// 上一次的住宅ID
///
private static string oldHomeID = string.Empty;
public static void Init()
{
if (isInited)
{
return;
}
isInited = true;
new System.Threading.Thread(async () =>
{
var gateWayList = new List { };
var searchCount = 6;
var broadBytes = new byte[44];// byteHomeId[0] ,//H
broadBytes[0] = 0xfe;
broadBytes[1] = 0x29;
broadBytes[2] = 0x00;
broadBytes[3] = 0x00;
broadBytes[4] = 0x00;
broadBytes[5] = 0x00;
broadBytes[6] = 0x00;
broadBytes[43] = 0x02;
while (true)
{
try
{
if (string.IsNullOrEmpty(Shared.Common.Config.Instance.HomeId))
{
//住宅ID为空只有一种可能就是退出了登录,这里的上一次住宅ID要清空
oldHomeID = "?";
System.Threading.Thread.Sleep(1000);
continue;
}
//首次进入网关,和切换住宅会清除网关列表,重新搜索存储
if (Shared.Common.Config.Instance.HomeId != oldHomeID)
{
//因为那一瞬间,有可能mqtt会加回来,所以先加缓存
var list = new List();
list.AddRange(ZbGateway.GateWayList);
//然后清空掉
ZbGateway.GateWayList.Clear();
//最后再断开mqtt连接
for (int i = 0; i < list.Count; i++)
{
list[i].DisConnectLocalMqttClient("1");
}
list.Clear();
oldHomeID = Shared.Common.Config.Instance.HomeId;
var tempBytes = System.Text.Encoding.UTF8.GetBytes(Shared.Common.Config.Instance.HomeId);
System.Array.Copy(tempBytes, 0, broadBytes, 7, 36 < tempBytes.Length ? 36 : tempBytes.Length);
//住宅中已经存在的网关如果局域网不存在,需要在当前住宅中虚拟一个网关ID相同的网关
var gateWayFileList = Global.FileListByHomeId().FindAll(obj => obj.StartsWith("Gateway_"));
foreach (var filePath in gateWayFileList)
{
var paths = filePath.Split('_');
if (paths.Length < 3)
continue;
var gateWay = ZbGateway.GateWayList.Find(obj => (obj != null) && (obj.getGatewayBaseInfo != null) && (obj.getGatewayBaseInfo.gwID == paths[2]));
if (gateWay == null)
{
gateWay = new ZbGateway { IsVirtual = true };
gateWay.getGatewayBaseInfo.gwID = paths[2];
gateWay.getGatewayBaseInfo.HomeId = Shared.Common.Config.Instance.HomeId;
ZbGateway.GateWayList.Add(gateWay);
}
}
}
var broadcastIpAddress = new Shared.Net.NetWiFi().BroadcastIpAddress;
if (Shared.Application.IsWifi)
{
if (0 < gateWayList.Count)
{
searchCount = 6;
ZbGateway.IsRemote = false;
}
else
{
if (searchCount < 0)
{
ZbGateway.IsRemote = true;
}
}
}
else
{
ZbGateway.IsRemote = true;
for (int i = 0; i < ZbGateway.GateWayList.Count; i++)
{
ZbGateway.GateWayList[i].DisConnectLocalMqttClient("1");
}
}
searchCount--;
#region 1秒搜索一次网关
//每0.5秒广播发现一次网关,共1s
int count = 2;
new System.Threading.Thread(() =>
{
gateWayList.Clear();
while (0 < count--)
{
try
{
//点对点发送(先发一条已有的点播,回复几率高一点)
for (int i = 0; i < gateWayList.Count; i++)
{
FindGateWaySocket.BeginSend(new System.Net.IPEndPoint(System.Net.IPAddress.Parse(gateWayList[i].getGatewayBaseInfo.IpAddress), 7624), broadBytes);
}
//广播发送
if (broadcastIpAddress.ToString() != "0.0.0.0")
{
FindGateWaySocket.BeginSend(new System.Net.IPEndPoint(broadcastIpAddress, 7624), broadBytes);
}
}
catch { }
System.Threading.Thread.Sleep(500);
}
})
{ IsBackground = true }.Start();
while (0 < count)
{
try
{
if (FindGateWaySocket.busSocket == null)
{
System.Threading.Thread.Sleep(100);
continue;
}
var bytes = new byte[1024];
var len = FindGateWaySocket.busSocket.Receive(bytes, bytes.Length, System.Net.Sockets.SocketFlags.None);
if (bytes[43] == 0xA2)
{
//广播回复网关的基本信息处理
var ipAddress = $"{bytes[3]}.{bytes[4]}.{bytes[5]}.{bytes[6]}";
var homeID = System.Text.Encoding.UTF8.GetString(bytes, 7, 36);
homeID = homeID.Replace('\0', ' ').Trim();
var isMainGateWay = bytes[44] == 1;
var time = (bytes[48] & 0xff) << 24 | (bytes[47] & 0xff) << 16 | (bytes[46] & 0xff) << 8 | (bytes[45] & 0xff);
var gwNameLength = bytes[49];
var gwName = System.Text.Encoding.UTF8.GetString(bytes, 50, gwNameLength);
var gwIdLength = bytes[49 + gwNameLength + 1];
var id = Encoding.UTF8.GetString(bytes, 49 + gwNameLength + 2, gwIdLength);
var pubKeyLengthByte0 = bytes[49 + gwNameLength + 1 + gwIdLength + 1];
var pubKeyLengthByte1 = bytes[49 + gwNameLength + 1 + gwIdLength + 2];
int pubKeyLength = ((pubKeyLengthByte1 & 0xff) << 8 | (pubKeyLengthByte0 & 0xff));
var pubKey = Encoding.UTF8.GetString(bytes, 49 + gwNameLength + 1 + gwIdLength + 2 + 1, pubKeyLength);
var zbGateWay = new ZbGateway
{
getGatewayBaseInfo = new ZbGateway.GatewayBaseInfo
{
IpAddress = ipAddress,
Time = time,
GwName = gwName,
HomeId = homeID,
IsMainGateWay = isMainGateWay,
gwID = id,
},
GatewayOnlineFlage = true,
PubKey = pubKey
};
//通讯到网关列表
if (gateWayList.Find(obj => obj.getGatewayBaseInfo.gwID == zbGateWay.getGatewayBaseInfo.gwID) == null)
{
//网关匹配当前住宅中到网关
if (Shared.Common.Config.Instance.HomeId == homeID)
{
gateWayList.Add(zbGateWay);
}
//UI界面正在搜索,不必配当前住宅到到网关此时也通讯
else if (IsSearchingGateway)
{
gateWayList.Add(zbGateWay);
}
//网关中到住宅ID为空此时也通讯
else if (homeID == string.Empty)
{
gateWayList.Add(zbGateWay);
}
}
//网关列表存储处理
var gateWay = ZbGateway.GateWayList.Find(obj => obj.getGatewayBaseInfo != null && obj.getGatewayBaseInfo.gwID == zbGateWay.getGatewayBaseInfo.gwID);
if (gateWay == null)
{
ZbGateway.GateWayList.Add(zbGateWay);
await zbGateWay.StartLocalMqtt(ipAddress);
NewGateWayAction?.Invoke(zbGateWay);
}
else
{
gateWay.IsVirtual = false;
//将该网关标识为【可搜索到,即:在线】
gateWay.GatewayOnlineFlage = true;
if (gateWay.getGatewayBaseInfo.IpAddress != ipAddress)
{
await gateWay.DisConnectLocalMqttClient("2");
ZbGateway.GateWayList.Remove(gateWay);
gateWay = zbGateWay;
ZbGateway.GateWayList.Add(gateWay);
await zbGateWay.StartLocalMqtt(ipAddress);
}
else
{
gateWay.PubKey = pubKey;
gateWay.getGatewayBaseInfo.Time = time;
gateWay.getGatewayBaseInfo.GwName = gwName;
gateWay.getGatewayBaseInfo.HomeId = homeID;
await gateWay.StartLocalMqtt(ipAddress);
}
//主网关设置
if (isMainGateWay && oldHomeID == gateWay.getGatewayBaseInfo.HomeId)
{
for (int i = 0; i < ZbGateway.GateWayList.Count; i++)
{
var gw = ZbGateway.GateWayList[i];
//网关ID不是当前的网关,则把网关列表中其他网关标记为不是主网关
if (gw.getGatewayBaseInfo.gwID != id && oldHomeID == gw.getGatewayBaseInfo.HomeId)
{
gw.getGatewayBaseInfo.IsMainGateWay = false;
}
}
//标记当前网关是主网关
gateWay.getGatewayBaseInfo.IsMainGateWay = true;
}
}
}
}
catch { }
}
#endregion
}
catch { }
System.Threading.Thread.Sleep(500);
}
})
{ IsBackground = true }.Start();
///远程主网关更新
new System.Threading.Thread(async () =>
{
while (true)
{
try
{
//定时检测远程连接情况
await ZbGateway.StartRemoteMqtt();
if (!ZbGateway.IsRemote)
{
System.Threading.Thread.Sleep(500);
continue;
}
var gateWayList = ZbGateway.GateWayList.FindAll(obj => obj.getGatewayBaseInfo.HomeId == Shared.Common.Config.Instance.HomeId);
if (gateWayList.Count == 1)
{
gateWayList[0].getGatewayBaseInfo.IsMainGateWay = true;
}
else
{
if (gateWayList.Find((obj) => obj.getGatewayBaseInfo.IsMainGateWay) == null)
{
for (int i = 0; i < gateWayList.Count; i++)
{
var gateWay = gateWayList[i];
var info = await gateWay.GetZbGwInfoAsync();
if (info == null || info.getGwData == null)
{
continue;
}
if (info.getGwData.IsDominant == 1)
{
for (int j = 0; j < gateWayList.Count; j++)
{
if (gateWayList[i].getGatewayBaseInfo.gwID == info.getGwData.GwId)
{
gateWayList[i].getGatewayBaseInfo.IsMainGateWay = true;
}
else
{
gateWayList[i].getGatewayBaseInfo.IsMainGateWay = false;
}
}
break;
}
}
}
}
}
catch { }
System.Threading.Thread.Sleep(2000);
}
})
{ IsBackground = true }.Start();
}
///
/// 重新搜索,注意:调用该方法,则促使全部网关的mqtt全部断开,然后重新搜索(可能会有1秒延迟)
///
public static void ReSearch()
{
//为了那么多少万分之一的几率,这里设置成别的另一类的值
oldHomeID = "**";
}
///
/// 接收处理UDP数据包
///
///
public static class FindGateWaySocket
{
//本地Socket
public static System.Net.Sockets.Socket busSocket;
///
/// 启动Socket接收和发送功能
///
///
public static void Start(int port = 7624)
{
if (IsRunning)
{
return;
}
//定义网络类型,数据连接类型和网络协议UDP
busSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
busSocket.EnableBroadcast = true;
busSocket.ReceiveTimeout = 1000;
busSocket.SendTimeout = 1000;
busSocket.Bind(new IPEndPoint(IPAddress.Any, port));
}
///
/// 停止Socket
///
public static void Stop()
{
if (!IsRunning)
{
return;
}
try
{
busSocket.Close();
}
catch { }
busSocket = null;
Console.WriteLine("BusSocket关闭成功!");
}
///
/// 当前的Socket是否运行
///
public static bool IsRunning
{
get
{
return null == busSocket ? false : true;
}
}
///
/// 异步发送数据
///
///
public static void BeginSend(System.Net.IPEndPoint iPEndPoint, byte[] bytes)
{
try
{
Start(7624);
busSocket.BeginSendTo(bytes, 0, bytes.Length, SocketFlags.None, iPEndPoint, new AsyncCallback(asyncEndSend), null);
}
catch { }
}
///
/// 异步发送数据结束
///
///
private static void asyncEndSend(IAsyncResult iar)
{
try
{
int bytesSent = busSocket.EndSendTo(iar);
}
catch { }
}
}
}
}