TC emulieren

Begonnen von wkarl, 02 Januar 2014, 10:39:55

Vorheriges Thema - Nächstes Thema

martinp876

Hi,

vorsicht mit der Aktuellen Version - ich glaube zwar keinen tippfehler drin zu haben (hat komplett 'compared') aber mein System hat sich aufgehängt.
Kritisch ist m.E. diese Until-loop - die scheint auch endlos laufen zu können.
Werde mir die Berechnung doch einmal reinziehen müssen - oder hast du etwas gefunden Frank?
Endlose Berechnungen machen eh keinen Sinn, da ist neustart angesagt - lässt sich nicht mehr synchen

Ich werden heute noch einmal einchecken, so dass "normal-user" nicht am update sterben ;)
Gruss Martin

frank

hallo martin,

die do schleife wird wohl endlos laufen, weil du das beste aus 2 philosophien verknüpft hast.  :)

meiner meinung nach kann die schleife nicht endlos laufen. es sei denn irgendetwas wird null oder negativ bei der $nextTimer berechnung. es wird ja ständig aufsummiert, und wenn das aufsummierte grösser als die aktuelle zeit wird, ist der durchlauf beendet.

es kann natürlich lange dauern, wenn du wie heute mittag folgendes einbaust, und nextF 0 wird, dann fangen wir wohl im jahre 1900 oder wer weiss wo an. das hat bei mir wohl das system zum glühen gebracht, als ich die readings gelöscht habe.

  $hash->{helper}{vd}{nextF} = ReadingsVal($name,".next",0);

ist die v4815 nun eigentlich ok oder nur notdürftig geflickt?

gruss frank
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

frank

hallo martin,

meine version ist eigentlich aus der alten version ohne rettungsfeature entstanden. da laufen wir ja quasi den ganzen tag im kreis. bei jedem durchlauf wird aus dem alten $hash->{helper}{vd}{next} jeweils $hash->{helper}{vd}{nextF} und $hash->{helper}{vd}{nextM} berechnet und später nach prüfung eins von beiden zum neuen $hash->{helper}{vd}{next} usw, usw.

durch den einbau der do schleife sollte sich eigentlich erst einmal nichts ändern. sie wird mindestens einmal durchlaufen und die until prüfung wird immer sofort bestanden. denn das alte $hash->{helper}{vd}{next} ist ja ungefähr $tn. also mit meiner version ist das normale verhalten genauso, wie vor dem feature. eine nexttimer berechnung und weiter.

es ändert (soll) sich erst bei systemstart. meine version startet genauso wie die alte, wenn keine readings mit rettungsdaten existieren. erst durch die existenz der rettungsdaten werden die genutzt, um das system zu initialisieren. in diesem moment kommt man das einzige mal mit einem älteren $hash->{helper}{vd}{next} in die funktion und muss die do schleife entsprechend oft durchlaufen, bis das erste $hash->{helper}{vd}{nextF} grösser als die aktuelle zeit wird.

ich speichere zur zeit alle 15 min mein fhem.save file. wenn es dumm läuft und bei speicherung der letzte, verifizierte meetingpoint 15 min zurückliegt, sind meine daten also höchstens 30 min alt. bei einem meeting cycle von ca 2,5 min ergeben sich in diesem fall ca 12 durchläufe der do schleife. das aber auch nur im fall eines neustartes!!
wie gesagt, sonst immer 1 mal, egal ob meeting erfolgreich oder nicht. das sollte also kein problem geben.

vor der do schleife in 4815 habe ich das hier gefunden.

  $hash->{helper}{vd}{next} = ReadingsVal($name,".next",$tn)
        if (!defined $hash->{helper}{vd}{next});


das brauchen wir eigentlich nicht, da es bereits schon vor dem ersten funktionsaufruf eingebaut ist.

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

nächster punkt: msgNbr bug:

ich stelle regelmässig fest, das der message zähler beim übergang falsch zählt. er zählt: ....fd,fe, 00, 01.... es fehlt also der wert ff. der fehler liegt in dieser berechnung:

$msgCnt = ($msgCnt + 1)%255;

ich bringe meine seltenen vd ausfälle mit diesem bug in verbindung. wäre das behoben, gäbe es vielleicht keine aussetzer mehr.  ;D wie wäre es damit:

$msgCnt = ($msgCnt + 1)%256;

gruss frank
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

martinp876

Hallo Frank,
Zitatdas brauchen wir eigentlich nicht, da es bereits schon vor dem ersten funktionsaufruf eingebaut ist.
hm - das ist falsch. Mein system hat sich aufgehängt - hat nur noch ein kill-9 geholfen. Ich habe es geloggt - es haben werte gefehlt.
Diese Abfrage macht die Sache sicher - den ein Aufhängen - zumal in dieser Form ist indiskutablel.
Die Version habe ich gestern noch 'repariert' mit dieser Abfrage.

Man kann es sicher auch anders lösen. Meine Version vorher hatte zu allen Abfragen auch default wenn nichts gesetzt ist - das ist jetzt wieder so. Hast du den Quer-einstieg nach reboot berücksichtigt? Da liegt die Ursache begraben

und klar - modulo 256. Gut beobachtet.

Gruss Martin

frank

hallo martin,

ich habe den fehler gefunden.
meine version baut auf v4711 auf. dort fehlt folgender block mit dem aufruf der funktion CUL_HM_valvePosUpdt.

    elsif ("virtual" eq $st) {#setup virtuals
      $hash->{helper}{role}{vrt} = 1;
      if (   $hash->{helper}{fkt}
          && $hash->{helper}{fkt} =~ m/^(vdCtrl|virtThSens)$/){
        my $n = ReadingsVal($name,".next",0);
        my $now = gettimeofday();
        $n = $now if ($n<$now);
        my $vId = substr($id."01",0,8);
        $hash->{helper}{virtTC} = "00";
        CUL_HM_Set($hash,$name,"valvePos",ReadingsVal($name,"valvePosTC",""));
        CUL_HM_Set($hash,$name,"virtTemp",ReadingsVal($name,"temperature",""));
        CUL_HM_Set($hash,$name,"virtHum" ,ReadingsVal($name,"humidity",""));
        RemoveInternalTimer("valvePos:$vId");
        InternalTimer($n,"CUL_HM_valvePosUpdt","valvePos:$vId",0);
        }
    }


wenn du von hier einsteigst ist natürlich nichts abgesichert.

gruss frank
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

martinp876

Hi Frank

so isses - ausser Readings ;) Die (und nur die) sind nach neustart da.
Mit "set" einzusteigen zu aufwändig...

Aber eigentlich is mein code zu aufwändig. Ich werden einfach
        InternalTimer(ReadingsVal($name,".next",1) ,"CUL_HM_valvePosUpdt","valvePos:$vId",0);
nutzen. kein Next oder next kleiner "now" startet dann einfach sofort die Bearbeitung - weniger code, gleiches resultat.

Gruss Martin

frank

hallo martin,

auch mit v4820 erreicht man nun 100% rettungsquote. da macht das herumschrauben am system wieder spass. nicht mehr nach jedem shutdown, ob gewollt oder nicht, durchs ganze haus jagen und sämtliche vd reanimieren.

wo wir gerade beim rumschrauben sind. ich hätte da noch eine "klitzekleine" erweiterung anzubieten. bisher wird bei einem neustart das erste climateEvent ohne aussicht auf erfolg gesendet. nicht nur dass unnötig resourcen verschenkt und gerade beim neustart der funk sinnlos belastet wird, erscheint in meinem log dieses "hässliche" miss_1.

mit folgenden änderungen:

