| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 | # 主業務邏輯中的視圖和路由的定義import osimport datetimefrom flask import render_template, request, session, Response, url_for# 導入藍圖程序,用於構建路由from werkzeug.utils import redirect, secure_filenamefrom . import mainfrom manage import mqtt# 導入db,用於操作數據庫from manage import db, app# 導入實體類,用於操作數據庫from ..models import *import jsonfrom datetime import datetime as dtfrom sqlalchemy import textimport socketimport pickleimport cv2import numpy as npimport mathimport threadingimport timefrom flask_mqtt import Mqttimport requestsimport reimport copyfrom selenium import webdriverfrom selenium.webdriver.support.ui import Selectfrom bs4 import BeautifulSoupfrom time import sleep as slfrom app import ALLOWED_EXTENSIONSimport geocoder# 主頁的訪問路徑@main.route('/')def main_index():    # 獲取登入信息    if 'id' in session and 'uname' in session and 'status' in session:        username = session['uname']        if session['status'] == 1:            return redirect('/purchase')        elif session['status'] == 2:            return redirect('/register_number')    else:        return render_template('index.html')# 登入頁面的訪問路徑@main.route('/login', methods=['GET', 'POST'])def login_views():    if request.method == 'GET':        if 'id' in session and 'uname' in session and 'status' 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(username=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.username            session['id'] = user.sn            session['status'] = user.status            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.firstname = request.form['firstname']        user.lastname = request.form['lastname']        user.mail = request.form['email']        user.phone = request.form['phone']        user.username = request.form['username']        user.password = request.form['password']        user.status = 1        user.isActive = True        # 將數據保存進資料庫  - 註冊        db.session.add(user)        # 手動提交,目的是為了獲取提交後的user的id        db.session.commit()        # 當user成功插入進資料庫之後,程序會自動將所有信息取出來在賦值給user        # 完成登入的操作        user = User.query.filter_by(username=user.username).first()        session['id'] = user.sn        session['uname'] = user.username        session['status'] = user.status        return redirect('/purchase')#登入重設密碼的頁面@main.route('/reset_password', methods=['POST', 'GET'])def reset_password_views():    if request.method == 'GET':        if 'mail' in session:            del session['mail']        return render_template('reset_pwd1.html')    else:        #如果有id在session裡,代表從reset_pwd2過來的        if "mail" in session:            new_pwd = request.form['new_pwd']            confirm_pwd = request.form['confirm_pwd']            #判斷密碼是否一致            if new_pwd == confirm_pwd:                mail = session['mail']                user = User.query.filter_by(mail=mail).first()                user.password = new_pwd                db.session.add(user)                del session['mail']                #修改完後回登入頁                return redirect('/login')            else:                errMsg = "Passwords does not match"                return render_template('reset_pwd2.html', errMsg=errMsg)        email = request.form['email']        user = User.query.filter_by(mail=email).first()        if user:            session['mail'] = user.mail            return render_template('reset_pwd2.html')        else:            errMsg = "Wrong email.Please try again"            return render_template('reset_pwd1.html', errMsg=errMsg)#驗證email訪問路徑@main.route('/check_email')def check_email_views():    email = request.args['email']    user = User.query.filter_by(mail=email).first()    if user:        result = {"errMsg":" "}    else:        result = {"pass":" "}    return json.dumps(result)#驗證username訪問路徑@main.route('/check_username')def check_username_views():    username = request.args['username']    user = User.query.filter_by(username=username).first()    if user:        result = {"errMsg":" "}    else:        result = {"pass":" "}    return json.dumps(result)#購買頁面的訪問路徑@main.route('/purchase', methods=['POST', 'GET'])def purchase_views():    username = session['uname']    if request.method == 'GET':        return render_template('purchase.html', params=locals())    else:        print(request.form)        purchase_info = PurchaseInfo()        purchase_info.loc_length = request.form['length']        purchase_info.loc_width = request.form['width']        purchase_info.location = request.form['location']        purchase_info.monitor_num = request.form['monitor_num']        purchase_info.connect = request.form['connection']        purchase_info.user_id = session['id']        purchase_info.datetime = dt.now()        db.session.add(purchase_info)        db.session.commit()        return redirect('/monitor')#監控功能頁面的訪問路徑@main.route('/monitor', methods=['POST', 'GET'])def monitor_views():    username = session['uname']    purchase_info = PurchaseInfo.query.filter_by(user_id=session['id']).first()    monitor_num = purchase_info.monitor_num    if request.method == 'GET':        return render_template('monitor.html', params=locals())    else:        print(request.form)        D = {}        for i in range(1, monitor_num + 1):            d = {}            for monitor in request.form.getlist('features' + str(i)):                d[monitor] = []            D['node' + str(i)] = d        session['node_info1'] = D        # node_info = NodeInfo()        # node_info.node_info = str(D)        # node_info.purchase_id = purchase_info.sn        # db.session.add(node_info)        # db.session.commit()        return redirect('/module')#模組頁面的訪問路徑@main.route('/module', methods=['POST', 'GET'])def module_views():    username = session['uname']    user = User.query.filter_by(username=username).first()    purchase_id = user.purchase_info.sn    # node_info = NodeInfo.query.filter_by(purchase_id=purchase_id).first()    # node_info = node_info.node_info    if request.method == 'GET':        #將字串變成字典(eval函數:用来执行一个字符串表达式,并返回表达式的值)        # node_info = eval(node_info)        node_info = session['node_info1']        print(node_info)        D = {}        for node in node_info:            l = []            for monitor in node_info[node]:                l.append(monitor)            D[node] = l        sort_L = []        #從node1開始往後按順序排        for i in range(1, len(D) + 1):            sort_L.append(D['node' + str(i)])        sensors = SensorList.query.all()        sensor_list = []        for sensor in sensors:            sensor_list.append(sensor.toDict())        return render_template('module.html', params=locals())    else:        monitor_num = user.purchase_info.monitor_num        D = session['node_info1']        #深拷貝區分session['node_info1']與session['node_info2']        A = copy.deepcopy(D)        for i in range(1, monitor_num + 1):            try:                for module in request.form.getlist('weather_module' + str(i)):                    A['node' + str(i)]['weather'].append(module)            except Exception as e:                pass            try:                for module in request.form.getlist('irrigation_module' + str(i)):                    A['node' + str(i)]['irrigation'].append(module)            except Exception as e:                pass            try:                for module in request.form.getlist('water_module' + str(i)):                    A['node' + str(i)]['water'].append(module)            except Exception as e:                pass        session['node_info2'] = A        return redirect('/list')#清單頁面的訪問路徑@main.route('/list', methods=['POST', 'GET'])def list_views():    username = session['uname']    purchase_info = PurchaseInfo.query.filter_by(user_id=session['id']).first()    D = session['node_info2']    if request.method == 'GET':        sort_L = []        for i in range(1, len(D) + 1):            sort_L.append(json.dumps(D['node' + str(i)]))        sensors = SensorList.query.all()        sensor_list = []        for sensor in sensors:            sensor_list.append(sensor.toDict())        return render_template('list.html', params=locals())    else:        user = User.query.filter_by(username=username).first()        user.status = 2        session['status'] = user.status        print(session['node_info2'])        node_info = NodeInfo()        node_info.node_info = str(session['node_info2'])        node_info.user_id = session['id']        db.session.add(node_info)        db.session.add(user)        db.session.commit()        return redirect('/register_number')#過濾前端傳過來文件副檔名函數def allowed_file(filename):    return '.' in filename and \           filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS#登錄序號頁面1的訪問路徑@main.route('/register_number', methods=['POST', 'GET'])def register_number_views():    username = session['uname']    purchase_info = PurchaseInfo.query.filter_by(user_id=session['id']).first()    node_info = NodeInfo.query.filter_by(user_id=session['id']).first()    D = eval(node_info.node_info)    if request.method == 'GET':        sort_L = []        for i in range(1, len(D) + 1):            sort_L.append(json.dumps(D['node' + str(i)]))        sensors = SensorList.query.all()        sensor_list = []        for sensor in sensors:            sensor_list.append(sensor.toDict())        return render_template('register_number.html', params=locals())    else:        #使用geocoder庫找經緯度        def get_coordinate(addr):            g = geocoder.arcgis(u"" + addr)            lat, lng = g.latlng            return lat, lng        #使用Geocoding API找經緯度        # def get_coordinate(addr):        #     url = 'https://maps.googleapis.com/maps/api/geocode/json'        #     params = {'sensor': 'false', 'address': addr, 'key': 'AIzaSyDKVm-6LBJqxrDJLEzJujGjZLVTfK0RiAE'}        #     r = requests.get(url, params=params)        #     results = r.json()['results']        #     location = results[0]['geometry']['location']        #     lat, lng = location['lat'], location['lng']        #     return lat, lng        #爬蟲查找地址經緯度函數        # def get_coordinate(addr):        #     options = webdriver.ChromeOptions()        #     options.add_argument("headless")        #     browser = webdriver.Chrome(executable_path='chromedriver', options=options)        #     browser.get("https://www.map.com.tw/")        #     search = browser.find_element_by_id("searchWord")        #     search.clear()        #     search.send_keys(addr)        #     browser.find_element_by_xpath("/html/body/form/div[10]/div[2]/img[2]").click()        #     time.sleep(2)        #     iframe = browser.find_elements_by_tag_name("iframe")[1]        #     browser.switch_to.frame(iframe)        #     coor_btn = browser.find_element_by_xpath("/html/body/form/div[4]/table/tbody/tr[3]/td/table/tbody/tr/td[2]")        #     coor_btn.click()        #     coor = browser.find_element_by_xpath("/html/body/form/div[5]/table/tbody/tr[2]/td")        #     coor = coor.text.strip().split(" ")        #     lat = coor[-1].split(":")[-1]        #     lng = coor[0].split(":")[-1]        #     browser.quit()        #     return lat, lng        # 創建農場圖片資料夾,檔名為用戶名        if not os.path.exists(app.config['UPLOAD_FOLDER'] + '//' + session['uname']):            os.mkdir(app.config['UPLOAD_FOLDER'] + '//' + session['uname'])        location = request.form['location']        file = request.files['filename']        farm_info = FarmInfo()        if file and allowed_file(file.filename):            # 避免檔名為類似 /../../../ filename的Directory traversal attack 發生            filename = secure_filename(file.filename)            path = os.path.join(app.config['UPLOAD_FOLDER'], session['uname'], filename)            if '\\' in path:                path = path.replace('\\','/')            #這個儲存的格式/或\對f.save來說不會報錯            file.save(path)            farm_info.path = path        if not location:            pass        else:            farm_info.location = location            lat, lng = get_coordinate(location)            farm_info.loc_lat = lat            farm_info.loc_lng = lng        farm_info.user_id = session['id']        current_time = dt.now()        farm_info.datetime = current_time        db.session.add(farm_info)        D = request.form.to_dict()        for module in D:            if module != 'location':                module_sn_num = ModuleSerialNumber()                module_sn_num.module_name = module                module_sn_num.sn_number = D[module]                module_sn_num.user_id = session['id']                module_sn_num.datetime = current_time                db.session.add(module_sn_num)        db.session.commit()        return redirect('/register_number2')#登錄序號頁面2的訪問路徑@main.route('/register_number2', methods=['POST', 'GET'])def register_number2_views():    username = session['uname']    farm_info = FarmInfo.query.filter_by(user_id=session['id']).first()    purchase_info = PurchaseInfo.query.filter_by(user_id=session['id']).first()    monitor_num = purchase_info.monitor_num    if request.method == 'GET':        path = farm_info.path        if path == '0':            path = False        lat = farm_info.loc_lat        lng = farm_info.loc_lng        if lat== '0' or lng == '0':            lat = False            lng = False        return render_template('register_number2.html', params=locals())    else:        current_time = dt.now()        for i in range(1, monitor_num + 1):            node = NodePosition()            node.node_name = "Nr." + str(i)            if i < 10:                node.pos_lat = request.form['lat0' + str(i)]                node.pos_lng = request.form['lng0' + str(i)]            else:                node.pos_lat = request.form['lat' + str(i)]                node.pos_lng = request.form['lng' + str(i)]            node.user_id = session['id']            node.datetime = current_time            db.session.add(node)        files = request.files.getlist('filename')        num = 1        current_time = dt.now()        for file in files:            if file and allowed_file(file.filename):                # 避免檔名為類似 /../../../ filename的Directory traversal attack 發生                filename = secure_filename(file.filename)                path = os.path.join(app.config['UPLOAD_FOLDER'], session['uname'], filename)                file.save(path)                node_img = NodeImage()                node_img.path = path                node_img.node_name = 'Nr.' + str(num)                node_img.user_id = session['id']                node_img.datetime = current_time                db.session.add(node_img)            num += 1        db.session.commit()        return redirect('/schedule')#排程設定的訪問路徑@main.route('/schedule', methods=['POST', 'GET'])def schedule_views():    username = session['uname']    if request.method == 'GET':        return render_template('schedule.html', params=locals())    else:        pass#用戶農場的訪問路徑@main.route('/map', methods=['POST', 'GET'])def map_views():    username = session['uname']    farm_info = FarmInfo.query.filter_by(user_id=session['id']).first()    purchase_info = PurchaseInfo.query.filter_by(user_id=session['id']).first()    monitor_num = purchase_info.monitor_num    nodes = NodePosition.query.filter_by(user_id=session['id']).all()    if request.method == 'GET':        path = farm_info.path        if path == '0':            path = False        lat = farm_info.loc_lat        lng = farm_info.loc_lng        return render_template('map.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']        del session['status']    return redirect('/')
 |