test.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. # 主業務邏輯中的視圖和路由的定義
  2. import os
  3. import datetime
  4. from flask import render_template, request, session, Response
  5. # 導入藍圖程序,用於構建路由
  6. from werkzeug.utils import redirect
  7. from . import main
  8. from manage import mqtt
  9. # 導入db,用於操作數據庫
  10. from manage import db
  11. # 導入實體類,用於操作數據庫
  12. from ..models import *
  13. import json
  14. from datetime import datetime as dt
  15. from sqlalchemy import text
  16. import socket
  17. import pickle
  18. import cv2
  19. import numpy as np
  20. import math
  21. import threading
  22. import time
  23. from flask_mqtt import Mqtt
  24. c_sock = 0
  25. s_sock = 0
  26. # 主頁的訪問路徑
  27. @main.route('/')
  28. def main_index():
  29. # 獲取登入信息
  30. if 'id' in session and 'uname' in session:
  31. return render_template('allindex.html')
  32. else:
  33. return render_template('sign_in.html')
  34. # 登入頁面的訪問路徑
  35. @main.route('/login', methods=['GET', 'POST'])
  36. def login_views():
  37. if request.method == 'GET':
  38. if 'id' in session and 'uname' in session:
  39. return redirect('/')
  40. else:
  41. return render_template('sign_in.html')
  42. else:
  43. # 接收前端傳過來的資料
  44. username = request.form['username']
  45. password = request.form['password']
  46. # 使用接收的用戶和密碼到資料庫中查詢
  47. user = User.query.filter_by(account=username, password=password).first()
  48. # 如果用戶存在,將信息保存置session並重定向回首頁,否則重定向回登入頁
  49. if user:
  50. resp = redirect('/')
  51. # 判斷是否有記住密碼
  52. if 'rem' in request.form:
  53. sn = str(user.sn)
  54. max_age = 60 * 60 * 24 * 365
  55. resp.set_cookie("username", username, max_age=max_age)
  56. resp.set_cookie("sn", sn, max_age=max_age)
  57. session['uname'] = user.account
  58. session['id'] = user.sn
  59. return resp
  60. else:
  61. errMsg = "Wrong login or password"
  62. return render_template('sign_in.html', errMsg=errMsg)
  63. # 註冊頁面的訪問路徑
  64. @main.route('/register', methods=['POST', "GET"])
  65. def register_views():
  66. if request.method == 'GET':
  67. return render_template('registration.html')
  68. else:
  69. # 獲取文本框的值並賦值給user實體對象
  70. user = User()
  71. user.account = request.form['username']
  72. user.password = request.form['password']
  73. # 將數據保存進資料庫 - 註冊
  74. db.session.add(user)
  75. # 手動提交,目的是為了獲取提交後的user的id
  76. db.session.commit()
  77. # 當user成功插入進資料庫之後,程序會自動將所有信息取出來在賦值給user
  78. # 完成登入的操作
  79. user = User.query.filter_by(account=user.account).first()
  80. session['id'] = user.sn
  81. session['uname'] = user.account
  82. return redirect('/')
  83. # 毛豆田的主頁面
  84. @main.route('/aindex', methods=['POST', 'GET'])
  85. def aindex_views():
  86. return render_template('aindex.html')
  87. # 毛豆車的主頁面
  88. @main.route('/cindex', methods=['POST', 'GET'])
  89. def cindex_views():
  90. return render_template('cindex.html')
  91. # 毛豆田拍攝設定的主頁面
  92. @main.route('/ashoot_setting/<tid>', methods=['POST', 'GET'])
  93. def ashoot_setting_views(tid):
  94. if request.method == 'GET':
  95. global s_sock, c_sock
  96. #當跳轉小兵頁面時,判定scoket是否還在連接中
  97. if c_sock != 0:
  98. c_sock.shutdown(2)
  99. c_sock.close()
  100. c_sock = 0
  101. print("c_sock is closing")
  102. if s_sock != 0:
  103. s_sock.shutdown(2)
  104. s_sock.close()
  105. s_sock = 0
  106. print("s_sock is closing")
  107. dict = request.args.to_dict()
  108. if dict:
  109. try:
  110. nr = "KDAIS" + dict['nr']
  111. mode = int(dict['mode'])
  112. jvtotime = JvtOTime.query.filter_by(nr=nr, MODE=mode).order_by(text('datetime desc')).first()
  113. tilt_angle = jvtotime.tilt_angle
  114. pan_angle = jvtotime.pan_angle
  115. zoom = str(jvtotime.zoom_now)
  116. time1 = jvtotime.time1
  117. time2 = jvtotime.time2
  118. time3 = jvtotime.time3
  119. time4 = jvtotime.time4
  120. time5 = jvtotime.time5
  121. time6 = jvtotime.time6
  122. time7 = jvtotime.time7
  123. time8 = jvtotime.time8
  124. dict = {"tilt_angle": tilt_angle, "pan_angle": pan_angle, "zoom": zoom, "time1": time1,
  125. "time2": time2, "time3": time3, "time4": time4, "time5": time5, "time6": time6,
  126. "time7": time7, "time8": time8}
  127. return json.dumps(dict)
  128. except Exception:
  129. dict = {"tilt_angle": "0", "pan_angle": "0", "zoom": "0", "time1": "00000000",
  130. "time2": "00000000", "time3": "00000000", "time4": "00000000", "time5": "00000000",
  131. "time6": "00000000",
  132. "time7": "00000000", "time8": "00000000"}
  133. return json.dumps(dict)
  134. return render_template('aim.html', params=locals())
  135. else:
  136. dict = request.form.to_dict()
  137. jvtotime = JvtOTime()
  138. if dict['nr'] == '1':
  139. jvtotime.MAC = 'b8:27:eb:a1:b0:70'
  140. elif dict['nr'] == '2':
  141. jvtotime.MAC = 'b8:27:eb:e7:51:44'
  142. elif dict['nr'] == '3':
  143. jvtotime.MAC = 'b8:27:eb:ce:a5:35'
  144. elif dict['nr'] == '4':
  145. jvtotime.MAC = 'b8:27:eb:06:9a:f1'
  146. elif dict['nr'] == '5':
  147. jvtotime.MAC = 'b8:27:eb:0c:f0:21'
  148. elif dict['nr'] == '6':
  149. jvtotime.MAC = 'b8:27:eb:df:4b:0f'
  150. elif dict['nr'] == '7':
  151. jvtotime.MAC = 'b8:27:eb:af:df:b6'
  152. elif dict['nr'] == '8':
  153. jvtotime.MAC = 'b8:27:eb:d2:d0:8f'
  154. elif dict['nr'] == '9':
  155. jvtotime.MAC = 'b8:27:eb:57:3c:da'
  156. elif dict['nr'] == '10':
  157. jvtotime.MAC = 'b8:27:eb:bd:29:b1'
  158. elif dict['nr'] == '11':
  159. jvtotime.MAC = 'b8:27:eb:7c:f6:06'
  160. elif dict['nr'] == '12':
  161. jvtotime.MAC = 'b8:27:eb:74:bd:ac'
  162. elif dict['nr'] == '13':
  163. jvtotime.MAC = 'b8:27:eb:e7:21:e5'
  164. elif dict['nr'] == '14':
  165. jvtotime.MAC = 'b8:27:eb:6f:5a:6b'
  166. elif dict['nr'] == '15':
  167. jvtotime.MAC = 'b8:27:eb:e3:f1:f4'
  168. elif dict['nr'] == '16':
  169. jvtotime.MAC = 'b8:27:eb:60:1c:2e'
  170. elif dict['nr'] == '17':
  171. jvtotime.MAC = 'b8:27:eb:9d:68:05'
  172. elif dict['nr'] == '18':
  173. jvtotime.MAC = 'b8:27:eb:4d:e4:34'
  174. jvtotime.nr = 'KDAIS' + dict['nr']
  175. jvtotime.MODE = int(dict['mode'])
  176. jvtotime.tilt_angle = dict['tilt_angle']
  177. jvtotime.pan_angle = dict['pan_angle']
  178. jvtotime.zoom_before = 0
  179. jvtotime.zoom_now = int(dict['zoom'])
  180. jvtotime.time1 = dict['time1']
  181. jvtotime.time2 = dict['time2']
  182. jvtotime.time3 = dict['time3']
  183. jvtotime.time4 = dict['time4']
  184. jvtotime.time5 = dict['time5']
  185. jvtotime.time6 = dict['time6']
  186. jvtotime.time7 = dict['time7']
  187. jvtotime.time8 = dict['time8']
  188. jvtotime.datetime = dt.now()
  189. db.session.add(jvtotime)
  190. db.session.commit()
  191. return {"status": "OK"}
  192. # 毛豆田歷史資料的主頁面
  193. @main.route('/aimg_history/<tid>', methods=['POST', 'GET'])
  194. def aimg_history_views(tid):
  195. if request.method == 'GET':
  196. return render_template('ahistory_ndvi1.html', params=locals())
  197. else:
  198. pass
  199. # 毛豆車拍攝設定的主頁面
  200. @main.route('/cshoot_setting/<tid>', methods=['POST', 'GET'])
  201. def cshoot_setting_views(tid):
  202. if request.method == 'GET':
  203. return render_template('cim.html', params=locals())
  204. else:
  205. pass
  206. # 毛豆車歷史資料的主頁面
  207. @main.route('/cimg_history/<tid>', methods=['POST', 'GET'])
  208. def cimg_history_views(tid):
  209. if request.method == 'GET':
  210. return render_template('chistory_ndvi1.html', params=locals())
  211. else:
  212. pass
  213. # 退出的訪問路徑
  214. @main.route('/logout')
  215. def logout_views():
  216. if 'id' in session and 'uname' in session:
  217. del session['id']
  218. del session['uname']
  219. return redirect('/')
  220. @main.route("/udp_client", methods=['POST', 'GET'])
  221. def udp_views():
  222. time.sleep(0.5)
  223. if request.method == 'GET':
  224. def close():
  225. global c_sock
  226. time.sleep(300)
  227. c_sock.shutdown(2)
  228. c_sock.close()
  229. c_sock = 0
  230. print("c_sock is closing")
  231. max_length = 65000
  232. # max_length = 95000
  233. # lab1的IP
  234. # host = "192.168.50.65"
  235. # lab2的IP
  236. host = "192.168.51.161"
  237. port = 8000
  238. global c_sock
  239. c_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  240. t = threading.Thread(target=close)
  241. t.daemon = True
  242. t.start()
  243. # 地下室小兵
  244. cap = cv2.VideoCapture('rtsp://admin:abcd1234@192.168.51.48/av2_0')
  245. # 主機攝像頭
  246. # cap = cv2.VideoCapture(0)
  247. # 外面小兵
  248. # cap = cv2.VideoCapture('rtsp://admin:admin@192.168.50.182/av2_0')
  249. ret, frame = cap.read()
  250. while ret:
  251. # compress frame
  252. frame = cv2.resize(frame, (550, 400), interpolation=cv2.INTER_AREA)
  253. retval, buffer = cv2.imencode(".jpg", frame)
  254. if retval:
  255. # convert to byte array
  256. buffer = buffer.tobytes()
  257. # get size of the frame
  258. buffer_size = len(buffer)
  259. num_of_packs = 1
  260. if buffer_size > max_length:
  261. num_of_packs = math.ceil(buffer_size / max_length)
  262. frame_info = {"packs": num_of_packs}
  263. # send the number of packs to be expected
  264. # print("Number of packs:", num_of_packs)
  265. c_sock.sendto(pickle.dumps(frame_info), (host, port))
  266. left = 0
  267. right = max_length
  268. for i in range(num_of_packs):
  269. # print("left:", left)
  270. # print("right:", right)
  271. # truncate data to send
  272. data = buffer[left:right]
  273. left = right
  274. right += max_length
  275. # send the frames accordingly
  276. c_sock.sendto(data, (host, port))
  277. ret, frame = cap.read()
  278. print("done")
  279. else:
  280. global c_sock
  281. c_sock.shutdown(2)
  282. c_sock.close()
  283. c_sock = 0
  284. print("c_sock is closing")
  285. # 影像串流的路徑
  286. @main.route("/video_feed", methods=['POST', 'GET'])
  287. def video_feed_views():
  288. if request.method == 'GET':
  289. def close():
  290. global s_sock
  291. time.sleep(300)
  292. s_sock.shutdown(2)
  293. s_sock.close()
  294. s_sock = 0
  295. print("s_sock is closing")
  296. # lab1的IP
  297. # host = "192.168.50.65"
  298. # lab2的IP
  299. host = "192.168.51.161"
  300. port = 8000
  301. max_length = 65540
  302. # max_length = 95540
  303. print(host,port)
  304. global s_sock
  305. s_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  306. s_sock.bind((host, port))
  307. t = threading.Thread(target=close)
  308. t.daemon = True
  309. t.start()
  310. frame_info = None
  311. buffer = None
  312. frame = None
  313. print("-> waiting for connection")
  314. # 影像生成器函數,將影像以jpg格式傳給前端
  315. def generate():
  316. while True:
  317. global s_sock, frame_info, buffer, frame
  318. data, address = s_sock.recvfrom(max_length)
  319. if len(data) < 100:
  320. frame_info = pickle.loads(data)
  321. if frame_info:
  322. nums_of_packs = frame_info["packs"]
  323. for i in range(nums_of_packs):
  324. data, address = s_sock.recvfrom(max_length)
  325. if i == 0:
  326. buffer = data
  327. else:
  328. buffer += data
  329. frame = np.frombuffer(buffer, dtype=np.uint8)
  330. frame = frame.reshape(frame.shape[0], 1)
  331. frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
  332. frame = cv2.resize(frame, (1280, 720), interpolation=cv2.INTER_AREA)
  333. # encode the frame in JPEG format
  334. (flag, encodedImage) = cv2.imencode(".jpg", frame)
  335. # ensure the frame was successfully encoded
  336. if not flag:
  337. continue
  338. # yield the output frame in the byte format
  339. yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +
  340. bytearray(encodedImage) + b'\r\n')
  341. # return the response generated along with the specific media
  342. # type (mime type)
  343. return Response(generate(), mimetype="multipart/x-mixed-replace; boundary=frame")
  344. else:
  345. global s_sock
  346. s_sock.shutdown(2)
  347. s_sock.close()
  348. s_sock = 0
  349. print("s_sock is closing")
  350. #mqtt發布
  351. @main.route('/mqtt', methods=['GET','POST'])
  352. def mqtt_views():
  353. import json
  354. dict = request.args.to_dict()
  355. json = json.dumps(dict)
  356. print(json)
  357. mqtt.publish('AISKY/AppleFarm/MK-G/b8:27:eb:f8:24:92', json)
  358. return "Publish done"