Browse Source

update frame

master
fajiao 1 year ago
parent
commit
f7714971dd
  1. 1
      EC.Util/EC.Util.csproj
  2. 2
      EC.Util/Port/SerialPortParam.cs
  3. 2
      EC.Util/Zmq/ZmqUtil.cs
  4. 13
      JiLinApp.Biz/JiLinApp.Biz.csproj
  5. 33
      JiLinApp.Biz/Transmit/Entity/AlarmMessage.cs
  6. 40
      JiLinApp.Biz/Transmit/Entity/AlarmMessageHelper.cs
  7. 5
      JiLinApp.Biz/Transmit/Service/AlarmMqttService.cs
  8. 5
      JiLinApp.Biz/Transmit/Service/AlarmZmqService.cs
  9. 5
      JiLinApp.Biz/Transmit/Service/Interfaces/IAlarmService.cs
  10. 9
      JiLinApp.Docking/Alarm/AlarmCode.cs
  11. 41
      JiLinApp.Docking/Alarm/AlarmCodeHelper.cs
  12. 25
      JiLinApp.Docking/FenceAlarm/Entity/DeviceStateMessage.cs
  13. 67
      JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs
  14. 170
      JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs
  15. 30
      JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs
  16. 12
      JiLinApp.Docking/FenceAlarm/Entity/UdpManagerConfig.cs
  17. 141
      JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs
  18. 85
      JiLinApp.Docking/FenceAlarm/Service/Udp.cs
  19. 838
      JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs
  20. 19
      JiLinApp.Docking/JiLinApp.Docking.csproj
  21. 130
      JiLinApp.Docking/Ptz/DCamera.cs
  22. 242
      JiLinApp.Docking/Ptz/PelcoD.cs
  23. 339
      JiLinApp.Docking/Ptz/PelcoP.cs
  24. 219
      JiLinApp.Docking/Ptz/PtzCmd.cs
  25. 73
      JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs
  26. 89
      JiLinApp.Docking/VibrateAlarm/Entity/DataMessage.cs
  27. 14
      JiLinApp.Docking/VibrateAlarm/Entity/DataRequest.cs
  28. 57
      JiLinApp.Docking/VibrateAlarm/Entity/SectionState.cs
  29. 20
      JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs
  30. 16
      JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs
  31. 10
      JiLinApp.Docking/VibrateAlarm/Entity/TcpManagerConfig.cs
  32. 17
      JiLinApp.Docking/VibrateAlarm/Entity/TcpSectionTable.cs
  33. 522
      JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs
  34. 49
      JiLinApp.Docking/VibrateAlarm/Service/CRC8.cs
  35. 26
      JiLinApp.Docking/VibrateAlarm/Service/TcpClientConnectedEventArgs.cs
  36. 26
      JiLinApp.Docking/VibrateAlarm/Service/TcpClientDisconnectedEventArgs.cs
  37. 47
      JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs
  38. 29
      JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs
  39. 685
      JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs
  40. 2198
      JiLinApp.Docking/config/alarmcode.json
  41. 14
      JiLinApp.sln

1
EC.Util/EC.Util.csproj

@ -37,7 +37,6 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="NetMQ" Version="4.0.1.11" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.IO.Ports" Version="7.0.0" />
</ItemGroup>

2
EC.Util/Port/SerialPortParam.cs

