Shelly Pro3EM MQTT Template

Begonnen von denis.robel, 07 April 2024, 12:50:02

Vorheriges Thema - Nächstes Thema

denis.robel

Hallo,

ich habe jezt einen Shell pro 3EM via MQTT an den Start gebracht und habe noch ein paar Fragen:

1. Hat jemand schon ein Template für das Teil?
2. Wie kann ich die Werte Umrechnen in kWh?
3. Mit welchem Hilfsmodul visualisiert ihr den Verbrauch (statistics etc.)?

Für ein paar Denkanstöße wäre ich sehr dankbar.
VG

Denis

Beta-User

Zitat von: denis.robel am 07 April 2024, 12:50:02Hallo,

ich habe jezt einen Shell pro 3EM via MQTT an den Start gebracht und habe noch ein paar Fragen:

1. Hat jemand schon ein Template für das Teil?
2. Wie kann ich die Werte Umrechnen in kWh?
3. Mit welchem Hilfsmodul visualisiert ihr den Verbrauch (statistics etc.)?

Für ein paar Denkanstöße wäre ich sehr dankbar.
Denkanstöße:
- Bitte keine Doppelposts, schon gleich nicht ohne Querverweise (https://forum.fhem.de/index.php?topic=137799.msg1309953#msg1309953). Bitte im anderen thread einen Verweis reinmachen und den dann (ausnahmsweise) schließen.
- ob es bereits jemanden gibt, der sich mit dem Ding beschäftigt hat, zeigt dir ggf. die Suche.

- v.a. https://forum.fhem.de/index.php?topic=112327.0 gilt auch für dieses Device...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

denis.robel

Zitat von: Beta-User am 09 April 2024, 08:33:36Denkanstöße:
- Bitte keine Doppelposts, schon gleich nicht ohne Querverweise (https://forum.fhem.de/index.php?topic=137799.msg1309953#msg1309953). Bitte im anderen thread einen Verweis reinmachen und den dann (ausnahmsweise) schließen.

@Beta-User: ich war jetzt eine Weile unterwegs un komme erst jetzt dazu, hier wieder zu lesen. Ich habe den Beitrag im Zitat mit einem Querverweis auf diesen Beitrag versehen und geschlossen...
VG

Denis

87insane

#3
Da es hier sehr lange nicht weiter ging, anbei mal meine Interpretation dazu.

1. Shelly via MQTT2 und autocreate rein laufen lasen.
2. devicetopic anpassen auf shelly Name: shellypro3em-123abc
3. jsonMap anlegen:
tC:chip_temperature
tF:0
total_aprt_power:total_apparent_power
total_act_power:total_active_power
a_act_power:a_active_power
a_aprt_power:a_apparent_power
a_freq:a_frequency
a_pf:a_power_factor
a_total_act_energy:a_total_active_power
a_total_act_ret_energy:a_total_active_returned_energy
b_act_power:b_active_power
b_aprt_power:b_apparent_power
b_freq:b_frequency
b_pf:b_power_factor
b_total_act_energy:b_total_active_power
b_total_act_ret_energy:b_total_active_returned_energy
c_act_power:c_active_power
c_aprt_power:c_apparent_power
c_freq:c_frequency
c_pf:c_power_factor
c_total_act_energy:c_total_active_power
c_total_act_ret_energy:c_total_active_returned_energy
4. ReadingsList anpassen
$DEVICETOPIC/online:.* online
  $DEVICETOPIC/status/mqtt:.* { json2nameValue($EVENT, 'mqtt_', $JSONMAP) }
  $DEVICETOPIC/status/sys:.* { json2nameValue($EVENT, 'sys_', $JSONMAP) }
  $DEVICETOPIC/status/cloud:.* {}
  $DEVICETOPIC/rpc:.* { json2nameValue($EVENT, 'req_', $JSONMAP, 'in_mode')}
  $DEVICETOPIC/status/input_0:.* { json2nameValue($EVENT, 'input_', $JSONMAP) }
  fhem2shelly/rpc:.* {}
  $DEVICETOPIC/status:.* {}
  $DEVICETOPIC/status/ble:.* { json2nameValue($EVENT, 'ble_', $JSONMAP) }
  $DEVICETOPIC/status/wifi:.* { json2nameValue($EVENT, 'wifi_', $JSONMAP) }
  $DEVICETOPIC/status/ws:.* { json2nameValue($EVENT, 'ws_', $JSONMAP) }
  $DEVICETOPIC/status/em_0:.* { json2nameValue($EVENT, '', $JSONMAP) }
  $DEVICETOPIC/status/bthome:.* { json2nameValue($EVENT, '', $JSONMAP) }
  $DEVICETOPIC/status/emdata_0:.* { json2nameValue($EVENT, '', $JSONMAP) }
  $DEVICETOPIC/status/eth:.* { json2nameValue($EVENT, '', $JSONMAP) }
  $DEVICETOPIC/status/modbus:.* {}
  $DEVICETOPIC/status/temperature_0:.* { json2nameValue($EVENT, '', $JSONMAP) }
  $DEVICETOPIC/events/rpc:.* {}
5. Wer mag, kann sich noch die kleine setList einbauen:
x_status_update:noArg $DEVICETOPIC/command status_update
  x_update:noArg $DEVICETOPIC/rpc {"id":0,"src":"fhem2shelly","method":"Shelly.Update","params": {"stage":"stable"}}
  x_reboot:noArg $DEVICETOPIC/rpc {"id":0,"src":"fhem2shelly","method":"Shelly.Reboot"}
  x_eco:true,false $DEVICETOPIC/rpc {"id":0,"src":"fhem2shelly","method":"Sys.SetConfig","params": {"config": {"device": {"eco_mode": $EVTPART1}}}}
6. event-on-change-reading minimal auf .* setzen
7. devStateIcon - Und hier wird es spannend. Ich habe mir Hilfe geholt in Form von ChatGPT. Das Aussehen der Tabellen ist angelehnt an das Aussehen innerhalb der Shelly Oberfläche. Hinzu sind hier Spielereien drin wie:
- Wenn Fenster zu klein, schreibe die Tabellen untereinander.
- Es müssen nicht alle Phasen bei Änderungswunsch einzeln angepasst werden.
- ....
{
    # Speichere die Funktionsreferenzen in einem globalen Hash, sodass sie nur einmal initialisiert werden
    $main::DEVSTATEICON_FUNCTIONS ||= {};

    unless (exists $main::DEVSTATEICON_FUNCTIONS->{generate_box}) {
        $main::DEVSTATEICON_FUNCTIONS->{generate_box} = sub {
            my ($title, $content, $ipImage) = @_;
            my $html = "<div style='display:block; border-radius:5px; overflow:hidden; text-align:left; line-height:1; font-size:12px; margin:2px 0;'>";
            $html .= "<div style='background:#f0f0f0; padding:2px;'>";
            $html .= "<span style='color:#000; font-weight:normal; font-size:12px;'>$title</span>";
            if ($ipImage) {
                $html .= "<span style='margin-left:5px; vertical-align:middle;'>$ipImage</span>";
            }
            $html .= "</div>";
            $html .= "<div style='background:#fff; padding:2px;'>$content</div>";
            $html .= "</div>";
            return $html;
        };

        $main::DEVSTATEICON_FUNCTIONS->{generate_content_grid} = sub {
            my @rows = @_;  # Array von [Label, Wert]
            my $html = "<div style='display:grid; grid-template-columns: auto auto; gap:1px; line-height:1; font-size:12px;'>";
            foreach my $row (@rows) {
                my ($label, $value) = @$row;
                $html .= "<div style='padding:1px; text-align:left;'>$label</div>";
                $html .= "<div style='padding:1px; text-align:right;'>$value</div>";
            }
            $html .= "</div>";
            return $html;
        };

        $main::DEVSTATEICON_FUNCTIONS->{generate_phase_box} = sub {
            my ($phase, $voltage, $current, $active, $apparent, $pf, $freq) = @_;
            my $content = $main::DEVSTATEICON_FUNCTIONS->{generate_content_grid}->(
                [ 'Voltage:', "$voltage V" ],
                [ 'Current:', "$current A" ],
                [ 'Active Power:', "$active W" ],
                [ 'Apparent Power:', "$apparent VA" ],
                [ 'Power Factor:', $pf ],
                [ 'Frequency:', "$freq Hz" ]
            );
            return $main::DEVSTATEICON_FUNCTIONS->{generate_box}->("Phase $phase", $content, "");
        };
    }

    # Hole die Funktionsreferenzen aus dem globalen Hash
    my $generate_box           = $main::DEVSTATEICON_FUNCTIONS->{generate_box};
    my $generate_content_grid  = $main::DEVSTATEICON_FUNCTIONS->{generate_content_grid};
    my $generate_phase_box     = $main::DEVSTATEICON_FUNCTIONS->{generate_phase_box};

    my $css = <<'CSS';
<style>
  .responsive-table {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  .responsive-table table {
    width: 100%;
    border-collapse: collapse;
  }
  @media screen and (max-width: 600px) {
    .responsive-table table,
    .responsive-table table th,
    .responsive-table table td {
      font-size: 12px;
    }
  }
</style>
CSS

    # Werte für Total
    my $onl   = ReadingsVal($name, 'online', 'false') eq 'false' ? '10px-kreis-rot' : '10px-kreis-gruen';
    my $ip    = ReadingsVal($name, 'wifi_sta_ip', 'unknown');
    my $tactp = ReadingsVal($name, 'total_active_power', 'ERROR');
    my $toapp = ReadingsVal($name, 'total_apparent_power', 'ERROR');
    my $tcurr = ReadingsVal($name, 'total_current', 'ERROR');

    # Werte für die Phasen
    my $avolt = ReadingsVal($name, 'a_voltage', 'ERROR');
    my $acurr = ReadingsVal($name, 'a_current', 'ERROR');
    my $aactp = ReadingsVal($name, 'a_active_power', 'ERROR');
    my $aappp = ReadingsVal($name, 'a_apparent_power', 'ERROR');
    my $apowf = ReadingsVal($name, 'a_power_factor', 'ERROR');
    my $afreq = ReadingsVal($name, 'a_frequency', 'ERROR');

    my $bvolt = ReadingsVal($name, 'b_voltage', 'ERROR');
    my $bcurr = ReadingsVal($name, 'b_current', 'ERROR');
    my $bactp = ReadingsVal($name, 'b_active_power', 'ERROR');
    my $bappp = ReadingsVal($name, 'b_apparent_power', 'ERROR');
    my $bpowf = ReadingsVal($name, 'b_power_factor', 'ERROR');
    my $bfreq = ReadingsVal($name, 'b_frequency', 'ERROR');

    my $cvolt = ReadingsVal($name, 'c_voltage', 'ERROR');
    my $ccurr = ReadingsVal($name, 'c_current', 'ERROR');
    my $cactp = ReadingsVal($name, 'c_active_power', 'ERROR');
    my $cappp = ReadingsVal($name, 'c_apparent_power', 'ERROR');
    my $cpowf = ReadingsVal($name, 'c_power_factor', 'ERROR');
    my $cfreq = ReadingsVal($name, 'c_frequency', 'ERROR');

    # Erzeuge den Inhalt für die Total-Box als Grid (2 Spalten)
    my $totalContent = $generate_content_grid->(
        [ 'Total Active Power:',   "$tactp W" ],
        [ 'Total Apparent Power:', "$toapp VA" ],
        [ 'Total Current:',        "$tcurr A" ]
    );
    # Status-Icon neben Total (direkt neben der Überschrift)
    my $statusImage = "<a href=\"http://$ip\" target=\"_blank\">" . FW_makeImage($onl) . "</a>";
    my $totalBox    = $generate_box->("Total", $totalContent, $statusImage);

    # Erzeuge die Phase-Boxen
    my $phaseA = $generate_phase_box->("A", $avolt, $acurr, $aactp, $aappp, $apowf, $afreq);
    my $phaseB = $generate_phase_box->("B", $bvolt, $bcurr, $bactp, $bappp, $bpowf, $bfreq);
    my $phaseC = $generate_phase_box->("C", $cvolt, $ccurr, $cactp, $cappp, $cpowf, $cfreq);

    # Gesamt-Layout: Total-Bereich und darunter die Phasen
    my $html = $css;
    $html .= "<div style='display:flex; flex-wrap:wrap; gap:2px;'>";
    $html .= "<div style='flex:0 0 300px;'>$totalBox</div>";
    $html .= "</div>";
    $html .= "<div style='display:flex; flex-wrap:wrap; gap:2px; margin-top:2px;'>";
    $html .= "<div style='flex:0 0 300px;'>$phaseA</div>";
    $html .= "<div style='flex:0 0 300px;'>$phaseB</div>";
    $html .= "<div style='flex:0 0 300px;'>$phaseC</div>";
    $html .= "</div>";

    return $html;
}

Ich habe den Shelly bei mir aktuell nur rum liegen.
Daher erweitere ich das erst, wenn er auch aktiv in Benutzung ist.
Ein Template dafür habe ich nicht erstellt aber zumindest brauch man das hier nur rauß kopieren bzw. den Anweisungen folgen.


Edit: Ich habe das Design nochmal ein wenig angepasst. So ist es in meinen Augen schöner. Der Rest der Funktionen bleibt erhalten. (Bild: NEU_groß.png)