修复项目上出现的BUG

This commit is contained in:
葛林强 2026-03-23 13:50:54 +08:00
parent f601365450
commit 525491eaeb
11 changed files with 395 additions and 626 deletions

View File

@ -1,12 +0,0 @@
package com.listenvision;
/*********************************************************************************************
* LedServerCallback 动态库回调Java方法实时告知上下线控制卡
* Msg 1有控制卡上线 2有控制卡下线
* wParam 暂时没用
* networkIdStr 控制卡唯一标识
********************************************************************************************/
public interface LxLedCallBack {
public abstract void LedServerCallback(int Msg, int wParam, String networkIdStr);
}

View File

@ -1,553 +0,0 @@
package com.listenvision;
public class LxLedCommunication {
static{
System.loadLibrary("lv_led");
}
/********************************************************************************************
* InitLedType 初始化控制卡型号程序启动初始化调用一次即可
* <p>
* 参数说明
* LedType 卡型号 0 T/A/U/XC/W 系列
1 E 系列
2 X 系列
3 C 系列
********************************************************************************************/
public native static void InitLedType(int LedType);
/********************************************************************************************
* CreateProgram 创建节目对象成功返回节目对象句柄注意此处屏宽高及颜色参数必需与设置屏参的屏宽高及颜色一致否则发送时会提示错误
* <p>
* 参数说明
* LedWidth 屏的宽度
* LedHeight 屏的高度
* ColorType 屏的颜色 1.单色 2.双基色 3.三基色 C卡全彩参数为3 X系列卡参数固定为 4
* GrayLevel 灰度等级 赋值 1-5对应的灰度等级分别为 ,4,8,16,32 除C卡外其它卡传0
* SaveType 节目保存位置默认为0保存为flash节目3保存为ram节目flash节目掉电不清除ram节目掉电清除应用场景需要实时刷新的建议保持为ram节目
* 返回值
* 0 创建节目对象失败
* 非0 创建节目对象成功
********************************************************************************************/
public native static long CreateProgram(int LedWidth,int LedHeight,int ColorType,int GrayLevel,int SaveType);
/*********************************************************************************************
* AddProgram 添加一个节目
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* ProgramTime 节目播放时长 0.节目播放时长 非0.指定播放时长
* LoopCount 循环播放次数 1-255
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddProgram(long hProgram,int ProgramNo,int ProgramTime,int LoopCount);
/*********************************************************************************************
* LV_AddImageTextArea 添加一个图文区域
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* l 区域左上角横坐标
* t 区域左上角纵坐标
* w 区域宽度
* h 区域高度
* nLayout 区域层号0.前景区默认 1.背景区 除C系列其它默认为1
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddImageTextArea(long hProgram,int ProgramNo,int AreaNo,int l,int t,int w,int h,int nLayout);
/*********************************************************************************************
* AddFileToImageTextArea 添加一个文件到图文区
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* FilePath 文件路径支持的文件类型有 txt rtf bmp gif png jpg jpeg tiff
* InStyle 入场特技取值范围 0-38具体查看开发文档
* nSpeed 特技速度 (取值范围1-255)值越大速度越慢
* DelayTime 停留时间 (1-65535)
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddFileToImageTextArea(long hProgram,int ProgramNo,int AreaNo,String FilePath,int InStyle,int nSpeed,int DelayTime);
/*********************************************************************************************
* AddMultiLineTextToImageTextArea 添加一个多行文本到图文区
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* AddType 添加的类型 0.为字符串 1.文件只支持txt和rtf文件
* AddStr AddType为为字符串数据,AddType为1则为文件路径 换行符\n
* FontName 字体名
* FontSize 字体大小
* FontColor 字体颜色 格式BBGGRR 0xff 红色 0xff00 绿色 0xffff黄色
* FontBold 是否加粗 0不加粗 1加粗
* FontItalic 是否是斜体 0 不斜 1斜
* FontUnderline 是否下划线 0不加下划线 1加下划线
* InStyle 入场特技取值范围 0-38具体查看开发文档
* nSpeed 特技速度 (取值范围1-255)值越大速度越慢
* DelayTime 停留时间 (1-65535) 当入场特技为连续左移连续右移连续上移连续下移时此参数无效
* nAlignment 左右居中对齐方式 0.左对齐 1.右对齐 2.水平居中 注意只对字符串和txt文件有效
* IsVCenter 是否垂直居中 0.置顶默认 1.垂直居中
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddMultiLineTextToImageTextArea(long hProgram,int ProgramNo,int AreaNo,int AddType,String AddStr,String FontName,int FontSize,int FontColor,int FontBold,int FontItalic,int FontUnderline,int InStyle,int nSpeed,int DelayTime,int nAlignment,int IsVCenter);
/*********************************************************************************************
* AddStaticTextToImageTextArea 添加一个静止文本到图文区
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* AddType 添加的类型 0.为字符串 1.文件只支持txt和rtf文件
* AddStr AddType为0则为字符串数据,AddType为1则为文件路径
* FontName 字体名
* FontSize 字体大小
* FontColor 字体颜色 格式BBGGRR 0xff 红色 0xff00 绿色 0xffff黄色
* FontBold 是否加粗 0不加粗 1加粗
* FontItalic 是否是斜体 0 不斜 1斜
* FontUnderline 是否下划线 0不加下划线 1加下划线
* DelayTime 停留时间 (1-65535) 当入场特技为连续左移连续右移连续上移连续下移时此参数无效
* nAlignment 左右居中对齐方式 0.左对齐 1.右对齐 2.水平居中 注意只对字符串和txt文件有效
* IsVCenter 是否垂直居中 0.置顶默认 1.垂直居中
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddStaticTextToImageTextArea(long hProgram,int ProgramNo,int AreaNo,int AddType,String AddStr,String FontName,int FontSize,int FontColor,int FontBold,int FontItalic,int FontUnderline,int DelayTime,int nAlignment,int IsVCenter);
/*********************************************************************************************
* AddSinglelineTextToImageTextArea 添加一个单行文本到图文区
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* AddType 添加的类型 0.为字符串 1.文件只支持txt和rtf文件
* AddStr AddType为0则为字符串数据,AddType为1则为文件路径
* FontName 字体名
* FontSize 字体大小
* FontColor 字体颜色 0xff 红色 0xff00 绿色 0xffff黄色
* FontBold 是否加粗 0不加粗 1加粗
* FontItalic 是否是斜体 0 不斜 1斜
* FontUnderline 是否下划线 0不加下划线 1加下划线
* InStyle 入场特技取值范围 0-38体查看开发文档
* nSpeed 特技速度 (取值范围1-255)值越大速度越慢
* DelayTime 停留时间 (1-65535)
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddSinglelineTextToImageTextArea(long hProgram,int ProgramNo,int AreaNo,int AddType,String AddStr,String FontName,int FontSize,int FontColor,int FontBold,int FontItalic,int FontUnderline,int InStyle,int nSpeed,int DelayTime);
/*********************************************************************************************
* AddSinglelineTextToImageTextArea 添加一个数字时钟区域
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* l 区域左上角横坐标
* t 区域左上角纵坐标
* w 区域宽度
* h 区域高度
* FontName 字体名
* FontSize 字体大小
* FontColor 字体颜色 0xff 红色 0xff00 绿色 0xffff黄色
* FontBold 是否加粗 0不加粗 1加粗
* FontItalic 是否是斜体 0 不斜 1斜
* FontUnderline 是否下划线 0不加下划线 1加下划线
* IsYear 是否显示年 1为显示 0不显示 下同
* IsWeek 是否显示星期
* IsMonth 是否显示月
* IsDay 是否显示日
* IsHour 是否显示时
* IsMinute 是否显示分
* IsSecond 是否显示秒
* DateFormat 日期格式 0.YYYY年MM月DD日 1.YY年MM月DD日 2.MM/DD/YYYY 3.YYYY/MM/DD 4.YYYY-MM-DD 5.YYYY.MM.DD 6.MM.DD.YYYY 7.DD.MM.YYYY
* DateColor 日期字体颜色0xff 红色 0xff00 绿色 0xffff黄色
* WeekFormat 星期格式 0.星期X 1.Monday 2.Mon.
* WeekColor 星期字体颜色0xff 红色 0xff00 绿色 0xffff黄色
* TimeFormat 时间格式 0.HH时mm分ss秒 1.HH時mm分ss秒 2.HH:mm:ss 3.上午 HH:mm:ss 4.AM HH:mm:ss 5.HH:mm:ss 上午 6.HH:mm:ss AM
* TimeColor 时间字体颜色0xff 红色 0xff00 绿色 0xffff黄色
* IsMutleLineShow 0 单行 1多行
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddDigitalClockArea(long hProgram,int ProgramNo,int AreaNo,int l,int t,int w,int h,String FontName,int FontSize,int FontColor,int FontBold,int FontItalic,int FontUnderline,int IsYear,int IsWeek,int IsMonth,int IsDay,int IsHour,int IsMinute,int IsSecond,int DateFormat,int DateColor,int WeekFormat,int WeekColor,int TimeFormat,int TimeColor,int IsMutleLineShow);
/*********************************************************************************************
* AddTimeArea 添加一个计时区域
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* l 区域左上角横坐标
* t 区域左上角纵坐标
* w 区域宽度
* h 区域高度
* FontName 字体名
* FontSize 字体大小
* //FontColor 字体颜色 格式BBGGRR 0xff 红色 0xff00 绿色 0xffff黄色
* FontBold 是否加粗 0不加粗 1加粗
* FontItalic 是否是斜体 0 不斜 1斜
* FontUnderline 是否下划线 0不加下划线 1加下划线
* TimeColor 时间字体颜色0xff 红色 0xff00 绿色 0xffff黄色
* TxtColor 自定义文字字体颜色0xff 红色 0xff00 绿色 0xffff黄色
* ShowStyle 显示格式 0.xx天xx时xx分xx秒 1.xx天xx時xx分xx秒 2.xxDayxxHourxxMinxxSec 3.XXdXXhXXmXXs 4.xx:xx:xx:xx
* IsMutleLineShow 0 单行 1多行
* TxtStr 自定义文字字符串
* nYear; 结束年
* nMonth; 结束月
* nDay; 结束日
* nHour; 结束时
* nMinute; 结束分
* nSecond; 结束秒
* IsShowDay; 是否显示天
* IsShowHour; 是否显示时
* IsShowMinute; 是否显示分
* IsShowSecond; 是否显示秒
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddTimeArea(long hProgram,int ProgramNo,int AreaNo,int l,int t,int w,int h,String FontName,int FontSize,int FontBold,int FontItalic,int FontUnderline,int TimeColor,int TxtColor,int ShowStyle,int IsMutleLineShow,String TxtStr,int nYear,int nMonth,int nDay,int nHour,int nMinute,int nSecond,int IsShowDay,int IsShowHour,int IsShowMinute,int IsShowSecond);
/*********************************************************************************************
* AddVoiceArea 添加一个语音区域 (文本中可以加入文本控制标记来对语音合成发音人音量语速语调等的设置,文本控制标记请查看语音协议)
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* VoiceStr; 文本
* DelayTime; 间隔时间
* PlayCount; 播放次数 取值范围1-255
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddVoiceArea(long hProgram,int ProgramNo,int AreaNo,String VoiceStr,int DelayTime,int PlayCount);
/*********************************************************************************************
* LV_RefreshVoiceArea 刷新语音区域
* <p>
* 参数说明
* IpStr LED屏IP 格式例如 192.168.1.100 / 广域网开发时,指定LED屏网络唯一ID
* NeiMaStr 刷新的数据字符串,格式可以查看<<语音区域局部更新协议>>文档
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int RefreshVoiceArea(String IpStr, String NeiNaStr);
/*********************************************************************************************
* AddNeiMaArea 添加一个内码区域
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* l 区域左上角横坐标
* t 区域左上角纵坐标
* w 区域宽度
* h 区域高度
* NeiMaStr 字符串
* FontSize 字体大小 16 24 32
* FontColor 字体颜色 格式BBGGRR 0xff 红色 0xff00 绿色 0xffff黄色
* InStyle 入场特技 取值范围 0-9具体值如下
* 0=立即显示
* 1=随机
* 2=左移
* 3=右移
* 4=上移
* 5=下移
* 6=连续左移
* 7=连续右移
* 8=连续上移
* 9=连续下移
* nSpeed 特技速度 (取值范围1-255) 值越大速度则越慢
* DelayTime 停留时间 (1-65535) 当入场特技为连续左移连续右移连续上移连续下移时此参数无效
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddNeiMaArea(long hProgram,int ProgramNo,int AreaNo,int l,int t,int w,int h,String NeiMaStr,int FontSize,int FontColor,int InStyle,int nSpeed,int DelayTime);
/*********************************************************************************************
* LV_RefreshNeiMaArea 刷新内码区域
* <p>
* 参数说明
* IpStr LED屏IP 格式例如 192.168.1.100 / 广域网开发时,指定LED屏网络唯一ID
* NeiMaStr 刷新的数据字符串,格式可以查看<<内码区域局部更新协议>>文档
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int RefreshNeiMaArea(String IpStr, String NeiNaStr);
/*********************************************************************************************
* DeleteProgram 销毁节目对象(注意如果此节目对象不再使用请调用此函数销毁否则会造成内存泄露)
* <p>
* 参数说明
* hProgram 节目对象句柄
********************************************************************************************/
public native static void DeleteProgram(long hProgram);
/*********************************************************************************************
* NetWorkSend 发送节目此发送为一对一发送
* <p>
* 参数说明
* IpStr LED屏IP 格式例如 192.168.1.100 / 广域网开发时,指定LED屏网络唯一ID
* hProgram 节目对象句柄
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int NetWorkSend(String IpStr,long hProgram);
/*********************************************************************************************
* SetBasicInfo 设置基本屏参
* <p>
* 参数说明
* IpStr LED屏的IP 格式例如 192.168.1.100
* ColorType 屏的颜色 1.单色 2.双基色 3.三基色 C卡全彩参数为3 X系列卡参数固定4
* GrayLevel 灰度等级 赋值 1-5对应的灰度等级分别为 ,4,8,16,32
* LedWidth 屏的宽度点数
* LedHeight 屏的高度点数
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int SetBasicInfo(String IpStr,int ColorType,int GrayLevel,int LedWidth,int LedHeight);
/*********************************************************************************************
* SetOEDA 设置OE DA
* <p>
* 参数说明
* IpStr LED屏的IP
* Oe OE 0.低有效 1.高有效
* Da DA 0.负极性 1.正极性
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int SetOEDA(String IpStr,int Oe,int Da);
/*********************************************************************************************
* AdjustTime 校时
* <p>
* 参数说明
* IpStr LED屏的IP
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AdjustTime(String IpStr);
/*********************************************************************************************
* PowerOnOff 开关屏
* <p>
* 参数说明
* IpStr LED屏的IP
* OnOff 开关值 0.开屏 1.关屏 2.重启
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int PowerOnOff(String IpStr,int OnOff);
/*********************************************************************************************
* TimePowerOnOff 定时开关屏
* <p>
* 参数说明 当参数起始时间和结束时间都都为0时既是取消定时开关屏
* IpStr LED屏的IP
* StartHour 起始小时
* StartMinute 起始分钟
* EndHour 结束小时
* EndMinute 结束分钟
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int TimePowerOnOff(String IpStr,int StartHour,int StartMinute,int EndHour,int EndMinute);
/*********************************************************************************************
* SetBrightness 设置亮度
* <p>
* 参数说明
* IpStr LED屏的IP
* BrightnessValue 亮度值 0~15
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int SetBrightness(String IpStr,int BrightnessValue);
/*********************************************************************************************
* TestOnline LED测试通讯是否正常
* <p>
* 参数说明
* IpStr LED屏的IP
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int TestOnline(String IpStr);
/*********************************************************************************************
* LedInitServer 启动控制卡心跳包服务C2M C4M才支持
* <p>
* 参数说明
* port 监听的端口
* 返回值
* 0 成功
* 非0 失败调用LV_GetError来获取错误信息
********************************************************************************************/
public native static int LedInitServer(int port);
/*********************************************************************************************
* LedShudownServer 断开控制卡心跳包服务C2M C4M才支持
********************************************************************************************/
public native static int LedShudownServer();
/*********************************************************************************************
* RegisterLedServerCallback 注册回调动态库才会调用LedServerCallback实时告知上下线控制卡C2M C4M才支持
* cb 回调对象
********************************************************************************************/
public native static void RegisterLedServerCallback(LxLedCallBack cb);
/*********************************************************************************************
* AddBorder 添加一个边框
* <p>
* 参数说明
* hProgram 节目对象句柄
* ProgramNo 节目号 取值范围0-255)从0开始
* AreaNo 区域号 取值范围1-255
* l 区域左上角横坐标
* t 区域左上角纵坐标
* w 区域宽度
* h 区域高度
* BorderType 边框类型 0单色 1炫色 2全彩
* BorderValue 边框的值 具体可参考PC客户端软件对应的选项
* BorderColor 边框颜色 只有单色才可设置颜色
* BorderStyle 边框特技 0固定 1顺时针 2逆时针 3 闪烁
* BorderSpeed 边框速度 0-31 越大越慢
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int AddBorder(long hProgram,int ProgramNo,int AreaNo,int l,int t,int w,int h,int BorderType, int BorderValue, int BorderColor, int BorderStyle, int BorderSpeed);
/*********************************************************************************************
* SetLedCommunicationParameter 设置LED屏的网络信息
* <p>
* 参数说明
* IpStr LED屏的IP
* NewIp LED屏的新IP
* NewNetMask LED屏的新子网掩码
* NewGateway LED屏的新网关
* NewMac LED屏的新mac地址
* IsClient 1为启动客户端模式 0为不起动 //当为0时以下参数设置为0
* ServerIp 服务器IP
* ServerPort 端口
* IsDHCP 1自动分配 0手动配置
* IsHeartBeat 1启动心跳包 0不起动心跳包
* HeartBeatTime LED心跳包时间
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int SetLedCommunicationParameter(String IpStr,String NewIp,String NewNetMask,String NewGateway,String NewMac,int IsClient,String ServerIp,int ServerPort,int IsDHCP,int IsHeartBeat,int HeartBeatTime);
/*********************************************************************************************
* SetLedServerInfo 设置LED屏的服务器信息
* <p>
* 参数说明
* IpStr LED屏的IP
* IsClient 1为启动客户端模式 0为不启动(当前带有广域网功能的卡默认为启动)
* ServerIp 服务器IP
* ServerPort 端口
* HeartBeatTime LED心跳包时间(最小20秒)
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int SetLedServerInfo(String IpStr,int IsClient,String ServerIp,int ServerPort,int HeartBeatTime);
/*********************************************************************************************
* GetErrorCodeInfo 获取错误信息
* 参数说明
* nErrCode 错误码
* 返回值
* 返回错误信息
********************************************************************************************/
public native static String GetErrorCodeInfo(int nErrCode);
/*********************************************************************************************
* SetRelay 设置LED屏的继电器信息 C8 T8支持
* <p>
* 参数说明
* IpStr LED屏的IP
* type 控制模式 0:手动模式 1:定时模式
* manualSwitch 手动模式时的开关值 0: 1:
* flag1 定时模式的第一组时间标志 0:无效 1:有效
* startTime1 定时模式的第一组起始时间,格式如:"12:00:00"
* endTime1 定时模式的第一组结束时间,格式如:"13:59:59"
* flag2 定时模式的第二组时间标志 0:无效 1:有效
* startTime2 定时模式的第二组起始时间,格式如:"14:00:00"
* endTime2 定时模式的第二组结束时间,格式如:"15:59:59"
* flag3 定时模式的第三组时间标志 0:无效 1:有效
* startTime3 定时模式的第三组起始时间,格式如:"16:00:00"
* endTime3 定时模式的第三组结束时间,格式如:"17:59:59"
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int SetRelay(String IpStr, int type,int manualSwitch, int flag1, String startTime1, String endTime1 , int flag2,String startTime2,String endTime2, int flag3,String startTime3,String endTime3);
/*********************************************************************************************
* SetProgramTime 设置节目为定时节目
* <p>
* 参数说明
* hProgram 节目句柄
* ProgramNo 节目ID
* EnableFlag 启用定时的标记ENABLE_DATE为启用日期,ENABLE_TIME为启用时间,ENABLE_WEEK为启用星期,可用或运算进行组合 ENABLE_DATE | ENABLE_TIME | ENABLE_WEEK
* WeekValue 启用星期后选择要定时的星期里的某些天用宏 WEEK_MON,WEEK_TUES,WEEK_WEN,WEEK_THUR,WEEK_FRI,WEEK_SAT,WEEK_SUN 通过或运算进行组合
* 其他参数 起始年月日时分秒和结束年月日时分秒
* 返回值
* 0 成功
* 非0 失败
********************************************************************************************/
public native static int SetProgramTime(int hProgram, int ProgramNo, int EnableFlag,int WeekValue, int StartYear, int StartMonth, int StartDay,int StartHour, int StartMinute, int StartSecond, int EndYear, int EndMonth, int EndDay, int EndHour, int EndMinute, int EndSecond);
}

