带 ESP8266 客户端的 Flask REST API 服务器
Flask REST API Server with ESP8266 Client
我使用 Arduino Nano+ESP8266(前端)和 Flask REST API 服务器后端开发了一个密码验证系统。
以下是我的 ESP8266 代码,它将 HTTP POST 请求传递给 REST API 服务器,
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP8266HTTPClient.h>
#include<SoftwareSerial.h>
SoftwareSerial link(4, 0);
byte greenLED = 13;
byte statusLED = 14;
String hexstring = "";
// Replace with your network credentials
const char *ssid = "***********";
const char *password = "***********";
const long utcOffsetInSeconds = 240;
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "asia.pool.ntp.org", utcOffsetInSeconds);
//Week Days
String weekDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Month names
String months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
Serial.print("Initializing System");
for (int i = 10; i > 0; i--) {
delay(500);
Serial.print(i); Serial.println(' ');
}
pinMode(statusLED, OUTPUT);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
link.begin(9600);
link.setTimeout(100);
// clear any pending stuff
link.readString();
pinMode(greenLED, OUTPUT);
}
// Initialize a NTPClient to get time
timeClient.begin();
timeClient.setTimeOffset(19770);
}
void loop() {
timeClient.update();
unsigned long epochTime = timeClient.getEpochTime();
String formattedTime = timeClient.getFormattedTime();
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
int currentSecond = timeClient.getSeconds();
String weekDay = weekDays[timeClient.getDay()];
//Get a time structure
struct tm *ptm = gmtime ((time_t *)&epochTime);
int monthDay = ptm->tm_mday;
int currentMonth = ptm->tm_mon + 1;
String currentMonthName = months[currentMonth - 1];
int currentYear = ptm->tm_year + 1900;
//Print complete date:
String currentDate = String(currentYear) + String(currentMonth) + String(monthDay) + String(currentHour) + String(currentMinute) + String(currentSecond);
delay(1000);
if (link.available()) {
String rec = link.readString();
Serial.print(F("rec:")); Serial.println(rec);
if (rec.length() > 0) { // print it out
Serial.println(F("Received data"));
for (size_t i = 0; i < rec.length(); i++) {
digitalWrite(greenLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(greenLED, LOW);
if (i % 8 == 0) {
Serial.println();
}
Serial.print(" 0x");
if (rec[i] < 10) {
Serial.print("0");
hexstring += '0';
}
Serial.print(rec[i], HEX);
hexstring += String(rec[i], HEX);
}
Serial.println();
Serial.print("Current Date: ");
Serial.println(currentDate);
Serial.println("Your String Sir:");
Serial.print(hexstring);
Serial.println();
//confirmation();
String sub1 = hexstring.substring(0, 2);
String sub2 = hexstring.substring(16, 32);
String sub3 = hexstring.substring(32, 34);
if (sub3 == "31") { //New User Registartion
String data = "{\"user_id\" :\"" + sub1 + "\",\"encrypted_password\" :\"" + sub2 + "\",\"option\" :\"" + sub3 + "\" ,\"request_datetime\" :\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://192.168.8.228:5000/users/"); //Specify request destination
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(data.c_str());
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code1") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
else if (sub3 == "32") { //Confirm Password
String data ="{\"user_id\":\"" + sub1 + "\",\"encrypted_password\":\"" + sub2 + "\",\"option\":\"" + sub3 + "\" ,\"request_datetime\":\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
String link2 = "http://192.168.8.228:5000/users/" + sub1;
http.begin(link2); //Specify request destination
http.addHeader("Content - Type", "application / json");
int httpCode = http.POST(data.c_str());
delay(1000);
Serial.println(data.c_str());
Serial.println(httpCode);
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code2") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
else if (sub3 == "33") { //Change Password
String data = "{\"user_id\" :\"" + sub1 + "\",\"encrypted_password\" :\"" + sub2 + "\",\"option\" :\"" + sub3 + "\" ,\"request_datetime\" :\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://192.168.8.228:5000/users/"); //Specify request destination
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(data.c_str());
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code3") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
}
}
}
如你所见,有3种方法,
新用户注册码部分:
if (sub3 == "31") { //New User Registartion
String data = "{\"user_id\" :\"" + sub1 + "\",\"encrypted_password\" :\"" + sub2 + "\",\"option\" :\"" + sub3 + "\" ,\"request_datetime\" :\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://192.168.8.228:5000/users/"); //Specify request destination
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(data.c_str());
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code1") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
验证密码代码部分:
else if (sub3 == "32") { //Confirm Password
String data ="{\"user_id\":\"" + sub1 + "\",\"encrypted_password\":\"" + sub2 + "\",\"option\":\"" + sub3 + "\" ,\"request_datetime\":\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
String link2 = "http://192.168.8.228:5000/users/" + sub1;
http.begin(link2); //Specify request destination
http.addHeader("Content - Type", "application / json");
int httpCode = http.POST(data.c_str());
delay(1000);
Serial.println(data.c_str());
Serial.println(httpCode);
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code2") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
下面是我的Flask/PythonAPI服务器后端代码:
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
import uuid
app = Flask(__name__)
db = SQLAlchemy(app)
DEBUG = True
# app.config['SECRET_KEY'] = 'secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root@localhost:3306/app'
print("App2 Change2")
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, index=True)
user_id = db.Column(db.VARCHAR(10), nullable=False, unique=True)
encrypted_password = db.Column(db.VARCHAR(20), nullable=False)
option = db.Column(db.VARCHAR(3), nullable=False)
request_datetime = db.Column(db.VARCHAR(20), nullable=False)
public_id = db.Column(db.VARCHAR(100), nullable=False)
def __repr__(self):
return f'User <{self.public_id}>'
db.create_all()
@app.route('/')
def home():
return {
'message': 'Welcome to Vinod Test App'
}
@app.route('/users/')
def get_users():
return jsonify([
{
'user_id': user.user_id, 'encrypted_password': user.encrypted_password, 'option': user.option,
'request_datetime': user.request_datetime
} for user in User.query.all()
])
@app.route('/users/<user_id>/')
def get_user(user_id):
print(user_id)
user = User.query.filter_by(user_id=user_id).first_or_404()
return {
'user_id': user.user_id, 'encrypted_password': user.encrypted_password,
'public_id': user.public_id, 'original_time': user.request_datetime
}
# Add New User
@app.route('/users/', methods=['POST'])
def create_user():
data = request.get_json()
print(request.get_json())
if not 'user_id' in data or not 'encrypted_password' in data or not 'option' in data:
return jsonify({
'error': 'Bad Request',
'message': 'User Id and Encrypted Data is Missing'
}), 400
if len(data['encrypted_password']) < 16:
return jsonify({
'error': 'Bad Request',
'message': 'Length Error in Encrypted Data'
}), 400
u = User(
user_id=data['user_id'],
encrypted_password=data['encrypted_password'],
option=data.get('option'),
request_datetime=data['request_datetime'],
public_id=str(uuid.uuid4())
)
db.session.add(u)
db.session.commit()
return {
'id': u.user_id, 'encrypted_data': u.encrypted_password,
'public_id': u.public_id, 'original_time': u.request_datetime,
}, 200
# Verify Password
@app.route('/users/<user_id>', methods=['POST'])
def check_user(user_id):
data = request.get_json()
if 'user_id' not in data:
return {
'error': 'Bad Request',
'message': 'User_id field needs to be present'
}, 400
user = User.query.filter_by(user_id=user_id).first_or_404()
user.user_id = data['user_id']
if 'user_id' in data:
if user.encrypted_password == data['encrypted_password']:
return jsonify({
'user_id': user.public_id,
'encrypted_password': user.encrypted_password,
'original_time': user.request_datetime
})
else:
return {
'error': 'Bad Request',
'message': 'Password Do Not Match'
}, 400
@app.route('/users/<user_id>/', methods=['DELETE'])
def delete_user(user_id):
user = User.query.filter_by(user_id=user_id).first_or_404()
db.session.delete(user)
db.session.commit()
return {
'success': 'Data deleted successfully'
}
if __name__ == '__main__':
app.run(debug=True)
我的问题是:当验证密码通过 ESP8266 传递到后端以验证密码时,不工作。但是新用户注册通过ESP8266是有效的。
下面是我在 PyCharm:
中遇到的错误
* Running on http://192.168.8.100:5000/ (Press CTRL+C to quit)
[2021-09-26 14:57:55,237] ERROR in app: Exception on /users/32 [POST]
Traceback (most recent call last):
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 2070, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 1515, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 1513, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 1499, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\app2_Change2.py", line 108, in check_user
if 'user_id' not in data:
TypeError: argument of type 'NoneType' is not iterable
192.168.8.174 - - [26/Sep/2021 15:52:20] "POST /users/32 HTTP/1.1" 500 -
但是当我从 Postman
发送相同的请求(验证密码)时,它起作用了,
以下是邮递员对验证的回复:
此请求与从 Mockon 测试服务器捕获的 ESP8266 发送的请求相同:
后端预期响应[使用 Postman]
192.168.8.103 - - [26/Sep/2021 15:52:59] "POST /users/32 HTTP/1.1" 400 -
注意: Arduino Nano 将加密数据连同用户输入传递给 ESP,如下所示:
错误TypeError: argument of type 'NoneType' is not iterable
意味着你的data = request.get_json()
return一个None
。 return a None
的原因可以在 falsk.Request.get_json API 文档中找到。它说:
By default this function will return None if the mimetype is not application/json
看看你的 Arduino 代码,你在 http header:
上添加了额外的空格
http.addHeader("Content - Type", "application / json");
HTTP header 应该是:
Content-Type: application/json
我使用 Arduino Nano+ESP8266(前端)和 Flask REST API 服务器后端开发了一个密码验证系统。
以下是我的 ESP8266 代码,它将 HTTP POST 请求传递给 REST API 服务器,
#include <ESP8266WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ESP8266HTTPClient.h>
#include<SoftwareSerial.h>
SoftwareSerial link(4, 0);
byte greenLED = 13;
byte statusLED = 14;
String hexstring = "";
// Replace with your network credentials
const char *ssid = "***********";
const char *password = "***********";
const long utcOffsetInSeconds = 240;
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "asia.pool.ntp.org", utcOffsetInSeconds);
//Week Days
String weekDays[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//Month names
String months[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
Serial.print("Initializing System");
for (int i = 10; i > 0; i--) {
delay(500);
Serial.print(i); Serial.println(' ');
}
pinMode(statusLED, OUTPUT);
// Connect to Wi-Fi
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
link.begin(9600);
link.setTimeout(100);
// clear any pending stuff
link.readString();
pinMode(greenLED, OUTPUT);
}
// Initialize a NTPClient to get time
timeClient.begin();
timeClient.setTimeOffset(19770);
}
void loop() {
timeClient.update();
unsigned long epochTime = timeClient.getEpochTime();
String formattedTime = timeClient.getFormattedTime();
int currentHour = timeClient.getHours();
int currentMinute = timeClient.getMinutes();
int currentSecond = timeClient.getSeconds();
String weekDay = weekDays[timeClient.getDay()];
//Get a time structure
struct tm *ptm = gmtime ((time_t *)&epochTime);
int monthDay = ptm->tm_mday;
int currentMonth = ptm->tm_mon + 1;
String currentMonthName = months[currentMonth - 1];
int currentYear = ptm->tm_year + 1900;
//Print complete date:
String currentDate = String(currentYear) + String(currentMonth) + String(monthDay) + String(currentHour) + String(currentMinute) + String(currentSecond);
delay(1000);
if (link.available()) {
String rec = link.readString();
Serial.print(F("rec:")); Serial.println(rec);
if (rec.length() > 0) { // print it out
Serial.println(F("Received data"));
for (size_t i = 0; i < rec.length(); i++) {
digitalWrite(greenLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(greenLED, LOW);
if (i % 8 == 0) {
Serial.println();
}
Serial.print(" 0x");
if (rec[i] < 10) {
Serial.print("0");
hexstring += '0';
}
Serial.print(rec[i], HEX);
hexstring += String(rec[i], HEX);
}
Serial.println();
Serial.print("Current Date: ");
Serial.println(currentDate);
Serial.println("Your String Sir:");
Serial.print(hexstring);
Serial.println();
//confirmation();
String sub1 = hexstring.substring(0, 2);
String sub2 = hexstring.substring(16, 32);
String sub3 = hexstring.substring(32, 34);
if (sub3 == "31") { //New User Registartion
String data = "{\"user_id\" :\"" + sub1 + "\",\"encrypted_password\" :\"" + sub2 + "\",\"option\" :\"" + sub3 + "\" ,\"request_datetime\" :\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://192.168.8.228:5000/users/"); //Specify request destination
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(data.c_str());
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code1") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
else if (sub3 == "32") { //Confirm Password
String data ="{\"user_id\":\"" + sub1 + "\",\"encrypted_password\":\"" + sub2 + "\",\"option\":\"" + sub3 + "\" ,\"request_datetime\":\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
String link2 = "http://192.168.8.228:5000/users/" + sub1;
http.begin(link2); //Specify request destination
http.addHeader("Content - Type", "application / json");
int httpCode = http.POST(data.c_str());
delay(1000);
Serial.println(data.c_str());
Serial.println(httpCode);
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code2") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
else if (sub3 == "33") { //Change Password
String data = "{\"user_id\" :\"" + sub1 + "\",\"encrypted_password\" :\"" + sub2 + "\",\"option\" :\"" + sub3 + "\" ,\"request_datetime\" :\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://192.168.8.228:5000/users/"); //Specify request destination
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(data.c_str());
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code3") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
}
}
}
如你所见,有3种方法,
新用户注册码部分:
if (sub3 == "31") { //New User Registartion
String data = "{\"user_id\" :\"" + sub1 + "\",\"encrypted_password\" :\"" + sub2 + "\",\"option\" :\"" + sub3 + "\" ,\"request_datetime\" :\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
http.begin("http://192.168.8.228:5000/users/"); //Specify request destination
http.addHeader("Content-Type", "application/json");
int httpCode = http.POST(data.c_str());
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code1") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
验证密码代码部分:
else if (sub3 == "32") { //Confirm Password
String data ="{\"user_id\":\"" + sub1 + "\",\"encrypted_password\":\"" + sub2 + "\",\"option\":\"" + sub3 + "\" ,\"request_datetime\":\"" + currentDate + "\"}";
HTTPClient http; //Declare object of class HTTPClient
String link2 = "http://192.168.8.228:5000/users/" + sub1;
http.begin(link2); //Specify request destination
http.addHeader("Content - Type", "application / json");
int httpCode = http.POST(data.c_str());
delay(1000);
Serial.println(data.c_str());
Serial.println(httpCode);
if (httpCode == 200) {
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
if (payload == "Code2") {
link.read();
Serial.println(F("Prompt other side Confirmation"));
link.print("Success_Code1");
digitalWrite(statusLED, HIGH); //flash led to show data is arriving
delay(20);
digitalWrite(statusLED, LOW);
}
}
else {
link.read();
Serial.println(F("Prompt other side Error1"));
link.print("Error 1");
}
http.end();
rec = ""; // clear for next receive
hexstring = ""; //Clear hexstring
}
下面是我的Flask/PythonAPI服务器后端代码:
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
import uuid
app = Flask(__name__)
db = SQLAlchemy(app)
DEBUG = True
# app.config['SECRET_KEY'] = 'secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root@localhost:3306/app'
print("App2 Change2")
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, index=True)
user_id = db.Column(db.VARCHAR(10), nullable=False, unique=True)
encrypted_password = db.Column(db.VARCHAR(20), nullable=False)
option = db.Column(db.VARCHAR(3), nullable=False)
request_datetime = db.Column(db.VARCHAR(20), nullable=False)
public_id = db.Column(db.VARCHAR(100), nullable=False)
def __repr__(self):
return f'User <{self.public_id}>'
db.create_all()
@app.route('/')
def home():
return {
'message': 'Welcome to Vinod Test App'
}
@app.route('/users/')
def get_users():
return jsonify([
{
'user_id': user.user_id, 'encrypted_password': user.encrypted_password, 'option': user.option,
'request_datetime': user.request_datetime
} for user in User.query.all()
])
@app.route('/users/<user_id>/')
def get_user(user_id):
print(user_id)
user = User.query.filter_by(user_id=user_id).first_or_404()
return {
'user_id': user.user_id, 'encrypted_password': user.encrypted_password,
'public_id': user.public_id, 'original_time': user.request_datetime
}
# Add New User
@app.route('/users/', methods=['POST'])
def create_user():
data = request.get_json()
print(request.get_json())
if not 'user_id' in data or not 'encrypted_password' in data or not 'option' in data:
return jsonify({
'error': 'Bad Request',
'message': 'User Id and Encrypted Data is Missing'
}), 400
if len(data['encrypted_password']) < 16:
return jsonify({
'error': 'Bad Request',
'message': 'Length Error in Encrypted Data'
}), 400
u = User(
user_id=data['user_id'],
encrypted_password=data['encrypted_password'],
option=data.get('option'),
request_datetime=data['request_datetime'],
public_id=str(uuid.uuid4())
)
db.session.add(u)
db.session.commit()
return {
'id': u.user_id, 'encrypted_data': u.encrypted_password,
'public_id': u.public_id, 'original_time': u.request_datetime,
}, 200
# Verify Password
@app.route('/users/<user_id>', methods=['POST'])
def check_user(user_id):
data = request.get_json()
if 'user_id' not in data:
return {
'error': 'Bad Request',
'message': 'User_id field needs to be present'
}, 400
user = User.query.filter_by(user_id=user_id).first_or_404()
user.user_id = data['user_id']
if 'user_id' in data:
if user.encrypted_password == data['encrypted_password']:
return jsonify({
'user_id': user.public_id,
'encrypted_password': user.encrypted_password,
'original_time': user.request_datetime
})
else:
return {
'error': 'Bad Request',
'message': 'Password Do Not Match'
}, 400
@app.route('/users/<user_id>/', methods=['DELETE'])
def delete_user(user_id):
user = User.query.filter_by(user_id=user_id).first_or_404()
db.session.delete(user)
db.session.commit()
return {
'success': 'Data deleted successfully'
}
if __name__ == '__main__':
app.run(debug=True)
我的问题是:当验证密码通过 ESP8266 传递到后端以验证密码时,不工作。但是新用户注册通过ESP8266是有效的。
下面是我在 PyCharm:
* Running on http://192.168.8.100:5000/ (Press CTRL+C to quit)
[2021-09-26 14:57:55,237] ERROR in app: Exception on /users/32 [POST]
Traceback (most recent call last):
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 2070, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 1515, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 1513, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\venv\lib\site-packages\flask\app.py", line 1499, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "C:\Users\Vinod Amarathunga\PycharmProject\Test1\server1\app2_Change2.py", line 108, in check_user
if 'user_id' not in data:
TypeError: argument of type 'NoneType' is not iterable
192.168.8.174 - - [26/Sep/2021 15:52:20] "POST /users/32 HTTP/1.1" 500 -
但是当我从 Postman
发送相同的请求(验证密码)时,它起作用了,
以下是邮递员对验证的回复:
此请求与从 Mockon 测试服务器捕获的 ESP8266 发送的请求相同:
后端预期响应[使用 Postman]
192.168.8.103 - - [26/Sep/2021 15:52:59] "POST /users/32 HTTP/1.1" 400 -
注意: Arduino Nano 将加密数据连同用户输入传递给 ESP,如下所示:
错误TypeError: argument of type 'NoneType' is not iterable
意味着你的data = request.get_json()
return一个None
。 return a None
的原因可以在 falsk.Request.get_json API 文档中找到。它说:
By default this function will return None if the mimetype is not application/json
看看你的 Arduino 代码,你在 http header:
上添加了额外的空格 http.addHeader("Content - Type", "application / json");
HTTP header 应该是:
Content-Type: application/json