unit device_thread;

interface

uses
  Classes, Windows, SysUtils, D2xxUnit, Dialogs, DeviceRD, IzmUnit, DateUtils, user_types, Forms;

type TIzmResult = IzmUnit.TIzmResult;

type
  device_thread_th = class(TThread)
  public
    destructor Destroy; override;

  var
    points_amount,
    repeat_amount,
    params_amount      :  integer;
  private
     decoded_message: params_record; { Private declarations }
  protected



    procedure Execute; override;
    procedure Get_message;
    procedure Update;
    procedure Update_dev_cond_string_getdata;
    procedure Update_dev_cond_string_ready;
    procedure Update_dev_cond_string_decode;
    procedure Update_message_count;
    procedure Check_and_load_data;
    procedure Check_errors;

  end;

Var

num:          integer;
point,povtor: integer;
izm_result:   TIzmResult;
message_:     message_Array;
execute_t:      boolean;

implementation

uses MainUnit, ConstUnit, DataUnit;


{ Important: Methods and properties of objects in visual components can only be
  used in a method called using Synchronize, for example,

      Synchronize(UpdateCaption);

  and UpdateCaption could look like,

    procedure device_thread.UpdateCaption;
    begin
      Form1.Caption := 'Updated in a thread';
    end; }

{ device_thread }
destructor device_thread_th.Destroy;
begin
//Suspend;
//inherited;


//здесь выполняй все действия, что должны выполниться при разрушении потока,
 // например пошли sendmessage "родительскому" окну
 //что поток закончил свою работу (при этом Synchronize не нужна)

end;

procedure device_thread_th.Execute;
begin
self.OnTerminate := nil;
Get_message;
end;

procedure device_thread_th.Get_message;
var i,
    j,
    k,m:              integer;
    message_begin:  boolean;
begin
points_amount:=24;
repeat_amount:=5;
params_amount:=7;
//устанавливаем длину массива результатов измерений
SetLength(izm_result,points_amount+1,repeat_amount+1);
//инициализируем массив результатов измерений
for i:=1 to points_amount do
    for j:=1 to repeat_amount do
    begin
      izm_result[i,j].R:=0;
      izm_result[i,j].G0:=0;
      izm_result[i,j].G1:=0;
      izm_result[i,j].G2:=0;
      izm_result[i,j].G3:=0;
      izm_result[i,j].C:=0;
      izm_result[i,j].Usm:=0;

      izm_result[i,j].R_e:=0;
      izm_result[i,j].G0_e:=0;
      izm_result[i,j].G1_e:=0;
      izm_result[i,j].G2_e:=0;
      izm_result[i,j].G3_e:=0;
      izm_result[i,j].C_e:=0;
      izm_result[i,j].Usm_e:=0;

      for k:= 0 to 2400 do begin
              izm_result[i,j].U_izm[k]:=0;
              izm_result[i,j].I_izm[k]:=0;
      end;
    end;

j:=0;
num:=0;
povtor:=0;
point:=1;
message_begin:=false;
for i:=0 to length(message_)-1 do message_[i]:=0;
execute_t:=true;
//ждем сообщение
Purge_USB_Device_In;
Purge_USB_Device_Out;
Reset_USB_Device; 
if IzmForm.Visible then
while execute_t do
            begin
              repeat
                Application.ProcessMessages;
                Get_USB_Device_Status;   //проверяем буфер устройства
