精益生产轻量级按(安)灯系统python实现

轻量级按(安)灯系统python实现

按灯系统是精益生产常用的工具之一

传统使用软件+硬件搭建系统,本案例使用python的标准库纯软件实现。

python主要标准库及功能
tkinter UI界面
socket 服务端/客户端通信
sqlite 数据保存

本案例实现了按灯的基本功能,后续可进行扩展:
如可以根据按灯保存的数据使用python第三方库matplotlib实现可视化功能。
统计:机器异常种类,异常持续时间,间隔等
客户端代码:

from tkinter import *
import os
from random import randint
import socket, threading
import tkinter.ttk
from datetime import datetime
root = Tk()
width = 600
height =470
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth-width)/2, (screenheight-height)/2)
root.geometry(alignstr)
root.title("MyAndon")
root.resizable(0,0)
root.iconbitmap(".\\pic\\smart.ico")

one = Label(root, text="© Powered by Will Wu "+"2020-"+str(datetime.now().year), width=30, height=2, font=("Arial", 10))
one.pack(side=BOTTOM)


f1=LabelFrame(root,text="CNC_状态",labelanchor="n" )
f1.place(x=30,y=10,width=215,height=400)

cv = Canvas(f1)
cv.place(x=0,y=10,width=200,height=200)
green_button = PhotoImage(file = ".\\pic\\greenlight.png")
red_button = PhotoImage(file = ".\\pic\\redlight.png")
btn = cv.create_image(150, 0, anchor=NE, image=green_button)

def flashr():
    
    global c
    cv.itemconfigure(btn, image=[red_button,green_button][randint(0,1)])
    c=root.after(500, flashr)  
 

def combine():
    send_content("N")
    flashr()

def cancel_red():
    
    send_content("Y")
    root.after_cancel(c)
    cv.itemconfigure(btn, image=green_button)
 



def get_local_ip():  #获取当前计算机的IP地址
    local_ip = ""
    try:
        socket_objs = [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]
        #print(socket_objs[0][1])
        ip_from_ip_port = [(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in socket_objs][0][1]
        ip_from_host_name = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1]
        local_ip = [l for l in (ip_from_ip_port, ip_from_host_name) if l][0]
    except (Exception) as e:
        print("get_local_ip found exception : %s" % e)
    return local_ip if("" != local_ip and None != local_ip) else socket.gethostbyname(socket.gethostname())
 
def connectServer():
          global ck
          #ipStr = eip.get()
          ipStr = termhost.get()
          print(ipStr)
          portStr = eport.get()
          userStr = comboNO.get()
          client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#socked所遵守ipv4或ipv6,和相关协议的
          client.connect((ipStr, int(portStr)))#连接ip和端口号!!!1:注意输入的端口号是str型而这里的要传入int型 #是服务器地址
          client.send(userStr.encode("utf-8"))

          ck = client
          t = threading.Thread(target=getInfo)
          t.start()


def getInfo(): #后续使用
          while True:
              data = ck.recv(1024)#用于接收服务器发送的信息
              text.insert(tkinter.INSERT, data.decode("utf-8"))#显示在信息框上


def send_content(signal):
          userStr = comboNO.get()
          sendStr = combo_abnormal.get()
          sendStr = userStr+ ":" +signal+":" + sendStr+"\n"
          ck.send(sendStr.encode("utf-8"))
      

photo1 = PhotoImage(file=os.getcwd()+".\\pic\\machine.png")
theLabel = Label(f1,justify=CENTER,image=photo1,compound=CENTER,fg="white")
theLabel.place(x=0,y=130,width=200,height=200)

photog = PhotoImage(file=os.getcwd()+".\\pic\\green.png")
photor = PhotoImage(file=os.getcwd()+".\\pic\\red.png")


buttonGeen=Button(f1,image=photog,command=cancel_red) 
buttonGeen.place(relx=0,rely=0.85)

buttonRed=Button(f1,image=photor,command=combine)
buttonRed.place(relx=0.66,rely=0.85)



