FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: maddhin am 14 Oktober 2017, 16:29:24

Titel: Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 14 Oktober 2017, 16:29:24
Hi,

ich möchte aus gemessenen Feinstaubwerten den bzw: einen Air Quality Index / AQI berechnen. Da gibt es bei Wiki (https://en.wikipedia.org/wiki/Air_quality_index (https://en.wikipedia.org/wiki/Air_quality_index)) eine Formel mit der ich auch soweit zurechtkomme (density ist hier der Feinstaubwert):


###############################################################################
#
#  PM in ug/m3 to AQI (US)
#
#  Aufruf: PMtoAQIus(devicename,readingname)
#
###############################################################################

sub PMtoAQIus($$$){
   my ($name,$reading) = @_;


// AQI formula: https://en.wikipedia.org/wiki/Air_Quality_Index#United_States
int toAQI(int I_high, int I_low, int C_high, int C_low, int C) {
return (I_high - I_low) * (C - C_low) / (C_high - C_low) + I_low;
}

//thanks to https://gist.github.com/nfjinjing/8d63012c18feea3ed04e
int calculateAQI25(float density) {
int d10 = (int)(density * 10);
if (d10 <= 0) {
return 0;
} else if(d10 <= 120) {
return toAQI(50, 0, 120, 0, d10);
} else if (d10 <= 354) {
return toAQI(100, 51, 354, 121, d10);
} else if (d10 <= 554) {
return toAQI(150, 101, 554, 355, d10);
} else if (d10 <= 1504) {
return toAQI(200, 151, 1504, 555, d10);
} else if (d10 <= 2504) {
return toAQI(300, 201, 2504, 1505, d10);
} else if (d10 <= 3504) {
return toAQI(400, 301, 3504, 2505, d10);
} else if (d10 <= 5004) {
return toAQI(500, 401, 5004, 3505, d10);
} else if (d10 <= 10000) {
return toAQI(1000, 501, 10000, 5005, d10);
} else {
return 1001;
}
}


Aber voran ich verzweifle ist das in FHEM zu bekommen. Eigentlich ja eine recht simple Funktion, aber ich kann absolut kein Perl. Ich habe versucht das anhand von z.B. der "movingAverage" Funktion, die ich in FHEM nutze, analog irgendwie hinzubekommen, aber ich müsste mich jetzt erstmal ein paar Tage hinsetzen und Perl lernen um halbwegs zu verstehen, was da eigentlich was ist.

Könnte mir jemand helfen und hier die Funktion und Variablen definieren damit ich das in die 99_MyUtils machen kann? Dann sollte ich an der Formel, etc selbst weiterbasteln können:)

Das wäre genial, ganz lieben Dank im Voraus!
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: igami am 14 Oktober 2017, 18:08:53
Na das sieht doch mal interessant aus. Gucke ich mir mal an :)
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 14 Oktober 2017, 18:31:08
Zitat von: igami am 14 Oktober 2017, 18:08:53
Na das sieht doch mal interessant aus. Gucke ich mir mal an :)

Super! Ich wollte eine PM -> AQI und AQI -> PM Funktion machen, dann kann man Werte vergleichen. Ggf. kann man dann auch mit unterschiedlichen Indizes arbeiten.

http://www.aqicn.org (http://www.aqicn.org) einige gute Tools & Info (und auch API um Werte zu holen). Da kann man auch online umrechnen und die Formel testen:)

Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: igami am 14 Oktober 2017, 18:38:35