//в этом месте идет загрузка на 100%. Вопрос в том как справится!!!
              until FT_Q_Bytes > 0;

              Read_USB_Device_Buffer(1);  //читаем буфер устройства
              i:=FT_In_Buffer[0];         //читаем первое число


              if i=240 then
                begin
                   for m:=0 to length(message_)-1 do message_[m]:=0;
                   message_begin:=true;//посылка пошла
                   //Выводим сообщение о получении данных
                   //прогресс бар измерения в 0
                   Synchronize(Update_dev_cond_string_getdata);
                end;
              if message_begin then
                begin
                    //запоминаем число из посылки
                   message_[j]:=i;
                   inc(j);
                end;
              if i=255 then begin  //посылка закончилась
                            j:=0;
                            message_begin:=false;
                            Purge_USB_Device_In;
                            Purge_USB_Device_Out;
                            Reset_USB_Device;
                            //Вывод сообщения о декодировании посылки
                            Synchronize(Update_dev_cond_string_decode);
                            /// Обрабатываем посылку
                            ///  Выводим результаты в лист
                            ///  Выводим сообщения об ошибках
                            Synchronize(Update);
                            //Вывод сообщения о готовности прибора к измерению
                            Synchronize(Update_dev_cond_string_ready);

                            // Уведичиваем порядковый номер замера
                            inc(num);
                            //Увеличиваем значение повтора
                            inc(povtor);

                            //Загружаем информацию в базу данных
                            Synchronize(Check_and_load_data);
                            //проверяем условие перехода на новую точку
                            Synchronize(Update_message_count);


                            for i:=0 to length(message_)-1 do message_[i]:=0;
                            Purge_USB_Device_Out;//очищаем буфер

                            end;
            end;
//Suspend;
end;


procedure device_thread_th.Update;
var i:integer;
begin
/// Обрабатываем посылку
///  Выводим результаты в лист
///  Выводим сообщения об ошибках
decoded_message:=MainForm.device.message_decode(message_);
IzmForm.incoming_message(decoded_message,povtor+1,point);
 for i:=0 to length(message_)-1 do message_[i]:=0;
end;

procedure device_thread_th.Update_dev_cond_string_getdata;
begin
      //Выводим сообщение о получении данных
      IzmForm.Izm_condition_label.Caption:=ConstUnit.izm_get_data;
      IZmForm.IzmPB.Position:=0;
      IZmForm.IzmTimer.Enabled:=true;
end;

procedure device_thread_th.Update_dev_cond_string_ready;
begin
      //Вывод сообщения о готовности прибора к измерению
      IzmForm.Izm_condition_label.Caption:=ConstUnit.izm_device_ready;
      IZmForm.IzmTimer.Enabled:=false;
end;

procedure device_thread_th.Update_dev_cond_string_decode;
begin
      //Вывод сообщения о декодировании посылки
      IzmForm.Izm_condition_label.Caption:=ConstUnit.izm_mes_decode;
end;

procedure device_thread_th.Update_message_count;
begin
      IzmForm.izm_mes_count.Caption:=inttostr(num);
      if ((num mod 5)=0) then
          begin
           povtor:=0;
           inc(point);
           IzmForm.izm_next_point.Execute;
          end;
      IzmForm.izm_mes_tek_count.Caption:=inttostr(povtor);
end;

procedure device_thread_th.Check_and_load_data;
var list:TStringList;
    //i,j,
    k: Integer;
    str,
    y1,
    y2:string;
    tmp:array of extended;
begin
setLength(tmp,params_amount+1);
//Проверяем значения на ошибки
Check_errors;
//в массив результатов записываем декодированное сообщение
izm_result[point,povtor]:=decoded_message;

//создаем запись об измерении
with SQL_DM.mysql_query4 do begin
Connection:=SQL_DM.mysql_con;
        SQL.Clear;
        //Создаем запись об измерении.
        SQL.Add('SELECT * FROM `rd`.`rd_izmerenia` WHERE');
        SQL.Add(' `id`='+IzmForm.Izm_gen_num.Caption+';');
      try
        Active:=true;
      except
      //
      end;