View File

@ -1,3 +0,0 @@
此软件包是灵信LED屏通讯的相关方法严禁修改包名已经上级包名修改了就调用不了了
只能64位运行32位无法运行
如连接失败请检查导入的DLL是否正确官网的依赖是否都安装官网依赖仅支持Windows系统

View File

@ -7,9 +7,11 @@ import org.wcs.business.data.intf.IDataRecorder;
import org.wcs.constant.enums.database.EquipmentTypeEnum;
import org.wcs.mapper.intf.AppRecordApiRequestService;
import org.wcs.mapper.intf.AppRecordErrService;
import org.wcs.mapper.intf.AppRecordScanService;
import org.wcs.mapper.intf.AppRecordTaskMsgService;
import org.wcs.model.po.app.AppRecordApiRequest;
import org.wcs.model.po.app.AppRecordErr;
import org.wcs.model.po.app.AppRecordScan;
import org.wcs.model.po.app.AppRecordTaskMag;
import org.wcs.plugin.webHttpClient.model.HttpResponse;
import org.wcs.utils.AppStringUtils;
@ -29,6 +31,7 @@ public class DataRecorder implements IDataRecorder {
private final AppRecordApiRequestService recordApiRequestDao; // 请求外部系统的数据表操作
private final AppRecordTaskMsgService recordStockMsgDao;
private final AppRecordErrService recordErrService;
private final AppRecordScanService recordScanService;
/**
* 记录接口请求外部数据
@ -89,4 +92,25 @@ public class DataRecorder implements IDataRecorder {
recordErr.setErrCode(AppStringUtils.isEmptyOr(String.valueOf(errorCode), "-"));
recordErrService.insert(recordErr);
}
/**
* 扫描入库码
* @param scanId 扫描ID
* @param code 扫描码
*/
@Override
public void recordStockScanCode(String scanId, String code) {
AppRecordScan recordScan = new AppRecordScan();
recordScan.setRecordId(AppUUIDUtils.getNewUUID());
recordScan.setLocation(AppStringUtils.isEmptyOr(scanId, ""));
recordScan.setCode(AppStringUtils.isEmptyOr(code, ""));
recordScan.setScanTime(LocalDateTime.now());
recordScan.setSize(AppStringUtils.isEmptyOr("0", ""));
recordScan.setWeight(BigDecimal.ZERO);
recordScan.setLength(BigDecimal.ZERO);
recordScan.setWidth(BigDecimal.ZERO);
recordScan.setHeight(BigDecimal.ZERO);
recordScan.setRemark("");
recordScanService.insert(recordScan);
}
}