sub myUtils_PM10_to_AQI(@_) {
  my ($C) = @_;
  my ($I_high, $I_low, $C_high, $C_low);

  return unless(looks_like_number($C));

  if($C < 55){
    $I_high =   0 ;
    $I_low  =  50 ;
    $C_high =   0 ;
    $C_low  =  54 ;
  }
  elsif($C < 155){
    $I_high =  51 ;
    $I_low  = 100 ;
    $C_high =  55 ;
    $C_low  = 154 ;   
  }
  elsif($C < 255){
    $I_high = 101 ;
    $I_low  = 150 ;
    $C_high = 155 ;
    $C_low  = 254 ;   
  }
  elsif($C < 355){
    $I_high = 151 ;
    $I_low  = 200 ;
    $C_high = 255 ;
    $C_low  = 354 ;   
  }
  elsif($C < 425){
    $I_high = 201 ;
    $I_low  = 300 ;
    $C_high = 355 ;
    $C_low  = 424  ;   
  }
  elsif($C < 505){
    $I_high = 301 ;
    $I_low  = 400 ;
    $C_high = 425 ;
    $C_low  = 504 ;   
  }
  elsif($C < 605){
    $I_high = 401 ;
    $I_low  = 500 ;
    $C_high = 505 ;
    $C_low  = 604 ;   
  }
  else{
    return;   
  }

  my $I = ($I_high - $I_low) / ($C_high - $C_low) * ($C - $C_low) + $I_low;

  return($I);
}


Im Feinstaubsensor dann noch folgende Attribute setzen:

attr <name> event-aggregator PM10_24h::linear:mean:86400
attr <name> userReadings AQI {myUtils_PM10_to_AQI(ReadingsNum($name, "PM10_24h", 0))},\
PM10_24h:PM10:.* {ReadingsNum($name, "PM10", 0)}
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 14 Oktober 2017, 18:46:18
Genial, DANKE!
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 15 Oktober 2017, 09:17:49
in dem ersten Skript waren die highs und lows vertauscht.

hier nun die fertigen Funktionen:



##########################################################
# PM10 to AQI(US)
# berechnet den Air Quality Index nach US Standard
# siehe https://en.wikipedia.org/wiki/Air_quality_index
##########################################################

sub myUtils_PM10_to_usAQI(@_) {
  my ($C) = @_;
  my ($I_high, $I_low, $C_high, $C_low);

  return unless(looks_like_number($C));

  if($C < 55){
    $I_high =  50 ;
    $I_low  =   0 ;
    $C_high =  54 ;
    $C_low  =   0 ;
  }
  elsif($C < 155){
    $I_high = 100 ;
    $I_low  =  51 ;
    $C_high = 154 ;
    $C_low  =  55 ;   
  }
  elsif($C < 255){
    $I_high = 150 ;
    $I_low  = 101 ;
    $C_high = 254 ;
    $C_low  = 155 ;   
  }
  elsif($C < 355){
    $I_high = 200 ;
    $I_low  = 151 ;
    $C_high = 354 ;
    $C_low  = 255 ;   
  }
  elsif($C < 425){
    $I_high = 300 ;
    $I_low  = 201 ;
    $C_high = 424 ;
    $C_low  = 355  ;   
  }
  elsif($C < 505){
    $I_high = 400 ;
    $I_low  = 301 ;
    $C_high = 504 ;
    $C_low  = 425 ;   
  }
  elsif($C < 605){
    $I_high = 500 ;
    $I_low  = 401 ;
    $C_high = 604 ;
    $C_low  = 505 ;   
  }
  else{
    return;   
  }

  my $I = ($I_high - $I_low) / ($C_high - $C_low) * ($C - $C_low) + $I_low;
  my $I = int($I);
  return($I);
}

##########################################################

##########################################################
# PM2.5 to AQI(US)
# berechnet den Air Quality Index nach US Standard
# siehe https://en.wikipedia.org/wiki/Air_quality_index
##########################################################

sub myUtils_PM25_to_usAQI(@_) {
  my ($C) = @_;
  my ($I_high, $I_low, $C_high, $C_low);

  return unless(looks_like_number($C));

  if($C < 12.1){
    $I_high =  50 ;
    $I_low  =   0 ;
    $C_high =  12 ;
    $C_low  =   0 ;
  }
  elsif($C < 35.5){
    $I_high = 100 ;
    $I_low  =  51 ;
    $C_high = 35.4 ;
    $C_low  = 12.1 ;   
  }
  elsif($C < 55.5){
    $I_high = 150 ;
    $I_low  = 101 ;
    $C_high = 55.4 ;
    $C_low  = 35.5 ;   
  }
  elsif($C < 150.5){
    $I_high = 200 ;
    $I_low  = 151 ;
    $C_high = 150.4 ;
    $C_low  = 55.5 ;   
  }
  elsif($C < 250.5){
    $I_high = 300 ;
    $I_low  = 201 ;
    $C_high = 250.4 ;
    $C_low  = 150.5 ;   
  }
  elsif($C < 350.5){
    $I_high = 400 ;
    $I_low  = 301 ;
    $C_high = 350.4 ;
    $C_low  = 250.5 ;   
  }
  elsif($C < 500.5){
    $I_high = 500 ;
    $I_low  = 401 ;
    $C_high = 500.4 ;
    $C_low  = 350.5 ;   
  }
  else{
    return;   
  }

  my $I = ($I_high - $I_low) / ($C_high - $C_low) * ($C - $C_low) + $I_low;
  my $I = int($I);
  return($I);
}