if SQL_DM.mysql_DSQ4.DataSet.IsEmpty
then
    begin
        SQL.Clear;
        //Создаем запись об измерении.
        SQL.Add('INSERT INTO `rd`.`rd_izmerenia` (');
        SQL.Add('`id` ,');
        SQL.Add('`date` ,');
        SQL.Add('`patient_num` ,');
        SQL.Add('`opisanie`');
        SQL.Add(')');
        SQL.Add('VALUES (');
        SQL.Add(' '''+IzmForm.Izm_gen_num.Caption+''' , NOW() , '''
        +MainForm.patient.Get_current_patient_ID + ''', ');
        SQL.Add(' '''+IzmForm.izm_opisanie_edit.Text+''');');
      try
        Execute;
      except
      //
      end;
    end;
end;


//проверяем не было ли уже записано в базу параметры текущей точки:
with SQL_DM.mysql_query4 do begin
Connection:=SQL_DM.mysql_con;
        SQL.Clear;

        SQL.Add('SELECT * FROM `rd`.`'+table_znacheniya_name+'` WHERE (');
        SQL.Add(' (`izm_num`='+IzmForm.Izm_gen_num.Caption+') AND ('+
                ' `param_num`='+inttostr(3)+') AND ('+
                ' `povtor_num`='+inttostr(povtor)+') AND ('+
                ' `point_num`='+inttostr(point)+'));');
        //showmessage(SQL.Text);
      try
        Active:=true;
      except
      //
      end;
end;

//берем информацию с прибора
tmp[1]:=decoded_message.R_e;
tmp[2]:=decoded_message.G0_e;
tmp[3]:=decoded_message.G1_e;
tmp[4]:=decoded_message.G2_e;
tmp[5]:=decoded_message.G3_e;
tmp[6]:=decoded_message.C_e;
tmp[7]:=decoded_message.Usm_e;

y1:=IzmForm.get_string(decoded_message.U_izm);
y2:=IzmForm.get_string(decoded_message.I_izm);

//showmessage (inttostr(SQL_DM.mysql_DSQ4.DataSet.RecordCount));
if not (SQL_DM.mysql_DSQ4.DataSet.RecordCount=0)
then  //в случае если апдейт
begin
//создаем стринглист для загрузки в него запроса к базе
list:=TStringList.Create;
list.Clear;

for k:=1 to params_amount do
    begin
         list.Add('UPDATE `rd`.`'+table_znacheniya_name+'` SET `znach`=');
         DecimalSeparator:='.';
         str:=floattostrf(tmp[k],ffExponent, 6, 2);
         list.Add(''''+str+''''+' WHERE ((`param_num`='+inttostr(k+2)+
                  ') AND (`izm_num`='+IzmForm.Izm_gen_num.Caption+
                  ') AND (`point_num`='+inttostr(point)+
                  ') AND (`povtor_num`='+inttostr(povtor)+')); ');
          //list.Add(str);

    end;
    //showmessage(list.Text);
list.SaveToFile('znachzapros.txt');
end
else //в случае если надо записать
/////////////////////////////////
///
///  Здесь остановились чтобы сделать Usm
///
///
///  //////////////////////
begin
//создаем стринглист для загрузки в него запроса к базе
list:=TStringList.Create;
with list do
   begin
     Clear;
     Add('INSERT INTO `rd`.`'+table_znacheniya_name+'` (');
     Add('`id` ,');
     Add('`izm_num` ,');
     Add('`param_num` ,');
     Add('`point_num` ,');
     Add('`povtor_num` ,');
     Add('`znach` ,');
     Add('`znach_UI`');
     Add(')');
     Add('VALUES');
   end;

for k:=1 to params_amount do
    begin
      DecimalSeparator:='.';
      str:='(NULL , '''+
         IzmForm.Izm_gen_num.Caption+''', '''+
         inttostr(k+2)+''', '''+
         inttostr(point)+''', '''+
         inttostr(povtor)+''', ''';
      str:=str+floattostrf(tmp[k],ffExponent, 6, 2)+''',' +'NULL';
      if (k=params_amount) and not(MainForm.izm_write_ui.Checked) then
                 str:=str+')'
              else str:=str+'),';
          list.Add(str);
    end;


      //если необходимо также записывать значения тока и напряжения
       if MainForm.izm_write_ui.Checked then
       begin
        str:='(NULL , '''+
                IzmForm.Izm_gen_num.Caption+''', '''+
                inttostr(1)+''', '''+
                inttostr(point)+''', '''+
                inttostr(povtor)+''', '''+floattostr(0)+''',' +y1+'),';
       list.Add(str);
       str:='(NULL , '''+
                IzmForm.Izm_gen_num.Caption+''', '''+
                inttostr(2)+''', '''+
                inttostr(point)+''', '''+
                inttostr(povtor)+''', '''+floattostr(0)+''',' +y2+')';
       if  not(k=params_amount) then
           str:=str+',';

       list.Add(str);
       end;
list.SaveToFile('znachzapros.txt');


end;





//непосредственная запись в базу
with SQL_DM.mysql_query4 do begin
        Connection:=SQL_DM.mysql_con;
        SQL.Clear;
        SQL.AddStrings(list);
      try
        Execute;
      except
      //
      end;
end;
list.Destroy;



{//запись текущего измерения в виде sql запросов в текстовый файл
AssignFile(file_record, 'last_measute.dat'); Assigns the Filename
   if (point=1) and (povtor=1) then ReWrite(file_record)
   else Append(file_record);

   Writeln(file_record, izm_result[i,j].R+#9+
        izm_result[point,povtor].G0+#9+
        izm_result[point,povtor].G1+#9+
        izm_result[point,povtor].G2+#9+
        izm_result[point,povtor].G3+#9+
        izm_result[point,povtor].C;);
   Closefile(file_record); //Closes file F}


//если пришли к концу всего измерения: 24 точки по 5 повторов
if (point=points_amount) and (povtor=repeat_amount) then
  //выводим сообщение о законченности измерения
  if MessageBox(0,
              PChar(izm_izm_end),
              PChar(izm_caption_message),
              MB_ICONQUESTION or MB_OKCANCEL
              )=id_OK then
    //если пользователь выбрал загрузку
      begin
        IzmForm.Izm_stop_btn.Caption:=izm_unit_end_measurment_btn_label;
        Suspend;
        IzmForm.Close;
        MainForm.GoToLookResults.Execute;


{
//проходим по каждой точке, каждому повтору по точке, и каждому параметру
for i:=1 to points_amount do
  begin
    //запись полученных значений
    for j:=1 to repeat_amount do
      begin
        // во временный файл заносим результаты для данной точки и повтора
        tmp[1]:=izm_result[i,j].R;
        tmp[2]:=izm_result[i,j].G0;
        tmp[3]:=izm_result[i,j].G1;
        tmp[4]:=izm_result[i,j].G2;
        tmp[5]:=izm_result[i,j].G3;
        tmp[6]:=izm_result[i,j].C;

        y1:=IzmForm.get_string(izm_result[i,j].U_izm);
        y2:=IzmForm.get_string(izm_result[i,j].I_izm);
       //по параметрам, и сразу же формируем строку для записи
       for k:=1 to params_amount do
          begin
              DecimalSeparator:='.';
              str:='(NULL , '''+
                    IzmForm.Izm_gen_num.Caption+''', '''+
                    inttostr(k+2)+''', '''+
                    inttostr(i)+''', '''+
                    inttostr(j)+''', ''';
              str:=str+floattostrf(tmp[k],ffExponent, 6, 2)+''',' +'NULL';

              if (i=points_amount) and (j=repeat_amount) and (k=params_amount) and
                    not(IzmForm.izm_write_ui.Checked) then
                 str:=str+')'
              else str:=str+'),';

          list.Add(str);
          end;


      //если необходимо также записывать значения тока и напряжения
       if IzmForm.izm_write_ui.Checked then begin
        str:='(NULL , '''+
                IzmForm.Izm_gen_num.Caption+''', '''+
                inttostr(1)+''', '''+
                inttostr(i)+''', '''+
                inttostr(j)+''', '''+floattostr(0)+''',' +y1+'),';
       list.Add(str);
       str:='(NULL , '''+
                IzmForm.Izm_gen_num.Caption+''', '''+
                inttostr(2)+''', '''+
                inttostr(i)+''', '''+
                inttostr(j)+''', '''+floattostr(0)+''',' +y2+')';
       if  not((i=points_amount) and (j=repeat_amount) and (k=6)) then
           str:=str+',';

       list.Add(str);
       end;
      end;


  end;
list.SaveToFile('znachzapros.txt');

//формируем время измерения
GetSystemTime(s);
date:=inttostr(s.wYear)+'-'+inttostr(s.wMonth)+'-'+inttostr(s.wDay)+' '+
inttostr(s.wHour+4)+':'+inttostr(s.wMinute)+':'+inttostr(s.wSecond);


//непосредственная запись в базу
with SQL_DM.mysql_query4 do begin
        Connection:=SQL_DM.mysql_con;
        SQL.Clear;
        //Создаем запись об измерении. Почему только здесь???
        SQL.Add('INSERT INTO `rd`.`rd_izmerenia` (');
        SQL.Add('`id` ,');
        SQL.Add('`date` ,');
        SQL.Add('`patient_num` ,');
        SQL.Add('`opisanie`');
        SQL.Add(')');
        SQL.Add('VALUES (');
        SQL.Add(' '''+IzmForm.Izm_gen_num.Caption+''' , '''+date+
              ''', '''+IzmForm.Izm_pat_id.Caption+''', ');
        SQL.Add(' '''+IzmForm.izm_opisanie_edit.Text+''');');

        Execute;
        Active:=false;
        SQL.Clear;
        SQL.AddStrings(list);
      try
        Execute;
      except
      //
      end;
end;
list.Destroy;
//запись в файл токов и напряжений
{list:=Tstringlist.Create;
str:='';
for i:=1 to 24 do
  for j:=1 to 5 do
     begin
      ///формируем следующим образом:
      ///  создаем табулированный файл для последующего экспорта в эксель
      ///  в первой строчке номер точки, номер повтора
      ///  потом столбец значений
      str:=str+'точка: '+inttostr(i)+'повтор: '+inttostr(j)+'U'+#9+
                'точка: '+inttostr(i)+'повтор: '+inttostr(j)+'I'+#9;
    end;
list.Add(str);
str:='';

for i:=1 to 24 do
for j:=1 to 5 do
  for k:=0 to 2400 do

  begin

    begin
      str:=str+inttostr(izm_result[i,j].U_izm[k])+#9+inttostr(izm_result[i,j].I_izm[k])+#9;
      list.Add(str);
    end;
  list.SaveToFile(IzmForm.izm_opisanie_edit.Text+'номер пациента: '+IzmForm.Izm_pat_id.Caption+'точка №:'+inttostr(i));

  end;
  end;
showmessage('Токи и напряжения записаны');
list.Destroy;}
end;
            //  IzmForm.load_data_to_database(izm_result);
end;

procedure device_thread_th.Check_errors;
begin
 /////////////////////////////////
//Обработка ошибок в измерении //
/////////////////////////////////
if decoded_message.U_mis
then begin
  //если была ошибка, то обнуляем результаты
  if MainForm.Izm_null_result_CB.Checked then
    begin
      decoded_message.R:=0;
      decoded_message.C:=0;
      decoded_message.g0:=0;
      decoded_message.g1:=0;
      decoded_message.g2:=0;
      decoded_message.g3:=0;
      decoded_message.Usm:=0;

      decoded_message.R_e:=0;
      decoded_message.C_e:=0;
      decoded_message.g0_e:=0;
      decoded_message.g1_e:=0;
      decoded_message.g2_e:=0;
      decoded_message.g3_e:=0;
      decoded_message.Usm_e:=0;

    end;
end;
if decoded_message.I_mis then
begin
  //если была ошибка, то обнуляем результаты
  if MainForm.Izm_null_result_CB.Checked then
    begin
      decoded_message.R:=0;
      decoded_message.C:=0;
      decoded_message.g0:=0;
      decoded_message.g1:=0;
      decoded_message.g2:=0;
      decoded_message.g3:=0;
      decoded_message.Usm:=0;

      decoded_message.R_e:=0;
      decoded_message.C_e:=0;
      decoded_message.g0_e:=0;
      decoded_message.g1_e:=0;
      decoded_message.g2_e:=0;
      decoded_message.g3_e:=0;
      decoded_message.Usm_e:=0;

    end;
end;
end;


end.
