Interface mehrere Instanzen übergeben

OOP

Level-1
Beiträge
49
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich nutze Codesys V33.5.9.x.

Ich würde gerne wie man es aus Hochsprachen gewohnt ist aus einem Baustein (Klasse) heraus ein Event senden.
Ich habe hierzu dem Baustein ein Interface als Eingang spendiert.
Diesem weise ich eine Instanz eines anderen Bausteins zu, in welcher dann die entsprechende Interfacemethode quasi das "Event" ausführt.

Nun habe ich 2 Fragen / Wünsche.

1. Das Interface hat 4 Methoden (4 Events).
Nicht jeder Baustein hat jedes Event. Benötige ich also mehrere Interface? Oder muss ich diese Kaskadieren?

2. Bspw. in C# kann ich ja jedem Event mehrere Methoden zuweisen, welche dann aufgerufen werden.
Geht so etwas auch irgendwie, oder müsste ich es mir selbst bauen? Bspw. durch ein Array von Interfaces?

Danke für euren Rat.
 
Du kannst ein Basisinterface deklarieren, das die Methoden aufführt, die jeder der Eventbausteine hat und so eins als FB-Input verwenden. Diesem Interface kannst Du dann ja auch Bausteine zuweisen, die vom Basisinterface abgeleitete umfangreichere Interfaces implementieren. In dem FB, der den Event-FB aufrufen soll, kannst Du dann mit der Funktion __QUERYINTERFACE das Input-Basisinterface in ein
erweitertes Interface konvertieren, sofern der Event-FB, auf den das Input-Interface zeigt, auch tatsächlich das erweiterte Interface implementiert. Dazu müssen die Interfaces vom Typ __System.IQueryInterface abgeleitet sein. Ich mache so etwas mit Beckhoff TwinCat, gehe aber davon aus, dass es keine Beckhoff-spezifische Funktionalität ist, sondern CoDeSys das von Haus aus mitbringt.
 
Und ich dachte, dieses SPS-Forum sei ein ...

... für SPS-Programmierer ...

Ich weiss nicht, was der TE konkret vorhat. Ich selbst lehne den Einsatz solch böser Programmierung für die eigentliche Steuerungsfunktion ab, sondern mache so was nur beim Drumherum wie der Visualisierung. Ich habe ein Meldungs-Logsystem, das Meldungen in einem Binärformat absetzt, um die Steuerungstasks nicht allzu sehr damit zu belasten. Eine langsamere Hintergrundtask muss dann zusehen, dass sie daraus Textmeldungen macht. Früher habe ich dafür Text-Arrays angelegt, in denen die Texte für alle Maschinen und Baugruppen stehen. Damit hatte im System Daten, die eigentlich zu den Maschinen und Baugruppen gehören, aber nicht dort untergebracht sind. Da vergisst man bei Änderungen schnell etwas, und das nicht erst in meinem fortgeschrittenen Alter. Deshalb habe ich eine Möglichkeit gesucht und mit der o. g. beschriebenen Technik auch gefunden, die Meldungstexte in den Maschinen- und Baugruppen-FBs unterzubringen und trotzdem aus der Hintergrundtask darauf zugreifen zu können.
 
Hi, danke für den Tipp, so kann ich mir natürlich das anlegen mehrerer Interfaces an einen FB sparen, aber bekomme leider nicht in, dass ich verschiedene fbs, die ein Interface implementieren mit einem
Code:
Interface.Methode();
Aufruf ansprechen kann.
 
... und das nicht erst in meinem fortgeschrittenen Alter. ...
In dieser Beziehung bin ich noch etwas "fortschrittlicher" als Du und als solcher hatte ich mich erdreistet, (sinngemäss) mit "Häää???" zu reagieren ;o)
Dass die "HochsprachenProgrammier" längst den Kurs für die WeiterEntwicklung der SPS-Programmierung vorgeben, ist ja nicht neu.
Dafür können wir nix und beobachten alldieweil amüsiert, wie längst gelöste oder nie gekannte Problemchen zu nervtötenden DauerProblemen weiterentwickelt wurden.