@ -5,7 +5,7 @@
/// </summary>
public class SerialPortParam
{
#region fields
#region Fields
/// <summary>
/// 串口名称

2
EC.Util/Zmq/ZmqUtil.cs

@ -2,7 +2,7 @@
internal class ZmqUtil
{
//#region fields
//#region Fields
//private SubscriberSocket SubSocket { get; set; }
//private PublisherSocket PubSocket { get; set; }

13
JiLinApp.Biz/JiLinApp.Biz.csproj

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\JiLinApp.Docking\JiLinApp.Docking.csproj" />
</ItemGroup>
</Project>

33
JiLinApp.Biz/Transmit/Entity/AlarmMessage.cs

@ -0,0 +1,33 @@
namespace JiLinApp.Biz.Transmit;
public class AlarmMessage
{
/** (必填)传感器设备编码*/
public string labelCode;
/** (必填)报警类型((1-视频报警,2-雷达报警;3-微振动警报,4-电子围网警报,9-其他报警))*/
public int warnType;
/** (必填)报警级别(1-5)*/
public int warnLevel;
/** (必填)报警内容*/
public string warnContent;
/** 处置方式*/
public int dealWay;
/** (必填)处置状态(1-未处理,2-已处理)*/
public int dealStatus;
/** (必填)发生地点*/
public string cameraLoc;
/** (必填)发生时间*/
public DateTime createTime;
/** 负责人*/
public string director;
/** (必填)类型(1-预警,2-报警,3-故障,)*/
public int kind;
/** 现场照片*/
public string imgUrl;
public override string ToString()
{
return string.Format("{{ labelCode:{0}, warnType:{1}, warnLevel:{2}, warnContent:{3}, createTime:{4} }}",
labelCode, warnType, warnLevel, warnContent, createTime);
}
}

40
JiLinApp.Biz/Transmit/Entity/AlarmMessageHelper.cs

@ -0,0 +1,40 @@
using JiLinApp.Docking.Alarm;
using JiLinApp.Docking.FenceAlarm;
using JiLinApp.Docking.VibrateAlarm;
namespace JiLinApp.Biz.Transmit;
public static class AlarmMessageHelper
{
public static AlarmMessage ToAlarmMessage(this TcpAlarmHostMessage msg)
{
AlarmCode code = AlarmCodeHelper.Get(msg.AlarmId);
AlarmMessage obj = new()
{
labelCode = Convert.ToString(msg.DeviceID),
warnType = 3,
warnLevel = code.Level,
warnContent = code.Content,
dealStatus = 1,
createTime = Convert.ToDateTime(msg.AlarmTime),
kind = 2,
};
return obj;
}
public static AlarmMessage ToAlarmMessage(this UdpAlarmHostMessage msg)
{
AlarmCode code = AlarmCodeHelper.Get(msg.CID);
AlarmMessage obj = new()
{
labelCode = Convert.ToString(msg.DeviceID),
warnType = 4,
warnLevel = code.Level,
warnContent = code.Content,
dealStatus = 1,
createTime = Convert.ToDateTime(msg.AlarmTime),
kind = 2,
};
return obj;
}
}

5
JiLinApp.Biz/Transmit/Service/AlarmMqttService.cs

@ -0,0 +1,5 @@
using JiLinApp.Biz.Transmit;
public class AlarmMqttService : IAlarmService
{
}

5
JiLinApp.Biz/Transmit/Service/AlarmZmqService.cs

@ -0,0 +1,5 @@
using JiLinApp.Biz.Transmit;
public class AlarmZmqService : IAlarmService
{
}

5
JiLinApp.Biz/Transmit/Service/Interfaces/IAlarmService.cs

@ -0,0 +1,5 @@
namespace JiLinApp.Biz.Transmit;
public interface IAlarmService
{
}

9
JiLinApp.Docking/Alarm/AlarmCode.cs

@ -0,0 +1,9 @@
namespace JiLinApp.Docking.Alarm;
public class AlarmCode
{
public string Id { get; set; }
public int Level { get; set; }
public string Type { get; set; }
public string Content { get; set; }
}

41
JiLinApp.Docking/Alarm/AlarmCodeHelper.cs

@ -0,0 +1,41 @@
using Newtonsoft.Json;
namespace JiLinApp.Docking.Alarm;
public class AlarmCodeHelper
{
#region Fields
private static readonly Dictionary<string, AlarmCode> AlarmCodeDict;
private static readonly List<int> LevelList;
private static readonly List<string> TypeList;
#endregion fields
static AlarmCodeHelper()
{
using StreamReader r = new(Path.Combine("config", "alarmcode.json"));
string jsonStr = r.ReadToEnd();
List<AlarmCode> list = JsonConvert.DeserializeObject<List<AlarmCode>>(jsonStr) ?? new();
AlarmCodeDict = list.ToDictionary(item => item.Id, item => item);
LevelList = list.GroupBy(item => item.Level)
.Select(it => it.First().Level).ToList();
TypeList = list.GroupBy(item => item.Type)
.Select(it => it.First().Type).ToList();
}
public static void Init()
{ }
public static AlarmCode Get(string id)
{
return AlarmCodeDict[id];
}
public static bool TryGet(string id, out AlarmCode alarmCode)
{
bool flag = AlarmCodeDict.TryGetValue(id, out AlarmCode? temp);
alarmCode = temp ?? new();
return flag;
}
}

25
JiLinApp.Docking/FenceAlarm/Entity/DeviceStateMessage.cs

@ -0,0 +1,25 @@
namespace JiLinApp.Docking.FenceAlarm;
public class DeviceStateMessage
{
public int deviceID { get; set; }//设备唯一ID
public string StatusTime { get; set; }//时间
public int channel { get; set; }//防区
public int StatusType { get; set; }//状态
public DeviceStateMessage(int id, DateTime time, int Channel, int statusType)
{
deviceID = id;
StatusTime = time.ToString("yyyy-MM-dd HH:mm:ss");
channel = Channel;
StatusType = statusType;
}
public DeviceStateMessage()
{
deviceID = -1;
StatusTime = "";
channel = -1;
StatusType = -1;
}
}

67
JiLinApp.Docking/FenceAlarm/Entity/SectorState.cs

@ -0,0 +1,67 @@
namespace JiLinApp.Docking.FenceAlarm;
public class SectorState
{
public int id { get; set; }//防区号
/*0使
1
2
3
4
5线
6线(线线)
*/
public int state { get; set; }//防区状态
public string stateStr
{
get
{
switch (state)
{
case 0: return "防区未使用";
case 1: return "防区撤防";
case 2: return "防区布防";
case 3: return "防区旁路";
case 4: return "防区报警";
case 5: return "无线防区欠压";
case 6: return "防区掉线";
default: return "未知状态:" + state;
}
}
}
/*
0:
1线线
2
3
4
5线
*/
public int type { get; set; }//防区类型,特殊参数需单独查询
public string typeStr
{
get
{
switch (type)
{
case 0: return "普通防区";
case 1: return "张力防区";
case 2: return "脉冲围栏";
case 3: return "振动光纤";
case 4: return "泄漏电缆";
case 5: return "网络或总线多子防区模块";
default: return "未知类型:" + type;
}
}
}
public SectorState(int id, byte data)
{
this.id = id;
state = data & 0x0F;
type = data >> 4;
}
}

170
JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostDevice.cs

@ -0,0 +1,170 @@
namespace JiLinApp.Docking.FenceAlarm;
public class UdpAlarmHostDevice
{
public int deviceID { get; set; }//设备唯一ID
public string IP { get; set; }//设备IP
public int groupID { get; set; }//分组号,报警主机可划入不同组
public int userID { get; set; }//用户ID,指主机名称,有多台主机可以通过此名称区分
/*0x00:
0x04: ()
0x02:()
0x08 :(,)
0x01:()
0x09:
*/
public int deviceState { get; set; }//主机布撤状态,
public string deviceStateStr
{
get
{
switch (deviceState)
{
case 0x00:
return "撤防状态";
case 0x01:
return "外出布防";
case 0x02:
return "即时布防";
case 0x04:
return "在家布防";
case 0x08:
return "即时留守布防";
case 0x09:
return "部分防区布防";
default:
return "未知状态号:" + deviceState;
}
}
}
/*0x00,
0x01,,,退
0x02
0x03
0x04
*/
public int deviceWorkState { get; set; }//设备工作状态
public string deviceWorkStateStr
{
get
{
switch (deviceState)
{
case 0x00:
return "常规工作状态";
case 0x01:
return "在设置模式";
case 0x02:
return "用户正在查询报警";
case 0x03:
return "用户正在设置时钟";
case 0x04:
return "用户密码修改模式";
default:
return "未知状态号:" + deviceWorkState;
}
}
}
public int cellState { get; set; }//电池状态 1=电池故障 0=电池正常
public int electricityState { get; set; }//交流状态 1=交流掉电 0=交流正常
public int fuseState { get; set; }//警保险丝状态 1=外接警号断了0=正常
public int sectorState { get; set; }//有线防区触发了 1=其中有线防区触发了 0=所有有线防区准备好
public int cellTestState { get; set; }//正在电池载能测试 1=主机正在进行电池载能测试 0=无(主机会降低电压到电池12V以下,来测试电池负载特性需要2分钟)
public int deviceElectricityState { get; set; }//设备交流电状态1=交流掉电,目前电池供电0=正常 这是即时状态
public int soundState { get; set; }//设备声音输出状态(=0关闭声音) =1 输出声音) 用于布防和报警延时
public int testState { get; set; }//主机本地测试状态1=主机在本地测试(用于测试探测好坏是没有报警记录的)0=无
public int criticalAlarmState { get; set; }//软防区紧急报警状态1=有紧急报警(用户通过手动按下主机自带装置报警) 0=无
public int fireAlarmState { get; set; }//软防区火警报警状态1=有火警报警(用户通过手动按下主机自带装置报警) 0=无
public int stealAlarmState { get; set; }//软防区盗警报警状态1=有盗警报警(用户通过手动按下主机自带装置报警) 0=无
public int deviceFireAlarmState { get; set; }//设备中有火警报警状态 1=其中有火警防区触发了 0=无 整体状态
public int deviceAlarmState { get; set; }//设备有报警发生 1=指设备有报警状态,任一一种0=无报警
public int deviceBywayState { get; set; }//设备有旁路防区1=指设备某些防区有旁路了(这时软件可以要求上传具体旁路的防区) 2=无防区旁路
public int busOfflineState { get; set; }//有总线防区掉线状态1=指某些总线防区掉线了0=无
public int netOfflineState { get; set; }//有网络防区掉线状态1=指某些网络防区掉线了0=无
/*00:
01:EH508报警主机
02:EH508NP网络模块
03: NETLINKBOARD32路网络模块
04: EH508NETCILENT网络终端
05: EH800 8
06: EH508NP_UDP
07: EH508CILENT_UDP
08: EH508SEVER_UDP
09: EH508MAP_UDP
0A: EH508_UDP EH508主机
0x32: H768_IP系列网络模块
0x33: D238C_IP网络模块
0x34: H778S+
0x35: H778S系列报警主机
0x36:N201 N202网络模块
*/
public int devideType { get; set; }//设备类型:区分不同的设备类型 增强可控,防止混乱,具体的设备类型见附加说明表格
public int signalIntensity { get; set; }//31:信号最强,如果设备类型不是这种不需要显示 指主要带有GPRS模块设备跟据设备类型来的
public int channelNum { get; set; }//分区数量
public List<int> channelState { get; set; }//分区布防撤防状态,0为撤防,1为布防
public List<int> channelAlarmState { get; set; }//分区报警状态,0为报警中,1为未报警
//-------------------------------防区信息-----------------------------//
public int maxSectorNum { get; set; }//最大防区号
public List<SectorState> sectorList { get; set; }
public int deviceOnlineState { get; set; }//设备在线状态
public int keep_live { get; set; }//设备在线状态
public UdpAlarmHostDevice()
{
deviceID = 0;
groupID = 0;
userID = 0;
deviceState = -1;
deviceWorkState = 0;
cellState = 0;
electricityState = 0;
fuseState = 0;
sectorState = 0;
cellTestState = 0;
deviceElectricityState = 0;
soundState = 0;
testState = 0;
criticalAlarmState = 0;
fireAlarmState = 0;
stealAlarmState = 0;
deviceFireAlarmState = 0;
deviceAlarmState = 0;
deviceBywayState = 0;
busOfflineState = 0;
netOfflineState = 0;
devideType = 0;
signalIntensity = 0;
channelNum = 0;
channelState = null;
channelAlarmState = null;
sectorList = null;
deviceOnlineState = 0;
}
}

30
JiLinApp.Docking/FenceAlarm/Entity/UdpAlarmHostMessage.cs

@ -0,0 +1,30 @@
using Newtonsoft.Json.Linq;
namespace JiLinApp.Docking.FenceAlarm;
public class UdpAlarmHostMessage
{
public int Id { get; set; }
public string AlarmTime { get; set; }//报警时间
public string CID { get; set; }//CID代码
/*设备信息*/
public int DeviceID { get; set; }//设备唯一ID
public int ChannelNum { get; set; }//防区号
public int SubChannelNum { get; set; }//子防区号
public string Ip { get; set; }//设备IP
public int GroupID { get; set; }//分组号,报警主机可划入不同组
public int UserID { get; set; }//用户ID,指主机名称,有多台主机可以通过此名称区分
public int LinkOut { get; set; }//联动输出
public string ExtendArgs { get; set; }//扩展参数
/*CID信息*/
public string AlarmLevel { get; set; }//报警级别
public string AlarmContent { get; set; }//报警内容
public string AlarmRemarks { get; set; }//报警备注
public string AlarmType { get; set; }//报警类型
/*联动信息*/
public bool IsLinked { get; set; }//是否有联动信息
public JArray Linklist { get; set; }
}

12
JiLinApp.Docking/FenceAlarm/Entity/UdpManagerConfig.cs

@ -0,0 +1,12 @@
namespace JiLinApp.Docking.FenceAlarm;
public class UdpManagerConfig
{
public string ServerIp { get; set; }
public int ServerPort { get; set; }
public int DevicePort { get; set; }
public int DeviceHeartKeep { get; set; }
}

141
JiLinApp.Docking/FenceAlarm/Service/AlarmEncode.cs

@ -0,0 +1,141 @@
namespace JiLinApp.Docking.FenceAlarm;
public class AlarmEncode
{
private static byte[] TEA_key = new byte[16] {
0x08,0x01,0x08,0x06,0x07,0x08,0x07,0x08,
0x08,0x90,0xC5,0x04,0x0D,0x0E,0x0F,0x10
};
public static byte[] encodeMessage(byte[] msg)
{
if (!checkMessage(msg)) return null;
return getMessage(msg[0], btea_encrypt(getContent(msg, msg[0] - 1)));
}
public static byte[] decodeMessage(byte[] msg)
{
if (!checkMessage(msg)) return null;
return getMessage(msg[0], btea_decrpyt(getContent(msg, msg[0] - 1)));
}
public static byte[] CRC16(byte[] data)
{
int len = data.Length;
if (len > 0)
{
ushort crc = 0xFFFF;
for (int i = 0; i < len; i++)
{
crc = (ushort)(crc ^ (data[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ 0xA001) : (ushort)(crc >> 1);
}
}
byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
byte lo = (byte)(crc & 0x00FF); //低位置
return new byte[] { hi, lo };
}
return new byte[] { 0, 0 };
}
private static byte version = 0x12;
private static byte[] head = new byte[] { 0xF0, 0xFA };
private static byte end = 0x0D;
public static byte[] getSendMessage(byte command, byte[] data)
{
byte[] msg = null;
if (data == null)
{
msg = new byte[8];
}
else
{
msg = new byte[data.Length + 8];
}
msg[0] = (byte)msg.Length;
msg[1] = version;
msg[2] = head[0];
msg[3] = head[1];
msg[4] = command;
if (data != null)
{
for (int i = 0; i < data.Length; i++)
{
msg[i + 5] = data[i];
}
}
byte[] subMsg = null;
if (data == null)
{
subMsg = new byte[4];
}
else
{
subMsg = new byte[4 + data.Length];
}
for (int i = 0; i < subMsg.Length; i++)
{
subMsg[i] = msg[i + 1];
}
byte[] crc = CRC16(subMsg);
msg[msg.Length - 3] = crc[1];
msg[msg.Length - 2] = crc[0];
msg[msg.Length - 1] = end;
return msg;
}
private static bool checkMessage(byte[] msg)
{
if (msg == null) return false;
if (msg[0] > msg.Length) return false;
return true;
}
private static byte[] getContent(byte[] msg, int len)
{
byte[] bytes = new byte[len];
for (int i = 0; i < len; i++)
{
bytes[i] = msg[i + 1];
}
return bytes;
}
private static byte[] getMessage(byte msgLen, byte[] msg)
{
byte[] out_msg = new byte[msg.Length + 1];
out_msg[0] = msgLen;
for (int i = 0; i < msg.Length; i++)
{
out_msg[i + 1] = msg[i];
}
return out_msg;
}
private static byte[] btea_encrypt(byte[] bytes)
{
byte[] output = new byte[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
{
byte abyte = (byte)(bytes[i] ^ TEA_key[i % 16]);
output[i] = (byte)(((byte)(abyte >> 3)) | ((byte)(abyte << 5)));
}
return output;
}
private static byte[] btea_decrpyt(byte[] bytes)
{
byte[] output = new byte[bytes.Length];
for (int i = 0; i < bytes.Length; i++)
{
byte abyte = (byte)(((byte)(bytes[i] << 3)) | ((byte)(bytes[i] >> 5)));
output[i] = (byte)(abyte ^ TEA_key[i % 16]);
}
return output;
}
}

85
JiLinApp.Docking/FenceAlarm/Service/Udp.cs

@ -0,0 +1,85 @@
using System.ComponentModel;
using System.Net;
using System.Net.Sockets;
namespace JiLinApp.Docking.FenceAlarm;
public class Udp
{
private BackgroundWorker back = null;
/// <summary>
/// 用于UDP发送的网络服务类
/// </summary>
private UdpClient udpcSend = null;
/// <summary>
/// 用于UDP接收的网络服务类
/// </summary>
private UdpClient udpcRecv;
public delegate void UDPReceive(string IP, byte[] str);//
public event UDPReceive myUDPReceive;//
public Udp(string ip, int port)
{
IPEndPoint localIpep = new IPEndPoint(
IPAddress.Parse(ip), port); // 本机IP和监听端口号
udpcRecv = new UdpClient(localIpep);
udpcSend = new UdpClient();
back = new BackgroundWorker();
back.WorkerSupportsCancellation = true;
back.DoWork += back_DoWork;
back.RunWorkerAsync();
}
~Udp()
{
Stop();
}
public void Stop()
{
if (back != null)
{
back.CancelAsync();
back = null;
}
if (udpcRecv != null)
{
udpcRecv.Close();
udpcRecv = null;
}
if (udpcSend != null)
{
udpcSend.Close();
udpcSend = null;
}
}
public bool SendMessage(byte[] sendbytes, string IP, int port)
{
IPEndPoint remoteIpep = new IPEndPoint(
IPAddress.Parse(IP), port); // 发送到的IP地址和端口号
int result = udpcSend.Send(sendbytes, sendbytes.Length, remoteIpep);
return result >= sendbytes.Length;
}
private void back_DoWork(object sender, DoWorkEventArgs e)
{
IPEndPoint remoteIpep = new IPEndPoint(IPAddress.Any, 0);
while (!back.CancellationPending)
{
try
{
byte[] bytRecv = udpcRecv.Receive(ref remoteIpep);
myUDPReceive(remoteIpep.Address.ToString(), bytRecv);
}
catch
{
}
}
}
}

838
JiLinApp.Docking/FenceAlarm/Service/UdpManager.cs

@ -0,0 +1,838 @@
using System.Data;
using System.Timers;
using Timer = System.Timers.Timer;
namespace JiLinApp.Docking.FenceAlarm;
public class UdpManager
{
#region Fields
private Udp myUdp = null;
private int udp_sendPort = -1;
private int udp_ReceivePort = -1;
private int keep_alive = -1;
private Timer PtzCheckTimer = new();
private List<UdpAlarmHostDevice> deviceList = new();
#endregion fields
public UdpManager()
{
PtzCheckTimer.Interval = 1000;
PtzCheckTimer.Elapsed += PTZCheckTimer_Elapsed;
}
//计时判断设备是否在线,若超过规定时间没有新消息发来,则设备离线
private void PTZCheckTimer_Elapsed(object sender, ElapsedEventArgs e)
{
foreach (UdpAlarmHostDevice p1 in deviceList)
{
if (p1.keep_live >= 0)
{
p1.keep_live--;
}
if (p1.keep_live < 0)
{
p1.deviceOnlineState = 0;
if (OnUdpAlarmDeviceState != null)
{
OnUdpAlarmDeviceState(p1.deviceID, "设备离线");
}
}
}
}
public List<UdpAlarmHostDevice> getDeviceAll()
{
return deviceList;
}
public UdpAlarmHostDevice getDevice(int deviceID)
{
foreach (UdpAlarmHostDevice p1 in deviceList)
{
if (p1.deviceID == deviceID) return p1;
}
return null;
}
public List<SectorState> getDeviceChannelAll(int deviceID)
{
foreach (UdpAlarmHostDevice p1 in deviceList)
{
if (p1.deviceID == deviceID) return p1.sectorList;
}
return null;
}
public SectorState getDeviceChannel(int deviceID, int channel)
{
UdpAlarmHostDevice state = getDevice(deviceID);
if (state == null || state.sectorList == null) return null;
foreach (SectorState p1 in state.sectorList)
{
if (p1.id == channel) return p1;
}
return null;
}
#region BaseMethod
public bool StartServer(UdpManagerConfig config)
{
string s_IP = config.ServerIp;
int s_Port = config.ServerPort;
int d_Port = config.DevicePort;
int d_Keep = config.DeviceHeartKeep;
return AlarmHostLogin(s_IP, s_Port, d_Port, d_Keep);
}
public bool StopServer()
{
return AlarmHostLoginOut();
}
private bool AlarmHostLogin(string IP, int Port, int device_port, int keep_alive)
{
if (myUdp != null) AlarmHostLoginOut();
this.udp_ReceivePort = Port;
this.udp_sendPort = device_port;
this.keep_alive = keep_alive;
try
{
//启动UDP协议
myUdp = new Udp(IP, udp_ReceivePort);
myUdp.myUDPReceive += myUDPReceive;
}
catch (Exception ex)
{
myUdp = null;
return false;
}
if (keep_alive > 0)
{
PtzCheckTimer.Enabled = true;
}
return true;
}
private bool AlarmHostLoginOut()
{
PtzCheckTimer.Enabled = false;
if (myUdp != null)
{
myUdp.myUDPReceive -= myUDPReceive;
myUdp.Stop();
myUdp = null;
}
return true;
}
#endregion BaseMethod
public delegate void UDPAlarmDeviceStateEvent(int deviceId, string state);
public event UDPAlarmDeviceStateEvent OnUdpAlarmDeviceState;
public delegate void UDPAlarmSectionStateEvent(int deviceId, int channel, string state);
public event UDPAlarmSectionStateEvent OnUdpAlarmSectionState;
public delegate void UDPAlarmEvent(UdpAlarmHostMessage msg);
public event UDPAlarmEvent OnUdpAlarmEvent;
public delegate void UDPAlarmCancelEvent(int deviceId, int channel);
public event UDPAlarmCancelEvent OnUdpAlarmCancel;
private void myUDPReceive(string Ip, byte[] str)
{
//解码
byte[] msg = AlarmEncode.decodeMessage(str);
//解析
switch (msg[4])
{
case 0x01: //心跳数据
analysisHeartMessage(Ip, msg);
break;
case 0x02://报警信息
AnalysisAlarmMessage(Ip, msg);
break;
case 0x03://防区信息
analysisAllSectorMessage(Ip, msg);
break;
case 0x04://张力防区信息
analysisSectorMessage(Ip, msg);
break;
case 0x05://报警主机最大防区信息
analysisMaxSectorMessage(Ip, msg);
break;
case 0x08://返回报警主机设置参数回服务器,无需解析
break;
default:
break;
}
Console.WriteLine("消息类型:" + msg[4]);
sendOK(Ip);
}
private void sendOK(string IP)
{
if (myUdp == null) return;
//byte[] bytes = new byte[] { 0x08, 0x12, 0xF0, 0xFA, 0x8F, 0x7F, 0x2E, 0x0D };
byte[] bytes = new byte[] { 0x08, 0x12, 0xF0, 0xFA, 0x8F, 0x06, 0x6B, 0x0D };
myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), IP, udp_sendPort);
}
private void analysisHeartMessage(string IP, byte[] msg)
{
int deviceID = ByteToInt(msg, 5);
UdpAlarmHostDevice device = getDevice(deviceID);
if (device == null)
{
device = new UdpAlarmHostDevice();
device.deviceID = deviceID;
device.userID = ByteToInt(msg, 13);
device.IP = IP;
device.deviceOnlineState = 1;
device.keep_live = keep_alive;
deviceList.Add(device);
}
device.deviceID = deviceID;
device.IP = IP;
device.groupID = ByteToInt(msg, 9);
device.userID = ByteToInt(msg, 13);
if (device.deviceState != msg[17])
{
if (OnUdpAlarmDeviceState != null)
{
switch (msg[17])
{
case 0x00://撤防状态
OnUdpAlarmDeviceState(device.deviceID, "撤防状态");
break;
case 0x01://外出布防
OnUdpAlarmDeviceState(device.deviceID, "外出布防(普通布防最常用)");
break;
case 0x02://即时布防(所有防区没有延时)
OnUdpAlarmDeviceState(device.deviceID, "即时布防(所有防区没有延时)");
break;
case 0x04://在家布防(留守布防有些防区可能是在旁路状态)
OnUdpAlarmDeviceState(device.deviceID, "在家布防(留守布防有些防区可能是在旁路状态)");
break;
case 0x08://即时留守布防(有些防区可能旁路,但是没有旁路防区没有延时)
OnUdpAlarmDeviceState(device.deviceID, "即时留守布防(有些防区可能旁路,但是没有旁路防区没有延时)");
break;
case 0x09://部分防区布防部分防区撤防
OnUdpAlarmDeviceState(device.deviceID, "部分防区布防部分防区撤防");
break;
}
}
}
device.deviceState = msg[17];
device.deviceWorkState = msg[18];
//设备状态1
device.cellState = getBit(msg[19], 0);
device.electricityState = getBit(msg[19], 1);
device.fuseState = getBit(msg[19], 2);
device.sectorState = getBit(msg[19], 3);
device.cellTestState = getBit(msg[19], 4);
device.deviceElectricityState = getBit(msg[19], 5);
device.soundState = getBit(msg[19], 6);
device.testState = getBit(msg[19], 7);
//设备状态2
device.criticalAlarmState = getBit(msg[20], 0);
device.fireAlarmState = getBit(msg[20], 1);
device.stealAlarmState = getBit(msg[20], 2);
device.deviceFireAlarmState = getBit(msg[20], 3);
device.deviceAlarmState = getBit(msg[20], 4);
device.deviceBywayState = getBit(msg[20], 5);
device.busOfflineState = getBit(msg[20], 6);
device.netOfflineState = getBit(msg[20], 7);
//设备状态3,4暂不使用
device.devideType = msg[23];
device.signalIntensity = msg[24];
device.channelNum = msg[25];
if (device.channelNum > 0)
{
device.channelState = new List<int>();
device.channelAlarmState = new List<int>();
for (int i = 0; i < device.channelNum; i++)
{
device.channelState.Add(getBit(msg[26], i));
device.channelAlarmState.Add(getBit(msg[27], i));
}
}
//在线状态
device.keep_live = keep_alive;
if (device.deviceOnlineState == 0)
{
if (OnUdpAlarmDeviceState != null)
{
OnUdpAlarmDeviceState(device.deviceID, "设备上线");
}
}
device.deviceOnlineState = 1;
}
private int getBit(byte bytes, int index)
{
switch (index)
{
case 0:
return bytes & 0x01;
case 1:
return (bytes & 0x02) >> 1;
case 2:
return (bytes & 0x04) >> 2;
case 3:
return (bytes & 0x08) >> 3;
case 4:
return (bytes & 0x10) >> 4;
case 5:
return (bytes & 0x20) >> 5;
case 6:
return (bytes & 0x40) >> 6;
case 7:
return (bytes & 0x80) >> 7;
default:
return 0;
}
}
private int ByteToInt(byte[] msg, int start)
{
byte[] bytes = new byte[] { msg[start + 3], msg[start + 2], msg[start + 1], msg[start] };
return BitConverter.ToInt32(bytes, 0);
}
private byte[] IntToByte(int num)
{
byte[] bytes = BitConverter.GetBytes(num);
return new byte[] { bytes[3], bytes[2], bytes[1], bytes[0] };
}
public void TestAlarm(string devideId, string channel)
{
byte[] bytes = BitConverter.GetBytes(int.Parse(devideId));
byte[] bytes2 = BitConverter.GetBytes(int.Parse(channel));
byte[] msg = new byte[36]{
0x24,0x12,0xF0,0xFA,
0x02,bytes[3],bytes[2],bytes[1],
bytes[0],0x00,0x00,0x00,
0x00,bytes[3],bytes[2],bytes[1],
bytes[0],0x22,0x12,0x23,
0x10,0x10,0x10,0x01,
0x01,0x03,0x01,0x00,
0x02,bytes2[0],bytes2[1],0x00,
0x00,0x04,0x03,0x01
};
AnalysisAlarmMessage("127.0.0.1", msg);
}
private void AnalysisAlarmMessage(string ip, byte[] msg)
{
string CID = getCID(msg[23]) + getCID(msg[24]) + getCID(msg[25]) + getCID(msg[26]);
int deviceID = ByteToInt(msg, 5);
int channelNum = msg[29] + msg[30] * 256;
string alarmTime = "20" + getBCD(msg[17]) + "-" + getBCD(msg[18]) + "-" + getBCD(msg[19])
+ " " + getBCD(msg[20]) + ":" + getBCD(msg[21]) + ":" + getBCD(msg[22]);
UdpAlarmHostMessage alarm = new()
{
DeviceID = deviceID,
Ip = ip,
GroupID = ByteToInt(msg, 9),
UserID = ByteToInt(msg, 13),
AlarmTime = alarmTime,
//CID暂定
CID = CID,
LinkOut = msg[27] + msg[28] * 256,
ChannelNum = channelNum,
SubChannelNum = msg[31] + msg[32] * 256,
ExtendArgs = msg[33].ToString("X2") + " " + msg[34].ToString("X2") + " " + msg[35].ToString("X2"),
};
ProcessAlarm(alarm);
}
//处理报警事件
private void ProcessAlarm(UdpAlarmHostMessage msg)
{
OnUdpAlarmEvent(msg);
////报警信息放入数据库
//JObject obj = new()
//{
// { "alarmTime", msg.AlarmTime },
// { "CID", msg.CID },
// { "deviceID", msg.DeviceID },
// { "channelNum", msg.ChannelNum },
// { "subChannelNum", msg.SubChannelNum },
// { "IP", msg.Ip },
// { "groupID", msg.GroupID },
// { "userID", msg.UserID },
// { "linkOut", msg.LinkOut },
// { "extendArgs", msg.ExtendArgs },
// { "alarm_level", msg.AlarmLevel },
// { "alarm_content", msg.AlarmContent },
// { "alarm_remarks", msg.AlarmRemarks },
// { "alarm_type", msg.AlarmType },
// { "IsLinked", msg.IsLinked },
// { "linklist", msg.Linklist }
//};
//string error = "";
//DBCenter.center.InsertResult("table_UDPAlarmMessage", obj, ref error);
////打开预览窗口
//if (msg.IsLinked)
//{
// if (OnUdpAlarmEvent != null)
// {
// OnUdpAlarmEvent(msg);
// }
// //联动预置位
// for (int i = 0; i < msg.Linklist.Count; i++)
// {
// if (msg.Linklist[i]["needPreset"].ToString() == "true")
// {
// //int camID = int.Parse(msg.linklist[i]["camID"].ToString());
// //string camType = msg.linklist[i]["camType"].ToString();
// //CamType device_type = CamType.Table;
// //if (camType == "摄像机") device_type = CamType.Camera;
// //int presetId = int.Parse(msg.linklist[i]["presetID"].ToString());
// //RequestToService.center.NET_SDK_PTZPreset_Other(camID, device_type, (int)WMPTZPresetCommand.WMPTZPreset_GOTO, presetId, ref error);
// }
// }
//}
}
private string getCID(byte bytes)
{
switch (bytes)
{
case 0x00:
return "0";
case 0x01:
return "1";
case 0x02:
return "2";
case 0x03:
return "3";
case 0x04:
return "4";
case 0x05:
return "5";
case 0x06:
return "6";
case 0x07:
return "7";
case 0x08:
return "8";
case 0x09:
return "9";
case 0x0A:
return "A";
case 0x0B:
return "B";
case 0x0C:
return "C";
case 0x0D:
return "D";
case 0x0E:
return "E";
case 0x0F:
return "F";
default:
return "0";
}
}
private string getBCD(byte bytes)
{
int num = (bytes >> 4) * 10 + (bytes & 0x0F);
return num.ToString();
}
private byte getBCDByte(int num)
{
if (num >= 100) num = num % 100;
int hex = num / 10;
int lex = num % 10;
return (byte)(hex * 16 + lex);
}
private byte[] getBCDTime(DateTime time)
{
return new byte[] { getBCDByte(time.Year),getBCDByte((int)time.DayOfWeek),getBCDByte(time.Month),getBCDByte(time.Day),
getBCDByte(time.Hour),getBCDByte(time.Minute),getBCDByte(time.Second) };
}
private string getBCD2(byte bytes)
{
int num1 = bytes / 16;
int num2 = bytes % 16;
return (num1 * 10 + num2).ToString();
}
private void analysisAllSectorMessage(string IP, byte[] msg)
{
int deviceID = ByteToInt(msg, 5);
UdpAlarmHostDevice device = getDevice(deviceID);
if (device == null)
{
device = new UdpAlarmHostDevice();
device.deviceID = deviceID;
device.IP = IP;
device.deviceOnlineState = 1;
device.keep_live = keep_alive;
deviceList.Add(device);
}
device.IP = IP;
device.groupID = ByteToInt(msg, 9);
device.userID = ByteToInt(msg, 13);
if (device.sectorList == null)
{
device.sectorList = new List<SectorState>();
}
int count = msg[19];
for (int i = 0; i < count; i++)
{
int index = i + msg[20];//防区序号
int pos = 21 + i;//防区信息所在byte数组未知
SectorState state = new SectorState(index, msg[pos]);
updateSector(state, device.sectorList, device.deviceID);
}
}
private void updateSector(SectorState state, List<SectorState> list, int deviceId)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].id == state.id)
{
//设备离线
if (list[i].state != state.state)
{
reportSectorState(deviceId, state.id, state.state);
}
list[i] = state; //防区存在,更新
return;
}
}
list.Add(state);//防区不存在,添加
reportSectorState(deviceId, state.id, state.state);
}
private void reportSectorState(int deviceId, int channel, int state)
{
if (OnUdpAlarmSectionState != null)
{
switch (state)
{
case 0:
OnUdpAlarmSectionState(deviceId, channel, "防区未使用");
break;
case 1://撤防
OnUdpAlarmSectionState(deviceId, channel, "防区撤防");
break;
case 2://布防
OnUdpAlarmSectionState(deviceId, channel, "防区布防");
break;
case 3://旁路
OnUdpAlarmSectionState(deviceId, channel, "防区旁路");
break;
case 4://报警
OnUdpAlarmSectionState(deviceId, channel, "防区报警");
break;
case 5://无线防区欠压
OnUdpAlarmSectionState(deviceId, channel, "无线防区欠压");
break;
case 6://防区掉线
OnUdpAlarmSectionState(deviceId, channel, "防区掉线(与主线总线脱离)");
break;
case 7://未准备就绪
OnUdpAlarmSectionState(deviceId, channel, "未准备就绪");
break;
}
}
}
private void analysisSectorMessage(string IP, byte[] msg)
{
//东北没有张力防区,暂不解析
}
private void analysisMaxSectorMessage(string IP, byte[] msg)
{
int deviceID = ByteToInt(msg, 5);
UdpAlarmHostDevice device = getDevice(deviceID);
if (device == null)
{
device = new UdpAlarmHostDevice();
device.deviceID = deviceID;
device.IP = IP;
device.deviceOnlineState = 1;
device.keep_live = keep_alive;
deviceList.Add(device);
}
device.IP = IP;
device.groupID = ByteToInt(msg, 9);
device.userID = ByteToInt(msg, 13);
device.maxSectorNum = msg[17] * 256 + msg[18];
}
private bool checkDevice(UdpAlarmHostDevice device, ref string error)
{
if (device == null)
{
error = "没有此报警主机的记录";
return false;
}
if (device.deviceOnlineState == 0)
{
error = "此报警主机离线";
return false;
}
if (myUdp == null)
{
error = "UDP故障";
return false;
}
return true;
}
//外出布防或者布防
public bool setDeviceDefence(int deviceID, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x60 });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//立即布防
public bool setDeviceDefenceImmediately(int deviceID, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x62 });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//在家布防留守布防
public bool setDeviceDefenceHome(int deviceID, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x63 });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//即时留守布防
public bool setDeviceDefenceHomeImmediately(int deviceID, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x64 });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//撤防
public bool withdrawDeviceDefence(int deviceID, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x61 });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//清除报警记忆(复位)
public bool clearDeviceDefence(int deviceID, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0x80, new byte[] { 0x65 });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//校对系统时间
public bool setDeviceTime(int deviceID, DateTime time, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] content = getBCDTime(time);
byte[] bytes = AlarmEncode.getSendMessage(0x8D, content);
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//设备重启
public bool rebootDevice(int deviceID, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0xA0, null);
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//单防区布防
public bool setDeviceChannelDefence(int deviceID, int channel, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0xC0, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//单防区撤防
public bool withdrawDeviceChannelDefence(int deviceID, int channel, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0xC1, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//单防区旁路
public bool setDeviceChannelByway(int deviceID, int channel, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0xC2, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
//单防区旁路恢复
public bool withdrawDeviceChannelByway(int deviceID, int channel, ref string error)
{
UdpAlarmHostDevice device = getDevice(deviceID);
if (checkDevice(device, ref error))
{
byte[] bytes = AlarmEncode.getSendMessage(0xC3, new byte[] { (byte)(channel / 256), (byte)(channel % 256) });
return myUdp.SendMessage(AlarmEncode.encodeMessage(bytes), device.IP, udp_sendPort);
}
else
{
return false;
}
}
}

19
JiLinApp.Docking/JiLinApp.Docking.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\EC.Util\EC.Util.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="config\alarmcode.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

130
JiLinApp.Docking/Ptz/DCamera.cs

@ -0,0 +1,130 @@
using System;
namespace JiLinApp.Docking.Ptz;
public class DCamera
{
#region Fields
#region Data3
public static double SpeedMin = 1;
public static double SpeedMax = 60;
#endregion Data3
#endregion fields
#region BaseMethod
private static byte[] CommandPara(byte com1, byte com2, int data1, int data2)
{
byte[] b = new byte[11];
b[0] = 0xA1;
int temp1 = data1;
int temp2 = data2;
b[1] = 0x00;
b[2] = 0x0B;
b[3] = com1;
b[4] = com2;
b[5] = (byte)(data1 >> 8 & 0xFF);
b[6] = (byte)(temp1 & 0xFF);
b[7] = (byte)(data2 >> 8 & 0xFF);
b[8] = (byte)(temp2 & 0xFF);
b[9] = (byte)(b[0] ^ b[1] ^ b[2] ^ b[3] ^ b[4] ^ b[5] ^ b[6] ^ b[7] ^ b[8]);
b[10] = 0xAF;
return b;
}
private static byte[] SendJoystick(double headSpeed, double pitchSpeed)
{
return CommandPara(0x4D, 0x58, (int)(headSpeed * 100), (int)(pitchSpeed * 100));
}
#endregion BaseMethod
#region PtzMethod
public static byte[] Left(double headSpeed)
{
double absHs = Math.Abs(headSpeed);
if (absHs < SpeedMin) headSpeed = -SpeedMin;
if (absHs > SpeedMax) headSpeed = -SpeedMax;
return SendJoystick(headSpeed, 0);
}
public static byte[] Right(double headSpeed)
{
double absHs = Math.Abs(headSpeed);
if (absHs < SpeedMin) headSpeed = SpeedMin;
if (absHs > SpeedMax) headSpeed = SpeedMax;
return SendJoystick(headSpeed, 0);
}
public static byte[] Up(double pitchSpeed)
{
double absPs = Math.Abs(pitchSpeed);
if (absPs < SpeedMin) pitchSpeed = SpeedMin;
if (absPs > SpeedMax) pitchSpeed = SpeedMax;
return SendJoystick(0, pitchSpeed);
}
public static byte[] Down(double pitchSpeed)
{
double absPs = Math.Abs(pitchSpeed);
if (absPs < SpeedMin) pitchSpeed = -SpeedMin;
if (absPs > SpeedMax) pitchSpeed = -SpeedMax;
return SendJoystick(0, pitchSpeed);
}
public static byte[] LeftUp(double headSpeed, double pitchSpeed)
{
double absHs = Math.Abs(headSpeed);
if (absHs < SpeedMin) headSpeed = -SpeedMin;
if (absHs > SpeedMax) headSpeed = -SpeedMax;
double absPs = Math.Abs(pitchSpeed);
if (absPs < SpeedMin) pitchSpeed = SpeedMin;
if (absPs > SpeedMax) pitchSpeed = SpeedMax;
return SendJoystick(headSpeed, pitchSpeed);
}
public static byte[] LeftDown(double headSpeed, double pitchSpeed)
{
double absHs = Math.Abs(headSpeed);
if (absHs < SpeedMin) headSpeed = -SpeedMin;
if (absHs > SpeedMax) headSpeed = -SpeedMax;
double absPs = Math.Abs(pitchSpeed);
if (absPs < SpeedMin) pitchSpeed = -SpeedMin;
if (absPs > SpeedMax) pitchSpeed = -SpeedMax;
return SendJoystick(headSpeed, pitchSpeed);
}
public static byte[] RightUp(double headSpeed, double pitchSpeed)
{
double absHs = Math.Abs(headSpeed);
if (absHs < SpeedMin) headSpeed = SpeedMin;
if (absHs > SpeedMax) headSpeed = SpeedMax;
double absPs = Math.Abs(pitchSpeed);
if (absPs < SpeedMin) pitchSpeed = SpeedMin;
if (absPs > SpeedMax) pitchSpeed = SpeedMax;
return SendJoystick(headSpeed, pitchSpeed);
}
public static byte[] RightDown(double headSpeed, double pitchSpeed)
{
double absHs = Math.Abs(headSpeed);
if (absHs < SpeedMin) headSpeed = SpeedMin;
if (absHs > SpeedMax) headSpeed = SpeedMax;
double absPs = Math.Abs(pitchSpeed);
if (absPs < SpeedMin) pitchSpeed = -SpeedMin;
if (absPs > SpeedMax) pitchSpeed = -SpeedMax;
return SendJoystick(headSpeed, pitchSpeed);
}
public static byte[] Stop()
{
return SendJoystick(0, 0);
}
#endregion PtzMethod
}

242
JiLinApp.Docking/Ptz/PelcoD.cs

@ -0,0 +1,242 @@
using System;
namespace JiLinApp.Docking.Ptz;
public class PelcoD
{
private string watchdir = ""; //监控方向
private static readonly byte STX = 0xFF; //同步字节
#region 监控方向和定时监控实体
public string WatchDir
{
get { return watchdir; }
set { watchdir = value; }
}
#endregion 监控方向和定时监控实体
#region 基本指令定义
#region 指令码1
private const byte FocusNear = 0x01; //增加聚焦
private const byte IrisOpen = 0x02; //减小光圈
private const byte IrisClose = 0x04; //增加光圈
private const byte CameraOnOff = 0x08; //摄像机打开和关闭
private const byte AutoManualScan = 0x10; //自动和手动扫描
private const byte Sense = 0x80; //Sence码
#endregion 指令码1
#region 指令码2
private const byte PanRight = 0x02; //右
private const byte PanLeft = 0x04; //左
private const byte TiltUp = 0x08; //上
private const byte TiltDown = 0x10; //下
private const byte ZoomTele = 0x20; //增加对焦
private const byte ZoomWide = 0x40; //减小对焦
private const byte FocusFar = 0x80; //减小聚焦
#endregion 指令码2
#region 镜头左右平移的速度
public static byte PanSpeedMin = 0x00; //停止
public static byte PanSpeedMax = 0x3F; //最高速
#endregion 镜头左右平移的速度
#region 镜头上下移动的速度
public static byte TiltSpeedMin = 0x00; //停止
public static byte TiltSpeedMax = 0x3F; //最高速
#endregion 镜头上下移动的速度
#endregion 基本指令定义
private const byte PanRightUp = 0xa; //右上
private const byte PanLeftUp = 0x0c; //左上
private const byte PanRightDown = 0x12; //右下
private const byte PanLeftDown = 0x14; //左下
#region 云台控制枚举
public enum Switch
{
On = 0x01,
Off = 0x02
} //雨刷控制
public enum Focus
{
Near = FocusNear,
Far = FocusFar
} //聚焦控制
public enum Zoom
{
Wide = ZoomWide,
Tele = ZoomTele
} //对焦控制
public enum Tilt
{
Up = TiltUp,
Down = TiltDown
} //上下控制
public enum Pan
{
Left = PanLeft,
Right = PanRight,
LeftUp = PanLeftUp,
LeftDown = PanLeftDown,
RightUp = PanRightUp,
RightDown = PanRightDown
} //左右控制
public enum Scan
{
Auto,
Manual
} //自动和手动控制
public enum Iris
{
Open = IrisOpen,
Close = IrisClose
} //光圈控制
public enum PresetAction
{
Set = 0x03,
Clear = 0x05,
Goto = 0x07
}
#endregion 云台控制枚举
#region 云台控制方法
//雨刷控制
public static byte[] CameraSwitch(uint deviceAddress, Switch action)
{
byte m_action = CameraOnOff;
if (action == Switch.On)
m_action = CameraOnOff + Sense;
return Message.GetMessage(deviceAddress, m_action, 0x00, 0x00, 0x00);
}
//光圈控制
public static byte[] CameraIrisSwitch(uint deviceAddress, Iris action)
{
return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
}
//聚焦控制
public static byte[] CameraFocus(uint deviceAddress, Focus action)
{
if (action == Focus.Near)
return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
else
return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, 0x00);
}
//对焦控制
public static byte[] CameraZoom(uint deviceAddress, Zoom action)
{
return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, 0x00);
}
/// <summary>
/// 上下控制
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="action"></param>
/// <param name="speed"></param>
/// <returns></returns>
public static byte[] CameraTilt(uint deviceAddress, Tilt action, uint speed)
{
if (speed < TiltSpeedMin)
speed = TiltSpeedMin;
if (speed > TiltSpeedMax)
speed = TiltSpeedMax;
return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, (byte)speed);
}
/// <summary>
/// 左右控制
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="action"></param>
/// <param name="speed"></param>
/// <returns></returns>
public static byte[] CameraPan(uint deviceAddress, Pan action, uint speed)
{
if (speed < PanSpeedMin)
speed = PanSpeedMin;
if (speed > PanSpeedMax)
speed = PanSpeedMax;
return Message.GetMessage(deviceAddress, 0x00, (byte)action, (byte)speed, 0x00);
}
//停止云台的移动
public static byte[] CameraStop(uint deviceAddress)
{
return Message.GetMessage(deviceAddress, 0x00, 0x00, 0x00, 0x00);
}
//自动和手动控制
public static byte[] CameraScan(uint deviceAddress, Scan scan)
{
byte m_byte = AutoManualScan;
if (scan == Scan.Auto)
m_byte = AutoManualScan + Sense;
return Message.GetMessage(deviceAddress, m_byte, 0x00, 0x00, 0x00);
}
public static byte[] Preset(uint deviceAddress, PresetAction action, byte presetId)
{
return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, presetId);
}
#endregion 云台控制方法
public struct Message
{
public static byte Address;
public static byte CheckSum;
public static byte Command1,
Command2,
Data1,
Data2;
public static byte[] GetMessage(
uint address,
byte command1,
byte command2,
byte data1,
byte data2
)
{
if (address < 1 & address > 256)
throw new Exception("Pelco D协议只支持256设备");
Address = byte.Parse(address.ToString());
Command1 = command1;
Command2 = command2;
Data1 = data1;
Data2 = data2;
CheckSum = (byte)(Address + Command1 + Command2 + Data1 + Data2);
return new byte[] { STX, Address, Command1, Command2, Data1, Data2, CheckSum };
}
}
}

