diff --git a/EC.Util/CameraSDK/Common/CameraStruct.cs b/EC.Util/CameraSDK/Common/CameraStruct.cs index 547bf3c..2105df2 100644 --- a/EC.Util/CameraSDK/Common/CameraStruct.cs +++ b/EC.Util/CameraSDK/Common/CameraStruct.cs @@ -12,6 +12,8 @@ public class CameraInfo /// public string Id { get; set; } = string.Empty; + public string Name { get; set; } = string.Empty; + /// /// 相机厂商 /// @@ -103,7 +105,7 @@ public enum CameraPort : int { HiK = 8000, DaHua = 37777, - YuShi = 8800, + YuShi = 80, } /// diff --git a/EC.Util/CameraSDK/DaHua/DaHuaOriSDK.cs b/EC.Util/CameraSDK/DaHua/DaHuaOriSDK.cs index a8c352d..f4408b1 100644 --- a/EC.Util/CameraSDK/DaHua/DaHuaOriSDK.cs +++ b/EC.Util/CameraSDK/DaHua/DaHuaOriSDK.cs @@ -8,6 +8,8 @@ public static class DaHuaOriSDK private const string LibDhNetSDK = @"./libs/dh-win64/dhnetsdk.dll"; + private const bool Debug = true; + #endregion Lib Attr static DaHuaOriSDK() diff --git a/EC.Util/CameraSDK/DaHua/DaHuaSDK.cs b/EC.Util/CameraSDK/DaHua/DaHuaSDK.cs index 4b940ff..068c95b 100644 --- a/EC.Util/CameraSDK/DaHua/DaHuaSDK.cs +++ b/EC.Util/CameraSDK/DaHua/DaHuaSDK.cs @@ -10,6 +10,8 @@ public class DaHuaSDK : ICameraSDK private IntPtr RealplayHandle { get; set; } = IntPtr.Zero; + private int Channel { get; } = 1; + #endregion Fields public DaHuaSDK(CameraInfo cameraInfo) : base(cameraInfo) @@ -22,7 +24,6 @@ public class DaHuaSDK : ICameraSDK { bool ret = ConnectSuccess(); if (ret) return true; - DaHuaOriSDK.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY stuInParam = new(); stuInParam.dwSize = (uint)Marshal.SizeOf(stuInParam); stuInParam.szIP = CameraInfo.Ip; @@ -39,7 +40,7 @@ public class DaHuaSDK : ICameraSDK { LoginId = lLoginID; }, IntPtr.Zero); - + else BuildException(); return ret; } @@ -47,10 +48,9 @@ public class DaHuaSDK : ICameraSDK { bool ret = ConnectSuccess(); if (!ret) return true; - ret = DaHuaOriSDK.CLIENT_Logout(LoginId); if (ret) LoginId = IntPtr.Zero; - + else BuildException(); return ret; } @@ -138,20 +138,18 @@ public class DaHuaSDK : ICameraSDK public override bool PtzMove(int cmd, int stop, int speed) { if (!ConnectSuccess()) return false; - int channel = 0; - bool stopFlag = stop == 1; - bool flag = DaHuaOriSDK.CLIENT_DHPTZControlEx2(LoginId, channel, (uint)cmd, speed, speed, 0, stopFlag, IntPtr.Zero); - //if (flag) BuildException(); - return flag; + bool stopret = stop == 1; + bool ret = DaHuaOriSDK.CLIENT_DHPTZControlEx2(LoginId, Channel, (uint)cmd, speed, speed, 0, stopret, IntPtr.Zero); + if (!ret) BuildException(); + return ret; } public override bool PtzPreset(int cmd, int presetId) { if (!ConnectSuccess()) return false; - int channel = 0; - bool flag = DaHuaOriSDK.CLIENT_DHPTZControlEx2(LoginId, channel, (uint)DaHuaOriSDK.EM_EXTPTZ_ControlType.POINT_MOVE, 0, presetId, 0, false, IntPtr.Zero); - if (flag) BuildException(); - return flag; + bool ret = DaHuaOriSDK.CLIENT_DHPTZControlEx2(LoginId, Channel, (uint)DaHuaOriSDK.EM_EXTPTZ_ControlType.POINT_MOVE, 0, presetId, 0, false, IntPtr.Zero); + if (!ret) BuildException(); + return ret; } #endregion Ptz Method @@ -161,17 +159,16 @@ public class DaHuaSDK : ICameraSDK public override void StartPlay(IntPtr hwnd) { if (!ConnectSuccess() || IsPlaying()) return; - int channel = 1; - RealplayHandle = DaHuaOriSDK.CLIENT_RealPlayEx(LoginId, channel, hwnd, DaHuaOriSDK.EM_RealPlayType.Realplay); + RealplayHandle = DaHuaOriSDK.CLIENT_RealPlayEx(LoginId, Channel, hwnd, DaHuaOriSDK.EM_RealPlayType.Realplay); if (RealplayHandle == IntPtr.Zero) BuildException(); } public override void StopPlay() { if (!IsPlaying()) return; - bool flag = DaHuaOriSDK.CLIENT_StopRealPlayEx(RealplayHandle); + bool ret = DaHuaOriSDK.CLIENT_StopRealPlayEx(RealplayHandle); RealplayHandle = IntPtr.Zero; - if (flag) BuildException(); + if (!ret) BuildException(); } public override bool IsPlaying() diff --git a/EC.Util/CameraSDK/HiK/HiKOriSDK.cs b/EC.Util/CameraSDK/HiK/HiKOriSDK.cs index 769184a..04a1a04 100644 --- a/EC.Util/CameraSDK/HiK/HiKOriSDK.cs +++ b/EC.Util/CameraSDK/HiK/HiKOriSDK.cs @@ -6,7 +6,10 @@ public static class HiKOriSDK { #region Lib Attr - public const string LibHcNetSDK = @"./libs/hk-win64/HCNetSDK.dll"; + public const string LibHkNetSDK = @"./libs/hk-win64/HCNetSDK.dll"; + //public const string LibHkNetSDK = @"./libs/hk-win64/libhcnetsdk.so"; + + private const bool Debug = true; #endregion Lib Attr @@ -25,6 +28,7 @@ public static class HiKOriSDK bool ret = NET_DVR_Init(); InitSuccess = ret; if (!ret) throw new Exception("HiKOriSDK global init failure."); + if (Debug) NET_DVR_SetLogToFile(3, Path.Combine("./log", "hikSdkLog"), true); return ret; } @@ -45,6 +49,10 @@ public static class HiKOriSDK public const int PtzSpeedMin = 1; public const int PtzSpeedMax = 7; + public const int NET_DVR_DEV_ADDRESS_MAX_LEN = 129; + public const int NET_DVR_LOGIN_USERNAME_MAX_LEN = 64; + public const int NET_DVR_LOGIN_PASSWD_MAX_LEN = 64; + #region 用于 NET_DVR_SetDVRConfig 和 NET_DVR_GetDVRConfig public const int NET_DVR_SET_PTZPOS = 292; //云台设置PTZ位置 @@ -176,6 +184,62 @@ public static class HiKOriSDK public byte[] byRes2; //保留 } + public delegate void LOGINRESULTCALLBACK(int lUserID, int dwResult, IntPtr lpDeviceInfo, IntPtr pUser); + + [StructLayout(LayoutKind.Sequential)] + public struct NET_DVR_USER_LOGIN_INFO + { + [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NET_DVR_DEV_ADDRESS_MAX_LEN, ArraySubType = UnmanagedType.I1)] + public byte[] sDeviceAddress; + + public byte byUseTransport; + public ushort wPort; + + [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NET_DVR_LOGIN_USERNAME_MAX_LEN, ArraySubType = UnmanagedType.I1)] + public byte[] sUserName; + + [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = NET_DVR_LOGIN_PASSWD_MAX_LEN, ArraySubType = UnmanagedType.I1)] + public byte[] sPassword; + + public LOGINRESULTCALLBACK cbLoginResult; + public IntPtr pUser; + public bool bUseAsynLogin; + public byte byProxyType; //0:不使用代理,1:使用标准代理,2:使用EHome代理 + public byte byUseUTCTime; //0-不进行转换,默认,1-接口上输入输出全部使用UTC时间,SDK完成UTC时间与设备时区的转换,2-接口上输入输出全部使用平台本地时间,SDK完成平台本地时间与设备时区的转换 + public byte byLoginMode; //0-Private, 1-ISAPI, 2-自适应 + public byte byHttps; //0-不适用tls,1-使用tls 2-自适应 + public int iProxyID; //代理服务器序号,添加代理服务器信息时,相对应的服务器数组下表值 + public byte byVerifyMode; //认证方式,0-不认证,1-双向认证,2-单向认证;认证仅在使用TLS的时候生效; + + [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 119, ArraySubType = UnmanagedType.I1)] + public byte[] byRes3; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NET_DVR_DEVICEINFO_V40 + { + public NET_DVR_DEVICEINFO_V30 struDeviceV30; + public byte bySupportLock; //设备支持锁定功能,该字段由SDK根据设备返回值来赋值的。bySupportLock为1时,dwSurplusLockTime和byRetryLoginTime有效 + public byte byRetryLoginTime; //剩余可尝试登陆的次数,用户名,密码错误时,此参数有效 + public byte byPasswordLevel; //admin密码安全等级0-无效,1-默认密码,2-有效密码,3-风险较高的密码。当用户的密码为出厂默认密码(12345)或者风险较高的密码时,上层客户端需要提示用户更改密码。 + public byte byProxyType;//代理类型,0-不使用代理, 1-使用socks5代理, 2-使用EHome代理 + public uint dwSurplusLockTime; //剩余时间,单位秒,用户锁定时,此参数有效 + public byte byCharEncodeType; //字符编码类型(SDK所有接口返回的字符串编码类型,透传接口除外):0- 无字符编码信息(老设备),1- GB2312(简体中文),2- GBK,3- BIG5(繁体中文),4- Shift_JIS(日文),5- EUC-KR(韩文),6- UTF-8,7- ISO8859-1,8- ISO8859-2,9- ISO8859-3,…,依次类推,21- ISO8859-15(西欧) + public byte bySupportDev5;//支持v50版本的设备参数获取,设备名称和设备类型名称长度扩展为64字节 + public byte bySupport; //能力集扩展,位与结果:0- 不支持,1- 支持 + + // bySupport & 0x1: 保留 + // bySupport & 0x2: 0-不支持变化上报 1-支持变化上报 + public byte byLoginMode; //登录模式 0-Private登录 1-ISAPI登录 + + public int dwOEMCode; + public int iResidualValidity; //该用户密码剩余有效天数,单位:天,返回负值,表示密码已经超期使用,例如“-3表示密码已经超期使用3天” + public byte byResidualValidity; // iResidualValidity字段是否有效,0-无效,1-有效 + + [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 243, ArraySubType = UnmanagedType.I1)] + public byte[] byRes2; + } + //球机位置信息 [StructLayout(LayoutKind.Sequential)] public struct NET_DVR_PTZPOS @@ -242,54 +306,39 @@ public static class HiKOriSDK #region Common Method - [DllImport(LibHcNetSDK)] + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] public static extern bool NET_DVR_Init(); - [DllImport(LibHcNetSDK)] + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] public static extern bool NET_DVR_Cleanup(); - [DllImport(LibHcNetSDK)] + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern bool NET_DVR_SetLogToFile(int bLogEnable, string strLogDir, bool bAutoDel); + + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] public static extern uint NET_DVR_GetLastError(); - [DllImport(LibHcNetSDK)] - public static extern int NET_DVR_Login_V30( - string sDVRIP, - int wDVRPort, - string sUserName, - string sPassword, - ref NET_DVR_DEVICEINFO_V30 lpDeviceInfo - ); + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern int NET_DVR_Login_V30(string sDVRIP, int wDVRPort, string sUserName, string sPassword, ref NET_DVR_DEVICEINFO_V30 lpDeviceInfo); - [DllImport(LibHcNetSDK)] + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern int NET_DVR_Login_V40(ref NET_DVR_USER_LOGIN_INFO pLoginInfo, ref NET_DVR_DEVICEINFO_V40 lpDeviceInfo); + + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] public static extern bool NET_DVR_Logout(int iUserID); + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern bool NET_DVR_SetReconnect(uint dwInterval, int bEnableRecon); + //参数配置 begin - [DllImport(LibHcNetSDK)] - public static extern bool NET_DVR_GetDVRConfig( - int lUserID, - uint dwCommand, - int lChannel, - IntPtr lpOutBuffer, - uint dwOutBufferSize, - ref uint lpBytesReturned - ); - - [DllImport(LibHcNetSDK)] - public static extern bool NET_DVR_PTZControlWithSpeed_Other( - int lUserID, - int lChannel, - uint dwPTZCommand, - uint dwStop, - uint dwSpeed - ); - - [DllImport(LibHcNetSDK)] - public static extern bool NET_DVR_PTZPreset_Other( - int lUserID, - int lChannel, - uint dwPTZPresetCmd, - uint dwPresetIndex - ); + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern bool NET_DVR_GetDVRConfig(int lUserID, uint dwCommand, int lChannel, IntPtr lpOutBuffer, uint dwOutBufferSize, ref uint lpBytesReturned); + + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern bool NET_DVR_PTZControlWithSpeed_Other(int lUserID, int lChannel, uint dwPTZCommand, uint dwStop, uint dwSpeed); + + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern bool NET_DVR_PTZPreset_Other(int lUserID, int lChannel, uint dwPTZPresetCmd, uint dwPresetIndex); /********************************************************* Function: REALDATACALLBACK @@ -303,13 +352,7 @@ public static class HiKOriSDK Return: void **********************************************************/ - public delegate void REALDATACALLBACK( - int lRealHandle, - uint dwDataType, - IntPtr pBuffer, - uint dwBufSize, - IntPtr pUser - ); + public delegate void RealDataCallBack(int lRealHandle, uint dwDataType, IntPtr pBuffer, uint dwBufSize, IntPtr pUser); /********************************************************* Function: NET_DVR_RealPlay_V40 @@ -322,16 +365,9 @@ public static class HiKOriSDK Return: 1表示失败,其他值作为NET_DVR_StopRealPlay等函数的句柄参数 **********************************************************/ - [DllImport(LibHcNetSDK)] - public static extern int NET_DVR_RealPlay_V40( - int iUserID, - ref NET_DVR_PREVIEWINFO lpPreviewInfo, - REALDATACALLBACK fRealDataCallBack_V30, - IntPtr pUser - ); + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] + public static extern int NET_DVR_RealPlay_V40(int iUserID, ref NET_DVR_PREVIEWINFO lpPreviewInfo, RealDataCallBack fRealDataCallBack_V30, IntPtr pUser); - // [DllImport(@".\HCNetSDK.dll")] - // public static extern int NET_DVR_GetRealPlayerIndex(int lRealHandle); /********************************************************* Function: NET_DVR_StopRealPlay Desc: 停止预览。 @@ -340,7 +376,7 @@ public static class HiKOriSDK Return: **********************************************************/ - [DllImport(LibHcNetSDK)] + [DllImport(LibHkNetSDK, CallingConvention = CallingConvention.StdCall)] public static extern bool NET_DVR_StopRealPlay(int iRealHandle); #endregion Common Method diff --git a/EC.Util/CameraSDK/HiK/HiKSDK.cs b/EC.Util/CameraSDK/HiK/HiKSDK.cs index eec10ad..98eb2ab 100644 --- a/EC.Util/CameraSDK/HiK/HiKSDK.cs +++ b/EC.Util/CameraSDK/HiK/HiKSDK.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using System.Text; namespace EC.Util.CameraSDK; @@ -10,6 +11,8 @@ public class HiKSDK : ICameraSDK private int RealplayHandle { get; set; } = -1; + private int Channel { get; } = 1; + #endregion Fields public HiKSDK(CameraInfo cameraInfo) : base(cameraInfo) @@ -22,11 +25,24 @@ public class HiKSDK : ICameraSDK { bool ret = ConnectSuccess(); if (ret) return true; - - HiKOriSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new(); - LoginId = HiKOriSDK.NET_DVR_Login_V30(CameraInfo.Ip, CameraInfo.Port, CameraInfo.UserName, CameraInfo.Password, ref deviceInfo); + HiKOriSDK.NET_DVR_USER_LOGIN_INFO loginInfo = new() + { + bUseAsynLogin = false, + sDeviceAddress = new byte[129], + wPort = (ushort)CameraInfo.Port, + sUserName = new byte[64], + sPassword = new byte[64] + }; + Encoding.Default.GetBytes(CameraInfo.Ip).CopyTo(loginInfo.sDeviceAddress, 0); + Encoding.Default.GetBytes(CameraInfo.UserName).CopyTo(loginInfo.sUserName, 0); + Encoding.Default.GetBytes(CameraInfo.Password).CopyTo(loginInfo.sPassword, 0); + HiKOriSDK.NET_DVR_DEVICEINFO_V40 deviceInfo = new(); + LoginId = HiKOriSDK.NET_DVR_Login_V40(ref loginInfo, ref deviceInfo); ret = ConnectSuccess(); - + if (ret) HiKOriSDK.NET_DVR_SetReconnect(10000, 1); + else BuildException(); + //HiKOriSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new(); + //LoginId = HiKOriSDK.NET_DVR_Login_V30(CameraInfo.Ip, CameraInfo.Port, CameraInfo.UserName, CameraInfo.Password, ref deviceInfo); return ret; } @@ -34,10 +50,9 @@ public class HiKSDK : ICameraSDK { bool ret = ConnectSuccess(); if (!ret) return true; - ret = HiKOriSDK.NET_DVR_Logout(LoginId); if (ret) LoginId = -1; - + else BuildException(); return ret; } @@ -124,19 +139,17 @@ public class HiKSDK : ICameraSDK public override bool PtzMove(int cmd, int stop, int speed) { if (!ConnectSuccess()) return false; - int lChannel = 1; - bool flag = HiKOriSDK.NET_DVR_PTZControlWithSpeed_Other(LoginId, lChannel, (uint)cmd, (uint)stop, (uint)speed); - if (flag) BuildException(); - return flag; + bool ret = HiKOriSDK.NET_DVR_PTZControlWithSpeed_Other(LoginId, Channel, (uint)cmd, (uint)stop, (uint)speed); + if (!ret) BuildException(); + return ret; } public override bool PtzPreset(int cmd, int presetId) { if (!ConnectSuccess()) return false; - int lChannel = 1; - bool flag = HiKOriSDK.NET_DVR_PTZPreset_Other(LoginId, lChannel, (uint)cmd, (uint)presetId); - if (flag) BuildException(); - return flag; + bool ret = HiKOriSDK.NET_DVR_PTZPreset_Other(LoginId, Channel, (uint)cmd, (uint)presetId); + if (!ret) BuildException(); + return ret; } #endregion Ptz Method @@ -149,7 +162,7 @@ public class HiKSDK : ICameraSDK HiKOriSDK.NET_DVR_PREVIEWINFO previewInfo = new() { hPlayWnd = hwnd, //预览窗口 - lChannel = 1, //预览的设备通道 + lChannel = Channel, //预览的设备通道 dwStreamType = 0, //码流类型:0-主码流,1-子码流,2-码流3,3-码流4,以此类推 dwLinkMode = 0, //连接方式:0- TCP方式,1- UDP方式,2- 多播方式,3- RTP方式,4-RTP/RTSP,5-RSTP/HTTP bBlocked = true, //0- 非阻塞取流,1- 阻塞取流 @@ -165,9 +178,9 @@ public class HiKSDK : ICameraSDK public override void StopPlay() { if (!IsPlaying()) return; - bool flag = HiKOriSDK.NET_DVR_StopRealPlay(RealplayHandle); + bool ret = HiKOriSDK.NET_DVR_StopRealPlay(RealplayHandle); RealplayHandle = -1; - if (!flag) BuildException(); + if (!ret) BuildException(); } public override bool IsPlaying() diff --git a/EC.Util/CameraSDK/YuShi/YuShiOriSDK.cs b/EC.Util/CameraSDK/YuShi/YuShiOriSDK.cs index 991cb12..495aea7 100644 --- a/EC.Util/CameraSDK/YuShi/YuShiOriSDK.cs +++ b/EC.Util/CameraSDK/YuShi/YuShiOriSDK.cs @@ -8,6 +8,8 @@ public static class YuShiOriSDK public const string LibYsNetSDK = @"./libs/ys-win64/NetDEVSDK.dll"; + private const bool Debug = true; + #endregion Lib Attr static YuShiOriSDK() diff --git a/EC.Util/CameraSDK/YuShi/YuShiSDK.cs b/EC.Util/CameraSDK/YuShi/YuShiSDK.cs index 4b99a78..7e37652 100644 --- a/EC.Util/CameraSDK/YuShi/YuShiSDK.cs +++ b/EC.Util/CameraSDK/YuShi/YuShiSDK.cs @@ -8,6 +8,8 @@ public class YuShiSDK : ICameraSDK private IntPtr RealplayHandle { get; set; } = IntPtr.Zero; + private int Channel { get; } = 1; + #endregion Fields public YuShiSDK(CameraInfo cameraInfo) : base(cameraInfo) @@ -20,7 +22,6 @@ public class YuShiSDK : ICameraSDK { bool ret = ConnectSuccess(); if (ret) return true; - YuShiOriSDK.NETDEV_DEVICE_LOGIN_INFO_S loginInfo = new(); loginInfo.szIPAddr = CameraInfo.Ip; loginInfo.dwPort = CameraInfo.Port; @@ -29,7 +30,7 @@ public class YuShiSDK : ICameraSDK YuShiOriSDK.NETDEV_SELOG_INFO_S logInfo = new(); LoginId = YuShiOriSDK.NETDEV_Login_V30(ref loginInfo, ref logInfo); ret = ConnectSuccess(); - + if(!ret) BuildException(); return ret; } @@ -37,10 +38,9 @@ public class YuShiSDK : ICameraSDK { bool ret = ConnectSuccess(); if (!ret) return true; - ret = YuShiOriSDK.NETDEV_Logout(LoginId); if (ret) LoginId = IntPtr.Zero; - + else BuildException(); return ret; } @@ -65,7 +65,7 @@ public class YuShiSDK : ICameraSDK bool ret = ConnectSuccess(); if (!ret) return PtzInfo.Default; YuShiOriSDK.NETDEV_PTZ_STATUS_S entity = new(); - ret = YuShiOriSDK.NETDEV_PTZGetStatus(LoginId, 1, ref entity); + ret = YuShiOriSDK.NETDEV_PTZGetStatus(LoginId, Channel, ref entity); if (!ret) { BuildException(); return PtzInfo.Default; } return PtzInfo.New(entity.fPanTiltX, entity.fPanTiltY, entity.fZoomX); } @@ -75,7 +75,7 @@ public class YuShiSDK : ICameraSDK bool ret = ConnectSuccess(); if (!ret) { ptzInfo = PtzInfo.Default; return false; } YuShiOriSDK.NETDEV_PTZ_STATUS_S entity = new(); - ret = YuShiOriSDK.NETDEV_PTZGetStatus(LoginId, 1, ref entity); + ret = YuShiOriSDK.NETDEV_PTZGetStatus(LoginId, Channel, ref entity); if (!ret) { BuildException(); ptzInfo = PtzInfo.Default; return false; } ptzInfo = PtzInfo.New(entity.fPanTiltX, entity.fPanTiltY, entity.fZoomX); return true; @@ -85,21 +85,19 @@ public class YuShiSDK : ICameraSDK { if (!ConnectSuccess()) return false; if (stop == 1) cmd = YuShiOriSDK.ALLSTOP; - int channel = 0; - int ret = YuShiOriSDK.NETDEV_PTZControl_Other(LoginId, channel, cmd, speed); - bool flag = ret == YuShiOriSDK.TRUE; - if (!flag) BuildException(); - return flag; + int retNum = YuShiOriSDK.NETDEV_PTZControl_Other(LoginId, Channel, cmd, speed); + bool ret = retNum == YuShiOriSDK.TRUE; + if (!ret) BuildException(); + return ret; } public override bool PtzPreset(int cmd, int presetId) { if (!ConnectSuccess()) return false; - int channel = 0; - int ret = YuShiOriSDK.NETDEV_PTZPreset_Other(LoginId, channel, cmd, Array.Empty(), presetId); - bool flag = ret == YuShiOriSDK.TRUE; - if (!flag) BuildException(); - return flag; + int retNum = YuShiOriSDK.NETDEV_PTZPreset_Other(LoginId, Channel, cmd, Array.Empty(), presetId); + bool ret = retNum == YuShiOriSDK.TRUE; + if (!ret) BuildException(); + return ret; } #endregion Ptz Method @@ -112,7 +110,7 @@ public class YuShiSDK : ICameraSDK YuShiOriSDK.NETDEV_PREVIEWINFO_S stPreviewInfo = new() { hPlayWnd = hwnd, - dwChannelID = 1, + dwChannelID = Channel, dwStreamType = 0, // YuShiOriSDK.NETDEV_LIVE_STREAM_INDEX_E dwLinkMode = 1, // YuShiOriSDK.NETDEV_PROTOCAL_E dwFluency = 0, // YuShiOriSDK.NETDEV_PICTURE_FLUENCY_E @@ -124,9 +122,9 @@ public class YuShiSDK : ICameraSDK public override void StopPlay() { if (!IsPlaying()) return; - int flag = YuShiOriSDK.NETDEV_StopRealPlay(RealplayHandle); + int ret = YuShiOriSDK.NETDEV_StopRealPlay(RealplayHandle); RealplayHandle = IntPtr.Zero; - if (flag == YuShiOriSDK.FALSE) BuildException(); + if (ret == YuShiOriSDK.FALSE) BuildException(); } public override bool IsPlaying() diff --git a/EC.Util/Common/NetworkUtil.cs b/EC.Util/Common/NetworkUtil.cs new file mode 100644 index 0000000..b0caad0 --- /dev/null +++ b/EC.Util/Common/NetworkUtil.cs @@ -0,0 +1,36 @@ +using System.Net.Sockets; + +namespace EC.Util.Common; + +public static class NetworkUtil +{ + public static string LocalAddr(this TcpClient client) + { + return client.Client.LocalEndPoint?.ToString() ?? ":"; + } + + public static string LocalIp(this TcpClient client) + { + return LocalAddr(client).Split(':')[0]; + } + + public static string LocalPort(this TcpClient client) + { + return LocalAddr(client).Split(':')[1]; + } + + public static string ClientAddr(this TcpClient client) + { + return client.Client.RemoteEndPoint?.ToString() ?? ":"; + } + + public static string ClientIp(this TcpClient client) + { + return ClientAddr(client).Split(':')[0]; + } + + public static string ClientPort(this TcpClient client) + { + return ClientAddr(client).Split(':')[1]; + } +} \ No newline at end of file diff --git a/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs b/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs index 5f2af5f..c14e9e0 100644 --- a/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs +++ b/JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs @@ -49,7 +49,7 @@ public class UdpManager Server.DatagramReceived += Server_DatagramReceived; Server.Start(); - PtzCheckTimer.Interval = 1000;//1s + PtzCheckTimer.Interval = 3000;//3s PtzCheckTimer.Elapsed += PTZCheckTimer_Elapsed; PtzCheckTimer.Enabled = true; @@ -92,7 +92,7 @@ public class UdpManager foreach (var key in DeviceDict.Keys) { UdpAlarmHost device = DeviceDict[key]; - if (device.KeepLive >= 0) device.KeepLive--; + if (device.KeepLive > 0) device.KeepLive--; else ProcessDeviceStateEvent(ref device, 0, device.DefenceState); } } @@ -101,9 +101,10 @@ public class UdpManager { IPEndPoint ipep = e.Ipep; //解码 + //byte[] msg = e.Datagram; byte[] msg = AlarmEncode.DecodeMessage(e.Datagram); bool vaild = msg.Length >= 8 && msg[2] == AlarmEncode.Head[0] && msg[3] == AlarmEncode.Head[1]; - Console.WriteLine("Recv from {0}:{1} => {2}, {3}", ipep.Address.ToString(), ipep.Port, DataMessage.ToHexString(msg), vaild); + Console.WriteLine("Recv from {0}:{1} => {2}, {3}, {4}", ipep.Address.ToString(), ipep.Port, DataMessage.ToHexString(e.Datagram), DataMessage.ToHexString(msg), vaild); if (!vaild) return; //解析 DeviceCmd deviceCmd = (DeviceCmd)msg[4]; @@ -161,6 +162,8 @@ public class UdpManager AddDevice(deviceId, ref device); } byte defenceState = msg[17]; + //在线状态 + device.KeepLive = Config.DeviceHeartKeep; ProcessDeviceStateEvent(ref device, 1, defenceState); device.WorkState = msg[18]; //设备状态1 @@ -185,8 +188,6 @@ public class UdpManager device.DevideType = msg[23]; device.SignalIntensity = msg[24]; device.SectorTotal = msg[25]; - //在线状态 - device.KeepLive = Config.DeviceHeartKeep; } private void AnalysisAlarmMessage(IPEndPoint ipep, byte[] msg) @@ -313,8 +314,16 @@ public class UdpManager bool reportFlag = false; if (device.OnlineState != onlineState) { - reportFlag = true; - device.OnlineState = onlineState; + if (onlineState == 0 && device.KeepLive < 0) + { + reportFlag = true; + device.OnlineState = onlineState; + } + else if (onlineState == 1 && device.KeepLive >= 0) + { + reportFlag = true; + device.OnlineState = onlineState; + } } if (device.DefenceState != defenceState) { @@ -361,8 +370,52 @@ public class UdpManager { if (!IsRunning()) return false; byte[] bytes = new byte[] { 0x08, 0x12, 0xF0, 0xFA, 0x8F, 0x06, 0x6B, 0x0D }; - //byte[] bytes = AlarmEncode.GetSendMessage(0x8F, Array.Empty()); + ////byte[] bytes = AlarmEncode.GetSendMessage(0x8F, Array.Empty()); return Server.SendMessage(ipep.Address.ToString(), ipep.Port, AlarmEncode.EncodeMessage(bytes)); + //Console.WriteLine(); + //byte[] bytes = new byte[] { + // 0x24, 0x12, 0xF0, 0xFA, + // 0x02, + // 0x77, 0x35, 0x94, 0x01, + // 0x07, 0x5B, 0xCD, 0x15, + // 0x00, 0x01, 0xE2, 0x40, + // 0x23, 0x05, 0x18, 0x17, 0x12, 0x34, + // 0x01, 0x00, 0x00, 0x01, + // 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + // 0x0F, 0x41, 0x0D }; + //Console.WriteLine(DataMessage.ToHexString(AlarmEncode.EncodeMessage(bytes))); bytes = new byte[] { + // 0x24, 0x12, 0xF0, 0xFA, + // 0x02, + // 0x77, 0x35, 0x94, 0x01, + // 0x07, 0x5B, 0xCD, 0x15, + // 0x00, 0x01, 0xE2, 0x40, + // 0x23, 0x05, 0x18, 0x17, 0x12, 0x34, + // 0x01, 0x00, 0x00, 0x02, + // 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + // 0x3C, 0x05, 0x0D }; + //Console.WriteLine(DataMessage.ToHexString(AlarmEncode.EncodeMessage(bytes))); bytes = new byte[] { + // 0x24, 0x12, 0xF0, 0xFA, + // 0x02, + // 0x77, 0x35, 0x94, 0x01, + // 0x07, 0x5B, 0xCD, 0x15, + // 0x00, 0x01, 0xE2, 0x40, + // 0x23, 0x05, 0x18, 0x17, 0x12, 0x34, + // 0x01, 0x00, 0x00, 0x01, + // 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + // 0x0E, 0x35, 0x0D }; + //Console.WriteLine(DataMessage.ToHexString(AlarmEncode.EncodeMessage(bytes))); bytes = new byte[] { + // 0x24, 0x12, 0xF0, 0xFA, + // 0x02, + // 0x77, 0x35, 0x94, 0x01, + // 0x07, 0x5B, 0xCD, 0x15, + // 0x00, 0x01, 0xE2, 0x40, + // 0x23, 0x05, 0x18, 0x17, 0x12, 0x34, + // 0x01, 0x00, 0x00, 0x02, + // 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + // 0x3C, 0xC9, 0x0D }; + //Console.WriteLine(DataMessage.ToHexString(AlarmEncode.EncodeMessage(bytes))); + //Server.SendMessage(ipep.Address.ToString(), ipep.Port, AlarmEncode.EncodeMessage(bytes)); + //return true; } /// diff --git a/JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs b/JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs index 24a2e0b..2793054 100644 --- a/JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs +++ b/JiLinApp.Docking/FenceAlarm/Service/UdpServer.cs @@ -118,7 +118,7 @@ public class UdpServer IPEndPoint ipep = new(IPAddress.Parse(ip), port); int result = SendUdp.Send(msg, msg.Length, ipep); bool flag = result == msg.Length; - Console.WriteLine("Send to {0}:{1} => {2}, {3}", ip, port, DataMessage.ToHexString(AlarmEncode.DecodeMessage(msg)), flag); + Console.WriteLine("Send to {0}:{1} => {2}, {3}, {4}", ip, port, DataMessage.ToHexString(msg), DataMessage.ToHexString(AlarmEncode.DecodeMessage(msg)), flag); return flag; } diff --git a/JiLinApp.Docking/Military/Config.cs b/JiLinApp.Docking/Military/Config.cs index 388452e..ef30ee5 100644 --- a/JiLinApp.Docking/Military/Config.cs +++ b/JiLinApp.Docking/Military/Config.cs @@ -10,7 +10,7 @@ public class MilitaryConfig public string Password { get; set; } - public int RequestRetryTime { get; set; } + public int RequestTryTime { get; set; } - public int RequestRetryInterval { get; set; } + public int RequestTryInterval { get; set; } } \ No newline at end of file diff --git a/JiLinApp.Docking/Military/MilitaryService.cs b/JiLinApp.Docking/Military/MilitaryService.cs index e00f656..1315cea 100644 --- a/JiLinApp.Docking/Military/MilitaryService.cs +++ b/JiLinApp.Docking/Military/MilitaryService.cs @@ -46,13 +46,13 @@ public class MilitaryService password = Config.Password, }; JObject response = new(); - for (int i = 0; i < Config.RequestRetryTime; i++) + for (int i = 0; i < Config.RequestTryTime; i++) { response = WithToken(url).PostJsonAsync(data).ReceiveJson().Result; bool success = response["success"].ToBoolean(); if (!success) { - Thread.Sleep(Config.RequestRetryInterval); + Thread.Sleep(Config.RequestTryInterval); continue; } string? token = response["result"]?["token"]?.ToString(); @@ -66,13 +66,13 @@ public class MilitaryService { string url = $"{GetUrl()}/camera/setting/list"; JObject response = new(); - for (int i = 0; i < Config.RequestRetryTime; i++) + for (int i = 0; i < Config.RequestTryTime; i++) { response = WithToken(url).GetAsync().ReceiveJson().Result; bool success = response["success"].ToBoolean(); if (!success) { - Thread.Sleep(Config.RequestRetryInterval); + Thread.Sleep(Config.RequestTryInterval); continue; } JToken records = response?["result"]?["records"] ?? new JObject(); @@ -89,9 +89,11 @@ public class MilitaryService string ip = item?["ip"]?.ToString() ?? string.Empty; string username = item?["user"]?.ToString() ?? string.Empty; string password = item?["password"]?.ToString() ?? string.Empty; + string name = $"{item?["siteName"]?.ToString()}-{item?["cameraName"]?.ToString()}-{ip}"; if (VerifyUtil.IsEmpty(id) || !VerifyUtil.IsIp(ip) || VerifyUtil.IsEmpty(username) || VerifyUtil.IsEmpty(password)) continue; CameraInfo info = CameraInfo.New(manufactor, ip, username, password); info.Id = id; + info.Name = name; list.Add(info); } return list; @@ -104,13 +106,13 @@ public class MilitaryService { string url = $"{GetUrl()}/msFencesInfo/list"; JObject response = new(); - for (int i = 0; i < Config.RequestRetryTime; i++) + for (int i = 0; i < Config.RequestTryTime; i++) { response = WithToken(url).GetAsync().ReceiveJson().Result; bool success = response["success"].ToBoolean(); if (!success) { - Thread.Sleep(Config.RequestRetryInterval); + Thread.Sleep(Config.RequestTryInterval); continue; } return new List(); @@ -123,13 +125,13 @@ public class MilitaryService { string url = $"{GetUrl()}/military/MsCameraLinkage/list"; JObject response = new(); - for (int i = 0; i < Config.RequestRetryTime; i++) + for (int i = 0; i < Config.RequestTryTime; i++) { response = WithToken(url).GetAsync().ReceiveJson().Result; bool success = response["success"].ToBoolean(); if (!success) { - Thread.Sleep(Config.RequestRetryInterval); + Thread.Sleep(Config.RequestTryInterval); continue; } JToken records = response?["result"]?["records"] ?? new JObject(); diff --git a/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs index 85df307..67dd1d9 100644 --- a/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs +++ b/JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs @@ -1,4 +1,5 @@ -using System.Collections.Concurrent; +using EC.Util.Common; +using System.Collections.Concurrent; using System.Net.Sockets; namespace JiLinApp.Docking.VibrateAlarm; @@ -11,57 +12,85 @@ public class ClientMessage public TcpAlarmHost Host { get; set; } - public string Ip + public int OnlineState { get; set; }//设备在线状态 + + public bool IsOnline { get { - if (Host != null) return Host.Ip; - //if (Client != null) return Client.Client.RemoteEndPoint.ToString().Split(':')[0]; - return ""; + return Host != null && Host.Id >= 0 && OnlineState == 1; } } - public string Port + public ConcurrentDictionary SensorDict { get; } = new(); + + public int SensorTotal { get { - if (Host != null) return Host.Port; - //if (Client != null) return Client.Client.RemoteEndPoint.ToString().Split(':')[1]; - return "-1"; + return SensorDict.Count; } } - public int OnlineState { get; set; }//设备在线状态 + public bool SensorsEmpty + { + get + { + return SensorDict == null || SensorDict.IsEmpty; + } + } - public bool IsOnline + public List DataList { get; } = new(); + + public string ClientAddr { get { - return Host != null && Host.Id >= 0 && OnlineState == 1; + return Client.ClientAddr(); } } - public int SensorTotal + public string ClientIp { get { - return SensorDict.Count; + if (Host != null) return Host.Ip; + return Client.ClientIp(); } } - public ConcurrentDictionary SensorDict { get; } = new(); + public string ClientPort + { + get + { + if (Host != null) return Host.Port; + return Client.ClientPort(); + } + } - public bool SensorsEmpty + public string LocalAddr { get { - return SensorDict == null || SensorDict.IsEmpty; + return Client.LocalAddr(); } } - public ReaderWriterLockSlim SensorsLock { get; } = new(); + public string LocalIp + { + get + { + return Client.LocalIp(); + } + } - public List DataList { get; } = new(); + public string LocalPort + { + get + { + return Client.LocalPort(); + } + } #endregion Fields diff --git a/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs index 09391a1..540808a 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs @@ -1,4 +1,5 @@ -using System.Collections.Concurrent; +using EC.Util.Common; +using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Text; @@ -114,7 +115,7 @@ public class AsyncTcpServer : IDisposable { foreach (var client in Clients.Values) { - client.TcpClient.Client.Disconnect(false); + client.Client.Client.Disconnect(false); } Clients.Clear(); } @@ -149,15 +150,18 @@ public class AsyncTcpServer : IDisposable /// public event EventHandler>? DatagramReceived; - private void RaiseClientConnected(string clientKey, TcpClientState clientState) + private void RaiseClientConnected(string clientAddr, TcpClientState clientState) { - Clients.AddOrUpdate(clientKey, clientState, (n, o) => { return clientState; }); - ClientConnected?.Invoke(this, new TcpClientConnectedEventArgs(clientState.TcpClient)); + if (string.IsNullOrEmpty(clientAddr) || clientAddr.Equals(":")) return; + Clients.AddOrUpdate(clientAddr, clientState, (n, o) => { return clientState; }); + ClientConnected?.Invoke(this, new TcpClientConnectedEventArgs(clientState.Client)); } - private void RaiseClientDisconnected(string clientKey, TcpClient client) + private void RaiseClientDisconnected(string clientAddr, TcpClient client) { - if (Clients.TryRemove(clientKey, out _)) + if (string.IsNullOrEmpty(clientAddr) || clientAddr.Equals(":")) return; + client.Client.Disconnect(false); + if (Clients.TryRemove(clientAddr, out _)) { ClientDisconnected?.Invoke(this, new TcpClientDisconnectedEventArgs(client)); } @@ -180,89 +184,97 @@ public class AsyncTcpServer : IDisposable private void HandleTcpClientAccepted(IAsyncResult ar) { if (!IsRunning()) return; - TcpListener? listener; + if (ar.AsyncState is not TcpListener listener) return; + TcpClient? client; try { - listener = ar.AsyncState as TcpListener; - client = listener?.EndAcceptTcpClient(ar); + client = listener.EndAcceptTcpClient(ar); + if (client == null || !client.Connected) + { + client?.Client.Disconnect(false); + return; + } } catch (Exception) { return; } - if (listener == null || client == null || !client.Connected) return; + // add client connection to cache + string clientAddr = client.ClientAddr(); byte[] buffer = new byte[client.ReceiveBufferSize]; TcpClientState clientState = new(client, buffer); - - // add client connection to cache - string clientKey = client.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey == "") return; - RaiseClientConnected(clientKey, clientState); + RaiseClientConnected(clientAddr, clientState); // begin to read data - try - { - NetworkStream networkStream = clientState.NetworkStream; - ReadBuffer(clientState, networkStream); - } - catch (Exception) - { - RaiseClientDisconnected(clientKey, clientState.TcpClient); - return; - } + ReadBuffer(clientState); // keep listening to accept next connection AcceptTcpClient(listener); } - private void ReadBuffer(TcpClientState clientState, NetworkStream networkStream) + private void ReadBuffer(TcpClientState clientState) { - networkStream.BeginRead(clientState.Buffer, 0, clientState.Buffer.Length, HandleDatagramReceived, clientState); + try + { + NetworkStream stream = clientState.GetStream; + if (clientState.IsRead) return; + lock (clientState.IsReadLock) + { + if (clientState.IsRead) return; + clientState.IsRead = true; + stream.BeginRead(clientState.Buffer, 0, clientState.Buffer.Length, HandleDatagramReceived, clientState); + } + } + catch (IOException e) + { + LogUnit.Error(e); + return; + } + catch (Exception e) + { + LogUnit.Error(e); + string clientAddr = clientState.Client.ClientAddr(); + RaiseClientDisconnected(clientAddr, clientState.Client); + } } private void HandleDatagramReceived(IAsyncResult ar) { if (!IsRunning()) return; - TcpClientState? internalClient = ar.AsyncState as TcpClientState; - if (internalClient == null) return; - string clientKey = internalClient.TcpClient.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey == "") return; - if (!internalClient.TcpClient.Connected) - { - // connection has been closed - RaiseClientDisconnected(clientKey, internalClient.TcpClient); - } + if (ar.AsyncState is not TcpClientState clientState) return; - NetworkStream networkStream; - int readBytesNum; + int readNum; + string clientAddr = clientState.Client.ClientAddr(); try { - networkStream = internalClient.NetworkStream; - // if the remote host has shutdown its connection, - // read will immediately return with zero bytes. - readBytesNum = networkStream.EndRead(ar); + NetworkStream networkStream = clientState.GetStream; + // if the remote host has shutdown its connection, read will immediately return with zero bytes. + readNum = networkStream.EndRead(ar); + if (readNum == 0) + { + RaiseClientDisconnected(clientAddr, clientState.Client); + return; + } } catch (Exception) { - RaiseClientDisconnected(clientKey, internalClient.TcpClient); - return; - } - if (readBytesNum == 0) - { - // connection has been closed - RaiseClientDisconnected(clientKey, internalClient.TcpClient); + RaiseClientDisconnected(clientAddr, clientState.Client); return; } // received byte and trigger event notification - byte[] receivedBytes = new byte[readBytesNum]; - Buffer.BlockCopy(internalClient.Buffer, 0, receivedBytes, 0, readBytesNum); - RaiseDatagramReceived(internalClient, receivedBytes); + byte[] receivedBytes = new byte[readNum]; + Buffer.BlockCopy(clientState.Buffer, 0, receivedBytes, 0, readNum); + RaiseDatagramReceived(clientState, receivedBytes); + lock (clientState.IsReadLock) + { + clientState.IsRead = false; + } // continue listening for tcp datagram packets - ReadBuffer(internalClient, networkStream); + ReadBuffer(clientState); } #endregion Receive @@ -277,20 +289,16 @@ public class AsyncTcpServer : IDisposable public void Send(TcpClient client, byte[] datagram) { if (!IsRunning()) return; - if (client == null || !client.Connected || datagram == null) return; + if (client == null || datagram == null) return; try { NetworkStream stream = client.GetStream(); - if (stream.CanWrite) - { - stream.Write(datagram, 0, datagram.Length); - } + stream.Write(datagram, 0, datagram.Length); } catch (Exception) { - string clientKey = client.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey == "") return; - if (client != null) RaiseClientDisconnected(clientKey, client); + string clientAddr = client.ClientAddr(); + RaiseClientDisconnected(clientAddr, client); } } @@ -313,7 +321,7 @@ public class AsyncTcpServer : IDisposable if (!IsRunning()) return; foreach (var client in Clients.Values) { - Send(client.TcpClient, datagram); + Send(client.Client, datagram); } } @@ -335,18 +343,17 @@ public class AsyncTcpServer : IDisposable public bool SendAsync(TcpClient client, byte[] datagram) { if (!IsRunning()) return false; - if (client == null || !client.Connected || datagram == null) return false; + if (client == null || datagram == null) return false; try { NetworkStream stream = client.GetStream(); - if (!stream.CanWrite) return false; IAsyncResult result = stream.BeginWrite(datagram, 0, datagram.Length, HandleDatagramWritten, client); return result.IsCompleted; } catch (Exception) { - string clientKey = client.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey != "" && client != null) RaiseClientDisconnected(clientKey, client); + string clientAddr = client.ClientAddr(); + RaiseClientDisconnected(clientAddr, client); } return false; } @@ -356,9 +363,9 @@ public class AsyncTcpServer : IDisposable /// /// 客户端 /// 报文 - public void SendAsync(TcpClient client, string datagram) + public bool SendAsync(TcpClient client, string datagram) { - SendAsync(client, Encoding.GetBytes(datagram)); + return SendAsync(client, Encoding.GetBytes(datagram)); } /// @@ -370,7 +377,7 @@ public class AsyncTcpServer : IDisposable if (!IsRunning()) return; foreach (var client in Clients.Values) { - SendAsync(client.TcpClient, datagram); + SendAsync(client.Client, datagram); } } @@ -386,17 +393,15 @@ public class AsyncTcpServer : IDisposable private void HandleDatagramWritten(IAsyncResult ar) { - TcpClient? client = null; + if (ar.AsyncState is not TcpClient client) return; try { - client = ar.AsyncState as TcpClient; - client?.GetStream().EndWrite(ar); + client.GetStream().EndWrite(ar); } catch (Exception) { - string clientKey = client?.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey == "") return; - if (client != null) RaiseClientDisconnected(clientKey, client); + string clientAddr = client.ClientAddr(); + RaiseClientDisconnected(clientAddr, client); } } diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs index b9b5fe7..f96d572 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs @@ -7,22 +7,21 @@ public class TcpClientState /// /// Constructor for a new Client /// - /// The TCP client + /// The TCP client /// The byte array buffer - public TcpClientState(TcpClient tcpClient, byte[] buffer) + public TcpClientState(TcpClient client, byte[] buffer) { - if (tcpClient == null) throw new ArgumentNullException("tcpClient"); + if (client == null) throw new ArgumentNullException("tcpClient"); if (buffer == null) throw new ArgumentNullException("buffer"); - - TcpClient = tcpClient; + Client = client; Buffer = buffer; - temp = string.Empty; + Temp = string.Empty; } /// /// Gets the TCP Client /// - public TcpClient TcpClient { get; private set; } + public TcpClient Client { get; private set; } /// /// Gets the Buffer. @@ -32,16 +31,23 @@ public class TcpClientState /// /// TCP接收到但未处理的数据 /// - public string temp { get; set; } + public string Temp { get; set; } /// /// Gets the network stream /// - public NetworkStream NetworkStream + public NetworkStream GetStream { get { - return TcpClient.GetStream(); + NetworkStream stream = Client.GetStream(); + stream.ReadTimeout = 5000; + stream.WriteTimeout = 5000; + return stream; } } + + public bool IsRead { get; set; } + + public object IsReadLock { get; } = new(); } \ No newline at end of file diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs index ec1edf1..c2b55a8 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs @@ -9,7 +9,7 @@ public class TcpDatagramReceivedEventArgs : EventArgs /// /// 客户端 /// - public TcpClientState TcpClient { get; private set; } + public TcpClientState ClientState { get; private set; } /// /// 报文 @@ -23,7 +23,7 @@ public class TcpDatagramReceivedEventArgs : EventArgs /// 报文 public TcpDatagramReceivedEventArgs(TcpClientState tcpClient, T datagram) { - TcpClient = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient)); + ClientState = tcpClient ?? throw new ArgumentNullException(nameof(tcpClient)); Datagram = datagram; } } \ No newline at end of file diff --git a/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs index d908225..0d1209c 100644 --- a/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs +++ b/JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs @@ -1,4 +1,5 @@ -using System.Collections.Concurrent; +using EC.Util.Common; +using System.Collections.Concurrent; using System.Net; using System.Timers; using Timer = System.Timers.Timer; @@ -97,11 +98,11 @@ public class TcpManager private void Server_ClientConnected(object? sender, TcpClientConnectedEventArgs e) { - string clientKey = e.TcpClient.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey == "") return; - string clientIp = clientKey.Split(':')[0]; - string clientPort = clientKey.Split(':')[1]; - Console.WriteLine("上线:{0}", clientIp); + string clientAddr = e.TcpClient.ClientAddr(); + if (clientAddr == ":") return; + string clientIp = clientAddr.Split(':')[0]; + string clientPort = clientAddr.Split(':')[1]; + Console.WriteLine("主机上线:{0}", clientIp); if (!TryGetDevice(clientIp, out ClientMessage clientMsg)) { clientMsg = new() @@ -119,11 +120,11 @@ public class TcpManager private void Server_ClientDisconnected(object? sender, TcpClientDisconnectedEventArgs e) { - string clientKey = e.TcpClient.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey == "") return; - string clientIp = clientKey.Split(':')[0]; - string clientPort = clientKey.Split(':')[1]; - Console.WriteLine("下线:{0}", clientIp); + string clientAddr = e.TcpClient.ClientAddr(); + if (clientAddr == ":") return; + string clientIp = clientAddr.Split(':')[0]; + string clientPort = clientAddr.Split(':')[1]; + Console.WriteLine("主机下线:{0}", clientIp); if (TryGetDevice(clientIp, out ClientMessage clientMsg)) { ProcessDeviceStateEvent(ref clientMsg, 0); @@ -132,12 +133,16 @@ public class TcpManager private void Server_DatagramReceived(object? sender, TcpDatagramReceivedEventArgs e) { - string clientKey = e.TcpClient.TcpClient.Client.RemoteEndPoint?.ToString() ?? ""; - if (clientKey == "") return; - string clientIp = clientKey.Split(':')[0]; + string clientAddr = e.ClientState.Client.ClientAddr(); + if (clientAddr == ":") return; + string clientIp = clientAddr.Split(':')[0]; + string clientPort = clientAddr.Split(':')[1]; if (TryGetDevice(clientIp, out ClientMessage clientMsg)) { + if (clientMsg.Client == null || !clientMsg.Client.Connected) clientMsg.Client = e.ClientState.Client; + clientMsg.Host ??= new() { Id = -1, Ip = clientIp, Port = clientPort }; clientMsg.AddData(e.Datagram); + ProcessDeviceStateEvent(ref clientMsg, 1); AnalysisClientMessage(ref clientMsg); } } @@ -148,96 +153,105 @@ public class TcpManager private void AnalysisClientMessage(ref ClientMessage clientMsg) { - List msglist = clientMsg.GetMessageList(); - if (msglist == null || msglist.Count == 0) return; - for (int i = 0; i < msglist.Count; i++) + List msgList = clientMsg.GetMessageList(); + foreach (byte[] msg in msgList) { - byte[] msg = msglist[i]; bool vaild = msg.Length >= 19 && msg[0] == 0xAA && msg[1] == 0xAA; - Console.WriteLine("Recv from {0}:{1} => {2}, {3}", clientMsg.Ip, clientMsg.Port, DataMessage.ToHexString(msg), vaild); + Console.WriteLine("Recv from {0}:{1} => {2}, vaild:{3}", clientMsg.ClientIp, clientMsg.ClientPort, DataMessage.ToHexString(msg), vaild); if (!vaild) continue; DataMessage mm = new(); - mm.Decode(msglist[i]); + mm.Decode(msg); + if (clientMsg.Host.Id != mm.DeviceId) clientMsg.Host.Id = mm.DeviceId; switch (mm.FunctionNum) { case 0x00: - Console.WriteLine("主机登录:{0}", clientMsg.Ip); - if (clientMsg.Host == null || clientMsg.Host.Id != mm.DeviceId) - { - clientMsg.Host = new() { Id = mm.DeviceId, Ip = mm.SendIp, Port = mm.SendPort.ToString() }; - UpdateDevice(clientMsg.Ip, clientMsg.Host); - } - ProcessDeviceStateEvent(ref clientMsg, 1); + Console.WriteLine("主机登录:{0}", clientMsg.ClientAddr); ResponseHostLogin_10(clientMsg, mm); - ClientMessage taskClientMsg = clientMsg; - if (taskClientMsg.SensorsEmpty && taskClientMsg.SensorsLock.TryEnterWriteLock(1000)) - { - Task.Run(() => - { - while (taskClientMsg.SensorsEmpty) - { - RequestSensorList_07(taskClientMsg); - Thread.Sleep(1000); - } - taskClientMsg.SensorsLock.ExitWriteLock(); - }); - } + RequestHostAutoUploadState_24(clientMsg); + RequestSensorList_07(clientMsg); break; case 0x01: - Console.WriteLine("心跳:{0}", clientMsg.Ip); - if (clientMsg.Host == null || clientMsg.Host.Id != mm.DeviceId) - { - clientMsg.Host = new() { Id = mm.DeviceId, Ip = mm.SendIp, Port = mm.SendPort.ToString() }; - UpdateDevice(clientMsg.Ip, clientMsg.Host); - } - ProcessDeviceStateEvent(ref clientMsg, 1); + Console.WriteLine("主机心跳:{0}", clientMsg.ClientAddr); break; case 0x12: - Console.WriteLine("传感器地址设置响应:{0}", clientMsg.Ip); - SetDataRequest(mm, 0x02); + Console.WriteLine("传感器地址设置响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x02); break; case 0x13: - Console.WriteLine("传感器模式设置响应:{0}", clientMsg.Ip); - SetDataRequest(mm, 0x03); + Console.WriteLine("传感器模式设置响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x03); break; case 0x14: - Console.WriteLine("传感器轮询状态响应:{0}", clientMsg.Ip); + Console.WriteLine("传感器轮询状态响应:{0}", clientMsg.ClientAddr); int sensorAddr = mm.Data[0] + mm.Data[1] * 256; int state = mm.Data[2] + mm.Data[3] * 256; - int offline = state % 2; - int alarm = state / 2 % 2; - ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, offline, alarm); - SetDataRequest(mm, 0x04); + ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, state); + + SetDataResponse(mm, 0x04); break; case 0x15: - Console.WriteLine("传感器复位响应:{0}", clientMsg.Ip); - SetDataRequest(mm, 0x05); + Console.WriteLine("传感器复位响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x05); break; case 0x17: - Console.WriteLine("返回传感器列表:{0}", clientMsg.Ip); - if (clientMsg.SensorsEmpty) + Console.WriteLine("主机返回传感器列表:{0}", clientMsg.ClientAddr); + for (int j = 2; j < mm.Data.Length; j++) { - for (int j = 2; j < mm.Data.Length; j++) - { - sensorAddr = Convert.ToByte((mm.Data[j] + mm.Data[++j] * 256)); - SensorState sensor = new(mm.DeviceId, sensorAddr, 0, 0); - clientMsg.SensorDict[sensorAddr] = sensor; - } - RequestSensorsStateActively_08(clientMsg); + sensorAddr = Convert.ToByte((mm.Data[j] + mm.Data[++j] * 256)); + if (clientMsg.SensorDict.ContainsKey(sensorAddr)) continue; + SensorState sensor = new(mm.DeviceId, sensorAddr, 0, 0); + clientMsg.SensorDict[sensorAddr] = sensor; } - SetDataRequest(mm, 0x07); + RequestSensorsState_04(clientMsg); + + SetDataResponse(mm, 0x07); break; case 0x18: - Console.WriteLine("传感器主动状态响应:{0}", clientMsg.Ip); + Console.WriteLine("传感器主动状态响应:{0}", clientMsg.ClientAddr); + sensorAddr = mm.Data[0] + mm.Data[1] * 256; + state = mm.Data[2] + mm.Data[3] * 256; + ProcessSensorStateEvent(ref clientMsg, mm, sensorAddr, state); + ResponseHostUploadState_08(clientMsg, mm); + break; + + case 0x19: + Console.WriteLine("传感器关闭响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x09); + break; + + case 0x30: + Console.WriteLine("传感器启动响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x20); + break; - SetDataRequest(mm, 0x08); + case 0x31: + Console.WriteLine("传感器全部启动响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x21); + break; + + case 0x34: + Console.WriteLine("主机启动自动上传响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x24); + break; + + case 0x35: + Console.WriteLine("主机关闭自动上传响应:{0}", clientMsg.ClientAddr); + + SetDataResponse(mm, 0x25); break; } } @@ -252,8 +266,10 @@ public class TcpManager } } - private void ProcessSensorStateEvent(ref ClientMessage client, DataMessage mm, int sensorAddr, int offline, int alarm) + private void ProcessSensorStateEvent(ref ClientMessage client, DataMessage mm, int sensorAddr, int state) { + int offline = state % 2; + int alarm = state / 2 % 2; if (!client.SensorDict.TryGetValue(sensorAddr, out SensorState? sensor)) { sensor = new(mm.DeviceId, sensorAddr, offline, alarm); @@ -269,7 +285,7 @@ public class TcpManager if (alarm == 1) { ReportAlarm(sensor.DeviceId, sensorAddr); - //RequestSensorReset_05(clientMsg, sensorAddr); + RequestSensorReset_05(client, sensorAddr); } } @@ -299,41 +315,24 @@ public class TcpManager #region Send - public bool SendMessage(string ip, byte[] bytes) - { - if (Server == null || !Server.IsRunning()) return false; - if (!TryGetDevice(ip, out ClientMessage clientMsg)) return false; - string cmd = DataMessage.ToHexString(bytes); - DataMessage mm = new(); - mm.Decode(bytes); - bool flag = Server.SendAsync(clientMsg.Client, bytes); - Console.WriteLine("Send to {0}:{1} => {2}, {3}", ip, clientMsg.Port, cmd, flag); - return flag; - } - - public bool SendRequest(ref DataRequest request) - { - if (request.Request == null) return false; - request.Request.FrameNum = FrameNumber; - FrameNumber++; - bool send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); - return send; - } - - public bool SendNoRequest(DataMessage msg) - { - msg.FrameNum = FrameNumber; - FrameNumber++; - bool send = SendMessage(msg.ReceiveIp, msg.Encode()); - return send; - } - - public bool SendResponse(DataMessage msg) + /// + /// 0x10:主机响应0x00登录 + /// + /// + /// + /// + public bool ResponseHostLogin_10(ClientMessage client, DataMessage mm) { - bool send = SendMessage(msg.ReceiveIp, msg.Encode()); - return send; + if (!client.IsOnline) return false; + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x10, 0); + return SendResponse(msg, mm.FrameNum); } + /// + /// 0x01:心跳 + /// + /// + /// public bool SendHostHeart_01(ClientMessage client) { if (!client.IsOnline) return false; @@ -342,6 +341,12 @@ public class TcpManager return SendNoRequest(msg); } + /// + /// 0x02:设置传感器地址 + /// + /// + /// + /// public bool RequestSensorChange_02(ClientMessage client, int newSensorAddr) { if (!client.IsOnline) return false; @@ -351,9 +356,15 @@ public class TcpManager { Request = msg }; - return SendRequest(ref request); + return SendRequestTry(ref request); } + /// + /// 0x04:请求传感器状态 + /// + /// + /// + /// public bool RequestSensorState_04(ClientMessage client, int sensorAddr) { if (!client.IsOnline) return false; @@ -364,13 +375,17 @@ public class TcpManager { Request = msg }; - return SendRequest(ref request); + return SendRequestTry(ref request); } + /// + /// 0x04:请求传感器状态 + /// + /// + /// public bool RequestSensorsState_04(ClientMessage client) { if (!client.IsOnline) return false; - if (client.SensorsEmpty) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x04, 2); foreach (var item in client.SensorDict.Values) { @@ -380,11 +395,17 @@ public class TcpManager { Request = msg }; - SendRequest(ref request); + SendRequestTry(ref request); } return true; } + /// + /// 0x05:复位传感器 + /// + /// + /// + /// public bool RequestSensorReset_05(ClientMessage client, int sensorAddr) { if (!client.IsOnline) return false; @@ -395,9 +416,14 @@ public class TcpManager { Request = msg }; - return SendRequest(ref request); + return SendRequestTry(ref request); } + /// + /// 0x07:请求传感器列表 + /// + /// + /// public bool RequestSensorList_07(ClientMessage client) { if (!client.IsOnline) return false; @@ -406,27 +432,50 @@ public class TcpManager { Request = msg }; - return SendRequest(ref request); + return SendRequestMust(ref request); } - public bool RequestSensorStateActively_08(ClientMessage client, int sensorAddr) + /// + /// 0x08:主机响应0x18主动上传状态 + /// + /// + /// + /// + public bool ResponseHostUploadState_08(ClientMessage client, DataMessage mm) { if (!client.IsOnline) return false; - if (!client.SensorDict.TryGetValue(sensorAddr, out _)) return false; DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x08, 2); + msg.Data = new byte[] { mm.Data[0], mm.Data[1] }; + return SendResponse(msg, mm.FrameNum); + } + + /// + /// 0x09:关闭传感器 + /// + /// + /// + /// + public bool RequestSensorTurnOff_09(ClientMessage client, int sensorAddr) + { + if (!client.IsOnline) return false; + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x09, 2); msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; DataRequest request = new() { Request = msg }; - return SendRequest(ref request); + return SendRequestTry(ref request); } - public bool RequestSensorsStateActively_08(ClientMessage client) + /// + /// 0x09:关闭传感器 + /// + /// + /// + public bool RequestSensorsTurnOff_09(ClientMessage client) { if (!client.IsOnline) return false; - if (client.SensorsEmpty) return false; - DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x08, 2); + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x09, 2); foreach (var item in client.SensorDict.Values) { int sensorAddr = item.Addr; @@ -435,42 +484,38 @@ public class TcpManager { Request = msg }; - SendRequest(ref request); + SendRequestTry(ref request); } return true; } - public bool ResponseHostLogin_10(ClientMessage client, DataMessage mm) - { - if (!client.IsOnline) return false; - DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x10, 0); - msg.FrameNum = mm.FrameNum; - return SendResponse(msg); - } - - public bool RequestSensorTurnOff_09(ClientMessage client, int sensorAddr) + /// + /// 0x20:启动传感器 + /// + /// + /// + /// + public bool RequestSensorTurnOn_20(ClientMessage client, int sensorAddr) { if (!client.IsOnline) return false; - if (client.SensorsEmpty) return false; - DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x19, 2); - foreach (var item in client.SensorDict.Values) + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 2); + msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; + DataRequest request = new() { - int sensorAddr = item.Addr; - msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; - DataRequest request = new() - { - Request = msg - }; - SendRequest(ref request); - } - return true; + Request = msg + }; + return SendRequestTry(ref request); } - public bool RequestSensorsTurnOff_09(ClientMessage client) + /// + /// 0x20:启动传感器 + /// + /// + /// + public bool RequestSensorsTurnOn_20(ClientMessage client) { if (!client.IsOnline) return false; - if (client.SensorsEmpty) return false; - DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x19, 2); + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 2); foreach (var item in client.SensorDict.Values) { int sensorAddr = item.Addr; @@ -479,52 +524,57 @@ public class TcpManager { Request = msg }; - SendRequest(ref request); + SendRequestTry(ref request); } return true; } - public bool RequestSensorTurnOn_20(ClientMessage client, int sensorAddr) + /// + /// 0x21:启动全部传感器 + /// + /// + /// + public bool RequestSensorsTurnOn_21(ClientMessage client) { if (!client.IsOnline) return false; - if (client.SensorsEmpty) return false; - DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 2); - msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x21, 0); DataRequest request = new() { Request = msg }; - return SendRequest(ref request); + return SendRequestTry(ref request); } - public bool RequestSensorsTurnOn_20(ClientMessage client) + /// + /// 0x24:启动自动上传 + /// + /// + /// + public bool RequestHostAutoUploadState_24(ClientMessage client) { if (!client.IsOnline) return false; - if (client.SensorsEmpty) return false; - DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x20, 2); - foreach (var item in client.SensorDict.Values) + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x24, 0); + DataRequest request = new() { - int sensorAddr = item.Addr; - msg.Data = new byte[] { (byte)(sensorAddr % 256), (byte)(sensorAddr / 256) }; - DataRequest request = new() - { - Request = msg - }; - SendRequest(ref request); - } - return true; + Request = msg + }; + return SendRequestMust(ref request); } - public bool RequestSensorsTurnOn_21(ClientMessage client) + /// + /// 0x25:关闭自动上传 + /// + /// + /// + public bool RequestSensorsTurnOn_25(ClientMessage client) { if (!client.IsOnline) return false; - if (client.SensorsEmpty) return false; - DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x21, 0); + DataMessage msg = GetSendMessageHead(client.Host.Id, client, 0x25, 0); DataRequest request = new() { Request = msg }; - return SendRequest(ref request); + return SendRequestTry(ref request); } #endregion Send @@ -577,13 +627,6 @@ public class TcpManager return DeviceDict.Remove(clientIp, out _); } - private bool UpdateDevice(string clientIp, TcpAlarmHost host) - { - if (!DeviceDict.ContainsKey(clientIp)) return false; - DeviceDict[clientIp].Host = host; - return true; - } - public List GetDeviceList() { return DeviceDict.Values.ToList(); @@ -593,36 +636,129 @@ public class TcpManager #region Set - private byte FrameNumber { get; set; } = 0; + private byte Frame { get; set; } = 0; + + private byte FrameInc + { get { return (byte)(++Frame % byte.MaxValue); } } + + private int SendTryTime { get; set; } = 5; + + private int SendTryInterval { get; set; } = 200; + + private int ReqWaitTime { get; set; } = 3 * 10; - private DataMessage GetSendMessageHead(int deviceId, ClientMessage client, byte fun_num, byte datalen) + private int ReqWaitInterval { get; set; } = 100; + + private DataMessage GetSendMessageHead(int deviceId, ClientMessage client, byte funNum, byte dataLen) { DataMessage msg = new() { DeviceId = deviceId, - SendIp = client.Host.Ip, - //SendIp = client.Client.Client.LocalEndPoint.ToString().Split(':')[0], - SendPort = Server.Port, - ReceiveIp = client.Ip, - ReceivePort = int.Parse(client.Port), - FunctionNum = fun_num, - DataLen = datalen + SendIp = client.LocalIp, + SendPort = client.LocalPort.ToInt(), + ReceiveIp = client.ClientIp, + ReceivePort = client.ClientPort.ToInt(), + FunctionNum = funNum, + DataLen = dataLen }; return msg; } - public void SetDataRequest(DataMessage msg, byte functionNum) + private bool SendMessage(string ip, byte[] bytes) + { + if (Server == null || !Server.IsRunning()) return false; + if (!TryGetDevice(ip, out ClientMessage clientMsg)) return false; + string cmd = DataMessage.ToHexString(bytes); + bool send = false; + for (int i = 0; i < SendTryTime; i++) + { + send = Server.SendAsync(clientMsg.Client, bytes); + if (send) break; + Thread.Sleep(SendTryInterval); + } + Console.WriteLine("Send to {0}:{1} => {2}, send:{3}", clientMsg.ClientIp, clientMsg.ClientPort, cmd, send); + return send; + } + + private bool SendRequestTry(ref DataRequest request) { - lock (this) + if (request.Request == null) return false; + request.Request.FrameNum = FrameInc; + bool send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); + if (!send) return false; + bool respond = false; + SetDataRequest(request); + for (int i = 0; i < ReqWaitTime; i++) { - //for (int i = 0; i < Reqlist.Count; i++) - //{ - // if (Reqlist[i].Request.FunctionNum == functionNum && Reqlist[i].Request.FrameNum == msg.FrameNum) - // { - // Reqlist[i].Responce = msg; - // } - //} + respond = IsResponse(request); + if (respond) break; + Thread.Sleep(ReqWaitInterval); } + RemoveDataRequest(request); + return respond; + } + + private bool SendRequestMust(ref DataRequest request) + { + if (request.Request == null) return false; + request.Request.FrameNum = FrameInc; + bool send, respond = false; + do + { + send = SendMessage(request.Request.ReceiveIp, request.Request.Encode()); + if (!send) continue; + SetDataRequest(request); + for (int i = 0; i < ReqWaitTime; i++) + { + respond = IsResponse(request); + if (respond) break; + Thread.Sleep(ReqWaitInterval); + } + } while (!send && !respond); + RemoveDataRequest(request); + return true; + } + + private bool SendNoRequest(DataMessage request) + { + request.FrameNum = FrameInc; + bool send = SendMessage(request.ReceiveIp, request.Encode()); + return send; + } + + private bool SendResponse(DataMessage request, byte frameNum) + { + request.FrameNum = frameNum; + bool send = SendMessage(request.ReceiveIp, request.Encode()); + return send; + } + + private ConcurrentDictionary DataRequestDict { get; } = new(); + + private void SetDataRequest(DataRequest request) + { + string key = $"{request.Request.FunctionNum}-{request.Request.FrameNum}"; + DataRequestDict[key] = request; + } + + private void SetDataResponse(DataMessage msg, byte funcNum) + { + string key = $"{funcNum}-{msg.FrameNum}"; + DataRequest? item = DataRequestDict[key]; + if (item != null) item.Responce = msg; + } + + private void RemoveDataRequest(DataRequest request) + { + string key = $"{request.Request.FunctionNum}-{request.Request.FrameNum}"; + DataRequestDict.Remove(key); + } + + private bool IsResponse(DataRequest request) + { + string key = $"{request.Request.FunctionNum}-{request.Request.FrameNum}"; + DataRequest? item = DataRequestDict[key]; + return item != null && item.Responce != null; } #endregion Set diff --git a/JiLinApp/Components/CameraRealPlay.xaml.cs b/JiLinApp/Components/CameraRealPlay.xaml.cs index a851b8f..c126bbb 100644 --- a/JiLinApp/Components/CameraRealPlay.xaml.cs +++ b/JiLinApp/Components/CameraRealPlay.xaml.cs @@ -34,7 +34,7 @@ public partial class CameraRealPlay : Window private void Init() { // 初始化预置位 - for (int i = 1; i <= 8; i++) + for (int i = 1; i <= 10; i++) { PresetId.Items.Add(new ComboBoxItem { Content = i }); } @@ -80,7 +80,7 @@ public partial class CameraRealPlay : Window while (!IsPlaying()) { StartPlay(); - Thread.Sleep(100); + Thread.Sleep(200); } } diff --git a/JiLinApp/JiLinApp.csproj b/JiLinApp/JiLinApp.csproj index acf3c25..cc52e02 100644 --- a/JiLinApp/JiLinApp.csproj +++ b/JiLinApp/JiLinApp.csproj @@ -2,7 +2,7 @@ WinExe net6.0-windows - zh-Hans + zh-Hans true diff --git a/JiLinApp/Pages/FenceServerManage/Main.xaml.cs b/JiLinApp/Pages/FenceServerManage/Main.xaml.cs index f263b5b..c581f30 100644 --- a/JiLinApp/Pages/FenceServerManage/Main.xaml.cs +++ b/JiLinApp/Pages/FenceServerManage/Main.xaml.cs @@ -119,18 +119,6 @@ public partial class Main : UserControl defenceState = item.DefenceState }); } - //int[] dsArr = { 0, 1, 2, 4, 8, 9 }; - //for (int i = 1; i <= 6; i++) - //{ - // respDeviceList.Add(new - // { - // id = i, - // //groupId = item.GroupId, - // //userId = item.UserId, - // onlineState = i % 2, - // defenceState = dsArr[(i - 1) % 6] - // }); - //} AlarmService.SendDevices(DeviceType.Fence, respDeviceList); } @@ -149,16 +137,6 @@ public partial class Main : UserControl type = item.Type, }); } - //for (int i = 1; i <= 7; i++) - //{ - // respSensorList.Add(new - // { - // id = i, - // deviceId = deviceId, - // state = (i - 1) % 7, - // type = 0, - // }); - //} AlarmService.SendSensors(DeviceType.Fence, deviceId, respSensorList); } diff --git a/JiLinApp/Pages/PtzManage/Main.xaml b/JiLinApp/Pages/PtzManage/Main.xaml index 823a74c..3f2c465 100644 --- a/JiLinApp/Pages/PtzManage/Main.xaml +++ b/JiLinApp/Pages/PtzManage/Main.xaml @@ -81,6 +81,7 @@ +