树莓派远程音乐播放器
本文首发阿里云,之后会同步到csdn
当前功能
udp助手发送指令到云服务器
云服务器中转到树莓派
树莓派处理指令
- 放歌
- 向指定端口发送udp客户端请求的数据
- 停止放歌
- 停止程序
整体实现
整个流程实现的感觉都没有什么技术含量,让我真切地感受到了现在可能已经真的步入了一个新的万物互联的时代,其中最让我震惊的就是这个frp透穿的这个工具,真的牛皮。
环境简介
手机端操作的话去应用商店下一个网络调试助手,挑个广告少的下就行。
电脑端如果不调试的话直接下一个netAssistant ,用到的安装包都整理到云盘上了,或者也可以去支持下我的csdn付费下载,如果对你有帮助的话
电脑端如果调试的话,我这里的配置是:
pycharm + python3.9/python3.10
vscode + sshRemote(为了方便之后远程改代码)
mobaXterm(粗调用)
目前的云端就是阿里云,搭了frp的自启动,有感兴趣的可以看我前一个记录,或者自己自行搜一下树莓派frp穿透。
透穿框架
整体透穿通信框架如下:
如图所示,目前的发送和接受各玩各的,树莓派端接收手机发送的指令,可以接受指令放歌,停止放歌,展示当前歌单,终止程序。其中展示歌单的歌单会发送给pc端的网络调试助手上显示。具体工作细节如下:
- 手机/PC网络调试助手 向云端服务器指定端口1发送指令。
- 当树莓派能连到公网时,通过frp 客户端配置,将云端的指定端口1映射给自己的端口2
- 树莓派udp监控本地绑定的端口2获取到网络调试助手的消息,并解码
- 树莓派udp发送反馈信息给云服务器指定端口3
- pc端frp client 将服务器上的指定端口3映射到本地端口4
- pc端监控本地端口4获取回传信息。
代码
树莓派端python代码
import os
import vlc
import time
import _thread
from socket import * #socket模块
sing_flag = 0
mp3List = list()
thread_flag = 1
delay = 100
MediaPlayer=vlc.MediaPlayer()
def sing_song():
global sing_flag,mp3List,thread_flag,MediaPlayer,delay
start_flag = 0
while thread_flag:
if(sing_flag):
if(start_flag ==0):
MediaPlayer = vlc.MediaPlayer(mp3List[int(bytes.decode(data).split(" ")[1])])
MediaPlayer.play()
start_flag = 1
time.sleep(1)
delay = delay - 1
if(delay == 0):
MediaPlayer.stop()
sing_flag = 0
start_flag = 0
else:
start_flag = 0
# 监听端口配置 server s
HOST_LISTEN ='127.0.0.1'
PORT_LISTEN = 469
s = socket(AF_INET,SOCK_DGRAM) #定义socket类型,网络通信,UDP
#s.bind((HOST,PORT)) #套接字绑定的IP与端口
ADDR_LISTEN = (HOST_LISTEN,PORT_LISTEN)
s.bind(ADDR_LISTEN)
# 反馈端口配置 post p
HOST_SEND ='39.0.0.0'
PORT_SEND = 2000
p = socket(AF_INET,SOCK_DGRAM) #定义socket类型,网络通信,UDP
#s.bind((HOST,PORT)) #套接字绑定的IP与端口
ADDR_SEND = (HOST_SEND,PORT_SEND)
g = os.walk('/home/rui/udp')
song_num = 0
for path, d, files in g:
for filename in files:
file = os.path.join(path, filename)
if 'mp3' == file.split(".")[-1]:
mp3List.append(file)
song_num = song_num+1
t = _thread.start_new_thread(sing_song,())
while 1:
data,addr=s.recvfrom(1024) #接受udp连接,并返回新的套接字与IP地址
if(bytes.isascii(data)):
if (bytes.decode(data).split(" ")[0] == 'play'):
if (bytes.decode(data).split(" ")[1].isnumeric()):
if int(bytes.decode(data).split(" ")[1])<song_num:
sing_flag = 1
if (len(bytes.decode(data).split(" "))==3 and bytes.decode(data).split(" ")[2].isnumeric()):
delay = int(bytes.decode(data).split(" ")[2])
elif (bytes.decode(data).split(" ")[1] == 'list'):
if(len(bytes.decode(data).split(" "))==3 and bytes.decode(data).split(" ")[2].isnumeric()and int(bytes.decode(data).split(" ")[2])<song_num):
p.sendto( str.encode('The '+bytes.decode(data).split(" ")[2]+'th song is : '),ADDR_SEND)
p.sendto( str.encode(mp3List[int(bytes.decode(data).split(" ")[2])].split('/')[-1]),ADDR_SEND)
else:
p.sendto( str.encode('The all songs num is : '+str(song_num)),ADDR_SEND)
for num_i in range(0,song_num):
p.sendto( str.encode(str(num_i)+". "+mp3List[num_i].split('/')[-1]),ADDR_SEND)
elif (bytes.decode(data).split(" ")[1] == 'stop'):
if(MediaPlayer):
sing_flag = 0
MediaPlayer.stop()
# 如果发送stop 终止程序
if bytes.decode(data) == 'stop':
break
s.close() #关闭连接
PC udp监听代码
from socket import * #socket模块
HOST='127.0.0.1'
PORT=8878
s= socket(AF_INET,SOCK_DGRAM) #定义socket类型,网络通信,UDP
#s.bind((HOST,PORT)) #套接字绑定的IP与端口
ADDR = (HOST,PORT)
s.bind(ADDR)
while 1:
data,addr=s.recvfrom(1024) #接受TCP连接,并返回新的套接字与IP地址
# print ('Connected by',addr) #输出客户端的IP地址
print(bytes.decode(data))
if bytes.decode(data) == 'stop':
break
s.close() #关闭连接
指令说明
play list
向服务器指定端口发送当前路径下的mp3。
play list i
向服务器指定端口发送当前路径下的第i个mp3的名字。
play i
播放当前列表下的第i首歌,放100 秒。
play i n
播放当前列表下的第i首歌,放 n 秒。
play stop
放歌过程中,停止放歌。
stop
终止服务器程序,测试用。
下一版本规划
- 可以设定响铃时间/按周设定是否响铃
增加闹钟指令 响铃周期/次数 闹钟响铃方式
删除闹钟
向指定端口展示当前闹钟 - 可以自动列表循环播放歌单
- 可以远程调节音量
尾注
「player_v0_1」https://www.aliyundrive.com/s/QgSQ7i9t9nS 提取码: 24vf