Khởi tạo và Thực hiện chương trình (Tham khảo tại Readme.md)

Một phần của tài liệu Hệ thống bảng giá kệ sử dụng bluetooth 5.0 và màn hình E- ink (phần mềm + phần cứng ) của gateway (Trang 45)

7. KẾT CẤU CỦA ĐỒ ÁN

4.11 Khởi tạo và Thực hiện chương trình (Tham khảo tại Readme.md)

Bước 1: Tạo Application cho Web [9]

Bước 2: Thu thập các Nhiệm vụ mà Web sẽ phải thực hiện 4.12 Khởi động Gate Way trên Raspberry pi:

Để khởi động Gate Way trên Raspberry thì cần sử dụng 3 dịng code trong terminal:

• cd ~/Desktop/bluetag

• source env/bin/activate

• python3 main.py

Sau khi đánh xong dòng lệnh thứ 3, đoạn code sẽ hiện lên IP address của Gate Way, click chuột phải vào IP address và click open URL để vào Gate Way

37

Chương 5

THI CÔNG

5.1 Sử dụng Gate Way Bluetag: 5.1.1 Trang Login: 5.1.1 Trang Login:

Sau khi vào được Gate Way có tên là Bluetag, trang đầu tiên hiện lên trên màn hình sẽ trang Login ( đăng nhập):

Hình 5.1: Trang Login của Gate Way

Login name: bluetag Password: bluetag

Sau khi nhập thành công Login name và Password, Gate Way sẽ chuyển tiếp sang giao diện mới, trang này có chức năng quản lý phần hiển thị của các bảng giá đã được kết nối, cập nhật tên, giá của bảng giá cũ hoặc thêm bảng giá mới

38

5.1.2 Trang chào:

Hình 5.2: Giao diện trang chào

5.1.3 Trang Làm việc các kết nối cũ:

Hình 5.3: Giao diện quản lý thiết bị Trang này được nằm mục Slave ở bên trái màn hình Trang này được nằm mục Slave ở bên trái màn hình

39

Scan for new slaves: Dùng để quét thiết bị mới

Refresh slave list: làm mới danh sách thiết bị đã kết nối

Edit: Cập nhật tên hoặc giá cho nhiều màn hình

Trong trường hợp muốn cập nhật tên và giá của 1 màn hình, click vào Details của thiết bị muốn được cập nhật

Hình 5.4: Giao diện chi tiết của thiết bị đã kết nối Trong giao diện này có 3 thơng tin có thể thay đổi hoặc cập nhật Trong giao diện này có 3 thơng tin có thể thay đổi hoặc cập nhật

Product name: hiển thị tên sản phẩm

Product price: hiển thị giá sản phẩm

Device name: tên của bảng giá hiển thị 5.1.4 Trang làm việc với kết nối mới

40

Hình 5.5: Giao diện hiển thị kết nối mới

Nút Re-scan có chức năng để quét lại, làm mới danh sách thiết để thuận tiện hơn cho việc tìm kiếm kết nối mới.

Một khi chọn được thiết bị mới để kết nối, bấm vào nút Detail, sau đó web sẽ hiện lên thơng tin chi tiết để đặt tên cho thiết bị đó. Ở mục Add device, Device name, bằng cách đặt tên cho thiết bị mới (tên: màn hình 6) và bấm nút Add this

device. Toàn bộ giao thức này được sử dụng trên nền tảng WAP-HTML và cơng cụ

41

Hình 5.6: Thơng tin chi tiết kết nối mới

Sau đó thiết bị này sẽ được lưu lại và cho vào danh sách thiết bị đã kết nối.

42

5.1.5 Trang làm việc với nhiều thiết bị cùng 1 lúc:

Trong trường hợp muốn cập nhật tên và giá từ 2 màn hình trở lên, click vào Edit, mục Product name và Product price sẽ có thể cập nhật được tên và giá mới ngay trên danh sách thiết bị đã nối thay vì phải click vào Detail của từng thiết bị.

Sau khi nhập xong tên và giá mới, click vào Display, gate way sẽ gửi dữ liệu mới vào các màn hình cần phải cập nhật tên và giá mới.

