Страница 27 из 28 ПерваяПервая ... 1725262728 ПоследняяПоследняя
Показано с 261 по 270 из 279

Тема: CODESYS V3.5. Архивация

  1. #261

    По умолчанию

    Цитата Сообщение от Евгений Кислов Посмотреть сообщение
    Добрый день.
    https://owen.ru/forum/showthread.php...l=1#post418790

    Путь к SD: /mnt/ufs/media/mmcblk0p1
    Спасибо! С этим разобрался.
    Возник еще вопрос. Есть проект в нем настроен Alarm Configuration - там ведутся журналы аварий, предупреждений и сообщений и все это отображается на визуализации. Журналы ведутся очень подробно - там регистрируются все события, в т.ч. и действия оператора на ВП110.
    Как известно, все это хранится в AlarmStorage в файле "Application.alarmstorage.1.sqlite".
    Простое скачивание (или копирование на флешку) этого файла и открытие его в SqliteBrowser ничего пока не дали - там непонятно как отображается время и нет самих текстовых сообщений:

    sqlite.jpg

    Зато если из под Codesys конвертировать его в CSV, то все прекрасно открывается в Excel и все текстовые сообщения на месте.
    Собственно вопрос: можно ли из кода программы выполнить эту конвертацию в CSV (ну и дальше средствами CAA File уже скопировать на флешку)? Очень уж не хочется писать отдельный архив на флешку когда по сути вся необходимая информация у меня уже есть:

    alarms_csv.jpg

  2. #262
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,255

    По умолчанию

    Цитата Сообщение от Задумкин Сергей Посмотреть сообщение
    Как известно, все это хранится в AlarmStorage в файле "Application.alarmstorage.1.sqlite".
    Простое скачивание (или копирование на флешку) этого файла и открытие его в SqliteBrowser ничего пока не дали - там непонятно как отображается время и нет самих текстовых сообщений:
    SELECT name FROM sqlite_master WHERE name NOT LIKE 'sqlite_%'
    такая команда даст Вам представление какие таблицы хранятся в базе. Необходимо только скачать к винде такой файлик sqlite3.exe, запустить его и вставлять команды SQL
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  3. #263

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    такая команда даст Вам представление какие таблицы хранятся в базе. Необходимо только скачать к винде такой файлик sqlite3.exe, запустить его и вставлять команды SQL
    Все это должны делать люди, далекие от всего этого. При возникновении гарантийных претензий служба эксплуатации заказчика (или наша) должна вставить флешку в ПЛК210, нажать на условную кнопку на ВП110 чтобы сохранить туда архив и отправить его в нашу службу качества.
    Соответственно мне либо писать этот архив сразу на SD/USB, либо как то реализовать вариант выгрузки уже имеющегося архива из AlarmStorage (только это должно быть в удобно читаемом виде, т.е. CSV)

  4. #264
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,253

    По умолчанию

    Цитата Сообщение от Задумкин Сергей Посмотреть сообщение
    Все это должны делать люди, далекие от всего этого. При возникновении гарантийных претензий служба эксплуатации заказчика (или наша) должна вставить флешку в ПЛК210, нажать на условную кнопку на ВП110 чтобы сохранить туда архив и отправить его в нашу службу качества.
    Соответственно мне либо писать этот архив сразу на SD/USB, либо как то реализовать вариант выгрузки уже имеющегося архива из AlarmStorage (только это должно быть в удобно читаемом виде, т.е. CSV)
    Выгрузить Application.alarmstorage.1.sqlite на накопитель, по FTP или через web-визуализацию - не проблема.
    А потом вам требуется научить (это самое сложное) вашу службу качества запускать у них на ПК ваш проект на виртуальном контроллере CODESYS Control Win V3 и подкладывать ему присланный .sqlite. А потом уже можно через команду CODESYS конвертировать в .csv или смотреть прямо в визуализации.
    Такой вариант подходит?

  5. #265
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,255

    По умолчанию

    Цитата Сообщение от Задумкин Сергей Посмотреть сообщение
    Все это должны делать люди, далекие от всего этого. При возникновении гарантийных претензий служба эксплуатации заказчика (или наша) должна вставить флешку в ПЛК210, нажать на условную кнопку на ВП110 чтобы сохранить туда архив и отправить его в нашу службу качества.
    Соответственно мне либо писать этот архив сразу на SD/USB, либо как то реализовать вариант выгрузки уже имеющегося архива из AlarmStorage (только это должно быть в удобно читаемом виде, т.е. CSV)
    Вы в состоянии вставить команду которую я выложил в консоль базы данных? Если да, то не каким то далеким людям потребуется что то искать, а выполнить команду которую подготовит специалист, которая из одной таблицы, которую Вы представили на скрине, возьмут коды алармов, их сопоставят с текстовыми сообщениями из другой таблицы. И Вашим не далеким людям останется только её запустить, чтоб посмотреть на то же самое что на скрине, где и время юникс будет в понятном формате и тексты будут которые описывают произошедьшие события
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  6. #266

    По умолчанию

    Возникла задача организации записи логов действий и нарушений с СПК107 и ПЛК210 на флеш-накопитель.

    Формат вывода нужен приблизительно такой (накапливается на флешке по файлу в день. Чтоб легко открывался и читался):



    Перечитал файл "CDSv3.5_Archives_v3.0.pdf", скачал и опробовал вложенные примеры.
    С примером OwenArchiver разобраться не сложно, все отлично работает, только это не совсем то что нужно в данном случае.
    с остальными примерами либо не разобрался, либо они неработоспособны. Нажимал кнопки, вводил числа, но ничего не записалось

    Вот такой код был для записи на флеш-накопитель для ПЛК110 (Codesys 2.3) на библиотеке "OwenLibFileAsync.lib":

    Код:
    PROGRAM USB_PRG
    VAR
    Name_old:STRING(12);
    rTMP1,rTMP2,rTMP3,rTMP4:REAL;
    LAG1,LAG2:LAG;
    (*Переменные для обслуживания библиотеки SysLibTime*)
        GetTime: CurTimeEx;
        TimeAndDate: SystemTimeDate;
        Sys_Time: SysTime64;
    
        set_time: BOOL := 0;            (*установить  дату*)
        set_date: BOOL := 0;            (*установить время*)
    
    (*Переменные для обслуживания библиотеки OwenLibFileAsync*)
        pref:STRING:='usb:';             (*префикс названия файла, варианты префиксов:
                                                                                                usb: - съемный flash-носитель;
                                                                                                ffs: (или отсутствие!) - внутренняя память;
                                                                                                ram: тестовый RAM диск*)
        handle:DWORD:=0;            (*дескриптор файла*)
        res: ASYNC_RET_VALUE;    (*переменная для организации работы библиотеки OwenLibFileAsync*)
        result:DWORD;                (*размер буфера*)
    
        StartArchivation: BOOL;                (*Переменная запуска архивации. Для начала архивации задайте переменной значение TRUE, для остановки архивации - FALSE.*)
        timer_archiv: TON;                    (*таймер архивации*)
        header: STRING(255);                (*заголовок таблицы*)
        need_new_header: BOOL := 0;        (*необходимость сформировать новый заголовок*)
        start_archiv: BOOL := 0;
        divider:DWORD;
    
        index_old:WORD;
        R_TRIG:R_TRIG;    
    count:INT;
    END_VAR
    
    VAR RETAIN
        name_of_file: STRING;         (*название файла с префиксом*)
        today: UINT;                    (*сегодняшнее число*)
    END_VAR
    
    IF Messages.ALARM[0] <> '' THEN
    TRIP:=TRUE;
    
    IF Name='' THEN Name:='LOGFILES'; END_IF;
        
    (*Далее сохраняем на USB*)
                                        (*-------------Работа с временем и датой ПЛК------------*)
    (* Получаем текущее время и дату*)
    HH    :=    Hour    ;        (*    Значение времени в часах    *)
    MM    :=    Minute    ;        (*    Значение времени в минутах    *)
    SS    :=    Second    ;        (*    Значение времени в секундах    *)
    DD    :=    Day    ;        (*    Значение даты в днях    *)
    MT    :=    Month    ;        (*    Значение даты в месяцах    *)
    YYYY:=    Year    ;        (*    Значение даты в годах    *)
    
    
    (*Если set_time - истина, то можно менять время*)
        IF set_time THEN
            set_time:=0;
            TimeAndDate.Minute:=MM;
            TimeAndDate.Second:=SS;
            TimeAndDate.Hour:=HH;
            GetTime (SystemTime:=Sys_Time , TimeDate:= TimeAndDate);
        END_IF
    
    (*Если set_date - истина, то можно менять дату*)
        IF set_date THEN
            set_date:=0;
            TimeAndDate.Day:=DD;
            TimeAndDate.Month:=MT;
            TimeAndDate.Year:=YYYY;
            GetTime (SystemTime:=Sys_Time , TimeDate:= TimeAndDate);
        END_IF;
    
    index:=index;
    Messages.FLAG[index]:=Messages.FLAG[index];
    
    IF NOT Messages.FLAG[index] THEN (*если необходимо архивировать, то*)
        IF Name<>Name_old THEN (*если наступил новый день, то формируем новый файл с новым именем даты*)
            name_of_file:=CONCAT(pref,Name);
            name_of_file:=CONCAT(name_of_file,UINT_TO_STRING(DD));
            name_of_file:=CONCAT(name_of_file,'.');
            name_of_file:=CONCAT(name_of_file,UINT_TO_STRING(MT));
            name_of_file:=CONCAT(name_of_file,'.');
            name_of_file:=CONCAT(name_of_file,UINT_TO_STRING(YYYY));
            name_of_file:=CONCAT(name_of_file,'.csv');
            today:=DD;(*запомнить дату *)
            need_new_header:=1;(*далее в новом файле необходимо будет создать "шапку" архива*)
            Name_old:=Name;
        END_IF
    
                                            (*-------------Работа с библиотекой OwenLibFileAsync------------*)
        CASE state OF
            0:    (*Открытие файла -  этап 1*)
                res:=OwenFileOpenAsync(name_of_file,'a',ADR(handle));;(*возвращает дескриптор файла, либо 0 (в некоторых случаях 4 294 967 295 или -1) в случае ошибки*)
                IF res=ASYNC_WORKING THEN
                    state:=1;(*нет ошибок, переход на открытие файла этап 2*)
                ELSE state:=0;
                END_IF
        
            1:    (*Открытие файла -  этап 2*)
                res:=OwenFileOpenAsync(name_of_file,'a',ADR(handle));
                IF res=ASYNC_DONE  THEN (*если "готов", и нет ошибок, то переход в состояние 2*)
                    IF handle<>0 THEN
                        state:=2;(*нет ошибок, переход на  запись этап 1*)
                    ELSE
                        state:=0;(*иначе можно перейти на 1 этап открытия файла, либо предусмотреть собственное действие самостоятельно *)
                    END_IF
                ELSIF res<0 THEN
                    state:=0;
                END_IF
    
            2:    (*Запись в файл - этап 1*)
                IF need_new_header THEN (*если новый день суток, формируем новую" шапку"*)
                    (*формируем колонку Дата*)
                        header:=CONCAT('Индекс',';');(*|число.месяц.год.|*)
                    (*формируем колонку с именем первой переменной var1*)
                        header:=CONCAT(header,'Сообщение');(*|var1*)
                        header:=CONCAT(header,';');(*|var1|*)
                        header:=CONCAT(header, '$0A');(*OA =Line Feed - перевод строки, см. таблицу ASCII -символов*)
                    (*заполняем следующую строку непосредственно данными*)
                        header:=CONCAT(header,UINT_TO_STRING(index));(*|число*)
                        header:=CONCAT(header,';');(*|число.*)
                    (*формируем значение первой переменной var1*)
                        header:=CONCAT(header, Messages.ALARM[index]);(**)
                        header:=CONCAT(header,';');(**)
                        header:=CONCAT(header, '$0A');(*OA =Line Feed - перевод строки, см. ASCII таблицу*)
                        need_new_header:=0;(*сбрасываем необходимость формировать "шапку" в следующий раз*)
    
                ELSE (*иначе, если файл открывается на дозапись,то формируем только строку архива в формате |число.месяц.год|часы.минуты.секунды|значение var1|значение var2|*)
    
                    (*заполняем следующую строку непосредственно данными*)
                        header:=CONCAT(header,UINT_TO_STRING(index));(*|число*)
                        header:=CONCAT(header,';');(*|число.*)
                    (*формируем значение первой переменной var1*)
                        header:=CONCAT(header, Messages.ALARM[index]);(**)
                        header:=CONCAT(header,';');(**)
                        header:=CONCAT(header, '$0A');(*OA =Line Feed - перевод строки, см. ASCII таблицу*)
                END_IF
                
                (*Пишем строку в файл*)
                res:=OwenFileWriteAsync(handle,ADR(header), LEN(header), ADR(result));(*пишем данные *)
                IF res=ASYNC_WORKING THEN
                    state:=3;(*нет ошибок, переход на запись файла этап 2, либо по усмотрению пользователя*)
                ELSE
                    state:=4;(*иначе можно перейти на  этап закрытия файла, либо предусмотреть собственное действие самостоятельно *)
                END_IF
    
            3:    (*Запись в файл - этап 2*)
                res:=OwenFileWriteAsync(handle,ADR(header), LEN(header), ADR(result));
                IF res=ASYNC_DONE THEN
                    IF result=LEN(header) THEN (*если результат равен длине строки, то перейти к закрытию файла, либо по усмотрению пользователя*)
                        state:=4;
                    ELSE
                        state:=4;(*иначе всё равно перейти на закрытие *)
                    END_IF
                ELSIF res<0 THEN
                    state:=0;
                END_IF
        
            4:     (*Закрываем файл - этап 1*)
                res:=OwenFileCloseAsync(handle, ADR(result));
                IF res=ASYNC_WORKING THEN
                    state:=5;(*нет ошибок, переход на закрытие файла этап 2*, либо по усмотрению пользователя*)
                ELSE
                    state:=0;(*иначе можно перейти на  этап открытия файла, либо предусмотреть собственное действие самостоятельно *)
                END_IF
        
            5:    (*Закрываем файл - этап 2*)
                res:=OwenFileCloseAsync(handle, ADR(result));
                Messages.FLAG[index]:=1;
                IF index<=98 THEN index:=index+1; END_IF;
                IF res=ASYNC_DONE THEN header:='';
                    handle:=0;
                    IF result=0 THEN
                        state:=0;(*если файл закрыт успешно, то выходим из условного оператора CASE *)
                    ELSE
                        state:=0;(*иначе всё равно выходим, либо предусмореть собственное действие*)
                    END_IF
                ELSIF res<0 THEN (*выход, либо собственное действие*)
                    state:=0;
                END_IF
    
            ELSE state:=0;
        END_CASE
    END_IF;
    (*
    Messages_ALARM1_old:=Messages.ALARM[99];
    index_old:=index;
    *)
    
        IF index>=99 THEN
            FOR i:=0 TO 98 BY 1 DO
            Messages.FLAG[i]:=0;
            Messages.ALARM[i]:='';
            END_FOR;
             index:=0;
            TRIP:=FALSE;
        END_IF;
    END_IF;
    Messages.FLAG[i]:=Messages.FLAG[i];
    Count:=Count+1;
    Прошу подсказать как можно организовать вывод текстовых сообщений с индексом и временем возникновения события
    +79104444236
    С уважением,
    Лапшин Вячеслав

  7. #267
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,253

    По умолчанию

    с остальными примерами либо не разобрался, либо они неработоспособны.
    Прошу подсказать как можно организовать вывод текстовых сообщений с индексом и временем возникновения события
    Для этого нужно разобраться с остальными примерами. Они, безусловно, работоспособны.

  8. #268

    По умолчанию

    Разобрался)) правда как-то "по-шамански".
    1. Посмотрел Ваш (3 года тому назад) снятый видеоролик на ютубе https://www.youtube.com/watch?v=kZpPiwQ5wEI
    2. Скачал архивный документ v.2.0
    3. Скачал оттуда пример работы с библиотекой CAA File CODESYS V3.5 SP11 Patch 5
    4. Сконвертировал, все обновил на что ругалось, поменял таргет на ПЛК210, загрузил и все заработало
    Последний раз редактировалось krollcbas; 16.10.2023 в 00:42.
    +79104444236
    С уважением,
    Лапшин Вячеслав

  9. #269

    По умолчанию

    Цитата Сообщение от Евгений Кислов Посмотреть сообщение
    Итак, по поводу архивации в WSTRING/Unicode.

    1. Берем исходный пример и везде, где идет работа с сохраняемыми данными, меняем тип STRING на WSTRING (это касается как кода программы StringFileExample_PRG, так и вспомогательных функций и ФБ типа CONCAT11, SPLIT_DT_TO_FSTRINGS и всех остальных). Также меняем строковые функции из библиотеки Standard на аналогичные из Standard64 (CONCAT на WCONCAT и т.д.).

    2. При записи в файл умножаем длину строки на 2 (т.к. у WSTRING каждый символ весит 2 байта):
    Код:
    fbFileWrite(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(wsArchEntry), szSize:=2*INT_TO_UDINT(WLEN(wsArchEntry)));
    3. У семейства Unicode есть разные кодировки - Utf8, Utf16, Utf32. Кроме того, бывают разные вариации с порядком байт (Big Endian и Little Endian). Чтобы упростить жизнь, придумали такую штуку, как маркер последовательности байт. В сущности - это несколько спецсимволов, которые записываются в начало файла и содержат информацию о кодировке/порядке байт. В текстовом редакторе, соответственно, эти символы не отображаются. Подробнее по ссылке.

    В CODESYS тип WSTRING связан с кодировкой UCS2. В принципе, это тот же UTF16, только каждый символ всегда занимает ровно 2 байта.
    Давайте добавим к нашему файлу маркер. Создадим в программе переменную wsByteOrderMark и инициализируем ее в коде (поскольку маркер - спецсимвол, то задаем его прямо побайтно):
    Код:
    wsByteOrderMark[0]:=16#FEFF; // почему именно такое значение - см. ссылку выше
    Маркер должен быть в начале файла - т.е. в нашем случае перед заголовком архива. Поэтому склеим его и заголовок в переменную wsFirstString:
    Код:
    wsFirstSting:=WCONCAT(wsByteOrderMark, c_sTitle);
    И теперь везде в программе, где мы раньше использовали c_sTitle, заменим ее на wsFirstSting. Собственно, вот и вся история с маркером.

    4. Не все текстовые редакторы адекватно отображают Unicode-файлы, в которых есть маркеры и спецсимволы. Например, стандартный Блокнот и встроенный редактор WinSCP - не лучший выбор. Лучше использовать что-то типа Notepad++.


    Прикладываю к посту архив с адаптированным примером, в котором ведется архивация строк типа WSTRING в файл формата .txt.
    Возник у меня такой же вопрос по архивации в WSTRING/Unicode.
    Методом проб и ошибок у меня вышло закодировать все это в UTF-16 (Little Endian), т.е. маркер не 16#FEFF, а 16#FFFE. Маркер я правда не ставил, а создал в Блокноте документ и при "сохранении как" выбрал кодировку UTF-16 (LE) - все заработало
    Вдруг кому поможет

  10. #270

    По умолчанию

    Добрый день!

    Есть необходимость в архивировании данных по трём датчикам одновременно. При этом по каждому датчику хочу вести отдельный файл. Вопрос вот какой - сколько файлов одновременно можно записывать в память на ПЛК210-02? У самого архиватора OwenArchiver ограничение - два файла, например. Но если не им, а с помощью библиотеки CAA, то можно больше?

Страница 27 из 28 ПерваяПервая ... 1725262728 ПоследняяПоследняя

Похожие темы

  1. ОРМ и архивация трм202
    от Vlad$13 в разделе OWEN Proces Manager
    Ответов: 5
    Последнее сообщение: 13.01.2017, 08:44
  2. OPM и Архивация
    от DmitrySoratnik в разделе OWEN Proces Manager
    Ответов: 1
    Последнее сообщение: 30.09.2016, 11:19
  3. Архивация в CoDeSys v3.5 SP7
    от Анатолий К. в разделе СПК2хх
    Ответов: 3
    Последнее сообщение: 04.03.2016, 11:49
  4. Архивация
    от Salvafion в разделе Master SCADA 3
    Ответов: 7
    Последнее сообщение: 28.09.2011, 08:29
  5. Архивация данных
    от Alor в разделе ПЛК1хх
    Ответов: 1
    Последнее сообщение: 25.11.2008, 11:27

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •