1 февраля 2010 г.

TwinCAT: Функциональный блок копирования файлов

Во время разработки одного из проектов для С6915 обнаружился небольшой нюанс: TwinCAT не имеет готового функционального блока для копирования файлов. Конечно, есть библиотека TcSystem.lib, содержащая всё необходимое для создания, записи и чтения файлов, но не более того. Между тем её функционал вполне позволяет создать свой собственный блок, производящий копирование файлов.

Итак, разработанный (см. код ниже) блок позволяет создавать копию файла в пределах одного AmsNetId. Т.е. нельзя, к примеру, произвести копирование с одного ПК/ПЛК на другой, который имеет иной IP- и NetId-адрес. Но вот сделать копию файла из локальной папки в другую, или, допустим, на карту памяти и обратно — легко.

(*Описание входов/выходов функционального блока*)
FUNCTION_BLOCK FB_COPY_FILES
VAR_INPUT
   sSrcNetId: T_AmsNetId;
   sSrcFileName: T_MaxString;
   sDestNetId: T_AmsNetId;
   sDestFileName: T_MaxString;
   bExecute: BOOL;
   tAdsTimeOut: TIME;
END_VAR
VAR_OUTPUT
   bBusy: BOOL;
   bError: BOOL;
   iErrId: UDINT;
END_VAR
VAR
   fbFileOpen: FB_FileOpen;
   fbFileClose: FB_FileClose;
   fbFileRead: FB_FileRead;
   fbFileWrite: FB_FileWrite;
   iHandleSrcFile: UINT := 0;
   iHandleDestFile: UINT := 0;
   iStep: INT;
   fbRisingEdge: R_TRIG;
   byBuffRead: ARRAY [1..100] OF BYTE;
   iReadLength: UDINT := 0;
END_VAR

(*Тело функционального блока*)
fbRisingEdge (CLK := bExecute);
   IF fbRisingEdge.Q THEN
      IF NOT(bBusy) THEN
         bBusy := TRUE;
         bError := FALSE;
         iErrId := 0;
         iStep := 1;
         iReadLength := 0;
         iHandleSrcFile := 0;
         iHandleDestFile := 0;
      END_IF
   END_IF

