From cf43f985bf8e90b0dc6a53209f51aa453ad3f24d Mon Sep 17 00:00:00 2001 From: bethebestKR Date: Tue, 13 May 2025 23:33:44 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EB=B3=BC=ED=8A=B8=EA=B0=92=20100=EC=9D=B4?= =?UTF-8?q?=EC=83=81=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95,=20=EB=9D=BC?= =?UTF-8?q?=EC=A6=88=EB=B2=A0=EB=A6=AC=ED=8C=8C=EC=9D=B4=20serial=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gui_app.py | 5 +++-- gui_client.py | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gui_app.py b/gui_app.py index 777a7e1..9b01219 100644 --- a/gui_app.py +++ b/gui_app.py @@ -78,9 +78,9 @@ def create_widgets(self): self.ws_entry = ttk.Entry(ws_frame) self.ws_entry.pack(side=tk.LEFT, fill=tk.X, expand=True) - self.ws_entry.insert(0, "ws://localhost:8080/ocpp") - + self.ws_entry.insert(0, "ws://localhost:8080/ocpp") # Serial port + #"/dev/ttyUSB0" serial_frame = ttk.Frame(left_frame) serial_frame.pack(fill=tk.X, pady=5) @@ -89,6 +89,7 @@ def create_widgets(self): self.serial_entry = ttk.Entry(serial_frame) self.serial_entry.pack(side=tk.LEFT, fill=tk.X, expand=True) + # self.serial_entry.insert(0, "/dev/ttyUSB0") # Use serial checkbox self.use_serial_var = tk.BooleanVar(value=False) diff --git a/gui_client.py b/gui_client.py index 9d91ec4..6a8f7c3 100644 --- a/gui_client.py +++ b/gui_client.py @@ -355,7 +355,7 @@ def get_load3_data(self, number_of_load: int) -> bool: if i*2 < len(self.load3_mv): voltage = self.load3_mv[i*2] # 전압이 임계값(예: 50V) 이상이면 케이블이 연결된 것으로 간주 - if voltage > 50.0: + if voltage > 100.0: if not self.cable_connected[i]: self.cable_connected[i] = True self.app.log(f"충전기 {i+1}: 케이블 연결 감지됨") From 688698a08f9fb4bd934a04ac8c0c8c893e4c3210 Mon Sep 17 00:00:00 2001 From: bethebestKR Date: Wed, 28 May 2025 15:17:48 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=B5=9C=EC=8B=A0=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/charger_windows.cpython-311.pyc | Bin 0 -> 25667 bytes __pycache__/charger_windows.cpython-313.pyc | Bin 27106 -> 24983 bytes __pycache__/charger_windows.cpython-38.pyc | Bin 0 -> 13443 bytes __pycache__/enums.cpython-311.pyc | Bin 0 -> 1252 bytes __pycache__/enums.cpython-313.pyc | Bin 1156 -> 1183 bytes __pycache__/enums.cpython-38.pyc | Bin 0 -> 969 bytes __pycache__/gui_app.cpython-311.pyc | Bin 0 -> 20989 bytes __pycache__/gui_app.cpython-313.pyc | Bin 20106 -> 20135 bytes __pycache__/gui_app.cpython-38.pyc | Bin 0 -> 9048 bytes __pycache__/gui_client.cpython-311.pyc | Bin 0 -> 29911 bytes __pycache__/gui_client.cpython-313.pyc | Bin 27531 -> 29171 bytes __pycache__/gui_client.cpython-38.pyc | Bin 0 -> 14028 bytes __pycache__/ocpp_comm.cpython-311.pyc | Bin 0 -> 11646 bytes __pycache__/ocpp_comm.cpython-313.pyc | Bin 9938 -> 11107 bytes __pycache__/ocpp_comm.cpython-38.pyc | Bin 0 -> 5093 bytes __pycache__/ocpp_message.cpython-311.pyc | Bin 0 -> 1213 bytes __pycache__/ocpp_message.cpython-313.pyc | Bin 1105 -> 1132 bytes __pycache__/ocpp_message.cpython-38.pyc | Bin 0 -> 911 bytes __pycache__/visual_dashboard.cpython-311.pyc | Bin 0 -> 12671 bytes __pycache__/visual_dashboard.cpython-313.pyc | Bin 11597 -> 11624 bytes __pycache__/visual_dashboard.cpython-38.pyc | Bin 0 -> 6582 bytes charger_windows.py | 145 ++++++++++--- gui_app.py | 26 ++- gui_client.py | 206 +++++++++++++++---- ocpp_comm.py | 136 +++++++++++- tempCodeRunnerFile.py | 1 + visual_dashboard.py | 25 +++ 27 files changed, 459 insertions(+), 80 deletions(-) create mode 100644 __pycache__/charger_windows.cpython-311.pyc create mode 100644 __pycache__/charger_windows.cpython-38.pyc create mode 100644 __pycache__/enums.cpython-311.pyc create mode 100644 __pycache__/enums.cpython-38.pyc create mode 100644 __pycache__/gui_app.cpython-311.pyc create mode 100644 __pycache__/gui_app.cpython-38.pyc create mode 100644 __pycache__/gui_client.cpython-311.pyc create mode 100644 __pycache__/gui_client.cpython-38.pyc create mode 100644 __pycache__/ocpp_comm.cpython-311.pyc create mode 100644 __pycache__/ocpp_comm.cpython-38.pyc create mode 100644 __pycache__/ocpp_message.cpython-311.pyc create mode 100644 __pycache__/ocpp_message.cpython-38.pyc create mode 100644 __pycache__/visual_dashboard.cpython-311.pyc create mode 100644 __pycache__/visual_dashboard.cpython-38.pyc create mode 100644 tempCodeRunnerFile.py diff --git a/__pycache__/charger_windows.cpython-311.pyc b/__pycache__/charger_windows.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..03c00e949101ed76df1165cdc738ebe55400d3d9 GIT binary patch literal 25667 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 delta 6411 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 diff --git a/__pycache__/charger_windows.cpython-38.pyc b/__pycache__/charger_windows.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f5b63f6beb11d8c3d514b49957cfeb0843aa445 GIT binary patch literal 13443 zcmbtbd2n0Dd4Crk9&r&oL{X9@!*=WlJ|y}~s(KvTI&7s5otkvyu$^KcEJy(a0e0Vm zEuv5&Te3}CQX?gntvI4fI*M&2P9k54le(#!G`)}MF+E;q`cFG;B|5`cB(&%sUr7p|MEc=%lEo(FfQZV2ix zynQZp;mw1K^RJ{D=YAt{9^JL!wBehcH|a;F@~)em$nUM}&rwDDpBZG_dy&X%V>%Xy zg^ig{YU5a@Fb_LpmO>i~V`Q-~M|2(5u&{`T;_HZ*h~wM!q-JSj5iB6#NAIgl6v}%F zWl?#gdNsygTsVE8{^W{Oa@77VmA>RKjLHv#Rs1sJY}03G!2TF`i$ z$bxpjMm~yf7~j|ePH4SWw+Rkv2dHg4C<_N=T_`h!U3W0QUGMsWHfIGmBxqEjVH3i` z@6i&}0n!0+Hr3jQvGC19L;G(U8rpTA$@n3!;Fa>e zGm)=Mqk%c?$;iDS?!1SZhg?rOLyy3b|zmbPhi32iLE>G?xa_l-kQr!yI!T7&rHvNkjh(S*4>+z zGaoN(ZEg%O1p&HSre`Fb1tH*W0?_oB-m6CdZS~J|bo$qie*;;uQ^(-X z!Iy}0JAUo}YCNr|*I5J{GY)`Ai-u{?qO+z^5 z@N`y)LV05Jtl?YZg;L44^ZTc>Wg$c8A!&2drXRXX7P6)DL_WT?w^9<++RN|v(5F)N z&Ki9}4?um~g2XA?jcZY5^g_W3<|bv)Be^`SFU(PsmEO zEQZs)k_3kz+9k77=rEnlP5K4|zIFHgqxbru`?7oUCFVR|f5^A)+qrAh5A6gq&iHX~ zIxQ_jygB3Bg)+Fz^Ft$qpx>3Nl*bDbRhjo~wO~KQvc>Nj@g&ad6Itm;TrcZY-3(Am zJ93Z^iA-f7f5sV`D9f!(iEtQeO~-XhS+140qwiQu39r4pzkVzjTs26cfn;z6rPcy` z06&+2W+wEcxn7T%5j|-n^@I`A2lNE^IRRcyqPADBt#9Y&PDz!cEo}bL@ezr94?p+Y zAOWZt)`E{4>ooAK;9sq16v6-VAyx-a zLX?LJ;_rNzxOF#F*S#9?vRe|-5$(8MyWVq(P%S}UC??XZ#|+hyxtK<^kL&WYwHLkU zd@N{dFX#tCUc4SU1e0Vkg!-H6A(2?8A!h`+?sZUxtz2jwl%7b|?MWJKv*>}kORm#Y zPNhW;+JK`)FZb%-qwUc|--t#MqaMckjd6p@MzpfSbp!3GJzDtzOY@?|#AF0BJfuS{ z>e?r1jI|@M6TEIN|5Y6dR@Z8SBymWc(x^6CeNubTqOpZ>!1 zm)BzqrR z1B`XG>=Hj5NDe=|oj4_1g7Ekx+CT=)Oy|><9}jG+QDk=uzbnWhX=ig@p;9I}H&d!) zMcUX^CCXhq`wT3(#>)o-EMV82xp?%I2~^>)|IRc-qgR;9SE`0j7yXt7Wsmw@6a@30OGO6-cBE8!dh)SIR@+ z#9 z%F4ai2w%@D5tc$mk{t89i2T_8-GMAy;F^?2Uz{IT^D<41Npp-0Sq-O?@7(l?ng z)F<_84M!h@{Swg~qu+=?>h;2Y>D4zI5t4Xo+9h6Vo(>a+1fPW;+t;H=%<4rLAPd@4 z+AORj&wzys;YS98Fh{5s;tW<>N5AWVBnu%ycV8rH$&N zQDZc!PNU9h3y?Es^un&u#$_C1XN}0yX_chkmKp|O((%a02pj-F0q;8#2$M>Rs)#Ps z{Iv0(!H?0`jF@2=aFs6qU-0M7HBQR8%~|6_CDpAU8;}zJxySMO|AuJDfkdb#B9fv9Uv>%cjge7@ zZ(IzBwfH8)pjd}*w^%PW;F}beiH-R7h)v>he0w?617k3q@)O%B3IVTRkBat?Z?A$L zuy9T{o_&)dKDm%u1Vb{jTb%e$$gCdOQQXFn7R965JUP@R@#V_6j-VKi!>|k73RhTw zyfRU8x-&5@k26eQ#O{FTlI#X+^F8=d45$|-w~g2jG#bZ#C?3=ol-WTU#e?9!lL-t+ zCM)Yil=cUst`TTc9AG@P`L#^gq+Gg&*|$aD=hmV9w@~0mVDYSQ*z%Obp?-4D$1*#1 z-nVmfXJ*gt;T`wyNe@ceF-3apauWSWvbj`Tg`}YhsW=??z*+cxuvW{ivOzPj7bVO@ zzk8ZQGfP}Z>5}k!R6%ZEJ~x?RJIqhAnWf5=Cz{B4Abt3R<$R7tiNcu$XArC8WiQR$ zM}YWQt|36SBJ+svK*ykSrNr_rSE{&#+W_N}QFBaH5a@yxRGtXzExC@mbHJ#zFm~1@ z8I+Q&dP$aoWS&Y zR}pOa)5Lt{*iURleBdo!BI1LXYFoqy{vXGDtQ9dIv)CniL@!5TA{>b!uQMY05Pzb` z4#l6A;zJxZRq-5-3&q=JvBCV!SvZ2z){|yg6U-9jS;&Wt@+?l>S#_4KdKZ_6G3wG< zx*%Gbvqb7aj4Fs<(JX6&Sz%GhHF|ndvaV>hT6W59B z#SLN$MqDqpilJjTk<13vY*-Zs)$>NwUnXv9^&AL#-+T;l$;?L7Zd@HBj*i|UZWXtQ z4nUqz%Q<*t@-}4NBblrG*2b9=@=oLsTu%)IKlIW;iGJ;nM0{PT;6!@985ukI(e4&2&tf`HI{O~XHPAD=JP>+cF9zVqnys8Km)pi4g`n08jrW`Nj$mu+Wdyk|v z_ae`2{`B%un;TA3Q$!TE2Ec~Th>%tu9$$J<&&CTUYT>JH*?!lqTZeFAu&;pD!FjV1 zP=UcD%O^XW-o&9_xs#gjB5)6ZdkO3&KqM+Z zO5o=Rj1U+F@OyGqNjEZq_C@s8PXwwR0T7Dj`VkHsb5L2{M}4A7Q**3X4%1LSPsP32 z>FLr;Ca?y$jh|Gi-7QR2OIZ%7^dj9f9x_3Aw;R_s)0wtL&W_z9ciny8&K>?5YAyc_(*4Tsd63ri z30hY(_{_m-xd%mK%_264#`-$H(-APdyx7f z2&PI12B{x7(ZN;9(egi>ShEIge`MRWjmvDk_qh)sUzL0^lKL(gp3q=?M+ehi58M;F z2{Sn2Y*tB$1oHagiPK>5RO7kF7muBz8~dlw1}X40xx39nGx6iKk(z3*jlv;;AKr&zrO7%L z0vCKKco5*vLC)oP#{(=#%2(a{31OO6GisNuj;?BWX*@~Q)M>{lU^57eb$SLs7?dGkUN&aw{=Q6FCKqIzJRgmcuwLgze?aSfadYgotW}}mM?NJSY#Vl zt7VMPdL4|R88)J~38VJG)mOcu=cR)tr1aova?m6=q&A{k{PHVMCwLsP`0}HHhN0-> zM&;ir>Or6~({U^+#FN6nYGusmpGWo=+Rp3hWtb~5t43V%;5zUo;%YI^L1c))=#m_! zoj$1HatY~qGkDKI<I1rG6=#~{N7H5L}eU&li#C$p925^k~omxA@ExS zQZ2wILoG9OGUSeGX0I8cf4CulyNmlz$E;ny?5y7R^gE6$gb|5gx8vvjBS7st9vvI_ zitaq=U4zgkb$P94A{2wyK@0GMa3g1pP^*v#;kk@K{8_Y%;kt1<^D5E~rG<@qQN3<% zpgT|URc+jL8Y0}Up&dMyrMw8OMHvTC>|%ubQb5HnMk$RWjb zBeE~BcpSscHlBV<*@s)+y9(VJr{^y||H{Ra&?~cFA;a=Z@3d}7PN^%BbkYxv~k1yKT$Thb{cNL z61dUA3mwpR3`T~9ToRWPG5jNXAB4G4yJ8uwuQW+J2%NN!jUN;EI1;$vCuIVqt`rBz z%y94a5M@NlI)tY@UInUQFPr58WhC=z#J`l@D$U zh+CB_5I6yWd>*Y*+^QKbJ#(V)Hk`h*y8I$ahtoYupuCHWJOSXFQ`!CU8OqXCiabn! z&oj{}Zq!LrC{}(8z_+1e@T5bz32##IuXFM6{SSQXuKSug{4b~?)dE*g>iYn5bSeW# zkS2?mwn3+n(5)X^mJPX6yK>nnbmGFIuj3dnoJO*SkKvb)P{+WKltQ4zv6ZIW=Hc2A zDI2dQAmS-L6I?IS(Q(YH81-U!$z%rGpWuAA$}@+Dl*`SYSZn*)+1n-OFunY1fZ=p< zNqoz9shGBW`9{Y(MEJ6OmOk}hU+nKFMVl;nyPu#`ss(s!e+Svu+qYJ2E?;Ujw{|&! zcg((WXFDYLCXB6iw)U?c?HjIiTXNih93P^+r8jDU9LL2L?X<94ay+bLH_P-e$!o~v z@G?0bCK)Z9mK<;8h0SuDW)3UaP1qnE<8kQx;y7(cZj#|hbt_xWOV0ODyZK(iCSW;! zxyGxZNZ6X@z;8na1KF=u8f}yPbd4A52*$LB9Y$I5 zOY(N)?*S-bE`Oi$VE|=ZwgLyK&4B_T8|-tZ(@awG5701u85;!h52@$-3T636)P!WQ z{9^)tLf}scuvzggrP#_?;{Cs+GG=q8RpRwF8f-DTWNQ2~s{L~UsTN>D{3f#BCqldp z2@U*hK(<~=_JT+u1KRn&A9hFWn)jCh%6l!%tdIjFl35O{V%qkjuBn$>JB<(xj9N*| zv#RO(ZB+b#7DFS$)mUk|t`-yMz^j9cevDCSfAiDWK}FjG--u8kkGeP?Y2~AB`~|ti zHVyGbte9ApzhcGi4*qK81ODPzc`?a-Rl0}A#C2B7PU>s&Sh3&zD{$HxGLpe3WFZYq zM&y5XSV*ki+AO4K^-65QvdC8JF*-tlfihdcG9*{o2wLKsQNP_C%0&DY zl`#>wOqfe^OUpP>d_x*cUXu1-L+yVNxm=F~td17tb1-66%fr@VWP4n`D#b4aTslaK zh|$82N&U-6;J{&6dqxqjYyv{DIFJ875aexPKoH|eAKH>2)**aV8g>ZMWHgho#lvC} zzMXktu<&Ku1;Urwt2B(~+ez3$VFqG1A@G1uSuXM=jG1%+=}r_jP8dSckuL&aCDF2! z!ggsB`0*c0!(H?mb=kr3aq+?N5&rZCM}8FZdDA}mODagUz!j8w1K=9$u1kKfrb0-3 zYVEdSOs{QPaatWA$d1FJ^|cP`Ze-}NB(xE3PLK*V%aFIRAH<^K`p=t#}A4jV${|x+fKxegX>)cRA*_#rwBYv;0S>T z0g4|g-{Dpxe4j(oXaJ(PsbQPJi463YeYO;x(9_Sx=x#=o-En8 zOc#|YDX3%$z;{L~(dGwLemKLZ`BY~(oP)n>JP_V6FktSANLl(>Ry=o1KZTzT|EklKn zVCaI%K&4Kgst7S4_zA2XBd<)TK?*8UC+>-xQc|Yg>wG>r-?`WK`+WR_@9<|ZVkg1T6B=wIjOqw8m~Ajkw$3t$MLC4IO@w*EzT*(ur@v^_xjq-8+{ihO z?{jg=CC+g%oGhcIRIp6IXb|i3xc~8qqN#q^kPk=o-CkBZBG-Rl;JX&SAFBW3C>VkyFS5Tyy{>bf|zV!f(uI{VM5a^y-74JOlexv#z6z(F-?0G=#3L5Uan+I z6Ww1bzyA<-)t^L!1WQbqej%*_oJY=OP%JZp$#;$wB=Ey&12#=Gq!@OGNi< zE1VGZ)do=;0nK5>3a3_xPu!Z`2#88t)5fL|PRKRM^bFgwh(R5s*11VI1vH#HN+FyS zvk&vKrsk`;oGfWdA)Hx}D{@JzW%E^zoIj0HAvKrBBYcl}`F<`%!0V zq5T+Uq!Q|(ZR47TZG(0y4^8C4#~O7}-@X3U|Jr(-xEFQzefK6UhVRJRr_kdVhUu{^ z!}kzC0x`1(=DnU|M~0SHuf$z`10$lK2-qwH)Ilbl#kT#}!c8dH>5oRnHr8IT!Ml3H96 Kv-vXP872VT(i0{C diff --git a/__pycache__/enums.cpython-38.pyc b/__pycache__/enums.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bd2d316dced54b6aa0928d3e33ad4afd2141a69c GIT binary patch literal 969 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 Q-mStfao(RdfWUnG|KdRmN&o-= literal 0 HcmV?d00001 diff --git a/__pycache__/gui_app.cpython-313.pyc b/__pycache__/gui_app.cpython-313.pyc index 9c4250090ba8d335a187416db12b44d60dfad29e..e36e6faa04cae1d246a1c4d1be793e05b24b50db 100644 GIT binary patch delta 108 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 YZ(A^Jw$sqYso`&l|L-0UN_ydc0gb}uh5!Hn literal 0 HcmV?d00001 diff --git a/__pycache__/gui_client.cpython-313.pyc b/__pycache__/gui_client.cpython-313.pyc index 7eb42c1634d680d3ded3fe5e19eb06f242f0a74c..cc0c8d8a7f919ad68ba723b5e2403a8f0dc847f5 100644 GIT binary patch delta 5325 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 AOaK4? literal 0 HcmV?d00001 diff --git a/__pycache__/ocpp_comm.cpython-311.pyc b/__pycache__/ocpp_comm.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fd8d77d665c13ef0f3088d16720a0e7934365c3a GIT binary patch literal 11646 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 delta 1344 zcmYLJU5Fc16rMXjnKYXp)1tDEd&I`2a#??{6Rql@3~XmdHCkcckg%3 zz2|4XU%zoA`fDT-64lC z&v@IrqX;GFUkNM4)5>oG#~do8y?vD^O=1XZXm3PMLbq5j8IaceM zHH0Ne7aEAUb?G@{5h?V#VbP1(r=JPoIMZVP+SsYR8B#Oe8|I1C&wk>3f! zAa+RC?XWK6xBkBsVBb2ulGD`pnMpnq=(o8fiqhY6EAc;KLNa?RVcbX<-;FQ)`CF78 z&99vq^-0Emkud%yuQ1u!_#pvNR4N4CmY8)8**WRFR$3M>p;9q$d5&3I<_KHadI;Hu zyfq&HyNG~a*6j)9swOhYRecxO`B^)q3`P~k3{nbX1``t424bo~Jr}T-)WI~eXTyX2 zVXzlfwqQp5|3MON#8bjsn2!_8g`Yb}li$UB*!bk~`GG%xDVLki?-GO`CHjeZ(KFVQ*|=h1z5um1 xL%0c>`1n5n);@p={mDx2ZG-9iVAe2LY`gV-%UQ-Q%}-6oPKn6+MF8ZR{srmxCi?&Y diff --git a/__pycache__/ocpp_comm.cpython-38.pyc b/__pycache__/ocpp_comm.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..36dc3d83611c1fb69a723d3b17369d73d43e73f6 GIT binary patch literal 5093 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 RSi9V%gBPiA|4Ui-{0pI|MH~PC literal 0 HcmV?d00001 diff --git a/__pycache__/ocpp_message.cpython-313.pyc b/__pycache__/ocpp_message.cpython-313.pyc index c89d08855ad4eaf513fba4bb58c0f9d335c998ed..17423926b26dd6b4f95fc922c8904e166a475ec4 100644 GIT binary patch delta 84 zcmcb}@rHx%GcPX}0}$k_Qq1_oxRI}j(cD!(v^ce>SU)$hGBrOhJvk#WFJ0dywK%&Z mzd%1Zv7oplKQA@Dpt2+*KTp3Xu{bHUs4^f^fAbv1txN#8%N{@g delta 57 zcmaFEagl@XGcPX}0}zPslFMLW+Q?VLD5K?U6_cD;P+XFqml{))Se%qvR2h&NQ<7R- L60>*wD1IG;^$=taX##q&hzPAv57t8M!M!Z&&X`2AAI$7xBOVIf zinJap6qUOam8&1%|!59aOrnt8w9yxEnhsUiYte!5owr6BZE zI-{b3a~Bq007a0Ah(d5vF%|f#P3&S5D~PH@Ybzv2#$wIX{&{&)053*o+npB`FX)q+!FQV2?2xM$B_$Zd5dI=3w#5pokKpp0bCYVSSB#kE`1_i9ev_G*=R%AbdRP;u;lhrUOxpcU4AuflBpgtFFBqvAV3V7ZiY zyGCb%R&u^ZJ<5ROFlaT1?9VYMgxNUg{}{`eWsIl6_{+D4iL$2vPaIu`V7e2FZeL#b z@j)y)J9@glCc3fMe4noO)9rZ3_(JJ%x#X5h-qo_k8xr9sX@ z?GWq~*hV4ATNd#h%VIfsj=YFOg*(Vb!6czXZFnJ*)gxW9myxw9+;)8uHR&D6iOauF M(+bKYp4O(dKm7vz&;S4c literal 0 HcmV?d00001 diff --git a/__pycache__/visual_dashboard.cpython-311.pyc b/__pycache__/visual_dashboard.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..137ce46b257a8c23a794b1a8e5e3555f2da04c3b GIT binary patch literal 12671 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 delta 57 zcmaD6bvBCcGcPX}0}$lwmCHD&x{;5ASw_#R`_ diff --git a/__pycache__/visual_dashboard.cpython-38.pyc b/__pycache__/visual_dashboard.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..01d449c4dd9df9093eb0777a34475470371c7ca2 GIT binary patch literal 6582 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 0 else 0.0 # 0으로 나누기 방지 self.ocpp_client.load3_mv[idx*2] = voltage self.ocpp_client.load3_mv[idx*2+1] = current @@ -484,20 +523,34 @@ def start_charging_manually(self): # 케이블 연결 상태 설정 self.ocpp_client.cable_connected[idx] = True else: - # 시리얼 포트 사용 중인 경우 실제 측정값 사용 - power = max(3000, self.last_power_value) # 최소 3000W 또는 현재 측정값 + # 시리얼 포트 사용 중인 경우 초기 전력값 0으로 시작 + power = 0 # 기본값을 0W로 변경 # 충전 시작 self.charging = True self.update_status("충전 중 (수동 모드)") self.update_connection_status(True) - # 트랜잭션 시작 이벤트 전송 - asyncio.run_coroutine_threadsafe( - self.ocpp_client.start_charging(self.charger_id, power), - self.event_loop - ) - self.transaction_started = True + # 트랜잭션 시작 이벤트 전송 시 예외 처리 추가 + try: + # 트랜잭션 시작 이벤트를 별도의 함수로 분리하여 실행 + def start_transaction_async(): + try: + asyncio.run_coroutine_threadsafe( + self.ocpp_client.start_charging(self.charger_id, power), + self.event_loop + ) + self.transaction_started = True + except Exception as e: + print(f"트랜잭션 시작 오류: {e}") + messagebox.showerror("충전 시작 오류", f"충전 시작 중 오류가 발생했습니다:\n{str(e)}") + + # 약간의 지연을 두어 GUI 업데이트 후 트랜잭션 시작 + self.after(100, start_transaction_async) + except Exception as e: + print(f"충전 시작 예약 오류: {e}") + messagebox.showerror("충전 시작 오류", f"충전 시작 중 오류가 발생했습니다:\n{str(e)}") + return # 버튼 상태 업데이트 self.start_button.config(state=tk.DISABLED) @@ -505,6 +558,9 @@ def start_charging_manually(self): except ValueError: messagebox.showerror("입력 오류", "유효한 숫자를 입력하세요") + except Exception as e: + print(f"충전 시작 중 예상치 못한 오류: {e}") + messagebox.showerror("충전 시작 오류", f"충전 시작 중 오류가 발생했습니다:\n{str(e)}") def stop_charging_manually(self): """수동 충전 중지""" @@ -525,3 +581,28 @@ def on_closing(self): self.destroy() else: self.destroy() + + def update_total_price(self, total_price): + """총 금액 정보 업데이트""" + try: + if total_price is not None: + # 금액 유효성 확인 + if isinstance(total_price, (int, float)) and total_price >= 0: + self.total_price_var.set(f"{total_price}원") + + # 충전 상태를 '완료'로 변경하고 버튼 상태 업데이트 + self.charging = False + self.manual_mode = False + self.update_status("충전 완료") + + # 버튼 상태 업데이트 + self.start_button.config(state=tk.NORMAL) + self.stop_button.config(state=tk.DISABLED) + else: + print(f"금액 형식 오류: {total_price}") + self.total_price_var.set("금액 오류") + else: + self.total_price_var.set("-") + except Exception as e: + print(f"총 금액 업데이트 오류: {e}") + self.total_price_var.set("업데이트 오류") diff --git a/gui_app.py b/gui_app.py index 9b01219..299e644 100644 --- a/gui_app.py +++ b/gui_app.py @@ -78,7 +78,8 @@ def create_widgets(self): self.ws_entry = ttk.Entry(ws_frame) self.ws_entry.pack(side=tk.LEFT, fill=tk.X, expand=True) - self.ws_entry.insert(0, "ws://localhost:8080/ocpp") + self.ws_entry.insert(0, "ws://172.23.141.144:8080/ocpp") + # Serial port #"/dev/ttyUSB0" serial_frame = ttk.Frame(left_frame) @@ -87,10 +88,11 @@ def create_widgets(self): serial_label = ttk.Label(serial_frame, text="시리얼 포트:") serial_label.pack(side=tk.LEFT, padx=(0, 5)) + self.serial_entry = ttk.Entry(serial_frame) self.serial_entry.pack(side=tk.LEFT, fill=tk.X, expand=True) - # self.serial_entry.insert(0, "/dev/ttyUSB0") - + self.serial_entry.insert(0, "/dev/ttyUSB0") + # Use serial checkbox self.use_serial_var = tk.BooleanVar(value=False) use_serial_check = ttk.Checkbutton( @@ -269,6 +271,19 @@ def update_power_display(self, charger_id, power_value): if charger_id in self.charger_windows and self.charger_windows[charger_id].winfo_exists(): self.charger_windows[charger_id].update_power_display(power_value) + def update_total_price(self, charger_id, total_price): + """충전 완료 후 총 금액 정보 업데이트""" + if 1 <= charger_id <= NUM_EVSE: + # 로그에 기록 + self.log(f"충전기 {charger_id}: 총 금액 {total_price}원") + + # 시각화 대시보드에 총 금액 업데이트 + self.charger_visuals[charger_id - 1].update_total_price(total_price) + + # 충전기 창이 열려 있으면 금액 정보 업데이트 + if charger_id in self.charger_windows and self.charger_windows[charger_id].winfo_exists(): + self.charger_windows[charger_id].update_total_price(total_price) + def toggle_connection(self): """연결/해제 토글""" if not self.ocpp_client or not self.ocpp_client.running: @@ -334,6 +349,11 @@ def open_charger(self, charger_id): messagebox.showinfo("충전기 사용중", f"충전기 {charger_id}는 현재 사용중입니다.") return + # Check if charger is unavailable + if self.charger_status_vars[charger_id - 1].get() == "Unavailable": + messagebox.showinfo("충전기 사용 불가", f"충전기 {charger_id}는 현재 사용할 수 없습니다.") + return + # First show login window LoginWindow(self, charger_id, lambda: self.on_login_success(charger_id), self.ocpp_client, self.event_loop) diff --git a/gui_client.py b/gui_client.py index 6a8f7c3..e716794 100644 --- a/gui_client.py +++ b/gui_client.py @@ -35,6 +35,7 @@ def __init__(self, app, websocket_url: str, serial_port: str = None, baud_rate: self.seq_num_counter = [1] * NUM_EVSE # 시퀀스 넘버 카운터 self.boot_notification_sent = False self.server_tx_id_received = False # 서버에서 트랜잭션 ID를 받았는지 여부 + self.tx_id_lock = asyncio.Lock() # 트랜잭션 ID 생성을 위한 락 추가 self.load3_mv = [0.0] * 10 self.running = False @@ -46,6 +47,18 @@ def __init__(self, app, websocket_url: str, serial_port: str = None, baud_rate: # 트랜잭션 시작 상태 추적을 위한 변수 추가 self.transaction_started = [False] * NUM_EVSE + + # 충전 대기 상태 플래그 추가 + self.charging_pending = [False] * NUM_EVSE # 충전 대기 상태 플래그 + + # 충전기 가용성 상태 추적 변수 추가 + self.charger_available = [True] * NUM_EVSE # 초기값은, 모든 충전기가 사용 가능 + + # ChangeAvailability 콜백 등록 + self.comm.set_change_availability_callback(self.handle_change_availability) + + # RequestStopTransaction 콜백 등록 + self.comm.set_stop_transaction_callback(self.handle_request_stop_transaction) def is_raspberry_pi(self): """라즈베리파이 환경인지 확인""" @@ -126,28 +139,30 @@ async def send_transaction_event_started(self, evse_id: int) -> bool: self.app.log(f"EVSE {evse_id}: 이미 트랜잭션이 시작되었습니다. 중복 이벤트 무시.") return True - # 트랜잭션 ID 관리 - # 서버에서 트랜잭션 ID를 받은 적이 없고, 서버에서 받은 트랜잭션 ID가 있으면 사용 - if not self.server_tx_id_received and hasattr(self.comm, 'last_transaction_id') and self.comm.last_transaction_id: - try: - # 'tx-001' 형태에서 숫자 부분만 추출 - tx_id = self.comm.last_transaction_id - if tx_id.startswith('tx-'): - tx_num = int(tx_id[3:]) # 'tx-001'에서 '001'을 추출하여 정수로 변환 - # 다음 트랜잭션 ID를 위해 +1 - self.transaction_id_counter = tx_num + 1 - self.app.log(f"서버 응답에서 트랜잭션 ID({tx_id})를 기반으로 다음 ID 설정: tx-{self.transaction_id_counter:03d}") - self.server_tx_id_received = True # 서버에서 ID를 받았음을 표시 - except (ValueError, AttributeError) as e: - self.app.log(f"트랜잭션 ID 파싱 오류: {e}. 기본 카운터 사용.") - - # 현재 충전기에 트랜잭션 ID 할당 - current_tx_id = self.transaction_id_counter - self.transaction_ids[evse_id - 1] = current_tx_id - self.app.log(f"충전기 {evse_id}에 트랜잭션 ID tx-{current_tx_id:03d} 할당") - - # 다음 트랜잭션을 위해 카운터 증가 (다음 충전기가 사용할 ID 준비) - self.transaction_id_counter += 1 + # 트랜잭션 ID 생성 및 할당 (락을 사용하여 동기화) + async with self.tx_id_lock: + # 트랜잭션 ID 관리 + # 서버에서 트랜잭션 ID를 받은 적이 없고, 서버에서 받은 트랜잭션 ID가 있으면 사용 + if not self.server_tx_id_received and hasattr(self.comm, 'last_transaction_id') and self.comm.last_transaction_id: + try: + # 'tx-001' 형태에서 숫자 부분만 추출 + tx_id = self.comm.last_transaction_id + if tx_id.startswith('tx-'): + tx_num = int(tx_id[3:]) # 'tx-001'에서 '001'을 추출하여 정수로 변환 + # 다음 트랜잭션 ID를 위해 +1 + self.transaction_id_counter = tx_num + 1 + self.app.log(f"서버 응답에서 트랜잭션 ID({tx_id})를 기반으로 다음 ID 설정: tx-{self.transaction_id_counter:03d}") + self.server_tx_id_received = True # 서버에서 ID를 받았음을 표시 + except (ValueError, AttributeError) as e: + self.app.log(f"트랜잭션 ID 파싱 오류: {e}. 기본 카운터 사용.") + + # 현재 충전기에 트랜잭션 ID 할당 + current_tx_id = self.transaction_id_counter + self.transaction_ids[evse_id - 1] = current_tx_id + self.app.log(f"충전기 {evse_id}에 트랜잭션 ID tx-{current_tx_id:03d} 할당") + + # 다음 트랜잭션을 위해 카운터 증가 (다음 충전기가 사용할 ID 준비) + self.transaction_id_counter += 1 # TransactionEvent 메시지 생성 message = { @@ -269,11 +284,40 @@ async def send_transaction_event_ended(self, evse_id: int, power_value: int) -> } } self.seq_num_counter[evse_id - 1] += 1 + + # 응답 수신을 위해 미리 total_price를 초기화 + self.comm.total_price = None + + # 메시지 전송 success = await self.comm.send_message(message) if success: self.app.log(f"EVSE {evse_id}: 충전 종료 이벤트 전송됨, 마지막 보고된 전력 [{power_value}W] (트랜잭션 ID: tx-{self.transaction_ids[evse_id - 1]:03d})") - self.transaction_started[evse_id - 1] = False # 트랜잭션 종료 상태로 변경 - self.transaction_ids[evse_id - 1] = None # 트랜잭션 ID 초기화 + + # 서버 응답을 기다림 (최대 3초) + wait_time = 0 + max_wait = 30 # 100ms * 30 = 3초 + while wait_time < max_wait and self.comm.total_price is None: + await asyncio.sleep(0.1) + wait_time += 1 + + # total_price가 설정된 경우에만 UI 업데이트 + if self.comm.total_price is not None: + total_price = self.comm.total_price + self.app.log(f"EVSE {evse_id}: 총 충전 금액: {total_price}원") + + # GUI에 총 금액 표시 업데이트 + if hasattr(self.app, 'update_total_price'): + self.app.update_total_price(evse_id, total_price) + + # 사용 후 초기화 + self.comm.total_price = None + else: + self.app.log(f"EVSE {evse_id}: 서버에서 총 금액 정보를 받지 못했습니다.") + + # 트랜잭션 상태 초기화 + self.transaction_started[evse_id - 1] = False + self.transaction_ids[evse_id - 1] = None + return success async def send_meter_values(self, evse_id: int, power_value: int) -> bool: @@ -343,6 +387,7 @@ def get_load3_data(self, number_of_load: int) -> bool: self.serial_data_valid = False return False values = data.strip().split() + self.app.log(f"수신된 데이터: {values}") for i in range(min(len(values), 10)): try: self.load3_mv[i] = float(values[i]) @@ -355,7 +400,7 @@ def get_load3_data(self, number_of_load: int) -> bool: if i*2 < len(self.load3_mv): voltage = self.load3_mv[i*2] # 전압이 임계값(예: 50V) 이상이면 케이블이 연결된 것으로 간주 - if voltage > 100.0: + if voltage > 50.0: if not self.cable_connected[i]: self.cable_connected[i] = True self.app.log(f"충전기 {i+1}: 케이블 연결 감지됨") @@ -419,13 +464,20 @@ def update_power_data(self, evse_id: int, power_value: int): async def check_charging_start(self): """충전 시작 확인""" for i in range(NUM_EVSE): - if self.prev_power_data[i] == 0 and self.power_data[i] > 0: - evse_id = i + 1 - # 상태 알림만 보내고, 트랜잭션 이벤트는 start_charging에서만 보냄 + evse_id = i + 1 + + # 충전 대기 상태이고 전력값이 일정 이상이면 트랜잭션 시작 + if self.charging_pending[i] and self.power_data[i] > 100: # 100W 이상일 때 + self.charging_pending[i] = False # 대기 상태 해제 + + # 이제 실제 측정값으로 트랜잭션 시작 이벤트 전송 + await self.send_transaction_event_started(evse_id) + self.app.log(f"충전기 {evse_id}: 실제 전력 감지됨, 트랜잭션 시작 ({self.power_data[i]}W)") + + # 기존 로직 + elif self.prev_power_data[i] == 0 and self.power_data[i] > 0: if not self.transaction_started[i]: await self.send_status_notification(evse_id, ConnectorStatus.OCCUPIED) - # 트랜잭션 이벤트는 start_charging에서 이미 보냈으므로 여기서는 보내지 않음 - # await self.send_transaction_event_started(evse_id) async def report_power_usage(self): """전력 사용량 보고""" @@ -450,25 +502,67 @@ async def check_charging_end(self): self.charging_active[i] = False self.prev_power_data[i] = self.power_data[i] + async def handle_change_availability(self, evse_id: int, is_operative: bool) -> bool: + """서버로부터 ChangeAvailability 요청 처리""" + try: + if 1 <= evse_id <= NUM_EVSE: + port_idx = evse_id - 1 + + # 충전기 가용성 상태 업데이트 + self.charger_available[port_idx] = is_operative + + # UI 업데이트 + if is_operative: + # Available 상태로 변경 (사용 가능) + await self.send_status_notification(evse_id, ConnectorStatus.AVAILABLE) + self.app.log(f"충전기 {evse_id}: 서버 요청에 의해 '사용 가능' 상태로 변경되었습니다.") + else: + # Unavailable 상태로 변경 (사용 불가) + await self.send_status_notification(evse_id, ConnectorStatus.UNAVAILABLE) + self.app.log(f"충전기 {evse_id}: 서버 요청에 의해 '사용 불가' 상태로 변경되었습니다.") + + # 충전 중이면 충전 중지 + if self.charging_active[port_idx]: + await self.stop_charging(evse_id) + + return True + else: + self.app.log(f"유효하지 않은 충전기 ID: {evse_id}") + return False + except Exception as e: + self.app.log(f"ChangeAvailability 처리 중 오류: {e}") + return False + async def start_charging(self, evse_id: int, power_value: int): """충전 시작""" if 1 <= evse_id <= NUM_EVSE: port_idx = evse_id - 1 + + # 충전기가 사용 불가 상태인 경우 충전 불가 + if not self.charger_available[port_idx]: + self.app.log(f"충전기 {evse_id}는 현재 사용 불가 상태입니다.") + return False + self.manual_power[port_idx] = power_value self.charging_active[port_idx] = True self.app.log(f"충전기 {evse_id}의 충전을 시작합니다. 전력: {power_value}W") - + # 시리얼 연결이 있는 경우 전력 공급 명령 전송 if self.use_serial: self.send_power_control_command(evse_id, True) - # Update status to Occupied - await self.send_status_notification(evse_id, ConnectorStatus.OCCUPIED) - - # 트랜잭션 시작 이벤트 전송 (여기서만 전송) - await self.send_transaction_event_started(evse_id) + # 상태만 Occupied로 변경하고, 트랜잭션 이벤트는 아직 보내지 않음 + await self.send_status_notification(evse_id, ConnectorStatus.OCCUPIED) - return True + # 트랜잭션 시작 플래그 설정 (아직 이벤트는 보내지 않음) + # 수정: 특정 충전기만 대기 상태로 설정 + self.charging_pending[evse_id - 1] = True # 해당 충전기만 대기 상태로 설정 + return True + else: + # 시리얼 연결이 없는 경우 기존처럼 처리 + await self.send_status_notification(evse_id, ConnectorStatus.OCCUPIED) + await self.send_transaction_event_started(evse_id) + return True return False async def stop_charging(self, evse_id: int): @@ -491,6 +585,29 @@ async def stop_charging(self, evse_id: int): return True return False + async def handle_request_stop_transaction(self, evse_id: int) -> bool: + """서버로부터 RequestStopTransaction 요청 처리""" + try: + if 1 <= evse_id <= NUM_EVSE: + port_idx = evse_id - 1 + + # 충전 중인지 확인 + if self.charging_active[port_idx]: + self.app.log(f"충전기 {evse_id}: 서버 요청에 의해 충전이 중지됩니다.") + + # 충전 중지 호출 + success = await self.stop_charging(evse_id) + return success + else: + self.app.log(f"충전기 {evse_id}: 충전 중이 아니므로 중지 요청이 거부되었습니다.") + return False + else: + self.app.log(f"유효하지 않은 충전기 ID: {evse_id}") + return False + except Exception as e: + self.app.log(f"RequestStopTransaction 처리 중 오류: {e}") + return False + async def run_loop(self): """메인 루프 실행""" self.running = True @@ -514,6 +631,7 @@ async def run_loop(self): self.power_data[i] = 0 self.prev_power_data[i] = 0 self.transaction_started[i] = False # 트랜잭션 시작 상태 초기화 + self.manual_power[i] = 0 # 초기 수동 전력값을 0으로 설정 if websocket_connected: await self.send_boot_notification() @@ -549,10 +667,16 @@ async def run_loop(self): # Generate temporary data for active chargers for i in range(NUM_EVSE): if self.charging_active[i]: - base_power = self.manual_power[i] if self.manual_power[i] > 0 else 3000 - variation = random.uniform(-200, 200) + base_power = self.manual_power[i] + # 전력값이 0이면 변동 없이 유지, 0보다 크면 변동 추가 + if base_power > 0: + variation = random.uniform(-200, 200) + power_with_variation = max(0, base_power + variation) + else: + power_with_variation = 0 + self.load3_mv[i*2] = 220.0 # Voltage - self.load3_mv[i*2+1] = (base_power + variation) / 220.0 # Current + self.load3_mv[i*2+1] = power_with_variation / 220.0 if power_with_variation > 0 else 0.0 # Current else: self.load3_mv[i*2] = 0.0 self.load3_mv[i*2+1] = 0.0 @@ -571,7 +695,7 @@ async def run_loop(self): else: self.app.log("데이터 읽기 오류") - await asyncio.sleep(0.1) + await asyncio.sleep(0.5) # 0.1초에서 0.5초로 변경 except Exception as e: self.app.log(f"오류 발생: {e}") finally: diff --git a/ocpp_comm.py b/ocpp_comm.py index 32c4d5b..0be5ae2 100644 --- a/ocpp_comm.py +++ b/ocpp_comm.py @@ -35,6 +35,9 @@ def __init__(self, websocket_url, serial_port=None, baud_rate=2400, max_retries= # 트랜잭션 ID 정보 저장 self.last_transaction_id = None # 마지막으로 수신한 트랜잭션 ID + + # 충전 완료 후 총 금액 정보 저장 + self.total_price = None # 트랜잭션 종료 시 받은 총 금액 async def connect_websocket(self) -> bool: """WebSocket 연결""" @@ -138,6 +141,11 @@ async def _send_message_and_wait_response(self, message: dict) -> bool: retry_info = f" (재시도: {message.get('retry_count', 0)}/{self.max_retries})" if message.get('retry_count', 0) > 0 else "" print(f"[WebSocket sending]{retry_info} {json_message}") + # 트랜잭션 종료 이벤트인지 확인 + is_tx_ended = message.get("action") == "TransactionEvent" and message.get("payload", {}).get("eventType") == "Ended" + if is_tx_ended: + print("트랜잭션 종료 이벤트 전송 - 응답에서 총 금액 정보 확인 예정") + await self.websocket.send(json_message) # 응답 수신 태스크 시작 @@ -174,13 +182,34 @@ async def receive_message(self): response = await self.websocket.recv() print(f"서버 응답: {response}") - # 응답 저장 및 이벤트 설정 - self.last_response = response - self.response_event.set() - # 응답 파싱 try: response_data = json.loads(response) + + # 요청 메시지 처리 (CALL - messageTypeId = 2) + if len(response_data) >= 4 and response_data[0] == 2: + message_id = response_data[1] + action = response_data[2] + payload = response_data[3] + + # 요청 처리 완료 후 응답 이벤트 설정 (중요: 응답 대기 타임아웃 방지) + self.last_response = "request_handled" + self.response_event.set() + + # ChangeAvailability 요청 처리 + if action == "ChangeAvailability": + await self.handle_change_availability(message_id, payload) + return + + # RequestStopTransaction 요청 처리 추가 + if action == "RequestStopTransaction": + await self.handle_request_stop_transaction(message_id, payload) + return + + # 일반 응답 처리 (기존 로직) + self.last_response = response + self.response_event.set() + if len(response_data) >= 3 and response_data[0] == 3: # 응답 메시지인 경우 payload = response_data[2] # 응답 페이로드 message_id = response_data[1] # 메시지 ID @@ -198,6 +227,17 @@ async def receive_message(self): tx_id = f"tx-{int(tx_id):03d}" self.last_transaction_id = tx_id print(f"트랜잭션 ID 업데이트: {self.last_transaction_id}") + + # 총 금액 정보 추출 (TransactionEvent.Ended 응답에 포함) + if "totalPrice" in payload: + price_value = payload["totalPrice"] + # 숫자인지 확인하고 유효한 경우에만 설정 + if isinstance(price_value, (int, float)) and price_value >= 0: + # total_price 설정 (이 값은 send_transaction_event_ended에서 확인됨) + self.total_price = price_value + print(f"총 금액 정보 수신: {self.total_price}원") + else: + print(f"유효하지 않은 금액 정보: {price_value}") except Exception as e: print(f"응답 파싱 중 오류: {e}") @@ -208,3 +248,91 @@ async def receive_message(self): self.websocket = None # 오류 발생 시에도 이벤트 설정 (대기 중인 태스크가 진행되도록) self.response_event.set() + + async def handle_change_availability(self, message_id, payload): + """ChangeAvailability 요청 처리""" + try: + print(f"ChangeAvailability 요청 수신: {payload}") + + # 요청 파라미터 확인 + operational_status = payload.get("operationalStatus") + evse_id = payload.get("evse", {}).get("id") + + if not operational_status or not evse_id: + print("필수 파라미터 누락") + # 오류가 있어도 항상 일반 응답 전송 + await self.send_availability_response(message_id, False) + return + + # 이벤트 발생 (GUI 클라이언트에서 처리) + if hasattr(self, 'change_availability_callback') and callable(self.change_availability_callback): + is_operative = (operational_status == "Operative") + success = await self.change_availability_callback(evse_id, is_operative) + + # 응답 전송 + await self.send_availability_response(message_id, success) + else: + print("change_availability_callback이 설정되지 않음") + await self.send_availability_response(message_id, False) + + except Exception as e: + print(f"ChangeAvailability 처리 중 오류: {e}") + # 오류가 발생해도 항상 일반 응답으로 처리 + await self.send_availability_response(message_id, False) + + async def handle_request_stop_transaction(self, message_id, payload): + """RequestStopTransaction 요청 처리""" + try: + print(f"RequestStopTransaction 요청 수신: {payload}") + + # 요청 파라미터 확인 + evse_id = payload.get("evseId") + + if not evse_id: + print("필수 파라미터 누락") + await self.send_stop_transaction_response(message_id, False) + return + + # 문자열이면 정수로 변환 + try: + evse_id = int(evse_id) + except ValueError: + print(f"유효하지 않은 충전기 ID: {evse_id}") + await self.send_stop_transaction_response(message_id, False) + return + + # 콜백 호출 + if hasattr(self, 'stop_transaction_callback') and callable(self.stop_transaction_callback): + success = await self.stop_transaction_callback(evse_id) + await self.send_stop_transaction_response(message_id, success) + else: + print("stop_transaction_callback이 설정되지 않음") + await self.send_stop_transaction_response(message_id, False) + + except Exception as e: + print(f"RequestStopTransaction 처리 중 오류: {e}") + await self.send_stop_transaction_response(message_id, False) + + async def send_stop_transaction_response(self, message_id, success): + """RequestStopTransaction 응답 전송""" + status = "Accepted" if success else "Rejected" + response = json.dumps([3, message_id, {"status": status}]) + + print(f"RequestStopTransaction 응답 전송: {response}") + await self.websocket.send(response) + + def set_stop_transaction_callback(self, callback): + """RequestStopTransaction 콜백 설정""" + self.stop_transaction_callback = callback + + async def send_availability_response(self, message_id, success): + """ChangeAvailability 응답 전송""" + status = "Accepted" if success else "Rejected" + response = json.dumps([3, message_id, {"status": status}]) + + print(f"ChangeAvailability 응답 전송: {response}") + await self.websocket.send(response) + + def set_change_availability_callback(self, callback): + """ChangeAvailability 콜백 설정""" + self.change_availability_callback = callback diff --git a/tempCodeRunnerFile.py b/tempCodeRunnerFile.py new file mode 100644 index 0000000..a604cb7 --- /dev/null +++ b/tempCodeRunnerFile.py @@ -0,0 +1 @@ +OcppGuiApp \ No newline at end of file diff --git a/visual_dashboard.py b/visual_dashboard.py index af0b70a..1ac4e5a 100644 --- a/visual_dashboard.py +++ b/visual_dashboard.py @@ -220,6 +220,17 @@ def create_widgets(self): power_value = ttk.Label(power_frame, textvariable=self.power_var) power_value.pack(side=tk.LEFT) + # Total price info + price_frame = ttk.Frame(info_frame) + price_frame.pack(fill=tk.X, pady=2) + + price_label = ttk.Label(price_frame, text="총 금액:", width=10) + price_label.pack(side=tk.LEFT) + + self.total_price_var = tk.StringVar(value="-") + price_value = ttk.Label(price_frame, textvariable=self.total_price_var, font=("Arial", 10, "bold")) + price_value.pack(side=tk.LEFT) + # Last updated info update_frame = ttk.Frame(info_frame) update_frame.pack(fill=tk.X, pady=2) @@ -251,3 +262,17 @@ def update_power(self, power): self.power_var.set(f"{power} W") self.power_meter.update_power(power) self.update_var.set(time.strftime('%H:%M:%S')) + + def update_total_price(self, total_price): + """총 금액 정보 업데이트""" + if total_price is not None: + self.total_price_var.set(f"{total_price}원") + + # 상태가 Available이 아니면 사용 가능으로 변경 (충전 완료 시) + if self.status_var.get() != "사용 가능": + self.update_status("Available") + + # 현재 시간 업데이트 + self.update_var.set(time.strftime('%H:%M:%S')) + else: + self.total_price_var.set("-")