首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有烧瓶的Ajax在网页上实时更新传感器数据

带有烧瓶的Ajax在网页上实时更新传感器数据
EN

Stack Overflow用户
提问于 2020-01-17 01:19:09
回答 1查看 2.4K关注 0票数 1

我一直试图让这个烧瓶服务器用一个循环生成的数据更新自己,该循环运行在.py脚本上,用户通过网页上的按钮调用该循环。我一直在研究推荐的解决方案,并看到websockets (sockets.io)、ajax、nodejs出现了。我知道我需要在我的项目中实现某种形式的js,ajax看起来是最简单的(所以我认为)。我在python中只有大约3周的编程经验。主要是我寻找接近我想要的例子,然后尝试修改它以适应我的需要,但没有找到任何我正在寻找的例子。即使如此,我对编程的总体新鲜感意味着,我“套用”的例子越多,我就越有可能降低我已经完成的工作的总体结构。

目标

目标是更新显示在页面上的值,而不需要重新加载,而是让js每秒钟更新一次值。该值是从我的x=x+1文件中的一个.py计数器生成的。这将取代传感器输入收集从我的Rpi稍后。

实际结果

当我运行当前代码时,

  1. 我的html元素会被双发,所以我看到了我在index.html文件中放置了两次的内容,尽管第二个按钮元素实际上并不响应单击,
  2. 在我的终点站窗口,我也得到了无数的帖子。
  3. 单击按钮元素不再在.py文件中执行我的循环,而是显示“不允许的方法”。

我试过什么

我尝试在我的html文件中实现setTmeout,作为每秒钟调用python应用程序并获得更新值( x=x+1)的一种方法。我读过关于使用setTimeout作为使用setInterval处理问题的方法的文章。由于我看到ajax调用的使用方式多种多样,学习资源主要是针对表单、数据库和聊天应用程序构建的,所以我的大部分搜索并没有给我带来任何新的经验教训。我目前正在做ajax教程,希望能得到一些我可以使用的东西,任何帮助都将不胜感激。

ajaxTest.py我的python烧瓶文件

代码语言:javascript
复制
import threading
import time
from flask import Flask, render_template, jsonify, request
import RPi.GPIO as GPIO
import datetime
from datetime import datetime
from datetime import timedelta
app = Flask(__name__)

bioR_on = False
ledGrnSts = 0
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
air = 21
light = 20
waste = 16
feed = 12
water = 26
pinList = [21,20,16,12,26] 

def pump(pin):
        GPIO.output(pin, GPIO.LOW)
        print(pin,'on')
        time.sleep(1)
        GPIO.output(pin, GPIO.HIGH)
        print(pin, 'off')
        time.sleep(1)

def on(pin):
    GPIO.output(pin, GPIO.LOW)

@app.route("/")
def index(): 
    templateData = {
              'title' : 'Bioreactor output Status!',
              'ledGrn'  : ledGrnSts,
        }
    return render_template('index.html', **templateData)

@app.route('/<deviceName>/<action>', methods = ["POST"])
def start(deviceName, action):
    # script for Pi Relays
    def run():
        if action == "on":
            alarm = datetime.now() + timedelta(seconds =10)
            global bioR_on
            bioR_on = True

            while bioR_on:

                tday = datetime.now()
                time.sleep(1)
                #feed(tday, alarm)
                x=x+1
                return jsonify(x)
                GPIO.setmode(GPIO.BCM)

                for i in pinList:
                    GPIO.setup (i, GPIO.OUT)
                    GPIO.output(i, GPIO.HIGH)
                on(air)
                on(light)
                print(tday)
                if tday >= alarm:
                    print('alarm activated')
              #  run = False
                    pump(waste)
                    print('waste activated')
                    pump(feed)
                    print('feed on')
                    GPIO.cleanup()
                    alarm = datetime.now() + timedelta(seconds =10)
                    print('next feeding time ', alarm)
                    time.sleep(1)
        if action == 'off':
            bioR_on = False
            #return "off"
            GPIO.cleanup()

    thread = threading.Thread(target=run)
    thread.start()

    templateData = {
            'ledGrn'  : ledGrnSts,
    }
    return render_template('index.html', **templateData)


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80, debug=True, threaded=True)

