一.项目介绍
本项目基于BeagleBone® Black平台(以下简称BBB),实现任务二:在系统中建立一个网页,并且与LED联动,使用网线连接到设备上时,可以从网页中控制LED的开关与闪烁。
二.设计思路
2.1 系统架构
在BBB板上创建一个基于Flask的Web服务器,该服务器允许用户通过网络浏览器访问HTML页面,并通过该页面上的交互元素来控制连接到BBB板的LED灯。用户可以通过输入BBB板的IP地址和指定端口号来访问Web界面,进而实现对LED的开关控制。
2.2 硬件介绍
如下图所示,PC电脑和BBB各通过一条以太网线与路由器相连,形成局域网络。led实现使用BBB板载的四个led灯。
2.3 配置说明
整个局域网络的ip地址由路由器静态分配,其中路由器地址为192.168.2.1,为BBB分配的ip地址为192.168.2.28,pc端的ip地址为192.168.2.10,该应用的端口号选择4000,不与其他应用冲突。
在/etc/systemd/中创建一个服务led_control.service,用于上电启动python文件Eth_Flask_Local.py,led_control.service配置如下。
[Unit]
Description=My Python Script
After=network.target multi-user.target
[Service]
Type=simple
User=debian
ExecStart=/usr/bin/python3.7 /var/lib/cloud9/BeagleBone/Black/Eth_Flask_Local.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
第三部分:功能介绍
3.1 前端功能实现
使用HTML、CSS以及JavaScript实现前端功能。
设置页面标题为“LED Control”,创建一个CSS样式类.button用于统一按钮外观和行为,其中:hover伪类用于鼠标悬停在按钮上时改变背景颜色,:active伪类用于按钮被按下时调整背景颜色和阴影位置,模拟物理按钮的按下效果。
<head>
<meta charset="UTF-8">
<title>LED Control</title>
<style>
.button {
display: inline-block;
padding: 10px 20px;
margin: 10px;
font-size: 16px;
cursor: pointer;
text-align: center;
text-decoration: none;
outline: none;
color: #fff;
background-color: #4CAF50;
border: none;
border-radius: 15px;
box-shadow: 0 9px #999;
}
.button:hover {background-color: #3e8e41}
.button:active {
background-color: #3e8e41;
box-shadow: 0 5px #666;
transform: translateY(4px);
}
</style>
</head>
主标题显示“Control LEDs”,放置4个容器分别用于4个led灯的控制,每个led灯分别设置3个按钮:"Turn on"、"Turn off"、"Blink",每个按钮使用一个onclick
事件处理程序,当用户点击时会调用相应的JavaScript函数(s
endCommand
)来发送命令给服务器。
<div>
<h2>LED 1</h2>
<button onclick="sendCommand(1)" class="button">Turn On</button>
<button onclick="sendCommand(2)" class="button">Turn Off</button>
<button onclick="sendCommand(3)" class="button">Blink</button>
</div>
<div>
<h2>LED 2</h2>
<button onclick="sendCommand(11)" class="button">Turn On</button>
<button onclick="sendCommand(12)" class="button">Turn Off</button>
<button onclick="sendCommand(13)" class="button">Blink</button>
</div>
<div>
<h2>LED 3</h2>
<button onclick="sendCommand(21)" class="button">Turn On</button>
<button onclick="sendCommand(22)" class="button">Turn Off</button>
<button onclick="sendCommand(23)" class="button">Blink</button>
</div>
<div>
<h2>LED 4</h2>
<button onclick="sendCommand(31)" class="button">Turn On</button>
<button onclick="sendCommand(32)" class="button">Turn Off</button>
<button onclick="sendCommand(33)" class="button">Blink</button>
</div>
async function sendCommand(command):异步函数,用于向服务器发送控制LED的命令。
参数command:表示要执行的操作,如开启、关闭或闪烁特定的LED。命令值根据按钮的不同而变化。
fetch API:使用fetch函数发起HTTP POST请求到服务器的/led端点,同时传递一个包含command键值对的JSON字符串作为请求体。
await response.json():等待服务器返回的数据并解析为JavaScript对象。
async function sendCommand(command) {
const response = await fetch(`/led`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ command: command })
});
const data = await response.json();
document.getElementById('response').innerText = `Result: ${data.result}`;
}
3.2 指令执行功能实现
使用python实现Flask服务器和控制gpio使led闪烁功能。
首先在主函数中初始化global_led_flag列表,将其所有元素设置为False,这表示所有LED灯初始状态下都不闪烁。然后启动后台线程,依次调用start_background_thread0()到start_background_thread3()函数,分别创建并启动四个后台线程,用于控制每个LED灯的闪烁行为。最后调用app.run(host='0.0.0.0', port=4000)来启动Flask Web服务器,监听所有网络接口上的4000端口。这意味着任何连接到BBB板所在网络的设备都可以通过IP地址和4000端口访问这个Web服务器。
# 如果这个文件是主程序,启动Flask应用
if __name__ == '__main__':
global_led_flag = [False,False,False,False]
print(global_led_flag)
start_background_thread0()
start_background_thread1()
start_background_thread2()
start_background_thread3()
app.run(host='0.0.0.0', port=4000)
# 创建led灯闪烁线程函数
def start_background_thread0():
thread = threading.Thread(target=led_blingbling_task0)
thread.daemon = True
thread.start()
def start_background_thread1():
thread = threading.Thread(target=led_blingbling_task1)
thread.daemon = True
thread.start()
def start_background_thread2():
thread = threading.Thread(target=led_blingbling_task2)
thread.daemon = True
thread.start()
def start_background_thread3():
thread = threading.Thread(target=led_blingbling_task3)
thread.daemon = True
thread.start()
home()函数用于flask服务器的应用主页
@app.route('/')
def home():
return render_template('led.html')
接收和处理信息的函数如下,若有预检请求进行处理,允许前端从不同域访问此API端点。获取和解析POST请求中的JSON数据,command的十位为用于控制哪颗le灯,个位用于控制led灯状态,分别通过整除和取余进行区分。若为闪烁,则给全局变量global_led_flag置位,在其余四个led灯闪烁线程会对此全局变量进行处理。处理结束后返回结果JSON数据。
# 定义一个POST请求的API端点,用于执行命令
@app.route('/led', methods=['POST', 'OPTIONS'])
def post_command():
if request.method == "OPTIONS":
# 处理预检请求
return '', 204
data = request.json # 获取POST请求中的JSON数据
command = data.get('command') # 从JSON数据中提取命令
#print(f"Received command: {command}, type: {type(command)}")
if command:
ledNumber = command // 10
ledStatus = command % 10
#result = execute_command(command) # 执行命令
global global_led_flag
global_led_flag[ledNumber] = False
print(global_led_flag)
if ledStatus == 1 :
GPIO.output("USR%d" % ledNumber, GPIO.HIGH)
elif ledStatus == 2:
GPIO.output("USR%d" % ledNumber, GPIO.LOW)
elif ledStatus == 3:
global_led_flag[ledNumber] = True
print(global_led_flag)
return jsonify({'result': 'Executed successfully'}), 200
else:
return jsonify({'error': 'No command provided'}), 400
4个线程分别被相应的全局变量控制,闪烁时以0.5s每次的频率闪烁。
# led灯闪烁函数
def led_blingbling_task0():
while True:
while global_led_flag[0]:
GPIO.output("USR%d" % 0, GPIO.HIGH)
time.sleep(0.5)
if global_led_flag[0]:
GPIO.output("USR%d" % 0, GPIO.LOW)
time.sleep(0.5)
def led_blingbling_task1():
while True:
while global_led_flag[1]:
GPIO.output("USR%d" % 1, GPIO.HIGH)
time.sleep(0.5)
if global_led_flag[1]:
GPIO.output("USR%d" % 1, GPIO.LOW)
time.sleep(0.5)
def led_blingbling_task2():
while True:
while global_led_flag[2]:
GPIO.output("USR%d" % 2, GPIO.HIGH)
time.sleep(0.5)
if global_led_flag[2]:
GPIO.output("USR%d" % 2, GPIO.LOW)
time.sleep(0.5)
def led_blingbling_task3():
while True:
while global_led_flag[3]:
GPIO.output("USR%d" % 3, GPIO.HIGH)
time.sleep(0.5)
if global_led_flag[3]:
GPIO.output("USR%d" % 3, GPIO.LOW)
time.sleep(0.5)
3.3 软件流程图
第四部分:功能展示
BBB上电等待系统初始化完成,打开浏览器访问http://192.168.2.28:4000/加载出LED Control界面
此时四个灯全部熄灭
点击LED 2的Turn On按键,第二个灯亮起。
点击LED 3 Blink按键,第三个灯开始闪烁,具体可见视频,点击Turn Off灯熄灭。
总结及心得体会
本项目成功地在BeagleBone Black上搭建了一个基于Flask的Web服务器,并实现了远程控制led灯开关和闪烁的功能。在实现功能的过程中,从选择方案开始我就走了很多弯路,但经过了这个项目,我从一个对网络编程一无所知的小小白,到现在对web服务器略有了解,并进行实践,迈出了我个人的一大步,感到很有成就感,非常感谢这次活动。
如果要说有什么意见建议,那就是还是期待主办方提供更多的课程或者资料支持,交流群中有很多大佬,也有如我这样的小白,希望后面的小伙伴可以少走一些弯路,学到更多有用的实用的技能。
再次感谢硬禾学堂。