Showing sensor reading in a django website

£可爱£侵袭症+ 提交于 2020-02-03 02:32:51

问题


I want to design a web based application for showing sound sensor readings, collected from an Arduino based setup (and also show some analysis results). For making my arduino setup work I had developed a python program named 'ard_sensor_project.py' which collects readings and store in .csv file and create a graph.

Now I want to display the readings generated in a django website. For that I have imported 'ard_sensor_project.py' in views.py of my django site and called a method to print the sensor reading at real time.

But on running the program, it seems that though the reading collecting module has started, the site has not started yet and I can neither see the web page nor any reading.

Is there any way such that I can show the readings on the django site?

Here is my ard_sensor_project.py

import matplotlib.pyplot as plt
from datetime import datetime

#necessary declarations
sr = serial.Serial("COM6",9600)

#self declared methods

def getsensordata():
    st = list(str(sr.readline(),'utf-8'))
    return int(str(''.join(st[:])))


def storedata(fname,val1,val2):
    #stores data in a .csv file, will update if required

def plotgraph():
    #method for plotting data in a matplotlib graph, will update if required


#codes as part of main execution + function calls

print("------Reading collection starts now------")

while True:
    try:
        timeNow = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
        storedata('op.csv', timeNow, getsensordata())
        #plotgraph()

    except KeyboardInterrupt:
        break

sr.close()
print("------Reading collection ends successfully------")

Here is views.py of my django site

from django.shortcuts import render

# Create your views here.

from django.template.loader import get_template
from django.http import HttpResponse
from . import ard_sensor_project as ard

def index(request):
    return render(request,'start.html',{'noise_level':ard.getsenordata})

My runtime output :

So it seems that the server is not at all running. When I replace ard.getsensordata by 0 (also removing ard import), I get :

Now instead of 0, I want the reading. How should I proceed?


回答1:


In a context of a web application, I think your data collection program must have a different philosophy.

You see the print("------Reading collection starts now------") because all you top level code is executed when you import your module with from . import ard_sensor_project as ard

It prints the message but it also opens the serial port and start the while True infinite loop.

The web server and this loop are in the same thread. So the server will not start until the loop ends.

You may have different strategy

1) If reading from the Arduino is fast and you just have one user accessing

You can reorganize your module and put all the data reading stuff in a function

def getsensordata():
    print("------Reading collection starts now------")
    sr = serial.Serial("COM6",9600)
    st = list(str(sr.readline(),'utf-8'))
    sr.close() 
    print("------Reading collection ends successfully------")
    return int(str(''.join(st[:])))

Then your django view can call this function

from . import ard_sensor_project as ard

def index(request):
    return render(request, 'start.html', {'noise_level':ard.getsenordata()})

Note that your forgot the () after ard.getsenordata in your example and if so, the function is not called

When you access your index view, the ard.getsenordata is called, the data is read from the Arduino and put in your context. You can display in correctly in the start.html template

2) If reading from the Arduino is fast and you want the data to be automatically updated, and you still have one user accessing

In the previous example, the data is just read when the page is displayed. If you want to refresh it, you need to refresh the page on your browser.

If you want an automatic update of the data, you need to implement something with ajax

from . import ard_sensor_project as ard

def index(request):
    return render(request, 'start.html', {})

def ajax_data(request):
    data = {'noise_level':ard.getsenordata()}
    json_data = json.dumps(data)
    return Response(json_data, mimetypes='application/json')

Then in your start.html, you need to implement a javascript function that will call this ajax_data view with AJAX on periodic basis

3) If reading from the Arduino is not fast or if you have several user accessing

The previous codes assume that reading from Arduino is fast. Your view will wait for the reading to end before sending a response.

If you have several people accessing the same page, you will have to implement a lock on the getsensordata otherwise the reading may fail.

Then, I would recommend to use another strategy by using a Database.

You can develop an external program with collects the data on a periodic basis and store it into a database. It might be a good idea to develop it as a Django command See the docs and then to be able to access the database through Django ORM.

For exemple if you have defined a MyNoiseLevelModel model

class Command(BaseCommand):
    def handle(self, *args, **options):
         while True:
         try:
              now = datetime.now()
              noise_level = getsenordata()
              MyNoiseLevelModel.objects.create(timestamp=now(), value=noise_level)
              # maybe wait a little bit here
              # time.sleep(1) # 1 sec
         except KeyboardInterrupt:
              break

Then you can run this command in parallel of your web server. It collects the data and you can get it in your view

def index(request):
    return render(request, 'start.html', {})

def ajax_data(request):
    values = MyNoiseLevelModel.objects.all().values('value')
    json_data = json.dumps(data)
    return Response(json_data, mimetypes='application/json')


来源:https://stackoverflow.com/questions/49170851/showing-sensor-reading-in-a-django-website

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!