f2=LabelFrame(root,text="信息传递",labelanchor="n")
f2.place(x=300,y=10,width=230,height=400)

labelName = Label(f2, text='机器编号').place(relx=0,rely=0.01,width=60,height=20)
labelIp = Label(f2, text='本机ip').place(relx=0,rely=0.1,width=40,height=20)
labelPort = Label(f2, text='port').place(relx=0,rely=0.2,width=40,height=20)
TermIp = Label(f2, text='终端ip').place(relx=0,rely=0.3,width=40,height=20)
labeltext = Label(f2, text='发送消息').place(relx=0.0,rely=0.5,width=60,height=30)

eip =Variable()
eip.set(get_local_ip())

eport = Variable()
eport.set("9999")

var_NO=["M001","M002","M003","M004","M005","M006","M007","M008"]


termhost=Variable()
termhost.set(get_local_ip())

var_abnormal=["机器不工作","尺寸超差","缺料"]

comboNO = tkinter.ttk.Combobox(f2,value=tuple(var_NO))
comboNO.place(relx=0.3,rely=0.01,width=150,height=20)
comboNO.set("M001")

combo_abnormal=tkinter.ttk.Combobox(f2,value=tuple(var_abnormal))
combo_abnormal.place(relx=0,rely=0.6,relwidth=0.99,height=20)
combo_abnormal.set("正常")

entryIp = Entry(f2, textvariable=eip).place(relx=0.3,rely=0.1,width=150,height=20)
entryPort = Entry(f2, textvariable=eport).place(relx=0.3,rely=0.2,width=150,height=20)
entryterm = Entry(f2, textvariable=termhost).place(relx=0.3,rely=0.3,width=150,height=20)


button = Button(f2, text="连接服务器", command=connectServer).place(relx=0.3,rely=0.8,width=100,height=30) #1启动服务器按钮
text = Text(f2, height=5, width=30)

root.mainloop()

服务端代码:

kinter
import socket, threading
import datetime
import time
import sqlite3
import os

root = tkinter.Tk()  # 创建主窗口
root.title('模拟服务器')
root.geometry("400x300+200+20")
root.resizable(0,0)
root.iconbitmap(".\\pic\\smart.ico")
users = {}#用户字典,也可以连接数据库


class lightFrame: #构造灯类,每个灯代表一台机器
    def __init__(self,name,pic,x,y):
        self.name=name
        self.pic=pic
        self.x=x-0.1
        self.y=y+0.4
        fx=tkinter.LabelFrame(root,text=self.name)
        fx.place(relx=self.x,rely=self.y,relwidth=0.2,relheight=0.23)
        self.photo0 = tkinter.PhotoImage(file=self.pic)
        theLabel = tkinter.Label(fx,image=self.photo0,fg="white")
        theLabel.pack()


def create_db(tablename):
          conn=sqlite3.connect(".\\db\\abnormal_log.db")
          c=conn.cursor()
          content="id INTEGER PRIMARY KEY AUTOINCREMENT ,Keyindate DATE,Machine TEXT,Signal TEXT,Description TEXT"   #拼接字段语句
          sql="CREATE TABLE IF NOT EXISTS"+chr(32)+tablename+chr(32) +"("+content+")"
          c.execute(sql)
          conn.commit()
          conn.close()
        

def insert_to_db(table_name,value):
          conn=sqlite3.connect(".\\db\\abnormal_log.db")
          c=conn.cursor()
          content="Keyindate,Machine,Signal,Description"
          sql="INSERT INTO"+chr(32)+ table_name +chr(32)+ "("+content+")"+"VALUES"+"("+value+")"
          #print(sql)
          c.execute(sql)
          conn.commit()
          conn.close()


def get_local_ip():  #获取当前计算机的IP地址
    local_ip = ""
    try:
        socket_objs = [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]
        ip_from_ip_port = [(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in socket_objs][0][1]
        ip_from_host_name = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1]
        local_ip = [l for l in (ip_from_ip_port, ip_from_host_name) if l][0]
    except (Exception) as e:
        print("get_local_ip found exception : %s" % e)
    return local_ip if("" != local_ip and None != local_ip) else socket.gethostbyname(socket.gethostname())
 