43

5.1.6 Trang Đổi pass

Trang đổi mật khẩu được nằm trong mục System ở bên trái màn hình

Hình 5.9: Giao diện đổi mật khẩu

Login name: Tên đăng nhập.

Old password: Mật khẩu cũ.

New password: Mật khẩu mới.

Re-type new password: Nhập lại mật khẩu mới. 5.2 Thao tác trang Web với màn hình E-inks:

Sau khi nhập tên và giá cho sản phẩm , click vào Display product name và

Display product price, Gate Way sẽ truyền dữ liệu cho bảng giá hiển thị qua bluetooth

44

Hình 5.10: Hiện thị tên và giá trên màn hình E-ink

Refresh Display được dùng cho trường hợp khi chữ hiển thị trên màn hình E-ink bị

mờ đi hoặc theo thời gian, giúp làm mới màn hình và hiển thị chữ rõ như ban đầu.

45

Chương 6

ĐÁNH GIÁ KẾT QUẢ, KẾT LUẬN

6.1 Kết quả đạt được của hệ thống:

Khả năng truyền nhận của Gate way với màn hình E-ink ổn Dữ liệu hoạt động ngoài thực tế:

Khoảng cách truyền nhận 10 – 13 m Thời gian nhãn kệ thay đổi 1 – 3 giây Số lượng kết nối cùng lúc 10+

Bảng 6.1: Số liệu ngoài thực tế Sự đổi mới :

Thay vì phải sử dụng mã code arduino và internet cho mỗi lần thay đổi thì với Website này, ta có thể tiết kiệm được một khoảng thời gian và không cần phải chi trả thêm cho kết nối internet bằng dây cáp mạng.

Điều đó sẽ thay đổi một phần khơng nhỏ đến kinh tế và sự chính xác trong khâu bán hàng , quản lí

6.2 Lỗi mà hệ thống gặp phải:

Theo kết quả quan sát được, nhóm đã nhận định lỗi mà Gate way gặp phải khi truyền dữ liệu đồng loạt cho nhiều màn hình E-ink (2 loại lỗi)

Thứ nhất là lỗi ưu tiên, nghĩa là trong quá trình thiết lập kết nối với màn hình E-ink mới thì Gate way sẽ làm tạo kết nối với từng màn hình E-ink riêng biệt. Nhưng khi đổi hay cập nhật dữ của các màn hình E-ink đó thì Gate way chỉ ưu tiên và cho phép thiết bị kết nối đầu tiên (ở trên cùng của danh sách thiết bị đã kết nối) đổi thành dữ liệu mới, cịn các màn hình

Thứ hai là lỗi dung lượng truyền. Đây là hiện tượng trang web nhận 1 lượng dung lượng thông tin nhất định nhưng không chia luồng và gói. Dẫn đến tình trạng tồn bộ dung lượng thơng tin truyền thẳng vào màn hình ưu tiên từ đó dẫn đến số

46

lượng thơng tin cịn lại bị xem là thừa , bộ xử lí phía màn hình tự động loại bỏ khi nhận đủ thơng tin của riêng nó.

6.3 Phương pháp giải quyết và khắc phục:

Đối với lỗi thứ nhất:

Nhóm nhận thấy việc ưu tiên thường do kiểu truyền thông tin nối tiếp . Vậy nên việc thay đổi thành kiểu truyền song hành sẽ là lựa chọn thích hợp tại Pi.

Đối với lỗi thứ hai:

Nhóm nhận thấy việc ngắt lượng thơng tin thành gói thơng tin sẽ cho phép màn hình nhận đúng phần gói thơng tin của nó và tránh bị lược bỏ gói thơng tin của những màn hình khác.

Vì tình trạng dịch bệnh nên nhóm hiện tại vẫn chưa thể tương tác trực tiếp để sửa chữa lỗi .

6.4 Hướng phát triển của đề tài:

Sự phát triển của cơng nghệ là địi hỏi tốc độ và quy mơ ảnh hưởng nên đồ án này có thể được nâng lên khơng cịn quản lí ở một cửa hàng nhỏ trong một chuỗi cửa hàng.

Sự đi lên của đồ án sẽ là một server cho cả một hệ thống : - Điều khiển từ rất xa thông qua một trang web có miền - Điều khiển được rất nhiều Raspberry

- Nắm giữ thông tin và sự thay đổi cấp thiết , nhanh chóng và chính xác của tồn hệ thống

- Hệ thống có thể biến hóa theo mong muốn của các cơng ty mà vẫn giữ được giá trị cốt lõi của đồ án

47

48

TÀI LIỆU THAM KHẢO

Với tài liệu báo chí:

1. R. Fernández, E. Z. Casanova and I. G. Alonso. “Review of display technologies focusing on power consumption”. Sustainability, vol. 7, no. 8,

pp. 10854-10875, Aug. 2015.

2. J. K. Borchardt. “Developments in organic displays”. Mater. Today, vol. 7, no. 9, pp. 42-46, Sep. 2004.

3. J. Sung. “End of paper labels: Emerging smart labels toward Internet of Things”. Proc. IEEE 2nd World Forum Internet Things (WF-IoT), Dec. 2015, pp. 216-221.

Với tài liệu có từ Internet

1. Trang chủ : W3S :Ngơn ngữ và hướng dẫn cơ bản lập trình HTML.

https://www.w3schools.com/tags/default.asp

Ngày truy cập: 20/5/2021

2. Youtube: HTML5 & CSS Development: Learn How to Build a Professional Website | Udemy, Jordan Hudgens – Tác giả : Udemy.

https://www.youtube.com/watch?v=5bMdjkfvONE

Ngày truy cập: 20/5/2021

3. Youtube : Python Website Full Tutorial - Flask, Authentication, Databases & More – Tác giả : Tech with Tim.

https://www.youtube.com/watch?v=dam0GPOAvVI

Ngày truy cập: 24/5/2021

4. Youtube: How To Make Website Using HTML & CSS | Full Responsive Multi Page Website Design Step by Step – Tác giả : Easy Tutorials

https://www.youtube.com/watch?v=oYRda7UtuhA

Ngày truy cập: 24/5/2021

5. Trang chủ : Raspberry OS - Raspberry ORG.

https://www.raspberrypi.org/software/

49

6. Diễn đàn công nghệ thông tin: Chủ đề: Thiết kế web

https://github.com/topics/website-design

Ngày truy cập: 10/6/2021

7. Trang chủ nền tảng xây dụng web: Phần mềm - Flask

https://flask.palletsprojects.com/en/2.0.x/

Ngày truy cập: 12/6/2021

8. Youtube : BLE DEMO ON PI – Tác giả : Tomy Vithayathil

https://www.youtube.com/watch?v=RxH5nM3eP5Q\

Ngày truy cập: 15/6/2021

9. Diễn đàn công nghệ thông tin: Chủ đề: Sử dụng code để thiết lập nhiệm vụ cho BLE

https://github.com/search?q=ble

Ngày truy cập: 15/6/2021

10. Trang chủ: Phần mềm : Bleak, Bleak Introduction.

https://buildmedia.readthedocs.org/media/pdf/bleak/stable/bleak.pdf

Ngày truy cập:18/6/2021

50

PHỤ LỤC

1. Phụ lục linh kiện:

Thông số kỹ thuật của raspberry pi zero w:

• 802.11 b/g/n wireless LAN

• Bluetooth 4.1

• Bluetooth Low Energy (BLE)

• Phần cịn lại, máy tính nhúng Raspberry Pi Zero W có cấu hình tương tự người tiền nhiệm:

• Chip BCM2835 tốc độ 1GHz (nhanh hơn 40% cho với Pi 1)

• 512MB RAM

• Cổng Mini HDMI

• Cổng USB On-The-Go

• Cổng nguồn Micro USB

• Chân gắm GPIO 40 chân

• Có chân cắm cổng Composite video và reset máy.

• Cổng CSI cho camera

• Kích thước: 66.0mm x 30.5mm x 5.0mm

Thơng số kỹ thuật của raspberry pi 4:

• Broadcom BCM2711, Quad core Cortex-A72 (ARM v8) 64-bit SoC @ 1.5GHz

