Volkszaehler: Unterschied zwischen den Versionen

Aus FHEMWiki
(→‎Daten mit Volkszaehler loggen: Hinweis darauf, dass 23_VOLKSZAEHLER geladen sein muss, da sonst LWP::UserAgent::get nicht verfügbar ist (Forum #123917))
 
(28 dazwischenliegende Versionen von 6 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
[[Datei:volkszaehler.png]]
{{Infobox Modul
|ModPurpose=Einbindung der Daten von voelkszaehler.org in FHEM
|ModType=x
|ModCmdRef=VOLKSZAEHLER
|ModForumArea=
|ModFTopic=http://forum.fhem.de/index.php/topic,12834.0.html
|ModTechName=23_VOLKSZAEHLER.pm
|ModOwner=({{Link2FU|81|Forum}}/[[Benutzer Diskussion:Bgewehr|Wiki]])
}}
[[Datei:volkszaehler.png|right]]


=Volkszaehler.org Modul für fhem=
Volkszaehler.org ist ein freies SmartMeter Projekt für den Selbstbau ([http://www.volkszaehler.org siehe volkszaehler.org]) Der Nutzer behält dabei die vollständige Kontrolle über die anfallenden Daten seiner Strom-, Wasser- und Gaszähler.


== Was ist ein Volkszaehler? ==
==Features==
volkszaehler.org ist ein freies Smart Meter im Selbstbau. [http://www.volkszaehler.org siehe volkszaehler.org]
* 100% Open-Source
Der Nutzer behält dabei die vollständige Kontrolle über die anfallenden Daten seiner Strom-, Wasser- & Gaszähler.
* kostenlos
* offene Protokolle
* erweiterbar
* minmale Anforderungen (LAMP-Stack)
* flexibele Verwaltungsmöglichkeiten
* Verbrauchs & Kostenprognose
* verschiedenste Messgrößen
** Strom
** Wasser
** Gas
** Betriebsstunden
** Temperatur
* Läuft u. a. auf Raspberry Pi ([http://wiki.volkszaehler.org/howto/raspberry_pi_image Installationsbeschreibung)]


===Features===
== Volkszaehler in FHEM einbinden ==
*100% Open-Source
*kostenlos
*offene Protokolle
*erweiterbar
*minmale Anforderungen (LAMP-Stack)
*flexibele Verwaltungsmöglichkeiten
*Verbrauchs & Kostenprognose
*verschiedenste Messgrößen
**Strom
**Wasser
**Gas
**Betriebsstunden
**Temperatur
*Läuft u. a. auf Raspberry Pi [http://wiki.volkszaehler.org/howto/raspberry_pi_image Volkszaehler-Installation auf einem Raspberry Pi]


==Volkszaehler in fhem einbinden==
Das FHEM-Modul für Volkszaehler.org bindet diese Daten in FHEM ein. Das Modul 23_VOLKSZAEHLER.pm greift per http auf den Volkszaehler zu und interpretiert die JSON-Antwort in FHEM-device-Readings. Daraus können Logs und Plots gebildet werden oder devices mit Kennzahlen aus den Volkszaehler-Daten.


Das fhem-Modul für Volkszaehler.org bindet diese Daten in fhem ein. Das Modul 23_volkszaehler.pm greift per http auf den Volkszaehler zu und interpretiert die JSON - Antwort in fhem-device-Readings. Daraus können logs und plots gebildet werden oder devices mit Kennzahlen aus den Volkszaehler-Daten.  
Es ist z. B. für Solarstrom-Anlagenbesitzer denkbar, bei hoher verfügbarer Sonnenenergie mit FHEM Verbraucher einzuschalten, um die Eigenverbrauchsrate zu erhöhen, was die Energiekosten reduziert.


Es ist für Solarstrom-Anlagenbesitzer auch denkbar, bei hoher verfügbarer Sonnenenergie mit fhem Verbraucher einzuschalten, um die Eigenverbrauchsrate zu erhöhen, was die Energiekosten reduziert.
== Installation ==
==Installation==
Für die Installation müssen einige Files heruntergeladen und in die richtigen Verzeichnisse kopiert werden.
 
=== FHEM-Modul ===
 
Meine aktuellen Versionen liegen hier: <code>https://github.com/bgewehr/fhem</code>


Für die Installation müssen einige Files heruntergeladen und in die richtigen Verzeichnisse kopiert werden.
Die Datei <code>23_VOLKSZAEHLER.pm</code> kommt ins Verzeichnis <code>../fhem/FHEM</code>


===fhem-Modul===
Die Datei <code>volkszaehler.gplot</code> kommt ins Verzeichnis <code>../fhem/www/gplot</code>
Meine aktuellen Versionen liegen hier:
https://github.com/bgewehr/fhem


Das File 23_VOLKSZAEHLER.pm kommt ins Verzeichnis \\fritz.box\FRITZ.NAS\fhem\fhem\
Nur zur Sicherheit: Um die Dateien auf einem Windows-Rechner lokal zu erstellen, bitte den Text aus der "raw" Ansicht aus Github kopieren und bitte nicht in Notepad, sondern in z. B. [http://www.heise.de/download/notepad.html Notepad++] einfügen und dann unter dem richtigen Dateinamen speichern. Mit Notepad von Microsoft werden falsche Zeilenenden erzeugt, die dann unter Linux nicht funktionieren.
Das File volkszaehler.gplot kommt ins Verzeichnis \\fritz.box\FRITZ.NAS\fhem\fhem\www\gplot


===JSON für Perl===
=== JSON für Perl ===
Das Modul nutzt einen JSON-Interpreter, um die Antwort vom Volkszaehler in eine PERL-Variable zu wandeln. Dazu sind einige zusätzliche PERL Module notwendig.
Das Modul nutzt einen JSON-Interpreter, um die Antwort vom Volkszaehler in eine PERL-Variable zu wandeln. Dazu ist ein zusätzliches PERL Modul notwendig.


JSON für PERL kann von hier geladen werden:
#> cpan JSON
http://cpansearch.perl.org/src/MAKAMAKA/JSON-1.15/lib/JSON/


Das File JSON.pm muss in \\fritz.box\FRITZ.NAS\fhem\lib\perl5\site_perl\5.12.2\mips-linux\
sollte alle nötigen Dateien installieren.  
Die Files Converter.pm und Parser.pm habe ich in \\fritz.box\FRITZ.NAS\fhem\lib\perl5\site_perl\5.12.2\mips-linux\ ins neue Verzeichnis JSON kopiert.


Auf anderen Plattformen sind die Pfade sicher ähnlich.
Hinweis zur Fritz!Box:
Da die Fritz!Box inzwischen nicht mehr für FHEM taugt, habe ich die für diese Installation nötigen beonderen JSON files hier nicht mehr aufgelistet. Auch die aktuelle Version meines Moduls greift auf das aktuelle JSON Perl Modul zurück und wird so auf einer Fritz!Box nicht mehr laufen.


==Definition der devices==
== Definition der devices ==
Die Device-Definitionen werden in einer [[Konfiguration]] (üblicherweise fhem.cfg) angelegt
:<code>define <name> VOLKSZAEHLER <ip-address> <port-nr> <channel> <state:last/min/max/average/consumption> <poll-delay></code>


  define <name> VOLKSZAEHLER <ip-address> <port-nr> <channel> <state:last/min/max/average/consumption> <poll-delay>
* <name>: Name des neuen FHEM-devices
* <ip-address>: IP des Volkszaehlers
* <port-Nr>: Port, auf dem der Volkszaehler-http-Server erreichtbar ist
* <channel>: UUID des Volkszaehler-Frontend-Channels, der gelesen werden soll
* <state>: Das Reading, welches als state genommen werden soll, kann im define gewählt werden. Dabei besteht die Auswahl aus
** last (letzter geladener Wert, manchmal leer bei zu kleinem poll-delay)
** min (kleinster Wert innerhalb des poll-delay, manchmal leer bei zu kleinem poll-delay)
** max (größter Wert innerhalb des poll-delay, manchmal leer bei zu kleinem poll-delay)
** average (Durchschnitt der Werte im poll-delay, manchmal leer bei zu kleinem poll-delay)
** consumption (Verbrauch innerhalb des poll-delays, manchmal leer bei zu kleinem poll-delay)
* <poll-delay>: Zeitraum, der ausgelesen werden soll in Sekunden


*<name>: Name des neuen fhem-devices
== Beispiele ==
*<ip-address>: IP des Volkszaehlers
Ein vollständiges Beispiel für die erforderlichen Definitionen und das daraus resultierende Ergebnis:
*<port-Nr>: Port, auf dem der Volkszaehler-http-Server erreichtbar ist
*<channel>: UUID des Volkszaehler-Frontend-Channels, der gelesen werden soll
*<state>: Das Reading, welches als state genommen werden soll, kann im define gewählt werden. Dabei besteht die Auswahl aus
**last (letzter geladener Wert, manchmal leer bei zu kleinem poll-delay)
**min (kleinster Wert innerhalb des poll-delay, manchmal leer bei zu kleinem poll-delay)
**max (größter Wert innerhalb des poll-delay, manchmal leer bei zu kleinem poll-delay)
**average (Durchschnitt der Werte im poll-delay, manchmal leer bei zu kleinem poll-delay)
**consumption (Verbrauch innerhalb des poll-delays, manchmal leer bei zu kleinem poll-delay)
*<poll-delay>: Zeitraum, der ausgelesen werden soll


==Beispiele:==
=== Momentanverbrauch ===
Kanal im Volkszaehler, der den Momentanverbrauch per I/R-Lesekopf ermittelt (alle 60 Sekunden, daraus der Mittelwert)


===Kanal im Volkszaehler, der den Momentanverbrauch per I/R-Lesekopf ermittelt, alle 60 Sekunden davon der Mittelwert ===
   define Verbrauch_aktuell VOLKSZAEHLER 192.168.178.45 80 635481a0-6fcd-11e2-8587-eda25228f8bf average 60
   define Verbrauch_aktuell VOLKSZAEHLER 192.168.178.45 80 635481a0-6fcd-11e2-8587-eda25228f8bf average 60
  attr Verbrauch_aktuell delay 60
   attr Verbrauch_aktuell group Strom
   attr Verbrauch_aktuell group Strom
   attr Verbrauch_aktuell room Volkszaehler
   attr Verbrauch_aktuell room Volkszaehler


===In fhem loggen, um einen Graphen daraus zu zeigen ===
=== Logdatei ===
Definition der Logdatei, aus der die Grafik erzeugt werden kann:
 
   define FileLog_Verbrauch_aktuell FileLog ./log/Verbrauch_aktuell-%Y-%m.log Verbrauch_aktuell
   define FileLog_Verbrauch_aktuell FileLog ./log/Verbrauch_aktuell-%Y-%m.log Verbrauch_aktuell
  attr FileLog_Verbrauch_aktuell group Volkszaehler
   attr FileLog_Verbrauch_aktuell logtype text
   attr FileLog_Verbrauch_aktuell logtype text
   attr FileLog_Verbrauch_aktuell room Z_Log
   attr Verbrauch_aktuell room Volkszaehler


===der Graph dazu===
=== Der Graph dazu ===
   define FilePlot_Verbrauch_aktuell weblink fileplot FileLog_Verbrauch_aktuell:Volkszaehler:CURRENT
   define FilePlot_Verbrauch_aktuell weblink fileplot FileLog_Verbrauch_aktuell:Volkszaehler:CURRENT
   attr FilePlot_Verbrauch_aktuell label "Stromverbrauch: $data{currval1}"
   attr FilePlot_Verbrauch_aktuell label "Stromverbrauch: $data{currval1}"
   attr FilePlot_Verbrauch_aktuell room Volkszaehler
   attr FilePlot_Verbrauch_aktuell room Volkszaehler


===Kanal im Volkszaehler, der den Zählerstand per I/R-Lesekopf ermittelt, jede Stunde davon der letzte Wert ===
=== Zählerstand ===
Kanal im Volkszaehler, der den Zählerstand per I/R-Lesekopf ermittelt, jede Stunde davon der letzte Wert.
 
   define Zaehlerstand VOLKSZAEHLER 192.168.178.45 80 ebb9c9b0-7058-11e2-b5ed-d12ec87a3a7f last 1800
   define Zaehlerstand VOLKSZAEHLER 192.168.178.45 80 ebb9c9b0-7058-11e2-b5ed-d12ec87a3a7f last 1800
  attr Zaehlerstand delay 1800
   attr Zaehlerstand group Strom
   attr Zaehlerstand group Strom
   attr Zaehlerstand room Volkszaehler
   attr Zaehlerstand room Volkszaehler


===Kanal im Volkszaehler, der den Zählerstand per I/R-Lesekopf ermittelt, alle 24 Stunden davon der Verbrauch ===
=== Verbrauch ===
Kanal im Volkszaehler, der den Zählerstand per I/R-Lesekopf ermittelt, alle 24 Stunden davon der Verbrauch.
 
   define Verbrauch_24h VOLKSZAEHLER 192.168.178.45 80 635481a0-6fcd-11e2-8587-eda25228f8bf consumption 86400
   define Verbrauch_24h VOLKSZAEHLER 192.168.178.45 80 635481a0-6fcd-11e2-8587-eda25228f8bf consumption 86400
   attr Verbrauch_24h group Strom
   attr Verbrauch_24h group Strom
   attr Verbrauch_24h room Volkszaehler
   attr Verbrauch_24h room Volkszaehler


===Beispiel-Ergebnis===
=== Ergebnis ===
Als Ergebnis erhält man (z. B.) folgendes:
[[Datei:23_volkszaehler.JPG|mini|zentriert|hochkant=3.0|Strom- und Gasverbrauch aus Volkszählerdaten generiert - Beispieldarstellung]]
 
== Daten mit Volkszaehler loggen ==
Hier eine Möglichkeit mit einem notify Temperaturen (oder andere Messwerte) an die Middelware vom Volkszaehler zu schicken um die Daten über ein Volkszaehler Frontend auswerten zu können ('''Achtung''': folgender Kode-Schnipsel funktioniert nur, wenn 23_VOLKSZAEHLER installiert und geladen wurde): 
<syntaxhighlight lang="Perl">
  .*:temperature.* {
    # return "Heizung $NAME" if $NAME =~ /\A.{3}Heizung/; # [[MAX]] Geräte ausschließen. Workaround für aufgebrauchte credits.
    my $base_url = AttrVal('vz', 'vz_URL', undef);
    my $temp = ReadingsVal($NAME, 'temperature', undef);
    my $uuid = AttrVal($NAME, 'vz_UUID', undef);
    unless (defined($uuid)) {
      my $create_url = $base_url . '/channel.json?type=temperature&title=' . $NAME . '&public=on&style=lines&operation=add';
      Log 5, $create_url;
      my $response = decode_json(get($create_url));
      $uuid = $response->{entity}->{uuid};
      $attr{$NAME}{'vz_UUID'} = $uuid;
      Log 4, "created $uuid for $NAME";
    }
    my $update_url = $base_url . '/data/' . $uuid . '.json?operation=add&value=' . $temp;
    Log 5, $update_url;
    Log 4, get($update_url);
  }
</syntaxhighlight>
 
Der Volkszaehler-URL wird in einem Attribut (vz_URL) eines [[dummy|dummies]] gespeichert, welches vorher angelegt werden muss.
 
Jedes Thermometer, das auch im Volkszaehler erscheinen soll, muss nun nur noch im Volkszaehler angelegt werden und die UUID als Attribut (vz_UUID) des Thermometers gespeichert werden. Dieser Schritt kann auch ausgelassen werden. In diesem Fall wird ein neues Thermometer automatisch angelegt.
 
  define vz dummy
  attr vz vz_URL http://localhost/volkszaehler.org/htdocs/middleware.php
  attr vz vz_UUID XXXXXXXXXXXXXXXXXXXXXXXXXXX


[[Datei:23_volkszaehler.JPG]]
== Links ==
* Volkszähler [http://www.volkszaehler.org Homepage]
* [https://github.com/bgewehr/fhem FHEM Module] für Volkszähler von "bgewehr"


[[Kategorie:Other Components]]
[[Kategorie:Other Components]]
[[Kategorie:HOWTOS]]
[[Kategorie:HOWTOS]]
[[Kategorie:Energieverbrauchsmessung]]

Aktuelle Version vom 5. November 2021, 20:47 Uhr

VOLKSZAEHLER
Zweck / Funktion
Einbindung der Daten von voelkszaehler.org in FHEM
Allgemein
Typ Inoffiziell
Details
Dokumentation Thema
Modulname 23_VOLKSZAEHLER.pm
Ersteller (Forum /Wiki)
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref!
Volkszaehler.png

Volkszaehler.org ist ein freies SmartMeter Projekt für den Selbstbau (siehe volkszaehler.org) Der Nutzer behält dabei die vollständige Kontrolle über die anfallenden Daten seiner Strom-, Wasser- und Gaszähler.

Features

  • 100% Open-Source
  • kostenlos
  • offene Protokolle
  • erweiterbar
  • minmale Anforderungen (LAMP-Stack)
  • flexibele Verwaltungsmöglichkeiten
  • Verbrauchs & Kostenprognose
  • verschiedenste Messgrößen
    • Strom
    • Wasser
    • Gas
    • Betriebsstunden
    • Temperatur
  • Läuft u. a. auf Raspberry Pi (Installationsbeschreibung)

Volkszaehler in FHEM einbinden

Das FHEM-Modul für Volkszaehler.org bindet diese Daten in FHEM ein. Das Modul 23_VOLKSZAEHLER.pm greift per http auf den Volkszaehler zu und interpretiert die JSON-Antwort in FHEM-device-Readings. Daraus können Logs und Plots gebildet werden oder devices mit Kennzahlen aus den Volkszaehler-Daten.

Es ist z. B. für Solarstrom-Anlagenbesitzer denkbar, bei hoher verfügbarer Sonnenenergie mit FHEM Verbraucher einzuschalten, um die Eigenverbrauchsrate zu erhöhen, was die Energiekosten reduziert.

Installation

Für die Installation müssen einige Files heruntergeladen und in die richtigen Verzeichnisse kopiert werden.

FHEM-Modul

Meine aktuellen Versionen liegen hier: https://github.com/bgewehr/fhem

Die Datei 23_VOLKSZAEHLER.pm kommt ins Verzeichnis ../fhem/FHEM

Die Datei volkszaehler.gplot kommt ins Verzeichnis ../fhem/www/gplot

Nur zur Sicherheit: Um die Dateien auf einem Windows-Rechner lokal zu erstellen, bitte den Text aus der "raw" Ansicht aus Github kopieren und bitte nicht in Notepad, sondern in z. B. Notepad++ einfügen und dann unter dem richtigen Dateinamen speichern. Mit Notepad von Microsoft werden falsche Zeilenenden erzeugt, die dann unter Linux nicht funktionieren.

JSON für Perl

Das Modul nutzt einen JSON-Interpreter, um die Antwort vom Volkszaehler in eine PERL-Variable zu wandeln. Dazu ist ein zusätzliches PERL Modul notwendig.

  1. > cpan JSON

sollte alle nötigen Dateien installieren.

Hinweis zur Fritz!Box: Da die Fritz!Box inzwischen nicht mehr für FHEM taugt, habe ich die für diese Installation nötigen beonderen JSON files hier nicht mehr aufgelistet. Auch die aktuelle Version meines Moduls greift auf das aktuelle JSON Perl Modul zurück und wird so auf einer Fritz!Box nicht mehr laufen.

Definition der devices

Die Device-Definitionen werden in einer Konfiguration (üblicherweise fhem.cfg) angelegt

define <name> VOLKSZAEHLER <ip-address> <port-nr> <channel> <state:last/min/max/average/consumption> <poll-delay>
  • <name>: Name des neuen FHEM-devices
  • <ip-address>: IP des Volkszaehlers
  • <port-Nr>: Port, auf dem der Volkszaehler-http-Server erreichtbar ist
  • <channel>: UUID des Volkszaehler-Frontend-Channels, der gelesen werden soll
  • <state>: Das Reading, welches als state genommen werden soll, kann im define gewählt werden. Dabei besteht die Auswahl aus
    • last (letzter geladener Wert, manchmal leer bei zu kleinem poll-delay)
    • min (kleinster Wert innerhalb des poll-delay, manchmal leer bei zu kleinem poll-delay)
    • max (größter Wert innerhalb des poll-delay, manchmal leer bei zu kleinem poll-delay)
    • average (Durchschnitt der Werte im poll-delay, manchmal leer bei zu kleinem poll-delay)
    • consumption (Verbrauch innerhalb des poll-delays, manchmal leer bei zu kleinem poll-delay)
  • <poll-delay>: Zeitraum, der ausgelesen werden soll in Sekunden

Beispiele

Ein vollständiges Beispiel für die erforderlichen Definitionen und das daraus resultierende Ergebnis:

Momentanverbrauch

Kanal im Volkszaehler, der den Momentanverbrauch per I/R-Lesekopf ermittelt (alle 60 Sekunden, daraus der Mittelwert)

 define Verbrauch_aktuell VOLKSZAEHLER 192.168.178.45 80 635481a0-6fcd-11e2-8587-eda25228f8bf average 60
 attr Verbrauch_aktuell group Strom
 attr Verbrauch_aktuell room Volkszaehler

Logdatei

Definition der Logdatei, aus der die Grafik erzeugt werden kann:

 define FileLog_Verbrauch_aktuell FileLog ./log/Verbrauch_aktuell-%Y-%m.log Verbrauch_aktuell
 attr FileLog_Verbrauch_aktuell logtype text
 attr Verbrauch_aktuell room Volkszaehler

Der Graph dazu

 define FilePlot_Verbrauch_aktuell weblink fileplot FileLog_Verbrauch_aktuell:Volkszaehler:CURRENT
 attr FilePlot_Verbrauch_aktuell label "Stromverbrauch: $data{currval1}"
 attr FilePlot_Verbrauch_aktuell room Volkszaehler

Zählerstand

Kanal im Volkszaehler, der den Zählerstand per I/R-Lesekopf ermittelt, jede Stunde davon der letzte Wert.

 define Zaehlerstand VOLKSZAEHLER 192.168.178.45 80 ebb9c9b0-7058-11e2-b5ed-d12ec87a3a7f last 1800
 attr Zaehlerstand group Strom
 attr Zaehlerstand room Volkszaehler

Verbrauch

Kanal im Volkszaehler, der den Zählerstand per I/R-Lesekopf ermittelt, alle 24 Stunden davon der Verbrauch.

 define Verbrauch_24h VOLKSZAEHLER 192.168.178.45 80 635481a0-6fcd-11e2-8587-eda25228f8bf consumption 86400
 attr Verbrauch_24h group Strom
 attr Verbrauch_24h room Volkszaehler

Ergebnis

Strom- und Gasverbrauch aus Volkszählerdaten generiert - Beispieldarstellung

Daten mit Volkszaehler loggen

Hier eine Möglichkeit mit einem notify Temperaturen (oder andere Messwerte) an die Middelware vom Volkszaehler zu schicken um die Daten über ein Volkszaehler Frontend auswerten zu können (Achtung: folgender Kode-Schnipsel funktioniert nur, wenn 23_VOLKSZAEHLER installiert und geladen wurde):

   .*:temperature.* {
    # return "Heizung $NAME" if $NAME =~ /\A.{3}Heizung/; # [[MAX]] Geräte ausschließen. Workaround für aufgebrauchte credits.
    my $base_url = AttrVal('vz', 'vz_URL', undef);
    my $temp = ReadingsVal($NAME, 'temperature', undef);
    my $uuid = AttrVal($NAME, 'vz_UUID', undef);
    unless (defined($uuid)) {
      my $create_url = $base_url . '/channel.json?type=temperature&title=' . $NAME . '&public=on&style=lines&operation=add';
      Log 5, $create_url;
      my $response = decode_json(get($create_url));
      $uuid = $response->{entity}->{uuid};
      $attr{$NAME}{'vz_UUID'} = $uuid;
      Log 4, "created $uuid for $NAME";
    }
    my $update_url = $base_url . '/data/' . $uuid . '.json?operation=add&value=' . $temp;
    Log 5, $update_url;
    Log 4, get($update_url);
  }

Der Volkszaehler-URL wird in einem Attribut (vz_URL) eines dummies gespeichert, welches vorher angelegt werden muss.

Jedes Thermometer, das auch im Volkszaehler erscheinen soll, muss nun nur noch im Volkszaehler angelegt werden und die UUID als Attribut (vz_UUID) des Thermometers gespeichert werden. Dieser Schritt kann auch ausgelassen werden. In diesem Fall wird ein neues Thermometer automatisch angelegt.

 define vz dummy
 attr vz vz_URL http://localhost/volkszaehler.org/htdocs/middleware.php
 attr vz vz_UUID XXXXXXXXXXXXXXXXXXXXXXXXXXX

Links