339
JiLinApp.Docking/Ptz/PelcoP.cs

@ -0,0 +1,339 @@
using System;
namespace JiLinApp.Docking.Ptz;
/// <summary>
/// dot.NET Implementation of Pelco P Protocol
/// </summary>
public class PelcoP
{
private const byte STX = 0xA0;
private const byte ETX = 0xAF;
#region Pan and Tilt Commands
#region Data1
private const byte FocusFar = 0x01;
private const byte FocusNear = 0x02;
private const byte IrisOpen = 0x04;
private const byte IrisClose = 0x08;
private const byte CameraOnOff = 0x10;
private const byte AutoscanOn = 0x20;
private const byte CameraOn = 0x40;
#endregion Data1
#region Data2
private const byte PanRight = 0x02;
private const byte PanLeft = 0x04;
private const byte TiltUp = 0x08;
private const byte TiltDown = 0x10;
private const byte ZoomTele = 0x20;
private const byte ZoomWide = 0x40;
#endregion Data2
#region Data3
public static byte PanSpeedMin = 0x00;
public static byte PanSpeedMax = 0x3F;
#endregion Data3
#region Data4
public static byte TiltSpeedMin = 0x00;
public static byte TiltSpeedMax = 0x3F;
#endregion Data4
#endregion Pan and Tilt Commands
#region Enums
public enum PatternAction
{
Start,
Stop,
Run
}
public enum Action
{
Start,
Stop
}
public enum LensSpeed
{
Low = 0x00,
Medium = 0x01,
High = 0x02,
Turbo = 0x03
}
public enum Pan
{
Left = PanLeft,
Right = PanRight
}
public enum Tilt
{
Up = TiltUp,
Down = TiltDown
}
public enum Iris
{
Open = IrisOpen,
Close = IrisClose
}
public enum Zoom
{
Wide = ZoomWide,
Tele = ZoomTele
}
public enum Switch
{
On,
Off
}
public enum Focus
{
Near = FocusNear,
Far = FocusFar
}
public enum PresetAction
{
Set = 0x03,
Clear = 0x05,
Goto = 0x07
}
#endregion Enums
#region Extended Command Set
public static byte[] Preset(uint deviceAddress, PresetAction action, byte presetId)
{
return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, presetId);
}
public static byte[] Flip(uint deviceAddress)
{
return Message.GetMessage(deviceAddress, 0x00, 0x07, 0x00, 0x21);
}
public static byte[] ZeroPanPosition(uint deviceAddress)
{
return Message.GetMessage(deviceAddress, 0x00, 0x07, 0x00, 0x22);
}
public static byte[] AutoScan(uint deviceAddress, Action action)
{
byte m_action;
if (action == Action.Start)
m_action = 0x09;
else
m_action = 0x0B;
return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, 0x00);
}
public static byte[] RemoteReset(uint deviceAddress)
{
return Message.GetMessage(deviceAddress, 0x00, 0x0F, 0x00, 0x00);
}
public static byte[] Zone(uint deviceAddress, byte zone, Action action)
{
if (zone < 0x01 & zone > 0x08)
throw new Exception("Zone value should be between 0x01 and 0x08 include");
byte m_action;
if (action == Action.Start)
m_action = 0x11;
else
m_action = 0x13;
return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, zone);
}
public static byte[] WriteToScreen(uint deviceAddress, string text)
{
if (text.Length > 40)
text = text.Remove(40, text.Length - 40);
System.Text.Encoding encoding = System.Text.Encoding.ASCII;
byte[] m_bytes = new byte[encoding.GetByteCount(text) * 8];
int i = 0;
byte m_scrPosition;
byte m_ASCIIchr;
foreach (char ch in text)
{
m_scrPosition = Convert.ToByte(i / 8);
m_ASCIIchr = Convert.ToByte(ch);
Array.Copy(
Message.GetMessage(deviceAddress, 0x00, 0x15, m_scrPosition, m_ASCIIchr),
0,
m_bytes,
i,
8
);
i += 8;
}
return m_bytes;
}
public static byte[] ClearScreen(uint deviceAddress)
{
return Message.GetMessage(deviceAddress, 0x00, 0x17, 0x00, 0x00);
}
public static byte[] AlarmAcknowledge(uint deviceAddress, uint alarmID)
{
if (alarmID < 1 & alarmID > 8)
throw new Exception("Only 8 alarms allowed for Pelco P implementation");
return Message.GetMessage(deviceAddress, 0x00, 0x19, 0x00, Convert.ToByte(alarmID));
}
public static byte[] ZoneScan(uint deviceAddress, Action action)
{
byte m_action;
if (action == Action.Start)
m_action = 0x1B;
else
m_action = 0x1D;
return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, 0x00);
}
public static byte[] Pattern(uint deviceAddress, PatternAction action)
{
byte m_action = action switch
{
PatternAction.Start => 0x1F,
PatternAction.Stop => 0x21,
PatternAction.Run => 0x23,
_ => 0x23,
};
return Message.GetMessage(deviceAddress, 0x00, m_action, 0x00, 0x00);
}
public static byte[] SetZoomLensSpeed(uint deviceAddress, LensSpeed speed)
{
return Message.GetMessage(deviceAddress, 0x00, 0x25, 0x00, (byte)speed);
}
public static byte[] SetFocusLensSpeed(uint deviceAddress, LensSpeed speed)
{
return Message.GetMessage(deviceAddress, 0x00, 0x27, 0x00, (byte)speed);
}
#endregion Extended Command Set
#region Base Command Set
public static byte[] CameraSwitch(uint deviceAddress, Switch action)
{
byte m_action = CameraOnOff;
if (action == Switch.On)
m_action += CameraOnOff; //Maybe wrong !!!
return Message.GetMessage(deviceAddress, m_action, 0x00, 0x00, 0x00);
}
public static byte[] CameraIrisSwitch(uint deviceAddress, Iris action)
{
return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
}
public static byte[] CameraFocus(uint deviceAddress, Focus action)
{
return Message.GetMessage(deviceAddress, (byte)action, 0x00, 0x00, 0x00);
}
public static byte[] CameraZoom(uint deviceAddress, Zoom action)
{
return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, 0x00);
}
public static byte[] CameraTilt(uint deviceAddress, Tilt action, uint speed)
{
if (speed < TiltSpeedMin)
speed = TiltSpeedMin;
if (speed > TiltSpeedMax)
speed = TiltSpeedMax;
return Message.GetMessage(deviceAddress, 0x00, (byte)action, 0x00, (byte)speed);
}
public static byte[] CameraPan(uint deviceAddress, Pan action, uint speed)
{
if (speed < PanSpeedMin)
speed = PanSpeedMin;
if (speed > PanSpeedMax)
speed = PanSpeedMax;
return Message.GetMessage(deviceAddress, 0x00, (byte)action, (byte)speed, 0x00);
}
public static byte[] CameraPanTilt(
uint deviceAddress,
Pan panAction,
uint panSpeed,
Tilt tiltAction,
uint tiltSpeed
)
{
byte[] m_tiltMessage = CameraTilt(deviceAddress, tiltAction, tiltSpeed);
byte[] m_panMessage = CameraPan(deviceAddress, panAction, panSpeed);
byte[] m_bytes = Message.GetMessage(
deviceAddress,
0x00,
(byte)(m_tiltMessage[3] + m_panMessage[3]),
m_panMessage[4],
m_tiltMessage[5]
);
return m_bytes;
}
public static byte[] CameraStop(uint deviceAddress)
{
return Message.GetMessage(deviceAddress, 0x00, 0x00, 0x00, 0x00);
}
#endregion Base Command Set
public struct Message
{
public static byte Address;
public static byte CheckSum;
public static byte Data1,
Data2,
Data3,
Data4;
public static byte[] GetMessage(
uint address,
byte data1,
byte data2,
byte data3,
byte data4
)
{
if (address < 0 & address > 32)
throw new Exception("Protocol Pelco P support 32 devices only");
Address = byte.Parse((address - 1).ToString());
Data1 = data1;
Data2 = data2;
Data3 = data3;
Data4 = data4;
CheckSum = (byte)(STX ^ Address ^ Data1 ^ Data2 ^ Data3 ^ Data4 ^ ETX);
return new byte[] { STX, Address, Data1, Data2, Data3, Data4, ETX, CheckSum };
}
}
}

