gpt4 book ai didi

python - Cherrypy 和 JSON Arduino Web 界面

转载 作者:太空宇宙 更新时间:2023-11-03 18:56:08 25 4
gpt4 key购买 nike

编辑#2:猜猜看,我就快到了!就编程而言,我面临的似乎是我的最后一个问题。这其实很有趣,我以前从未遇到过这样的事情。问题出在下面的代码中,我的 javascript 函数。我通常不会发布看起来很容易解决的问题,但我真的不知道这里发生了什么。

问题似乎出在更新功能的第一个条件上。查看alert('hey'); 行?好吧,如果我删除该行,由于某种未知的原因,什么都不会发送到操作函数。 Arduino、控制台也没有……什么也没有发生。这绝对是令人着迷的,我喜欢这样调用它。我不知道。我想也许alert()创建了某种读取arduino输出所必需的延迟,但是当我用setTimeout创建延迟时,也没有任何反应。太不可思议了。

再一次:如果没有警报,则不会调用操作函数,我通过让函数打印一些内容(如果调用了该函数)来进行检查。没有打印任何东西,什么也没有。只是没有被调用。但是有了警报,该函数就会被调用,并且 arduino 会打开 LED。

有什么解释吗?这是我的代码:

function update(command=0) {
// if command send it
if (command!=0) {
$.getJSON('/action?command='+command);
alert('hey');
}

// read no matter what
$.getJSON('/read', {}, function(data) {
if (data.state != 'failure' && data.content != '') {
$('.notice').text(data.content);
$('.notice').hide().fadeIn('slow');
setTimeout(function () { $('.notice').fadeOut(1000); }, 1500);
}
setTimeout(update, 5000);
});
}

update();

我正在尝试创建一个可从任何计算机访问的网络界面来控制我的 Arduino。我越来越近了。我的问题之一是,使用以下代码,当我按下按钮向 Arduino 发送命令时,Arduino 确实收到了它(LED 按照配置闪烁),然后发送一条消息,并且 Python 脚本确实检索数据,但无法正确显示。字符串丢失了一些字符,并且 index.html 未按预期返回。

基本上,按下按钮时会调用一个函数,并且我需要在与生成结果的函数不同的函数中返回该函数的结果。

这是代码:

# -*- coding: utf-8 -*-

import cherrypy, functools, json, uuid, serial, threading, webbrowser, time

try:
ser = serial.Serial('COM4', 9600)
time.sleep(2)
ser.write('1')
except:
print('Arduino not detected. Moving on')

INDEX_HTML = open('index.html', 'r').read()

def timeout(func, args = (), kwargs = {}, timeout_duration = 10, default = None):
class InterruptableThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.result = default
def run(self):
self.result = func(*args, **kwargs)

it = InterruptableThread()
it.start()
it.join(timeout_duration)
if it.isAlive():
return it.result
else:
return it.result

def get_byte(useless):
return ser.read().encode('Utf-8')

def json_yield(command):
@functools.wraps(command)
def _(self, command):
if (command == 'Turn the LED on'):
ser.write('2')
time.sleep(2)
print('wrote to port')
print('ok, ok')
try:
m = ''
while 1:
print('reading...')
byte = timeout(get_byte, ('none',), timeout_duration = 5)
if byte == '*' or byte == None: break
m = m + byte
content = m
time.sleep(1)
return json.dumps({'state': 'ready', 'content':content})
except StopIteration:
return json.dumps({'state': 'done', 'content': None})
return _

class DemoServer(object):
@cherrypy.expose
def index(self):
return INDEX_HTML

@cherrypy.expose
@json_yield
def yell(self):
yield 'nothing'

@cherrypy.expose
@json_yield
def command(self):
yield 'nothing'

if __name__ == '__main__':
t = threading.Timer(0.5, webbrowser.open, args=('http://localhost:8080',))
t.daemon = True
t.start()
cherrypy.quickstart(DemoServer(), config='config.conf')

最佳答案

首先,我并没有想过在你之前的问题中告诉你这一点,但不久前我写了一个名为 pyaler 的软件。这正是您想要的(除了它不支持长轮询请求,因为它是(曾经?)wsgi 限制)。

为了回答你的问题,为什么不让你的表单成为一个发送操作的 JavaScript 查询,并获取 JSON 格式的结果,你可以解析它并使用结果更新当前页面?这更加优雅、简单和 2013 年......

