add send support
This commit is contained in:
48
data.json
48
data.json
@@ -1,10 +1,19 @@
|
|||||||
{
|
{
|
||||||
"Label": {
|
"Label":[
|
||||||
"name":"label-dtitle",
|
{
|
||||||
"text":"数据标题",
|
"name":"label-dtitle",
|
||||||
"column": 1,
|
"text":"数据标题",
|
||||||
"row": 1
|
"column": 1,
|
||||||
},
|
"row": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"label-dempty",
|
||||||
|
"text":" ",
|
||||||
|
"column": 8,
|
||||||
|
"colweight": 1,
|
||||||
|
"row": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
"Entry": {
|
"Entry": {
|
||||||
"name":"entry-dfile",
|
"name":"entry-dfile",
|
||||||
"bg":"gold",
|
"bg":"gold",
|
||||||
@@ -15,10 +24,10 @@
|
|||||||
"Text":{
|
"Text":{
|
||||||
"name":"text-dsetting",
|
"name":"text-dsetting",
|
||||||
"bg":"#cccccc",
|
"bg":"#cccccc",
|
||||||
"width":30,
|
"width":50,
|
||||||
"height":3,
|
"height":5,
|
||||||
"column": 1,
|
"column": 1,
|
||||||
"columnspan": 3,
|
"columnspan": 10,
|
||||||
"rowweight": 1,
|
"rowweight": 1,
|
||||||
"row": 2
|
"row": 2
|
||||||
},
|
},
|
||||||
@@ -29,11 +38,18 @@
|
|||||||
"column": 1,
|
"column": 1,
|
||||||
"row": 3
|
"row": 3
|
||||||
},
|
},
|
||||||
"Button":{
|
"Button":[
|
||||||
"name":"btn-dsave",
|
{
|
||||||
"text":"保存",
|
"name":"btn-dsend",
|
||||||
"column": 3,
|
"text":"发送",
|
||||||
"colweight": 1,
|
"column": 9,
|
||||||
"row": 3
|
"row": 3
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"name":"btn-dsave",
|
||||||
|
"text":"保存",
|
||||||
|
"column": 10,
|
||||||
|
"row": 3
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
58
scomm.json
58
scomm.json
@@ -8,7 +8,7 @@
|
|||||||
"Button":[
|
"Button":[
|
||||||
{
|
{
|
||||||
"name":"btn-scan",
|
"name":"btn-scan",
|
||||||
"text":"串口设置",
|
"text":"串口扫描",
|
||||||
"column": 1,
|
"column": 1,
|
||||||
"weight": 0,
|
"weight": 0,
|
||||||
"row": 1
|
"row": 1
|
||||||
@@ -68,6 +68,18 @@
|
|||||||
"row": 6
|
"row": 6
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"Canvas":[
|
||||||
|
{
|
||||||
|
"name":"canvas-led",
|
||||||
|
"text":"led",
|
||||||
|
"height":18,
|
||||||
|
"width":18,
|
||||||
|
"weight":0,
|
||||||
|
"sticky":"w",
|
||||||
|
"column": 6,
|
||||||
|
"row": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
"Label":[
|
"Label":[
|
||||||
{
|
{
|
||||||
"name":"empty-01",
|
"name":"empty-01",
|
||||||
@@ -98,6 +110,20 @@
|
|||||||
"column": 2,
|
"column": 2,
|
||||||
"row": 3
|
"row": 3
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"ckbtn-sendshow",
|
||||||
|
"text":"发送显示",
|
||||||
|
"sticky": "w",
|
||||||
|
"column": 3,
|
||||||
|
"row": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"ckbtn-time",
|
||||||
|
"text":"收发时间",
|
||||||
|
"sticky": "w",
|
||||||
|
"column": 4,
|
||||||
|
"row": 3
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"ckbtn-shex",
|
"name":"ckbtn-shex",
|
||||||
"text":"HEX发送",
|
"text":"HEX发送",
|
||||||
@@ -107,14 +133,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"ckbtn-0d",
|
"name":"ckbtn-0d",
|
||||||
"text":"追加\\r",
|
"text":"追送\\r",
|
||||||
"sticky": "w",
|
"sticky": "w",
|
||||||
"column": 3,
|
"column": 3,
|
||||||
"row": 4
|
"row": 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"ckbtn-0a",
|
"name":"ckbtn-0a",
|
||||||
"text":"追加\\n",
|
"text":"追送\\n",
|
||||||
"sticky": "w",
|
"sticky": "w",
|
||||||
"column": 4,
|
"column": 4,
|
||||||
"row": 4
|
"row": 4
|
||||||
@@ -183,7 +209,21 @@
|
|||||||
"name":"label-data",
|
"name":"label-data",
|
||||||
"text":"预置数据:",
|
"text":"预置数据:",
|
||||||
"column": 2,
|
"column": 2,
|
||||||
"row": 7
|
"row": 20
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"label-encoding",
|
||||||
|
"text":"数据编码:",
|
||||||
|
"column": 2,
|
||||||
|
"row": 30
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Entry":[
|
||||||
|
{
|
||||||
|
"name":"entry-encoding",
|
||||||
|
"width":10,
|
||||||
|
"column": 2,
|
||||||
|
"row": 31
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"Button":[
|
"Button":[
|
||||||
@@ -221,31 +261,31 @@
|
|||||||
"name":"btn-data01",
|
"name":"btn-data01",
|
||||||
"text":"data-01",
|
"text":"data-01",
|
||||||
"column": 2,
|
"column": 2,
|
||||||
"row": 8
|
"row": 21
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"btn-data02",
|
"name":"btn-data02",
|
||||||
"text":"data-02",
|
"text":"data-02",
|
||||||
"column": 2,
|
"column": 2,
|
||||||
"row": 9
|
"row": 22
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"btn-data03",
|
"name":"btn-data03",
|
||||||
"text":"data-03",
|
"text":"data-03",
|
||||||
"column": 2,
|
"column": 2,
|
||||||
"row": 10
|
"row": 23
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"btn-data04",
|
"name":"btn-data04",
|
||||||
"text":"data-04",
|
"text":"data-04",
|
||||||
"column": 2,
|
"column": 2,
|
||||||
"row": 11
|
"row": 24
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"btn-data05",
|
"name":"btn-data05",
|
||||||
"text":"data-05",
|
"text":"data-05",
|
||||||
"column": 2,
|
"column": 2,
|
||||||
"row": 12
|
"row": 25
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
187
scomm.py
187
scomm.py
@@ -1,15 +1,157 @@
|
|||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
import os,json
|
import os,sys,json
|
||||||
|
import serial
|
||||||
|
import serial.tools.list_ports
|
||||||
import tkgen.gengui
|
import tkgen.gengui
|
||||||
import tkinter
|
import tkinter
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
|
class UIproc():
|
||||||
|
def __init__(self, app):
|
||||||
|
self.root = app
|
||||||
|
self.combobox_port = self.root.get('cbbox-com')
|
||||||
|
self.entry_baud = self.root.get('entry-baud')
|
||||||
|
self.entry_split = self.root.get('entry-split')
|
||||||
|
self.entry_cycle = self.root.get('entry-cycle')
|
||||||
|
self.entry_encoding = self.root.get('entry-encoding')
|
||||||
|
self.entry_sendText = self.root.get('entry-sendText')
|
||||||
|
self.btn_onoff = self.root.get('btn-onoff')
|
||||||
|
self.canvas_led = self.root.get('canvas-led')
|
||||||
|
self.event_init()
|
||||||
|
def getSendData(self):
|
||||||
|
data = self.entry_sendText.var.get()
|
||||||
|
encoding = self.entry_encoding.var.get()
|
||||||
|
return data.encode(encoding, 'ignore')
|
||||||
|
def serial_open(self):
|
||||||
|
self.entry_baud.configure(state='disabled')
|
||||||
|
self.combobox_port.configure(state='disabled')
|
||||||
|
self.btn_onoff.configure(text='关闭串口')
|
||||||
|
root.get('canvas-led').create_oval(4,4,19,19,fill='green')
|
||||||
|
def serial_close(self):
|
||||||
|
self.entry_baud.configure(state='normal')
|
||||||
|
self.combobox_port.configure(state='normal')
|
||||||
|
self.btn_onoff.configure(text='打开串口')
|
||||||
|
root.get('canvas-led').create_oval(4,4,19,19,fill='red')
|
||||||
|
def read_serial_port(self):
|
||||||
|
return self.combobox_port.get()
|
||||||
|
def read_serial_baud(self):
|
||||||
|
return self.entry_baud.var.get()
|
||||||
|
def set_serial_port_list(self, portList):
|
||||||
|
currText = self.combobox_port.get()
|
||||||
|
_ports = []
|
||||||
|
for i in portList:
|
||||||
|
_ports.append(str(i[0]))
|
||||||
|
self.combobox_port['values'] = _ports
|
||||||
|
if currText in _ports:
|
||||||
|
self.combobox_port.set(currText)
|
||||||
|
else:
|
||||||
|
self.combobox_port.set(_ports[-1])
|
||||||
|
def log(self, s):
|
||||||
|
print('[todo.log]: %s'%s)
|
||||||
|
def event_init(self):
|
||||||
|
self.combobox_port.bind("<<ComboboxSelected>>", lambda x:self.log(self.combobox_port.get()))
|
||||||
|
|
||||||
|
|
||||||
|
class SerComm():
|
||||||
|
#root = None
|
||||||
|
|
||||||
|
def __init__(self, app):
|
||||||
|
self.ui = UIproc(app)
|
||||||
|
self.com = serial.Serial()
|
||||||
|
self.thread = None
|
||||||
|
self.alive = threading.Event()
|
||||||
|
self.setting = None
|
||||||
|
self.isDetectSerialPort = False
|
||||||
|
self.receiveProgressStop = True
|
||||||
|
self.sendCount = 0
|
||||||
|
self.recvCount = 0
|
||||||
|
|
||||||
|
def detectSerialPort(self):
|
||||||
|
if not self.isDetectSerialPort:
|
||||||
|
self.isDetectSerialPort = True
|
||||||
|
t = threading.Thread(target=self.detectSerialPortProcess)
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def openCloseSerial(self):
|
||||||
|
t = threading.Thread(target=self.openCloseSerialProcess)
|
||||||
|
t.setDaemon(True)
|
||||||
|
t.start()
|
||||||
|
|
||||||
|
def receiveData(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def sendData(self):
|
||||||
|
#try:
|
||||||
|
if True:
|
||||||
|
if self.com.is_open:
|
||||||
|
data = self.ui.getSendData()
|
||||||
|
if data and len(data) > 0:
|
||||||
|
self.com.write(data)
|
||||||
|
self.sendCount += len(data)
|
||||||
|
self.ui.log('%s: send data: %s' % (self.com.port,len(data)))
|
||||||
|
# scheduled send
|
||||||
|
#if self.sendSettingsScheduledCheckBox.isChecked():
|
||||||
|
# if not self.isScheduledSending:
|
||||||
|
# t = threading.Thread(target=self.scheduledSend)
|
||||||
|
# t.setDaemon(True)
|
||||||
|
# t.start()
|
||||||
|
#except Exception as e:
|
||||||
|
# self.ui.log('%s: send trace: %s' % (self.com.port,str(e)))
|
||||||
|
|
||||||
|
def openCloseSerialProcess(self):
|
||||||
|
try:
|
||||||
|
if self.com.is_open:
|
||||||
|
self.receiveProgressStop = True
|
||||||
|
self.com.close()
|
||||||
|
self.ui.serial_close()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.com.baudrate = int(self.ui.read_serial_baud())
|
||||||
|
self.com.port = self.ui.read_serial_port()
|
||||||
|
self.com.bytesize = 8
|
||||||
|
self.com.parity = 'N'
|
||||||
|
self.com.stopbits = 1
|
||||||
|
self.com.timeout = None
|
||||||
|
self.com.open()
|
||||||
|
self.ui.serial_open()
|
||||||
|
self.ui.log('%s: open success' % self.com.port)
|
||||||
|
self.receiveProcess = threading.Thread(target=self.receiveData)
|
||||||
|
self.receiveProcess.setDaemon(True)
|
||||||
|
self.receiveProcess.start()
|
||||||
|
except Exception as e:
|
||||||
|
self.com.close()
|
||||||
|
self.ui.serial_close()
|
||||||
|
self.receiveProgressStop = True
|
||||||
|
self.ui.log('%s: open failed: %s' % (self.com.port,str(e)))
|
||||||
|
except Exception as e:
|
||||||
|
self.ui.log('%s: openClose trace: %s' % (self.com.port,str(e)))
|
||||||
|
|
||||||
|
def findSerialPort(self):
|
||||||
|
self.port_list = list(serial.tools.list_ports.comports())
|
||||||
|
return self.port_list
|
||||||
|
|
||||||
|
def detectSerialPortProcess(self):
|
||||||
|
while(1):
|
||||||
|
portList = self.findSerialPort()
|
||||||
|
if len(portList)>0:
|
||||||
|
self.ui.log('detectSerialPort = %s' % len(portList))
|
||||||
|
self.ui.set_serial_port_list(portList)
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
self.isDetectSerialPort = False
|
||||||
|
|
||||||
|
def safe_exit(self):
|
||||||
|
self.com.close()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def open_wm_data(root,btn):
|
def open_wm_data(root,btn):
|
||||||
def _save_dfile():
|
def _save_dfile():
|
||||||
pass
|
pass
|
||||||
print('debug: toplevel=%s'%btn)
|
root.toplevel('data.json', title='预置数据').configure(bg='#e8e8e8')
|
||||||
root.toplevel('data.json', title='预置数据')
|
|
||||||
_cfg = root.usercfg.get(btn)
|
_cfg = root.usercfg.get(btn)
|
||||||
if _cfg:
|
if _cfg:
|
||||||
root.entry('entry-dfile').set(_cfg.get('title', btn))
|
root.entry('entry-dfile').set(_cfg.get('title', btn))
|
||||||
@@ -17,19 +159,19 @@ def open_wm_data(root,btn):
|
|||||||
root.checkbox('ckbtn-dhex').set(_cfg.get('hex') and 1 or 0)
|
root.checkbox('ckbtn-dhex').set(_cfg.get('hex') and 1 or 0)
|
||||||
root.button('btn-dsave', cmd=_save_dfile, focus=True)
|
root.button('btn-dsave', cmd=_save_dfile, focus=True)
|
||||||
def open_wm_pack(root,btn):
|
def open_wm_pack(root,btn):
|
||||||
print('debug: toplevel=%s'%btn)
|
pass
|
||||||
#root.toplevel('pack.json', title='组帧脚本')
|
#root.toplevel('pack.json', title='组帧脚本').configure(bg='#e8e8e8')
|
||||||
def open_wm_unpack(root,btn):
|
def open_wm_unpack(root,btn):
|
||||||
print('debug: toplevel=%s'%btn)
|
pass
|
||||||
#root.toplevel('unpack.json', title='解析脚本')
|
#root.toplevel('unpack.json', title='解析脚本').configure(bg='#e8e8e8')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
root = tkgen.gengui.TkJson('scomm.json', title='scomm串口调试助手')
|
root = tkgen.gengui.TkJson('scomm.json', title='scomm串口调试助手')
|
||||||
|
comm = SerComm(root)
|
||||||
|
# 读取用户数据文件
|
||||||
cfg_file = 'app.json'
|
cfg_file = 'app.json'
|
||||||
root.usercfg = json.load(open(cfg_file)) if os.path.isfile(cfg_file) else {}
|
root.usercfg = json.load(open(cfg_file)) if os.path.isfile(cfg_file) else {}
|
||||||
|
|
||||||
# 预置数据回调函数
|
# 预置数据回调函数
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
name = 'btn-data%02d'%(i+1)
|
name = 'btn-data%02d'%(i+1)
|
||||||
@@ -63,6 +205,29 @@ if __name__ == '__main__':
|
|||||||
btn.config(text=_cfg.get('title',name))
|
btn.config(text=_cfg.get('title',name))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
# UI相关设置
|
||||||
root.configure(background='#e8e8e8')
|
root.get('canvas-led').create_oval(4,4,19,19,fill='gray')
|
||||||
|
root.checkbox('ckbtn-rhex').set(0)
|
||||||
|
root.checkbox('ckbtn-shex').set(0)
|
||||||
|
root.checkbox('ckbtn-0d').set(0)
|
||||||
|
root.checkbox('ckbtn-0a').set(0)
|
||||||
|
root.checkbox('ckbtn-split').set(1)
|
||||||
|
root.checkbox('ckbtn-cycle').set(0)
|
||||||
|
root.checkbox('ckbtn-time').set(1)
|
||||||
|
root.checkbox('ckbtn-sendshow').set(1)
|
||||||
|
root.entry('entry-split').set('50')
|
||||||
|
root.entry('entry-cycle').set('1000')
|
||||||
|
root.entry('entry-baud').set('9600')
|
||||||
|
root.entry('entry-encoding').set('gbk')
|
||||||
|
root.entry('entry-sendText', key='<Return>', cmd=lambda x:comm.sendData()).set('')
|
||||||
|
root.button('btn-scan', cmd=lambda:comm.detectSerialPort())
|
||||||
|
root.button('btn-onoff', cmd=lambda:comm.openCloseSerial())
|
||||||
|
root.button('btn-send', cmd=lambda:comm.sendData())
|
||||||
|
# 其他设置
|
||||||
|
root.configure(bg='#e8e8e8')
|
||||||
|
root.lift() # 把主窗口置于最前面
|
||||||
|
#root.wm_state('zoomed') # 最大化窗口
|
||||||
|
root.protocol("WM_DELETE_WINDOW", lambda:comm.safe_exit())
|
||||||
|
# 启动任务
|
||||||
|
comm.detectSerialPort()
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|||||||
Reference in New Issue
Block a user