Menu

Client.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2008-2010 Michael Schulze <mschulze@ivs.cs.uni-magdeburg.de>
00004  * All rights reserved.
00005  *
00006  *    Redistribution and use in source and binary forms, with or without
00007  *    modification, are permitted provided that the following conditions
00008  *    are met:
00009  *
00010  *    * Redistributions of source code must retain the above copyright
00011  *      notice, this list of conditions and the following disclaimer.
00012  *
00013  *    * Redistributions in binary form must reproduce the above copyright
00014  *      notice, this list of conditions and the following disclaimer in
00015  *      the documentation and/or other materials provided with the
00016  *      distribution.
00017  *
00018  *    * Neither the name of the copyright holders nor the names of
00019  *      contributors may be used to endorse or promote products derived
00020  *      from this software without specific prior written permission.
00021  *
00022  *
00023  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00024  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00025  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00026  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *
00036  * $Id$
00037  *
00038  ******************************************************************************/
00039 
00040 #ifndef __ccp_Client_h__
00041 #define __ccp_Client_h__
00042 
00043 #include "mw/nl/can/constants.h"
00044 #include "mw/nl/can/canETAGS.h"
00045 #include "mw/common/UID.h"
00046 #include "debug.h"
00047 
00048 
00049 namespace famouso {
00050     namespace mw {
00051         namespace nl {
00052             namespace CAN {
00053                 namespace ccp {
00054                     using namespace famouso::mw::nl::CAN::detail;
00055 
00056                     enum {
00057                         CCP_RUNNING = 0,    
00058                         CCP_COMPLETE,       
00059                         CCP_WAIT            
00060                     };
00061 
00062                     //
00063                     // damit der Algorithmus ordentlich funktioniert, ist eine
00064                     // Randbedingung, dass die UID = 0x0 von keinem Knoten
00065                     // verwendet wird.
00066                     //
00067 
00068                     template < class CAN_Driver >
00069                     class Client {
00070                             void debug(char* s) {
00071                             }
00072 
00073                             uint8_t compareUID(const uint8_t *msg, const uint8_t* uid_str, uint8_t stage) {
00074                                 register int8_t count;
00075 
00076                                 for (count = constants::ccp::ccp_stages;count >= stage;--count) {
00077                                     register uint8_t uidPart = (constants::ccp::ccp_stages - count) >> 1;
00078                                     register uint8_t uidNibble = (count % 2) ? (uid_str[uidPart] >> 4) : (uid_str[uidPart] & 0xf);
00079                                     register uint8_t msgNibble = (count % 2) ? (msg[uidPart] >> 4) : (msg[uidPart] & 0xf);
00080                                     if (uidNibble != msgNibble) {
00081                                         return 0;
00082                                     }
00083                                 }
00084                                 return 1;
00085                             }
00086 
00087                         public:
00088 
00089                             typedef typename CAN_Driver::MOB::IDType IDType;
00090 
00091                             uint8_t ccp_configure_tx_node(const UID &uid, CAN_Driver& canDriver) {
00092                                 const uint8_t *uid_str = uid.tab();
00093                                 typename CAN_Driver::MOB msg;
00094                                 msg.extended();
00095 
00096                                 IDType *id = &msg.id();
00097                                 uint8_t ccp_status;
00098                                 uint8_t ccp_stage;
00099                                 uint8_t tx_node;
00100                                 int8_t stage;
00101 
00102                                 uint8_t zeros[8] = {0};
00103 
00104                                 ccp_status = CCP_RUNNING;
00105                                 ccp_stage = 0;
00106 
00107                                 // Anzahl der durchzufuehrenden Stages
00108                                 stage = constants::ccp::ccp_stages;
00109                                 do {
00110                                     // erzeuge die entsprechende ID
00111                                     register uint8_t uidPart = (constants::ccp::ccp_stages - stage) >> 1;
00112                                     register uint8_t uidNibble = (stage % 2) ? (uid_str[uidPart] >> 4) :
00113                                                                  (uid_str[uidPart] & 0xf);
00114 
00115                                     // 0xFD is non-real-time
00117                                     id->prio(0xFD);
00118                                     id->ccp_stage(stage);
00119                                     id->ccp_nibble(uidNibble);
00120 
00121                                     id->etag(famouso::mw::nl::CAN::detail::ETAGS::CCP_RSI);
00122 
00123                                     msg.len(0);
00124 
00125                                     // Nachricht senden
00126                                     canDriver.transmit(msg);
00127 
00128                                     ccp_status = CCP_WAIT;
00129 
00130                                     do {
00131                                         // und auf Antwort warten
00132                                         do {
00133                                             canDriver.receive_blocking(&msg);
00134                                             // Ist die Nachricht ein Konfigurationsantwort
00135                                         } while (id->etag() != famouso::mw::nl::CAN::detail::ETAGS::CCP_SSI);
00136 
00137                                         // extrahiere die KnotenID
00138                                         tx_node = id->tx_node();
00139                                         // ja, also laufen wir erstmal weiter
00140                                         ccp_status = CCP_RUNNING;
00141                                         // ist dies eine Brokernachricht mit Stagezaehler im letzten Datenbyte der Nachricht
00142                                         // wird angezeigt durch die knotenID == BrokerID == 0x7f
00143                                         if (tx_node == constants::Broker_tx_node) {
00144                                             // ist ein knoten vielleicht ausgestiegen, dann generiert der Broker
00145                                             // eine Nachricht mit leerem Inhalt, um unselektierte Knoten zur
00146                                             // Neukonfiguration zu bewegen
00147                                             if (compareUID(msg.data(), zeros, 0)) {
00148                                                 stage = constants::ccp::ccp_stages;
00149                                             } else {
00150                                                 if ((stage == (msg.data()[7] & 0xf)) && compareUID(msg.data(), uid_str, stage)) {
00151                                                     // gehe in den naechsten Zyklus
00152                                                     --stage;
00153                                                 } else {
00154                                                     ccp_status = CCP_WAIT;
00155                                                 }
00156                                             }
00157 
00158                                         } else {
00159                                             // die BrokerNachricht enthaelt keinen Stagezaehler mehr, dafuer aber eine
00160                                             // konfigurierte KnotenID, weil sich mindestens ein Knoten in Stage 0 befindet
00161                                             // dies koennte ich sein. Einfach mal die uid mit den Daten vergleichen
00162 
00163                                             // untersuche Nachrichteninhalt auf Gleichheit mit eigener ID
00164                                             // wenn ja, extrahierte txnode ist meine
00165                                             // verlasse beide Schleifen da stage==0 und ccp_status==CCP_RUNNING
00166                                             if (compareUID(msg.data(), uid_str, 0)) {
00167                                                 ::logging::log::emit< ::logging::Trace>()
00168                                                     << PROGMEMSTRING("It is my knot ID")
00169                                                     << ::logging::log::endl;
00170                                                 ccp_stage = CCP_COMPLETE;
00171                                             } else {
00172                                                 // wenn nein einfach von vorn
00173                                                 // und gehe in die aeussere Schleife weil ccp_status==CCP_RUNNING
00174                                                 // und setze stage wieder auf den initialen Wert
00175                                                 ::logging::log::emit< ::logging::Trace>()
00176                                                     << PROGMEMSTRING("It is not my knot ID")
00177                                                     << ::logging::log::endl;
00178                                                 stage = constants::ccp::ccp_stages;
00179                                             }
00180                                         }
00181                                     } while ((ccp_status != CCP_RUNNING));
00182                                 } while ((ccp_stage != CCP_COMPLETE));
00183                                 // Konfiguration erfolgreich und KnotenID erhalten
00184                                 return tx_node;
00185                             }
00186 
00187                             bool handle_ccp_configure_request(typename CAN_Driver::MOB&, CAN_Driver&) {
00188                                 return false;
00189                             };
00190                     };
00191                 }
00192             } /* namespace CAN */
00193         } /* namespace nl */
00194     } /* namespace mw */
00195 } /* namespace famouso */
00196 
00197 
00198 #endif