Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <pthread.h> // Для работы с потоками
- #include <time.h> // Для работы с таймерами
- #include <errno.h>
- #include <signal.h> // Добавлено для signal.h
- #include "common.h"
- #define PORT 8080 // Общий порт для УВМ и СВ-М
- // Глобальные переменные для счетчика BCB и мьютекса
- uint32_t bcb_counter = 0;
- pthread_mutex_t bcb_mutex;
- void timer_handler(union sigval sv) {
- pthread_mutex_lock(&bcb_mutex);
- bcb_counter++;
- pthread_mutex_unlock(&bcb_mutex);
- }
- int main() {
- int sockfd, newsockfd;
- struct sockaddr_in serv_addr, cli_addr;
- socklen_t clilen;
- Message received_message;
- uint16_t message_counter = 0;
- // Инициализация счетчиков (имитация)
- uint16_t linkup_changes = 0; // Счетчик изменений состояния LinkUp
- uint32_t linkup_low_time = 0; //Счётчик времени LinkUP в 0.
- uint16_t signdet_changes = 0; // Счетчик изменений состояния SignDet
- // Состояние СВ-М
- SVMState svm_state = STATE_NOT_INITIALIZED;
- // Создаем сокет
- if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- perror("socket creation failed");
- exit(EXIT_FAILURE);
- }
- // Заполняем структуру адреса сервера (СВ-М)
- memset(&serv_addr, 0, sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = INADDR_ANY; // Слушаем на всех интерфейсах
- serv_addr.sin_port = htons(PORT);
- // Привязываем сокет к адресу
- if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
- perror("bind failed");
- exit(EXIT_FAILURE);
- }
- // Начинаем слушать входящие соединения
- if (listen(sockfd, 5) < 0) { // 5 - максимальная длина очереди ожидающих соединений
- perror("listen failed");
- exit(EXIT_FAILURE);
- }
- printf("SVM listening on port %d\n", PORT);
- // Инициализация мьютекса и запуск таймера BCB
- pthread_mutex_init(&bcb_mutex, NULL);
- struct sigevent sev;
- struct itimerspec its;
- timer_t timerid;
- sev.sigev_notify = SIGEV_THREAD;
- sev.sigev_notify_function = timer_handler;
- sev.sigev_notify_attributes = NULL;
- sev.sigev_value.sival_ptr = &timerid;
- timer_create(CLOCK_MONOTONIC, &sev, &timerid);
- its.it_value.tv_sec = 1;
- its.it_value.tv_nsec = 0;
- its.it_interval = its.it_value;
- timer_settime(timerid, 0, &its, NULL);
- clilen = sizeof(cli_addr);
- // Принимаем входящее соединение (блокирующий вызов)
- if ((newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen)) < 0) {
- perror("accept failed");
- exit(EXIT_FAILURE);
- }
- printf("SVM accepted connection from UVM\n");
- // Главный цикл обработки сообщений
- while (1)
- {
- // Принимаем сообщение
- memset(&received_message, 0, sizeof(Message)); // Важно обнулять перед приемом!
- ssize_t bytes_received = recv(newsockfd, &received_message, sizeof(Message), 0);
- if (bytes_received < 0) {
- perror("recv failed");
- exit(EXIT_FAILURE);
- }
- else if (bytes_received == 0)
- {
- printf("Connection closed by UVM.\n");
- close(newsockfd);
- close(sockfd);
- exit(EXIT_SUCCESS);
- }
- else if (bytes_received < sizeof(MessageHeader)) //Проверка приёма всего заголовка
- {
- printf("Received incomplete message header.\n");
- close(newsockfd);
- close(sockfd);
- exit(EXIT_FAILURE);
- }
- message_to_host_byte_order(&received_message); //После приёма
- // --- ОБРАБОТКА СООБЩЕНИЙ ---
- if (svm_state == STATE_NOT_INITIALIZED) {
- // Если СВ-М не инициализирован, обрабатываем только "Инициализацию канала"
- if (received_message.header.message_type == MESSAGE_TYPE_INIT_CHANNEL) {
- printf("Received Init Channel message\n");
- // Обработка полученного сообщения (пример)
- uint16_t received_message_number = get_full_message_number(&received_message.header);
- printf("Received message number: %u\n", received_message_number);
- InitChannelBody *body = (InitChannelBody *)received_message.body;
- printf("Received Init Channel message from UVM: LAUVM=0x%02X, LAK=0x%02X\n", body->LAUVM, body->LAK);
- // --- ОБРАБОТКА СООБЩЕНИЯ "ИНИЦИАЛИЗАЦИЯ КАНАЛА" (3.3.3) ---
- // 1. Отключение излучения лазера (имитация)
- printf("SVM: Emulating laser shutdown in unused channel...\n");
- // 2. Запуск счетчиков (имитация)
- // bcb_counter++; // Увеличение счетчика времени работы - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР!
- linkup_changes++; // Имитируем изменение состояния LinkUp
- // 3. Формируем ответ
- uint8_t slp = 0x03; // Оба канала LinkUp в состоянии 1 (включены)
- uint8_t vdr = 0x01; // Версия прошивки (пример)
- uint8_t vor1 = 0x02; // Версия прошивки (пример)
- uint8_t vor2 = 0x03; // Версия прошивки (пример)
- // Создаем сообщение "Подтверждение инициализации канала"
- pthread_mutex_lock(&bcb_mutex);
- Message confirm_message = create_confirm_init_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1, slp, vdr, vor1, vor2, bcb_counter, message_counter++);
- pthread_mutex_unlock(&bcb_mutex);
- message_to_network_byte_order(&confirm_message); //Перед отправкой
- // Отправляем сообщение "Подтверждение инициализации канала"
- if (send(newsockfd, &confirm_message, sizeof(MessageHeader) + ntohs(confirm_message.header.body_length), 0) < 0)
- {
- perror("Send confirmation init error");
- exit(EXIT_FAILURE);
- }
- printf("Sent Confirm Init message\n");
- //-----------------
- svm_state = STATE_INITIALIZED; // Переходим в состояние "инициализирован"
- }
- else
- {
- printf("SVM: Ignoring message (not initialized). Type: %u\n", received_message.header.message_type);
- }
- }
- else if(svm_state == STATE_INITIALIZED)
- {
- // Добавлена обработка "Провести контроль"
- if (received_message.header.message_type == MESSAGE_TYPE_PROVESTI_KONTROL) {
- printf("Received Provesti Kontrol message\n");
- // Имитация самоконтроля
- printf("SVM: Emulating self-test...\n");
- // bcb_counter++; // Увеличиваем счетчик (имитация времени) - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
- // Отправляем "Подтверждение контроля"
- ProvestiKontrolBody *received_body = (ProvestiKontrolBody *)received_message.body; // Получаем тело принятого сообщения
- pthread_mutex_lock(&bcb_mutex);
- Message confirm_message = create_podtverzhdenie_kontrolya_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1, received_body->TK, bcb_counter, message_counter++);
- pthread_mutex_unlock(&bcb_mutex);
- message_to_network_byte_order(&confirm_message);
- if (send(newsockfd, &confirm_message, sizeof(MessageHeader) + ntohs(confirm_message.header.body_length), 0) < 0) {
- perror("send podtverzhdenie_kontrolya failed");
- exit(EXIT_FAILURE);
- }
- printf("Sent Podtverzhdenie Kontrolya message\n");
- }
- // Добавлена обработка "Выдать результаты контроля"
- else if (received_message.header.message_type == MESSAGE_TYPE_VYDAT_RESULTATY_KONTROLYA) {
- printf("Received Vydat Rezultaty Kontrolya message\n");
- // Имитация получения результатов контроля (пока константы)
- uint8_t rsk = 0x01; // Типа "успешно"
- uint16_t bck = 100; // Типа 100 мс
- // Отправляем "Результаты контроля"
- pthread_mutex_lock(&bcb_mutex);
- Message results_message = create_rezultaty_kontrolya_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1, rsk, bck, bcb_counter, message_counter++);
- pthread_mutex_unlock(&bcb_mutex);
- message_to_network_byte_order(&results_message);
- if (send(newsockfd, &results_message, sizeof(MessageHeader) + ntohs(results_message.header.body_length), 0) < 0) {
- perror("send rezultaty_kontrolya failed");
- exit(EXIT_FAILURE);
- }
- printf("Sent Rezultaty Kontrolya message\n");
- }
- // Добавлена обработка "Выдать состояние линии"
- else if (received_message.header.message_type == MESSAGE_TYPE_VYDAT_SOSTOYANIE_LINII) {
- printf("Received Vydat Sostoyanie Linii message\n");
- // Имитация получения состояния линий (пока константы)
- uint16_t kla = 0x0001; // Типа 1 изменение LinkUp
- uint32_t sla = 0x00000000; // Типа LinkUp всегда в высоком состоянии
- uint16_t ksa = 0x0000; // Типа SignDet всегда 1 (сигнал есть)
- // Отправляем "Состояние линии"
- pthread_mutex_lock(&bcb_mutex);
- Message sostoyanie_message = create_sostoyanie_linii_message(LOGICAL_ADDRESS_SVM_PB_BZ_CHANNEL_1,
- kla, sla, ksa, bcb_counter, message_counter++);
- pthread_mutex_unlock(&bcb_mutex);
- message_to_network_byte_order(&sostoyanie_message);
- if (send(newsockfd, &sostoyanie_message, sizeof(MessageHeader) + ntohs(sostoyanie_message.header.body_length), 0) < 0) {
- perror("send sostoyanie_linii failed");
- exit(EXIT_FAILURE);
- }
- printf("Sent Sostoyanie Linii message\n");
- }
- else if (received_message.header.message_type == MESSAGE_TYPE_PRINYAT_PARAMETRY_CO)
- {
- printf("Received Prinyat Parametry CO message\n");
- // Тут нужно сохранить полученные параметры в структуре данных СВ-М (пока не реализовано)
- PrinyatParametryCOBody *body = (PrinyatParametryCOBody *)received_message.body;
- printf("Received Prinyat Parametry CO from UVM: PP=0x%02X, BRL=0x%02X, Qo=0x%02X, Q=0x%04X, ARU=0x%02X, SIGMAYBM=0x%04X\n",
- body->PP, body->BRL, body->Qo, ntohs(body->Q), body->ARU, ntohs(body->SIGMAYBM)); //Добавили ntohs
- // bcb_counter++; // Временно - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
- message_counter++;
- }
- else if (received_message.header.message_type == MESSAGE_TYPE_PRINYAT_TIME_REF_RANGE) {
- printf("Received Prinyat Time Ref Range message\n");
- // Временный вывод для отладки (пока не сохраняем данные)
- PrinyatTimeRefRangeBody *body = (PrinyatTimeRefRangeBody *)received_message.body;
- printf("Received Time Ref Range from UVM: First element: real=%d, imag=%d\n",
- body->time_ref_range[0].real, body->time_ref_range[0].imag);
- // bcb_counter++; // Временно - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
- message_counter++;
- }
- // Добавлено: обработка "Принять Reper"
- else if (received_message.header.message_type == MESSAGE_TYPE_PRINYAT_REPER) {
- printf("Received Prinyat Reper message\n");
- PrinyatReperBody *body = (PrinyatReperBody *)received_message.body;
- printf("Received Reper Data from UVM: reperR1=0x%04X, reperA1=0x%04X\n",
- ntohs(body->reperR1), ntohs(body->reperA1)); // не забываем
- // bcb_counter++; //временно - ТЕПЕРЬ ДЕЛАЕТ ТАЙМЕР
- message_counter++;
- }
- else{
- printf("SVM: Ignoring message after initialization. Type: %u\n", received_message.header.message_type);
- }
- }
- }
- // Закрываем соединение и сокет. Тут не должно быть, но пока оставим
- close(newsockfd);
- close(sockfd);
- pthread_mutex_destroy(&bcb_mutex); // Уничтожение мьютекса
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement