Документация по модулю обработки файлов BSL

Оглавление

  1. Описание модуля
  2. Диаграмма архитектуры модуля
  3. Блок-схема процессов модуля
  4. Алгоритм работы модуля
  5. Установка и настройка
  6. Конфигурация
  7. Использование модуля
  8. Вывод данных и отчеты
  9. Обслуживание и обновление
  10. Обработка ошибок и исключений
  11. Глоссарий

Описание модуля

Модуль предназначен для автоматизированной обработки зашифрованных файлов формата BSL[^BSL] (и дополнительных файлов BSLC[^BSLC]) с результатами тестирования аккумуляторных батарей. Он выполняет полный цикл действий от чтения и расшифровки входного файла до сохранения полученных данных в базе данных и формирования подробного отчета для пользователя. Основная задача, решаемая модулем, – упрощение анализа результатов испытаний батарей: модуль декодирует исходные бинарные файлы, извлекает из них все ключевые параметры теста и представления графиков, сохраняет эти данные для последующего анализа и выдает наглядный отчет с итоговыми показателями.

Принцип работы: Модуль работает в контексте веб-приложения и запускается при получении запроса на обработку загруженного файла испытаний (идентифицируемого по ID файла в системе). В процессе работы он строго следует определенному алгоритму (см. раздел Алгоритм работы модуля), включающему проверку прав доступа пользователя к файлу, расшифровку содержимого, парсинг данных измерений, сохранение результатов в базе и генерацию HTML-отчета. Модуль поддерживает тесты батарей с несколькими фазами (например, цикл заряда и разряда батареи, или измерение внутреннего сопротивления[^resistance] аккумулятора) в рамках одного файла. Также предусмотрена обработка парных файлов .BSL/.BSLC: если тест состоит из двух связанных файлов (например, основной файл разрядного теста и дополнительный файл с данными внутреннего сопротивления), модуль способен обрабатывать их совместно и формировать сводный отчет по обоим файлам.

Назначение: Внедрение данного модуля позволяет автоматизировать обработку результатов тестирования батарей. Ранее пользователям приходилось вручную расшифровывать и интерпретировать содержимое файлов испытаний; теперь же модуль берет на себя всю эту работу. В результате обеспечивается единообразное хранение результатов в структуре базы данных и получение удобочитаемых отчетов с ключевыми показателями состояния батарей, такими как емкость, напряжение, температура, внутреннее сопротивление, State of Health (SOH)[^SOH] и др. Это повышает эффективность диагностики аккумуляторов и минимизирует вероятность ошибок при ручной обработке данных.

Диаграмма архитектуры модуля

graph TD;
    start[Начало] --> checkAccess{Доступ разрешён?};
    checkAccess -- Нет --> errAccess[Ошибка доступа];
    checkAccess -- Да --> init[Инициализация контекста];
    init --> fetchMeta[Запрос метаданных];
    fetchMeta --> fileFound{Файл есть?};
    fileFound -- Нет --> errFile[Файл не найден];
    fileFound -- Да --> auth{Права доступа?};
    auth -- Нет --> errAuth[Нет прав];
    auth -- Да --> extCheck{Расширение .BSL?};
    extCheck -- Да --> decAES[Расшифровка AES];
    extCheck -- Нет --> decShift[Расшифровка сдвигом];
    decAES --> decOK{Успешно?};
    decShift --> decOK;
    decOK -- Нет --> errDecrypt[Ошибка расшифровки];
    decOK -- Да --> beginTx[Начало транзакции];
    beginTx --> parse[Парсинг файла];
    parse --> parseOK{Успех?};
    parseOK -- Нет --> errParse[Ошибка парсинга];
    parseOK -- Да --> commitTx[Фиксация транзакции];
    commitTx --> genRep[Создать отчёт];
    genRep --> output[Вывод HTML];
    output --> stop[Конец];

Рис. 1: Общая архитектура модуля обработки BSL-данных. На диаграмме показаны основные компоненты модуля и их взаимодействие: пользователь инициирует обработку загруженного файла теста батареи, после чего центральный компонент модуля (класс BSLProcessor) выполняет расшифровку файла с помощью подключаемой библиотеки и сохраняет результаты в базе данных. Затем пользователю отображается сгенерированный отчет. При наличии парных файлов (.bsl + .bslc) компонент ConsolidatedReportGenerator агрегирует данные из базы и формирует сводный отчет по нескольким файлам. База данных служит для временного хранения исходных и вычисленных параметров теста, а также для последующего анализа результатов. Пользователь взаимодействует с модулем через веб-интерфейс: загружает файл(ы) и просматривает сформированные отчеты.

Блок-схема процессов модуля

graph TD;
    user[Пользователь] -->|запускает| bslProc[BSLProcessor];
    file[Файл BSL/BSLC] -->|вход| bslProc;
    bslProc -->|расшифровка| decrypt[DecryptBSL];
    decrypt -->|AES| aesDec[AESFileDecoder];
    decrypt -->|метаданные| db[База данных];
    bslProc -->|запись| db;
    subgraph Данные теста
        tCycle[TestCycle];
        tData[TestData];
        sData[StringData];
        tPhase[TestPhase];
    end;
    bslProc -->|парсинг| tCycle;
    bslProc -->|парсинг| tData;
    bslProc -->|парсинг| sData;
    bslProc -->|фазы| tPhase;
    bslProc -->|отчёт| crg[ReportGenerator];
    crg -->|чтение| tCycle;
    crg -->|чтение| tData;
    crg -->|чтение| sData;
    crg -->|фазы| tPhase;

Рис. 2: Блок-схема всех процессов модуля. Данная блок-схема отражает пошаговый процесс работы модуля при обработке одного файла испытаний. На схеме представлены основные этапы: старт обработки, проверка прав доступа пользователя к файлу, расшифровка содержимого файла, разбор (парсинг) данных, сохранение результатов и формирование отчета. Указаны также точки возможного возникновения ошибок (отказ в доступе или сбой расшифровки) с прекращением процесса. Как видно из схемы, при успешном прохождении проверки доступа модуль расшифровывает файл и переходит к фазе парсинга. После извлечения всех данных выполняется сохранение результатов в базе данных с последующей фиксацией транзакции. На заключительном этапе генерируется HTML-отчет, который отправляется пользователю. Более детальное описание логики представлено в разделе Алгоритм работы модуля.

Блок-схема парсинга содержимого файла

graph TD;
    start[Начало] --> lines{Ещё строки?};
    lines -- Да --> type{Тип строки?};
    type -- Заголовок --> newCycle[Создать TestCycle];
    type -- Данные --> saveData[Сохранить TestData];
    type -- Итог --> saveSummary[Обработать итоги];
    type -- Фазы --> parsePhases[Обработать фазы];
    type -- Неизвестно --> err[Ошибка формата];
    newCycle --> lines;
    saveData --> lines;
    saveSummary --> lines;
    parsePhases --> lines;
    lines -- Нет --> finish[Завершено];
    err --> finish;

Блок-схема обработки фаз теста

graph TD
    A[Начало] --> B{Есть маркеры?}
    B -->|Да| C[Разобрать маркеры]
    B -->|Нет| D[Вычислить фазы]
    C --> E[Создать TestPhase]
    D --> E
    E --> F[Конец]

Блок-схема генерации отчёта

graph TD;
    start[Начало] --> check{Данные есть?};
    check -- Нет --> err[Нет данных];
    check -- Да --> init[Подготовить HTML];
    init --> table1[Таблица сопротивлений];
    table1 --> table2[Таблица фаз];
    table2 --> table3[Таблица параметров];
    table3 --> table4[Таблица диапазонов];
    table4 --> done[Отчёт готов];

Алгоритм работы модуля

Алгоритм функционирования модуля можно описать следующим образом, в порядке выполнения шагов:

  1. Получение запроса на обработку файла. Модуль запускается, когда пользователь через веб-интерфейс инициирует обработку загруженного файла испытаний. Обычно это происходит либо автоматически после загрузки файла, либо при явном вызове соответствующего скрипта с указанием ID файла (например, параметр ID в URL запроса). Модуль определяет идентификатор файла, а также параметры сессии пользователя (его UserID и права доступа).
  2. Проверка прав доступа к файлу. Перед любыми операциями модуль удостоверяется, что текущий пользователь имеет право доступа к запрашиваемому файлу. Выполняется запрос в базу данных, чтобы получить информацию о владельце файла и его пути на диске. Если пользователь, инициировавший обработку, является владельцем файла или обладает административными правами (администраторы перечислены в специальном списке BWO_ADMIN_IDS[^BWO]), то доступ разрешается. Иначе модуль выдает ошибку «Access denied» и прекращает работу. Эта проверка предотвращает несанкционированное обращение к чужим данным.
  3. Проверка наличия файла на диске. Модуль также проверяет физическое наличие файла по указанному пути в файловой системе сервера. Если файл не найден (например, был удален или путь неверен), генерируется ошибка «File not found» и выполнение останавливается. При успешной проверке доступности файла модуль переходит к следующему этапу.
  4. Инициализация контекста и расшифровка файла. Перед чтением файла модуль настраивает контекст для процесса декодирования (инициализирует соединение с базой и параметры пользователя в библиотеке расшифровки). Затем выполняется расшифровка содержимого BSL-файла.
  • Для файлов с расширением .bsl используется алгоритм AES-расшифровки: модуль вызывает функцию расшифровки DecryptBSL из подключаемой библиотеки (BSLDecryptor), которая в свою очередь использует класс AESFileDecoder. В процессе декодирования из файла извлекается встроенный RTF-документ с данными теста, из которого удаляются служебные теги и который затем конвертируется в текст в кодировке UTF-8.
  • Для файлов с расширением .bslc применяется альтернативный механизм дешифровки: эти файлы, как правило, не зашифрованы AES, а лишь содержат текст, закодированный особым образом (со сдвигом символов). Библиотека BSLDecryptor выполняет преобразование байтов согласно заданному алгоритму (корректирует некоторые байты и сдвигает кодовые точки символов на фиксированную величину), получая исходный текст. Если на этапе расшифровки происходит сбой (например, неверный ключ шифрования или поврежденный файл), модуль выбрасывает исключение «Decryption failed» и останавливает процесс. В случае успеха на выходе этого шага имеется расшифрованное текстовое содержимое файла с данными теста. Модуль дополнительно проверяет и приводит кодировку текста к UTF-8 (для корректного отображения символов, например, русских букв).
  1. Предварительная обработка содержимого. Расшифрованный текст разбивается на строки и очищается от лишних пустых символов. Некоторые строки файла представляют собой продолжения данных, поэтому модуль объединяет фрагментированные строки: каждую запись с данными измерений он собирает в одну строку, соединяя части, которые в файле могли переходить на новую строку. На этом этапе контент подготавливается к разбору – удаляются лишние переносы строк, склеиваются многострочные записи, что облегчает дальнейший парсинг.
  2. Парсинг данных файла. Это один из ключевых этапов алгоритма, где модуль анализирует каждую строку расшифрованного файла и извлекает из нее структурированную информацию. Парсинг происходит последовательно, строка за строкой, с распознаванием разных типов данных:
  • Общие параметры теста. Модуль ищет в тексте специальную метку, обозначающую дату проведения теста, и при ее обнаружении извлекает дату и сохраняет как дату испытания. Также из другой строкы считывается название теста – как правило, это строка, содержащая описание режима (например, «Тест разряда аккумулятора №…») и другие характеристики. Назначение теста позволяет определить его тип: по ключевым словам модуль выясняет, какой вид испытания проводился (разряд, заряд, мониторинг, измерение сопротивления). Эти сведения сохраняются в объекте параметров теста. Кроме того, модуль выделяет дополнительные настройки теста: номинальную емкость батареи (Ah), ток разряда (A), предельное напряжение отключения (V), ограничения по температуре и емкости, коэффициент температуры и флаги «начальная зарядка» и «итоговая дозарядка». Все эти параметры парсятся с помощью регулярных выражений из секции настроек, присутствующей в файле, и сохраняются для включения в отчет (см. раздел Конфигурация, параметрические настройки теста).
  • Метки начала и конца фаз. Если в ходе испытания батарея проходила несколько фаз (например, сначала заряд, потом разряд), то в файле присутствуют строки, отмечающие начало и окончание каждой фазы. Модуль распознает строки вида «Начало разряда 12:00:00» и «Окончание разряда 14:30:00» (строки могут быть на английском или другом языке, в файле они могут быть закодированы, но библиотека декодирования сохраняет их понятный смысл). При обнаружении начала фазы создается новый объект фазы теста (класс TestPhase) с указанием типа фазы (заряд, разряд и т.д.) и временем старта. При обнаружении соответствующей строки окончания – в текущий объект фазы заносится время окончания. Таким образом, модуль фиксирует хронологию фаз теста. Если тест одностадийный (только разряд или только сопротивление), будет одна фаза; если многостадийный – фазы добавляются последовательно в массив фаз.
  • Данные измерений по точкам времени. На протяжении теста аппарат фиксирует показания в определенные моменты времени (секундные или минутные интервалы). Каждая такая запись содержит метку времени (часы:минуты:секунды), режим работы и измеренные параметры по каналам. Модуль распознает эти строки с помощью шаблонов: извлекает время, номер канала (или батарейной цепочки) и значения величин — обычно напряжение на строке (группе аккумуляторов) и температура батареи в данный момент. В некоторых записях также может присутствовать текущий ток или другие показатели (в данном модуле учитываются напряжение и температура, поскольку ток не явно хранится в BSL-файле). Каждая такая запись заносится как объект DataPoint с полями: порядковый номер записи, номер строки батарей, время измерения, значение напряжения и температуры. Модуль параллельно обновляет глобальные минимальные/максимальные значения напряжения и температуры по всему тесту (для итоговой справки о диапазонах измерений). В результате парсинга этой части получается список временных точек, характеризующих поведение батареи в ходе теста (напряжение vs. время, температура vs. время).
  • Сводные данные по каналам (строкам). После завершения каждой фазы теста устройство часто выдает сводку по каждому каналу (строке батарей). Модуль распознает блоки строк, относящиеся к такому своду: номер канала, стартовое и конечное напряжение в начале и конце фазы, длительность фазы для данного канала, причина остановки (например, достижение минимального напряжения или окончание заданного времени теста), а также измеренная емкость, отдаваемая батареей за фазу, и процент от номинальной емкости. Эти данные парсятся и сохраняются в объекте ChannelSummary для каждого канала в структуре фазы. Например, для канала №1 модуль зафиксирует: StartVoltage (начальное напряжение), EndVoltage (конечное напряжение), MeasuredCapacity (отданная емкость, Ah), CapacityPercent (в процентах от номинала), Duration (продолжительность работы канала) и StopReason (причина завершения теста по этому каналу). Такая сводная информация помогает понять итоги разрядной (или зарядной) фазы для каждой группы аккумуляторов.
  • Данные внутреннего сопротивления. Если файл содержит результаты измерения внутреннего сопротивления батарей (как правило, это отдельный тест или отдельная часть теста), модуль ищет строки, где указаны значения тока короткого замыкания и внутреннего сопротивления для каждого канала. Эти строки распознаются по ключевым словам и единицам измерения (например, «…Resistance… мΩ»). Найденные значения модуль сохраняет в виде объектов InternalResistanceData с указанием номера канала, тока КЗ (A) и рассчитанного внутреннего сопротивления (мОм). Если таких строк несколько (по числу каналов), формируется соответствующая коллекция данных сопротивлений. В дальнейшем они будут сохранены в отдельной таблице базы данных и отображены в отчете.
  • Версия прошивки/формата. В конце файла (или в специальной строке) может содержаться информация о версии прибора или формата файла (например, обозначение версии прошивки тестера, как сочетание цифр и буквы: 1.03A). Модуль распознает такую подстроку и, если находит, сохраняет значение версии прошивки для справки. Эта информация затем заносится в базу (поле FirmwareVersion) и может отображаться в интерфейсе для понимания, каким прибором или ПО получен данный файл. По завершении этапа парсинга модуль обладает полной внутренней структурой данных по испытанию: параметры теста, список фаз (связанных с началом/окончанием и сводками по каналам), последовательность точек измерений во времени, данные по внутреннему сопротивлению, а также агрегированные экстремальные значения. Все эти данные находятся в оперативной памяти (объекты PHP) и готовы к сохранению.
  1. Сохранение данных в базе данных. Модуль переходит к этапу сохранения результатов парсинга в базу данных системы. Перед сохранением выполняется очистка старых данных, связанных с данным файлом (если файл повторно обрабатывается или обновляется). Удаляются все старые записи во вспомогательных таблицах (TestData, TestConfig, TestCycle, StringData, CellVoltageData, CellVoltageStat, InternalResistanceData, MultiConfig, BSL_Data) для данного FileID, чтобы избежать дублирования. Далее данные сохраняются по таблицам:
  • Конфигурация теста. В таблицу TestConfig заносится основная информация о тесте: идентификатор файла, тип теста (код вида испытания: 0 – разряд, 1 – заряд, 2 – мониторинг, 3 – измерение сопротивления), статус (по умолчанию 0, можно использовать для отметки успешности импорта), дата и время теста (если известна, берется дата испытания, время обычно начало дня либо из файла), а также предельные значения, применявшиеся в тесте – например, предельное напряжение отключения и предельная температура (если такие параметры были в настройках). Эти данные позволяют идентифицировать тест и его основные настройки в системе.
  • Детальные данные измерений. В таблицу TestData сохраняется каждая точка измерения из разобранного файла. Для каждой записи указывается FileID, порядковый номер записи (RecordNo по возрастанию времени), номер строки (StringNo, идентификатор канала/цепочки батарей), время (относительно начала теста или реальное время суток), зафиксированные величины: максимальное и минимальное напряжение строки в данный момент (в контексте одной записи они равны между собой, т.к. это одно измерение), а также максимальная и минимальная температура. Поскольку в рамках одной записи модуль оперирует одной строкой батарей, он заносит измеренное напряжение как «макс.» и «мин.» одинаково (для совместимости со схемой БД, которая рассчитана на агрегирование, но здесь каждая запись относится к отдельной строке). Аналогично с температурой. Таким образом, TestData содержит последовательность измерений, пригодную для построения графиков напряжения/температуры во времени.
  • Данные по фазам (циклам теста). Модуль сохраняет информацию о каждой фазе испытания в таблицу TestCycle. Для каждой фазы указывается FileID, номер фазы (Test No или Cycle No, начиная с 1), тип фазы (как определено Stage: 0 = разряд, 1 = заряд, 2 = мониторинг, 3 = сопротивление), а также время начала и окончания фазы (полные дата-время, объединяя дату теста и время из файла). Эти данные позволяют затем анализировать длительность каждой фазы. Кроме того, на основе фаз можно судить о последовательности действий в тесте.
  • Сводные данные по каналам. Детальная информация по каждому каналу в каждой фазе сохраняется в таблицу StringData. Для каждой записи StringData модуль указывает FileID, номер записи (RecordNo, начиная с 1 в рамках таблицы, соответствует каналу), номер теста/фазы (Test No, чтобы связать с TestCycle), номер канала (StringNo), а также поля: StartVoltage, EndVoltage, TestDuration (длительность фазы для данного канала), StopReason (причина остановки). Если доступны измеренные емкости, также заполняются MeasuredCapacity (А·ч) и MeasuredCapacityPercent (% от номинала) — эти поля таблицы предназначены для отображения емкости, отданной каждым каналом, и процента от номинальной емкости батареи. В текущей реализации модуля значения емкости и процента сохраняются только если они присутствовали в файле (например, для разрядных тестов). Эта таблица позволяет затем строить отчеты по каждому каналу (строке батарей) — например, сравнить, сколько емкости отдала каждая из групп аккумуляторов и до какого напряжения она разрядилась.
  • Данные внутреннего сопротивления. Если модуль получил данные внутреннего сопротивления, они записываются в таблицу InternalResistanceData. Для каждой строки батарей (ChannelNo) сохраняется значение тока короткого замыкания (ShortCircuitCurrent, А) и рассчитанное внутреннее сопротивление (InternalResistance, мΩ). Первичным ключом служит комбинация FileID+ChannelNo, то есть по каждому файлу на канал одна запись. Эта информация затем используется для вывода на экран значений внутренних сопротивлений аккумуляторов и расчета их состояния.
  • Параметры теста. В таблицу BSL_Data модуль сохраняет перечень ключевых параметров теста и их значений (одним столбцом Name, другим Value). Сюда входят номинальная емкость батареи (ParamName = NominalCapacity, в А·ч), ток разряда (DischargeCurrent, А), предел напряжения отключения (VoltageLimit, В), предел температуры (TemperatureLimit, °C, если был задан), предел емкости (CapacityLimit, А·ч, если применялся досрочный стоп по емкости), коэффициент температурной корректировки емкости (TemperatureCoefficient, 1/°C), а также флаги InitialCharge и FinalCharge (начальный заряд перед тестом и финальный заряд после теста – 1 или 0). Каждая пара (ParamName, Value) сохраняется отдельной записью. Эти данные позволяют при генерации отчета или при дальнейшем анализе точно знать, с какими настройками проводился тест. Все операции записи данных происходят внутри транзакции базы данных. Это означает, что если на любом шаге сохранения произойдет ошибка (например, сбой соединения или некорректные данные), транзакция будет откатана, и частично записанных сведений не останется — сохранится целостность данных. При успешном сохранении модуль фиксирует (commit) транзакцию, и новые записи становятся постоянными в базе.
  1. Обновление статуса файла. После успешного занесения всех результатов модуль обновляет информацию о файле в общей таблице Files. В частности, устанавливается ImportPercent = 100 (что сигнализирует о завершении импорта данных на 100%), поле Test Date and Time обновляется фактической датой/временем теста (из расшифрованного файла), записывается распознанная версия прошивки прибора (FirmwareVersion), а также тип теста (TestTypeID) — код, соответствующий основной фазе (например, 0 для разрядного теста). Эти поля могут использоваться системой для отображения списка файлов и фильтрации по типу/дате теста. Обновление статуса завершается без запуска новых транзакций, так как файл уже успешно обработан.
  2. Генерация отчета. Если модуль запущен в режиме вывода отчета (константа SHOW_REPORT включена, что обычно соответствует интерактивному вызову из интерфейса пользователя), выполняется формирование HTML-отчета по обработанному файлу. Отчет генерируется динамически на основании сохраненных данных:
  • В шапке отчета указываются идентификатор файла, дата теста, тип теста (название, например «Тест разряда №5»).
  • Если есть данные внутреннего сопротивления, выводится таблица внутреннего сопротивления с колонками: Канал, Ток КЗ (А), Внутреннее сопротивление (мΩ) для каждого канала.
  • Затем для каждой фазы теста выводится блок с заголовком фазы (например, «Фаза Discharge (10:00:00 — 14:30:00)» с указанием времени начала и конца). Под заголовком приводится таблица, суммирующая результаты этой фазы по каналам: колонки «Channel» (№ канала), «Start (V)» (начальное напряжение), «End (V)» (конечное напряжение), «Capacity (Ah)» (отданная емкость, если есть), «%» (процент от номинала, если есть), «Duration» (длительность фазы для канала) и «Stop Reason» (причина остановки). Таблица строится на основе данных StringData. Если каких-то данных нет (например, емкость может отсутствовать в фазе заряда), в ячейках ставится «N/A». Такой табличный отчет позволяет сравнить поведение разных групп аккумуляторов в рамках одной фазы.
  • После данных по фазам выводится раздел ключевых параметров теста (Key Parameters) – перечень основных настроек, использованных в тесте: номинальная емкость, ток разряда, предел напряжения, коэффициент температуры, флаг начальной зарядки, флаг финальной зарядки и т.д. Этот список формируется из параметров, сохраненных в BSL_Data (или напрямую из объекта параметров теста) и позволяет увидеть, при каких настройках проходил тест.
  • Далее приводится секция диапазонов измерений (Measurements Range), где показывается минимальное и максимальное напряжение, зафиксированное за все время теста, а также минимальная и максимальная температура батареи за время теста. Эти значения модуль вычислял в процессе парсинга (обновляя globalVoltageMin, globalVoltageMax и аналогично для температуры). Диапазоны помогают оценить, в каких пределах менялись параметры батареи. HTML-код отчета включает стили для таблиц и заголовков, оформляя отчет в удобочитаемом виде (таблицы с полосатой заливкой строк, цветовые обозначения для статусов и т.п.). Отчет выводится непосредственно на страницу пользователя, позволяя сразу просмотреть результаты после обработки файла. Если модуль запускается в фоновом режиме (например, плановой обработке без необходимости вывода), флаг SHOW_REPORT может быть отключен, и тогда генерация отчета пропускается.
  1. Генерация сводного отчета (при наличии нескольких файлов). В случае, когда пользователю необходимо объединить результаты нескольких связанных тестов, модуль поддерживает режим формирования сводного отчета. Этот режим активируется, если запрос на обработку не содержит конкретного FileID, но SHOW_REPORT включен и известен UserID. В таком сценарии запускается компонент ConsolidatedReportGenerator, который собирает все файлы данного пользователя, группирует их по базовому имени (имя до расширения) и выявляет группы с более чем одним файлом. Обычно это пары файлов: .bsl + .bslc. Для каждой такой группы компонент выполняет агрегирование данных:
    • Из таблицы InternalResistanceData извлекаются записи всех файлов группы и компонуются единым набором значений сопротивлений по каналам (если в одном из файлов группы есть сопротивления, они попадут в итог).
    • Из таблицы StringData извлекаются данные емкости (MeasuredCapacity) и процент от номинала (MeasuredCapacityPercent) по каналам для всех файлов группы. Если, например, .bsl файл содержал разрядные данные (емкость), то эти значения объединяются; если .bslc файл — данные сопротивления, он емкости не содержит.
    • Затем рассчитывается State of Health (SOH)[^SOH] для каждого канала. SOH здесь интерпретируется как процент остаточной емкости от номинальной, но не превышающий 100%. Компонент берет процент емкости (если >100, обрезается до 100) и относит его к одной из категорий состояния: «Excellent» (отличное состояние, SOH ≥ 85%), «Good» (хорошее, ≥ 75%), «Fair» (удовлетворительное, ≥ 65%) или «Poor» (плохое, < 65%). Также этим категориям соответствуют цветовые пометки в отчете.
    • Сформированный сводный отчет выводится в виде таблиц: первая таблица — Internal Resistance по каналам (канал vs сопротивление, мΩ); вторая — Capacity Measurements по каналам (канал vs измеренная емкость, А·ч, и % от номинала); третья — State of Health (SOH) по каналам (канал vs SOH % vs статусный вывод «Excellent/Good/Fair/Poor» с цветовой отметкой). Если какой-то из наборов данных отсутствует (например, нет отдельного файла с измерением сопротивления), соответствующая таблица может не выводиться. В конце каждого блока группы файлов выводится общая информация по объединенному тесту.
    Сводный отчет удобен тем, что в одном месте показывает как емкостные характеристики (результаты разрядного теста), так и внутреннее сопротивление (результаты теста на сопротивление) для одних и тех же батарей. Пользователь получает целостную картину состояния батареи.
  2. Завершение работы. После генерации требуемого отчета модуль логгирует факт успешного завершения (при активном отладочном режиме DEBUG выводится сообщение в журнал) и освобождает использованные ресурсы. Все временные структуры данных в памяти уничтожаются сборщиком PHP автоматически после окончания скрипта. Если в ходе обработки возникли ошибки, которые не были перехвачены внутри алгоритма, они логгируются (либо отображаются, если DEBUG включен) и прокидываются выше. В любом случае, по окончании работы пользователь либо получает готовый отчет, либо сообщение об ошибке, а транзакция либо фиксируется (при успехе), либо откатывается (при исключении).

Вышеописанный алгоритм охватывает полный жизненный цикл обработки файла тестирования. Для пользователя большинство шагов «скрыто» — он видит только запуск процесса, индикатор выполнения (процент импорта) и результат. Однако понимание внутренних этапов важно для грамотного обслуживания и устранения неполадок, о чем подробнее в разделах об ошибках и обслуживании.

Установка и настройка

Данный модуль разработан на PHP (совместим с PHP 8.3 и выше) и интегрируется в состав веб-приложения (например, системы мониторинга батарей). Ниже представлены требования и пошаговая инструкция по установке:

Требования к окружению:

  • PHP версии 8.1+ (модуль протестирован на PHP 8.3, с учетом строгой типизации). Необходимы включенные расширения PHP: MySQLi (для работы с базой данных), OpenSSL (для расшифровки AES), и поддержка многобайтовых строк (mbstring) для корректной обработки кодировок.
  • СУБД MySQL версии 5.7 или выше (либо MariaDB эквивалентной версии). Предполагается наличие базы данных с требуемыми таблицами (см. ниже). В прилагаемой структуре БД (wizard_online) предусмотрены все необходимые таблицы.
  • Веб-сервер (например, Apache или Nginx с PHP-FPM) для запуска PHP-скриптов, если модуль используется через веб-интерфейс.

