Jump to content

Wie Steckdosen von 2 "Sendern" konfliktfrei schalten?


Recommended Posts

Hallo zusammen,

 

wenn 2 Sender (Programme die aufs Remote Switch Bricklet zugreifen) mehrere Steckdosen ueber das gleiche Remote Switch Bricklet schalten wollen und dies zur gleichen Zeit tun, dann wird der "zweite" Befehl evtl verworfen, da der erste Befehl noch ausgefuehrt wird. So habe ich zumindest die Doku verstanden.

 

Nun gibt es ja den Befehl "get_switching_state": (Gibt den aktuellen Zustand des Schaltens zurück. Wenn der aktuell Zustand busy (beschäftigt) ist, sendet das Bricklet gerade einen Code um eine Steckdose zu schalten. Weitere Aufrufe von switch_socket werden ignoriert bis der Zustand auf ready (fertig) wechselt.)

Das hilft aber auch nicht, wenn beide "Sender" dies abfragen und ein "frei" bekommen und dann senden.

 

Darum mein Vorschlag den Befehl "get_switching_state" um 2 Paramter zu erweitern, die eine Reservierung ermoeglichen:

 

- Set_Booking (0 bis 255 Sekunden)

- Booking_ID (0 bis 255) (Von User frei wahlbar)

 

Wenn 0 dann wird der Befehl wie bisher verarbeitet.

Eine >0 dann das Bricklet fuer x Sekunden exklusiv gebucht.

Als Rueckgabewert kommt dann eine 0 fuer nicht moeglich oder eine 1 fuer akzeptiert zurueck.

 

Damit kann man dann im 2. Schritt den Befehl zum Bricklet senden und man weiss ganz genau, dass der auch verarbeitet wird.

 

Warum noch eine Booking ID? Wie soll man sonst die Buchung zuordnen? Wenn man das ueber die Anfragenden IP Adresse macht, koennte es Konflikte geben wenn beide "Sender" von der gleichen IP Adresse aus senden. So kann der User eine ID festlegen und gibt sie beim senden nochmals mit.

 

Alternativ koennte man auch die "switch_socket_x" Befehle um Antworten erweitern, so dass man weiss ob der Befehl angenommen wurde. Dann koennte derjenige "Sender" dessen Paket verworfen wurde ein zweites mal senden und hoffen, dass dann keine Konflikte vorliegen.

-> Irgendwie finde ich diese Alternative schicker als den eigentlichen Vorschlag, aber ich lasse das mal alles so stehen.

 

 

Der Loetkolben

 

 

Link to comment
Share on other sites

Nur von mir als Senf: Ich finde die Alternative auch schicker, weil der Booking-Mechanismus eigentlich zu "groß" für das Problem ist (viel Aufwand in Implementierung und für den Nutzer auch im Verständnis).

 

Die Alternative ist einfach zu verstehen und kann vom Nutzer völlig ignoriert werden wenn er nur einen "Sender" hat. Außerdem ist sie mindestens auf Ebene der Bindings kompatibel zum alten Methodenruf (Auf IP-Ebene gibt es eine neue Antwort)

Link to comment
Share on other sites

Ich hatte ein ähnliches Problem. "GetSwitchingState" in C# hat nicht zuverlässig gearbeitet. Meine Lösung war das ich vor dem Senden den zugriff mit einer Variable sperre und den CallBack abwarte, der dann die Variable freigibt und den nächsten Sender das go gibt.

 

Vielleicht hilft dir das weiter.

Link to comment
Share on other sites

Oder man bastelt sich eine Queue und arbeitet mit der Callback-Methode. Sobald alles abgearbeitet wurde, prüft man regelmäßig ob neue Switch-Aufträge anstehen und startet dann ggf. wieder durch.

 

@Temp: Damit hast du theoretisch genau die gleiche Konflikt-Möglichkeit. Ob du nun eine selbst definierte Variable oder via get_switching_state() prüfst, macht nun erstmal keinen Unterschied. Allenfalls die Antwortzeit könnte sich unterscheiden.

 

Grüße

nItro

Link to comment
Share on other sites

@nItroFreeZer

Das stimmt rein Theoretisch wäre die gleiche Konflikt Möglichkeit da, aber ich habe durch das rum Testen die Erfahrung gemacht, das wenn der CallBack aufgerufen wird dann auch wirklich der nächste Senden kann. Beim "get_switching_state()" habe ich die Erfahrung gemacht das es nicht immer funktioniert hat, wenn der Zustand „Ready“ zurückkommt mit den C# Bindings.

Link to comment
Share on other sites

Also grundsätzlich kann man im eigenen Code (und in einem Programm) durch Locking usw schon dafür sorgen, dass diese Methoden funktionieren...

 

