当前位置: 首页 > news >正文

树莓派远程音乐播放器

树莓派远程音乐播放器

阿里云同步csdn

当前功能

udp助手发送指令到云服务器
云服务器中转到树莓派
树莓派处理指令
- 放歌
- 向指定端口发送udp客户端请求的数据
- 停止放歌
- 停止程序

整体实现

整个流程实现的感觉都没有什么技术含量,让我真切地感受到了现在可能已经真的步入了一个新的万物互联的时代,其中最让我震惊的就是这个frp透穿的这个工具,真的牛皮。

环境简介

手机端操作的话去应用商店下一个网络调试助手,挑个广告少的下就行。
电脑端如果不调试的话直接下一个netAssistant ,用到的安装包都整理到云盘上了,或者也可以去支持下我的csdn付费下载,如果对你有帮助的话
电脑端如果调试的话,我这里的配置是:
pycharm + python3.9/python3.10
vscode + sshRemote(为了方便之后远程改代码)
mobaXterm(粗调用)
目前的云端就是阿里云,搭了frp的自启动,有感兴趣的可以看我前一个记录,或者自己自行搜一下树莓派frp穿透。

透穿框架

整体透穿通信框架如下:
透穿通信框架.png
如图所示,目前的发送和接受各玩各的,树莓派端接收手机发送的指令,可以接受指令放歌,停止放歌,展示当前歌单,终止程序。其中展示歌单的歌单会发送给pc端的网络调试助手上显示。具体工作细节如下:

  1. 手机/PC网络调试助手 向云端服务器指定端口1发送指令。
  2. 当树莓派能连到公网时,通过frp 客户端配置,将云端的指定端口1映射给自己的端口2
  3. 树莓派udp监控本地绑定的端口2获取到网络调试助手的消息,并解码
  4. 树莓派udp发送反馈信息给云服务器指定端口3
  5. pc端frp client 将服务器上的指定端口3映射到本地端口4
  6. 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

终止服务器程序,测试用。

下一版本规划

  • 可以设定响铃时间/按周设定是否响铃
    增加闹钟指令 响铃周期/次数 闹钟响铃方式
    删除闹钟
    向指定端口展示当前闹钟
  • 可以自动列表循环播放歌单
  • 可以远程调节音量

尾注

东西近期上传到阿里云盘和csdn.

相关文章:

  • LeetCode用数组建立二叉树
  • Leetcode560. 和为 K 的子数组
  • Docker部署Tomcat
  • NFT交易量下滑 传统品牌布局热情未衰
  • 2022下半年各省软考报名费用汇总,不知道的看这里
  • 社交网络的数据挖掘与分析,什么是社交网络分析
  • Allegro DVT与SiMa.ai携手优化嵌入式边缘应用的能效
  • 2022-8-30 第七小组 学习日记 (day54)JavaWeb、Servlet、HTTP-请求 响应、乱码问题
  • U9二次开发之BE插件开发
  • 推荐系统-Hive基础
  • 通信原理 | 基本概念:信源、信道、噪声、信宿等
  • 关于Flask高级_RequestParser中的add_argument方法参数详解
  • flume系列之:基于zookeeper部署flume agent升级guava和curator版本
  • 触摸控件——滑动调节
  • NetApp与VMware和AWS合作,帮助客户实现云端企业工作负载的现代化和扩展
  • Angular Elements 及其运作原理
  • Brief introduction of how to 'Call, Apply and Bind'
  • export和import的用法总结
  • HashMap剖析之内部结构
  • IndexedDB
  • java第三方包学习之lombok
  • laravel with 查询列表限制条数
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • Promise面试题,控制异步流程
  • Sequelize 中文文档 v4 - Getting started - 入门
  • 从零开始学习部署
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 数组大概知多少
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 学习使用ExpressJS 4.0中的新Router
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​520就是要宠粉,你的心头书我买单
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • # Maven错误Error executing Maven
  • #mysql 8.0 踩坑日记
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (阿里云万网)-域名注册购买实名流程
  • (二)PySpark3:SparkSQL编程
  • (分享)自己整理的一些简单awk实用语句
  • (生成器)yield与(迭代器)generator
  • (转)德国人的记事本
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET gRPC 和RESTful简单对比
  • .NET 读取 JSON格式的数据
  • .NET 自定义中间件 判断是否存在 AllowAnonymousAttribute 特性 来判断是否需要身份验证
  • .Net8 Blazor 尝鲜
  • .net企业级架构实战之7——Spring.net整合Asp.net mvc
  • .考试倒计时43天!来提分啦!
  • @ConfigurationProperties注解对数据的自动封装
  • [3300万人的聊天室] 作为产品的上游公司该如何?
  • [Android] Implementation vs API dependency
  • [AutoSar NVM] 存储架构
  • [C#基础知识系列]专题十七:深入理解动态类型