219
JiLinApp.Docking/Ptz/PtzCmd.cs

@ -0,0 +1,219 @@
using EC.Util.CameraSDK;
using System;
namespace JiLinApp.Docking.Ptz;
public class PtzCmd
{
public static PtzControlType GetControlType(string ctrlStr)
{
return ctrlStr switch
{
"PelcoD" => PtzControlType.PelcoD,
"PelcoP" => PtzControlType.PelcoP,
"HikSdk" => PtzControlType.HikSdk,
_ => PtzControlType.None
};
}
public static PtzCmdType GetCmdType(string cmdStr)
{
return cmdStr switch
{
"Top" => PtzCmdType.Top,
"Down" => PtzCmdType.Down,
"Left" => PtzCmdType.Left,
"Right" => PtzCmdType.Right,
"TopLeft" => PtzCmdType.LeftTop,
"TopRight" => PtzCmdType.RightTop,
"DownLeft" => PtzCmdType.LeftDown,
"DownRight" => PtzCmdType.RightDown,
"Stop" => PtzCmdType.Stop,
"AutoStart" => PtzCmdType.AutoStart,
"AutoStop" => PtzCmdType.AutoStop,
"PresetSet" => PtzCmdType.PresetSet,
"PresetClear" => PtzCmdType.PresetClear,
"PresetGoto" => PtzCmdType.PresetGoto,
_ => PtzCmdType.None
};
}
/// <summary>
/// GetPelcoDCmd
/// GetPelcoPCmd
/// DCamearCmd
/// </summary>
/// <param name="ctrlType"></param>
/// <param name="cmdType"></param>
/// <param name="args"></param>
/// <returns></returns>
public static byte[] GetCmd(PtzControlType ctrlType, PtzCmdType cmdType, object[] args = null)
{
byte[] cmd = ctrlType switch
{
PtzControlType.PelcoD => GetPelcoDCmd(cmdType, args),
PtzControlType.PelcoP => GetPelcoPCmd(cmdType, args),
PtzControlType.DCamera => GetDCameraCmd(cmdType, args),
_ => Array.Empty<byte>(),
};
return cmd;
}
public static byte[] GetPelcoDCmd(PtzCmdType cmdType, object[] args)
{
uint addr = (byte)args[0];
uint panSpeed = 0x2f;
uint tiltSpeed = (uint)(PelcoD.TiltSpeedMax + PelcoD.TiltSpeedMin) / 2;
byte[] cmd = cmdType switch
{
PtzCmdType.Left => PelcoD.CameraPan(addr, PelcoD.Pan.Left, panSpeed),
PtzCmdType.Right => PelcoD.CameraPan(addr, PelcoD.Pan.Right, panSpeed),
PtzCmdType.Top => PelcoD.CameraTilt(addr, PelcoD.Tilt.Up, tiltSpeed),
PtzCmdType.Down => PelcoD.CameraTilt(addr, PelcoD.Tilt.Down, tiltSpeed),
PtzCmdType.LeftTop => PelcoD.CameraPan(addr, PelcoD.Pan.LeftUp, panSpeed),
PtzCmdType.LeftDown => PelcoD.CameraPan(addr, PelcoD.Pan.LeftDown, panSpeed),
PtzCmdType.RightTop => PelcoD.CameraPan(addr, PelcoD.Pan.RightUp, panSpeed),
PtzCmdType.RightDown => PelcoD.CameraPan(addr, PelcoD.Pan.RightDown, panSpeed),
PtzCmdType.Stop => PelcoD.CameraStop(addr),
PtzCmdType.AutoStart => PelcoD.CameraScan(addr, PelcoD.Scan.Auto),
PtzCmdType.AutoStop => PelcoD.CameraScan(addr, PelcoD.Scan.Manual),
PtzCmdType.PresetGoto => PelcoD.Preset(addr, PelcoD.PresetAction.Goto, (byte)args[1]),
_ => Array.Empty<byte>(),
};
return cmd;
}
public static byte[] GetPelcoPCmd(PtzCmdType cmdType, object[] args)
{
uint addr = (byte)args[0];
uint panSpeed = (uint)(PelcoP.PanSpeedMax + PelcoP.PanSpeedMin) / 2;
uint tiltSpeed = (uint)(PelcoP.TiltSpeedMax + PelcoP.TiltSpeedMin) / 2;
byte[] cmd = cmdType switch
{
PtzCmdType.Left => PelcoP.CameraPan(addr, PelcoP.Pan.Left, panSpeed),
PtzCmdType.Right => PelcoP.CameraPan(addr, PelcoP.Pan.Right, panSpeed),
PtzCmdType.Top => PelcoP.CameraTilt(addr, PelcoP.Tilt.Up, tiltSpeed),
PtzCmdType.Down => PelcoP.CameraTilt(addr, PelcoP.Tilt.Down, tiltSpeed),
PtzCmdType.LeftTop => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Left, panSpeed, PelcoP.Tilt.Up, tiltSpeed),
PtzCmdType.LeftDown => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Left, panSpeed, PelcoP.Tilt.Down, tiltSpeed),
PtzCmdType.RightTop => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Right, panSpeed, PelcoP.Tilt.Up, tiltSpeed),
PtzCmdType.RightDown => PelcoP.CameraPanTilt(addr, PelcoP.Pan.Right, panSpeed, PelcoP.Tilt.Down, tiltSpeed),
PtzCmdType.Stop => PelcoP.CameraStop(addr),
PtzCmdType.AutoStart => PelcoP.AutoScan(addr, PelcoP.Action.Start),
PtzCmdType.AutoStop => PelcoP.AutoScan(addr, PelcoP.Action.Stop),
PtzCmdType.PresetGoto => PelcoP.Preset(addr, PelcoP.PresetAction.Goto, (byte)args[1]),
_ => Array.Empty<byte>(),
};
return cmd;
}
public static byte[] GetDCameraCmd(PtzCmdType cmdType, object[] args)
{
double speed = (DCamera.SpeedMax + DCamera.SpeedMin) / 2;
byte[] cmd = cmdType switch
{
PtzCmdType.Left => DCamera.Left(speed),
PtzCmdType.Right => DCamera.Right(speed),
PtzCmdType.Top => DCamera.Up(speed),
PtzCmdType.Down => DCamera.Down(speed),
PtzCmdType.LeftTop => DCamera.LeftUp(speed, speed),
PtzCmdType.LeftDown => DCamera.LeftDown(speed, speed),
PtzCmdType.RightTop => DCamera.RightUp(speed, speed),
PtzCmdType.RightDown => DCamera.RightDown(speed, speed),
PtzCmdType.Stop => DCamera.Stop(),
//PtzCmdType.PresetGoto => DCamera.Up(speed),
_ => Array.Empty<byte>(),
};
return cmd;
}
public static void HikPtzMove(ref HiKSDK sdk, PtzCmdType cmdType, uint[] args)
{
if (sdk == null || args == null) return;
uint[] arr = new uint[args.Length + 1];
args.CopyTo(arr, 1);
switch (cmdType)
{
case PtzCmdType.Left:
arr[0] = HiKOriSDK.PAN_LEFT;
sdk.PtzMove(arr);
break;
case PtzCmdType.Right:
arr[0] = HiKOriSDK.PAN_RIGHT;
sdk.PtzMove(arr);
break;
case PtzCmdType.Top:
arr[0] = HiKOriSDK.TILT_UP;
sdk.PtzMove(arr);
break;
case PtzCmdType.Down:
arr[0] = HiKOriSDK.TILT_DOWN;
sdk.PtzMove(arr);
break;
case PtzCmdType.LeftTop:
arr[0] = HiKOriSDK.UP_LEFT;
sdk.PtzMove(arr);
break;
case PtzCmdType.LeftDown:
arr[0] = HiKOriSDK.DOWN_LEFT;
sdk.PtzMove(arr);
break;
case PtzCmdType.RightTop:
arr[0] = HiKOriSDK.UP_RIGHT;
sdk.PtzMove(arr);
break;
case PtzCmdType.RightDown:
arr[0] = HiKOriSDK.DOWN_RIGHT;
sdk.PtzMove(arr);
break;
case PtzCmdType.AutoStart:
arr[0] = HiKOriSDK.PAN_AUTO;
sdk.PtzMove(arr);
break;
case PtzCmdType.PresetGoto:
arr[0] = HiKOriSDK.GOTO_PRESET;
sdk.PtzPreset(arr);
break;
default:
break;
}
}
}
public enum PtzControlType
{
PelcoD,
PelcoP,
DCamera,
HikSdk,
None,
}
public enum PtzCmdType
{
Top,
Down,
Left,
Right,
LeftTop,
LeftDown,
RightTop,
RightDown,
Stop,
AutoStart,
AutoStop,
PresetSet,
PresetClear,
PresetGoto,
None
}