##########################################################


Ich habe das kurz getestet und es scheint alles zu funktionieren. Muss aber jetzt eine Weile damit spielen.

Den 24h Durchschnitt habe ich erstmal nicht genommen - das ist eine philosophische Frage, ob das Sinn macht. Denn wenn Wind aufkommt kann die Luft ja schon in ein paar Minuten sauber sein, aber der Index würde Stunden(?) brauchen, um das abzubilden...

Mir ging es hier primär darum, Werte vergleichen zu können.

Ich beschäftige mich weiter damit und poste ggf. Weiteres. Ansonsten PM an mich. Wenn das generell von Interesse ist kann ich das alles auch mal irgendwie posten.

@igami: super, herzlichen Dank für Deine Hilfe!


Ich versuche im Moment auch, externe AQI Werte via JSON zu bekommen (https://forum.fhem.de/index.php/topic,38463.msg699578.html#msg699578 (https://forum.fhem.de/index.php/topic,38463.msg699578.html#msg699578)), ab er das ist nicht so einfach.

Ggf. kann man das Ganze auch mit LuftdatenInfo verbinden, da muss ich aber auch erst gucken, was/wie das Sinn macht. Aber sicherlich haben die doch auch eine Art Index mit schönen Farbdefinitionen :)

Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 15 Oktober 2017, 09:34:22
Etwas off topic aber:

AQIcn.org (z.B. http://aqicn.org/city/germany/berlin/ (http://aqicn.org/city/germany/berlin/)) hat wirklich sehr schöne Widgets (siehe http://aqicn.org/faq/2015-07-28/air-quality-widget-new-improved-feed/ (http://aqicn.org/faq/2015-07-28/air-quality-widget-new-improved-feed/), die kann man toll in TabletUI einbauen, etc.

Die sind Teil des World Air Quality Index Projects. Wäre eigentlich genial, wenn man so auch die LuftdatenInfo Daten bekommen könnte.
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 15 Oktober 2017, 09:56:18
zu den Funktionen bekomme ich noch ein paar Fehlermeldungen:

2017.10.15 15:44:48 1: PERL WARNING: Prototype after '@' for main::myUtils_PM10_to_usAQI : @_ at /usr/share/fhem/FHEM/99_MyUtils.pm line 110.
2017.10.15 15:44:48 1: PERL WARNING: "my" variable $I masks earlier declaration in same scope at /usr/share/fhem/FHEM/99_MyUtils.pm line 163.
2017.10.15 15:44:48 1: PERL WARNING: Prototype after '@' for main::myUtils_PM25_to_usAQI : @_ at /usr/share/fhem/FHEM/99_MyUtils.pm line 175.
2017.10.15 15:44:48 1: PERL WARNING: "my" variable $I masks earlier declaration in same scope at /usr/share/fhem/FHEM/99_MyUtils.pm line 228.


Scheint nicht kritisch zu sein, aber macht wohl Sinn das noch aufzuräumen;)
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: igami am 15 Oktober 2017, 10:03:30
mach mal "sub myUtils_PM10_to_AQI($)" draus und lass das my vor dem zweiten $I weg.
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 15 Oktober 2017, 13:16:30
Danke! Da habe ich heute ja doch etwas Perl gelernt! ;)

Habe noch die entsprechenden Kategorien als Funktion hinzugefügt:

