From 46f208349000745c824c081f256d9991932c0453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=A4fliger?= Date: Fri, 12 Apr 2024 16:52:15 +0200 Subject: [PATCH] Initial commit, Json formatting, engine, user, producer und meter erstellt. --- __pycache__/energyuser.cpython-39.pyc | Bin 0 -> 2103 bytes client/Energydistributer.py | 54 +++++ client/JsonHandling.py | 79 +++++++ .../__pycache__/JsonHandling.cpython-39.pyc | Bin 0 -> 2367 bytes client/__pycache__/energymeter.cpython-39.pyc | Bin 0 -> 3888 bytes .../__pycache__/energyproducer.cpython-39.pyc | Bin 0 -> 3900 bytes client/__pycache__/energyuser.cpython-39.pyc | Bin 0 -> 6498 bytes client/__pycache__/main.cpython-39.pyc | Bin 0 -> 5786 bytes .../__pycache__/serverrequests.cpython-39.pyc | Bin 0 -> 690 bytes client/config.txt | 20 ++ client/data.json | 1 + client/energymeter.py | 116 +++++++++ client/energyproducer.py | 126 ++++++++++ client/energyuser.py | 222 ++++++++++++++++++ client/engine.py | 54 +++++ client/hey.html | 112 +++++++++ client/main.py | 164 +++++++++++++ client/serverrequests.py | 23 ++ server/main.py | 56 +++++ 19 files changed, 1027 insertions(+) create mode 100644 __pycache__/energyuser.cpython-39.pyc create mode 100644 client/Energydistributer.py create mode 100644 client/JsonHandling.py create mode 100644 client/__pycache__/JsonHandling.cpython-39.pyc create mode 100644 client/__pycache__/energymeter.cpython-39.pyc create mode 100644 client/__pycache__/energyproducer.cpython-39.pyc create mode 100644 client/__pycache__/energyuser.cpython-39.pyc create mode 100644 client/__pycache__/main.cpython-39.pyc create mode 100644 client/__pycache__/serverrequests.cpython-39.pyc create mode 100644 client/config.txt create mode 100644 client/data.json create mode 100644 client/energymeter.py create mode 100644 client/energyproducer.py create mode 100644 client/energyuser.py create mode 100644 client/engine.py create mode 100644 client/hey.html create mode 100644 client/main.py create mode 100644 client/serverrequests.py create mode 100644 server/main.py diff --git a/__pycache__/energyuser.cpython-39.pyc b/__pycache__/energyuser.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2e4aaa2e03cb290fe520cd4ac1aa462b41604816 GIT binary patch literal 2103 zcmc&#!EPf(5bf?6kH;nsLDnt{EXzoX00W93#}z`6$OiV}OA-l_4o;#H50oved|Kw_+Z=_=P$s;k~>r=3ol(evw_)6*tn zzdK_MeC+qJ%maXAk{2vyUot7A_nb-ZT*MrfFB`BLil2M2fE~yt?549l$&Xksyu|yg zpAoJ<0>(a;`52&B%q5G3}!9o`=>Os7ibAYbroDD8kQWq3kPoPbSJ$Y&+RRYc;Bparsnf+g+Mc z6;)b0=fe6%6{j}H%F$^)m^1waM4OMkk${x4fepx+QMkx7E>r&5!?jW-b(qTCnRqmKI?2x;?%0pqs zO`1<{t(CrtILv4$%jXIaB6uq{W8b3wA9y8RfS6JY#0A%PXP_vpp5H${baUiB-GD(a28~qv*>RSNYbP=i6uaoO70wT^DP+K+i zhKOoN{~-@sq33g7IDZD$m4|}&vCId6l}e#dC}|*|PN7CO~3?Q{nL?^;|n39$#+<_3v%0O)A-Tr?^=lq;hwL zH?bjs5XpYV9XSL3;-7PloAZdxz5aCP#N?wvRLe9`Tm{~pCIB!O6>h>O6dDk!Mg-EjhcRUuZ((cebkzm vuyK^{;|uytT_0szleg#VJM^@jSi+% literal 0 HcmV?d00001 diff --git a/client/Energydistributer.py b/client/Energydistributer.py new file mode 100644 index 0000000..90c1ba6 --- /dev/null +++ b/client/Energydistributer.py @@ -0,0 +1,54 @@ + + +class Energydistributer(): + @staticmethod + def distribute_energy(energy_users, current_power): + remaining_power = current_power - sum(user.current_delta_power for user in energy_users) + + # Filtere Benutzer mit idle = True + idle_energy_users = [user for user in energy_users if user.idle] + + # Erweitere die Schritte für modulare Benutzer + for user in idle_energy_users: + if user.modular: + user.powersteps = list(range(min(user.powersteps), max(user.powersteps) + 1)) + + # Sortiere die Benutzer nach ihrer Priorität und dann nach ihrer ID + idle_energy_users.sort(key=lambda x: (x.user_prio, x.used_energy)) + + # Schleife durch alle Prioritäten + priorities = set(user.user_prio for user in idle_energy_users) + for priority in priorities: + # Benutzer mit gleicher Priorität sammeln + same_priority_users = [u for u in idle_energy_users if u.user_prio == priority] + if not same_priority_users: + continue + + # Sammle alle Schritte der Benutzer in einem Array + all_steps = [] + for user in same_priority_users: + all_steps.extend([(user, step) for step in user.powersteps]) + + # Sortiere die Schritte nach Größe + all_steps.sort(key=lambda x: x[1]) + + # Variable zur Verfolgung der bereitgestellten Energie für jeden Benutzer + user_energy_prov = {user: 0 for user in same_priority_users} + + # Iteriere durch alle Schritte + for user, powerstep in all_steps: + # Überprüfe, ob noch genügend verbleibende Energie für den nächsten Schritt vorhanden ist + if remaining_power >= powerstep - user_energy_prov[user]: + # Aktualisiere die verbleibende Energie und die bereitgestellte Energie für den Benutzer + remaining_power -= (powerstep - user_energy_prov[user]) + user_energy_prov[user] = powerstep + + # Verteile die bereitgestellte Energie auf die Benutzer + for user in same_priority_users: + user.use_energy(user_energy_prov[user]) + + print("Final state after distributing power:") + for user in energy_users: + print(f"{user.ID}: {user.used_energy}") + + \ No newline at end of file diff --git a/client/JsonHandling.py b/client/JsonHandling.py new file mode 100644 index 0000000..677ba62 --- /dev/null +++ b/client/JsonHandling.py @@ -0,0 +1,79 @@ +import json +import os +import serverrequests as serverrequests +import JsonHandling +import energymeter +import energyproducer +import energyuser +import datetime + +class JsonHandling: + + @staticmethod + def check_config_has_changed(json_data): + data = json.loads(json_data) + return data["metadata"]["config_has_changed"] == "1" + + +class DataCollector: + def __init__(self): + self.data = {"timestamps": []} + self.now = datetime.datetime.now() + + + def collect_and_store_data(self, producer_values, meter_values, user_values): + + print("a") + if self.now.minute == datetime.datetime.now().minute: + print("b") + + return + self.now = datetime.datetime.now() + print("cccccccc") + + timestamp = self.now.strftime("%Y-%m-%d %H:%M") + self.data["timestamps"].append(timestamp) + # Werte für Produzenten hinzufügen + for producer_id, values in producer_values.items(): + if producer_id not in self.data: + self.data[producer_id] = {} + self.data[producer_id]["values"] = self.update_values(self.data[producer_id].get("values", {}), values) + + # Werte für Meter hinzufügen + for meter_id, values in meter_values.items(): + if meter_id not in self.data: + self.data[meter_id] = {} + self.data[meter_id]["values"] = self.update_values(self.data[meter_id].get("values", {}), values) + + # Werte für Benutzer hinzufügen + for user_id, values in user_values.items(): + if user_id not in self.data: + self.data[user_id] = {} + self.data[user_id]["values"] = self.update_values(self.data[user_id].get("values", {}), values) + + # Begrenzung der Daten auf die letzten 24 Stunden (1440 Minuten) + if len(self.data["timestamps"]) > 1440: + self.data["timestamps"].pop(0) + for key in self.data.keys(): + if key != "timestamps": + for value_key in self.data[key]["values"]: + self.data[key]["values"][value_key].pop(0) + + + if os.path.exists("data.json"): + with open("data.json", "r") as file: + existing_data = json.load(file) + existing_data.update(self.data) + self.data = existing_data + + # Daten als JSON speichern + with open("data.json", "w") as file: + json.dump(self.data, file) + + + def update_values(self, current_values, new_values): + for key, value in new_values.items(): + if key not in current_values: + current_values[key] = [] + current_values[key].append(value) + return current_values \ No newline at end of file diff --git a/client/__pycache__/JsonHandling.cpython-39.pyc b/client/__pycache__/JsonHandling.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c36a3ba3cb83e21287b42ee8794e853d515bb2f GIT binary patch literal 2367 zcmZ`)&5zSY6rT^4&|rYflP<4}YU0;D3O=F&q&L}iS}$vT@j*|D>f zmA8j3_wpwsmrCs)(m!HOm3r#Er>ckk-XvKP*xH&m^XB9C-n_4g8jTvm_v5wg?)5rj ze-g9$Nig@&@@F85DL!DGdCxoC@}eVbFFVrqPRFsm+i`90bv)ZwI+d@P5=y>eN}h<0 z1m`FhoD0rZ{9D%Y{(=B zCCczyEn%EKWEpobic}7^N^EG4I7EMCnk@Uz=Z|hbjr8**E%G8QlEFF?57Hznp028W zbNtd=j`xyyKYUkoKI}Cv$mGg?hZLadr zyQ%`S`=;>_hI=p?43fAQ={5h6FA4J0e~R~53J->?;C((7GlnrD5kR7CYDGFsaG&8g zZ%JLnLF2b4znr`qG+aHk90ouYu;H zSruA7M?<8Y#S7!38+xC%ovuFI5Uxutst{nVe2ajvSol+8rxq1knWx_5^iJS)Wt zQUyqr1=8;eq{<3X4*F^*P9D0e+A1w0}FE&>+hmQTF{M8 zxT@?s!1!f3Gp#G%+5kJIfwjWj<7!z|?!LsnuDxHCkhaM}SC1`LxtJ+ykh?&5%@2M; z>lTfEb9zoyXQb=D#fGY?+KKr2%5l9oKiw?r@Ide#{N&(2k(_0lx7cf*|M4l~_J0Ce z2Ga{9*=iQRkFLe31Lvy6*|K`oXM(eLutfgJDwYl5plx_$_;cgOi|?qp`{c&%@W!s% z*?n|-_Zz*5P&3|PG?*lLI(3nmlp{w~Dn2)DZQ|PS7p;rN9qTkJ^p-s^OtVRmXbNxR z=Y{T4O3X9Fi^k(5Q^rM|8s?@k8B@xHa}h@NlETPAk{LN3jg7OPyv&Ul<;EFD#h&q! zAJV)4Hv)$C2;QOEXuLU$anxiuZZ-5pS~@q@C_-_fm*@e?&Ks^i$=@*5(_A+7(_^X9 zRK;zf#@1AsiampYgl48{wGL_Mbkjj%8dg6%3${kTo%WaFdDRK=c7!>KPhz*xbCcf( zVZ!HI+!qcHKm)!ZHc%F7{JMP82bSOB8@!3pCf|`w?EVq%Rek&${OG;)%dJIDyX9%Bjk-zX z9Fa>zz9K?^D?$iX+h^uHMik;Xg%YH={%4xzT2&id`a_IO6Jc_g;35Y|f+Dvsk*OzH rqI)lGK$+&8S;md2&3TFyn*$c}ECq~zXZ}v!rL@XP6}s!nFPi>;HBLO~ literal 0 HcmV?d00001 diff --git a/client/__pycache__/energymeter.cpython-39.pyc b/client/__pycache__/energymeter.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d160761d1cf5460cdb01de99e94a4d08b5b8d85b GIT binary patch literal 3888 zcmcf^U2ojRad-K7)Td?FkQ^sagTl=rfh5a?-8iyq#~-mDd^IYgMh`Yvn!A=M^Ny$8 zJtsQw`Vbj?ZlCP{(xdVi}!Dn>1&^w_MtP&JK;`}fu>DEVuv%sP&VNC}pmwP~Y z!r5_}F3>&?fDSC}0Uh!h&^1f@oUW64^exCIjTGVN9lA}-4De%wsgVHO5P48aP7Y z5_M+S(u#4?TphM+w3cT|r$wuC^(4&vI}FmhJZjEVibRXp#t+VopUR>YZ>plbw3ZiX zlB=tL422lqPE_(IAV^LCsE5W;+sXv3f_HPFFaX<0OT;l^JWC-Ijc;A5jEi!Omlp|F z#!osO(dHnahU}OpIx*33XCP^+3aCmq_}EUUL8QrQZiQNtOjvGpdQ3Q!ao8GX-n`ip zuoZO*0AXjCOCvT(LwiSbj`hy{XBHcCK03Yz!$zVDXA2_{5>a)#ue}Unu*8V_E5sow znGJ|}h%B~8Y&=5jmCmjMNzvJ377Grr@BphJ#z7v&ZAnYE>8`*4fwSoe`|hh)u>t(xo|=z8m4v+b5*?F zZ9R~fa`rtFsBW4HrOe!oK@PZnBfkGEfuwT&7~bkJybEULe(|Z0zY$3u-$&_k8HCFf z1m_W~BDetHcHNWcYI}Gjo(qX-!zN{T^%mkk2VguK>}F~#F`3A6Z3rF?u+x~Fk~|+z zW$LFOOq~Nj*eM9Ah=$AuXzzde0nqdmowxTHcAECy9SyhRMK7ALXf(s9eUk!n z?85wW4Td@k;7w(hdzc%IZykUBhpDX6fdyrN08iQBZQ$mwz!`CV2(r;tQuwdtYg~3q1<7NDN8~6tCw@ zehozm+NeHs)ujXN(3jkUf&(oR;uU5aCs%tQ3!0?TwQmk++gy3O4Ey~(1`QVCp~a!e z0=#DN(BhHBYkZ>gq2&t88lQaaJ%px;Px0xDj$;o=`y!&wwV; z4t+(wU^~#T4Zrls@8BP$AN?T$Y4*87Rse%^HQVR~&$RAbUS959SXM=z$T;a_%P-C^ zer$&2{yWXo3NL8CS|EO|*9cZPNN2oLJ; z5#9we+rc^VZ594{Ja9F=CiKY?if0U*e<@?GIA33D>H+ Tdlg+etd>yOr!US<%ufFs+$3DK literal 0 HcmV?d00001 diff --git a/client/__pycache__/energyproducer.cpython-39.pyc b/client/__pycache__/energyproducer.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f3849a3c487b4881a227c7cdc95a397ed84d853 GIT binary patch literal 3900 zcmcgv-ESN<5VyUbce#X63N%nqkoXFqBn?oYgwjCL4+)N{sVF^xR?FHA8}@E5wy#o7 zn-|hQ0G?P_&w`t* z-m$#H$tF2+n}%Ikhj!ICYg`_=#@P~DV!)(_#0PT3jH^U;%lJv&xs`4m5!nFo?{8i{ z_jxS86scA^)gl}3Bv~pt`g38I-5o4@vAb)+C`vo2jv}vPk%D~j z{2tYSBu)33bTwc{!^w~?zQ1OV);G%1X;4Wx~qLWMrQCORpaRhtx?R zggwPvT4xO!+NVxW(Ee+GCxBy!Ks3~#S$Mi|<`ABcsmjOw!Ak*{1;X$b04FJ!Mae0E z8#^QxqyWgmIdC9rI)}`1!H^4wTn#x6_7KbkE!eiZ3g01|<*x$+wVTnjayUjBRibr3wcD^IqsOTAyLmjwB!)`(ggM08O0+@}LsTJA6%4qC+(?+7WQkf;?c0r4i<2H z(D5t{Yt*`}Q3cs1-$SkV(b=Ql(*6le58&Pc*Cqy)1!~vV3~Q5IfjR}(s}AD?>&~}S z&J^we)S;9dLIvaA;O!6ILHX7m*tb_HymB3*A3jjuKUTl?K>grY{rUs-!@_|}pAT2P zkWc;K-GHkcR8jnogU>*6gLF<)f)8(uj``#!=r4mNq`&EAKln=P?zyF<{@Ep!XHc-> zZn|{)%+e*HuXJt;sfD~I;!LM)u?|2Iu;=RpXrA7PhPp~t_{UGPN#zhTN zUthZ!Z8SHoUAk%fPx0ogjB|DEL({na$@R65s-dZy8*A4F9k~cbE-nQ2Z-@z{*ny9< zvZc^WVWH@$D9O2y&*5y2($fA}S*Y2&yK#Cl!_QPV@4)TL7F(>E$5q^s12xQ$pMkDA z2ZYcWd$X$3Sty9h<--^qJb#3>dwe7CM@IT{6@LHDLB`a46(=8NP?SI*uyR>vReX0=owtQn+WAaq zXGg8NXt~-$%ZuF|XVpX7*9Ei--1gB9bP??$w+mXXh-&E())BQjmE%7LjqAA5cTmKF z*2cP0tIx!$qaE$yj@7h}yQd2}z}?qHUBbN(2YODIKNCB0wTSw>Uf_C3pTLSIZRtiU zHtSn=(%94$rXT*OPUn9USNblBzTAZb_GDj#lIu9_od2n%y+3 zG@6|xZel+b>|`L1N;A$j+InBwGqrYhYd9j-H;ieUeQ8c$Wp1RPV)5FCeDs+Vl?9T;v21R zXxiyjPs7y0q2YWKCEYlEc5L-$$5uZ)a$*+~;HhAa3}(LxHEzpH?K%YAb+sqW#Xew9 zSJkcEUS|8Ry4Gn%pO|^PWqlL1bh`=T+-NuIadjZIA_n9(J$-~Tv@sJu#MU!_gVp#v zoq=ppsFFMPb2+-qO{ik!JOFvvZBs|2Hntdu>dfbrVNf zOc*jWGF&t5X1JNQTZ>oW)}kc6hRSdX>(RK>d=s;nlPIczb<(ZW=8h^($)&WSW*ml8 z(~UZui}iEMv@T6+y`&xK6gcX1;+Dn)MS2|SD2r@qcr46Rj@eK0&Qj}gf9`q5sw@t2 zt0v67p$&#pOiSYY%#*%^gQNs>p)M#_mQ+~={4dGVs`uh?gf*dc(s&Wqgb5sZtl8on z5(tSY2dHP~-y8&+cRAS1VSo_ zBl5}1k2K20`#6}PwppNJBrg^f$(z{QEIzWpC!0-0XiY{Qos}twtmSJQ5kXn8_h>Z| zwvfHE`Rrdt7)Y1A$OTl0?@+M(6Zmu=`=D&TV-xFjeAfyA7rVoD@rcoDAQCNU+HyVyM-PZREk1aJ@mX@A%o2Xow^r%mwO zO;^j$Js66r0hN<@w(c!(RYo=XDBUpR%yKeI(bddRag;EBh>jRnT1FwHJN*B*_jJDF zL*AiQEinGfGF~umQ!#}%nsZDZBS_ssM-5j>dkR!A4>-Aop3Vl+Yv>&T37H6-=sI$r zJo7;&!Wj=T5zcg03%aD|kdXws3|YID)VDnoP5MgwESjlaYoD1lhAU2 zW{M@#XaQ0{#t13y6jE}GxYHPUB0PRe8{-^)2#){d;8Fk+TEUIcBK8#B&w~+5Q~2f^=Q zDJHK-Mh$vGI&>xi~&8n%MtRfXno%mSz+sQiF`|n-bIWm z_B}*VMPu)Z4=`@q`_v=t*Aj2s`iyt4 zRH^}M&IW@tHD#l)bNT*|r|8&R!X}wBo1fBli#I;0$DORvZdLvKGlSDL3C)mp+ARco z=FD?rOIjI^Ma2v*FBg5%S^OSa4Fb<+cNVmy|@Ew6n21eu|-+e7}HPUEOb!!Qx;B6%^1sA4p z0X>C2y*X|Q?x$|61Vh06zz`4?e@-heTrzPIZC$$j27uXm-74gpPJ3;QjiUF$Nckz0 zpX<8P?q;2CRw3=gi@l{Ib&lbz^CMn?zWp4jA$E}C{})sv#hM5OSQLG`vK}vC?$dMf zyN0OJv=UEYsiDO4o&6P~Qt|?%zYDBC`bO9L&e0k>^!@}lq*&KAn=o9#jJ$OLw{#ANlJwzMidKp1usA6)kUbpAfkQ*iJWkWA z9(~IqGHHH-0)d{-vq=wFjU=*}T;m_;%ufU5lmVz-<>=Eqfv;1N%sP1vm1zcoHoWMj z2PWd@OvImNBG>VnAt9gt}KZj8+$nWV@3*)?RVQi^!0po&iV{C)k_GhXy zKD(uri!UIBRw=V|#t*iy2Jsr^AS5cST_Q|;23c=GWsLk zH!+71T2r+-)#iN-`{gPrzj-Y!bg-S<7GX;;uucn6t9DwGs*5~s7Zju1gpy6x7-fk+nzLqCY5mrWk>)QE#X-f5;S#y%6?Gc|vjALbL*8R$u=p%}a8d+uVoA3k& zvrUt13#l#f*3J5hQ@7nnsv{Oy~h;tO4%YaHoZpRx~c8D zjh5eus9$v5osJh}Ps9QkiqmM)yrS@gI73rssUgo9Ye=m^M^nHRlW$neDpY<~ZhD1eVtYYHlh}^OZ3K zk~b(A-hM$k7kO%CsTt`+se|9Ljr6=KBs{Zz8w=1uBZ10>h({l94G|4uAlb(DCvJ z1C_(P_!=!dN6pu%ai~%LF!Yl#wn`OB3*P`8Er=~N7BiT|t%9K0|E^1{ZoK$An1;_` zpZ}ptC>_7jB`%XPrUXvq6085QONh6@U%W%j%S?ThBiN2}_&czHQ5ro z6H%B1An+-OMCfGsT>>PMFKOHQzHy*k!$v(;*Lqx<`vCR<>*)!$UBZ)(F87QCA!bSI znYf#{=Mskbv%P#`Ci!jtKod6-zMoI>Np26Bo@qNbc2*Lu^7e!s~&l!sVI>JQ=uKqSbJ><5qKd9i@gB#aGZ7 zFi1_nUc};E@DL}^z#4kI8~2ky5UW5y352RIB#qnyFG4m-4dR%ZQOom@*SvN+X!=-N zplR3lq?g)*_W^Y=i&w7NEH%{gtPmRODm_q{BiyWHNv#2kqbis``fk@DdQ1q=_?z5d zHZL-yB>Zi*z`Lc-SI&e_Q_vsg6^eRN+h^o-2fU}jx^OiHtHU|;ic0q3-)5jXT~KaL z^OWT&0)G=Dlq}3UD*jg~PY-G~?|~Oa-X>DAsuZeN)KBm94&8T;%l?Yh6S0u8GX*Dt zXYAvp;EsLlBnmHk>iO(KYOh6zw{`HymskX&@8wUg{dj?FJ@t=1d1G~Az z1kJf;EXnQLpEA(R5FPDDTof+rev7VLi#7ZFT zl6FSBZ;H>x$M56Kv#0CY&Sz@hQ}nj`GuaB->p9ywxARys|3qeRa6bDCAcs6fr003u zXOW6-2q9a1d?)gN!A=I9a^T05m5%Jwox0D2T`9{a2v18CS9wMJWXR>G!=CatC42>Q zJ(?#|P8D7`%L1N;1UZ|OSF_?*iVS?b^LkAq5IB8*z_U? z`CbN&w0xNzAN-2L_agzeK!e_vlnAJ zG7kKvPf+lp$juJ3^D0wk0S08P2Weq=)K!{=Tl|7{SMESYOHU48d$8|sFde^#M&qY( zR+!T*d{-#x^ZEit3phV;9cKu37Bh2tkkA;bQa*Z^NsDBOu$FyO z5L8u)4Qi+c$b3Ti*~r<>;{j2`6niYjnZ1C^-DKmhRADtaQQYugBD*(#>n7wbC6N z%ke-hRAwoyUA#~lemyF!t@ae>FU;)HB(qBs%-;Kw%vL9vtxhnz^nc9^s+nR<_~0vb zc6qwaUYi-*3_;Mg%SG`%oK_I%vU;`nA!_y;s97V#hIFRZilU$5 zq&bO+WYYUgVhT+11=C~c$DZuSt_;4im;(h5_=Ztr&q%a$jVH-zit4xFV-;YYV44>Q z7P*pb*q8nlyJX+!cXH*u#(5mq#-l{_Cd51%6WXjdh?m}sSYLKG6l;!ig41=F7HXco z8`@9SQN13$x3-*)MysOI!hpU2EwXZYG#-yfRVfn-qCN1;77I{MBkK4EQ>g2o=xF`m zq!AmmOgS)Bnu0O&D$iHLb^m3OzixQOM8WQOO4d)dYYaA~NW8JQ? ziLDF{mf-wSXUayt^BV)M(`qHnlKed-NgWym@98PmLP=Qt@rk7sHbkhJ#1a@WLd~6hhvJJ OsejOb1-*cA8q$BesJ#II literal 0 HcmV?d00001 diff --git a/client/config.txt b/client/config.txt new file mode 100644 index 0000000..b2e86ef --- /dev/null +++ b/client/config.txt @@ -0,0 +1,20 @@ + { + "metadata":{"config_has_changed" : "1"}, + "users": [ + {"type": "User1", "config": {"ID":"Umod1","user_prio":1,"lock_prio":2}}, + {"type": "User1", "config": {"ID":"Umod3","user_prio":3,"lock_prio":4}}, + {"type": "User1", "config": {"ID":"Umod2.0","user_prio":2,"lock_prio":3}}, + {"type": "User1", "config": {"ID":"Umod2.1","user_prio":2,"lock_prio":3}}, + {"type": "User1", "config": {"ID":"Umod2.2","user_prio":2,"lock_prio":3}}, + {"type": "User1", "config": {"ID":"Umod2.3","user_prio":2,"lock_prio":3}}, + {"type": "User2", "config": {"ID":"Usta2.0","user_prio":2,"lock_prio":6}}, + {"type": "Boiler_1Stufig_Shelly", "config": {"ID":"shelly_Boiler","user_prio":2,"lock_prio":6, "shelly_ip" : "192.168.20.233", "boilerpower": 5000, "temperatur": 38}} + ], + "producers": [ + {"type": "Fronius", "config": {"ID":"Fronius_15kW","IP":"192.168.20.51","Adr":1}}, + {"type": "Fronius", "config": {"ID":"Fronius_20kW","IP":"192.168.20.51","Adr":2}} + ], + "meters": [ + {"type": "Fronius", "config": {"ID":"Meter_Fronius","IP":"192.168.20.51","Adr":1}} + ] + } \ No newline at end of file diff --git a/client/data.json b/client/data.json new file mode 100644 index 0000000..41d7638 --- /dev/null +++ b/client/data.json @@ -0,0 +1 @@ +{"timestamps": ["2024-04-12 16:43"], "Producer_sum": {"values": {"success": [true], "day_energy": [205790], "pac": [19349], "total_energy": [58877902], "year_energy": [7792097]}}, "Fronius_15kW": {"values": {"success": [true], "day_energy": [84970], "pac": [8075], "total_energy": [30943902], "year_energy": [3146688]}}, "Fronius_20kW": {"values": {"success": [true], "day_energy": [120820], "pac": [11274], "total_energy": [27934000], "year_energy": [4645409]}}, "Meter_Sum": {"values": {"success": [true], "Current_AC_Phase_1": [-10.55], "Current_AC_Phase_2": [-21.65], "Current_AC_Phase_3": [-19.2], "PowerReal_P_Sum": [-11792.6]}}, "Meter_Fronius": {"values": {"success": [true], "Current_AC_Phase_1": [-10.55], "Current_AC_Phase_2": [-21.65], "Current_AC_Phase_3": [-19.2], "PowerReal_P_Sum": [-11792.6]}}, "User_data": {"values": {"Current_Power": [0], "Used_Energy": [0], "Current_Prio": [0], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Umod1": {"values": {"Current_Power": [0], "Used_Energy": [6], "Current_Prio": [1], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Umod3": {"values": {"Current_Power": [0], "Used_Energy": [6], "Current_Prio": [3], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Umod2.0": {"values": {"Current_Power": [0], "Used_Energy": [6], "Current_Prio": [2], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Umod2.1": {"values": {"Current_Power": [0], "Used_Energy": [6], "Current_Prio": [2], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Umod2.2": {"values": {"Current_Power": [0], "Used_Energy": [6], "Current_Prio": [2], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Umod2.3": {"values": {"Current_Power": [0], "Used_Energy": [6], "Current_Prio": [2], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Usta2.0": {"values": {"Current_Power": [0], "Used_Energy": [4], "Current_Prio": [2], "Current_deltaPower": [0], "measured_Temp": [0]}}, "Usta2.1": {"values": {"Current_Power": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], "Used_Energy": [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], "Current_Prio": [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], "Current_deltaPower": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}}, "shelly_Boiler": {"values": {"Current_Power": [0], "Used_Energy": [0], "Current_Prio": [2], "Current_deltaPower": [0], "measured_Temp": [25.19]}}} \ No newline at end of file diff --git a/client/energymeter.py b/client/energymeter.py new file mode 100644 index 0000000..dc1d760 --- /dev/null +++ b/client/energymeter.py @@ -0,0 +1,116 @@ +import sys +import json +import requests + +class EnergyMeter: + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + + def get_current_value(self): + raise NotImplementedError("Subclasses must implement use_energy method") + + + + @staticmethod + def create_meterlist_from_json(json_data): + subclasses = [cls for cls in sys.modules[__name__].__dict__.values() if isinstance(cls, type) and issubclass(cls, EnergyMeter) and cls != EnergyMeter] + + energy_meters = [] + data = json.loads(json_data) + + for user_data in data["meters"]: + user_type = user_data["type"] + user_config = user_data["config"] + for subclass in subclasses: + if user_type in subclass.__name__: + energy_meters.append(subclass(user_config)) + + return energy_meters + + @staticmethod + def get_all_current_values(meters): + data = {"Meter_Sum": {"success": True, "Current_AC_Phase_1": 0, "Current_AC_Phase_2": 0, "Current_AC_Phase_3": 0, "PowerReal_P_Sum": 0}} + for meter in meters: + if isinstance(meter, EnergyMeter): + current_value = meter.get_current_value() + meter_data = { + "success": current_value["success"], + "Current_AC_Phase_1": current_value.get("Current_AC_Phase_1", 0), + "Current_AC_Phase_2": current_value.get("Current_AC_Phase_2", 0), + "Current_AC_Phase_3": current_value.get("Current_AC_Phase_3", 0), + "PowerReal_P_Sum": current_value.get("PowerReal_P_Sum", 0) + } + data[meter.ID] = meter_data + if current_value["success"]: + data["Meter_Sum"]["success"] &= True + data["Meter_Sum"]["Current_AC_Phase_1"] += meter_data["Current_AC_Phase_1"] + data["Meter_Sum"]["Current_AC_Phase_2"] += meter_data["Current_AC_Phase_2"] + data["Meter_Sum"]["Current_AC_Phase_3"] += meter_data["Current_AC_Phase_3"] + data["Meter_Sum"]["PowerReal_P_Sum"] += meter_data["PowerReal_P_Sum"] + else: + data["Meter_Sum"]["success"] &= False + return data + + + +class Meter1(EnergyMeter): + + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + + def get_current_value(self): + raise NotImplementedError("Subclasses must implement use_energy method") + +class Meter2(EnergyMeter): + + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + + + def get_current_value(self): + + raise NotImplementedError("Subclasses must implement use_energy method") + + +class Fronius(EnergyMeter): + + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + + def get_current_value(self): + url = f"http://{self.IP}/solar_api/v1/GetMeterRealtimeData.cgi?Scope=System" + try: + response = requests.get(url) + if response.status_code == 200: + data = response.json() + if "Body" in data and "Data" in data["Body"]: + meter_data = data["Body"]["Data"] + if str(self.Adr) in meter_data: + meter_values = meter_data[str(self.Adr)] + current_ac_phase_1 = meter_values.get("Current_AC_Phase_1", 0) + current_ac_phase_2 = meter_values.get("Current_AC_Phase_2", 0) + current_ac_phase_3 = meter_values.get("Current_AC_Phase_3", 0) + power_real_p_sum = meter_values.get("PowerReal_P_Sum", 0) + return {"success": True, + "Current_AC_Phase_1": current_ac_phase_1, + "Current_AC_Phase_2": current_ac_phase_2, + "Current_AC_Phase_3": current_ac_phase_3, + "PowerReal_P_Sum": power_real_p_sum} + return {"success": False} + else: + return {"success": False} + except Exception as e: + print(f"An error occurred: {str(e)}") + return {"success": False} \ No newline at end of file diff --git a/client/energyproducer.py b/client/energyproducer.py new file mode 100644 index 0000000..1aec05d --- /dev/null +++ b/client/energyproducer.py @@ -0,0 +1,126 @@ +import sys +import json +import requests + +class EnergyProducer: + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + def get_current_value(self): + raise NotImplementedError("Subclasses must implement use_energy method") + + + @staticmethod + def create_producerlist_from_json(json_data): + subclasses = [cls for cls in sys.modules[__name__].__dict__.values() if isinstance(cls, type) and issubclass(cls, EnergyProducer) and cls != EnergyProducer] + + energy_producers = [] + data = json.loads(json_data) + + for user_data in data["producers"]: + user_type = user_data["type"] + user_config = user_data["config"] + for subclass in subclasses: + if user_type in subclass.__name__: + energy_producers.append(subclass(user_config)) + return energy_producers + + @staticmethod + def get_all_current_values(producers): + data = {"Producer_sum": {"success": True, "day_energy": 0, "pac": 0, "total_energy": 0, "year_energy": 0}} + for producer in producers: + if isinstance(producer, EnergyProducer): + current_value = producer.get_current_value() + producer_data = { + "success": current_value["success"], + "day_energy": current_value.get("day_energy", 0), + "pac": current_value.get("pac", 0), + "total_energy": current_value.get("total_energy", 0), + "year_energy": current_value.get("year_energy", 0) + } + data[producer.ID] = producer_data + if current_value["success"]: + data["Producer_sum"]["success"] &= True + data["Producer_sum"]["day_energy"] += producer_data["day_energy"] + data["Producer_sum"]["pac"] += producer_data["pac"] + data["Producer_sum"]["total_energy"] += producer_data["total_energy"] + data["Producer_sum"]["year_energy"] += producer_data["year_energy"] + else: + data["Producer_sum"]["success"] &= False + return data + +class Producer1(EnergyProducer): + + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + + def get_current_value(self): + raise NotImplementedError("Subclasses must implement use_energy method") + + + +class Producer2(EnergyProducer): + + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + + + def get_current_value(self): + raise NotImplementedError("Subclasses must implement use_energy method") + + +class Fronius(EnergyProducer): + + def __init__(self, config): + self.ID = config.get("ID") + self.IP = config.get("IP") + self.Adr = config.get("Adr") + + + def get_current_value(self): + url = f"http://{self.IP}/solar_api/v1/GetInverterRealtimeData.cgi?Scope=System" + + try: + response = requests.get(url) + + success = response.status_code == 200 + data = response.json() if success else None + + if data: + day_energy = data.get("Body", {}).get("Data", {}).get("DAY_ENERGY", {}).get("Values", {}).get(str(self.Adr)) + pac = data.get("Body", {}).get("Data", {}).get("PAC", {}).get("Values", {}).get(str(self.Adr)) + total_energy = data.get("Body", {}).get("Data", {}).get("TOTAL_ENERGY", {}).get("Values", {}).get(str(self.Adr)) + year_energy = data.get("Body", {}).get("Data", {}).get("YEAR_ENERGY", {}).get("Values", {}).get(str(self.Adr)) + return { + "success": success, + "day_energy": day_energy, + "pac": pac, + "total_energy": total_energy, + "year_energy": year_energy + } + else: + return { + "success": success, + "day_energy": None, + "pac": None, + "total_energy": None, + "year_energy": None + } + except: + return { + "success": False, + "day_energy": None, + "pac": None, + "total_energy": None, + "year_energy": None + } + + \ No newline at end of file diff --git a/client/energyuser.py b/client/energyuser.py new file mode 100644 index 0000000..f79db3b --- /dev/null +++ b/client/energyuser.py @@ -0,0 +1,222 @@ +import random +import sys +import json +import requests +class EnergyUser: + def __init__(self, config): + self.ID = config.get("ID") + self.user_prio = config.get("user_prio", 0) + self.lock_prio = config.get("lock_prio", 0) + self.idle = True + self.used_energy = 0 + self.current_power = 0 + self.current_delta_power = 0 + + self.modular = False + self.powersteps = [] + + def calc_used_power(self): + raise NotImplementedError("Subclasses must implement use_energy method") + + + + def use_energy(self, amount): + raise NotImplementedError("Subclasses must implement use_energy method") + + + + + def get_current_values(self): + raise NotImplementedError("Subclasses must implement use_energy method") + + + def get_requested_power(self): + + max_power = max(self.powersteps) + return max_power if random.choice([True, False]) else max_power + return 0 + + + + + @staticmethod + def create_userlist_from_json(json_data): + subclasses = [cls for cls in sys.modules[__name__].__dict__.values() if isinstance(cls, type) and issubclass(cls, EnergyUser) and cls != EnergyUser] + + energy_users = [] + data = json.loads(json_data) + + for user_data in data["users"]: + user_type = user_data["type"] + user_config = user_data["config"] + for subclass in subclasses: + if user_type in subclass.__name__: + energy_users.append(subclass(user_config)) + + return energy_users + + + + @staticmethod + def get_all_current_values(users): + data = {"User_data": { "Current_Power": 0, "Used_Energy": 0, "Current_Prio": 0, "Current_deltaPower": 0, "measured_Temp": 0}} + for user in users: + current_value = user.get_current_value() + userdata = { + "Current_Power": current_value.get("Current_Power", 0), + "Used_Energy": current_value.get("Used_Energy", 0), + "Current_Prio": current_value.get("Current_Prio", 0), + "Current_deltaPower": current_value.get("Current_deltaPower", 0), + "measured_Temp": current_value.get("measured_Temp", 0) + } + + data[user.ID] = userdata + return data + + + +class User1(EnergyUser): + + def __init__(self, config): + self.ID = config.get("ID") + self.user_prio = config.get("user_prio", 0) + self.lock_prio = config.get("lock_prio", 0) + self.idle = True + self.used_energy = 6 + self.current_power = 0 + self.current_delta_power = 0 + + self.modular = False + self.powersteps = [100, 600] + + + def calc_used_power(self): + pass + + + def use_energy(self, amount): + print(f"Using energy as {self.ID} with amount {amount}") + # Hier kannst du die spezifische Logik für User 1 implementieren + + def get_current_value(self): + return {"Current_Power": self.current_power, + "Used_Energy": self.used_energy, + "Current_Prio": self.user_prio, + "Idle": self.idle, + "Current_deltaPower": self.current_delta_power} + + + + + +class User2(EnergyUser): + modular = False + powersteps = [200, 400] + + def __init__(self, config): + self.ID = config.get("ID") + self.user_prio = config.get("user_prio", 0) + self.lock_prio = config.get("lock_prio", 0) + self.idle = True + self.used_energy = 4 + self.current_power = 0 + self.current_delta_power = 0 + + self.modular = False + self.powersteps = [0] + + + def calc_used_power(self): + pass + + + def use_energy(self, amount): + print(f"Using energy as {self.ID} with amount {amount}") + # Hier kannst du die spezifische Logik für User 2 implementieren + + def get_current_value(self): + return {"Current_Power": self.current_power, + "Used_Energy": self.used_energy, + "Current_Prio": self.user_prio, + "Current_deltaPower": self.current_delta_power} + + + + +class Boiler_1Stufig_Shelly(EnergyUser): + + def __init__(self, config): + self.ID = config.get("ID") + self.user_prio = config.get("user_prio", 0) + self.lock_prio = config.get("lock_prio", 0) + self.idle = True + self.used_energy = 0 + self.current_power = 0 + self.current_delta_power = 0 + + self.modular = False + self.powersteps = [0] + + self.measured_Temp =0 + # userdefinierte Variablen + self.boilerleistung = config.get("boilerpower", 0) + self.temperatur = config.get("temperatur", 0) + self.shelly_ip = config.get("shelly_ip") + + + def get_shelly_temperature(self): + try: + url = f"http://{self.shelly_ip}/status" + response = requests.get(url) + if response.status_code == 200: + data = response.json() + temperature = data.get("ext_temperature", {}).get("0", {}).get("tC") + self.measured_Temp =temperature + + return temperature + else: + print("Failed to get temperature from Shelly.") + self.measured_Temp = 0 + + return None + except Exception as e: + print(f"Error occurred while getting temperature from Shelly: {e}") + return None + + def set_shelly_output(self, state): + try: + url = f"http://{self.shelly_ip}/relay/0?turn={'on' if state else 'off'}" + response = requests.get(url) + if response.status_code != 200: + print("Failed to set Shelly output state.") + except Exception as e: + print(f"Error occurred while setting Shelly output state: {e}") + + def calc_used_power(self): + + temperature = self.get_shelly_temperature() + if temperature is not None and temperature < self.temperatur: + self.powersteps[0] = self.boilerleistung + else: + self.current_power = 0 + + def use_energy(self, amount): + if amount == self.boilerleistung: + self.set_shelly_output(True) + else: + self.set_shelly_output(False) + print(f"Using energy as {self.ID} with amount {amount}") + + def get_current_value(self): + return {"Current_Power": self.current_power, + "Used_Energy": self.used_energy, + "Current_Prio": self.user_prio, + "measured_Temp": self.measured_Temp, + + "Idle": self.idle, + "Current_deltaPower": self.current_delta_power} + + + + + diff --git a/client/engine.py b/client/engine.py new file mode 100644 index 0000000..8a6528f --- /dev/null +++ b/client/engine.py @@ -0,0 +1,54 @@ + +import serverrequests as serverrequests +import JsonHandling +import energymeter +import energyproducer +import energyuser +import time +import datetime +import json +import main +# Gehe in eine Dauerschlaufe + +ID = "SRING_TO_DEFINE" + +producer_values = [] +producers =[] + +meter_values = [] +meter = [] + +user_values = [] +users = [] + +Collector = JsonHandling.DataCollector() +data = {} + +def calcSomeStuff(): + return + + + +while True: + + # Neue Konfig holen + config = serverrequests.update_config_on_server(ID, data) + if JsonHandling.JsonHandling.check_config_has_changed(config): + producers = energyproducer.EnergyProducer.create_producerlist_from_json(config) + meter = energymeter.EnergyMeter.create_meterlist_from_json(config) + users = energyuser.EnergyUser.create_userlist_from_json(config) + + producer_values = energyproducer.EnergyProducer.get_all_current_values(producers) + meter_values = energymeter.EnergyMeter.get_all_current_values(meter) + + calcSomeStuff() + for user in users: + user.calc_used_power() + + main.EnergyUserFactory.distribute_energy(users, meter_values["Meter_Sum"]["PowerReal_P_Sum"]) + + user_values = energyuser.EnergyUser.get_all_current_values(users) + + Collector.collect_and_store_data(producer_values, meter_values, user_values) + data = Collector.data + time.sleep(5) \ No newline at end of file diff --git a/client/hey.html b/client/hey.html new file mode 100644 index 0000000..449fe32 --- /dev/null +++ b/client/hey.html @@ -0,0 +1,112 @@ + + + + + + Highcharts Line Chart + + + + + + +
+ +
+ PAC Values +
+ Success Values + + + + + diff --git a/client/main.py b/client/main.py new file mode 100644 index 0000000..a649e13 --- /dev/null +++ b/client/main.py @@ -0,0 +1,164 @@ +import json +import sys +import random +import JsonHandling as JsonHandling +from collections import defaultdict +import energyuser as energyuser +import random + +class EnergyUser: + def __init__(self, config): + self.ID = config.get("ID") + self.user_prio = config.get("user_prio", 0) + self.lock_prio = config.get("lock_prio", 0) + self.idle = True + self.used_energy = 0 + self.current_power = 0 + self.current_delta_power = 0 + + def use_energy(self, amount): + raise NotImplementedError("Subclasses must implement use_energy method") + + modular = False + powersteps = [] + + def get_requested_power(self): + + max_power = max(self.powersteps) + return max_power if random.choice([True, False]) else max_power + return 0 + +class User1(EnergyUser): + modular = True + powersteps = [100, 600] + + def __init__(self, config): + self.ID = config.get("ID") + self.user_prio = config.get("user_prio", 0) + self.lock_prio = config.get("lock_prio", 0) + self.idle = True + self.used_energy = 6 + self.current_power = 0 + self.current_delta_power = 0 + + def use_energy(self, amount): + print(f"Using energy as {self.ID} with amount {amount}") + # Hier kannst du die spezifische Logik für User 1 implementieren + + + +class User2(EnergyUser): + modular = False + powersteps = [200, 400] + + def __init__(self, config): + self.ID = config.get("ID") + self.user_prio = config.get("user_prio", 0) + self.lock_prio = config.get("lock_prio", 0) + self.idle = True + self.used_energy = 4 + self.current_power = 0 + self.current_delta_power = 0 + + + def use_energy(self, amount): + print(f"Using energy as {self.ID} with amount {amount}") + # Hier kannst du die spezifische Logik für User 2 implementieren + + + +class EnergyUserFactory: + @staticmethod + def create_from_json(json_data): + subclasses = [cls for cls in sys.modules[__name__].__dict__.values() if isinstance(cls, type) and issubclass(cls, EnergyUser) and cls != EnergyUser] + + energy_users = [] + data = json.loads(json_data) + + for user_data in data["users"]: + user_type = user_data["type"] + user_config = user_data["config"] + for subclass in subclasses: + if user_type in subclass.__name__: + energy_users.append(subclass(user_config)) + + return energy_users + + + + + @staticmethod + def get_current_available_power(): + a = random.randint(0,3000) + print(a) + return a + + @staticmethod + def distribute_energy(energy_users, current_power): + remaining_power = current_power - sum(user.current_delta_power for user in energy_users) + print(remaining_power) + # Filtere Benutzer mit idle = True + idle_energy_users = [user for user in energy_users if user.idle] + + # Erweitere die Schritte für modulare Benutzer + for user in idle_energy_users: + if user.modular: + user.powersteps = list(range(min(user.powersteps), max(user.powersteps) + 1)) + + # Sortiere die Benutzer nach ihrer Priorität und dann nach ihrer ID + idle_energy_users.sort(key=lambda x: (x.user_prio, x.used_energy)) + + # Schleife durch alle Prioritäten + priorities = set(user.user_prio for user in idle_energy_users) + for priority in priorities: + # Benutzer mit gleicher Priorität sammeln + same_priority_users = [u for u in idle_energy_users if u.user_prio == priority] + if not same_priority_users: + continue + + # Sammle alle Schritte der Benutzer in einem Array + all_steps = [] + for user in same_priority_users: + all_steps.extend([(user, step) for step in user.powersteps]) + + # Sortiere die Schritte nach Größe + all_steps.sort(key=lambda x: x[1]) + + # Variable zur Verfolgung der bereitgestellten Energie für jeden Benutzer + user_energy_prov = {user: 0 for user in same_priority_users} + + # Iteriere durch alle Schritte + for user, powerstep in all_steps: + # Überprüfe, ob noch genügend verbleibende Energie für den nächsten Schritt vorhanden ist + if remaining_power >= powerstep - user_energy_prov[user]: + # Aktualisiere die verbleibende Energie und die bereitgestellte Energie für den Benutzer + remaining_power -= (powerstep - user_energy_prov[user]) + user_energy_prov[user] = powerstep + + # Verteile die bereitgestellte Energie auf die Benutzer + for user in same_priority_users: + user.use_energy(user_energy_prov[user]) + + print("Final state after distributing power:") + for user in energy_users: + print(f"{user.ID}: {user.used_energy}") + +# Beispielverwendung +json_data = ''' +{ + "metadata":{"config_has_changed" : "0"}, + "users": [ + {"type": "User1", "config": {"ID":"Umod1","user_prio":1,"lock_prio":2}}, + {"type": "User1", "config": {"ID":"Umod3","user_prio":3,"lock_prio":4}}, + {"type": "User1", "config": {"ID":"Umod2","user_prio":2,"lock_prio":3}}, + {"type": "User1", "config": {"ID":"Umod2","user_prio":2,"lock_prio":3}}, + {"type": "User1", "config": {"ID":"Umod2","user_prio":2,"lock_prio":3}}, + {"type": "User1", "config": {"ID":"Umod2","user_prio":2,"lock_prio":3}}, + {"type": "User2", "config": {"ID":"Usta2","user_prio":2,"lock_prio":6}}, + {"type": "User2", "config": {"ID":"Usta2","user_prio":2,"lock_prio":6}} + ] +} + +''' + +# \ No newline at end of file diff --git a/client/serverrequests.py b/client/serverrequests.py new file mode 100644 index 0000000..3d5664d --- /dev/null +++ b/client/serverrequests.py @@ -0,0 +1,23 @@ +import requests + +def update_config_on_server(token, config): + ## For developement now just return json from here + with open("config.txt", 'r') as file: + json_data = file.read() + + return json_data + + + ## For server later + response = requests.post(f'http://your_server_ip:5000/update_config?token={token}', json=config) + if response.status_code == 200: + print('Config updated successfully.') + else: + print('Failed to update config.') + return response + +if __name__ == '__main__': + # Beispiel für die Verwendung der Funktion update_config_on_server + token = 'your_token' + config = {'key1': 'new_value1', 'key2': 'new_value2'} + update_config_on_server(token, config) \ No newline at end of file diff --git a/server/main.py b/server/main.py new file mode 100644 index 0000000..703b94d --- /dev/null +++ b/server/main.py @@ -0,0 +1,56 @@ +from flask import Flask, request, jsonify, abort +import os + +app = Flask(__name__) + +TOKENS_FILE = "tokens.txt" +CONFIG_DIR = "configs" + +@app.route('/getconfig', methods=['POST']) +def get_config(): + # Überprüfe, ob die erforderlichen Daten im Request vorhanden sind + if not request.json or 'token' not in request.json or 'data' not in request.json: + abort(400, 'Bad request. JSON data with "token" and "data" is required.') + + token = request.json['token'] + data = request.json['data'] + + # Überprüfe, ob der Token gültig ist + if not is_valid_token(token): + abort(401, 'Unauthorized. Invalid token.') + + # Speichere die Daten in einem Datei für das entsprechende Token + save_data(token, data) + + # Lade die Konfigurationsdatei für das Token + config = load_config(token) + + return jsonify(config) + +def is_valid_token(token): + # Überprüfe, ob der Token in der tokens.txt Datei vorhanden ist + with open(TOKENS_FILE, 'r') as file: + tokens = file.read().splitlines() + return token in tokens + +def save_data(token, data): + # Erstelle das Verzeichnis für die Konfigurationsdateien, falls es nicht existiert + if not os.path.exists(CONFIG_DIR): + os.makedirs(CONFIG_DIR) + + # Speichere die Daten in einer Datei für das entsprechende Token + with open(os.path.join(CONFIG_DIR, f'{token}.json'), 'w') as file: + file.write(jsonify(data)) + +def load_config(token): + config_file = os.path.join(CONFIG_DIR, f'{token}.json') + + # Lade die Konfigurationsdatei für das Token + if os.path.exists(config_file): + with open(config_file, 'r') as file: + return json.load(file) + else: + return {} + +if __name__ == '__main__': + app.run(debug=True)