73
JiLinApp.Docking/VibrateAlarm/Entity/ClientMessage.cs

@ -0,0 +1,73 @@
using System.Collections;
using System.Net.Sockets;
namespace JiLinApp.Docking.VibrateAlarm;
public class ClientMessage
{
public TcpClient client { get; set; }
public TcpAlarmHostTable host { get; set; }
public string IP
{
get
{
if (host != null) return host.ip;
if (client != null) return client.Client.RemoteEndPoint.ToString().Split(':')[0];
return "";
}
}
public string Port
{
get
{
if (host != null) return host.port;
if (client != null) return client.Client.RemoteEndPoint.ToString().Split(':')[1];
return "-1";
}
}
public List<byte> list { get; set; }
public Hashtable sectioTable { get; set; }
public ClientMessage()
{
list = new List<byte>();
host = null;
sectioTable = new Hashtable();
}
public List<byte[]> getMessageList()
{
List<byte[]> msglist = new List<byte[]>();
while (list.Count >= 19)
{
if (list[0] == 0xAA && list[1] == 0xAA)
{
int num = list[17];
if (list.Count < 19 + num)
{
break;
}
else
{
byte[] bytes = new byte[num + 19];
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = list[i];
}
msglist.Add(bytes);
list.RemoveRange(0, num + 19);
}
}
else
{
list.RemoveAt(0);
}
}
return msglist;
}
}