sub CUL_HM_valvePosUpdt(@) {#update valve position periodically to please valve
  my($in ) = @_;
  my(undef,$vId) = split(':',$in);
  my $hash = CUL_HM_id2Hash($vId);
  my $name = $hash->{NAME};
  my $msgCnt = $hash->{helper}{vd}{msgCnt};
  my ($idl,$lo,$hi,$nextTimer);
  my $tn = gettimeofday();
  $hash->{helper}{vd}{next} = ReadingsVal($name,".next",$tn)
        if (!defined $hash->{helper}{vd}{next});
  $hash->{helper}{vd}{nextF} = $hash->{helper}{vd}{next};
# int32_t result = (((_address << 8) | messageCounter) * 1103515245 + 12345) >> 16;
#                          4e6d = 20077                        12996205 = C64E6D
# return (result & 0xFF) + 480;

  if ($tn > ($hash->{helper}{vd}{nextF} + 3000)){# mised 20 periods;
    Log3 $name,3,"CUL_HM $name virtualTC timer off by:".int($tn - $hash->{helper}{vd}{nextF});
    $hash->{helper}{vd}{nextF} = $tn;
  }
  do {
    $msgCnt = ($msgCnt + 1)%256;
    $idl = $hash->{helper}{vd}{idl}+$msgCnt;
    $lo = int(($idl*0x4e6d +12345)/0x10000)&0xff;
    $hi = ($hash->{helper}{vd}{idh}+$idl*198)&0xff;
    $nextTimer = (($lo+$hi)&0xff)/4 + 120;
    $hash->{helper}{vd}{nextF} += $nextTimer;
  } until ($hash->{helper}{vd}{nextF} > $tn);

  $hash->{helper}{vd}{nextM} = $tn+$nextTimer;
  $hash->{helper}{vd}{msgCnt} = $msgCnt;
  if ($hash->{helper}{vd}{cmd}){
    if ($hash->{helper}{vd}{typ} == 1){

##################################################################################
      CUL_HM_PushCmdStack($hash,sprintf("%02X%s%s%s"
                                        ,$msgCnt
                                        ,$hash->{helper}{vd}{cmd}
                                        ,$hash->{helper}{virtTC}
                                        ,$hash->{helper}{vd}{val}))
if (ReadingsVal($name,"valveCtrl","init") ne "init");
##################################################################################

    }
    else{
      CUL_HM_PushCmdStack($hash,sprintf("%02X%s%s"
                                        ,$msgCnt
                                        ,$hash->{helper}{vd}{cmd}
                                        ,$hash->{helper}{vd}{val}));
    }
  }
  else{
    delete $hash->{helper}{virtTC};
    CUL_HM_UpdtReadSingle($hash,"state","stopped",1);
    return;# terminate processing
  }
  $hash->{helper}{virtTC} = "00";
  CUL_HM_ProcessCmdStack($hash);
  InternalTimer($tn+10,"CUL_HM_valvePosTmr","valveTmr:$vId",0);
}
sub CUL_HM_valvePosTmr(@) {#calc next vd wakeup
  my($in ) = @_;
  my(undef,$vId) = split(':',$in);
  my $hash = CUL_HM_id2Hash($vId);
  my $name = $hash->{NAME};
  if ($hash->{helper}{vd}{typ} == 1){

##################################################################################
if (ReadingsVal($name,"valveCtrl","init") eq "init") {
      $hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextF};
CUL_HM_UpdtReadSingle($hash,"valveCtrl","ready",1);
}
else {
##################################################################################

my $pn = CUL_HM_id2Name($hash->{helper}{vd}{id});
my $ackTime = ReadingsTimestamp($pn, "ValvePosition", "");
my $vc;
if (!$ackTime || $ackTime eq $hash->{helper}{vd}{ackT} ){
$hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextF};
$vc = (++$hash->{helper}{vd}{miss} > 5)
?"lost"
:"miss_".$hash->{helper}{vd}{miss};
Log3 $name,5,"CUL_HM $name virtualTC use fail-timer";
}
else{
CUL_HM_UpdtReadBulk($hash,0,".next:".$hash->{helper}{vd}{next}
,".msgCnt:".($hash->{helper}{vd}{msgCnt}-1));
$hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextM};
$vc = "ok";
$hash->{helper}{vd}{miss} = 0;
}
CUL_HM_UpdtReadSingle($hash,"valveCtrl",$vc,1)
if(ReadingsVal($name,"valveCtrl","") ne $vc);
$hash->{helper}{vd}{ackT} = $ackTime;

##################################################################################
}
##################################################################################

  }
  InternalTimer($hash->{helper}{vd}{next},"CUL_HM_valvePosUpdt","valvePos:$vId",0);
}


sieht mein log nach shutdwn & restart dann so aus:

