问题
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