• Có 3 lựa chọn RAM: 2GB, 4GB hoặc 8GB LPDDR4-2400 SDRAM • Wifi chuẩn 2.4 GHz và 5.0 GHz IEEE 802.11ac. Bluetooth 5.0, BLE • Cổng mạng Gigabit Ethernet

• 2 cổng USB 3.0 và 2 cổng USB 2.0

• Chuẩn 40 chân GPIO, tương thích với các phiên bản trước

• Hỗ trợ 2 cổng ra màn hình chuẩn Micro HDMI với độ phân giải lên tới 4K • Cổng MIPI DSI

51 • Cổng MIPI CSI

• Cổng AV 4 chân

• H.265 (4kp60 decode), H264 (1080p60 decode, 1080p30 encode) • OpenGL ES 3.0 graphics

• Khe cắm Micro-SD cho hệ điều hành và lưu trữ • Nguồn điện DC 5V – 3A DC chuẩn USB-C • 5V DC via GPIO header (minimum 3A*)

• Hỗ trợ Power over Ethernet (PoE) (yêu cầu có PoE HAT)

2. Phụ lục code:

.vscode launch.json {

// Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes.

// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0",

"configurations": [ {

"name": "Python: Flask", "type": "python", "request": "launch", "module": "flask", "env": { "FLASK_APP": "app.py", "FLASK_ENV": "development", "FLASK_DEBUG": "1", }, "args": [ "run",

52 "--no-debugger" ], "jinja": true } ] } settings.json { "python.pythonPath": "env/bin/python" } __pycache__

app.cpython-37.pyc (tài liệu mã hoá) api

__pycache__

auth.cpython-37.pyc (tài liệu mã hoá) slave.cpython-37.pyc (tài liệu mã hoá) system.cpython-37.pyc (tài liệu mã hoá) auth.py

from flask import request, Blueprint, current_app import datetime

from functools import wraps

from core.data import responses as resp from core.cypherutil import *

from core.datetimeutil import * from core import logging as log

from core.data.database import *

53

bp = Blueprint("api/auth", __name__, url_prefix="/api/auth")

def authorize(f): @wraps(f)

def decorator(*args, **kwargs): try:

token=None

if 'access-token' in request.headers: token = request.headers['access-token'] if not token: return resp.create('-2', 'Token is missing')

data = jwt.decode(token, current_app.config['SECRET_KEY']) db= dbconnect() user = db.execute(dbquerry.get_user()).fetchone() dbclose(db) if user['login_name'] != data['login_name']: return resp.create('-2', 'Wrong user name')

if data['expired'] < datenum(datetime.datetime.utcnow()): return resp.create('-2', 'Token expired')

return f(*args, **kwargs) except:

log.error("Authorize error")

return resp.create('-2', 'Authorize error') return decorator

54 def login():

request_data = request.get_json()

if not request_data: return resp.create('-1', 'Missing request body') if not 'name' in request_data: return resp.create('-1', 'The field \'name\' is required')

if not 'pwd' in request_data: return resp.create('-1', 'The field \'pwd\' is required') hashpwd = create_hash(request_data['pwd']) login_name= request_data['name'] login_pwd= hashpwd db= dbconnect() user = db.execute(dbquerry.get_user()).fetchone() dbclose(db)

if user['login_name'] != login_name: return resp.create('-1', 'Wrong user name') if user['login_pwd'] != login_pwd: return resp.create('-1', 'Wrong password login')

# todo: login with real info

now= datetime.datetime.utcnow() + datetime.timedelta(minutes= 30) ip= request.environ.get('HTTP_X_REAL_IP', request.remote_addr) token_data= {

'login_name': login_name, 'ip': ip,

55 }

tokenBytes = token_encode(token_data, current_app.config['SECRET_KEY']) token = tokenBytes.decode('utf-8')

log.event(f'{login_name} logged in, loc: {ip}') return resp.create('0', 'Login success', {

'token': token,

'expired': formatted_date_str(now) })

slave.py

from flask import * import threading

from core.data import responses as resp from core.data.database import dbconnect from core import bleutils as ble

