source: trunk/MagicSoft/Control/SubsystemIO/Subsystem.orig.cxx@ 6522

Last change on this file since 6522 was 1054, checked in by casaldaliga, 23 years ago
changed .H to .hxx in includes to work with new naming
File size: 9.8 KB
Line 
1/* Copyright (C) 2001 Marc Casaldaliga Albisu <casaldaliga@ifae.es>
2================================================================
3
4 This code is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This code is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with Emacs (which is required to make this stuff work); if
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA.
18==================================================================
19*/
20
21//it is a good idea to encapsulate all the configuration file dependence in one a wrapper class SubFormatSubsystem, and derive from it
22//#include "SubFormatSubsystem.hxx"
23#include "Subsystem.hxx"
24#include "PeriodicAction.hxx"
25#include "TCPListener.hxx"
26#include "TCPSender.hxx"
27#include "IONotifier.hxx"
28#include <string>
29//for signals/slots (Callbacks in C++, see http://libsigc.sourceforge.net/)
30#include <sigc++/signal_system.h>
31//libsigc must be installed
32#include <stdio.h>
33using namespace SigC;
34//there's no agreement in maximum lenght message, by now
35
36
37Subsystem::Subsystem (unsigned short int portCommandListener, unsigned long int reportPeriod, char * ccName, unsigned short int portReportListener , unsigned short int maxTimeoutCount_ )
38 :
39 TCPListener(portCommandListener), reportSender(ccName,portReportListener), tryReportConn(reportPeriod), locked(false), reportingLoop(reportPeriod), reporting(false),reportAckNotifier(0),maxTimeoutCount(maxTimeoutCount_)
40 {
41//the behaviour is the following: commandListener has been started as a being derived from TCPListener. When connection from cc is opened commands are processed in this->process()
42//when REPOR arrives reportSender(TCPSender) here tries to connect reportListener in CC. When this happens will start a periodic reporting
43
44
45//tryReportConn is the PeriodicAction which will try periodically reportSender.isTrialToConnectSuccesful ...
46 tryReportConn.DoWhileNot(slot(reportSender, &TCPSender::isTrialToConnectSuccesful) );
47//... and when it is succesfull will start reportingLoop periodic action
48 tryReportConn.FinallyDo(slot(this, &Subsystem::StartReporting));
49//tryReportConn is started when REPOR received (See process())
50
51//reportingLoop is a PeriodicAction which periodically sends the relevant report
52 reportingLoop.DoWhile(slot(this,&Subsystem::SendReport));
53//according the line above, it will be started whe reportSender connection is succesfull
54
55//by now
56//demo report:
57 strcpy(reportString,"standby:11:44:20:11:01:6:34:12:6.0:6.1:6.05:11:01:36:34:12:10.6:6.0:6.0:00:00:30.0:00:00:4.6:0.1:0.05:0.004:0.0:0.001:0.003:guiding:0.1deg:on:3.1Hz:0.09deg:J2000:Mkn421:messagefromthedrive:");
58 pthread_mutex_init(&mutex4report,NULL);
59 pthread_mutex_init(&mutex4ack,NULL);
60 }
61
62void Subsystem::SetReportString(char * report)
63{
64 SuspendComm();
65 strcpy(this->reportString,report);
66 ResumeComm();
67
68}
69
70bool Subsystem::SendSpecialReportContaining(char * specialReport)
71{
72 pthread_mutex_lock(&mutex4ack);
73 if(!acknowledgeReceivedForLastReport){
74 timeoutCount++;
75 if(timeoutCount==maxTimeoutCount){
76 pthread_mutex_unlock(&mutex4ack);
77 return false; //SendReport is not succesfull so this will stop Periodic action
78 }
79 }
80 //before writing the report or sending it make sure no other thread thouches it
81 pthread_mutex_lock(&mutex4report);
82// SubFormatSubsystem::ElaborateReport
83 //calls overriden method GenerateReport that will do the
84 //append the tag for specialReport in this protocol
85 sprintf(this->reportString,"SPECIAL:%s",specialReport);
86
87 //GenerateReport may have filled timestamp. Record it to checkreportacknowledge in future
88
89
90 ExtractTimeStampFromLastReportTo(lastTimeStamp);
91 reportSender.Send(this->reportString);
92 cerr<<"Sending "<<this->reportString<<"\n";
93 pthread_mutex_unlock(&mutex4report);
94
95 acknowledgeReceivedForLastReport=false;
96 pthread_mutex_unlock(&mutex4ack);
97//????????Order mutexes are lock/unlock????????????
98 return true; //if it goes here reporting was succesfull (Used in PeriodicAction reportingLoop)
99}
100
101 inline void Subsystem::StartReporting()
102 {
103 reportingLoop.Start();
104 reportAckNotifier=new IONotifier(reportSender.IODescriptor());
105//after report is sent via reportSender socket, reportListener in CC is sending an acknowledge. The next signal triggers CheckReportAcknowledge when something is received in reportSender channel (suposedly to be this ack)
106 reportAckNotifier->readable.connect(slot(this,&Subsystem::CheckReportAcknowledge));
107 //the first time
108 timeoutCount=0;
109 acknowledgeReceivedForLastReport=true;
110
111 }
112 void Subsystem::ResetConnectionToCC () {
113 if(locked){
114 ULock();
115 }
116 reportingLoop.Stop();
117 reporting=false;
118 delete reportAckNotifier;
119 reportSender.CloseConnection();
120 TCPListener::ClosingChannel(); //but still is waiting for new connections
121 }
122 void Subsystem::process(){
123 if (!locked){
124 if(!reporting){
125//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! pending: compare the whole string, not only the first 5 bytes. strcmp gave problems ???????????????????
126 if ( !strncmp(TCPListener::receivedStream, "REPOR", 5) ) {
127 cerr<<"received REPOR\n";
128 //before startreporting, the connection to cc by reportSender has to be stablished
129 tryReportConn.Start();
130 reporting=true;
131 return;
132 }
133 } else { //already reporting
134 if ( !strncmp(TCPListener::receivedStream,"LOCK!", 5) ) {
135 Lock();
136 return;
137 }
138 }
139
140 } else { //locked
141//as preliminary tests instead of commands, the new subsystem state is sent
142 if (! strncmp(TCPListener::receivedStream, "ULOCK", 5) ) {
143 ULock();
144 return;
145 }
146 cerr<<"processing ... seting new state: "<< TCPListener::receivedStream <<"\n";
147 //calls overriden method thet will process the command itself
148 ProcessCmd(TCPListener::receivedStream);
149
150 //state=receivedStream;
151 return;
152
153 }
154
155//if program reaches here is because it hasn't Received REPOR & LOCK in the proper way. Network partner it's not (a properly working) CC. Closing the opened connection and waiting for new one
156 ResetConnectionToCC();
157 }
158
159bool Subsystem::SendReport () {
160
161 pthread_mutex_lock(&mutex4ack);
162 if(!acknowledgeReceivedForLastReport){
163 timeoutCount++;
164 if(timeoutCount==maxTimeoutCount){
165 pthread_mutex_unlock(&mutex4ack);
166 return false; //SendReport is not succesfull so this will stop Periodic action
167 }
168 }
169 //before writing the report or sending it make sure no other thread thouches it
170 pthread_mutex_lock(&mutex4report);
171// SubFormatSubsystem::ElaborateReport
172 //calls overriden method GenerateReport that will do the
173 GenerateReport();
174 //GenerateReport may have filled timestamp. Record it to checkreportacknowledge in future
175
176
177 ExtractTimeStampFromLastReportTo(lastTimeStamp);
178 reportSender.Send(this->reportString);
179 cerr<<"Sending "<<this->reportString<<"\n";
180 pthread_mutex_unlock(&mutex4report);
181
182 acknowledgeReceivedForLastReport=false;
183 pthread_mutex_unlock(&mutex4ack);
184//????????Order mutexes are lock/unlock????????????
185 return true; //if it goes here reporting was succesfull (Used in PeriodicAction reportingLoop)
186 //acknowledge check is done elsewhere, when it arrives (asynchronously)
187}
188 void Subsystem::CheckReportAcknowledge()
189 {
190 reportSender.Receive();
191
192 pthread_mutex_lock(&mutex4ack);
193//incorporate lastTimeStamp in check
194 if (reportSender.ReturnNew() == "RECV@" ) {
195 acknowledgeReceivedForLastReport=true;
196 timeoutCount=0;
197 }else{
198 cerr<<"wrong ack!\n";
199 }
200 pthread_mutex_unlock(&mutex4ack);
201 }
202
203 void Subsystem::Lock(){
204 cerr<<"Locking to CC mode\n";
205 locked=true;
206 }
207 void Subsystem::ULock(){
208 cerr<<"UNLocking from CC mode\n";
209 locked=false;
210 }
211 void Subsystem::SuspendComm()
212 {
213 pthread_mutex_lock(&mutex4report);
214 };
215 void Subsystem::ResumeComm()
216 {
217 pthread_mutex_unlock(&mutex4report);
218 };
219void Subsystem::ExtractTimeStampFromLastReportTo(char * lastTimeStamp)
220{
221 string report(this->reportString);
222 string::iterator it=report.begin();
223 //point it to the first appearence of :
224 it+=report.find(":");
225
226//cut the first field (between :) which is the status
227 report.erase(report.begin(),it);
228
229//#define TIMESTAMP_LEN 12
230//%02.2d:%02.2d:%02.2d:%03.3d
231 it=report.begin(); //back to the beginning
232 it+=12;
233//cut from the timestamp end to the rest
234 report.erase(it,report.end());
235 strcpy(lastTimeStamp,report.c_str());
236
237}
238
239
240//TO BE OVERRIDEN:
241
242 void Subsystem::ProcessCmd(char *)
243 {};
244 void Subsystem::GenerateReport()
245 {};
246 void Subsystem::HandleConnectionTimeoutIsOver()
247 {};
248
249
Note: See TracBrowser for help on using the repository browser.