Зависимости модуля:

  • Библиотека BSLDecryptor[^BSLDecryptor] – обеспечивает функции DecryptBSL и класс FileDecryptor для расшифровки файлов .bsl/.bslc. В проекте она подключается через файл php/deynekin.ru/BSL/bsl_decryptor_o3.php. Убедитесь, что этот файл присутствует и подключается до использования модуля.
  • Класс AESFileDecoder – реализует низкоуровневую расшифровку AES и обработку RTF. Подключается из php/deynekin.ru/AESFileDecoder.php. Этот файл также должен быть доступен. Оба файла (BSLDecryptor и AESFileDecoder) входят в поставку модуля. Если они были изменены или обновлены, используйте последние версии, совместимые с вашим PHP.
  • Файл конфигурации config.php – содержит настройки соединения с базой данных и параметры приложения (например, константа BWO_ADMIN_IDS для списка администраторов). Он должен быть скорректирован под вашу БД (имя сервера, имя базы, логин/пароль пользователя БД) и подключен перед использованием модуля.

Установка:

  1. Скопируйте файлы модуля в проект. В состав модуля входят как минимум: основной файл с классом BSLProcessorConsolidatedReportGenerator), файл bsl_decryptor_o3.php, файл AESFileDecoder.php, а также вспомогательные файлы (например, global.php и прочие, если требуются). Разместите их в директории вашего проекта (рекомендуется сохранить исходную структуру папок php/deynekin.ru/... для совместимости). Убедитесь, что файлы доступны для подключения через require_once в коде.
  2. Настройте базу данных. Выполните SQL-скрипт создания необходимых таблиц, если база еще не настроена. Минимально должны существовать таблицы, упомянутые в модуле: Files, File (таблица с путями файлов), TestConfig, TestData, TestCycle, StringData, InternalResistanceData, BSL_Data и др. (Полный список таблиц см. документацию базы данных или файл структуры БД). В прилагаемом файле структуры БД такие таблицы описаны. Особенно обратите внимание, чтобы поля этих таблиц соответствовали тем, которые модуль пытается заполнить (в случае расхождений версий следует обновить модуль или структуру).
  3. Настройте файл конфигурации. Откройте config.php и пропишите параметры доступа к вашей базе данных (хост, имя базы, пользователь, пароль). Установите константу BWO_ADMIN_IDS — массив ID пользователей, которым будет разрешено обрабатывать любые файлы (администраторы). Обычно в эту константу включают ID вашего администратора или технической учетной записи. Убедитесь, что config.php подключается перед созданием объекта BSLProcessor (в коде модуля он подключается через require_once 'config.php').
  4. Проверьте подключение зависимостей. Удостоверьтесь, что в основном файле модуля правильные пути в require_once для bsl_decryptor_o3.php и AESFileDecoder.php. При необходимости скорректируйте пути, если файлы лежат в другом каталоге. Аналогично, проверьте, что в bsl_decryptor_o3.php используется правильный неймспейс и подключается класс AESFileDecoder (в предоставленном файле это уже настроено).
  5. Включите модуль в приложение. Если ваше приложение имеет механизм автозагрузки классов – убедитесь, что классы MikhailDeynekin\BSLDecryptor\FileDecryptor, AESFileDecoder, BSLProcessor и другие доступны. Если нет – прямое подключение через require_once (как реализовано) должно быть достаточно. Обычно модуль интегрируется в обработчик загрузки файлов: после того, как файл загружен и сохранен, вызывается new BSLProcessor($mysqlix, $fileId) и затем $processor->process(). Добавьте этот вызов в нужном месте логики вашего приложения (например, в контроллере после сохранения файла).
  6. Настройка прав и доступа. Следует убедиться, что пользователь веб-сервера имеет права на чтение загруженных файлов в директории, где они хранятся (путь SystemPath указывается в таблице File). Также, если используется open_basedir или другие ограничения, путь к файлам должен быть разрешен для чтения.
  7. Отладочные настройки (при необходимости). В начале основного файла модуля определены константы DEBUG и SHOW_REPORT.
  • DEBUG включает вывод отладочной информации (в виде HTML-блоков <pre> с логами) и запись ошибок в error_log. В рабочей (продуктивной) среде стоит установить DEBUG = false, чтобы не показывать внутренние детали. Однако на этапе настройки полезно включить DEBUG, чтобы видеть ход выполнения и возможные проблемы.
  • SHOW_REPORT управляет выводом отчета. Если модуль используется в интерактивном режиме, оставьте true – тогда отчет будет показываться сразу после обработки. Если же модуль вызывается в фоне (без прямого показа отчета пользователю), можно отключить SHOW_REPORT, чтобы скрипт отработал тихо, сохранив данные в БД, а отчет мог быть сформирован позже другими средствами.
  1. Тестирование установки. После выполнения всех настроек, загрузите через систему тестовый BSL-файл и попытайтесь его обработать. Проверьте, что:
  • Проходят этапы доступа (если вы не владелец файла, убедитесь, что ваш ID включен в BWO_ADMIN_IDS, либо тестируйте под владельцем).
  • Файл успешно расшифровывается (в случае ошибки на этом этапе убедитесь, что файл валидный и библиотека расшифровки работает – попробуйте декодировать известный корректный файл).
  • В базу данных заносятся записи. По окончании ImportPercent в таблице Files должен стать 100, а таблицы TestData и прочие – пополниться новыми строками. Если этого не произошло, ищите сообщения об ошибках (при DEBUG они отобразятся на странице, также смотрите логи веб-сервера и MySQL).
  • Отчет формируется и корректно отображает информацию из вашего тестового файла. Проверьте отображение символов (должны читаться русские буквы, единицы измерения, спецсимволы температуры °C и т.д. – если вместо них «?�, значит проблемы с кодировкой UTF-8, убедитесь что mbstring работает и файл действительно сконвертирован).
  • Попробуйте загрузить парный файл (если есть .bsl и .bslc с одинаковым именем). После обработки каждого убедитесь, что сводный отчет (который выводится при открытии страницы отчета без указания конкретного ID, т.е. автоматически для всех файлов пользователя) содержит объединенную информацию.

Если все шаги прошли успешно, модуль установлен и готов к использованию. В противном случае обратитесь к разделу Обработка ошибок и исключений для получения советов по устранению неполадок.

Конфигурация

В данном разделе подробно описываются конфигурационные параметры модуля и их влияние на работу, а также способы их изменения.

Файл конфигурации (config.php): Этот файл загружается модулем и должен содержать следующие настройки:

  • Параметры подключения к базе данных: $DB_Server (адрес сервера БД), $DB_Name (имя базы), $DB_User и $DB_Password (учетные данные доступа). Они используются для создания объекта $mysqlix (соединение MySQLi), через который модуль выполняет все SQL-запросы.
  • Константа BWO_ADMIN_IDS: массив с целочисленными ID пользователей, которым предоставлены права администратора в контексте обработки файлов. Любой UserID, присутствующий в этом списке, минует проверку владения файлом – то есть сможет обработать файл, загруженный другим пользователем. По умолчанию в примере конфигурации указаны ID 9 и 10, их следует заменить или дополнить в соответствии с вашей системой (например, ID учетной записи администратора). Обратите внимание: сам по себе этот список не управляет привилегиями в интерфейсе, но именно на него опирается модуль при решении, давать ли доступ к чужому файлу.
  • Настройки локали/языка (если применимо): В приведенном config.php производится выборка из таблицы Translate и установка глобального массива $GLOBALS["Translate..."] с переводами. Это указывает, что система поддерживает мультиязычные надписи. Убедитесь, что таблица Translate существует и содержит необходимые ключи. Переводы используются, например, для сообщений об ошибках (в коде есть вызов die(«Access Blocked»), который в данном случае на английском, но система, возможно, подставляет переводы).
  • Прочие глобальные переменные $GLOBALS[...]: В config.php загружаются данные текущего пользователя (UserName, CompanyID и др.). Обычно изменять эти настройки не требуется – они получены из базы для текущей сессии. Но важно понимать, что модуль использует $GLOBALS['UserID'] для определения текущего пользователя. Если вы интегрируете модуль в нестандартную среду, убедитесь, что глобальная переменная UserID установлена до вызова модуля (в противном случае проверка доступа всегда будет падать). В стандартной поставке config.php это уже сделано.

Внутренние константы модуля:

  • DEBUG (boolean): включение режима отладки. Если TRUE, модуль будет выводить подробный лог выполнения в браузер (каждый шаг с пометкой [DEBUG]) и также записывать ошибки через error_log. В режиме DEBUG веб-страница отчета может содержать технические сведения, поэтому не рекомендуется оставлять DEBUG=true на рабочем сервере. Для постоянного использования установите FALSE.
  • SHOW_REPORT (boolean): флаг отображения отчета. Если TRUE, модуль после обработки немедленно выведет разметку отчета (в HTML) в поток вывода. Если модуль вызывается через AJAX или в случае, когда отчет формируется иначе, можно поставить FALSE, чтобы избежать вывода HTML. Обычно этот флаг оставляют включенным при интерактивной работе.
  • Stage (перечисление enum): внутри кода определено перечисление типов фаз теста (Discharge = 0, Charge = 1, Monitoring = 2, Resistance = 3). Это используется для установки полей TestTypeID и при парсинге. При необходимости можно добавить новые типы, если появятся другие режимы тестов, но тогда потребуется и расширение логики парсера и сохранения.
  • Размер сдвига для BSLC: в bsl_decryptor_o3.php класс FileDecryptor использует свойство private readonly int $shift = 10 для дешифровки .bslc файлов. Обычно менять это не нужно (10 – это известный сдвиг по протоколу производителя). Но если вдруг файлы BSLC в будущем будут шифроваться иначе, здесь можно корректировать алгоритм.

