#include #include #include #include #include #include #include #include #include #include #include #include #include #define CLOCKID CLOCK_MONOTONIC #define HEART_BEAT_TIME 60 //Интервал отправки Heart Beat, с #define MODBUS_ANSWER_TIME 25 //Время паузы перед ответом на запрос Modbus, мс #define TCP_KEEP_ALIVE_TIME 10 //Интревал отправки Keep Alive пакетов, с #define IP_ADDRESS_SERVER_DISPSKY "5.17.125.18" #define PORT_SERVER_DISPSKY 5010 //Порт сервера DispSky #define BUFFER_MODBUS_SIZE 300 #define TCP_HDRLEN 20 // TCP header length, excludes options data timer_t timer1_id, timer2_id, timer3_id; struct sigevent sev_1, sev_2, sev_3; struct itimerspec timer_1, timer_2, timer_3, timer_4, timer_stop; int ret1, ret2, ret3; int len; uint8_t Data_tcp[] = {0x44, 0x33, 0x67}; uint8_t keep_alive_on, keep_alive_on1; //Флаг запуска таймера keep alive char heart_beat[] = "112233445568"; //Необходимо ввести этот ID при подключении к DispSky uint8_t bufferModbus[BUFFER_MODBUS_SIZE]; uint8_t bufRaw[BUFFER_MODBUS_SIZE]; uint8_t packet[80]; uint8_t ModbusCS [200]; uint8_t ModbusIS [200]; unsigned int ModbusHR [130]; unsigned int ModbusIR [130]; int sock, raw_sock; struct sockaddr_in addr, addr_raw, addr_out, eert; unsigned long ack_to_raw, seq_to_raw, delta_seq_to_raw, ack_from_server; struct tcphdr tcphdr; void modbusTCP_handler(); void sigpipe_handler(); void set_timers(); void TCP_keep_alive_handler(); void start_modbus(); void timer1_handler() //Функция для отправки Heart Beat { send(sock, &heart_beat, (sizeof(heart_beat) - 1), 0) ; } void connect_to_server() //Функция подключения с серверу DispSky { addr.sin_family = AF_INET; addr.sin_port = htons(PORT_SERVER_DISPSKY); addr.sin_addr.s_addr = inet_addr(IP_ADDRESS_SERVER_DISPSKY); sock = socket(AF_INET, SOCK_STREAM, 0); fcntl(sock, F_SETFL, O_NONBLOCK); connect(sock, (struct sockaddr *)&addr, sizeof(addr)); delay(50); timer_settime(timer1_id, 0, &timer_1, NULL); //Запуск таймера Heart Beat unsigned int len_addr_out = sizeof(addr_out); getsockname(sock, (struct sockaddr *)&addr_out, &len_addr_out); eert.sin_family = AF_INET; eert.sin_port = addr_out.sin_port; } int main(int argc, char *argv[]) { signal(SIGPIPE, sigpipe_handler); //Установка обработчика сигнала SIGPIPE wiringPiSetup () ; pinMode (4, OUTPUT) ; pinMode (5, OUTPUT) ; digitalWrite(5, LOW); set_timers(); //Установка таймеров connect_to_server(); //Подключение к серверу DispSky raw_sock = socket (AF_INET, SOCK_RAW, IPPROTO_TCP); // Создание raw-сокета fcntl(raw_sock, F_SETFL, O_NONBLOCK); addr_raw.sin_family = AF_INET; start_modbus(); //Установка начальных значений регистров modbus while (1) { unsigned int len_addr = sizeof(addr); recvfrom(raw_sock, bufRaw, BUFFER_MODBUS_SIZE, 0, (struct sockaddr *)&addr, &len_addr); if (bufRaw[12] == (addr.sin_addr.s_addr & 0xFF) && bufRaw[13] == ((addr.sin_addr.s_addr>>8) & 0xFF) && bufRaw[14] == ((addr.sin_addr.s_addr>>16) & 0xFF) && bufRaw[15] == ((addr.sin_addr.s_addr>>24) & 0xFF)) { if (((bufRaw[22]<<0)& 0xFF) + ((bufRaw[23]<<8) & 0xFFFF) == addr_out.sin_port) { seq_to_raw = ((bufRaw[31] << 0) & 0xFF) + ((bufRaw[30] << 8) & 0xFFFF) + ((bufRaw[29] << 16) & 0xFFFFFF) + ((bufRaw[28] << 24) & 0xFFFFFFFF); } } len = recv(sock,(uint8_t *) &bufferModbus, BUFFER_MODBUS_SIZE, 0); if (len > 0) { timer_settime(timer2_id, 0, &timer_2, NULL); //Запуск таймера для запуска функции modbusTCP_handler() if (keep_alive_on == 1) //Установка флага возможности запуска таймера Keep Alive { timer_settime(timer3_id, 0, &timer_stop, NULL); keep_alive_on = 0; } } else { if (keep_alive_on == 0) { timer_settime(timer3_id, 0, &timer_3, NULL); //Запуск таймера Keep Alive keep_alive_on = 1; //Установка флага блокировки запуска таймера Keep Alive } } if (ModbusCS[9] == 0) digitalWrite(5, LOW); //Управление выходом GPIO при помощи регистра modbus if (ModbusCS[9] == 1) digitalWrite(5, HIGH); } } void modbusTCP_handler() //Функция обработки протокола modbus TCP/IP { unsigned int numberOfRegisters; unsigned int firstRegisterAddress; //unsigned int transactionNumber; unsigned int counterRegisters; unsigned int numberOfFunction; unsigned int lenghtData; unsigned int countOfByte; unsigned int valueData; numberOfFunction = bufferModbus[7]; digitalWrite(4, !digitalRead(4)); switch (numberOfFunction) { case 0x01: //transactionNumber = (bufferModbus[0]<<8)|bufferModbus[1]; numberOfRegisters = (bufferModbus[10]<<8)|bufferModbus[11]; firstRegisterAddress = (bufferModbus[8]<<8)|bufferModbus[9]; countOfByte = (numberOfRegisters - 1)/8 + 1; lenghtData = 4 + (numberOfRegisters - 1)/8; bufferModbus[4] = (lenghtData>>8) & 0xFF; bufferModbus[5] = lenghtData & 0xFF; bufferModbus[8] = countOfByte; counterRegisters = 9; bufferModbus[9] = 0; for (int i = 0; i < numberOfRegisters; i++) { bufferModbus[counterRegisters] |= ((ModbusCS[i+firstRegisterAddress]&1)<<(i%8)); if((i+1)%8 == 0 && i != numberOfRegisters - 1) { counterRegisters++; bufferModbus[counterRegisters] = 0; } } send(sock, &bufferModbus, counterRegisters + 1, 0); break; case 0x02: //transactionNumber = (bufferModbus[0]<<8)|bufferModbus[1]; numberOfRegisters = (bufferModbus[10]<<8)|bufferModbus[11]; firstRegisterAddress = (bufferModbus[8]<<8)|bufferModbus[9]; countOfByte = (numberOfRegisters - 1)/8 + 1; lenghtData = 4 + (numberOfRegisters - 1)/8; bufferModbus[4] = (lenghtData>>8) & 0xFF; bufferModbus[5] = lenghtData & 0xFF; bufferModbus[8] = countOfByte; counterRegisters = 9; bufferModbus[9] = 0; for (int i = 0; i < numberOfRegisters; i++) { bufferModbus[counterRegisters] |= ((ModbusIS[i+firstRegisterAddress]&1)<<(i%8)); if((i+1)%8 == 0 && i != numberOfRegisters - 1) { counterRegisters++; bufferModbus[counterRegisters] = 0; } } send(sock, &bufferModbus, counterRegisters + 1, 0); break; case 0x03: //transactionNumber = (bufferModbus[0]<<8)|bufferModbus[1]; numberOfRegisters = (bufferModbus[10]<<8)|bufferModbus[11]; firstRegisterAddress = (bufferModbus[8]<<8)|bufferModbus[9]; lenghtData = numberOfRegisters*2 + 3; bufferModbus[4] = (lenghtData>>8) & 0xFF; bufferModbus[5] = lenghtData & 0xFF; counterRegisters = 9; for (int i = firstRegisterAddress; i <= firstRegisterAddress + numberOfRegisters - 1; i++) { bufferModbus[counterRegisters] = (ModbusHR[i]>>8) & 0xFF; bufferModbus[counterRegisters + 1] = ModbusHR[i] & 0xFF; counterRegisters += 2; } bufferModbus[8] = numberOfRegisters*2; send(sock, &bufferModbus, (numberOfRegisters*2 + 9), 0); break; case 0x04: //transactionNumber = (bufferModbus[0]<<8)|bufferModbus[1]; numberOfRegisters = (bufferModbus[10]<<8)|bufferModbus[11]; firstRegisterAddress = (bufferModbus[8]<<8)|bufferModbus[9]; lenghtData = numberOfRegisters*2 + 3; bufferModbus[4] = (lenghtData>>8) & 0xFF; bufferModbus[5] = lenghtData & 0xFF; counterRegisters = 9; for (int i = firstRegisterAddress; i <= firstRegisterAddress + numberOfRegisters - 1; i++) { bufferModbus[counterRegisters] = (ModbusIR[i]>>8) & 0xFF; bufferModbus[counterRegisters + 1] = ModbusIR[i] & 0xFF; counterRegisters += 2; } bufferModbus[8] = numberOfRegisters*2; send(sock, &bufferModbus, (numberOfRegisters*2 + 9), 0); break; case 0x05: firstRegisterAddress = (bufferModbus[8]<<8)|bufferModbus[9]; valueData = bufferModbus[10]; ModbusCS[firstRegisterAddress] = valueData & 1; send(sock, &bufferModbus, 12, 0); break; case 0x10: firstRegisterAddress = (bufferModbus[8]<<8)|bufferModbus[9]; valueData = (bufferModbus[13]<<8)|bufferModbus[14]; bufferModbus[5] = 6; ModbusHR[firstRegisterAddress] = valueData; send(sock, &bufferModbus, 12, 0); break; } } void sigpipe_handler() { puts("Сигнал SIGPIPE"); } void set_timers() //Установка таймеров { sev_1.sigev_notify = SIGEV_THREAD; sev_1.sigev_notify_function = timer1_handler; ret1 = timer_create(CLOCKID, &sev_1, &timer1_id); timer_1.it_interval.tv_sec = HEART_BEAT_TIME; timer_1.it_interval.tv_nsec = 0; timer_1.it_value.tv_sec = 0; timer_1.it_value.tv_nsec = 1; sev_2.sigev_notify = SIGEV_THREAD; sev_2.sigev_notify_function = modbusTCP_handler; ret2 = timer_create(CLOCKID, &sev_2, &timer2_id); //timer_2.it_interval.tv_sec = 0; //timer_2.it_interval.tv_nsec = 0; //timer_2.it_value.tv_sec = 0; timer_2.it_value.tv_nsec = MODBUS_ANSWER_TIME * 1000000; sev_3.sigev_notify = SIGEV_THREAD; sev_3.sigev_notify_function = TCP_keep_alive_handler; ret3 = timer_create(CLOCKID, &sev_3, &timer3_id); //timer_3.it_interval.tv_sec = 1; //timer_3.it_interval.tv_nsec = 0; timer_3.it_value.tv_sec = TCP_KEEP_ALIVE_TIME; //timer_3.it_value.tv_nsec = 1; //timer_4.it_interval.tv_sec = 1; //timer_4.it_interval.tv_nsec = 0; timer_4.it_value.tv_sec = 1; //timer_3.it_value.tv_nsec = 1; } void TCP_keep_alive_handler() //Обработчик сигнала разрыва связи с сервером { tcphdr.th_seq = htonl (ack_to_raw); tcphdr.th_ack = htonl (seq_to_raw); memcpy (packet, &tcphdr, TCP_HDRLEN * sizeof (uint8_t)); memcpy ((packet + TCP_HDRLEN), &Data_tcp, 3 * sizeof (uint8_t)); if (keep_alive_on == 2) { if (seq_to_raw - ack_from_server < 3) { close(sock); connect_to_server(); } timer_settime(timer3_id, 0, &timer_3, NULL); keep_alive_on = 0; } if (keep_alive_on == 1) { send(sock, Data_tcp, 3, 0); ack_from_server = seq_to_raw; keep_alive_on = 2; timer_settime(timer3_id, 0, &timer_4, NULL); //Запуск таймера Keep Alive } } void start_modbus() // Установка начальных значений регистров modbus { ModbusCS[0] = 1; //Coils ModbusCS[1] = 0; ModbusCS[2] = 1; ModbusCS[5] = 1; ModbusCS[19] = 1; ModbusCS[25] = 1; ModbusCS[140] = 1; ModbusCS[142] = 1; ModbusCS[246] = 1; ModbusIS[22] = 1; //Discrete Inputs ModbusIS[23] = 1; ModbusIS[47] = 1; ModbusIS[54] = 1; ModbusIS[99] = 1; ModbusIS[123] = ModbusIS[140] = 1; ModbusIS[142] = 1; ModbusIS[163] = 1; ModbusHR[5] = 1212; //Holding Registers ModbusHR[6] = 3434; ModbusHR[18] = 5656; ModbusHR[55] = 7878; ModbusHR[56] = 9090; ModbusHR[100] = 11111; ModbusHR[101] = 22222; ModbusHR[102] = 33333; ModbusHR[103] = 44444; ModbusIR[17] = 2257; //Input Registers ModbusIR[18] = 3780; ModbusIR[19] = 421; ModbusIR[63] = 7528; ModbusIR[77] = 5282; ModbusIR[112] = 9321; ModbusIR[113] = 100; ModbusIR[114] = 4216; ModbusIR[115] = 12345; }