Das SPS-Forum als "QueryInterface" zu interpretieren, finde ich übrigens gar nicht so übel.
 
Ich bin im Hochsprachenbereich nicht so bewandert. Kannst Du etwas ausführlicher erklären, was da passieren soll?
Also ich kann bspw. in C# dem Event "Hupen" der Klasse "Auto" die Methode "Umdrehen" der Klasse "Mensch" zuweisen. Zusätzlic hkann ich aber auch die Methode "Bellen" der klasse "Hund" zuweisen.

Wenn also Auto.Hupen() erfolgt => Mensch.Umdrehen() und Hund.Bellen();

Das würde aber denke ich nur funktionieren, wenn ich 2 Interface hätte, oder eins nach außen führe und dort die beiden anderen aufrufe, oder?
Also mein Event zeigt quasi auf zwei Instanzen.
 
Ja, aber selbst wenn die beide diese Methode haben, brauche ich immer noch 2 Interface am Baustein Auto, die ich übergebe. Einmal auf die Instanz von mensch und einmal auf die Instanz von Hund.

Ich kann leider nicht aus der klasse Auto heraus mit dem Aufruf Interface.Hupen() mehrere Interfaces außen ansprechen. das ist mein vorhaben
 
Ja, aber selbst wenn die beide diese Methode haben, brauche ich immer noch 2 Interface am Baustein Auto, die ich übergebe. Einmal auf die Instanz von mensch und einmal auf die Instanz von Hund.
ähmnein, du mußt ein Interface "HupenReaktionsfaehig" mit einer Methode "HupenReaktion" erzeugen

Dann in der Klasse Mensch eintragen, daß sie HupenReaktionsfaehig implementiert, und die Methode HupenReaktion mit Umdrehen implementieren.
Sowie in der Klasse Hund eintragen, daß sie HupenReaktionsfaehig implementiert, und die Methode HupenReaktion mit Bellen impementieren.

Dann kannst du an die Klasse Auto das Interface HupenReaktionsfaehig übergeben, und im Falle des Hupens HupenReaktionsfaehig.HupenReaktion() ausführen.

Wie du dann hinkriegst, daß mehrere Autos hupen können, oder mehrere Menschen/Hunde auf hupen reagieren können, sei dem geneigten Leser als leichte Übung überlassen. (ggf. solltest du das aber nicht auf SPS-Ebene machen, sondern IoT-Protokolle wie MQTT bemühen. Aber ich weiß ja nicht, was du eigentlich vorhast)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wie es implementiert wird ist mir ja klar.
Ich wollte, dass durch einen Aufruf in der Klasse Auto mittels.... Interface.hupen() die entsprechenden Methoden in der Klasse Mensch UND der Klasse Hund aufgerufen wird.
Aber dass beide aufgerufen werden geht wohl nur, wenn ich zwei Interface an Auto lege, oder außerhalb von Auto die Reaktion Abgänge und auf Mensch und Hund weiter leite
 
... Da wirst Du "Mensch" und "Hund" eine Methode "HupenReaktion" verpassen müssen ...

... brauche ich immer noch 2 Interface am Baustein Auto ...

Damit wären wir jetzt beim Thema "vorausschauendes Hupen"! Richtig, man muss vor dem Hupen schon genau abwägen, ob man eine unbeabsichtigte Lawine von Nebenwirkungen auslösen will oder doch lieber auf ein Event verzichtet und - ohne jegliches Aufsehen zu erregen - einfach den Fussgänger zur Fussmatte umfunktioniert.
Ich kann mich an Zeiten erinnern, als die Logik irgendwie noch überschaubar war - oder mir zumindest so vorkam.
Das muss wohl TopDownDesign sein. Alle Eventualitäten sorgfältigst einplanen, um dann vor lauter Bytes die Bits nicht mehr zu sehen?

... Wie du dann hinkriegst, daß mehrere Autos hupen können, oder mehrere Menschen/Hunde auf hupen reagieren können, sei dem geneigten Leser als leichte Übung überlassen. (ggf. solltest du das aber nicht auf SPS-Ebene machen, sondern IoT-Protokolle wie MQTT bemühen. Aber ich weiß ja nicht, was du eigentlich vorhast)
Früher kannten wir noch die FlankenErkennung von Bits und haben sie sogar auf StatusBits angewendet.
Schnittstellen bestanden aus DatenBereichen und wir haben Events unwissentlich noch für etwas Angenehmes gehalten.
 
Zuletzt bearbeitet:
Wie es implementiert wird ist mir ja klar.
Ich wollte, dass durch einen Aufruf in der Klasse Auto mittels.... Interface.hupen() die entsprechenden Methoden in der Klasse Mensch UND der Klasse Hund aufgerufen wird.
Aber dass beide aufgerufen werden geht wohl nur, wenn ich zwei Interface an Auto lege, oder außerhalb von Auto die Reaktion Abgänge und auf Mensch und Hund weiter leite
Was du hier wohl willst ist ein "Listener"-Pattern.

Also nicht ein direkter Aufruf der Funktionen Mensch.HupenReaktion() und Hund.HupenReaktion(), sondern ein "FOR EACH Listerner DO Listener.HupenReaktion()". Da wirst du aber das Problem bekommen, daß Sprachen wie C# auf diesem Gebiet ungefähr 5 Generationen weiter sind als ST.

Wie gesagt, dafür sind IoT-Protokolle wie z.b. MQTT gedacht.

Oder du machst es doch wieder "Oldschool" und setzt ein Ausgangsbit "HupeAktiv" anstatt über Interfaces und Methoden zu gehen, die bei üblichen Steuerungsaufgaben eher wie Kanonen auf Spatzen schießen wirken.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja es geht ja nicht wirklich um ein bit, was etwas auslöst.
Ich habe das Interface benutzt, um nicht zu viel Logik drum herum basteln zu müssen.
Es gibt in der Maschine Zustände, welche von ca. 10 - 20 Variablen abhängig sind und je nach zustand muss ich etwas über einen Socket senden.
Hatte zuerst extern (außerhalb des Bausteins) diese Zustände abgefragt, da sie nach außen geführt sind. man kann aber leicht diverse Überschneidungen bekommen und somit habe ich mich dazu entschieden, wenn der Zustand da ist (Im Baustein viel leichter zu erkennen) dann löse ich eine Methode über ein Event aus.
Das geht direkt auf meinen Socket Baustein und sendet die Daten.
Funktioniert auch Super. Ich wollte nur wissen, ob man mehrfach ein Interface belegen kann. sonst nichts.
Wenn mehrere Externe Bausteine reagieren müssen, so muss ich vielleicht das Interface auf einen Eventmanager legen und in dessen Methoden die anderen Instanzen aufrufen.
 
Also ich hab immer noch nicht ganz richtig verstanden was du machen möchtest, vielleicht hilft ein UML Chart?
Du kannst auf alle Fälle mehrere Interfaces implementieren (falls das hilft)

Code:
FUNCTION BLOCK Auto EXTENDS FahrzeugBase IMPLEMENTS FahrzeugBase, AutoInterface

Die Klasse Auto kann allerdings immer nur von einer Mutterklasse erben die du mit SUPER^.methode() erreichen kannst.

Interfaces haben eigentlich zwei Funktionen:
  • du kannst du einen Entwickler zwingen gewisse Funktionen zu implementieren
  • sie können (einfach gesagt) als Pointer auf eine Instanz verwendet werden
  • du kannst mit denen aber auch Funktionen verbergen

z.B.:
Du hast eine Klasse Auto und diese hat durch obige Deklaration ja alle Methoden der Klasse FahrzeugBase.
Wenn du nun beim IMPLEMENTS das Interface FahrzeugBase weglässt und nicht direkt auf die Instanz zugreifst sondern nur über das Interface AutoInterface
Dann siehst du auch nur diese Methoden. Insofern stimmt das mit dem Pointer ja nicht ganz, aber fast ;-).