CASE iStep OF
   0: (*Ожидание пуска*)
      ;

   1: (*Открытие копируемого файла*)
      fbFileOpen (bExecute := FALSE);
      fbFileOpen (sNetId := sSrcNetId,
         sPathName := sSrcFileName,
         nMode := FOPEN_MODEREAD OR FOPEN_MODEBINARY,
         ePath := PATH_GENERIC,
         tTimeout := tAdsTimeout,
         bExecute := TRUE);
      iStep := iStep + 1;

   2: (*Получение дескриптора исходного файла*)
      fbFileOpen (bExecute := FALSE);
         IF NOT(fbFileOpen.bBusy) THEN
            IF fbFileOpen.bError THEN
               iErrId := fbFileOpen.nErrId;
               bError := TRUE;
               iStep := 50;
            ELSE
               iHandleSrcFile := fbFileOpen.hFile;
               iStep := iStep + 1;
            END_IF
         END_IF

   3: (*Создание копии файла*)
      fbFileOpen (bExecute := FALSE);
      fbFileOpen (sNetId := sDestNetId,
         sPathName := sDestFileName,
         nMode := FOPEN_MODEWRITE OR FOPEN_MODEBINARY,
         ePath := PATH_GENERIC,
         tTimeout := tAdsTimeout,
         bExecute := TRUE);
      iStep := iStep + 1;

   4: (*Получение дескриптора создаваемой копии файла*)
      fbFileOpen (bExecute := FALSE);
      IF NOT(fbFileOpen.bBusy) THEN
         IF fbFileOpen.bError THEN
            iErrId := fbFileOpen.nErrId;
            bError := TRUE;
            iStep := 50;
         ELSE
            iHandleDestFile := fbFileOpen.hFile;
            iStep := iStep + 1;
         END_IF
      END_IF

   5: (*Чтение данных из копируемого файла*)
      iReadLength := 0;
      fbFileRead (bExecute := FALSE);
      fbFileRead (sNetId := sSrcNetId,
         hFile := iHandleSrcFile,
         pReadBuff := ADR(byBuffRead),
         cbReadLen := SIZEOF(byBuffRead),
         bExecute := TRUE,
         tTimeout := tAdsTimeOut);
      iStep := iStep + 1;

   6: (*Завершение буферизации*)
      fbFileRead (bExecute:= FALSE);
         IF NOT(fbFileRead.bBusy) THEN
            IF fbFileRead.bError THEN
               iErrId := fbFileRead.nErrId;
               bError := TRUE;
               iStep := 50;
            ELSE
               iReadLength := fbFileRead.cbRead;
               iStep := iStep + 1;
            END_IF
         END_IF

   7: (*Запись данных в созданный файл*)
      fbFileWrite (bExecute := FALSE);
      fbFileWrite (sNetId := sDestNetId,
         hFile := iHandleDestFile,
         pWriteBuff := ADR(byBuffRead),
         cbWriteLen := iReadLength,
         bExecute := TRUE,
         tTimeout := tAdsTimeOut);
      iStep := iStep + 1;

   8: (*Завершение записи*)
      fbFileWrite (bExecute := FALSE);
         IF NOT(fbFileWrite.bBusy) THEN
            IF fbFileWrite.bError THEN
               iErrId := fbFileWrite.nErrId;
               bError := TRUE;
               iStep := 50;
            ELSE
               IF fbFileRead.bEOF THEN
                  iStep := 50;
               ELSE
                  iStep := 5;
               END_IF
            END_IF
         END_IF

   30: (*Закрытие созданного файла*)
       fbFileClose (bExecute := FALSE);
       fbFileClose (sNetId := sDestNetId,
          hFile := iHandleDestFile,
          bExecute := TRUE,
          tTimeout := tAdsTimeOut);
       iStep := iStep + 1;

   31: (*Проверка закрытия*)
       fbFileClose(bExecute := FALSE);
          IF NOT(fbFileClose.bBusy) THEN
             IF fbFileClose.bError THEN
                iErrId := fbFileClose.nErrId;
                bError := TRUE;
             END_IF
             iStep := 50;
             iHandleDestFile := 0;
          END_IF

   40: (*Закрытие копируемого файла*)
       fbFileClose (bExecute := FALSE);
       fbFileClose (sNetId := sSrcNetId,
          hFile := iHandleSrcFile,
          bExecute := TRUE,
          tTimeout := tAdsTimeOut);
       iStep := iStep + 1;

   41: (*Проверка закрытия*)
       fbFileClose (bExecute := FALSE);
          IF NOT(fbFileClose.bBusy) THEN
             IF fbFileClose.bError THEN
                iErrId := fbFileClose.nErrId;
                bError := TRUE;
             END_IF
             iStep := 50;
             iHandleSrcFile := 0;
          END_IF

   50: (*Очистка*)
       IF iHandleDestFile <> 0 THEN
          iStep := 30;
       ELSIF iHandleSrcFile <> 0 THEN
          iStep := 40;
       ELSE
          iStep := 0;
          bBusy := FALSE;
       END_IF
END_CASE


В ниже приведённом примере — вызов разработанного функционального блока FB_COPY_FILES. На его входах достаточно определить что именно и куда требуется скопировать.

(*Объявление функционального блока в MAIN*)
PROGRAM MAIN
VAR
   fbFileCopy: FB_COPY_FILES;
   sSourceFile: STRING := 'c:\folder1\file1.txt';
   sDestinationFile: STRING := 'd:\file2.txt';
   bCopyDone: BOOL := FALSE;
END_VAR

(*Вызов блока*)
IF NOT(bCopyDone) THEN
   fbFileCopy (sSrcNetId := '',
      sSrcFileName := sSourceFile,
      sDestNetId := '',
      sDestFileName := sDestinationFile,
      bExecute := TRUE,
      tAdsTimeOut := t#2s);
   IF NOT(fbFileCopy.bError) THEN
      IF NOT(fbFileCopy.bBusy) THEN
         bCopyDone := TRUE;
      END_IF
   END_IF
ELSE
   fbFileCopy (bExecute := FALSE);
END_IF

Комментариев нет:

Отправить комментарий