map/das-dn/cmg/changemaster.cpp
2024-07-08 10:27:17 +08:00

643 lines
18 KiB
C++

#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");
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);
exit(EXIT_FAILURE);
}
if (m_control.m_node == NULL)
{
vLog(LOG_ERROR, "node table error, cann't change!\n");
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)
{
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)
{
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);
}