map/das-dn/cmg/changemaster.cpp
2024-10-21 10:53:15 +08:00

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);
}