def run(ck, ca):
    userName = ck.recv(1024)#接收客户端发送的信息以1k作为单位这里接受到的信息为byte类型,收到用户名(发起用户)
    users[userName.decode("utf-8")] = ck#解码并储存用户的信息
    printStr = "" + userName.decode("utf-8") + "连接\n"#在连接显示框中显示是否连接成功
    text.insert(tkinter.INSERT, printStr)
    while True:
        rData = ck.recv(1024)#接收客户端发送的信息以1k作为单位这里接受到的信息为byte类型
        dataStr = rData.decode("utf-8")
        infolist = dataStr.split(":")  #将接收的内容分割
        text.insert(tkinter.INSERT,dataStr)
        
        date=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        value="'"+date+"','"+userName.decode("utf-8")+"','"+infolist[1]+"','"+infolist[2] +"'"
        create_db("abnormal_log")
        insert_to_db("abnormal_log",value)
        #print("ck",ck)       
        if infolist[1]=="N":
            if 0.2*int(userName.decode("utf-8")[3])<0.9:
                f=lightFrame(userName.decode("utf-8"),".\\pic\\red.png",0.2*int(userName.decode("utf-8")[3]),0) #M001[3]
            else:
                f=lightFrame(userName.decode("utf-8"),".\\pic\\red.png",0.2*int(userName.decode("utf-8")[3])-0.8,0.25)
        else:
            if 0.2*int(userName.decode("utf-8")[3])<0.9:
                  f=lightFrame(userName.decode("utf-8"),".\\pic\\green.png",0.2*int(userName.decode("utf-8")[3]),0)
            else:
                  f=lightFrame(userName.decode("utf-8"),".\\pic\\green.png",0.2*int(userName.decode("utf-8")[3])-0.8,0.25)  
   

def start():#3
    ipStr = eip.get()#从输入端中获取ip
    portStr = eport.get()#从输入端中获取端口,注意端口取得时候不能被占用(可以取8080,9876,等)
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#socked
    server.bind((ipStr, int(portStr)))#绑定ip和端口号
    server.listen(10)#设置监听,和设置连接的最大的数量
    printStr = "服务器启动成功\n"#,是否连接成功
    text.insert(tkinter.INSERT, printStr)#显示在信息窗口中
    while True:#这里用死循环是因为模拟的服务器要一直运行
        ck, ca = server.accept()
        t = threading.Thread(target=run, args=(ck, ca))
        t.start()


def startSever():
    s = threading.Thread(target=start)#启用一个线程开启服务器
    s.start()


labelIp = tkinter.Label(root, text='ip').place(relx=0.1,rely=0.01,width=30,height=20)
labelPort = tkinter.Label(root, text='port').place(relx=0.1,rely=0.1,width=30,height=20)
eip =tkinter.Variable()
eip.set(get_local_ip())
eport = tkinter.Variable()
eport.set("9999")
scr=tkinter.Scrollbar(root)
#scr.grid(row=7)
scr.place(relx=0.8,rely=0.2)

entryIp = tkinter.Entry(root, textvariable=eip).place(relx=0.2,rely=0.01,width=100,height=20)
entryPort = tkinter.Entry(root, textvariable=eport).place(relx=0.2,rely=0.1,width=100,height=20)

button = tkinter.Button(root, text="启动", command=startSever).place(relx=0.5,rely=0.03,width=60,height=30) #1启动服务器按钮


labeltext = tkinter.Label(root, text='连接消息').place(relx=0.05,rely=0.2,width=60,height=20)
text = tkinter.Text(root,yscrollcommand=scr.set)
text.place_configure(relx=0.2,rely=0.2,width=230,height=60)
'''text = tkinter.Text(root, height=5, width=5,yscrollcommand=scr.set)
text.grid(row=7, column=1)'''


root.mainloop()

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>