Параметры теста из файла: После обработки файла модуль сохраняет ряд параметров в таблице BSL_Data, как упоминалось ранее. Кратко опишем их и откуда они берутся:

  • NominalCapacity – номинальная емкость батареи (А·ч), задается в настройках теста оператором перед началом (или считывается из профиля батареи). В файле обычно присутствует строка с этим значением.
  • DischargeCurrent – ток разряда (А), при котором проводился тест. В протоколе устройства есть строка, содержащая заданный ток нагрузки для теста разряда.
  • VoltageLimit – предельное напряжение (В), до которого разряжается батарея (нижний порог, при достижении которого тест останавливается). Указывается в настройках теста.
  • TemperatureLimit – предельная температура (°C), выше которой тест должен быть прерван (например, во избежание перегрева). В ряде устройств можно задать такую защиту. Если такая настройка была (и строка присутствует), модуль может её считать. В текущей версии кода парсинг TemperatureLimit явно не реализован (возможно, в рассматриваемом формате не было этой опции или она не передается), но поле присутствует – его можно расширить при необходимости.
  • CapacityLimit – предельная отдаваемая емкость (А·ч) для досрочного завершения теста. Иногда тест останавливают, если набрано определенное количество А·ч, даже если напряжение не упало до лимита. Если файл содержит этот параметр, он будет зафиксирован.
  • TemperatureCoefficient – температурный коэффициент емкости, 1/°C. Для некоторых батарей емкость пересчитывается к стандартной температуре (обычно 25°C) с использованием коэффициента α. Значение α (например, 0.0060 или другое) могло быть указано в настройках теста – модуль его считывает. Это значение не участвует прямо в расчетах модуля, но может использоваться пользователем отчета для корректировки емкости при отличии от нормированной температуры.
  • InitialChargeEnabled – флаг, указывающий, был ли перед началом теста выполнен начальный заряд батареи. В протоколе это может отображаться как отметка «Initial charge: Yes/No». Модуль парсит строку и записывает 1 (если «Да») или 0 (если «Нет»).
  • FinalChargeEnabled – флаг о том, выполнялся ли заключительный заряд после теста (например, чтобы восстановить батарею). Аналогично парсится и сохраняется как 1 или 0.

Изменять эти параметры вручную не требуется – они извлекаются из файлов. Однако, важно их наличие в отчете. Если вы замечаете, что какой-то параметр не был считан, возможно, формат файла отличен и регулярное выражение в коде не сработало. В этом случае можно поправить функцию parseTestParameters в модуле, добавив или скорректировав паттерн для нужной строки.

Настройка формата отчетов: По умолчанию модуль формирует HTML-таблицы с англоязычными заголовками колонок («Channel», «Start (V)», etc.) и статусами («Excellent», «Good»). Если требуется локализация отчета на русский (или другой язык), необходимо либо модифицировать шаблон генерации отчета (в методе generateReport() класса BSLProcessor и в методе renderConsolidatedReport() класса ConsolidatedReportGenerator), либо воспользоваться системой переводов приложения (таблица Translate). Проще всего отредактировать строки прямо в коде на нужный язык. Например, заменить <th>Channel</th> на <th>Канал</th> и т.д. Также категории SOH («Excellent» и пр.) можно заменить на локализованные варианты. Имейте в виду, что при обновлении модуля эти изменения нужно будет применять заново, т.к. они не выносятся в настройки.

Использование модуля

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

Запуск обработки файла: Пользователь обычно взаимодействует с модулем через интерфейс загрузки/просмотра файлов. Типовой сценарий:

  1. Пользователь загружает файл результатов теста батареи (формата .bsl и при наличии .bslc) через веб-интерфейс. Система сохраняет файл на сервере и регистрирует его в базе данных (запись в таблице Files и File с привязкой к UserID).
  2. После загрузки рядом с файлом в интерфейсе появляется опция «Импортировать данные» или автоматически стартует импорт. При старте импортирования приложение вызывает наш модуль, передавая ему идентификатор файла. Это может быть реализовано, например, через переход на URL вида /process_file.php?ID=<номер> или через AJAX-вызов соответствующего скрипта.
  3. Модуль BSLProcessor начинает обработку в соответствии с алгоритмом (подробно описанным выше). Пользователь может видеть индикатор выполнения (например, процент, который обновляется от 0 до 100). В нашем случае модуль устанавливает поле ImportPercent = 100 только по завершении, поэтому если нужна плавная индикация, это делается внешними средствами или транслируется лог исполнения (при DEBUG можно видеть этапы, но для пользователя обычно достаточно дождаться готовности).
  4. По окончании обработки, если все прошло успешно, пользователю отображается отчет. Отчет представляет собой веб-страницу (или часть страницы), где красиво оформлена вся информация теста. Пользователь может пролистать отчет, скопировать оттуда данные или сохранить страницу для отчета. Если модуль интегрирован правильно, отчет будет встроен в ваш шаблон интерфейса.

Просмотр сводного отчета: Если пользователь загрузил парные файлы или несколько результатов по одной батарее, ему может понадобиться сводный отчет. В типичной реализации интерфейса сводный отчет может формироваться автоматически, когда пользователь открывает страницу с деталями конкретного теста. Например, если файлы именуются Battery123.bsl и Battery123.bslc, то при открытии отчета Battery123 система может отобразить объединенные данные. Наш модуль реализует сводный отчет, когда вызов происходит без явного ID (но при условии, что SHOW_REPORT = true и известен текущий пользователь). То есть если, к примеру, веб-страница отчета устроена так, что при переходе на нее она не получает параметр ID, то модуль сгенерирует отчет по всем файлам текущего пользователя сгруппированно. В противном случае, чтобы инициировать сводный отчет, можно создать отдельный режим: вызывать ConsolidatedReportGenerator вручную с нужными ID группы.

Для пользователя сводный отчет выглядит как часть обычного отчета: после основной информации по каждому отдельному тесту (или вместо нее) отображаются агрегированные таблицы. Пользователю не нужно предпринимать специальных действий, кроме как загрузить оба файла и открыть отчет – модуль сам распознает, что у файла есть «пара».

Использование результатов из базы: Помимо визуального отчета, результаты, сохраненные модулем, могут использоваться далее в приложении. Например:

  • Построение графиков разряда: можно выбрать данные из TestData по нужному файлу и построить график напряжения по времени, доступный на отдельной вкладке интерфейса.
  • Сравнение каналов: по таблице StringData можно составить сравнение, какие группы аккумуляторов сильнее просели по напряжению или отдали меньшую емкость.
  • Анализ трендов: если система ведет историю тестов одной и той же батареи (идентифицируя по BatteryID), то через связку BatteryID -> Files -> BSL_Data/StringData можно отслеживать деградацию (например, SOH) с течением времени.
  • Экспорт данных: при необходимости администратор может выгрузить данные в CSV или другой формат напрямую из таблиц, зная, что они актуальны и получены из исходного файла.

Интерпретация отчета пользователем: Документация модуля должна снабжать конечного пользователя разъяснениями по содержимому отчета. В отчете присутствуют следующие ключевые элементы, требующие понимания:

  • Внутреннее сопротивление (мΩ) – показывает здоровье батареи: более низкое сопротивление обычно говорит о лучшем состоянии. Пользователь может сравнить эти значения с эталонными или между каналами.
  • Измеренная емкость (А·ч) – сколько емкости смогла отдать батарея при разряде. Идеально это близко к номиналу, снижение говорит об ухудшении емкости.
  • Процент от номинала (%) – тот же показатель емкости, выраженный в процентах номинальной. Проще для восприятия состояния: например, 85% и выше обычно считается хорошим состоянием.
  • Продолжительность теста – время, за которое батарея разрядилась до порога. Это косвенно тоже характеризует емкость и нагрузку.
  • Причина остановки – указывает, что положило конец тесту: чаще всего «достигнуто минимальное напряжение» (что нормально) или, например, «достигнут лимит времени» либо «ошибка» – на этот пункт стоит обращать внимание, т.к. если тест прерван не по достижению разрядного порога, результаты могут быть неполными.
  • Диапазоны напряжения/температуры – полезно для убедиться, что тест проходил в штатных условиях: например, температура не превышала допустимую, напряжение упало до ожидаемого порога.
  • SOH и статус – в сводном отчете каждому каналу дается оценка состояния. Это позволяет сразу увидеть, какие батареи требуют внимания (помечены «Poor» – плохое состояние, вероятно, требуют замены), а какие работают хорошо.

Для уверенности пользователя в корректной работе модуля можно указать, что все вычисления (например, процент емкости, SOH) берутся напрямую из исходных данных или простыми формулами, без сложных моделей. Например, % емкости – это (измеренная емкость / номинальная * 100), а SOH – это этот процент ограниченный 100%. Таким образом, пользователи будут знать, что оценка SOH напрямую связана с емкостным тестом.

Особые случаи использования:

  • Однофайловые тесты. Если тест не разбит на два файла, модуль все равно сработает. Например, если прибор выводит все данные (и сопротивление тоже) в одном .bsl файле, модуль парсит и сохранит все. Сводный отчет в этом случае по сути повторит одиночный, или же система может не вызывать ConsolidatedReportGenerator вовсе.
  • Несколько тестов подряд. Если пользователь загрузил много разных файлов, их обработка производится по одному. Модуль не предназначен для пакетного импорта сразу множества файлов за один вызов — для этого нужно вызывать process() для каждого FileID отдельно или использовать цикл. Однако, если нужно автоматизировать импорт сразу всех загруженных файлов (например, ночной обработкой), можно написать скрипт, выбирающий все файлы ImportPercent != 100 и вызывающий для каждого BSLProcessor.
  • Повторная обработка файла. Если по каким-то причинам нужно перезапустить импорт одного и того же файла (например, после обновления алгоритма парсинга), достаточно повторно вызвать модуль с тем же ID. Модуль сам очистит предыдущие данные и заново заполнит БД. Важно: при этом ImportPercent будет уже 100, но можно перед повторной обработкой сбросить его вручную в 0 для наглядности (не обязательно). Также убедитесь, что файл физически на месте.
  • Удаление/очистка данных. Если файл удаляется из системы, стоит удалить и связанные с ним записи в таблицах, т.к. модуль их не удалит автоматически при удалении файла (он удаляет только при повторном импорте). Обычно в системе настроены каскадные удаления (например, InternalResistanceData связан FOREIGN KEY с Files.ID ON DELETE CASCADE). Проверьте, что Constraints в БД настроены, как в структуре, чтобы при удалении записи Files все связанные TestData и прочие удалились.