##########################################################
# AQI(US) Category
#
# siehe https://en.wikipedia.org/wiki/Air_quality_index
##########################################################

sub myUtils_usAQI_cat($) {
  my ($AQI) = @_;
  my ($cat);

  return unless(looks_like_number($AQI));

  if($AQI < 50) { $cat = "Good"}
  elsif($AQI < 100) { $cat = "Moderate"}
  elsif($AQI < 150) { $cat = "Unhealthy for Sensitive Groups"}
  elsif($AQI < 200) { $cat = "Unhealthy"}
  elsif($AQI < 300) { $cat = "Very Unhealthy"}
  elsif($AQI < 400) { $cat = "Hazardous"}
  elsif($AQI < 500) { $cat = "Hazardous"}

  else{return;}

  return($cat);
}

##########################################################


und rufe das Ganze über ein Userreading mit:

usAQI25 {myUtils_PM25_to_usAQI(ReadingsNum($name, "PM2.5", 0))},
usAQI25_cat {myUtils_usAQI_cat(ReadingsNum($name, "usAQI25", 0))},
usAQI10 {myUtils_PM10_to_usAQI(ReadingsNum($name, "PM10", 0))},
usAQI10_cat {myUtils_usAQI_cat(ReadingsNum($name, "usAQI10", 0))}


ab.
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 18 Oktober 2017, 08:35:11
Ein kurzer Tip falls jemand die AQIcn.org JSON API (http://www.aqicn.org/api/ (http://www.aqicn.org/api/)) nutzen möchte um Feinstaubwerte abzufragen:

Zuerst einen Token holen und dann super komfortabel mit dem Modul JSONREADINGS.PM (https://forum.fhem.de/index.php/topic,38463.0.html) via

https://api.waqi.info/feed/@YYYY/?token=XXX
die Daten abfragen.

Zum Testen kann man https://api.waqi.info/feed/shanghai/?token=demo nehmen. Aber Achtung: mit dem Token scheint dann eine Abfrage via Städtenamen nicht zu funktionieren!

@YYYY ist der IDX Code der Stadt (Berlin beispielsweise @6132) - der IDX Code ist nicht ganz einfach zu finden, ich habe die gesuchte Stadt via Browser aufgerufen und mir mit  "Seitenquelltext anzeigen" den HTML Code angesehen und nach "idx" gesucht.

XXX ist der token, den ihr nach Anmeldung via Email bekommt.

Mal abgesehen von dem Gefummel mit dem IDX Code funktioniert das super, alle PM2.5, PM10, O3, NO2, CO2, etc kommen in Fhem und man kann sie weiterverarbeiten.


Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: CoolTux am 19 Oktober 2017, 13:24:40
Ich habe mir erlaubt daraus ein Modul zu machen. Hier gibt es eine erste Alpha Version
https://github.com/LeonGaultier/fhem-Aqicn


define aqicnWebBridge Aqicn token=<YOUR-TOKEN>


Der Rest ist selbst erklärend
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 19 Oktober 2017, 14:41:07
geil! Das teste ich später gleich mal!
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: CoolTux am 19 Oktober 2017, 14:42:56
Hier der Link zum Modul Thread
https://forum.fhem.de/index.php/topic,78201.0.html
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: harway2007 am 26 Oktober 2017, 18:28:05
Messungen der Städte in meinem Umfeld haben Werte
die mehr als 5 Monate alt sind ?
z.B.
Titel: Antw:Air Quality Index Berechnung als Funktion
Beitrag von: maddhin am 27 Oktober 2017, 08:38:35
da muss jemand im Juni wohl über ein wichtiges Kabel im Westen gestolpert sein und einen Stecker gezogen haben...  :o

Scheint alles gleichzeitig offline gegangen zu sein. Unten auf der Webseite steht:

ZitatAir Quality Data provided by LANUV - State Agency for Nature, Environment and Consumer Protection of North Rhine Westphalia (Landesamt für Natur, Umwelt und Verbraucherschutz NRW) (lanuv.nrw.de)

Mal bei denen nachfragen? Die haben wahrscheinlich die Weiterleitung der Daten gestoppt.