2014.02.06 16:28:16.802 0: Server shutdown
2014.02.06 16:28:21.270 1: Including fhem.cfg
2014.02.06 16:28:25.726 1: HMLAN_Parse: HMLAN1 new condition disconnected
2014.02.06 16:28:25.784 1: HMLAN_Parse: HMLAN1 new condition init
2014.02.06 16:28:37.709 1: Including ./log/fhem.save
2014.02.06 16:28:40.630 1: ----- VD-STATUS ----- VentilControler.Kueche_Btn1 valveCtrl: init
2014.02.06 16:28:41.883 0: Server started with 356 defined entities (version $Id: fhem.pl 4709 2014-01-21 18:00:07Z rudolfkoenig $, os linux, user root, pid 3890)
2014.02.06 16:28:43.730 1: HMLAN_Parse: HMLAN1 new condition ok
2014.02.06 16:28:46.495 1: ----- VD-STATUS ----- VentilControler.SZ_Btn1 valveCtrl: init
2014.02.06 16:28:46.663 1: ----- VD-STATUS ----- VentilControler.Bad_Btn1 valveCtrl: init
2014.02.06 16:28:47.183 1: ----- VD-STATUS ----- VentilControler.WZ_Btn1 valveCtrl: init
2014.02.06 16:28:47.377 1: ----- VD-STATUS ----- VentilControler.AZ.Nord_Btn1 valveCtrl: init
2014.02.06 16:28:51.822 1: ----- VD-STATUS ----- VentilControler.Kueche_Btn1 valveCtrl: ready
2014.02.06 16:28:56.605 1: ----- VD-STATUS ----- VentilControler.SZ_Btn1 valveCtrl: ready
2014.02.06 16:28:56.749 1: ----- VD-STATUS ----- VentilControler.Bad_Btn1 valveCtrl: ready
2014.02.06 16:28:57.278 1: ----- VD-STATUS ----- VentilControler.WZ_Btn1 valveCtrl: ready
2014.02.06 16:28:57.476 1: ----- VD-STATUS ----- VentilControler.AZ.Nord_Btn1 valveCtrl: ready
2014.02.06 16:29:22.287 1: ----- VD-STATUS ----- VentilControler.Bad_Btn1 valveCtrl: ok
2014.02.06 16:29:58.969 1: ----- VD-STATUS ----- VentilControler.AZ.Nord_Btn1 valveCtrl: ok
2014.02.06 16:30:25.531 1: ----- VD-STATUS ----- VentilControler.Kueche_Btn1 valveCtrl: ok
2014.02.06 16:30:49.689 1: ----- VD-STATUS ----- VentilControler.WZ_Btn1 valveCtrl: ok
2014.02.06 16:30:52.389 1: ----- VD-STATUS ----- VentilControler.SZ_Btn1 valveCtrl: ok


gruss frank
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

martinp876

Hallo Frank,

nun - operationell hatte ich ja nichts verändert - ist immer noch dein code.

Code bauen ich ein.
Wenn es aber häufig eingesetzt werden soll wird man den code evtl optimieren müssen. Will man z.B. 10 Thermostate nutzen wird die CPU last wichtig!

Gruss Martin

frank

hallo martin,

deine variation bringt, glaub ich, ärger! weil "typ=1 & init" nach else will.  ;)
hatte ich der schönheit wegen auch erst, dann aber nicht gewagt.

    if (   $hash->{helper}{vd}{typ} == 1
        && ReadingsVal($name,"valveCtrl","init") ne "init"){
      CUL_HM_PushCmdStack($hash,sprintf("%02X%s%s%s"
                                        ,$msgCnt
                                        ,$hash->{helper}{vd}{cmd}
                                        ,$hash->{helper}{virtTC}
                                        ,$hash->{helper}{vd}{val}));
    }
    else{
      CUL_HM_PushCmdStack($hash,sprintf("%02X%s%s"
                                        ,$msgCnt
                                        ,$hash->{helper}{vd}{cmd}
                                        ,$hash->{helper}{vd}{val}));
    }


ZitatWenn es aber häufig eingesetzt werden soll wird man den code evtl optimieren müssen. Will man z.B. 10 Thermostate nutzen wird die CPU last wichtig!

dann mach dich schon mal warm!
das läuft so überzeugend, da werde ich wohl noch kräftig erweitern. da gerade alle auf rt umswitchen gibt es die vd bestimmt bald zum schrottpreis. aber nicht weitersagen.  :)

gruss frank
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

martinp876

Hi Frank,

sorry - schlecht nachgedacht. - korrogiert

Zur "massenhaft" Nutztung wird muss man einige andere Dinge betrachten - so z.B. das message aufkommen und die HMLAN Grenzen...

Gruss Martin

Hauswart

Ist es mit PID20, welcher die benötigte Ventileinstellung berechnet, über die virtuelle Einstellungen "valvePos" und "virtTemp" die Ventilöffnung bzw. die Temperatur bei einem HM-CC-RT-DN zu regeln?