89
JiLinApp.Docking/VibrateAlarm/Entity/DataMessage.cs

@ -0,0 +1,89 @@
using System.Text;
namespace JiLinApp.Docking.VibrateAlarm;
public class DataMessage
{
private byte headA = 0xAA;
private byte headB = 0xAA; //(1)帧头
public int deviceID { get; set; } //(2)设备ID
public string sendIP { get; set; } //(3)原地址
public int sendPort { get; set; }//(3)原地址
public string receiveIP { get; set; }//(4)目标地址
public int receivePort { get; set; }//(4)目标地址
public byte frameNum { get; set; }//(5)帧编号
public byte functionNum { get; set; }//(6)功能码
public byte dataLen { get; set; }//(7)传输数据长度
public byte[] data { get; set; }//(8)传输数据
public byte CRC { get; set; }//(9)CRC8
public void decode(byte[] bytes)
{
deviceID = bytes[2];
sendIP = bytes[3].ToString() + "." + bytes[4].ToString() + "." + bytes[5].ToString() + "." + bytes[6].ToString();
sendPort = bytes[8] * 256 + bytes[7];
receiveIP = bytes[9].ToString() + "." + bytes[10].ToString() + "." + bytes[11].ToString() + "." + bytes[12].ToString();
receivePort = bytes[13] * 256 + bytes[14];
frameNum = bytes[15];
functionNum = bytes[16];
dataLen = bytes[17];
data = new byte[dataLen];
for (int i = 0; i < dataLen; i++)
{
data[i] = bytes[18 + i];
}
CRC = bytes[18 + dataLen];
}
public byte[] encode()
{
byte[] bytes = new byte[19 + dataLen];
bytes[0] = bytes[1] = 0xAA;
bytes[2] = (byte)deviceID;
string[] strs = sendIP.Split('.');
bytes[3] = byte.Parse(strs[0]);
bytes[4] = byte.Parse(strs[1]);
bytes[5] = byte.Parse(strs[2]);
bytes[6] = byte.Parse(strs[3]);
bytes[7] = (byte)(sendPort % 256);
bytes[8] = (byte)(sendPort / 256);
string[] strs2 = receiveIP.Split('.');
bytes[9] = byte.Parse(strs2[0]);
bytes[10] = byte.Parse(strs2[1]);
bytes[11] = byte.Parse(strs2[2]);
bytes[12] = byte.Parse(strs2[3]);
bytes[13] = (byte)(receivePort % 256);
bytes[14] = (byte)(receivePort / 256);
bytes[15] = frameNum;
bytes[16] = functionNum;
bytes[17] = dataLen;
for (int i = 0; i < dataLen; i++)
{
bytes[18 + i] = data[i];
}
bytes[bytes.Length - 1] = CRC8.CRC(bytes, 0, bytes.Length - 1);
Console.WriteLine("发送指令:" + ToHexString(bytes));
return bytes;
}
private string ToHexString(byte[] bytes)
{
string hexString = string.Empty;
if (bytes != null)
{
StringBuilder strB = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
strB.Append(bytes[i].ToString("X2") + " ");
}
hexString = strB.ToString();
}
return hexString;
}
}

14
JiLinApp.Docking/VibrateAlarm/Entity/DataRequest.cs

@ -0,0 +1,14 @@
namespace JiLinApp.Docking.VibrateAlarm;
public class DataRequest
{
public DataMessage request { get; set; }
public DataMessage responce { get; set; }
public DataRequest()
{
responce = null;
request = null;
}
}

57
JiLinApp.Docking/VibrateAlarm/Entity/SectionState.cs

@ -0,0 +1,57 @@
namespace JiLinApp.Docking.VibrateAlarm;
public class SectionState
{
public int deviceID { get; set; }
public string channel { get; set; }
public int online { get; set; }
public string onLine_str
{
get
{
if (online == 0)
{
return "在线";
}
else
{
return "离线";
}
}
}
public int alarm { get; set; }
public string alarm_str
{
get
{
if (alarm == 0)
{
return "消警";
}
else
{
return "报警";
}
}
}
public SectionState(int id, int chan, int state)
{
deviceID = id;
channel = chan.ToString();
online = state % 2;
alarm = state / 2 % 2;
}
public SectionState(int id, int chan, int on, int a)
{
deviceID = id;
channel = chan.ToString();
online = on;
alarm = a;
}
}

20
JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostMessage.cs

@ -0,0 +1,20 @@
using Newtonsoft.Json.Linq;
namespace JiLinApp.Docking.VibrateAlarm;
public class TcpAlarmHostMessage
{
public int Id { get; set; }
public string AlarmId { get; set; }//CID代码
public string AlarmTime { get; set; }//报警时间
/*设备信息*/
public int DeviceID { get; set; }//设备唯一ID
public string ChannelNum { get; set; }//防区号
public string Mode { get; set; }
public string Sensitivity { get; set; }
/*联动信息*/
public bool IsLinked { get; set; }//是否有联动信息
public JArray Linklist { get; set; }
}

16
JiLinApp.Docking/VibrateAlarm/Entity/TcpAlarmHostTable.cs

@ -0,0 +1,16 @@
namespace JiLinApp.Docking.VibrateAlarm;
public class TcpAlarmHostTable
{
public int id { get; set; }
public string name { get; set; }
public string lat { get; set; }
public string lng { get; set; }
public string ip { get; set; }
public string port { get; set; }
}

10
JiLinApp.Docking/VibrateAlarm/Entity/TcpManagerConfig.cs

@ -0,0 +1,10 @@
namespace JiLinApp.Docking.VibrateAlarm;
public class TcpManagerConfig
{
public string ServerIp { get; set; }
public int ServerPort { get; set; }
public int DeviceHeartKeep { get; set; }
}

17
JiLinApp.Docking/VibrateAlarm/Entity/TcpSectionTable.cs

@ -0,0 +1,17 @@
namespace JiLinApp.Docking.VibrateAlarm;
public class TcpSectionTable
{
public int id { get; set; }
public int deviceID { get; set; }
public string name { get; set; }
public string lat { get; set; }
public string lng { get; set; }
public string channel { get; set; }
public string mode { get; set; }
public string sensitivity { get; set; }
}

522
JiLinApp.Docking/VibrateAlarm/Service/AsyncTcpServer.cs

@ -0,0 +1,522 @@
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
namespace JiLinApp.Docking.VibrateAlarm;
public class AsyncTcpServer : IDisposable
{
#region Fields
private TcpListener _listener;
private ConcurrentDictionary<string, TcpClientState> _clients;
private bool _disposed = false;
#endregion Fields
#region Ctors
private byte[] inOptionValues;
/// <summary>
/// 异步TCP服务器
/// </summary>
/// <param name="listenPort">监听的端口</param>
public AsyncTcpServer(int listenPort)
: this(IPAddress.Any, listenPort)
{
uint dummy = 0;
inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
}
/// <summary>
/// 异步TCP服务器
/// </summary>
/// <param name="localEP">监听的终结点</param>
public AsyncTcpServer(IPEndPoint localEP)
: this(localEP.Address, localEP.Port)
{
uint dummy = 0;
inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
}
/// <summary>
/// 异步TCP服务器
/// </summary>
/// <param name="localIPAddress">监听的IP地址</param>
/// <param name="listenPort">监听的端口</param>
public AsyncTcpServer(IPAddress localIPAddress, int listenPort)
{
uint dummy = 0;
inOptionValues = new byte[Marshal.SizeOf(dummy) * 3];
BitConverter.GetBytes((uint)1).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy));
BitConverter.GetBytes((uint)1000).CopyTo(inOptionValues, Marshal.SizeOf(dummy) * 2);
Address = localIPAddress;
Port = listenPort;
Encoding = Encoding.Default;
_clients = new ConcurrentDictionary<string, TcpClientState>();
_listener = new TcpListener(Address, Port);
_listener.AllowNatTraversal(true);
}
#endregion Ctors
#region Properties
/// <summary>
/// 服务器是否正在运行
/// </summary>
public bool IsRunning { get; private set; }
/// <summary>
/// 监听的IP地址
/// </summary>
public IPAddress Address { get; private set; }
/// <summary>
/// 监听的端口
/// </summary>
public int Port { get; private set; }
/// <summary>
/// 通信使用的编码
/// </summary>
public Encoding Encoding { get; set; }
#endregion Properties
#region Server
/// <summary>
/// 启动服务器
/// </summary>
/// <returns>异步TCP服务器</returns>
public AsyncTcpServer Start()
{
return Start(30);
}
/// <summary>
/// 启动服务器
/// </summary>
/// <param name="backlog">服务器所允许的挂起连接序列的最大长度</param>
/// <returns>异步TCP服务器</returns>
public AsyncTcpServer Start(int backlog)
{
if (IsRunning) return this;
IsRunning = true;
_listener.Start(backlog);
ContinueAcceptTcpClient(_listener);
return this;
}
/// <summary>
/// 停止服务器
/// </summary>
/// <returns>异步TCP服务器</returns>
public AsyncTcpServer Stop()
{
if (!IsRunning) return this;
try
{
_listener.Stop();
foreach (var client in _clients.Values)
{
client.TcpClient.Client.Disconnect(false);
}
_clients.Clear();
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("对象注销错误:" + ex.Message);
}
catch (SocketException ex)
{
Console.WriteLine("socket错误:" + ex.Message);
}
IsRunning = false;
return this;
}
private void ContinueAcceptTcpClient(TcpListener tcpListener)
{
try
{
tcpListener.BeginAcceptTcpClient(new AsyncCallback(HandleTcpClientAccepted), tcpListener);
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("对象注销错误:" + ex.Message);
}
catch (SocketException ex)
{
Console.WriteLine("socket错误:" + ex.Message);
}
}
#endregion Server
#region Receive
private void HandleTcpClientAccepted(IAsyncResult ar)
{
if (!IsRunning) return;
TcpListener tcpListener;
TcpClient tcpClient;
try
{
tcpListener = (TcpListener)ar.AsyncState;
tcpClient = tcpListener.EndAcceptTcpClient(ar);
tcpClient.Client.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("对象注销错误:" + ex.Message);
return;
}
if (!tcpClient.Connected) return;
byte[] buffer = new byte[tcpClient.ReceiveBufferSize];
TcpClientState internalClient = new TcpClientState(tcpClient, buffer);
// add client connection to cache
string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString();
_clients.AddOrUpdate(tcpClientKey, internalClient, (n, o) => { return internalClient; });
RaiseClientConnected(tcpClient);
// begin to read data
NetworkStream networkStream = internalClient.NetworkStream;
ContinueReadBuffer(internalClient, networkStream);
// keep listening to accept next connection
ContinueAcceptTcpClient(tcpListener);
}
private void HandleDatagramReceived(IAsyncResult ar)
{
if (!IsRunning) return;
try
{
TcpClientState internalClient = (TcpClientState)ar.AsyncState;
if (!internalClient.TcpClient.Connected) return;
NetworkStream networkStream = internalClient.NetworkStream;
int numberOfReadBytes = 0;
try
{
// if the remote host has shutdown its connection,
// read will immediately return with zero bytes.
numberOfReadBytes = networkStream.EndRead(ar);
}
catch (Exception ex)
{
Console.WriteLine("错误:" + ex.Message);
numberOfReadBytes = 0;
}
if (numberOfReadBytes == 0)
{
// connection has been closed
TcpClientState internalClientToBeThrowAway;
string tcpClientKey = internalClient.TcpClient.Client.RemoteEndPoint.ToString();
_clients.TryRemove(tcpClientKey, out internalClientToBeThrowAway);
RaiseClientDisconnected(internalClient.TcpClient);
return;
}
// received byte and trigger event notification
byte[] receivedBytes = new byte[numberOfReadBytes];
Buffer.BlockCopy(internalClient.Buffer, 0, receivedBytes, 0, numberOfReadBytes);
RaiseDatagramReceived(internalClient, receivedBytes);
// continue listening for tcp datagram packets
ContinueReadBuffer(internalClient, networkStream);
}
catch (InvalidOperationException ex)
{
Console.WriteLine("错误:" + ex.Message);
}
}
private void ContinueReadBuffer(TcpClientState internalClient, NetworkStream networkStream)
{
try
{
networkStream.BeginRead(internalClient.Buffer, 0, internalClient.Buffer.Length, HandleDatagramReceived, internalClient);
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("对象注销错误:" + ex.Message);
}
}
#endregion Receive
#region Events
/// <summary>
/// 接收到数据报文事件
/// </summary>
public event EventHandler<TcpDatagramReceivedEventArgs<byte[]>> DatagramReceived;
private void RaiseDatagramReceived(TcpClientState sender, byte[] datagram)
{
if (DatagramReceived != null)
{
DatagramReceived(this, new TcpDatagramReceivedEventArgs<byte[]>(sender, datagram));
}
}
/// <summary>
/// 与客户端的连接已建立事件
/// </summary>
public event EventHandler<TcpClientConnectedEventArgs> ClientConnected;
/// <summary>
/// 与客户端的连接已断开事件
/// </summary>
public event EventHandler<TcpClientDisconnectedEventArgs> ClientDisconnected;
private void RaiseClientConnected(TcpClient tcpClient)
{
if (ClientConnected != null)
{
ClientConnected(this, new TcpClientConnectedEventArgs(tcpClient));
}
}
private void RaiseClientDisconnected(TcpClient tcpClient)
{
if (ClientDisconnected != null)
{
ClientDisconnected(this, new TcpClientDisconnectedEventArgs(tcpClient));
}
}
#endregion Events
#region Send
private void GuardRunning()
{
if (!IsRunning)
throw new InvalidProgramException("This TCP server has not been started yet.");
}
/// <summary>
/// 发送报文至指定的客户端
/// </summary>
/// <param name="tcpClient">客户端</param>
/// <param name="datagram">报文</param>
public void Send(TcpClient tcpClient, byte[] datagram)
{
GuardRunning();
if (tcpClient == null)
throw new ArgumentNullException("tcpClient");
if (datagram == null)
throw new ArgumentNullException("datagram");
try
{
NetworkStream stream = tcpClient.GetStream();
if (stream.CanWrite)
{
stream.BeginWrite(datagram, 0, datagram.Length, HandleDatagramWritten, tcpClient);
}
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("对象注销错误:" + ex.Message);
}
}
/// <summary>
/// 发送报文至指定的客户端
/// </summary>
/// <param name="tcpClient">客户端</param>
/// <param name="datagram">报文</param>
public void Send(TcpClient tcpClient, string datagram)
{
Send(tcpClient, Encoding.GetBytes(datagram));
}
/// <summary>
/// 发送报文至所有客户端
/// </summary>
/// <param name="datagram">报文</param>
public void SendToAll(byte[] datagram)
{
GuardRunning();
foreach (var client in _clients.Values)
{
Send(client.TcpClient, datagram);
}
}
public ICollection<TcpClientState> GetAllClient()
{
return _clients.Values;
}
/// <summary>
/// 发送报文至所有客户端
/// </summary>
/// <param name="datagram">报文</param>
public void SendToAll(string datagram)
{
GuardRunning();
SendToAll(Encoding.GetBytes(datagram));
}
private void HandleDatagramWritten(IAsyncResult ar)
{
try
{
((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("对象注销错误:" + ex.Message);
}
catch (InvalidOperationException ex)
{
Console.WriteLine("错误:" + ex.Message);
}
catch (IOException ex)
{
Console.WriteLine("错误:" + ex.Message);
}
}
/// <summary>
/// 发送报文至指定的客户端
/// </summary>
/// <param name="tcpClient">客户端</param>
/// <param name="datagram">报文</param>
public void SyncSend(TcpClient tcpClient, byte[] datagram)
{
GuardRunning();
if (tcpClient == null)
throw new ArgumentNullException("tcpClient");
if (datagram == null)
throw new ArgumentNullException("datagram");
try
{
NetworkStream stream = tcpClient.GetStream();
if (stream.CanWrite)
{
stream.Write(datagram, 0, datagram.Length);
}
}
catch (ObjectDisposedException ex)
{
Console.WriteLine("对象注销错误:" + ex.Message);
}
}
/// <summary>
/// 发送报文至指定的客户端
/// </summary>
/// <param name="tcpClient">客户端</param>
/// <param name="datagram">报文</param>
public void SyncSend(TcpClient tcpClient, string datagram)
{
SyncSend(tcpClient, Encoding.GetBytes(datagram));
}
/// <summary>
/// 发送报文至所有客户端
/// </summary>
/// <param name="datagram">报文</param>
public void SyncSendToAll(byte[] datagram)
{
GuardRunning();
foreach (var client in _clients.Values)
{
SyncSend(client.TcpClient, datagram);
}
}
/// <summary>
/// 发送报文至所有客户端
/// </summary>
/// <param name="datagram">报文</param>
public void SyncSendToAll(string datagram)
{
GuardRunning();
SyncSendToAll(Encoding.GetBytes(datagram));
}
#endregion Send
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources;
/// <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
try
{
Stop();
if (_listener != null)
{
_listener = null;
}
}
catch (SocketException ex)
{
Console.WriteLine("socket错误:" + ex.Message);
}
}
_disposed = true;
}
}
#endregion IDisposable Members
}

