From 868daf94f29ce1ffdd799a68c07bb668cd373bcd Mon Sep 17 00:00:00 2001
From: HP\李良庭 <liliangting@lanpucloud.cn:1111>
Date: 星期二, 08 七月 2025 11:49:03 +0800
Subject: [PATCH] 提交分辨率自适应版本V3.1.0.1500

---
 src/thread/testThread.~pas |  332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 332 insertions(+), 0 deletions(-)

diff --git a/src/thread/testThread.~pas b/src/thread/testThread.~pas
new file mode 100644
index 0000000..82df1b5
--- /dev/null
+++ b/src/thread/testThread.~pas
@@ -0,0 +1,332 @@
+{------------------------------------------------------------------------------}
+{单元名称:testThread.pas                                                      }
+{模块名称:自动检测线程                                                        }
+{模块说明:线程创建后自动启动                                                  }
+{          自动检测线程根据plc指令,控制水分仪自动完成含水率检测,自动上报结果 }
+{建立日期:2023-10-27                                                          }
+{修改修改:2023-11-11                                                          }
+{版权所有:李良庭 liangtingli@outlook.com                                      }
+{------------------------------------------------------------------------------}
+unit testThread;
+
+interface
+
+uses
+  Windows, Classes, SysUtils, PubUtils, DateUtils, ActuatorLib;
+
+type
+  TTestThread = class(TThread)
+  private
+    { Private declarations }
+    t_ret : Integer;
+    t_faultCode : Word;                //水分仪故障码
+
+    t_val1, t_val2 : Double;           //计算出来的含水率、容重比
+    t_val3, t_val4 : Double;           //采集出来的 温度、湿度
+    t_nGrainType : Word;               //粮种代码
+    t_nDatas : array[0..3] of Word;    //水分仪数据
+    x0,x1,x2,x3,x4,x5 : double;        //校准系数
+    procedure UpdateStartClock;
+    procedure UpdateStopClock;
+    procedure UpdateSendGrain;
+    procedure UpdateSendTest;
+    procedure UpdateReadStateError;
+    procedure UpdateReLink;
+    procedure UpdateModifyGrain;
+    procedure UpdateModifyGrainError;
+    procedure UpdateTest;
+    procedure UpdateTestError;
+    procedure UpdateResetError;
+    procedure UpdateQuit;
+  protected
+    procedure Start();
+    procedure Execute; override;
+  public
+    constructor Create(param: Boolean=false);
+    procedure Terminate;
+  end;
+
+implementation
+
+uses
+  uMain, uDM, uInit, uSaveData, Global, log4me;
+
+{ TTestThread }
+//--------线程初始化----------------------------------------
+//线程初始化
+constructor TTestThread.Create(param: Boolean=false);
+begin
+  //线程停止后自动释放
+  inherited Create(param);        //设置线程运行, False-自动运行, True-手动启动
+  FreeOnTerminate := True;        //设置线程退出自动销
+  t_val1 := 0;
+  t_val2 := 0;
+  t_val3 := 0;
+  t_val4 := 0;
+  t_ret := 0;
+end;
+
+//线程销毁事件
+procedure TTestThread.Terminate;
+begin
+  inherited;
+  m_TestThread := 0;             //清理线程句柄
+end;
+
+//--------界面处理函数--------------------------------------
+//计数器开始
+procedure TTestThread.UpdateStartClock;
+begin
+  //启动检测计时器动画
+  glStartTest := GetMillisecondTimeStamp;
+  dm.tmAutoTest.Enabled := true;
+end;
+
+//计数器结束
+procedure TTestThread.UpdateStopClock;
+begin
+  dm.tmAutoTest.Enabled := false;
+  frmMain.mtAutoClock.Value := 0;
+end;
+
+//状态显示--下发修改粮种指令
+procedure TTestThread.UpdateSendGrain;
+begin
+  //加载粮种校准系数
+  Grain := queryGrainSql1(t_Grain, t_nGrainType);
+  x0 := StrToFloat(Grain.coef[0]);
+  x1 := StrToFloat(Grain.coef[1]);
+  x2 := StrToFloat(Grain.coef[2]);
+  x3 := StrToFloat(Grain.coef[3]);
+  x4 := StrToFloat(Grain.coef[4]);
+  x5 := StrToFloat(Grain.Intercept);//新增截距
+
+  //更新界面信息
+  frmMain.lblAutoInfo.Caption := '修改粮种信息,请稍候......';
+  frmMain.lblAutoRet.Caption := '';
+  frmMain.lblAutoRet_error.Caption := '';
+end;
+
+//状态显示--下发检测指令
+procedure TTestThread.UpdateSendTest;
+begin
+  //更新界面信息
+  frmMain.lblAutoInfo.Caption := '正在检测含水率,请稍候......';
+  frmMain.lblAutoRet.Caption := '';
+  frmMain.lblAutoRet_error.Caption := '';
+end;
+
+//-------- 错误信息 ---------------------------------------
+//出错显示--读PLC状态字异常
+procedure TTestThread.UpdateReadStateError;
+begin
+  //更新界面信息
+  frmMain.lblAutoRet.Caption := '';
+  frmMain.lblAutoRet_error.Caption := '读取 PLC状态字 异常!';
+  log4error(Format('错误:读取 PLC状态字 异常,返回值=[%d].',[t_ret]));
+end;
+
+//出错回复--一般是重连恢复
+procedure TTestThread.UpdateReLink;
+begin
+  if frmMain.lblAutoRet_error.Caption<>'' then begin
+    frmMain.lblAutoRet_error.Caption := '';
+    log4error('连接:通讯异常后,自动断开重连成功!');
+  end;
+end;
+
+//正常显示--修改粮种信息
+procedure TTestThread.UpdateModifyGrain;
+begin
+  //更新界面信息
+  frmMain.lblAutoInfo.Caption := '粮食品种修改成功,准备就绪!';
+  frmMain.lblAutoRet.Caption := '';
+  frmMain.lblAutoRet_error.Caption := '';
+  log4info('粮种信息:粮食品种修改成功,准备就绪!');
+end;
+
+//出错显示--修改粮种出错
+procedure TTestThread.UpdateModifyGrainError;
+begin
+  //更新界面信息
+  frmMain.lblAutoRet.Caption := '';
+  frmMain.lblAutoRet_error.Caption := Format('粮食品种修改失败,水分仪故障码 [%d]!',[t_faultCode]);
+  log4error('粮种信息:粮食品种修改失败,水分仪故障!');
+end;
+
+//正常显示--执行检测
+procedure TTestThread.UpdateTest;
+var ss : string;
+begin
+  if glIsDebug then
+    frmMain.lblAutoInfo1.Caption := Format('粮种[%s], 系数[%s,%s,%s,%s,%s]',
+                  [Grain.Name,
+                   Grain.Coef[0],
+                   Grain.Coef[1],
+                   Grain.Coef[2],
+                   Grain.Coef[3],
+                   Grain.Coef[4]]);
+  //更新界面信息
+  frmMain.lblAutoInfo.Caption := '含水率检测成功!';
+  ss := '含水率: '+Format('%.2f',[Trunc(t_val1*100)/100])+'%, 温度: '+Format('%.2f',[t_val3])+'℃, 湿度: '+Format('%.2f',[t_val4])+'%.';
+  frmMain.lblAutoRet.Caption := ss;
+  frmMain.lblAutoRet_error.Caption := '';
+  log4info('自动检测:含水率检测成功,'+ss);
+
+  //更新数据库和保存csv
+  insertTestSql(t_Data,Ord(rmAuto),1,DateTimeToUnix(Now),
+                Grain.Code,Grain.Name,'',
+                Trunc(t_val1*100)/100, t_val3, t_val4);
+  //保存csv文件
+  WriteCsvFile(Grain.Name, t_val1, t_val3, t_val4);
+end;
+
+//出错显示--执行检测出错
+procedure TTestThread.UpdateTestError;
+begin
+  //更新界面信息
+  frmMain.lblAutoInfo.Caption := '执行检测失败!';
+  frmMain.lblAutoRet.Caption := '';
+  frmMain.lblAutoRet_error.Caption := '执行检测失败,水分仪故障!';
+end;
+
+//出错显示--复位失败
+procedure TTestThread.UpdateResetError;
+begin
+  //更新界面信息
+  frmMain.lblAutoInfo.Caption := '执行复位失败!';
+  frmMain.lblAutoRet.Caption := '';
+  frmMain.lblAutoRet_error.Caption := '执行复位操作失败,水分仪故障!';
+end;
+
+//退出线程--打印日志
+procedure TTestThread.UpdateQuit;
+begin
+  log4info('退出:线程 TestThread()退出.');
+end;
+
+//------- 执行线程 ----------------------------------------
+procedure TTestThread.Start();
+var
+  nState : Word;    //plc状态字、粮种代码
+  ret : Integer;
+  y : double; //公式y=kx+b
+begin
+  //初始化线程变量
+  nState := 0;
+  t_nGrainType := 0;
+  t_nDatas[0] := 0;
+  t_nDatas[1] := 0;
+  t_nDatas[2] := 0;
+  t_nDatas[3] := 0;
+
+  //读PLC状态字,获取nState、nGrainType
+  t_ret := ReadState(hPlcDev,@nState,@t_nGrainType);
+  if t_ret<=0 then
+    Synchronize(UpdateReadStateError)
+  else if ((nState>0) and (t_nGrainType>0)) then begin
+  //==========================================
+  //从PLC读取命令并执行
+  //注意,这里仅处理PLC下发给水分仪的命令
+  //==========================================
+    case nState of
+      //0x01-粮食品种改了
+      PLC_READY_GRAIN: begin
+        //检查水分仪故障码
+        ret := ReadFaultCode(hWrDev, @t_faultCode);
+        //向水分仪下发粮种修改指令
+        if ret >=0 then begin
+          Synchronize(UpdateStartClock);
+          Synchronize(UpdateSendGrain);    //加载粮种系数
+          ret := SendCommands(hWrDev, WR_READY, t_nGrainType, glTime1);
+          Synchronize(UpdateStopClock);
+        end;
+        if ret<0 then begin
+          Synchronize(UpdateModifyGrainError);
+          ResponseState(hPlcDev, PLC_DEVICE_WR_FAULT);
+        end
+        else begin
+          Synchronize(UpdateModifyGrain);
+          ResponseState(hPlcDev, PLC_READY_FINISH);
+        end;
+      end;
+      //0x03-开始测试
+      PLC_DETECT_START: begin
+        //向水分仪下发检测指令
+        Synchronize(UpdateStartClock);
+        Synchronize(UpdateSendTest);
+        ret := SendCommands(hWrDev, WR_DETECT, 0, glTime2);
+        Synchronize(UpdateStopClock);
+        if ret<0 then begin
+          Synchronize(UpdateTestError);
+          ResponseState(hPlcDev, PLC_DEVICE_WR_FAULT);
+        end
+        else begin
+          //从水分仪读取检测结果:
+          //0-电压、1-重量、2-温度、3-湿度
+          ReadDatas(hWrDev, @t_nDatas);
+          //返回PLC检测成功
+          ResponseState(hPlcDev, PLC_DETECT_FINISH);
+          //计算含水率
+          {t_val1 := x0 +
+                    x1 * t_nDatas[0] +
+                    x2 * t_nDatas[0] * t_nDatas[0] +
+                    x3 * t_nDatas[0] * t_nDatas[0] * t_nDatas[0] +
+                    x4 * t_nDatas[0] * t_nDatas[0] * t_nDatas[0] * t_nDatas[0]; }
+          t_val1 := CalcValue(t_nDatas[0], x0,x1,x2,x3,x4) + x5; //将截距加进去
+          //--------------------------------------------
+          //用公式 y=kx+b 计算重量,重量-去皮
+          y := Wg.k * (t_nDatas[1]-SysConfig.Tare) + Wg.b;
+          //--------------------------------------------
+          //计算容重比
+          if SysConfig.Volume=0 then SysConfig.Volume:=1;
+          t_val2 := y / SysConfig.Volume;    //注意这里使用新公式计算容重比
+
+          //调整温湿度高低位,liliangting 2024-10-15
+          t_val3 := t_nDatas[2]/10;
+          t_val4 := t_nDatas[3]/10;
+          //t_val3 := SwapHighLowWord(t_nDatas[2])/10; //对温度高低位交换
+          //t_val4 := SwapHighLowWord(t_nDatas[3])/10; //对湿度高低位交换
+
+          //结果输出到界面
+          Synchronize(UpdateTest);
+
+          //拼成三个数据的数组,传给PLC
+          t_nDatas[0] := t_nGrainType;        //粮食品种
+          t_nDatas[1] := Trunc(t_val1*100);   //含水率-->PLC要求乘以100取整,以便寄存器存入整数,并非真实结果
+          t_nDatas[2] := Trunc(t_val2*10);    //容重比-->PLC要求乘以10 取整,以便寄存器存入整数,并非真实结果
+          UploadData(hPlcDev, @t_nDatas);
+        end;
+      end;
+      //0xFE-复位命令
+      PLC_DEVICE_WR_RESET: begin
+        if SendCommands(hWrDev, WR_RESET, 0, glTime2)<0 then begin
+          Synchronize(UpdateResetError);
+          ResponseState(hPlcDev, PLC_DEVICE_WR_FAULT);
+        end;
+      end;
+      //其他命令字时,仅清除异常标签,liliangting 2023-12-7
+      else
+        Synchronize(UpdateReLink);
+    end;
+    //=====PLC指令解析结束======================
+  end
+  //当不满足指令时,也更新重连标签信息!liliangting 2023.12.8
+  else
+    Synchronize(UpdateReLink);
+end;
+
+//------- 线程入口 ----------------------------------------
+procedure TTestThread.Execute;
+begin
+  { Place thread code here }
+  while not terminated do begin
+    //执行检测代码
+    Start();
+    //防止线程阻塞CPU
+    Sleep(1000);
+  end;
+  Synchronize(UpdateQuit);
+end;
+
+end.

--
Gitblit v1.9.3