MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Instruments/Ocean/iRelay/RelayBoard.cpp
Go to the documentation of this file.
00001 
00002 //
00003 //   MOOS - Mission Oriented Operating Suite 
00004 //  
00005 //   A suit of Applications and Libraries for Mobile Robotics Research 
00006 //   Copyright (C) 2001-2005 Massachusetts Institute of Technology and 
00007 //   Oxford University. 
00008 //    
00009 //   This software was written by Paul Newman and others
00010 //   at MIT 2001-2002 and Oxford University 2003-2005.
00011 //   email: pnewman@robots.ox.ac.uk. 
00012 //      
00013 //   This file is part of a  MOOS Instrument. 
00014 //        
00015 //   This program is free software; you can redistribute it and/or 
00016 //   modify it under the terms of the GNU General Public License as 
00017 //   published by the Free Software Foundation; either version 2 of the 
00018 //   License, or (at your option) any later version. 
00019 //          
00020 //   This program is distributed in the hope that it will be useful, 
00021 //   but WITHOUT ANY WARRANTY; without even the implied warranty of 
00022 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
00023 //   General Public License for more details. 
00024 //            
00025 //   You should have received a copy of the GNU General Public License 
00026 //   along with this program; if not, write to the Free Software 
00027 //   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
00028 //   02111-1307, USA. 
00029 //
00031 // RelayBoard.cpp: implementation of the CRelayBoard class.
00032 //
00034 #include <MOOSLIB/MOOSLib.h>
00035 #include <iostream>
00036 using namespace std;
00037 
00038 #include "RelayBoard.h"
00039 
00041 // Construction/Destruction
00043 
00044 CRelayBoard::CRelayBoard()
00045 {
00046     //some sensible defaults (missionfile can overwrite this)
00047     SetAppFreq(1);
00048     SetCommsFreq(5);
00049 
00050     //state strings
00051     m_sRECORDING    = "RECORDING";
00052     m_sSTOPPED      = "STOPPED";
00053     m_sRECORD       = "RECORD";
00054     m_sSTOP         = "STOP";
00055     m_sLIGHT        = "LIGHT";
00056     m_sDARK         = "DARK";
00057     m_sON           = "ON";
00058     m_sOFF          = "OFF";
00059     m_sVCR_POWER    = "VCR_POWER";
00060     m_sCAMERA_POWER = "CAMERA_POWER";
00061     m_sBOARD_POWER  = "BOARD_POWER";
00062     m_sLIGHT_POWER  = "LIGHT_POWER";
00063 
00064     m_RelayToggleMap[m_sCAMERA_POWER] = RELAY0_TOGGLE;
00065     m_RelayToggleMap[m_sVCR_POWER]    = RELAY1_TOGGLE;
00066     m_RelayToggleMap[m_sLIGHT_POWER]  = RELAY2_TOGGLE;
00067     m_RelayToggleMap[m_sRECORD]       = RELAY3_TOGGLE;
00068     m_RelayToggleMap[m_sBOARD_POWER]  = RELAY7_TOGGLE;
00069 
00070     m_RelayCheckMap[m_sCAMERA_POWER] = RELAY0;
00071     m_RelayCheckMap[m_sVCR_POWER]    = RELAY1;
00072     m_RelayCheckMap[m_sLIGHT_POWER]  = RELAY2;
00073     m_RelayCheckMap[m_sRECORD]       = RELAY3;
00074     m_RelayCheckMap[m_sBOARD_POWER]  = RELAY7;
00075 
00076     m_InputNameMap[m_sRECORDING]    = INPUT3;
00077 }
00078 
00079 CRelayBoard::~CRelayBoard()
00080 {
00081     Stop();
00082     ToggleRelaySwitch(m_sLIGHT_POWER, m_sOFF);
00083 
00084 }
00085 
00086 
00089 bool CRelayBoard::Iterate()
00090 {
00091 
00092     if(GetData())
00093     {
00094         PublishData();
00095     }
00096 
00097     return true;
00098 }
00099 
00100 
00101 bool CRelayBoard::OnStartUp()
00102 {
00103     CMOOSInstrument::OnStartUp();
00104     //here we make the variables that we are managing
00105     double dfRelayPeriod = 1.0;
00106     
00107     //Register for the variable that will provide for dynamic configuration
00108     //of the Relay board
00109     //This version of the iRelay only corresponds to the Video System
00110     //the video system states
00111     AddMOOSVariable("VIDEO_STATUS", "RELAY_VIDEO_UPDATE",  "RELAY_VIDEO_REPLY", dfRelayPeriod);
00112     AddMOOSVariable("RELAY_STATUS", "RELAY_UPDATE",        "RELAY_UPDATE_REPLY",dfRelayPeriod);
00113     
00114 
00115     RegisterMOOSVariables();
00116 
00117     if(IsSimulateMode())
00118     {
00119         SetAppFreq(2);
00120         SetCommsFreq(2);
00121     }
00122     else
00123     {
00124         //try to open 
00125         if(!SetupPort())
00126         {
00127             return false;
00128         }
00129         
00130         //try 10 times to initialise sensor
00131         if(!InitialiseSensorN(10,"RELAY"))
00132         {
00133             return false;
00134         }          
00135 
00136     }
00137     return true;
00138 }
00139 
00140 
00141 
00142 bool CRelayBoard::OnNewMail(MOOSMSG_LIST &NewMail)
00143 {
00144     CMOOSMsg Msg;
00145     double dfTimeNow = MOOSTime();
00146     string sVal;
00147 
00148     if(m_Comms.PeekMail(NewMail,"RELAY_VIDEO_UPDATE",Msg))
00149     {
00150         sVal = Msg.m_sVal;
00151         MOOSTrace("..............new : %s\n", sVal.c_str());
00152         if(sVal == m_sRECORD)
00153             return Record();
00154         else if(sVal == m_sSTOP)
00155                return Stop();
00156         else if(sVal == m_sLIGHT)
00157                return ToggleRelaySwitch(m_sLIGHT_POWER, m_sON);
00158         else if(sVal == m_sDARK)
00159                return ToggleRelaySwitch(m_sLIGHT_POWER, m_sOFF);
00160         else
00161             return true;
00162     }
00163     else if(m_Comms.PeekMail(NewMail,"RELAY_UPDATE",Msg))
00164     {
00165         return UpdateRelay(Msg);
00166     }
00167 
00168     else
00169     {
00170         return UpdateMOOSVariables(NewMail);
00171     }
00172 }
00173 
00174 bool CRelayBoard::PublishData()
00175 {  
00176     return PublishFreshMOOSVariables();
00177 }
00178 
00179 
00180 
00181 bool CRelayBoard::OnConnectToServer()
00182 {
00183     if(IsSimulateMode())
00184     {
00185         RegisterMOOSVariables();
00186     }
00187     return true;
00188 }
00189 
00190 
00192 // here we initialise the sensor, giving it start up values
00193 bool CRelayBoard::InitialiseSensor()
00194 {   
00195     return ToggleRelaySwitch(m_sBOARD_POWER, m_sON);
00196 }
00197 
00198 
00199 
00200 bool CRelayBoard::GetData()
00201 {
00202     if(!IsSimulateMode())
00203     {
00204         //   string sStatus;
00205         //we will publish the state of the relays
00206         // RELAY_FUNCTION_2_CHECK_MAP::iterator p;
00207         //for(p = m_RelayCheckMap.begin(); p != m_RelayCheckMap.end(); p++)
00208         //{
00209         //    string sRelay = p->first.c_str();
00210         //    sStatus += sRelay + (IsPowered(sRelay) ? ": true " : ": false ");
00211         //}
00212         //alert the DB
00213         //SetMOOSVar("RELAY_STATUS", sStatus, MOOSTime());
00214 
00215     }
00216     else
00217     {
00218         //in simulated mode there is nothing to do..all data
00219         //arrives via comms.
00220     }
00221 
00222     return true;
00223 
00224 }
00225 
00226 bool CRelayBoard::SetRelayHi(short val)
00227 {
00228     string sRelay = "MK";
00229     short MASK;
00230     char pChar[4];
00231     
00232     //should check the range of val
00233     if(val>255 || val < 0)
00234     {
00235         MOOSTrace("Acceptable Relay range 0-255\n");
00236         return false;
00237     }
00238     else
00239     {
00240         //we need to make a mask out of what the state of the RelayBoard
00241         //already is so that we do not shut off relays in the process of
00242         //trying to turn only a specific one on
00243         short nState = (short)CheckAllRelayStates();
00244         MASK = nState | val;
00245         
00246         //make note of this value we are writing
00247         sprintf(pChar, "%d\r", MASK);
00248          //The format for setting the relay is MKddd
00249         //where 'ddd' corresponds to the 3 characters in a 0-255 value short
00250         sRelay += pChar;
00251         //write the new command
00252         m_Port.Write((char *)sRelay.c_str(), sRelay.size());
00253     }
00254    
00255     
00256     return true;
00257 }
00258 
00264 int CRelayBoard::CheckRelayState(short val)
00265 {
00266     string sRelay = "RPK";
00267     string sReply;
00268     double dfWhen = 0.5;
00269     char pChar[4];
00270     
00271     //should check the range of val
00272     if(val > 7 || val < 0)
00273     {
00274         MOOSTrace("Acceptable Relay range 0-7\n");
00275         return -1;
00276     }
00277     else
00278     {
00279         //make note of this value we are writing
00280         sprintf(pChar,"%d\r",val);
00281          //The format for setting the relay is MKddd
00282         //where 'ddd' corresponds to the 3 characters in a 0-255 value short
00283         sRelay += pChar;
00284         //write the new command
00285         m_Port.Write((char *)sRelay.c_str(), sRelay.size());
00286 
00287         while(!m_Port.GetTelegram(sReply,dfWhen))
00288         {
00289             MOOSPause(10);
00290         }
00291         
00292         short nRet = (short)atof(sReply.c_str());
00293 
00294         if(m_Port.IsVerbose())
00295         {
00296             MOOSTrace("checked: %d and found its state to be: %d\n", val, nRet);
00297         }
00298 
00299         return nRet;
00300     }
00301    
00302 }
00303 
00306 int CRelayBoard::CheckInputState(short val)
00307 {
00308     string sRelay = "RPA";
00309     string sReply;
00310     double dfWhen = 0.5;
00311     char pChar[4];
00312     
00313     //should check the range of val
00314     if(val > 3 || val < 0)
00315     {
00316         MOOSTrace("Acceptable Input range 0-3\n");
00317         return -1;
00318     }
00319     else
00320     {
00321         //the relay needs 0.5 seconds to make the state change
00322         MOOSPause(5000);
00323         //make note of this value we are writing
00324         sprintf(pChar,"%d\r",val);
00325         sRelay += pChar;
00326         //write the new command
00327         m_Port.Write((char *)sRelay.c_str(), sRelay.size());
00328 
00329         while(!m_Port.GetTelegram(sReply,dfWhen))
00330         {
00331             MOOSPause(10);
00332         }
00333         
00334         short nRet = (short)atof(sReply.c_str());
00335 
00336         if(m_Port.IsVerbose())
00337         {
00338             MOOSTrace("checked input: %d and found its state to be: %d\n", val, nRet);
00339         }
00340 
00341         return nRet;
00342     }
00343     
00344 }
00345 
00347 bool CRelayBoard::Record()
00348 {
00349     int nInputToMonitor = -1;
00350 
00351     INPUT_NAME_2_INT_MAP::iterator p = m_InputNameMap.find(m_sRECORDING);
00352     if(p != m_InputNameMap.end())
00353     {
00354         nInputToMonitor = p->second;
00355         MOOSTrace("[REC]Looking for %d\n", nInputToMonitor);
00356     }
00357     else
00358     {
00359         MOOSTrace("You have entered an incorrect Input Name[REC]\n");
00360         return false;
00361     }
00362 
00363     //make sure the relay board has power
00364     //and then turn on the VCR and CAMERA
00365     ToggleRelaySwitch(m_sBOARD_POWER, m_sON);
00366     ToggleRelaySwitch(m_sVCR_POWER, m_sON);
00367     ToggleRelaySwitch(m_sCAMERA_POWER, m_sON);
00368     ToggleRelaySwitch(m_sRECORD, m_sON);       
00369 
00370     if(CheckInputState(nInputToMonitor) == LO)
00371     {
00372         SetMOOSVar("VIDEO_STATUS", m_sRECORDING,MOOSTime());
00373         return true;
00374     }
00375     else
00376     {
00377         string sProblem = m_sRECORDING + ": FAILED";
00378         SetMOOSVar("VIDEO_STATUS", sProblem,MOOSTime());
00379         return false;
00380     }
00381 }
00382 
00383 bool CRelayBoard::Stop()
00384 {
00385     int nInputToMonitor = -1;
00386 
00387     INPUT_NAME_2_INT_MAP::iterator p = m_InputNameMap.find(m_sRECORDING);
00388     if(p != m_InputNameMap.end())
00389     {
00390         nInputToMonitor = p->second;
00391         MOOSTrace("[STOP]Looking for %d\n", nInputToMonitor);
00392     }
00393     else
00394     {
00395         MOOSTrace("You have entered an incorrect Input Name[STOP]\n");
00396         return false;
00397     }
00398 
00399     ToggleRelaySwitch(m_sRECORD, m_sOFF);       
00400     ToggleRelaySwitch(m_sCAMERA_POWER, m_sOFF);
00401     ToggleRelaySwitch(m_sVCR_POWER, m_sOFF);
00402     
00403     if(CheckInputState(nInputToMonitor) == HI)
00404     {
00405         SetMOOSVar("VIDEO_STATUS", m_sSTOPPED, MOOSTime());
00406         return true;
00407     }
00408     else
00409     {
00410         string sProblem = m_sSTOPPED + ": FAILED";
00411         SetMOOSVar("VIDEO_STATUS", sProblem,MOOSTime());
00412         return false;
00413     }
00414 
00415 }
00416 
00417 
00418 bool CRelayBoard::UpdateRelay(CMOOSMsg &Msg)
00419 {
00420     string sNewRelayStates = Msg.m_sVal;
00421     string sMOOSChompResult = MOOSChomp(sNewRelayStates, ",");
00422     string sStatus;
00423        
00424     while(!sMOOSChompResult.empty())
00425     {
00426         string sRelay = MOOSChomp(sMOOSChompResult,":");
00427         string sState = sMOOSChompResult;
00428         if(ToggleRelaySwitch(sRelay,sState))
00429         {
00430             sStatus += sRelay + ": OK ";
00431         }
00432         else
00433         {
00434             sStatus += sRelay + ": FAIL ";
00435         }
00436         MOOSTrace("sRelay: %s sState: %s",sRelay.c_str(),sState.c_str());
00437 
00438         sMOOSChompResult = MOOSChomp(sNewRelayStates, ",");
00439     }
00440 
00441     //SetMOOSVar("RELAY_STATUS", sStatus, MOOSTime());
00442      MOOSTrace("sStatus: %s ", sStatus.c_str());
00443     return true;
00444     
00445 }
00446 
00447 
00451 bool CRelayBoard::ToggleRelaySwitch(string sRelay, string sDesiredState)
00452 {
00453     int nRelayToSwitch = -1;
00454     //we know we are talking to the relay board's power switch
00455     RELAY_FUNCTION_2_TOGGLE_MAP::iterator p = m_RelayToggleMap.find(sRelay);
00456     if(p != m_RelayToggleMap.end())
00457     {
00458         nRelayToSwitch = p->second;
00459         MOOSTrace("[TBP]Toggling %d\n", nRelayToSwitch);
00460     }
00461     else
00462     {
00463         MOOSTrace("You have entered an incorrect Relay Name[TBP]\n");
00464         return false;
00465     }
00466 
00467     if(sDesiredState == m_sON)
00468     {
00469         if(!IsPowered(sRelay))
00470         {
00471            SetRelayHi(nRelayToSwitch);
00472         }
00473     }
00474     else if(sDesiredState == m_sOFF)
00475     {
00476         if(IsPowered(sRelay))
00477         {
00478            SetRelayLo(nRelayToSwitch);
00479         }
00480         
00481     }
00482     
00483     return ShowRelayBoardStatus();
00484 }
00485 
00489 bool CRelayBoard::IsPowered(string sRelay)
00490 {
00491     //figure out what relay we are trying to query
00492     int nRelayToCheck = -1;
00493     RELAY_FUNCTION_2_CHECK_MAP::iterator p = m_RelayCheckMap.find(sRelay);
00494    
00495     if(p != m_RelayCheckMap.end())
00496     {
00497         nRelayToCheck = p->second;
00498 
00499         if(m_Port.IsVerbose())
00500         {
00501              MOOSTrace("[IP]checking relay: %d\n", nRelayToCheck);
00502         }
00503     
00504     }
00505 
00506     
00507     return (CheckRelayState(nRelayToCheck) == HI);
00508 }
00509 
00510 bool CRelayBoard::SetRelayLo(short val)
00511 {
00512     string sRelay = "MK";
00513     short MASK;
00514     char pChar[4];
00515     
00516     //should check the range of val
00517     if(val>255 || val < 0)
00518     {
00519         MOOSTrace("Acceptable Relay range 0-255\n");
00520         return false;
00521     }
00522     else
00523     {
00524         //we need to make a mask out of what the state of the RelayBoard
00525         //already is so that we do not shut off relays in the process of
00526         //trying to turn only a specific one off
00527         short nState = (short)CheckAllRelayStates();
00528         MASK = nState & ~val;
00529         
00530         //make note of this value we are writing
00531         sprintf(pChar, "%d\r", MASK);
00532          //The format for setting the relay is MKddd
00533         //where 'ddd' corresponds to the 3 characters in a 0-255 value short
00534         sRelay += pChar;
00535         //write the new command
00536         m_Port.Write((char *)sRelay.c_str(), sRelay.size());
00537     }
00538    
00539     
00540     return true;
00541     
00542 }
00543 
00546 int CRelayBoard::CheckAllRelayStates()
00547 {
00548     string sRelay = "PK\r";
00549     string sReply;
00550     double dfWhen = 1.0;
00551     
00552     //write the status command
00553     
00554     m_Port.Write((char *)sRelay.c_str(), sRelay.size());
00555 
00556     while(!m_Port.GetTelegram(sReply,dfWhen))
00557     {
00558         MOOSPause(10);
00559     }
00560 
00561     short nRet = (short)atof(sReply.c_str());
00562 
00563     if(m_Port.IsVerbose())
00564     {
00565         MOOSTrace("status of ALL relays: %d\n", nRet);
00566     }
00567 
00568     return nRet;
00569 
00570 }
00571 
00572 bool CRelayBoard::ShowRelayBoardStatus()
00573 {
00574     
00575     string sStatus;
00576     //we will publish the state of the relays
00577     RELAY_FUNCTION_2_CHECK_MAP::iterator p;
00578     for(p = m_RelayCheckMap.begin(); p != m_RelayCheckMap.end(); p++)
00579     {
00580         string sRelay = p->first.c_str();
00581         sStatus += sRelay + (IsPowered(sRelay) ? ": ON " : ": OFF ");
00582     }
00583     //alert the DB
00584     SetMOOSVar("RELAY_STATUS", sStatus, MOOSTime());
00585 
00586     return true;
00587 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines