#include "changemaster.h" #include "../hostiec101unbalanced/host_iec101_unbalanced.h" #include "../hostiec101balanced/host_iec101_balanced.h" #include "../subiec101balanced/sub_iec101_balanced.h" #include "../subiec101unbalanced/sub_iec101_unbalanced.h" #include "../hostiec104/host_iec104.h" #include "../subiec104/sub_iec104.h" #include "../hostmodbusrtu/host_modbus_rtu.h" #include "../hostmodbusascii/host_modbus_ascii.h" #include "../hostmodbustcp/host_modbus_tcp.h" #include "../hostmodbusrtuovernet/host_modbus_rtu_tcp.h" #include "../submodbustcp/sub_modbus_rtu_tcp.h" #include "../submodbusrtu/sub_modbus_rtu.h" #include "../rtustatusproc/rtustatus.h" #include "../zjd3100proc/zjd3100pro.h" //#include "../bfftpfile2issmqtt/bfftpfile2issmqtt.h" #ifdef USE_MQTT #endif //USE_MQTT #include "../hostsacnet103/host_sacnet103.h" #ifdef USE_SQLITE3 #include "../subgdw104/sub_gdw104.h" #endif #ifdef USE_WEBSOCKET #endif BYTE CChangeMaster::m_tcitype; CChangeMaster::CChangeMaster() { char hostname[32]; if (gethostname(hostname, sizeof(hostname)) < 0) { vLog(LOG_ERROR, "gethostname error.\n"); return; exit(EXIT_FAILURE); } if (NULL == (m_control.m_node = GetNode(hostname))) { vLog(LOG_ERROR, "node table error, cann't run(%s,%s)!\n", m_control.m_node->m_machine_name, hostname); return; exit(EXIT_FAILURE); } if (m_control.m_node == NULL) { vLog(LOG_ERROR, "node table error, cann't change!\n"); return; exit(EXIT_FAILURE); } if ((m_control.m_node->m_tcitype != MASTER_TCI) && (m_control.m_node->m_tcitype != STANDBY_TCI)) { vLog(LOG_ERROR, "running not on TCI terminal, check the node table!\n"); } memset(&m_changeStruct, 0, sizeof(m_changeStruct)); strncpy(m_changeStruct.m_host, m_control.m_node->m_machine_name, HOST_NAME_LENGTH); m_changeStruct.m_type = MASTER_TCI_ALIVE; m_tcitype = m_control.m_node->m_tcitype; m_lastTcitype = m_tcitype; m_control.m_total = 0; m_control.m_count = 0; m_control.m_dualMaster = FALSE; memset(m_control.m_hostTr, 0, HOST_NAME_LENGTH); m_control.m_total = TCI_CHANGE_FULL_CRITICAL; #ifdef WIN32 uart_fd = INVALID_HANDLE_VALUE; #else uart_fd = -1; #endif } CChangeMaster::~CChangeMaster() { } BOOLEAN CChangeMaster::uart_init(const char *dev) { #ifdef WIN32 if (uart_fd != INVALID_HANDLE_VALUE) { CloseHandle(uart_fd); uart_fd = INVALID_HANDLE_VALUE; } uart_fd = CreateFile(dev, GENERIC_READ | GENERIC_WRITE, (DWORD)0, NULL, OPEN_EXISTING, 0, NULL); if (uart_fd == INVALID_HANDLE_VALUE) { char errorMsg[256] = { '\0' }; DWORD ntError = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ntError, GetSystemDefaultLangID(), errorMsg, sizeof(errorMsg), NULL); vLog(LOG_ERROR, "%s error(%d,%s)\r\n", dev, ntError, errorMsg); return FALSE; } if (!SetupComm(uart_fd, (DWORD)MAX_PORT_BUFFER_SIZE, (DWORD)MAX_PORT_BUFFER_SIZE)) { CloseHandle(uart_fd); uart_fd = INVALID_HANDLE_VALUE; char errorMsg[256] = { '\0' }; DWORD ntError = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ntError, GetSystemDefaultLangID(), errorMsg, sizeof(errorMsg), NULL); vLog(LOG_ERROR, "%s error(%d,%s)\r\n", dev, ntError, errorMsg); return FALSE; } DCB dcb; if (!GetCommState(uart_fd, &dcb)) { CloseHandle(uart_fd); uart_fd = INVALID_HANDLE_VALUE; char errorMsg[256] = { '\0' }; DWORD ntError = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ntError, GetSystemDefaultLangID(), errorMsg, sizeof(errorMsg), NULL); vLog(LOG_ERROR, "%s error(%d,%s)\r\n", dev, ntError, errorMsg); return FALSE; } dcb.BaudRate = 19200; dcb.ByteSize = 8; dcb.Parity = 0; dcb.fParity = FALSE; dcb.StopBits = 0; dcb.fOutxDsrFlow = FALSE; dcb.fDsrSensitivity = FALSE; dcb.fOutxCtsFlow = FALSE; dcb.fRtsControl = FALSE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fAbortOnError = TRUE; dcb.fBinary = TRUE; dcb.fTXContinueOnXoff = FALSE; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.ErrorChar = 0; dcb.fNull = 0; dcb.fDummy2 = 0; if (!SetCommState(uart_fd, &dcb)) { char errorMsg[256] = { '\0' }; DWORD ntError = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ntError, GetSystemDefaultLangID(), errorMsg, sizeof(errorMsg), NULL); vLog(LOG_ERROR, "%s error(%d,%s)\r\n", dev, ntError, errorMsg); return FALSE; } COMMTIMEOUTS commTimeouts; commTimeouts.WriteTotalTimeoutConstant = 0; commTimeouts.WriteTotalTimeoutMultiplier = 0; commTimeouts.ReadTotalTimeoutMultiplier = 0; commTimeouts.ReadTotalTimeoutConstant = 0; commTimeouts.ReadIntervalTimeout = MAXDWORD; if (!SetCommTimeouts(uart_fd, &commTimeouts)) { char errorMsg[256] = { '\0' }; DWORD ntError = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ntError, GetSystemDefaultLangID(), errorMsg, sizeof(errorMsg), NULL); vLog(LOG_ERROR, "%s error(%d,%s)\r\n", dev, ntError, errorMsg); return FALSE; } #else struct termios opt; uart_fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY); if (uart_fd < 0) { vLog(LOG_ERROR, "can't open dev(%s).\n", dev); return FALSE; } if (fcntl(uart_fd, F_SETFL, 0) < 0) { vLog(LOG_ERROR, "fcntl error.\n"); close(uart_fd); uart_fd = -1; return FALSE; } if (isatty(uart_fd) == 0) { vLog(LOG_ERROR, "standard input is not a terminal device!\n"); close(uart_fd); uart_fd = -1; return FALSE; } if (tcgetattr(uart_fd, &opt ) != 0) { vLog(LOG_ERROR, "tcgetattr error.\n"); close(uart_fd); uart_fd = -1; return FALSE; } tcflush(uart_fd, TCIOFLUSH); cfsetispeed(&opt, B19200); cfsetospeed(&opt, B19200); opt.c_cflag &= ~CSIZE; opt.c_cflag |= CS8; opt.c_cflag &= ~PARENB; opt.c_iflag &= ~INPCK; opt.c_cflag &= ~CSTOPB; tcflush(uart_fd, TCIFLUSH); opt.c_iflag = 0; opt.c_oflag = 0; opt.c_lflag = 0; opt.c_cc[VTIME] = 0; opt.c_cc[VMIN] = 0; if (tcsetattr(uart_fd, TCSANOW, &opt) != 0) { vLog(LOG_ERROR, "tcsetarrt fd.\n"); close(uart_fd); uart_fd = -1; return FALSE; } #endif return TRUE; } BOOLEAN CChangeMaster::Init(void) { if (nodes.interfaces.enable) { char uart_dev[128]; #ifdef WIN32 snprintf(uart_dev, sizeof(uart_dev), "\\\\.\\%s", nodes.interfaces.name); #else snprintf(uart_dev, sizeof(uart_dev), "/dev/%s", nodes.interfaces.name); #endif return uart_init(uart_dev); } return TRUE; } int CChangeMaster::uart_write(const void *data, int size) { #ifdef WIN32 if (uart_fd == INVALID_HANDLE_VALUE) return 0; return WriteFile(uart_fd, data, size, NULL, NULL); #else if (uart_fd < 0) return 0; return write(uart_fd, data, size); #endif return -1; } int CChangeMaster::uart_read(void* data, int size) { #ifdef WIN32 if (uart_fd == INVALID_HANDLE_VALUE) return 0; return ReadFile(uart_fd, data, size, NULL, NULL); #else if (uart_fd < 0) return 0; return read(uart_fd, data, size); #endif return -1; } void CChangeMaster::OnReceive(ChangeMaster change) { if (change.m_type != MASTER_TCI_ALIVE) return; if (strcmp(change.m_host, m_control.m_node->m_machine_name) != 0) { //strncpy(m_control.m_hostTr, change.m_host, wMin(sizeof(m_control.m_hostTr)-1, strlen(change.m_host))); snprintf(m_control.m_hostTr, sizeof(m_control.m_hostTr), "%s", change.m_host); if (m_control.m_node->m_tcitype == STANDBY_TCI) { m_control.m_total = TCI_CHANGE_FULL_CRITICAL; } else { m_control.m_dualMaster = TRUE; } } } void CChangeMaster::MasterSend() { if (IsMasterTci()) { if (m_control.m_dualMaster) { ChangeDual(); m_tcitype = m_control.m_node->m_tcitype; m_control.m_dualMaster = FALSE; } else { uart_write(&m_changeStruct, sizeof(ChangeMaster)); } } else { ChangeMaster change; int len = uart_read(&change, sizeof(ChangeMaster)); if (len >= (int)sizeof(ChangeMaster)) { OnReceive(change); } if (m_control.m_total > 0) { m_control.m_total--; } if (m_control.m_total == 0) { ChangeNode(); m_tcitype = m_control.m_node->m_tcitype; m_control.m_total = TCI_CHANGE_FULL_CRITICAL; } m_control.m_count = 0; } } BOOLEAN CChangeMaster::IsMasterTci() { if (m_control.m_node == NULL) { vLog(LOG_DEBUG, "node table error, cann't change!\n"); return FALSE; } m_tcitype = m_control.m_node->m_tcitype; if ((m_control.m_node->m_tcitype != MASTER_TCI) && (m_control.m_node->m_tcitype != STANDBY_TCI)) { vLog(LOG_DEBUG, "running not on TCI terminal, check the node table!\n"); return FALSE; } if ((m_tcitype == MASTER_TCI) && (m_lastTcitype == STANDBY_TCI)) { vLog(LOG_DEBUG, "create ChangeNewObject thread.\n"); pthread_t pid; pthread_create(&pid, NULL, ChangeNewObject, this); } else if ((m_tcitype == STANDBY_TCI) && (m_lastTcitype == MASTER_TCI)) { ChangeDelete(); } m_lastTcitype = m_tcitype; if (m_control.m_node->m_tcitype == MASTER_TCI) return TRUE; else return FALSE; } void CChangeMaster::ChangeNode() { int i = 0; m_control.m_total = TCI_CHANGE_FULL_CRITICAL; NODE_STRUCT *mNode; mNode = GetNode(m_control.m_hostTr); memset(m_control.m_hostTr, 0, HOST_NAME_LENGTH); int MaxNum = MAX_NODE_NUM; if ((mNode == NULL)) { for (i = 0; i < MaxNum; i++) { mNode = GetNode(i); { if (mNode == NULL) continue; if (mNode->m_tcitype == MASTER_TCI) break; else mNode = NULL; } } } if (m_control.m_node != NULL) { m_control.m_node->m_tcitype = MASTER_TCI; SendNodeWarn(m_control.m_node->m_netnode_no, ON); } } void CChangeMaster::ChangeDual() { int i = 0; m_control.m_total = TCI_CHANGE_FULL_CRITICAL; NODE_STRUCT *mNode; mNode = GetNode(m_control.m_hostTr); memset(m_control.m_hostTr, 0, HOST_NAME_LENGTH); int MaxNum = MAX_NODE_NUM; if ((mNode == NULL)) { for (i = 0; i < MaxNum; i++) { mNode = GetNode(i); { if (mNode == NULL) continue; if ((mNode->m_netnode_no != m_control.m_node->m_netnode_no) && ((mNode->m_tcitype == MASTER_TCI) || (mNode->m_tcitype == STANDBY_TCI))) { break; } else { mNode = NULL; } } } } if ((mNode != NULL) && (m_control.m_node != NULL)) { if (mNode->m_netnode_no < m_control.m_node->m_netnode_no) { mNode->m_tcitype = MASTER_TCI; m_control.m_node->m_tcitype = STANDBY_TCI; SendNodeWarn(mNode->m_netnode_no, ON); SendNodeWarn(m_control.m_node->m_netnode_no, OFF); } else { mNode->m_tcitype = STANDBY_TCI; m_control.m_node->m_tcitype = MASTER_TCI; SendNodeWarn(mNode->m_netnode_no, OFF); SendNodeWarn(m_control.m_node->m_netnode_no, ON); } } } NODE_STRUCT* CChangeMaster::GetNode(char *name) { return &nodes.m_node[0]; int i = 0; for (i = 0; i < MAX_NODE_NUM; i++) { if (strcmp(nodes.m_node[i].m_machine_name, name) == 0) { return &nodes.m_node[i]; } } return NULL; } NODE_STRUCT* CChangeMaster::GetNode(int netno) { return &nodes.m_node[0]; int i = 0; for (i = 0; i < MAX_NODE_NUM; i++) { if (nodes.m_node[i].m_netnode_no == netno) { return &nodes.m_node[i]; } } return NULL; } void CChangeMaster::StartUp(void) { int i; if (!initialize_thread()) { vLog(LOG_ERROR, "thread initialize error.\n"); return; } for (i = 0; i < PROCESSES_NUM; i++) { if (TRUE == config.processes[i].state) { if (PROTOCOL_HOST_MODBUS_RTU == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: modbus rtu主协议.\n", i); procs[i] = new CHostModbusRtuProcess(); } else if (PROTOCOL_HOST_UNBALANCED_IEC101 == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: 不平衡方式IEC101主协议.\n", i); procs[i] = new CIEC101PrimaryUnbalancedProcess(); } else if (PROTOCOL_HOST_BALANCED_IEC101 == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: 平衡方式IEC101主协议.\n", i); procs[i] = new CIEC101PrimaryBalancedProcess(); } else if (PROTOCOL_SUB_BALANCED_IEC101 == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: 平衡方式IEC101从协议.\n", i); procs[i] = new CIEC101SecondaryBalancedProcess(); } else if (PROTOCOL_SUB_UNBALANCED_IEC101 == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: 不平衡方式IEC101从协议.\n", i); procs[i] = new CIEC101SecondaryUnbalancedProcess(); } else if (PROTOCOL_SUB_MODBUS_RTU == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: modbus rtu从协议.\n", i); procs[i] = new CSubModbusRtuProcess(); } else if (PROTOCOL_HOST_MODBUS_ASCII == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: modbus ascii主协议.\n", i); procs[i] = new CHostModbusAsciiProcess(); } else if (PROTOCOL_HOST_IEC104 == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: iec104主协议.\n", i); procs[i] = new CHostIEC104Process(); } else if (PROTOCOL_SUB_IEC104 == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: iec104从协议.\n", i); procs[i] = new CSubIEC104Process(); } else if (PROTOCOL_HOST_MODBUS_TCP == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: modbus tcp主协议.\n", i); procs[i] = new CHostModbusTcpProcess(); } else if (PROTOCOL_SUB_MODBUS_TCP == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: modbus tcp从协议.\n", i); procs[i] = new CSubModbusTcpProcess(); } else if (PROTOCOL_HOST_MODBUS_RTU_TCP == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: modbus rtu over tcp主协议.\n", i); procs[i] = new CHostModbusRtuOverTcpProcess(); } else if (PROTOCOL_LOCAL_DEBUG == config.processes[i].proto) {//Local debug vLog(LOG_INFO, "协议<%d>创建为: 本地调试协议.\n", i); procs[i] = new CZJD3100Process(); } else if (PROTOCOL_RTU_STATE == config.processes[i].proto) {//网关状态 vLog(LOG_INFO, "协议<%d>创建为: 网关状态协议.\n", i); procs[i] = new CRTUStatusProcess(); } #if 0 else if (PROTOCOL_BF_FTP == config.processes[i].proto) {//倍福FTP文件协议 vLog(LOG_INFO, "协议<%d>创建为: 倍福FTP文件协议.\n", i); procs[i] = new CBFFTPFile2ISSMQTTProcess(); } #endif #ifdef USE_MQTT #endif #ifdef USE_SQLITE3 else if (PROTOCOL_SUB_GDW104 == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: DLT634.5104-2009.\n", i); procs[i] = new CSubGDW104Process(); } #endif #ifdef USE_WEBSOCKET #endif else { vLog(LOG_ERROR, "(%s,%d)系统不支持该协议或该协议未知.\n", config.processes[i].name, config.processes[i].proto); } } if (procs[i] != NULL) { if (!procs[i]->Create(i)) { procs[i]->Destroy(); delete procs[i]; procs[i] = NULL; } } } } void CChangeMaster::MasterTciFirstRun() { if (m_control.m_node->m_tcitype == MASTER_TCI) { StartUp(); SendNodeWarn(m_control.m_node->m_netnode_no, ON); } } void CChangeMaster::SendNodeWarn(BYTE netno , BYTE onOff) { vLog(LOG_DEBUG, "NodeNo.(%d) is %s.\n", netno, onOff ? "ON" : "OFF"); } void CChangeMaster::ChangeDelete() { int i = 0; vLog(LOG_DEBUG, "DeleteObject.\n"); for (i = 0; i < PROCESSES_NUM; i++) { if (procs[i] != NULL) { procs[i]->Destroy(); delete procs[i]; procs[i] = NULL; } } destroy_thread(); } void CChangeMaster::ChangeNew() { vLog(LOG_DEBUG, "NewObject.\n"); StartUp(); } void *ChangeNewObject(void *args) { usleep(250000); CChangeMaster *pMaster = (CChangeMaster *)args; if (pMaster == NULL) return ((void *)0); pMaster->ChangeNew(); pthread_exit(0); return ((void *)1); }