from core.data.database import *

from core.data import querry as dbquerry import uuid

import traceback

from api.auth import authorize

from app import get_threads, init_threads, remove_threads import time

bp = Blueprint("api/slave", __name__, url_prefix="/api/slave")

@bp.route('/all', methods=['GET']) @authorize

56 data= [] init_threads() db= dbconnect() dbdata= db.execute(dbquerry.get_slave()) for row in dbdata:

runtime= 0

def x(y): ble.bleappendthread(y)

threading.Thread(target=x(row['mac'])).start()

threads= get_threads() for thread in threads:

if thread['mac'] == row['mac']: runtime= 1 data.append({ 'mac': row['mac'], 'device_name': row['device_name'], 'product_name': row['product_name'], 'product_price': row['product_price'], 'run_time': runtime }) dbclose(db) print(get_threads())

57 @bp.route('/get', methods=['GET']) @authorize def get(): mac = request.args.get('mac')

if mac == None: return resp.create('-1', 'Provide a mac address to peform this action')

data= None db= dbconnect()

current_slave = db.execute(dbquerry.get_slave(mac)).fetchone()

if current_slave == None: return resp.create('-1', f'Slave with mac equals to {mac} not found')

data= { 'mac': current_slave['mac'], 'device_name': current_slave['device_name'], 'product_name': current_slave['product_name'], 'product_price': current_slave['product_price'] } dbclose(db)

return resp.success(data= data)

@bp.route('/remove', methods=['POST']) @authorize def remove(): mac = request.args.get('mac') threads= get_threads()

58 if len(threads) != 0:

for thread in threads: if thread['mac'] == mac: curr= get_threads(mac) remove_threads(curr)

db= dbconnect()

current_slave = db.execute(dbquerry.get_slave(mac)).fetchone()

if current_slave == None: return resp.create('-1', f'Slave with mac equals to {mac} not found')

db.execute(dbquerry.update_slave(current_slave['uid'], mac= mac, status_code= '-1')) db.commit() dbclose(db) return resp.success() @bp.route('/update', methods=['POST']) @authorize def update(): mac = request.args.get('mac') name = request.args.get('name') db= dbconnect() current_slave = db.execute(dbquerry.get_slave(mac)).fetchone()

if current_slave == None: return resp.create('-1', f'Slave with mac equals to {mac} not found')

db.execute(dbquerry.update_slave(current_slave['uid'], device_name = name)) db.commit()

59 dbclose(db) return resp.success() @bp.route('/scan', methods=['GET']) @authorize def scan(): device_list= ble.blescan() db= dbconnect()

for device in device_list[::-1]:

current_slave = db.execute(dbquerry.get_slave(device['mac'])).fetchone() if current_slave != None: device_list.remove(device) dbclose(db)

return resp.success(data= device_list) @bp.route('/add', methods=['POST']) @authorize def add(): req_json = request.get_json() mac= req_json['mac'] device_name= req_json['device_name'] product_name= req_json['product_name'] product_price= req_json['product_price'] ble.bleappendthread(mac)

60 db= dbconnect()

current_slave = db.execute(dbquerry.get_slave(mac)).fetchone() if current_slave != None:

dbclose(db)

return resp.create('-1', f'Slave with mac {mac} is already exists, remove it first.')

result= db.execute(dbquerry.add_slave(str(uuid.uuid4()), mac, device_name, product_name, product_price, '')) db.commit() dbclose(db) return resp.success() @bp.route('/disp-product', methods=['POST']) @authorize def display_product(): try: req_json = request.get_json() mac= req_json['mac'] product_name= req_json['product_name'] product_price= req_json['product_price'] # bleclient= ble.bleconnect(mac) listble= get_threads() # print(listble) if len(listble) == 0:

61 for x in listble: if x['mac'] == mac: bleclient = x['client'] ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, f'#{product_name}') ble.blewrite(bleclient, f'!{product_price}') ble.blewrite(bleclient, '@e') # ble.bledisconnect(bleclient) db= dbconnect() current_slave = db.execute(dbquerry.get_slave(mac)).fetchone()

