436 lines
11 KiB
C++
436 lines
11 KiB
C++
#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;
|
|
}
|
|
|
|
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(void)
|
|
{
|
|
if (nodes.interfaces.enable)
|
|
{
|
|
char uart_dev[128];
|
|
snprintf(uart_dev, sizeof(uart_dev), "/dev/%s", nodes.interfaces.name);
|
|
return uart_init(uart_dev);
|
|
}
|
|
|
|
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();
|
|
}
|
|
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);
|
|
}
|
|
|