diff --git a/README.md b/README.md new file mode 100644 index 0000000..578a8e6 --- /dev/null +++ b/README.md @@ -0,0 +1,449 @@ +# DRK Blutspende + +This component has been created to be used with Home Assistant. + +DRK Blutspende allows you to get upcoming dates for blood donation into Home Assistant. + +## Data source + +The data is fetched from https://www.spenderservice.net/ + +## ### Installation: + +#### HACS + +- Ensure that HACS is installed. +- Search for and install the "DRK Blutspende" integration. +- Restart Home Assistant. + +#### Manual installation + +- Download the latest release. +- Unpack the release and copy the custom_components/drkblutspende directory into the custom_components directory of your Home Assistant installation. +- Restart Home Assistant. + +### Example entry for configuration.yaml + +``` +- platform: drkblutspende + zipcode: 79790 + radius: 10 + countyid: "08337" + lookahead: 14 + timeformat: "%A, %d.%m.%Y" + zipfilter: + - 79790 + - 79801 +``` + + - `zipcode` is required, this defines the center of the search + - `radius` is optional, this defines the radius to search within in kilometers + - `countyid` is optional, limits the results to the selected county (see list below) + - `lookahead` is optional, defines how far into the future the rsults can be + - `timeformat` is optional, lets you define how the date and time is formated + - `zipfilter` is optional, a list of zipcodes that allows you to limit the results to the zipcodes in the list + +### County ID lookup table + + - 07131: Ahrweiler + - 09771: Aichach-Friedberg + - 08425: Alb-Donau-Kreis + - 16077: Altenburger Land + - 07132: Altenkirchen (Westerwald) + - 15081: Altmarkkreis Salzwedel + - 09171: Altötting + - 07331: Alzey-Worms + - 09361: Amberg (Kreisfreie Stadt) + - 09371: Amberg-Sulzbach + - 03451: Ammerland + - 15082: Anhalt-Bitterfeld + - 09571: Ansbach + - 09561: Ansbach (Kreisfreie Stadt) + - 09671: Aschaffenburg + - 09661: Aschaffenburg (Kreisfreie Stadt) + - 09772: Augsburg + - 09761: Augsburg (Kreisfreie Stadt) + - 03452: Aurich + - 07332: Bad Dürkheim + - 09672: Bad Kissingen + - 07133: Bad Kreuznach + - 09173: Bad Tölz-Wolfratshausen + - 08211: Baden-Baden (Stadtkreis) + - 09471: Bamberg + - 09461: Bamberg (Kreisfreie Stadt) + - 12060: Barnim + - 14625: Bautzen + - 09472: Bayreuth + - 09462: Bayreuth (Kreisfreie Stadt) + - 09172: Berchtesgadener Land + - 06431: Bergstraße + - 11000: Berlin (Kreisfreie Stadt) + - 07231: Bernkastel-Wittlich + - 08426: Biberach + - 05711: Bielefeld (Kreisfreie Stadt) + - 07134: Birkenfeld + - 08115: Böblingen + - 05911: Bochum (Kreisfreie Stadt) + - 08435: Bodenseekreis + - 05314: Bonn (Kreisfreie Stadt) + - 15083: Börde + - 05554: Borken + - 05512: Bottrop (Kreisfreie Stadt) + - 12051: Brandenburg an der Havel (Kreisfreie Stadt) + - 03101: Braunschweig (Kreisfreie Stadt) + - 08315: Breisgau-Hochschwarzwald + - 04011: Bremen (Kreisfreie Stadt) + - 04012: Bremerhaven (Kreisfreie Stadt) + - 15084: Burgenlandkreis + - 08235: Calw + - 03351: Celle + - 09372: Cham + - 14511: Chemnitz (Kreisfreie Stadt) + - 03453: Cloppenburg + - 09473: Coburg + - 09463: Coburg (Kreisfreie Stadt) + - 07135: Cochem-Zell + - 05558: Coesfeld + - 12052: Cottbus (Kreisfreie Stadt) + - 03352: Cuxhaven + - 09174: Dachau + - 12061: Dahme-Spreewald + - 06411: Darmstadt (Kreisfreie Stadt) + - 06432: Darmstadt-Dieburg + - 09271: Deggendorf + - 03401: Delmenhorst (Kreisfreie Stadt) + - 15001: Dessau-Roßlau (Kreisfreie Stadt) + - 03251: Diepholz + - 09773: Dillingen a.d. Donau + - 09279: Dingolfing-Landau + - 01051: Dithmarschen + - 09779: Donau-Ries + - 07333: Donnersbergkreis + - 05913: Dortmund (Kreisfreie Stadt) + - 14612: Dresden (Kreisfreie Stadt) + - 05112: Duisburg (Kreisfreie Stadt) + - 05358: Düren + - 05111: Düsseldorf (Kreisfreie Stadt) + - 09175: Ebersberg + - 16061: Eichsfeld + - 09176: Eichstätt + - 07232: Eifelkreis Bitburg-Prüm + - 16056: Eisenach (Kreisfreie Stadt) + - 12062: Elbe-Elster + - 03402: Emden (Kreisfreie Stadt) + - 08316: Emmendingen + - 03454: Emsland + - 05954: Ennepe-Ruhr-Kreis + - 08236: Enzkreis + - 09177: Erding + - 16051: Erfurt (Kreisfreie Stadt) + - 09562: Erlangen (Kreisfreie Stadt) + - 09572: Erlangen-Höchstadt + - 14521: Erzgebirgskreis + - 05113: Essen (Kreisfreie Stadt) + - 08116: Esslingen + - 05366: Euskirchen + - 01001: Flensburg (Kreisfreie Stadt) + - 09474: Forchheim + - 07311: Frankenthal (Pfalz) (Kreisfreie Stadt) + - 12053: Frankfurt (Oder) (Kreisfreie Stadt) + - 06412: Frankfurt am Main (Kreisfreie Stadt) + - 08311: Freiburg im Breisgau (Stadtkreis) + - 09178: Freising + - 08237: Freudenstadt + - 09272: Freyung-Grafenau + - 03455: Friesland + - 06631: Fulda + - 09179: Fürstenfeldbruck + - 09573: Fürth + - 09563: Fürth (Kreisfreie Stadt) + - 09180: Garmisch-Partenkirchen + - 05513: Gelsenkirchen (Kreisfreie Stadt) + - 16052: Gera (Kreisfreie Stadt) + - 07334: Germersheim + - 06531: Gießen + - 03151: Gifhorn + - 08117: Göppingen + - 14626: Görlitz + - 03153: Goslar + - 16067: Gotha + - 03159: Göttingen + - 03456: Grafschaft Bentheim + - 16076: Greiz + - 06433: Groß-Gerau + - 09774: Günzburg + - 05754: Gütersloh + - 05914: Hagen (Kreisfreie Stadt) + - 15002: Halle (Saale) (Kreisfreie Stadt) + - 02000: Hamburg (Kreisfreie Stadt) + - 03252: Hameln-Pyrmont + - 05915: Hamm (Kreisfreie Stadt) + - 03353: Harburg + - 15085: Harz + - 09674: Haßberge + - 12063: Havelland + - 03358: Heidekreis + - 08221: Heidelberg (Stadtkreis) + - 08135: Heidenheim + - 08125: Heilbronn + - 08121: Heilbronn (Stadtkreis) + - 05370: Heinsberg + - 03154: Helmstedt + - 05758: Herford + - 05916: Herne (Kreisfreie Stadt) + - 06632: Hersfeld-Rotenburg + - 01053: Herzogtum Lauenburg + - 16069: Hildburghausen + - 03254: Hildesheim + - 05958: Hochsauerlandkreis + - 06434: Hochtaunuskreis + - 09475: Hof + - 09464: Hof (Kreisfreie Stadt) + - 08126: Hohenlohekreis + - 03255: Holzminden + - 05762: Höxter + - 16070: Ilm-Kreis + - 09161: Ingolstadt (Kreisfreie Stadt) + - 16053: Jena (Kreisfreie Stadt) + - 15086: Jerichower Land + - 07335: Kaiserslautern + - 07312: Kaiserslautern (Kreisfreie Stadt) + - 08215: Karlsruhe + - 08212: Karlsruhe (Stadtkreis) + - 06633: Kassel + - 06611: Kassel (Kreisfreie Stadt) + - 09762: Kaufbeuren (Kreisfreie Stadt) + - 09273: Kelheim + - 09763: Kempten (Allgäu) (Kreisfreie Stadt) + - 01002: Kiel (Kreisfreie Stadt) + - 09675: Kitzingen + - 05154: Kleve + - 07111: Koblenz (Kreisfreie Stadt) + - 05315: Köln (Kreisfreie Stadt) + - 08335: Konstanz + - 05114: Krefeld (Kreisfreie Stadt) + - 09476: Kronach + - 09477: Kulmbach + - 07336: Kusel + - 16065: Kyffhäuserkreis + - 06532: Lahn-Dill-Kreis + - 07313: Landau in der Pfalz (Kreisfreie Stadt) + - 09181: Landsberg am Lech + - 09274: Landshut + - 09261: Landshut (Kreisfreie Stadt) + - 03457: Leer + - 14729: Leipzig + - 14713: Leipzig (Kreisfreie Stadt) + - 05316: Leverkusen (Kreisfreie Stadt) + - 09478: Lichtenfels + - 06533: Limburg-Weilburg + - 09776: Lindau (Bodensee) + - 05766: Lippe + - 08336: Lörrach + - 01003: Lübeck (Kreisfreie Stadt) + - 03354: Lüchow-Dannenberg + - 08118: Ludwigsburg + - 07314: Ludwigshafen am Rhein (Kreisfreie Stadt) + - 13076: Ludwigslust-Parchim + - 03355: Lüneburg + - 15003: Magdeburg (Kreisfreie Stadt) + - 06435: Main-Kinzig-Kreis + - 09677: Main-Spessart + - 08128: Main-Tauber-Kreis + - 06436: Main-Taunus-Kreis + - 07315: Mainz (Kreisfreie Stadt) + - 07339: Mainz-Bingen + - 08222: Mannheim (Stadtkreis) + - 15087: Mansfeld-Südharz + - 06534: Marburg-Biedenkopf + - 12064: Märkisch-Oderland + - 05962: Märkischer Kreis + - 07137: Mayen-Koblenz + - 13071: Mecklenburgische Seenplatte + - 14627: Meißen + - 09764: Memmingen (Kreisfreie Stadt) + - 10042: Merzig-Wadern + - 05158: Mettmann + - 09182: Miesbach + - 09676: Miltenberg + - 05770: Minden-Lübbecke + - 14522: Mittelsachsen + - 05116: Mönchengladbach (Kreisfreie Stadt) + - 09183: Mühldorf a. Inn + - 05117: Mülheim an der Ruhr (Kreisfreie Stadt) + - 09184: München + - 09162: München (Kreisfreie Stadt) + - 05515: Münster (Kreisfreie Stadt) + - 08225: Neckar-Odenwald-Kreis + - 09775: Neu-Ulm + - 09185: Neuburg-Schrobenhausen + - 09373: Neumarkt i.d. OPf. + - 01004: Neumünster (Kreisfreie Stadt) + - 10043: Neunkirchen + - 09575: Neustadt a.d. Aisch-Bad Windsheim + - 09374: Neustadt a.d. Waldnaab + - 07316: Neustadt an der Weinstraße (Kreisfreie Stadt) + - 07138: Neuwied + - 03256: Nienburg (Weser) + - 01054: Nordfriesland + - 16062: Nordhausen + - 14730: Nordsachsen + - 13074: Nordwestmecklenburg + - 03155: Northeim + - 09564: Nürnberg (Kreisfreie Stadt) + - 09574: Nürnberger Land + - 09780: Oberallgäu + - 05374: Oberbergischer Kreis + - 05119: Oberhausen (Kreisfreie Stadt) + - 12065: Oberhavel + - 12066: Oberspreewald-Lausitz + - 06437: Odenwaldkreis + - 12067: Oder-Spree + - 06438: Offenbach + - 06413: Offenbach am Main (Kreisfreie Stadt) + - 03458: Oldenburg + - 03403: Oldenburg (Oldb) (Kreisfreie Stadt) + - 05966: Olpe + - 08317: Ortenaukreis + - 03459: Osnabrück + - 03404: Osnabrück (Kreisfreie Stadt) + - 08136: Ostalbkreis + - 09777: Ostallgäu + - 03356: Osterholz + - 01055: Ostholstein + - 12068: Ostprignitz-Ruppin + - 05774: Paderborn + - 09275: Passau + - 09262: Passau (Kreisfreie Stadt) + - 03157: Peine + - 09186: Pfaffenhofen a.d. Ilm + - 08231: Pforzheim (Stadtkreis) + - 01056: Pinneberg + - 07317: Pirmasens (Kreisfreie Stadt) + - 01057: Plön + - 12054: Potsdam (Kreisfreie Stadt) + - 12069: Potsdam-Mittelmark + - 12070: Prignitz + - 08216: Rastatt + - 08436: Ravensburg + - 05562: Recklinghausen + - 09276: Regen + - 09375: Regensburg + - 09362: Regensburg (Kreisfreie Stadt) + - 03241: Region Hannover + - 10041: Regionalverband Saarbrücken + - 08119: Rems-Murr-Kreis + - 05120: Remscheid (Kreisfreie Stadt) + - 01058: Rendsburg-Eckernförde + - 08415: Reutlingen + - 05362: Rhein-Erft-Kreis + - 07140: Rhein-Hunsrück-Kreis + - 05162: Rhein-Kreis Neuss + - 07141: Rhein-Lahn-Kreis + - 08226: Rhein-Neckar-Kreis + - 07338: Rhein-Pfalz-Kreis + - 05382: Rhein-Sieg-Kreis + - 06439: Rheingau-Taunus-Kreis + - 05378: Rheinisch-Bergischer Kreis + - 09673: Rhön-Grabfeld + - 09187: Rosenheim + - 09163: Rosenheim (Kreisfreie Stadt) + - 13072: Rostock + - 13003: Rostock (Kreisfreie Stadt) + - 03357: Rotenburg (Wümme) + - 09576: Roth + - 09277: Rottal-Inn + - 08325: Rottweil + - 16074: Saale-Holzland-Kreis + - 16075: Saale-Orla-Kreis + - 15088: Saalekreis + - 16073: Saalfeld-Rudolstadt + - 10044: Saarlouis + - 10045: Saarpfalz-Kreis + - 14628: Sächsische Schweiz-Osterzgebirge + - 03102: Salzgitter (Kreisfreie Stadt) + - 15089: Salzlandkreis + - 03257: Schaumburg + - 01059: Schleswig-Flensburg + - 16066: Schmalkalden-Meiningen + - 09565: Schwabach (Kreisfreie Stadt) + - 08127: Schwäbisch Hall + - 06634: Schwalm-Eder-Kreis + - 09376: Schwandorf + - 08326: Schwarzwald-Baar-Kreis + - 09678: Schweinfurt + - 09662: Schweinfurt (Kreisfreie Stadt) + - 13004: Schwerin (Kreisfreie Stadt) + - 01060: Segeberg + - 05970: Siegen-Wittgenstein + - 08437: Sigmaringen + - 05974: Soest + - 05122: Solingen (Kreisfreie Stadt) + - 16068: Sömmerda + - 16072: Sonneberg + - 07318: Speyer (Kreisfreie Stadt) + - 12071: Spree-Neiße + - 10046: St. Wendel + - 03359: Stade + - 05334: Städteregion Aachen + - 09188: Starnberg + - 01061: Steinburg + - 05566: Steinfurt + - 15090: Stendal + - 01062: Stormarn + - 09263: Straubing (Kreisfreie Stadt) + - 09278: Straubing-Bogen + - 08111: Stuttgart (Stadtkreis) + - 07337: Südliche Weinstraße + - 07340: Südwestpfalz + - 16054: Suhl (Kreisfreie Stadt) + - 12072: Teltow-Fläming + - 09377: Tirschenreuth + - 09189: Traunstein + - 07211: Trier (Kreisfreie Stadt) + - 07235: Trier-Saarburg + - 08416: Tübingen + - 08327: Tuttlingen + - 12073: Uckermark + - 03360: Uelzen + - 08421: Ulm (Stadtkreis) + - 05978: Unna + - 16064: Unstrut-Hainich-Kreis + - 09778: Unterallgäu + - 03460: Vechta + - 03361: Verden + - 05166: Viersen + - 06535: Vogelsbergkreis + - 14523: Vogtlandkreis + - 13075: Vorpommern-Greifswald + - 13073: Vorpommern-Rügen + - 07233: Vulkaneifel + - 06635: Waldeck-Frankenberg + - 08337: Waldshut + - 05570: Warendorf + - 16063: Wartburgkreis + - 09363: Weiden i.d. OPf. (Kreisfreie Stadt) + - 09190: Weilheim-Schongau + - 16055: Weimar (Kreisfreie Stadt) + - 16071: Weimarer Land + - 09577: Weißenburg-Gunzenhausen + - 06636: Werra-Meißner-Kreis + - 05170: Wesel + - 03461: Wesermarsch + - 07143: Westerwaldkreis + - 06440: Wetteraukreis + - 06414: Wiesbaden (Kreisfreie Stadt) + - 03405: Wilhelmshaven (Kreisfreie Stadt) + - 15091: Wittenberg + - 03462: Wittmund + - 03158: Wolfenbüttel + - 03103: Wolfsburg (Kreisfreie Stadt) + - 07319: Worms (Kreisfreie Stadt) + - 09479: Wunsiedel i. Fichtelgebirge + - 05124: Wuppertal (Kreisfreie Stadt) + - 09679: Würzburg + - 09663: Würzburg (Kreisfreie Stadt) + - 08417: Zollernalbkreis + - 07320: Zweibrücken (Kreisfreie Stadt) + - 14524: Zwickau + diff --git a/custom_components/drkblutspende/__init__.py b/custom_components/drkblutspende/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/custom_components/drkblutspende/__init__.py @@ -0,0 +1 @@ + diff --git a/custom_components/drkblutspende/const.py b/custom_components/drkblutspende/const.py new file mode 100644 index 0000000..b8dc5d1 --- /dev/null +++ b/custom_components/drkblutspende/const.py @@ -0,0 +1,414 @@ +ICON = "mdi:calendar" + +CONF_ZIPCODE = "zipcode" +CONF_RADIUS = "radius" +CONF_COUNTY_ID = "countyid" +CONF_LOOKAHEAD = "lookahead" +CONF_TIMEFORMAT = "timeformat" +CONF_ZIPFILTER = "zipfilter" + +RADIUS_OPTIONS = [5, 10, 15, 25, 50, 75] +COUNTY_OPTIONS = [ + "07131", + "09771", + "08425", + "16077", + "07132", + "15081", + "09171", + "07331", + "09361", + "09371", + "03451", + "15082", + "09571", + "09561", + "09671", + "09661", + "09772", + "09761", + "03452", + "07332", + "09672", + "07133", + "09173", + "08211", + "09471", + "09461", + "12060", + "14625", + "09472", + "09462", + "09172", + "06431", + "11000", + "07231", + "08426", + "05711", + "07134", + "08115", + "05911", + "08435", + "05314", + "15083", + "05554", + "05512", + "12051", + "03101", + "08315", + "04011", + "04012", + "15084", + "08235", + "03351", + "09372", + "14511", + "03453", + "09473", + "09463", + "07135", + "05558", + "12052", + "03352", + "09174", + "12061", + "06411", + "06432", + "09271", + "03401", + "15001", + "03251", + "09773", + "09279", + "01051", + "09779", + "07333", + "05913", + "14612", + "05112", + "05358", + "05111", + "09175", + "16061", + "09176", + "07232", + "16056", + "12062", + "03402", + "08316", + "03454", + "05954", + "08236", + "09177", + "16051", + "09562", + "09572", + "14521", + "05113", + "08116", + "05366", + "01001", + "09474", + "07311", + "12053", + "06412", + "08311", + "09178", + "08237", + "09272", + "03455", + "06631", + "09179", + "09573", + "09563", + "09180", + "05513", + "16052", + "07334", + "06531", + "03151", + "08117", + "14626", + "03153", + "16067", + "03159", + "03456", + "16076", + "06433", + "09774", + "05754", + "05914", + "15002", + "02000", + "03252", + "05915", + "03353", + "15085", + "09674", + "12063", + "03358", + "08221", + "08135", + "08125", + "08121", + "05370", + "03154", + "05758", + "05916", + "06632", + "01053", + "16069", + "03254", + "05958", + "06434", + "09475", + "09464", + "08126", + "03255", + "05762", + "16070", + "09161", + "16053", + "15086", + "07335", + "07312", + "08215", + "08212", + "06633", + "06611", + "09762", + "09273", + "09763", + "01002", + "09675", + "05154", + "07111", + "05315", + "08335", + "05114", + "09476", + "09477", + "07336", + "16065", + "06532", + "07313", + "09181", + "09274", + "09261", + "03457", + "14729", + "14713", + "05316", + "09478", + "06533", + "09776", + "05766", + "08336", + "01003", + "03354", + "08118", + "07314", + "13076", + "03355", + "15003", + "06435", + "09677", + "08128", + "06436", + "07315", + "07339", + "08222", + "15087", + "06534", + "12064", + "05962", + "07137", + "13071", + "14627", + "09764", + "10042", + "05158", + "09182", + "09676", + "05770", + "14522", + "05116", + "09183", + "05117", + "09184", + "09162", + "05515", + "08225", + "09775", + "09185", + "09373", + "01004", + "10043", + "09575", + "09374", + "07316", + "07138", + "03256", + "01054", + "16062", + "14730", + "13074", + "03155", + "09564", + "09574", + "09780", + "05374", + "05119", + "12065", + "12066", + "06437", + "12067", + "06438", + "06413", + "03458", + "03403", + "05966", + "08317", + "03459", + "03404", + "08136", + "09777", + "03356", + "01055", + "12068", + "05774", + "09275", + "09262", + "03157", + "09186", + "08231", + "01056", + "07317", + "01057", + "12054", + "12069", + "12070", + "08216", + "08436", + "05562", + "09276", + "09375", + "09362", + "03241", + "10041", + "08119", + "05120", + "01058", + "08415", + "05362", + "07140", + "05162", + "07141", + "08226", + "07338", + "05382", + "06439", + "05378", + "09673", + "09187", + "09163", + "13072", + "13003", + "03357", + "09576", + "09277", + "08325", + "16074", + "16075", + "15088", + "16073", + "10044", + "10045", + "14628", + "03102", + "15089", + "03257", + "01059", + "16066", + "09565", + "08127", + "06634", + "09376", + "08326", + "09678", + "09662", + "13004", + "01060", + "05970", + "08437", + "05974", + "05122", + "16068", + "16072", + "07318", + "12071", + "10046", + "03359", + "05334", + "09188", + "01061", + "05566", + "15090", + "01062", + "09263", + "09278", + "08111", + "07337", + "07340", + "16054", + "12072", + "09377", + "09189", + "07211", + "07235", + "08416", + "08327", + "12073", + "03360", + "08421", + "05978", + "16064", + "09778", + "03460", + "03361", + "05166", + "06535", + "14523", + "13075", + "13073", + "07233", + "06635", + "08337", + "05570", + "16063", + "09363", + "09190", + "16055", + "16071", + "09577", + "06636", + "05170", + "03461", + "07143", + "06440", + "06414", + "03405", + "15091", + "03462", + "03158", + "03103", + "07319", + "09479", + "05124", + "09679", + "09663", + "08417", + "07320", + "14524", +] + diff --git a/custom_components/drkblutspende/manifest.json b/custom_components/drkblutspende/manifest.json new file mode 100644 index 0000000..5056159 --- /dev/null +++ b/custom_components/drkblutspende/manifest.json @@ -0,0 +1,13 @@ +{ + "domain": "drkblutspende", + "name": "DRK Blutspende", + "documentation": "", + "requirements": [ + "feedparser", + "requests" + ], + "dependencies": [], + "codeowners": [ + "Bouni" + ] +} diff --git a/custom_components/drkblutspende/sensor.py b/custom_components/drkblutspende/sensor.py new file mode 100644 index 0000000..c74054d --- /dev/null +++ b/custom_components/drkblutspende/sensor.py @@ -0,0 +1,163 @@ +""" German red cross blood donation sensor.""" +import asyncio +import logging +import re +import xml.etree.ElementTree as et +from datetime import datetime as dt +from datetime import timedelta as td + +import feedparser +import requests + +import homeassistant.helpers.config_validation as cv +import voluptuous as vol +from const import ( + CONF_COUNTY_ID, + CONF_LOOKAHEAD, + CONF_RADIUS, + CONF_TIMEFORMAT, + CONF_ZIPCODE, + CONF_ZIPFILTER, + COUNTY_OPTIONS, + ICON, + RADIUS_OPTIONS, +) +from homeassistant.components.sensor import ENTITY_ID_FORMAT, PLATFORM_SCHEMA +from homeassistant.const import CONF_NAME +from homeassistant.helpers.entity import Entity, async_generate_entity_id +from homeassistant.helpers.typing import HomeAssistantType +from homeassistant.util import Throttle + +_LOGGER = logging.getLogger(__name__) + +DOMAIN = "drkblutspende" + +DEFAULT_TIMEFORMAT = "%A, %d.%m.%Y" +DEFAULT_LOOKAHEAD = 14 + + +MIN_TIME_BETWEEN_UPDATES = td(seconds=3600) # minimum one hour between requests + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( + { + vol.Required(CONF_ZIPCODE): vol.Coerce(int), + vol.Optional(CONF_RADIUS): vol.All(vol.Coerce(int), vol.In(RADIUS_OPTIONS)), + vol.Optional(CONF_COUNTY_ID): vol.All(cv.string, vol.In(COUNTY_OPTIONS)), + vol.Optional(CONF_LOOKAHEAD, default=DEFAULT_LOOKAHEAD): vol.Coerce(int), + vol.Optional(CONF_TIMEFORMAT, default=DEFAULT_TIMEFORMAT): cv.string, + vol.Optional(CONF_ZIPFILTER): vol.All(list, [vol.Coerce(int)]), + } +) + + +@asyncio.coroutine +def async_setup_platform(hass, config, async_add_devices, discovery_info=None): + """Set up date sensor.""" + zipcode = config.get(CONF_ZIPCODE) + radius = config.get(CONF_RADIUS) + countyid = config.get(CONF_COUNTY_ID) + lookahead = config.get(CONF_LOOKAHEAD) + timeformat = config.get(CONF_TIMEFORMAT) + zipfilter = config.get(CONF_ZIPFILTER) + + devices = [] + devices.append( + DRKBlutspendeSensor( + hass, zipcode, radius, countyid, lookahead, timeformat, zipfilter, + ) + ) + async_add_devices(devices) + + +class DRKBlutspendeSensor(Entity): + """Representation of a DRKBlutspende Sensor.""" + + def __init__( + self, + hass: HomeAssistantType, + zipcode, + radius, + countyid, + lookahead, + timeformat, + zipfilter, + ): + """Initialize the sensor.""" + self._state_attributes = {} + self._state = None + self._name = "blutspende" + self._zipcode = zipcode + self._radius = radius + self._countyid = countyid + self._lookahead = lookahead + self._timeformat = timeformat + self._zipfilter = zipfilter + + self.entity_id = async_generate_entity_id( + ENTITY_ID_FORMAT, "blutspende", hass=hass + ) + + @property + def name(self): + """Return the name of the sensor.""" + return self._name + + @property + def device_state_attributes(self): + """Return the state attributes.""" + return self._state_attributes + + @property + def state(self): + """Return the state of the sensor.""" + return self._state + + @property + def icon(self): + """Return the icon to use in the frontend.""" + return ICON + + def get_data(self): + date_to = (dt.now() + td(days=self._lookahead)).strftime("%d.%m.%Y") + url = "https://www.spenderservice.net/termine.rss" + try: + feed = feedparser.parse( + f"{url}?term={self._zipcode}&radius={self._radius}&county_id={self._countyid}&date_to={date_to}" + ) + except Exception as e: + _LOGGER.error("Couldn't get data from spenderservice.net") + return + + self._state = "unknown" + for entry in feed["entries"]: + t = re.search( + r"(?P\d{5})\s(?P.*)\sam\s(?P[\d\.]+),\s(?P[\d\:]+)[^\d]+(?P[\d\:]+)", + entry["title"], + ) + data = t.groupdict() + d = re.search( + r"-\s(?P
.*)\s-\s(?P[^<]+)", entry["description"] + ) + description = d.groupdict() + if not self._zipfilter: + self._state = dt.strptime( + f"{data['date']} {data['start']}", "%d.%m.%Y %H:%M" + ) + self._state_attributes = data + self._state_attributes["address"] = description["address"] + self._state_attributes["location"] = description["location"] + break + else: + if data["zip"] in self._zipfilter: + self._state = dt.strptime( + f"{data['date']} {data['start']}", "%d.%m.%Y %H:%M" + ) + self._state_attributes = data + self._state_attributes["address"] = description["address"] + self._state_attributes["location"] = description["location"] + break + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def update(self): + """Fetch new state data for the sensor from the ics file url.""" + self.get_data() diff --git a/hacs.json b/hacs.json new file mode 100644 index 0000000..fe76714 --- /dev/null +++ b/hacs.json @@ -0,0 +1,4 @@ +{ + "name": "DRK Blutspende", + "render_readme": true +}