using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Threading; using System.Text.RegularExpressions; //using Serializer; using CrossThreadCalls; namespace DynamicRFIDAgentEnvironment { public class AgentNode { #region Parameters of Agent Node public AgentStateMachine _AgentState = AgentStateMachine.NULL; public AgentMoveDirection _NextMovingDirection = AgentMoveDirection.STILL; public AgentMoveDirection _PreMovingDirection = AgentMoveDirection.STILL; public int _NodeId = -1; //public Dictionary _RSSIMap = new Dictionary(new Position.EqualityComparer()); public Dictionary _RSSIMap = new Dictionary(); public AgentDAL m_DAL; public string _DBStr = ""; public bool _MasterFlag = false; public string _AgentNodeName = SolutionConstants.iniAgentNodeName; public Position _iniPosition; public Position _nextPosition; public Position _currPosition; public int _nextRSSI = SolutionConstants.iniRSSI; public int _currRSSI = SolutionConstants.iniRSSI; public float _DtoTissue1 = SolutionConstants.iniDtoTissue; public float _DtoTissue2 = SolutionConstants.iniDtoTissue; public float _DtoTissue3 = SolutionConstants.iniDtoTissue; public float _DtoTissue4 = SolutionConstants.iniDtoTissue; public bool _connectedTissue1 = false; public bool _connectedTissue2 = false; public bool _connectedTissue3 = false; public bool _connectedTissue4 = false; public IPAddress _IP = IPAddress.Parse(SolutionConstants.iniIP); public float _antennaPowerdbm = SolutionConstants.iniAntennaPowerDbm; public float _antennaAngle = SolutionConstants.iniAntennaAngle; public List _TissueList = new List(); public Dictionary _TissueConnectionList = new Dictionary(); //public AgentNode _Tissue1; //public AgentNode _Tissue2; //public AgentNode _Tissue3; //public AgentNode _Tissue4; public MasterTissueNum _MasterTissue = MasterTissueNum.T0; public HeartBeatStatus _HeartBeat = HeartBeatStatus.DEAD; //public Dictionary _cmdList; public AgentCommandList _AgentCommandList; private System.Threading.Timer mHeartBeatTimer; private System.Threading.Timer mProcessTimer; //private System.Threading.Timer mResetBackColorTimer; #endregion public AgentNode(Dictionary aRSSIMap, string DBConnectionStr, List _TissueList) { //Pas the RSSI Map in _RSSIMap = aRSSIMap; _DBStr = DBConnectionStr; // Load up the command list _AgentCommandList = new AgentCommandList(); //_Tissue1 = new AgentNode(_RSSIMap,_DBStr); //_Tissue2 = new AgentNode(_RSSIMap, _DBStr); //_Tissue3 = new AgentNode(_RSSIMap, _DBStr); //_Tissue4 = new AgentNode(_RSSIMap, _DBStr); mHeartBeatTimer = new System.Threading.Timer(new System.Threading.TimerCallback(OnHearBeatTimer), null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); mProcessTimer = new System.Threading.Timer(new System.Threading.TimerCallback(OnProcessTimer), null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); m_DAL = new AgentDAL(_DBStr); } #region Initialization //1. Need to set up this one first. public void Ini1_SetAgentName(string aAgentName) { _AgentState = AgentStateMachine.INITIAL; _AgentNodeName = aAgentName; _AgentState = AgentStateMachine.NULL; } //2. Intialize the start position public void Ini2_Position(int iniX, int iniY) { _AgentState = AgentStateMachine.INITIAL; //Create the initial Postion _iniPosition = new Position(iniX, iniY, SolutionConstants.xMax, SolutionConstants.yMax); //in the beginning, the next position is the same as the initial position _nextPosition = _iniPosition; _currPosition = _iniPosition; GetCurrPosRSSI(); _AgentState = AgentStateMachine.NULL; } ////4. Activate the Node //public void Ini3_ActivateNode() //{ // _AgentState = AgentStateMachine.INITIAL; // if (mHeartBeatTimer != null) // mHeartBeatTimer.Change(SolutionConstants.iniHeartBeatRate_ms, System.Threading.Timeout.Infinite); // _AgentState = AgentStateMachine.NULL; //} //5. Load all the Node //public void Init4_LoadNeighbour() //{ // _AgentState = AgentStateMachine.INITIAL; // //_TissueConnectionList.Add( // _AgentState = AgentStateMachine.NULL; //} #endregion #region Start the agent, run baby! run!!! private void OnProcessTimer(object AObject) { try { //Scanning the area around current location //if cannot see anything, move sequence followed anticlock wise circle // //If there is nothing running if (_HeartBeat == HeartBeatStatus.LIVE) { jnl_search("Searching Started"); StartSearchProcess(); Thread.Sleep(SolutionConstants.rtTimingInterval_ms); jnl_search("Moving Started"); StartMovingProcess(); //Trigger the Star Run Agent again,in order to start the heart beat again. if (_HeartBeat == HeartBeatStatus.LIVE) { if (mHeartBeatTimer != null) mHeartBeatTimer.Change(SolutionConstants.iniHeartBeatRate_ms, System.Threading.Timeout.Infinite); } } else { jnl_hearbeat("Node:" + _AgentNodeName + "is not active..NodeId:" + _NodeId.ToString()); } } catch (Exception ex) { ex.ToString(); throw ex; } finally { //if (mProcessTimer != null) // mProcessTimer.Change(SolutionConstants.rtTimingInterval_ms, System.Threading.Timeout.Infinite); } } #region Journal override Section private void jnl_moving(string desc) { m_DAL.Morpho_Insert_Journal(JournalType.MOVE.ToString(), desc, _NodeId.ToString()); } private void jnl_search(string desc) { m_DAL.Morpho_Insert_Journal(JournalType.SEARCHING.ToString(), desc, _NodeId.ToString()); } private void jnl_hearbeat(string desc) { m_DAL.Morpho_Insert_Journal(JournalType.HEARTBEAT.ToString(), desc, _NodeId.ToString()); } #endregion public void Start_RunAgent(object sender) { //It is live now!!!!!!!!!!!!!!!!!! _HeartBeat = HeartBeatStatus.LIVE; //Start HearBeat if (mHeartBeatTimer != null) mHeartBeatTimer.Change(SolutionConstants.iniHeartBeatRate_ms, System.Threading.Timeout.Infinite); //When HeartBeat Finished, it will trigger the process timer. //if (mProcessTimer != null) // mProcessTimer.Change(SolutionConstants.rtTimingInterval_ms, System.Threading.Timeout.Infinite); } public void Stop_RunAgent(object sender) { //It is dead now!!!!!!!!!!!!!!!!!! _HeartBeat = HeartBeatStatus.DEAD; //Stop HearBeat if (mHeartBeatTimer != null) mHeartBeatTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); //When HeartBeat Finished, it will trigger the process timer. //if (mProcessTimer != null) // mProcessTimer.Change(SolutionConstants.rtTimingInterval_ms, System.Threading.Timeout.Infinite); } #endregion #region Deactivate/ReActivate the node public void Deactivate_Node() { while (_AgentState == AgentStateMachine.HEARTBEAT) { Thread.Sleep(50); } //1. Update self heart beat status _HeartBeat = HeartBeatStatus.DEAD; //2. Stop Heart Beat if (mHeartBeatTimer != null) mHeartBeatTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite); //3. Update Field self not status m_DAL.Field_Update_Node_HeartBeat_Status(HeartBeatStatus.DEAD, _NodeId); } public void ReActivate_Node() { //1. Update self heart beat status _HeartBeat = HeartBeatStatus.LIVE; //2. Stop Heart Beat if (mHeartBeatTimer != null) mHeartBeatTimer.Change(SolutionConstants.iniHeartBeatRate_ms, System.Threading.Timeout.Infinite); //3. Update Field self not status m_DAL.Field_Update_Node_HeartBeat_Status(HeartBeatStatus.LIVE, _NodeId); } #endregion #region RSSI Returning Section private int GetRSSI(Position zPos) { int zRSSI = SolutionConstants.iniRSSI; if (_RSSIMap != null) { if (_RSSIMap.Count > 0) { if (_RSSIMap.ContainsKey(zPos)) { zRSSI = _RSSIMap[zPos]; } else { zRSSI = SolutionConstants.iniRSSI; } } } return zRSSI; } private void GetCurrPosRSSI() { if (_RSSIMap != null) { if (_RSSIMap.Count > 0) { if (_RSSIMap.ContainsKey(_currPosition)) { _nextRSSI = _RSSIMap[_currPosition]; } else { _nextRSSI = SolutionConstants.iniRSSI; } //Only journal it when RSSI changed. if (_nextRSSI != _currRSSI) { //Journal it m_DAL.Morpho_Insert_Journal(JournalType.RSSI.ToString(), "Agent " + _AgentNodeName + " current RSSI changed from " + _currRSSI.ToString() + " to " + _nextRSSI.ToString(), SolutionConstants.sysadmin); } _currRSSI = _nextRSSI; } } } #endregion #region Search Actions private void StartSearchProcess() { AgentMoveDirection zTagSearchingResult = AgentMoveDirection.UP; if(SearchTagProcess(ref zTagSearchingResult)) { _NextMovingDirection = zTagSearchingResult; } else { AgentMoveDirection zPathSearchResult = AgentMoveDirection.STILL; if (SearchPathProcess(_PreMovingDirection, ref zPathSearchResult)) { if (zPathSearchResult != AgentMoveDirection.STILL) { _NextMovingDirection = zPathSearchResult; } else { _NextMovingDirection = AgentMoveDirection.STILL; } } } } private bool SearchPathProcess(AgentMoveDirection zPreMovingDirection, ref AgentMoveDirection zSuggesedNextMovingDirection) { bool zRet = true; AgentMoveDirection zNextMoveDirection = AgentMoveDirection.STILL; _AgentState = AgentStateMachine.SEARCHING; switch (zPreMovingDirection) { case AgentMoveDirection.UP: zNextMoveDirection = AgentMoveDirection.RIGHT; break; case AgentMoveDirection.DOWN: zNextMoveDirection = AgentMoveDirection.LEFT; break; case AgentMoveDirection.LEFT: zNextMoveDirection = AgentMoveDirection.UP; break; case AgentMoveDirection.RIGHT: zNextMoveDirection = AgentMoveDirection.DOWN; break; default: //Still zNextMoveDirection = AgentMoveDirection.UP; break; } List zSearchRetList = new List(4); zSearchRetList.Add(true);//UP zSearchRetList.Add(true);//DOWN zSearchRetList.Add(true);//RIGHT zSearchRetList.Add(true);//LEFT for (int zInd = 0; zInd <= 3; zInd++) { //If the default next moving location is invalid......the potential next location should be moved on. if (!SearchPath(zNextMoveDirection, _currPosition)) { zRet = false; switch (zNextMoveDirection) { case AgentMoveDirection.UP: zSearchRetList[0] = false;//Tried Up failed zNextMoveDirection = AgentMoveDirection.RIGHT; break; case AgentMoveDirection.DOWN: zSearchRetList[1] = false;//Tried Down failed zNextMoveDirection = AgentMoveDirection.LEFT; break; case AgentMoveDirection.LEFT: zSearchRetList[2] = false;//Tried LEFT failed zNextMoveDirection = AgentMoveDirection.UP; break; case AgentMoveDirection.RIGHT: zSearchRetList[3] = false;//Tried RIGHT failed zNextMoveDirection = AgentMoveDirection.DOWN; break; default: //Still zNextMoveDirection = AgentMoveDirection.UP; break; } } else { zRet = true; zSuggesedNextMovingDirection = zNextMoveDirection; break;//If found the right direction, move on, otherwise continue find the next avaiailbe position, it will find a direction to move //on anyway, it will only take 3 times max....... } } //IF 4 direction all false, force it to go up.Dont worry about repeat postiion. if (!zSearchRetList.Contains(true)) { zNextMoveDirection = AgentMoveDirection.UP; zRet = true; zSuggesedNextMovingDirection = zNextMoveDirection; } _AgentState = AgentStateMachine.NULL; return zRet; } private bool SearchTagProcess(ref AgentMoveDirection zSuggesedNextMovingDirection) { bool zRet = false; _AgentState = AgentStateMachine.SEARCHING; int zReturnRSSI = SolutionConstants.iniRSSI; List zSearchRetList = new List(4); zSearchRetList.Add(true);//UP zSearchRetList.Add(true);//DOWN zSearchRetList.Add(true);//RIGHT zSearchRetList.Add(true);//LEFT for (int zInd = 0; zInd <= 3; zInd++) { //If the default next moving location is invalid......the potential next location should be moved on. if (!SearchTag(zSuggesedNextMovingDirection, _currPosition, ref zReturnRSSI)) { zRet = false; switch (zSuggesedNextMovingDirection) { case AgentMoveDirection.UP: zSearchRetList[0] = false;//Tried Up failed zSuggesedNextMovingDirection = AgentMoveDirection.RIGHT; break; case AgentMoveDirection.DOWN: zSearchRetList[1] = false;//Tried Down failed zSuggesedNextMovingDirection = AgentMoveDirection.LEFT; break; case AgentMoveDirection.LEFT: zSearchRetList[2] = false;//Tried LEFT failed zSuggesedNextMovingDirection = AgentMoveDirection.UP; break; case AgentMoveDirection.RIGHT: zSearchRetList[3] = false;//Tried RIGHT failed zSuggesedNextMovingDirection = AgentMoveDirection.DOWN; break; default: //Still zSuggesedNextMovingDirection = AgentMoveDirection.UP; break; } } else { zRet = true; break;//If found the right direction, move on, otherwise continue find the next avaiailbe position, it will find a direction to move //on anyway, it will only take 3 times max....... } } _AgentState = AgentStateMachine.NULL; return zRet; } /// /// Search one grid around current postion /// /// /// /// /// private bool SearchPath(AgentMoveDirection Direction, Position zPos) { _AgentState = AgentStateMachine.SEARCHING; bool zRet = false; try { Position zSearchPos = zPos; //Move Up if (Direction == AgentMoveDirection.UP) { try { zSearchPos = new Position(zPos._x + 1, zPos._y, SolutionConstants.xMax, SolutionConstants.yMax); } catch (Exception ex) { m_DAL.Morpho_Insert_Journal(JournalType.MOVEWARNING.ToString(), ex.ToString(), _NodeId.ToString()); zRet = false; } } //Move Down else if (Direction == AgentMoveDirection.DOWN) { try { zSearchPos = new Position(zPos._x, zPos._y - 1, SolutionConstants.xMax, SolutionConstants.yMax); } catch (Exception ex) { m_DAL.Morpho_Insert_Journal(JournalType.MOVEWARNING.ToString(), ex.ToString(), _NodeId.ToString()); zRet = false; } } //Move Left else if (Direction == AgentMoveDirection.LEFT) { try { zSearchPos = new Position(zPos._x - 1, zPos._y, SolutionConstants.xMax, SolutionConstants.yMax); } catch (Exception ex) { m_DAL.Morpho_Insert_Journal(JournalType.MOVEWARNING.ToString(), ex.ToString(), _NodeId.ToString()); zRet = false; } } //Move Right else if (Direction == AgentMoveDirection.RIGHT) { try { zSearchPos = new Position(zPos._x, zPos._y + 1, SolutionConstants.xMax, SolutionConstants.yMax); } catch (Exception ex) { m_DAL.Morpho_Insert_Journal(JournalType.MOVEWARNING.ToString(), ex.ToString(), _NodeId.ToString()); zRet = false; } } //If the next searching point has been searched before. if (m_DAL.Path_PathChecking(zSearchPos._x, zSearchPos._y, _NodeId, SolutionConstants.currRunBatch)) { zRet = true; } _AgentState = AgentStateMachine.NULL; } catch (Exception ex) { throw ex; } return zRet; } /// /// Search one grid around current postion /// /// /// /// /// private bool SearchTag(AgentMoveDirection Direction, Position zPos, ref int zPosRSSI) { _AgentState = AgentStateMachine.SEARCHING; bool zRet = false; try { Position zSearchPos = zPos; //Move Right if (Direction == AgentMoveDirection.RIGHT) { zSearchPos = new Position(zPos._x + 1, zPos._y, SolutionConstants.xMax, SolutionConstants.yMax); } //Move Down else if (Direction == AgentMoveDirection.DOWN) { zSearchPos = new Position(zPos._x, zPos._y - 1, SolutionConstants.xMax, SolutionConstants.yMax); } //Move Left else if (Direction == AgentMoveDirection.LEFT) { zSearchPos = new Position(zPos._x - 1, zPos._y, SolutionConstants.xMax, SolutionConstants.yMax); } //Move UP else if (Direction == AgentMoveDirection.UP) { zSearchPos = new Position(zPos._x, zPos._y + 1, SolutionConstants.xMax, SolutionConstants.yMax); } // //If the next searching point has been searched before. //if (m_DAL.Path_PathChecking(zSearchPos._x, zSearchPos._y, _NodeId, SolutionConstants.currRunBatch)) //{ // zRet = false; //} zPosRSSI = GetRSSI(zSearchPos); if (zPosRSSI != SolutionConstants.iniRSSI) { if (zPosRSSI >= _currRSSI) { zRet = true; } } _AgentState = AgentStateMachine.NULL; } catch (Exception ex) { m_DAL.Morpho_Insert_Journal(JournalType.MOVEWARNING.ToString(), ex.ToString(), _NodeId.ToString()); zRet = false; } return zRet; } #endregion #region Moving Actions private void StartMovingProcess() { _AgentState = AgentStateMachine.MOVING; Move(_NextMovingDirection); _PreMovingDirection = _NextMovingDirection; _NextMovingDirection = AgentMoveDirection.STILL; UpdateFieldAgentInform(); AddIntoPathHistory(); _AgentState = AgentStateMachine.NULL; } private void UpdateFieldAgentInform() { m_DAL.Field_Update_Node_Position_Status(_currPosition, _currRSSI, _NodeId); } private void AddIntoPathHistory() { m_DAL.Path_InsertPath(_currPosition._x.ToString(), _currPosition._y.ToString(), _NodeId, SolutionConstants.currRunBatch); } private void Move(AgentMoveDirection Direction) { try { Position zPos = null; //Move Right if (Direction == AgentMoveDirection.RIGHT) { zPos = new Position(_nextPosition._x + 1, _nextPosition._y, SolutionConstants.xMax, SolutionConstants.yMax); } //Move Down else if (Direction == AgentMoveDirection.DOWN) { zPos = new Position(_nextPosition._x, _nextPosition._y - 1, SolutionConstants.xMax, SolutionConstants.yMax); } //Move Left else if (Direction == AgentMoveDirection.LEFT) { zPos = new Position(_nextPosition._x - 1, _nextPosition._y, SolutionConstants.xMax, SolutionConstants.yMax); } //Move Up else if (Direction == AgentMoveDirection.UP) { zPos = new Position(_nextPosition._x, _nextPosition._y + 1, SolutionConstants.xMax, SolutionConstants.yMax); } else { //Stay still...................It should only happen, when it found the tag and no place to move anymore.................. } if (Direction != AgentMoveDirection.STILL) { //Get the curr position _nextPosition = zPos; //Journal it m_DAL.Morpho_Insert_Journal(JournalType.MOVE.ToString(), "Agent " + _AgentNodeName + " moved from " + _currPosition._x.ToString() + "," + _currPosition._y.ToString() + " to " + _nextPosition._x.ToString() + "," + _nextPosition._y.ToString(), _NodeId.ToString()); _currPosition = _nextPosition; //Get the currPositionRSSI ???? GetCurrPosRSSI(); //Update current postion in the Field playground. m_DAL.Field_Update_Node_Position_Status(_currPosition, _currRSSI, _NodeId); } } catch (Exception ex) { m_DAL.Morpho_Insert_Journal(JournalType.MOVEWARNING.ToString(), ex.ToString(), _NodeId.ToString()); //zRet = false; } } #endregion #region Command Receive Sending Section public void CommandReceived(AgentCommands aCmd, AgentNode aFromAgentNode) { } public void SendCommand(AgentCommands aCmd, AgentNode aToAgentNode) { } #endregion #region HeartBeat private void OnHearBeatTimer(object AObject) { _AgentState = AgentStateMachine.HEARTBEAT; try { jnl_hearbeat("HeartBeat Started"); //1. Update self heart beat _HeartBeat = HeartBeatStatus.LIVE; //2. Update Field node HeartStatus in the db m_DAL.Field_Update_Node_HeartBeat_Status(HeartBeatStatus.LIVE, _NodeId); //3. Get the field node list ->Tissue List // this is the simulation, in the future, it would be getting the ip list from the router _TissueList = m_DAL.Field_GetAllNodes(_RSSIMap, _DBStr); //3. Checking Node List - Other Node's Connection Status //4. Check Fields Node List if there is any new node added //5. Get Self Master/Slave Flag _TissueConnectionList.Clear();//Clear current connection status list. if (_TissueList != null) { foreach (AgentNode zAgent in _TissueList) { if (zAgent._NodeId != _NodeId) { //if(zAgent.con //IN THE FUTURE, based on the ip, ping the node, if it response, set the flag if (zAgent._HeartBeat == HeartBeatStatus.LIVE) { _TissueConnectionList.Add(zAgent, true); } else { _TissueConnectionList.Add(zAgent, false); } } else { //Update self Master flag from the _Field decision. _MasterFlag = zAgent._MasterFlag; } } } _AgentState = AgentStateMachine.NULL; } catch (Exception ex) { ex.ToString(); throw ex; } finally { //if (mHeartBeatTimer != null) // mHeartBeatTimer.Change(SolutionConstants.iniHeartBeatRate_ms, System.Threading.Timeout.Infinite); if (mProcessTimer != null) mProcessTimer.Change(SolutionConstants.rtTimingInterval_ms, System.Threading.Timeout.Infinite); } } private void CommunicateWithNode(int NodeId) { //1. Find the Agent From the AgentContactList //2. //3. } #endregion } }