Ja genau das meine ich. Und das die einzelnen Komponenten nicht zu stark untereinander gekoppelt sind.
Druckbare Version
Ja genau das meine ich. Und das die einzelnen Komponenten nicht zu stark untereinander gekoppelt sind.
Ich veröffentliche hier mal mein derzeitiges experimentiermodell:
Es ist wirklich quick and dirty, aber es funktioniert derzeit wie gewollt. Aus einfachheit habe ich alles public gemacht, was im späteren Projekt natürlich nicht mehr sein darf. Auch fehlen noch ein paar essentielle klassen. Mir ist es derzeit nur darum gegangen die kommunikation in die subklassen zu testen, und eine sichere Objektverwaltung zu gewährleisten.Code:/*
* File: SensorHandler.hpp
* Author: pointhi
*
* Created on 26. April 2013, 14:13
*/
#ifndef SENSORHANDLER_HPP
#define SENSORHANDLER_HPP
#include <string>
#include <set>
#include <iostream>
// Achtung, Machbarkeitsanalyse, aus einfachheit mit public-variablen gemacht.
namespace SensorHandler {
class Baseclass { // Basisklasse um gennerelle Variablen und virtuelle Funktionen zu deklarieren
public:
std::string Name; // Variable, die jedes Objekt besitzt
Baseclass() {this->Name = "1234";}
void Output() {std::cout << "Hello Name: " << this->Name << std::endl;}
virtual Baseclass* GetItem(std::string Name) = 0;
virtual Baseclass* GetItem(signed int Id) = 0;
virtual signed int GetItemCount( void ) = 0;
// virtual void NewItem(std::string Name, std::string Type) = 0;
};
namespace Hardware {
class I2c : public SensorHandler::Baseclass {
public:
class Slave : public SensorHandler::Baseclass {
public:
Slave() {this->Name = "testclass";}
Baseclass* GetItem(std::string Name) {return NULL;}
I2c::Slave* GetItem(signed int Id) {return NULL;}
signed int GetItemCount( void ) {return 0;}
// void NewItem(std::string Name, std::string Type=NULL);
};
private:
// std::set<I2c::Slave> SlaveList;
I2c::Slave test; // Kindklasse
public:
I2c() {this->Name = "testtest";}
I2c::Slave* GetItem(std::string Name) {return &this->test;}
I2c::Slave* GetItem(signed int Id) {return &this->test;}
signed int GetItemCount( void ) {return 1;}
// void NewItem(std::string Name, std::string Type=NULL);
};
}
}
#endif /* SENSORHANDLER_HPP */
Als info, damit ihr euch auskennt wie ich mir das derzeit vorstelle:
Gibt einen Pointer auf die nächstfolgede Klasse. So können auch Standardvariablen wie der Name von jeder untergeordneten Klasse aufgerufen werden. In der klasse selber wird nicht die Klasse Baseclass sondern ein darauf aufbauender Typ angegeben. Mit diesem Typ werden auch die Kindelemente in der Klasse gespeichert. So kann diese Klasse auf alle Funktionen der Kindklasse zugreifen, eine allgemeine Funktion die nur durchnavigieren kann und nur auf Standardparameter und funktionen die jede klasse besitzt zugreifen kann. Durch die Spezialisierung wird auch vermieden dass falsche Kindklassen eingebunden werden können. (Z.b. das das I2C-System eine kindklasse von einem I2C-Slave wird.)Code:virtual Baseclass* GetItem(std::string Name) = 0;
virtual Baseclass* GetItem(signed int Id) = 0;
Es wird 2. Zugriffsmethoden geben, eine auf Namen bassierte und eine mit einer Id.
Gibt die Anzahl der Kindklasse zurück, um sauber durchnavigieren zu könnenCode:virtual signed int GetItemCount( void ) = 0;
Erstellt eine neue Kindklasse. Ich dachte vorher dass ich den Typ der Klasse übergebe, hab aber noch keine saubere Funktion dafür gefunden. Ich hab mir derzeit überlegt dass man einen Namen übergibt der den Klassentyp der Kindklasse repräsentiert, wenn es nur 1. Kindklassentyp gibt wird der Wert ignoriert und standardmäßig eine 0 übergeben.Code:virtual void NewItem(std::string Name, std::string Type) = 0;
Ich hoffe ihr kennt euch aus. Besonders das mit NewItem würde ich gerne noch überarbeiten. Was haltet ihr von der allgemeinen Idee, hier geht es derzeit nur darum in der Klasse zu navigieren. Das Dynamische Anlegen von Kindelementen ist z.b. noch nicht ausprobiert, wobei da villeicht eine Templateklasse für die Elementeverarbeitung ins spiel kommt, die von allen anderen Klassen die diese funktion benötigen geerbt wird.
Hier noch ein kleines Testprogramm von mir bezüglich der Navigation:
Es schaut einfach nur ob ich durchnavigieren kann. Die Ausgabe ist die folgende:Code:/*
* File: main.cpp
* Author: pointhi
*
* Created on 26. April 2013, 14:20
*/
#include <cstdlib>
#include <tr1/memory>
#include "SensorHandler.hpp"
using namespace std;
int main(int argc, char** argv) {
std::tr1::shared_ptr<SensorHandler::Baseclass> testClass(new SensorHandler::Hardware::I2c);
testClass->Output();
testClass->GetItem("123")->Output();
return 0;
}
Es zeigt dass beim ersten ->Output die erstellte Klasse angesprochen wird, beim 2. Output aber die aufgerufene kindklasse davon. Ich bin auch noch nicht sicher ob ich villeicht nicht shared_ptr als rückgabetyp geben soll, um speicherlecks und fehlzugriffe zu vermeiden. Ich hab mit diesen Klassen aber noch sehr wenig erfahrung.Code:Hello Name: testtest
Hello Name: testclass
mfg, pointhi
Das experimentiermodell entwickelt sich langsam weiter, erzeugt aber wie erwartet immer neue hürden da ich in einem Bereich programmiere den ich noch nie genutzt habe.
Ich hab mal eine Schematik erstellt die zeigen soll wie ich mir es in etwa vorstelle, wie die abhängikeitsstrukur ausschauen soll:
Anhang 25360
Dabei gibt es eine Basisklasse, die andere Klassen erstellen kann, die wiederum andere Klassen instanzieren können. Ich hab die Farben so gewählt, dass 1. Farbei eine Hauptgruppe ist, wobei nur diese Hauptgruppe von der darunterliegenden Klasse instanziert werden kann.
Dann wie die erzeugte Struktur z.B. so ausschauen könnte:
Anhang 25361
Hier hab ich sozusagen 2. unabhängige I2C-Stränge an denen ein paar I2C-Slaves hängen, und auch eine RS232-Schnittstelle mit Buspartner.
Ich hab mir auch gedanken über die implementierung dieser Struktur in C++ gemacht:
Anhang 25362
Hier hab ich die Implementierung in richtung I2C-Slave gezeichnet. Dieses Diagramm ist nicht mehr ganz simpel, es sollte aber bei richtiger Implementierungen alle benötigten Eigenschaften aufweisen (besonders auch die Typensicherheit). Derzeit hänge ich bei der Implementierung einer Klasse mit dem Namen TreeHandler fest, der die abgehenden Objekte speichern und verwalten soll. Die Klassen wir Hardware werden von der Baseclass abgeleitet, und sorgen dafür dass alle Hardwarerepräsentierend Klassen typenmäßig zusammengefasst werden. Diese Klassen sind rein Virtuell deklariert.
Ich hab auch kurz bei den DesignPatterns gesucht um meinen Entwurf darin zu finden. Ich glaube man kann es unter Abstrakte Fabrik einordnen, bzw. ist es genau so eine.
Wie findet ihr die idee?
Bezügl. der Lizenz werde ich die LGPL nehmen, da ich mit den freizügigeren Lizenzen die ich gefunden habe nicht zufrieden bin. Der Vorteil dafür ist aber auch, dass auch bei kommerziellen Produkten ein neues Datenformat oä. hinzugefügt werden kann.
Es gibt noch mehr gründe, die ich jetzt aber nicht aufliste. Unter anderem muss ein Compiler den C++ Standard unterstützen, und vermutlich auch ein minimal-OS eingesetzt werden (z.B. benötigt man eine Speicherverwaltung und ein Filesystem wenn die hardwarestruktur nicht hardcodiert wird.), wodurch die Bibliotek in den meisten fällen auch dynamisch gelinkt werden kann.
mfg, pointhi
Ich hab heute wieder begonnen weiterzuarbeiten. Vor einiger zeit habe ich das ganze noch einmal neu geschrieben, und jetzt funktioniert auch das ganze arbeiten im Baum fehlerfrei. XML-Dateien werden schon teilweise geparst, und sobald die Daten korrekt geladen sind, und auch I2C angesprochen werden kann, werde ich den neuen Code auf GitHub stellen (ich hab das alte gelöscht, weil es wirklich nicht gut geproggt wurde).
mfg, pointhi
Die erste Alpha-Version rückt immer näher (Lua funktioniert bereits, I2C wird in den nächsten Tagen implementiert).
Code ist hier zu finden: https://github.com/pointhi/OpenSensorSystem, ich hab auch ein kleines Wiki geschrieben, in dem der grundlegende Aufbau der XML und Lua-Dateien beschrieben ist.
Ich würde mich noch immer auf mitentwickler freuen. Sobald das Lua-System ausgereift ist ist es dann besonders einfach mitzuhelfen, indem man Lua-Plugins für bekannte Hardware schreibt (z.B. RN-Hardware, bekannte Portexpander, Sensoren,...). Die Syntax ist nicht sehr schwer.
Ein Ziel wäre es, die Bibliotek + den Lua-Plugins als DebianPaket zur Verfügung zu stellen, um die Nutzung zu vereinfachen. Leider ist mein Wissen im paketbau mehr als mangelhaft.
mfg, pointhi