49
JiLinApp.Docking/VibrateAlarm/Service/CRC8.cs

@ -0,0 +1,49 @@
namespace JiLinApp.Docking.VibrateAlarm;
public class CRC8
{
/// <summary>
/// CRC8位校验表
/// </summary>
private static byte[] CRC8Table = new byte[] {
0,94,188,226,97,63,221,131,194,156,126,32,163,253,31,65,
157,195,33,127,252,162,64,30, 95,1,227,189,62,96,130,220,
35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,98,
190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,255,
70,24,250,164,39,121,155,197,132,218,56,102,229,187,89,7,
219,133,103,57,186,228,6,88,25,71,165,251,120,38,196,154,
101,59,217,135,4,90,184,230,167,249,27,69,198,152,122,36,
248,166,68,26,153,199,37,123,58,100,134,216,91,5,231,185,
140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
202,148,118,40,171,245,23,73,8,86,180,234,105,55,213,139,
87,9,235,181,54,104,138,212,149,203, 41,119,244,170,72,22,
233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53 };
public static byte CRC(byte[] buffer)
{
return CRC(buffer, 0, buffer.Length);
}
public static byte CRC(byte[] buffer, int off, int len)
{
byte crc = 0;
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
if (off < 0 || len < 0 || off + len > buffer.Length)
{
throw new ArgumentOutOfRangeException();
}
for (int i = off; i < len; i++)
{
crc = CRC8Table[crc ^ buffer[i]];
}
return crc;
}
}

26
JiLinApp.Docking/VibrateAlarm/Service/TcpClientConnectedEventArgs.cs

@ -0,0 +1,26 @@
using System.Net.Sockets;
namespace JiLinApp.Docking.VibrateAlarm;
/// <summary>
/// 与客户端的连接已建立事件参数
/// </summary>
public class TcpClientConnectedEventArgs : EventArgs
{
/// <summary>
/// 与客户端的连接已建立事件参数
/// </summary>
/// <param name="tcpClient">客户端</param>
public TcpClientConnectedEventArgs(TcpClient tcpClient)
{
if (tcpClient == null)
throw new ArgumentNullException("tcpClient");
TcpClient = tcpClient;
}
/// <summary>
/// 客户端
/// </summary>
public TcpClient TcpClient { get; private set; }
}

26
JiLinApp.Docking/VibrateAlarm/Service/TcpClientDisconnectedEventArgs.cs

@ -0,0 +1,26 @@
using System.Net.Sockets;
namespace JiLinApp.Docking.VibrateAlarm;
/// <summary>
/// 与客户端的连接已断开事件参数
/// </summary>
public class TcpClientDisconnectedEventArgs : EventArgs
{
/// <summary>
/// 与客户端的连接已断开事件参数
/// </summary>
/// <param name="tcpClient">客户端</param>
public TcpClientDisconnectedEventArgs(TcpClient tcpClient)
{
if (tcpClient == null)
throw new ArgumentNullException("tcpClient");
TcpClient = tcpClient;
}
/// <summary>
/// 客户端
/// </summary>
public TcpClient TcpClient { get; private set; }
}

47
JiLinApp.Docking/VibrateAlarm/Service/TcpClientState.cs

@ -0,0 +1,47 @@
using System.Net.Sockets;
namespace JiLinApp.Docking.VibrateAlarm;
public class TcpClientState
{
/// <summary>
/// Constructor for a new Client
/// </summary>
/// <param name="tcpClient">The TCP client</param>
/// <param name="buffer">The byte array buffer</param>
public TcpClientState(TcpClient tcpClient, byte[] buffer)
{
if (tcpClient == null) throw new ArgumentNullException("tcpClient");
if (buffer == null) throw new ArgumentNullException("buffer");
TcpClient = tcpClient;
Buffer = buffer;
temp = string.Empty;
}
/// <summary>
/// Gets the TCP Client
/// </summary>
public TcpClient TcpClient { get; private set; }
/// <summary>
/// Gets the Buffer.
/// </summary>
public byte[] Buffer { get; private set; }
/// <summary>
/// TCP接收到但未处理的数据
/// </summary>
public string temp { get; set; }
/// <summary>
/// Gets the network stream
/// </summary>
public NetworkStream NetworkStream
{
get
{
return TcpClient.GetStream();
}
}
}

29
JiLinApp.Docking/VibrateAlarm/Service/TcpDatagramReceivedEventArgs.cs

@ -0,0 +1,29 @@
namespace JiLinApp.Docking.VibrateAlarm;
/// <summary>
/// 接收到数据报文事件参数
/// </summary>
/// <typeparam name="T">报文类型</typeparam>
public class TcpDatagramReceivedEventArgs<T> : EventArgs
{
/// <summary>
/// 接收到数据报文事件参数
/// </summary>
/// <param name="tcpClient">客户端</param>
/// <param name="datagram">报文</param>
public TcpDatagramReceivedEventArgs(TcpClientState tcpClient, T datagram)
{
TcpClient = tcpClient;
Datagram = datagram;
}
/// <summary>
/// 客户端
/// </summary>
public TcpClientState TcpClient { get; private set; }
/// <summary>
/// 报文
/// </summary>
public T Datagram { get; private set; }
}

685
JiLinApp.Docking/VibrateAlarm/Service/TcpManager.cs