result= db.execute(dbquerry.update_slave(current_slave['uid'], None, None, product_name, product_price, None, None))

db.commit() dbclose(db) return resp.success() except: traceback.print_exc() return resp.failed() @bp.route('/disp-product-name', methods=['POST']) @authorize def display_product_name(): try:

62 req_json = request.get_json() mac= req_json['mac'] product_name= req_json['product_name'] type_func= req_json['type'] if type_func == 'test': bleclient= ble.bleconnect(mac) ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, f'#{product_name}') ble.blewrite(bleclient, '@e') ble.bledisconnect(bleclient) if type_func == 'notest': listble= get_threads() # print(listble) if len(listble) == 0: return resp.failed(); for x in listble: if x['mac'] == mac: bleclient = x['client'] ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, f'#{product_name}') ble.blewrite(bleclient, '@e') db= dbconnect() current_slave = db.execute(dbquerry.get_slave(mac)).fetchone()

63

result= db.execute(dbquerry.update_slave(current_slave['uid'], None, None, product_name, None, None, None))

db.commit() dbclose(db) return resp.success() except: traceback.print_exc() return resp.failed() @bp.route('/disp-product-price', methods=['POST']) @authorize def display_product_price(): try: req_json = request.get_json() mac= req_json['mac'] product_price= req_json['product_price'] type_func= req_json['type'] if type_func == 'test': bleclient= ble.bleconnect(mac) ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, f'#{product_price}') ble.blewrite(bleclient, '@e') ble.bledisconnect(bleclient) if type_func == 'notest': # bleclient= ble.bleconnect(mac)

64 listble= get_threads() if len(listble) == 0: return resp.failed(); # print(listble) for x in listble: if x['mac'] == mac: bleclient = x['client'] ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, f'!{product_price}') ble.blewrite(bleclient, '@e') # ble.bledisconnect(bleclient) db= dbconnect() current_slave = db.execute(dbquerry.get_slave(mac)).fetchone()

result= db.execute(dbquerry.update_slave(current_slave['uid'], None, None, None, product_price, None, None))

db.commit() dbclose(db) return resp.success() except: return resp.failed() @bp.route('/disp-refresh', methods=['POST']) @authorize def display_refresh(): try: req_json = request.get_json()

65 mac= req_json['mac'] type_func= req_json['type'] if type_func == 'test': bleclient= ble.bleconnect(mac) ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, '@dr -') ble.blewrite(bleclient, '@e') ble.bledisconnect(bleclient) if type_func == 'notest': # bleclient= ble.bleconnect(mac) listble= get_threads() if len(listble) == 0: return resp.failed(); # print(listble) for x in listble: if x['mac'] == mac: bleclient = x['client'] ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, '@dr -') ble.blewrite(bleclient, '@e') # ble.bledisconnect(bleclient) return resp.success() except: return resp.failed()

66 @bp.route('/disp-refresh-all', methods=['POST']) @authorize def display_refresh_all(): try: db= dbconnect() all_slave = db.execute(dbquerry.get_slave()).fetchall() dbclose(db)

for slave in all_slave:

# bleclient= ble.bleconnect(slave['mac']) listble= get_threads()

if len(listble) == 0:

return resp.failed("No device connected"); # print(listble) for x in listble: if x['mac'] == slave['mac']: bleclient = x['client'] ble.blewrite(bleclient, '@s') ble.blewrite(bleclient, '@dr -') ble.blewrite(bleclient, '@e') # ble.bledisconnect(bleclient) return resp.success() except: return resp.failed() @bp.route('/connect', methods=['POST']) @authorize def connectSlave():

67 try: mac= request.args.get('mac') bleclient= ble.bleappendthread(mac) if bleclient is None: return resp.failed() return resp.success() except: return resp.failed() system.py

from flask import Blueprint, request from core.data import responses as resp from core.data.database import *

from core.cypherutil import *

from core.data import querry as dbquerry

Một phần của tài liệu Hệ thống bảng giá kệ sử dụng bluetooth 5.0 và màn hình E- ink (phần mềm + phần cứng ) của gateway (Trang 45)

Tải bản đầy đủ (PDF)

(115 trang)