# Описание работы c сетевыми интерфейсами На данный момент главным рабочим модулем приложения является модуль работы с сетевыми интерфейсами. Данный модуль позволяет отображать сетевые интерфейсы хоста в графическом виде и управлять IP адресами интерфейсов. В основе работы модуля лежит достаточно большая библиотека ReactFlow, которая позволяет строить различные графы по средством блоков и связей между ними. Далее для удобства блоки будут называться нодами (node), связи эджами (edge), а само поле ReactFlow холстом ### 1\. Подключение модуля в рабочее пространство Работа модуля начинается с файла /src/components/workSpace/workspace.tsx, здесь в рабочее пространство приложения подключаются сами модули. ``` {workModule === workSpaceNames[3] &&
} ``` В данном блоке этого файла подключается модуль сетевых интерфейсов в рабочее пространство. Из localstorage берётся название текущего модуля, который должен быть подключён, в этом случаи это ‘networkInterfaces‘ и по названию определяется необходимый модуль. Здесь <Header/> - это верхняя панель для управления холстом <NetWorkInterfaces/> - Сам компонент работы с сетевыми интерфейсами, в нём пропсы key - ключ компонента, будет равен текущему ip хоста, startConnection - флаг, при передачи которого начинается работа компонента, ws - передача ip текущего хоста для создания WebSocket подключения ### 2\. Компонент NetworkInterfaces Рассмотрение компонента логично начать с обзора его переменных состояния, которых в этом компоненте присутствует немало. #### 2.1. Переменные состояния компонента NetworkInterfaces 1. initializationAttempt - Тип: React.useRef<number> - Описание: Счетчик попыток инициализации данных, хранящийся в useRef. Используется для отслеживания статуса начальной загрузки нод и эджей. Начальное значение — 0. После успешной инициализации устанавливается в 1. Позволяет избежать повторных попыток инициализации или перезагрузки страницы при сбоях. 2. requestError - Тип: { status: boolean, message: string } - Описание: Состояние для отслеживания ошибок при установлении WebSocket-соединения или загрузке данных. Содержит флаг status (true, если ошибка произошла) и поле message с текстом ошибки (например, "Соединение с сервером разорвано" или "Превышено время ожидания"). Используется для отображения ошибок через модальное окно. 3. { openModal, closeLoader } - Тип: Методы из useModalContext - Описание: Функции, полученные из контекста ModalWindowContext, для управления модальными окнами. openModal открывает модальное окно с указанным типом и параметрами (например, для отображения ошибок или уведомлений о загрузке). closeLoader закрывает экран загрузки после завершения инициализации данных. 4. loader - Тип: boolean - Описание: Флаг, управляющий отображением экрана загрузки. Изначально установлен в true, что указывает на процесс загрузки данных. После успешной инициализации нод и эджей устанавливается в false, и экран загрузки скрывается с помощью closeLoader. 5. socket - Тип: WebSocket | null - Описание: Состояние для хранения объекта WebSocket, используемого для связи с сервером по адресу ws://192.168.1.147:8001/api/v1. Изначально null. После успешного подключения сохраняет экземпляр WebSocket, позволяя отправлять и получать данные о сетевых интерфейсах. 6. data - Тип: ResponseData\[\] - Описание: Массив данных, полученных через WebSocket. Содержит два элемента: данные об активных (activation) и неактивных (deactivation) сетевых интерфейсах. Используется как источник для преобразования в ноды и эджи для отображения на холсте ReactFlow. 7. wifiData - Тип: ResponseNetwork | undefined - Описание: Состояние для хранения информации о Wi-Fi интерфейсе, извлеченной из активных данных (activation). Обновляется, если в полученных данных присутствует интерфейс с типом WIFI. Используется для специфической обработки и отображения Wi-Fi нод на холсте. 8. hasInited - Тип: boolean - Описание: Флаг, указывающий, были ли данные (ноды и эджи) успешно инициализированы. Изначально false. Устанавливается в true после первичной обработки данных и вызова handleInit из useInitCanvas, чтобы предотвратить повторную инициализацию. 9. { initedNodes, initedEdges, handleInit } - Тип: Значения и метод из useInitCanvas - Описание: Данные и функция из пользовательского хука useInitCanvas. initedNodes и initedEdges содержат инициализированные ноды и эджи, подготовленные для отображения на холсте. handleInit выполняет начальную обработку edgeData и interfaces для создания этих структур. 10. interfaces - Тип: Interfaces\[\] - Описание: Состояние для хранения преобразованных данных о сетевых интерфейсах, полученных из data с помощью функции initNetworkIntData. Содержит структурированные объекты, описывающие интерфейсы, в формате, удобном для построения нод на холсте ReactFlow. 11. edgeData - Тип: IEdge\[\] - Описание: Состояние для хранения преобразованных данных о связях (эджи) между сетевыми интерфейсами, полученных из data с помощью initNetworkIntData. Используется как промежуточный формат перед финальной инициализацией эджей для отображения. 12. nodes - Тип: Массив нод для ReactFlow - Описание: Состояние, управляемое хуком useNodesState, для хранения и отображения нод (блоков) на холсте ReactFlow. Инициализируется пустым массивом и заполняется данными из initedNodes после обработки. Обновляется при изменении позиций, групп или Wi-Fi данных. 13. edges - Тип: Массив эджей для ReactFlow - Описание: Состояние, управляемое хуком useEdgesState, для хранения и отображения связей (эджей) между нодами на холсте ReactFlow. Изначально пустой массив, заполняется из initedEdges после инициализации и обновляется при добавлении новых связей. 14. isPanDisabled - Тип: boolean - Описание: Флаг, полученный из хука usePannableStore, определяющий, отключена ли возможность перемещения (прокрутки) холста ReactFlow. Если true, пользователь не может перемещать холст, что полезно для фиксации вида при определенных действиях. 15. changeArray - Тип: any\[\] - Описание: Массив для временного хранения изменений позиций нод, полученных через processNodeChanges. Накапливает данные о перемещениях, которые затем отправляются на сервер через autosavePosition с интервалом в 1 секунду для сохранения позиций. 16. groups - Тип: Данные из useGroupStore - Описание: Состояние, полученное из хука useGroupStore, содержащее информацию о группах сетевых интерфейсов (например, активные и неактивные). Используется для сортировки и сворачивания/разворачивания групп нод на холсте с помощью groupSort и collapseGroup. 17. { isNullPos, setNullPos } - Тип: Значения и метод из usePosStore - Описание: Состояние и функция из хука usePosStore. isNullPos — флаг, указывающий, нужно ли сбросить позиции нод. setNullPos — метод для управления этим флагом. При активации сбрасывает позиции нод через resetPosition, отправляя запрос по WebSocket. #### 2.2. Методы Функции и эффекты 1. Первый useEffect — Подключение к WebSocket ```jsx useEffect(() => { if (startConnection) { openModal(ModalMap['2'], 'Идет загрузка данных'); setNodes([]); setEdges([]); setHasInited(false); initializationAttempt.current = 0; const newSocket = new WebSocket(`ws://192.168.1.147:8001/api/v1`); let connectionTimeout; setSocket(newSocket); connectionTimeout = setTimeout(() => { if (newSocket.readyState !== WebSocket.OPEN) { newSocket.close(); } }, 5000); newSocket.onopen = () => { console.log('WebSocket connection established'); }; newSocket.onmessage = (event) => { const newData = JSON.parse(event.data); setData(() => [newData.activation, newData.deactivation]); }; newSocket.onerror = (error) => { console.error('WebSocket error:', error); }; newSocket.onclose = () => { console.log('WebSocket connection closed'); setRequestError({ status: true, message: 'Соединение с сервером разорвано' }); }; return () => { newSocket.close(); closeLoader(); }; } }, [startConnection, ws]); ``` - Условие: Срабатывает при изменении startConnection или ws. - Логика: Открывает модальное окно загрузки, сбрасывает ноды, эджи и флаги. Создает WebSocket, устанавливает тайм-аут (5 сек) для проверки соединения. Обрабатывает открытие, получение данных, ошибки и закрытие. - Очистка: Закрывает WebSocket и загрузчик. - Цель: Установить связь с сервером и получить данные. 2. Второй useEffect — Обработка данных из WebSocket ```jsx useEffect(() => { if (data.length > 0) { const { interfaces: newInterfaces, edgeData: newEdgeData } = initNetworkIntData(data); const activationData = data[0].interfaces; const wifi = activationData.find((el: any) => el.type === 'WIFI'); setInterfaces(newInterfaces); setEdgeData(newEdgeData); if (wifi) { setWifi(wifi); } } }, [data]); ``` - Условие: Срабатывает при изменении data. - Логика: Преобразует data в interfaces и edgeData через initNetworkIntData. Ищет Wi-Fi интерфейс в активных данных, обновляет состояния. - Цель: Подготовить данные для холст. 3. Третий useEffect — Инициализация нод и эджей ```jsx useEffect(() => { if (interfaces.length > 0 && !hasInited) { handleInit(edgeData, interfaces); setHasInited(true); } }, [interfaces, edgeData, hasInited]); ``` - Условие: Срабатывает при изменении interfaces, edgeData, hasInited. - Логика: Если данные есть и инициализация не выполнена, вызывает handleInit для подготовки нод и эджей, затем устанавливает hasInited в true. - Цель: Инициализировать холст. 4. Четвертый useEffect — Мониторинг инициализации ```jsx useEffect(() => { if (initializationAttempt.current === 0 && !requestError.status) { const checkInterval = setInterval(() => { setTimeout(() => { if (!initedNodes.some(node => node.id === 'g0_nw0_rx0_ip0')) { window.location.reload(); } }, 500); if (initedNodes.length > 0 && initedEdges.length > 0) { setNodes(initedNodes); setEdges(initedEdges); console.log("Ноды и эджи успешно инициализированы"); initializationAttempt.current = 1; clearInterval(checkInterval); clearTimeout(timeoutId); } else { console.log("Попытка инициализации нод и эджей..."); } }, 1000); const timeoutId = setTimeout(() => { console.error("Ошибка: слишком долгая загрузка данных"); clearInterval(checkInterval); setRequestError({ status: true, message: 'Превышено время ожидания' }); }, 30000); return () => { clearInterval(checkInterval); clearTimeout(timeoutId); }; } }, [initedNodes, initedEdges, requestError]); ``` - Условие: Срабатывает при изменении initedNodes, initedEdges, requestError. - Логика: Проверяет каждую секунду наличие инициализированных данных. Через 500 мс проверяет ключевую ноду; если нет — перезагрузка. При успехе обновляет nodes, edges, логирует, останавливает проверки. Тайм-аут (30 сек) фиксирует ошибку. - Очистка: Удаляет интервал и тайм-аут. - Цель: Гарантировать успешную инициализацию. 5. Пятый useEffect — Обновление счетчика попыток ```jsx useEffect(() => { if (nodes.length === 0) { initializationAttempt.current = 0; } else { initializationAttempt.current = 1; } }, [nodes]); ``` - Условие: Срабатывает при изменении nodes. - Логика: Сбрасывает initializationAttempt в 0, если нод нет, иначе устанавливает 1. - Цель: Отслеживать состояние инициализации. 6. Шестой useEffect — Управление загрузчиком ```jsx useEffect(() => { if (nodes.length > 0 && loader == true) { setLoader(false); closeLoader(); } }, [nodes, loader]); ``` - Условие: Срабатывает при изменении nodes, loader. - Логика: Если ноды есть и загрузчик активен, скрывает его. - Цель: Убрать экран загрузки после рендера. 7. Функция onEdgesChange ```jsx const onEdgesChange = useCallback( (changes: any) => setEdges((eds) => applyEdgeChanges(changes, eds)), [setEdges] ); ``` - Тип: useCallback - Вход: changes — массив изменений эджей. - Логика: Применяет изменения к эджам через applyEdgeChanges, обновляет edges. - Цель: Обработать изменения связей. 8. Функция onConnect ```jsx const onConnect = useCallback( (connection: any) => setEdges((eds) => addEdge(connection, eds)), [setEdges] ); ``` - Тип: useCallback - Вход: connection — объект новой связи. - Логика: Добавляет связь через addEdge, обновляет edges. - Цель: Создавать новые связи на холсте. 9. Функция handleNodesChange ```jsx const handleNodesChange = (changes: any) => { onNodesChange(changes); const newData = processNodeChanges(changes, data); if (newData) { setChangeArray((prevArray) => [...prevArray, newData]); } }; ``` - Вход: changes — массив изменений нод. - Логика: Обновляет ноды через onNodesChange, извлекает изменения позиций через processNodeChanges, добавляет в changeArray. - Цель: Отслеживать перемещения нод. 10. Седьмой useEffect — Автосохранение позиций ```jsx useEffect(() => { const interval = setInterval(() => { if (socket && socket.readyState === WebSocket.OPEN) { autosavePosition(changeArray, socket); } setChangeArray([]); }, 1000); return () => { clearInterval(interval); }; }, [changeArray, socket]); ``` - Условие: Срабатывает при изменении changeArray, socket. - Логика: Каждую секунду отправляет изменения позиций через autosavePosition, очищает changeArray. - Очистка: Удаляет интервал. - Цель: Сохранять позиции на сервере. 11. Восьмой useEffect — Обработка групп ```jsx useEffect(() => { const sortedGroups = groupSort(groups, nodes); setNodes(collapseGroup(sortedGroups, nodes)); }, [groups]); ``` - Условие: Срабатывает при изменении groups. - Логика: Сортирует ноды по группам через groupSort, сворачивает/разворачивает через collapseGroup, обновляет nodes. - Цель: Организовать ноды по группам. 12. Девятый useEffect — Обновление Wi-Fi ```jsx useEffect(() => { if (wifiData) { setNodes(updateWifiData(wifiData, nodes)); } }, [wifiData]); ``` - Условие: Срабатывает при изменении wifiData. - Логика: Обновляет ноды с учетом Wi-Fi через updateWifiData. - Цель: Отобразить Wi-Fi данные. 13. Десятый useEffect — Обработка ошибок ```jsx useEffect(() => { if (requestError.status) { setTimeout(() => { openModal(ModalMap['3'], { message: requestError.message }); }, 1000); } }, [requestError]); ``` - Условие: Срабатывает при изменении requestError. - Логика: При ошибке через 1 сек открывает модальное окно с сообщением. - Цель: Уведомить об ошибках. 14. Одиннадцатый useEffect — Сброс позиций ```jsx useEffect(() => { if (isNullPos) { if (socket && socket.readyState === WebSocket.OPEN) { resetPosition(socket, setNullPos, nodes, setNodes); } } }, [isNullPos]); ``` - Условие: Срабатывает при изменении isNullPos. - Логика: При истинном isNullPos сбрасывает позиции через resetPosition, обновляет ноды. - Цель: Вернуть исходные позиции. #### 2.3. Рендеринг ```jsx return ( <> ); ``` - Компонент: ReactFlow рендерит холст. - Параметры: Ноды, эджи, обработчики, фон, зум (0–4), сетка (20x20), перетаскивание по isPanDisabled, кастомные ноды. - Дочерние: Background (сетка), Controls (кнопки для управления зумом).