When measuring temperature with Raspberry Pi and acquiring sensor status with GPIO, it is convenient to be able to debug with the software alone. Therefore, I created a debug environment that simulates the acquisition of sensor status by temperature measurement and GPIO and displays it on the website (created with Flask). Save the simulated temperature and sensor state in SQLite and refresh the page via Ajax. Since it is difficult to understand from the values of temperature and sensor status, it looks as if the temperature of the living room and the sensor have changed.
No breadboard or wiring is required in this environment. It is not suitable for temperature measurement and sensor status acquisition that require real-time performance. We assume an environment where the temperature only needs to be known at 30-second intervals.
--The temperature and sensor status arrows are updated.
--Here, create a Sensor folder and install the environment with pipenv. --Installation of pipenv and Web server (Nginx, uWSGI, etc.) is omitted.
$ mkdir Sensor
$ cd Sensor
$ pipenv install --python 3.7.2
$ pipenv install flask
$ pipenv install sqlalchemy
$ pipenv shell
--Create the following folders and files. --jQuery downloads the appropriate version from jQuery. --Download the arrow icon (On / Off) from [Free Icon] Arrow (up / down / left / right). --The background can be downloaded from Cute Free Material Collection Irasutoya.
└ Sensor/
├ server.py
├ app/
│ ├ app.py
│ └ static/
│ │ ├ css/
│ │ │ └ sample.css
│ │ ├ img/
│ │ │ ├ arrow_on.png #Arrow when on
│ │ │ ├ arrow_off.png #Arrow when Off
│ │ │ └ bg_house_living.jpg #background image
│ │ ├ jquery/
│ │ │ └ jquery-3.4.1-min.js
│ │ └ js/
│ │ └ sample.js
│ └ templates/
│ └ index.html
├ models/ #SQLite3 definition
│ ├ __init__.py
│ ├ database.py
│ └ models.py
└ output_log/ #Background execution log folder
--Init_db () initializes the Database. (Only executed if the * .db file does not exist)
server.py
# -*- coding: utf-8 -*-
from flask import Flask
from app.app import app
from models.database import init_db
if __name__ == "__main__":
#Database initialization
init_db()
#Launch the app(host=0,0,0,0 for all permissions)
app.run(host='0.0.0.0', debug=True)
--Simulate temperature and sensor every 3 seconds. --The temperature is simulated at 25 degrees + α. --The sensor simulates with 0 or 1.
(reference) How to execute in Python at regular intervals and verification
sensor.py
# -*- coding: utf-8 -*-
import time
import threading
import random
from models.models import SensorCurrent
from models.database import db_session
from datetime import datetime
#Periodic execution processing
def schedule():
#Temperature simulation(25 degrees+α)
now = time.time()
temp = 25 + now % 5 + (now / 10) % 10
#Truncate to two decimal places
str = "{0:.2f}".format(temp)
temp = float(str)
#Sensor state simulation(0 or 1)
sensor = random.randint(0, 1)
#Current data update
current = SensorCurrent.query.first()
current.temp1 = temp
current.sensor1 = sensor
db_session.commit()
db_session.close()
#Periodic execution setting processing
def scheduler(interval, f, wait = True):
base_time = time.time()
next_time = 0
while True:
t = threading.Thread(target = f)
t.start()
if wait:
t.join()
next_time = ((base_time - time.time()) % interval) or interval
time.sleep(next_time)
if __name__ == "__main__":
#Periodic execution setting(3 second intervals)
scheduler(3, schedule, True)
--Describe website display and Ajax processing.
/app/app.py
# -*- coding: utf-8 -*-
from flask import Flask,render_template,request, json, jsonify
from models.models import SensorCurrent
app = Flask(__name__)
#Website display processing
@app.route("/")
def index():
#Get current temperature and sensor data from SQlite
data = SensorCurrent.query.first()
return render_template("index.html",sensor=data)
#Ajax processing
@app.route("/currdata", methods=['POST'])
def getCurrData():
#Get current temperature and sensor data from SQlite
data = SensorCurrent.query.first()
#Convert to JSON and return the result
json_data = {
'sensor1': data.sensor1,
'temp1': data.temp1
}
return jsonify(Result=json.dumps(json_data))
if __name__ == "__main__":
app.run(debug=True)
--Define the SQLite3 database (sensor.db).
models/database.py
# -*- coding: utf-8 -*-
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
import os
#Database file settings
databese_file = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'sensor.db')
engine = create_engine('sqlite:///' + databese_file, convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,autoflush=False,bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()
#Database initialization
def init_db():
import models.models
Base.metadata.create_all(bind=engine)
--Define the temperature and current sensor data table (currdata).
models/models.py
# -*- coding: utf-8 -*-
from sqlalchemy import Column, Integer, Float, String, Text, DateTime
from models.database import Base
from datetime import datetime
#Current data table definition for temperature and sensor
#Here is one temperature data,Save one sensor data
#Please set the table definition as appropriate
class SensorCurrent(Base):
__tablename__ = 'currdata'
id = Column(Integer, primary_key=True)
name = Column(String(128))
temp1 = Column(Float)
sensor1 = Column(Integer)
date = Column(DateTime, default=datetime.now())
def __init__(self, name=None, temp1=None, sensor1=None, date=None):
self.name = name
self.temp1 = temp1
self.sensor1 = sensor1
self.date = date
def __repr__(self):
return '<Name %r>' % (self.name)
--The current data is acquired and displayed at startup. (The arrow defaults to Off) --Use Ajax to get the current data every 2 seconds and rewrite the page.
app/templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>{{sensor.name}}</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../static/css/sample.css">
<script src="../static/jquery/jquery-3.4.1.min.js"></script>
<script src="../static/js/sample.js"></script>
</head>
<body>
<h1 id="h1_temp1">Temp : {{sensor.temp1}}</h1>
<h1 id="h1_sensor1">Sensor : {{sensor.sensor1}}</h1>
<div class="sample-box">
<img class="sample-box-bg" src="../static/img/bg_house_living.jpg " alt="">
<div class="sample-sensor">
<img class="sample-sensor-img" id="sensor1" src="../static/img/arrow_off.png " alt="">
</div>
<div id="temp1" class="sample-tempareture">
</div>
</div>
</body>
<script>
setInterval(function () {
getcurrdata();
}, 2000);
</script>
</html>
--Get the current data using Ajax.
app/static/js/sample.js
//Current data acquisition
function getcurrdata() {
$.ajax({
type: 'POST',
url: '/currdata',
data: '',
contentType: 'application/json'
})
.done( (data) => {
//Successful data acquisition
console.log("success");
//Extract data from JSON
var json_data = JSON.parse(data.Result);
const sensor1 = json_data.sensor1;
const temp1 = json_data.temp1;
//Temperature setting in the background image
$("#temp1").html(temp1 + "℃");
//Temperature setting(For confirmation)
$("#h1_temp1").html("Temp : " + temp1);
//Sensor image settings
if (sensor1 == 0) {
$("#sensor1").attr("src", "../static/img/arrow_off.png ");
} else {
$("#sensor1").attr("src", "../static/img/arrow_on.png ");
}
//Sensor settings(For confirmation)
$("#h1_sensor1").html("Sensor : " + sensor1);
})
.fail( (data) => {
//Data acquisition failure
console.log("error");
});
}
――It easily supports responsive design.
app/static/css/sample.css
@charset "utf-8";
@media screen and (min-width: 481px) {
.sample-box {
position: relative;
display:inline-block;
}
.sample-box-bg {
}
.sample-sensor {
position: absolute;
left: 60%;
top: 5%;
}
.sample-sensor-img {
}
.sample-tempareture {
position: absolute;
top: 35%;
left: 55%;
color: RED;
font-size: 36px;
}
}
@media screen and (max-width: 480px) {
.sample-box {
position: relative;
display:inline-block;
}
.sample-box-bg {
width: 100%;
}
.sample-sensor {
position: absolute;
left: 60%;
top: 5%;
}
.sample-sensor-img {
width: 70%;
height: 70%;
}
.sample-tempareture {
position: absolute;
top: 35%;
left: 55%;
color: RED;
font-size: 22px;
}
}
Learn from simulating temperature and sensors to displaying websites.
--Initial values of temperature and sensor (only one) are added to the currdata table. --Start python in the Sensor folder and execute the following source code. --You only need to execute it once.
$ python
from models.database import db_session
from models.models import SensorCurrent
data = SensorCurrent("sample",25.3, 0)
db_session.add(data)
db_session.commit()
exit()
--From the Sensor folder, launch an app that simulates temperature and sensors in the background. --I run it in the background because I want to run it at the same time as the server app.
#Run in the following folder
(Sensor) pi@raspberrypi:~/Sensor $
#Execute the following command
nohup python sensor.py > ./output_log/out.log &
--If you have already started the simulation, kill the process before starting it.
#Find the process running python
$ ps aux | grep python
pi 22965 0.7 2.0 32200 19176 pts/2 S 16:43 0:27 python sensor.py
# sensor.kill py process
$ kill -9 (sensor.py process id->22965 here)
--Start the server main process.
#Run in the following folder
(Sensor) pi@raspberrypi:~/Sensor $
#Execute the following command
python server.py
--Start your browser and access http://127.0.0.1:5000. --You can also access the local IP address of the web server. ――If you access from a smartphone, I think that the responsive design is simply applied.
If you want to try IoT with Raspberry Pi, but you are developing hardware at the same time, or if you can not prepare breadboard and wiring, you can easily simulate it. The temperature and the number of sensors can be freely designed according to the definition of SQLite, so I will utilize it from now on.
I referred to the following site. Inexperienced web application developers use Flask, SQLite, and Heroku to release the service in a week Start a web server with Raspberry pi + Nginx + uWSGI and deploy the Django app Part 1 How to execute in Python at regular intervals and verification Save time with background execution! !!
Recommended Posts