遗憾的是,根据您的代码,我无法真正说出为什么您没有得到结果。它太复杂了,无法理解它是否真的按照你想要的方式做...KISS!

避免在模块范围内执行任何操作,除非将其放入 if __name__ == "__main__" 中,或者当您想要通过导入模块来扩展模块时,您将顺便执行一些代码,它会迫使您对代码进行更好的设计。

您可以从超时函数中取出InterruptableThread() 类,并将default 作为参数。 InterruptableThread(default)def __init__(self, default): self.result = default。但说到那部分,为什么你明明得到了 timeout argument 却要做这么复杂的事情呢?您可以在创建串行连接时使用吗?

这是我对您的代码进行的轻微修改:

# -*- coding: utf-8 -*-

import cherrypy, functools, json, uuid, serial, threading, webbrowser, time

def arduino_connect(timeout=0):
try:
ser=serial.Serial('COM4', 9600, timeout=timeout)
time.sleep(2)
ser.write('1')
return ser
except:
raise Exception('Arduino not detected. Moving on')

class ArduinoActions(object):
def __init__(self, ser):
self.ser = ser

def get_data(self):
content = ""
while True:
print('reading...')
data = self.ser.read().encode('utf-8')
if not data or data == '*':
return content
content += data

def turn_led_on(self):
ser.write('2')
time.sleep(2)
print('wrote led on to port')

def turn_led_off(self):
ser.write('2') # Replace with the value to tur the led off
time.sleep(2)
print('wrote to led off port')

class DemoServer(ArduinoActions):
def __init__(self, ser):
ArduinoActions.__init__(self, ser)
with open('index.html', 'r') as f:
self.index_template = f.read()

@cherrypy.expose
def index(self):
return self.index_template

@cherrypy.expose
def action(self, command):
state = 'ready'
if command == "on":
content = self.turn_led_on()
elif command == "off":
content = self.turn_led_off()
else:
content = 'unknown action'
state = 'failure'
return {'state': state, 'content': content}

@cherrypy.expose
def read(self):
content = self.get_data()
time.sleep(1)
# set content-type to 'application/javascript'
return content

if __name__ == '__main__':
ser = arduino_connect(5)
# t = threading.Timer(0.5, webbrowser.open, args=('http://localhost:8080',))
# t.daemon = True
# t.start()
cherrypy.quickstart(DemoServer(), config='config.conf')

在您的 javascript 代码中,您调用的 yell 资源实际上不返回任何内容。您最好创建一个 action 方法(因为我修改了给定的 python 代码)和一个单独的 read() 方法。所以你的action方法将通过写入字节来作用于arduino,从而向arduino发出命令,并且read 方法将读取输出。

由于网络服务器可能会创建对串行对象上的读/写方法的并行调用,并且你不能并行读取同一个对象,你可能想通过创建一个独立的线程一个继承自 threading.Thread 的新类,您可以实现读取输出的无限循环串行的(通过将串行对象作为参数提供给该类的 __init__ 函数)。然后,如果您想保留所有以前的数据的日志,则可以将每个新的 content 数据推送到 list 中,或者如果您只想返回最后一个读数,则为 Queue.Queue。然后从 ArduinoActions 中的 read() 中方法,您只需要返回该列表,该列表将随着 arduino 的任何新读数而增长,并且因此,记录所有数据(或者如果有队列,则获取最后的数据)。

$(function() {
function update(command) {
// if you give a command argument to the function, it will send a command
if (command) {
$.getJSON('/action?command='+command);
}
// then it reads the output
$.getJSON('/read, {}, function(data) {
if (data.state !== 'failure' && data.content !== '') {
$('.notice').text(data.content);
$('.notice').hide().fadeIn('fast');
setTimeout(function () { $('.notice').fadeOut('fast'); }, 1500);
}
// and rearms the current function so it refreshes the value
setTimeout(update(), 2); // you can make the updates less often, you don't need to flood your webserver and anyway the arduino reading are blocking
});
}
update();
});

在 JavaScript 中始终使用 ===!==,这样类型就不会被强制。您可以较少地再次调用该函数如果您不评估 JavaScript 参数,则默认情况下它将设置为未定义。

这只是您所写内容的一点更新,现在已经很晚了,所以我希望您能从中做出一些好东西!

HTH

关于python - Cherrypy 和 JSON Arduino Web 界面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17218925/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com