123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432 |
- # 主業務邏輯中的視圖和路由的定義
- import os
- import datetime
- from flask import render_template, request, session, Response
- # 導入藍圖程序,用於構建路由
- from werkzeug.utils import redirect
- from . import main
- from manage import mqtt
- # 導入db,用於操作數據庫
- from manage import db
- # 導入實體類,用於操作數據庫
- from ..models import *
- import json
- from datetime import datetime as dt
- from sqlalchemy import text
- import socket
- import pickle
- import cv2
- import numpy as np
- import math
- import threading
- import time
- from flask_mqtt import Mqtt
- c_sock = 0
- s_sock = 0
- # 主頁的訪問路徑
- @main.route('/')
- def main_index():
- # 獲取登入信息
- if 'id' in session and 'uname' in session:
- return render_template('allindex.html')
- else:
- return render_template('sign_in.html')
- # 登入頁面的訪問路徑
- @main.route('/login', methods=['GET', 'POST'])
- def login_views():
- if request.method == 'GET':
- if 'id' in session and 'uname' in session:
- return redirect('/')
- else:
- return render_template('sign_in.html')
- else:
- # 接收前端傳過來的資料
- username = request.form['username']
- password = request.form['password']
- # 使用接收的用戶和密碼到資料庫中查詢
- user = User.query.filter_by(account=username, password=password).first()
- # 如果用戶存在,將信息保存置session並重定向回首頁,否則重定向回登入頁
- if user:
- resp = redirect('/')
- # 判斷是否有記住密碼
- if 'rem' in request.form:
- sn = str(user.sn)
- max_age = 60 * 60 * 24 * 365
- resp.set_cookie("username", username, max_age=max_age)
- resp.set_cookie("sn", sn, max_age=max_age)
- session['uname'] = user.account
- session['id'] = user.sn
- return resp
- else:
- errMsg = "Wrong login or password"
- return render_template('sign_in.html', errMsg=errMsg)
- # 註冊頁面的訪問路徑
- @main.route('/register', methods=['POST', "GET"])
- def register_views():
- if request.method == 'GET':
- return render_template('registration.html')
- else:
- # 獲取文本框的值並賦值給user實體對象
- user = User()
- user.account = request.form['username']
- user.password = request.form['password']
- # 將數據保存進資料庫 - 註冊
- db.session.add(user)
- # 手動提交,目的是為了獲取提交後的user的id
- db.session.commit()
- # 當user成功插入進資料庫之後,程序會自動將所有信息取出來在賦值給user
- # 完成登入的操作
- user = User.query.filter_by(account=user.account).first()
- session['id'] = user.sn
- session['uname'] = user.account
- return redirect('/')
- # 毛豆田的主頁面
- @main.route('/aindex', methods=['POST', 'GET'])
- def aindex_views():
- return render_template('aindex.html')
- # 毛豆車的主頁面
- @main.route('/cindex', methods=['POST', 'GET'])
- def cindex_views():
- return render_template('cindex.html')
- # 毛豆田拍攝設定的主頁面
- @main.route('/ashoot_setting/<tid>', methods=['POST', 'GET'])
- def ashoot_setting_views(tid):
- if request.method == 'GET':
- global s_sock, c_sock
- #當跳轉小兵頁面時,判定scoket是否還在連接中
- if c_sock != 0:
- c_sock.shutdown(2)
- c_sock.close()
- c_sock = 0
- print("c_sock is closing")
- if s_sock != 0:
- s_sock.shutdown(2)
- s_sock.close()
- s_sock = 0
- print("s_sock is closing")
- dict = request.args.to_dict()
- if dict:
- try:
- nr = "KDAIS" + dict['nr']
- mode = int(dict['mode'])
- jvtotime = JvtOTime.query.filter_by(nr=nr, MODE=mode).order_by(text('datetime desc')).first()
- tilt_angle = jvtotime.tilt_angle
- pan_angle = jvtotime.pan_angle
- zoom = str(jvtotime.zoom_now)
- time1 = jvtotime.time1
- time2 = jvtotime.time2
- time3 = jvtotime.time3
- time4 = jvtotime.time4
- time5 = jvtotime.time5
- time6 = jvtotime.time6
- time7 = jvtotime.time7
- time8 = jvtotime.time8
- dict = {"tilt_angle": tilt_angle, "pan_angle": pan_angle, "zoom": zoom, "time1": time1,
- "time2": time2, "time3": time3, "time4": time4, "time5": time5, "time6": time6,
- "time7": time7, "time8": time8}
- return json.dumps(dict)
- except Exception:
- dict = {"tilt_angle": "0", "pan_angle": "0", "zoom": "0", "time1": "00000000",
- "time2": "00000000", "time3": "00000000", "time4": "00000000", "time5": "00000000",
- "time6": "00000000",
- "time7": "00000000", "time8": "00000000"}
- return json.dumps(dict)
- return render_template('aim.html', params=locals())
- else:
- dict = request.form.to_dict()
- jvtotime = JvtOTime()
- if dict['nr'] == '1':
- jvtotime.MAC = 'b8:27:eb:a1:b0:70'
- elif dict['nr'] == '2':
- jvtotime.MAC = 'b8:27:eb:e7:51:44'
- elif dict['nr'] == '3':
- jvtotime.MAC = 'b8:27:eb:ce:a5:35'
- elif dict['nr'] == '4':
- jvtotime.MAC = 'b8:27:eb:06:9a:f1'
- elif dict['nr'] == '5':
- jvtotime.MAC = 'b8:27:eb:0c:f0:21'
- elif dict['nr'] == '6':
- jvtotime.MAC = 'b8:27:eb:df:4b:0f'
- elif dict['nr'] == '7':
- jvtotime.MAC = 'b8:27:eb:af:df:b6'
- elif dict['nr'] == '8':
- jvtotime.MAC = 'b8:27:eb:d2:d0:8f'
- elif dict['nr'] == '9':
- jvtotime.MAC = 'b8:27:eb:57:3c:da'
- elif dict['nr'] == '10':
- jvtotime.MAC = 'b8:27:eb:bd:29:b1'
- elif dict['nr'] == '11':
- jvtotime.MAC = 'b8:27:eb:7c:f6:06'
- elif dict['nr'] == '12':
- jvtotime.MAC = 'b8:27:eb:74:bd:ac'
- elif dict['nr'] == '13':
- jvtotime.MAC = 'b8:27:eb:e7:21:e5'
- elif dict['nr'] == '14':
- jvtotime.MAC = 'b8:27:eb:6f:5a:6b'
- elif dict['nr'] == '15':
- jvtotime.MAC = 'b8:27:eb:e3:f1:f4'
- elif dict['nr'] == '16':
- jvtotime.MAC = 'b8:27:eb:60:1c:2e'
- elif dict['nr'] == '17':
- jvtotime.MAC = 'b8:27:eb:9d:68:05'
- elif dict['nr'] == '18':
- jvtotime.MAC = 'b8:27:eb:4d:e4:34'
- jvtotime.nr = 'KDAIS' + dict['nr']
- jvtotime.MODE = int(dict['mode'])
- jvtotime.tilt_angle = dict['tilt_angle']
- jvtotime.pan_angle = dict['pan_angle']
- jvtotime.zoom_before = 0
- jvtotime.zoom_now = int(dict['zoom'])
- jvtotime.time1 = dict['time1']
- jvtotime.time2 = dict['time2']
- jvtotime.time3 = dict['time3']
- jvtotime.time4 = dict['time4']
- jvtotime.time5 = dict['time5']
- jvtotime.time6 = dict['time6']
- jvtotime.time7 = dict['time7']
- jvtotime.time8 = dict['time8']
- jvtotime.datetime = dt.now()
- db.session.add(jvtotime)
- db.session.commit()
- return {"status": "OK"}
- # 毛豆田歷史資料的主頁面
- @main.route('/aimg_history/<tid>', methods=['POST', 'GET'])
- def aimg_history_views(tid):
- if request.method == 'GET':
- return render_template('ahistory_ndvi1.html', params=locals())
- else:
- pass
- # 毛豆車拍攝設定的主頁面
- @main.route('/cshoot_setting/<tid>', methods=['POST', 'GET'])
- def cshoot_setting_views(tid):
- if request.method == 'GET':
- return render_template('cim.html', params=locals())
- else:
- pass
- # 毛豆車歷史資料的主頁面
- @main.route('/cimg_history/<tid>', methods=['POST', 'GET'])
- def cimg_history_views(tid):
- if request.method == 'GET':
- return render_template('chistory_ndvi1.html', params=locals())
- else:
- pass
- # 退出的訪問路徑
- @main.route('/logout')
- def logout_views():
- if 'id' in session and 'uname' in session:
- del session['id']
- del session['uname']
- return redirect('/')
- @main.route("/udp_client", methods=['POST', 'GET'])
- def udp_views():
- time.sleep(0.5)
- if request.method == 'GET':
- def close():
- global c_sock
- time.sleep(300)
- c_sock.shutdown(2)
- c_sock.close()
- c_sock = 0
- print("c_sock is closing")
- max_length = 65000
- # max_length = 95000
- # lab1的IP
- # host = "192.168.50.65"
- # lab2的IP
- host = "192.168.51.161"
- port = 8000
- global c_sock
- c_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- t = threading.Thread(target=close)
- t.daemon = True
- t.start()
- # 地下室小兵
- cap = cv2.VideoCapture('rtsp://admin:abcd1234@192.168.51.48/av2_0')
- # 主機攝像頭
- # cap = cv2.VideoCapture(0)
- # 外面小兵
- # cap = cv2.VideoCapture('rtsp://admin:admin@192.168.50.182/av2_0')
- ret, frame = cap.read()
- while ret:
- # compress frame
- frame = cv2.resize(frame, (550, 400), interpolation=cv2.INTER_AREA)
- retval, buffer = cv2.imencode(".jpg", frame)
- if retval:
- # convert to byte array
- buffer = buffer.tobytes()
- # get size of the frame
- buffer_size = len(buffer)
- num_of_packs = 1
- if buffer_size > max_length:
- num_of_packs = math.ceil(buffer_size / max_length)
- frame_info = {"packs": num_of_packs}
- # send the number of packs to be expected
- # print("Number of packs:", num_of_packs)
- c_sock.sendto(pickle.dumps(frame_info), (host, port))
- left = 0
- right = max_length
- for i in range(num_of_packs):
- # print("left:", left)
- # print("right:", right)
- # truncate data to send
- data = buffer[left:right]
- left = right
- right += max_length
- # send the frames accordingly
- c_sock.sendto(data, (host, port))
- ret, frame = cap.read()
- print("done")
- else:
- global c_sock
- c_sock.shutdown(2)
- c_sock.close()
- c_sock = 0
- print("c_sock is closing")
- # 影像串流的路徑
- @main.route("/video_feed", methods=['POST', 'GET'])
- def video_feed_views():
- if request.method == 'GET':
- def close():
- global s_sock
- time.sleep(300)
- s_sock.shutdown(2)
- s_sock.close()
- s_sock = 0
- print("s_sock is closing")
- # lab1的IP
- # host = "192.168.50.65"
- # lab2的IP
- host = "192.168.51.161"
- port = 8000
- max_length = 65540
- # max_length = 95540
- print(host,port)
- global s_sock
- s_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s_sock.bind((host, port))
- t = threading.Thread(target=close)
- t.daemon = True
- t.start()
- frame_info = None
- buffer = None
- frame = None
- print("-> waiting for connection")
- # 影像生成器函數,將影像以jpg格式傳給前端
- def generate():
- while True:
- global s_sock, frame_info, buffer, frame
- data, address = s_sock.recvfrom(max_length)
- if len(data) < 100:
- frame_info = pickle.loads(data)
- if frame_info:
- nums_of_packs = frame_info["packs"]
- for i in range(nums_of_packs):
- data, address = s_sock.recvfrom(max_length)
- if i == 0:
- buffer = data
- else:
- buffer += data
- frame = np.frombuffer(buffer, dtype=np.uint8)
- frame = frame.reshape(frame.shape[0], 1)
- frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
- frame = cv2.resize(frame, (1280, 720), interpolation=cv2.INTER_AREA)
- # encode the frame in JPEG format
- (flag, encodedImage) = cv2.imencode(".jpg", frame)
- # ensure the frame was successfully encoded
- if not flag:
- continue
- # yield the output frame in the byte format
- yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +
- bytearray(encodedImage) + b'\r\n')
- # return the response generated along with the specific media
- # type (mime type)
- return Response(generate(), mimetype="multipart/x-mixed-replace; boundary=frame")
- else:
- global s_sock
- s_sock.shutdown(2)
- s_sock.close()
- s_sock = 0
- print("s_sock is closing")
- #mqtt發布
- @main.route('/mqtt', methods=['GET','POST'])
- def mqtt_views():
- import json
- dict = request.args.to_dict()
- json = json.dumps(dict)
- print(json)
- mqtt.publish('AISKY/AppleFarm/MK-G/b8:27:eb:f8:24:92', json)
- return "Publish done"
|