Dann wäre das HM-CC-RT-DN de facto ein reiner Stellantrieb? Ist-Temperatur wird nicht vom RT gemessen, Ventilöffnung von PID20 berrechnet, Soll-Temperatur wird von PID20 festgelegt bzw. über Dummy?

1. Installation:
KNX, Tasmota (KNX), Sonos, Unifi

2. Installation:
HM-CFG-USB, Unifi (, SIGNALduino 868, MySensors, SIGNALduino 433)

frank

hallo hauswart,

Zitat von: Hauswart am 10 Februar 2014, 10:05:41
Ist es mit PID20, welcher die benötigte Ventileinstellung berechnet, über die virtuelle Einstellungen "valvePos" und "virtTemp" die Ventilöffnung bzw. die Temperatur bei einem HM-CC-RT-DN zu regeln?

wie du im anderen thread bereits mehrfach gehört hast, ist diese methode mit dem rt nicht möglich! jedenfals habe ich das dort so verstanden. ich habe kein rt und kann es selbst nicht beurteilen. da beim rt regler und ventil in einem gehäuse untergebracht sind, ist es wohl nicht möglich die datenverbindung zwischen regler und ventil zu kappen, um dem ventil eigene daten zu übermitteln.

wenn du die firmware vom rt verändern würdest, hättest du vielleicht eine chance.  ;)

die möglichkeiten in diesem thread beziehen sich ausschliesslich auf einen hm-cc-vd. bei diesem model ist kein regler im gleichen gehäuse enthalten. es handelt sich hier, um einen reinen stellantrieb, ohne extras.

gruss frank
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

martinp876

kann ich bestaetigen - der RT bekommt kann, wenn gepeert, die ist-temp von extern bekommen. Die Ventilstellung berechnet er immer intern

frank

hallo martin,

nachdem, seit den letzten erweiterungen des vtc, keine ausfälle der realen vd mehr aufgetreten sind, habe ich es gewagt, dem vd nicht mehr zu jedem zyclus ein climateEvent anzubieten. ziel ist, den funkverkehr zum vd zu reduzieren.

mit folgender erweiterung wird nach jedem erfolgreichen meeting ein zyclus ausgelassen. dieses feature soll steuerbar sein. normalerweise müsste die steuerung durch die einstellung eines attributs erfolgen. aus unkenntnis der attributeinbindung habe ich es erst einmal über ein reading ausprobiert.

