#{NpCp`s}qF=kF*3Eem<#SObbf`1Y5G5N$~(Cq`($GKV$1O0Wi zx>?K)yWta6p>D$>B#4l4K*P_@U}V6ZIVD=A>AH zqlKX6fL9*|%dH)5kISAU1`n`hg3>g@##E>BejaQ+g zH%kc`bE4D+5PE(Wp`A;ZYGT@$Ir{2{ub%H5_XaCA^YFKHb6Ay?W_e)B3z~{}Q_)yc zz_c=~M%i{L5R9=?*0SNc@2rcb%{kD&IRCSQA0HfBHkG?7n7fA0T{D$iIlS?^tlawr z%P(%euzBprR6)fV=7BjoXfEZ=rQ?eN=Bn^w1hHYx#CKuhb;yu&o(kH^c=$`j>~LPR zishR?5{EaR8Sv+p_)FINjT`RiUVr{951DgE2Sx^fXr|@-iz)klmNl5Qg3nq3yfSSs zAqJzOu|M?}t@E$j?Qd%K@BWG3@<{aW%)ZW^Y~uhRAF(4BG`_pBvxeO b|i 8f@9m`i`1RNg zKFo~cu=$6tPle8Y`skO(C3F_Z)=n1A;{d8~{_X4*)Gn^u(Z&h}08iE@9>g7R&USM? zoTr&N^;KwaJapq&Xky~gsm~r>zX-A9(Pv-Sifs@S9*_RM($=djveob2X=|*jwE4>L z7%^squK(iEiLYjkzK8Ms?C)nzk3XEaUTKRpWm_(fn (etNia*7CT&7nGc^~q+OUf_t)^`p^?9P__x1?N40? v zj9o2-l^Ph#)#0KZ7Y(=&!wB|fDU3)*k1A;Q<|t7lL5OpKil- 9rFJ!Wdo>O9 z#F#xKV)g+f<|trA@mC#sYa8S+NI-Rx+oa%BqU3rX0V!HlG(}6n$tb}Ist>-Q^uja= zPfbzGmd`wJQouw^ya3(f@&-dYDAcEdH5S1d)qU#3r=P>fLkt-c%MzZa)XMBbB^2sO z0;G+eF#xgcfY{2a)bR+}r)p1?*R0(8qOnUnYb0SzAG*qlcLme!8XrE&hlWRH-ak5X z?)_*w0{}G2k3%O%9v^*Aa`p!Jo~3hjd3>D9;q |0^J30WryD%YEAciXeHEul=GKYN~k2A4to=C3M z#mXO`Bzh}?5k?=#tU{*O6HjFY22Un(-QIKsilUvzV5sLGp@8Ja;yk}5`$0}#FsGEy zDSd(%rfP6oSf$ZdeV1;#Z!5T{y`UW{pKt|ib;FG!x3%*o``FrXFTbKHSXj#!*52GW zRk$@^+9q %m&sj56%N4VjgLbU(h#plnG#Y~7wUlqZs>WMOc=7xab^=U&v(6E9xtQgxCG*t42O3W(tRZ>Fa7uDLD zG}UApQ%lm5mc=#e>B;pp)aRrxqx5S)bY<~tA#8 A{=4y{7MwH1FOFbmGC4PGG5{Z;5#=0t= zc) {zAGdPWMtfV!9yitBYi3f4m*L+J_xK^xnCdE1yTddo=i#;!g3?NYoRh zvnF=3lOw cA)<3(e-~#5*TXMO z@>_h^6El*Mlj1jkPnj+!7x{9*?Zz5->bYMm@WOjjVmuDMdz{8ve-8yXoAf0YLUG2T zplKOzTJ{7{OdT;;7gmw_Iszy4wIkY(bYU8Ihf@%IxJb^qo1BB?8?iiSSi&2Y1P#l1 z!}5Tk5CSuk;!k-cpjkSt(FHYDUSkbv@_0?&JxxB2(Kw+ )=wOoX!U2-1P!&k zp%w>Lki2-764BZyX;t6MyP59KtPdI*cteAzwUL -^#}mO90`t_+xmNv(x2p2wI1u z6DTZXf*pd+;W*@Tc1RKqC+MZTa2~GVlR1Zp71x9dyvtuA4*zr{&V{qT94_#i62GM% zM^9BWo%bXqi!Oh%DxJ=JQdmG&6Hm4hR=V;@rIB9wba^^mAlbkp@v=IdZCwrr_Xf7M z2MW7N`9NmZiirsk(xp^34h9@P#|bL8N1UD8i(6{xe-lW{{}ZefUFfW4o%F!#IR^*; ze~@Pr6!0Pl;(Mh39wmQ|3{d_v%K08K|Dpaf6;bd Yec925X-fOEt?zC9>Gm*)E#gf71w2w@1ONa4 diff --git a/config/__init__.py b/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/config/__pycache__/__init__.cpython-39.pyc b/config/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62c663cb127bad384f91d06674123b23662b6d8c GIT binary patch literal 138 zcmYe~<>g`k0=758nIQTxh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2DX#VV$tGC3o$ zD7T;}KPxr4B*rtZIJKz6C9xziCOJPZEi*kPK0Y%qvm`!Vub}c4hfQvNN@-529mt^1 HK+FIDWu6~I literal 0 HcmV?d00001 diff --git a/config/__pycache__/settings.cpython-39.pyc b/config/__pycache__/settings.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..618bb99bfd33d578793db69eec04951e6aba5d70 GIT binary patch literal 736 zcmYjOOK;Oa5VjrHabBelDse$VoXDYRY$r`qAyhv?8%XWoO#!VUS+>VcgOWJ1T~LEK zaNx+9OF8rg7r0hJi2va$P?R6Q1vs#2tEw~F+4*L7XXl%-3xzC2 e za0G0T73stPg(;wc8PJ%96lQ>hIp81-{1J;&kijfu@f_qJ4+WTqYp`%MhdIdOG%R8s zmT(4^aTc!Q959F~t{g0pq|-NVe|`P* (8ejj(@&?HziR@pRDZ1@pyA>O%Q9P zGErf(S}vETIdX`z0&&ko!0CYp2ay-zEys7kma48_@f^D@LZ!MP)g{4kyo&GFMBfMB z-f*gJ-K{t^aa|A`kR-qA*pBCw*XvMZak?D_z0e+F2B|nR2zvdIZV$bLAKOv%A_!q} zQ`_u5ut#1HtSW-Iswo$!B$kHYOmd2fY9-M^nt~?zm*`RJ7V^U9UifN~xnzPl1&NZT zBur%ElpspQS)al_xt4H*%53Msj%~+|$lo(|BT_|}BHa5Yw@K4(5N|pg-IPp?D&~{4 zWkKLtR>A~P!YeXrSbJtG$+nE`rfz9+M^5HtRc#<-X^PdBJ3GnJRgBOR!_@F1DcC{{ z^KrwpR71bt+)nt8+O~EK)H(OshS^C9yYf>@-focio{5rqb*G^|w3>Q{yp&sbVb{=` z9mBkge5Aq^Qs literal 0 HcmV?d00001 diff --git a/config/settings.py b/config/settings.py new file mode 100644 index 0000000..9d8c5db --- /dev/null +++ b/config/settings.py @@ -0,0 +1,32 @@ +"""配置信息模块""" +import os + +# API配置 +BASE_URL = "http://127.0.0.1:5000"#https://www.shnthy.com:9154 +LOGIN_DATA = { + "Program": 11, + "SC": "1000000001", + "loginName": "leduser", + "password": "bfcda35cf4eba92d4583931bbe4ff72ffdfa8b5c9c4b72611bd33f5babee069d" +} + +# 数据库配置 +ACCESS_DB_PATH = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" +ACCESS_DB_PASSWORD = "BCS7.2_SDBS" + +SQL_SERVER_CONFIG = { + "driver": "{SQL Server}", + "server": "127.0.0.1", + "database": "BS23DB", + "username": "sa", + "password": "123" +} + +# TCP配置 +TCP_HOST = '127.0.0.1' +TCP_PORT = 8888 + +# 其他配置 +MAX_AGE_HOURS = 24 +CHECK_INTERVAL = 10 +MONITOR_INTERVAL = 2 diff --git a/database/__init__.py b/database/__init__.py new file mode 100644 index 0000000..255bfcf --- /dev/null +++ b/database/__init__.py @@ -0,0 +1,5 @@ +"""数据库包""" +from .access_db import AccessDB +from .sql_server import SQLServerDB + +__all__ = ['AccessDB', 'SQLServerDB'] diff --git a/database/__pycache__/__init__.cpython-39.pyc b/database/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81602cf8c3214c882598bb636404c0644eabcad2 GIT binary patch literal 289 zcmYe~<>g`kg3s@SGn;|*V-N=!FabFZKwPW=BvKfn7*ZHhm~t3%nWC5&L2Tw6=3JI2 z79g7?g*BZiiZz8Tm_d`hln1E%+0+fsde=SOHTh{z>q|zUfF|QD4#(u=)Z$_nCm@?U zIM63JwWut$$i=A$WKj__knq!FyTu+KpOT*(AAgH85v)8uB?+wH7FTg$PJA&~4_Gls zWnxZFeEdp=A`XxVAmW#yi&acPWpYMhQEov|epYI7NsMP6P*;gdVo7353Xn)jEKZGy lkI&4@EQycTE2zB1VUwGmQks)$2XbdI8<1dO jO#>gp%E=AT8T@xiXwy%5=~S3;S?efQxZgx6|`FKY#OJw*O}R+ zjaf@U4VQ|RLj{$f1shRO4h1A6KorE4zhSS$ZgSzmEeFbbyNR0w#+o-@Z)fKHe)E2I z2M2Qm%HMxIQTanB ubN=?%nHj@7&seWm5Fe?ko%jr=ZFg!1$y@;T(qNtdf$F zol;V{#&sBL+~6j(Iv?OUXbrv(PR=K0c5LB{hd16X*vH+^LY2c{Vj2^N#0)H)0+w+C z-_xS4BnB@#4L4j!%!VuF =DDu`!5(m+jVg;mjKoO>O-A zg~G%p9k;c|uq1k8IpAe4F}A=Hcww6fjIw0nq$5L-VwV{c7DOJ*KB#g(7@{z$K2n+b zkN${hdD`6Hhh=NiU8o=>SW{F^LI*LCLosR74x#C&%{rt-W7<|Y-~w~Bt#$yl!=%Mx z#+8VO 6q} z+aow |mowBi!Qj!qc zcuYzLxw;rs>WNbI>tYCw-Xg}WR_$E&evMj1Iu$Nc_fo!5bv=I}sB&M(L|ck{v78vf zmr*s8r9q%s`1Q~UU3p0+iU=+zD)O1A^KjR_tR6@|Pn{t_+%S^Q!WB~CB`LKkkeZ_h zX&!ziQ>h8Rr)Z8fkMxQD&lbD#1jFvj;Sm@huVOf5H_a4O69+T}uxF`WbU*lE x bL0ja7)KR^{oC2g#V3La>Y`cf4k{*QYtw&0~NyhUy4%$@^INX1DzH@iE#J0HK9 z-Qv1+aRT3yzXnV9V}$&Po!(D_&OT^z2M|sQgj3EuTA=XPJXY2U8YPDa*ST?#aATeo zbk6c5W!ARCg8U~(l6hC0b4BO7yPeCwwEwu;xqA8G{TrQIt@gsT#~?y-DH?7BK|7zB zIFXsK4;;-M%pP)Zs`q2i*#}MT2I3M>fD{-ibCDD@u5lgypaeJJZ}1qm;BWFi9*2L7 z_k&7_upf?z)JgAmDD1QRA&& TLw6Ie`hDJ_gUex>3%LCLQO6c0@p zI9)n(n})h{z0 YOuO6y>V$XJExtwjx~-q>DjuiUT=Sl l>w1p<)8V!t&*S5iSj~@Kc`Re8xp{&1_p2$MT_I&nyvN;-s zaZhMQrq$!4>G8?&{p0z}p3qvhy>5&i&!%CZ22zz`*@b~)Cvl)!l=8eU_!1pW>B4~X zL$f;P^HWY3>$+c{b5cy8qY4|J$HbO_C{@m=7(@i!A~pi)hbFfIAsVCBQ=M7=>YDYB zu3LYbPgyKM>w~?1?(XTJYnMM07;MVT0Wj!5InW@Bv_+`uEwUDA0w@=?23^!!q(z$= z_Bi9(MFL|+i=@dsIJv2Fy`e#PjD`->TriqOgDsj3BZx(EAjP`7T55kb(+44msgQKO zzS6#Qvzt?2+&w0IUUS?>ty^`rGx-8IG*C7VO(FXXX!@zug!K8A&FYBkCHj%_R*Hpe z h)Jiq1y(qqaHR!d1TD xC0wMl?n4)rPz~&)% zQK4&4L=PZL15D|G-eB`|C_ HH4t8I@X<96B}G0Nq3rkR}O8mH}E%zAUUOBC+Cbeib%He2Xm#<*M@H zb!S6{0Fqe^0o1 -aRu zt4lh)e?%?Kr7XOx@z%2KFmBsrsCpjq3EQ5n6}@Oi;KNE4G4U313f6c+ RILS0f= zqw!RUt1N2iR>E3u4GJ7j8DY$}x$oGvz{g3rK6-YHK=d&eqSX z*UqNatqTwsH~(nK{_G><7hJ3!A}n?S*slR%BuN-$f 0Yzn_Nko`QdB^?38TX7`{p@1=#mH zquYlHW9h>wD_5}0BcOh$J8$cj6HPg(AqMDB%GQVM5kmtm#6SZ*OIEZN#<;3!*?iW~ zG>AK~@g_n`z%}>#|^j?RX#v;M(2;1fykggfL+ !@yn7{kor~k@b$rtVGhD`0?3bV4{S4nO6at9pG(^8;4 zx~qTJ?p=x44z4bTq9nHubVq?v1gU%~rvu}?L1YwCwtdvJ*nQd_7A*;G=1O7AWQWq+ zw-hu;hK&4;kAkS#j+M=4+-!IVBWY~_gt@ez0z|}Ssy>ti^?@X+e@l}3m-0~Xm7ZHG z%uAXZqKt|V@EzE{0xFXkGD|A7OlK&}Lg~j+nbC?^79e)wETse}5q6{usmNt1N)Gm% zBq!XwRFp|F4DSYtRdw8A9T%cxoK}1elq^#xNZE&L;HYJJMky Sk~GGC!hw_6(`aA(9&2u{e5-%T E6C*tS_|tfGgFoV_{=zs6%}1_%2!i>?Z(apb`%@Rp<$*h0WwM zVMI!JeaU?ZVSx*+ZJcJWQZ8EN(MQjN2Re+b?WE0Ip|chA{0=}$?Q6Y 7 _S*5BV36ej6Gldm>M%)CHK-C8US@EfV3PLk&rW>HOHjAZK{$upxVFf=w`~ftL z2Q)2bvZ8@>lctRnQ--%=sc0v5a|_K`mH(9@u&}^zWg`LuMK$R1!ZP=18Z* 0: - first_artifact = artifact_list[0] # 获取第一个元素 - beton_task_id = first_artifact["BetonTaskID"] - beton_volume = first_artifact["BetonVolume"] - artifact_id = first_artifact["ArtifactActionID"] # 获取ArtifactID - print(f"获取到BetonTaskID: {beton_task_id}") - print(f"获取到BetonVolume: {beton_volume}") - print(f"获取到ArtifactActionID: {artifact_id}") - return beton_task_id, beton_volume, artifact_id - else: - raise Exception("未找到未浇筑信息") - raise Exception("获取未浇筑信息失败") - - -# 连接Access数据库 -def connect_to_access_db(db_path, password): - conn_str = ( - r'DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};' - f'DBQ={db_path};' - f'PWD={password};' - ) - return pyodbc.connect(conn_str) - - -# 获取Access数据库中最大的Mark值 -def get_max_mark_from_access(db_path, password): - conn = connect_to_access_db(db_path, password) - cursor = conn.cursor() - - # 查询最大的Mark值 - cursor.execute("SELECT MAX(Mark) FROM Produce") - max_mark = cursor.fetchone()[0] - - # 如果没有记录,返回0 - if max_mark is None: - max_mark = 0 - - conn.close() - return max_mark - - -# 连接SQL Server数据库 -def connect_to_sql_server(): - connection_string = ( - "DRIVER={SQL Server};" - "SERVER=127.0.0.1;" - "DATABASE=BS23DB;" - "UID=sa;" - "PWD=123;" - ) - return pyodbc.connect(connection_string) - - -# 插入数据到Produce表 -def insert_into_produce_table(connection, task_info, beton_volume, erp_id): - cursor = connection.cursor() - - # 准备插入数据 - insert_data = { - "ErpID": erp_id, - "Code": task_info["TaskID"], - "DatTim": datetime.now(), - "Recipe": task_info["ProduceMixID"], - "MorRec": "", - "ProdMete": beton_volume, - "MorMete": 0.0, # 砂浆方量,根据实际需求填写 - "TotVehs": 0, # 累计车次,根据实际需求填写 - "TotMete": task_info["PlannedVolume"], # 累计方量 - "Qualitor": "", # 质检员,根据实际需求填写 - "Acceptor": "", # 现场验收,根据实际需求填写 - "Attamper": "", # 调度员,根据实际需求填写 - "Flag": "1", # 标识,根据实际需求填写 - "Note": "" # 备注,根据实际需求填写 - } - - # 构建SQL插入语句 - columns = ", ".join(insert_data.keys()) - placeholders = ", ".join(["?" for _ in insert_data.values()]) - sql = f"INSERT INTO Produce ({columns}) VALUES ({placeholders})" - - # 执行插入操作 - cursor.execute(sql, list(insert_data.values())) - connection.commit() - print(f"数据已成功插入到Produce表中") - - -# 主函数 -def main(): - try: - # 步骤1:获取AppID - app_id = get_app_id() - - # 上次获取的ArtifactID,用于检测变化 - last_artifact_id = None - - # Access数据库路径和密码 - access_db_path = "D:\\Janeoo-B12-DB\\Janeoo.2.mdb" # 替换为实际路径 - access_password = "BCS7.2_SDBS" # Access数据库密码 - - while True: - try: - # 步骤2:获取未浇筑信息中的BetonTaskID、BetonVolume和ArtifactID - beton_task_id, beton_volume, artifact_id = get_not_pour_info(app_id) - # beton_task_id = "20251016-01" - - # 检查ArtifactID是否发生变化 - if artifact_id != last_artifact_id: - print(f"检测到新任务: {artifact_id}") - - # 步骤3:使用BetonTaskID获取任务单信息 - task_info = get_task_info(app_id, beton_task_id) - - # 步骤4:连接Access数据库并获取最大Mark值 - max_mark = get_max_mark_from_access(access_db_path, access_password) - erp_id = int(max_mark) + 1 # 在最大Mark值基础上加1 - print(f"获取到ERP ID: {erp_id}") - - # 步骤5:连接SQL Server数据库并插入数据 - connection = connect_to_sql_server() - insert_into_produce_table(connection, task_info, beton_volume, erp_id) - connection.close() - - # 更新上次获取的ArtifactID - last_artifact_id = artifact_id - - # 每2秒检查一次 - time.sleep(2) - - except Exception as e: - print(f"发生错误: {e}") - # 继续循环,避免程序退出 - time.sleep(2) - - except KeyboardInterrupt: - print("程序已停止") - - -if __name__ == "__main__": - main() diff --git a/main.py b/main.py new file mode 100644 index 0000000..f07040f --- /dev/null +++ b/main.py @@ -0,0 +1,132 @@ +"""主程序入口""" +import time +import threading +from datetime import datetime +from API.client import APIClient +from API.mix_weight_api import MixWeightAPI +from services.task_service import TaskService +from services.monitoring_service import MonitoringService +from database.access_db import AccessDB +from database.sql_server import SQLServerDB +from tcp.server import TCPServer +from config.settings import ( + ACCESS_DB_PATH, ACCESS_DB_PASSWORD, + TCP_HOST, TCP_PORT, CHECK_INTERVAL, MAX_AGE_HOURS +) +from utils.helpers import cleanup_old_timestamps + +def start_api_service(): + """启动配比重量API服务""" + api = MixWeightAPI() + api.run(host='127.0.0.1', port=5001, debug=False, threaded=True) + +def main(): + api_thread = threading.Thread(target=start_api_service) + api_thread.daemon = True + api_thread.start() + try: + # 初始化TCP服务端 + tcp_server = TCPServer(host=TCP_HOST, port=TCP_PORT) + tcp_server_thread = threading.Thread(target=tcp_server.start) + tcp_server_thread.daemon = True + tcp_server_thread.start() + + # 等待服务端启动 + time.sleep(1) + + # 初始化服务 + api_client = APIClient() + task_service = TaskService() + monitoring_service = MonitoringService(tcp_server) + + # 步骤1:获取AppID + app_id = api_client.login() + task_service.api_client.app_id = app_id + + # 存储上次获取的所有ArtifactID + last_artifact_ids = set() + last_artifact_list = [] # 用于存储上一次的完整artifact_list + + # 启动Access数据库Flag监控线程 + access_monitor_thread = threading.Thread(target=monitoring_service.monitor_access_flag_changes) + access_monitor_thread.daemon = True + access_monitor_thread.start() + + while True: + try: + # 步骤2:获取所有未浇筑信息 + tasks, artifact_list, send_list, half_volume = task_service.process_not_pour_info() + current_artifact_ids = {task["artifact_id"] for task in tasks} + + # 检查artifact_list是否发生变化 + if artifact_list != last_artifact_list: + print(f"检测到artifact_list更新: {artifact_list}") + + # 处理新出现的任务 + new_artifact_ids = current_artifact_ids - last_artifact_ids + if new_artifact_ids: + print(f"检测到 {len(new_artifact_ids)} 个新任务") + + for task in tasks: + if task["artifact_id"] in new_artifact_ids: + task_info = api_client.get_task_info(task["beton_task_id"]) + + # 步骤4:连接Access数据库并获取最大Mark值 + access_db = AccessDB(ACCESS_DB_PATH, ACCESS_DB_PASSWORD) + try: + max_mark = access_db.get_max_mark() + finally: + access_db.close() + + erp_id = int(max_mark) + 1 + + # 步骤5:连接SQL Server数据库并插入数据 + sql_db = SQLServerDB() + try: + # 准备插入数据 + insert_data = { + "ErpID": erp_id, + "Code": task_info["TaskID"], + "DatTim": datetime.now(), + "Recipe": task_info["ProduceMixID"], + "MorRec": "", + "ProdMete": task["beton_volume"], + "MorMete": 0.0, + "TotVehs": 0, + "TotMete": task_info["PlannedVolume"], + "Qualitor": "", + "Acceptor": "", + "Attamper": "", + "Flag": "1", + "Note": "" + } + + sql_db.insert_produce_data(insert_data) + print(f"数据已成功插入到Produce表中,ERP ID: {erp_id}") + finally: + sql_db.close() + + # 更新上次获取的ArtifactID集合和artifact_list + last_artifact_ids = current_artifact_ids + last_artifact_list = artifact_list.copy() + + # 每10分钟清理一次过期的时间戳记录 + cleanup_old_timestamps(task_service.artifact_timestamps, current_artifact_ids, MAX_AGE_HOURS) + + # 每10秒检查一次 + time.sleep(CHECK_INTERVAL) + + except Exception as e: + print(f"发生错误: {e}") + # 继续循环,避免程序退出 + time.sleep(2) + + except KeyboardInterrupt: + print("程序已停止") + # 停止TCP服务端 + if 'tcp_server' in locals(): + tcp_server.stop() + + +if __name__ == "__main__": + main() diff --git a/models/__init__.py b/models/__init__.py new file mode 100644 index 0000000..36fc1f9 --- /dev/null +++ b/models/__init__.py @@ -0,0 +1,4 @@ +"""模型包""" +from .task import Task, SendTask + +__all__ = ['Task', 'SendTask'] diff --git a/models/task.py b/models/task.py new file mode 100644 index 0000000..bb33d89 --- /dev/null +++ b/models/task.py @@ -0,0 +1,20 @@ +"""任务相关数据模型""" +from datetime import datetime + +class Task: + def __init__(self, beton_task_id, beton_volume, artifact_id, block_number): + self.beton_task_id = beton_task_id + self.beton_volume = beton_volume + self.artifact_id = artifact_id + self.block_number = block_number + +class SendTask: + def __init__(self, beton_task_id, beton_volume, artifact_id, block_number, + beton_grade, mix_id, timestamp=None): + self.beton_task_id = beton_task_id + self.beton_volume = beton_volume + self.artifact_id = artifact_id + self.block_number = block_number + self.beton_grade = beton_grade + self.mix_id = mix_id + self.timestamp = timestamp or datetime.now() diff --git a/services/__init__.py b/services/__init__.py new file mode 100644 index 0000000..dc69dbb --- /dev/null +++ b/services/__init__.py @@ -0,0 +1,5 @@ +"""服务包""" +from .task_service import TaskService +from .monitoring_service import MonitoringService + +__all__ = ['TaskService', 'MonitoringService'] diff --git a/services/__pycache__/__init__.cpython-39.pyc b/services/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..603d984dc6465ecfac7adaf9db5e5427b6cf0b43 GIT binary patch literal 306 zcmYe~<>g`kg3s@SGv@;7#~= 9(3Trx36l)4wFoPz0DJM|*vpKy_yB0p}X?@8E }zQ`1o5qB|v@g#So2PHMfLv;d -Rxt&Y$r*`7xdlb}S*gh-F`juq^GaM2OA=$C1{cS~$7cc^ g6d$iwP XDp5x_<4%Ii?w&S|P z524;O^7xJsM?CEaG&R3(^Oh}JM@FpShpfjo@7m_C=xmRS?0$6Tu%CS7(aiQ;kM6X# zXLfDf`J>G{z$Uh9%VPl>n`Z3%sc1Zi Xf!1xpyI}v6^Bjc?CK1)JZBe+0wnplrc^1C|AImWzwb}_w0)0N@1a%a}Qek z3c3BRuepxrFDnL9JKUl!*YC@hFxG3gW8MMb pRN!!GMKp6;MyBzV14OeS-Ar zydqYjxbeX7(4NY;eIO@_6;Xc5vAsRpCClNQm)k?@!2aAl;k@80*9O`^W!yI{D-Tgv z7HNbl)s-3en@AID7Kv$~HQZ(x-}=#Kl%%|}=<%SflZ+`7H#|0_dfGJVHRUPGouA z?mfE|uIh@eOhU7FE2AcQr6lXDv!|52TX7#7RG9off!vEuDs^>YO--FLy;u#iOtZSS zTR}TMjs8-+RU1?SrKz!DWs=o(ucxL@vYNJ9sYkHBNKHGVoKtC)Xc@Igt5u7*f1nk4 z39r}dn^fxtW;3RiVYY~zEsEKU_H1Eo5c``-)*`j&v>NP4SG?sX+4xST)J;g@KFkuW znXOr1lWJi_JywfNt)zADR-S-F>gF@%sM%Q$XoJciRwQjVR=pdN4s18D&*rK3n#V6T zuDm?++Y8P2f8RLq(#+MXu<6;KA9)yhH~akM=HX|n-^EvrYlj=}zVL;=&2$|$8HSED zg5>ri+mEe3nW!@lW-`fMQb+ZXKr> 50JBnL-;RK2X09G@ zTzIW<_7{*#AfTa?9M$;XH#1jXoFCgbIyLwD+nuAn30_M|Eky!uzIqulpMB+xxmRAl ze(BOsN|0@&`~64-0OR>O!Koi{3yxC}QFMvrl=UL>b-P>{7bH%<-#*~j2Q6m|TOcD1 z&_Smi`4PKNh9Q%U3UV4ELYYCIEg!8qVqA{4TrcNUU4N|w93bTGq_%|R$F`2yPQ}ZY zOMc7~IosKr1IWbWS~0twj*AswoK4CFSYFu*MeiH#Xu;xpv#Yw-2mrCr |z NBs pe0wCYnIUhiqo!>ns4{B01S`PrsP09{a*+d6 zrva9LNV8^&k1;M*GYPzT6wWPCU5$-4-aayW@~0uhNNj1Gc&%~lw69c2rJHXZZoctO z(4DF#K}l^$H9mZ~@w4M(EJLYvlDKYtYUXz@%oA_0b$;}RrGusNp;G2kI@nGqOKlaE z?Zc@XeW|-P3opMfXM5X+VZL9%xO6H6y2jyaFy-c%_nW8R8%j;+sSTS_>A0_v4Ql%x zPxN54xRo+#fPJX>Yb;<0FE|091O^nEiZnN0Kj@6R{;JlnV%~Mz)|rk;QxR$6Ng(0J z0~;U{5F{)=(Nb~>0kXXn;XIu$S6w-s-;)bB16=fbyI3!PNpT05J&fe0kSQ9eZvu+F zR@T--wb%SZSL0ez?`Jxj7+9>>pM?oF0Z{8lbxP8iPoM&=fIFXNVm0)EAr#Wc#g%?6 z=_=@hpsQ{A!;%h{FSdcMwdn(ru7my)(DgR`7D P7~{wIHQ~DVi)!h__wj=O*AOnsxjESdJfowU?TyF ztnF4x_aG2q;~9h@u=R;G=+Wmx9~o*y>e@3}Db8g{p#}mT#tj}ls{+ReyR;h4je?Yr z+u06o=I3$a5u9W!aJ3RUf-_vl*8v%tXMcJ9qchj1kHLS=TzOYea8o7o99q~lM_%<) zviQKn11{uzpSuFjJCw>)mr-Xo!}Drjhen_VpHhqgZ#{ST+3 ZgUO%q?cxoWg{|1T=UA*m1--l7;yY6GISE`{jsno}V{u?<;x^4;BH zJ9YnnvK^FVC|h8qgmIHdU-mc--TXLaz?2Y+E?)(4mFn>eXf8`uN8k++v@{jcc&*c=a}HHHZ#E z3op@u21nVrc&vHpRB)Q)c!#>^nd( *|W_HZw68KoQ7U`(!s-p zRF05i`;^Z|JAAtguA@Bf+Bv~R+jzwz#Aqo^7)HmdNG@%H4AW%aKnVG7nrG?%`mmHf zROa=8?y9Fl>+aNtfIhDeL3^P-=s2T=`Vew#>w|cl1}$~gThVa|=|6MUm7AaSf3I&I zlTaKyEFh+S@tx)?m%E_2yK7F~M?0XnyZc{(VhV2mNQd$zJ>yu{OCGH&h9ra8qo~Mh z+B0<(*EGES)HMmk_qU-qxUk9V7edk2yOj!f#HEeG-bJrdyE g9xUgVqv>``65;~3RdSWXC+*RC|){&oAsK@6fNBgHN5LAClVWa-rPi|;i)JQciF zEPnY3UM-qOPX`E!tI56iYW}7pzD-TSMX?i^uT{#G`5RF>3}qgm{`)DD;q6k9Ej=Xt z3CX3q9WLJTDvgUaTTh|Ox|@eCUH6+zx|iM_OSz(BS$^EYBLlDE8fN(k%Nnib3PFz` zA&Cu?-9Z_J)q;X3K_@B*wFQ~8AoUTnv?9ojpA=2~q*N{mEz?D~_7?nrqEovmgJ} z`1i{Z>1BS@vUu6HEU}h8qj*wKl;N+ScyDjcbq3n+7xE#-U)k=UHx7Dibwu! ORx&)I+@n&|;-R-pVu|4-r zfz7Oev_K&=d>E*KlI)N|ED6{I&>|rw{`8OhzCVnK-6>5>{9*i|BK3LSGk11oI%|k` za?kfY_uTV7@AJOrox;$Nr{Vh9-!_+?{hFrzg(}^biOOEw;XD$d`()o17%X?f;l{1xWKC5eYYr+-j6PidLH}XTm zo6~Zc`WRkx@q-W6o^Gz4J#p!|Ct7Dtp?n#wT27B$QHX-5R0&W{Pv3W7f4LM?BkGtg z7K1RH*@tpw?nmFB3*@mtqH4s$)BE>-cW%y~+2`Lkeg8f2Sa*GH?k7L|@eCf?vKU1E zf $HUSX-^ z7kM}1%%MVg!9P|j*DFDsiSSZ?K3J&9Al_V%QE8!2jC_(o7!@i@A@ TO^#ru zf89QF=fR~%iiZlavLtJVgJN{>Ks5|xG*gHQ2T`EqhX;Auc5Q0uk=XV9QneKMeg>0- zE)q?5bx(Kn*iXo=S%GY(N^L=@H(5XHaNphqYC`sjcV@J>0&i(GP9Lf;ESH)okcZ zeZ^=%a+BJMiQGVLAvclR$Svd!Mp_MB*pnJYry42YOln9|oVuK*CpF=nv9PT+Mmr6w z;WSbWvti>6&WhV`8Pr>_qy)}yw%&X4(p%48{9Uv4*so%@4Y@ELO2AjF)vHlF9Mz&i z8Hh~eu&|CwmRvkEA4IjP&l_11aaL86;T=hF7o)mbugnMXoF%tnIr17xCMcOil1oWq zf_M|DLA4g)WpxROK oOe2Om3oMtyD4%?NsNP8|AU9JoP6_Q_ob7&1Ug1&(VZ9tN@KiENBex`L?fH;R z=n8is(G1V9^kLHj!1!klTMmGR-zTnXQU0lAFW=Y=yMZ$nN$HZyLBYn&7~F$`Vugl2 zqa6p
$d#ad-)4@`yjcih_YZQYyH0Yn1osoi){p&af(A$j(ywG;n@bkp}@ z<-@dcp-pNJXu5V3D%xH%q5T0SrCGJKn=!tBk?GxwK{a@IN$$CWdcS~V`PR?6#^lkQ zB?ka7XU1kZsK#bkuSjB>oWoF-H_)2~JkYl`xgF!af;*(KnlTLUjp?pw==}R+`MUqP z&K|JQo~3Xz*hm_R@UU+nG^RE#p$=k03R(jiKx@Ko674x>Z0u^PPWrDPw)WxA*Pc41 zEN`2eGW%%DX;BAeWDXTS~V){EyaKl$w13(s8q@YJOb-&WF5a=A>Z zewoZRTYx%IPV4E{KYr_t*_^Y^xfM`iX$j<;s9`+bq2q^Y>#bXp*05AvTpu29PTH$o zgY6|*szz)KU@K_*6+aU-%N>-k1~6T-LXb0{#7CSgiJ0!i9TMa;%LV_s`Y3Ksx2{;I zXHj0hxkm*yvLQu_=4f9eLo!jU3co-B(t!0RMVKI)u2g_>Rsyo@#ITFRxC8po1}o1t zUX{qsYlopcYKF*MwVGPf5a}~1%t1Z^5YaG|tJO4hjD{cJG$Czx0gykfhNPYI>SSr# z>UQ?!ix=KxUVr&S>-ghqPrS!6ReIDh%W@l@kfaH*$J%(eEQlbse^7e(z|6VSAg#-1 zlq0Z6BlAwB^so;Xz+$I4#qyIwG%4wxBtXSxwf0av;TM*cf~xQfLa^@(=YteAjIZ_U zOXPNUG_%|JYeQiNP1ccpJW>#c>tPg##Cx&TROyi3K&GHyv5CWqxY>OLH<}JuQ5ocR z2|)4m@qfCRG1D^!1LZ2<7s)Or7x_0GpnQr71PTBwk{a(){3%RWON;6P@DTQjQ{4&? z!f|ZFiCjZ+5gp=C0E6n}4m!eRNTvGQQD+wsV^k@_a59NZ=*h@hwHZ!XhLhX1rjPp8 z^iji(;9wrt#Sm!f4-HEU0jR^1S{18XG^&n*;7S?*Of_7%66rP^;f69CQ)qMPYZ#6r zU2wd3;p|{Ieii$~4x;=VO8+3n`MCLd>!tU*fZD;R{3eaQlag;yLdK2_2b?}~3l-)_ z1`2|NKKX4*zC;N*P4YWPa-JfXb#CcEOYWsXq(^d^l6^?xlyZ8*eo) FcOlV? z?K*rrGP`YX8SwTLxQql`SxYyrSXT_#72^ub@)hG#OW$_IGM)bz7Cc5{dB;G8>Y~*m z?NM^kw{|eM3(QUOT_k_(V8fK#K^w5o@X~-gNYPkvA{}zouLXS_CmKWBZlFt*h|suX zq0OLUNz#6ewvwvefw@6zn0vXa7j(zH6X-R#_i4N*Rdv-E9BY#HRpC?#*FYr>E{5O( z4szhP;nE=obeHaLM;(Y3S;jY&fJv;%gbC#*JNO=Ee0xle9v_bsRi+vqV>695^bWx0 z+Nl?>!X_h&4I%j@l2OVB8nOZk9_)}Xk#2;~oXdcWZHW_?=%U6BF5{awVnrVZBR{d5 z3bdJi(DoX{JdSz_r-Lxu4_)$J-@qMG0S6X+t3J*@a3H|y7_PB(V;E-`syhckHCeNY zbQDdRzI_o{cEI|3R0ymPr?Qe)+fSUL2lu0WkPRgdif4(8RkO>6;`EGjHcsCW=oIwk zf! JV4I(7%o$f5aWqu| Rig6?>KfA@@68k+U+J}aSPgE^tjz_kZhDc z1fP}<8xD>ZIJr^{ghsSvv2nB#(})(tz>sQ(VeV9K
RMegcVmWzxL|d*_ST8e4-s?Jb8ZY+2=1m z`q TVE zkqLuh4PFs>NU;|kD#> &FkF@2|K+au_vpLZ2`!eUz+T*AFg~ zH>h>_rXCz^;0^YGiNbCjFp+ipKfrYUDlj383Oi-WpEhinr*O!mcC-rHGz#D-o5x@v zs|J98I2d^FZ5VDA+bsn*hbRQ|+Z32%Z!5LxGUzf1=$_N%&OX?=1hz#`*rL8*9Mj~V z)EWSPr~O6+$rRcNh&I0wk!+M {`KY4@3v09b5-Pu-ZzIk zB=__X=6W!j#I9aYu{K>rSZTv@I8`8vtx^ v%E )J?0C9j%zi71(44T$hM?v3uSn{g-H>)c(avo4oRbCbHj1U_eHJf`|2?4 z;a{aG^+$;MXJm}xSM!B1m@4pJOum?xB=~r9rz1RC21U~!PLh16cm#yLP+FXVI3k2r xLg}DYQlKIpsz;@AICUr}F9kB>Fd{Ex(09b{Zna^1AORKfvh-~GH;RDCe*wKbqXYl| literal 0 HcmV?d00001 diff --git a/services/monitoring_service.py b/services/monitoring_service.py new file mode 100644 index 0000000..248838a --- /dev/null +++ b/services/monitoring_service.py @@ -0,0 +1,228 @@ + +"""监控服务""" +import time +import threading +from datetime import datetime +from database.access_db import AccessDB +from database.sql_server import SQLServerDB +from config.settings import ACCESS_DB_PATH, ACCESS_DB_PASSWORD, MONITOR_INTERVAL +from tcp.server import TCPServer + +class MonitoringService: + def __init__(self, tcp_server): + self.tcp_server = tcp_server + self.task_flags = {} + self.monitored_tasks = set() + self.inserted_tasks = {} + self.tasks_lock = threading.Lock() + + def monitor_access_flag_changes(self): + """监控Access数据库中派发任务的Flag状态""" + print("开始监控Access数据库中派发任务的Flag状态") + + while True: + try: + # 每2秒检查一次 + time.sleep(MONITOR_INTERVAL) + + with self.tasks_lock: + # 如果没有需要监控的任务,跳过 + if not self.monitored_tasks: + continue + + # 创建需要监控的任务列表副本 + tasks_to_monitor = self.monitored_tasks.copy() + + # 检查SQL Server中任务是否还存在 + sql_db = SQLServerDB() + try: + existing_tasks_in_sql = sql_db.check_existing_tasks(list(tasks_to_monitor)) + finally: + sql_db.close() + + # 分离已删除和未删除的任务 + erp_ids_str = [str(erp_id) for erp_id in tasks_to_monitor] + deleted_from_sql_tasks = set(erp_ids_str) - existing_tasks_in_sql + + print(f"SQL Server中仍存在的任务: {existing_tasks_in_sql}") + print(f"已从SQL Server删除的任务: {deleted_from_sql_tasks}") + + # 只有已从SQL Server删除的任务才需要在Access中查找 + if not deleted_from_sql_tasks: + continue + + # 查询Access数据库中已删除任务的状态 + access_db = AccessDB(ACCESS_DB_PATH, ACCESS_DB_PASSWORD) + try: + current_tasks = access_db.query_task_status(list(deleted_from_sql_tasks)) + finally: + access_db.close() + + # 处理任务状态变化 + self._process_task_status_changes(deleted_from_sql_tasks, current_tasks) + + except Exception as e: + print(f"监控Access数据库 Flag时发生错误: {e}") + import traceback + traceback.print_exc() + continue + + def _process_task_status_changes(self, deleted_from_sql_tasks, current_tasks): + """处理任务状态变化""" + # 检查每个已删除任务的状态变化 + for erp_id_str in deleted_from_sql_tasks: + erp_id = int(erp_id_str) + current_flag = current_tasks.get(erp_id_str, "") + previous_flag = self.task_flags.get(erp_id_str, "") + + # 添加调试信息 + print(f"检查任务 {erp_id} - 当前Flag: '{current_flag}', 之前Flag: '{previous_flag}'") + + # 如果状态发生变化 + if current_flag != previous_flag: + with self.tasks_lock: + artifact_id = self.inserted_tasks.get(erp_id, "Unknown") + print( + f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 的Flag值已更新: {previous_flag} -> {current_flag}") + self.task_flags[erp_id_str] = current_flag + + # 根据Flag值末尾的字母执行相应操作并更新自定义数据表状态 + self._handle_flag_status_change(erp_id, current_flag, artifact_id) + + # 检查是否有任务记录已被删除(不在查询结果中但仍在监控列表中) + # 这表示任务可能已完成或从系统中移除 + missing_tasks = set(deleted_from_sql_tasks) - set(current_tasks.keys()) + if missing_tasks: + self._handle_missing_tasks(missing_tasks) + + def _handle_flag_status_change(self, erp_id, current_flag, artifact_id): + """处理标志状态变化""" + if current_flag.endswith('d'): + self._handle_status_d(erp_id, artifact_id) + elif current_flag.endswith('w'): + self._handle_status_w(erp_id, artifact_id) + elif current_flag.endswith('n'): + self._handle_status_n(erp_id, artifact_id) + elif current_flag.endswith('p'): + self._handle_status_p(erp_id, artifact_id) + elif current_flag.endswith('x'): + self._handle_status_x(erp_id, artifact_id) + + def _handle_status_d(self, erp_id, artifact_id): + """处理状态'd' - 未进行生产""" + print(f"派发任务 ErpID {erp_id}: 未进行生产") + # 调用同事提供的状态更新函数 + try: + print(1) + # update_custom_table_status(erp_id, "未进行生产") + except Exception as e: + print(f"更新状态时出错: {e}") + + # 发送数据给TCP客户端(只发送erp_id和状态) + try: + status_data = { + "erp_id": erp_id, + "status": "未进行生产" + } + self.tcp_server.send_data(status_data) + except Exception as e: + print(f"发送状态数据给TCP客户端时出错: {e}") + + def _handle_status_w(self, erp_id, artifact_id): + """处理状态'w' - 正在生产中""" + print(f"派发任务 ErpID {erp_id}: 正在生产中") + # 调用同事提供的状态更新函数 + try: + print(2) + # update_custom_table_status(erp_id, "正在生产中") + except Exception as e: + print(f"更新状态时出错: {e}") + + # 发送数据给TCP客户端(只发送erp_id和状态) + try: + status_data = { + "erp_id": erp_id, + "status": "正在生产中" + } + self.tcp_server.send_data(status_data) + except Exception as e: + print(f"发送状态数据给TCP客户端时出错: {e}") + + def _handle_status_n(self, erp_id, artifact_id): + """处理状态'n' - 生产完毕""" + print(f"派发任务 ErpID {erp_id}: 生产完毕") + # 任务完成,可以从监控列表中移除 + with self.tasks_lock: + self.monitored_tasks.discard(erp_id) + print(f"派发任务 ErpID {erp_id} 已完成,停止监控") + # 调用同事提供的状态更新函数 + try: + print(3) + # update_custom_table_status(erp_id, "生产完毕") + except Exception as e: + print(f"更新状态时出错: {e}") + + # 发送数据给TCP客户端(只发送erp_id和状态) + try: + status_data = { + "erp_id": erp_id, + "status": "生产完毕" + } + self.tcp_server.send_data(status_data) + except Exception as e: + print(f"发送状态数据给TCP客户端时出错: {e}") + + def _handle_status_p(self, erp_id, artifact_id): + """处理状态'p' - 生产中断""" + print(f"派发任务 ErpID {erp_id}: 生产中断") + # 任务中断,可以从监控列表中移除 + with self.tasks_lock: + self.monitored_tasks.discard(erp_id) + print(f"派发任务 ErpID {erp_id} 已中断,停止监控") + # 调用同事提供的状态更新函数 + try: + print(4) + # update_custom_table_status(erp_id, "生产中断") + except Exception as e: + print(f"更新状态时出错: {e}") + + # 发送数据给TCP客户端(只发送erp_id和状态) + try: + status_data = { + "erp_id": erp_id, + "status": "生产中断" + } + self.tcp_server.send_data(status_data) + except Exception as e: + print(f"发送状态数据给TCP客户端时出错: {e}") + + def _handle_status_x(self, erp_id, artifact_id): + """处理状态'x' - 数据已接收""" + print(f"派发任务 ErpID {erp_id}: 数据已接收") + # 调用同事提供的状态更新函数 + try: + print(5) + # update_custom_table_status(erp_id, "数据已接收") + except Exception as e: + print(f"更新状态时出错: {e}") + + # 发送数据给TCP客户端(只发送erp_id和状态) + try: + status_data = { + "erp_id": erp_id, + "status": "数据已接收" + } + self.tcp_server.send_data(status_data) + except Exception as e: + print(f"发送状态数据给TCP客户端时出错: {e}") + + def _handle_missing_tasks(self, missing_tasks): + """处理缺失的任务""" + for erp_id_str in missing_tasks: + erp_id = int(erp_id_str) + with self.tasks_lock: + artifact_id = self.inserted_tasks.get(erp_id, "Unknown") + self.monitored_tasks.discard(erp_id) + self.inserted_tasks.pop(erp_id, None) + self.task_flags.pop(erp_id_str, None) + print(f"派发任务 ErpID {erp_id} (ArtifactID: {artifact_id}) 记录已从Access数据库中删除或完成") diff --git a/services/task_service.py b/services/task_service.py new file mode 100644 index 0000000..4e8770b --- /dev/null +++ b/services/task_service.py @@ -0,0 +1,303 @@ +"""任务处理服务""" +from datetime import datetime +from API.client import APIClient +from database.access_db import AccessDB +from database.sql_server import SQLServerDB +from config.settings import ACCESS_DB_PATH, ACCESS_DB_PASSWORD +from utils.helpers import get_f_block_positions + + +class TaskService: + def __init__(self): + self.api_client = APIClient() + self.half_volume = [0, 0] + self.task_before = None + self.artifact_timestamps = {} + + def process_not_pour_info(self): + """处理未浇筑信息""" + artifact_list = self.api_client.get_not_pour_info() + + if not artifact_list: + return [], [], [], self.half_volume + + # 处理F块信息 + f_blocks_info = self._process_f_blocks(artifact_list) + f_blocks = f_blocks_info["f_blocks"] + f_block_count = f_blocks_info["f_block_count"] + total_f_volume = f_blocks_info["total_f_volume"] + f_positions = f_blocks_info["f_positions"] + + # 处理当前任务 + current_task = self._process_current_task(artifact_list[0]) + + # 更新上一个任务信息 + self.task_before = { + "beton_task_id": current_task["beton_task_id"], + "beton_volume": current_task["beton_volume"], + "artifact_id": current_task["artifact_id"], + "block_number": current_task["block_number"] + } + + # 根据F块情况处理任务 + task_result = self._handle_tasks_by_f_blocks( + f_block_count, f_positions, current_task, + f_blocks, total_f_volume, artifact_list + ) + + return task_result + + def _process_f_blocks(self, artifact_list): + """处理F块相关信息""" + f_blocks = [artifact for artifact in artifact_list if artifact.get("BlockNumber") == "F"] + f_block_count = len(f_blocks) + total_f_volume = sum(artifact["BetonVolume"] for artifact in f_blocks) + f_positions = get_f_block_positions(artifact_list) + + return { + "f_blocks": f_blocks, + "f_block_count": f_block_count, + "total_f_volume": total_f_volume, + "f_positions": f_positions + } + + def _process_current_task(self, latest_artifact): + """处理当前任务信息""" + task_data = self.api_client.get_task_info(latest_artifact["BetonTaskID"]) + return { + "beton_task_id": latest_artifact["BetonTaskID"], + "beton_volume": latest_artifact["BetonVolume"], + "artifact_id": latest_artifact["ArtifactActionID"], + "block_number": latest_artifact.get("BlockNumber", ""), + "task_data": task_data + } + + def _handle_tasks_by_f_blocks(self, f_block_count, f_positions, current_task, + f_blocks, total_f_volume, artifact_list): + """根据F块数量和位置处理任务""" + # 多个F块情况 + if f_block_count > 2: + return self._handle_multiple_f_blocks(current_task, total_f_volume, artifact_list) + + # 两个F块情况 + elif f_block_count == 2: + return self._handle_two_f_blocks(f_positions, current_task, total_f_volume, artifact_list) + + # 一个F块情况 + elif f_block_count == 1: + return self._handle_single_f_block(f_positions, current_task, f_blocks, + total_f_volume, artifact_list) + + # 无F块情况 + elif f_block_count == 0: + return self._handle_no_f_blocks(current_task, artifact_list) + + else: + print("报警") + return [], [], [], self.half_volume + + def _handle_multiple_f_blocks(self, current_task, total_f_volume, artifact_list): + """处理多个F块的情况""" + adjusted_volume = total_f_volume - self.half_volume[0] + + tasks = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": adjusted_volume, + "artifact_id": current_task["artifact_id"], + "block_number": current_task["block_number"], + }] + + send_list = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": adjusted_volume, + "artifact_id": current_task["artifact_id"], + "block_number": current_task["block_number"], + "beton_grade": current_task["task_data"]["BetonGrade"], + "mix_id": current_task["task_data"]["MixID"], + "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now()) + }] + + # 处理后续任务 + self._append_additional_tasks(send_list, artifact_list, [0, 0]) + + # 更新时间戳 + self._update_artifact_timestamps(send_list) + + return tasks, artifact_list, send_list, self.half_volume + + def _handle_two_f_blocks(self, f_positions, current_task, total_f_volume, artifact_list): + """处理两个F块的情况""" + if f_positions == [0, 1] and self.task_before.get("block_number") == "F": + adjusted_volume = 0 + block_number = "补方" + else: + adjusted_volume = total_f_volume - self.half_volume[0] + block_number = current_task["block_number"] + + tasks = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": adjusted_volume, + "artifact_id": current_task["artifact_id"], + "block_number": block_number, + }] + + send_list = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": adjusted_volume, + "artifact_id": current_task["artifact_id"], + "block_number": block_number, + "beton_grade": current_task["task_data"]["BetonGrade"], + "mix_id": current_task["task_data"]["MixID"], + "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now()) + }] + + # 处理后续任务 + volumes = [adjusted_volume, + artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0] if f_positions == [0, + 1] and self.task_before.get( + "block_number") == "F" else [0, 0] + self._append_additional_tasks(send_list, artifact_list, volumes) + + # 更新时间戳 + self._update_artifact_timestamps(send_list) + + return tasks, artifact_list, send_list, self.half_volume + + def _handle_single_f_block(self, f_positions, current_task, f_blocks, total_f_volume, artifact_list): + """处理单个F块的情况""" + if f_positions == [2]: + f_volume = f_blocks[0].get("BetonVolume") if f_blocks else 0 + self.half_volume[0] = round(total_f_volume / 2, 2) + self.half_volume[1] = f_volume - self.half_volume[0] + adjusted_volume = current_task["beton_volume"] + self.half_volume[0] + elif f_positions == [1]: + adjusted_volume = current_task["beton_volume"] + self.half_volume[1] + elif f_positions == [0]: + adjusted_volume = 0 + else: + adjusted_volume = current_task["beton_volume"] + + block_number = "补方" if f_positions == [0] else current_task["block_number"] + + tasks = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": adjusted_volume, + "artifact_id": current_task["artifact_id"], + "block_number": block_number, + }] + + send_list = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": adjusted_volume, + "artifact_id": current_task["artifact_id"], + "block_number": block_number, + "beton_grade": current_task["task_data"]["BetonGrade"], + "mix_id": current_task["task_data"]["MixID"], + "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now()) + }] + + # 处理后续任务 + self._append_additional_tasks_for_single_f(send_list, artifact_list, f_positions) + + # 更新时间戳 + self._update_artifact_timestamps(send_list) + + return tasks, artifact_list, send_list, self.half_volume + + def _handle_no_f_blocks(self, current_task, artifact_list): + """处理无F块的情况""" + tasks = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": current_task["beton_volume"], + "artifact_id": current_task["artifact_id"], + "block_number": current_task["block_number"], + }] + + send_list = [{ + "beton_task_id": current_task["beton_task_id"], + "beton_volume": current_task["beton_volume"], + "artifact_id": current_task["artifact_id"], + "block_number": current_task["block_number"], + "beton_grade": current_task["task_data"]["BetonGrade"], + "mix_id": current_task["task_data"]["MixID"], + "time": self.artifact_timestamps.get(current_task["artifact_id"], datetime.now()) + }] + + # 处理后续任务 + self._append_additional_tasks(send_list, artifact_list, + [artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0, + artifact_list[2]["BetonVolume"] if len(artifact_list) > 2 else 0]) + + # 更新时间戳 + self._update_artifact_timestamps(send_list) + + return tasks, artifact_list, send_list, self.half_volume + + def _append_additional_tasks(self, send_list, artifact_list, volumes): + """添加额外的任务到发送列表""" + # 安全获取后续任务 + second_task = artifact_list[1] if len(artifact_list) > 1 else None + third_task = artifact_list[2] if len(artifact_list) > 2 else None + + if second_task: + task_data_second = self.api_client.get_task_info(second_task["BetonTaskID"]) + send_list.append({ + "beton_task_id": second_task["BetonTaskID"], + "beton_volume": volumes[0], + "artifact_id": second_task["ArtifactActionID"], + "block_number": second_task["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": self.artifact_timestamps.get(second_task["ArtifactActionID"], datetime.now()) + }) + + if third_task: + task_data_third = self.api_client.get_task_info(third_task["BetonTaskID"]) + send_list.append({ + "beton_task_id": third_task["BetonTaskID"], + "beton_volume": volumes[1], + "artifact_id": third_task["ArtifactActionID"], + "block_number": third_task["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": self.artifact_timestamps.get(third_task["ArtifactActionID"], datetime.now()) + }) + + def _append_additional_tasks_for_single_f(self, send_list, artifact_list, f_positions): + """为单个F块情况添加额外任务""" + second_task = artifact_list[1] if len(artifact_list) > 1 else None + third_task = artifact_list[2] if len(artifact_list) > 2 else None + + if second_task: + task_data_second = self.api_client.get_task_info(second_task["BetonTaskID"]) + volume = (third_task["BetonVolume"] if third_task else 0) if f_positions != [2] else ( + second_task["BetonVolume"] + self.half_volume[1]) + send_list.append({ + "beton_task_id": second_task["BetonTaskID"], + "beton_volume": volume, + "artifact_id": second_task["ArtifactActionID"], + "block_number": second_task["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": self.artifact_timestamps.get(second_task["ArtifactActionID"], datetime.now()) + }) + + if third_task: + task_data_third = self.api_client.get_task_info(third_task["BetonTaskID"]) + volume = third_task["BetonVolume"] if f_positions in [[1], [0]] else 0 + send_list.append({ + "beton_task_id": third_task["BetonTaskID"], + "beton_volume": volume, + "artifact_id": third_task["ArtifactActionID"], + "block_number": third_task["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": self.artifact_timestamps.get(third_task["ArtifactActionID"], datetime.now()) + }) + + def _update_artifact_timestamps(self, send_list): + """更新artifact时间戳""" + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in self.artifact_timestamps: + self.artifact_timestamps[artifact_id] = datetime.now() diff --git a/tcp/__init__.py b/tcp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tcp/__pycache__/__init__.cpython-39.pyc b/tcp/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..01634508fdafa81db5cf1411819c427a56a6e318 GIT binary patch literal 135 zcmYe~<>g`kg6D69GePuY5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!HHi&acPWpYMh zQEov|epYI7NsMP+acWVCOJYf4Oi6M &ryk0@&Ee@O9{FKt1R6CF 4_4=rC?6zZmFP;5t#)F4cSa-!NEHw&Dx_s+As zsCPP3zS mZA1{I;{VuR%boErZG_TakRtVYXYbBuFlu_Mo!Omv z=bhPkpXYtwxol@=T)}VV>!ta%D-`9Q^wR#*@$wpOcNhg%I2%(kVa+m3zN;Bk)>=k; zL*XjdPAFVEu4Z)G;QB#TY_oN4aFa()s~OWatC1OnLC=Vij?O`+GMuBb{iosOHQeqH z3R|IhFh>v9xPF3VG}3lL$>==7qo@rY<8jm`@8Aj45#Gs@sH41#ccYH+C75ez5Zm?o zjuBfNvc;p=OB-MA+koq(x!bE0B}WrBfAp;4ejT@qPNl*siltOklvoH#l~aqhpPqHD zK)E_Rlr{qWK*99_y;u-l(CNyVEVqz5XnR3C?^?oloV>F?Nan`!w&OLr+_V evM#ZnNpth|%= zEGveQt~4n#8&|of_2qp{u^fY3^GBadL*yrajfe7G`H70hs?1}fDsF9tHbAc^qk7fA zyNNr()ftUp8_*U-8N(glr_QiOTL;(Z*-LO57rUr%gCtO!myP4p(>a<%OBZK^j!9Nw z)owyZc{y4Yan4&(?ZF(7oH({yaaQSyx3qMdK|*Scl8%Z}?WHkqD~`HBfz(DwEi3(t zDU&KRt-$QDih5DGtdjI@$np53dRTShVZA}wfEF0B!|%bT*QRdNPF=%>)i0f{otl~b z%Z*)gv{!Rv9{;;2+WTr>{xux%@4LUBy?C}Z^;zl>>o044eSK*)FuknU59^yeYmXNk z|5=QVxAfMpe^k44t@i7`%}rm2ybty@W}g?CzE%6}ow;-G_os%_%S99tf!TmmWXq7X zb$D=B&@r<8^*61NT{{Q2{8U6pB<|WCNfnAf-pKa1ERuj^Vr09ubMR*)gIfj$b_V+1 zyu;^F7noyt*R!3#D2lw}1u^e{u(O;HYwnVdK~FZ9vx}aUD>x3&m@hbPV7T~5px(=m z+jtqX?P9RxO}n(WkQIEZ $bFx|s?aV6Lat(!$PYU##Xl=Y}dR_>a|x?I@;ppy+-K)-?)39}33w@|aH zI-~3X2qyvbQLU<1m;|o@DgZuQy{t*dnxhf)N8uIJeQ WD zIuH2ifZsYf!y(TA^z{WGG$-}L`oskZ$nY7opf&>J1fBuOh`$VrtiOA;c4oTv`G@tB zUjmO0?p;C4f9N|}Z7H8#Q-EXGy9@if1TBFM1iFHN?Wa&Is;b_OvJQ!|5JzTc96>%M zFtf#?4ZwT{FXA~WR#J24fvm&FY%6qX(p+LSI?{$TaL~EH+qIlumUCgdZl>8C+F!gt zddc~et^hTEkFMKzhqlCXETrZXM3SHCfh1T1f&wfx+?^`FG*0yj@YX+hxv7(T_y zzbJnt&GnF6{wO=7h==7N_#`-d>C;$MBX30Jb~nM)4`Ftld|cI-fw?QX$asiv6&*70 zbnuA=jf12KP{c;#B`@?{Z=;27w3?$GrOyBs6JSY6Pf1`iDki|9w>*|PX&yEwOaKJ+ z27*|p^l&t49Y#eYM5Bw2df0&20u6we318Vynx M*8@V$NOH~Zu;9(?jq{mN8JJmoJ(V`|&T_Tl<_H|wWAZ%4fx@R K5RJ#|l~Q21^n8b6`q?U=~O07fZ2(AktLQMISXFRSXJI5Ftg0gn=m# zcn(2xZmi(i>4@Z{_&&PCI_lR+T@V?^1lj#|5TlvHDHdbmix~1MZg(>ZVq!N_)wmW1 z4|OexGOi|ZMbW+%Z0u!g)o!* Y^BLVETBSV$Z} zE>%8-RHQag5cE@Jy7>o>fj$}~8PelQ5|y9#)Cv;D<46h6AEh213t`zv8MM;7Ab}xM z1_t;W3%qs5q;c2){AEoZ+Bt^#5(ia)AE^-Ue9DZ;#*AH$&A17~(?C3|=l_^9iJ7|F zlNqO}XIq<|CI4&fyaS}_@yVY)2Kop0&ebknnZ0l#gngjp#yK(ppcTP%ycn3aC|Y@* z=>{sfFH-;u5xyY&??GAp+^yQlo3*>gYPWCCp8Mebolij0*$=L!)~CR>x#=(ZQ|0)& z)Zoq?sjUP3DW3v-yR`oUQX<(|yYt7{Q@83zjuMkDeo;Sv^ZxBS{i$~8)Y_(^M=Tvi zH!1j-f_9!~I&xVjXOCI?Y@4?&`Tp(epzBkX94_ zihZe_{m1>ke~gVt(MBwEZ%_E0v>s?kCMCHuEBqpui>T`(uNt?!>|TUmn8@?pF#4Jy z(|-iT;uR`>Oa+m5(HOf49UQky6jxL*nJzH77a3O^Oir>jR5#wb*&4M6+%B)2=kg+c zY5}7u;8J9lhm240upbFJh1&t;=jBPQyt$%@0Xl3{7>)xfjsrTvs|MC;&nO792&xoJ zAJ3#F;uJ(n#~S!wjec_;{}mPCSRO)T5R4FuC*oYzGS7-vRLs9((yW-Y7KHp$R3mho zG~2`}9syUPKJ80w>TLa;BlSz~w9+gPr4?XmXU@(YIU1U6D9wU|?YO?Mt*o2N=K~fO z>!HG@oC(9BYSDqf0ukwH-R)RT$7Eh6HbOoyxIbQWgNTa^Eju;_o;nm!<|Bci3`)F= zq8S8!i04c%&%2Fm-sa5{X&4_QbSMfScgI=cv8*hJ(Nr>29EFTahZo>RjUzkLSyJsq zmY&45N{a$F<)!mDX^mTunQIu{LdQ+Kga=Sc5@4T!Nmfo!BG$;U6XZQh!?1aH#M8Oj z?iF#w)98pdkqB#P=>&8c;zF4YoJLcVJS=LZKecH>99iJ`r6zcOS(7FYe`io)Mr*5@ zv?8tnBc|VlW!H{gs$c)Gb$}c4DO(87crAm6IRV-7%vpF89Pb|7xPcR%Pc{l=Lj|?> zuhp(jQ_g;U`U!EFf?!))a}liM?65GM6hnAWsFp4v#DY8@A{(%?qHzQhLnN_SxF;mO zhr3~16M MV (-KY2coheOI3=u_P!J+OEr`fPMrbWL<+ zv{z6c%{`vYJC@b9B6a@En~us 2: + adjusted_volume = total_f_volume - half_volume[0] + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": 0, + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": 0, + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + + elif f_block_count == 2 and f_positions == [0, 1] and task_before.block_number == "F": + adjusted_volume = 0 + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": "补方", + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": adjusted_volume, + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + + elif f_block_count == 2 and f_positions == [1, 2]: + adjusted_volume = total_f_volume - half_volume[0] + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": beton_volume, + "artifact_id": artifact_id, + "block_number": block_number, + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": beton_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": adjusted_volume, + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": 0, + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + + elif f_block_count == 2 and f_positions == [0, 1] and task_before.block_number != "F": + adjusted_volume = total_f_volume - half_volume[0] + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": 0, + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + + elif f_block_count == 1 and f_positions == [2]: + adjusted_volume = beton_volume + half_volume[0] + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": beton_volume + half_volume[1], + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + + elif f_block_count == 1 and f_positions == [1]: + adjusted_volume = beton_volume + half_volume[1] + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + + elif f_block_count == 1 and f_positions == [0]: + adjusted_volume = 0 + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": "补方", + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + elif f_block_count == 0: + adjusted_volume = beton_volume + tasks.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + }) + send_list.append({ + "beton_task_id": beton_task_id, + "beton_volume": adjusted_volume, + "artifact_id": artifact_id, + "block_number": block_number, + "beton_grade": task_data["BetonGrade"], + "mix_id": task_data["MixID"], + "time": artifact_timestamps.get(artifact_id, datetime.now()) + }) + dispatch_list_second = artifact_list[1] + task_data_second = get_task_info(app_id, dispatch_list_second["BetonTaskID"]) + dispatch_list_third = artifact_list[2] + task_data_third = get_task_info(app_id, dispatch_list_third["BetonTaskID"]) + send_list.append({ + "beton_task_id": dispatch_list_second["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_second["ArtifactActionID"], + "block_number": dispatch_list_second["BlockNumber"], + "beton_grade": task_data_second["BetonGrade"], + "mix_id": task_data_second["MixID"], + "time": artifact_timestamps.get(dispatch_list_second["ArtifactActionID"], datetime.now()) + }) + send_list.append({ + "beton_task_id": dispatch_list_third["BetonTaskID"], + "beton_volume": dispatch_list_third["BetonVolume"], + "artifact_id": dispatch_list_third["ArtifactActionID"], + "block_number": dispatch_list_third["BlockNumber"], + "beton_grade": task_data_third["BetonGrade"], + "mix_id": task_data_third["MixID"], + "time": artifact_timestamps.get(dispatch_list_third["ArtifactActionID"], datetime.now()) + }) + # 更新新出现的 artifact_id 的时间戳 + current_artifact_ids = {item["artifact_id"] for item in send_list} + for artifact_id in current_artifact_ids: + if artifact_id not in artifact_timestamps: + artifact_timestamps[artifact_id] = datetime.now() + return tasks, artifact_list, send_list, half_volume + + else: + print("报警") + + raise Exception("获取未浇筑信息失败") + + +{ + "ArtifactID": "QR1B32000153AD", + "ArtifactActionID": 346482967298128, + "ArtifactIDVice1": "Q00001AD", + "ProduceRingNumber": 1, + "MouldCode": "SHR2B3-9", + "SkeletonID": "QR1B2000048A", + "RingTypeCode": "R22", + "SizeSpecification": "6900*1500", + "BuriedDepth": "中埋", + "BlockNumber": "F", + "HoleRingMarking": "否", + "GroutingPipeMarking": "否", + "PolypropyleneFiberMarking": "否", + "BetonVolume": 0.55, + "BetonTaskID": "20251020-01" +}, \ No newline at end of file diff --git a/test.py b/test.py deleted file mode 100644 index 3861ab0..0000000 --- a/test.py +++ /dev/null @@ -1,5 +0,0 @@ -import pyodbc -print("系统中可用的ODBC驱动程序:") -for driver in pyodbc.drivers(): - if "Access" in driver or "Excel" in driver: - print(f" {driver}") diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/__pycache__/__init__.cpython-39.pyc b/utils/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a0ca318661cd3b356b4eba21d2a5281a9bb61194 GIT binary patch literal 137 zcmYe~<>g`kf>UpVGePuY5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!HXi&acPWpYMh zQEov|epYI7NsMP+acWVCOJYf4Ole7GPH{|pd}dx|NqoFsLFFwDo80`A(wtN~kU5`$ Gm;nH)Zy&+{ literal 0 HcmV?d00001 diff --git a/utils/__pycache__/helpers.cpython-39.pyc b/utils/__pycache__/helpers.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc045d5576476880d71f3ba0c6cab175c02010cc GIT binary patch literal 1234 zcmZ`(&1)M+6rb5It!ycnCM`}6LC}*9?IGk)L>rRS1bXqMH=(lG>`d&f_bW5AZ2~I@ z_#-wnwIR4p>zGK8&<}`fXsAtNk^f_^)ymSPKJ*fL>f04k6=(-$=FOY;-f!OT&5T_x zPa$Z3{dv|c8VLQ7Ehd`^i!0FiyD$(`M+6gP1=TSr5S x4 zmXauKjL~h70Z5JC1IPY1hw0|GHWThG+Yy%Ma?w3{ejNZ$zF+Bf9-MUc<@7Z#be860 z|0ZP;U$3gNNQ2m?%obFt3sgwMjv^Y6swT^CgsK;#kh{VS11_;E&C%vhh!p|+@Av0w zjp(kkXfr=z;TO~qjZXtknV7SM-H3(j@x~(cBFgv&(OvmAU|F}Uo7r)!apa5$o|CU= zcm|)rCCsKlH$Rw#(aDG(wG32;p7XW^LRJJ1`KYO4l=0O@O%1rz6Vy`L2)L{PmqxRY zV4}u|f0!5v{t~lFq9uh{)HD;brM6L`5bYdV(m=1bw8Y3+1{wUPnnr>W<70IDMxwKI zp%YygiN1_?5rKIZ?P<$Ulc5f(Qixx}v8F1}dPl1#TWkGS_j`|@KrwndzYTU?^wxjv z?;oU{?Wx@6DqG;ST*^E~^jgC8DHpaM@mgi C!??1hGX{gKN4Ip<^#nL2jwX!7U-I+58#aVTSbaa1TtHc*z zS?M1A{D0ikD%Ao5KP1&4{7UMspgxyn5enP0ICa8+aF*QzsYlEWgj78mREzTLINg5< zl;{47sCxO0v~#d}X=Iss*Qe>7$YqpRz^j}dM|O!Uj-yKzn9HBSaLDqM?>HW{gE+E6 zk4#ju414+Kfr=%?#F{#z%wQ9GNi|{C@T|hlgH2VLXQgabWx=vY=vY?%9P-Txtn4kY W9MJs84@vCN%h?yh^S?zki~j)DUYouE literal 0 HcmV?d00001 diff --git a/utils/helpers.py b/utils/helpers.py new file mode 100644 index 0000000..6cba2f8 --- /dev/null +++ b/utils/helpers.py @@ -0,0 +1,43 @@ +"""工具函数模块""" + + +def get_f_block_positions(artifact_list): + """获取artifact_list中F块的位置""" + positions = [] + for i, artifact in enumerate(artifact_list): + if artifact.get("BlockNumber") == "F": + positions.append(i) + return positions + + +def cleanup_old_timestamps(artifact_timestamps, current_artifact_ids=None, max_age_hours=24): + """ + 清理过期的时间戳记录 + + Args: + artifact_timestamps: 时间戳字典 + current_artifact_ids: 当前活跃的artifact_id集合,可选 + max_age_hours: 时间戳最大保留时间(小时),默认24小时 + """ + from datetime import datetime + + current_time = datetime.now() + expired_ids = [] + + # 遍历所有存储的时间戳记录 + for artifact_id, timestamp in artifact_timestamps.items(): + # 如果提供了当前活跃ID列表,且该ID不在当前活跃列表中,则检查是否过期 + if current_artifact_ids is None or artifact_id not in current_artifact_ids: + age = current_time - timestamp + # 如果超过最大保留时间,则标记为过期 + if age.total_seconds() > max_age_hours * 3600: + expired_ids.append(artifact_id) + + # 删除过期的时间戳记录 + for artifact_id in expired_ids: + del artifact_timestamps[artifact_id] + + if expired_ids: + print(f"清理了 {len(expired_ids)} 个过期的时间戳记录: {expired_ids}") + + return len(expired_ids) diff --git a/zjsh_ui_sysytem b/zjsh_ui_sysytem index 30d00b8..fe751e8 160000 --- a/zjsh_ui_sysytem +++ b/zjsh_ui_sysytem @@ -1 +1 @@ -Subproject commit 30d00b8aef550efa6a06e69a64c24ab6b021e5c2 +Subproject commit fe751e8dd209b7a4bb8ac88b27a7291d347e20b9