Soviel zu den Basics. Mehrfachvererbung und Signatur der Methode ändern geht bei TC nicht (laut Codesys wird dran gearbeitet aber derzeit leidet noch die Laufzeit zu sehr darunter).
Was natürlich auch geht ist dass Interfaces von anderen Interfaces erben (analog zu den Function Blocks)...

Wenn du vielleicht deine Problemstellung etwas genauer beschreiben könntest dann kann ich dir helfen?!

Zum anderen Thema bleibt mir nur zu sagen: Bei der Leistung die moderne SPSen heute liefern und bei der dementsprechend möglichen Maschinengröße in einem Projekt schafft man es kaum mit normaler strukturierter Programmierung (ohne Objektorientierung) diese Programme übersichtlich und nachvollziehbar zu erstellen. Da muss man auf diese OOP Hilfsmittel zurückgreifen. Die Umstellung wird für viele hart, aber es bietet einem aus meiner Sicht extrem viele Vorteile.

ok ich war viel zu langsam...
 
Zuletzt bearbeitet:
Konnte es lösen:
Also mein erstes Problem war, dass ich gerne von einem FB mehrere Interface aufrufen möchte. also der FB_Sender ruf über ein Interface einmal fb_empfänger1.Methode auf und einmal fb_empfänger2.Methode.
Dies wird wohl nicht anders gehen, als mehrere Interface zu übergeben.
Das zweite Problem war, dass beide Empfänger das gleiche Interface implementieren, ich zwar zu empfänger1 jede interfacemethode aus dem Sender zulassen möchte, zu Empfänger2 allerdings nur eine bestimmte.
Sagen wir mal es gibt Methode A und B. ich habe daraus die Interface Ia, Ib gemacht. beide werden von den Empfängern implementiert.
Im Sender habe ich ein Array für InterfaceA und Interface b angelegt. über eine registermethode (damit man von außen nicht so die Arrays sieht) habe ich dann Empfänger1 und Empfänger2 jeweils einem arrayelement von InterfaceA zugewiesen und dem element von InterfaceB habe ich nur empänger1 zugewiesen.
Wenn jetzt MethodeA aufgerufen werden soll, rufe ich alle interfaceA aus dem Array auf und das gleiche mit B. Funktioniert einwandfrei.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich habe das Interface benutzt, um nicht zu viel Logik drum herum basteln zu müssen.
Da bist Du hier wohl auf der falschen Spielwiese. Bei SPS = PLC = "programmable logic controller" besteht das Programm zum allergrößten Teil aus Logik. Die überdies immer wieder ausgeführt wird und nicht nur einmal nach Events.
Soll Deine SPS auch noch was produktives tun außer OOP-mäßig "hupen"? Oder ist es kein Problem, wenn die SPS ab und zu sekundenlang alle Sensoren, Lichtschranken, Stop-Tasten und ähnliches ignoriert, weil sie auf besonders smarte unlogische Art "hupen" soll? ;)

Harald
 
Mensch, Harald!
Jetzt müssen wir Dich umdrehen, sonst bist Du der Hund, der vor dem falschen Loch bellt!
"Das ist doch nur ein Beispiel" für altmodische Autofahrer, die nur den Umgang mit der Hupe verstehen.
Zu denen gehörst Du doch gar nicht!

Gruss, Heinileini
 
Also nur zum klarstellen.
Mein SPS Programm arbeitet natürlich zyklisch alles ab.
Das mit dem Hupen war nur ein beispiel.

Ich wollte nur aus dem zyklischen Programm heraus lediglich an den entsprechenden Stellen eine Methode aufrufen, welche dann Daten über einen Socket sendet.

Dies ist dann nämlich losgelöst vom restlichen Programm und Modular.
Hierzu wollte ich die sowieso vorhandene Prohrammlogig nicht nochmal nur zum senden im Socket FB nachbauen.
 
Zurück
Oben