Update~Read PLC for Chart ~ Log By Shift To be... Alarm AI Machine Learning

上圖~
持續迭代
1、增加報警彈窗,具體到哪個值,雙邊規格具體是多少
2、實時顯示當前值的統計特征,Max  Min  AVG ...






import tkinter as tk
from tkinter import simpledialog
import time
import threading
import queue
import logging
from datetime import datetime
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg  # 新增導入
from matplotlib.animation import FuncAnimation
from openpyxl import Workbook, load_workbook
from HslCommunication import MelsecMcNet
import os
import csv
import winsound
import json# 配置日志
logging.basicConfig(level=logging.INFO,format='%(asctime)s.%(msecs)03d %(levelname)s: %(message)s',datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger("PLC_Monitor")# 設置中文字體支持
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus'] = False    # 用來正常顯示負號class PLCMonitor:def __init__(self):self.is_running = Trueself.is_collecting = Falseself.data_queue = queue.Queue()self.data_points = []self.register_addresses = ["D390", "D391", "D392", "D393", "D394", "D395"]  # 6個默認地址# 新增初始化屬性self.current_date = datetime.now().strftime("%Y%m%d")  # 當前日期self.current_shift = self.get_shift()  # 當前班別self.last_shift_check = time.time()  # 上次班別檢查時間self.data_dir = "C:\\Log\\Cature_Datawen"  # 數據存儲目錄# 確保數據目錄存在os.makedirs(self.data_dir, exist_ok=True)self.current_filepath = os.path.join(self.data_dir, f"{self.current_date}_{self.current_shift}.txt")  # 初始化文件路徑# 初始化圖表屬性self.fig, self.ax = plt.subplots(figsize=(12, 6))self.fig.patch.set_facecolor('#2E2E2E')  # 設置圖表背景色self.canvas = None  # 初始化canvas屬性# 創建主窗口self.root = tk.Tk()self.root.title("Design By Tim")self.root.geometry("1200x700")self.root.minsize(1000, 600)self.root.configure(bg='#2E2E2E')# 初始化UI組件self.value_labels = []  # 初始化label列表# 創建圖表容器self.chart_frame = tk.Frame(self.root, bg='#2E2E2E')self.chart_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=10, pady=10)# 創建值顯示區域self.values_frame = tk.Frame(self.root, bg='#2E2E2E')self.values_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=10, pady=10)# 初始化值標簽for i in range(6):label = tk.Label(self.values_frame,text="  ",font=('Arial', 12),bg='#2E2E2E',fg='white')label.pack(side=tk.LEFT, padx=10)self.value_labels.append(label)# 添加analysis按鈕 (位置保持不變)self.analysis_button = tk.Button(self.chart_frame,text="analysis",command=self.launch_analysis,font=('Arial', 10),bg='#4E4E4E',fg='white')self.analysis_button.pack(side=tk.TOP, anchor=tk.NE, padx=10, pady=6)  # 修改位置到右上角# 添加By Chart按鈕 (新位置)self.chart_button = tk.Button(self.chart_frame,text="By Chart",command=self.create_subplots,font=('Arial', 10),bg='#4E4E4E',fg='white')self.chart_button.pack(side=tk.TOP, anchor=tk.NE, padx=10, pady=5)# 添加Alarm Setting按鈕 (位置保持不變)self.alarm_button = tk.Button(self.chart_frame,text="Alarm Setting",command=self.open_alarm_settings,font=('Arial', 10),bg='#4E4E4E',fg='white')self.alarm_button.pack(side=tk.TOP, anchor=tk.NE, padx=10, pady=5)# 創建圖表self.canvas = FigureCanvasTkAgg(self.fig, master=self.chart_frame)self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)# 隱藏初始的Tk窗口self.root.withdraw()# 獲取PLC連接參數self.plc_ip = simpledialog.askstring("PLC Par", "PLC_IP:", initialvalue="192.168.0.11",parent=self.root)self.plc_port = simpledialog.askinteger("PLC Par", "PLC_Port:", initialvalue=1028,parent=self.root)# 獲取采集信號配置self.start_signal = simpledialog.askstring("Signal ","Start_signal addresses(Y70):",initialvalue="Y70",parent=self.root)self.stop_signal = simpledialog.askstring("Signal ","Stop_signal addresses(Y75):",initialvalue="Y75",parent=self.root)try:self.plc = MelsecMcNet(self.plc_ip, self.plc_port)if not self.plc.ConnectServer().IsSuccess:logger.error("PLC Content NG")self.is_running = Falseelse:logger.info(f"PLC Content OK: {self.plc_ip}:{self.plc_port}")logger.info(f"Start_signal: {self.start_signal}, Stop_signal: {self.stop_signal}")except Exception as e:logger.error(f"PLC Content Error: {str(e)}")self.is_running = False# 獲取寄存器配置register_input = simpledialog.askstring("Addresses Config", "Addresses(Max 6,Betwin ,):",initialvalue="D390,D391,D392,D393,D394,D395")if register_input:addresses = [addr.strip() for addr in register_input.split(',')][:6]  # 修改為最多6個地址self.register_addresses = addresseslogger.info(f"Addresses Config: {', '.join(addresses)}")# Initialize alarm settingsself.alarm_settings = {addr: {'upper': float('inf'), 'lower': -float('inf')} for addr in self.register_addresses}self.alarm_active = {addr: False for addr in self.register_addresses}# 加載保存的報警設置self.load_alarm_settings()def open_alarm_settings(self):"""打開報警設置彈窗"""# 創建彈窗alarm_window = tk.Toplevel(self.root)alarm_window.title("Alarm Settings")alarm_window.geometry("400x300")alarm_window.configure(bg='#2E2E2E')alarm_window.transient(self.root)# 創建標簽和輸入框entries = {}for i, addr in enumerate(self.register_addresses):# 地址標簽addr_label = tk.Label(alarm_window,text=f"Address {addr}",font=('Arial', 10),bg='#2E2E2E',fg='white')addr_label.grid(row=i, column=0, padx=10, pady=5, sticky='w')# 下限輸入lower_frame = tk.Frame(alarm_window, bg='#2E2E2E')lower_frame.grid(row=i, column=1, padx=5, pady=5)lower_label = tk.Label(lower_frame,text="Lower:",font=('Arial', 8),bg='#2E2E2E',fg='white')lower_label.pack(side=tk.LEFT)lower_entry = tk.Entry(lower_frame, width=10)lower_entry.pack(side=tk.LEFT)lower_entry.insert(0, str(self.alarm_settings[addr]['lower']) if self.alarm_settings[addr]['lower'] != -float('inf') else '')# 上限輸入upper_frame = tk.Frame(alarm_window, bg='#2E2E2E')upper_frame.grid(row=i, column=2, padx=5, pady=5)upper_label = tk.Label(upper_frame,text="Upper:",font=('Arial', 8),bg='#2E2E2E',fg='white')upper_label.pack(side=tk.LEFT)upper_entry = tk.Entry(upper_frame, width=10)upper_entry.pack(side=tk.LEFT)upper_entry.insert(0, str(self.alarm_settings[addr]['upper']) if self.alarm_settings[addr]['upper'] != float('inf') else '')entries[addr] = {'lower': lower_entry, 'upper': upper_entry}# 保存按鈕def save_settings():for addr, entry in entries.items():try:lower_val = float(entry['lower'].get()) if entry['lower'].get() else -float('inf')upper_val = float(entry['upper'].get()) if entry['upper'].get() else float('inf')self.alarm_settings[addr]['lower'] = lower_valself.alarm_settings[addr]['upper'] = upper_vallogger.info(f"Alarm settings updated for {addr}: Lower={lower_val}, Upper={upper_val}")except ValueError:logger.error(f"Invalid numeric value for {addr}")# 保存報警設置到JSON文件self.save_alarm_settings()alarm_window.destroy()save_btn = tk.Button(alarm_window,text="Save",command=save_settings,font=('Arial', 10),bg='#4E4E4E',fg='white')save_btn.grid(row=len(self.register_addresses), column=1, padx=10, pady=15)# 取消按鈕cancel_btn = tk.Button(alarm_window,text="Cancel",command=alarm_window.destroy,font=('Arial', 10),bg='#4E4E4E',fg='white')cancel_btn.grid(row=len(self.register_addresses), column=2, padx=10, pady=15)self.current_date = datetime.now().strftime("%Y%m%d")  # 當前日期self.current_shift = self.get_shift()  # 當前班別self.last_shift_check = time.time()  # 上次班別檢查時間def get_shift(self):"""獲取當前班別"""now = datetime.now()hour &

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88984.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88984.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88984.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

es的自定義詞典和停用詞

在 Elasticsearch 中,自定義詞典是優化分詞效果的核心手段,尤其適用于中文或專業領域的文本處理。以下是關于 ES 自定義詞典的完整指南: 為什么需要自定義詞典? 默認分詞不足: ES 自帶的分詞器(如 Standard…

微算法科技技術突破:用于前饋神經網絡的量子算法技術助力神經網絡變革

隨著量子計算和機器學習的迅猛發展,企業界正逐步邁向融合這兩大領域的新時代。在這一背景下,微算法科技(NASDAQ:MLGO)成功研發出一套用于前饋神經網絡的量子算法,突破了傳統神經網絡在訓練和評估中的性能瓶頸。這一創新…

一文讀懂循環神經網絡(RNN)—語言模型+讀取長序列數據(2)

目錄 讀取長序列數據 為什么需要 “讀取長序列數據”? 讀取長序列數據的核心方法 1. 滑動窗口(Sliding Window) 2. 分段截取(Segmentation) 3. 滾動生成(Rolling Generation) 4. 關鍵信息…

Oracle Virtualbox 虛擬機配置靜態IP

Oracle Virtualbox 虛擬機配置靜態IP VirtualBox的網卡,默認都是第一個不能自定義,后續新建的可以自定義。 新建NAT網卡、host主機模式網卡 依次點擊:管理->工具->網絡管理器新建host主機模式網卡 這個網卡的網段自定義,創建…

Linux RAID1 創建與配置實戰指南(mdadm)

Linux RAID1 創建與配置實戰指南(mdadm)一、RAID1 核心價值與實戰目標RAID1(磁盤鏡像) 通過數據冗余提供高可靠性:當單塊硬盤損壞時,數據不丟失支持快速陣列重建讀寫性能略低于單盤(鏡像寫入開銷…

MySQL數據庫----函數

目錄函數1,字符串函數2,數值函數3,日期函數4,流程函數函數 1,字符串函數 MySQL中內置了很多字符串函數 2,數值函數 3,日期函數 4,流程函數

1.2 vue2(組合式API)的語法結構以及外部暴露

vue2 vue3中可以寫vue2的語法&#xff0c;vue2的結構像一個花盆里的根&#xff08;根組件App.vue&#xff09;&#xff0c;根上可以插上不同的枝杈和花朵&#xff08;組件&#xff09;。 組件的結構&#xff1a; // 這里寫邏輯行為 <script lang"ts"> export d…

Swift 解 LeetCode 324:一步步實現擺動排序 II,掌握數組重排的節奏感

文章目錄摘要描述題解答案題解代碼&#xff08;Swift&#xff09;題解代碼分析步驟一&#xff1a;排序數組步驟二&#xff1a;左右指針分段步驟三&#xff1a;按位置交錯插入示例測試及結果示例 1示例 2示例 3&#xff08;邊界情況&#xff09;時間復雜度分析空間復雜度分析總結…

使用SQLMAP的文章管理系統CMS的sql注入滲透測試

SQLMAP注入演示&#xff1a;抓包拿到Cookie:召喚sqlmap&#xff1a;sqlmap -u "http://192.168.1.99:8085/show.php?id34" --cookie "pma_langzh_CN; kbqug_admin_username2621-PL_LxhFjyVe43ZuQvht6MI5q0ZcpRVV5FI0pzQ6XR8; kbqug_siteid2621-PL_LxhFjyVe4yA5…

I3C通信協議核心詳解

一、物理層與電氣特性雙線結構 SCL&#xff08;串行時鐘線&#xff09;&#xff1a;主設備控制&#xff0c;支持 推挽&#xff08;Push-Pull&#xff09;輸出&#xff08;高速模式&#xff09;和 開漏&#xff08;Open-Drain&#xff09;&#xff08;兼容I2C模式&#xff09;。…

Docker搭建Redis哨兵集群

Redis提供了哨兵機制實現主從集群下的故障轉移&#xff0c;其中包含了對主從服務的檢測、自動故障恢復和通知。 1.環境 centos7、redis6.2.4、MobaXterm 目的&#xff1a; 搭建redis的主從同步哨兵集群&#xff08;一主一從三哨兵&#xff09; 2.步驟 1.主從集群的搭建 主從…

暑假Python基礎整理 --異常處理及程序調試

異常概念 在程序運行過程中&#xff0c;經常會遇到各種各樣的錯誤&#xff0c;這些錯誤統稱為“異常”。如下表是Python常見的異常與描述&#xff1a; 異常描述NameError嘗試訪問一個未聲明的變量引發錯誤IndexError索引超出序列范圍引發錯誤IndentationError縮進錯誤ValueErr…

k8s-高級調度(二)

目錄 Taint(污點)與Toleration(容忍) Taint&#xff08;污點&#xff09;&#xff1a;節點的排斥標記 Toleration&#xff08;容忍&#xff09;&#xff1a;Pod的適配聲明 與節點親和性的對比 警戒(cordon)和轉移(drain) Cordon&#xff1a;節點隔離&#xff08;阻止新 Po…

基于OpenCV的深度學習人臉識別系統開發全攻略(DNN+FaceNet核心技術選型)

核心技術選型表 技術組件版本/型號用途OpenCV DNN4.5.5人臉檢測FaceNet (facenet-pytorch)0.5.0人臉特征提取MiniConda最新版Python環境管理PyTorch1.8.0FaceNet運行基礎OpenVINO2021.4模型加速(可選)SSD Caffe模型res10_300x300高精度人臉檢測 一、環境準備與項目搭建 1.1 M…

【AI News | 20250714】每日AI進展

AI Repos 1、All-Model-Chat All Model Chat 是一款為Google Gemini API家族設計的網頁聊天應用&#xff0c;支持多模態輸入&#xff08;圖片、音頻、PDF等&#xff09;和多種模型&#xff08;如Gemini Flash、Imagen&#xff09;。它提供了豐富的自定義功能&#xff0c;包括高…

C 語言(二)

主要包括變量與常量、數據類型、存儲方式、數制轉換以及字符處理等內容一、變量與常量在 C 語言中&#xff0c;變量是用來存儲數據的命名空間&#xff0c;它會在內存中分配地址。例如&#xff1a;int i; i 12345; 其中 i 是變量&#xff0c;12345 是常量。常量表示在程序運行過…

原型繼承(prototypal inheritance)的工作原理

這是一個非常常見的 JavaScript 問題。所有 JS 對象都有一個__proto__屬性&#xff0c;指向它的原型對象。當試圖訪問一個對象的屬性時&#xff0c;如果沒有在該對象上找到&#xff0c;它還會搜尋該對象的原型&#xff0c;以及該對象的原型的原型&#xff0c;依次層層向上搜索&…

OpenCV 視頻處理與攝像頭操作詳解

1. 引言大家都來寫OpenCV&#x1f60a;&#xff0c;學的好開心&#xff01;2. 視頻基礎與OpenCV簡介2.1 視頻的定義視頻&#xff08;Video&#xff09;是由一系列靜態圖像&#xff08;幀&#xff09;以一定速率連續播放形成的動態影像。其本質是利用人眼的視覺暫留效應&#xf…

Agentic AI 的威脅與緩解措施

原文&#xff1a;https://www.aigl.blog/content/files/2025/04/Agentic-AI—Threats-and-Mitigations.pdf AI Agent 的定義 1. 定義與基礎 智能代理&#xff08;Agent&#xff09;的定義&#xff1a; 智能代理是一種能夠感知環境、進行推理、做出決策并自主采取行動以實現特定…

ArrayList列表解析

ArrayList集合 ArrayList 的底層是數組隊列&#xff0c;相當于動態數組。與 Java 中的數組相比&#xff0c;它的容量能動態增長。在添加大量元素前&#xff0c;應用程序可以使用ensureCapacity操作來增加 ArrayList 實例的容量。這可以減少遞增式再分配的數量。 ArrayList 繼承…