我的index.html文件

代码语言:javascript
复制
<!DOCTYPE html>
   <head>
      <title>BioReactor Control</title>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <link rel="stylesheet" href='../static/style.css'/>
   </head>
   <body>
        <h1>Actuators</h1>
        <h2> Status </h2>
        <h3> GRN LED ==>  {{ ledGrn  }}</h3>
        <br>
        <h2> Commands </h2>
        <h3> 
            Activate Bioreactor Ctrl ==> 
            <a href="/bioR/on" class="button">TURN ON</a>  
            <a href="/bioR/off"class="button">TURN OFF</a>
        </h3>
        <h3>
            Current Count 
        </h3>
        <p id="demo"></p>
        <script>
                    setTimeout($.ajax({
                        url: '/<deviceName>/<action>',
                        type: 'POST',
                        success: function(response) {
                            console.log(response);
                            $("#num").html(response);
                        },
                        error: function(error) {
                            console.log(error);
                        }
                    }), 1000);


        </script>
        <h1>Output</h1>
        <h1 id="num"></h1>
   </body>
</html>

结果图

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-17 02:56:05

我创建了最少的代码,它使用AJAX每1秒获得一次新值。

我使用setInterval每1秒重复一次。我还使用function(){ $.ajax ... }创建函数,该函数不会立即执行,但setInterval将每1秒调用一次。在没有function(){...}代码的情况下,$.ajax在开始时被执行,它的结果被用作函数,每1秒执行一次--但是它什么也不返回--所以最后它只更新了一次值(在开始时),然后setInterval没有运行。

我增加了当前的时间,看看它是否还在运行。

buttons运行函数'/<device>/<action>',启动和停止线程,但AJAX使用/update获取当前值。

我使用render_template_string将所有代码都放在一个文件中,这样其他人就可以轻松地复制和测试它。

我把HTML降到了最小。为了确保我把<h1>放在脚本之前,脚本需要这些标记。

我没有用global=True测试它,它可能在新线程中运行,而且可能会产生问题。

代码语言:javascript
复制
from flask import Flask, request, render_template_string, jsonify
import datetime
import time
import threading

app = Flask(__name__)

running = False # to control loop in thread
value = 0       

def rpi_function():
    global value

    print('start of thread')
    while running: # global variable to stop loop  
        value += 1
        time.sleep(1)
    print('stop of thread')


@app.route('/')
@app.route('/<device>/<action>')
def index(device=None, action=None):
    global running
    global value

    if device:
        if action == 'on':
            if not running:
                print('start')
                running = True
                threading.Thread(target=rpi_function).start()
            else:
                print('already running')
        elif action == 'off':
            if running:
                print('stop')
                running = False  # it should stop thread
            else:
                print('not running')

    return render_template_string('''<!DOCTYPE html>
   <head>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
   </head>
   <body>
        <a href="/bioR/on">TURN ON</a>  
        <a href="/bioR/off">TURN OFF</a>
        <h1 id="num"></h1>
        <h1 id="time"></h1>
        <script>
            setInterval(function(){$.ajax({
                url: '/update',
                type: 'POST',
                success: function(response) {
                    console.log(response);
                    $("#num").html(response["value"]);
                    $("#time").html(response["time"]);
                },
                error: function(error) {
                    console.log(error);
                }
            })}, 1000);
        </script>
   </body>
</html>
''')

@app.route('/update', methods=['POST'])
def update():
    return jsonify({
        'value': value,
        'time': datetime.datetime.now().strftime("%H:%M:%S"),
    })

app.run() #debug=True
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59780007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档