using System;
|
using System.Collections;
|
using System.Data.OracleClient;
|
using NLog;
|
using TRACEROBJECTLib;
|
|
namespace CCSTrace.CCS.EventAI
|
{
|
public class TraceSubject
|
{
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
|
private string _mDbConnectionString;
|
private static bool _isNewCase;
|
private static ArrayList _mLinkList; // store the switch of the new case path
|
private static TraceEngine _mTEngine;
|
private static Hashtable _mTreeMap; // store the switch of the old case path
|
private static int _sFsc;
|
private static int _sUfid;
|
private readonly ArrayList _mTmp = new ArrayList();
|
private NetworkContext _mPContext;
|
|
private readonly OracleConnection _connectionTpc;
|
private readonly OracleTransaction _transaction;
|
|
public TraceSubject(OracleConnection conn, OracleTransaction trx, string traceConnectionString)
|
{
|
_connectionTpc = conn;
|
_transaction = trx;
|
_mDbConnectionString = traceConnectionString;
|
|
try
|
{
|
if (_mTEngine == null)
|
{
|
_mTEngine = new TraceEngine();
|
}
|
}
|
catch (Exception ex)
|
{
|
Logger.Error(ex, ex.Message);
|
throw ex;
|
}
|
}
|
|
public void DiscardEngine()
|
{
|
_mTEngine = null;
|
}
|
|
public ArrayList GetNewResult()
|
{
|
return _mLinkList;
|
}
|
|
public Hashtable GetOldResult()
|
{
|
return _mTreeMap;
|
}
|
|
// for EOS(only get the reverse tree)
|
public void StartTrace(int startFsc, int startUfid, bool mIsNew)
|
{
|
_sFsc = startFsc;
|
_sUfid = startUfid;
|
_isNewCase = mIsNew;
|
_mTreeMap = new Hashtable();
|
_mLinkList = new ArrayList();
|
|
try
|
{
|
SetReverseTree(Trace(true));
|
}
|
catch (Exception e)
|
{
|
Logger.Error(e, e.Message);
|
throw;
|
}
|
}
|
|
private bool GetSwitchOn(int ufid)
|
{
|
var sqlStmt = "SELECT M.OSTATUS as OSTATUS FROM (SELECT UFID,OSTATUS FROM BASEDB.CONNECTIVITY WHERE FSC = 114) M,"
|
+ "BASEDB.SWITCH S WHERE M.UFID = S.UFID AND S.NSTATUS <> 0 AND M.UFID = " + ufid;
|
|
OracleCommand command = null;
|
OracleDataReader reader = null;
|
|
try
|
{
|
command = new OracleCommand(sqlStmt, _connectionTpc, _transaction);
|
reader = command.ExecuteReader();
|
|
if (reader.Read())
|
{
|
if (Convert.ToInt32(reader["OSTATUS"]) == 1)
|
return true;
|
}
|
reader.Close();
|
}
|
catch (Exception e)
|
{
|
Logger.Error(e, e.Message);
|
}
|
finally
|
{
|
command?.Dispose();
|
|
reader?.Close();
|
}
|
return false;
|
}
|
|
private bool GetJumperOn(int ufid)
|
{
|
var sqlStmt = "SELECT OSTATUS FROM BASEDB.CONNECTIVITY WHERE FSC = 109 AND UFID = " + ufid;
|
|
OracleCommand command = null;
|
OracleDataReader reader = null;
|
|
try
|
{
|
command = new OracleCommand(sqlStmt, _connectionTpc, _transaction);
|
reader = command.ExecuteReader();
|
|
if (reader.Read())
|
{
|
if (Convert.ToInt32(reader["OSTATUS"]) == 1)
|
return true;
|
}
|
reader.Close();
|
}
|
catch (Exception e)
|
{
|
Logger.Error(e, e.Message);
|
}
|
finally
|
{
|
command?.Dispose();
|
|
reader?.Close();
|
}
|
return false;
|
}
|
|
private readonly Hashtable _traceCounts = new Hashtable();
|
|
private void SetReverseTree(ResultTree tree)
|
{
|
int i = 0;
|
TreeIterator iti = null;
|
bool ostatus = true;
|
|
if (tree != null)
|
{
|
i = 0;
|
iti = tree.CreateTreeIterator();
|
bool isNotEnd = true;
|
|
while (isNotEnd)
|
{
|
if (GetTraceCount(iti.Value.ClassID, iti.Value.ObjectID) > 5)
|
throw new TraceLoopException("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + iti.Value.ClassID + "," + iti.Value.ObjectID + ")");
|
else
|
AddTraceCount(iti.Value.ClassID, iti.Value.ObjectID);
|
|
while (iti.IsLeaf == 0)
|
{
|
TreeNode node = iti.Value;
|
|
if ((node.ClassID == 114) || (node.ClassID == 108) || (node.ClassID == 109))
|
{
|
Equipment equip = new Equipment(node.ClassID, node.ObjectID);
|
|
if (_isNewCase)
|
_mLinkList.Add(equip);
|
else
|
{
|
_mTreeMap.Add(node.ObjectID, equip);
|
_mTmp.Add(equip);
|
}
|
i++;
|
|
/* if (getTraceCount(node.ClassID, node.ObjectID) > 2)
|
throw new Exception("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + node.ClassID + "," + node.ObjectID + ")");
|
else
|
AddTraceCount(node.ClassID, node.ObjectID);
|
*/
|
}
|
|
Console.WriteLine(node.ClassID + "----->" + node.ObjectID);
|
Logger.Info(node.ClassID + "----->" + node.ObjectID);
|
|
iti.MoveDescent((short)0);
|
}
|
|
// 當從breaker出來的導線不只一條時,breaker可能會不被add(因為breaker是leaf但其parent的DescentCount > 1,所以被忽略)
|
/*
|
* if ( ((com.origo.TraceModel.ITreeNode)iti.get_Value()).get_ClassID() == EOS.GlobalVariable.Breaker ) {
|
* com.origo.TraceModel.ITreeNode node = iti.get_Value(); Equipment Equip = new Equipment(node.get_ClassID(),node.get_ObjectID()); if (
|
* IsNewCase ) m_LinkList.add(i,Equip); else { m_TreeMap.put(new Integer(node.get_ObjectID()),Equip); m_Tmp.add(Equip); }
|
* System.out.println(node.get_ClassID() + "----->" + node.get_ObjectID()); System.out.println("Trace Finish...."); i++; break; }
|
*/
|
|
if ((iti.Value).ClassID == GlobalVariable.Breaker)
|
{
|
TreeNode node = iti.Value;
|
Equipment equip = new Equipment(node.ClassID, node.ObjectID);
|
|
if (_isNewCase)
|
_mLinkList.Add(equip);
|
else
|
{
|
_mTreeMap.Add(node.ObjectID, equip);
|
_mTmp.Add(equip);
|
}
|
i++; //後面直接就FINISH,所以就不用判斷tracecount
|
|
Logger.Info(node.ClassID + "----->" + node.ObjectID);
|
Logger.Info("Trace Finish....");
|
break;
|
}
|
// 當追蹤到被切開的開關且該上一層設備只有該開關一個child)
|
else if (iti.Value.ClassID == GlobalVariable.Switch || iti.Value.ClassID == GlobalVariable.Jumper)
|
{
|
TreeNode node = iti.Value;
|
iti.MoveAscent();
|
|
Equipment equip = new Equipment(node.ClassID, node.ObjectID);
|
|
if (IsEndEquip(equip))
|
{
|
if (_isNewCase)
|
_mLinkList.Add(equip);
|
else
|
{
|
_mTreeMap.Add(node.ObjectID, equip);
|
_mTmp.Add(equip);
|
}
|
i++; //後面直接就FINISH,所以就不用判斷tracecount
|
|
Logger.Info(node.ClassID + "----->" + node.ObjectID);
|
Logger.Info("Trace Finish....");
|
break;
|
}
|
|
//switch (node.ClassID)
|
//{
|
// case 114:
|
// ostatus = getSwitchOn(node.ObjectID);
|
// break;
|
// case 109:
|
// ostatus = getJumperOn(node.ObjectID);
|
// break;
|
//}
|
|
//if (!ostatus && (iti.DescentCount == 1)) {
|
// Equipment Equip = new Equipment(node.ClassID, node.ObjectID);
|
|
// if (IsNewCase)
|
// m_LinkList.Add(Equip);
|
// else {
|
// m_TreeMap.Add(node.ObjectID, Equip);
|
// m_Tmp.Add(Equip);
|
// }
|
// i++;
|
|
// Console.WriteLine(node.ClassID + "----->" + node.ObjectID);
|
// _Plogger.Info(node.ClassID + "----->" + node.ObjectID);
|
// Console.WriteLine("Trace Finish....");
|
// _Plogger.Info("Trace Finish....");
|
// break;
|
//}
|
}
|
else
|
{
|
TreeNode node = iti.Value;
|
iti.MoveAscent();
|
|
if (iti.DescentCount == 1)
|
throw new Exception("追蹤到非開關類斷開之設備(Fsc = " + node.ClassID + ",Ufid = " + node.ObjectID);
|
}
|
|
for (int j = 1; j < iti.DescentCount; j++)
|
{
|
iti.MoveDescent((short)j);
|
|
if (iti.IsLeaf == 1)
|
{
|
TreeNode node = iti.Value;
|
Equipment equip = new Equipment(node.ClassID, node.ObjectID);
|
|
switch (node.ClassID)
|
{
|
case 108:
|
if (_isNewCase)
|
_mLinkList.Add(equip);
|
else
|
{
|
_mTreeMap.Add(node.ObjectID, equip);
|
_mTmp.Add(equip);
|
}
|
|
Logger.Info(node.ClassID + "----->" + node.ObjectID);
|
i++;
|
|
/* if (getTraceCount(node.ClassID, node.ObjectID) > 2)
|
throw new Exception("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + node.ClassID + "," + node.ObjectID + ")");
|
else
|
AddTraceCount(node.ClassID, node.ObjectID);
|
*/
|
break;
|
|
case 109:
|
case 114:
|
switch (node.ClassID)
|
{
|
case 114:
|
ostatus = GetSwitchOn(node.ObjectID);
|
break;
|
|
case 109:
|
ostatus = GetJumperOn(node.ObjectID);
|
break;
|
}
|
|
// Only for switch because the breaker only has one node to descent
|
if (!ostatus)
|
{
|
if (_isNewCase)
|
_mLinkList.Add(equip);
|
else
|
{
|
_mTreeMap.Add(node.ObjectID, equip);
|
_mTmp.Add(equip);
|
}
|
|
Logger.Info(node.ClassID + "----->" + node.ObjectID);
|
i++;
|
|
/* if (getTraceCount(node.ClassID, node.ObjectID) > 2)
|
throw new Exception("追蹤產生迴圈狀況。(Fsc,Ufid) = (" + node.ClassID + "," + node.ObjectID + ")");
|
else
|
AddTraceCount(node.ClassID, node.ObjectID);
|
*/
|
}
|
break;
|
|
default:
|
break;
|
} // switch
|
|
iti.MoveAscent();
|
isNotEnd = false;
|
}
|
else
|
{
|
isNotEnd = true;
|
break;
|
}
|
} // for
|
} // while
|
Logger.Info("Tree Node Count = " + i);
|
}
|
else
|
{
|
Logger.Info("Tree is null");
|
throw new Exception("無法追蹤到任何設備,可能是該用戶所在變壓器設備連結性有問題。");
|
}
|
}
|
|
private ResultTree Trace(bool reverse)
|
{
|
ResultTree tree = null;
|
|
try
|
{
|
ConfigTrace();
|
Logger.Info("configTrace OK.");
|
}
|
catch (Exception e)
|
{
|
Logger.Error(e.Message);
|
Console.WriteLine(e.StackTrace);
|
return tree;
|
}
|
|
try
|
{
|
tree = ModeTrace(reverse);
|
}
|
catch (Exception e)
|
{
|
Logger.Error(e.Message);
|
Console.WriteLine(e.StackTrace);
|
}
|
|
return tree;
|
}
|
|
private void ConfigTrace()
|
{
|
if (_mDbConnectionString == null)
|
{
|
_mDbConnectionString = "basedb/basedb000@nntpc";
|
}
|
try
|
{
|
if (_mPContext == null) _mPContext = _mTEngine.teoCreateContext();
|
|
if (_mPContext.IsConnected == 0)
|
{
|
_mPContext.Connect("", _mDbConnectionString);
|
}
|
}
|
catch (Exception ex)
|
{
|
Logger.Error(ex, ex.Message);
|
}
|
}
|
|
private ResultTree ModeTrace(bool reverse)
|
{
|
TravelContext tContext = new TravelContext();
|
TravelStartCriterion sCriterion = new TravelStartCriterion();
|
TravelTerminateCriterion eCriterion = new TravelTerminateCriterion();
|
|
sCriterion.ClsID = (short)_sFsc;
|
sCriterion.ObjID = _sUfid;
|
|
if (reverse) // 反向上追
|
{
|
sCriterion.StartMode = (TRAVELSTARTCRITERIONTYPE)(Convert.ToInt32(TRAVELSTARTCRITERIONTYPE.TRAVELBYNEGDIR) + Convert.ToInt32(TRAVELSTARTCRITERIONTYPE.TRAVELWITHFOLLOW));
|
|
eCriterion.ClsID = (short)GlobalVariable.Breaker;
|
eCriterion.EndMode = TRAVELTERMCRITERIONTYPE.TRAVELTOTHISCLASS;
|
}
|
else // 順向追蹤
|
{
|
sCriterion.StartMode = TRAVELSTARTCRITERIONTYPE.TRAVELBYCURDIR;
|
|
eCriterion.EndMode = TRAVELTERMCRITERIONTYPE.TRAVELTOTHISCLASS;
|
}
|
|
tContext.addCriterion(sCriterion);
|
tContext.addCriterion(eCriterion);
|
|
_mPContext.ResetContext();
|
|
Logger.Info("Set ModeTrace OK.");
|
ResultTreeBuilder trBuilder = _mPContext.CreateTreeBuilder();
|
if (!trBuilder.constructResultTree(tContext, TRAVELTHREADMODE.CONMODE_SYNCHRONOUS)) { return null; }
|
Logger.Info("ConstructResultTree OK.");
|
ResultTree result = trBuilder.ResultTree;
|
|
Logger.Info("getResultTree OK.");
|
return result;
|
}
|
|
//判斷是否為最終設備(逆向追到已經無child的設備時,檢查該設備是否為最終設備(查驗該設備的同層設備,是否仍有可繼續逆向追蹤的設備,若無,則該設備為最終設備
|
private bool IsEndEquip(Equipment selfEquip)
|
{
|
string sqlStmt;
|
OracleCommand command = null;
|
OracleDataReader reader = null;
|
long nValue = 0;
|
|
sqlStmt = "SELECT DIR,OSTATUS,N1,N2 FROM BASEDB.CONNECTIVITY WHERE FSC = " + selfEquip.Fsc+ " AND UFID = " + selfEquip.Ufid;
|
|
try
|
{
|
command = new OracleCommand(sqlStmt, _connectionTpc, _transaction);
|
reader = command.ExecuteReader();
|
|
if (reader.Read())
|
{
|
if (Convert.ToInt32(reader["OSTATUS"]) == 1) //如果設備本身為非切開的設備,那應該繼續往逆向追
|
return false;
|
else
|
{
|
if (Convert.ToInt32(reader["DIR"]) == 3) //順向無電 N1-->N2,所以逆向的上游N值抓N2
|
nValue = Convert.ToInt32(reader["N2"]);
|
else
|
nValue = Convert.ToInt32(reader["N1"]);
|
}
|
}
|
reader.Close();
|
|
sqlStmt = "SELECT FSC,UFID,DIR,OSTATUS,N1,N2 FROM BASEDB.CONNECTIVITY WHERE N1 <> N2 AND ( N1 = " + nValue + " OR N2 = " + nValue + ")";
|
command.CommandText = sqlStmt;
|
|
reader = command.ExecuteReader();
|
|
while (reader.Read())
|
{
|
if (Convert.ToInt32(reader["FSC"]) == selfEquip.Fsc&& Convert.ToInt32(reader["UFID"]) == selfEquip.Ufid)
|
continue;
|
|
if (Convert.ToInt32(reader["OSTATUS"]) == 0) //切開的設備不可能為逆向的上游
|
continue;
|
|
if (Convert.ToInt32(reader["N1"]) == nValue)
|
{
|
switch (Convert.ToInt32(reader["DIR"]))
|
{
|
case 1:
|
case 3:
|
break;
|
|
case 2:
|
case 4:
|
return false; //如果逆向的上游連接點為N1,一定要N2-->N1才可能還有需要逆向追蹤設備
|
case 99:
|
break; //未供電設備不可能是逆向上游
|
}
|
}
|
else if (Convert.ToInt32(reader["N2"]) == nValue)
|
{
|
switch (Convert.ToInt32(reader["DIR"]))
|
{
|
case 1:
|
case 3:
|
return false; //如果逆向的上游連接點為N2,一定要N1-->N2才可能還有需要逆向追蹤設備
|
case 2:
|
case 4:
|
break;
|
|
case 99:
|
return false; //未供電設備不可能是逆向上游
|
}
|
}
|
}
|
reader.Close();
|
}
|
catch (Exception e)
|
{
|
Logger.Error(e, e.Message);
|
return false;
|
}
|
finally
|
{
|
if (command != null)
|
command.Dispose();
|
|
if (reader != null)
|
reader.Close();
|
}
|
|
return true;
|
}
|
|
private int GetTraceCount(int fsc, int ufid)
|
{
|
if (_traceCounts.ContainsKey(fsc + "|" + ufid))
|
return int.Parse(_traceCounts[fsc + "|" + ufid].ToString());
|
else
|
return 0;
|
}
|
|
private void AddTraceCount(int fsc, int ufid)
|
{
|
int count = 1;
|
|
if (_traceCounts.ContainsKey(fsc + "|" + ufid))
|
{
|
count = int.Parse(_traceCounts[fsc + "|" + ufid].ToString());
|
count++;
|
_traceCounts.Remove(fsc + "|" + ufid);
|
}
|
|
_traceCounts.Add(fsc + "|" + ufid, count.ToString());
|
}
|
}
|
|
public class TraceLoopException : Exception
|
{
|
public TraceLoopException(string message) : base(message)
|
{
|
}
|
}
|
}
|