python - Python 3.7.1 ANT+ TKinter - 在 Tkinter 中显示来自 ANT+ 设备的实时数据
问题描述
与我昨天的问题相关(在这里),我尝试使用Bissont创建的 fork来实现这个python-ant 存储库。我尝试将他的电源演示用于 tacx bushido 智能训练器,因为这与我使用的设备相同。我稍微修改了代码以适合我的 Suunto ANT+ 接收器,并在控制台中运行它,代码工作正常。现在我尝试在 TKinter 环境中实现它以显示从 ANT+ 设备接收到的实时数据,但最终出现以下错误代码并且 Tkinter 窗口不再打开:
Traceback(最近一次调用最后一次):文件“/usr/local/lib/python3.5/dist-packages/ant-0.1.1-py3.5.egg/ant/core/node.py”,第 212 行,在启动 self.reset(wait) 文件“/usr/local/lib/python3.5/dist-packages/ant-0.1.1-py3.5.egg/ant/core/node.py”,第 197 行,重置evm.waitForMessage(message.StartupMessage) 文件“/usr/local/lib/python3.5/dist-packages/ant-0.1.1-py3.5.egg/ant/core/event.py”,第 163 行,在waitForMessage 返回 self.msg.waitFor(class_, timeout) 文件 "/usr/local/lib/python3.5/dist-packages/ant-0.1.1-py3.5.egg/ant/core/event.py",第 114 行,在 waitFor 中引发 MessageTimeoutError("%s: timeout" % str(foo), internal=foo) ant.core.exceptions.MessageTimeoutError: : timeout
在处理上述异常的过程中,又出现了一个异常:
Traceback(最近一次调用最后):文件“/home/pi/python-ant/demos/ant.core/ANT+power.py”,第 47 行,在 antnode.start() 文件“/usr/local/lib/python3 .5/dist-packages/ant-0.1.1-py3.5.egg/ant/core/node.py",第 217 行,开始引发 NodeError(err) ant.core.exceptions.NodeError: : timeout
所以这是(最终程序)应该做的:
- 接收和存储 ANT 数据
- 将数字四舍五入到小数点后 2-3 位(最大)
- 从文件中读取到目前为止的总功率输出
- 将功率数据写入文件(附加)
- 总输出功率之和
- 显示当前速度、踏频、功率和总功率输出
到目前为止,这是我的代码:
# imports
import random
import time
from tkinter import *
from ant.core import driver
from ant.core.node import Node, Network, ChannelID
from ant.core.constants import NETWORK_KEY_ANT_PLUS, NETWORK_NUMBER_PUBLIC
from ant.plus.power import *
from config import *
# creating root tkinter Window
root = Tk()
root.title("TacX Bushido ANT+ Live Data")
# defining text variables
running = 0
SAVE_FILE = "power_doc.txt"
HEADLINE_TEXT = StringVar()
HEADLINE_TEXT.set('Headline')
HEADLINE_M= StringVar()
HEADLINE_M.set('M')
power_display = StringVar()
power_display.set('0')
cadence_display = StringVar()
cadence_display.set('0')
speed_display = StringVar()
speed_display.set('0')
powertotal_display = StringVar()
powertotal_display.set('0')
# defining ANT variables
device = driver.USB2Driver(log=LOG, debug=DEBUG, idProduct=0x1008)
antnode = Node(device)
antnode.start()
network = Network(key=NETWORK_KEY_ANT_PLUS, name='N:ANT+')
antnode.setNetworkKey(NETWORK_NUMBER_PUBLIC, network)
# defining Window Size
root.geometry("800x600")
# creating Label Frame to wrap labels
frame = LabelFrame(root)
frame.pack(padx=20, pady=20)
# creating labels, Headline 1
Mlabel = Label(root, font = ("Helvetica",48) ,textvariable = HEADLINE_M, justify=CENTER, bg="#FFFFFF", fg = '#000000')
Mlabel.pack(fill=BOTH, padx=20, pady=10)
# headline 2
headLine = Label(root, font=("Helvetica", 26), textvariable= HEADLINE_TEXT, justify=CENTER, bg="#FFFFFF", fg = '#000000')
headLine.pack(fill=BOTH, pady=5)
# power
l1 = Label(root, font = ("Helvetica",20) ,textvariable = power_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l1.pack(fill=BOTH)
# cadence
l2 = Label(root, font = ("Helvetica",20), textvariable = cadence_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l2.pack(fill=BOTH)
# speed
l3 = Label(root, font = ("Helvetica",20), textvariable = speed_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l3.pack(fill=BOTH)
# total Power
l4 = Label(root, font = ("Helvetica",20), textvariable = powertotal_display, justify=CENTER, bg="#190000", fg = '#B0C4C2')
l4.pack(fill=BOTH)
# function to read total power values out of a file
def get_power_total(SAVE_FILE):
power_total = 0
with open(SAVE_FILE, 'r') as inp:
for line in inp:
try:
num = float(line)
power_total += num
except ValueError:
print('{} is not a number!'.format(line))
power_total = round_number(power_total)
return power_total
# rounds numbers to 2 decimals
def round_number(inputNumber):
inputNumber = round(inputNumber, 2)
return inputNumber
# use formula for a 28" Wheel to determine Speed using cadence
def determine_speed(cadence):
speed = float(cadence)*0.356
speed = round_number(speed)
return speed
# write in document to determine total power output
def write_file(SAVE_FILE, power):
f = open(SAVE_FILE, "a+")
f.write(str(power) + '\n')
f.close()
# updates label
def update_label(power, cadence):
power_total = get_power_total(SAVE_FILE)
speed = determine_speed(cadence)
power_total += power
write_file(SAVE_FILE, power)
power_display.set("Power: {} W".format(power))
cadence_display.set("Cadence: {}".format(cadence))
speed_display.set("Speed : {} Km/h".format(speed))
powertotal_display.set("Total Power Output: {} W".format(power_total))
root.after(1000, power_data)
root.update_idletasks()
# find device
def device_found(self, device_number, transmission_type):
print("Detect monitor device number: %d, transmission type: %d" % (device_number, transmission_type))
# determine power
def power_data(eventCount, pedalDiff, pedalPowerRatio, cadence, accumPower, instantPower):
update_label(instantPower, cadence)
power = BicyclePower(antnode, network, callbacks = {'onDevicePaired': device_found,
'onPowerData': power_data})
# Unpaired, search:
power.open()
monitor = None
while True:
try:
time.sleep(1)
except KeyboardInterrupt:
break
power.close()
antnode.stop()
# mainloop to display the window
root.after(1000, power_data)
root.mainloop()
我已经知道 while True 语句将阻止我的 Tkinter 窗口打开,直到找到一个设备,这是低于标准的,但我没有想出一个更好的方法来让它保持原样。
任何建议,帮助或任何受到高度赞赏的东西。
提前干杯!
编辑(对于任何对同一主题感兴趣或陷入困境的人):在进一步检查库之后,我发现 power.open() 创建了一个无限循环的回调,这导致 root.mainloop() 永远无法到达。我还没有找到一种方法来干扰回调循环以获取数据,将其显示在主循环中并继续执行回调循环。找到后,我将尝试提供更多信息和可能的解决方案。如果您对此有想法或不同的方法,请随时贡献:)
编辑 2:由于 ANT+ 模块本身读取和写入数据,一种方法可能是写入文件并让另一个脚本从文件中读取数据。但是,我不知道这在 python 中是否可行(类似于 readonly-mode 而不会阻止来自其他来源的访问)。
编辑 3:问题已解决:将脚本分成两部分(单独的脚本)。第一个脚本:读取 ANT+ 数据并将其写入如下文件:
def write_file(SAVE_FILE, power):
f = open(SAVE_FILE, "w")
f.write(str(power) + '\n')
f.close()
第二个脚本:只读数据和赋值,像这样:
def readFile():
file = open("ultimateFile.txt", "r")
VALUE = file.readline()
file.close()
return VALUE
我将在 2019 年更新代码/脚本并将更新的代码/脚本上传到 github。
解决方案
推荐阅读
- spring-boot - 禁用不需要的 OAuth 端点 spring boot
- reactjs - 如何在我的反应组件中添加验证消息
- vba - For-Next 循环没有停止
- ios - Swift ios 从视图中切出圆角矩形,允许颜色变化
- sapui5 - 带有文本换行的 sap.ui.table.table(渲染问题)
- typescript - 在 Typescript 中将静态转换为动态导入
- reactjs - 编辑使用“yarn build”构建的 reactapp 结果中的字符串而不重建
- javascript - 在带有 ion-item 的 NTH 元素之后添加项目
- html - 将进度条引导程序 4(居中值)与按钮对齐
- rust - 夜间使用 rust 时无法安装 xargo -“属性中的非字符串文字或顶级位置的字符串文字是实验性的”