@ -0,0 +1,685 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Timer = System.Timers.Timer;
namespace JiLinApp.Docking.VibrateAlarm;
public class TcpManager
{
#region Fields
private JsonSerializerSettings jSetting { get; } = new();
private AsyncTcpServer server { get; set; } = null;
private Timer stateSpanTimer { get; } = new();
private Timer heartTimer { get; } = new();
private List<ClientMessage> list { get; } = new();
#endregion fields
public TcpManager()
{
jSetting.NullValueHandling = NullValueHandling.Ignore;
jSetting.DefaultValueHandling = DefaultValueHandling.Ignore;
}
#region BaseMethod
public void StartServer(TcpManagerConfig config)
{
if (IsRunning()) return;
IPAddress address = IPAddress.Any;
_ = IPAddress.TryParse(config.ServerIp, out address);
server = new AsyncTcpServer(address, config.ServerPort);
server.ClientConnected += server_ClientConnected;
server.ClientDisconnected += server_ClientDisconnected;
server.DatagramReceived += server_DatagramReceived;
server.Start();
heartTimer.Close();
heartTimer.Interval = 1000 * config.DeviceHeartKeep;
heartTimer.Elapsed += HeartTimer_Elapsed;
heartTimer.Enabled = true;
heartTimer.Start();
}
public void StopServer()
{
heartTimer.Enabled = false;
if (IsRunning())
{
server.Stop();
server = null;
}
}
public bool IsRunning()
{
return server != null && server.IsRunning;
}
public bool StartScan(ref string error)
{
if (server == null)
{
error = "服务未创建";
return false;
}
if (!server.IsRunning)
{
error = "服务未运行";
return false;
}
stateSpanTimer.Enabled = true;
return true;
}
public void StopScan()
{
stateSpanTimer.Enabled = false;
}
#endregion BaseMethod
private void StateSpanTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
string error = "";
for (int i = 0; i < list.Count; i++)
{
sendState(list[i], ref error);
}
}
private void HeartTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
string error = "";
for (int i = 0; i < list.Count; i++)
{
sendHeart(list[i], ref error);
}
}
private ClientMessage GetClientMessage(TcpClient client)
{
string clientIP = client.Client.RemoteEndPoint.ToString().Split(':')[0];
for (int i = 0; i < list.Count; i++)
{
if (list[i].IP == clientIP)
{
return list[i];
}
}
return null;
}
private ClientMessage GetClientMessageIP(string clientIP)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].IP == clientIP)
{
return list[i];
}
}
return null;
}
private ClientMessage GetClientMessageDeviceID(int deviceId)
{
for (int i = 0; i < list.Count; i++)
{
if (list[i].host != null && list[i].host.id == deviceId)
{
return list[i];
}
}
return null;
}
public delegate void TCPSectionAlarmOnEvent(TcpAlarmHostMessage msg);
public event TCPSectionAlarmOnEvent OnTcpSectionAlarmOn;
public delegate void TCPSectionStateChangeEvent(SectionState state);
public event TCPSectionStateChangeEvent OnTcpSectionStateChange;
public delegate void TCPDeviceMessageEvent(TcpAlarmHostTable host, string msg);
public event TCPDeviceMessageEvent OnTcpDeviceMessage;
public delegate void TCPSectionMessageEvent(TcpAlarmHostTable host, TcpSectionTable section, string msg);
public event TCPSectionMessageEvent OnTcpSectionMessage;
private void server_DatagramReceived(object sender, TcpDatagramReceivedEventArgs<byte[]> e)
{
string clientIP = e.TcpClient.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
ClientMessage client = GetClientMessage(e.TcpClient.TcpClient);
if (client != null)
{
AnalysisClientMessage(client, e.Datagram);
}
}
public void TestAlarm(string devideId, string channel)
{
ClientMessage message = new ClientMessage();
message.client = new TcpClient("127.0.0.1", 5080);
list.Add(message);
byte[] bytes1 = BitConverter.GetBytes(int.Parse(devideId));
byte[] bytes2 = BitConverter.GetBytes(int.Parse(channel));
byte[] bytes = new byte[24]{
0xAA,0xAA,bytes1[0],bytes1[1],
127,0,0,1,
0x00,0x00,127,0,
0,1,0x00,0x00,
1,0x14,0x04,bytes2[0],
bytes2[1],0x02,0x00,0x00
};
AnalysisClientMessage(message, bytes);
}
private string ToHexString(byte[] bytes)
{
string hexString = string.Empty;
if (bytes != null)
{
StringBuilder strB = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
{
strB.Append(bytes[i].ToString("X2") + " ");
}
hexString = strB.ToString();
}
return hexString;
}
private void AnalysisClientMessage(ClientMessage client, byte[] bytes)
{
client.list.AddRange(bytes);
List<byte[]> msglist = client.getMessageList();
if (msglist != null && msglist.Count > 0)
{
for (int i = 0; i < msglist.Count; i++)
{
Console.WriteLine(client.IP + " 收到数据:" + ToHexString(msglist[i]));
DataMessage mm = new DataMessage();
mm.decode(msglist[i]);
switch (mm.functionNum)
{
case 0x00:
Console.WriteLine(client.IP + " 登录");
if (client.host == null || client.host.id != mm.deviceID)
{
//string error = "";
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "id=" + mm.deviceID, ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
client.host = JsonConvert.DeserializeObject<TcpAlarmHostTable>(arr[0].ToString(), jSetting);
client.host.ip = mm.sendIP;
client.host.port = mm.sendPort.ToString();
}
}
if (OnTcpDeviceMessage != null)
{
if (client.host != null)
{
OnTcpDeviceMessage(client.host, "报警主机登录");
}
else
{
OnTcpDeviceMessage(new TcpAlarmHostTable() { id = mm.deviceID, ip = mm.sendIP, port = mm.sendPort.ToString(), name = "未知设备" }, "报警主机登录");
}
}
break;
case 0x01:
Console.WriteLine(client.IP + " 心跳");
break;
case 0x12:
Console.WriteLine(client.IP + "传感器地址设置响应");
SetDataRequest(mm, 0x02);
break;
case 0x13:
Console.WriteLine(client.IP + "传感器模式设置响应");
SetDataRequest(mm, 0x03);
break;
case 0x14:
Console.WriteLine(client.IP + "传感器状态响应");
int channel = mm.data[0] + mm.data[1] * 256;
int state = mm.data[2] + mm.data[3] * 256;
int online = state % 2;
int alarm = state / 2 % 2;
TcpAlarmHostTable host = new() { id = mm.deviceID, ip = mm.sendIP, port = mm.sendPort.ToString(), name = "未知设备" };
ProcessOnlineEvent(client, host, mm, channel, online);
ProcessAlarmEvent(client, host, mm, channel, alarm);
UpdateOnLineAlarm(client, host, channel, online, alarm);
SetDataRequest(mm, 0x04);
break;
case 0x15:
Console.WriteLine(client.IP + "传感器复位响应");
SetDataRequest(mm, 0x05);
break;
}
}
}
}
private void ProcessOnlineEvent(ClientMessage client, TcpAlarmHostTable host, DataMessage mm, int channel, int online)
{
if (client.sectioTable.ContainsKey(channel))
{
SectionState oldState = client.sectioTable[channel] as SectionState;
if (oldState.online == online) return;
}
TcpAlarmHostTable host1 = client.host == null ? host : client.host;
string error = "";
TcpSectionTable section = new TcpSectionTable() { deviceID = host.id, name = "未知传感器", channel = channel.ToString() };
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID=" + mm.deviceID + "/channel='" + channel + "'", ref error);
JArray arr = new();
if (arr != null && arr.Count > 0) section = JsonConvert.DeserializeObject<TcpSectionTable>(arr[0].ToString(), jSetting);
if (OnTcpSectionMessage != null)
{
OnTcpSectionMessage(host1, section, online == 0 ? "传感器上线" : "传感器离线");
}
}
private void ProcessAlarmEvent(ClientMessage client, TcpAlarmHostTable host, DataMessage mm, int channel, int alarm)
{
if (client.sectioTable.ContainsKey(channel))
{
SectionState oldState = client.sectioTable[channel] as SectionState;
if (oldState.alarm == alarm) return;
}
TcpAlarmHostTable host1 = client.host == null ? host : client.host;
if (alarm == 1)
{
ProcessAlarm(host1.id, channel, alarm);
}
}
private void UpdateOnLineAlarm(ClientMessage client, TcpAlarmHostTable host, int channel, int online, int alarm)
{
if (client.sectioTable.ContainsKey(channel))
{
SectionState oldState = client.sectioTable[channel] as SectionState;
oldState.online = online;
oldState.alarm = alarm;
if (OnTcpSectionStateChange != null)
{
OnTcpSectionStateChange(oldState);
}
}
else
{
TcpAlarmHostTable host1 = client.host == null ? host : client.host;
SectionState state = new SectionState(host1.id, channel, online, alarm);
client.sectioTable[channel] = state;
if (OnTcpSectionStateChange != null)
{
OnTcpSectionStateChange(state);
}
}
}
private void ProcessAlarm(int deviceId, int channel, int alarmId)
{
TcpAlarmHostMessage alarm = new()
{
AlarmId = Convert.ToString(alarmId),
AlarmTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
DeviceID = deviceId,
ChannelNum = channel.ToString()
};
ProcessAlarmDB(alarm);
}
//处理报警事件
private void ProcessAlarmDB(TcpAlarmHostMessage msg)
{
if (OnTcpSectionAlarmOn != null) OnTcpSectionAlarmOn(msg);
}
public void SetDataRequest(DataMessage msg, byte functionNum)
{
lock (this)
{
for (int i = 0; i < reqlist.Count; i++)
{
if (reqlist[i].request.functionNum == functionNum && reqlist[i].request.frameNum == msg.frameNum)
{
reqlist[i].responce = msg;
}
}
}
}
public bool SendMessage(string IP, byte[] bytes, ref string error)
{
if (server == null)
{
error = "服务未创建";
return false;
}
if (!server.IsRunning)
{
error = "服务未运行";
return false;
}
ClientMessage client = GetClientMessageIP(IP);
if (client != null)
{
server.Send(client.client, bytes);
return true;
}
else
{
error = "主机未连接";
return false;
}
}
private List<DataRequest> reqlist = new List<DataRequest>();
private byte frameNumber = 0;
public bool sendRequest(ref DataRequest request, ref string error)
{
if (request.request == null)
{
error = "请求信息未填写";
return false;
}
//int waitTime = int.Parse(DBCenter.center.GetConfig("WW_TCP_DeviceTimeOut")) * 10;
int waitTime = 100;
request.request.frameNum = frameNumber;
frameNumber++;
bool send = SendMessage(request.request.receiveIP, request.request.encode(), ref error);
if (!send) return false;
reqlist.Add(request);
for (int i = 0; i < waitTime; i++)
{
if (request.responce != null)
{
reqlist.Remove(request);
return true;
}
System.Threading.Thread.Sleep(100);
}
return false;
}
public bool sendNoRequest(DataMessage msg, ref string error)
{
msg.frameNum = frameNumber;
frameNumber++;
return SendMessage(msg.receiveIP, msg.encode(), ref error);
}
public bool sendHeart(ClientMessage client, ref string error)
{
if (client.host == null)
{
error = "报警主机信息缺失";
return false;
}
DataMessage msg = getSendMessageHead(client.host.id, client, 0x01, 1);
msg.data = new byte[] { 0xFF };
return sendNoRequest(msg, ref error);
}
public bool SetSectionAddress(int deviceId, string channel_str, int address, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return false;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x02, 4);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256), (byte)(address % 256), (byte)(address / 256) };
DataRequest request = new DataRequest();
request.request = msg;
bool result = sendRequest(ref request, ref error);
if (result)
{
JObject conlist = new JObject();
conlist.Add("deviceID", deviceId);
conlist.Add("channel", channel_str);
JObject valuelist = new JObject();
valuelist.Add("channel", address.ToString());
//DBCenter.center.UpdateResult("table_TCPSection", valuelist, conlist, ref error);
}
return result;
}
public bool SetSectionMode(int deviceId, string channel_str, byte mode, byte sensitivity, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return false;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x03, 3);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256), (byte)(mode + sensitivity * 8) };
DataRequest request = new DataRequest();
request.request = msg;
bool result = sendRequest(ref request, ref error);
if (result)
{
JObject conlist = new JObject();
conlist.Add("deviceID", deviceId);
conlist.Add("channel", channel_str);
JObject valuelist = new JObject();
valuelist.Add("mode", mode.ToString());
valuelist.Add("sensitivity", sensitivity.ToString());
//DBCenter.center.UpdateResult("table_TCPSection", valuelist, conlist, ref error);
}
return result;
}
public bool SetSectionReset(int deviceId, string channel_str, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return false;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x05, 2);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
DataRequest request = new DataRequest();
request.request = msg;
return sendRequest(ref request, ref error);
}
public SectionState SetSectionCheck(int deviceId, string channel_str, ref string error)
{
ClientMessage client = GetClientMessageDeviceID(deviceId);
if (client == null)
{
error = "此主机号不在线";
return null;
}
DataMessage msg = getSendMessageHead(deviceId, client, 0x04, 2);
int channel = int.Parse(channel_str);
msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
DataRequest request = new DataRequest();
request.request = msg;
bool result = sendRequest(ref request, ref error);
if (result)
{
int channel2 = request.responce.data[0] + request.responce.data[1] * 256;
int state2 = request.responce.data[2] + request.responce.data[3] * 256;
return new SectionState(deviceId, channel2, state2);
}
else
{
return null;
}
}
public List<SectionState> SetDeviceCheck(int deviceId, ref string error)
{
List<SectionState> list = new List<SectionState>();
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID=" + deviceId, ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
for (int i = 0; i < arr.Count; i++)
{
string channel = arr[i]["channel"].ToString();
SectionState state = SetSectionCheck(deviceId, channel, ref error);
if (state == null)
{
state = new SectionState(deviceId, int.Parse(channel), -1, -1);
}
list.Add(state);
}
}
else
{
error = "数据库中没有防区信息";
}
return list;
}
public List<SectionState> SetAllCheck(ref string error)
{
List<SectionState> list = new List<SectionState>();
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "", ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
for (int i = 0; i < arr.Count; i++)
{
int deviceId = int.Parse(arr[i]["id"].ToString());
list.AddRange(SetDeviceCheck(deviceId, ref error));
}
}
return list;
}
private DataMessage getSendMessageHead(int deviceId, ClientMessage client, byte fun_num, byte datalen)
{
//DataMessage msg = new DataMessage();
//msg.deviceID = deviceId;
//msg.sendIP = DBCenter.center.GetConfig("WW_TCP_ServeIP");
//msg.sendPort = int.Parse(DBCenter.center.GetConfig("WW_TCP_ServePort"));
//msg.receiveIP = client.IP;
//msg.receivePort = int.Parse(client.Port);
//msg.functionNum = fun_num;
//msg.dataLen = datalen;
//return msg;
return null;
}
public void sendState(ClientMessage client, ref string error)
{
//if (client.host == null)
//{
// error = "报警主机信息缺失";
// return;
//}
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPSection", "deviceID='" + client.host.id + "'", ref error);
//if (arr != null && arr.Count > 0)
//{
// for (int i = 0; i < arr.Count; i++)
// {
// DataMessage msg = getSendMessageHead(client.host.id, client, 0x04, 2);
// int channel = int.Parse(arr[i]["channel"].ToString());
// msg.data = new byte[] { (byte)(channel % 256), (byte)(channel / 256) };
// sendNoRequest(msg, ref error);
// }
//}
}
private void server_ClientDisconnected(object sender, TcpClientDisconnectedEventArgs e)
{
string clientIP = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
Console.WriteLine(clientIP + "下线");
ClientMessage client = GetClientMessage(e.TcpClient);
if (client != null)
{
list.Remove(client);
if (OnTcpDeviceMessage != null)
{
if (client.host != null)
{
OnTcpDeviceMessage(client.host, "报警主机掉线");
}
else
{
OnTcpDeviceMessage(new TcpAlarmHostTable() { id = -1, ip = clientIP, port = client.Port, name = "未知设备" }, "报警主机掉线");
}
}
}
}
private void server_ClientConnected(object sender, TcpClientConnectedEventArgs e)
{
string error = "";
string clientIP = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[0];
string port = e.TcpClient.Client.RemoteEndPoint.ToString().Split(':')[1];
Console.WriteLine(clientIP + "上线");
ClientMessage client = GetClientMessage(e.TcpClient);
if (client == null)
{
ClientMessage msg = new ClientMessage();
msg.client = e.TcpClient;
//JArray arr = DBCenter.center.SearchByConditionJArray("table_TCPAlarmHost", "IP='" + clientIP + "'", ref error);
JArray arr = new();
if (arr != null && arr.Count > 0)
{
msg.host = JsonConvert.DeserializeObject<TcpAlarmHostTable>(arr[0].ToString(), jSetting);
}
list.Add(msg);
if (OnTcpDeviceMessage != null)
{
if (msg.host != null)
{
OnTcpDeviceMessage(msg.host, "报警主机上线");
}
else
{
OnTcpDeviceMessage(new TcpAlarmHostTable() { id = -1, ip = clientIP, port = client.Port, name = "未知设备" }, "报警主机上线");
}
}
}
}
public List<SectionState> getOnlineState(int deviceId)
{
ClientMessage msg = GetClientMessageDeviceID(deviceId);
if (msg != null)
{
return msg.sectioTable.Values as List<SectionState>;
}
else
{
return new List<SectionState>();
}
}
}

2198
JiLinApp.Docking/config/alarmcode.json

File diff suppressed because it is too large

14
JiLinApp.sln

@ -5,7 +5,11 @@ VisualStudioVersion = 17.4.33205.214
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JiLinApp", "JiLinApp\JiLinApp.csproj", "{273E34C9-ED30-460E-BA9A-66A8F27CC5FE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EC.Util", "EC.Util\EC.Util.csproj", "{A41E47C9-1930-4FF0-955E-B91EC859D262}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EC.Util", "EC.Util\EC.Util.csproj", "{A41E47C9-1930-4FF0-955E-B91EC859D262}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiLinApp.Docking", "JiLinApp.Docking\JiLinApp.Docking.csproj", "{B664DFEE-E137-44AC-A766-95D384E3F70B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JiLinApp.Biz", "JiLinApp.Biz\JiLinApp.Biz.csproj", "{7CE63A50-C92C-4554-8E0C-F7BED355C1FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -21,6 +25,14 @@ Global
{A41E47C9-1930-4FF0-955E-B91EC859D262}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A41E47C9-1930-4FF0-955E-B91EC859D262}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A41E47C9-1930-4FF0-955E-B91EC859D262}.Release|Any CPU.Build.0 = Release|Any CPU
{B664DFEE-E137-44AC-A766-95D384E3F70B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B664DFEE-E137-44AC-A766-95D384E3F70B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B664DFEE-E137-44AC-A766-95D384E3F70B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B664DFEE-E137-44AC-A766-95D384E3F70B}.Release|Any CPU.Build.0 = Release|Any CPU
{7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7CE63A50-C92C-4554-8E0C-F7BED355C1FD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Loading…
Cancel
Save