#+++++++++++++++++ set/get support subroutines+++++++++++++++++++++++++++++++++
sub CUL_HM_valvePosUpdt(@) {#update valve position periodically to please valve
  my($in ) = @_;
  my(undef,$vId) = split(':',$in);
  my $hash = CUL_HM_id2Hash($vId);
  my $name = $hash->{NAME};
  my $msgCnt = $hash->{helper}{vd}{msgCnt};
  my ($idl,$lo,$hi,$nextTimer);
  my $tn = gettimeofday();
  $hash->{helper}{vd}{next} = ReadingsVal($name,".next",$tn)
        if (!defined $hash->{helper}{vd}{next});
  $hash->{helper}{vd}{nextF} = $hash->{helper}{vd}{next};
# int32_t result = (((_address << 8) | messageCounter) * 1103515245 + 12345) >> 16;
#                          4e6d = 20077                        12996205 = C64E6D
# return (result & 0xFF) + 480;

  if ($tn > ($hash->{helper}{vd}{nextF} + 3000)){# mised 20 periods;
    Log3 $name,3,"CUL_HM $name virtualTC timer off by:".int($tn - $hash->{helper}{vd}{nextF});
    $hash->{helper}{vd}{nextF} = $tn;
  }
  do {
#######################################################
    $msgCnt = ($msgCnt + 1)%256;
#######################################################
    $idl = $hash->{helper}{vd}{idl}+$msgCnt;
    $lo = int(($idl*0x4e6d +12345)/0x10000)&0xff;
    $hi = ($hash->{helper}{vd}{idh}+$idl*198)&0xff;
    $nextTimer = (($lo+$hi)&0xff)/4 + 120;
    $hash->{helper}{vd}{nextF} += $nextTimer;
  } until ($hash->{helper}{vd}{nextF} > $tn);

  $hash->{helper}{vd}{nextM} = $tn+$nextTimer;
  $hash->{helper}{vd}{msgCnt} = $msgCnt;
  if ($hash->{helper}{vd}{cmd}){
    if    ($hash->{helper}{vd}{typ} == 1){

#######################################################################################
#   msgReduce=0 => push all cycle (100% msgLoad)
#   msgReduce=1 => push 1 cycle, miss 1 cycle if first cycle ok (50% msgLoad)

CUL_HM_UpdtReadSingle($hash,"msgReduce",0,0)
if (!defined ReadingsVal($name,"msgReduce",undef));
my $mr = ReadingsVal($name,"msgReduce",0);

my $vc = ReadingsVal($name,"valveCtrl","init");
if (!(($vc eq "init") || ($vc eq "ok") && $mr)) { #push if ready,idle,miss,lost
CUL_HM_PushCmdStack($hash,sprintf("%02X%s%s%s"
,$msgCnt
,$hash->{helper}{vd}{cmd}
,$hash->{helper}{virtTC}
,$hash->{helper}{vd}{val}));
}
#
#######################################################################################

      InternalTimer($tn+10,"CUL_HM_valvePosTmr","valveTmr:$vId",0);
    }
    elsif ($hash->{helper}{vd}{typ} == 2){
      CUL_HM_PushCmdStack($hash,sprintf("%02X%s%s"
                                        ,$msgCnt
                                        ,$hash->{helper}{vd}{cmd}
                                        ,$hash->{helper}{vd}{val}));
      $hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextM};
      InternalTimer($hash->{helper}{vd}{next},"CUL_HM_valvePosUpdt","valvePos:$vId",0);
    }
  }
  else{
    delete $hash->{helper}{virtTC};
    CUL_HM_UpdtReadSingle($hash,"state","stopped",1);
    return;# terminate processing
  }
  $hash->{helper}{virtTC} = "00";
  CUL_HM_ProcessCmdStack($hash);
}
sub CUL_HM_valvePosTmr(@) {#calc next vd wakeup
  my($in ) = @_;
  my(undef,$vId) = split(':',$in);
  my $hash = CUL_HM_id2Hash($vId);
  my $name = $hash->{NAME};

#######################################################################################
#
my $vc = ReadingsVal($name,"valveCtrl","init");
if ($vc eq "init") {
$hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextF};
CUL_HM_UpdtReadSingle($hash,"valveCtrl","ready",1);
}
my $mr = ReadingsVal($name,"msgReduce",0);
elsif (($vc eq "ok") && $mr) {
$hash->{helper}{vd}{miss} = 1;
$hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextF};
CUL_HM_UpdtReadSingle($hash,"valveCtrl","idle",1);
}
#
#######################################################################################

  else {
    my $pn = CUL_HM_id2Name($hash->{helper}{vd}{id});
    my $ackTime = ReadingsTimestamp($pn, "ValvePosition", "");
    my $vc;
    if (!$ackTime || $ackTime eq $hash->{helper}{vd}{ackT} ){
      $hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextF};
      $vc = (++$hash->{helper}{vd}{miss} > 5)
                                          ?"lost"
                                          :"miss_".$hash->{helper}{vd}{miss};
      Log3 $name,5,"CUL_HM $name virtualTC use fail-timer";
    }
    else{
      CUL_HM_UpdtReadBulk($hash,0,".next:".$hash->{helper}{vd}{next}
                                 ,".msgCnt:".($hash->{helper}{vd}{msgCnt}-1));
      $hash->{helper}{vd}{next} = $hash->{helper}{vd}{nextM};
      $vc = "ok";
      $hash->{helper}{vd}{miss} = 0;
    }
    CUL_HM_UpdtReadSingle($hash,"valveCtrl",$vc,1)
          if(ReadingsVal($name,"valveCtrl","") ne $vc);
    $hash->{helper}{vd}{ackT} = $ackTime;
  }
  InternalTimer($hash->{helper}{vd}{next},"CUL_HM_valvePosUpdt","valvePos:$vId",0);
}



seit gut 24 std läuft diese erweiterung bei mir problemlos. da meine hauptfunklast durch 5 vtc und 4 vvd erzeugt wird, die ca alle 2.5 min messages zu ihren realen partnern senden, erzielt diese erweiterung eine enorme reduzierung der funklast. laufen diese 9 virtuellen entities unter volllast, kann ich am hmlan unter msgLoadEst im normalen betrieb eine gemittelte funklast von 25% feststelen. über hminfo:msgStat entspricht es stündlich ca 220 messages. nach dem einbau der erweiterung sinken die werte auf 15%/160msg. und das bei bisher 100% lebenserhaltung der vd.