object switchLock = new object();

void firstAccessor()
{
  lock (switchLock)
  {
    if (bricklet.GetSwitchingState() == SWITCHING_STATE_READY)
    {
      //do switch
    }
  }
}

void otherAccessor()
{
  lock (switchLock)
  {
    if (bricklet.GetSwitchingState() == SWITCHING_STATE_READY)
    {
      //do switch on something different
    }
  }
}

 

Das Problem: Wenn jeder per locking darauf zugreifen würde, dann wäre es ausgeschlossen, dass jemals ein busy zurück kommt. Deswegen ist der Fall, dass man eine Anwendung für alles hat quasi auch ohne TF gelöst.

 

Aber was ist beispielsweise wenn die Clients von Loetkolben auf unterschiedlichen Maschinen oder zumindest ohne gemeinsamen Speicher laufen? Dann wäre es gut, wenn man allein mit TF-Mitteln das Locking realisiert bekommt... Dazu die beiden Vorschläge.

Link to comment
Share on other sites

Ich würde begrüssen wenn;

die "switch_socket_x" Befehle um Antworten erweitern, so dass man weiss ob der Befehl angenommen wurde.

So wie es in anderen Sprachen wie zB. php auch ist.

Würde bedeuten dass alle bisherigen Programme weiter laufen, aber bei Bedarf die Antwort, in einer Schleife, ausgewertet werden könnte.

Link to comment
Share on other sites

Aber was ist beispielsweise wenn die Clients von Loetkolben auf unterschiedlichen Maschinen oder zumindest ohne gemeinsamen Speicher laufen? Dann wäre es gut, wenn man allein mit TF-Mitteln das Locking realisiert bekommt... Dazu die beiden Vorschläge.

 

Ups. Hatte ich vergessen das zu sagen?  ;D  Ja, die Programme laufen auf verschienen Servern, sonst koennte man das mit Flags regeln. Zum einen auf einem Cronjobserver und zum anderen auf mehreren "Webfernbedienungen" via Handy.

 

Aber wieso wuerde die API gebrochen, wenn der Stack eine Antwort liefern wuerde ob der Befehle angenommen oder verworfen wird?

 

Der Loetkolben

Link to comment
Share on other sites

Was wären denn die Konsequenzen aus einer zusätzlichen Antwort? Also ja: Die API würde streng genommen gebrochen, aber was passiert dann?

 

Für jemanden der mit neuer Firmware auch neue Bindings nutzt

Nichts, denn aus void wird int (o.ä.) und das ist echt ungefährlich. Nahezu jeder Code sollte vorher und nachher kompilieren (Ausnahme: Func<TResult, ...>).

Einziges Problem: Neues Timing + Es kann Timeouts geben

 

Für jemanden mit neuer Firmware und alten Bindings

Das ist mir nicht ganz klar... ich glaube aber mich zu erinnern, dass unerwartete Antworten von den Bindings verworfen werden... sollte also gar kein Problem sein.

 

Für jemanden mit neuer Firmware und ohne Bindings (TCP)

Okay... der hat je nachdem wie er es implementiert hat wirklich ein Problem... aber ich weiß nicht wie wichtig dieser Use Case ist...

 

Frage: Ist das vertretbar? (Habt ihr so viele Nutzer die das tatsächlich schmerzen würde)

 

(jetzt kommt der allgemeine Teil)

 

Die Alternative zu solchen inkompatiblen Änderungen ist ja immer nur eine schlechte API. Entweder schlecht weil die existierenden Probleme nicht behoben werden oder schlecht weil es zu viele Methoden gibt die nur aus Kompatibilitätsgründen existieren...

 

Vorschlag: Vielleicht solltet ihr über soetwas wie deprecation nachdenken... Also halt jetzt eine neue Methode einführen die den Rückgabewert hat (und einen ordentlichen Namen) und die alte Methode deprecaten, damit ihr sie in einem halben Jahr löschen könnt... ich fürchte aber, dass das aufgrund eures knappen Speichers auf den Bricklets nicht überall klappen wird...

Link to comment
Share on other sites

Für jemanden mit neuer Firmware und ohne Bindings (TCP)

Okay... der hat je nachdem wie er es implementiert hat wirklich ein Problem... aber ich weiß nicht wie wichtig dieser Use Case ist...

 

Hallo AuronX.

 

Der hat kein Problem, der hat eine Chance!  ;D  ;D

 

Ich wuerde mich freuen. Fummelkram, aber das sollte ich hinbekommen.

 

Muss ja nicht sofort sein und mal hoeren was Tinkerforge so sagt. Das Problem wird ja dadurch verschaerft, dass man den Status (On/Off) der Funksteckdosen nicht im Nachhinein abfragen kann.

 

Der Loetkolben

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...