Вывод данных и отчеты

Этот раздел фокусируется на выходных данных модуля – HTML-отчетах и содержимом, сохраненном в базах, – с описанием их структуры и рекомендациями по использованию.

HTML-отчет после импорта: Отчет формируется модулем автоматически и выдаётся пользователю. Структура отчета:

  • Заголовок отчета: Название (например, Battery Test Report), может быть изменено под нужды приложения (в коде это строка "<h2>Battery Test Report</h2>"). Далее – краткие сведения: File ID, Test Date (дата испытания), Test Type (название теста). Эти данные дают понять, какой файл и какой тест пользователь смотрит.
  • Таблица внутреннего сопротивления: Появляется только если в данных присутствуют значения сопротивления. Таблица имеет заголовки: Channel | Short Circuit Current (A) | Resistance (mΩ). Здесь перечисляются все каналы, для которых были данные. Если, скажем, тест был на 6 аккумуляторов, будет 6 строк – канал 1..6 и соответствующие значения. Пользователю это показывает разброс сопротивлений и токов КЗ по батареям.
  • Фазы теста: Далее для каждой фазы (Phase) выводится подзаголовок <h4> с именем фазы (например, Discharge Phase или Charge Phase) и, если известны времена, в скобках интервал времени (Start — End). Внутри каждого блока фазы – таблица channel-summary с детальной информацией, описанной ранее. Эта таблица содержит 7 колонок: Channel, Start (V), End (V), Capacity (Ah), %, Duration, Stop Reason. Каждая строка – один канал (строка батарей).
  • Channel – номер канала.
  • Start (V) – напряжение в начале фазы (обычно полностью заряженное напряжение для разряда, или начальное для заряда).
  • End (V) – напряжение в конце фазы (например, конечное напряжение разряда или достигнутое при заряде).
  • Capacity (Ah) – измеренная емкость, которая прошла через аккумулятор за фазу. Заполнена для фаз разряда (отданная емкость) или заряда (полученная емкость), если устройство это рассчитывает. Может быть N/A, если не применимо.
  • % – процент от номинальной емкости, соответствующий этой емкости. Помогает сразу видеть, насколько каждая группа отстала от 100%.
  • Duration – длительность фазы для данного канала. Как правило, должна совпадать между каналами, если все закончились одновременно, но может отличаться, если какие-то каналы отключились раньше (например, один элемент просел по напряжению быстрее).
  • Stop Reason – текстовое описание причины остановки конкретно этого канала. Может быть, например, «Voltage limit reached» (достигнут порог напряжения), «Time limit reached» (вышло отведенное время), либо указание на ручную остановку или ошибку. Таблица позволяет сравнить показатели каналов между собой. Например, если один из 6 каналов имеет Capacity 80% а остальные ~95%, это сразу видно – значит этот канал слабее держит емкость.
  • Ключевые параметры: Список в виде <ul> (маркированный список), где каждый пункт – имя параметра и его значение. Тут выведены Nominal Capacity, Discharge Current, Voltage Limit, Temperature Coefficient, Initial Charge (Yes/No), Final Charge (Yes/No). Эти параметры берутся из объекта TestParameters, где они были сохранены. Если какого-то параметра нет, пишется ‘N/A’. Например, если не задан лимит температуры, Temperature Coefficient будет N/A.
  • Диапазоны измерений: Тоже список: Voltage Range и Temperature Range, показывающие минимальное и максимальное напряжение (например, 10.5V — 13.8V) и минимальную/максимальную температуру (например, 18°C — 27°C) за весь тест.
  • Дополнительно: В оформлении отчета могут быть цветовые маркеры для SOH (в сводном отчете). Там используется CSS классы .status-excellent (зеленый текст), .status-good (светло-зеленый), .status-fair (оранжевый), .status-poor (красный). Они применяются к ячейкам статуса SOH, чтобы визуально выделять состояние батарей. Также, при DEBUG, отчет может включать блоки <pre class='debug-log'> с подробностями парсинга – в нормальных условиях этого не будет.

Отчет можно распечатать или сохранить как HTML – он автономен (включает стили в <style>). Если нужно изменить внешний вид отчета (например, подгон под корпоративный стиль), можно отредактировать CSS в конце файла модуля (там явно выводятся стили).

Структура данных в базе: После работы модуля база содержит информацию, которая может быть задействована в разных пользовательских отчетах и интерфейсах:

  • В таблице Files для данного файла установлены Test Date and Time (дата/время испытания) и TestTypeID. UI системы может, например, показывать список файлов с колонками «Дата испытания» и «Тип теста» – эти поля заполнены благодаря модулю.
  • TestData – временные ряды напряжений/температур. Может быть использовано для графиков. Например, построение графика напряжения строки №1: SELECT Time, String Voltage Min, String Voltage Max FROM TestData WHERE FileID=X AND StringNo=1 даст точки для графика (Min и Max будут равны, т.к. это одно значение в момент).
  • StringData – конечные результаты по фазам. Ее можно использовать для отчета о емкости: например, вывести для файла X: канал, измеренная емкость, процент – это напрямую из этой таблицы (MeasuredCapacity, MeasuredCapacityPercent). В принципе HTML-отчет это уже показывает. Кроме того, там есть StartVoltage и EndVoltage – можно, к примеру, в UI отобразить не только емкость, но и до какого напряжения разрядилась батарея.
  • InternalResistanceData – если планируется отдельный раздел интерфейса для сопротивлений, по этой таблице можно вывести список сопротивлений по каналам. Например, система может показывать «Внутреннее сопротивление батареи №…: 5 мΩ» и т.д. Также, если несколько тестов, можно отслеживать изменение сопротивления во времени.
  • BSL_Data – содержит параметры NominalCapacity и прочие. Может использоваться, чтобы заполнить карточку теста: например, при открытии файла выводить «Номинальная емкость: 100 А·ч, Ток разряда: 50 А, Ожидался порог напряжения: 10.5 В» – все это можно взять из BSL_Data. Также туда записаны InitialCharge и FinalCharge (0/1) – можно отобразить галочки типа «Начальная зарядка проведена: Да/Нет».
  • TestCycle – содержит времена начала/конца фаз и их типы. Можно, например, на таймлайне отобразить, когда был заряд и когда разряд. Или вывести длительность каждой фазы. Частично это дублируется в StringData (TestDuration), но TestCycle более про весь файл, а StringData – по каналам.

Взаимосвязи: TestCycle и StringData по полю Test No (номер фазы), Files с остальными по FileID. Обычно, интерфейс приложения уже знает FileID, и через него можно JOIN-ить эти таблицы для составления сложных отчетов.

Важно отметить: данные в базе хранятся в инженерных единицах (В, А, А·ч, °C, Ом). Следовательно, при выводе их на экран нужно форматировать с нужным количеством знаков и добавлять единицы измерения. В HTML-отчете, например, это сделано прямо в шаблоне (добавлены V, A, Ah, %, °C где нужно). Если вы делаете свой вывод, не забывайте единицы.

Экспорт и интеграция данных: При необходимости, модуль можно использовать не только для веб-отчетов, но и для экспорта в другие форматы. Например, можно доработать его, чтобы после сохранения в БД сразу генерировать CSV-файл с ключевой информацией или PDF-отчет. Благодаря тому, что вся логика получения данных уже реализована, подобные расширения сводятся к формированию нужного представления. В текущей версии модуль таких форматов на выходе не создает, но открытость данных позволяет внешними средствами это делать.

Обслуживание и обновление

Для поддержания работоспособности модуля в долгосрочной перспективе, следует учесть несколько моментов по обслуживанию, мониторингу и обновлению:

Логирование и мониторинг: При включенном DEBUG модуль пишет отладочные сообщения в системный лог PHP (через error_log). Рекомендуется настроить улавливание важных сообщений (например, ошибок расшифровки, отказов доступа) в логах и уведомление ответственных лиц при их появлении. В продакшене DEBUG обычно отключен, но можно оставить запись ошибок (в блоке catch (Exception $e) ошибки пишутся в лог вне зависимости от DEBUG). Регулярно просматривайте эти логи, чтобы выявлять проблемы (например, новые типы файлов, которые не парсятся полностью, или повторяющиеся отказы доступа).

Очистка данных: Если база данных активно наполняется тестовыми данными, объем таблиц TestData и особенно StringData может расти существенно (каждый тест может содержать тысячи точек измерений). Разработайте политику очистки/архивации: например, хранить подробные данные только за последний год, старые архивировать или удалять. Модуль сам не удаляет ничего, кроме связанных данных того же файла при его повторной обработке, поэтому контроль за объемом лежит на администраторах БД.

Обновление модуля: Время от времени могут выходить обновления модуля от разработчика (особенно если изменяется формат BSL-файлов производителем оборудования). Чтобы обновить модуль:

  • Замените файлы класса (BSLProcessor, ConsolidatedReportGenerator, BSLDecryptor, AESFileDecoder) на новые версии.
  • Проверьте заметки о смене версий (в комментариях в начале файлов обычно перечислены изменения). Обратите внимание, не появились ли новые поля, которые нужно добавить в БД, или изменения форматов.
  • Протестируйте на нескольких файлах, особенно на тех, которые ранее могли вызывать затруднения.
  • При обновлении убедитесь, что сохранены ваши локальные правки (например, переводы интерфейса или измененные настройки). По возможности, старайтесь вносить изменения через конфигурацию, а не в код – тогда обновление пройдет прозрачнее. Например, если хотели поменять текст в отчете, лучше добавить соответствующие переводы в таблицу Translate, чем править строку кода.