View File

@ -30,4 +30,10 @@ public interface IDataRecorder {
void recordStackerErr(String equipmentName, String equipmentId, Integer errorCode);
/**
* 记录扫码数据
* @param scanId 扫码ID
* @param code 扫码内容
*/
void recordStockScanCode(String scanId, String code);
}

View File

@ -0,0 +1,145 @@
package org.wcs.business.redis;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.wcs.model.po.app.AppStockScan;
import org.wcs.utils.AppStringUtils;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 扫码器缓存
*/
@Component
@RequiredArgsConstructor
public class ScanRedis {
/**
* Redis操作类
*/
private final StringRedisTemplate stringRedisTemplate;
public static final String SCANNER_DATA_REDIS_KEY = "WCS:CACHE:SCANNER_JOB_KEY"; // 扫码数据的缓存键
public static final String SCANNER_DELAY_REDIS_KEY = "WCS:CACHE:SCANNER_DELAY_KEY"; // 扫码延迟的缓存键
public static final String SCANNER_CODE_REDIS_KEY = "WCS:CACHE:SCANNER_CODE_KEY"; // 扫码条码的缓存键
public static final String SCANNER_TCP_DATA_REDIS_KEY = "WCS:CACHE:SCANNER_TCP_DATA_KEY"; // TCP扫码数据的缓存键
/**
* 设置扫码数据
* @param value 扫码数据
* @param timeout 超时时间
* @return 设置结果
*/
public boolean setScannerData(String value, long timeout) {
try {
stringRedisTemplate.opsForValue().set(SCANNER_DATA_REDIS_KEY, value, timeout, TimeUnit.SECONDS);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 获取扫码数据
* @return 扫码数据
*/
public String getScannerData() {
try {
return stringRedisTemplate.opsForValue().get(SCANNER_DATA_REDIS_KEY);
} catch (Exception e) {
return null;
}
}
/**
* 设置扫码延迟
* @param scanId 扫码id
* @param timeout 超时
* @return 设置结果
*/
public boolean setScanDelay(String scanId, long timeout) {
try {
stringRedisTemplate.opsForValue().set(SCANNER_DELAY_REDIS_KEY + ":" + scanId, "Y", timeout, TimeUnit.SECONDS);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 检查扫码冷却
* @param scanId 扫码id
* @return true 表示扫码冷却false 表示没有扫码冷却
*/
public boolean checkScanDelay(String scanId) {
try {
return stringRedisTemplate.opsForValue().get(SCANNER_DELAY_REDIS_KEY + ":" + scanId) != null;
} catch (Exception e) {
return false;
}
}
/**
* 设置扫码条码
* @param scanId 扫码id
* @param code 条码
* @param timeout 超时
* @return 缓存结果
*/
public boolean setScanCode(String scanId, String code, long timeout) {
try {
stringRedisTemplate.opsForValue().set(SCANNER_CODE_REDIS_KEY + ":" + scanId, code, timeout, TimeUnit.SECONDS);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 获取扫码条码
* @param scanId 扫码id
* @return 条码
*/
public String getScanCode(String scanId) {
try {
return stringRedisTemplate.opsForValue().get(SCANNER_CODE_REDIS_KEY + ":" + scanId);
} catch (Exception e) {
return null;
}
}
/**
* 设置TCP扫码数据
* @param value 扫码数据
* @param timeout 超时
* @return 缓存结果
*/
public boolean setScannerTcpData(List<AppStockScan> value, long timeout) {
try {
stringRedisTemplate.opsForValue().set(SCANNER_TCP_DATA_REDIS_KEY, AppStringUtils.objectToString(value), timeout, TimeUnit.SECONDS);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 获取TCP扫码数据
* @return 扫码数据
*/
public List<AppStockScan> getScannerTcpData() {
try {
return JSONObject.parseObject(stringRedisTemplate.opsForValue().get(SCANNER_TCP_DATA_REDIS_KEY), new TypeReference<>() {});
} catch (Exception e) {
return null;
}
}
}

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.wcs.mapper.AppRecordScanMapper;
import org.wcs.mapper.intf.AppRecordScanService;
import org.wcs.model.bo.db.DataBaseActionIntResult;
import org.wcs.model.bo.tuple.Tuple2;
import org.wcs.model.dto.serve.recordScan.QueryRecordScanReq;
import org.wcs.model.po.app.AppRecordScan;
@ -65,6 +66,23 @@ public class AppRecordScanDao extends ServiceImpl<AppRecordScanMapper, AppRecord
}
}
/**
* 插入数据
* @param appRecordScan 数据
* @return 插入数量
*/
@Override
public DataBaseActionIntResult insert(AppRecordScan appRecordScan) {
if(appRecordScan == null) {
return new DataBaseActionIntResult(new Exception("待插入数据为空"));
}
try {
return new DataBaseActionIntResult(baseMapper.insert(appRecordScan));
} catch (Exception e) {
return new DataBaseActionIntResult(e);
}
}
/**
* 删除指定天数前的数据
* @param saveDays 保存天数

View File

@ -1,6 +1,7 @@
package org.wcs.mapper.intf;
import com.baomidou.mybatisplus.extension.service.IService;
import org.wcs.model.bo.db.DataBaseActionIntResult;
import org.wcs.model.bo.tuple.Tuple2;
import org.wcs.model.dto.serve.recordScan.QueryRecordScanReq;
import org.wcs.model.po.app.AppRecordScan;
@ -12,6 +13,7 @@ public interface AppRecordScanService extends IService<AppRecordScan> {
Tuple2<Long, List<AppRecordScan>> query(QueryRecordScanReq queryRecordScanReq, Integer pageSize, Integer pageIndex);
List<AppRecordScan> query(QueryRecordScanReq queryRecordScanReq);
DataBaseActionIntResult insert(AppRecordScan appRecordScan); // 插入数据
int deleteBySaveDays(int saveDays); // 删除指定天数前的数据
}

View File

@ -5,9 +5,7 @@ import org.wcs.plugin.tcp.enums.SocketStatusEnum;
import org.wcs.plugin.tcp.intf.ISocketClientEvent;
import org.wcs.plugin.tcp.model.SocketDataItem;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
@ -115,7 +113,9 @@ public class SocketClient {
*/
private void connect(List<SocketDataItem> socketDataItemList) {
for (SocketDataItem socketDataItem : socketDataItemList) {
Thread thread = new Thread(() -> connect(socketDataItem));
Thread thread = new Thread(() -> {
connect(socketDataItem);
});
thread.start();
}
}
@ -148,18 +148,19 @@ public class SocketClient {
while (true) {
try {
InputStream inputStream = socket.getInputStream();
byte[] bytes = new byte[socketDataItem.getReceiveBytesLength()];
byte[] bytes = new byte[1024];
int read = inputStream.read(bytes);
String message = new String(bytes, 0, read, StandardCharsets.US_ASCII).trim();
socketDataItem.setLastReceiveMessageTime(LocalDateTime.now());
if(socketClientEvent != null) {
socketClientEvent.onBytes(socketDataItem, bytes);
String message = new String(bytes, 0, read, StandardCharsets.US_ASCII).trim();
socketClientEvent.onMessage(socketDataItem, message); // 触发收到数据事件
}
} catch (Exception e) {
// 断开的结果
socket = null;
socketDataItem.setSocketStatus(SocketStatusEnum.DISCONNECTED);
socketDataItem.setSocket(null);
socketDataItem.setSocket(socket);
if(socketClientEvent != null) {
socketClientEvent.onDisconnect(socketDataItem); // 触发断开连接事件
}
@ -168,8 +169,9 @@ public class SocketClient {
}
} catch (IOException e) {
// 连接失败的结果
socket = null;
socketDataItem.setSocketStatus(SocketStatusEnum.ERROR);
socketDataItem.setSocket(null);
socketDataItem.setSocket(socket);
if(socketClientEvent != null) {
socketClientEvent.onError(socketDataItem, e); // 触发连接失败事件
}
@ -181,7 +183,7 @@ public class SocketClient {
*/
public void checkAndReconnect() {
List<SocketDataItem> disConnectSocketDataItems = getDisConnectSocket();
if (disConnectSocketDataItems != null) {
if (disConnectSocketDataItems != null && !disConnectSocketDataItems.isEmpty()) {
connect(disConnectSocketDataItems);
}
}
@ -223,25 +225,21 @@ public class SocketClient {
return false;
}
// 如果上次收到消息时间和当前时间差距不超过5秒则默认认为连接正常
LocalDateTime lastReceiveMessageTime = socketDataItem.getLastReceiveMessageTime();
if(lastReceiveMessageTime == null || lastReceiveMessageTime.plusSeconds(5).isBefore(LocalDateTime.now())) {
return true;
}
// LocalDateTime lastReceiveMessageTime = socketDataItem.getLastReceiveMessageTime();
// if(lastReceiveMessageTime == null || lastReceiveMessageTime.plusSeconds(5).isBefore(LocalDateTime.now())) {
// return true;
// }
// 检测Socket是否断开发送心跳包
Socket socket = socketDataItem.getSocket();
if(socket == null) {
socketDataItem.setSocketStatus(SocketStatusEnum.DISCONNECTED);
return false;
}
// if(socket == null) {
// socketDataItem.setSocketStatus(SocketStatusEnum.DISCONNECTED);
// return false;
// }
if(socketDataItem.getHeartBeatString() == null) {
socketDataItem.setHeartBeatString("");
}
byte[] bytes = socketDataItem.getHeartBeatString().getBytes(StandardCharsets.US_ASCII);
try {
OutputStream outputStream = socket.getOutputStream();
outputStream.write(bytes);
outputStream.flush();
} catch (IOException e) {
String sendResult = sendMessage(socketDataItem, socketDataItem.getHeartBeatString());
if(sendResult != null) {
// 发送失败了则认为断开了
try {
socket.getOutputStream().close();
@ -250,22 +248,35 @@ public class SocketClient {
socket.shutdownInput();
socket.close();
} catch (IOException ignored) {}
socket = null;
socketDataItem.setSocketStatus(SocketStatusEnum.DISCONNECTED);
socketDataItem.setSocket(null);
socketDataItem.setSocket(socket);
return false;
}
byte[] bytes = socketDataItem.getHeartBeatString().getBytes(StandardCharsets.US_ASCII);
try {
OutputStream outputStream = socket.getOutputStream();
outputStream.write(bytes);
outputStream.flush();
} catch (IOException e) {
}
try {
if(socket.isClosed() || !socket.isConnected()) {
socket = null;
socketDataItem.setSocketStatus(SocketStatusEnum.DISCONNECTED);
socketDataItem.setSocket(null);
socketDataItem.setSocket(socket);
return false;
}
return true;
} catch (Exception ignored) {
socket = null;
socketDataItem.setSocketStatus(SocketStatusEnum.DISCONNECTED);
socketDataItem.setSocket(null);
socketDataItem.setSocket(socket);
return false;
}
//return true;
}
/**
@ -292,16 +303,15 @@ public class SocketClient {
* @param message 消息
* @return 发送结果
*/
public String sendMessage(SocketDataItem socketDataItem, String message) {
public synchronized String sendMessage(SocketDataItem socketDataItem, String message) {
if(socketDataItem == null || socketDataItem.getSocket() == null) {
return "Socket连接不存在或者未连接";
}
Socket socket = socketDataItem.getSocket();
synchronized (socket) {
try(OutputStream outputStream = socket.getOutputStream()) {
try {
OutputStream outputStream = socket.getOutputStream();
try {
byte[] bytes = message.getBytes(StandardCharsets.US_ASCII);
outputStream.write(bytes);
outputStream.flush();
return null;
@ -312,7 +322,6 @@ public class SocketClient {
return "发送失败,异常信息:" + e.getMessage();
}
}
}
/**
* 发送消息返回异常信息发送成功返回 null

View File

@ -9,6 +9,9 @@ import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.wcs.annotation.ScanMethodTag;
import org.wcs.business.data.impl.DataRecorder;
import org.wcs.business.data.intf.IDataRecorder;
import org.wcs.business.redis.ScanRedis;
import org.wcs.business.stock.intf.IScanMethod;
import org.wcs.constant.enums.common.TrueOrFalseEnum;
import org.wcs.constant.enums.database.StockScanTypeEnum;
@ -17,6 +20,10 @@ import org.wcs.model.bo.tuple.Tuple2;
import org.wcs.model.po.app.AppStockScan;
import org.wcs.plugin.plc.PlcCommunicationFactory;
import org.wcs.plugin.plc.model.ScanInfo;
import org.wcs.plugin.plc.model.TaskConveyStatus;
import org.wcs.plugin.tcp.SocketClient;
import org.wcs.plugin.tcp.intf.ISocketClientEvent;
import org.wcs.plugin.tcp.model.SocketDataItem;
import org.wcs.utils.AppStringUtils;
import org.wcs.utils.AppThreadUtils;
@ -37,11 +44,12 @@ import java.util.concurrent.TimeUnit;
public class ScannerJob implements Job {
private final AppStockScanService stockScanService;
private final StringRedisTemplate stringRedisTemplate;
private final IScanMethod scanMethod;
private final ScanRedis scanRedis;
private final IDataRecorder dataRecorder;
public static final String SCANNER_DATA_REDIS_KEY = "WCS:CACHE:SCANNER_JOB_KEY";
private static Map<String, Method> scanMethodMap = new ConcurrentHashMap<>();
private static SocketClient socketClient; // TCP 连接的 Socket客户端
@Override
public void execute(JobExecutionContext jobExecutionContext) {
@ -49,15 +57,23 @@ public class ScannerJob implements Job {
if(scanMethodMap.isEmpty()) {
getScanMethod();
}
plcScan();
tcpScan();
}
/**
* PLC扫码信息处理
*/
private void plcScan() {
// 获取扫码数据
List<AppStockScan> stockScans; // 扫码数据
String scanDataCache = stringRedisTemplate.opsForValue().get(SCANNER_DATA_REDIS_KEY);
String scanDataCache = scanRedis.getScannerData();
if(AppStringUtils.isEmpty(scanDataCache)) {
AppStockScan queryParam = new AppStockScan();
queryParam.setScanStatus(TrueOrFalseEnum.TRUE.getCode());
queryParam.setScanType(StockScanTypeEnum.PLC_SCAN.getCode());
stockScans = stockScanService.query(queryParam);
stringRedisTemplate.opsForValue().set(SCANNER_DATA_REDIS_KEY, AppStringUtils.objectToString(stockScans), 10, TimeUnit.SECONDS);
scanRedis.setScannerData(AppStringUtils.objectToString(stockScans), 30);
} else {
stockScans = JSONObject.parseObject(scanDataCache, new TypeReference<>(){});
}
@ -70,12 +86,130 @@ public class ScannerJob implements Job {
if(AppStringUtils.isEmpty(stockScan.getScanId()) || AppStringUtils.isEmpty(stockScan.getScanMethod())) {
return;
}
Tuple2<String, ScanInfo> stringScanInfoTuple2 = PlcCommunicationFactory.getPlcCommunicationByPlcId(stockScan.getPlcId()).readScannerInfo(stockScan.getScanId());
Tuple2<String, TaskConveyStatus> stringScanInfoTuple2 = PlcCommunicationFactory.getPlcCommunicationByPlcId(stockScan.getPlcId()).readTaskConveyStatus(stockScan.getScanId());
//Tuple2<String, String> stringScanInfoTuple2 = PlcCommunicationFactory.getPlcCommunicationByPlcId(stockScan.getPlcId()).readScannerCode(stockScan.getScanId());
if(stringScanInfoTuple2.item1 != null || stringScanInfoTuple2.item2 == null) {
log.error("扫码器[{}]信息读取失败: {}", stockScan.getScanId(), stringScanInfoTuple2.item1);
//log.error("扫码器[{}]信息读取失败: {}", stockScan.getScanId(), stringScanInfoTuple2.item1);
return;
}
TaskConveyStatus taskConveyStatus = stringScanInfoTuple2.item2;
if(taskConveyStatus.getPlcTaskId() != 0) {
return;
}
String code = taskConveyStatus.getVehicleNo().trim();
if(AppStringUtils.isEmpty(code)) {
scanRedis.setScanCode(stockScan.getScanId(), "", -1);
return;
}
String oldCode = scanRedis.getScanCode(stockScan.getScanId());
if(AppStringUtils.isEmpty(oldCode) || !oldCode.equals(code)) {
scanRedis.setScanCode(stockScan.getScanId(), code, 30);
log.info("扫码:{},扫码成功(PLC转发),条码:{}",stockScan.getScanId(), code);
dataRecorder.recordStockScanCode(stockScan.getScanId(), code);
ScanInfo scanInfo = ScanInfo.builder().tag((short) 0).vehicleSize((short) 0).length(0).width(0).height(0).weight(0).vehicleNo(code).build();
executeScanMethod(stockScan, scanInfo);
}
});
}
AppThreadUtils.waitAllTaskComplete(runnableList);
}
/**
* TCP直连的扫码信息
*/
private void tcpScan() {
if(socketClient != null) {
// 不是空说明已经初始化过了调用检查重连方法
socketClient.checkAndReconnect();
return;
}
List<AppStockScan> stockScans = scanRedis.getScannerTcpData();
if(stockScans == null) {
AppStockScan queryParam = new AppStockScan();
queryParam.setScanStatus(TrueOrFalseEnum.TRUE.getCode());
queryParam.setScanType(StockScanTypeEnum.TCP_SCAN.getCode());
List<AppStockScan> stockScansNew = stockScanService.query(queryParam);
if(stockScansNew == null || stockScansNew.isEmpty()) {
return;
}
scanRedis.setScannerTcpData(stockScansNew, 60);
stockScans = stockScansNew;
}
socketClient = new SocketClient();
stockScans.forEach(stockScan -> {
String ipAndPort = stockScan.getReadStatusAddress();
if(AppStringUtils.isEmpty(ipAndPort)) {
log.error("扫码器[{}]信息处理失败: {}", stockScan.getScanId(), "未配置扫码地址");
return;
}
String[] split = ipAndPort.trim().split(":");
if(split.length < 2) {
log.error("扫码器[{}]信息处理失败: {}", stockScan.getScanId(), "扫码地址格式错误");
return;
}
String ip = split[0];
int port = Integer.parseInt(split[1]);
socketClient.addSocketDataItem(SocketDataItem.builder()
.socketId(stockScan.getScanId())
.socketIp(ip).socketPort(port).socketTag("TCP_SCAN").build());
});
socketClient.setSocketClientEvent(new ISocketClientEvent() {
@Override
public void onConnect(SocketDataItem socketDataItem) {
log.info("扫码器[{}]连接成功: {}", socketDataItem.getSocketId(), socketDataItem.getSocketIp() + ":" + socketDataItem.getSocketPort());
}
@Override
public void onDisconnect(SocketDataItem socketDataItem) {
log.info("扫码器[{}]断开连接: {}", socketDataItem.getSocketId(), socketDataItem.getSocketIp() + ":" + socketDataItem.getSocketPort());
}
@Override
public void onMessage(SocketDataItem socketDataItem, String message) {
log.info("扫码器[{}]扫码信息: {}", socketDataItem.getSocketId(), message);
dataRecorder.recordStockScanCode(socketDataItem.getSocketId(), message);
List<AppStockScan> stockScanList = scanRedis.getScannerTcpData();
if(stockScanList == null) {
log.error("扫码器[{}]信息处理失败: {}", socketDataItem.getSocketId(), "检索扫码器信息失败");
return;
}
stockScanList.stream().filter(stockScan -> stockScan.getScanId().equals(socketDataItem.getSocketId())).findFirst().ifPresent(stockScan -> {
ScanInfo scanInfo = ScanInfo.builder()
.vehicleNo(message)
.tag((short) 0)
.vehicleSize((short)0)
.length(0)
.width(0)
.height(0)
.weight(0).build();
executeScanMethod(stockScan, scanInfo); // 执行扫码方法
});
}
@Override
public void onBytes(SocketDataItem socketDataItem, byte[] bytes) {
}
@Override
public void onError(SocketDataItem socketDataItem, Throwable throwable) {
log.error("扫码器[{}]连接异常IP{},端口:{}", socketDataItem.getSocketId(), socketDataItem.getSocketIp(), socketDataItem.getSocketPort(), throwable);
}
});
socketClient.connectAll();
}
/**
* 执行扫码方法
* @param stockScan 扫码数据
* @param scanInfo 扫码信息
*/
private void executeScanMethod(AppStockScan stockScan, ScanInfo scanInfo) {
if(AppStringUtils.isEmpty(stockScan.getScanId()) || AppStringUtils.isEmpty(stockScan.getScanMethod())) {
return;
}
ScanInfo scanInfo = stringScanInfoTuple2.item2;
if(scanMethodMap.isEmpty()) {
getScanMethod();
}
@ -93,11 +227,10 @@ public class ScannerJob implements Job {
} catch (IllegalAccessException | InvocationTargetException e) {
log.error("扫码器[{}]信息处理失败: {},扫码方法调用失败", stockScan.getScanId(), stockScan.getScanMethod());
}
});
}
AppThreadUtils.waitAllTaskComplete(runnableList);
}
/**
* 获取扫码方法
*/