#include "changemaster.h" #include "../hostiec104/host_iec104.h" #include "../subiec104/sub_iec104.h" #include "../hostmodbusrtu/host_modbus_rtu.h" #include "../hostmodbustcp/host_modbus_tcp.h" #include "../rtustatusproc/rtustatus.h" #include "../zjd3100proc/zjd3100pro.h" //#include "../bfftpfile2issmqtt/bfftpfile2issmqtt.h" #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; uart_fd = -1; m_conn = NULL; } CChangeMaster::~CChangeMaster() { } BOOLEAN CChangeMaster::uart_init(const char *dev) { 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; } return TRUE; } BOOLEAN CChangeMaster::Init(noPollConn *conn) { if (nodes.interfaces.enable) { char uart_dev[128]; snprintf(uart_dev, sizeof(uart_dev), "/dev/%s", nodes.interfaces.name); return uart_init(uart_dev); } if (conn) { m_conn = conn; } return TRUE; } int CChangeMaster::uart_write(const void *data, int size) { if (uart_fd < 0) return 0; return write(uart_fd, data, size); } int CChangeMaster::uart_read(void* data, int size) { if (uart_fd < 0) return 0; return read(uart_fd, data, size); } 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_MODBUS_TCP == config.processes[i].proto) { vLog(LOG_INFO, "协议<%d>创建为: modbus tcp主协议.\n", i); procs[i] = new CHostModbusTcpProcess(m_conn); } 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_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(); } 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); }