Совместимость: Следите за версиями PHP – с выходом новых версий может потребоваться небольшая корректировка кода (как это было при переходе на PHP 8.3 – комментарий в коде говорит о приведение в соответствие). Разработчики модуля уже адаптировали его к 8.3, поэтому проблем не ожидается, но при переходе на PHP 8.4+ имейте это в виду. Также убедитесь, что библиотека OpenSSL в PHP актуальна (для AES), и mbstring способен распознать cp1251 -> utf8 корректно (в старых версиях иногда были проблемы с редкими символами).

Изменение формата файлов: Если производитель оборудования внесет изменения в формат BSL/BSLC:

  • Добавятся новые типы строк – потребуется дополнить парсер. Например, если начнут записывать ток нагрузки в каждую точку, модуль сейчас его не считывает. Чтобы не потерять данные, можно дописать в parseDataPoints распознавание тока (в файле могут быть конструкции типа I1=...).
  • Изменится способ шифрования – потребуется обновление или замена AESFileDecoder/алгоритма. Например, сменят ключ шифрования – тогда функцию generateDefaultKey() надо будет заменить на чтение нового ключа (возможно, ключ будет привязан к устройству, тогда нужно получение ключа из кода или базы).
  • Появятся новые секции данных – например, данные о заряде батареи при восстановлении. Их тоже можно добавить: модуль устроен модульно, можно вставить новый метод parseXYZ и вызывать его в цикле парсинга строк.

В подобных случаях тщательно протестируйте модификации на копиях файлов, убедитесь, что не нарушили парсинг старых форматов (желательно сохранять обратную совместимость).

Производительность: При обработке очень больших файлов (десятки тысяч записей) модуль может потреблять значительные ресурсы. В коде уже предприняты некоторые оптимизации (работа с транзакцией, использование подготовленных выражений при вставке данных, чтобы не переподключаться к БД). Тем не менее, следите за:

  • Лимитом памяти PHP: большие файлы (сотни тысяч строк) могут не поместиться, рекомендуется PHP memory_limit не ниже 128M, а лучше 256M на всякий случай.
  • Временем выполнения: при необходимости, увеличьте max_execution_time для скрипта, если ожидаете очень долгих импортов. В противном случае PHP может прервать выполнение на середине (в логах вы это увидите).
  • Разбиением больших файлов: если устройство генерирует гигантские BSL, подумайте, нужно ли разбивать тест на части. Наш модуль не делает стриминговой обработки (он читает весь файл в память, а затем разбирает), поэтому файлы в сотни МБ будут тяжелы. Возможно, лучше ограничивать размер тестов или обновить модуль, чтобы он читал и обрабатывал построчно (стриминг).

Резервное копирование: Так как результаты тестов сохраняются в БД, важно настроить резервное копирование базы, чтобы не потерять накопленную статистику. Сами исходные файлы .bsl/.bslc также могут храниться (в таблице File хранится SystemPath – путь к ним). Решите, нужно ли хранить сами файлы после успешного импорта. Если нет, можно их удалять для экономии места, оставляя только данные в базе и отчеты. Если да – убедитесь, что они тоже включены в бэкап, т.к. без них повторный импорт невозможен.

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

Обработка ошибок и исключений

Несмотря на надежность алгоритма, в процессе работы модуля могут возникать ошибки – как вследствие некорректных данных, так и из-за проблем окружения. В этом разделе перечислены наиболее часто встречающиеся исключения, их причины и способы устранения.

1. Ошибка доступа к файлу (Access denied).
Симптомы: В интерфейсе при попытке обработки файла появляется сообщение об ошибке доступа, либо в логах фиксируется исключение RuntimeException: "Access denied for file: X" (где X – ID файла).
Причины: Текущий пользователь не является владельцем файла и не входит в список администраторов BWO_ADMIN_IDS. Модуль останавливает работу, чтобы предотвратить чтение чужого файла.
Решение: Убедитесь, что пользователь имеет права на данный файл. Если необходимо, добавьте его ID во временный список админов или отключите проверку (не рекомендуется в продуктиве). Правильнее – зайти под пользователем-владельцем или настроить распределение прав в системе (например, позволять определенным ролям просматривать файлы других). Также, проверьте, корректно ли определяется $GLOBALS['UserID'] – возможно, при вызове модуля вне нормальной сессии пользователя переменная не установлена, тогда доступ будет воспринят как от несуществующего пользователя. Установите глобально UserID перед вызовом process().

2. Файл не найден (File not found).
Симптомы: В логе: RuntimeException: "File not found: /path/to/file" или "File not found: {fileId}". В отчете DEBUG может быть строка [ERROR] File not found: ....
Причины: По указанному в базе пути файл отсутствует на диске. Это может быть из-за удаления файла, некорректного пути (например, неправильно настроен базовый каталог загрузки), отсутствия прав доступа на файловой системе или попытки доступа к файлу до завершения загрузки.
Решение: Проверьте, существует ли файл по пути, указанному в таблице File (поле SystemPath). Если нет – возможно, загрузка прошла неверно или файл был удален вручную. Заново загрузите файл. Если путь неверный – исправьте путь в базе или механизм формирования пути. Также проверьте права: веб-сервер должен видеть этот путь. Если используются символические ссылки или сетевые хранилища – убедитесь, что PHP имеет к ним доступ.

