HWObject

HWObject ist die Basisklasse für ein Hardware-Objekt. Über diese Klasse kommuniziert der Allgemeine Treiber mit dem hardwarespezifischen Teil. Wird eine eigene Hardware-Adresse benötigt (über den Peripherie-Adress-String hinaus), dann muss von dieser Klasse ein erweitertes Objekt abgeleitet werden. Generiert z.B. der Modbus eine spontane Benachrichtigung, so erzeugt das HWService-Objekt des Modbus -Treibers ein (Modbus-spezifisches) HWObject und übergibt dieses der toDp(...) Funktion des DrvManagers. Umgekehrt, versucht ein Benutzer einen Wert an der Peripherie zu setzen, wird der Treiber vom Eventmanager über einen HotLink benachrichtigt. Der in diesem HotLink enthaltene Wert wird vom Treiber umgerechnet, ein HWObject erzeugt, der umgerechnete Wert in ein HW-spezifisches Datum transformiert und dem HWService-Objekt übergeben. Eine Hardware-Adresse wird dadurch implementiert, dass vom HWObject ein neues Objekt abgeleitet wird, welches die zusätzlichen Attribute für die Hardware-Adresse enthält (beim Modbus z.B. Kommunikationsreferenz (kr) und Index (ix)). Weiters sollten die Vergleichsfunktionen des abgeleiteten HWMapper den Hardware-Adressen des abgeleiteten HWObject angepasst werden.

Das HWObject enthält einen Zeiger auf einen Datenbuffer, in dem die Daten der Peripherie gespeichert werden, ein Attribut dataLen, das die Größe dieses Buffer in Bytes angibt, einen Adressstring, welcher der im Peripherieadresskonfig angegebenen Adresse entspricht. Das Attribut transType enthält die Nummer der Transformation, die diesem HWObject zugeordnet ist, in originTime kann dem Objekt eine Zeitbeigabe zugewiesen werden (die aktuelle Zeit, wenn bei Eintreffen der Daten keine eigene Quellzeit mitgeliefert wurde). Dem objSrcType kann eine der folgenden Datenarten zugeordnet werden: srcSpont für spontan eintreffende Daten, srcPolled für Daten, die durch polling gewonnen wurden, srcSingleQ für Daten, die Ergebnis einer Einzelabfrage sind, und schließlich srcGeneralQ für Daten, die bei einer Generalabfrage geschickt wurden. Diese Datenarten werden unter anderem bei der Behandlung der Glättung (Glättungsmodus) verwendet.

Für alle Attribute gibt es die entsprechenden setxxx- und getxxx-Methoden. Um die Informationen, für die sich der Treiber beim Eventmanager zusätzlich zum Originalwert angemeldet hat, im HWObject zu speichern, dient die virtuelle Methode setAdditionalData(const RecVar &data, subix) des HWObject, die als ersten Parameter die Daten enthält und als zweiten den Subindex des betreffenden Datenpunktelements. Soll beispielsweise bei Feldern das Invalidbit im HWObject immer dann gesetzt werden, wenn mindestens ein Datenpunktelement invalid gesetzt ist, sollte die Funktion folgendermaßen abgeleitet werden:

void setAdditionalData( const RecVar &data, subix)
{
  if (data.getRecLength() ) // Zusatzinformation existiert
  {
    int flags = ( (UIntegerVar *)data.getFirstVar() )->getValue();
    // die erste Variable enthält die Flags, die angeben, welche Informationen geschickt wurden
    if ( flags & DrvManager::DRVCONNMODE_TIME )
    {
      data.getNextVar();
    } // ignoriere Zeit
    if ( flags & DrvManager::DRVCONNMODE_GA )
    { data.getNextVar(); } // ignoriere GA-Bit
    if ( flags & DrvManager::DRVCONNMODE_EA )
    { data.getNextVar(); } // ignoriere EA-Bit
    if ( flags & DrvManager::DRVCONNMODE_INVALID )
    { 
      if ( (! getSbit(DRV_INVALID)) && (((BitVar *)data.getNextVar())->getValue()))
      setSbit(DRV_INVALID);
    } // oder-Verknüpfung der invalid-Bits, Funktion wird für jeden Subindex extra aufgerufen
    ...
    // ignoriere User-Bits
  }
}

Es ist zu beachten, dass im ersten Eintrag von RecVar ein Bitmuster (in einer Variable vom Typ UIntegerVar) steht, das angibt, welche Informationen verschickt wurden, daher muss sequentiell für jedes gesetzte Bit die nächste Variable (getNextVar()) ausgewertet werden, selbst wenn sie (wie oben) dann nicht weiterverwendet wird (außer dem Invalidbit im Beispiel). Da sich der Treiber beim Eventmanager auf Grund des Peripherieadresskonfigs aber nur für "interessante" Informationen anmelden sollte (mittels der Methode getAttribs2Connect(..) des DrvManager), sollten auch hier in der RecVar nur die relevanten Flags gesetzt sein (also das Invalidbit im Beispiel). Es könnte z.B. eine entsprechende Fehlermeldung ausgegeben werden, falls zusätzliche Informationen in RecVar entdeckt wurden.

Hinweis

Beachten Sie, dass cutData() verwendet werden muss, um alte Daten aus einem Objekt zu löschen, wenn man nicht will, dass der Datenzeiger im Objekt durch ein neues setData oder beim Löschen des Objektes, gelöscht werden soll. Also z.B.:

int myFunc ()
{
  PVSSchar buffer[10];
  // filling buffer with data
  HWObject obj;
  obj.setData(buffer);
  ...//any processing
  obj.cutData() // avoid deletion of buffer, because it is an automatic
  // variable allocated on the stack
}

In diesem Beispiel muss cutData() verwendet werden, weil bei dem Destruktor vom HWObject der alte Datenzeiger gelöscht wird wenn dieser !=NULL ist. Das passiert nicht, wenn vorher ein cutData() verwendet wird. cutData() setzt den internen Datenzeiger im HWObject auf NULL und liefert den Zeigerwert zurück, gibt aber keinen Speicher frei (im Destruktor des HWObjects wird dann kein Datenzeiger gelöscht da der Wert NULL ist.) Der Speicher muss selbst freigeben werden.