als nächsten schritt wollte ich die vvd funklast verringern. mit folgendem code ist es mir aber nur gelungen, die antworten zum tc zu ändern, anstatt sie zu reduzieren. das sollte dir ja bestimmt keine probleme bereiten.  ;) zumindestens kann ich die funktion meiner erweiterung im log erkennen. bei jedem "gewollten" auslassen antwortet fhem nun mit einem normalen ack (00). man kann am realen tc gut erkennen, dass ihm das nicht gefällt. zur zeit läuft ein vvd mit einstellung msgReduce=4 (1x msg und 4x auslassen), was ca 20% der bisherigen volllast entsprechen sollte. mit dieser einstellung scheint er gerade noch zufrieden zu sein, ohne ein stündliches beep, beep von sich zu geben. mit einstellung 5 gab es einmal alarm. daher könnte man sich auf einstellungen von 0-4 begnügen. wahrscheinlich würde es auch reichen, ihm 1-2 antworten kurz vor der vollen Stunde zu senden, wenn einem das blinkende antennensymbol in der restlichen zeit nicht stört. auch bei dieser erweiterung nutze ich ein reading anstelle eines attributes.

    elsif($mTp eq "58" && $p =~ m/^(..)(..)/) {# climate event
      my ($d1,$vp) =($1,hex($2)); # adjust_command[0..4] adj_data[0..250]
      $vp = int($vp/2.56+0.5);    # valve position in %
      my $chnHash = $modules{CUL_HM}{defptr}{$dst."01"};
      $chnHash = $dhash if (!$chnHash);
      push @entities, CUL_HM_UpdtReadBulk($chnHash,1,"ValvePosition:$vp %",
                                                     "ValveAdjCmd:".$d1);

#######################################################################################
#   msgReduce=0 => push all cycle  (100% msgLoad)
#   msgReduce=1 => push 1 cycle, miss 1 cycle  (50% msgLoad)
#   msgReduce=2 => push 1 cycle, miss 2 cycle  (33% msgLoad)
#   msgReduce=3 => push 1 cycle, miss 3 cycle  (25% msgLoad)
#   msgReduce=4 => push 1 cycle, miss 4 cycle  (20% msgLoad)
CUL_HM_UpdtReadSingle($chnHash,"msgReduce",0,0)
if (!defined ReadingsVal($chnHash->{NAME},"msgReduce",undef));
my $ctrRange = ReadingsVal($chnHash->{NAME},"msgReduce",0)+1;
$chnHash->{helper}{cntr} = ($ctrRange-1)
if (!defined $chnHash->{helper}{cntr});

$chnHash->{helper}{cntr} = ($chnHash->{helper}{cntr} +1)%$ctrRange;
if (!$chnHash->{helper}{cntr}) {
push @ack,$chnHash,$mNo."8002".$dst.$src.'0101'.
                         sprintf("%02X",$vp*2)."0000";
}
#
#######################################################################################
    }


ps: deine neue variation des modulo256-zählers musste ich wieder ändern. hat immer die selbe msgNbr erzeugt.

pps: anbei noch ein plot einer vd/vtc-kommunikation nach einem reset. ab ca 17.35 habe ich auf reduzierung der funklast umgeschaltet. kleine rote kästchen sind die phasen ohne climateEvent (status=idle).

gruss frank
FHEM: 6.0(SVN) => Pi3(buster)
IO: CUL433|CUL868|HMLAN|HMUSB2|HMUART
CUL_HM: CC-TC|CC-VD|SEC-SD|SEC-SC|SEC-RHS|Sw1PBU-FM|Sw1-FM|Dim1TPBU-FM|Dim1T-FM|ES-PMSw1-Pl
IT: ITZ500|ITT1500|ITR1500|GRR3500
WebUI [HMdeviceTools.js (hm.js)]: https://forum.fhem.de/index.php/topic,106959.0.html

martinp876

Hi Frank,

die reduzierung zum Senden habe ich vorbereitet.
Da attribute nicht selektiv sind und ich hier eine Uuberschwemmung vermeiden will gibt es das Sammelattribut "param"
Einschalten ueber Attribut "param" = msgReduce
attr <name> param msgReduce

Den 2. Teil werde ich nicht einbauen. Wenn das device eine Antwort anfordert wird diese gesendet. Alles andere sind Verletzungen des Funkprotokols - und das kann nicht die Loesung sein.

Gruss Martin