3. Расшифровка не удалась (Decryption failed / empty content).
Симптомы: В отладочном выводе сообщение Decryption failed: ... или RuntimeException: "Decryption returned empty content". Отчет не сформирован.
Причины: Модуль не смог корректно декодировать файл. Возможные подтексты:

  • Файл поврежден или не является корректным BSL-файлом.
  • Неправильно подключена или работает библиотека AESFileDecoder (например, отсутствует OpenSSL).
  • Файл зашифрован незнакомым ключом или другим методом (если это новый формат, неподдерживаемый данной версией модуля).
  • В редких случаях файл может не содержать данных (0 байт), тогда после расшифровки контент пустой.
  • Функция DecryptBSL могла не найти функцию (если Context не инициализирован или функция не подключена). Но в коде на этот случай стоит проверка. Если, однако, вы видите ошибку ‘DecryptBSL function not found’ – значит, не подключен файл bsl_decryptor_o3.php.
    Решение: Убедитесь, что подключены все нужные файлы (в начале лога DEBUG должна быть строка «[DEBUG] File content loaded successfully…» – если ее нет, вероятно не вызвалась DecryptBSL). Если функция не найдена – проверьте пространство имен: возможно, вызов должен быть \MikhailDeynekin\BSLDecryptor\DecryptBSL (в коде это учтено). Если проблема в самом шифровании – попытайтесь вручную воспользоваться функцией Decode_AES_IV($filePath) из AESFileDecoder, чтобы проверить, расшифровывается ли файл. Также проверьте, начинается ли исходный файл с заголовка RTF (обычно в зашифрованном виде это невозможно увидеть, но после дешифровки должен появиться {\\rtf). Если этого не происходит – возможно, ключ шифрования другой. По умолчанию AESFileDecoder использует ключ из 32 байт (0x00..0x1F) – стандартный для данного прибора. Если производитель сменил ключ, необходимо его узнать и указать (например, поправить метод generateDefaultKey или передать нужный ключ в конструктор AESFileDecoder).
    Если файл поврежден (не полностью скопирован, обрезан) – перезагрузите файл заново.
    При ошибке «empty content» – файл расшифровался без ошибок, но на выходе пусто. Это указывает на неправильную обработку RTF. Возможно, формат файла – чистый текст без RTF, а код ожидал RTF. Посмотрите содержимое файла: откройте .bsl через HEX-редактор или с помощью функции decodeAsHtml (есть в AESFileDecoder), чтобы увидеть, что внутри. Если внутри просто читаемый текст, значит, нужно адаптировать decodeBSL: убрать проверку на RTF (or str_starts_with(\$plain,'{\rtf’)), или изменить алгоритм. В debug логе, кстати, был указатель: // Convert encoding if needed – если mb_detect_encoding не нашел UTF-8, происходит mb_convert. Возможно, plain был UTF-8 сразу, и тогда double-conversion его испортит. Проверьте, не двоятся ли символы. В общем, для таких случаев лучше проконсультироваться с разработчиком модуля или форумом поддержки.

4. Ошибки парсинга (неправильные данные).
Симптомы: Отчет сформирован, но некоторые поля пустые или явно некорректные (например, даты 1970-01-01, нулевые емкости при том, что батарея разрядилась, или пропущена фаза).
Причины: Парсер не смог найти ожидаемые строки в новом формате файла. Формат протокола мог измениться: другие ключевые слова, другая языковая локализация (например, если прибор выдает англоязычный отчет, а наш парсер заточен под русский текст, или наоборот). В результате некоторые регулярные выражения в функциях parseTestDate/parseTestName/parseTestParameters/parsePhaseMarkers/parseDataPoints/… не сработали и нужные данные не были извлечены. Например, если устройство переключили на английский язык интерфейса, строки «Начало разряда» превратятся в «Discharge start» — наш парсер их не узнает, т.к. шаблоны заточены под кодировку или русские слова (в кодировке CP1251).
Решение: Необходимо адаптировать парсер. Для начала, определите, в чем расхождение. Откройте расшифрованный текст файла (в режиме DEBUG он может быть виден через вызов decodeAsHtml, или же временно модифицируйте код, чтобы он печатал исходный текст). Найдите в тексте те места, которые не попали в отчет. Затем скорректируйте соответствующие регулярные выражения:

  • Если язык другой, возможно, стоит добавить альтернативы в шаблонах (например, учесть слова «Charge» и «Discharge» наряду с русскими).
  • Если изменился формат чисел (например, запятая вместо точки как десятичный разделитель) – настройте preg_match на оба варианта.
  • Если поменялись символы управления (в коде видны странные конструкции типа  \. которые соответствуют определенным символам-разделителям в RTF) – возможно, в новых версиях они другие.
  • Возможно, проще: использовать не специфичные символы, а более общие. Например, время парсится как \d{2}:\d{2}:\d{2}, это надежно. А вот идентификатор канала V(?<ch>\d+)= предполагает букву V в начале – если в новом языке будет «U» (volt) или «Напр» на русском, шаблон не найдет. Нужно менять шаблон на что-то вроде /(?:V|Voltage|Напр)=.../ или даже лучше искать по структуре ...=(\d+\.\d+).
  • Тщательно протестируйте парсинг на новых примерах.

Данный модуль достаточно сложен для унификации всех языков, поэтому, возможно, целесообразно сконфигурировать прибор на определенный язык вывода (например, всегда английский) и один раз настроить парсер под него. Или же развить систему Translate для ключевых слов. Так или иначе, при появлении неправильных данных в отчете – это сигнал разобраться и поправить логику.

5. Проблемы с базой данных.
Симптомы: В процессе сохранения вылетает исключение mysqli (видно при DEBUG) о невозможности выполнить запрос, либо ImportPercent не обновляется на 100, транзакция откатывается.
Причины: Нарушения на уровне базы:

  • Отсутствие необходимых таблиц или столбцов (SQL-ошибка «Table not found» или «Unknown column»).
  • Несоответствие типов (например, попытка записать слишком длинное значение в поле).
  • Ошибка ограничения целостности (foreign key constraint fails), например, если запись File с данным ID была удалена из Files прежде, чем модуль попытался поставить внешние ключи.
  • Переполнение данных (хотя типы выбраны с запасом, например float 12,6 для емкости – до 999999 А·ч, что с большим запасом).
  • Блокировки или проблемы транзакции (маловероятно, но если параллельно идет еще обработка того же файла).
    Решение: Ознакомьтесь с сообщением об ошибке SQL (в debug output или в логах MySQL). Скорректируйте базу:
  • Если таблица отсутствует – создайте по образцу из структуры.
  • Если столбец отсутствует – возможно, у вас более старая версия базы, добавьте недостающий столбец. Например, модуль ожидает, что в StringData есть MeasuredCapacityPercent, а в старой БД этого поля нет – тогда либо добавьте поле, либо поправьте модуль не пытаться его писать.
  • Если foreign key падает – убедитесь, что добавляемый FileID существует в таблице Files. Это значит, что запись Files не была создана или была удалена. Модуль предполагает, что FileID валиден. Обычно Files и File заполняются при загрузке файла. Если у вас этого не произошло, проверьте процесс загрузки файла.
  • Если транзакция не коммитится – возможно, ошибка была, но модуль ее поймал и сделал rollback молча (например, внутри parseContent может быть try/catch, но там в основном ловится Exception с логированием). При DEBUG вы бы увидели. В любом случае, попробуйте снова с DEBUG или проанализируйте таблицы: если ни одна не заполнилась, значит, ранний откат (скорее всего, на этапе парсинга была необработанная ситуация).
  • Если ImportPercent не 100 – значит, модуль мог не дойти до конца (бросил исключение). Тогда по логам выясняем на каком шаге. ImportPercent выставляется только в самом конце, так что любая ошибка до этого оставит старое значение.

6. Временные зависания или медленная работа.
Симптомы: Обработка файла занимает слишком много времени, интерфейс «подвисает».
Причины: Очень большой объем данных, либо недостаточная производительность сервера/СУБД. Напрямую это не ошибка, но может вызвать таймауты.
Решение: См. раздел Производительность выше. Включите профилирование: с DEBUG вы увидите, сколько строк парсится (например, [DEBUG] Parsing completed. Data points: 12345). Если десятки тысяч – рассмотрите оптимизацию. Можно оптимизировать вставку в MySQL пакетом (сейчас в коде вставляется запись за записью; можно улучшить, собирая INSERT … VALUES (…),(…)). Однако это усложнит код. Альтернативно, разбейте файл: если устройство позволяет снимать данные пореже или частями – используйте это.
Вы также можете увеличить max_execution_time в php.ini или программно: set_time_limit(0) перед началом обработки, чтобы скрипт не прерывался. Но будьте осторожны – очень долгие запросы могут быть убиты и на стороне веб-сервера (например, limit body request time).

7. Исключения ConsolidatedReportGenerator.
Симптомы: При попытке сгенерировать сводный отчет что-то не отображается или в логах ошибка, связанная с ConsolidatedReportGenerator (например, null reference).
Причины: Этот компонент предполагает, что к моменту его вызова все файлы пользователя уже обработаны и данные присутствуют. Если какие-то ожидания не оправдались (например, нет данных BSL_Data для номинальной емкости, а код пытается вычислить SOH), могут быть предупреждения или исключения. Например, getNominalCapacity выбирает Value из BSL_Data с ParamName = ‘NominalCapacity’. Если такого нет – fetch_assoc вернет null и floatval даст 0.0, тогда SOH % будет = percent (в тесте), min(100, percent) – если percent не задан тоже 0. Это может привести к делению на 0 или просто некорректному SOH.
Решение: Убедитесь, что NominalCapacity всегда сохраняется (в противном случае, внесите вручную номинальную емкость для данного BatteryID или отредактируйте BSL_Data). Также проверьте, правильно ли определяются группы файлов: grouping baseName работает по имени файла. Если у вас имена файлов уникальные (UUID) без общего префикса, ConsolidatedReportGenerator может не сгруппировать .bsl и .bslc. В таком случае сводный отчет просто не появится, т.к. компонент решит, что нет групп с >1 файлом. Тогда стоит скорректировать логику группировки под вашу схему именования (например, если .bslc хранится не как отдельный файл record, а внутри Files_BSLC).
Если ConsolidatedReportGenerator вообще не нужен, можно не вызывать его (например, всегда вызывать модуль с конкретным FileID). Однако если он используется – отладьте на примере: в DEBUG он должен показать хотя бы [DEBUG] Consolidated Report: grouping files... если вы его вызвали.

8. Прочие исключения:
В коде могут возникнуть и стандартные PHP-ошибки – например, Undefined index или TypeError, если вдруг переданы неверные типы. Например, \$fileId не целый – тогда (int)\$fileId = 0 и сразу InvalidArgumentException «Invalid request parameters». Такие моменты решаются дисциплиной вызова: всегда передавайте правильные параметры.

Советы по устранению неполадок:

  • Включайте DEBUG режим на проблемных файлах, просматривайте HTML-вывод в режиме разработчика (в нем могут быть спрятаны <pre class="error-log">).
  • Пользуйтесь логами. Модуль логгирует ошибки через error_log – это обычно попадает в файл error.log сервера. Там могут быть детали стека вызовов, которые не показаны пользователю.
  • Если ошибка связана с конкретным файлом, попробуйте другой файл – это поможет понять, проблема общая или частная.
  • Обновите модуль до последней версии, если вы столкнулись с известным багом – возможно, он уже исправлен (например, дублирование данных .bsl/.bslc).
  • Обратитесь к глоссарию (ниже) для уточнения терминов, а также к документации производителя батарейного тестера – иногда понимание содержимого BSL-файла помогает понять, что ожидать в отчете и где искать ошибку.

При правильной настройке и внимательном отношении большинство вышеописанных проблем удается решить. В результате модуль будет стабильно работать, предоставляя ценные данные о состоянии батарей без ручных усилий.

Глоссарий

[^BSL]: BSL-файл – зашифрованный файл результатов тестирования батарей, формируемый измерительным оборудованием (Battery Analyzer). Обычно содержит данные одного теста (например, цикл разряда) в формате, включающем текстовые отчеты и измерения. Требует расшифровки и разбора для чтения человеком.

[^BSLC]: BSLC-файл – дополнительный файл-компаньон к BSL, содержащий связанные данные испытания. Как правило, используется для хранения результатов измерений внутреннего сопротивления или другой дополнительной информации, не включенной в основной BSL. Кодировка более простая (не AES, а смещенные байты).

[^resistance]: Внутреннее сопротивление – электрическое сопротивление аккумуляторной батареи, измеренное при подаче кратковременной нагрузки (например, метод короткого импульса тока). Выражается в миллиОмах (мΩ). Повышенное внутреннее сопротивление указывает на деградацию или проблемы с батареей.

[^SOH]: State of Health (SOH) – показатель состояния аккумулятора, обычно выраженный в процентах от состояния нового элемента. 100% соответствует новому аккумулятору. SOH рассчитывается на основе различных параметров, в данном модуле – по остаточной емкости (измеренной в тесте) относительно номинальной. Высокий SOH (ближний к 100%) означает отличное состояние, низкий (менее ~70%) – что батарея значительно изношена.

[^BWO]: BWO_ADMIN_IDS – специальная настройка (константа) в конфигурации, задающая список идентификаторов пользователей с административными правами. BWO может означать название системы (например, Battery Wizard Online или другое), где администраторы имеют расширенные полномочия. В контексте модуля через этот список определяется, кто имеет право обрабатывать файлы, загруженные другими пользователями.

[^BSLDecryptor]: BSLDecryptor – библиотека (набор классов и функций), отвечающая за расшифровку BSL/BSLC файлов. Содержит класс FileDecryptor, реализующий логику дешифрования в зависимости от типа файла, и функцию-обертку DecryptBSL(id) для удобства. Разработана М. Дейнекиным (указанным в исходном коде) и модифицирована под актуальные версии PHP. Без этой библиотеки модуль не сможет прочитать содержимое файлов.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх