diff --git a/ConsoleTest.sln b/ConsoleTest.sln new file mode 100644 index 0000000..94b5397 --- /dev/null +++ b/ConsoleTest.sln @@ -0,0 +1,63 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32901.215 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleTest", "ConsoleTest\ConsoleTest.csproj", "{37FD52CA-308E-4CC4-9E9F-4072E1C1C216}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EC.Helper", "EC.Helper\EC.Helper.csproj", "{83B3DB14-D962-4F46-977D-DA5B81D3248B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "UnitTest\UnitTest.csproj", "{66782776-2FCE-4DCE-AF5A-798C8E56F378}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x86 = Debug|x86 + HXFFFFFFFFFFF|Any CPU = HXFFFFFFFFFFF|Any CPU + HXFFFFFFFFFFF|x86 = HXFFFFFFFFFFF|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.Debug|x86.ActiveCfg = Debug|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.HXFFFFFFFFFFF|Any CPU.ActiveCfg = Release|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.HXFFFFFFFFFFF|Any CPU.Build.0 = Release|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.HXFFFFFFFFFFF|x86.ActiveCfg = Release|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.HXFFFFFFFFFFF|x86.Build.0 = Release|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.Release|Any CPU.Build.0 = Release|Any CPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216}.Release|x86.ActiveCfg = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Debug|x86.ActiveCfg = Debug|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Debug|x86.Build.0 = Debug|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.HXFFFFFFFFFFF|Any CPU.ActiveCfg = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.HXFFFFFFFFFFF|Any CPU.Build.0 = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.HXFFFFFFFFFFF|x86.ActiveCfg = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.HXFFFFFFFFFFF|x86.Build.0 = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Release|Any CPU.Build.0 = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Release|x86.ActiveCfg = Release|Any CPU + {83B3DB14-D962-4F46-977D-DA5B81D3248B}.Release|x86.Build.0 = Release|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Debug|Any CPU.Build.0 = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Debug|x86.ActiveCfg = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Debug|x86.Build.0 = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.HXFFFFFFFFFFF|Any CPU.ActiveCfg = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.HXFFFFFFFFFFF|Any CPU.Build.0 = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.HXFFFFFFFFFFF|x86.ActiveCfg = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.HXFFFFFFFFFFF|x86.Build.0 = Debug|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Release|Any CPU.ActiveCfg = Release|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Release|Any CPU.Build.0 = Release|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Release|x86.ActiveCfg = Release|Any CPU + {66782776-2FCE-4DCE-AF5A-798C8E56F378}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5932126B-188B-4B1C-A213-C558A7CB5A9A} + EndGlobalSection +EndGlobal diff --git a/ConsoleTest.sln.DotSettings b/ConsoleTest.sln.DotSettings new file mode 100644 index 0000000..c03f35c --- /dev/null +++ b/ConsoleTest.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/ConsoleTest/App.config b/ConsoleTest/App.config new file mode 100644 index 0000000..9d6519d --- /dev/null +++ b/ConsoleTest/App.config @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/FingerPrint/FingerPrintManager.cs b/ConsoleTest/AutoWeight/FingerPrint/FingerPrintManager.cs new file mode 100644 index 0000000..79d9252 --- /dev/null +++ b/ConsoleTest/AutoWeight/FingerPrint/FingerPrintManager.cs @@ -0,0 +1,204 @@ +using System.Text; + +namespace ConsoleTest.AutoWeight.FingerPrint +{ + /// + /// 暂时只测试了 USB 接口 + /// + public class FingerPrintManager + { + //连接参数 + private readonly FingerPrintParam _fpParam; + + //通讯句柄 + private int _handle; + + //返回码 + private int _ret; + + public FingerPrintManager() + { + _fpParam = new FpUsbParam(); + } + + public FingerPrintManager(FingerPrintParam fpParam) + { + _fpParam = fpParam; + } + + #region Start & Stop Server + + /// + /// 开启服务 + /// + /// + public bool StartServer() + { + _ret = TesoLiveSDK.TcCreateHDL(_fpParam.Port, _fpParam.NPort, _fpParam.NRidx, _fpParam.NSped); + _handle = _ret; + return _ret >= 0; + } + + /// + /// 停止服务 + /// + /// + public bool StopServer() + { + if (!IsConnected()) + return true; + _ret = TesoLiveSDK.TcDeleteHDL(_handle); + if (_ret < 0) + return false; + _handle = -1; + return true; + } + + #endregion Start & Stop Server + + #region Tool Methods + + /// + /// 获取设备内核号 + /// + /// + /// + public bool GetDevKerNel(ref string data) + { + if (!IsConnected()) + return false; + var builder = new StringBuilder(); + _ret = TesoLiveSDK.TcGetDevVsin(_handle, builder); + data = _ret >= 0 ? builder.ToString() : string.Empty; + return _ret >= 0; + } + + /// + /// 获取设备序列号 + /// + /// + /// + public bool GetDevSn(ref string data) + { + if (!IsConnected()) + return false; + var builder = new StringBuilder(); + _ret = TesoLiveSDK.TcReadDevSn(_handle, builder); + data = _ret >= 0 ? builder.ToString() : string.Empty; + return _ret >= 0; + } + + /// + /// 注册窗体默认开启 + /// + /// + /// + public bool SetRegBoxAble(bool able) + { + if (!IsConnected()) + return false; + var nIdx = 16;//#define T_SHOWREG 16 弹出注册窗体 + var nVal = able ? 1 : 0; + _ret = TesoLiveSDK.TcExtnEntry(_handle, 0, nIdx, nVal, null); + return _ret >= 0; + } + + /// + /// 认证窗体默认关闭 + /// + /// + /// + public bool SetVerBoxAble(bool able) + { + if (!IsConnected()) + return false; + var nIdx = 17;//#define T_SHOWVER 17 弹出认证窗体 + var nVal = able ? 1 : 0; + _ret = TesoLiveSDK.TcExtnEntry(_handle, 0, nIdx, nVal, null); + return _ret >= 0; + } + + /// + /// 控制设备上的 LED 闪灯和 BUZZER 蜂鸣,声光同时提示 + /// + /// 0=短嘀,1=长嘀,2=嘀嘀 + /// + public bool SetBeepLight(int mode) + { + if (!IsConnected()) + return false; + mode %= 3; + _ret = TesoLiveSDK.TcBeepLight(_handle, mode); + return _ret >= 0; + } + + /// + /// 获取指纹模板 + /// + /// + /// + public bool GetRegFingerPrint(ref string regFp) + { + if (!IsConnected()) + return false; + var builder = new byte[513]; + _ret = TesoLiveSDK.TcDoTemplet(_handle, builder); + regFp = Encoding.ASCII.GetString(builder).Trim('\0'); + return _ret >= 0; + } + + /// + /// 获取指纹特征 + /// + /// + /// + public bool GetVerFingerPrint(ref string verFp) + { + if (!IsConnected()) + return false; + var builder = new byte[513]; + _ret = TesoLiveSDK.TcDoFeature(_handle, builder); + verFp = Encoding.ASCII.GetString(builder).Trim('\0'); + return _ret >= 0; + } + + /// + /// 对比指纹模板和特征 + /// + /// + /// + /// + public bool MatchFingerPrint(string regFp, string verFp) + { + if (!IsConnected()) + return false; + if (string.IsNullOrEmpty(regFp) || string.IsNullOrEmpty(verFp)) + return false; + _ret = TesoLiveSDK.TcSafeMatch(_handle, verFp, regFp); + return _ret >= 0; + } + + /// + /// 判断设备是否连接 + /// + /// + public bool IsConnected() + { + if (_handle <= 0) + return false; + + return true; + } + + /// + /// 返回函数运行返回码 + /// + /// 返回码 + public int GetResultCode() + { + return _ret; + } + + #endregion Tool Methods + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/FingerPrint/FingerPrintParam.cs b/ConsoleTest/AutoWeight/FingerPrint/FingerPrintParam.cs new file mode 100644 index 0000000..55eb8a0 --- /dev/null +++ b/ConsoleTest/AutoWeight/FingerPrint/FingerPrintParam.cs @@ -0,0 +1,71 @@ +namespace ConsoleTest.AutoWeight.FingerPrint +{ + /// + /// 基础连接参数 + /// + public class FingerPrintParam + { + /// + /// 协议号(USB=0,COM=2) + /// + public int NPort { get; set; } + + /// + /// 端口号 通讯端口号(USB=0,COM=[1, 255]) + /// + public int Port { get; set; } + + /// + /// 波特率索引号(波特率级别,默认给 3,即 9600,如表 1 所示) + /// + public int NRidx { get; set; } + + /// + /// 串口是否提速(USB=0,COM=2) + /// + public int NSped { get; set; } + + public bool IsUsb() + { + return NPort.Equals(0); + } + + public bool IsCom() + { + return NPort.Equals(2); + } + + public int GetPortType() + { + return NPort.Equals(0) ? 0 : 1; + } + } + + /// + /// USB 连接参数 + /// + public class FpUsbParam : FingerPrintParam + { + public FpUsbParam() + { + NPort = 0; + Port = 0; + NRidx = 3; + NSped = 0; + } + } + + /// + /// Com 连接参数 + /// + public class FpComParam : FingerPrintParam + { + public FpComParam() + { + NPort = 2; + Port = 1; + NRidx = 3; + NSped = 2; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/FingerPrint/TesoLiveSDK.cs b/ConsoleTest/AutoWeight/FingerPrint/TesoLiveSDK.cs new file mode 100644 index 0000000..29f27f0 --- /dev/null +++ b/ConsoleTest/AutoWeight/FingerPrint/TesoLiveSDK.cs @@ -0,0 +1,294 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace ConsoleTest.AutoWeight.FingerPrint +{ + /// + /// 指纹动态库有两套独立的对外接口,一套是简单接口,一套是复杂接口; + /// 简单接口以函数名 FPI 开始,调用接口较少,开发者不用关心底层调用,直接调用对外接口即可,使用非常简单。但是这种方式相呆板,不能够进行配置。 + /// 复杂接口以函数名 Tc 开始,调用接口较多,需要自己对指纹设备或者算法进行控制,当然,也可以使用默认值。复杂接口可以非常灵活的使用,可以对一些功能进行配置,例如,是否显示对话框,配置超时时间等功能。 + /// + public class TesoLiveSDK + { + #region FPI(No Test) + + /// + /// 获得注册指纹模板。驱动 USB 指纹设备时,可以获得图像 + /// + /// 端口号,0=USB,1=COM1,2=COM2,3=COM3... + /// 输出的 B64 模板缓冲,最大 513 字节(含'\0'结束符) + /// 返回注册指纹模板实际长度(不含'\0'结束符) + /// 返回出错时字符串信息,最大 64 字节(含'\0'结束符) + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int FPIGetTemplate(int nPort, byte[] pRegBuf, ref int pnRegLen, byte[] pszErrMsg); + + //public static extern int FPIGetTemplate(int nPort, ref string pRegBuf, ref int pnRegLen, ref string pszErrMsg); + + //int FPIGetTemplate(int nPort, char* pRegBuf, int* pnRegLen, char* pszErrMsg); + + /// + /// 获得验证用的指纹特征;驱动 USB 指纹设备时,可以获得图像 + /// + /// 端口号,0=USB,1=COM1,2=COM2,3=COM3... + /// 输出的 B64 特征缓冲,最大 513 字节(含'\0'结束符) + /// 返回验证指纹特征实际长度(不含'\0'结束符) + /// 返回出错时字符串信息,最大 64 字节(含'\0'结束符) + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int FPIGetFeature(int nPort, ref byte pVerBuf, ref int pnVerLen, ref byte pszErrMsg); + + //int FPIGetFeature(int nPort, char* pVerBuf, int* pnVerLen, char* pszErrMsg); + + /// + /// 比对采集时得到的模板和特征数据,可指定安全级 + /// + /// 输入的 B64 模板数据,最大 513 字节(含'\0'结束符) + /// 输入的 B64 特征数据,最大 513 字节(含'\0'结束符) + /// 全级别,数字[1, 5],默认为 3 级别 + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int FPIMatch(string pRegBuf, string pVerBuf, int nLevel = 3); + + //int FPIMatch(const char* pRegBuf, const char* pVerBuf,int nLevel); + + /// + /// 取得指纹图像 + /// + /// 要取得指纹图像的索引数字[1, 3] + /// 成功时:返回B64编码纯数据区图像,失败时:返回NULL + [DllImport("TesoLive.dll")] + public static extern string FPIGetImageData(int nImageIdx); + + //char* FPIGetImageData(int nImageIdx); + + /// + /// 通过前期采集的一幅指纹图象数据,产生验证用特征数据 + /// + /// B64 编码图像,请参见 FPIGetImageData 函数中的说明 + /// 输出的B64特征缓冲,最大513字节(含'\0'结束符) + /// 返回验证指纹特征实际长度(不含'\0'结束符) + /// 返回出错时字符串信息,最大 64 字节(含'\0'结束符) + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int FPIGetFeatureByImg(string pImg, ref byte pVerBuf, ref int pnVerLen, ref byte pszErrMsg); + + //int FPIGetFeatureByImg(const char* pImg,char* pVerBuf, int* pnVerLen,char* pszErrMsg); + + /// + /// 通过前期采集的三幅指纹图象数据,产生注册用模版数据 + /// + /// B64 编码图像 1,请参见 FPIGetImageData 函数中的说明 + /// B64 编码图像 2,请参见 FPIGetImageData 函数中的说明 + /// B64 编码图像 3,请参见 FPIGetImageData 函数中的说明 + /// 输出的B64模板缓冲,最大513字节(含'\0'结束符) + /// 返回注册指纹模板实际长度(不含'\0'结束符) + /// 返回出错时字符串信息,最大 64 字节(含'\0'结束符) + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int FPIGetTemplateByImg(string pImg1, string pImg2, string pImg3, ref byte pRegBuf, ref int pnRegLen, ref byte pszErrMsg); + + //int FPIGetTemplateByImg(const char* pImg1, const char* pImg2, const char* pImg3, char* pRegBuf, int* pnRegLen,char* pszErrMsg); + + #endregion FPI(No Test) + + #region Tc(Test) + + /// + /// 创建通讯句柄,并初始化环境 + /// + /// 通讯端口号(USB=0,COM=[1, 255]) + /// 协议号(USB=0,COM=2) + /// 索引号(波特率级别,默认给 3,如表 1 所示) + /// 串口是否提速(如果是 USB 则,该值为 0,如果是串口,则该值为 2) + /// 成功时:返回值大于等于0(句柄),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcCreateHDL(int port, int nPort, int nRidx, int nSped); + + //int TcCreateHDL(int Port, int nPort, int nRidx, int nSped); + + /// + /// 释放句柄所占用资源,若设备已连接则会自行断开 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcDeleteHDL(int vHdl); + + //int TcDeleteHDL(int vHdl); + + /// + /// 连接设备,等待用户按捺 3 或者 4 次直到超时(超时默认 30 秒),成功后返回模板 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 返回的模板数据(最大不会超过 513 字节) + /// 成功时:返回值大于等于0(模板长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcDoTemplet(int vHdl, byte[] hTpl); + + //int TcDoTemplet(int vHdl, void* hTpl); + + /// + /// 连接设备,等待用户按捺一次直到超时(默认超时 18 秒),成功后返回特征 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 返回的特征数据(最大不会超过 513 字节) + /// 成功时:返回值大于等于0(特征长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcDoFeature(int vHdl, byte[] hFea); + + //int TcDoFeature(int vHdl, void* hFea); + + /// + /// 基于安全级别,比对给定的特征和模板,判断它俩是否匹配 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄(一般传 0 值即可) + /// 指纹特征数据 + /// 指纹模板数据 + /// 安全等级[1-5] + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcSafeMatch(int vHdl, string hFea, string hTpl, int nLvl = 3); + + //int TcSafeMatch(int vHdl, const void* hFea,const void* hTpl, int nLvl); + + /// + /// 配置是否弹出对话框,采集指纹特征超时时间等 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 操作方向(0=设定新值,1=读取配置值) + /// 准备要操作的功能代码(详见配置参数宏定义说明) + /// 要配置的新值(详见配置参数宏定义说明) + /// 固定 NULL + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcExtnEntry(int vHdl, int nRead, int nIdx, int nVal, string hVoid); + + //int TcExtnEntry(int vHdl, int nRead, int nIdx, int nVal, void* hVoid); + + /// + /// 控制设备上的 LED 闪灯和 BUZZER 蜂鸣,声光同时提示 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 方式:0=短嘀,1=长嘀,2=嘀嘀 + /// 成功时:返回值大于等于0,失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcBeepLight(int vHdl, int nMode); + + //int TcBeepLight(int vHdl, int nMode); + + /// + /// 获取设备的 32 字节的 SN 产品序列号+1 字节'\0' + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 返回的 SN 字符串(建议提供 64 个字节缓存) + /// 成功时:返回值大于等于0( SN 的长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcReadDevSn(int vHdl, StringBuilder chSn); + + //int TcReadDevSn(int vHdl, char* chSn); + + /// + /// 获取内核版本 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 返回的 SN 字符串(建议提供 64 个字节缓存) + /// 成功时:返回值大于等于0( SN 的长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcGetDevVsin(int vHdl, StringBuilder devSn); + + #endregion Tc(Test) + + #region Tc(No Test) + + /// + /// 读取 Win32 的标准 BMP 文件到内存里 + /// + /// 要读取的来源 BMP 文件的路径 + /// 要写入的目标内存缓存区 + /// 固定为 3 + /// 成功时:返回值大于等于0(编码后图像长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcLoadFrBmp(string chFile, IntPtr hFpr, int nStyle); + + //int TcLoadFrBmp(const char* chFile, void* hFpr, int nStyle); + + /// + /// 指定句柄内五个图像缓冲区中的一个,获取图像数据区数据; + /// 在调用此函数前,一定要先调用 TcDoTemplet 或者 TcDoFeature。否则调用失败 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 图像缓冲号[0, 4],特征区号 128+[0, 4] + /// 返回图像或特征数据区数据,如果是图像建议大小 90K 空间大小 + /// 成功时:返回值大于等于0(图像/特征数据长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcGetImgDat(int vHdl, int nIdx, IntPtr hFpr); + + //int TcGetImgDat(int vHdl, int nIdx, void* hFpr); + + /// + /// 另存指纹图像为 Win32 的标准 BMP 文件格式 + /// + /// 要保存的目标 BMP 文件,已存在则覆盖 + /// 由 TcGetImgDat 获取的,将要保存的图像数据 + /// 成功时:返回值大于等于0(保存的 BMP 文件字节大小),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcSaveAsBmp(string chFile, IntPtr hFpr); + + //int TcSaveAsBmp(const char* chFile, const void* hFpr); + + /// + /// 由给定的一枚指纹图像,提取出一枚指纹特征 + /// + /// TcCreateHDL 获取的上下文控制句柄 + /// 由 TcGetImgDat 或者 TcLoadFrBmp 的一枚图像数据 + /// 指纹特征数据(最大 513 字节,非定长) + /// 成功时:返回值大于等于0(特征长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcFeaFrmImg(int vHdl, IntPtr hFpr, StringBuilder hFea); + + //int TcFeaFrmImg(int vHdl, const void* hFpr, void* hFea); + + /// + /// 由给定的四枚指纹 BMP 图像(或特征),合成出一枚指纹模板 + /// + /// 由 TcCreateHDL 获取的上下文控制句柄 + /// 由 TcGetImgDat 或者 TcLoadFrBmp 获取的四枚图像数据 + /// + /// + /// 其中第四枚图像可以传入 NULL + /// 指纹模板数据(最大 513 字节,非定长) + /// 成功时:返回值大于等于0(模板长度),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcTplFrmImg(int vHdl, IntPtr hFp0, IntPtr hFp1, IntPtr hFp2, IntPtr hFp3, StringBuilder hTpl); + + //int TcTplFrmImg(int vHdl, const void* hFp0, const void* hFp1, const void* hFp2, const void* hFp3, void* hTpl); + + /// + /// 给定端口区间,速率,返回首个设备所在的端口号 + /// + /// 要搜索的目标端口区间[],0 为 USB,>=1 为 COM + /// + /// 串口波特率索引号[0, 7],对应为[1200, 115200] + /// 默认 0 + /// BP 盒的前后缀字串儿,可为 NULL,默认用'|'分隔 + /// 成功时:返回值大于等于0(0 为 USB,>=1 为 COM,1-com1,2-com2…),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcWhereAreu(int nBgn, int nEnd, int nRidx, int nMask, string chFix); + + //int TcWhereAreu(int nBgn, int nEnd, int nRidx, int nMask, const char* chFix); + + /// + /// 判断是否有手指按捺(仅限于 USB 设备使用) + /// + /// TcCreateHDL 获取的上下文控制句柄 + /// 成功时:返回值大于等于0(有手指按捺),失败时:返回值小于0(详见函数返回码说明) + [DllImport("TesoLive.dll")] + public static extern int TcChkPressed(int vHdl); + + //int TcChkPressed(int vHdl); + + #endregion Tc(No Test) + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/LedTW/LedTWManager.cs b/ConsoleTest/AutoWeight/LedTW/LedTWManager.cs new file mode 100644 index 0000000..bf1666c --- /dev/null +++ b/ConsoleTest/AutoWeight/LedTW/LedTWManager.cs @@ -0,0 +1,84 @@ +using System; +using System.Text; + +namespace ConsoleTest.AutoWeight.LedTW +{ + public class LedTWManager + { + private byte[] _ip; + private ushort _port; + + public LedTWManager() + { + } + + public LedTWManager(string ip, ushort port) + { + _ip = Encoding.Default.GetBytes(ip); + _port = port; + } + + #region Start & Stop Server + + /// + /// 开启服务 + /// + /// + public void OpenServer() + { + //初始化动态库 + bxdualsdk.bxDual_InitSdk(); + } + + /// + /// 停止服务 + /// + /// + public void CloseServer() + { + //释放动态库 + bxdualsdk.bxDual_ReleaseSdk(); + } + + #endregion Start & Stop Server + + //删除节目 + public static void DeleteProgram() + { + //初始化动态库 + var err = bxdualsdk.bxDual_InitSdk(); + Console.WriteLine($"bxDual_InitSdk:\t{err}"); + var ip = Encoding.Default.GetBytes("192.168.1.155"); + //获取节目列表 + var driBlock = new bxdualsdk.GetDirBlock_G56(); + err = bxdualsdk.bxDual_cmd_ofsReedDirBlock(ip, 5005, ref driBlock); + //获取节目详细信息 + for (var i = 0; i < driBlock.fileNumber; i++) + { + var fileAttr = new bxdualsdk.FileAttribute_G56(); + err = bxdualsdk.bxDual_cmd_getFileAttr(ref driBlock, (ushort)i, ref fileAttr); + Console.WriteLine("fileName:" + Encoding.Default.GetString(fileAttr.fileName)); + //删除指定节目 + err = bxdualsdk.bxDual_cmd_ofsDeleteFormatFile(ip, 5005, 1, fileAttr.fileName); + } + } + + //删除节目 + public bool DeleteAllProgram() + { + //获取节目列表 + var driBlock = new bxdualsdk.GetDirBlock_G56(); + var err = bxdualsdk.bxDual_cmd_ofsReedDirBlock(_ip, _port, ref driBlock); + if (err < 0) + return false; + //获取节目详细信息 + for (var i = 0; i < driBlock.fileNumber; i++) + { + var fileAttr = new bxdualsdk.FileAttribute_G56(); + err = bxdualsdk.bxDual_cmd_getFileAttr(ref driBlock, (ushort)i, ref fileAttr); + err = bxdualsdk.bxDual_cmd_ofsDeleteFormatFile(_ip, _port, 1, fileAttr.fileName); + } + return true; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/LedTW/bxdualsdk.cs b/ConsoleTest/AutoWeight/LedTW/bxdualsdk.cs new file mode 100644 index 0000000..fd1e318 --- /dev/null +++ b/ConsoleTest/AutoWeight/LedTW/bxdualsdk.cs @@ -0,0 +1,3689 @@ +using System; +using System.Runtime.InteropServices; + +namespace ConsoleTest.AutoWeight.LedTW +{ + public class bxdualsdk + { + public enum E_ScreenColor_G56 + { + eSCREEN_COLOR_SINGLE = 1, //单基色 + eSCREEN_COLOR_DOUBLE, //双基色 + eSCREEN_COLOR_THREE, //七彩色 + eSCREEN_COLOR_FULLCOLOR, //全彩色 + } + + public enum E_DoubleColorPixel_G56 : int + { + eDOUBLE_COLOR_PIXTYPE_1 = 1, //双基色1:G+R + eDOUBLE_COLOR_PIXTYPE_2, //双基色2:R+G + } + + public enum E_arrMode : int + { + eSINGLELINE, //单行 + eMULTILINE, //多行 + } + + public enum E_DateStyle : int + { + eYYYY_MM_DD_MINUS, //YYYY-MM-DD + eYYYY_MM_DD_VIRGURE, //YYYY/MM/DD + eDD_MM_YYYY_MINUS, //DD-MM-YYYY + eDD_MM_YYYY_VIRGURE, //DD/MM/YYYY + eMM_DD_MINUS, //MM-DD + eMM_DD_VIRGURE, //MM/DD + eMM_DD_CHS, //MM月DD日 + eYYYY_MM_DD_CHS, //YYYY年MM月DD日 + } + + public enum E_TimeStyle : int + { + eHH_MM_SS_COLON, //HH:MM:SS + eHH_MM_SS_CHS, //HH时MM分SS秒 + eHH_MM_COLON, //HH:MM + eHH_MM_CHS, //HH时MM分 + eAM_HH_MM, //AM HH:MM + eHH_MM_AM, //HH:MM AM + }; + + public enum E_WeekStyle : int + { + eMonday = 1, //Monday + eMon, //Mon. + eMonday_CHS, //星期一 + } + + public enum E_Color_G56 + { + eBLACK, //黑色 + eRED, //红色 + eGREEN, //绿色 + eYELLOW, //黄色 + eBLUE, //蓝色 + eMAGENTA, //品红/洋红 + eCYAN, //青色 + eWHITE, //白色 + } //5代时间区只支持四种颜色 + + public enum E_ClockStyle + { + eLINE, //线形 + eSQUARE, //方形 + eCIRCLE, //圆形 + };//表盘样式 + + public enum E_txtDirection + { + pNORMAL, //正常 + pROTATERIGHT, //向右旋转 + pMIRROR, //镜像 + pROTATELEFT, //向左旋转 + };//图文区文字方向---暂不支持 + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct ConfigFile + { + public byte FileType; //文件类型 + public byte[] ControllerName; // 控制器名称 + private ushort Address; //控制器地址 + public byte Baudrate; /* 串口波特率 + 0x00 –保持原有波特率不变 + 0x01 –强制设置为 9600 + 0x02 –强制设置为 57600*/ + private ushort ScreenWidth; //显示屏宽度 + private ushort ScreenHeight; // 显示屏高度 + public byte Color; /* 显示屏颜色定义 Bit0 表示红, bit1 表示绿, bit2 表示 + 蓝, 对于每一个 Bit, 0 表示灭, 1 表示亮*/ + public byte MirrorMode; // 0x00 –无镜向 0x01 –镜向 + public byte OEPol; //OE 极性,0x00 – OE 低有效 0x01 – OE 高有效 + public byte DAPol; // 数据极性, 0x00 –数据低有效, 0x01 –数据高有效 + public byte RowOrder; /*行序模式, 该值范围为 0-31 + 0-15 代表正序 + 0 代表从第 0 行开始顺序扫描 + 1 代表从第 1 行开始顺序扫描 + ..... + 16-31 代表逆序 + 0 代表从第 0 行开始逆序扫描 + 1 代表从第 1 行开始逆序扫描*/ + public byte FreqPar; /*CLK 分频倍数 + 注意: 针对于 AX 系列, 为后级分频 + 数值为 0~15, 共 16 个等级。*/ + public byte OEWidth; // OE 宽度 + public byte OEAngle; // OE 提前角 + public byte FaultProcessMode; /*控制器的错误处理模式 + 0x00 –自动处理 + 0x01 –手动处理(此模式仅供调试人员 + 使用)*/ + public byte CommTimeoutValue; /*通讯超时设置(单位秒) + 建议值: + 串口– 2S + TCP/IP – 6S + GPRS – 30S*/ + public byte RunningMode; /*控制器运行模式, 具体定义如下: + 0x00 –正常模式 + 0x01 –调试模式*/ + public byte LoggingMode; /*日志记录模式 + 0x00 –无日志 + 0x01 –只对控制器错误及对错误进行 + 的错误进行记录 + 0x02 –对控制器的所有操作进行记 + 录, 包括: 控制器接收的各条指令、 + 发生的错误及错误处理*/ + public byte GrayFlag; /*灰度标志(仅 5Q 卡时有该字节) + 0x00–无灰度 + 0x01–灰度*/ + public byte CascadeMode; /*级联模式: (仅 5Q 卡时有该字节) + 0x00–非级联模式 + 0x01–级联模式*/ + public byte Default_brightness; /*AX 系列控制器专用, 表示上电时, 默 + 认的亮度等级值。 根据不同的屏幕类 + 型有所不同。*/ + public byte HUBConfig; /*HUB 板设置(仅 6E 控制器支持) + 0x00–HUB512 默认项 + 0x01–HUB256*/ + public byte Language; /*控制器多语言显示区。 + 0x00 ----简体中文显示。 + 0x01 ----非中文显示, 控制器显示图 + 形加英文字符。 + 其他值保留。*/ + public byte Backup; // 备用字节 + private ushort CRC16; //整个文件的 CRC16 校验 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct ConfigFile_G6 + { + public byte FileType; //文件类型 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] ControllerName; // 控制器名称 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)] + private byte[] ScreenAddress; //屏幕安装地址限制为 24个字节长度 + + private ushort Address; //控制器地址 + public byte Baudrate; /* 串口波特率 + 0x00 –保持原有波特率不变 + 0x01 –强制设置为 9600 + 0x02 –强制设置为 57600*/ + private ushort ScreenWidth; //显示屏宽度 + private ushort ScreenHeight; // 显示屏高度 + public byte Color; /* 显示屏颜色定义 Bit0 表示红, bit1 表示绿, bit2 表示 + 蓝, 对于每一个 Bit, 0 表示灭, 1 表示亮*/ + public byte modeofdisp; // 6Q 系列显示模式: 0为888, 1为565,对其余控制卡该字节为0 + public byte TipLanguage; //0 表示上位机软件是中文版,底层固件在显示提示信息时需调用内置的中文提示信息 + + //1 表示上位机软件是英文版,底层固件在显示提示信息时需调用内置的英文提示信息 + //255 表示上位机软件是其他语言版,底层固件在显示提示信息时需调用自定义提示信息 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public byte[] Reserved; // 5个备用字节 + + public byte FaultProcessMode; /*控制器的错误处理模式 +0x00 –自动处理 +0x01 –手动处理(此模式仅供调试人员使用)*/ + public byte CommTimeoutValue; /*通讯超时设置(单位秒) +建议值: +串口– 2S +TCP/IP – 6S +GPRS – 30S*/ + public byte RunningMode; /* 控制器运行模式,具体定义如下: +0x00 –正常模式 +0x01 –调试模式*/ + public byte LoggingMode; /*日志记录模式 +0x00 –无日志 +0x01 –只对控制器错误及对错误进行 +的错误进行记录 +0x02 –对控制器的所有操作进行记 +录, 包括: 控制器接收的各条指令、 +发生的错误及错误处理*/ + public byte DevideScreenMode; /*针对 6Q2 卡的分屏模式 +对其余的卡为保留字节 0*/ + public byte Reserved2; //备用字节 + public byte Default_brightness; /*AX 系列控制器专用,表示上电时,默 +认的亮度等级值。其余的控制卡该字 +节为保留字 0*/ + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)] + public byte[] Backup; // 备用值字节 + + public ushort CRC16; //整个文件的 CRC16 校验 + }; + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct Ping_data + { + // 控制器类型 + //小端存储低位在前高位在后, 比如 0x254 反着取,低位表示系列,高位编号 [0x54, 0x02] 【系列,编号】 + public ushort ControllerType; + + // 固件版本号 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] FirmwareVersion; + + // 控制器参数文件状态 0x00 –控制器中没有参数配置文件,以下返回的是控制器的默认参数。 此时, PC 软件应提示用户必须先加载屏参。0x01 –控制器中有参数配置文件 + public byte ScreenParaStatus; + + // 控制器地址 + public ushort uAddress; + + // 波特率 + public byte Baudrate; + + // 屏宽 + public ushort ScreenWidth; + + // 屏高 + public ushort ScreenHeight; + + // 显示屏颜色定义 + public byte Color; + + //当前亮度值 整数1-16 + public byte CurrentBrigtness; + + // 控制器开关机状态 0 关机 1开机? + public byte CurrentOnOffStatus; + + // 扫描配置编号 + public ushort ScanConfNumber; + + // 第一个自己一路数据代几行,其他基本用不上,如有需要可参考协议取相应的字节 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] + public byte[] reversed; + + // 控制器ip地址 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + public byte[] ipAdder; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct heartbeatData + { + public string password; //密码 + public string ip; //控制器IP地址 + public string subNetMask; // 子网掩码 + public string gate; // 网关 + public short port; // 端口 + public string mac; // MAC地址 + public string netID; // 控制器网络ID + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct NetSearchCmdRet + { + //Oint8 CmdGroup; //1 0xA4 命令组 //public byte Cmd; //1 0x83 命令编号 //public ushort Status; //2 控制器状态//public ushort Error; //2 错误状态寄存器//public ushort DataLen; // 2 0xA4 数据长度 + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + public byte[] Mac; //6 Mac 地址 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] IP; //4 控制器 IP 地址 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] SubNetMask; //4 子网掩码 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] Gate; //4 网关 + + //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public ushort Port; //2 端口 + + public byte IPMode; //1 1 表示 DHCP 2 表示手动设置 + public byte IPStatus; //1 0 表示 IP 设置失败 1 表示 IP 设置成功 + public byte ServerMode; //1 0 Bit[0]表示服务器模式是否使能:1 –使能,0 –禁止 Bit[1]表示服务器模式:1 –web 模式,0 –普通模式 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] ServerIPAddress;// 4 服务器 IP 地址 + + public ushort ServerPort; //2 服务器端口号 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] ServerAccessPassword;// 8 服务器访问密码 + + public ushort HeartBeatInterval;//2 20S 心跳时间间隔(单位:秒) + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] CustomID; //12 用户自定义 ID,作为网络 ID 的前半部分,便于用户识别其控制卡 + + //Web 模式下参见下面的数据结构:NetSearchCmdRet_Web 返回下述 5 项的实际值,否则不上传下述 5 项 + //public byte WebUserID[128];// 128 0 WEB 平台用户 id//Oint32 GroupNum;// 4 0 屏幕组号//public byte DomainFlag;// 1 0 域名标志 0 - 无域名,1—域名//public byte DomainName[128];// 128 域名名称 当 DomainFlag 为 1 时下发//public byte WebControllerName[128];// 128 LED00001 WEB 平台控制器名称 + //Web 模式下返回结束 ================================================== + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] BarCode; //16 条形码,作为网络 ID 的后半部分,用以实现网络 ID 的唯一性 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] ControllerType; //2 其中低位字节表示设备系列,而高位字节表示设备编号,例如 BX - 6Q2 应表示为[0x66, 0x02],其它型号依此类推。 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public byte[] FirmwareVersion;// 8 Firmware 版本号 + + public byte ScreenParaStatus; //1 控制器参数文件状态 0x00 –控制器中没有参数配置文件,以下返回的是控制器的默认参数。此时,PC软件应提示用户必须先加载屏参。0x01 –控制器中有参数配置文件 + public ushort Address; //2 0x0001 控制器地址控制器出厂默认地址为 0x0001(0x0000 地址将保留)控制除了对发送给自身地址的数据包进行处理外,还需对广播数据包进行处理。 + public byte Baudrate; //1 0x00 波特率 0x00 –保持原有波特率不变 0x01 –强制设置为 9600 0x02 –强制设置为 57600 + public ushort ScreenWidth; //2 192 显示屏宽度 + public ushort ScreenHeight; //2 96 显示屏高度 + public byte Color; //1 0x01 对于无灰度系统,单色时返回 1,双色时返回 3,三色时返回 7;对于有灰度系统,返回 255 + public byte BrightnessAdjMode;// 1 调亮模式 0x00 –手动调亮 0x01 –定时调亮 0x02 –自动调亮 + public byte CurrentBrigtness; // 1 当前亮度值 + public byte TimingOnOff; //1 Bit0 –定时开关机状态,0 表示无定时开关机,1 表示有定时开关机 + public byte CurrentOnOffStatus;//1 开关机状态 + public ushort ScanConfNumber; //2 扫描配置编号 + public byte RowsPerChanel; //1 一路数据带几行 + public byte GrayFlag; //1 对于无灰度系统,返回 0;对于有灰度系 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] UnitWidth; //2 最小单元宽度 + + public byte modeofdisp; //1 6Q 显示模式 : 0 为 888, 1 为 565,其余卡为 0 + public byte NetTranMode; //1 当该字节为 0 时,网口通讯使用老的模式,即 UDP 和 TCP 均根据下面的PackageMode 字节确定包长,并且 UDP通讯时,将大包分为小包,每发送一小包做一下延时当该字节不为 0 时,网口通讯使用新的模式,即 UDP 的包长等于UDPPackageMode * 8KBYTE,且不再分为小包,将整包数据丢给协议栈TCP 的包长等于 PackageMode * 16KBYTE + public byte PackageMode; //1 包模式。0 小包模式,分包 600 byte。1 大包模式,分包 16K byte。 + public byte BarcodeFlag; //1 是否设置了条码 ID如果设置了,该字节第 0 位为 1,否则为0 + public ushort ProgramNumber; //2 控制器上已有节目个数 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] CurrentProgram; //4 当前节目名 + + public byte ScreenLockStatus; //1 Bit0 –是否屏幕锁定,1b’0 –无屏幕锁定,1b’1 –屏幕锁定 + public byte ProgramLockStatus;//1 Bit0 –是否节目锁定,1b’0 –无节目锁定,1’b1 –节目锁定 + public byte RunningMode; //1 控制器运行模式 + public byte RTCStatus; //1 RTC 状态 0x00 – RTC 异常 0x01 – RTC 正常 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] RTCYear; //2 年 + + public byte RTCMonth; //1 月 + public byte RTCDate; //1 日 + public byte RTCHour; //1 小时 + public byte RTCMinute; //1 分钟 + public byte RTCSecond; //1 秒 + public byte RTCWeek; //1 星期,范围为 1~7,7 表示周日 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] Temperature1; //3 温度传感器当前值 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] Temperature2; //3 温度传感器当前值 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] Humidity; //2 湿度传感器当前值 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] Noise; //2 噪声传感器当前值(除以 10 为当前值)针对 BX - ZS(485) 0xffff 时无效 + + public byte Reserved; //1 保留字节 + public byte LogoFlag; //1 0:表示未设置 Logo 节目 1:表示设置了 Logo 节目 + public ushort PowerOnDelay; //2 0:未设置开机延时 1:开机延时时长 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] WindSpeed; //2 风速(除以 10 为当前值) 0xfffff 时无效 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] WindDirction; //2 风向(当前值) 0xfffff 时无效 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] PM2_5; //2 PM2.5 值(当前值)0xfffff 时无效 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] PM10; //2 PM10 值(当前值)0xfffff 时无效 + + //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] + //public byte[] Reserved2; //24 保留字 + public ushort ExtendParaLen; // 2 0x40 扩展参数长度 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] ControllerName; // 16 LEDCON01 控制器名称限制为 16 个字节长度(全是 0x00 表示屏参丢失,参数无效,上位机空白显示) + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 44)] + public byte[] ScreenLocation; // 44 0 屏幕安装地址限制为 44 个字节长度(全是 0x00 表示屏参丢失,参数无效,上位机空白显示) + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] NameLocalationCRC32;// 4 控制器和屏幕安装地址共 60 个字节的CRC32 校验值,该值是为了便于上位机区分此处 64 个字节是表示控制器名称还是用来表示控制器名称和屏幕安装地址,进而采取不同的处理策略为了保持兼容,下位机不对该值进行验证 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] PM100; //2 风向(当前值) 0xfffff 时无效 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] AtmosphericPressure; //2 PM2.5 值(当前值)0xfffff 时无效 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] illumination; //2 PM10 值(当前值)0xfffff 时无效 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct NetSearchCmdRet_Web + { + //byte CmdGroup; //1 0xA4 命令组 //byte Cmd; //1 0x83 命令编号 //Oint16 Status; //2 控制器状态//Oint16 Error; //2 错误状态寄存器//Oint16 DataLen; // 2 0xA4 数据长度 + + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + // byte Mac[6]; //6 Mac 地址 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + // Ouint8 IP[4]; //4 控制器 IP 地址 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + // Ouint8 SubNetMask[4]; //4 子网掩码 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + // Ouint8 Gate[4]; //4 网关 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + // Ouint8 Port[2]; //2 端口 + //byte IPMode; //1 1 表示 DHCP 2 表示手动设置 + //byte IPStatus; //1 0 表示 IP 设置失败 1 表示 IP 设置成功 + //byte ServerMode; //1 0 Bit[0]表示服务器模式是否使能:1 –使能,0 –禁止 Bit[1]表示服务器模式:1 –web 模式,0 –普通模式 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + // Ouint8 ServerIPAddress[4];// 4 服务器 IP 地址 + // Oint16 ServerPort; //2 服务器端口号 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + // byte ServerAccessPassword[8];// 8 服务器访问密码 + // public ushort HeartBeatInterval;//2 20S 心跳时间间隔(单位:秒) + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + // byte CustomID[12]; //12 用户自定义 ID,作为网络 ID 的前半部分,便于用户识别其控制卡 + // //Web 模式下返回下述 5 项的实际值,否则不上传下述 5 项 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + // byte WebUserID[128]; // 128 0 WEB 平台用户 id + // public int GroupNum; // 4 0 屏幕组号 + //byte DomainFlag; // 1 0 域名标志 0 - 无域名,1—域名 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + // byte DomainName[128]; // 128 域名名称 当 DomainFlag 为 1 时下发 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + // byte WebControllerName[128];// 128 LED00001 WEB 平台控制器名称 + // //Web 模式下返回下述 5 项 结束 ################### + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 18)] + // byte BarCode[16]; //16 条形码,作为网络 ID 的后半部分,用以实现网络 ID 的唯一性 + //Oint16 ControllerType; //2 其中低位字节表示设备系列,而高位字节表示设备编号,例如 BX - 6Q2 应表示为[0x66, 0x02],其它型号依此类推。 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + // byte FirmwareVersion[8];// 8 Firmware 版本号 + //byte ScreenParaStatus; //1 控制器参数文件状态 0x00 –控制器中没有参数配置文件,以下返回的是控制器的默认参数。此时,PC软件应提示用户必须先加载屏参。0x01 –控制器中有参数配置文件 + //Oint16 Address; //2 0x0001 控制器地址控制器出厂默认地址为 0x0001(0x0000 地址将保留)控制除了对发送给自身地址的数据包进行处理外,还需对广播数据包进行处理。 + //byte Baudrate; //1 0x00 波特率 0x00 –保持原有波特率不变 0x01 –强制设置为 9600 0x02 –强制设置为 57600 + //Oint16 ScreenWidth; //2 192 显示屏宽度 + //Oint16 ScreenHeight; //2 96 显示屏高度 + //byte Color; //1 0x01 对于无灰度系统,单色时返回 1,双色时返回 3,三色时返回 7;对于有灰度系统,返回 255 + //byte BrightnessAdjMode;//1 调亮模式 0x00 –手动调亮 0x01 –定时调亮 0x02 –自动调亮 + //byte CurrentBrigtness; //1 当前亮度值 + //byte TimingOnOff; //1 Bit0 –定时开关机状态,0 表示无定时开关机,1 表示有定时开关机 + //byte CurrentOnOffStatus;//1 开关机状态 + //Oint16 ScanConfNumber; //2 扫描配置编号 + //byte RowsPerChanel; //1 一路数据带几行 + //byte GrayFlag; //1 对于无灰度系统,返回 0;对于有灰度系 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + // byte UnitWidth[2]; //2 最小单元宽度 + //byte modeofdisp; //1 6Q 显示模式 : 0 为 888, 1 为 565,其余卡为 0 + //byte NetTranMode; //1 当该字节为 0 时,网口通讯使用老的模式,即 UDP 和 TCP 均根据下面的PackageMode 字节确定包长,并且 UDP通讯时,将大包分为小包,每发送一小包做一下延时当该字节不为 0 时,网口通讯使用新的模式,即 UDP 的包长等于UDPPackageMode * 8KBYTE,且不再分为小包,将整包数据丢给协议栈TCP 的包长等于 PackageMode * 16KBYTE + //byte PackageMode; //1 包模式。0 小包模式,分包 600 byte。1 大包模式,分包 16K byte。 + //byte BarcodeFlag; //1 是否设置了条码 ID如果设置了,该字节第 0 位为 1,否则为0 + //Oint16 ProgramNumber; //2 控制器上已有节目个数 + //int CurrentProgram; //4 当前节目名 + //byte ScreenLockStatus; //1 Bit0 –是否屏幕锁定,1b’0 –无屏幕锁定,1b’1 –屏幕锁定 + //byte ProgramLockStatus;//1 Bit0 –是否节目锁定,1b’0 –无节目锁定,1’b1 –节目锁定 + //byte RunningMode; //1 控制器运行模式 + //byte RTCStatus; //1 RTC 状态 0x00 – RTC 异常 0x01 – RTC 正常 + //Oint16 RTCYear; //2 年 + //byte RTCMonth; //1 月 + //byte RTCDate; //1 日 + //byte RTCHour; //1 小时 + //byte RTCMinute; //1 分钟 + //byte RTCSecond; //1 秒 + //byte RTCWeek; //1 星期,范围为 1~7,7 表示周日 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + // byte Temperature1[3]; //3 温度传感器当前值 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + // byte Temperature2[3]; //3 温度传感器当前值 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + // byte Humidity[2]; //2 湿度传感器当前值 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + // byte Noise[2]; //2 噪声传感器当前值(除以 10 为当前值)针对 BX - ZS(485) 0xffff 时无效 + //byte Reserved; //1 保留字节 + //byte LogoFlag; //1 0:表示未设置 Logo 节目 1:表示设置了 Logo 节目 + //Oint16 PowerOnDelay; //2 0:未设置开机延时 1:开机延时时长 + //Oint16 WindSpeed; //2 风速(除以 10 为当前值) 0xfffff 时无效 + //Oint16 WindDirction; //2 风向(当前值) 0xfffff 时无效 + //Oint16 PM2_5; //2 PM2.5 值(当前值)0xfffff 时无效 + //Oint16 PM10; //2 PM10 值(当前值)0xfffff 时无效 + // //byte Reserved2[24]; //24 保留字 + //Oint16 ExtendParaLen; // 2 0x40 扩展参数长度 + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + // byte ControllerName[16]; // 16 LEDCON01 控制器名称限制为 16 个字节长度(全是 0x00 表示屏参丢失,参数无效,上位机空白显示) + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 44)] + // byte ScreenLocation[44]; // 44 0 屏幕安装地址限制为 44 个字节长度(全是 0x00 表示屏参丢失,参数无效,上位机空白显示) + // [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + // byte NameLocalationCRC32[4];// 4 控制器和屏幕安装地址共 60 个字节的CRC32 校验值,该值是为了便于上位机区分此处 64 个字节是表示控制器名称还是用来表示控制器名称和屏幕安装地址,进而采取不同的处理策略为了保持兼容,下位机不对该值进行验证 + }; + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct TimingOnOff + { + public byte onHour; // 开机小时 + public byte onMinute; // 开机分钟 + public byte offHour; // 关机小时 + public byte offMinute; // 关机分钟 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct Brightness + { + /* + 0x00 –手动调亮 + 0x01 –定时调亮 注:以下的亮度值表,在定时调亮和手 动调亮时控制器才需处理。但在协议上 不论什么模式,此表都需要发送给控制 器 + 0x00 –手动调亮 + 0x01 –定时调亮 注:以下的亮度值表,在定时调亮和手 动调亮时控制器才需处理。但在协议上 不论什么模式,此表都需要发送给控制 器 + */ + public byte BrightnessMode; + + //00:00 – 00:29 的亮度值, 0x00 – 0x0f + public byte HalfHourValue0; + + public byte HalfHourValue1; + public byte HalfHourValue2; + public byte HalfHourValue3; + public byte HalfHourValue4; + public byte HalfHourValue5; + public byte HalfHourValue6; + public byte HalfHourValue7; + public byte HalfHourValue8; + public byte HalfHourValue9; + public byte HalfHourValue10; + public byte HalfHourValue11; + public byte HalfHourValue12; + public byte HalfHourValue13; + public byte HalfHourValue14; + public byte HalfHourValue15; + public byte HalfHourValue16; + public byte HalfHourValue17; + public byte HalfHourValue18; + public byte HalfHourValue19; + public byte HalfHourValue20; + public byte HalfHourValue21; + public byte HalfHourValue22; + public byte HalfHourValue23; + public byte HalfHourValue24; + public byte HalfHourValue25; + public byte HalfHourValue26; + public byte HalfHourValue27; + public byte HalfHourValue28; + public byte HalfHourValue29; + public byte HalfHourValue30; + public byte HalfHourValue31; + public byte HalfHourValue32; + public byte HalfHourValue33; + public byte HalfHourValue34; + public byte HalfHourValue35; + public byte HalfHourValue36; + public byte HalfHourValue37; + public byte HalfHourValue38; + public byte HalfHourValue39; + public byte HalfHourValue40; + public byte HalfHourValue41; + public byte HalfHourValue42; + public byte HalfHourValue43; + public byte HalfHourValue44; + public byte HalfHourValue45; + public byte HalfHourValue46; + public byte HalfHourValue47; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct ControllerStatus_G56 + { + public byte onoffStatus; // 开关机状态 Bit 0 –开机/关机, 0 表示关机, 1 表示开机 + public byte timingOnOff; // 定时开关机状态 0 表示无定时开关机, 1 表示有定时开关机 + public byte brightnessAdjMode; //亮度模式 0x00 –手动调亮 0x01 –定时调亮 0x02 –自动调亮 + public byte brightness;// 当前亮度值 + public short programeNumber;// 控制器上已有节目个数 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] currentProgram;//当前节目名 + + public byte screenLockStatus;//是否屏幕锁定,0 –无屏幕锁定, 1 –屏幕锁定 + public byte programLockStatus; //是否节目锁定, 0 –无节目锁定,1 –节目锁定 + public byte runningMode;//控制器运行模式 + public byte RTCStatus;//RTC 状态0x00 – RTC 异常 0x01 – RTC 正常 + public short RTCYear;//年 + public byte RTCMonth;//月 + public byte RTCDate;//日 + public byte RTCHour;//时 + public byte RTCMinute;//分 + public byte RTCSecond;//秒 + public byte RTCWeek;//星期 1--7 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] temperature1;//温度1传感器当前值 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] temperature2;//温度2传感器当前值 + + public short humidity;//湿度传感器当前值 + public short noise;//噪声传感器当前值 + public byte switchStatus; //测试按钮状态 0 –打开 1 –闭合 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] CustomID; //用户自定义 ID,作为网络 ID 的前半部分,便于用户识别其控制卡 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public byte[] BarCode; //条形码,作为网络 ID 的后半部分,用以实现网络 ID 的唯一性 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct TimingReset + { + public byte rstMode; //复位模式 0x00 –取消定时复位功能 0x01 –周期复位, 此时 RstInterval 字段有效 0x02 –只在指定时间复位 + private uint RstInterval;//复位周期, 单位: 分钟如此字段为 0, 不进行复位操作 + public byte rstHour1; //小时 0Xff–表示此组无效, 下同 + public byte rstMin1; + public byte rstHour2; + public byte rstMin2; + public byte rstHour3; + public byte rstMin3; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct BattleTime + { + public short BattleRTCYear; //年 + public byte BattleRTCMonth;//月 + public byte BattleRTCDate;//日 + public byte BattleRTCHour;//时 + public byte BattleRTCMinute;//分 + public byte BattleRTCSecond;//秒 + public byte BattleRTCWeek;//星期 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQprogrampTime_G56 + { + public byte StartHour; + public byte StartMinute; + public byte StartSecond; + public byte EndHour; + public byte EndMinute; + public byte EndSecond; + };//节目的播放时段 + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQprogramppGrp_G56 + { + public byte playTimeGrpNum; //播放时间有效组数 0 没有播放时段全天播放 最大值8 + public EQprogrampTime_G56 timeGrp0; + public EQprogrampTime_G56 timeGrp1; + public EQprogrampTime_G56 timeGrp2; + public EQprogrampTime_G56 timeGrp3; + public EQprogrampTime_G56 timeGrp4; + public EQprogrampTime_G56 timeGrp5; + public EQprogrampTime_G56 timeGrp6; + public EQprogrampTime_G56 timeGrp7; + };//播放时段共有8组 + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQprogramHeader + { + /* + 默认:0x00 + LOGO文件:0x08 + 扫描配置文件:0x02 + 日志文件:0x06 + 字库文件:0x05 + 提示信息库文件: 0x07 + */ + public byte FileType; //文件类型 + public uint ProgramID;//节目ID + + /* + Bit0 –全局节目标志位 + Bit1 –动态节目标志位 + Bit2 –屏保节目标志位 + */ + public byte ProgramStyle;//节目类型 + + //注:带播放时段的节目优先级为 1,不 带播放时段的节目优先级为 0 + public byte ProgramPriority; //节目等级 + + public byte ProgramPlayTimes;//节目重播放次数 + public ushort ProgramTimeSpan; //播放的方式 + public byte ProgramWeek; //节目星期属性 + public ushort ProgramLifeSpan_sy;//年 + public byte ProgramLifeSpan_sm;//月 + public byte ProgramLifeSpan_sd;//日 + public ushort ProgramLifeSpan_ey;//结束年 + public byte ProgramLifeSpan_em;//结束日 + public byte ProgramLifeSpan_ed;//结束天 + //public byte PlayPeriodGrpNum;//播放时段的组数 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQscreenframeHeader + { + public byte FrameDispFlag; + public byte FrameDispStyle; + public byte FrameDispSpeed; + public byte FrameMoveStep; + public byte FrameWidth; + public ushort FrameBackup; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQareaframeHeader + { + public byte AreaFFlag; + public byte AreaFDispStyle; + public byte AreaFDispSpeed; + public byte AreaFMoveStep; + public byte AreaFWidth; + public ushort AreaFBackup; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQareaHeader + { + /* + 字库区域:0x01 + 透明文本:0x06 + + 时间区:0x02 + + 图文字幕:0x00 + + 战斗时间:0x09 + 噪声区:0x05 + 温度区:0x03 + 霓虹区:0x08 + 湿度区:0x04 + */ + public byte AreaType; //区域类型 + + public ushort AreaX; //区域X坐标 + public ushort AreaY; //区域Y坐标 + public ushort AreaWidth; //区域宽 + public ushort AreaHeight;//区域高 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQpageHeader + { + //请参考协议 图文字幕区数据格式 + public byte PageStyle; //数据页类型 + + public byte DisplayMode; //显示方式 (特效) + public byte ClearMode; // 退出方式/清屏方式 + public byte Speed; // 速度等级/背景速度等级 + public ushort StayTime; // 停留时间, 单位为 10ms + public byte RepeatTime;//重复次数/背景拼接步长(左右拼接下为宽度, 上下拼接为高度) + public ushort ValidLen; //用法比较复杂请参考协议 + public E_arrMode arrMode; //排列方式--单行多行 + public ushort fontSize; //字体大小 + public uint color;//字体颜色 + public byte fontBold; //是否为粗体 + public byte fontItalic;//是否为斜体 + public E_txtDirection tdirection;//文字方向 + public ushort txtSpace; //文字间隔 + public byte Valign; + public byte Halign; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQprogram + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] fileName; //文件名 + + public byte fileType; //文件类型 + public uint fileLen; //文件长度 + public IntPtr fileAddre; // 文件所在的缓存地址 + public uint fileCRC32; //文件CRC32校验码 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct getPageData + { + private ushort allPageNub; + private uint pageLen; + public byte[] fileAddre; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQunitHeader + { + private ushort UnitX; + private ushort UnitY; + public byte UnitType; + public byte Align; + public byte UnitColor; + public byte UnitMode; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQtimeAreaData_G56 + { + public E_arrMode linestyle; //排列方式,单行还是多行 + public uint color; //字体颜色 + public string fontName; //字体名字 + public ushort fontSize; //字体大小 + public byte fontBold; //字体加粗 + public byte fontItalic; //斜体 + public byte fontUnderline; //字体加下划线 + public byte fontAlign; //对齐方式--多行有效 + public byte date_enable; //是否添加日期 + public E_DateStyle datestyle; //日期格式 + public byte time_enable; //是否添加时间---默认添加 + public E_TimeStyle timestyle; //时间格式 + public byte week_enable; //是否添加星期 + public E_WeekStyle weekstyle; //星期格式 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQAnalogClockHeader_G56 + { + public ushort OrignPointX; //原点横坐标 + public ushort OrignPointY; //原点纵坐标 + public byte UnitMode; //表针模式 + public byte HourHandWidth; //时针宽度 + public byte HourHandLen; //时针长度 + public uint HourHandColor; //时针颜色 + public byte MinHandWidth; //分针宽度 + public byte MinHandLen; //分针长度 + public uint MinHandColor; //分针颜色 + public byte SecHandWidth; //秒针宽度 + public byte SecHandLen; //秒针长度 + public uint SecHandColor; //秒针颜色 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQprogramHeader_G6 + { + /* + 默认:0x00 + LOGO文件:0x08 + 扫描配置文件:0x02 + 日志文件:0x06 + 字库文件:0x05 + 提示信息库文件: 0x07 + */ + public byte FileType; //文件类型 + public uint ProgramID;//节目ID + + /* + Bit0 –全局节目标志位 + Bit1 –动态节目标志位 + Bit2 –屏保节目标志位 + */ + public byte ProgramStyle; //节目类型 + + //注:带播放时段的节目优先级为 1,不带播放时段的节目优先级为 0 + public byte ProgramPriority; //节目等级 + + public byte ProgramPlayTimes; //节目重播放次数 + public ushort ProgramTimeSpan; //播放的方式 + public byte SpecialFlag; //特殊节目标 + public byte CommExtendParaLen; //扩展参数长度,默认为0x00 + public ushort ScheduNum; //节目调度 + public ushort LoopValue; //调度规则循环次数 + public byte Intergrate; //调度相关 + public byte TimeAttributeNum; //时间属性组数 + public ushort TimeAttribute0Offset; //第一组时间属性偏移量--目前只支持一组 + public byte ProgramWeek; //节目星期属性 + public ushort ProgramLifeSpan_sy; //年 + public byte ProgramLifeSpan_sm; //月 + public byte ProgramLifeSpan_sd; //日 + public ushort ProgramLifeSpan_ey; //结束年 + public byte ProgramLifeSpan_em; //结束日 + public byte ProgramLifeSpan_ed; //结束天 + public byte PlayPeriodGrpNum; //播放时段的组数 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQscreenframeHeader_G6 + { + public byte FrameDispStype; //边框显示方式 + public byte FrameDispSpeed; //边框显示速度 + public byte FrameMoveStep; //边框移动步长 + public byte FrameUnitLength; //边框组元长度 + public byte FrameUnitWidth; //边框组元宽度 + public byte FrameDirectDispBit;//上下左右边框显示标志位,目前只支持6QX-M卡 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQSound_6G + { + public byte SoundFlag; //1 0x00 是否使能语音播放;0 表示不使能语音; 1 表示播放下文中 SoundData 部分内容; + + //SoundData 部分内容--------------------------------------------------------------------------------------------------------------------------------------------------- + public byte SoundPerson; //1 0x00 发音人 该值范围是 0 - 5,共 6 种选择只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 0 + + public byte SoundVolum; //1 0x05 音量该值范围是 0~10,共 11 种,0表示静音只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 5 + public byte SoundSpeed; //1 0x05 语速该值范围是 0~10,共 11 种只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 5 + public byte SoundDataMode; //1 0x00 SoundData 的编码格式:该值意义如下:0x00 GB2312; 0x01 GBK; 0x02 BIG5; 0x03 UNICODE只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送 + public int SoundReplayTimes; // 4 0x00000000 重播次数该值为 0,表示播放 1 次该值为 1,表示播放 2 次 + + //...... + //该值为 0xffffffff,表示播放无限次只有 SoundFlag(是否使能语播放)为 1 时才发送该字节,否则不发送该值默认为 0 + public int SoundReplayDelay;// 4 0x00000000 重播时间间隔该值表示两次播放语音的时间间隔,单位为 10ms只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 0 + + public byte SoundReservedParaLen;// 1 0x03 语音参数保留参数长度 + public byte Soundnumdeal; // 1 0 0:自动判断1:数字作号码处理 2:数字作数值处理只有当 SoundFlag 为 1 且SoundReservedParaLen不为 0才发送此参数 + public byte Soundlanguages; // 1 0 0:自动判断语种1:阿拉伯数字、度量单位、特殊符号等合成为中文2:阿拉伯数字、度量单位、特殊符号等合成为英文只有当 SoundFlag 为 1 且 SoundReservedParaLen不为 0才发送此参数(目前只支持中英文) + public byte Soundwordstyle; // 1 0 0:自动判断发音方式1:字母发音方式2:单词发音方式;只有当 SoundFlag 为 1 且SoundReservedParaLen不为 0才发送此参数 + public int SoundDataLen; // 4 语音数据长度; 只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送 + public IntPtr SoundData; // N 语音数据只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct ClockColor_G56 + { + public uint Color369; //369点颜色 + public uint ColorDot; //点颜色 + public uint ColorBG; //表盘外圈颜色 模式没有圈泽此颜色无效 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQareaHeader_G6 + { + public byte AreaType; //区域类型 + public ushort AreaX; //区域左上角横坐标 + public ushort AreaY; //区域左上角纵坐标 + public ushort AreaWidth; //区域宽度 + public ushort AreaHeight; //区域高度 + public byte BackGroundFlag; //是否有背景 + public byte Transparency; //透明度 + public byte AreaEqual; //前景、背景区域大小是否相同 + + //语音内容 + //使用语音功能时:部分卡需要配置串口为语音模式!!! + public EQSound_6G stSoundData; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQPicAreaSoundHeader_G6 + { + public byte SoundPerson; //发音人,范围0~5,共6种选择 + public byte SoundVolum; //音量,范围0~10 + public byte SoundSpeed; //语速,范围0~10 + public byte SoundDataMode; //语音数据的编码格式 + public uint SoundReplayTimes; //重播次数 + public uint SoundReplayDelay; //重播时间间隔 + public byte SoundReservedParaLen; //语音参数保留参数长度,默认0x03 + public byte Soundnumdeal; //详情见协议 + public byte Soundlanguages; //详情见协议 + public byte Soundwordstyle; //详情见协议 + }//图文分区播放语音 + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQTimeAreaBattle_G6 + { + public ushort BattleStartYear; //起始年份(BCD格式,下同) + public byte BattleStartMonth; //起始月份 + public byte BattleStartDate; //起始日期 + public byte BattleStartHour; //起始小时 + public byte BattleStartMinute; //起始分钟 + public byte BattleStartSecond; //起始秒钟 + public byte BattleStartWeek; //起始星期值 + public byte StartUpMode; //启动模式 + } //时间分区战斗时间 + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQpageHeader_G6 + { + public byte PageStyle; //数据页类型 + public byte DisplayMode; //显示方式 + public byte ClearMode; //退出方式/清屏方式 + public byte Speed; //速度等级 + public ushort StayTime; //停留时间 + public byte RepeatTime; //重复次数 + public ushort ValidLen; //此字段只在左移右移方式下有效 + public byte CartoonFrameRate; //特技为动画方式时,该值代表其帧率 + public byte BackNotValidFlag; //背景无效标志 + public E_arrMode arrMode; //排列方式--单行多行 + public ushort fontSize; //字体大小 + public uint color; //字体颜色 + public byte fontBold; //是否为粗体 0:false 1:true + public byte fontItalic; //是否为斜体 + public E_txtDirection tdirection; //文字方向 + public ushort txtSpace; //文字间隔 + public byte Valign; + public byte Halign; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQprogram_G6 + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] fileName; //节目参数文件名 + + public byte fileType; //文件类型 + public uint fileLen; //参数文件长度 + public IntPtr fileAddre; //文件所在的缓存地址 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] dfileName;//节目数据文件名 + + public byte dfileType; //节目数据文件类型 + public uint dfileLen; //数据文件长度 + public IntPtr dfileAddre; //数据文件缓存地址 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct GetDirBlock_G56 + { + public byte fileType; //要获取的文件类型 + public ushort fileNumber; //返回有多少个文件 + public IntPtr dataAddre; //返回文件列表地址 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct FileAttribute_G56 + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] fileName; //文件名 + + public byte fileType; //文件类型 + public int fileLen; //文件长度 + public int fileCRC; //文件CRC校验 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQdynamicHeader + { + public byte RunMode; + private ushort Timeout; + public byte ImmePlay; + public byte AreaType; + private ushort AreaX; + private ushort AreaY; + private ushort AreaWidth; + private ushort AreaHeight; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQSoundDepend_6G + { + public byte VoiceID; // 1 1 语音队列中每个语音的 ID,从 0 开始 + public EQSound_6G stSound; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct FileCRC16_G56 + { + private IntPtr fileAddre; //文件地址指針 + private ushort fileLen; //文件长度 + private ushort fileCRC16; //文件CRC16校验 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct FileCRC32_G56 + { + private IntPtr fileAddre; //文件地址指針 + private ushort fileLen; //文件长度 + private ushort fileCRC32; //文件CRC32校验 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct DynamicAreaParams + { + public byte uAreaId; + public EQareaHeader_G6 oAreaHeader_G6; + public EQpageHeader_G6 stPageHeader; + public IntPtr fontName; + public IntPtr strAreaTxtContent; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct BxAreaFrmae_Dynamic_G6 + { + public byte AreaFFlag; // 1 0x00 区域边框标志位; + public EQscreenframeHeader_G6 oAreaFrame; + public byte[] pStrFramePathFile; + }; + + /// + /// windows平台需要初始化SDK(默认如果没有初始化会自动初始化) + /// + /// + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_InitSdk(); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern void bxDual_ReleaseSdk(); + + /// + /// 设置目标地址,即设置屏号/设置屏地址/设置控制器的屏号 + /// + /// 2个字节长度,默认值0xfffe 为地址通配符 + /// + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_set_screenNum_G56(ushort usDstAddr); + + /// + /// 用于设置控制各种通讯方式每一包最大长度 + /// 注:5E,6E,6Q系列最大数据长途64K(建议最大不要超过63*1024) 其他系列最大长度1K(1204) + /// + /// 数据包长度 + /// + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_set_packetLen(ushort packetLen); + + /// + /// 搜索控制器命令 + /// + /// 请参考结构体Ping_data 所有回读参数都会通过结构体回调 + /// + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_searchController(ref Ping_data retData); + + /// + /// 搜索控制器命令-串口 + /// + /// 请参考结构体Ping_data 所有回读参数都会通过结构体回调 + /// 串口号 + /// + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_searchController(ref Ping_data retData, byte[] uartPort); + + /*! *********************************************************************************************************************** + * 函数名:cmd_uart_search_Net_6G() + * 参数名: + * uartPort 端口号,如:"COM3" + * nBaudRateType 1:9600; 2:57600; + * 命令结果放在了 retData 中;NetSearchCmdRet:参考结构体声明中的注释; + * 返回值:0 成功, 其他值为错误号 + * 功 能: 网络搜索命令,返回:温度传感器,空气,PM2.5等信息,详见 NetSearchCmdRet:参考结构体声明中的注释; + * 注: 针对 6代卡 的网络搜索命令 + ***************************************************************************************************************************/ + + /// + /// 网络搜索命令,返回:温度传感器,空气,PM2.5等信息,详见 NetSearchCmdRet:参考结构体声明中的注释; + /// 针对 6代卡 的网络搜索命令 + /// + /// NetSearchCmdRet:参考结构体声明中的注释; + /// 串口号,如:"COM3" + /// 1:9600; 2:57600; + /// + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_search_Net_6G(ref NetSearchCmdRet retData, byte[] uartPort, ushort nBaudRateType); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_search_Net_6G_Web(ref NetSearchCmdRet_Web retData, byte[] uartPort, ushort nBaudRateType); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsFormat() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * 返回值:0 成功, 其他值为错误号 + * 功 能:文件系统格式化 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsFormat(byte[] uartPort, byte baudRate); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsStartFileTransf() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * 返回值:0 成功, 其他值为错误号 + * 功 能:开始批量写文件 + * 注: + * 发送节目前调用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsStartFileTransf(byte[] uartPort, byte baudRate); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsEndFileTransf() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * 返回值:0 成功, 其他值为错误号 + * 功 能:写文件结束 + * 注: + * 发送节目后调用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsEndFileTransf(byte[] uartPort, byte baudRate); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsDeleteFormatFile() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileNub:要删除的文件个数 + * fileName:要删除的文件名 + * 返回值:0 成功, 其他值为错误号 + * 功 能:删除文件 + * 注: + * fileName是4个字节 fileNub值为N就要把N个fileName拼接 fileName大小 = fileName(4byte)*N + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsDeleteFormatFile(byte[] uartPort, byte baudRate, short fileNub, byte[] fileName); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_confDeleteFormatFile() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileNub:要删除的文件个数 + * fileName:要删除的文件名 + * 返回值:0 成功, 其他值为错误号 + * 功 能:删除文件 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * fileName是4个字节 fileNub值为N就要把N个fileName拼接 fileName大小 = fileName(4byte)*N + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_confDeleteFormatFile(byte[] uartPort, byte baudRate, short fileNub, byte[] fileName); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsGetMemoryVolume() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * totalMemVolume:全部空间大小 + * availableMemVolume:剩余空间大小 + * 返回值:0 成功, 其他值为错误号 + * 功 能:获取控制空间大小和剩余空间 + * 注: + * 发节目前需要查询防止空间不够用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsGetMemoryVolume(byte[] uartPort, byte baudRate, int[] totalMemVolume, int[] availableMemVolume); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsWriteFile() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileName:文件名 + * fileType:文件类型 + * fileLen:文件长度 + * fileAddre:文件所在的缓存地址 + * overwrite:是否覆盖控制上的文件 1覆盖 0不覆盖 建议发1 + * 返回值:0 成功, 其他值为错误号 + * 功 能:写文件到控制 + * 注:用于对存储在 OFS 中的文件的处理, 例如: 节目文件, 字库文件、 播放列表文件等 + * 内部包含多条命令注意返回状态方便查找问题 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsWriteFile(byte[] uartPort, byte baudRate, byte[] fileName, byte fileType, uint fileLen, byte overwrite, IntPtr fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_confWriteFile() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileName:文件名 + * fileType:文件类型 + * fileLen:文件长度 + * fileAddre:文件所在的缓存地址 + * overwrite:是否覆盖控制上的文件 1覆盖 0不覆盖 建议发1 + * 返回值:0 成功, 其他值为错误号 + * 功 能:写文件到控制 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * 内部包含多条命令注意返回状态方便查找问题 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_confWriteFile(byte[] uartPort, byte baudRate, byte[] fileName, byte fileType, int fileLen, byte overwrite, byte[] fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsStartReedFile() + * 参数名:ip:控制器IP, port:控制器端口 + * fileName:需要读取的文件名 + * fileSize:回读文件大小 + * fileCrc:回读的文件CRC + * 返回值:0 成功, 其他值为错误号 + * 功 能:开始读文件 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsStartReedFile(byte[] uartPort, byte baudRate, byte[] fileName, int[] fileSize, int[] fileCrc); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_confStartReedFile() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileName:需要读取的文件名 + * fileSize:回读文件大小 + * fileCrc:回读的文件CRC + * 返回值:0 成功, 其他值为错误号 + * 功 能:开始读文件 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_confStartReedFile(byte[] uartPort, byte baudRate, byte[] fileName, int[] fileSize, int[] fileCrc); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsReedFileBlock() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileName:需要读取的文件名 + * fileAddre:传入读文件写的位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:读文件 + * 注:用于对存储在 OFS 中的文件的处理, 例如: 节目文件, 字库文件、 播放列表文件等 + * fileAddre大小根据cmd_ofsStartReedFile函数回调值确定 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsReedFileBlock(byte[] uartPort, byte baudRate, byte[] fileName, byte[] fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_confReedFileBlock() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileName:需要读取的文件名 + * fileAddre:传入读文件写的位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:读文件 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * fileAddre大小根据cmd_ofsStartReedFile函数回调值确定 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_confReedFileBlock(byte[] uartPort, byte baudRate, byte[] fileName, byte[] fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_ofsReedDirBlock() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * fileName:需要读取的文件名 + * fileAddre:传入读文件写的位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:下面两条命令搭配使用可以获取所有文件名 + * 注: + * 下面两条命令用法比较复杂请配合协议使用不做嗷述 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsReedDirBlock(byte[] uartPort, byte baudRate, ref GetDirBlock_G56 dirBlock); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofs_freeDirBlock() + * 参数名: + * dirBlock: 上述两条命令所有使用的结构体 + * 返回值:0 成功, 其他值为错误号 + * 功 能:释放cmd_ofsReedDirBlock所创建的节目列表dirBlock + * 注: + * dirBlock 上述两条命令调用完成后dirBlock不再使用时用此函数释放文件列表 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsFreeDirBlock(ref GetDirBlock_G56 dirBlock); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_ofsGetTransStatus(byte[] uartPort, byte baudRate, byte[] r_w, byte[] fileName, int[] fileCrc, int[] fileOffset); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_sendConfigFile() + * 参数名:uartPort:串口端口号, baudRate:波特率 + configData 请参考结构体ConfigFile + * 返回值:0 成功, 其他值为错误号 + * 功 能:发送配置文件到控制器 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_sendConfigFile(byte[] uartPort, byte baudRate, ref ConfigFile configData); + + /*! *************************************************************** + * 函数名: bxDual_cmd_uart_programLock() + * 参数名:uartPort:串口端口号, baudRate:波特率 + * nonvolatile: 状态是否掉电保存 0x00 –掉电不保存 0x01 –掉电保存 + * lock:0x00 –解锁 0x01 –锁定 + * name: 节目名称4(byte)个字节 + * lockDuration: 节目锁定时间长度, 单位为 10 毫秒, 例 + * 如当该值为 100 时表示锁定节目 1 秒.注意: 当该值为 0xffffffff 时表示节目锁定无时间长度限制 + * 返回值:0 成功, 其他值为错误号 + * 功 能:节目锁定 + * 注: + * 具体使用方法参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_programLock(byte[] uartPort, byte baudRate, byte nonvolatile, byte locked, byte[] name, int lockDuration); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_uart_programLock_6G(byte[] uartPort, byte baudRate, byte nonvolatile, byte locked, byte[] name, int lockDuration); + + /*! *************************************************************** + ** 串口通讯命令 end ** + /*! ***************************************************************/ + + /*! *************************************************************** + * 函数名: cmd_AT_setWifiSsidPwd() + * 参数名:ssid:控制器WIFI ssid,pwd:控制WIFI密码 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置wifi卡的 ssid pwd + * 注: + * 通讯方式(UDP + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_AT_setWifiSsidPwd(byte[] ssid, byte[] pwd); + + /*! *************************************************************** + * 函数名: cmd_AT_getWifiSsidPwd() + * 参数名:ssid:控制器WIFI ssid,pwd:控制WIFI密码 + * 返回值:0 成功, 其他值为错误号 + * 功 能:获取WIFI卡ssid pwd + * 注: + * 通讯方式(UDP) + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_AT_getWifiSsidPwd(byte[] ssid, byte[] pwd); + + /*! *************************************************************** + ** UDP通讯命令 ** + /*! ***************************************************************/ + + /*! *************************************************************** + * 函数名: cmd_udpNetworkSearch() + * 参数名:retData 请参考结构体heartbeatData 所有回读参数都会通过结构体回调 + * 返回值:0 成功, 其他值为错误号 + * 功 能: + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_udpNetworkSearch(ref heartbeatData retData); //网络搜索 + + /*! ******************************************************************************************************************** + * 函数名:cmd_udpNetworkSearch_6G() + * 参数名:retData : 存放网络搜索结果; 具体参考结构体:NetSearchCmdRet 声明中的注释; + * 返回值:0 成功, 其他值为错误号; + * 功 能: 网络搜索命令,返回:温度传感器,空气,PM2.5等信息,详见 NetSearchCmdRet:参考结构体声明中的注释; + * 注: 针对 6代卡 的网络搜索命令 + ***********************************************************************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_udpNetworkSearch_6G(ref NetSearchCmdRet retData); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_udpNetworkSearch_6G_Web(ref NetSearchCmdRet_Web retData); + + /*! *************************************************************** + * 函数名: cmd_udpPing() + * 参数名:retData 请参考结构体Ping_data 所有回读参数都会通过结构体回调 + * 返回值:0 成功, 其他值为错误号 + * 功 能:UDP ping 命令 + * 注: + * 此命令用来搜索加屏使用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_udpPing(ref Ping_data retData); //UDP ping命令并返回IP地址 + + /*! *************************************************************** + * 函数名: cmd_udpSetMac() + * 参数名:mac 传入的MAC地址 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置 MAC 地址命令 + * 注: + * 需要修改MAC地址的时候调用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_udpSetMac(byte[] mac); + + /*! *************************************************************** + * 函数名: cmd_udpSetIP() + * 参数名 + byte mode; 控制器连接模式: + 0x00 –单机直连(PC 与控制器直接连 + 接) + 0x01 –自动获取IP(DHCP) + 0x02 –手动设置IP(Static IP) + 0x03 –服务器模式(动态 IP) + byte ip[] ; // 要设置的IP地址//设置IP + byte subnetMask[] ; 子网掩码 + byte gateway[]; 默认网关 + short port; 端口号 + byte serverMode; 服务器模式 + byte serverIP[]; 服务IP + short serverPort; 服务器端口号 + byte password[]; 服务器访问密码 + short heartbeat; 心跳间隔时间单位秒 默认值20 + byte netID[12]; 控制器网络ID + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置 IP 地址相关参数命令 + * 注: + * IP 地址 MAC地址都赋字符串 例:byte ip[] = "192.168.0.199" 具体使用细节请参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_udpSetIP(byte mode, byte[] ip, byte[] subnetMask, byte[] gateway, short port, byte serverMode, byte[] serverIP, short serverPort, byte[] password, short heartbeat, byte[] netID);// 由于传入参数到内部都需要转换没有使用结构体 + + /*! *************************************************************** + /**UDP CMD END**/ + /*! ***************************************************************/ + + /*! *************************************************************** + /** TCP命令 控制器维护命令 **/ + /*! ***************************************************************/ + + /*! *************************************************************** + * 函数名: cmd_sysReset() + * 参数名:ip, 控制器IP, port 控制器端口 + * 返回值:0 成功, 其他值为错误号 + * 功 能:让系统复位 + * 注: + * 此命令调用后所有参数全部会丢失 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_sysReset(byte[] ip, ushort port); + + /*! *************************************************************** + * 函数名: cmd_tcpPing() + * 参数名:ip:控制器IP, port:控制器端口, retData:请参考结构体Ping_data + * 返回值:0 成功, 其他值为错误号 + * 功 能:通过TCP方式获取到控制器相关属性和IP地址 + * 注: + * 和UDP PING命令获取到的参数相同 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_tcpPing(byte[] ip, ushort port, ref Ping_data retData); + + /*! *************************************************************** + * 函数名: cmd_check_time() + * 参数名:ip:控制器IP, port:控制器端口 + * 返回值:0 成功, 其他值为错误号 + * 功 能:校时,让控制器和当前上位机所在系统时间一致 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_check_time(byte[] ip, ushort port); + + /*! ******************************************************************************************************************** + * 函数名:cmd_tcpNetworkSearch_6G() + * 参数名:ip:控制器IP, port:控制器端口; + * 命令结果放在了 retData 中;NetSearchCmdRet:参考结构体声明中的注释; + * 返回值:0 成功, 其他值为错误号 + * 功 能: 网络搜索命令,返回:温度传感器,空气,PM2.5等信息,详见 NetSearchCmdRet:参考结构体声明中的注释; + * 注: 针对 6代卡 的网络搜索命令 + ***********************************************************************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_tcpNetworkSearch_6G(byte[] ip, ushort port, ref NetSearchCmdRet retData); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_tcpNetworkSearch_6G_Web(byte[] ip, ushort port, ref NetSearchCmdRet_Web retData); + + /*! *************************************************************** + * 函数名: cmd_coerceOnOff() + * 参数名:ip:控制器IP, port:控制器端口,onOff:控制器状态:0x01 –开机 0x00 –关机 + * 返回值:0 成功, 其他值为错误号 + * 功 能:强制开挂机命令 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_coerceOnOff(byte[] ip, ushort port, byte onOff); + + /*! *************************************************************** + * 函数名: cmd_timingOnOff() + * 参数名:ip:控制器IP, port:控制器端口,groupNum:有几组定时开关机 data:TimingOnOff结构体的地址 + * 返回值:0 成功, 其他值为错误号 + * 功 能:定时开关机命令 + * 注: + * groupNum值是n组情况,data大小 = n * TimingOnOff + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_timingOnOff(byte[] ip, ushort port, byte groupNum, byte[] data); + + /*! *************************************************************** + * 函数名: cmd_cancelTimingOnOff() + * 参数名:ip:控制器IP, port:控制器端口 + * 返回值:0 成功, 其他值为错误号 + * 功 能:取消定时开关机 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_cancelTimingOnOff(byte[] ip, ushort port); + + /*! *************************************************************** + * 函数名: cmd_setBrightness() + * 参数名:ip:控制器IP, port:控制器端口, brightness:亮度度表 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置亮度和相关模式 + * 注: + * 参考协议对应每一个表格,注意第一个字节模式的配置 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setBrightness(byte[] ip, ushort port, ref Brightness brightness); + + /*! *************************************************************** + * 函数名: cmd_readControllerID() + * 参数名:ip:控制器IP, port:控制器端口, ControllerID:传回控制器ID + * 返回值:0 成功, 其他值为错误号 + * 功 能:读控制器ID + * 注: + * ControllerID是8个字节 请定义char data[8]; + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_readControllerID(byte[] ip, ushort port, byte[] ControllerID); + + /*! *************************************************************** + * 函数名: cmd_screenLock() + * 参数名:ip:控制器IP, port:控制器端口 + * nonvolatile:状态是否掉电保存 0x00 –掉电不保存 0x01 –掉电保存 + * lock: 0x00 –解锁 0x01 –锁定 + * 返回值:0 成功, 其他值为错误号 + * 功 能:屏幕锁定 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_screenLock(byte[] ip, ushort port, byte nonvolatile, byte locked); + + /*! *************************************************************** + * 函数名: cmd_programLock() + * 参数名:ip:控制器IP, port:控制器端口 + * nonvolatile: 状态是否掉电保存 0x00 –掉电不保存 0x01 –掉电保存 + * lock:0x00 –解锁 0x01 –锁定 + * name: 节目名称4(byte)个字节 + * lockDuration: 节目锁定时间长度, 单位为 10 毫秒, 例 + * 如当该值为 100 时表示锁定节目 1 秒.注意: 当该值为 0xffffffff 时表示节目锁定无时间长度限制 + * 返回值:0 成功, 其他值为错误号 + * 功 能:节目锁定 + * 注: + * 具体使用方法参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_programLock(byte[] ip, ushort port, byte nonvolatile, byte locked, byte[] name, uint lockDuration); + + /*! *************************************************************** + * 函数名: cmd_check_controllerStatus() + * 参数名:ip:控制器IP, port:控制器端口, controllerStatus:请参考结构体ControllerStatus_G56 + * 返回值:0 成功, 其他值为错误号 + * 功 能:读控制器状态 + * 注: + * ControllerStatus_G56和协议时对应的可以参考协议的具体用法 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_check_controllerStatus(byte[] ip, ushort port, ref ControllerStatus_G56 controllerStatus); + + /*! *************************************************************** + * 函数名: cmd_setPassword() + * 参数名:ip:控制器IP, port:控制器端口, oldPassword:老密码, newPassword新密码 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置控制器密码 + * 注: + * 设置后一定要记住,设置后就不在能明码通讯 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setPassword(byte[] ip, ushort port, byte[] oldPassword, byte[] newPassword); + + /*! *************************************************************** + * 函数名: cmd_deletePassword() + * 参数名:ip:控制器IP, port:控制器端口, password:输出当前控制密码 + * 返回值:0 成功, 其他值为错误号 + * 功 能:删除当前控制器密码 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_deletePassword(byte[] ip, ushort port, byte[] password); + + /*! *************************************************************** + * 函数名: cmd_setDelayTime() + * 参数名:ip:控制器IP, port:控制器端口, delayTime:开机延时单位秒 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置控制开机延时时间 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setDelayTime(byte[] ip, ushort port, short delayTime); + + /*! *************************************************************** + * 函数名: cmd_setBtnFunc() + * 参数名:ip:控制器IP, port:控制器端口, btnMode:按钮模式 0x00–测试按钮 0x01 –沿触发切换节目 0x02 –电平触发切换节目 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置控制测试按钮功能 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setBtnFunc(byte[] ip, ushort port, byte btnMode); + + /*! *************************************************************** + * 函数名: cmd_setTimingReset() + * 参数名:ip:控制器IP, port:控制器端口, cmdData:参考结构体TimingReset + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置控制重启重启时间 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setTimingReset(byte[] ip, ushort port, ref TimingReset cmdData); + + /*! *************************************************************** + * 函数名: cmd_setDispMode() + * 参数名:ip:控制器IP, port:控制器端口 + * dispMode:控制器的显示模式(目前只针对 BX-5E系列控制器) + * Bit0 –串/并行, 0 表示并行, 1 表示并行 + * Bit1–同步使能, 1 使能同步, 0 禁止同步 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置控制重启重启时间 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setDispMode(byte[] ip, ushort port, byte dispMode); + + /*! *************************************************************** + * 函数名: cmd_battieTime() + * 参数名:ip:控制器IP, port:控制器端口, + * mode:战斗时间控制命令 + * 0x00:启动战斗时间 + * 0x01:暂停战斗时间 + * 0x02:复位战斗时间 + * battieData: 命令回读参数请参考结构体BattleTime + * 返回值:0 成功, 其他值为错误号 + * 功 能:战斗时间管理命令 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_battieTime(byte[] ip, ushort port, byte mode, ref BattleTime battieData); + + /*! *************************************************************** + * 函数名: cmd_getStopwatch() + * 参数名:ip:控制器IP, port:控制器端口, + * mode:秒表控制命令 + * 0x00:启动秒表 + * 0x01:暂停秒表 + * 0x02:复位秒表 + * timeValue:回读回来的当前秒表时间单位毫秒 + * 返回值:0 成功, 其他值为错误号 + * 功 能:秒表控制并获取秒表时间 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_getStopwatch(byte[] ip, ushort port, byte mode, int[] timeValue); + + /*! *************************************************************** + * 函数名: cmd_getSensorBrightnessValue() + * 参数名:ip:控制器IP, port:控制器端口 + * brightnessValue:当前亮度传感器值 + * 返回值:0 成功, 其他值为错误号 + * 功 能:获取亮度读传感器值 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_getSensorBrightnessValue(byte[] ip, ushort port, int[] brightnessValue); + + /*! *************************************************************** + * 函数名: cmd_setSpeedAdjust() + * 参数名:ip:控制器IP, port:控制器端口 + * speed:速度微调参数值 + 该值以 0.1 毫秒为单位, 共 256 级, 上 + 位机下发时该值为 0-255, 这样刚好使 + 用一个低位字节, 高位字节为 0, 留作 + 以后扩展使用。 下位机根据该参数在每 + 次循环中延时相应的时间, 以改善 LED + 屏幕的显示效果。 当该参数为 0 时, 下 + 位机延时为 0, 该参数为 1 时, 下位机 + 延时 0.1 毫秒, 以此类推 + * 返回值:0 成功, 其他值为错误号 + * 功 能:速度微调命令 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setSpeedAdjust(byte[] ip, ushort port, short speed); + + /*! *************************************************************** + * 函数名: cmd_setScreenAddress() + * 参数名:ip:控制器IP, port:控制器端口 + * address:屏幕号 + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置屏幕号 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_setScreenAddress(byte[] ip, ushort port, short address); + + /** TCP OFS_CMD**/ + /*! *************************************************************** + * 函数名: cmd_ofsFormat() + * 参数名:ip:控制器IP, port:控制器端口 + * 返回值:0 成功, 其他值为错误号 + * 功 能:文件系统格式化 + * 注: + * 具体细节参考协议 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsFormat(byte[] ip, ushort port); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsStartFileTransf() + * 参数名:ip:控制器IP, port:控制器端口 + * 返回值:0 成功, 其他值为错误号 + * 功 能:开始批量写文件 + * 注: + * 发送节目前调用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsStartFileTransf(byte[] ip, ushort port); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsEndFileTransf() + * 参数名:ip:控制器IP, port:控制器端口 + * 返回值:0 成功, 其他值为错误号 + * 功 能:写文件结束 + * 注: + * 发送节目后调用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsEndFileTransf(byte[] ip, ushort port); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsDeleteFormatFile() + * 参数名:ip:控制器IP, port:控制器端口 + * fileNub:要删除的文件个数 + * fileName:要删除的文件名 + * 返回值:0 成功, 其他值为错误号 + * 功 能:删除文件 + * 注: + * fileName是4个字节 fileNub值为N就要把N个fileName拼接 fileName大小 = fileName(4byte)*N + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsDeleteFormatFile(byte[] ip, ushort port, short fileNub, byte[] fileName); + + /*! *************************************************************** + * 函数名: bxDual_cmd_confDeleteFormatFile() + * 参数名:ip:控制器IP, port:控制器端口 + * fileNub:要删除的文件个数 + * fileName:要删除的文件名 + * 返回值:0 成功, 其他值为错误号 + * 功 能:删除文件 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * fileName是4个字节 fileNub值为N就要把N个fileName拼接 fileName大小 = fileName(4byte)*N + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_confDeleteFormatFile(byte[] ip, ushort port, short fileNub, byte[] fileName); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsGetMemoryVolume() + * 参数名:ip:控制器IP, port:控制器端口 + * totalMemVolume:全部空间大小 + * availableMemVolume:剩余空间大小 + * 返回值:0 成功, 其他值为错误号 + * 功 能:获取控制空间大小和剩余空间 + * 注: + * 发节目前需要查询防止空间不够用 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsGetMemoryVolume(byte[] ip, ushort port, int[] totalMemVolume, int[] availableMemVolume); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsWriteFile() + * 参数名:ip:控制器IP, port:控制器端口 + * fileName:文件名 + * fileType:文件类型 + * fileLen:文件长度 + * fileAddre:文件所在的缓存地址 + * overwrite:是否覆盖控制上的文件 1覆盖 0不覆盖 建议发1 + * 返回值:0 成功, 其他值为错误号 + * 功 能:写文件到控制 + * 注:用于对存储在 OFS 中的文件的处理, 例如: 节目文件, 字库文件、 播放列表文件等 + * 内部包含多条命令注意返回状态方便查找问题 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsWriteFile(byte[] ip, ushort port, byte[] fileName, byte fileType, uint fileLen, byte overwrite, IntPtr fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsWriteFile() + * 参数名:ip:控制器IP, port:控制器端口 + * fileName:文件名 + * fileType:文件类型 + * fileLen:文件长度 + * fileAddre:文件所在的缓存地址 + * overwrite:是否覆盖控制上的文件 1覆盖 0不覆盖 建议发1 + * 返回值:0 成功, 其他值为错误号 + * 功 能:写文件到控制 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * 内部包含多条命令注意返回状态方便查找问题 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_confWriteFile(byte[] ip, ushort port, byte[] fileName, byte fileType, int fileLen, byte overwrite, byte[] fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsStartReedFile() + * 参数名:ip:控制器IP, port:控制器端口 + * fileName:需要读取的文件名 + * fileSize:回读文件大小 + * fileCrc:回读的文件CRC + * 返回值:0 成功, 其他值为错误号 + * 功 能:开始读文件 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsStartReedFile(byte[] ip, ushort port, byte[] fileName, int[] fileSize, int[] fileCrc); + + /*! *************************************************************** + * 函数名: bxDual_cmd_confStartReedFile() + * 参数名:ip:控制器IP, port:控制器端口 + * fileName:需要读取的文件名 + * fileSize:回读文件大小 + * fileCrc:回读的文件CRC + * 返回值:0 成功, 其他值为错误号 + * 功 能:开始读文件 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_confStartReedFile(byte[] ip, ushort port, byte[] fileName, int[] fileSize, int[] fileCrc); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsReedFileBlock() + * 参数名:ip:控制器IP, port:控制器端口 + * fileName:需要读取的文件名 + * fileAddre:传入读文件写的位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:读文件 + * 注:用于对存储在 OFS 中的文件的处理, 例如: 节目文件, 字库文件、 播放列表文件等 + * fileAddre大小根据bxDual_cmd_ofsStartReedFile函数回调值确定 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsReedFileBlock(byte[] ip, ushort port, byte[] fileName, byte[] fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_confReedFileBlock() + * 参数名:ip:控制器IP, port:控制器端口 + * fileName:需要读取的文件名 + * fileAddre:传入读文件写的位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:读文件 + * 注:此函数用于对存储在固定位置的文件进行处理, 例 + 如: Firmware 文件、 控制器参数配置文件、 扫描配置文件等。 + * fileAddre大小根据bxDual_cmd_ofsStartReedFile函数回调值确定 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_confReedFileBlock(byte[] ip, ushort port, byte[] fileName, byte[] fileAddre); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofsReedDirBlock() + * 参数名:ip:控制器IP, port:控制器端口 + * dirBlock: 读会的文件列表,具体的具体参考GetDirBlock_G56结构体 + * 返回值:0 成功, 其他值为错误号 + * 功 能:获取文件列表 + * 注: + * 下面几条命令用法比较复杂请配合协议使用不做嗷述 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsReedDirBlock(byte[] ip, ushort port, ref GetDirBlock_G56 dirBlock); + + /*! *************************************************************** + * 函数名: bxDual_cmd_getFileAttr() + * 参数名: + * dirBlock: 上一条命令的回传结构体 + * number: 要获取的第几个文件的属性 + * fileAttr: 获取到的文件属性存放位置参考结构体FileAttribute_G56; + * 返回值:0 成功, 其他值为错误号 + * 功 能:获取指定文件的属性 + * 注: + * number:此参数值小于fileAttr.fileName 从0开始 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_getFileAttr(ref GetDirBlock_G56 dirBlock, ushort number, ref FileAttribute_G56 fileAttr); + + /*! *************************************************************** + * 函数名: bxDual_cmd_ofs_freeDirBlock() + * 参数名: + * dirBlock: 上述两条命令所有使用的结构体 + * 返回值:0 成功, 其他值为错误号 + * 功 能:释放bxDual_cmd_ofsReedDirBlock所创建的节目列表dirBlock + * 注: + * dirBlock 上述两条命令调用完成后dirBlock不再使用时用此函数释放文件列表 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofs_freeDirBlock(ref GetDirBlock_G56 dirBlock); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_ofsGetTransStatus(byte[] ip, ushort port, byte[] r_w, byte[] fileName, int[] fileCrc, int[] fileOffset); + + /*! *************************************************************** + * 函数名: bxDual_cmd_firmwareActivate() + * 参数名:ip:控制器IP, port:控制器端口,firmwareFileName要激活的固件名称 + * 返回值:0 成功, 其他值为错误号 + * 功 能:激活指定固件 + * 注: + * firmwareFileName 缺省值为4个字节字符串“F001” + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_firmwareActivate(byte[] ip, ushort port, byte[] firmwareFileName); + + /*! *************************************************************** + * 函数名: bxDual_cmd_sendConfigFile() + * 参数名:ip:控制器IP, port:控制器端口 + configData 请参考结构体ConfigFile + * 返回值:0 成功, 其他值为错误号 + * 功 能:发送5代卡配置文件到控制器 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_sendConfigFile(byte[] ip, ushort port, ref ConfigFile configData); + + /*! *************************************************************** + * 函数名: bxDual_cmd_sendConfigFile_G6() + * 参数名:ip:控制器IP, port:控制器端口 + configData 请参考结构体ConfigFile + * 返回值:0 成功, 其他值为错误号 + * 功 能:发送5代卡配置文件到控制器 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_cmd_sendConfigFile_G6(byte[] ip, ushort port, ref ConfigFile_G6 configData); + + /*! *************************************************************** + /** TCP命令 END **/ + /*! ***************************************************************/ + + /*! *************************************************************** + * 函数名: get_crc16() + * 参数名: + * 返回值:0 成功, 其他值为错误号 + * 功 能:用来计算CRC16值 + * 注: + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_get_crc16(ref FileCRC16_G56 crc16); + + /*! *************************************************************** + * 函数名: get_crc32() + * 参数名: + * 返回值:0 成功, 其他值为错误号 + * 功 能:用来计算CRC32值 + * 注: + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_get_crc32(ref FileCRC32_G56 crc32); + + /*! *************************************************************** + *** 以下是节目相关函数 + *** 注意事项: + *** + *** + /*! ***************************************************************/ + + /*! *************************************************************** + * 函数名: bxDual_program_deleteProgram() + * 返回值:0 成功, 其他值为错误 + * 功 能:删除节目 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_deleteProgram(); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_freeBuffer(ref EQprogram program); + + /*! *************************************************************** + * 函数名: bxDual_program_pictureArea() + * 参数名:ip:控制器IP, port:控制器端口 + * programID:节目的ID号 + * 返回值:0 成功, 其他值为错误号 + * 功 能:只是用来测试图文区 + * 注: + * 屏幕大小为1024X80 输出26个字母 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureArea(int programID, byte[] ip, ushort port); + + /*! *************************************************************** + * 函数名: bxDual_program_setScreenParams_G56() + * 返回值:0 成功, 其他值为错误号 + * 功 能:设置屏相关属性 + * 注: + * 三个参数请参考各自枚举值 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_setScreenParams_G56(E_ScreenColor_G56 color, ushort ControllerType, E_DoubleColorPixel_G56 doubleColor); //设置屏相关属性 + + //[DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)]public static extern int bxDual_program_setScreenParams_G6(E_ScreenColor_G56 color, ushort ControllerType, E_DoubleColorPixel_G56 doubleColor); + /*! *************************************************************** + * 函数名: bxDual_program_addProgram() + * programH:参考结构体EQprogramHeader + * 返回值:0 成功, 其他值为错误 + * 功 能:添加节目句柄 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_addProgram(ref EQprogramHeader programH); //添加节目句柄 + + /*! *************************************************************** + * 函数名: bxDual_program_changeProgramParams() + * programH:参考结构体EQprogramHeader + * 返回值:0 成功, 其他值为错误 + * 功 能:修改已添加节目的一些参数 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_changeProgramParams(ref EQprogramHeader programH); + + /*! *************************************************************** + * 函数名: bxDual_program_addPlayPeriodGrp() + * 返回值:0 成功, 其他值为错误 + * 功 能:添加节目播放时段 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_addPlayPeriodGrp(ref EQprogramppGrp_G56 header); + + /*! *************************************************************** + * 函数名: bxDual_program_AddArea() + * 参数名: + * areaID:区域的ID号 + * aheader:参考结构体EQareaHeader + * 返回值:0 成功, 其他值为错误号 + * 功 能:添加区域句柄 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_AddArea(ushort areaID, ref EQareaHeader aheader);//添加区域句柄 + + /*! *************************************************************** + * 函数名: bxDual_program_deleteArea() + * 参数名: + * areaID:区域的ID号 + * 返回值:0 成功, 其他值为错误号 + * 功 能:用来删除编号为areaID的区域 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_deleteArea(ushort areaID); + + /*! *************************************************************** + * 函数名: bxDual_program_picturesAreaAddTxt() + * areaID:区域的ID号 + * str:需要画的字符 + * fontName:字体名称 + * pheader:参考结构体EQpageHeader + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:画字符到图文区 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_picturesAreaAddTxt(ushort areaID, byte[] str, byte[] fontName, ref EQpageHeader pheader);//画字符到区域 + + /*! *************************************************************** + * 函数名: bxDual_program_picturesAreaChangeTxt() + * areaID:区域的ID号 + * str:需要画的字符 + * pheader:参考结构体EQpageHeader + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:修改图文区域内容 + * 注: + * 只可以修改文字内容和EQpageHeader结构体里面的参数,不可以修改字体,如需修改,需要删除区域后重新添加文本设置字体 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_picturesAreaChangeTxt(ushort areaID, byte[] str, ref EQpageHeader pheader); + + /*! *************************************************************** + * 函数名: bxDual_program_fontPath_picturesAreaAddTxt() + * areaID:区域的ID号 + * str:需要画的字符 + * fontPathName:字体绝对路径加字库文件名称 + * pheader:参考结构体EQpageHeader + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:图文区添加字符串--使用字库 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_fontPath_picturesAreaAddTxt(ushort areaID, byte[] str, byte[] fontPathName, ref EQpageHeader pheader); + + /*! *************************************************************** + * 函数名: bxDual_program_fontPath_picturesAreaChangeTxt() + * areaID:区域的ID号 + * str:需要更换的字符串 + * pheader:参考结构体EQpageHeader + * 返回值:0 成功, 其他值为错误号 + * 功 能:图文区修改字符串--使用字库 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_fontPath_picturesAreaChangeTxt(ushort areaID, byte[] str, ref EQpageHeader pheader); + + /*! *************************************************************** + * 函数名: bxDual_program_IntegrateProgramFile() + * 参数名: + * program:参考结构体EQprogram + * 返回值:0 成功, 其他值为错误号 + * 功 能:合成节目文件返回节目文件属性及地址 + * 注: + * EQprogram 结构体是用来回调发送文件所需要参数 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_IntegrateProgramFile(ref EQprogram program); + + /*! *************************************************************** + * 函数名: bxDual_program_picturesAreaAddFrame() + * 参数名:areaID:区域的ID号 + * EQareaframeHeader:参考结构体EQareaframeHeader + * picPath: 边框图片文件的路径 + * 返回值:0 成功, 其他值为错误号 + * 功 能:区域添加边框 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_picturesAreaAddFrame(ushort areaID, ref EQareaframeHeader afHeader, byte[] picPath); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_picturesAreaAddFrame_G6(ushort areaID, ref EQscreenframeHeader_G6 afHeader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_pictureAreaGetOnePage() + * 参数名: + * areaID:区域ID + * pageNum: 第几页,从0开始计算 + * 返回值:0 成功, 其他值为错误号 + * 功 能:返回区域第n张图片 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaGetOnePage(ushort areaID, int pageNum, ref getPageData pageData); + + /*! *************************************************************** + * 函数名: bxDual_program_picturesAreaAddPic() + * areaID:区域的ID号 + * picID:图片的ID号 + * EQpageHeader:参考结构体EQpageHeader + * picPath:添加的图片路径 + * 返回值:0 成功, 其他值为错误号 + * 功 能:添加图片到区域 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaAddPic(ushort areaID, ushort picID, ref EQpageHeader pheader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_addFrame() + * EQscreenframeHeader:参考结构体EQscreenframeHeader + * picPath:添加的边框图片路径 + * 返回值:0 成功, 其他值为错误号 + * 功 能:节目添加边框 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_addFrame(ref EQscreenframeHeader sfHeader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_changeFrame() + * EQscreenframeHeader:参考结构体EQscreenframeHeader + * picPath:边框图片路径 + * 返回值:0 成功, 其他值为错误号 + * 功 能:节目修改已添加边框的一些参数 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_changeFrame(ref EQscreenframeHeader sfHeader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_removeFrame() + * + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:节目去掉边框 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_removeFrame(); + + /*! *************************************************************** + * 函数名: bxDual_program_pictureAreaRemoveFrame() + * areaID:区域的ID号 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:区域去掉边框 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaRemoveFrame(ushort areaID); + + /*! *************************************************************** + * 函数名: bxDual_program_MoveArea() + * areaID:区域的ID号 + * x:区域left坐标 + * y:区域top坐标 + * width:区域宽度 + * height:区域高度 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:改变区域坐标大小 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_MoveArea(ushort areaID, int x, int y, int width, int height); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaAddContent() + * areaID:区域的ID号 + * timeData:详情请见时间区数据格式结构体EQtimeAreaData_G56 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区添加内容 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaAddContent(ushort areaID, ref EQtimeAreaData_G56 timeData); + + /*! *************************************************************** + * 函数名: bxDual_program_fontPath_timeAreaAddContent() + * areaID:区域的ID号 + * timeData:详情请见时间区数据格式结构体EQtimeAreaData_G56 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区添加内容EQtimeAreaData::fontName == 字库名称 + * 注:ios下无法使用program_timeAreaAddContent请使用program_fontPath_timeAreaAddContent() + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_fontPath_timeAreaAddContent(ushort areaID, ref EQtimeAreaData_G56 timeData); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaChangeContent() + * areaID:区域的ID号 + * timeData:详情请见时间区数据格式结构体EQtimeAreaData_G56 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区修改内容EQtimeAreaData::fontName == 字库的路径加字库文件名(字库地址) + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaChangeContent(ushort areaID, ref EQtimeAreaData_G56 timeData); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaGetOnePage() + * 参数名: + * areaID:区域ID + * pageNum: 第几页,从0开始计算 + * 返回值:0 成功, 其他值为错误号 + * 功 能:返回时间区域第n张图片 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaGetOnePage(ushort areaID, ref getPageData pageData); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaAddAnalogClock() + * 参数名: + * areaID:区域ID + * header: 详情见EQAnalogClockHeader_G56结构体 + * cStyle: 表盘样式,详情见E_ClockStyle + * cColor: 表盘颜色,详情见E_Color_G56通过此枚举值可以直接配置七彩色,如果大于枚举范围使用RGB888模式 + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区添加模拟时钟 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaAddAnalogClock(ushort areaID, ref EQAnalogClockHeader_G56 header, E_ClockStyle cStyle, ref ClockColor_G56 cColor); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaChangeAnalogClock() + * 参数名: + * areaID:区域ID + * header: 详情见EQAnalogClockHeader_G56结构体 + * cStyle: 表盘样式,详情见E_ClockStyle + * cColor: 表盘颜色,详情见E_Color_G56通过此枚举值可以直接配置七彩色,如果大于枚举范围使用RGB888模式 + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区修改模拟时钟的一些设置参数 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaChangeAnalogClock(ushort areaID, ref EQAnalogClockHeader_G56 header, E_ClockStyle cStyle, ref ClockColor_G56 cColor); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaChangeDialPic() + * 参数名: + * areaID: 区域ID + * picPath: 表盘图片位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区从外部添加表盘图片 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaChangeDialPic(ushort areaID, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaChangeDialPicAdd_G56() + * 参数名: + * areaID: 区域ID + * picPath: 表盘图片位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区从外部添加表盘图片 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaChangeDialPicAdd_G56(ushort areaID, byte[] picAdd, int picLen); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaRemoveDialPic() + * 参数名: + * areaID:区域ID + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区移除外部添加的表盘图片 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaRemoveDialPic(ushort areaID); + + //6代控制卡动态区功能开始:==================================================================================================================================================================================================================== + + /* + 功能:设置动态区颜色像素类型:R+G 或 G+R + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_SetDualPixel(E_DoubleColorPixel_G56 ePixelRGorGR); + + /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 功能说明:6代更新动态区最基本功能:仅显示动态区:即不与节目一起显示,如果当前有节目显示,调用此函数后,LED屏幕上会清空原来的内容,显示此函数中 strAreaTxtContent 参数的内容; + 如果要与屏幕上原来显示的节目一起显示,请调用下面的 动态区文本关联节目 函数;与节目一起显示时,要注意动态区域与原来的节目区域不能重叠! + + 参数说明: + pIP,nPort :(与控制卡直连时)控制卡IP; 端口号; + (通过服务端连时)服务端IP;服务端返回的控制卡对应的端口号; + + color :LED屏颜色类型,详见 E_ScreenColor_G56 声明; + uAreaId :区域号; 如果控制卡只支持4个动态区,则uAreaId的取值范围:0-3;共4个;且只能是0-3之间的值; + uAreaX,uAreaY :显示区域坐标,即动态区域左上角在LED显示屏的位置/坐标;如:(0,0)则是从LED显示屏幕的最左上角开始显示动态区域; + 注意:不同控制卡的最小LED屏宽不同,如BX-6E2X最小屏宽为80个显示单位,所以连接的LED屏如果只有64宽度,则在坐标为(0,0)且是靠左显示的情况下,最左边的16个单元会显示不完整; + 此时,可以考虑设置起始点X的坐标为16,即(16,0),此时宽高为(80-16,高); + uWidth,uHeight:动态区域的宽度,高度; + fontName :字体名称,如"宋体"; nFontSize:字体大小,如12; + strAreaTxtContent:要显示的文本内容 + -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaTxt_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaId, ushort uAreaX, ushort uAreaY, + ushort uWidth, ushort uHeight, byte[] fontName, byte nFontSize, byte[] strAreaTxtContent); + + //6代更新动态区详细功能:仅显示动态区; 将要显示的一些特性/属性,封装在 EQareaHeader_G6 和 EQpageHeader_G6 结构体中; + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaTxtDetails_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaId, ref EQareaHeader_G6 oAreaHeader_G6, + ref EQpageHeader_G6 stPageHeader, byte[] fontName, byte[] strAreaTxtContent); + + /* + 功能说明 :6代更新动态区详细功能:仅显示动态区; + 通讯方式 :使用串口发送; + 参数 说明 : + pSerialName :串口号字符串;如:byte pSerialName[] = "COM3"; + nBaudRateIndex :波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaTxtDetails_6G_Serial(byte[] pSerialName, byte nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaId, ref EQareaHeader_G6 oAreaHeader_G6, + ref EQpageHeader_G6 stPageHeader, byte[] fontName, byte[] strAreaTxtContent); + + //动态区文本关联节目: + //RelateProNum = 0 时,关联所有节目,与所有节目一起播放,如果没有节目,则不播放该动态区; + // > 0 时, 指定关联节目,要关联的节目ID存放在RelateProSerial[]中; + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaTxtDetails_WithProgram_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaId, ref EQareaHeader_G6 oAreaHeader_G6, + ref EQpageHeader_G6 stPageHeader, byte[] fontName, byte[] strAreaTxtContent, ushort RelateProNum, ushort[] RelateProSerial); + + /* + 功能说明:动态区关联节目 + 参数说明: + byte[] pSerialName : 串口名称,如"COM1"; + int nBaudRateIndex : 波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaTxtDetails_WithProgram_6G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaId, ref EQareaHeader_G6 oAreaHeader_G6, + ref EQpageHeader_G6 stPageHeader, byte[] fontName, byte[] strAreaTxtContent, ushort RelateProNum, ushort[] RelateProSerial); + + //更新动态区图片:仅显示动态区; + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaPic_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaId, ushort AreaX, ushort AreaY, + ushort AreaWidth, ushort AreaHeight, ref EQpageHeader_G6 pheader, byte[] picPath); + + /* + 功能说明:更新动态区图片:仅显示动态区; + 参数说明: + byte[] pSerialName : 串口名称,如"COM1"; + int nBaudRateIndex : 波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaPic_6G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaId, short AreaX, ushort AreaY, + ushort AreaWidth, ushort AreaHeight, ref EQpageHeader_G6 pheader, byte[] picPath); + + //动态区图片关联节目: + //RelateProNum = 0 时,关联所有节目,与所有节目一起播放,如果没有节目,则不播放该动态区; + // > 0 时, 指定关联节目,要关联的节目ID存放在RelateProSerial[]中; + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaPic_WithProgram_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaId, ushort AreaX, ushort AreaY, + ushort AreaWidth, ushort AreaHeight, ref EQpageHeader_G6 pheader, byte[] picPath, ushort RelateProNum, ushort[] RelateProSerial); + + /* + 功能说明:动态区图片关联节目: + 参数说明: + byte[] pSerialName : 串口名称,如"COM1"; + int nBaudRateIndex : 波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + RelateProNum : RelateProNum == 0 时,关联所有节目,与所有节目一起播放,如果没有节目,则不播放该动态区; + RelateProNum > 0 时, 指定关联节目,要关联的节目ID存放在RelateProSerial[]中; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaPic_WithProgram_G6_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaId, ushort AreaX, ushort AreaY, + ushort AreaWidth, ushort AreaHeight, ref EQpageHeader_G6 pheader, byte[] picPath, ushort RelateProNum, ushort[] RelateProSerial); + + //同时更新多个动态区:仅显示动态区,不显示节目 + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddTxtDetails_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams); + + /* + 功能说明:同时更新多个动态区文本:仅显示动态区,不显示节目; + 参数说明: + byte[] pSerialName : 串口名称,如"COM1"; + int nBaudRateIndex : 波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddTxtDetails_6G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams); + + //同时更新多个动态区文本:并与节目关联,即与节目一起显示 + //RelateProNum = 0 时,关联所有节目,与所有节目一起播放,如果没有节目,则不播放该动态区; + // > 0 时, 指定关联节目,要关联的节目ID存放在RelateProSerial[]中; + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddTxtDetails_WithProgram_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams, ushort RelateProNum, ushort[] RelateProSerial); + + /* + 功能说明:同时更新多个动态区文本:并与节目关联,即与节目一起显示 + 参数说明: + byte[] pSerialName : 串口名称,如"COM1"; + int nBaudRateIndex : 波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + ushort RelateProNum : = 0 时,关联所有节目,与所有节目一起播放,如果没有节目,则不播放该动态区; + > 0 时, 指定关联节目,要关联的节目ID存放在RelateProSerial[]中; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddTxtDetails_WithProgram_G6_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams, ushort RelateProNum, ushort[] RelateProSerial); + + //同时更新多个动态区图片:仅显示动态区图片;不与节目关联/不与节目一起显示; + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddAreaPic_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams); + + /* + 功能说明:同时更新多个动态区图片;仅显示动态区图片/不与节目关联/不与节目一起显示; + 参数说明: + byte[] pSerialName : 串口名称,如"COM1"; + int nBaudRateIndex : 波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddAreaPic_6G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams); + + //同时更新多个动态区图片,并与节目关联,即与节目一起显示; + //RelateProNum = 0 时,关联所有节目,与所有节目一起播放,如果没有节目,则不播放该动态区; + // > 0 时, 指定关联节目,要关联的节目ID存放在RelateProSerial[]中; + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddAreaPic_WithProgram_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams, ushort RelateProNum, ushort[] RelateProSerial); + + /* + 功能说明:同时更新多个动态区图片,并与节目关联,即与节目一起显示; + 参数说明: + byte[] pSerialName : 串口名称,如"COM1"; + int nBaudRateIndex : 波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + ushort RelateProNum : = 0 时,关联所有节目,与所有节目一起播放,如果没有节目,则不播放该动态区; + > 0 时, 指定关联节目,要关联的节目ID存放在RelateProSerial[]中; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicAreaS_AddAreaPic_WithProgram_6G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, byte uAreaCount, DynamicAreaParams[] pParams, ushort RelateProNum, ushort[] RelateProSerial); + + /* + 功能说明:增加多条信息(文本/图片)到指定的动态区,并可以关联这个动态区到指定的节目; + 通讯方式 :TCP + 参数 说明 : + pIP :控制卡IP地址,如"192.168.1.111"; + nPort :控制卡默认TCP方式的端口号为:5005 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaInfos_6G(byte[] pIP, int nPort, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + + byte nInfoCount, + DynamicAreaBaseInfo_5G[] pInfo + ); + + /* + 功能说明:增加多条信息(文本/图片)到指定的动态区,并可以关联这个动态区到指定的节目; + 通讯方式 :使用串口发送; + 参数 说明 : + pSerialName :串口号字符串;如:byte pSerialName[] = "COM3"; + nBaudRateIndex :波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaInfos_G6_Serial(byte[] pSerialName, byte nBaudRateIndex, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + + byte nInfoCount, + DynamicAreaBaseInfo_5G[] pInfo + ); + + /* + 功能说明:一次向一个动态区发送/更新多条信息(文字或图片)及语音 + 参数说明: + RunMode: 动态区运行模式 + //0— 动态区数据循环显示。 + //1— 动态区数据显示完成后静止显示最后一页数据。 + //2— 动态区数据循环显示,超过设定时间后数据仍未更新时不再显示 + //3— 动态区数据循环显示,超过设定时间后数据仍未更新时显示Logo 信息, Logo 信息即为动态区域的最后一页信息4— 动态区数据顺序显示,显示完最后一页后就不再显示 + Timeout: 动态区数据超时时间,单位为秒;该动态区显示时长超过这个值的时间(s),会自动删除,仅部分卡类型支持;未试过; + RelateAllPro: 当该字节为 1 时,所有异步节目播放时都允许播放该动态区域;为 0 时,由接下来的规则来决定 + RelateProNum: 动态区域关联了多少个异步节目一旦关联了某个异步节目,则当该异步节目播放时允许播放该动态区域,否则,不允许播放该动态区域 + RelateProSerial: 动态区域关联的节目编号; + pSoundData: 语音内容;默认为空不发送语音; + *参数详细说明参考《6th 动态区域用户手册》 + + 返回值:0 成功;-1 失败; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaInfos_6G_V2(byte[] pIP, int nPort, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + BxAreaFrmae_Dynamic_G6 oFrame, + + byte nInfoCount, + DynamicAreaBaseInfo_5G[] pInfo, + ref EQSound_6G pSoundData + ); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct BXSound_6G + { + public byte SoundFlag; //1 0x00 是否使能语音播放;0 表示不使能语音; 1 表示播放下文中 SoundData 部分内容; + + //SoundData 部分内容--------------------------------------------------------------------------------------------------------------------------------------------------- + public byte SoundPerson; //1 0x00 发音人 该值范围是 0 - 5,共 6 种选择只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 0 + + public byte SoundVolum; //1 0x05 音量该值范围是 0~10,共 11 种,0表示静音只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 5 + public byte SoundSpeed; //1 0x05 语速该值范围是 0~10,共 11 种只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 5 + public byte SoundDataMode; //1 0x00 SoundData 的编码格式:该值意义如下:0x00 GB2312; 0x01 GBK; 0x02 BIG5; 0x03 UNICODE只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送 + public int SoundReplayTimes; // 4 0x00000000 重播次数该值为 0,表示播放 1 次该值为 1,表示播放 2 次 + + //...... + //该值为 0xffffffff,表示播放无限次只有 SoundFlag(是否使能语播放)为 1 时才发送该字节,否则不发送该值默认为 0 + public int SoundReplayDelay;// 4 0x00000000 重播时间间隔该值表示两次播放语音的时间间隔,单位为 10ms只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送该值默认为 0 + + public byte SoundReservedParaLen;// 1 0x03 语音参数保留参数长度 + public byte Soundnumdeal; // 1 0 0:自动判断1:数字作号码处理 2:数字作数值处理只有当 SoundFlag 为 1 且SoundReservedParaLen不为 0才发送此参数 + public byte Soundlanguages; // 1 0 0:自动判断语种1:阿拉伯数字、度量单位、特殊符号等合成为中文2:阿拉伯数字、度量单位、特殊符号等合成为英文只有当 SoundFlag 为 1 且 SoundReservedParaLen不为 0才发送此参数(目前只支持中英文) + public byte Soundwordstyle; // 1 0 0:自动判断发音方式1:字母发音方式2:单词发音方式;只有当 SoundFlag 为 1 且SoundReservedParaLen不为 0才发送此参数 + public int SoundDataLen; // 4 语音数据长度; 只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送 + public IntPtr SoundData; // N 语音数据只有 SoundFlag(是否使能语音播放)为 1 时才发送该字节,否则不发送 + };/*这个语音结构体BXSound_6G仅在动态区时使用;图文分区播放语音请使用:EQPicAreaSoundHeader_G6;*/ + + /* + 功能说明:增加多条信息(文本/图片)到指定的动态区,并可以关联这个动态区到指定的节目; + 通讯方式 :使用串口发送; + 参数 说明 : + pSerialName :串口号字符串;如:byte pSerialName[] = "COM3"; + nBaudRateIndex :波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaInfos_6G_V2_Serial(byte[] pSerialName, byte nBaudRateIndex, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + + byte nInfoCount, + DynamicAreaBaseInfo_5G[] pInfo + ); + + /* + 功能:TCP方式删除动态区 + 删除动态区:删除单个动态区: + uAreaId = 0xff:删除所有区域 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_DelArea_6G(byte[] pIP, int nPort, byte uAreaId); + + /* + 功能:TCP方式删除多个动态区: + 参数: + pAreaID-存放要删除的动态区ID数组; + uAreaCount-动态区ID数组中的个数; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_DelAreas_6G(byte[] pIP, int nPort, byte uAreaCount, byte[] pAreaID); + + /* + 功能:串口方式删除动态区 + 删除动态区:删除单个动态区: + uAreaId = 0xff:删除所有区域 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] public static extern int bxDual_dynamicArea_DelArea_G6_Serial(byte[] pSerialName, byte nBaudRateIndex, byte uAreaId); + + /* + 功能:串口方式删除多个动态区: + 参数: + pAreaID-存放要删除的动态区ID数组; + uAreaCount-动态区ID数组中的个数; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_DelAreas_G6_Serial(byte[] pSerialName, byte nBaudRateIndex, byte uAreaCount, byte[] pAreaID); + + /* + 功能:插入独立语音 + 参数: + byte VoiceFlg; //1 1 语音属性 0:此条语音从头插入队列,且停止当前正在播放的语音 1:此条语音从头插入队列,不停止当前播报的语音 2:此条语音从尾插入队列 + byte StoreFlag; //1 0 该值为 1 表示需要存储到 FLASH 中,掉电信息不丢失该值为 0 表示需要存储到 RAM 中,掉电信息丢失 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_InsertSoundIndepend(byte[] pIP, int nPort, ref EQSoundDepend_6G stSoundData, byte VoiceFlg, byte StoreFlag); + + /* + 功能:5.4.3 更新独立语音命令 + stSoundData:指向存放EQSoundDepend_6G结构的一段内存首地址指针; + nSoundDataCount:指示stSoundData指向内存地址空间中存放EQSoundDepend_6G个数; + StoreFlag:该值为 1 表示需要存储到 FLASH 中,掉电信息不丢失;该值为 0 表示需要存储到 RAM 中,掉电信息丢失 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_UpdateSoundIndepend(byte[] pIP, int nPort, ref EQSoundDepend_6G stSoundData, ushort nSoundDataCount, byte StoreFlag); + + //6代控制卡动态区功能结束.============================================================================================================================================================================================================================== + + //5代控制卡动态区功能开始:==================================================================================================================================================================================================================== + /* + 功能说明:发送一条文本信息到指定的动态区,并可以关联这个动态区到指定的节目;其它参考信息参见 上面的 6代控制卡动态区功能 函数 bxDual_dynamicArea_AddAreaTxt_6G 上面的说明; + 参数说明: + strAreaTxtContent - 动态区域内要显示的文本内容 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaWithTxt_5G(byte[] pIP, int nPort, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + //PageStyle begin-------- + byte DisplayMode, + byte ClearMode, + byte Speed, + ushort StayTime, + byte RepeatTime, + //PageStyle End. + //显示内容和字体格式 begin--------- + EQfontData oFont, + byte[] fontName, + byte[] strAreaTxtContent + //end. + ); + + /* + 功能说明:发送一条文本信息到指定的动态区,并可以关联这个动态区到指定的节目; + 通讯方式 :使用串口发送; + 参数 说明 : + pSerialName :串口号字符串;如:byte pSerialName[] = "COM3"; + nBaudRateIndex :波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaWithTxt_5G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + //PageStyle begin-------- + byte DisplayMode, + byte ClearMode, + byte Speed, + ushort StayTime, + byte RepeatTime, + //PageStyle End. + //显示内容和字体格式 begin--------- + EQfontData oFont, + byte[] fontName, + byte[] strAreaTxtContent + //end. + ); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaWithTxt_Point_5G(byte[] pIP, int nPort, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + ref EQareaframeHeader oFrame, + //PageStyle begin-------- + byte DisplayMode, + byte ClearMode, + byte Speed, + ushort StayTime, + byte RepeatTime, + //PageStyle End. + //显示内容和字体格式 begin--------- + ref EQfontData oFont, + byte[] fontName, + byte[] strAreaTxtContent + //end. + ); + + /* + 功能说明:发送一条文本信息到指定的动态区,并可以关联这个动态区到指定的节目; + 通讯方式 :使用串口发送; + 参数 说明 : + pSerialName :串口号字符串;如:byte pSerialName[] = "COM3"; + nBaudRateIndex :波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaWithTxt_Point_5G_Serial(byte[] pSerialName, int nBaundRateIndex, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + ref EQareaframeHeader oFrame, + //PageStyle begin-------- + byte DisplayMode, + byte ClearMode, + byte Speed, + ushort StayTime, + byte RepeatTime, + //PageStyle End. + //显示内容和字体格式 begin--------- + ref EQfontData oFont, + byte[] fontName, + byte[] strAreaTxtContent + //end. + ); + + /* + 功能说明:发送一个图片到指定的动态区,并可以关联这个动态区到指定的节目; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaWithPic_5G(byte[] pIP, int nPort, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + //PageStyle begin-------- + byte DisplayMode, + byte ClearMode, + byte Speed, + ushort StayTime, + byte RepeatTime, + //PageStyle End. + //图片路径 begin--------- + byte[] filePath + //end. + ); + + /* + 功能说明:发送一个图片到指定的动态区,并可以关联这个动态区到指定的节目; + 通讯方式 :使用串口发送; + 参数 说明 : + pSerialName :串口号字符串;如:byte pSerialName[] = "COM3"; + nBaudRateIndex :波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + 函数返回: + 0 :成功; + -1 :失败; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaWithPic_5G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + //PageStyle begin-------- + byte DisplayMode, + byte ClearMode, + byte Speed, + ushort StayTime, + byte RepeatTime, + //PageStyle End. + //图片路径 begin--------- + byte[] filePath + //end. + ); + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct DynamicAreaBaseInfo_5G + { + public byte nType; // nType=1:文本; nType=2:图片; + + //PageStyle begin--------------- + public byte DisplayMode; + + public byte ClearMode; + public byte Speed; + public ushort StayTime; + public byte RepeatTime; + //PageStyle End. + + //文本显示内容和字体格式 begin--------- + public EQfontData oFont; + + public IntPtr fontName; + public IntPtr strAreaTxtContent; + //end. + + //图片路径 begin--------- + public IntPtr filePath; + + //end. + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct EQfontData + { + public E_arrMode arrMode; //排列方式--单行多行 E_arrMode:: eSINGLELINE, //单行 eMULTILINE, //多行 + public ushort fontSize; //字体大小 + public uint color;//字体颜色 E_Color_G56 此通过此枚举值可以直接配置七彩色,如果大于枚举范围使用RGB888模式 + public byte fontBold; //是否为粗体 + public byte fontItalic;//是否为斜体 + public E_txtDirection tdirection;//文字方向 + public ushort txtSpace; //文字间隔 + public byte Halign; //横向对齐方式(0系统自适应、1左对齐、2居中、3右对齐) + public byte Valign; //纵向对齐方式(0系统自适应、1上对齐、2居中、3下对齐) + } + + /* + 功能说明:发送多条信息(文本/图片)到指定的动态区,并可以关联这个动态区到指定的节目; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaInfos_5G(byte[] pIP, int nPort, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + + byte nInfoCount, + DynamicAreaBaseInfo_5G[] pInfo + ); + + /* + 功能说明:增加多条信息(文本/图片)到指定的动态区,并可以关联这个动态区到指定的节目; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaInfos_5G_Point(byte[] pIP, int nPort, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + + byte nInfoCount, + DynamicAreaBaseInfo_5G[] pInfo + + ); + + /* + 功能说明:发送多条信息(文本/图片)到指定的动态区,并可以关联这个动态区到指定的节目; + 通讯方式 :使用串口发送; + 参数 说明 : + pSerialName :串口号字符串;如:byte pSerialName[] = "COM3"; + nBaudRateIndex :波特率;取值为1时,代表波特率为9600; 取值为2时,代表波特率为57600; + 函数返回: + 0 :成功; + -1 :失败; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_AddAreaInfos_5G_Serial(byte[] pSerialName, int nBaudRateIndex, E_ScreenColor_G56 color, + byte uAreaId, + byte RunMode, + ushort Timeout, + byte RelateAllPro, + ushort RelateProNum, + ushort[] RelateProSerial, + byte ImmePlay, + ushort uAreaX, ushort uAreaY, ushort uWidth, ushort uHeight, + EQareaframeHeader oFrame, + + byte nInfoCount, + DynamicAreaBaseInfo_5G[] pInfo + ); + + //删除动态区: + /* + 功能:删除单个动态区: + 参数:uAreaId = 0xff:删除所有区域 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_DelArea_5G(byte[] pIP, int nPort, byte uAreaId); + + /* + 功能:删除多个动态区: + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_DelAreaS_5G(byte[] pIP, int nPort, byte uAreaCount, byte[] pAreaID); + + /* + 功能:串口方式删除动态区 + 删除动态区:删除单个动态区: + uAreaId = 0xff:删除所有区域 + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_dynamicArea_DelArea_G5_Serial(byte[] pSerialName, byte nBaudRateIndex, byte uAreaId); + + /* + 功能:串口方式删除多个动态区: + 参数: + pAreaID-存放要删除的动态区ID数组; + uAreaCount-动态区ID数组中的个数; + */ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] public static extern int bxDual_dynamicArea_DelAreaS_G5_Serial(byte[] pSerialName, byte nBaudRateIndex, byte uAreaCount, byte[] pAreaID); + + //5代控制卡动态区功能结束:==================================================================================================================================================================================================================== + + /*****************************以下为六代接口*******************************************/ + + /*! *************************************************************** + * 函数名: bxDual_program_addProgram_G6() + * 参数名: + * EQprogramHeader_G6:参考结构体EQprogramHeader_G6 + * 返回值:0 成功, 其他值为错误号 + * 功 能:添加节目 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_addProgram_G6(ref EQprogramHeader_G6 programH); + + /*! *************************************************************** + * 函数名: bxDual_program_addPlayPeriodGrp_G6() + * 返回值:0 成功, 其他值为错误 + * 功 能:添加节目播放时段 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_addPlayPeriodGrp_G6(ref EQprogramppGrp_G56 header); + + /*! *************************************************************** + * 函数名: bxDual_program_deleteProgram_G6() + * 参数名: + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:删除节目 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_deleteProgram_G6(); + + /*! *************************************************************** + * 函数名: bxDual_program_freeBuffer_G6() + * 参数名: + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:释放生成节目文件的缓冲区 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_freeBuffer_G6(ref EQprogram_G6 program); + + /*! *************************************************************** + * 函数名: bxDual_program_changeProgramParams_G6() + * EQprogramHeader_G6:参考结构体EQprogramHeader_G6 + * 返回值:0 成功, 其他值为错误号 + * 功 能:修改已添加节目的一些参数 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_changeProgramParams_G6(ref EQprogramHeader_G6 programH); + + /*! *************************************************************** + * 函数名: bxDual_program_addFrame_G6() + * sfHeader:参考结构体EQscreenframeHeader_G6 + * picPath:添加的边框图片路径 + * 返回值:0 成功, -1 不成功 + * 功 能:节目添加边框 + * 注:节目添加边框后,区域的坐标随即发生变化,添加区域的时候需注意 + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_addFrame_G6(ref EQscreenframeHeader_G6 sfHeader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_changeFrame_G6() + * sfHeader:参考结构体EQscreenframeHeader_G6 + * picPath:边框图片路径 + * 返回值:0 成功, -1 不成功 + * 功 能:节目修改已添加边框的一些参数 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_changeFrame_G6(ref EQscreenframeHeader_G6 sfHeader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_removeFrame_G6() + * 返回值:0 成功 + * 功 能:节目去掉边框 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_removeFrame_G6(); + + /*! *************************************************************** + * 函数名: bxDual_program_addArea_G6() + * 参数名:areaID:区域的ID号 + * aheader:参考结构体EQareaHeader_G6 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:节目添加区域 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_addArea_G6(ushort areaID, ref EQareaHeader_G6 aheader); + + /*! *************************************************************** + * 函数名: bxDual_program_deleteArea_G6() + * 参数名: + * areaID:区域ID号 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:节目删除已添加的区域 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_deleteArea_G6(ushort areaID); + + /*! *************************************************************** + * 函数名: bxDual_program_MoveArea_G6() + * areaID:区域的ID号 + * x:区域left坐标 + * y:区域top坐标 + * width:区域宽度 + * height:区域高度 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:改变区域坐标大小 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_MoveArea_G6(ushort areaID, int x, int y, int width, int height); + + /*! *************************************************************** + * 函数名: bxDual_program_picturesAreaAddTxt_G6() + * areaID:区域的ID号 + * str:需要画的文字 + * fontName:字体名称 + * pheader:参考结构体EQpageHeader_G6 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:画文字到图文区域 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_picturesAreaAddTxt_G6(ushort areaID, byte[] str, byte[] fontName, ref EQpageHeader_G6 pheader); + + /*! *************************************************************** + * 函数名: bxDual_program_picturesAreaChangeTxt_G6() + * areaID:区域的ID号 + * str:需要画的文字 + * pheader:参考结构体EQpageHeader_G6 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:修改图文区域已添加过的文字内容及EQpageHeader_G6结构体中的参数 + * 注: + * 如需修改字体,需要将区域删除,重新添加区域和文字 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_picturesAreaChangeTxt_G6(ushort areaID, byte[] str, ref EQpageHeader_G6 pheader); + + /*! *************************************************************** + * 函数名: bxDual_program_fontPath_picturesAreaAddTxt_G6() + * areaID:区域的ID号 + * str:需要画的文字 + * fontPathName:字体绝对路径加字库文件名称 + * pheader:参考结构体EQpageHeader_G6 + * 返回值:0 成功, 其他值为错误号 + * 功 能:图文区添加字符串--使用字库 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_fontPath_picturesAreaAddTxt_G6(ushort areaID, byte[] str, byte[] fontPathName, ref EQpageHeader_G6 pheader); + + /*! *************************************************************** + * 函数名: bxDual_program_fontPath_picturesAreaChangeTxt_G6() + * areaID:区域的ID号 + * str:需要画的文字 + * pheader:参考结构体EQpageHeader_G6 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:图文区修改字符串--使用字库 + * 注: + * 一定要参考协议对每一个值都不能理解出错否则发下去的内容显示肯定不是自己想要的 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_fontPath_picturesAreaChangeTxt_G6(ushort areaID, byte[] str, ref EQpageHeader_G6 pheader); + + /*! *************************************************************** + * 函数名: bxDual_program_pictureAreaAddPic_G6() + * areaID:区域的ID号 + * picID:图片编号,从0开始,第一次添加图片为0,第二次添加图片为1,依次累加,每个id对应一张图片 + * EQpageHeader_G6:参考结构体EQpageHeader_G6 + * picPath:图片的绝对路径加图片名称 + * 返回值:0 成功, 其他值为错误号 + * 功 能:添加图片到图文区域 + * 注:下位机播放图片的次序与picID一致,即最先播放picID为0的图片,依次播放 + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaAddPic_G6(ushort areaID, ushort picID, ref EQpageHeader_G6 pheader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_backGroundPic_G6() + * areaID:区域的ID号 + * picID:图片编号,从0开始,第一次添加图片为0,第二次添加图片为1,依次累加,每个id对应一张图片 + * EQpageHeader_G6:参考结构体EQpageHeader_G6 + * picPath:图片的绝对路径加图片名称 + * 返回值:0 成功, 其他值为错误号 + * 功 能:添加图片到图文区域 + * 注:下位机播放图片的次序与picID一致,即最先播放picID为0的图片,依次播放 + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_backGroundPic_G6(ushort areaID, ushort picID, ref EQpageHeader_G6 pheader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_backGroundColor_G6() + * areaID:区域的ID号 + * picID:图片编号,从0开始,第一次添加图片为0,第二次添加图片为1,依次累加,每个id对应一张图片 + * EQpageHeader_G6:参考结构体EQpageHeader_G6 + * BGColor:区域背景颜色值(RGB888) + * 返回值:0 成功, 其他值为错误号 + * 功 能:添加图片到图文区域 + * 注:下位机播放图片的次序与picID一致,即最先播放picID为0的图片,依次播放 + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_backGroundColor_G6(ushort areaID, ref EQpageHeader_G6 pheader, int BGColor); + + /*! **************************************************************** 函数名: bxDual_program_pictureAreaChangePic_G6() + * areaID:区域的ID号 + * picID:图片编号,传入需要修改的图片编号 + * EQpageHeader_G6:参考结构体EQpageHeader_G6 + * picPath:图片的绝对路径加图片名称 + * 返回值:0 成功, 其他值为错误号 + * 功 能:修改当前picID对应的图片和一些参数 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaChangePic_G6(ushort areaID, ushort picID, ref EQpageHeader_G6 pheader, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_pictureAreaEnableSound_G6() + * areaID:区域的ID号 + * sheader:参考结构体EQPicAreaSoundHeader_G6 + * soundData:语音数据 + * + * 返回值:0 成功, 其他值为错误 + * 功 能:图文分区使能语音播放 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaEnableSound_G6(ushort areaID, EQPicAreaSoundHeader_G6 sheader, byte[] soundData); + + /*! *************************************************************** + * 函数名: bxDual_program_pictureAreaChangeSoundSettings_G6() + * areaID:区域的ID号 + * sheader:参考结构体EQPicAreaSoundHeader_G6 + * soundData:语音数据 + * + * 返回值:0 成功, 其他值为错误 + * 功 能:图文分区修改语音播放的一些参数或数据 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaChangeSoundSettings_G6(ushort areaID, EQPicAreaSoundHeader_G6 sheader, byte[] soundData); + + /*! *************************************************************** + * 函数名: bxDual_program_pictureAreaDisableSound_G6() + * areaID:区域的ID号 + * + * + * + * 返回值:0 成功, 其他值为错误 + * 功 能:图文分区取消语音播放 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_pictureAreaDisableSound_G6(ushort areaID); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaSetBattleTime_G6() + * areaID:区域的ID号 + * header:参考结构体EQTimeAreaBattle_G6 + * + * + * 返回值:0 成功, 其他值为错误 + * 功 能:时间分区设置战斗时间和战斗时间的启动模式 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaSetBattleTime_G6(ushort areaID, ref EQTimeAreaBattle_G6 header); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaCancleBattleTime_G6() + * areaID:区域的ID号 + * + * + * + * 返回值:0 成功, 其他值为错误 + * 功 能:时间分区取消战斗时间 + * 注:取消后的时间分区将作为普通时间 + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaCancleBattleTime_G6(ushort areaID); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaAddContent_G6() + * areaID:区域的ID号 + * timeData:参考结构体EQtimeAreaData_G56 + * + * + * 返回值:0 成功, 其他值为错误 + * 功 能:时间分区添加时间等内容,详情请参考结构体EQtimeAreaData_G56 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaAddContent_G6(ushort areaID, ref EQtimeAreaData_G56 timeData); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaChangeContent_G6() + * areaID:区域的ID号 + * timeData:参考结构体EQtimeAreaData_G56 + * + * + * 返回值:0 成功, 其他值为错误 + * 功 能:时间分区修改时间等内容,详情请参考结构体EQtimeAreaData_G56 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaChangeContent_G6(ushort areaID, ref EQtimeAreaData_G56 timeData); + + /*! *************************************************************** + * 函数名: bxDual_program_fontPath_timeAreaAddContent_G6() + * areaID:区域的ID号 + * timeData:详情请见时间区数据格式结构体EQtimeAreaData_G56 + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区添加内容EQtimeAreaData::fontName == 字库名称 + * 注:ios下无法使用program_timeAreaAddContent_G6请使用program_fontPath_timeAreaAddContent_G6() + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_fontPath_timeAreaAddContent_G6(ushort areaID, ref EQtimeAreaData_G56 timeData); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaAddAnalogClock_G6() + * 参数名: + * areaID:区域ID + * header: 详情见EQAnalogClockHeader_G56结构体 + * cStyle: 表盘样式,详情见E_ClockStyle + * cColor: 表盘颜色,详情见E_Color_G56通过此枚举值可以直接配置七彩色,如果大于枚举范围使用RGB888模式 + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区添加模拟时钟 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaAddAnalogClock_G6(ushort areaID, ref EQAnalogClockHeader_G56 header, E_ClockStyle cStyle, ref ClockColor_G56 cColor); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaChangeAnalogClock_G6() + * 参数名: + * areaID:区域ID + * header: 详情见EQAnalogClockHeader_G56结构体 + * cStyle: 表盘样式,详情见E_ClockStyle + * cColor: 表盘颜色,详情见E_Color_G56通过此枚举值可以直接配置七彩色,如果大于枚举范围使用RGB888模式 + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区修改模拟时钟的一些设置参数 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaChangeAnalogClock_G6(ushort areaID, ref EQAnalogClockHeader_G56 header, E_ClockStyle cStyle, ref ClockColor_G56 cColor); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaChangeDialPic_G6() + * 参数名: + * areaID: 区域ID + * picPath: 表盘图片位置 + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区从外部添加表盘图片 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaChangeDialPic_G6(ushort areaID, byte[] picPath); + + /*! *************************************************************** + * 函数名: bxDual_program_timeAreaRemoveDialPic_G6() + * 参数名: + * areaID: 区域ID + * + * 返回值:0 成功, 其他值为错误号 + * 功 能:时间分区移除添加的表盘图片 + * 注: + * + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_timeAreaRemoveDialPic_G6(ushort areaID); + + /*! *************************************************************** + * 函数名: bxDual_program_IntegrateProgramFile_G6() + * 参数名: + * program:参考结构体EQprogram_G6 + * 返回值:0 成功, 其他值为错误号 + * 功 能:合成节目文件返回节目文件属性及地址 + * 注: + * EQprogram 结构体是用来回调发送文件所需要参数 + ******************************************************************/ + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_program_IntegrateProgramFile_G6(ref EQprogram_G6 program); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_Start_Server(int port); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_Stop_Server(int pServer); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_Get_Port_Barcode(byte[] barcode); + + [DllImport("bx_sdk_dual_server.dll", CharSet = CharSet.Unicode)] + public static extern int bxDual_Get_CardList(byte[] cards); + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/LedZK/LedZKManager.cs b/ConsoleTest/AutoWeight/LedZK/LedZKManager.cs new file mode 100644 index 0000000..cfa010a --- /dev/null +++ b/ConsoleTest/AutoWeight/LedZK/LedZKManager.cs @@ -0,0 +1,226 @@ +using System.Text; + +namespace ConsoleTest.AutoWeight.LedZK +{ + public class LedZKManager + { + private byte[] _ip; + private ushort _port; + private uint _handle; + private byte _width; + private byte _height; + + public LedZKManager() + { + _ip = Encoding.Default.GetBytes("192.168.0.199"); + _port = 5005; + } + + public LedZKManager(string ip, ushort port) + { + _ip = Encoding.Default.GetBytes(ip); + _port = port; + } + + #region Start & Stop Server + + /// + /// 开启服务 + /// + /// + public void StartServer() + { + //初始化动态库 + LedZKSDK.InitSdk(2, 2); + _handle = LedZKSDK.CreateClient(_ip, _port, LedZKSDK.bx_5k_card_type.BX_6K1, 3, 1, null); + ReadScreen(); + } + + /// + /// 停止服务 + /// + /// + public void StopServer() + { + LedZKSDK.Destroy(_handle); + //释放动态库 + LedZKSDK.ReleaseSdk(); + } + + #endregion Start & Stop Server + + #region Util Methods + + /// + /// 4x6 或 5x8 + /// \C1代表红色,\C2代表绿色,\C3代表黄色 + /// + /// + /// + /// + /// + /// + /// + /// 0x01:单行,0x02:多行 + /// 0x01:手动换行,0x02:自动换行 + /// + /// + public int SendDynamicArea(byte areaId, ushort x, ushort y, ushort width, ushort height, string text, + byte singleLine, byte newLine, byte speed) + { + var outText = Encoding.Default.GetBytes(text); + var header = new LedZKSDK.bx_5k_area_header + { + DynamicAreaLoc = areaId, + AreaType = 0x00, + AreaX = x, + AreaWidth = width, + AreaY = y, + AreaHeight = height, + RunMode = 0, + Timeout = 2, + SingleLine = singleLine, + NewLine = newLine, + Lines_sizes = 0, + DisplayMode = 0x01, + Speed = speed, + StayTime = 35 * 2, + Reserved1 = 0, + Reserved2 = 0, + Reserved3 = 0, + ExitMode = 0x00, + DataLen = outText.Length + }; + return LedZKSDK.SCREEN_SendDynamicArea(_handle, header, (ushort)outText.Length, outText); + } + + /// + /// 4x6 或 5x8 + /// \C1代表红色,\C2代表绿色,\C3代表黄色 + /// + /// + /// + /// + /// + /// + /// + /// + /// 0x01:单行,0x02:多行 + /// 0x01:手动换行,0x02:自动换行 + /// + /// + public int SendDynamicMoveArea(byte areaId, ushort x, ushort y, ushort width, ushort height, string text, + byte singleLine, byte newLine, byte speed) + { + var outText = Encoding.Default.GetBytes(text); + var header = new LedZKSDK.bx_5k_area_header + { + DynamicAreaLoc = areaId, + AreaType = 0x00, + AreaX = x, + AreaWidth = width, + AreaY = y, + AreaHeight = height, + RunMode = 0, + Timeout = 2, + SingleLine = singleLine, + NewLine = newLine, + Lines_sizes = 0, + DisplayMode = 0x03, + Speed = speed, + StayTime = 35 * 2, + Reserved1 = 0, + Reserved2 = 0, + Reserved3 = 0, + ExitMode = 0x00, + DataLen = outText.Length + }; + return LedZKSDK.SCREEN_SendDynamicArea(_handle, header, (ushort)outText.Length, outText); + } + + public void DelAllDynamicArea(byte min, byte max) + { + for (byte i = min; i <= max; i++) + DelDynamicArea(i); + } + + public int DelDynamicArea(byte areaId) + { + return LedZKSDK.SCREEN_DelDynamicArea(_handle, areaId); + } + + #endregion Util Methods + + #region Common Methods + + public int ReadScreen() + { + var status = new byte[24]; + ushort len = 0; + var ret = LedZKSDK.CON_ReadScreen(_handle, status, ref len); + _width = status[4]; + _height = status[6]; + return ret; + } + + /// + /// + /// + /// 当前亮度,强制调节亮度时有效,亮度值为0-15共16级。亮度值为15时亮度最高 + /// + public int ForceSetBrightness(byte lightValue) + { + lightValue %= 16; + return LedZKSDK.SCREEN_SetBrightness(_handle, 1, lightValue, null); + } + + /// + /// 获取屏号 + /// + /// + /// + public int GetScreenId(ref ushort screenId) + { + return LedZKSDK.CON_ReadScreenID(_handle, ref screenId); + } + + /// + /// 设置屏号 + /// + /// + /// + public int SetScreenId(ushort screenid) + { + return LedZKSDK.CON_SetScreenID(_handle, screenid); + } + + /// + /// 强制开机 + /// + /// + public int ForceTurnOn() + { + return LedZKSDK.SCREEN_ForceOnOff(_handle, 1); + } + + /// + /// 强制关机 + /// + /// + public int ForceTurnOff() + { + return LedZKSDK.SCREEN_ForceOnOff(_handle, 2); + } + + /// + /// 若ping命令执行成功,说明与控制卡通信成功 + /// + /// + public int Ping() + { + return LedZKSDK.CON_PING(_handle); ; + } + + #endregion Common Methods + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/LedZK/LedZKSDK.cs b/ConsoleTest/AutoWeight/LedZK/LedZKSDK.cs new file mode 100644 index 0000000..cca7d3b --- /dev/null +++ b/ConsoleTest/AutoWeight/LedZK/LedZKSDK.cs @@ -0,0 +1,966 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace ConsoleTest.AutoWeight.LedZK +{ + public class LedZKSDK + { + #region + + public class bx5k_err + { + public const int ERR_NO = 0; //No Error + public const int ERR_OUTOFGROUP = 1; //Command Group Error + public const int ERR_NOCMD = 2; //Command Not Found + public const int ERR_BUSY = 3; //The Controller is busy now + public const int ERR_MEMORYVOLUME = 4; //Out of the Memory Volume + public const int ERR_CHECKSUM = 5; //CRC16 Checksum Error + public const int ERR_FILENOTEXIST = 6; //File Not Exist + public const int ERR_FLASH = 7;//Flash Access Error + public const int ERR_FILE_DOWNLOAD = 8; //File Download Error + public const int ERR_FILE_NAME = 9; //Filename Error + public const int ERR_FILE_TYPE = 10;//File type Error + public const int ERR_FILE_CRC16 = 11;//File CRC16 Error + public const int ERR_FONT_NOT_EXIST = 12;//Font Library Not Exist + public const int ERR_FIRMWARE_TYPE = 13;//Firmware Type Error (Check the controller type) + public const int ERR_DATE_TIME_FORMAT = 14;//Date Time format error + public const int ERR_FILE_EXIST = 15;//File Exist for File overwrite + public const int ERR_FILE_BLOCK_NUM = 16;//File block number error + public const int ERR_COMMUNICATE = 100;//通信失败 + public const int ERR_PROTOCOL = 101;//协议数据不正确 + public const int ERR_TIMEOUT = 102;//通信超时 + public const int ERR_NETCLOSE = 103;//通信断开 + public const int ERR_INVALID_HAND = 104;//无效句柄 + public const int ERR_PARAMETER = 105;//参数错误 + public const int ERR_SHOULDREPEAT = 106;//需要重复上次数据包 + public const int ERR_FILE = 107;//无效文件 + } + + #endregion + + //串口停止位 + public enum serial_stopbits : byte + { + COM_ONESTOPBIT = 0, + COM_ONE5STOPBITS = 1, + COM_TWOSTOPBITS = 2, + } + + //串口校验模式 + public enum serial_parity : byte + { + COM_NOPARITY = 0, + COM_ODDPARITY = 1, + COM_EVENPARITY = 2, + COM_MARKPARITY = 3, + COM_SPACEPARITY = 4, + } + + //串口数据位 + public enum serial_databits : byte + { + COM_4BITS = 4, + COM_5BITS = 5, + COM_6BITS = 6, + COM_7BITS = 7, + COM_8BITS = 8, + } + + //控制器类型 + public enum bx_5k_card_type : byte + { + BX_5K1 = 0x51, + BX_5K2 = 0x58, + BX_5MK2 = 0x53, + BX_5MK1 = 0x54, + BX_5K1Q_YY = 0x5c, + BX_Any = 0xFE, + BX_6K1 = 0x61, + BX_6K2 = 0x62, + BX_6K3 = 0x63, + BX_6K1_YY = 0x64, + BX_6K2_YY = 0x65, + BX_6K3_YY = 0x66, + BX_6K1_4G = 0x67, + BX_6K2_4G = 0x68, + } + + //-------区域格式------ + // area header | data | + //--------------------- + //节目内区域定义 + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct bx_5k_area_header + { + public byte AreaType; + public ushort AreaX; + public ushort AreaY; + public ushort AreaWidth; + public ushort AreaHeight; + public byte DynamicAreaLoc; + public byte Lines_sizes; + public byte RunMode; + public short Timeout; + public byte Reserved1; + public byte Reserved2; + public byte Reserved3; + public byte SingleLine; + public byte NewLine; + public byte DisplayMode; + public byte ExitMode; + public byte Speed; + public byte StayTime; + public int DataLen; + } + + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct bx_5k_sound + { + public byte StoreFlag; + public byte SoundPerson;//一个字节 + public byte SoundVolum; + public byte SoundSpeed; + public byte SoundDataMode; + public int SoundReplayTimes; + public int SoundReplayDelay; + public byte SoundReservedParaLen; + public int SoundDataLen; + } + + [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.StdCall)] + public delegate void CallBackClientClose(uint hand, int err); + + //初始化动态库 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern void InitSdk(byte minorVer, byte majorVer); + + //释放动态库 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern void ReleaseSdk(); + + //创建广播通讯模式 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern uint CreateBroadCast(byte[] broad_ip, uint broad_port, bx_5k_card_type card_type, byte[] barcode, byte Option, int mode); + + //创建固定IP通讯模式 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern uint CreateClient(byte[] led_ip, uint led_port, bx_5k_card_type card_type, int tmout_sec, int mode, CallBackClientClose pCloseFunc); + + //创建TCP Modbus通讯 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern uint CreateTcpModbus(byte[] led_ip, bx_5k_card_type card_type, CallBackClientClose pCloseFunc); + + //创建串口通讯 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern uint CreateComClient(byte com, uint baudrate, bx_5k_card_type card_type, int mode, ushort ScreenID); + + //创建串口Modbus通讯 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern uint CreateComModbus(byte com, uint baudrate, serial_parity Parity, serial_databits DataBits, + serial_stopbits StopBits, bx_5k_card_type card_type, ushort ScreenID); + + //销毁通讯 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern void Destroy(uint dwHand); + + //设置通讯超时 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern void SetTimeout(uint dwHand, uint nSec); + + //ping + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_PING(uint dwHand); + + //复位 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_Reset(uint dwHand); + + // + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_ControllerStatus(uint dwHand, byte[] pStatus, ref ushort len); + + //查询字库信息 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_CheckCurrentFont(uint dwHand, byte[] fontStatus, ref ushort len); + + //回读客户信息 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_CheckCurrentCustomer(uint dwHand, byte[] CustomerStatus, ref ushort len); + + //参数回读 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_ReadScreen(uint dwHand, byte[] ScreenStatus, ref ushort len); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_SytemClockCorrect(uint dwHand); + + //查询固件状态 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_CheckCurrentFirmware(uint dwHand, byte[] FirmwareName, byte[] FirmwareVersion, byte[] FirmwareDateTime); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_SendFirmWareData(uint dwHand, byte overwrite, byte[] pFileName, byte[] FirmWareData, int FirmWareDataLen, CloseFunc pCloseFunc); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_FirmwareActivate(uint dwHand, byte[] FirmwareName); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_SetScreenID(uint dwHand, ushort newScreenID); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_ReadScreenID(uint dwHand, ref ushort pScreenID); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_ForceOnOff(uint dwHand, byte OnOffFlag); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_TimeTurnOnOff(uint dwHand, byte[] pTimer, int nGroup); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_SetBrightness(uint dwHand, byte BrightnessType, byte CurrentBrightness, byte[] BrightnessValue); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_SetWaitTime(uint dwHand, byte WaitTime); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_LockProgram(uint dwHand, byte LockFlag, byte StoreMode, byte[] ProgramFileName); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_DelDynamicArea(uint dwHand, byte DeleteAreaId); + + //动态区 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_SendDynamicArea(uint dwHand, bx_5k_area_header header, ushort TextLen, byte[] AreaText); + + //语音 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_SendSound(uint dwHand, bx_5k_sound sound, int TextLen, byte[] AreaText); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_SendSoundDynamicArea(uint dwHand, bx_5k_area_header header, ushort TextLen, byte[] AreaText, byte SoundMode, byte SoundPerson, byte SoundVolume, byte SoundSpeed, int sound_len, byte[] sounddata); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_Test(uint dwHand, byte TestTime); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SCREEN_CancelTimeOnOff(uint dwHand); + + #region 设置特殊动态区动态 + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_SetSpecialAppDynamic(uint dwHand, ushort AreaX, ushort AreaY, ushort AreaW, ushort AreaH, + byte DataType, byte Pagetotal, byte RunState, ushort Timeout, byte SingleLine, byte Lines_sizes, byte NewLine, ushort StayTime); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_SendPageData(uint dwHand, byte PageNum, ushort PageDataLen, byte[] PageData); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_SendLatticeMessage(uint dwHand, byte BlockFlag, ushort BlockAddr, byte[] BlockData, ushort BlockDataLen); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_DelSpecialAppDynamic(uint dwHand); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_SetIPAddress(uint dwHand, byte ConnnectMode, byte[] ip, byte[] SubnetMask, byte[] Gateway, ushort port, + byte ServerMode, byte[] ServerIPAddress, ushort ServerPort, byte[] ServerAccessPassword, ushort HeartBeatInterval, byte[] NetID); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_SetMACAddress(uint dwHand, byte[] MAC); + + //设置特殊动态区动态 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_SetSpecialAppDynamic(int dwHand, ushort AreaX, ushort AreaY, ushort AreaW, ushort AreaH, byte DataType, byte Pagetotal, + byte RunState, ushort Timeout, byte SingleLine, byte Lines_sizes, byte NewLine, ushort StayTime); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_WebSearch(uint dwHand, ref ushort Status, ref ushort Error, byte[] IP, + byte[] SubNetMask, byte[] Gate, ref ushort Port, byte[] Mac, byte[] NetID); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_DelPageData(uint dwHand, byte PageLog); + + #endregion + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_Formatting(uint dwHand); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_DeleteFile(uint dwHand, ushort FileNumber, byte[] pFileNameList); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_BeginSendMultiFiles(uint dwHand); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_SendFile(uint dwHand, byte overwrite, byte[] pFilePath); + + //发送节目 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_SendFileData(uint dwHand, byte overwrite, byte[] pFileName, ushort DisplayType, byte PlayTimes, + byte[] ProgramLife, byte ProgramWeek, byte ProgramTime, byte[] Period, byte AreaNum, byte[] AreaDataList, int AreaDataListLen); + + //添加扫描 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_SendScanData(uint dwHand, byte overwrite, byte[] pFileName, byte[] ScanData, int ScanDataLen); + + //添加字库 + public delegate void CloseFunc(int total, int sendlen); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_SendFontData(uint dwHand, byte overwrite, byte[] pFileName, byte FontWidth, byte FontHeight, + byte[] LibData, int LibData_len, byte FontEncode, CloseFunc pCloseFunc); + + //设置屏参 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_SendScreenData(uint dwHand, byte overwrite, byte[] pFileName, ushort Address, byte Baudrate, + ushort ScreenWith, ushort ScreenHeight, byte Color, byte MirrorMode, byte OE, byte DA, byte RowOrder, byte FreqPar, + byte OEAngle, byte CommTimeout, byte TipLanguage, byte LatticeMode); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_EndSendMultiFiles(uint dwHand); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int CON_SetDispInfo(uint dwHand, byte DispInfo); + + //设置客户信息 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int OFS_SetFontInformation(uint dwHand, byte OverWrite, byte[] ClientMsg); + + public delegate void CallBackCon(uint dwHand, string pid); + + public delegate void CallBackLedClose(uint dwHand, string pid, int err_code); + + //启动gprs服务器 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern bool StartGprsServer(uint port, CallBackCon pCallBackCon, CallBackLedClose pCallBackLedClose); + + //关闭gprs服务器 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern void CloseGprsServer(); + + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern void SetGprsAliveTick(uint dwHand, int time_sec); + + //扫描 + //返回值:0:发送数据正确;ERR_TIMEOUT:通讯超时;其它:返回错误代码。 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SendAndRecvBuff(uint dwHand, byte cmd_group, byte cmd, byte[] cmd_data, ushort data_len, byte[] recv_data, ref short p_recv_len); + + //返回值:0:发送数据正确;ERR_TIMEOUT:通讯超时;其它:返回错误代码。 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int SendBuff(uint dwHand, byte cmd_group, byte cmd, byte[] cmd_data, ushort data_len); + + // 网络搜索 + [DllImport("Led5kSDK.dll", CharSet = CharSet.Unicode)] + public static extern int BX5MK_WebSearch(uint dwHand, byte[] recv_buff, ushort[] recv_len); + } + + public class ItemObject + { + public string Text = ""; + public uint Value = 0;//可以多个 + + public ItemObject(string _text, uint _value) + { + Text = _text; + Value = _value; + } + } + + public class Led5kstaticArea + { + public LedZKSDK.bx_5k_area_header header; + public string text; + + public byte[] AreaToByteArray() + { + //计算header的大小:结构体bx_5k_area_header的大小 + LedZKSDK.bx_5k_area_header tu = new LedZKSDK.bx_5k_area_header(); + int hsz = Marshal.SizeOf(tu); + + //计算len的大小 + text = text.Replace("₩₩F", "\\F"); + List Byte_Area = new List(); + int Byte_t = 0; + string[] str_Area = text.Split('\\'); + int font = 0; + for (int n = 0; n < str_Area.Length; n++) + { + if (n > 0 && str_Area[n].Length > 1) + { + if (str_Area[n].Substring(0, 2).Equals("FK")) + { + font = 1; + if (str_Area[n].Length > 5) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n].Substring(0, 5)); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + + string Area_str = str_Area[n].Remove(0, 5); + byte[] Korean = System.Text.Encoding.Unicode.GetBytes(Area_str); + for (int k = 0; k < Korean.Length / 2; k++) + { + byte a = Korean[k * 2]; + Korean[k * 2] = Korean[k * 2 + 1]; + Korean[k * 2 + 1] = a; + } + Byte_Area.Add(Korean); + Byte_t += Korean.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("Unicode").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + else if (str_Area[n].Substring(0, 2).Equals("FE") || str_Area[n].Substring(0, 2).Equals("FO") || str_Area[n].Substring(0, 2).Equals("WF") || str_Area[n].Substring(0, 2).Equals("WC")) + { + font = 0; + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + else if (str_Area[n].Substring(0, 1).Equals("C") || str_Area[n].Substring(0, 1).Equals("D") || str_Area[n].Substring(0, 1).Equals("B") || str_Area[n].Substring(0, 1).Equals("T")) + { + if (font == 1) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n].Substring(0, 2)); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + + string Area_str = str_Area[n].Remove(0, 2); + byte[] Korean = System.Text.Encoding.Unicode.GetBytes(Area_str); + for (int k = 0; k < Korean.Length / 2; k++) + { + byte a = Korean[k * 2]; + Korean[k * 2] = Korean[k * 2 + 1]; + Korean[k * 2 + 1] = a; + } + Byte_Area.Add(Korean); + Byte_t += Korean.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + else if (str_Area[n].Substring(0, 1).Equals("n")) + { + if (font == 1) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n].Substring(0, 1)); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + + string Area_str = str_Area[n].Remove(0, 1); + byte[] Korean = System.Text.Encoding.Unicode.GetBytes(Area_str); + for (int k = 0; k < Korean.Length / 2; k++) + { + byte a = Korean[k * 2]; + Korean[k * 2] = Korean[k * 2 + 1]; + Korean[k * 2 + 1] = a; + } + Byte_Area.Add(Korean); + Byte_t += Korean.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + else + { + if (font == 1) + { + byte[] Korean = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[Korean.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < Korean.Length; c++) + { + special[c + 1] = Korean[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + } + else + { + if (n > 0) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + else + { + byte[] special = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + } + byte[] tmp = new byte[Byte_t]; + int g = 0; + for (int n = 0; n < Byte_Area.Count(); n++) + { + if (n > 0) + { + for (int j = 0; j < Byte_Area[n].Length; j++) + { + tmp[g + j] = Byte_Area[n][j]; + } + g += Byte_Area[n].Length; + } + else + { + for (int j = 0; j < Byte_Area[n].Length; j++) + { + tmp[j] = Byte_Area[n][j]; + } + g += Byte_Area[n].Length; + } + } + int len = tmp.Length + hsz + 4; + header.DataLen = tmp.Length; + //先copy len + byte[] bt = new byte[len]; + //byte[] lenToByte = System.BitConverter.GetBytes(len); + byte[] lenToByte = System.BitConverter.GetBytes(len); + lenToByte.CopyTo(bt, 0); + int index = lenToByte.Length; + + //再copy header + //分配结构体大小的内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(hsz); + //将结构体拷到分配好的内存空间 + Marshal.StructureToPtr(header, structPtr, false); + + //从内存空间拷到AreaDataList数组 + Marshal.Copy(structPtr, bt, index, hsz); + //释放内存空间 + Marshal.FreeHGlobal(structPtr); + //copy text + tmp.CopyTo(bt, index + hsz); + return bt; + } + + public int getAreaLen() + { + LedZKSDK.bx_5k_area_header tu = new LedZKSDK.bx_5k_area_header(); + int hsz = Marshal.SizeOf(tu); + //再考header + text = text.Replace("₩₩F", "\\F"); + List Byte_Area = new List(); + int Byte_t = 0; + string[] str_Area = text.Split('\\'); + int font = 0; + for (int n = 0; n < str_Area.Length; n++) + { + if (n > 0 && str_Area[n].Length > 1) + { + if (str_Area[n].Substring(0, 2).Equals("FK")) + { + font = 1; + if (str_Area[n].Length > 5) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n].Substring(0, 5)); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + + string Area_str = str_Area[n].Remove(0, 5); + byte[] Korean = System.Text.Encoding.Unicode.GetBytes(Area_str); + for (int k = 0; k < Korean.Length / 2; k++) + { + byte a = Korean[k * 2]; + Korean[k * 2] = Korean[k * 2 + 1]; + Korean[k * 2 + 1] = a; + } + Byte_Area.Add(Korean); + Byte_t += Korean.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("Unicode").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + else if (str_Area[n].Substring(0, 2).Equals("FE") || str_Area[n].Substring(0, 2).Equals("FO") || str_Area[n].Substring(0, 2).Equals("WF") || str_Area[n].Substring(0, 2).Equals("WC")) + { + font = 0; + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + else if (str_Area[n].Substring(0, 1).Equals("C") || str_Area[n].Substring(0, 1).Equals("D") || str_Area[n].Substring(0, 1).Equals("B") || str_Area[n].Substring(0, 1).Equals("T")) + { + if (font == 1) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n].Substring(0, 2)); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + + string Area_str = str_Area[n].Remove(0, 2); + byte[] Korean = System.Text.Encoding.Unicode.GetBytes(Area_str); + for (int k = 0; k < Korean.Length / 2; k++) + { + byte a = Korean[k * 2]; + Korean[k * 2] = Korean[k * 2 + 1]; + Korean[k * 2 + 1] = a; + } + Byte_Area.Add(Korean); + Byte_t += Korean.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + else if (str_Area[n].Substring(0, 1).Equals("n")) + { + if (font == 1) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n].Substring(0, 1)); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + + string Area_str = str_Area[n].Remove(0, 1); + byte[] Korean = System.Text.Encoding.Unicode.GetBytes(Area_str); + for (int k = 0; k < Korean.Length / 2; k++) + { + byte a = Korean[k * 2]; + Korean[k * 2] = Korean[k * 2 + 1]; + Korean[k * 2 + 1] = a; + } + Byte_Area.Add(Korean); + Byte_t += Korean.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + else + { + if (font == 1) + { + byte[] Korean = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[Korean.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < Korean.Length; c++) + { + special[c + 1] = Korean[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + else + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + } + else + { + if (n > 0) + { + byte[] special_1 = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + byte[] special = new byte[special_1.Length + 1]; + special[0] = 0x5c; + for (int c = 0; c < special_1.Length; c++) + { + special[c + 1] = special_1[c]; + } + Byte_Area.Add(special); + Byte_t += special.Length; + } + else + { + byte[] special = System.Text.Encoding.GetEncoding("GBK").GetBytes(str_Area[n]); + + Byte_Area.Add(special); + Byte_t += special.Length; + } + } + } + byte[] tmp = new byte[Byte_t]; + int g = 0; + for (int n = 0; n < Byte_Area.Count(); n++) + { + if (n > 0) + { + for (int j = 0; j < Byte_Area[n].Length; j++) + { + tmp[g + j] = Byte_Area[n][j]; + } + g += Byte_Area[n].Length; + } + else + { + for (int j = 0; j < Byte_Area[n].Length; j++) + { + tmp[j] = Byte_Area[n][j]; + } + g += Byte_Area[n].Length; + } + } + int len = tmp.Length + hsz + 4; + return len; + } + } + + public class Led5kProgram + { + public string name; + public bool overwrite; + + public ushort DisplayType; + public byte PlayTimes; + + public bool IsValidAlways; + public ushort StartYear; + public byte StartMonth; + public byte StartDay; + public ushort EndYear; + public byte EndMonth; + public byte EndDay; + + public byte ProgramWeek; + + public bool IsPlayOnTime; + public byte StartHour; + public byte StartMinute; + public byte StartSecond; + public byte EndHour; + public byte EndMinute; + public byte EndSecond; + public byte AreaNum; + public List m_arealist = new List(); + + #region//转DCB码 + + public static byte byte2bcd(byte num) + { + int i = num; + return (byte)(i / 10 * 16 + i % 10); + } + + public static byte bcd2byte(byte num) + { + int i = num; + return (byte)(i / 16 * 10 + i % 16); + } + + public static byte[] short2bcd(ushort num) + { + int i = num; + byte high = (byte)(i / 100); + byte low = (byte)(i % 100); + byte[] tmp = new byte[2]; + tmp[0] = byte2bcd(low); + tmp[1] = byte2bcd(high); + return tmp; + } + + #endregion + + public int SendProgram(uint hand) + { + byte[] ppFileName; + byte[] ProgramLife; + byte PlayPeriodGrpNum; + byte[] Period; + byte[] AreaDataList; + int AreaDataListLen; + + int sum = 0; + foreach (Led5kstaticArea s in m_arealist) + { + sum += s.getAreaLen(); + } + AreaDataList = new byte[sum]; + int index = 0; + foreach (Led5kstaticArea s in m_arealist) + { + byte[] bt = s.AreaToByteArray(); + bt.CopyTo(AreaDataList, index); + index += bt.Length; + } + AreaDataListLen = sum; + if (IsValidAlways == true) + { + ProgramLife = new byte[8]; + ProgramLife[0] = 0xff; + ProgramLife[1] = 0xff; + ProgramLife[2] = 0xff; + ProgramLife[3] = 0xff; + ProgramLife[4] = 0xff; + ProgramLife[5] = 0xff; + ProgramLife[6] = 0xff; + ProgramLife[7] = 0xff; + } + else + { + ProgramLife = new byte[8]; + byte[] tmp = Led5kProgram.short2bcd(StartYear); + ProgramLife[0] = tmp[0]; + ProgramLife[1] = tmp[1]; + ProgramLife[2] = byte2bcd(StartMonth); + ProgramLife[3] = byte2bcd(StartDay); + + byte[] tmp1 = Led5kProgram.short2bcd(EndYear); + + ProgramLife[4] = tmp1[0]; + ProgramLife[5] = tmp1[1]; + ProgramLife[6] = byte2bcd(EndMonth); + ProgramLife[7] = byte2bcd(EndDay); + } + + ppFileName = System.Text.Encoding.Default.GetBytes(name); + + if (IsPlayOnTime == true) + { + Period = new byte[7]; + Period[0] = byte2bcd(StartHour); + Period[1] = byte2bcd(StartMinute); + Period[2] = byte2bcd(StartSecond); + Period[3] = byte2bcd(EndHour); + Period[4] = byte2bcd(EndMinute); + Period[5] = byte2bcd(EndSecond); + Period[6] = 0; + } + else + { + Period = null; + } + + PlayPeriodGrpNum = Convert.ToByte(IsPlayOnTime ? 1 : 0); + + return LedZKSDK.OFS_SendFileData(hand, 1, ppFileName, DisplayType, PlayTimes, ProgramLife, + ProgramWeek, PlayPeriodGrpNum, Period, AreaNum, AreaDataList, AreaDataListLen); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Light/ILightManager.cs b/ConsoleTest/AutoWeight/Light/ILightManager.cs new file mode 100644 index 0000000..33841c9 --- /dev/null +++ b/ConsoleTest/AutoWeight/Light/ILightManager.cs @@ -0,0 +1,31 @@ +namespace ConsoleTest.AutoWeight.Light +{ + public interface ILightManager + { + #region Start & Stop Server + + public bool StartServer(); + + public bool StopServer(); + + public bool IsOpen(); + + #endregion Start & Stop Server + + #region Control Lights + + public bool OpenAllLight(); + + public bool CloseAllLight(); + + public bool OpenLight(int index); + + public bool CloseLight(int index); + + public bool LockLightOn(int index); + + public bool LockLightOff(int index); + + #endregion Control Lights + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Light/ILightRelay.cs b/ConsoleTest/AutoWeight/Light/ILightRelay.cs new file mode 100644 index 0000000..8baa2d7 --- /dev/null +++ b/ConsoleTest/AutoWeight/Light/ILightRelay.cs @@ -0,0 +1,35 @@ +namespace ConsoleTest.AutoWeight.Light +{ + public interface ILightRelay + { + /// + /// 连接设备 + /// + /// + bool StartServer(); + + /// + /// 断开设备 + /// + /// + bool StopServer(); + + /// + /// 是否连接设备 + /// + /// + bool IsOpen(); + + /// + /// 发送 Ascii 编码 + /// + /// + bool SendAscii(string text); + + /// + /// 发送 16进制 编码 + /// + /// + bool SendHex(string text); + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Light/LightManager.cs b/ConsoleTest/AutoWeight/Light/LightManager.cs new file mode 100644 index 0000000..9a1ef5f --- /dev/null +++ b/ConsoleTest/AutoWeight/Light/LightManager.cs @@ -0,0 +1,210 @@ +using ConsoleTest.Util; +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.IO; + +namespace ConsoleTest.AutoWeight.Light +{ + public class LightManager : ILightManager + { + private LightRelay _lightRelay; + private string _comName; + private int _baudRate; + private string _fileName; + + public LightManager() + { + } + + public LightManager(string comName, int baudRate, string fileName) + { + _comName = comName; + _baudRate = baudRate; + _fileName = fileName; + + _readCodeFlag = ReadLightCodeJson(); + } + + #region Start & Stop Server + + /// + /// 开启连接 + /// + /// + public bool StartServer() + { + _lightRelay = new LightRelay(_comName, _baudRate); + var ret = _lightRelay.StartServer(); + return ret; + } + + /// + /// 关闭连接 + /// + /// + public bool StopServer() + { + _lightRelay?.StopServer(); + _lightRelay = null; + return true; + } + + public bool IsOpen() + { + return _lightRelay?.IsOpen() ?? false; + } + + #endregion Start & Stop Server + + #region Control Lights Code + + private bool _readCodeFlag; + + /// + /// 控制所有灯编码,1 为开启所有灯,2 为关闭所有灯 + /// + private List _ctrlAllLightCodeList; + + /// + /// 开启某一路灯编码,不互斥,index 互相对应 + /// + private List _openLightCodeList; + + /// + /// 关闭某一路灯编码,不互斥,index 互相对应 + /// + private List _closeLightCodeList; + + /// + /// 互锁编码,控制只有一路灯亮,index 互相对应 + /// + private List _lockLightOnCodeList; + + /// + /// 互锁编码,控制只有一路灯灭,index 互相对应 + /// + private List _lockLightOffCodeList; + + private bool ReadLightCodeJson() + { + if (!File.Exists(_fileName)) return false; + JObject obj = JsonUtil.ReadFileJson(_fileName); + _ctrlAllLightCodeList = obj["CtrlAllLightCodeList"].ToObject>(); + _openLightCodeList = obj["OpenLightCodeList"].ToObject>(); + _closeLightCodeList = obj["CloseLightCodeList"].ToObject>(); + _lockLightOnCodeList = obj["LockLightOnCodeList"].ToObject>(); + _lockLightOffCodeList = obj["LockLightOffCodeList"].ToObject>(); + return true; + } + + public bool IsReadCodeSuccess() + { + return _readCodeFlag; + } + + #endregion Control Lights Code + + #region Control Lights + + /// + /// 开启所有灯 + /// + /// + public bool OpenAllLight() + { + var codeList = _ctrlAllLightCodeList; + var index = 1; + if (!IsIndexValid(codeList, index)) + return false; + var code = codeList[index]; + return _lightRelay.SendHex(code); + } + + /// + /// 关闭所有灯 + /// + /// + public bool CloseAllLight() + { + var codeList = _ctrlAllLightCodeList; + var index = 2; + if (!IsIndexValid(codeList, index)) + return false; + var code = codeList[index]; + return _lightRelay.SendHex(code); + } + + /// + /// 开启某一路灯 + /// + /// + /// + public bool OpenLight(int index) + { + var codeList = _openLightCodeList; + if (!IsIndexValid(codeList, index)) + return false; + var code = codeList[index]; + return _lightRelay.SendHex(code); + } + + /// + /// 关闭某一路灯 + /// + /// + /// + public bool CloseLight(int index) + { + var codeList = _closeLightCodeList; + if (!IsIndexValid(codeList, index)) + return false; + var code = codeList[index]; + return _lightRelay.SendHex(code); + } + + /// + /// 互斥开某一路灯 + /// + /// + /// + public bool LockLightOn(int index) + { + var codeList = _lockLightOnCodeList; + if (!IsIndexValid(codeList, index)) + return false; + var code = codeList[index]; + return _lightRelay.SendHex(code); + } + + /// + /// 互斥关某一路灯 + /// + /// + /// + public bool LockLightOff(int index) + { + var codeList = _lockLightOffCodeList; + if (!IsIndexValid(codeList, index)) + return false; + var code = codeList[index]; + return _lightRelay.SendHex(code); + } + + /// + /// 判断功能码是否可以使用 + /// + /// + /// + /// + public bool IsIndexValid(List codeList, int index) + { + if (codeList == null) + return false; + if (index < 1 || index > codeList.Count - 1) + return false; + return true; + } + + #endregion Control Lights + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Light/LightRelay.cs b/ConsoleTest/AutoWeight/Light/LightRelay.cs new file mode 100644 index 0000000..6380226 --- /dev/null +++ b/ConsoleTest/AutoWeight/Light/LightRelay.cs @@ -0,0 +1,65 @@ +using ConsoleTest.Util.PortUtil; +using System; + +namespace ConsoleTest.AutoWeight.Light +{ + public class LightRelay : ILightRelay + { + private YcSerialPort _port; + private readonly string _comName; + private readonly int _baudRate; + + public LightRelay(string comName, int baudRate) + { + _comName = comName; + _baudRate = baudRate; + } + + public bool StartServer() + { + _port = SerialPortBuilder.CreateSerialPort(_comName, _baudRate); + try + { + _port.OpenCom(); + } + catch (Exception ex) + { + Console.WriteLine(ex); + return false; + } + return true; + } + + public bool StopServer() + { + _port?.CloseCom(); + _port = null; + return true; + } + + public bool IsOpen() + { + if (_port == null) + return false; + if (!_port.IsOpen()) + return false; + return true; + } + + public bool SendAscii(string text) + { + if (!IsOpen()) + return false; + _port.SendAscii(text); + return true; + } + + public bool SendHex(string text) + { + if (!IsOpen()) + return false; + _port.SendHex(text); + return true; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Pos/PosManager.cs b/ConsoleTest/AutoWeight/Pos/PosManager.cs new file mode 100644 index 0000000..11be94a --- /dev/null +++ b/ConsoleTest/AutoWeight/Pos/PosManager.cs @@ -0,0 +1,206 @@ +namespace ConsoleTest.AutoWeight.Pos +{ + public class PosManager + { + private int _portType { get; set; }//0 COM,1 LPT ,2 USB 3 ETH + private int _printer { get; set; } + private int _bitmapType { get; set; } + private int _paperType { get; set; } = 1; //0 88m 1 58m 2 76m + + private int _result { get; set; } + + public PosManager() + { + } + + /// + /// 打开设备 + /// + /// + /// + /// + /// + public bool OpenDevice(int portType, bool bFile = false, string path = "") + { + string lpName; + _portType = portType; + switch (portType) + { + case PosSDK.POS_PT_COM: + lpName = "COM1:9600,N,8,1"; + break; + + case PosSDK.POS_PT_LPT: + lpName = "LPT1"; + break; + + case PosSDK.POS_PT_USB: + lpName = "SP-USB1"; + break; + + case PosSDK.POS_PT_NET: + lpName = "192.168.1.114"; + break; + + default: + lpName = "SP-USB1"; + portType = PosSDK.POS_PT_USB; + break; + } + _printer = PosSDK.POS_Port_OpenA(lpName, portType, bFile, path); + SetResult(_printer); + return _printer >= 0; + } + + /// + /// 关闭设备 + /// + /// + public bool CloseDevice() + { + int ret = PosSDK.POS_Port_Close(_printer); + SetResult(ret); + _printer = PosSDK.POS_ES_INVALIDPARA; + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 设备是否连接 + /// + /// + public bool IsConnected() + { + return _printer >= 0; + } + + public int GetResult() + { + return _result; + } + + private void SetResult(int ret) + { + _result = ret; + } + + /// + /// 初始化打印机 + /// + /// + public bool InitPrinter() + { + int ret = PosSDK.POS_Control_ReSet(_printer); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 选择字符对齐(居左/居中/居右)方式 + /// + /// 0:左对齐,1:居中,2:右对齐 + /// + public bool SetAlign(int alignType) + { + int ret = PosSDK.POS_Control_AlignType(_printer, alignType); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 设置打印左边距和打印区域 + /// + /// 设置左边距,默认值为 0 + /// 设置打印区域,默认值为 0 + /// + public bool SetLeftMargin(int iLeft, int iWidth) + { + int ret = PosSDK.POS_Control_SetPrintPosition(_printer, iLeft, iWidth); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 缓冲数据 + /// + /// + /// + /// + public bool PrintData(byte[] strBuff, int ilen) + { + int ret = PosSDK.POS_Output_PrintData(_printer, strBuff, ilen); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 打印本地单色位图 + /// + /// 本地单色位图存储路径 + /// + public bool PrintBmp(string bmpPath) + { + int ret = PosSDK.POS_Output_PrintBmpDirectA(_printer, bmpPath); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 打印格式化后的字符串 + /// + /// 0:选择标准 ASCII 字体A(12×24),1:选择压缩 ASCII 字体B(9×17) + /// 0:取消加粗模式,1:选择加粗模式 + /// 0:取消倍宽模式,1:选择倍宽模式 + /// 0:取消倍高模式,1:选择倍高模式 + /// 0:取消下划线模式,1:选择下划线模式 + /// 以空字符结尾的字符串 + /// + public bool PrintStr(int iFont, int iThick, int iWidth, int iHeight, int iUnderLine, string lpstring) + { + int ret = PosSDK.POS_Output_PrintFontStringA(_printer, iFont, iThick, iWidth, iHeight, iUnderLine, lpstring); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 打印缓冲区内容,进纸由参数 iLines 设置的行数并切纸 + /// + /// 0:全切,1:半切 + /// 进纸行数 + /// + public bool CutPaper(int type = 0, int len = 1) + { + int ret = PosSDK.POS_Control_CutPaper(_printer, type, len); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + public bool Color24_GrayBW(string path1, string path2) + { + int ret = PosSDK.Color24_GrayBW(path1, path2); + SetResult(ret); + return ret == PosSDK.POS_ES_SUCCESS; + } + + /// + /// 是否纸尽 + /// + /// + public bool IsPaperExhaust() + { + int ret = PosSDK.POS_Status_RTQueryTypeStatus(_printer, 4); + SetResult(ret); + return ret == PosSDK.POS_ES_PAPEROUT; + } + + /// + /// 是否将纸尽 + /// + /// + public bool IsPaperWillExhaust() + { + int ret = PosSDK.POS_Status_RTQueryTypeStatus(_printer, 4); + SetResult(ret); + return ret == PosSDK.POS_ES_PAPERENDING; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Pos/PosSDK.cs b/ConsoleTest/AutoWeight/Pos/PosSDK.cs new file mode 100644 index 0000000..3c7e769 --- /dev/null +++ b/ConsoleTest/AutoWeight/Pos/PosSDK.cs @@ -0,0 +1,274 @@ +using System.Runtime.InteropServices; +using System.Text; + +namespace ConsoleTest.AutoWeight.Pos +{ + public class PosSDK + { + #region Custom + + public struct PosParam + { + private string lpName; + private string portType; + private bool bFile; + private string path; + } + + #endregion Custom + + #region Const + + // pritner connect way + public const int POS_PT_COM = 1000; + + public const int POS_PT_LPT = 1001; + public const int POS_PT_USB = 1002; + public const int POS_PT_NET = 1003; + + // printer state + public const int POS_PS_NORMAL = 3001; + + public const int POS_PS_PAPEROUT = 3002; + public const int POS_PS_HEAT = 3003; + public const int POS_PS_DOOROPEN = 3004; + public const int POS_PS_BUFFEROUT = 3005; + public const int POS_PS_CUT = 3006; + public const int POS_PS_DRAWERHIGH = 3007; + + public const int POS_ES_PAPERENDING = 6; //纸将尽 + public const int POS_ES_DRAWERHIGH = 5; //钱箱高电平 + public const int POS_ES_CUT = 4; //切刀未复位 + public const int POS_ES_DOOROPEN = 3; //纸仓门开 + public const int POS_ES_HEAT = 2; //机头过热 + public const int POS_ES_PAPEROUT = 1; //打印机缺纸 + public const int POS_ES_SUCCESS = 0; //成功/发送成功/状态正常/打印完成 + public const int POS_ES_INVALIDPARA = -1; //参数错误 + public const int POS_ES_WRITEFAIL = -2; //写失败 + public const int POS_ES_READFAIL = -3; //读失败 + public const int POS_ES_NONMONOCHROMEBITMAP = -4; //非单色位图 + public const int POS_ES_OVERTIME = -5; //超时/写超时/读超时/打印未完成 + public const int POS_ES_FILEOPENERROR = -6; //文件/图片打开失败 + public const int POS_ES_OTHERERRORS = -100; //其他原因导致的错误 + + // barcode type + public const int POS_BT_UPCA = 4001; + + public const int POS_BT_UPCE = 4002; + public const int POS_BT_JAN13 = 4003; + public const int POS_BT_JAN8 = 4004; + public const int POS_BT_CODE39 = 4005; + public const int POS_BT_ITF = 4006; + public const int POS_BT_CODABAR = 4007; + public const int POS_BT_CODE93 = 4073; + public const int POS_BT_CODE128 = 4074; + + // 2D barcode type + public const int POS_BT_PDF417 = 4100; + + public const int POS_BT_DATAMATRIX = 4101; + public const int POS_BT_QRCODE = 4102; + + // HRI type + public const int POS_HT_NONE = 4011; + + public const int POS_HT_UP = 4012; + public const int POS_HT_DOWN = 4013; + public const int POS_HT_BOTH = 4014; + + //TSPL + public const int TSPL_PRINTER_STATUS_OUTPAPER = 1;//打印机缺纸 + + public const int TSPL_PRINTER_STATUS_WORK = 2; //打印中 + public const int TSPL_PRINTER_STATUS_ENCLOSURENOCLOSE = 3; //机壳未关 + public const int TSPL_PRINTER_STATUS_ERROR = 4; //打印机内部错误 + + public const int TSPL_PARAM_LESS_EQUAL_ZERO = -2; //参数小于等于0 + public const int TSPL_PARAM_GREAT_RANGE = -3; //参数大于指定范围 + public const int TSPL_SUCCESS = 0; + public const int TSPL_IDERROR = -1; + + #endregion Const + + #region Method + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Port_OpenA")] + public static extern int POS_Port_OpenA(string lpName, int iPort, bool bFile, string path); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintstringA")] + public static extern int POS_Output_PrintstringA(int printID, string strBuff); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintData")] + public static extern int POS_Output_PrintData(int printID, byte[] strBuff, int ilen); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Port_Close")] + public static extern int POS_Port_Close(int printID); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_CutPaper")] + public static extern int POS_Control_CutPaper(int printID, int type, int len); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_CashDraw")] + public static extern int POS_Control_CashDraw(int printID, int iNum, int time1, int time2); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Status_QueryStatus")] + public static extern int POS_Status_QueryStatus(int printID); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Status_RTQueryStatus")] + public static extern int POS_Status_RTQueryStatus(int printID); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Status_RTQueryTypeStatus")] + public static extern int POS_Status_RTQueryTypeStatus(int printID, int n); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_DownloadBmpToFlashA")] + public static extern int POS_Output_DownloadBmpToFlashA(int printID, string strPath); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_DownloadBmpToFlashNumA")] + public static extern int POS_Control_DownloadBmpToFlashNumA(int printID, string strPath, int num); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintBmpDirectA")] + public static extern int POS_Output_PrintBmpDirectA(int printID, string strPath); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintFontStringA")] + public static extern int POS_Output_PrintFontStringA(int printID, int iFont, int iThick, int iWidth, int iHeight, int iUnderLine, string lpString); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Input_PrinterId")] + public static extern int POS_Input_PrinterId(int printID, StringBuilder Buff); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_BlackMark")] + public static extern int POS_Control_BlackMark(int printID); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_SetPrintPosition")] + public static extern int POS_Control_SetPrintPosition(int printID, int iLeft, int iWidth); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Status_QueryTaskStatus")] + public static extern int POS_Status_QueryTaskStatus(int printID, int second); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintFlashBmp")] + public static extern int POS_Output_PrintFlashBmp(int printID, int n); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintOneDimensionalBarcodeA")] + public static extern int POS_Output_PrintOneDimensionalBarcodeA(int printID, int iType, int iWidth, int iHeight, int hri, string lpstring); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintTwoDimensionalBarcodeA")] + public static extern int POS_Output_PrintTwoDimensionalBarcodeA(int printID, int iType, int parameter1, int parameter2, int parameter3, string lpstring); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_DownloadRamBmpA")] + public static extern int POS_Output_DownloadRamBmpA(int printID, string lpFilePath); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_PrintRamBmp")] + public static extern int POS_Output_PrintRamBmp(int printID, int n); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_PrintTestpage")] + public static extern int POS_Control_PrintTestpage(int printID); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "Color24_GrayBW")] + public static extern int Color24_GrayBW(string szSourceFile, string szTargetFile); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_SetRotaryPrint")] + public static extern int POS_Control_SetRotaryPrint(int printID, int n); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_OppositeColor")] + public static extern int POS_Control_OppositeColor(int printID, bool bOppsite); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_AlignType")] + public static extern int POS_Control_SetRotaryPrint(int printID, bool iAlignType); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Output_SendLocalFileA")] + public static extern int POS_Output_SendLocalFileA(int printID, string lpFilePath); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_ReSet")] + public static extern int POS_Control_ReSet(int printID); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_SetPrintFontC")] + public static extern int POS_Control_SetPrintFontC(int printID, bool iDoubleWidth, bool iDoubleHeight, bool iUnderLine); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_SetInvertedPrint")] + public static extern int POS_Control_SetInvertedPrint(int printID, int n); + + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "POS_Control_AlignType")] + public static extern int POS_Control_AlignType(int printID, int iAlignType); + + //--------------ztongli.20170123-------------- + //设置页宽页高 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "PageSetupTSPL")] + public static extern int PageSetupTSPL(int printID, int PageWidth, int PageHeight); + + //画线 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "DrawLineTSPL")] + public static extern int DrawLineTSPL(int printID, int StartX, int StartY, int LineWidth, int LineHeight); + + //TL51打印 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "PrintTSPL")] + public static extern int PrintTSPL(int printID, int Set, int Copy); + + //画矩形 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "DrawBorderTSPL")] + public static extern int DrawBorderTSPL(int printID, int LineWidth, int top_left_x, int top_left_y, int bottom_right_x, int bottom_right_y); + + //文字 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "DrawTextTSPL")] + public static extern int DrawTextTSPL(int printID, int start_x, int start_y, bool isSimplifiedChinese, int xMultiplication, int yMultiplication, int rotate, string content); + + //一维条码 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "DrawBarCodeTSPL")] + public static extern int DrawBarCodeTSPL(int printID, int start_x, int start_y, string type, int height, bool isReadable, int rotate, int narrowWidth, int wideWidth, string content); + + ////清空缓冲区 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "ClearBuffTSPL")] + public static extern int ClearBuffTSPL(int printID); + + //二维条码 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "Draw2DBarCodeTSPL")] + public static extern int Draw2DBarCodeTSPL(int printID, int start_x, int start_y, string Max, string content); + + //下载位图 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "DownLoadBitMapTSPL")] + public static extern int DownLoadBitMapTSPL(int printID, bool isMoveFlash, string PathName); + + //将图片刷到缓冲区 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "PutBitMapTSPL")] + public static extern int PutBitMapTSPL(int printID, int start_x, int start_y, string fileName); + + //得到打印机状态 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "GetPrinterStatusTSPL")] + public static extern int GetPrinterStatusTSPL(int printID); + + //控制蜂鸣器发出一声响 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "DriveBeepTSPL")] + public static extern int DriveBeepTSPL(int printID); + + //设置国际字符集 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "SetCharsetNameTSPL")] + public static extern int SetCharsetNameTSPL(int printID, string CharsetName); + + //控制进纸或退纸距离 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "SetPaperbackOrPaperFeedTSPL")] + public static extern int SetPaperbackOrPaperFeedTSPL(int printID, bool isFeedBack, int mDot); + + //指定的区域反相打印命令 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "ReverseAreaTSPL")] + public static extern int ReverseAreaTSPL(int printID, int start_x, int start_y, int width, int height); + + //选择字符代码页 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "SelectCodePageTSPL")] + public static extern int SelectCodePageTSPL(int printID, int value); + + //设置标签间垂直间距 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "SetGAPTSPL")] + public static extern int SetGAPTSPL(int printID, double value); + + //定义标签的参考坐标原点命令 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "SetLabelReferenceTSPL")] + public static extern int SetLabelReferenceTSPL(int printID, int x, int y); + + //TL21打印 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "PrintTSPL21")] + public static extern int PrintTSPL21(int printID, int Set); + + //用于确认机型是TL21便于内部区别指令以及相关条件 + [DllImport("POS_SDK.dll", CharSet = CharSet.Ansi, EntryPoint = "SetIs21")] + public static extern int SetIs21(); + + #endregion Method + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Pos/dll.txt b/ConsoleTest/AutoWeight/Pos/dll.txt new file mode 100644 index 0000000..01694f8 --- /dev/null +++ b/ConsoleTest/AutoWeight/Pos/dll.txt @@ -0,0 +1,82 @@ +******************************************** +**由于DLL的特殊性,只能查看函数名/功能名!** +******************************************** +ClearBuffTSPL +Color24_GrayBW +DownLoadBitMapTSPL +Draw2DBarCodeTSPL +DrawBarCodeTSPL +DrawBorderTSPL +DrawLineTSPL +DrawTextTSPL +DriveBeepTSPL +GetPrinterStatusTSPL +NetGetStatus +NetWrite +NetWriteClose +NetWriteOpen +POS_Control_AlignType +POS_Control_BeginMacro +POS_Control_BlackMark +POS_Control_CancelMacro +POS_Control_CashDraw +POS_Control_ClearBuffer +POS_Control_CutPaper +POS_Control_DuplePrint +POS_Control_EndMacro +POS_Control_FeedLines +POS_Control_OppositeColor +POS_Control_PlayMacro +POS_Control_PrintTestpage +POS_Control_ReSet +POS_Control_SetInvertedPrint +POS_Control_SetLineSpace +POS_Control_SetPrintFontC +POS_Control_SetPrintFontE +POS_Control_SetPrintPosition +POS_Control_SetRotaryPrint +POS_Input_PrinterId +POS_Input_ReadPrinter +POS_Output_DownloadBmpToFlashA +POS_Output_DownloadBmpToFlashNumA +POS_Output_DownloadBmpToFlashW +POS_Output_DownloadRamBmpA +POS_Output_DownloadRamBmpW +POS_Output_PrintBarcodeA +POS_Output_PrintBarcodeW +POS_Output_PrintBmpDirectA +POS_Output_PrintBmpDirectW +POS_Output_PrintBmpInFlash +POS_Output_PrintBuffAndFeedLines +POS_Output_PrintData +POS_Output_PrintFlashBmp +POS_Output_PrintFontStringA +POS_Output_PrintFontStringW +POS_Output_PrintOneDimensionalBarcodeA +POS_Output_PrintOneDimensionalBarcodeW +POS_Output_PrintRamBmp +POS_Output_PrintStringA +POS_Output_PrintStringW +POS_Output_PrintTwoDimensionalBarcodeA +POS_Output_PrintTwoDimensionalBarcodeW +POS_Output_SendLocalFileA +POS_Output_SendLocalFileW +POS_Port_Close +POS_Port_OpenA +POS_Port_OpenW +POS_Status_GetVersion +POS_Status_QueryStatus +POS_Status_QueryTaskStatus +POS_Status_RTQueryStatus +POS_Status_RTQueryTypeStatus +PageSetupTSPL +PrintTSPL21 +PrintTSPL51 +PutBitMapTSPL +ReverseAreaTSPL +SelectCodePageTSPL +SetCharsetNameTSPL +SetGAPTSPL +SetIs21 +SetLabelReferenceTSPL +SetPaperbackOrPaperFeedTSPL diff --git a/ConsoleTest/AutoWeight/Pos/need.txt b/ConsoleTest/AutoWeight/Pos/need.txt new file mode 100644 index 0000000..02a7733 --- /dev/null +++ b/ConsoleTest/AutoWeight/Pos/need.txt @@ -0,0 +1,25 @@ +OpenDevice();//打开设备1 + +CloseDevice();//关闭设备1 + +IsConnected();//是否连接1 + +IsPaperExhaust();//是否纸尽1 + +InitPrinter();//初始化 or 重置1 + +SetAlign();//居中,居左,居右1 + +PrintRasterBmp();//打印图片1 + +PrintStr();//打印字符串1 + +SetEmphasized();//字体加粗1 + +SetLeftMargin();//设置左边距1 + +FeedPaper();//走纸,留空隙1 + +CutPaper();//切纸1 + +//设置 58mm \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Scales/IScales.cs b/ConsoleTest/AutoWeight/Scales/IScales.cs new file mode 100644 index 0000000..8e4ae9d --- /dev/null +++ b/ConsoleTest/AutoWeight/Scales/IScales.cs @@ -0,0 +1,20 @@ +using System; + +namespace ConsoleTest.AutoWeight.Scales +{ + /// + /// 秤接口 + /// + public interface IScales + { + bool StartServer(); + + bool StopServer(); + + bool IsOpen(); + + event EventHandler OnRecData; + + void RecData(object sender, byte[] buf); + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Scales/ScaleEventArgs.cs b/ConsoleTest/AutoWeight/Scales/ScaleEventArgs.cs new file mode 100644 index 0000000..a6ad4ae --- /dev/null +++ b/ConsoleTest/AutoWeight/Scales/ScaleEventArgs.cs @@ -0,0 +1,27 @@ +using System; + +namespace ConsoleTest.AutoWeight.Scales +{ + /// + /// 称重事件 + /// + public class ScaleEventArgs : EventArgs + { + /// + /// 重量 + /// + public decimal Weight { get; } + + /// + /// 重量单位 + /// + public string Units { get; } + + //事件参数重载 + public ScaleEventArgs(decimal weight, string units = "kg") + { + Weight = weight; + Units = units; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Scales/Scales.cs b/ConsoleTest/AutoWeight/Scales/Scales.cs new file mode 100644 index 0000000..a65aa6b --- /dev/null +++ b/ConsoleTest/AutoWeight/Scales/Scales.cs @@ -0,0 +1,61 @@ +using ConsoleTest.Util.PortUtil; +using System; + +namespace ConsoleTest.AutoWeight.Scales +{ + public class Scales : IScales + { + private YcSerialPort _port; + protected string ComName; + protected int BaudRate; + protected int ReceivedBytesThreshold; + + public Scales() + { + } + + public Scales(string comName, int baudRate) + { + ComName = comName; + BaudRate = baudRate; + ReceivedBytesThreshold = 32; + } + + public Scales(string comName, int baudRate, int receivedBytesThreshold) + { + ComName = comName; + BaudRate = baudRate; + ReceivedBytesThreshold = receivedBytesThreshold; + } + + public bool StartServer() + { + _port = SerialPortBuilder.CreateSerialPort(ComName, BaudRate, ReceivedBytesThreshold); + _port.OnRecData += RecData; + _port.OpenCom(); + return true; + } + + public bool StopServer() + { + _port?.CloseCom(); + _port = null; + return true; + } + + public bool IsOpen() + { + if (_port == null) + return false; + if (!_port.IsOpen()) + return false; + return true; + } + + public virtual event EventHandler OnRecData; + + public virtual void RecData(object sender, byte[] buf) + { + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Scales/ScalesDefault.cs b/ConsoleTest/AutoWeight/Scales/ScalesDefault.cs new file mode 100644 index 0000000..9897736 --- /dev/null +++ b/ConsoleTest/AutoWeight/Scales/ScalesDefault.cs @@ -0,0 +1,47 @@ +using System; +using System.Text; +using System.Text.RegularExpressions; + +namespace ConsoleTest.AutoWeight.Scales +{ + public class ScalesDefault : Scales + { + public ScalesDefault() + { + } + + public ScalesDefault(string comName, int baudRate) + { + ComName = comName; + BaudRate = baudRate; + } + + public override event EventHandler OnRecData; + + public override void RecData(object sender, byte[] buf) + { + var weightBuf = Encoding.UTF8.GetString(buf); + var weightArgs = weightBuf.Split('\n'); + var digitLimit = 3; + + foreach (var weightArg in weightArgs) + { + var args = Regex.Split(weightArg.Trim(), @"\s+", RegexOptions.IgnoreCase); + if (args.Length != 3) + continue; + if (!(args[0].Equals("+") ^ args[0].Equals("-"))) + continue; + + var weight = Math.Round(Convert.ToDecimal(args[0] + args[1]), digitLimit); + var units = args[2]; + //if (weight <= 0) + // continue; + + var scaleArgs = new ScaleEventArgs(weight, units); + + OnRecData?.Invoke(sender, scaleArgs); + break; + } + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Scales/ScalesHuiZhou.cs b/ConsoleTest/AutoWeight/Scales/ScalesHuiZhou.cs new file mode 100644 index 0000000..6365196 --- /dev/null +++ b/ConsoleTest/AutoWeight/Scales/ScalesHuiZhou.cs @@ -0,0 +1,47 @@ +using ConsoleTest.Util; +using System; +using System.Text; +using System.Text.RegularExpressions; + +namespace ConsoleTest.AutoWeight.Scales +{ + public class ScalesHuiZhou : Scales + { + public ScalesHuiZhou() + { + } + + public ScalesHuiZhou(string comName, int baudRate, int receivedBytesThreshold) : base(comName, baudRate, receivedBytesThreshold) + { + } + + public override event EventHandler OnRecData; + + public override void RecData(object sender, byte[] buf) + { + string tempBuf = Encoding.UTF8.GetString(buf); + string[] splitBufArray = tempBuf.Split('\r'); + foreach (var item in splitBufArray) + { + if (item.Length != 16) { continue; } + tempBuf = item; + Console.WriteLine($"item:{tempBuf}, length:{tempBuf.Length}"); + MatchCollection mc = Regex.Matches(tempBuf, @"(\d+)"); + Console.WriteLine($"mc:{mc}, count:{mc.Count}"); + for (int i = 0; i < mc.Count; i++) + { + Console.Write($"{i}:{mc[i].Value},"); + } + Console.WriteLine(); + if (mc.Count != 3) { continue; } + string weightArg = mc[1].Value; + decimal weight = CommonUtil.WeightStrToDec(weightArg) / 1000; + string unit = "t"; + Console.WriteLine($"weight:{weight}{unit}"); + var scaleArgs = new ScaleEventArgs(weight, unit); + OnRecData?.Invoke(sender, scaleArgs); + break; + } + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Scales/ScalesManager.cs b/ConsoleTest/AutoWeight/Scales/ScalesManager.cs new file mode 100644 index 0000000..4823c58 --- /dev/null +++ b/ConsoleTest/AutoWeight/Scales/ScalesManager.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +namespace ConsoleTest.AutoWeight.Scales +{ + public class ScalesManager + { + public Scales Scales; + private string _comName; + private int _baudRate; + + public ScalesManager() + { + } + + public ScalesManager(string comName, int baudRate) + { + _comName = comName; + _baudRate = baudRate; + } + + #region Start & Stop + + public bool StartServer() + { + Scales = new ScalesDefault(_comName, _baudRate); + Scales.OnRecData += RecData; + Scales.StartServer(); + return true; + } + + public void SetCom(string comName, int baudRate) + { + _comName = comName; + _baudRate = baudRate; + } + + public bool StopServer() + { + Scales?.StopServer(); + Scales = null; + return true; + } + + #endregion Start & Stop + + #region Set Send + + private bool _canSend = false; + + public void StartSend() + { + _canSend = true; + } + + public void StopSend() + { + _canSend = false; + } + + #endregion Set Send + + #region Rec Data + + public event EventHandler OnRecData; + + private readonly object lockWeightObj = new object(); + + public void RecData(object sender, ScaleEventArgs scaleArgs) + { + try + { + Monitor.Enter(lockWeightObj); + if (_canSend != true) + return; + + decimal weight = scaleArgs.Weight; + if (weight <= 0) + return; + AppendList(weight); + if (GetListLen() <= lenLimit / 2) + return; + + decimal avgWeight = GetAVGWeight(); + decimal diff = Math.Abs(weight - avgWeight) / avgWeight; + if (diff <= 0.001m) + { + OnRecData?.Invoke(sender, avgWeight); + StopSend(); + ClearList(); + } + } + finally + { + Monitor.Exit(lockWeightObj); + } + } + + #endregion Rec Data + + #region 滤波 + + private List WeightList = new List(); + private readonly int lenLimit = 10; + + private int GetListLen() + { + return WeightList.Count; + } + + public void AppendList(decimal inNumber) + { + if (inNumber <= 0) + return; + + if (WeightList.Count >= lenLimit) + { + WeightList.RemoveAt(0); + } + WeightList.Add(inNumber); + } + + public void ClearList() + { + WeightList = new List(); + } + + public decimal GetAVGWeight() + { + decimal totalWeight = 0.0m; + foreach (decimal value in WeightList) + { + totalWeight += value; + } + decimal avgWeight = totalWeight / GetListLen(); + + return avgWeight; + } + + #endregion 滤波 + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Scales/ScalesZhuHai.cs b/ConsoleTest/AutoWeight/Scales/ScalesZhuHai.cs new file mode 100644 index 0000000..71874b6 --- /dev/null +++ b/ConsoleTest/AutoWeight/Scales/ScalesZhuHai.cs @@ -0,0 +1,44 @@ +using System; +using System.Text; +using System.Text.RegularExpressions; + +namespace ConsoleTest.AutoWeight.Scales +{ + public class ScalesZhuHai : Scales + { + public ScalesZhuHai() + { + } + + public ScalesZhuHai(string comName, int baudRate, int receivedBytesThreshold) : base(comName, baudRate, receivedBytesThreshold) + { + } + + public override event EventHandler OnRecData; + + public override void RecData(object sender, byte[] buf) + { + var weightBuf = Encoding.UTF8.GetString(buf); + var weightArgs = weightBuf.Split('\n'); + var digitLimit = 4; + + foreach (var weightArg in weightArgs) + { + var args = Regex.Split(weightArg.Trim(), @"\s+", RegexOptions.IgnoreCase); + if (args.Length != 3) + continue; + if (!(args[0].Equals("+") ^ args[0].Equals("-"))) + continue; + + var weight = Math.Round(Convert.ToDecimal(args[0] + args[1]), digitLimit); + var units = args[2]; + //if (weight <= 0) + // continue; + + var scaleArgs = new ScaleEventArgs(weight, units); + OnRecData?.Invoke(sender, scaleArgs); + break; + } + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Some/MyThread.cs b/ConsoleTest/AutoWeight/Some/MyThread.cs new file mode 100644 index 0000000..8872935 --- /dev/null +++ b/ConsoleTest/AutoWeight/Some/MyThread.cs @@ -0,0 +1,43 @@ +using System; +using System.Threading; + +namespace ConsoleTest.AutoWeight.Some +{ + public class MyThread + { + private Thread _boardThread; + private bool boardThreadStopFlg; + + public void StartStationBoard() + { + boardThreadStopFlg = false; + _boardThread = new Thread(StationBoard); + _boardThread.IsBackground = true;//设置为后台线程 + _boardThread.Start(); + } + + public void StopStationBoard() + { + boardThreadStopFlg = true; + //_boardThread?.Abort(); + _boardThread = null; + } + + private void StationBoard() + { + try + { + var i = 0; + while (!boardThreadStopFlg) + { + Console.WriteLine(++i); + Thread.Sleep(1000); + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Speak/SpeakHelper.cs b/ConsoleTest/AutoWeight/Speak/SpeakHelper.cs new file mode 100644 index 0000000..22bf770 --- /dev/null +++ b/ConsoleTest/AutoWeight/Speak/SpeakHelper.cs @@ -0,0 +1,109 @@ +using System; +using System.Speech.Synthesis; + +namespace ConsoleTest.AutoWeight.Speak +{ + public class SpeakHelper + { + private static SpeechSynthesizer _curSpeak = new SpeechSynthesizer + { + Volume = 100,//音量 [0, 100] + Rate = 0//语速 [-10, 10] + }; + + public SpeakHelper() + { + } + + #region Start & Stop Server + + public static void Open(int volume = 100, int rate = 0) + { + _curSpeak = new SpeechSynthesizer + { + Volume = volume, + Rate = rate + }; + } + + public static void Close() + { + if (!IsOpen()) + return; + _curSpeak.Pause(); + _curSpeak.Dispose(); + _curSpeak = null; + } + + /// + /// 开启连接 + /// 音量 [0, 100] + /// 语速 [-10, 10] + /// + /// + public static void ReOpen(int volume = 100, int rate = 0) + { + Close(); + Open(volume, rate); + } + + #endregion Start & Stop Server + + #region + + public static bool IsOpen() + { + return _curSpeak != null; + } + + /// + /// Microsoft Huihui Desktop + /// Microsoft Zira Desktop + /// + /// + public static void SelectVoice(string name) + { + _curSpeak.SelectVoice(name); + } + + public static void SelectVoice(VoiceGender gender, VoiceAge age) + { + if (!IsOpen()) + return; + _curSpeak.SelectVoiceByHints(gender, age); + } + + public static void GetVoices() + { + foreach (var voice in _curSpeak.GetInstalledVoices()) + { + var info = voice.VoiceInfo; + Console.WriteLine($"Name:{info.Name}, Culture:{info.Culture}, Gender:{info.Gender}, Age:{info.Age}"); + } + } + + #endregion + + #region Tool Methods + + /// + /// + public static void Speak(string text) + { + if (!IsOpen()) + return; + _curSpeak.Speak(text); + } + + public static void SpeakAsync(string text, bool cancelAll = true) + { + if (!IsOpen()) + return; + if (cancelAll) + _curSpeak.SpeakAsyncCancelAll(); + _curSpeak.SpeakAsync(text); + } + + #endregion Tool Methods + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/Speak/SpeakManager.cs b/ConsoleTest/AutoWeight/Speak/SpeakManager.cs new file mode 100644 index 0000000..7047c17 --- /dev/null +++ b/ConsoleTest/AutoWeight/Speak/SpeakManager.cs @@ -0,0 +1,74 @@ +using System.Speech.Synthesis; + +namespace ConsoleTest.AutoWeight.Speak +{ + public class SpeakManager + { + private SpeechSynthesizer _curSpeech; + + public SpeakManager() + { + } + + #region Start & Stop Server + + /// + /// 开启连接 + /// + /// + public void StartServer() + { + _curSpeech = new SpeechSynthesizer + { + Volume = 100,//音量 [0, 100] + Rate = 0//语速 [-10, 10] + }; + } + + public void ReStartServer() + { + StopServer(); + StartServer(); + } + + /// + /// 关闭连接 + /// + /// + public void StopServer() + { + if (!IsOpen()) + return; + _curSpeech.Pause(); + _curSpeech.Dispose(); + _curSpeech = null; + } + + #endregion Start & Stop Server + + #region Tool Methods + + /// + /// + public void Speak(string text) + { + if (!IsOpen()) + return; + _curSpeech.Speak(text); + } + + public void SpeakAsync(string text, bool cancelAll = true) + { + if (cancelAll) + _curSpeech.SpeakAsyncCancelAll(); + _curSpeech.SpeakAsync(text); + } + + public bool IsOpen() + { + return _curSpeech != null; + } + + #endregion Tool Methods + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/YkPos/YkPosManager.cs b/ConsoleTest/AutoWeight/YkPos/YkPosManager.cs new file mode 100644 index 0000000..25295d7 --- /dev/null +++ b/ConsoleTest/AutoWeight/YkPos/YkPosManager.cs @@ -0,0 +1,71 @@ +using System.Text; + +namespace ConsoleTest.AutoWeight.YkPos +{ + internal class YkPosControl + { + /// + // static int iret = 0; + private static bool bIsOpen = false; + + public bool IsOpen + { + get { return bIsOpen; } + } + + public static int OpenDevice() + { + return YkPosSDK.OpenDevice(); + } + + public static int CloseDevice() + { + return YkPosSDK.CloseDevice(); + } + + public static int InitPrinter() + { + return YkPosSDK.InitPrinter(); + } + + public static int PrintStr(StringBuilder pstr) + { + return YkPosSDK.PrintStr(pstr); + } + + public static int IsConnected() + { + return YkPosSDK.IsConnected(); + } + + public static int FeedPaper() + { + return YkPosSDK.FeedPaper(); + } + + public static int GetStatus(byte n) + { + return YkPosSDK.GetStatus(n); + } + + public static int GetPrinterStatus(byte n) + { + return YkPosSDK.GetPrinterStatus(n); + } + + public static int PrintRasterBmp(StringBuilder pBmpFile) + { + return YkPosSDK.PrintRasterBmp(pBmpFile); + } + + public static int PrintBitmap(StringBuilder pBmpFile) + { + return YkPosSDK.PrintBitmap(pBmpFile); + } + + public static int CutPaper() + { + return YkPosSDK.CutPaper(); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/AutoWeight/YkPos/YkPosSDK.cs b/ConsoleTest/AutoWeight/YkPos/YkPosSDK.cs new file mode 100644 index 0000000..9ddb9fe --- /dev/null +++ b/ConsoleTest/AutoWeight/YkPos/YkPosSDK.cs @@ -0,0 +1,130 @@ +using System.Runtime.InteropServices; +using System.Text; + +namespace ConsoleTest.AutoWeight.YkPos +{ + internal class YkPosSDK + { + [DllImport("YkPosdll.dll")] + public static extern int YkOpenDevice(int iport, int baud); + + [DllImport("YkPosdll.dll")] + private static extern int YkCloseDevice(); + + [DllImport("YkPosdll.dll")] + private static extern int YkIsConnected(); + + [DllImport("YkPosdll.dll")] + private static extern int YkInitPrinter(); + + [DllImport("YkPosdll.dll", CharSet = CharSet.Ansi, EntryPoint = "YkPrintStr", CallingConvention = CallingConvention.StdCall)] + private static extern int YkPrintStr([MarshalAs(UnmanagedType.LPStr)] StringBuilder pstr); + + [DllImport("YkPosdll.dll")] + private static extern int YkFeedPaper(); + + [DllImport("YkPosdll.dll")] + private static extern int YkGetStatus(byte n); + + [DllImport("YkPosdll.dll")] + private static extern int YkGetPrinterStatus(byte n); + + [DllImport("YkPosdll.dll", CharSet = CharSet.Ansi, EntryPoint = "YkPrintRasterBmp", CallingConvention = CallingConvention.StdCall)] + private static extern int YkPrintRasterBmp([MarshalAs(UnmanagedType.LPStr)] StringBuilder pBmpFile); + + [DllImport("YkPosdll.dll", CharSet = CharSet.Ansi, EntryPoint = "YkPrintBitmap", CallingConvention = CallingConvention.StdCall)] + private static extern int YkPrintBitmap([MarshalAs(UnmanagedType.LPStr)] StringBuilder pBmpFile, int m); + + [DllImport("YkPosdll.dll", CharSet = CharSet.Ansi, EntryPoint = "YkPrintBarCode", CallingConvention = CallingConvention.StdCall)] + private static extern int YkPrintBarCode(int m, int n, [MarshalAs(UnmanagedType.LPStr)] StringBuilder barcode); + + [DllImport("YkPosdll.dll")] + private static extern int YkCutPaper(int m, int n); + + public static int OpenDevice() + { + int i; + i = YkOpenDevice(13, 0); + + return i; + } + + public static int CloseDevice() + { + int i; + i = YkCloseDevice(); + return i; + } + + public static int IsConnected() + { + int i; + i = YkIsConnected(); + return i; + } + + public static int InitPrinter() + { + int i; + i = YkInitPrinter(); + return i; + } + + public static int PrintStr([MarshalAs(UnmanagedType.LPStr)] StringBuilder pstr) + { + int i; + i = YkPrintStr(pstr); + return i; + } + + public static int PrintRasterBmp([MarshalAs(UnmanagedType.LPStr)] StringBuilder pBmpFile) + { + int i; + i = YkPrintRasterBmp(pBmpFile); + return i; + } + + public static int PrintBitmap([MarshalAs(UnmanagedType.LPStr)] StringBuilder pBmpFile) + { + int i; + i = YkPrintBitmap(pBmpFile, 33); + return i; + } + + public static int FeedPaper() + { + int i; + i = YkFeedPaper(); + return i; + } + + public static int GetStatus(byte n) + { + int i; + i = YkGetStatus(n); + return i; + } + + public static int GetPrinterStatus(byte n) + { + int i; + i = YkGetPrinterStatus(n); + return i; + } + + public static int PrintBarCode([MarshalAs(UnmanagedType.LPStr)] StringBuilder barcode) + { + int i; + int n = barcode.Length; + i = YkPrintBarCode(72, n, barcode); + return i; + } + + public static int CutPaper() + { + int i; + i = YkCutPaper(66, 0); + return i; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/ConsoleTest.csproj b/ConsoleTest/ConsoleTest.csproj new file mode 100644 index 0000000..16e9278 --- /dev/null +++ b/ConsoleTest/ConsoleTest.csproj @@ -0,0 +1,213 @@ + + + + + Debug + AnyCPU + {37FD52CA-308E-4CC4-9E9F-4072E1C1C216} + Exe + ConsoleTest + ConsoleTest + v4.7.2 + 8.0 + 512 + true + true + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + LocalIntranet + + + false + + + Properties\app.manifest + + + false + + + + + ..\packages\NewLife.Core.10.0.2022.1001\lib\net461\NewLife.Core.dll + + + ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll + + + + + + + ..\packages\System.Configuration.ConfigurationManager.5.0.0\lib\net461\System.Configuration.ConfigurationManager.dll + + + + + + + + + ..\packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll + True + True + + + + + ..\packages\System.Security.AccessControl.5.0.0\lib\net461\System.Security.AccessControl.dll + + + ..\packages\System.Security.Permissions.5.0.0\lib\net461\System.Security.Permissions.dll + + + ..\packages\System.Security.Principal.Windows.5.0.0\lib\net461\System.Security.Principal.Windows.dll + + + + + + + ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + PreserveNewest + + + + + False + Microsoft .NET Framework 4.7.2 %28x86 和 x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + + + PreserveNewest + + + + + \ No newline at end of file diff --git a/ConsoleTest/PTZApi/Entity.cs b/ConsoleTest/PTZApi/Entity.cs new file mode 100644 index 0000000..a5c548a --- /dev/null +++ b/ConsoleTest/PTZApi/Entity.cs @@ -0,0 +1,156 @@ +using System.Runtime.InteropServices; +using System.Runtime.Serialization; + +namespace ConsoleTest.PTZApi +{ + [DataContract(IsReference = true)] + public class CameraModel + { + [DataMember] + public int ID { get; set; } + + [DataMember] + public int indexID { get; set; } + + [DataMember] + public string CamName { get; set; } + + [DataMember] + public int CameraTypeID { get; set; } + + [DataMember] + public int CameraThreeInfoID { get; set; } + + [DataMember] + public string ServerIP { get; set; } + + [DataMember] + public int ServerPort { get; set; } + + [DataMember] + public string ServerUserName { get; set; } + + [DataMember] + public string ServerPwd { get; set; } + + [DataMember] + public string ServerId { get; set; } + + [DataMember] + public string PTZServerIP { get; set; } + + [DataMember] + public int FatherNodeID { get; set; } + + [DataMember] + public bool UVConvert { get; set; } + + [DataMember] + public double PointLat { get; set; } + + [DataMember] + public double PointLng { get; set; } + + [DataMember] + public int PlateType { get; set; } + + public string BelongIP { get; set; } + } + + #region 与ptz服务交互使用结构体 + + //---------------------------------------------------------------------------------------- + // 与ptz服务交互使用结构体 + //---------------------------------------------------------------------------------------- + //注意这个属性不能少 + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] + public struct RequestRealControl + { + public int token; + + public CameraInfo CameraInfo; + + public RealControlType realControlType; + + //请求时 状态 true:开始;false:结束 答复时:true:成功;其他:失败 + public bool Status; + + public PresentInfo PresentInfo; + + public PTZPosInfo PTZPositionInfo; + //int数组,SizeConst表示数组的个数,在转换成 + //byte数组前必须先初始化数组,再使用,初始化 + //的数组长度必须和SizeConst一致,例test = new int[6]; + //[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] + //public int[] test; + } + + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)] + public struct CameraInfo + { + public int cameraid; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)] + public char[] ip; + + public ushort port; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + private char[] user; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)] + private char[] password; + } + + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)] + public struct PresentInfo + { + public int presentNo;//预置位编号 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] + private char[] PresentName; // 预置位名称 + } + + [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 4)] + public struct PTZPosInfo + { + public int FP;//p信息 + public int FT;//T信息 + public int FZ;//Z信息 + public int TitlePosMin;//描述点垂直参数min + public int ZoomPosMin;//描述点变倍参数min + + public float FHorWidth;//水平宽度 精确到小数点后两位 *10000 + public float FVerWidth;//垂直宽度 精确到小数点后两位 *10000 + public float FFold;//zoom=1没变时的焦距 精确到小数点后两位 *100 + + public int CameraType; + } + + public enum RealControlType + { + MOVE_UP_ = 1, + MOVE_DOWN_, + MOVE_LEFT_, + MOVE_RIGHT_, + MOVE_LEFTUP_, + MOVE_LEFTDOWN_, + MOVE_RIGHTUP_, + MOVE_RIGHTDOWN_, + + ZOOM_IN_, + ZOOM_OUT_, + FOCUS_NEAR_, + FOCUS_FAR_, + IRIS_OPEN_, + IRIS_CLOSE_, + + PRESET_SET_, + PRESET_CALL_, + + PTZINFO_GET_, + PTZINFO_SET_ + } + + #endregion 与ptz服务交互使用结构体 +} \ No newline at end of file diff --git a/ConsoleTest/PTZApi/IService.cs b/ConsoleTest/PTZApi/IService.cs new file mode 100644 index 0000000..ecc4a0d --- /dev/null +++ b/ConsoleTest/PTZApi/IService.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.ServiceModel; + +namespace ConsoleTest.PTZApi +{ + [ServiceContract] + public interface IOperateService where T : class + { + [OperationContract] + bool Add(T model); + + [OperationContract] + bool Update(T model); + + [OperationContract] + bool Delete(T model); + + [OperationContract] + T Find(object key); + + [OperationContract] + IList FindAll(); + } + + [ServiceContract] + public interface ICameraService : IOperateService + { + } + + [ServiceContract] + public interface ICruiseCameraService : IOperateService + { + } + + [ServiceContract] + public interface ICameraModelService : IOperateService + { + } + + /// + /// PTZ Api 接口 + /// + public interface IPTZApi + { + } +} \ No newline at end of file diff --git a/ConsoleTest/PTZApi/Service.cs b/ConsoleTest/PTZApi/Service.cs new file mode 100644 index 0000000..d8289d8 --- /dev/null +++ b/ConsoleTest/PTZApi/Service.cs @@ -0,0 +1,340 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.ServiceModel; + +namespace ConsoleTest.PTZApi +{ + public class ServiceBase + { + protected string Host { get; set; } = "127.0.0.1"; + + protected string Port { get; set; } = "9999"; + + protected string Name { get; set; } + + public ServiceBase() + { + } + + protected virtual EndpointAddress CreateEndPointAddress() + { + string conn = $"net.tcp://{Host}:{Port}/{Name}"; + return new EndpointAddress(conn); + } + } + + public class CameraService : ServiceBase + { + public static CameraService instance = new CameraService(); + + public CameraService() + { + Name = "CameraService"; + } + + public bool DeleteCamera(CameraModel id) + { + try + { + return WcfUtil.UseService((ICameraService args) => args.Delete(id), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public bool UpdateCamera(CameraModel camera) + { + try + { + return WcfUtil.UseService((ICameraService args) => args.Update(camera), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public bool AddCamera(CameraModel camera) + { + try + { + return WcfUtil.UseService((ICameraService args) => args.Add(camera), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public CameraModel GetCamera(object obj) + { + try + { + return WcfUtil.UseService((ICameraService args) => args.Find(obj), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public List GetAllCamera() + { + List list = null; + try + { + list = WcfUtil.UseService((ICameraService args) => args.FindAll().ToList(), CreateEndPointAddress()); + } + catch (Exception) + { + } + return list != null ? list : new List(); + } + } + + public class CruiseCameraService : ServiceBase + { + public static CruiseCameraService instance = new CruiseCameraService(); + + public CruiseCameraService() + { + Name = "CruiseCameraService"; + } + + public bool DeleteCamera(CameraModel id) + { + try + { + return WcfUtil.UseService((ICruiseCameraService args) => args.Delete(id), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public bool UpdateCamera(CameraModel camera) + { + try + { + return WcfUtil.UseService((ICruiseCameraService args) => args.Update(camera), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public bool AddCamera(CameraModel camera) + { + try + { + return WcfUtil.UseService((ICruiseCameraService args) => args.Add(camera), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public CameraModel GetCamera(object obj) + { + try + { + return WcfUtil.UseService((ICruiseCameraService args) => args.Find(obj), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public List GetAllCamera() + { + List list = null; + try + { + list = WcfUtil.UseService((ICruiseCameraService args) => args.FindAll().ToList(), CreateEndPointAddress()); + } + catch (Exception) + { + } + return list != null ? list : new List(); + } + } + + public class CameraModelService : ServiceBase + { + public static CameraModelService instance = new CameraModelService(); + + public CameraModelService() + { + Name = "CameraModelService"; + } + + public bool DeleteCamera(CameraModel id) + { + try + { + return WcfUtil.UseService((ICameraModelService args) => args.Delete(id), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public bool UpdateCamera(CameraModel camera) + { + try + { + return WcfUtil.UseService((ICameraModelService args) => args.Update(camera), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public bool AddCamera(CameraModel camera) + { + try + { + return WcfUtil.UseService((ICameraModelService args) => args.Add(camera), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public CameraModel GetCamera(object obj) + { + try + { + return WcfUtil.UseService((ICameraModelService args) => args.Find(obj), CreateEndPointAddress()); + } + catch (Exception ex) + { + throw ex; + } + } + + public List GetAllCamera() + { + List list = null; + try + { + list = WcfUtil.UseService((ICameraModelService args) => args.FindAll().ToList(), CreateEndPointAddress()); + } + catch (Exception) + { + } + return list != null ? list : new List(); + } + } + + public class PTZServerApi : IPTZApi + { + #region Attr + + private TcpClient _tcpClient { get; set; } + + private NetworkStream _stream { get; set; } + + #endregion Attr + + public PTZServerApi() + { + Init(); + } + + private void Init() + { + string ip = "127.0.0.1"; + int port = 7022; + _tcpClient = new TcpClient(ip, port); + //创建一个 networkstream 用来写入和读取数据 + _stream = _tcpClient.GetStream(); + } + + public RequestRealControl GetPtzInfo(int cameraId) + { + RequestRealControl realControl = new RequestRealControl(); + try + { + string recieve_string = string.Empty; + realControl.token = 666; + + realControl.CameraInfo.cameraid = cameraId; + realControl.Status = true; + realControl.realControlType = RealControlType.PTZINFO_GET_; + byte[] data = StructToByte(realControl); + _stream.Write(data, 0, data.Length); + + byte[] recieve_byte = new byte[_tcpClient.ReceiveBufferSize]; + _stream.Read(recieve_byte, 0, (int)_tcpClient.ReceiveBufferSize); + //stream.BeginRead(recieve_byte, 0, (int)tcp_client.ReceiveBufferSize,EndRead, stream); + realControl = (RequestRealControl)BytetoStruct(recieve_byte, typeof(RequestRealControl)); + if (realControl.PTZPositionInfo.FT < 0) + { + realControl.PTZPositionInfo.FT = 3600 + realControl.PTZPositionInfo.FT; + } + } + catch (Exception) + { + realControl = default; + } + return realControl; + } + + public static byte[] StructToByte(object structObj) + { + //获取结构体大小 + int size = Marshal.SizeOf(structObj); + + byte[] data = new byte[size]; + + //分配内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(size); + // 将结构体数据复制到内存空间 + Marshal.StructureToPtr(structObj, structPtr, false); + // 将内存空间的数据拷贝到byte数组 + Marshal.Copy(structPtr, data, 0, size); + //释放内存 + Marshal.FreeHGlobal(structPtr); + return data; + } + + public static object BytetoStruct(byte[] bytes, Type type) + { + object obj = new object(); + try + { + byte[] temp = bytes; + // 获取结构体大小 + int size = Marshal.SizeOf(type); + if (size > bytes.Length) + return null; + // 分配结构体内存空间 + IntPtr structPtr = Marshal.AllocHGlobal(size); + // 将byte数组内容拷贝到内存中 + Marshal.Copy(temp, 0, structPtr, size); + + // 将内存空间转化为目标结构体 + obj = Marshal.PtrToStructure(structPtr, type); + //释放内存 + Marshal.FreeHGlobal(structPtr); + } + catch (Exception) + { + } + return obj; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/PTZApi/Test.cs b/ConsoleTest/PTZApi/Test.cs new file mode 100644 index 0000000..613a764 --- /dev/null +++ b/ConsoleTest/PTZApi/Test.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace ConsoleTest.PTZApi +{ + public class Test + { + public static void TestDbApi() + { + List cameraModelList = CameraService.instance.GetAllCamera(); + List cameraModelList2 = CruiseCameraService.instance.GetAllCamera(); + List cameraModelList3 = CameraModelService.instance.GetAllCamera(); + foreach (CameraModel cameraModel in cameraModelList) + { + System.Console.WriteLine(cameraModel); + } + + CameraModel m = new CameraModel(); + m.PTZServerIP = "111"; + CameraService.instance.AddCamera(m); + } + + public static void TestPtzApi() + { + PTZServerApi api = new PTZServerApi(); + RequestRealControl requestRealControl = api.GetPtzInfo(7); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/PTZApi/Util.cs b/ConsoleTest/PTZApi/Util.cs new file mode 100644 index 0000000..61ef84e --- /dev/null +++ b/ConsoleTest/PTZApi/Util.cs @@ -0,0 +1,41 @@ +using System; +using System.ServiceModel; + +namespace ConsoleTest.PTZApi +{ + public class WcfUtil + { + public static void UseService(Action action, EndpointAddress address = null) + { + ChannelFactory channelFactory = new ChannelFactory("*"); + TChannel val = ((!(address == null)) ? channelFactory.CreateChannel(address) : channelFactory.CreateChannel()); + try + { + ((IClientChannel)(object)val).Open(); + action(val); + ((IClientChannel)(object)val).Close(); + } + catch + { + ((IClientChannel)(object)val).Abort(); + } + } + + public static TReturn UseService(Func func, EndpointAddress address = null) + { + ChannelFactory channelFactory = new ChannelFactory("*"); + TChannel val = ((!(address == null)) ? channelFactory.CreateChannel(address) : channelFactory.CreateChannel()); + ((IClientChannel)(object)val).Open(); + TReturn result = func(val); + try + { + ((IClientChannel)(object)val).Close(); + } + catch (Exception) + { + ((IClientChannel)(object)val).Abort(); + } + return result; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Program.cs b/ConsoleTest/Program.cs new file mode 100644 index 0000000..865714b --- /dev/null +++ b/ConsoleTest/Program.cs @@ -0,0 +1,66 @@ +using ConsoleTest.Test.AutoWeight; +using ConsoleTest.Util; +using System; +using System.Text.RegularExpressions; + +namespace ConsoleTest +{ + public class Program + { + private static void Main(string[] args) + { + EnvUtil.InitWorkDirectory(); + EnvUtil.AddDllPath(EnvUtil.CombinePath(EnvUtil.GetWorkDirectory(), "dll")); + + //AutoWeightTest(); + //OtherTests(); + //PTZApi.Test.TestPtzApi(); + Console.ReadLine(); + } + + private static void TempTest(string tempBuf) + { + string[] splitBufArray = tempBuf.Split('\r'); + foreach (var item in splitBufArray) + { + if (item.Length != 16) { continue; } + Console.WriteLine($"item:{item}"); + MatchCollection mc = Regex.Matches(tempBuf, @"(\d+)"); + Console.WriteLine($"mc:{mc}, count:{mc.Count}"); + for (int i = 0; i < mc.Count; i++) + { + Console.Write($"{i}:{mc[i].Value}"); + } + Console.WriteLine(); + if (mc.Count != 3) { continue; } + string weightArg = mc[1].Value; + decimal weight = CommonUtil.WeightStrToDec(weightArg) / 1000; + string unit = "t"; + Console.WriteLine($"weight:{weight}{unit}"); + break; + } + } + + private static void AutoWeightTest() + { + try + { + //WeightTest.TestZhuHai(); + //WeightTest.TestHuiZhou(); + //LedTest.Test(); + //LightTest.Test(); + PosTest.Test(); + } + catch (Exception ex) + { + Console.WriteLine(ex); + throw; + } + } + + private static void OtherTest() + { + Test.OtherTest.ConfigTest(); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Properties/AssemblyInfo.cs b/ConsoleTest/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..7dc3e3f --- /dev/null +++ b/ConsoleTest/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("ConsoleTest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ConsoleTest")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("37fd52ca-308e-4cc4-9e9f-4072e1c1c216")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 +//通过使用 "*",如下所示: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/ConsoleTest/Properties/app.manifest b/ConsoleTest/Properties/app.manifest new file mode 100644 index 0000000..6448bd3 --- /dev/null +++ b/ConsoleTest/Properties/app.manifest @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ConsoleTest/Test/AutoWeight/LedTest.cs b/ConsoleTest/Test/AutoWeight/LedTest.cs new file mode 100644 index 0000000..08e0a33 --- /dev/null +++ b/ConsoleTest/Test/AutoWeight/LedTest.cs @@ -0,0 +1,93 @@ +using ConsoleTest.AutoWeight.LedZK; +using ConsoleTest.Util; +using System; + +namespace ConsoleTest.Test.AutoWeight +{ + public class LedTest + { + public static void Test() + { + string ip = ConfigUtil.GetStringVal("Led_Ip"); + ushort port = (ushort)ConfigUtil.GetShortVal("Led_Port"); + Console.WriteLine($"Ip : {ip}"); + Console.WriteLine($"Port : {port}"); + + var manager = new LedZKManager(ip, port); + manager.StartServer(); + Console.WriteLine($"Start success : {manager.Ping()}"); + + int ret; + while (true) + { + Console.Write("Please input [0,6] : "); + var read = Console.ReadLine(); + //manager.DelAllDynamicArea(0, 4); + + switch (read) + { + case "0": + ret = manager.SendDynamicArea(0, 0, 0, 96, 64, + @"\C2粤AAQ841 09:20:51\n\C2粤AAQ842 09:20:52\n\C2粤AAQ843 09:20:53\n\C2粤AAQ844 09:20:54\n\C3粤AAV141,粤AAV142,\C1粤AAM491,粤AAM492", + 0x02, 0x01, 10); + Console.WriteLine(ret); + break; + + case "1": + ret = manager.SendDynamicMoveArea(0, 0, 0, 96, 24, @"\C2粤AAQ841 09:20:51\n\C2粤AAQ842 09:20:52", 0x02, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(1, 0, 24, 96, 24, @"\C2粤AAQ843 09:20:53\n\C2粤AAQ844 09:20:54", 0x02, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(2, 0, 48, 96, 16, @"\C3粤AAV141,粤AAV142,\C1粤AAM491,粤AAM492", 0x01, 0x01, 10); + Console.WriteLine(ret); + break; + + case "2": + ret = manager.SendDynamicMoveArea(0, 0, 0, 96, 48, + @"\C2粤AAQ841 09:20:51\n\C2粤AAQ842 09:20:52\n\C2粤AAQ843 09:20:53\n\C2粤AAQ844 09:20:54", 0x02, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(1, 0, 48, 96, 16, @"\C3粤AAV141,粤AAV142,\C1粤AAM491,粤AAM492", 0x01, 0x01, 10); + Console.WriteLine(ret); + break; + + case "3": + ret = manager.SendDynamicMoveArea(0, 0, 0, 96, 64, + @"\C2粤AAQ841 09:20:51\n\C2粤AAQ842 09:20:52\n\C2粤AAQ843 09:20:53\n\C2粤AAQ844 09:20:54\n\C3粤AAV141,粤AAV142,\C1粤AAM491,粤AAM492", + 0x02, 0x01, 10); + Console.WriteLine(ret); + break; + + case "4": + ret = manager.SendDynamicMoveArea(0, 0, 0, 96, 12, @"\C2粤AAQ841 09:20:51", 0x01, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(1, 0, 12, 96, 12, @"\C2粤AAQ842 09:20:52", 0x01, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(2, 0, 24, 96, 12, @"\C2粤AAQ843 09:20:53", 0x01, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(3, 0, 36, 96, 12, @"\C2粤AAQ844 09:20:54", 0x01, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(4, 0, 48, 96, 16, @"\C3粤AAV141,粤AAV142,\C1粤AAM491,粤AAM492", 0x01, 0x01, 10); + Console.WriteLine(ret); + break; + + case "5": + ret = manager.SendDynamicArea(0, 0, 0, 96, 64, + @"\C2粤AAQ841 09:20:51\n\C2粤AAQ842 09:20:52\n\C2粤AAQ843 09:20:53\n\C2粤AAQ844 09:20:54\n\C3粤AAV141,粤AAV142,\C1粤AAM491,粤AAM492", + 0x02, 0x01, 10); + Console.WriteLine(ret); + break; + + case "6": + ret = manager.SendDynamicMoveArea(0, 0, 0, 96, 24, @"\C2粤AAQ841 09:20:51\n\C2粤AAQ842 09:20:52", 0x02, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(1, 0, 25, 96, 24, @"\C2粤AAQ843 09:20:53\n\C2粤AAQ844 09:20:54", 0x02, 0x01, 10); + Console.WriteLine(ret); + ret = manager.SendDynamicMoveArea(2, 0, 49, 96, 16, @"\C3粤AAV141,粤AAV142,\C1粤AAM491,粤AAM492", 0x01, 0x01, 10); + Console.WriteLine(ret); + break; + } + } + //manager.StopServer(); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Test/AutoWeight/LightTest.cs b/ConsoleTest/Test/AutoWeight/LightTest.cs new file mode 100644 index 0000000..2244c3a --- /dev/null +++ b/ConsoleTest/Test/AutoWeight/LightTest.cs @@ -0,0 +1,70 @@ +using ConsoleTest.AutoWeight.Light; +using ConsoleTest.Util; +using System; +using System.Threading; + +namespace ConsoleTest.Test.AutoWeight +{ + /// + /// 2022年6月9日17:39:08 + /// + public class LightTest + { + public static void Test() + { + string comName = ConfigUtil.GetStringVal("Light_Com"); + int baudRate = ConfigUtil.GetIntVal("Light_BaudRate"); + string lightCodeName = EnvUtil.CombinePath(EnvUtil.GetWorkDirectory(), "data", "light", ConfigUtil.GetStringVal("Light_Code_Name")); + Console.WriteLine($"Com : {comName}"); + Console.WriteLine($"BaudRate : {baudRate}"); + Console.WriteLine($"LightCodeName : {lightCodeName}"); + + LightManager lightManager = new LightManager(comName, baudRate, lightCodeName); + const int interval = 600; + bool ret = lightManager.StartServer(); + Console.WriteLine($"Start success : {ret}"); + Console.WriteLine($"Is open : {lightManager.IsOpen()}"); + Console.WriteLine($"Read data success : {lightManager.IsReadCodeSuccess()}"); + + lightManager.CloseAllLight(); + Thread.Sleep(interval); + lightManager.OpenAllLight(); + Thread.Sleep(interval); + lightManager.CloseAllLight(); + Thread.Sleep(interval); + + for (var i = 1; i < 5; i++) + { + lightManager.OpenLight(i); + Thread.Sleep(interval); + } + + for (var i = 1; i < 5; i++) + { + lightManager.CloseLight(i); + Thread.Sleep(interval); + } + + for (var i = 1; i < 5; i++) + { + lightManager.LockLightOn(i); + Thread.Sleep(interval); + } + + for (var i = 1; i < 5; i++) + { + lightManager.LockLightOff(i); + Thread.Sleep(interval); + } + + lightManager.CloseAllLight(); + Thread.Sleep(interval); + lightManager.OpenAllLight(); + Thread.Sleep(interval); + lightManager.CloseAllLight(); + Thread.Sleep(interval); + + lightManager.StopServer(); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Test/AutoWeight/PosTest.cs b/ConsoleTest/Test/AutoWeight/PosTest.cs new file mode 100644 index 0000000..fd4bf91 --- /dev/null +++ b/ConsoleTest/Test/AutoWeight/PosTest.cs @@ -0,0 +1,106 @@ +using ConsoleTest.AutoWeight.Pos; +using ConsoleTest.Util; +using System; +using System.Text; + +namespace ConsoleTest.Test.AutoWeight +{ + public class PosTest + { + public static void Test() + { + PosManager posManager = new PosManager(); + bool flag; + + // 打开设备 + flag = posManager.OpenDevice(PosSDK.POS_PT_USB); + Console.WriteLine($"OpenDevice:{flag}"); + + flag = posManager.IsConnected(); + Console.WriteLine($"IsConnected:{flag}"); + + flag = posManager.IsPaperExhaust(); + Console.WriteLine($"IsPaperExhaust:{flag},{posManager.GetResult()}"); + + flag = posManager.IsPaperWillExhaust(); + Console.WriteLine($"IsPaperWillExhaust:{flag},{posManager.GetResult()}"); + + flag = posManager.InitPrinter(); + Console.WriteLine($"InitPrinter:{flag}"); + + string bmpPath2 = EnvUtil.CombinePath(EnvUtil.GetWorkDirectory(), "data", "image", "logom.bmp"); + if (!EnvUtil.ExistFile(bmpPath2)) + { + string bmpPath1 = EnvUtil.CombinePath(EnvUtil.GetWorkDirectory(), "data", "image", "logo.bmp"); + flag = posManager.Color24_GrayBW(bmpPath1, bmpPath2); + Console.WriteLine($"IsPaperExhaust:{flag}"); + } + + // 打印票头 + //flag = posManager.SetLeftMargin(150, 0); + //Console.WriteLine($"SetLeftMargin:{flag}"); + flag = posManager.PrintBmp(bmpPath2); + Console.WriteLine($"PrintBmp:{flag},{posManager.GetResult()}"); + flag = posManager.InitPrinter(); + + // 缓冲区 + byte[] cmd = new byte[] { 0x1c, 0x26 }; + posManager.PrintData(cmd, 2); + + // 打印公司 + flag = posManager.SetAlign(1); + flag = posManager.PrintStr(0, 1, 0, 0, 0, "惠州航油公司\r\n"); + Console.WriteLine($"PrintStr:{flag}"); + // 打印分隔符 + flag = posManager.PrintStr(0, 0, 0, 0, 0, "================================\r\n"); + + // 打印运单信息 + flag = posManager.SetAlign(0); + var content = new StringBuilder(); + content.Append($"场地:\tcd000\r\n"); + content.Append($"运单号:\tydh000\r\n"); + content.Append($"供应商:\tgys000\r\n"); + content.Append($"运输车:\tysc000\r\n"); + content.Append($"挂车:\tgc000\n"); + content.Append($"运输员:\tysy000\n"); + content.Append($"押运员:\tyyy000\n"); + content.Append($"料号:\tlh000\n"); + flag = posManager.PrintStr(0, 0, 0, 0, 0, content.ToString()); + // 打印分隔符 + flag = posManager.SetAlign(1); + flag = posManager.PrintStr(0, 0, 0, 0, 0, "================================\r\n"); + + //// 缓冲区 + //cmd = new byte[] { 0x1c, 0x26 }; + //posManager.PrintData(cmd, 2); + // 打印进出场信息 + flag = posManager.SetAlign(0); + content = new StringBuilder(); + content.Append($"运单重量:\t30吨\n"); + content.Append($"入场重量:\t40吨\n"); + content.Append($"出场重量:\t10吨\n"); + content.Append($"实际重量:\t30吨\n"); + content.Append($"达标率:\t100%\n"); + content.Append($"入场时间:\t{DateTime.Now:yyyy/MM/dd HH:mm:ss}\n"); + content.Append($"出场时间:\t{DateTime.Now:yyyy/MM/dd HH:mm:ss}\n"); + content.Append($"运单状态:\t出场结束\n"); + flag = posManager.PrintStr(0, 0, 0, 0, 0, content.ToString()); + //打印分隔符 + flag = posManager.SetAlign(1); + flag = posManager.PrintStr(0, 0, 0, 0, 0, "================================\r\n"); + + //打印票尾 + flag = posManager.SetAlign(2); + flag = posManager.PrintStr(0, 0, 0, 0, 0, $"出票时间:{DateTime.Now:yyyy/MM/dd HH:mm:ss}\r\n"); + flag = posManager.InitPrinter(); + + //切纸 + flag = posManager.CutPaper(1, 3); + Console.WriteLine($"CutPaper:{flag}"); + + //关闭 + flag = posManager.CloseDevice(); + Console.WriteLine($"CloseDevice:{flag}"); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Test/AutoWeight/WeightTest.cs b/ConsoleTest/Test/AutoWeight/WeightTest.cs new file mode 100644 index 0000000..9637b17 --- /dev/null +++ b/ConsoleTest/Test/AutoWeight/WeightTest.cs @@ -0,0 +1,37 @@ +using ConsoleTest.AutoWeight.Scales; +using ConsoleTest.Util; +using System; + +namespace ConsoleTest.Test.AutoWeight +{ + public class WeightTest + { + public static void TestZhuHai() + { + string com = ConfigUtil.GetStringVal("Weight_Com"); + int baudrate = ConfigUtil.GetIntVal("Weight_BaudRate"); + int receivedBytesThreshold = ConfigUtil.GetIntVal("Weight_ReceivedBytesThreshold"); + Console.WriteLine($"Com : {com}"); + Console.WriteLine($"BaudRate : {baudrate}"); + Console.WriteLine($"ReceivedBytesThreshold : {receivedBytesThreshold}"); + + Scales scales = new ScalesHuiZhou(com, baudrate, receivedBytesThreshold); + bool ret = scales.StartServer(); + Console.WriteLine($"Start success : {ret}"); + } + + public static void TestHuiZhou() + { + string com = ConfigUtil.GetStringVal("Weight_Com"); + int baudrate = ConfigUtil.GetIntVal("Weight_BaudRate"); + int receivedBytesThreshold = ConfigUtil.GetIntVal("Weight_ReceivedBytesThreshold"); + Console.WriteLine($"Com : {com}"); + Console.WriteLine($"BaudRate : {baudrate}"); + Console.WriteLine($"ReceivedBytesThreshold : {receivedBytesThreshold}"); + + Scales scales = new ScalesHuiZhou(com, baudrate, receivedBytesThreshold); + bool ret = scales.StartServer(); + Console.WriteLine($"Start success : {ret}"); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Test/AutoWeight/YkPosTest.cs b/ConsoleTest/Test/AutoWeight/YkPosTest.cs new file mode 100644 index 0000000..2722720 --- /dev/null +++ b/ConsoleTest/Test/AutoWeight/YkPosTest.cs @@ -0,0 +1,76 @@ +namespace ConsoleTest.Test.AutoWeight +{ + public class YkPosTest + { + public static void Test() + { + //if (!YkPosManager.IsConnected() || YkPosManager.IsPaperExhaust()) + //{ + // var msg = "打印接口纸尽,请联系管理人员"; + // _mainServer?.SetScrollLabelText(msg); + // _mainServer?.ShowRecvMessage(msg); + // return; + //} + //if (billEntity == null) + // return; + + //YkPosManager.InitPrinter(); + //var bmpPath = EnvUtil.CombinePath(EnvUtil.GetWorkDirectory(), "data", "image", "logo.bmp"); + //YkPosManager.SetAlign(1);//居中 + //YkPosManager.PrintRasterBmp(new StringBuilder(bmpPath));//打印图片 + + ////YkPosManager.InitPrinter();//重置 + ////YkPosManager.SetAlign(1);//居中 + //YkPosManager.SetEmphasized(1);//字体加粗 + //YkPosManager.PrintStr(new StringBuilder($"{_mainServer.LocalAttrCenter.Company.F_FullName}\n"));//打印公司名 + + //YkPosManager.InitPrinter();//重置 + //YkPosManager.SetAlign(1);//居中 + //YkPosManager.PrintStr(new StringBuilder("========================================\n"));//打印分隔符 + + ////YkPosManager.InitPrinter();//重置 + //YkPosManager.SetAlign(0);//居左 + //YkPosManager.SetLeftMargin(8 * 8, 0);//设置左边距 + //var content = new StringBuilder(); + //content.Append($"场地:\t{billEntity.SiteName}\n"); + //content.Append($"运单号:\t{billEntity.SerialNumber}\n"); + //content.Append($"供应商:\t{billEntity.SupplierName}\n"); + //content.Append($"运输车:\t{billEntity.LicensePlate}\n"); + //content.Append($"挂车:\t{billEntity.TrailerPlate}\n"); + //content.Append($"运输员:\t{billEntity.DriverName}\n"); + //content.Append($"押运员:\t{billEntity.Driver2Name}\n"); + //content.Append($"料号:\t{billEntity.MaterialNo}\n"); + //YkPosManager.PrintStr(content);//打印内容 + + //YkPosManager.InitPrinter();//重置 + //YkPosManager.SetAlign(1);//居中 + //YkPosManager.PrintStr(new StringBuilder("----------------------------------------\n"));//打印分隔符 + + ////YkPosManager.InitPrinter();//重置 + //YkPosManager.SetAlign(0);//居左 + //YkPosManager.SetLeftMargin(8 * 8, 0);//设置左边距 + //content = new StringBuilder(); + //content.Append($"运单重量:\t{billEntity.BillWeight}吨\n"); + //content.Append($"入场重量:\t{billEntity.InWeight}吨\n"); + //content.Append($"出场重量:\t{billEntity.OutWeight}吨\n"); + //content.Append($"实际重量:\t{billEntity.NetWeight}吨\n"); + //content.Append($"达标率:\t{billEntity.StandardRate}%\n"); + //content.Append($"入场时间:\t{billEntity.InStartTime:yyyy/MM/dd HH:mm:ss}\n"); + //content.Append($"出场时间:\t{billEntity.OutFinishTime:yyyy/MM/dd HH:mm:ss}\n"); + ////content.Append($"运单状态:\t{BillStateExt.GetBillStateDesc(billEntity.State)}\n"); + //YkPosManager.PrintStr(content);//打印内容 + + //YkPosManager.InitPrinter();//重置 + //YkPosManager.SetAlign(1);//居中 + //YkPosManager.PrintStr(new StringBuilder("========================================\n")); + + ////YkPosManager.InitPrinter();//重置 + //YkPosManager.SetAlign(2);//居右 + // //YkPosManager.PrintStr(new StringBuilder($"管理员:{user?.F_RealName}\n")); + //YkPosManager.PrintStr(new StringBuilder($"出票时间:{DateTime.Now:yyyy/MM/dd HH:mm:ss}\n"));//打印页脚 + + //YkPosManager.FeedPaper();//走纸,留空隙 + //YkPosManager.CutPaper();//切纸 + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Test/Other/OtherTest.cs b/ConsoleTest/Test/Other/OtherTest.cs new file mode 100644 index 0000000..871ff80 --- /dev/null +++ b/ConsoleTest/Test/Other/OtherTest.cs @@ -0,0 +1,310 @@ +using ConsoleTest.AutoWeight.FingerPrint; +using ConsoleTest.AutoWeight.Some; +using ConsoleTest.AutoWeight.Speak; +using ConsoleTest.Util; +using ConsoleTest.Util.Encrypt; +using System; +using System.Collections.Generic; +using System.IO; +using System.Speech.Synthesis; +using System.Text.RegularExpressions; + +namespace ConsoleTest.Test +{ + public class OtherTest + { + private static void HttpTest() + { + var url = "http://192.168.1.200:8080/military/videoRecorder/qryCameraList"; + var respStr = HttpMethods.HttpGet(url); + var respObj = JsonUtil.ToJObject(respStr); + + var success = (bool)respObj["success"]; + var message = (string)respObj["message"]; + var code = (int)respObj["code"]; + var rObj = respObj["result"]; + var rStr = rObj.ToJson(); + //var result = JsonUtil.ToList(rStr); + + var timestamp = (string)respObj["timestamp"]; + } + + private static void StartCheckPhotoSaveCycle(bool once) + { + if (once) + CheckPhotoSaveCycle(); + var now = DateTime.Now; + var next = now.AddDays(1); + //var timeSpan = next - now; + var timeSpan = new DateTime(next.Year, next.Month, next.Day) - now; + CommonUtil.SetTimeout(() => + { + CheckPhotoSaveCycle(); + StartCheckPhotoSaveCycle(false); + }, timeSpan.TotalMilliseconds); + } + + public static void CheckPhotoSaveCycle() + { + var now = DateTime.Now; + var workPath = Directory.GetCurrentDirectory(); + var capDir = new DirectoryInfo(Path.Combine(workPath, "cap")); + if (!capDir.Exists) + return; + foreach (var yearDir in capDir.GetDirectories()) + { + if (!yearDir.Exists || !IsInt(yearDir.Name)) + continue; + var year = int.Parse(yearDir.Name); + + foreach (var monthDir in yearDir.GetDirectories()) + { + if (!monthDir.Exists || !IsInt(monthDir.Name)) + continue; + var month = int.Parse(monthDir.Name); + + foreach (var dayDir in monthDir.GetDirectories()) + { + if (!dayDir.Exists || !IsInt(dayDir.Name)) + continue; + var day = int.Parse(dayDir.Name); + + var curTime = new DateTime(year, month, day); + var timeSpan = now - curTime; + var diff = timeSpan.Days + 1; + var SavePhotoDay = 90; + if (diff > SavePhotoDay) + dayDir.Delete(true); + } + if (monthDir.GetDirectories().Length <= 0) + monthDir.Delete(); + } + if (yearDir.GetDirectories().Length <= 0) + yearDir.Delete(); + } + } + + public static bool IsInt(string value) + { + return Regex.IsMatch(value, @"^[-+]?\d+(\.\d+)?$"); + } + + public static decimal WeightStrToDec(string str, int afterLimit = 3) + { + try + { + return Math.Round(Convert.ToDecimal(str), afterLimit); + } + catch (Exception) + { + return 0m; + } + } + + /// + /// 车牌预处理 + /// + public static string PretreatPlate(string oldPlate) + { + oldPlate = oldPlate.ToUpper(); + if (oldPlate.Length < 7) + return oldPlate; + var newPlate = oldPlate.Length > 7 ? oldPlate.Substring(0, 7) : oldPlate; + var dict = new Dictionary { { "O", "0" }, { "I", "1" } }; + newPlate = SubRepString(newPlate, 3, newPlate.Length, dict); + dict = new Dictionary { { "D", "0" } }; + newPlate = SubRepString(newPlate, newPlate.Length - 3, newPlate.Length, dict); + return newPlate; + } + + /// + /// 2021-04-25 15:12:24 + /// + /// + /// + /// + /// + /// + public static string SubRepString(string str, int start, int end, Dictionary dict) + { + var beforeStr = str.Substring(0, start); + var changeStr = str.Substring(start, end - start); + var afterStr = str.Substring(end, str.Length - end); + foreach (var key in dict.Keys) + { + changeStr = changeStr.Replace(key, dict[key]); + } + return beforeStr + changeStr + afterStr; + } + + /// + /// 2021-03-02 09:19:04 + /// + public static void ListTest() + { + var list = new List(); + for (var i = 0; i < 10; i++) + { + list.Add(i); + } + + for (var i = 10; i < 20; i++) + { + list.Add(i); + } + + Console.WriteLine(list); + } + + /// + /// 2021-02-23 14:50:45 + /// + public static void ExceptionCatch() + { + try + { + ExceptionTest(); + } + catch (Exception e) + { + Console.WriteLine(e); + Console.WriteLine(e.Message); + Console.WriteLine(e.Data); + Console.WriteLine(e.Data["t"]); + Console.WriteLine(e.Data["test"]); + } + } + + /// + /// 2021-02-23 14:41:43 + /// + public static void ExceptionTest() + { + var e = new Exception("Exception Test"); + e.Data["test"] = "test"; + throw e; + } + + /// + /// 2021-02-03 14:19:46 + /// + public static void SpeakTest() + { + var chText = "你好,世界"; + var enText = "Hello, World"; + + SpeakHelper.SelectVoice("Microsoft Zira Desktop"); + SpeakHelper.GetVoices(); + + SpeakHelper.Speak(chText); + SpeakHelper.Speak(enText); + + SpeakHelper.SelectVoice(VoiceGender.Male, VoiceAge.Child); + + SpeakHelper.Speak(chText); + SpeakHelper.Speak(enText); + } + + /// + /// 2021-02-02 17:36:34 + /// + /// + public static void EncryptTest() + { + var pwd = Md5Helper.Encrypt(Console.ReadLine(), 32).ToLower(); + //var key = Md5Helper.Encrypt(Md5Helper.CreateNo(), 16).ToLower(); + var key = "cb0d8213f3d570c8"; + var enStr = DesEncrypt.Encrypt(pwd, key).ToLower(); + //var deStr = DesEncrypt.Decrypt(enStr, key).ToLower(); + var enPwd = Md5Helper.Encrypt(enStr, 32).ToLower(); + Console.WriteLine(new { pwd, key, enStr, enPwd }); + + var rePwd = Md5Helper.Encrypt(Console.ReadLine(), 32).ToLower(); + var reEnStr = DesEncrypt.Encrypt(rePwd, key).ToLower(); + var reEnPwd = Md5Helper.Encrypt(reEnStr, 32).ToLower(); + Console.WriteLine(new { rePwd, key, reEnStr, reEnPwd }); + + Console.WriteLine(string.Equals(enPwd, reEnPwd)); + } + + /// + /// 2021-01-18 15:42:47 + /// + public static void ConfigTest() + { + var config = ConfigUtil.GetConfiguration(Path.Combine(EnvUtil.GetWorkDirectory(), "data", "test.config")); + Console.WriteLine(ConfigUtil.GetValue(config, "WT_COM")); + ConfigUtil.SetValue(config, "WT_COM", "com1"); + Console.WriteLine(ConfigUtil.GetValue(config, "WT_COM")); + ConfigUtil.ReadAllSettings(config); + } + + /// + /// 2021-01-12 10:12:59 + /// + public static string WeightDecToStr(decimal dec, int afterLimit = 3, char patch = '#') + { + return dec.ToString("0.".PadRight(afterLimit + 2, patch)); + } + + /// + /// 2021-01-12 09:02:59 + /// + public static void FingerPrintTest() + { + var manager = new FingerPrintManager(); + + //开启服务 + manager.StartServer(); + + //获取设备内核版本 + var kernel = string.Empty; + manager.GetDevKerNel(ref kernel); + + //获取设备序列号 + var sn = string.Empty; + manager.GetDevSn(ref sn); + + ////设置模板弹框关闭 + //manager.SetRegBoxAble(false); + + //获取指纹模板 + var regBuf = string.Empty; + manager.GetRegFingerPrint(ref regBuf); + + //设置特征弹框开启 + manager.SetVerBoxAble(true); + + //获取指纹特征 + var verBuf = string.Empty; + manager.GetVerFingerPrint(ref verBuf); + + //对比模板和特征 + var ret = manager.MatchFingerPrint(regBuf, verBuf); + + //for (var i = 0; i < 10; i++) + //{ + // Thread.Sleep(1000); + // manager.SetBeepLight(i); + //} + + //关闭服务 + manager.StopServer(); + + Console.WriteLine(new { kernel, sn }); + Console.WriteLine(new { regBuf.Length, regBuf }); + Console.WriteLine(new { verBuf.Length, verBuf }); + Console.WriteLine(new { ret }); + } + + /// + /// 2021-01-02 09:03:07 + /// + public static void YuHuoTest() + { + YuHuo.Yu(); + YuHuo.Huo(); + YuHuo.YiHuo(); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Test/Other/YuHuo.cs b/ConsoleTest/Test/Other/YuHuo.cs new file mode 100644 index 0000000..9fde444 --- /dev/null +++ b/ConsoleTest/Test/Other/YuHuo.cs @@ -0,0 +1,44 @@ +using System; + +namespace ConsoleTest.AutoWeight.Some +{ + internal class YuHuo + { + public static void Yu() + { + Console.WriteLine("--------------------"); + Console.WriteLine(0 & 0); + Console.WriteLine(0 & 1); + Console.WriteLine(1 & 0); + Console.WriteLine(1 & 1); + Console.WriteLine("--------------------"); + } + + public static void Huo() + { + Console.WriteLine("--------------------"); + Console.WriteLine(0 | 0); + Console.WriteLine(0 | 1); + Console.WriteLine(1 | 0); + Console.WriteLine(1 | 1); + Console.WriteLine("--------------------"); + } + + public static void YiHuo() + { + Console.WriteLine("--------------------"); + Console.WriteLine(0 ^ 0); + Console.WriteLine(0 ^ 1); + Console.WriteLine(1 ^ 0); + Console.WriteLine(1 ^ 1); + Console.WriteLine("--------------------"); + } + + public static void Ping() + { + var ping = new System.Net.NetworkInformation.Ping(); + var result = ping.Send("www.baidu.com"); + Console.WriteLine(result); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/CommonUtil.cs b/ConsoleTest/Util/CommonUtil.cs new file mode 100644 index 0000000..e64bd8e --- /dev/null +++ b/ConsoleTest/Util/CommonUtil.cs @@ -0,0 +1,184 @@ +using System; +using System.Text.RegularExpressions; + +namespace ConsoleTest.Util +{ + public class CommonUtil + { + /// + /// 将 DateTime 转换为 UnixTime 单位秒 + /// + /// + /// + public static int DateTimeToUnixTime(DateTime dateTime) + { + return (int)(dateTime - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1))).TotalSeconds; + } + + /// + /// 将 UnixTime 转换为 DateTime 单位秒 + /// + /// + /// + public static DateTime UnixTimeToDateTime(int time) + { + if (time < 0) + throw new ArgumentOutOfRangeException("time is out of range"); + return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(time); + } + + /// + /// 小数字符串去零 + /// + /// + /// + public static string Trim0(string str) + { + string result = str.TrimEnd('0'); + if (result.EndsWith(".")) + { + result = result.Remove(result.Length - 1); + } + return result; + } + + /// + /// 判断车牌是否正确 + /// + /// + /// + public static bool IsSuccessPlate(string plate) + { + int len = plate.Length; + if (len == 7) + { + if (plate[0] > 127) + {//汉字 + for (int i = 1; i < 7; i++) + { + if (plate[i] > 127) + { + return false; + } + } + return true; + } + } + return false; + } + + /// 要舍入的字符串小数 + public static decimal StrToDec(string str) + { + try + { + return !string.IsNullOrEmpty(str) ? Convert.ToDecimal(str.Trim()) : 0m; + } + catch (Exception) + { + return 0m; + } + } + + /// + /// + /// + /// + /// + /// # or 0 + /// + public static string WeightDecToStr(decimal dec, int afterLimit = 3, char patch = '#') + { + return dec.ToString("0.".PadRight(afterLimit + 2, patch)); + } + + /// 要舍入的字符串小数 + /// 指定数字要舍入到的小数位数的值,范围从 0 到 28。 + public static decimal WeightStrToDec(string str, int afterLimit = 3) + { + try + { + return Math.Round(Convert.ToDecimal(str), afterLimit); + } + catch (Exception) + { + return 0m; + } + } + + public static string Reverse(string original) + { + var arr = original.ToCharArray(); + Array.Reverse(arr); + return new string(arr); + } + + public static bool IsNumber(string value) + { + return Regex.IsMatch(value, @"^[-+]?\d+(\.\d+)?$"); + } + + public static bool IsInt(string value) + { + return Regex.IsMatch(value, @"^[-+]?\d+(\.\d+)?$"); + } + + /// + /// 在指定时间过后执行指定的表达式 + /// + /// 时间(以毫秒为单位) + /// 要执行的表达式 + /// 返回timer对象 + public static void SetTimeout(Action action, double interval) + { + var timer = new System.Timers.Timer(interval); + timer.Elapsed += (sender, e) => + { + timer.Enabled = false; + action(); + timer.Dispose(); + timer.Close(); + timer = null; + }; + timer.Enabled = true; + } + + /// + /// 在指定时间周期重复执行指定的表达式 + /// + /// 时间(以毫秒为单位) + /// 要执行的表达式 + public static void SetInterval(Action action, double interval) + { + var timer = new System.Timers.Timer(interval); + timer.Elapsed += (sender, e) => { action(); }; + timer.Enabled = true; + } + + /// + ///生成随机字符串 + /// + ///目标字符串的长度 + ///是否包含数字,1=包含,默认为包含 + ///是否包含小写字母,1=包含,默认为包含 + ///是否包含大写字母,1=包含,默认为包含 + ///是否包含特殊字符,1=包含,默认为不包含 + ///指定长度的随机字符串 + public static string GetRandomString(int length, bool useNum = true, bool useLow = true, bool useUpp = true, bool useSpe = true) + { + var b = new byte[4]; + new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b); + var r = new Random(BitConverter.ToInt32(b, 0)); + string s = string.Empty, str = string.Empty; + if (useNum == true) { str += "0123456789"; } + if (useLow == true) { str += "abcdefghijklmnopqrstuvwxyz"; } + if (useUpp == true) { str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } + if (useSpe == true) { str += "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; } + for (int i = 0; i < length; i++) + { + s += str.Substring(r.Next(0, str.Length - 1), 1); + } + return s; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/ConfigUtil.cs b/ConsoleTest/Util/ConfigUtil.cs new file mode 100644 index 0000000..04ffc87 --- /dev/null +++ b/ConsoleTest/Util/ConfigUtil.cs @@ -0,0 +1,115 @@ +using System; +using System.Configuration; + +namespace ConsoleTest.Util +{ + public class ConfigUtil + { + #region App.config (*.exe.config) + + private static string GetValue(string key) + { + return ConfigurationManager.AppSettings[key]; + } + + public static string GetStringVal(string key) + { + return GetValue(key); + } + + public static short GetShortVal(string key) + { + bool ret = short.TryParse(GetValue(key), out short val); + return ret ? val : (short)0; + } + + public static int GetIntVal(string key) + { + bool ret = int.TryParse(GetValue(key), out int val); + return ret ? val : 0; + } + + public static double GetDoubleVal(string key) + { + bool ret = double.TryParse(GetValue(key), out double val); + return ret ? val : 0; + } + + public static bool GetBoolVal(string key) + { + bool ret = bool.TryParse(GetValue(key), out bool val); + return ret ? val : false; + } + + public static void SetValue(string key, string value) + { + var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); + config.AppSettings.Settings[key].Value = value; + // Save the configuration file. + config.AppSettings.SectionInformation.ForceSave = true; + config.Save(ConfigurationSaveMode.Modified); + // Force a reload of the changed section. + ConfigurationManager.RefreshSection("appSettings"); + } + + public static void ReadAllSettings() + { + var appSettings = ConfigurationManager.AppSettings; + + if (appSettings.Count == 0) + { + Console.WriteLine("AppSettings is empty."); + } + else + { + foreach (var key in appSettings.AllKeys) + { + Console.WriteLine("Key: {0} Value: {1}", key, appSettings[key]); + } + } + } + + #endregion App.config (*.exe.config) + + #region other.config + + /// + /// 打开指定的配置文件; + /// + public static Configuration GetConfiguration(string configFile) + { + var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile }; + return ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); + } + + public static string GetValue(Configuration config, string key) + { + return config.AppSettings.Settings[key].Value.Trim(); + } + + public static void SetValue(Configuration config, string key, string value) + { + config.AppSettings.Settings[key].Value = value; + config.AppSettings.SectionInformation.ForceSave = true; + config.Save(ConfigurationSaveMode.Modified); + } + + public static void ReadAllSettings(Configuration config) + { + var appSettings = config.AppSettings.Settings; + if (appSettings.Count == 0) + { + Console.WriteLine("AppSettings is empty."); + } + else + { + foreach (var key in appSettings.AllKeys) + { + Console.WriteLine("Key: {0} Value: {1}", key, appSettings[key].Value); + } + } + } + + #endregion other.config + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/Encrypt/DesEncrypt.cs b/ConsoleTest/Util/Encrypt/DesEncrypt.cs new file mode 100644 index 0000000..fba0716 --- /dev/null +++ b/ConsoleTest/Util/Encrypt/DesEncrypt.cs @@ -0,0 +1,65 @@ +using System; +using System.Security.Cryptography; +using System.Text; + +namespace ConsoleTest.Util.Encrypt +{ + /// + /// 加密、解密帮助类 + /// + public static class DesEncrypt + { + /// + /// 加密数据 + /// + /// 需要加密的内容 + /// 秘钥 + /// + public static string Encrypt(string str, string key) + { + var des = new DESCryptoServiceProvider(); + des.Key = Encoding.ASCII.GetBytes(Md5Helper.Hash(key).ToUpper().Substring(0, 8)); + des.IV = Encoding.ASCII.GetBytes(Md5Helper.Hash(key).ToUpper().Substring(0, 8)); + + var ms = new System.IO.MemoryStream(); + var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); + var byteArray = Encoding.Default.GetBytes(str); + cs.Write(byteArray, 0, byteArray.Length); + cs.FlushFinalBlock(); + + var builder = new StringBuilder(); + foreach (var b in ms.ToArray()) + { + builder.Append(b.ToString("x2")); + } + + return builder.ToString(); + } + + /// + /// 解密数据 + /// + /// 需要解密的内容 + /// 秘钥 + /// + public static string Decrypt(string str, string key) + { + var byteArray = new byte[str.Length / 2]; + for (var i = 0; i < byteArray.Length; i++) + { + byteArray[i] = (byte)Convert.ToInt32(str.Substring(i * 2, 2), 16); + } + + var des = new DESCryptoServiceProvider(); + des.Key = Encoding.ASCII.GetBytes(Md5Helper.Hash(key).ToUpper().Substring(0, 8)); + des.IV = Encoding.ASCII.GetBytes(Md5Helper.Hash(key).ToUpper().Substring(0, 8)); + + var ms = new System.IO.MemoryStream(); + var cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(byteArray, 0, byteArray.Length); + cs.FlushFinalBlock(); + + return Encoding.Default.GetString(ms.ToArray()); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/Encrypt/Md5Helper.cs b/ConsoleTest/Util/Encrypt/Md5Helper.cs new file mode 100644 index 0000000..b24859d --- /dev/null +++ b/ConsoleTest/Util/Encrypt/Md5Helper.cs @@ -0,0 +1,66 @@ +using System; +using System.Security.Cryptography; +using System.Text; + +namespace ConsoleTest.Util.Encrypt +{ + /// + /// md5加密 + /// + public class Md5Helper + { + /// + /// MD5加密 + /// + /// 加密字符 + /// 加密位数16/32 + /// + public static string Encrypt(string str, int len) + { + string encryptStr; + switch (len) + { + case 16: + encryptStr = Hash(str).Substring(8, 16); + break; + + case 32: + encryptStr = Hash(str); + break; + + default: + encryptStr = Hash(str); + break; + } + return encryptStr; + } + + /// + /// 32位MD5加密(小写) + /// + /// 输入字段 + /// + public static string Hash(string str) + { + var md5Hasher = new MD5CryptoServiceProvider(); + var byteArray = md5Hasher.ComputeHash(Encoding.Default.GetBytes(str)); + var builder = new StringBuilder(); + foreach (var b in byteArray) + { + builder.Append(b.ToString("x2")); + } + return builder.ToString(); + } + + /// + /// 生成编号,形如201008251145409865 + /// + /// + public static string CreateNo() + { + var randomStr = new Random().Next(1000, 10000).ToString(); //生成编号 + var number = DateTime.Now.ToString("yyyyMMddHHmmss") + randomStr; + return number; + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/EnvUtil.cs b/ConsoleTest/Util/EnvUtil.cs new file mode 100644 index 0000000..830678e --- /dev/null +++ b/ConsoleTest/Util/EnvUtil.cs @@ -0,0 +1,50 @@ +using System; +using System.IO; +using System.Reflection; + +namespace ConsoleTest.Util +{ + public class EnvUtil + { + private static string workDirectory; + + public static void InitWorkDirectory() + { + Directory.SetCurrentDirectory(GetWorkDirectory()); + } + + public static string GetWorkDirectory() + { + workDirectory = string.IsNullOrEmpty(workDirectory) ? Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) : workDirectory; + return workDirectory; + } + + public static bool AddDllPath(string dllPath) + { + if (!Directory.Exists(dllPath)) { return false; } + string envPath = Environment.GetEnvironmentVariable("PATH"); + Environment.SetEnvironmentVariable("PATH", envPath + ";" + dllPath); + return true; + } + + public static string CombinePath(string path1, string path2) + { + return Path.Combine(path1, path2); + } + + public static string CombinePath(params string[] paths) + { + return Path.Combine(paths); + } + + public static bool ExistFile(string file) + { + return File.Exists(file); + } + + public static bool ExistDirectory(string dir) + { + return Directory.Exists(dir); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/HttpMethods.cs b/ConsoleTest/Util/HttpMethods.cs new file mode 100644 index 0000000..e18852f --- /dev/null +++ b/ConsoleTest/Util/HttpMethods.cs @@ -0,0 +1,572 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace ConsoleTest.Util +{ + public class HttpMethods + { + #region POST + + /// + /// HTTP POST方式请求数据 + /// + /// URL. + /// POST的数据 + /// + public static string HttpPost(string url, string param = null) + { + HttpWebRequest request; + + //如果是发送HTTPS请求 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CheckValidationResult); + request = WebRequest.Create(url) as HttpWebRequest; + request.ProtocolVersion = HttpVersion.Version10; + } + else + { + request = WebRequest.Create(url) as HttpWebRequest; + } + + request.Method = "POST"; + request.ContentType = "application/x-www-form-urlencoded"; + request.Accept = "*/*"; + request.Timeout = 15000; + request.AllowAutoRedirect = false; + + StreamWriter requestStream = null; + WebResponse response = null; + string responseStr = null; + + try + { + requestStream = new StreamWriter(request.GetRequestStream()); + requestStream.Write(param); + requestStream.Close(); + + response = request.GetResponse(); + if (response != null) + { + StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); + responseStr = reader.ReadToEnd(); + reader.Close(); + } + } + catch (Exception ex) + { + throw ex; + } + finally + { + request = null; + requestStream = null; + response = null; + } + + return responseStr; + } + + private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, + SslPolicyErrors errors) + { + return true; //总是接受 + } + + public static string BuildRequest(string strUrl, Dictionary dicPara, string fileName) + { + string contentType = "image/jpeg"; + //待请求参数数组 + FileStream Pic = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + byte[] PicByte = new byte[Pic.Length]; + Pic.Read(PicByte, 0, PicByte.Length); + int lengthFile = PicByte.Length; + + //构造请求地址 + + //设置HttpWebRequest基本信息 + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(strUrl); + //设置请求方式:get、post + request.Method = "POST"; + //设置boundaryValue + string boundaryValue = DateTime.Now.Ticks.ToString("x"); + string boundary = "--" + boundaryValue; + request.ContentType = "\r\nmultipart/form-data; boundary=" + boundaryValue; + //设置KeepAlive + request.KeepAlive = true; + //设置请求数据,拼接成字符串 + StringBuilder sbHtml = new StringBuilder(); + foreach (KeyValuePair key in dicPara) + { + sbHtml.Append(boundary + "\r\nContent-Disposition: form-data; name=\"" + key.Key + "\"\r\n\r\n" + + key.Value + "\r\n"); + } + + sbHtml.Append(boundary + "\r\nContent-Disposition: form-data; name=\"pic\"; filename=\""); + sbHtml.Append(fileName); + sbHtml.Append("\"\r\nContent-Type: " + contentType + "\r\n\r\n"); + string postHeader = sbHtml.ToString(); + //将请求数据字符串类型根据编码格式转换成字节流 + Encoding code = Encoding.GetEncoding("UTF-8"); + byte[] postHeaderBytes = code.GetBytes(postHeader); + byte[] boundayBytes = Encoding.ASCII.GetBytes("\r\n" + boundary + "--\r\n"); + //设置长度 + long length = postHeaderBytes.Length + lengthFile + boundayBytes.Length; + request.ContentLength = length; + + //请求远程HTTP + Stream requestStream = request.GetRequestStream(); + Stream myStream = null; + try + { + //发送数据请求服务器 + requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length); + requestStream.Write(PicByte, 0, lengthFile); + requestStream.Write(boundayBytes, 0, boundayBytes.Length); + HttpWebResponse HttpWResp = (HttpWebResponse)request.GetResponse(); + myStream = HttpWResp.GetResponseStream(); + } + catch (WebException) + { + //LogResult(e.Message); + return ""; + } + finally + { + if (requestStream != null) + { + requestStream.Close(); + } + } + + //读取处理结果 + StreamReader reader = new StreamReader(myStream, code); + StringBuilder responseData = new StringBuilder(); + + String line; + while ((line = reader.ReadLine()) != null) + { + responseData.Append(line); + } + + myStream.Close(); + Pic.Close(); + + return responseData.ToString(); + } + + #endregion POST + + #region Put + + /// + /// HTTP Put方式请求数据. + /// + /// URL. + /// + public static string HttpPut(string url, string param = null) + { + HttpWebRequest request; + + //如果是发送HTTPS请求 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CheckValidationResult); + request = WebRequest.Create(url) as HttpWebRequest; + request.ProtocolVersion = HttpVersion.Version10; + } + else + { + request = WebRequest.Create(url) as HttpWebRequest; + } + + request.Method = "PUT"; + request.ContentType = "application/x-www-form-urlencoded"; + request.Accept = "*/*"; + request.Timeout = 15000; + request.AllowAutoRedirect = false; + + StreamWriter requestStream = null; + WebResponse response = null; + string responseStr = null; + + try + { + requestStream = new StreamWriter(request.GetRequestStream()); + requestStream.Write(param); + requestStream.Close(); + + response = request.GetResponse(); + if (response != null) + { + StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); + responseStr = reader.ReadToEnd(); + reader.Close(); + } + } + catch (Exception) + { + throw; + } + finally + { + request = null; + requestStream = null; + response = null; + } + + return responseStr; + } + + #endregion Put + + #region Delete + + /// + /// HTTP Delete方式请求数据. + /// + /// URL. + /// + public static string HttpDelete(string url, string param = null) + { + HttpWebRequest request; + + //如果是发送HTTPS请求 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CheckValidationResult); + request = WebRequest.Create(url) as HttpWebRequest; + request.ProtocolVersion = HttpVersion.Version10; + } + else + { + request = WebRequest.Create(url) as HttpWebRequest; + } + + request.Method = "Delete"; + request.ContentType = "application/x-www-form-urlencoded"; + request.Accept = "*/*"; + request.Timeout = 15000; + request.AllowAutoRedirect = false; + + StreamWriter requestStream = null; + WebResponse response = null; + string responseStr = null; + + try + { + requestStream = new StreamWriter(request.GetRequestStream()); + requestStream.Write(param); + requestStream.Close(); + + response = request.GetResponse(); + if (response != null) + { + StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); + responseStr = reader.ReadToEnd(); + reader.Close(); + } + } + catch (Exception) + { + throw; + } + + return responseStr; + } + + #endregion Delete + + #region Get + + /// + /// HTTP GET方式请求数据. + /// + /// URL. + /// + public static string HttpGet(string url, Hashtable headht = null) + { + HttpWebRequest request; + + //如果是发送HTTPS请求 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CheckValidationResult); + request = WebRequest.Create(url) as HttpWebRequest; + request.ProtocolVersion = HttpVersion.Version10; + } + else + { + request = WebRequest.Create(url) as HttpWebRequest; + } + + request.Method = "GET"; + //request.ContentType = "application/x-www-form-urlencoded"; + request.Accept = "*/*"; + request.Timeout = 15000; + request.AllowAutoRedirect = false; + WebResponse response = null; + string responseStr = null; + if (headht != null) + { + foreach (DictionaryEntry item in headht) + { + request.Headers.Add(item.Key.ToString(), item.Value.ToString()); + } + } + + try + { + response = request.GetResponse(); + + if (response != null) + { + StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); + responseStr = reader.ReadToEnd(); + reader.Close(); + } + } + catch (Exception) + { + throw; + } + + return responseStr; + } + + public static string HttpGet(string url, Encoding encodeing, Hashtable headht = null) + { + HttpWebRequest request; + + //如果是发送HTTPS请求 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback = + new RemoteCertificateValidationCallback(CheckValidationResult); + request = WebRequest.Create(url) as HttpWebRequest; + request.ProtocolVersion = HttpVersion.Version10; + } + else + { + request = WebRequest.Create(url) as HttpWebRequest; + } + + request.Method = "GET"; + //request.ContentType = "application/x-www-form-urlencoded"; + request.Accept = "*/*"; + request.Timeout = 15000; + request.AllowAutoRedirect = false; + WebResponse response = null; + string responseStr = null; + if (headht != null) + { + foreach (DictionaryEntry item in headht) + { + request.Headers.Add(item.Key.ToString(), item.Value.ToString()); + } + } + + try + { + response = request.GetResponse(); + + if (response != null) + { + StreamReader reader = new StreamReader(response.GetResponseStream(), encodeing); + responseStr = reader.ReadToEnd(); + reader.Close(); + } + } + catch (Exception) + { + throw; + } + + return responseStr; + } + + #endregion Get + + #region Post With Pic + + private string HttpPost(string url, IDictionary param, string filePath) + { + string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); + byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); + + HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); + wr.ContentType = "multipart/form-data; boundary=" + boundary; + wr.Method = "POST"; + wr.KeepAlive = true; + wr.Credentials = System.Net.CredentialCache.DefaultCredentials; + + Stream rs = wr.GetRequestStream(); + string responseStr = null; + + string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; + foreach (string key in param.Keys) + { + rs.Write(boundarybytes, 0, boundarybytes.Length); + string formitem = string.Format(formdataTemplate, key, param[key]); + byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); + rs.Write(formitembytes, 0, formitembytes.Length); + } + + rs.Write(boundarybytes, 0, boundarybytes.Length); + + string headerTemplate = + "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; + string header = string.Format(headerTemplate, "pic", filePath, "text/plain"); + byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); + rs.Write(headerbytes, 0, headerbytes.Length); + + FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + byte[] buffer = new byte[4096]; + int bytesRead = 0; + while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) + { + rs.Write(buffer, 0, bytesRead); + } + + fileStream.Close(); + + byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); + rs.Write(trailer, 0, trailer.Length); + rs.Close(); + + WebResponse wresp = null; + try + { + wresp = wr.GetResponse(); + Stream stream2 = wresp.GetResponseStream(); + StreamReader reader2 = new StreamReader(stream2); + responseStr = reader2.ReadToEnd(); + //logger.Debug(string.Format("File uploaded, server response is: {0}", responseStr)); + } + catch (Exception) + { + //logger.Error("Error uploading file", ex); + if (wresp != null) + { + wresp.Close(); + wresp = null; + } + + throw; + } + + return responseStr; + } + + #endregion Post With Pic + + #region Post With Pic + + /// + /// HTTP POST方式请求数据(带图片) + /// + /// URL + /// POST的数据 + /// 图片 + /// + public static string HttpPost(string url, IDictionary param, byte[] fileByte) + { + string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); + byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); + + HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url); + wr.ContentType = "multipart/form-data; boundary=" + boundary; + wr.Method = "POST"; + wr.KeepAlive = true; + wr.Credentials = System.Net.CredentialCache.DefaultCredentials; + + Stream rs = wr.GetRequestStream(); + string responseStr = null; + + string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; + foreach (string key in param.Keys) + { + rs.Write(boundarybytes, 0, boundarybytes.Length); + string formitem = string.Format(formdataTemplate, key, param[key]); + byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); + rs.Write(formitembytes, 0, formitembytes.Length); + } + + rs.Write(boundarybytes, 0, boundarybytes.Length); + + string headerTemplate = + "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; + string header = string.Format(headerTemplate, "pic", fileByte, "text/plain"); //image/jpeg + byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); + rs.Write(headerbytes, 0, headerbytes.Length); + + rs.Write(fileByte, 0, fileByte.Length); + + byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); + rs.Write(trailer, 0, trailer.Length); + rs.Close(); + + WebResponse wresp = null; + try + { + wresp = wr.GetResponse(); + Stream stream2 = wresp.GetResponseStream(); + StreamReader reader2 = new StreamReader(stream2); + responseStr = reader2.ReadToEnd(); + // logger.Error(string.Format("File uploaded, server response is: {0}", responseStr)); + } + catch (Exception) + { + //logger.Error("Error uploading file", ex); + if (wresp != null) + { + wresp.Close(); + wresp = null; + } + + throw; + } + + return responseStr; + } + + #endregion Post With Pic + + #region HttpsClient + + /// + /// 创建HttpClient + /// + /// + public static HttpClient CreateHttpClient(string url) + { + HttpClient httpclient; + //如果是发送HTTPS请求 + if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + { + ServicePointManager.ServerCertificateValidationCallback += + (sender, cert, chain, sslPolicyErrors) => true; + httpclient = new HttpClient(); + } + else + { + httpclient = new HttpClient(); + } + + return httpclient; + } + + #endregion HttpsClient + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/JsonUtil.cs b/ConsoleTest/Util/JsonUtil.cs new file mode 100644 index 0000000..771a061 --- /dev/null +++ b/ConsoleTest/Util/JsonUtil.cs @@ -0,0 +1,72 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Data; +using System.IO; + +namespace ConsoleTest.Util +{ + /// + /// Json操作 + /// + public static class JsonUtil + { + public static object ToJson(this string Json) + { + return Json == null ? null : JsonConvert.DeserializeObject(Json); + } + + public static string ToJson(this object obj) + { + var timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" }; + return JsonConvert.SerializeObject(obj, timeConverter); + } + + public static string ToJson(this object obj, string datetimeformats) + { + var timeConverter = new IsoDateTimeConverter { DateTimeFormat = datetimeformats }; + return JsonConvert.SerializeObject(obj, timeConverter); + } + + public static T ToObject(this string Json) + { + return Json == null ? default(T) : JsonConvert.DeserializeObject(Json); + } + + public static List ToList(this string Json) + { + return Json == null ? null : JsonConvert.DeserializeObject>(Json); + } + + public static DataTable ToTable(this string Json) + { + return Json == null ? null : JsonConvert.DeserializeObject(Json); + } + + public static JObject ToJObject(this string Json) + { + return Json == null ? JObject.Parse("{}") : JObject.Parse(Json.Replace(" ", "")); + } + + /// + /// 读取JSON文件 + /// + public static JObject ReadFileJson(string jsonFile) + { + try + { + using StreamReader file = File.OpenText(jsonFile); + using JsonTextReader reader = new JsonTextReader(file); + JObject jObject = (JObject)JToken.ReadFrom(reader); + return jObject; + } + catch (Exception ex) + { + Console.WriteLine(ex); + return null; + } + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/PortHelper/ECSerialPort.cs b/ConsoleTest/Util/PortHelper/ECSerialPort.cs new file mode 100644 index 0000000..b8fd873 --- /dev/null +++ b/ConsoleTest/Util/PortHelper/ECSerialPort.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Linq; +using System.Text.RegularExpressions; + +namespace ConsoleTest.Util.PortHelper +{ + /// + /// 返回数据类型 + /// + public enum ReturnDateType + { + /// + /// 返回byte[] + /// + Bytes = 0, + + HexStr = 1, + + Str = 2, + } + + /// + /// EC 串口类 + /// + public class ECSerialPort + { + private System.IO.Ports.SerialPort comm = new System.IO.Ports.SerialPort();//声明一个串口 + private SerialCustomer serialCustomer = null; + private bool openFlag = false;// 是否打开成功 + + public long ReceivedCount { get; set; }//接收计数 + + public long RendCount { get; set; }//发送计数 + + public ECSerialPort(SerialCustomer serialCustomer) + { + this.serialCustomer = serialCustomer; + } + + public bool OpenCom() + { + //根据当前串口对象,来判断操作 + if (comm.IsOpen) + { + //打开时点击,则关闭串口 + comm.Close(); + openFlag = false; + } + else + { + if (serialCustomer.ComName == "") + { + throw new Exception("请插入串口设备!"); + } + //关闭时点击,则设置好端口,波特率后打开 + //获得串口端口信息为: COM1:通讯端口 + + comm.PortName = serialCustomer.ComName; + comm.BaudRate = serialCustomer.BaudRate;// int.Parse(comboBaudrate.Text);//波特率 + comm.DataBits = serialCustomer.DataBits;//数据位 + comm.Parity = (Parity)serialCustomer.Parity;//奇偶校验0-4=no,odd,even,mark,space + comm.StopBits = (StopBits)Convert.ToInt32(serialCustomer.StopBits);//停止位 + comm.ReadTimeout = 2000;//写超时 + comm.WriteTimeout = 500;//读超时 + //comm.WriteBufferSize = 1024; + //comm.ReadBufferSize = 1024; + comm.ReceivedBytesThreshold = 128;//128Btye时触发一次事件,设置为1时易造成线程死锁。 + comm.RtsEnable = true; + comm.DtrEnable = true; + // comm.Handshake = Handshake.None; + //添加事件注册 + comm.DataReceived += new SerialDataReceivedEventHandler(Comm_DataReceived); + comm.Open(); + } + openFlag = comm.IsOpen ? true : false; + return openFlag; + } + + /// + /// 关闭串口 + /// + public void CloseCom() + { + comm.Close(); + openFlag = false; + } + + public bool IsOpen() + { + return comm.IsOpen; + } + + public event EventHandler OnRecData; //定义一个委托类型的事件 + + private void Comm_DataReceived(object sender, EventArgs e) + { + int n = comm.BytesToRead;//获取缓存区字节数 + byte[] buf = new byte[n];//存储串口数据用 + ReceivedCount += n;//接收计数 + comm.Read(buf, 0, n);//读取缓冲数据 + + //OnRecData?.BeginInvoke(this, buf, null, null); + OnRecData?.Invoke(this, buf); + } + + /// + /// 发送串口 + /// + /// + /// + /// + public void Send(bool checkBoxHexSend, string sendtext, bool newLine = false) + { + ; + //定义一个变量,记录发送了几个字节 + int n = 0; + //16进制发送 + if (checkBoxHexSend) + { + //正则得到有效的十六进制数(?i)对大小写不敏感,[/da-f],{2}连续出现2次 + // MatchCollection mc = Regex.Matches(txSend.Text, @"(?i)[/da-f]{2}"); + MatchCollection mc = Regex.Matches(sendtext, @"(?i)[\da-f]{2}"); + List buf = new List();//填充到这个临时列表中 + //依次添加到列表中 + foreach (Match m in mc) + { + buf.Add(byte.Parse(m.Value, System.Globalization.NumberStyles.HexNumber)); + } + //转换列表为数组后发送 + comm.Write(buf.ToArray(), 0, buf.Count); + if (newLine == true) + { //记录发送的字节数 + comm.WriteLine("\r\n"); + n = buf.Count + 2; + } + else + n = buf.Count; + } + else//ascii编码直接发送 + { + if (newLine == true) + { + comm.Write(sendtext + "\r\n"); + n = sendtext.Length + 2; + } + else//不包含换行符 + { + comm.Write(sendtext); + n = sendtext.Length; + } + } + RendCount += n;//累加发送字节数 + } + + /// + /// 16进制发送 + /// + /// + /// + public void SendHex(byte[] buf, bool newline = false) + { + //定义一个变量,记录发送了几个字节 + int n = 0; + + int bufLen = buf.Count(); + comm.Write(buf, 0, bufLen); + //if (newline == true) + //{ //记录发送的字节数 + //comm.WriteLine("\n"); + //n = bufLen + 2; + //} + //else + // n = bufLen; + + RendCount += n;//累加发送字节数 + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/PortHelper/SerialCustomer.cs b/ConsoleTest/Util/PortHelper/SerialCustomer.cs new file mode 100644 index 0000000..b6ea4f4 --- /dev/null +++ b/ConsoleTest/Util/PortHelper/SerialCustomer.cs @@ -0,0 +1,45 @@ +namespace ConsoleTest.Util.PortHelper +{ + /// + /// 串口参数类 + /// + public class SerialCustomer + { + public SerialCustomer() + { + BaudRate = 9600; + Parity = 0; + DataBits = 8; + StopBits = 1; + } + + /// + /// 串口名称 + /// + public string ComName { get; set; } + + /// + ///波特率 + /// + public int BaudRate { get; set; } + + /// + /// 奇偶校验0-4=no,odd,even,mark,space + /// + public int Parity { get; set; } + + ///// + ///// 校验位对应值 + ///// + //public int ParityValue { get; set; }// + /// + ///数据位 默认 + /// + public int DataBits { get; set; } = 8; + + /// + /// 停止位 + /// + public int StopBits { get; set; } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/PortHelper/SerialPortManager.cs b/ConsoleTest/Util/PortHelper/SerialPortManager.cs new file mode 100644 index 0000000..51605ff --- /dev/null +++ b/ConsoleTest/Util/PortHelper/SerialPortManager.cs @@ -0,0 +1,47 @@ +namespace ConsoleTest.Util.PortHelper +{ + /// + /// EC 串口管理类 + /// + public class SerialPortManager + { + /// + /// 根据参数对象创建 + /// + /// + /// + public static ECSerialPort CreateSerialPort(SerialCustomer serialCustomer) + { + return new ECSerialPort(serialCustomer); + } + + /// + /// 获取默认参数串口 + /// + /// + public static ECSerialPort CreateSerialPort(string comName) + { + SerialCustomer serialCustomer = new SerialCustomer + { + ComName = comName + }; + return new ECSerialPort(serialCustomer); + } + + /// + /// 根据不同波特率创建串口 + /// + /// + /// + /// + public static ECSerialPort CreateSerialPort(string comName, int baudRate) + { + SerialCustomer serialCustomer = new SerialCustomer + { + ComName = comName, + BaudRate = baudRate + }; + return new ECSerialPort(serialCustomer); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/PortUtil/SerialPortBuilder.cs b/ConsoleTest/Util/PortUtil/SerialPortBuilder.cs new file mode 100644 index 0000000..76f35aa --- /dev/null +++ b/ConsoleTest/Util/PortUtil/SerialPortBuilder.cs @@ -0,0 +1,61 @@ +namespace ConsoleTest.Util.PortUtil +{ + /// + /// 串口构建类 + /// + public class SerialPortBuilder + { + /// + /// + /// + /// + public static YcSerialPort CreateSerialPort(SerialPortParam param) + { + return new YcSerialPort(param); + } + + /// + /// + /// + public static YcSerialPort CreateSerialPort(string comName) + { + var param = new SerialPortParam + { + ComName = comName + }; + return new YcSerialPort(param); + } + + /// + /// + /// + /// + /// + public static YcSerialPort CreateSerialPort(string comName, int baudRate) + { + var param = new SerialPortParam + { + ComName = comName, + BaudRate = baudRate + }; + return new YcSerialPort(param); + } + + /// + /// + /// + /// + /// + /// + public static YcSerialPort CreateSerialPort(string comName, int baudRate, int receivedBytesThreshold) + { + var param = new SerialPortParam + { + ComName = comName, + BaudRate = baudRate, + ReceivedBytesThreshold = receivedBytesThreshold + }; + return new YcSerialPort(param); + } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/PortUtil/SerialPortParam.cs b/ConsoleTest/Util/PortUtil/SerialPortParam.cs new file mode 100644 index 0000000..d828e3c --- /dev/null +++ b/ConsoleTest/Util/PortUtil/SerialPortParam.cs @@ -0,0 +1,51 @@ +namespace ConsoleTest.Util.PortUtil +{ + /// + /// 串口参数类 + /// + public class SerialPortParam + { + public SerialPortParam() + { + BaudRate = 9600; + Parity = 0; + DataBits = 8; + StopBits = 1; + ReceivedBytesThreshold = 128; + } + + /// + /// 串口名称 + /// + public string ComName { get; set; } + + /// + ///波特率 + /// + public int BaudRate { get; set; } + + /// + /// 奇偶校验0-4=no,odd,even,mark,space + /// + public int Parity { get; set; } + + ///// + ///// 校验位对应值 + ///// + //public int ParityValue { get; set; }// + /// + ///数据位 默认 + /// + public int DataBits { get; set; } + + /// + /// 停止位 + /// + public int StopBits { get; set; } + + /// + /// ?Byte时,触发一次事件。设置为1时,易造成线程死锁 + /// + public int ReceivedBytesThreshold { get; set; } + } +} \ No newline at end of file diff --git a/ConsoleTest/Util/PortUtil/YcSerialPort.cs b/ConsoleTest/Util/PortUtil/YcSerialPort.cs new file mode 100644 index 0000000..07b8378 --- /dev/null +++ b/ConsoleTest/Util/PortUtil/YcSerialPort.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Linq; +using System.Text.RegularExpressions; + +namespace ConsoleTest.Util.PortUtil +{ + /// + /// 串口类 + /// + public class YcSerialPort + { + private SerialPort _port;//声明一个串口 + private readonly SerialPortParam _param; + + public long RecCount { get; set; }//接收计数 + + public long SendCount { get; set; }//发送计数 + + public YcSerialPort() + { + } + + public YcSerialPort(SerialPortParam param) + { + _param = param; + } + + /// + /// 打开串口 + /// + /// + public bool OpenCom() + { + if (IsOpen()) + CloseCom(); + if (string.IsNullOrEmpty(_param.ComName)) + throw new Exception("请插入串口设备!"); + + _port = new SerialPort + { + PortName = _param.ComName,//串口名 + BaudRate = _param.BaudRate,//波特率 + DataBits = _param.DataBits,//数据位 + Parity = (Parity)_param.Parity,//奇偶校验0-4=no,odd,even,mark,space + StopBits = (StopBits)Convert.ToInt32(_param.StopBits),//停止位 + ReadTimeout = 500,//读超时 + WriteTimeout = 2000,//写超时 + //ReadBufferSize = 1024, + //WriteBufferSize = 1024, + ReceivedBytesThreshold = _param.ReceivedBytesThreshold,//128Byte时触发一次事件,设置为1时易造成线程死锁。 + RtsEnable = true, + DtrEnable = true, + }; + _port.DataReceived += RecData; + //port.DataReceived += new SerialDataReceivedEventHandler(Comm_DataReceived); + _port.Open(); + return IsOpen(); + } + + /// + /// 关闭串口 + /// + public bool CloseCom() + { + if (IsOpen()) + { + _port.Close(); + _port = null; + } + return !IsOpen(); + } + + public bool IsOpen() + { + if (_port == null) + return false; + if (!_port.IsOpen) + return false; + return true; + } + + public event EventHandler OnRecData; //定义一个委托类型的事件 + + private void RecData(object sender, EventArgs e) + { + var count = _port.BytesToRead;//获取缓存区字节数 + var buf = new byte[count];//存储串口数据用 + _port.Read(buf, 0, count);//读取缓冲数据 + RecCount += count;//接收计数 + OnRecData?.Invoke(this, buf); + } + + /// + /// 发送 Ascii + /// + /// + /// + public void SendAscii(string text, bool newLine = false) + { + //定义一个变量,记录发送了几个字节 + int count; + + if (newLine) + { + _port.Write(text + "\r\n"); + count = text.Length + 2; + } + else//不包含换行符 + { + _port.Write(text); + count = text.Length; + } + + SendCount += count;//累加发送字节数 + } + + /// + /// 发送 Hex + /// + /// + /// + public void SendHex(string text, bool newLine = false) + { + int count;//定义一个变量,记录发送了几个字节 + var mc = Regex.Matches(text, @"(?i)[\da-f]{2}");//正则得到有效的十六进制数(?i)对大小写不敏感,[/da-f],{2}连续出现2次 + var buf = new List();//填充到这个临时列表中 + foreach (Match m in mc) + { + buf.Add(byte.Parse(m.Value, System.Globalization.NumberStyles.HexNumber));//依次添加到列表中 + } + _port.Write(buf.ToArray(), 0, buf.Count);//转换列表为数组后发送 + if (newLine) + { + _port.Write("\r\n"); + count = buf.Count + 2; + } + else//不包含换行符 + { + count = buf.Count; + } + + SendCount += count;//累加发送字节数 + } + + /// + /// 发送 Hex + /// + /// + /// + public void SendHex(byte[] buf, bool newline = false) + { + int count;//定义一个变量,记录发送了几个字节 + var bufLen = buf.Count(); + _port.Write(buf, 0, bufLen); + if (newline) + { //记录发送的字节数 + _port.WriteLine("\n"); + count = bufLen + 2; + } + else + { + count = bufLen; + } + + SendCount += count;//累加发送字节数 + } + } +} \ No newline at end of file diff --git a/ConsoleTest/data/image/logo.bmp b/ConsoleTest/data/image/logo.bmp new file mode 100644 index 0000000..b0300d2 Binary files /dev/null and b/ConsoleTest/data/image/logo.bmp differ diff --git a/ConsoleTest/data/light/lightCode.json b/ConsoleTest/data/light/lightCode.json new file mode 100644 index 0000000..b4da165 --- /dev/null +++ b/ConsoleTest/data/light/lightCode.json @@ -0,0 +1,7 @@ +{ + "CtrlAllLightCodeList": [ "", "3301140000000048", "3301130000000047" ], + "OpenLightCodeList": [ "", "3301120000000147", "3301120000000248", "3301120000000349", "330112000000044A" ], + "CloseLightCodeList": [ "", "3301110000000146", "3301110000000247", "3301110000000348", "3301110000000449" ], + "LockLightOnCodeList": [ "", "33011500000E045B", "33011500000D045A", "33011500000B0458", "3301150000070454" ], + "LockLightOffCodeList": [ "", "330115000001044E", "330115000002044F", "3301150000040451", "3301150000080455" ] +} \ No newline at end of file diff --git a/ConsoleTest/data/light/lightCode2.json b/ConsoleTest/data/light/lightCode2.json new file mode 100644 index 0000000..b39b98b --- /dev/null +++ b/ConsoleTest/data/light/lightCode2.json @@ -0,0 +1,7 @@ +{ + "CtrlAllLightCodeList": [ "", "01108050000204020F0804A0ED", "011080500002040200080490EE" ], + "OpenLightCodeList": [ "", "01050000FF008C3A", "01050001FF00DDFA", "01050002FF002DFA", "01050003FF007C3A" ], + "CloseLightCodeList": [ "", "010500000000CDCA", "0105000100009C0A", "0105000200006C0A", "0105000300003DCA" ], + "LockLightOnCodeList": [ "", "0110805000020402010804C12E", "0110805000020402020804312E", "0110805000020402040804D12F", "0110805000020402080804112C" ], + "LockLightOffCodeList": [ "", "01108050000204020E0804F12D", "01108050000204020D0804012D", "01108050000204020B0804E12C", "0110805000020402070804212F" ] +} \ No newline at end of file diff --git a/ConsoleTest/data/light/lightCode3.json b/ConsoleTest/data/light/lightCode3.json new file mode 100644 index 0000000..5e39467 --- /dev/null +++ b/ConsoleTest/data/light/lightCode3.json @@ -0,0 +1,7 @@ +{ + "CtrlAllLightCodeList": [ "", "010F0500000401003EC3", "010F05000004010F7EC7" ], + "OpenLightCodeList": [ "" ], + "CloseLightCodeList": [ "" ], + "LockLightOnCodeList": [ "", "010F050000040101FF03", "010F050000040102BF02", "010F0500000401043F00", "010F0500000401083F05" ], + "LockLightOffCodeList": [ "", "010F05000004010EBF07", "010F05000004010DFF06", "010F05000004010B7F04", "010F0500000401077F01" ] +} \ No newline at end of file diff --git a/ConsoleTest/data/light/lightCodeTemplate.json b/ConsoleTest/data/light/lightCodeTemplate.json new file mode 100644 index 0000000..2a790d0 --- /dev/null +++ b/ConsoleTest/data/light/lightCodeTemplate.json @@ -0,0 +1,12 @@ +{ + // �������еƱ��룬1 Ϊ�������еƣ�2 Ϊ�ر����е� + "CtrlAllLightCodeList": [ "" ], + // ����ijһ·�Ʊ��룬�����⣬index �����Ӧ + "OpenLightCodeList": [ "" ], + // �ر�ijһ·�Ʊ��룬������,index �����Ӧ + "CloseLightCodeList": [ "" ], + // �������룬����ֻ��һ·������index �����Ӧ + "LockLightOnCodeList": [ "" ], + // �������룬����ֻ��һ·����index �����Ӧ + "LockLightOffCodeList": [ "" ] +} \ No newline at end of file diff --git a/ConsoleTest/data/test.config b/ConsoleTest/data/test.config new file mode 100644 index 0000000..17b4fea --- /dev/null +++ b/ConsoleTest/data/test.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ConsoleTest/dll/Led5kSDK.dll b/ConsoleTest/dll/Led5kSDK.dll new file mode 100644 index 0000000..12d4fc5 Binary files /dev/null and b/ConsoleTest/dll/Led5kSDK.dll differ diff --git a/ConsoleTest/dll/TesoLive.dll b/ConsoleTest/dll/TesoLive.dll new file mode 100644 index 0000000..9124ea5 Binary files /dev/null and b/ConsoleTest/dll/TesoLive.dll differ diff --git a/ConsoleTest/packages.config b/ConsoleTest/packages.config new file mode 100644 index 0000000..06f8874 --- /dev/null +++ b/ConsoleTest/packages.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/EC.Helper/CameraSDK/Common/CameraException.cs b/EC.Helper/CameraSDK/Common/CameraException.cs new file mode 100644 index 0000000..7b4853c --- /dev/null +++ b/EC.Helper/CameraSDK/Common/CameraException.cs @@ -0,0 +1,54 @@ +namespace EC.Helper.CameraSDK; + +/// +/// 相机异常 +/// +public class CameraException : Exception +{ + public CameraException() : base() + { + } + + public CameraException(string? message) : base(message) + { + } + + public CameraException(string? message, Exception? innerException) : base(message, innerException) + { + } + + protected class CameraExceptionObj + { + public CameraType Type { get; set; } + + public int ErrCode { get; set; } + + public string? ErrMsg { get; set; } + + public override string? ToString() + { + return $"Type:{Type}, ErrCode:{ErrCode}, ErrMsg:{ErrMsg}"; + } + } + + public static CameraException New(CameraType type, int errCode) + { + CameraExceptionObj obj = new() + { + Type = type, + ErrCode = errCode + }; + return new CameraException(obj.ToString()); + } + + public static CameraException New(CameraType type, int errCode, string errMsg) + { + CameraExceptionObj obj = new() + { + Type = type, + ErrCode = errCode, + ErrMsg = errMsg + }; + return new CameraException(obj.ToString()); + } +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/Common/CameraStruct.cs b/EC.Helper/CameraSDK/Common/CameraStruct.cs new file mode 100644 index 0000000..28b4ead --- /dev/null +++ b/EC.Helper/CameraSDK/Common/CameraStruct.cs @@ -0,0 +1,111 @@ +namespace EC.Helper.CameraSDK; + +/// +/// 相机信息 +/// +public class CameraInfo +{ + #region Attr + + /// + /// 相机类型 + /// + public int Type { get; set; } + + /// + /// ip 地址 + /// + public string Ip { get; set; } = string.Empty; + + /// + /// 端口 + /// + public int Port { get; set; } + + /// + /// 账号 + /// + public string UserName { get; set; } = string.Empty; + + /// + /// 密码 + /// + public string Password { get; set; } = string.Empty; + + #endregion Attr + + public static CameraInfo New(int type, string ip, int port, string userName, string password) + { + CameraInfo info = new() { Type = type, Ip = ip, Port = port, UserName = userName, Password = password }; + if (port <= 0) + throw new Exception("Camera type not support."); + return info; + } + + public static CameraInfo New(int type, string ip, string userName, string password) + { + CameraInfo info = new() { Type = type, Ip = ip, UserName = userName, Password = password }; + int port = (CameraType)type switch + { + CameraType.HiK => CameraPort.HiK, + CameraType.DaHua => CameraPort.DaHua, + CameraType.YuShi => CameraPort.YuShi, + _ => -1, + }; + info.Port = port; + if (port <= 0) + throw new Exception("Camera type not support."); + return info; + } +} + +/// +/// 相机类型 +/// +public enum CameraType +{ + HiK = 0, + DaHua = 1, + YuShi = 2, +} + +/// +/// 相机默认连接端口 +/// +public class CameraPort +{ + public const int HiK = 8000; + public const int DaHua = 37777; + public const int YuShi = 8800; +} + +/// +/// Ptz 信息 +/// +public class PtzInfo +{ + #region Attr + + public double Pan { get; set; } + public double Tilt { get; set; } + public double Zoom { get; set; } + + #endregion Attr + + public PtzInfo(double pan, double tilt, double zoom) + { + Pan = pan; + Tilt = tilt; + Zoom = zoom; + } + + public static PtzInfo Default + { + get { return new(0, 0, 0); } + } + + public static PtzInfo New(double pan, double tilt, double zoom) + { + return new PtzInfo(pan, tilt, zoom); + } +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/Common/ICameraSDK.cs b/EC.Helper/CameraSDK/Common/ICameraSDK.cs new file mode 100644 index 0000000..703d290 --- /dev/null +++ b/EC.Helper/CameraSDK/Common/ICameraSDK.cs @@ -0,0 +1,58 @@ +namespace EC.Helper.CameraSDK; + +public abstract class ICameraSDK +{ + #region Attr + + protected CameraInfo CameraInfo { get; set; } + + #endregion Attr + + public ICameraSDK(CameraInfo cameraInfo) + { + CameraInfo = cameraInfo; + } + + #region Base Method + + /// + /// 初始化资源 + /// + /// + public abstract bool Init(); + + /// + /// 释放资源 + /// + /// + public abstract bool Destory(); + + /// + /// 连接是否成功 + /// + /// + public abstract bool ConnectSuccess(); + + /// + /// 构建异常 + /// + public abstract void BuildException(); + + #endregion Base Method + + #region Main Method + + /// + /// 获取 ptz + /// + /// + public abstract PtzInfo GetPtzInfo(); + + /// + /// 获取 ptz + /// + /// + public abstract bool TryGetPtzInfo(out PtzInfo ptzInfo); + + #endregion Main Method +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/DaHua/DaHuaOriSDK.cs b/EC.Helper/CameraSDK/DaHua/DaHuaOriSDK.cs new file mode 100644 index 0000000..0d1154c --- /dev/null +++ b/EC.Helper/CameraSDK/DaHua/DaHuaOriSDK.cs @@ -0,0 +1,848 @@ +//#define Linux32 +//#define Linux64 +//#define Win32 +//#define Win64 + +using System.Runtime.InteropServices; + +namespace EC.Helper.CameraSDK; + +public static class DaHuaOriSDK +{ + #region Lib Attr + +#if (Linux32) + private const string LibDhNetSDK = @"./libs/dahua/linux32/libdhnetsdk.so"; +#elif (Linux64) + private const string LibDhNetSDK = @"./libs/dahua/linux64/libdhnetsdk.so"; +#elif (Win32) + private const string LibDhNetSDK = @"./libs/dahua/win32/dhnetsdk.dll"; +#elif (Win64) + private const string LibDhNetSDK = @"./libs/dahua/win64/dhnetsdk.dll"; +#endif + + #endregion Lib Attr + + static DaHuaOriSDK() + { + GlobalInit(); + } + + #region Global + + public static bool InitSuccess { get; private set; } + + public static bool GlobalInit() + { + if (InitSuccess) return true; + bool ret = CLIENT_InitEx(null, IntPtr.Zero, IntPtr.Zero); + InitSuccess = ret; + if (!ret) throw new Exception("DaHuaOriSDK global init failure."); + return ret; + } + + public static bool GlobalDestory() + { + if (!InitSuccess) return true; + CLIENT_Cleanup(); + InitSuccess = false; + return true; + } + + #endregion Global + + #region SDK Enum + + /// + /// login device mode enumeration + /// 登陆设备方式枚举 + /// + public enum EM_LOGIN_SPAC_CAP_TYPE + { + /// + /// TCP login, default + /// TCP登陆, 默认方式 + /// + TCP = 0, + + /// + /// No criteria login + /// 无条件登陆 + /// + ANY = 1, + + /// + /// auto sign up login + /// 主动注册的登入 + /// + SERVER_CONN = 2, + + /// + /// multicast login, default + /// 组播登陆 + /// + MULTICAST = 3, + + /// + /// UDP method login + /// UDP方式下的登入 + /// + UDP = 4, + + /// + /// only main connection login + /// 只建主连接下的登入 + /// + MAIN_CONN_ONLY = 6, + + /// + /// SSL encryption login + /// SSL加密方式登陆 + /// + SSL = 7, + + /// + /// login IVS box remote device + /// 登录智能盒远程设备 + /// + INTELLIGENT_BOX = 9, + + /// + /// login device do not config + /// 登录设备后不做取配置操作 + /// + NO_CONFIG = 10, + + /// + /// USB key device login + /// 用U盾设备的登入 + /// + U_LOGIN = 11, + + /// + /// LDAP login + /// LDAP方式登录 + /// + LDAP = 12, + + /// + /// AD login + /// AD(ActiveDirectory)登录方式 + /// + AD = 13, + + /// + /// Radius login + /// Radius 登录方式 + /// + RADIUS = 14, + + /// + /// Socks5 login + /// Socks5登陆方式 + /// + SOCKET_5 = 15, + + /// + /// cloud login + /// 云登陆方式 + /// + CLOUD = 16, + + /// + /// dual authentication loin + /// 二次鉴权登陆方式 + /// + AUTH_TWICE = 17, + + /// + /// TS stream client login + /// TS码流客户端登陆方式 + /// + TS = 18, + + /// + /// web private login + /// 为P2P登陆方式 + /// + P2P = 19, + + /// + /// mobile client login + /// 手机客户端登陆 + /// + MOBILE = 20, + + /// + /// invalid login + /// 无效的登陆方式 + /// + INVALID = 21, + } + + /// + /// device type enumeration + /// 设备类型枚举 + /// + public enum EM_NET_DEVICE_TYPE + { + /// + /// Unknow + // 未知 + /// + NET_PRODUCT_NONE = 0, + + /// + /// Non real-time MACE + /// 非实时MACE + /// + NET_DVR_NONREALTIME_MACE, + + /// + /// Non real-time + /// 非实时 + /// + NET_DVR_NONREALTIME, + + /// + /// Network video server + /// 网络视频服务器 + /// + NET_NVS_MPEG1, + + /// + /// MPEG1 2-ch DVR + /// MPEG1二路录像机 + /// + NET_DVR_MPEG1_2, + + /// + /// MPEG1 8-ch DVR + /// MPEG1八路录像机 + /// + NET_DVR_MPEG1_8, + + /// + /// MPEG4 8-ch DVR + /// MPEG4八路录像机 + /// + NET_DVR_MPEG4_8, + + /// + /// MPEG4 16-ch DVR + /// MPEG4 十六路录像机 + /// + NET_DVR_MPEG4_16, + + /// + /// LB series DVR + /// LB系列录像机 + /// + NET_DVR_MPEG4_SX2, + + /// + /// GB series DVR + /// GB系列录像机 + /// + NET_DVR_MEPG4_ST2, + + /// + /// HB series DVR + /// HB系列录像机 + /// + NET_DVR_MEPG4_SH2, + + /// + /// GBE series DVR + /// GBE系列录像机 + /// + NET_DVR_MPEG4_GBE, + + /// + /// II network video server + /// II代网络视频服务器 + /// + NET_DVR_MPEG4_NVSII, + + /// + /// New standard configuration protocol + /// 新标准配置协议 + /// + NET_DVR_STD_NEW, + + /// + /// DDNS server + /// DDNS服务器 + /// + NET_DVR_DDNS, + + /// + /// ATM series + /// ATM机 + /// + NET_DVR_ATM, + + /// + /// 2nd non real-time NB series DVR + /// 二代非实时NB系列机器 + /// + NET_NB_SERIAL, + + /// + /// LN series + /// LN系列产品 + /// + NET_LN_SERIAL, + + /// + /// BAV series + /// BAV系列产品 + /// + NET_BAV_SERIAL, + + /// + /// SDIP series + /// SDIP系列产品 + /// + NET_SDIP_SERIAL, + + /// + /// IPC series + /// IPC系列产品 + /// + NET_IPC_SERIAL, + + /// + /// NVS B series + /// NVS B系列 + /// + NET_NVS_B, + + /// + /// NVS H series + /// NVS H系列 + /// + NET_NVS_C, + + /// + /// NVS S series + /// NVS S系列 + /// + NET_NVS_S, + + /// + /// NVS E series + /// NVS E系列 + /// + NET_NVS_E, + + /// + /// Search device type from QueryDevState. it is in string format + /// 从QueryDevState中查询设备类型,以字符串格式 + /// + NET_DVR_NEW_PROTOCOL, + + /// + /// NVD + /// 解码器 + /// + NET_NVD_SERIAL, + + /// + /// N5 + /// N5 + /// + NET_DVR_N5, + + /// + /// HDVR + /// 混合DVR + /// + NET_DVR_MIX_DVR, + + /// + /// SVR series + /// SVR系列 + /// + NET_SVR_SERIAL, + + /// + /// SVR-BS + /// SVR-BS + /// + NET_SVR_BS, + + /// + /// NVR series + /// NVR系列 + /// + NET_NVR_SERIAL, + + /// + /// N51 + /// N51 + /// + NET_DVR_N51, + + /// + /// ITSE Intelligent Analysis Box + /// ITSE 智能分析盒 + /// + NET_ITSE_SERIAL, + + /// + /// Intelligent traffic camera equipment + /// 智能交通像机设备 + /// + NET_ITC_SERIAL, + + /// + /// radar speedometer HWS + /// 雷达测速仪HWS + /// + NET_HWS_SERIAL, + + /// + /// portable video record + /// 便携式音视频录像机 + /// + NET_PVR_SERIAL, + + /// + /// IVS(intelligent video server series) + /// IVS(智能视频服务器系列) + /// + NET_IVS_SERIAL, + + /// + /// universal intelligent detect video server series + /// 通用智能视频侦测服务器 + /// + NET_IVS_B, + + /// + /// face recognisation server + /// 人脸识别服务器 + /// + NET_IVS_F, + + /// + /// video quality diagnosis server + /// 视频质量诊断服务器 + /// + NET_IVS_V, + + /// + /// matrix + /// 矩阵 + /// + NET_MATRIX_SERIAL, + + /// + /// N52 + /// N52 + /// + NET_DVR_N52, + + /// + /// N56 + /// N56 + /// + NET_DVR_N56, + + /// + /// ESS + /// ESS + /// + NET_ESS_SERIAL, + + /// + /// 人数统计服务器 + /// + NET_IVS_PC, + + /// + /// pc-nvr + /// pc-nvr + /// + NET_PC_NVR, + + /// + /// screen controller + /// 大屏控制器 + /// + NET_DSCON, + + /// + /// network video storage server + /// 网络视频存储服务器 + /// + NET_EVS, + + /// + /// an embedded intelligent video analysis system + /// 嵌入式智能分析视频系统 + /// + NET_EIVS, + + /// + /// DVR-N6 + /// DVR-N6 + /// + NET_DVR_N6, + + /// + /// K-Lite Codec Pack + /// 万能解码器 + /// + NET_UDS, + + /// + /// Bank alarm host + /// 银行报警主机 + /// + NET_AF6016, + + /// + /// Video network alarm host + /// 视频网络报警主机 + /// + NET_AS5008, + + /// + /// Network alarm host + /// 网络报警主机 + /// + NET_AH2008, + + /// + /// Alarm host series + /// 报警主机系列 + /// + NET_A_SERIAL, + + /// + /// Access control series of products + /// 门禁系列产品 + /// + NET_BSC_SERIAL, + + /// + /// NVS series product + /// NVS系列产品 + /// + NET_NVS_SERIAL, + + /// + /// VTO series product + /// VTO系列产品 + /// + NET_VTO_SERIAL, + + /// + /// VTNC series product + /// VTNC系列产品 + /// + NET_VTNC_SERIAL, + + /// + /// TPC series product, it is the thermal device + /// TPC系列产品, 即热成像设备 + /// + NET_TPC_SERIAL, + + /// + /// ASM series product + /// 无线中继设备 + /// + NET_ASM_SERIAL, + + /// + /// VTS series product + /// 管理机 + /// + NET_VTS_SERIAL, + + /// + /// Alarm host-ARC2016C + /// 报警主机ARC2016C + /// + NET_ARC2016C, + + /// + /// ASA Attendance machine + /// 考勤机 + /// + NET_ASA, + + /// + /// Industry terminal walkie-talkie + /// 行业对讲终端 + /// + NET_VTT_SERIAL, + + /// + /// Alarm column + /// 报警柱 + /// + NET_VTA_SERIAL, + + /// + /// SIP Server + /// SIP服务器 + /// + NET_VTNS_SERIAL, + + /// + /// Indoor unit + /// 室内机 + /// + NET_VTH_SERIAL, + } + + /// + /// 查询设备信息参数 + /// + public enum EM_DEVICE_STATE + { + /// + /// Query device online state(return a DWORD value, 1-online, 0-offline) + /// 查询设备的在线状态(返回一个DWORD, 1表示在线, 0表示断线) + /// + ONLINE = 0x0035, + + /// + /// Query ptz state(struct DH_PTZ_LOCATION_INFO) + /// 查询云台状态信息(对应结构体 DH_PTZ_LOCATION_INFO) + /// + PTZ_LOCATION = 0x0036, + } + + /// + /// 预置点状态枚举 + /// + public enum EM_DH_PTZ_PRESET_STATUS + { + UNKNOWN, // 未知 + REACH, // 预置点到达 + UNREACH, // 预置点未到达 + } + + #endregion SDK Enum + + #region SDK Struct + + /// + /// CLIENT_LoginWithHighLevelSecurity 输入参数 + /// + public struct NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY + { + public uint dwSize;// 结构体大小 + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] + public string szIP; // IP + + public int nPort; // 端口 + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] + public string szUserName; // 用户名 + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] + public string szPassword; // 密码 + + public EM_LOGIN_SPAC_CAP_TYPE emSpecCap; // 登录模式 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] byReserved; // 字节对齐 + + public IntPtr pCapParam; // 见 CLIENT_LoginEx 接口 pCapParam 与 nSpecCap 关系 + } + + /// + /// device information structure + /// 设备信息结构体 + /// + public struct NET_DEVICEINFO_Ex + { + /// + /// serial number + /// 序列号 + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] + public string sSerialNumber; + + /// + /// count of alarm input + /// 报警输入个数 + /// + public int nAlarmInPortNum; + + /// + /// count of alarm output + /// 报警输出个数 + /// + public int nAlarmOutPortNum; + + /// + /// number of disk + /// 硬盘个数 + /// + public int nDiskNum; + + /// + /// device type, refer to EM_NET_DEVICE_TYPE + /// 设备类型,见枚举NET_DEVICE_TYPE + /// + public EM_NET_DEVICE_TYPE nDVRType; + + /// + /// number of channel + /// 通道个数 + /// + public int nChanNum; + + /// + /// Online Timeout, Not Limited Access to 0, not 0 Minutes Limit Said + /// 在线超时时间,为0表示不限制登陆,非0表示限制的分钟数 + /// + public byte byLimitLoginTime; + + /// + /// When login failed due to password error, notice user by this parameter.This parameter is invalid when remaining login times is zero + /// 当登陆失败原因为密码错误时,通过此参数通知用户,剩余登陆次数,为0时表示此参数无效 + /// + public byte byLeftLogTimes; + + /// + /// keep bytes for aligned + /// 保留字节,字节对齐 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] + public byte[] bReserved; + + /// + /// when log in failed,the left time for users to unlock (seconds), -1 indicate the device haven't set the parameter + /// 当登陆失败,用户解锁剩余时间(秒数), -1表示设备未设置该参数 + /// + public int nLockLeftTime; + + /// + /// reserved + /// 保留字节 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] + public byte[] Reserved; + } + + /// + /// CLIENT_LoginWithHighLevelSecurity 输出参数 + /// + public struct NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY + { + public uint dwSize;// 结构体大小 + public NET_DEVICEINFO_Ex stuDeviceInfo; // 设备信息 + public int nError; // 错误码,见 CLIENT_Login 接口错误码 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 132)] + public byte[] byReserved; // 保留字节 + } + + /// + /// 云台定位中非归一化坐标和变倍 + /// + public struct NET_PTZSPACE_UNNORMALIZED + { + public int nPosX; // x坐标 + public int nPosY; // y坐标 + public int nZoom; // 放大倍率 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 52)] + public byte[] byReserved; // 预留字节 + } + + /// + /// 云台定位信息 + /// + //云台定位信息 + public struct DH_PTZ_LOCATION_INFO + { + public int nChannelID; // 通道号 + public int nPTZPan; // 云台水平运动位置,有效范围:[0,3600] + public int nPTZTilt; // 云台垂直运动位置,有效范围:[-1800,1800] + public int nPTZZoom; // 云台光圈变动位置,有效范围:[0,128] + public byte bState; // 云台运动状态, 0-未知 1-运动 2-空闲 + public byte bAction; // 云台动作,255-未知,0-预置点,1-线扫,2-巡航,3-巡迹,4-水平旋转,5-普通移动,6-巡迹录制,7-全景云台扫描,8-热度图 + + // 9-精确定位,10-设备校正,11-智能配置,12-云台重启 + public byte bFocusState; // 云台聚焦状态, 0-未知, 1-运动状态, 2-空闲 + + public byte bEffectiveInTimeSection; // 在时间段内预置点状态是否有效 + + //如果当前上报的预置点是时间段内的预置点,则为1,其他情况为0 + public int nPtzActionID; // 巡航ID号 + + public uint dwPresetID; // 云台所在预置点编号 + public float fFocusPosition; // 聚焦位置 + public byte bZoomState; // 云台ZOOM状态,0-未知,1-ZOOM,2-空闲 + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] + public byte[] bReserved; // 对齐 + + public uint dwSequence; // 包序号,用于校验是否丢包 + public uint dwUTC; // 对应的UTC(1970-1-1 00:00:00)秒数。 + public EM_DH_PTZ_PRESET_STATUS emPresetStatus; // 预置点位置 + + /// + /// 保留字段 + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 248)] + public int[] reserved; + }; + + #endregion SDK Struct + + #region Common Method + + /// + /// network disconnection callback function original shape + /// 断线回调函数 + /// + /// user LoginID:Login's returns value 登陆ID + /// device IP 设备IP + /// device prot 设备端口 + /// user data from Init function 用户数据 + public delegate void fDisConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser); + + /// + /// network re-connection callback function original shape + /// 重连回调函数 + /// + /// user LoginID:Login's returns value 登陆ID + /// device IP,string type 设备IP + /// device prot 设备端口 + /// user data from SetAutoReconnect function 用户数据 + public delegate void fHaveReConnectCallBack(IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser); + + [DllImport(LibDhNetSDK)] + public static extern bool CLIENT_InitEx(fDisConnectCallBack? cbDisConnect, IntPtr dwUser, IntPtr lpInitParam); + + [DllImport(LibDhNetSDK)] + public static extern void CLIENT_Cleanup(); + + [DllImport(LibDhNetSDK)] + public static extern int CLIENT_GetLastError(); + + [DllImport(LibDhNetSDK)] + public static extern IntPtr CLIENT_LoginWithHighLevelSecurity(ref NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY pstInParam, ref NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam); + + [DllImport(LibDhNetSDK)] + public static extern bool CLIENT_Logout(IntPtr lLoginID); + + [DllImport(LibDhNetSDK)] + public static extern void CLIENT_SetAutoReconnect(fHaveReConnectCallBack cbAutoConnect, IntPtr dwUser); + + [DllImport(LibDhNetSDK)] + public static extern bool CLIENT_QueryDevState(IntPtr lLoginID, int nType, IntPtr pBuf, int nBufLen, ref int pRetLen, int waittime); + + #endregion Common Method +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/DaHua/DaHuaSDK.cs b/EC.Helper/CameraSDK/DaHua/DaHuaSDK.cs new file mode 100644 index 0000000..fd3a94d --- /dev/null +++ b/EC.Helper/CameraSDK/DaHua/DaHuaSDK.cs @@ -0,0 +1,137 @@ +using System.Runtime.InteropServices; + +namespace EC.Helper.CameraSDK; + +public class DaHuaSDK : ICameraSDK +{ + #region Attr + + private IntPtr LoginId { get; set; } = IntPtr.Zero; + + #endregion Attr + + public DaHuaSDK(CameraInfo cameraInfo) : base(cameraInfo) + { + } + + #region Base Method + + public override bool Init() + { + bool ret = ConnectSuccess(); + if (ret) return true; + + DaHuaOriSDK.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY stuInParam = new(); + stuInParam.dwSize = (uint)Marshal.SizeOf(stuInParam); + stuInParam.szIP = CameraInfo.Ip; + stuInParam.nPort = CameraInfo.Port; + stuInParam.szUserName = CameraInfo.UserName; + stuInParam.szPassword = CameraInfo.Password; + stuInParam.emSpecCap = DaHuaOriSDK.EM_LOGIN_SPAC_CAP_TYPE.TCP; + stuInParam.pCapParam = IntPtr.Zero; + DaHuaOriSDK.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY stuOutParam = new(); + stuOutParam.dwSize = (uint)Marshal.SizeOf(stuOutParam); + LoginId = DaHuaOriSDK.CLIENT_LoginWithHighLevelSecurity(ref stuInParam, ref stuOutParam); + ret = ConnectSuccess(); + if (ret) DaHuaOriSDK.CLIENT_SetAutoReconnect(delegate (IntPtr lLoginID, IntPtr pchDVRIP, int nDVRPort, IntPtr dwUser) + { + LoginId = lLoginID; + }, IntPtr.Zero); + + return ret; + } + + public override bool Destory() + { + bool ret = ConnectSuccess(); + if (!ret) return true; + + ret = DaHuaOriSDK.CLIENT_Logout(LoginId); + if (ret) LoginId = IntPtr.Zero; + + return ret; + } + + public override bool ConnectSuccess() + { + return LoginId != IntPtr.Zero; + } + + public override void BuildException() + { + uint errCode = (uint)DaHuaOriSDK.CLIENT_GetLastError(); + if (errCode == 0) return; + errCode -= 0x80000000; + throw CameraException.New(CameraType.DaHua, (int)errCode); + } + + #endregion Base Method + + #region Main Method + + private static class GPIParams + { + public static int Size { get; private set; } + public static Type Type { get; private set; } + + static GPIParams() + { + DaHuaOriSDK.DH_PTZ_LOCATION_INFO info = new(); + Size = Marshal.SizeOf(info); + Type = info.GetType(); + } + } + + public override PtzInfo GetPtzInfo() + { + bool ret = ConnectSuccess(); + if (!ret) return PtzInfo.Default; + + DaHuaOriSDK.DH_PTZ_LOCATION_INFO entity = new(); + int nBufLen = GPIParams.Size; + int pRetLen = 0; + IntPtr ptrBuf = Marshal.AllocHGlobal(GPIParams.Size); + Marshal.StructureToPtr(entity, ptrBuf, true); + try + { + ret = DaHuaOriSDK.CLIENT_QueryDevState(LoginId, (int)DaHuaOriSDK.EM_DEVICE_STATE.PTZ_LOCATION, ptrBuf, nBufLen, ref pRetLen, 3000); + if (!ret) { BuildException(); return PtzInfo.Default; } + object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type); + if (objBuf == null) return PtzInfo.Default; + entity = (DaHuaOriSDK.DH_PTZ_LOCATION_INFO)objBuf; + return PtzInfo.New(entity.nPTZPan, entity.nPTZTilt, entity.nPTZZoom); + } + finally + { + Marshal.FreeHGlobal(ptrBuf); + } + } + + public override bool TryGetPtzInfo(out PtzInfo ptzInfo) + { + bool ret = ConnectSuccess(); + if (!ret) { ptzInfo = PtzInfo.Default; return false; } + + DaHuaOriSDK.DH_PTZ_LOCATION_INFO entity = new(); + int nBufLen = GPIParams.Size; + int pRetLen = 0; + IntPtr ptrBuf = Marshal.AllocHGlobal(GPIParams.Size); + Marshal.StructureToPtr(entity, ptrBuf, true); + try + { + ret = DaHuaOriSDK.CLIENT_QueryDevState(LoginId, (int)DaHuaOriSDK.EM_DEVICE_STATE.PTZ_LOCATION, ptrBuf, nBufLen, ref pRetLen, 3000); + if (!ret) { BuildException(); ptzInfo = PtzInfo.Default; return false; } + object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type); + if (objBuf == null) { ptzInfo = PtzInfo.Default; return false; } + entity = (DaHuaOriSDK.DH_PTZ_LOCATION_INFO)objBuf; + ptzInfo = PtzInfo.New(entity.nPTZPan, entity.nPTZTilt, entity.nPTZZoom); + return true; + } + finally + { + Marshal.FreeHGlobal(ptrBuf); + } + } + + #endregion Main Method +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/HiK/HiKOriSDK.cs b/EC.Helper/CameraSDK/HiK/HiKOriSDK.cs new file mode 100644 index 0000000..8d3a435 --- /dev/null +++ b/EC.Helper/CameraSDK/HiK/HiKOriSDK.cs @@ -0,0 +1,226 @@ +//#define Linux32 +//#define Linux64 +//#define Win32 +//#define Win64 + +using System.Runtime.InteropServices; + +namespace EC.Helper.CameraSDK; + +public static class HiKOriSDK +{ + #region Lib Attr + +#if (Linux32) + public const string LibHcNetSDK = @"./libs/hik/linux32/libhcnetsdk.so"; +#elif (Linux64) + public const string LibHcNetSDK = @"./libs/hik/linux64/libhcnetsdk.so"; +#elif (Win32) + public const string LibHcNetSDK = @"./libs/hik/win32/HCNetSDK.dll"; +#elif (Win64) + public const string LibHcNetSDK = @"./libs/hik/win64/HCNetSDK.dll"; +#endif + + #endregion Lib Attr + + static HiKOriSDK() + { + GlobalInit(); + } + + #region Global + + public static bool InitSuccess { get; private set; } + + public static bool GlobalInit() + { + if (InitSuccess) return true; + bool ret = NET_DVR_Init(); + InitSuccess = ret; + if (!ret) throw new Exception("HiKOriSDK global init failure."); + return ret; + } + + public static bool GlobalDestory() + { + if (!InitSuccess) return true; + bool ret = NET_DVR_Cleanup(); + if (ret) InitSuccess = false; + return ret; + } + + #endregion Global + + #region SDK Const + + public const int SERIALNO_LEN = 48; //序列号长度 + + #region 用于 NET_DVR_SetDVRConfig 和 NET_DVR_GetDVRConfig + + public const int NET_DVR_SET_PTZPOS = 292; //云台设置PTZ位置 + public const int NET_DVR_GET_PTZPOS = 293; //云台获取PTZ位置 + public const int NET_DVR_GET_PTZSCOPE = 294; //云台获取PTZ范围 + + #endregion 用于 NET_DVR_SetDVRConfig 和 NET_DVR_GetDVRConfig + + #endregion SDK Const + + #region SDK Struct + + //NET_DVR_Login()参数结构 + [StructLayoutAttribute(LayoutKind.Sequential)] + public struct NET_DVR_DEVICEINFO + { + [MarshalAsAttribute( + UnmanagedType.ByValArray, + SizeConst = SERIALNO_LEN, + ArraySubType = UnmanagedType.I1 + )] + public byte[] sSerialNumber; //序列号 + + public byte byAlarmInPortNum; //DVR报警输入个数 + public byte byAlarmOutPortNum; //DVR报警输出个数 + public byte byDiskNum; //DVR硬盘个数 + public byte byDVRType; //DVR类型, 1:DVR 2:ATM DVR 3:DVS ...... + public byte byChanNum; //DVR 通道个数 + public byte byStartChan; //起始通道号,例如DVS-1,DVR - 1 + } + + //NET_DVR_Login_V30()参数结构 + [StructLayoutAttribute(LayoutKind.Sequential)] + public struct NET_DVR_DEVICEINFO_V30 + { + [MarshalAsAttribute( + UnmanagedType.ByValArray, + SizeConst = SERIALNO_LEN, + ArraySubType = UnmanagedType.I1 + )] + public byte[] sSerialNumber; //序列号 + + public byte byAlarmInPortNum; //报警输入个数 + public byte byAlarmOutPortNum; //报警输出个数 + public byte byDiskNum; //硬盘个数 + public byte byDVRType; //设备类型, 1:DVR 2:ATM DVR 3:DVS ...... + public byte byChanNum; //模拟通道个数 + public byte byStartChan; //起始通道号,例如DVS-1,DVR - 1 + public byte byAudioChanNum; //语音通道数 + public byte byIPChanNum; //最大数字通道个数,低位 + public byte byZeroChanNum; //零通道编码个数 //2010-01-16 + public byte byMainProto; //主码流传输协议类型 0-private, 1-rtsp,2-同时支持private和rtsp + public byte bySubProto; //子码流传输协议类型0-private, 1-rtsp,2-同时支持private和rtsp + public byte bySupport; //能力,位与结果为0表示不支持,1表示支持, + + //bySupport & 0x1, 表示是否支持智能搜索 + //bySupport & 0x2, 表示是否支持备份 + //bySupport & 0x4, 表示是否支持压缩参数能力获取 + //bySupport & 0x8, 表示是否支持多网卡 + //bySupport & 0x10, 表示支持远程SADP + //bySupport & 0x20, 表示支持Raid卡功能 + //bySupport & 0x40, 表示支持IPSAN 目录查找 + //bySupport & 0x80, 表示支持rtp over rtsp + public byte bySupport1; // 能力集扩充,位与结果为0表示不支持,1表示支持 + + //bySupport1 & 0x1, 表示是否支持snmp v30 + //bySupport1 & 0x2, 支持区分回放和下载 + //bySupport1 & 0x4, 是否支持布防优先级 + //bySupport1 & 0x8, 智能设备是否支持布防时间段扩展 + //bySupport1 & 0x10, 表示是否支持多磁盘数(超过33个) + //bySupport1 & 0x20, 表示是否支持rtsp over http + //bySupport1 & 0x80, 表示是否支持车牌新报警信息2012-9-28, 且还表示是否支持NET_DVR_IPPARACFG_V40结构体 + public byte bySupport2; /*能力,位与结果为0表示不支持,非0表示支持 + + bySupport2 & 0x1, 表示解码器是否支持通过URL取流解码 + bySupport2 & 0x2, 表示支持FTPV40 + bySupport2 & 0x4, 表示支持ANR + bySupport2 & 0x8, 表示支持CCD的通道参数配置 + bySupport2 & 0x10, 表示支持布防报警回传信息(仅支持抓拍机报警 新老报警结构) + bySupport2 & 0x20, 表示是否支持单独获取设备状态子项 + bySupport2 & 0x40, 表示是否是码流加密设备*/ + public ushort wDevType; //设备型号 + public byte bySupport3; //能力集扩展,位与结果为0表示不支持,1表示支持 + + //bySupport3 & 0x1, 表示是否多码流 + // bySupport3 & 0x4 表示支持按组配置, 具体包含 通道图像参数、报警输入参数、IP报警输入、输出接入参数、 + // 用户参数、设备工作状态、JPEG抓图、定时和时间抓图、硬盘盘组管理 + //bySupport3 & 0x8为1 表示支持使用TCP预览、UDP预览、多播预览中的"延时预览"字段来请求延时预览(后续都将使用这种方式请求延时预览)。而当bySupport3 & 0x8为0时,将使用 "私有延时预览"协议。 + //bySupport3 & 0x10 表示支持"获取报警主机主要状态(V40)"。 + //bySupport3 & 0x20 表示是否支持通过DDNS域名解析取流 + + public byte byMultiStreamProto; //是否支持多码流,按位表示,0-不支持,1-支持,bit1-码流3,bit2-码流4,bit7-主码流,bit-8子码流 + public byte byStartDChan; //起始数字通道号,0表示无效 + public byte byStartDTalkChan; //起始数字对讲通道号,区别于模拟对讲通道号,0表示无效 + public byte byHighDChanNum; //数字通道个数,高位 + public byte bySupport4; + public byte byLanguageType; // 支持语种能力,按位表示,每一位0-不支持,1-支持 + + // byLanguageType 等于0 表示 老设备 + // byLanguageType & 0x1表示支持中文 + // byLanguageType & 0x2表示支持英文 + [MarshalAsAttribute( + UnmanagedType.ByValArray, + SizeConst = 9, + ArraySubType = UnmanagedType.I1 + )] + public byte[] byRes2; //保留 + } + + //球机位置信息 + [StructLayoutAttribute(LayoutKind.Sequential)] + public struct NET_DVR_PTZPOS + { + public ushort wAction; //获取时该字段无效 + public ushort wPanPos; //水平参数 + public ushort wTiltPos; //垂直参数 + public ushort wZoomPos; //变倍参数 + } + + //球机范围信息 + [StructLayoutAttribute(LayoutKind.Sequential)] + public struct NET_DVR_PTZSCOPE + { + public ushort wPanPosMin; //水平参数min + public ushort wPanPosMax; //水平参数max + public ushort wTiltPosMin; //垂直参数min + public ushort wTiltPosMax; //垂直参数max + public ushort wZoomPosMin; //变倍参数min + public ushort wZoomPosMax; //变倍参数max + } + + #endregion SDK Struct + + #region Common Method + + [DllImport(LibHcNetSDK)] + public static extern bool NET_DVR_Init(); + + [DllImport(LibHcNetSDK)] + public static extern bool NET_DVR_Cleanup(); + + [DllImport(LibHcNetSDK)] + public static extern uint NET_DVR_GetLastError(); + + [DllImport(LibHcNetSDK)] + public static extern int NET_DVR_Login_V30( + string sDVRIP, + int wDVRPort, + string sUserName, + string sPassword, + ref NET_DVR_DEVICEINFO_V30 lpDeviceInfo + ); + + [DllImport(LibHcNetSDK)] + public static extern bool NET_DVR_Logout(int iUserID); + + //参数配置 begin + [DllImport(LibHcNetSDK)] + public static extern bool NET_DVR_GetDVRConfig( + int lUserID, + uint dwCommand, + int lChannel, + IntPtr lpOutBuffer, + uint dwOutBufferSize, + ref uint lpBytesReturned + ); + + #endregion Common Method +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/HiK/HiKSDK.cs b/EC.Helper/CameraSDK/HiK/HiKSDK.cs new file mode 100644 index 0000000..517a28d --- /dev/null +++ b/EC.Helper/CameraSDK/HiK/HiKSDK.cs @@ -0,0 +1,123 @@ +using System.Runtime.InteropServices; + +namespace EC.Helper.CameraSDK; + +public class HiKSDK : ICameraSDK +{ + #region Attr + + private int LoginId { get; set; } = -1; + + #endregion Attr + + public HiKSDK(CameraInfo cameraInfo) : base(cameraInfo) + { + } + + #region Base Method + + public override bool Init() + { + bool ret = ConnectSuccess(); + if (ret) return true; + + HiKOriSDK.NET_DVR_DEVICEINFO_V30 deviceInfo = new(); + LoginId = HiKOriSDK.NET_DVR_Login_V30(CameraInfo.Ip, CameraInfo.Port, CameraInfo.UserName, CameraInfo.Password, ref deviceInfo); + ret = ConnectSuccess(); + + return ret; + } + + public override bool Destory() + { + bool ret = ConnectSuccess(); + if (!ret) return true; + + ret = HiKOriSDK.NET_DVR_Logout(LoginId); + if (ret) LoginId = -1; + + return ret; + } + + public override bool ConnectSuccess() + { + return LoginId >= 0; + } + + public override void BuildException() + { + uint errCode = HiKOriSDK.NET_DVR_GetLastError(); + if (errCode == 0) return; + throw CameraException.New(CameraType.HiK, (int)errCode); + } + + #endregion Base Method + + #region Main Method + + private static class GPIParams + { + public static int Size { get; private set; } + public static Type Type { get; private set; } + + static GPIParams() + { + HiKOriSDK.NET_DVR_PTZPOS ptzPos = new(); + Size = Marshal.SizeOf(ptzPos); + Type = ptzPos.GetType(); + } + } + + public override PtzInfo GetPtzInfo() + { + bool ret = ConnectSuccess(); + if (!ret) return PtzInfo.Default; + + HiKOriSDK.NET_DVR_PTZPOS entity = new(); + int dwSize = GPIParams.Size; + uint dwReturned = 0; + IntPtr ptrBuf = Marshal.AllocHGlobal(dwSize); + Marshal.StructureToPtr(entity, ptrBuf, true); + try + { + ret = HiKOriSDK.NET_DVR_GetDVRConfig(LoginId, HiKOriSDK.NET_DVR_GET_PTZPOS, 0, ptrBuf, (uint)dwSize, ref dwReturned); + if (!ret) { BuildException(); return PtzInfo.Default; } + object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type); + if (objBuf == null) return PtzInfo.Default; + entity = (HiKOriSDK.NET_DVR_PTZPOS)objBuf; + return PtzInfo.New(entity.wPanPos, entity.wTiltPos, entity.wZoomPos); + } + finally + { + Marshal.FreeHGlobal(ptrBuf); + } + } + + public override bool TryGetPtzInfo(out PtzInfo ptzInfo) + { + bool ret = ConnectSuccess(); + if (!ret) { ptzInfo = PtzInfo.Default; return false; } + + HiKOriSDK.NET_DVR_PTZPOS entity = new(); + int dwSize = GPIParams.Size; + uint dwReturned = 0; + IntPtr ptrBuf = Marshal.AllocHGlobal(dwSize); + Marshal.StructureToPtr(entity, ptrBuf, true); + try + { + ret = HiKOriSDK.NET_DVR_GetDVRConfig(LoginId, HiKOriSDK.NET_DVR_GET_PTZPOS, 0, ptrBuf, (uint)dwSize, ref dwReturned); + if (!ret) { BuildException(); ptzInfo = PtzInfo.Default; return false; } + object? objBuf = Marshal.PtrToStructure(ptrBuf, GPIParams.Type); + if (objBuf == null) { ptzInfo = PtzInfo.Default; return false; } + entity = (HiKOriSDK.NET_DVR_PTZPOS)objBuf; + ptzInfo = PtzInfo.New(entity.wPanPos, entity.wTiltPos, entity.wZoomPos); + return true; + } + finally + { + Marshal.FreeHGlobal(ptrBuf); + } + } + + #endregion Main Method +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/YuShi/YuShiOriSDK.cs b/EC.Helper/CameraSDK/YuShi/YuShiOriSDK.cs new file mode 100644 index 0000000..140c86b --- /dev/null +++ b/EC.Helper/CameraSDK/YuShi/YuShiOriSDK.cs @@ -0,0 +1,150 @@ +//#define Linux32 +//#define Linux64 +//#define Win32 +//#define Win64 + +using System.Runtime.InteropServices; + +namespace EC.Helper.CameraSDK; + +public static class YuShiOriSDK +{ + #region Lib Attr + +#if (Linux32) + public const string LibYsNetSDK = @"./libs/yushi/linux64/libNetDEVSDK.so"; +#elif (Linux64) + public const string LibYsNetSDK = @"./libs/yushi/linux64/libNetDEVSDK.so"; +#elif (Win32) + public const string LibYsNetSDK = @"./libs/yushi/win32/NetDEVSDK.dll"; +#elif (Win64) + public const string LibYsNetSDK = @"./libs/yushi/win64/NetDEVSDK.dll"; +#endif + + #endregion Lib Attr + + static YuShiOriSDK() + { + GlobalInit(); + } + + #region Global + + public static bool InitSuccess { get; private set; } + + public static bool GlobalInit() + { + if (InitSuccess) return true; + bool ret = NETDEV_Init(); + InitSuccess = ret; + if (!ret) throw new Exception("YuShiOriSDK global init failure."); + return ret; + } + + public static bool GlobalDestory() + { + if (!InitSuccess) return true; + bool ret = NETDEV_Cleanup(); + if (ret) InitSuccess = false; + return ret; + } + + #endregion Global + + #region SDK Const + + /* Common length */ + public const int NETDEV_LEN_64 = 64; + public const int NETDEV_LEN_128 = 128; + public const int NETDEV_LEN_132 = 132; + public const int NETDEV_LEN_260 = 260; + + #endregion SDK Const + + #region SDK Struct + + [StructLayout(LayoutKind.Sequential)] + public struct NETDEV_DEVICE_LOGIN_INFO_S + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NETDEV_LEN_260)] + public string szIPAddr; /* IP地址/域名 */ + + public Int32 dwPort; /* 端口号 */ + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NETDEV_LEN_132)] + public string szUserName; /* 用户名 */ + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NETDEV_LEN_128)] + public string szPassword; /* 密码 */ + + public Int32 dwLoginProto; /* 登录协议, 参见NETDEV_LOGIN_PROTO_E */ + public Int32 dwDeviceType; /* 设备类型, 参见NETDEV_DEVICE_TYPE_E */ + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)] + public byte[] byRes; /* Reserved */ + }; + + [StructLayout(LayoutKind.Sequential)] + public struct NETDEV_SELOG_INFO_S + { + public Int32 dwSELogCount; + public Int32 dwSELogTime; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public byte[] byRes; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct NETDEV_VIDEO_CHL_DETAIL_INFO_S + { + public Int32 dwChannelID; + public Int32 bPtzSupported; /* Whether ptz is supported */ + public Int32 enStatus; /* Channel status */ + public Int32 dwStreamNum; /* Number of streams */ + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NETDEV_LEN_64)] + public string szChnName; /* Device serial number */ + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] szReserve; + } + + [StructLayout(LayoutKind.Sequential)] + public struct NETDEV_PTZ_STATUS_S + { + public float fPanTiltX; /* 绝对水平坐标 Absolute horizontal coordinates*/ + public float fPanTiltY; /* 绝对竖直坐标 Absolute vertical coordinates*/ + public float fZoomX; /* 绝对聚焦倍数 Absolute multiples*/ + public Int32 enPanTiltStatus;/* 云台状态 PTZ Status*/ + public Int32 enZoomStatus; /* 聚焦状态 Focus Status*/ + }; + + #endregion SDK Struct + + #region Common Method + + [DllImport(LibYsNetSDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public static extern bool NETDEV_Init(); + + [DllImport(LibYsNetSDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public static extern bool NETDEV_Cleanup(); + + [DllImport(LibYsNetSDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public static extern int NETDEV_GetLastError(); + + [DllImport(LibYsNetSDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public static extern IntPtr NETDEV_Login_V30(ref NETDEV_DEVICE_LOGIN_INFO_S pstDevLoginInfo, ref NETDEV_SELOG_INFO_S pstSELogInfo); + + [DllImport(LibYsNetSDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public static extern bool NETDEV_Logout(IntPtr lpUserID); + + [DllImport(LibYsNetSDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public static extern Int32 NETDEV_QueryVideoChlDetailList(IntPtr lpUserID, ref int pdwChlCount, IntPtr pstVideoChlList); + + [DllImport(LibYsNetSDK, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] + public static extern bool NETDEV_PTZGetStatus(IntPtr lpUserID, int dwChannelID, ref NETDEV_PTZ_STATUS_S pstPTZStaus); + + //public boolean NETDEV_GetDevConfig(Pointer lpUserID, int dwChannelID, int dwCommand, Pointer lpOutBuffer, int dwOutBufferSize, IntByReference pdwBytesReturned); + + #endregion Common Method +} \ No newline at end of file diff --git a/EC.Helper/CameraSDK/YuShi/YuShiSDK.cs b/EC.Helper/CameraSDK/YuShi/YuShiSDK.cs new file mode 100644 index 0000000..6ff5959 --- /dev/null +++ b/EC.Helper/CameraSDK/YuShi/YuShiSDK.cs @@ -0,0 +1,87 @@ +namespace EC.Helper.CameraSDK; + +public class YuShiSDK : ICameraSDK +{ + #region Attr + + private IntPtr LoginId { get; set; } = IntPtr.Zero; + + #endregion Attr + + public YuShiSDK(CameraInfo cameraInfo) : base(cameraInfo) + { + } + + #region Base Method + + public override bool Init() + { + bool ret = ConnectSuccess(); + if (ret) return true; + + YuShiOriSDK.NETDEV_DEVICE_LOGIN_INFO_S loginInfo = new(); + loginInfo.szIPAddr = CameraInfo.Ip; + loginInfo.dwPort = CameraInfo.Port; + loginInfo.szUserName = CameraInfo.UserName; + loginInfo.szPassword = CameraInfo.Password; + YuShiOriSDK.NETDEV_SELOG_INFO_S logInfo = new(); + LoginId = YuShiOriSDK.NETDEV_Login_V30(ref loginInfo, ref logInfo); + ret = ConnectSuccess(); + + return ret; + } + + public override bool Destory() + { + bool ret = ConnectSuccess(); + if (!ret) return true; + + ret = YuShiOriSDK.NETDEV_Logout(LoginId); + if (ret) LoginId = IntPtr.Zero; + + return ret; + } + + public override bool ConnectSuccess() + { + return LoginId != IntPtr.Zero; + } + + public override void BuildException() + { + int errCode = YuShiOriSDK.NETDEV_GetLastError(); + if (errCode == 0) return; + throw CameraException.New(CameraType.YuShi, (int)errCode); + } + + #endregion Base Method + + #region Main Method + + public override PtzInfo GetPtzInfo() + { + bool ret = ConnectSuccess(); + if (!ret) return PtzInfo.Default; + + YuShiOriSDK.NETDEV_PTZ_STATUS_S entity = new(); + ret = YuShiOriSDK.NETDEV_PTZGetStatus(LoginId, 1, ref entity); + if (!ret) { BuildException(); return PtzInfo.Default; } + + return PtzInfo.New(entity.fPanTiltX, entity.fPanTiltY, entity.fZoomX); + } + + public override bool TryGetPtzInfo(out PtzInfo ptzInfo) + { + bool ret = ConnectSuccess(); + if (!ret) { ptzInfo = PtzInfo.Default; return false; } + + YuShiOriSDK.NETDEV_PTZ_STATUS_S entity = new(); + ret = YuShiOriSDK.NETDEV_PTZGetStatus(LoginId, 1, ref entity); + if (!ret) { BuildException(); ptzInfo = PtzInfo.Default; return false; } + + ptzInfo = PtzInfo.New(entity.fPanTiltX, entity.fPanTiltY, entity.fZoomX); + return true; + } + + #endregion Main Method +} \ No newline at end of file diff --git a/EC.Helper/EC.Helper.csproj b/EC.Helper/EC.Helper.csproj new file mode 100644 index 0000000..917b40f --- /dev/null +++ b/EC.Helper/EC.Helper.csproj @@ -0,0 +1,151 @@ + + + + net6.0 + enable + enable + + + + $(DefineConstants)TRACE;Win64 + + + + $(DefineConstants)TRACE;Win64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + diff --git a/EC.Helper/RabbitFunc/Compiler/CompilerException.cs b/EC.Helper/RabbitFunc/Compiler/CompilerException.cs new file mode 100644 index 0000000..4212528 --- /dev/null +++ b/EC.Helper/RabbitFunc/Compiler/CompilerException.cs @@ -0,0 +1,9 @@ +namespace EC.Helper.RabbitFunc.Compiler; + +[Serializable] +public class CompilerException : Exception +{ + public CompilerException(SourceLocation location, string message) + : base(string.Format("line:{0} column:{1}: {2}", location.Line, location.Column, message)) + { } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Compiler/IndexSpan.cs b/EC.Helper/RabbitFunc/Compiler/IndexSpan.cs new file mode 100644 index 0000000..bfa7f14 --- /dev/null +++ b/EC.Helper/RabbitFunc/Compiler/IndexSpan.cs @@ -0,0 +1,57 @@ +namespace EC.Helper.RabbitFunc.Compiler; + +[Serializable] +public readonly struct IndexSpan : IEquatable +{ + private readonly int start; + private readonly int length; + + public IndexSpan(int start, int length) + { + if (start < 0) + throw new ArgumentOutOfRangeException(nameof(start)); + if (length < 0) + throw new ArgumentOutOfRangeException(nameof(length)); + + this.start = start; + this.length = length; + } + + public int Start => start; + + public int End => start + length; + + public int Length => length; + + public bool IsEmpty => length == 0; + + public static bool operator ==(IndexSpan left, IndexSpan right) + { + return left.start == right.start && left.length == right.length; + } + + public static bool operator !=(IndexSpan left, IndexSpan right) + { + return left.start != right.start || left.length != right.length; + } + + public bool Equals(IndexSpan other) + { + return other.start == start && other.length == length; + } + + public override bool Equals(object obj) + { + return obj is IndexSpan other && Equals(other); + } + + public override int GetHashCode() + { + return (start.GetHashCode() << 16) ^ length.GetHashCode(); + } + + public override string ToString() + { + return string.Format("{{start:{0} length:{1}}}", start, length); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Compiler/Parser.cs b/EC.Helper/RabbitFunc/Compiler/Parser.cs new file mode 100644 index 0000000..ec91d1a --- /dev/null +++ b/EC.Helper/RabbitFunc/Compiler/Parser.cs @@ -0,0 +1,258 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Syntax; + +namespace EC.Helper.RabbitFunc.Compiler; + +internal class Parser +{ + private readonly Tokenizer tokenizer; + private TokenWithSpan lookahead; + private TokenWithSpan token; + + public Parser(Tokenizer tokenizer) + { + if (tokenizer == null) + throw new ArgumentNullException(nameof(tokenizer)); + + this.tokenizer = tokenizer; + Initialize(); + } + + private void Initialize() + { + FetchLookahead(); + } + + private Token NextToken() + { + token = lookahead; + FetchLookahead(); + return token.Token; + } + + private Token PeekToken() + { + return this.lookahead.Token; + } + + private void FetchLookahead() + { + lookahead = new TokenWithSpan(tokenizer.NextToken(), tokenizer.TokenSpan); + } + + private bool PeekToken(TokenKind kind) + { + return PeekToken().Kind == kind; + } + + private bool PeekToken(Token check) + { + return PeekToken() == check; + } + + private bool MaybeEat(TokenKind kind) + { + if (PeekToken().Kind == kind) + { + NextToken(); + return true; + } + return false; + } + + private LambdaExpression ParseStatement() + { + while (true) + { + switch (PeekToken().Kind) + { + case TokenKind.Comment: + case TokenKind.NewLine: + NextToken(); + continue; + case TokenKind.EndOfFile: + return null; + + default: + return ParseLambdaExpression(); + } + } + } + + private ExpressionType GetBinaryOperator(TokenKind kind) + { + return kind switch + { + TokenKind.Add => ExpressionType.Add, + TokenKind.Subtract => ExpressionType.Subtract, + TokenKind.Multiply => ExpressionType.Multiply, + TokenKind.Divide => ExpressionType.Divide, + TokenKind.Mod => ExpressionType.Modulo, + TokenKind.Power => ExpressionType.Power, + TokenKind.LessThan => ExpressionType.LessThan, + TokenKind.LessThanOrEqual => ExpressionType.LessThanOrEqual, + TokenKind.Equal => ExpressionType.Equal, + TokenKind.GreaterThanOrEqual => ExpressionType.GreaterThanOrEqual, + TokenKind.GreaterThan => ExpressionType.GreaterThan, + TokenKind.NotEqual => ExpressionType.NotEqual, + _ => throw new CompilerException(tokenizer.Position, string.Format("operator TokenKind:{0} error!", kind.ToString())), + }; + } + + private IList ParseArguments() + { + List list = new List(); + if (PeekToken().Kind != TokenKind.RightParen) + { + do + { + list.Add(ParseExpression()); + } while (MaybeEat(TokenKind.Comma)); + } + + return list; + } + + private Expression ParseTerm() + { + Expression expr = null; + Token token = NextToken(); + switch (token.Kind) + { + case TokenKind.Constant: + expr = Expression.Constant(token.Value); + break; + + case TokenKind.Subtract: + expr = Expression.Negate(ParseExpression()); + break; + + case TokenKind.LeftParen: + expr = ParseExpression(); + if (!MaybeEat(TokenKind.RightParen)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + break; + + case TokenKind.Identifier: + switch (PeekToken().Kind) + { + case TokenKind.LeftParen: + NextToken(); + expr = Expression.Call(null, token.Text, ParseArguments()); + if (!MaybeEat(TokenKind.RightParen)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + + break; + + case TokenKind.Dot: + expr = Expression.Parameter(null, token.Text); + while (MaybeEat(TokenKind.Dot)) + { + token = NextToken(); + if (token.Kind != TokenKind.Identifier) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + if (PeekToken().Kind == TokenKind.LeftParen) + { + expr = Expression.Call(expr, token.Text, ParseArguments()); + if (!MaybeEat(TokenKind.RightParen)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + break; + } + + expr = Expression.Member(expr, token.Text); + } + if (MaybeEat(TokenKind.LeftParen)) + { + expr = Expression.Call(expr, token.Text, ParseArguments()); + if (!MaybeEat(TokenKind.RightParen)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + } + break; + + default: + expr = Expression.Parameter(typeof(double), token.Text); + break; + } + break; + + case TokenKind.Not: + return Expression.Not(ParseExpression()); + + case TokenKind.IF: + if (!MaybeEat(TokenKind.LeftParen)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + var test = ParseExpression(); + if (!MaybeEat(TokenKind.Comma)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + var trueExpre = ParseExpression(); + if (!MaybeEat(TokenKind.Comma)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + var falseExpre = ParseExpression(); + if (!MaybeEat(TokenKind.RightParen)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + + expr = Expression.Condition(test, trueExpre, falseExpre); + break; + } + + return expr; + } + + private Expression ParseExpression(byte precedence = 0) + { + Expression leftOperand = ParseTerm(); + while (true) + { + Token token = PeekToken(); + if (token is OperatorToken operatorToken && operatorToken.Precedence >= precedence) + { + NextToken(); + Expression rightOperand = ParseExpression(checked((byte)(operatorToken.Precedence + 1))); + ExpressionType @operator = GetBinaryOperator(token.Kind); + leftOperand = new BinaryExpression(@operator, leftOperand, rightOperand); + continue; + } + + break; + } + + return leftOperand; + } + + private LambdaExpression ParseLambdaExpression() + { + Token token = NextToken(); + if (token.Kind != TokenKind.Identifier) + throw new CompilerException(tokenizer.Position, token.Text); + + var name = token.Text; + var parameters = new List(); + if (MaybeEat(TokenKind.LeftParen)) + { + if (!MaybeEat(TokenKind.RightParen)) + { + do + { + token = NextToken(); + if (token.Kind != TokenKind.Identifier) + throw new CompilerException(tokenizer.Position, token.Text); + + parameters.Add(Expression.Parameter(typeof(double), token.Text)); + } while (MaybeEat(TokenKind.Comma)); + + if (!MaybeEat(TokenKind.RightParen)) + throw new CompilerException(tokenizer.Position, token.Text); + } + } + if (!MaybeEat(TokenKind.Assign)) + throw new CompilerException(tokenizer.Position, PeekToken().Text); + + Expression body = ParseExpression(); + return Expression.Lambda(name, body, parameters); + } + + public LambdaExpression Parse() + { + return ParseStatement(); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Compiler/SourceLocation.cs b/EC.Helper/RabbitFunc/Compiler/SourceLocation.cs new file mode 100644 index 0000000..146a728 --- /dev/null +++ b/EC.Helper/RabbitFunc/Compiler/SourceLocation.cs @@ -0,0 +1,97 @@ +namespace EC.Helper.RabbitFunc.Compiler; + +[Serializable] +public readonly struct SourceLocation : IEquatable +{ + public static readonly SourceLocation None = new SourceLocation(0, 16707566, 0, true); + public static readonly SourceLocation Invalid = new SourceLocation(0, 0, 0, true); + public static readonly SourceLocation MinValue = new SourceLocation(0, 1, 1); + + private readonly int index; + private readonly int line; + private readonly int column; + + public SourceLocation(int index, int line, int column) + { + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index)); + if (line < 1) + throw new ArgumentOutOfRangeException(nameof(line)); + if (column < 1) + throw new ArgumentOutOfRangeException(nameof(column)); + + this.index = index; + this.line = line; + this.column = column; + } + + private SourceLocation(int index, int line, int column, bool _) + { + this.index = index; + this.line = line; + this.column = column; + } + + public int Index => index; + + public int Line => line; + + public int Column => column; + + public bool IsValid => line != 0 && column != 0; + + public static bool operator ==(SourceLocation left, SourceLocation right) + { + return left.index == right.index && left.line == right.line && left.column == right.column; + } + + public static bool operator !=(SourceLocation left, SourceLocation right) + { + return left.index != right.index || left.line != right.line || left.column != right.column; + } + + public static bool operator <(SourceLocation left, SourceLocation right) + { + return left.index < right.index; + } + + public static bool operator >(SourceLocation left, SourceLocation right) + { + return left.index > right.index; + } + + public static bool operator <=(SourceLocation left, SourceLocation right) + { + return left.index <= right.index; + } + + public static bool operator >=(SourceLocation left, SourceLocation right) + { + return left.index >= right.index; + } + + public static int Compare(SourceLocation left, SourceLocation right) + { + return left > right ? 1 : left < right ? -1 : 0; + } + + public bool Equals(SourceLocation other) + { + return other.index == index && other.line == line && other.column == column; + } + + public override bool Equals(object obj) + { + return obj is SourceLocation other && Equals(other); + } + + public override int GetHashCode() + { + return (line << 16) ^ column; + } + + public override string ToString() + { + return string.Format("{{index:{0} line:{1} column:{2}}}", index, line, column); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Compiler/TokenWithSpan.cs b/EC.Helper/RabbitFunc/Compiler/TokenWithSpan.cs new file mode 100644 index 0000000..82591be --- /dev/null +++ b/EC.Helper/RabbitFunc/Compiler/TokenWithSpan.cs @@ -0,0 +1,20 @@ +using EC.Helper.RabbitFunc.Syntax; + +namespace EC.Helper.RabbitFunc.Compiler; + +[Serializable] +internal readonly struct TokenWithSpan +{ + private readonly Token token; + private readonly IndexSpan span; + + public TokenWithSpan(Token token, IndexSpan span) + { + this.token = token; + this.span = span; + } + + public IndexSpan Span => span; + + public Token Token => token; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Compiler/Tokenizer.cs b/EC.Helper/RabbitFunc/Compiler/Tokenizer.cs new file mode 100644 index 0000000..f5b116d --- /dev/null +++ b/EC.Helper/RabbitFunc/Compiler/Tokenizer.cs @@ -0,0 +1,403 @@ +using EC.Helper.RabbitFunc.Syntax; + +namespace EC.Helper.RabbitFunc.Compiler; + +internal class Tokenizer +{ + #region Attr + + private const int DefaultBufferCapacity = 1024; + + private readonly TextReader reader; + private char[] buffer; + private int start; + private int end; + private int position; + private bool endOfStream; + private bool multiEolns; + private int tokenEnd; + private int tokenStartIndex; + private int tokenEndIndex; + private List newLineLocations; + private SourceLocation initialLocation; + + public bool EndOfStream => endOfStream; + + public int Index => tokenStartIndex + Math.Min(position, end) - start; + + public SourceLocation Position => IndexToLocation(Index); + + public IndexSpan TokenSpan => new(tokenStartIndex, tokenEndIndex - tokenStartIndex); + + private int TokenLength => tokenEnd - start; + + #endregion Attr + + public Tokenizer(TextReader reader) + { + this.reader = reader; + Init(DefaultBufferCapacity); + } + + private void Init(int bufferCapacity) + { + multiEolns = true; + buffer = new char[bufferCapacity]; + newLineLocations = new List(); + initialLocation = SourceLocation.MinValue; + } + + private static void ResizeInternal(ref char[] array, int newSize, int start, int count) + { + char[] array2 = (newSize != array.Length) ? new char[newSize] : array; + Buffer.BlockCopy(array, start * 2, array2, 0, count * 2); + array = array2; + } + + private static bool IsNameStart(int ch) + { + return char.IsLetter((char)ch) || ch == 95; + } + + private static bool IsNamePart(int ch) + { + return char.IsLetterOrDigit((char)ch) || ch == 95; + } + + private static Token BadChar(int ch) + { + return Token.Error(((char)ch).ToString()); + } + + private void RefillBuffer() + { + if (end == buffer.Length) + { + int newSize = Math.Max(Math.Max((end - start) * 2, buffer.Length), position); + ResizeInternal(ref buffer, newSize, start, end - start); + end -= start; + position -= start; + start = 0; + //_bufferResized = true; + } + + end += reader.Read(buffer, end, buffer.Length - end); + } + + private int Peek() + { + if (position >= end) + { + RefillBuffer(); + if (position >= end) + { + endOfStream = true; + return -1; + } + } + + return buffer[position]; + } + + private bool NextChar(int ch) + { + if (Peek() == ch) + { + position++; + return true; + } + return false; + } + + private int NextChar() + { + int result = Peek(); + position++; + return result; + } + + private int ReadLine() + { + int num; + do + { + num = NextChar(); + } while (num != -1 && !IsEoln(num)); + if (num == 10) + { + newLineLocations.Add(Index); + } + BufferBack(); + return num; + } + + private bool IsEoln(int current) + { + return current == 10 || (current == 13 && multiEolns); + } + + private void BufferBack() + { + SeekRelative(-1); + } + + private void SeekRelative(int disp) + { + position += disp; + } + + private void MarkTokenEnd() + { + tokenEnd = Math.Min(position, end); + int num = tokenEnd - start; + tokenEndIndex = tokenStartIndex + num; + } + + private void DiscardToken() + { + if (tokenEnd == -1) + { + MarkTokenEnd(); + } + + start = tokenEnd; + tokenStartIndex = tokenEndIndex; + tokenEnd = -1; + } + + private string GetTokenString() + { + return new string(buffer, start, tokenEnd - start); + } + + private string GetTokenSubstring(int offset) + { + return GetTokenSubstring(offset, tokenEnd - start - offset); + } + + private string GetTokenSubstring(int offset, int length) + { + return new string(buffer, start + offset, length); + } + + private int SkipWhiteSpace() + { + int num; + do + { + num = NextChar(); + } while (num == 32 || num == 9); + + BufferBack(); + DiscardToken(); + SeekRelative(1); + return num; + } + + private SourceLocation IndexToLocation(int index) + { + int num = newLineLocations.BinarySearch(index); + if (num < 0) + { + if (num == -1) + { + int column = checked(index + initialLocation.Column); + if (TokenLength > 0) column -= TokenLength; + return new SourceLocation(index + initialLocation.Index, initialLocation.Line, column); + } + num = ~num - 1; + } + + int fcolumn = index - newLineLocations[num] + initialLocation.Column; + if (TokenLength > 0) fcolumn -= TokenLength; + return new SourceLocation(index + initialLocation.Index, num + 1 + initialLocation.Line, fcolumn); + } + + private Token ReadName() + { + BufferBack(); + int num = NextChar(); + if (!IsNameStart(num)) + return BadChar(num); + + while (IsNamePart(num)) + { + num = this.NextChar(); + } + + BufferBack(); + MarkTokenEnd(); + return Token.Identifier(GetTokenString()); + } + + private Token ReadNumber() + { + int num; + do + { + num = NextChar(); + } while (48 <= num && num <= 57); + if (num == 46) + { + do + { + num = NextChar(); + } while (48 <= num && num <= 57); + } + + BufferBack(); + MarkTokenEnd(); + return Token.Constant(double.Parse(GetTokenString())); + } + + private Token ReadComment() + { + BufferBack(); + int num = NextChar(); + if (num == 42) + { + do + { + num = NextChar(); + if (num == 10) + { + newLineLocations.Add(Index); + } + } while (!(num == 42 && NextChar(47))); + + SeekRelative(-2); + MarkTokenEnd(); + SeekRelative(2); + return Token.Comment(GetTokenSubstring(2)); + } + else + { + ReadLine(); + MarkTokenEnd(); + return Token.Comment(GetTokenSubstring(2)); + } + } + + public Token NextToken() + { + DiscardToken(); + int num = NextChar(); + while (true) + { + switch (num) + { + case -1: + return Tokens.EndOfFileToken; + + case 10://'\n' + newLineLocations.Add(Index); + num = SkipWhiteSpace(); + continue; + case 13://'\r' + case 32://' ' + num = SkipWhiteSpace(); + continue; + case 33://! + var notToken = NextChar(61) ? Tokens.NotEqualToken : Tokens.NotToken; + MarkTokenEnd(); + return notToken; + + case 37://'%' + MarkTokenEnd(); + return Tokens.ModToken; + + case 40://'(' + MarkTokenEnd(); + return Tokens.LeftParenToken; + + case 41://')' + MarkTokenEnd(); + return Tokens.RightParenToken; + + case 42://'*' + MarkTokenEnd(); + return Tokens.MultiplyToken; + + case 43://'+' + MarkTokenEnd(); + return Tokens.AddToken; + + case 44://',' + MarkTokenEnd(); + return Tokens.CommaToken; + + case 45://'-' + MarkTokenEnd(); + return Tokens.SubtractToken; + + case 46://'.' + MarkTokenEnd(); + return Tokens.DotToken; + + case 47://'/' + if (NextChar(42) || NextChar(47)) + { + return ReadComment(); + } + + MarkTokenEnd(); + return Tokens.DivideToken; + + case 48://'0' + case 49: + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57://'9' + return ReadNumber(); + + case 59://';' + MarkTokenEnd(); + return Tokens.NewLineToken; + + case 60://< + var lessToken = NextChar(61) ? Tokens.LessThanOrEqualToken : Tokens.LessThanToken; + MarkTokenEnd(); + return lessToken; + + case 61://'=' + var assignOrEqualToken = NextChar(61) ? Tokens.EqualToken : Tokens.AssignToken; + MarkTokenEnd(); + return assignOrEqualToken; + + case 62://> + var greaterToken = NextChar(61) ? Tokens.GreaterThanOrEqualToken : Tokens.GreaterThanToken; + MarkTokenEnd(); + return greaterToken; + + case 91://'[' + MarkTokenEnd(); + return Tokens.LeftBracketToken; + + case 93://']' + MarkTokenEnd(); + return Tokens.RightBracketToken; + + case 94://'^' + MarkTokenEnd(); + return Tokens.PowerToken; + + case 105://i + if (NextChar(102)) + { + MarkTokenEnd(); + return Tokens.IFToken; + } + + return ReadName(); + + default: + return ReadName(); + } + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/BinaryExpression.cs b/EC.Helper/RabbitFunc/Expressions/BinaryExpression.cs new file mode 100644 index 0000000..bcc1a1c --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/BinaryExpression.cs @@ -0,0 +1,119 @@ +using EC.Helper.RabbitFunc.Runtime; +using System.Text; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class BinaryExpression : Expression +{ + internal BinaryExpression(ExpressionType nodeType, Expression left, Expression right) + : base(nodeType) + { + Left = left; + Right = right; + } + + public Expression Left { get; } + + public Expression Right { get; } + + public override object Eval(RuntimeContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + var leftResult = Left.Eval(context); + var rightResult = Right.Eval(context); + return NodeType switch + { + ExpressionType.Add => System.Convert.ToDouble(leftResult) + System.Convert.ToDouble(rightResult), + ExpressionType.Subtract => System.Convert.ToDouble(leftResult) - System.Convert.ToDouble(rightResult), + ExpressionType.Multiply => System.Convert.ToDouble(leftResult) * System.Convert.ToDouble(rightResult), + ExpressionType.Divide => System.Convert.ToDouble(leftResult) / System.Convert.ToDouble(rightResult), + ExpressionType.Modulo => System.Convert.ToDouble(leftResult) % System.Convert.ToDouble(rightResult), + ExpressionType.Power => Math.Pow(System.Convert.ToDouble(leftResult), System.Convert.ToDouble(rightResult)), + ExpressionType.LessThan => System.Convert.ToDouble(leftResult) < System.Convert.ToDouble(rightResult), + ExpressionType.LessThanOrEqual => System.Convert.ToDouble(leftResult) <= System.Convert.ToDouble(rightResult), + ExpressionType.Equal => leftResult is bool ? System.Convert.ToBoolean(leftResult) == System.Convert.ToBoolean(rightResult) : System.Convert.ToDouble(leftResult) == System.Convert.ToDouble(rightResult), + ExpressionType.GreaterThanOrEqual => System.Convert.ToDouble(leftResult) >= System.Convert.ToDouble(rightResult), + ExpressionType.GreaterThan => System.Convert.ToDouble(leftResult) > System.Convert.ToDouble(rightResult), + ExpressionType.NotEqual => leftResult is bool ? System.Convert.ToBoolean(leftResult) != System.Convert.ToBoolean(rightResult) : System.Convert.ToDouble(leftResult) != System.Convert.ToDouble(rightResult), + _ => throw new RuntimeException("unknown operator:" + NodeType.ToString()), + }; + } + + public override string ToString() + { + var sb = new StringBuilder(); + if (Left is BinaryExpression) + { + sb.Append('('); + sb.Append(Left.ToString()); + sb.Append(')'); + } + else + { + sb.Append(Left.ToString()); + } + switch (NodeType) + { + case ExpressionType.Add: + sb.Append('+'); + break; + + case ExpressionType.Subtract: + sb.Append('-'); + break; + + case ExpressionType.Multiply: + sb.Append('*'); + break; + + case ExpressionType.Divide: + sb.Append('/'); + break; + + case ExpressionType.Modulo: + sb.Append('%'); + break; + + case ExpressionType.Power: + sb.Append('^'); + break; + + case ExpressionType.LessThan: + sb.Append('<'); + break; + + case ExpressionType.LessThanOrEqual: + sb.Append("<="); + break; + + case ExpressionType.Equal: + sb.Append("=="); + break; + + case ExpressionType.GreaterThanOrEqual: + sb.Append(">="); + break; + + case ExpressionType.GreaterThan: + sb.Append('>'); + break; + + case ExpressionType.NotEqual: + sb.Append("!="); + break; + + default: + throw new RuntimeException("unknown operator:" + NodeType.ToString()); + } + if (Right is BinaryExpression) + sb.Append('('); + + sb.Append(Right.ToString()); + if (Right is BinaryExpression) + sb.Append(')'); + + return sb.ToString(); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/ConditionalExpression.cs b/EC.Helper/RabbitFunc/Expressions/ConditionalExpression.cs new file mode 100644 index 0000000..106208f --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/ConditionalExpression.cs @@ -0,0 +1,32 @@ +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class ConditionalExpression : Expression +{ + internal ConditionalExpression(Expression test, Expression trueExpression, Expression falseExpression) + : base(ExpressionType.MethodCall) + { + Test = test; + TrueExpression = trueExpression; + FalseExpression = falseExpression; + } + + public override ExpressionType NodeType => ExpressionType.Conditional; + + public Expression Test { get; } + + public Expression TrueExpression { get; } + + public Expression FalseExpression { get; } + + public override object Eval(RuntimeContext context) + { + return (bool)Test.Eval(context) ? TrueExpression.Eval(context) : FalseExpression.Eval(context); + } + + public override string ToString() + { + return string.Format("if({0},{1},{2})", Test, TrueExpression, FalseExpression); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/ConstantExpression.cs b/EC.Helper/RabbitFunc/Expressions/ConstantExpression.cs new file mode 100644 index 0000000..8222c17 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/ConstantExpression.cs @@ -0,0 +1,29 @@ +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class ConstantExpression : Expression +{ + internal ConstantExpression(object value) + : base(ExpressionType.Constant) + { + Value = value; + } + + public object Value { get; } + + public override Type Type => Value?.GetType(); + + public override object Eval(RuntimeContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + return Value; + } + + public override string ToString() + { + return Value.ToString(); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/Expression.cs b/EC.Helper/RabbitFunc/Expressions/Expression.cs new file mode 100644 index 0000000..6549315 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/Expression.cs @@ -0,0 +1,238 @@ +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Expressions; + +public abstract class Expression +{ + protected Expression() + { } + + protected Expression(ExpressionType nodeType) + { + NodeType = nodeType; + } + + public virtual ExpressionType NodeType { get; } + + public virtual Type Type { get; } + + public static ParameterExpression Parameter(Type type, string name) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + return new ParameterExpression(ExpressionType.Parameter, type, name); + } + + public static ParameterExpression Variable(Type type, string name) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + return new ParameterExpression(ExpressionType.Variable, type, name); + } + + public static MemberExpression Member(Expression instance, string name) + { + if (instance == null) + throw new ArgumentNullException(nameof(instance)); + if (name == null) + throw new ArgumentNullException(nameof(name)); + + return new MemberExpression(instance, name); + } + + public static MemberExpression Field(Expression instance, string name) + { + if (instance == null) + throw new ArgumentNullException(nameof(instance)); + if (name == null) + throw new ArgumentNullException(nameof(name)); + + return new MemberExpression(instance, name); + } + + public static MemberExpression Property(Expression instance, string name) + { + if (instance == null) + throw new ArgumentNullException(nameof(instance)); + if (name == null) + throw new ArgumentNullException(nameof(name)); + + return new MemberExpression(instance, name); + } + + public static BinaryExpression Assign(Expression left, Expression right) + { + if (left == null) + throw new ArgumentNullException(nameof(left)); + if (right == null) + throw new ArgumentNullException(nameof(right)); + + return new BinaryExpression(ExpressionType.Assign, left, right); + } + + public static ConstantExpression Constant(object value) + { + return new ConstantExpression(value); + } + + public static UnaryExpression Convert(Expression expression, Type type) + { + if (expression == null) + throw new ArgumentNullException(nameof(expression)); + if (type == null) + throw new ArgumentNullException(nameof(type)); + + return new UnaryExpression(ExpressionType.Constant, expression); + } + + public static BinaryExpression Add(Expression left, Expression right) + { + if (left == null) + throw new ArgumentNullException(nameof(left)); + if (right == null) + throw new ArgumentNullException(nameof(right)); + + return new BinaryExpression(ExpressionType.Add, left, right); + } + + public static BinaryExpression Subtract(Expression left, Expression right) + { + if (left == null) + throw new ArgumentNullException(nameof(left)); + if (right == null) + throw new ArgumentNullException(nameof(right)); + + return new BinaryExpression(ExpressionType.Subtract, left, right); + } + + public static BinaryExpression Multiply(Expression left, Expression right) + { + if (left == null) + throw new ArgumentNullException(nameof(left)); + if (right == null) + throw new ArgumentNullException(nameof(right)); + + return new BinaryExpression(ExpressionType.Multiply, left, right); + } + + public static BinaryExpression Divide(Expression left, Expression right) + { + if (left == null) + throw new ArgumentNullException(nameof(left)); + if (right == null) + throw new ArgumentNullException(nameof(right)); + + return new BinaryExpression(ExpressionType.Divide, left, right); + } + + public static BinaryExpression Modulo(Expression left, Expression right) + { + if (left == null) + throw new ArgumentNullException(nameof(left)); + if (right == null) + throw new ArgumentNullException(nameof(right)); + + return new BinaryExpression(ExpressionType.Modulo, left, right); + } + + public static BinaryExpression Power(Expression left, Expression right) + { + if (left == null) + throw new ArgumentNullException(nameof(left)); + if (right == null) + throw new ArgumentNullException(nameof(right)); + + return new BinaryExpression(ExpressionType.Power, left, right); + } + + public static UnaryExpression Negate(Expression expression) + { + if (expression == null) + throw new ArgumentNullException(nameof(expression)); + + return new UnaryExpression(ExpressionType.Negate, expression); + } + + public static BinaryExpression ArrayIndex(Expression array, Expression index) + { + if (array == null) + throw new ArgumentNullException(nameof(array)); + if (index == null) + throw new ArgumentNullException(nameof(index)); + + return new BinaryExpression(ExpressionType.ArrayIndex, array, index); + } + + public static UnaryExpression ArrayLength(Expression array) + { + if (array == null) + throw new ArgumentNullException(nameof(array)); + + return new UnaryExpression(ExpressionType.ArrayLength, array); + } + + public static MethodCallExpression Call(Expression instance, string methodName, params Expression[] arguments) + { + if (methodName == null) + throw new ArgumentNullException(nameof(methodName)); + + return new MethodCallExpression(instance, methodName, arguments); + } + + public static MethodCallExpression Call(Expression instance, string methodName, IList arguments) + { + if (methodName == null) + throw new ArgumentNullException(nameof(methodName)); + if (arguments == null) + throw new ArgumentNullException(nameof(arguments)); + + return new MethodCallExpression(instance, methodName, arguments); + } + + public static LambdaExpression Lambda(string name, Expression body, params ParameterExpression[] parameters) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + if (body == null) + throw new ArgumentNullException(nameof(body)); + + return new LambdaExpression(name, body, parameters); + } + + public static LambdaExpression Lambda(string name, Expression body, IList parameters) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + if (body == null) + throw new ArgumentNullException(nameof(body)); + + return new LambdaExpression(name, body, parameters.ToArray()); + } + + public static UnaryExpression Not(Expression expression) + { + if (expression == null) + throw new ArgumentNullException(nameof(expression)); + + return new UnaryExpression(ExpressionType.Not, expression); + } + + public static ConditionalExpression Condition(Expression condition, Expression trueExpression, Expression falseExpression) + { + if (condition == null) + throw new ArgumentNullException(nameof(condition)); + if (trueExpression == null) + throw new ArgumentNullException(nameof(trueExpression)); + if (falseExpression == null) + throw new ArgumentNullException(nameof(falseExpression)); + + return new ConditionalExpression(condition, trueExpression, falseExpression); + } + + public virtual object Eval(RuntimeContext context) + { + throw new NotSupportedException(); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/ExpressionCompiler.cs b/EC.Helper/RabbitFunc/Expressions/ExpressionCompiler.cs new file mode 100644 index 0000000..92f8063 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/ExpressionCompiler.cs @@ -0,0 +1,146 @@ +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Expressions; + +internal class ExpressionCompiler +{ + private readonly Dictionary lambdas = new Dictionary(); + + private LambdaCompiler GetLambdaCompiler(LambdaExpression expression) + { + if (!lambdas.TryGetValue(expression.Name, out var lambda)) + { + lambda = new LambdaCompiler(this, expression); + lambdas.Add(expression.Name, lambda); + } + return lambda; + } + + public Delegate Compile(LambdaExpression expression, Type delegateType = null) + { + var lambda = new LambdaCompiler(this, expression); + lambdas.Add(lambda.Name, lambda); + return lambda.Compile(delegateType); + } + + private sealed class LambdaCompiler + { + private readonly ExpressionCompiler compiler; + private readonly LambdaExpression expression; + private readonly List parameters; + + public LambdaCompiler(ExpressionCompiler compiler, LambdaExpression expression) + { + this.compiler = compiler; + this.expression = expression; + this.parameters = new List(); + foreach (var parameter in expression.Parameters) + { + parameters.Add(System.Linq.Expressions.Expression.Parameter(parameter.Type, parameter.Name)); + } + } + + public string Name => expression.Name; + + private System.Linq.Expressions.Expression EmitExpression(Expression expression) + { + switch (expression) + { + case ConditionalExpression conditionExpression: + { + var test = EmitExpression(conditionExpression.Test); + var trueExpression = EmitExpression(conditionExpression.TrueExpression); + var falseExpression = EmitExpression(conditionExpression.FalseExpression); + return System.Linq.Expressions.Expression.Condition(test, trueExpression, falseExpression); + } + case BinaryExpression binaryExpression: + { + var left = EmitExpression(binaryExpression.Left); + var right = EmitExpression(binaryExpression.Right); + return expression.NodeType switch + { + ExpressionType.Add => System.Linq.Expressions.Expression.Add(left, right), + ExpressionType.Subtract => System.Linq.Expressions.Expression.Subtract(left, right), + ExpressionType.Multiply => System.Linq.Expressions.Expression.Multiply(left, right), + ExpressionType.Divide => System.Linq.Expressions.Expression.Divide(left, right), + ExpressionType.Modulo => System.Linq.Expressions.Expression.Modulo(left, right), + ExpressionType.Power => System.Linq.Expressions.Expression.Power(left, right), + ExpressionType.LessThan => System.Linq.Expressions.Expression.LessThan(left, right), + ExpressionType.LessThanOrEqual => System.Linq.Expressions.Expression.LessThanOrEqual(left, right), + ExpressionType.Equal => System.Linq.Expressions.Expression.Equal(left, right), + ExpressionType.GreaterThanOrEqual => System.Linq.Expressions.Expression.GreaterThanOrEqual(left, right), + ExpressionType.GreaterThan => System.Linq.Expressions.Expression.GreaterThan(left, right), + ExpressionType.NotEqual => System.Linq.Expressions.Expression.NotEqual(left, right), + _ => throw new LambdaCompilerException("unknown operator char:" + expression.NodeType.ToString()), + }; + } + case ConstantExpression constantExpression: + return System.Linq.Expressions.Expression.Constant(constantExpression.Value); + + case MethodCallExpression methodCallExpression: + { + var lambda = methodCallExpression.GetLambda(this.expression.Domain); + if (lambda == null) throw new LambdaCompilerException(string.Format("missing method:{0}", methodCallExpression.MethodName)); + if (lambda is SystemLambdaExpression systemLambda) + { + var arguments = new List(); + foreach (var argument in methodCallExpression.Arguments) + { + arguments.Add(EmitExpression(argument)); + } + return System.Linq.Expressions.Expression.Call(null, systemLambda.Method, arguments); + } + else + { + var elementType = typeof(object); + var customLambda = compiler.GetLambdaCompiler(lambda); + var arguments = new System.Linq.Expressions.Expression[customLambda.parameters.Count]; + for (var i = 0; i < arguments.Length; i++) + { + var parameter = customLambda.parameters[i]; + var argument = EmitExpression(methodCallExpression.Arguments[i]); + arguments[i] = parameter.Type != elementType + ? System.Linq.Expressions.Expression.Convert(argument, elementType) + : argument; + } + + var custom = customLambda.Compile(); + return System.Linq.Expressions.Expression.Convert( + System.Linq.Expressions.Expression.Call( + System.Linq.Expressions.Expression.Constant(custom), + typeof(Delegate).GetMethod(nameof(Delegate.DynamicInvoke)), + System.Linq.Expressions.Expression.NewArrayInit(elementType, arguments)), + lambda.Type); + } + } + case ParameterExpression parameterExpression: + { + var parameter = parameters.Find(p => p.Name == parameterExpression.Name); + if (parameter == null) throw new RuntimeException("Missing member:" + parameterExpression.Name); + return parameter; + } + case UnaryExpression unaryExpression: + { + var operand = EmitExpression(unaryExpression.Operand); + return unaryExpression.NodeType switch + { + ExpressionType.Negate => System.Linq.Expressions.Expression.Negate(operand), + ExpressionType.Not => System.Linq.Expressions.Expression.Not(operand), + _ => throw new RuntimeException("unknown NodeType:" + unaryExpression.NodeType.ToString()), + }; + } + default: + return null; + } + } + + public Delegate Compile(Type delegateType = null) + { + var body = EmitExpression(this.expression.Body); + var lambda = delegateType == null + ? System.Linq.Expressions.Expression.Lambda(body, this.expression.Name, parameters) + : System.Linq.Expressions.Expression.Lambda(delegateType, body, this.expression.Name, parameters); + return lambda.Compile(); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/ExpressionType.cs b/EC.Helper/RabbitFunc/Expressions/ExpressionType.cs new file mode 100644 index 0000000..60637f1 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/ExpressionType.cs @@ -0,0 +1,65 @@ +namespace EC.Helper.RabbitFunc.Expressions; + +public enum ExpressionType : byte +{ + None, + Add, + Subtract, + Multiply, + Divide, + Modulo, + Power, + + Constant, + ArrayIndex, + ArrayLength, + Negate, + Convert, + Assign, + + MemberAccess, + Variable, + Parameter, + Lambda, + MethodCall, + + /// + /// < + /// + LessThan, + + /// + /// <= + /// + LessThanOrEqual, + + /// + /// == + /// + Equal, + + /// + /// >= + /// + GreaterThanOrEqual, + + /// + /// > + /// + GreaterThan, + + /// + /// != + /// + NotEqual, + + /// + /// ! + /// + Not, + + /// + /// IF + /// + Conditional, +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/LambdaCompilerException.cs b/EC.Helper/RabbitFunc/Expressions/LambdaCompilerException.cs new file mode 100644 index 0000000..6593c40 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/LambdaCompilerException.cs @@ -0,0 +1,9 @@ +namespace EC.Helper.RabbitFunc.Expressions; + +[Serializable] +public class LambdaCompilerException : Exception +{ + public LambdaCompilerException(string message) + : base(message) + { } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/LambdaExpression.cs b/EC.Helper/RabbitFunc/Expressions/LambdaExpression.cs new file mode 100644 index 0000000..6e16f0e --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/LambdaExpression.cs @@ -0,0 +1,75 @@ +using EC.Helper.RabbitFunc.Runtime; +using System.Collections.ObjectModel; +using System.Text; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class LambdaExpression : Expression +{ + internal LambdaExpression(string name, Expression body, params ParameterExpression[] parameters) + : base(ExpressionType.Lambda) + { + Name = name; + Parameters = new ReadOnlyCollection(parameters); + Body = body; + } + + public RabbitDomain Domain { get; internal set; } + + public string Name { get; } + + public ReadOnlyCollection Parameters { get; } + + public Expression Body { get; } + + public override Type Type => typeof(double); + + public Delegate Compile(Type deletageType = null) + { + var lambdaCompiler = new ExpressionCompiler(); + return lambdaCompiler.Compile(this, deletageType); + } + + public T Compile() + { + return (T)(object)Compile(typeof(T)); + } + + public override object Eval(RuntimeContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + var lambdaContext = new RuntimeContext(context); + lambdaContext.Domain = Domain; + for (int i = 0; i < Parameters.Count; i++) + { + var parameter = Parameters[i]; + var value = parameter.Eval(context); + lambdaContext.Variable(parameter.Name, value); + } + + return Body.Eval(lambdaContext); + } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append(Name).Append('('); + using (var e = Parameters.GetEnumerator()) + { + if (e.MoveNext()) + { + sb.Append(e.Current.Name); + while (e.MoveNext()) + { + sb.Append(','); + sb.Append(e.Current.Name); + } + } + } + + sb.Append(")=").Append(Body.ToString()); + return sb.ToString(); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/MemberExpression.cs b/EC.Helper/RabbitFunc/Expressions/MemberExpression.cs new file mode 100644 index 0000000..3f8ebf3 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/MemberExpression.cs @@ -0,0 +1,30 @@ +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class MemberExpression : Expression +{ + internal MemberExpression(Expression instance, string name) + : base(ExpressionType.MemberAccess) + { + Instance = instance; + Name = name; + } + + public Expression Instance { get; } + + public string Name { get; } + + public override object Eval(RuntimeContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + return default(double); + } + + public override string ToString() + { + return Instance == null ? Name : Instance.ToString() + "." + Name; + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/MethodCallExpression.cs b/EC.Helper/RabbitFunc/Expressions/MethodCallExpression.cs new file mode 100644 index 0000000..ac440a0 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/MethodCallExpression.cs @@ -0,0 +1,88 @@ +using EC.Helper.RabbitFunc.Runtime; +using System.Collections.ObjectModel; +using System.Text; +using MissingMethodException = EC.Helper.RabbitFunc.Runtime.MissingMethodException; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class MethodCallExpression : Expression +{ + internal MethodCallExpression(Expression instance, string methodName, IList arguments) + : base(ExpressionType.MethodCall) + { + Instance = instance; + MethodName = methodName; + Arguments = new ReadOnlyCollection(arguments); + } + + public Expression Instance { get; } + + public string MethodName { get; } + + public ReadOnlyCollection Arguments { get; } + + internal LambdaExpression GetLambda(RabbitDomain domain) + { + LambdaExpression lambda; + if (domain != null) + { + lambda = domain.GetLambda(MethodName); + } + else + { + lambda = Rabbit.GetSystemLambda(MethodName); + } + + return lambda; + } + + public override object Eval(RuntimeContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + if (Instance == null) + { + var lambdaExpression = GetLambda(context.Domain); + if (lambdaExpression == null) + throw new MissingMethodException(string.Format("missing method:{0}", MethodName)); + if (Arguments.Count != lambdaExpression.Parameters.Count) + throw new RuntimeException(string.Format("method:{0}. parame count error!", MethodName)); + + var lambdaContext = new RuntimeContext(context); + for (int i = 0; i < Arguments.Count; i++) + { + var parameter = lambdaExpression.Parameters[i]; + var argument = Arguments[i]; + var value = argument.Eval(context); + lambdaContext.Variable(parameter.Name, value); + } + + return lambdaExpression.Body.Eval(lambdaContext); + } + else + { + throw new NotSupportedException(); + } + } + + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append(MethodName).Append('('); + using (var e = Arguments.GetEnumerator()) + { + if (e.MoveNext()) + { + sb.Append(e.Current.ToString()); + while (e.MoveNext()) + { + sb.Append(','); + sb.Append(e.Current.ToString()); + } + } + } + sb.Append(')'); + return sb.ToString(); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/ParameterExpression.cs b/EC.Helper/RabbitFunc/Expressions/ParameterExpression.cs new file mode 100644 index 0000000..4d6f132 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/ParameterExpression.cs @@ -0,0 +1,45 @@ +using EC.Helper.RabbitFunc.Runtime; +using MissingMemberException = EC.Helper.RabbitFunc.Runtime.MissingMemberException; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class ParameterExpression : Expression +{ + internal ParameterExpression(ExpressionType nodeType, Type type, string name) + : base(nodeType) + { + Type = type; + Name = name; + } + + public override Type Type { get; } + + public string Name { get; } + + internal static object Access(RuntimeContext context, string name) + { + var value = context.Access(name); + if (value == null) + throw new MissingMemberException(string.Format("missing member:{0}", name)); + + return value.Value; + } + + internal static T Access(RuntimeContext context, string name) + { + return (T)Access(context, name); + } + + public override object Eval(RuntimeContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + return Access(context, Name); + } + + public override string ToString() + { + return Name; + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/SystemLambdaExpression.cs b/EC.Helper/RabbitFunc/Expressions/SystemLambdaExpression.cs new file mode 100644 index 0000000..01dd1ff --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/SystemLambdaExpression.cs @@ -0,0 +1,19 @@ +using System.Reflection; + +namespace EC.Helper.RabbitFunc.Expressions; + +public abstract class SystemLambdaExpression : LambdaExpression +{ + internal SystemLambdaExpression(MethodInfo method, string name, Expression body, params ParameterExpression[] parameters) + : base(name, body, parameters) + { + if (method == null) + throw new ArgumentNullException(nameof(method)); + + Method = method; + } + + public MethodInfo Method { get; } + + public override Type Type => Method.ReturnType; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Expressions/UnaryExpression.cs b/EC.Helper/RabbitFunc/Expressions/UnaryExpression.cs new file mode 100644 index 0000000..efb69a6 --- /dev/null +++ b/EC.Helper/RabbitFunc/Expressions/UnaryExpression.cs @@ -0,0 +1,48 @@ +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Expressions; + +public class UnaryExpression : Expression +{ + internal UnaryExpression(ExpressionType type, Expression operand) + : base(type) + { + Operand = operand; + } + + public Expression Operand { get; } + + public override object Eval(RuntimeContext context) + { + if (context == null) + throw new ArgumentNullException(nameof(context)); + + object value = Operand.Eval(context); + switch (NodeType) + { + case ExpressionType.Negate: + return (-(double)value); + + case ExpressionType.Not: + return (!(bool)value); + + default: + throw new RuntimeException("unknown unary:" + NodeType.ToString()); + } + } + + public override string ToString() + { + switch (NodeType) + { + case ExpressionType.Negate: + return Operand is BinaryExpression ? "-(" + Operand.ToString() + ")" : "-" + Operand.ToString(); + + case ExpressionType.Not: + return Operand is BinaryExpression ? "!(" + Operand.ToString() + ")" : "!" + Operand.ToString(); + + default: + throw new RuntimeException("unknown operator:" + NodeType.ToString()); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/AbsLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/AbsLambdaExpression.cs new file mode 100644 index 0000000..4586034 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/AbsLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class AbsLambdaExpression : SystemLambdaExpression +{ + public AbsLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Abs), new Type[] { typeof(double) }), "abs", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Abs(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/AcosLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/AcosLambdaExpression.cs new file mode 100644 index 0000000..430c0fb --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/AcosLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class AcosLambdaExpression : SystemLambdaExpression +{ + public AcosLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Acos), new Type[] { typeof(double) }), "acos", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Acos(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/AsinLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/AsinLambdaExpression.cs new file mode 100644 index 0000000..fdf167a --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/AsinLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class AsinLambdaExpression : SystemLambdaExpression +{ + public AsinLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Asin), new Type[] { typeof(double) }), "asin", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Asin(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/AtanLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/AtanLambdaExpression.cs new file mode 100644 index 0000000..e8e5648 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/AtanLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class AtanLambdaExpression : SystemLambdaExpression +{ + public AtanLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Atan), new Type[] { typeof(double) }), "atan", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Atan(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/CeilingLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/CeilingLambdaExpression.cs new file mode 100644 index 0000000..c789665 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/CeilingLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class CeilingLambdaExpression : SystemLambdaExpression +{ + public CeilingLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Ceiling), new Type[] { typeof(double) }), "ceiling", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Ceiling(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/CosLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/CosLambdaExpression.cs new file mode 100644 index 0000000..70700ca --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/CosLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class CosLambdaExpression : SystemLambdaExpression +{ + public CosLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Cos), new Type[] { typeof(double) }), "cos", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Cos(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/CoshLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/CoshLambdaExpression.cs new file mode 100644 index 0000000..a4f2f82 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/CoshLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class CoshLambdaExpression : SystemLambdaExpression +{ + public CoshLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Cosh), new Type[] { typeof(double) }), "cosh", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Cosh(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/ExpLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/ExpLambdaExpression.cs new file mode 100644 index 0000000..09ec321 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/ExpLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class ExpLambdaExpression : SystemLambdaExpression +{ + public ExpLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Exp), new Type[] { typeof(double) }), "exp", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Exp(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/ExternLambdaAttribute.cs b/EC.Helper/RabbitFunc/Extern/ExternLambdaAttribute.cs new file mode 100644 index 0000000..dc84f5b --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/ExternLambdaAttribute.cs @@ -0,0 +1,5 @@ +namespace EC.Helper.RabbitFunc.Extern; + +[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] +internal class ExternLambdaAttribute : Attribute +{ } \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/FloorLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/FloorLambdaExpression.cs new file mode 100644 index 0000000..5744285 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/FloorLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class FloorLambdaExpression : SystemLambdaExpression +{ + public FloorLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Floor), new Type[] { typeof(double) }), "floor", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Floor(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/LogLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/LogLambdaExpression.cs new file mode 100644 index 0000000..1eb262c --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/LogLambdaExpression.cs @@ -0,0 +1,24 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class LogLambdaExpression : SystemLambdaExpression +{ + public LogLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Log), new Type[] { typeof(double), typeof(double) }), "log", new BodyExpression(), + Expression.Parameter(typeof(double), "x"), + Expression.Parameter(typeof(double), "e")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + var x = ParameterExpression.Access(context, "x"); + var e = ParameterExpression.Access(context, "e"); + return Math.Log(x, e); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/MaxLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/MaxLambdaExpression.cs new file mode 100644 index 0000000..9a887ef --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/MaxLambdaExpression.cs @@ -0,0 +1,24 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class MaxLambdaExpression : SystemLambdaExpression +{ + public MaxLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Max), new Type[] { typeof(double), typeof(double) }), "max", new BodyExpression(), + Expression.Parameter(typeof(double), "left"), + Expression.Parameter(typeof(double), "right")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + var left = ParameterExpression.Access(context, "left"); + var right = ParameterExpression.Access(context, "right"); + return Math.Max(left, right); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/MinLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/MinLambdaExpression.cs new file mode 100644 index 0000000..c957d24 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/MinLambdaExpression.cs @@ -0,0 +1,24 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class MinLambdaExpression : SystemLambdaExpression +{ + public MinLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Min), new Type[] { typeof(double), typeof(double) }), "min", new BodyExpression(), + Expression.Parameter(typeof(double), "left"), + Expression.Parameter(typeof(double), "right")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + var left = ParameterExpression.Access(context, "left"); + var right = ParameterExpression.Access(context, "right"); + return Math.Min(left, right); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/RoundLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/RoundLambdaExpression.cs new file mode 100644 index 0000000..c724482 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/RoundLambdaExpression.cs @@ -0,0 +1,24 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class RoundLambdaExpression : SystemLambdaExpression +{ + public RoundLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Round), new Type[] { typeof(double), typeof(int) }), "round", new BodyExpression(), + Expression.Parameter(typeof(double), "value"), + Expression.Parameter(typeof(double), "digits")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + var value = ParameterExpression.Access(context, "value"); + var digits = (int)ParameterExpression.Access(context, "digits"); + return Math.Round(value, digits); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/SinLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/SinLambdaExpression.cs new file mode 100644 index 0000000..e491af3 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/SinLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class SinLambdaExpression : SystemLambdaExpression +{ + public SinLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Sin), new Type[] { typeof(double) }), "sin", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Sin(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/SinhLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/SinhLambdaExpression.cs new file mode 100644 index 0000000..1f8b2cc --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/SinhLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class SinhLambdaExpression : SystemLambdaExpression +{ + public SinhLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Sinh), new Type[] { typeof(double) }), "sinh", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Sinh(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/SqrtLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/SqrtLambdaExpression.cs new file mode 100644 index 0000000..df9f019 --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/SqrtLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class SqrtLambdaExpression : SystemLambdaExpression +{ + public SqrtLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Sqrt), new Type[] { typeof(double) }), "sqrt", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Sqrt(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/TanLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/TanLambdaExpression.cs new file mode 100644 index 0000000..a79766b --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/TanLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class TanLambdaExpression : SystemLambdaExpression +{ + public TanLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Tan), new Type[] { typeof(double) }), "tan", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Tan(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Extern/TanhLambdaExpression.cs b/EC.Helper/RabbitFunc/Extern/TanhLambdaExpression.cs new file mode 100644 index 0000000..d854a1a --- /dev/null +++ b/EC.Helper/RabbitFunc/Extern/TanhLambdaExpression.cs @@ -0,0 +1,21 @@ +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Runtime; + +namespace EC.Helper.RabbitFunc.Extern; + +[ExternLambda] +internal class TanhLambdaExpression : SystemLambdaExpression +{ + public TanhLambdaExpression() + : base(typeof(Math).GetMethod(nameof(Math.Tanh), new Type[] { typeof(double) }), "tanh", new BodyExpression(), + Expression.Parameter(typeof(double), "x")) + { } + + private class BodyExpression : Expression + { + public override object Eval(RuntimeContext context) + { + return Math.Tanh(ParameterExpression.Access(context, "x")); + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Rabbit.cs b/EC.Helper/RabbitFunc/Rabbit.cs new file mode 100644 index 0000000..2780f61 --- /dev/null +++ b/EC.Helper/RabbitFunc/Rabbit.cs @@ -0,0 +1,84 @@ +using EC.Helper.RabbitFunc.Compiler; +using EC.Helper.RabbitFunc.Expressions; +using EC.Helper.RabbitFunc.Extern; +using System.Reflection; + +namespace EC.Helper.RabbitFunc; + +public class Rabbit +{ + private static readonly Dictionary systemFunctions = new Dictionary(); + + static Rabbit() + { + var assembly = Assembly.GetExecutingAssembly(); + foreach (var type in assembly.GetTypes()) + { + var attributes = type.GetCustomAttributes(typeof(ExternLambdaAttribute), false); + if (attributes.Length > 0) + { + var constructor = type.GetConstructor(Type.EmptyTypes); + if (constructor != null) + Register((SystemLambdaExpression)constructor.Invoke(null)); + } + } + } + + internal static void Register(SystemLambdaExpression lambda) + { + if (lambda == null) + throw new ArgumentNullException(nameof(lambda)); + + systemFunctions[lambda.Name] = lambda; + } + + internal static bool TryGetSystemLambda(string name, out SystemLambdaExpression? lambda) + { + return systemFunctions.TryGetValue(name, out lambda); + } + + internal static SystemLambdaExpression? GetSystemLambda(string name) + { + systemFunctions.TryGetValue(name, out SystemLambdaExpression? lambda); + return lambda; + } + + public static LambdaExpression CompileFromSource(string source) + { + if (source == null) + throw new ArgumentNullException(nameof(source)); + + LambdaExpression? lambda = null; + using var reader = new StringReader(source); + var tokenizer = new Tokenizer(reader); + var parser = new Parser(tokenizer); + while (!tokenizer.EndOfStream) + { + var expression = parser.Parse(); + if (expression == null) break; + else lambda = expression; + } + + return lambda ?? throw new CompilerException(tokenizer.Position, "The formula was not found"); + } + + public static LambdaExpression CompileFromFile(string path) + { + if (path == null) + throw new ArgumentNullException(nameof(path)); + + LambdaExpression? lambda = null; + using var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + using var reader = new StreamReader(stream, System.Text.Encoding.UTF8); + var tokenizer = new Tokenizer(reader); + var parser = new Parser(tokenizer); + while (!tokenizer.EndOfStream) + { + var expression = parser.Parse(); + if (expression == null) break; + else lambda = expression; + } + + return lambda ?? throw new CompilerException(tokenizer.Position, "The formula was not found"); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/RabbitDomain.cs b/EC.Helper/RabbitFunc/RabbitDomain.cs new file mode 100644 index 0000000..10b7b03 --- /dev/null +++ b/EC.Helper/RabbitFunc/RabbitDomain.cs @@ -0,0 +1,83 @@ +using EC.Helper.RabbitFunc.Compiler; +using EC.Helper.RabbitFunc.Expressions; + +namespace EC.Helper.RabbitFunc; + +public class RabbitDomain +{ + private readonly Dictionary lambdas = new Dictionary(); + + public void Register(LambdaExpression lambda) + { + if (lambda == null) + throw new ArgumentNullException(nameof(lambda)); + + lambdas[lambda.Name] = lambda; + } + + public bool TryGetLambda(string name, out LambdaExpression? lambda) + { + if (lambdas.TryGetValue(name, out lambda)) + { + return true; + } + if (Rabbit.TryGetSystemLambda(name, out var systemLambda)) + { + lambda = systemLambda; + return true; + } + + return false; + } + + public LambdaExpression? GetLambda(string name) + { + TryGetLambda(name, out LambdaExpression? lambda); + return lambda; + } + + public LambdaExpression CompileFromSource(string source) + { + if (source == null) + throw new ArgumentNullException(nameof(source)); + + LambdaExpression? lambda = null; + using var reader = new StringReader(source); + var tokenizer = new Tokenizer(reader); + var parser = new Parser(tokenizer); + while (!tokenizer.EndOfStream) + { + var expression = parser.Parse(); + if (expression == null) break; + + expression.Domain = this; + Register(expression); + lambda = expression; + } + + return lambda ?? throw new CompilerException(tokenizer.Position, "The formula was not found"); + } + + public LambdaExpression CompileFromFile(string path) + { + if (path == null) + throw new ArgumentNullException(nameof(path)); + + LambdaExpression? lambda = null; + using var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + using var reader = new StreamReader(stream, System.Text.Encoding.UTF8); + var tokenizer = new Tokenizer(reader); + var parser = new Parser(tokenizer); + while (!tokenizer.EndOfStream) + { + var expression = parser.Parse(); + if (expression == null) break; + + expression.Domain = this; + Register(expression); + lambda = expression; + } + + return lambda ?? throw new CompilerException(tokenizer.Position, "The formula was not found"); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/RabbitFuncUtil.cs b/EC.Helper/RabbitFunc/RabbitFuncUtil.cs new file mode 100644 index 0000000..7b8ba6a --- /dev/null +++ b/EC.Helper/RabbitFunc/RabbitFuncUtil.cs @@ -0,0 +1,45 @@ +using EC.Helper.RabbitFunc.Compiler; +using EC.Helper.RabbitFunc.Expressions; + +namespace EC.Helper.RabbitFunc; + +public class RabbitFuncUtil +{ + public static LambdaExpression CompileFromSource(string source) + { + if (source == null) throw new ArgumentNullException(nameof(source)); + + LambdaExpression? lambda = null; + using var reader = new StringReader(source); + var tokenizer = new Tokenizer(reader); + var parser = new Parser(tokenizer); + while (!tokenizer.EndOfStream) + { + var expression = parser.Parse(); + if (expression == null) break; + lambda = expression; + } + + return lambda ?? throw new CompilerException(tokenizer.Position, "The formula was not found"); + } + + public static LambdaExpression CompileFromFile(string path) + { + if (path == null) + throw new ArgumentNullException(nameof(path)); + + LambdaExpression? lambda = null; + using var stream = new FileStream(path, FileMode.Open, FileAccess.Read); + using var reader = new StreamReader(stream, System.Text.Encoding.UTF8); + var tokenizer = new Tokenizer(reader); + var parser = new Parser(tokenizer); + while (!tokenizer.EndOfStream) + { + var expression = parser.Parse(); + if (expression == null) break; + lambda = expression; + } + + return lambda ?? throw new CompilerException(tokenizer.Position, "The formula was not found"); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Runtime/MemberAccessException.cs b/EC.Helper/RabbitFunc/Runtime/MemberAccessException.cs new file mode 100644 index 0000000..f8390dd --- /dev/null +++ b/EC.Helper/RabbitFunc/Runtime/MemberAccessException.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; + +namespace EC.Helper.RabbitFunc.Runtime +{ + [Serializable] + public class MemberAccessException : SystemException + { + public MemberAccessException() + { } + + public MemberAccessException(string message) + : base(message) + { } + + public MemberAccessException(string message, Exception innerException) + : base(message, innerException) + { } + + protected MemberAccessException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Runtime/MissingMemberException.cs b/EC.Helper/RabbitFunc/Runtime/MissingMemberException.cs new file mode 100644 index 0000000..a267bb7 --- /dev/null +++ b/EC.Helper/RabbitFunc/Runtime/MissingMemberException.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; + +namespace EC.Helper.RabbitFunc.Runtime +{ + [Serializable] + public class MissingMemberException : MemberAccessException + { + public MissingMemberException() + { } + + public MissingMemberException(string message) + : base(message) + { } + + public MissingMemberException(string message, Exception innerException) + : base(message, innerException) + { } + + protected MissingMemberException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Runtime/MissingMethodException.cs b/EC.Helper/RabbitFunc/Runtime/MissingMethodException.cs new file mode 100644 index 0000000..7474ea0 --- /dev/null +++ b/EC.Helper/RabbitFunc/Runtime/MissingMethodException.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; + +namespace EC.Helper.RabbitFunc.Runtime +{ + [Serializable] + public class MissingMethodException : MissingMemberException + { + public MissingMethodException() + { } + + public MissingMethodException(string message) + : base(message) + { } + + public MissingMethodException(string message, Exception innerException) + : base(message, innerException) + { } + + protected MissingMethodException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Runtime/RuntimeContext.cs b/EC.Helper/RabbitFunc/Runtime/RuntimeContext.cs new file mode 100644 index 0000000..2e6c6bb --- /dev/null +++ b/EC.Helper/RabbitFunc/Runtime/RuntimeContext.cs @@ -0,0 +1,91 @@ +namespace EC.Helper.RabbitFunc.Runtime; + +public class RuntimeContext +{ + private readonly Dictionary variables = new Dictionary(); + private readonly RuntimeContext parent; + + public RuntimeContext() + { } + + internal RuntimeContext(RuntimeContext parent) + { + if (parent == null) + throw new ArgumentNullException(nameof(parent)); + + this.parent = parent; + this.Domain = parent.Domain; + } + + public object this[string name] + { + set + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + variables[name] = new RuntimeVariable(value); + } + } + + internal RabbitDomain Domain { get; set; } + + private RuntimeContext FindCurrentOrParent(string name) + { + return variables.ContainsKey(name) ? this : parent?.FindCurrentOrParent(name); + } + + public void Variable(string name, object value) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + variables[name] = new RuntimeVariable(value); + } + + public RuntimeVariable Assign(string name, object value) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + var context = FindCurrentOrParent(name); + if (context == null) return null; + if (!context.variables.TryGetValue(name, out RuntimeVariable rv)) return null; + + rv.SetValue(value); + return rv; + } + + public RuntimeVariable Access(string name) + { + if (name == null) + throw new ArgumentNullException(nameof(name)); + + var context = FindCurrentOrParent(name); + if (context == null) return null; + if (!context.variables.TryGetValue(name, out RuntimeVariable rv)) return null; + return rv; + } + + public class RuntimeVariable + { + public RuntimeVariable() + { } + + public RuntimeVariable(object value) + { + Value = value; + IsAssigned = true; + } + + public object Value { get; set; } + + public bool IsAssigned { get; set; } + + public void SetValue(object value) + { + Value = value; + IsAssigned = true; + } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Runtime/RuntimeException.cs b/EC.Helper/RabbitFunc/Runtime/RuntimeException.cs new file mode 100644 index 0000000..1c3df77 --- /dev/null +++ b/EC.Helper/RabbitFunc/Runtime/RuntimeException.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; + +namespace EC.Helper.RabbitFunc.Runtime +{ + [Serializable] + public class RuntimeException : Exception + { + public RuntimeException() + { } + + public RuntimeException(string message) + : base(message) + { } + + public RuntimeException(string message, Exception innerException) + : base(message, innerException) + { } + + protected RuntimeException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Runtime/SystemException.cs b/EC.Helper/RabbitFunc/Runtime/SystemException.cs new file mode 100644 index 0000000..80d6510 --- /dev/null +++ b/EC.Helper/RabbitFunc/Runtime/SystemException.cs @@ -0,0 +1,23 @@ +using System.Runtime.Serialization; + +namespace EC.Helper.RabbitFunc.Runtime +{ + [Serializable] + public class SystemException : Exception + { + public SystemException() + { } + + public SystemException(string message) + : base(message) + { } + + public SystemException(string message, Exception innerException) + : base(message, innerException) + { } + + protected SystemException(SerializationInfo info, StreamingContext context) + : base(info, context) + { } + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/CommentToken.cs b/EC.Helper/RabbitFunc/Syntax/CommentToken.cs new file mode 100644 index 0000000..89a75d5 --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/CommentToken.cs @@ -0,0 +1,14 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal class CommentToken : Token +{ + private string comment; + + public CommentToken(string comment) + : base(TokenKind.Comment) + { + this.comment = comment; + } + + public override string Text => comment; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/ConstantToken.cs b/EC.Helper/RabbitFunc/Syntax/ConstantToken.cs new file mode 100644 index 0000000..0ba6ce6 --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/ConstantToken.cs @@ -0,0 +1,16 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal class ConstantToken : Token +{ + private double value; + + public ConstantToken(double value) + : base(TokenKind.Constant) + { + this.value = value; + } + + public override string Text => value.ToString(); + + public override double Value => value; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/ErrorToken.cs b/EC.Helper/RabbitFunc/Syntax/ErrorToken.cs new file mode 100644 index 0000000..e206388 --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/ErrorToken.cs @@ -0,0 +1,16 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal class ErrorToken : Token +{ + private string message; + + public ErrorToken(string message) + : base(TokenKind.Error) + { + this.message = message; + } + + public override string Text => message; + + public string Message => message; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/IdentifierToken.cs b/EC.Helper/RabbitFunc/Syntax/IdentifierToken.cs new file mode 100644 index 0000000..1616272 --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/IdentifierToken.cs @@ -0,0 +1,14 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal class IdentifierToken : Token +{ + private string name; + + public IdentifierToken(string name) + : base(TokenKind.Identifier) + { + this.name = name; + } + + public override string Text => name; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/OperatorToken.cs b/EC.Helper/RabbitFunc/Syntax/OperatorToken.cs new file mode 100644 index 0000000..84c56b0 --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/OperatorToken.cs @@ -0,0 +1,18 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal class OperatorToken : Token +{ + private string @operator; + private byte precedence; + + public OperatorToken(TokenKind kind, string @operator, byte precedence) + : base(kind) + { + this.@operator = @operator; + this.precedence = precedence; + } + + public override string Text => @operator; + + public byte Precedence => precedence; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/SymbolToken.cs b/EC.Helper/RabbitFunc/Syntax/SymbolToken.cs new file mode 100644 index 0000000..2baa9f2 --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/SymbolToken.cs @@ -0,0 +1,14 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal class SymbolToken : Token +{ + private string symbol; + + public SymbolToken(TokenKind kind, string symbol) + : base(kind) + { + this.symbol = symbol; + } + + public override string Text => symbol; +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/Token.cs b/EC.Helper/RabbitFunc/Syntax/Token.cs new file mode 100644 index 0000000..02cfd3c --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/Token.cs @@ -0,0 +1,55 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal abstract class Token +{ + private TokenKind kind; + + protected Token(TokenKind kind) + { + this.kind = kind; + } + + public abstract string Text { get; } + + public TokenKind Kind => kind; + + public virtual double Value + { + get => throw new System.NotSupportedException(); + } + + public static Token Error(string message) + { + return new ErrorToken(message); + } + + public static Token Operator(TokenKind kind, string @operator, byte precedence) + { + return new OperatorToken(kind, @operator, precedence); + } + + public static Token Symbol(TokenKind kind, string symbol) + { + return new SymbolToken(kind, symbol); + } + + public static Token Constant(double value) + { + return new ConstantToken(value); + } + + public static Token Comment(string text) + { + return new CommentToken(text); + } + + public static Token Identifier(string name) + { + return new IdentifierToken(name); + } + + public override string ToString() + { + return Text.ToString(); + } +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/TokenKind.cs b/EC.Helper/RabbitFunc/Syntax/TokenKind.cs new file mode 100644 index 0000000..1172658 --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/TokenKind.cs @@ -0,0 +1,113 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal enum TokenKind : byte +{ + EndOfFile, + NewLine, + Error, + Identifier, + Constant, + Comment, + + /// + /// + + /// + Add, + + /// + /// - + /// + Subtract, + + /// + /// * + /// + Multiply, + + /// + /// / + /// + Divide, + + /// + /// % + /// + Mod, + + /// + /// ^ + /// + Power, + + /// + /// , + /// + Comma, + + /// + /// = + /// + Assign, + + /// + /// . + /// + Dot, + + /// + /// ( + /// + LeftParen, + + /// + /// ) + /// + RightParen, + + /// + /// [ + /// + LeftBracket, + + /// + /// ] + /// + RightBracket, + + /// + /// ! + /// + Not, + + /// + /// < + /// + LessThan, + + /// + /// <= + /// + LessThanOrEqual, + + /// + /// == + /// + Equal, + + /// + /// >= + /// + GreaterThanOrEqual, + + /// + /// > + /// + GreaterThan, + + /// + /// != + /// + NotEqual, + + IF, +} \ No newline at end of file diff --git a/EC.Helper/RabbitFunc/Syntax/Tokens.cs b/EC.Helper/RabbitFunc/Syntax/Tokens.cs new file mode 100644 index 0000000..2f738ce --- /dev/null +++ b/EC.Helper/RabbitFunc/Syntax/Tokens.cs @@ -0,0 +1,32 @@ +namespace EC.Helper.RabbitFunc.Syntax; + +internal static class Tokens +{ + public static readonly Token EndOfFileToken = Token.Symbol(TokenKind.EndOfFile, ""); + public static readonly Token NewLineToken = Token.Symbol(TokenKind.NewLine, ""); + + public static readonly Token AddToken = Token.Operator(TokenKind.Add, "+", 4); + public static readonly Token SubtractToken = Token.Operator(TokenKind.Subtract, "-", 4); + public static readonly Token MultiplyToken = Token.Operator(TokenKind.Multiply, "*", 5); + public static readonly Token DivideToken = Token.Operator(TokenKind.Divide, "/", 5); + public static readonly Token ModToken = Token.Operator(TokenKind.Mod, "%", 5); + public static readonly Token PowerToken = Token.Operator(TokenKind.Power, "^", 6); + public static readonly Token CommaToken = Token.Symbol(TokenKind.Comma, ","); + public static readonly Token AssignToken = Token.Symbol(TokenKind.Assign, "="); + public static readonly Token DotToken = Token.Symbol(TokenKind.Dot, "."); + + public static readonly Token LeftParenToken = Token.Symbol(TokenKind.LeftParen, "("); + public static readonly Token RightParenToken = Token.Symbol(TokenKind.RightParen, ")"); + public static readonly Token LeftBracketToken = Token.Symbol(TokenKind.LeftBracket, "["); + public static readonly Token RightBracketToken = Token.Symbol(TokenKind.RightBracket, "]"); + + public static readonly Token NotToken = Token.Symbol(TokenKind.Not, "!"); + public static readonly Token LessThanToken = Token.Operator(TokenKind.LessThan, "<", 2); + public static readonly Token LessThanOrEqualToken = Token.Operator(TokenKind.LessThanOrEqual, "<=", 2); + public static readonly Token EqualToken = Token.Operator(TokenKind.Equal, "==", 1); + public static readonly Token GreaterThanOrEqualToken = Token.Operator(TokenKind.GreaterThanOrEqual, ">=", 2); + public static readonly Token GreaterThanToken = Token.Operator(TokenKind.GreaterThan, ">", 2); + public static readonly Token NotEqualToken = Token.Operator(TokenKind.NotEqual, "!=", 1); + + public static readonly Token IFToken = Token.Symbol(TokenKind.IF, "if"); +} \ No newline at end of file diff --git a/EC.Helper/libs/dahua/linux32/libdhnetsdk.so b/EC.Helper/libs/dahua/linux32/libdhnetsdk.so new file mode 100644 index 0000000..785f8b7 Binary files /dev/null and b/EC.Helper/libs/dahua/linux32/libdhnetsdk.so differ diff --git a/EC.Helper/libs/dahua/linux64/libdhnetsdk.so b/EC.Helper/libs/dahua/linux64/libdhnetsdk.so new file mode 100644 index 0000000..2bae458 Binary files /dev/null and b/EC.Helper/libs/dahua/linux64/libdhnetsdk.so differ diff --git a/EC.Helper/libs/dahua/win64/dhnetsdk.dll b/EC.Helper/libs/dahua/win64/dhnetsdk.dll new file mode 100644 index 0000000..aa3a5e4 Binary files /dev/null and b/EC.Helper/libs/dahua/win64/dhnetsdk.dll differ diff --git a/EC.Helper/libs/hik/linux32/HCNetSDKCom/libHCCoreDevCfg.so b/EC.Helper/libs/hik/linux32/HCNetSDKCom/libHCCoreDevCfg.so new file mode 100644 index 0000000..c0ba2c3 Binary files /dev/null and b/EC.Helper/libs/hik/linux32/HCNetSDKCom/libHCCoreDevCfg.so differ diff --git a/EC.Helper/libs/hik/linux32/HCNetSDKCom/libHCPreview.so b/EC.Helper/libs/hik/linux32/HCNetSDKCom/libHCPreview.so new file mode 100644 index 0000000..0266618 Binary files /dev/null and b/EC.Helper/libs/hik/linux32/HCNetSDKCom/libHCPreview.so differ diff --git a/EC.Helper/libs/hik/linux32/libHCCore.so b/EC.Helper/libs/hik/linux32/libHCCore.so new file mode 100644 index 0000000..a20f02d Binary files /dev/null and b/EC.Helper/libs/hik/linux32/libHCCore.so differ diff --git a/EC.Helper/libs/hik/linux32/libcrypto.so.1.1 b/EC.Helper/libs/hik/linux32/libcrypto.so.1.1 new file mode 100644 index 0000000..3a7f179 Binary files /dev/null and b/EC.Helper/libs/hik/linux32/libcrypto.so.1.1 differ diff --git a/EC.Helper/libs/hik/linux32/libhcnetsdk.so b/EC.Helper/libs/hik/linux32/libhcnetsdk.so new file mode 100644 index 0000000..88817a0 Binary files /dev/null and b/EC.Helper/libs/hik/linux32/libhcnetsdk.so differ diff --git a/EC.Helper/libs/hik/linux32/libssl.so.1.1 b/EC.Helper/libs/hik/linux32/libssl.so.1.1 new file mode 100644 index 0000000..3b5628e Binary files /dev/null and b/EC.Helper/libs/hik/linux32/libssl.so.1.1 differ diff --git a/EC.Helper/libs/hik/linux64/HCNetSDKCom/libHCCoreDevCfg.so b/EC.Helper/libs/hik/linux64/HCNetSDKCom/libHCCoreDevCfg.so new file mode 100644 index 0000000..402b4dc Binary files /dev/null and b/EC.Helper/libs/hik/linux64/HCNetSDKCom/libHCCoreDevCfg.so differ diff --git a/EC.Helper/libs/hik/linux64/HCNetSDKCom/libHCPreview.so b/EC.Helper/libs/hik/linux64/HCNetSDKCom/libHCPreview.so new file mode 100644 index 0000000..9df6065 Binary files /dev/null and b/EC.Helper/libs/hik/linux64/HCNetSDKCom/libHCPreview.so differ diff --git a/EC.Helper/libs/hik/linux64/libHCCore.so b/EC.Helper/libs/hik/linux64/libHCCore.so new file mode 100644 index 0000000..49ce40f Binary files /dev/null and b/EC.Helper/libs/hik/linux64/libHCCore.so differ diff --git a/EC.Helper/libs/hik/linux64/libcrypto.so.1.1 b/EC.Helper/libs/hik/linux64/libcrypto.so.1.1 new file mode 100644 index 0000000..88c3746 Binary files /dev/null and b/EC.Helper/libs/hik/linux64/libcrypto.so.1.1 differ diff --git a/EC.Helper/libs/hik/linux64/libhcnetsdk.so b/EC.Helper/libs/hik/linux64/libhcnetsdk.so new file mode 100644 index 0000000..89a8d7d Binary files /dev/null and b/EC.Helper/libs/hik/linux64/libhcnetsdk.so differ diff --git a/EC.Helper/libs/hik/linux64/libssl.so.1.1 b/EC.Helper/libs/hik/linux64/libssl.so.1.1 new file mode 100644 index 0000000..f3e4481 Binary files /dev/null and b/EC.Helper/libs/hik/linux64/libssl.so.1.1 differ diff --git a/EC.Helper/libs/hik/win64/HCCore.dll b/EC.Helper/libs/hik/win64/HCCore.dll new file mode 100644 index 0000000..266afa3 Binary files /dev/null and b/EC.Helper/libs/hik/win64/HCCore.dll differ diff --git a/EC.Helper/libs/hik/win64/HCNetSDK.dll b/EC.Helper/libs/hik/win64/HCNetSDK.dll new file mode 100644 index 0000000..0c4ef60 Binary files /dev/null and b/EC.Helper/libs/hik/win64/HCNetSDK.dll differ diff --git a/EC.Helper/libs/hik/win64/HCNetSDKCom/HCCoreDevCfg.dll b/EC.Helper/libs/hik/win64/HCNetSDKCom/HCCoreDevCfg.dll new file mode 100644 index 0000000..63a8836 Binary files /dev/null and b/EC.Helper/libs/hik/win64/HCNetSDKCom/HCCoreDevCfg.dll differ diff --git a/EC.Helper/libs/hik/win64/HCNetSDKCom/HCPreview.dll b/EC.Helper/libs/hik/win64/HCNetSDKCom/HCPreview.dll new file mode 100644 index 0000000..92a3cf9 Binary files /dev/null and b/EC.Helper/libs/hik/win64/HCNetSDKCom/HCPreview.dll differ diff --git a/EC.Helper/libs/hik/win64/libcrypto-1_1-x64.dll b/EC.Helper/libs/hik/win64/libcrypto-1_1-x64.dll new file mode 100644 index 0000000..6731338 Binary files /dev/null and b/EC.Helper/libs/hik/win64/libcrypto-1_1-x64.dll differ diff --git a/EC.Helper/libs/hik/win64/libssl-1_1-x64.dll b/EC.Helper/libs/hik/win64/libssl-1_1-x64.dll new file mode 100644 index 0000000..ac5e8fd Binary files /dev/null and b/EC.Helper/libs/hik/win64/libssl-1_1-x64.dll differ diff --git a/EC.Helper/libs/yushi/linux64/libNetDEVSDK.so b/EC.Helper/libs/yushi/linux64/libNetDEVSDK.so new file mode 100644 index 0000000..6363434 Binary files /dev/null and b/EC.Helper/libs/yushi/linux64/libNetDEVSDK.so differ diff --git a/EC.Helper/libs/yushi/win64/NetDEVSDK.dll b/EC.Helper/libs/yushi/win64/NetDEVSDK.dll new file mode 100644 index 0000000..b705019 Binary files /dev/null and b/EC.Helper/libs/yushi/win64/NetDEVSDK.dll differ diff --git a/UnitTest/EC.Helper/CameraSdkTest.cs b/UnitTest/EC.Helper/CameraSdkTest.cs new file mode 100644 index 0000000..0f42aa1 --- /dev/null +++ b/UnitTest/EC.Helper/CameraSdkTest.cs @@ -0,0 +1,121 @@ +using EC.Helper.CameraSDK; + +namespace UnitTest; + +[TestClass] +public class CameraSdkTest +{ + [TestMethod] + public void HiKTest() + { + Console.WriteLine("====HiK=========================="); + + try + { + string ip = "192.168.1.65"; + string username = "admin"; + string password = "hk123456"; + int type = (int)CameraType.HiK; + CameraInfo cameraInfo = CameraInfo.New(type, ip, username, password); + ICameraSDK sdk = new HiKSDK(cameraInfo); + ICameraSDK sdk2 = new HiKSDK(cameraInfo); + sdk.Init(); + sdk2.Init(); + + PtzInfo ptzInfo = sdk.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + + sdk.Destory(); + + Thread.Sleep(1000); + + ptzInfo = sdk.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + + ptzInfo = sdk2.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + throw; + } + Console.WriteLine("================================="); + } + + [TestMethod] + public void DaHuaTest() + { + Console.WriteLine("====DaHua========================"); + + try + { + string ip = "192.168.1.71"; + string username = "admin"; + string password = "hk123456"; + int type = (int)CameraType.DaHua; + CameraInfo cameraInfo = CameraInfo.New(type, ip, username, password); + ICameraSDK sdk = new DaHuaSDK(cameraInfo); + ICameraSDK sdk2 = new DaHuaSDK(cameraInfo); + sdk.Init(); + sdk2.Init(); + PtzInfo ptzInfo = sdk.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + + sdk.Destory(); + + Thread.Sleep(1000); + + ptzInfo = sdk.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + + ptzInfo = sdk2.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + throw; + } + + Console.WriteLine("================================="); + } + + [TestMethod] + public void YuShiTest() + { + Console.WriteLine("====YuShi========================"); + + try + { + string ip = "192.168.1.109"; + string username = "admin"; + string password = "hk123456"; + int type = (int)CameraType.YuShi; + CameraInfo cameraInfo = CameraInfo.New(type, ip, username, password); + ICameraSDK sdk = new YuShiSDK(cameraInfo); + ICameraSDK sdk2 = new YuShiSDK(cameraInfo); + sdk.Init(); + sdk2.Init(); + PtzInfo ptzInfo = sdk.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + + sdk.Destory(); + + Thread.Sleep(1000); + + ptzInfo = sdk.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + + ptzInfo = sdk2.GetPtzInfo(); + Console.WriteLine($"{ptzInfo.Pan}, {ptzInfo.Tilt}, {ptzInfo.Zoom}"); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + throw; + } + + Console.WriteLine("================================="); + } +} \ No newline at end of file diff --git a/UnitTest/EC.Helper/RabbitFormulaTest.cs b/UnitTest/EC.Helper/RabbitFormulaTest.cs new file mode 100644 index 0000000..4d8022e --- /dev/null +++ b/UnitTest/EC.Helper/RabbitFormulaTest.cs @@ -0,0 +1,6 @@ +namespace UnitTest.EC.Helper; + +[TestClass] +public class RabbitFormulaTest +{ +} \ No newline at end of file diff --git a/UnitTest/UnitTest.csproj b/UnitTest/UnitTest.csproj new file mode 100644 index 0000000..4193ce6 --- /dev/null +++ b/UnitTest/UnitTest.csproj @@ -0,0 +1,22 @@ + + + + net6.0 + enable + enable + + false + + + + + + + + + + + + + + diff --git a/UnitTest/Usings.cs b/UnitTest/Usings.cs new file mode 100644 index 0000000..ab67c7e --- /dev/null +++ b/UnitTest/Usings.cs @@ -0,0 +1 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; \ No newline at end of file