【12月原创】RT-thread - 柿饼UI —— 网络流媒体播放器
Persimmon UI作業(四)—— 網絡流媒體播放器
前言:這次的作業花費了一周的時間,因為學校接近末考同時面對大連疫情的嚴峻,使整個開發流程變得斷斷續續,不過還好總算是完成了這次網絡流媒體播放器,總體來說還是有些難度的,對我來說也算是個人水平的進一步的提升了。為此記錄一下開發流程以及我的創意分享。
視頻演示效果:
一.項目的規劃/構思
因為柿餅派的IO口有限,外接的IO口除了兩個串口就是電源和地了,但只要有串口基本上就可以滿足我們外接設備的需求了,畢竟是用柿餅派作為開發的SOC。
網絡流媒體播放器的整個系統的框架如下:
- 因為我們需要獲取網絡音頻等數據,所以聯網的模塊是必不可少的,良心的是柿餅派上板載SPI WIFI模塊 (RW007)通訊速度就叫一個快!
-
獲取到的音頻需要播放出來,柿餅PI的Audio Player 接口可以播放網絡/本都音頻流。
-
同時通過HTTP可以獲取API接口的天氣/音樂數據,MQTT可以實現柿餅派訂閱/發布指定topic,可以實現一個智能物聯網屏幕的功能。
-
UART接口可以和其他單片機進行數據交互,這里我使用了柿餅派與小熊派進行數據的聯動,通過小熊派NB模組將數據上報到小熊派訂閱的topic,同時通過串口與柿餅派連接,通過串口將數據發送至柿餅派。這樣就把我們前兩節課所學習到的網絡/串口結合到了一起,豈不美哉!
二.項目的實現
對于整個項目可以分為三個部分:
- 1.在app.js中編寫WIFI的配網-入網-獲取網絡信息的邏輯。
- 2.在app.js將UART作為全局對象,在子page中實現app.js的回調函數。
- 3.在子page中通過設置UI控件來綁定列表、button等控件,通過控件將網絡獲取的數據以UI界面展示。
1.WIFI配網-入網的實現:
整個WIFI調用流程如下:
- 1.實例化WIFI對象pm.createwifi()。
- 2.掃描WIFI熱點信息scan()。
- 3.連接WIFI熱點connect() 連接特定網絡。
- 4.監聽連接事件,回調onConnectEvent判斷連接結果。
- 5.監聽WFI連接網絡,回調onNetworkEvent判斷連接結果,當返回為true ,則連接網絡成功。
監聽連接事件,回調onConnectEvent判斷連接結果:
監聽連接網絡,回調onNetworkEvent判斷連接結果:
發起HTTP—GET請求消息:
2.串口收發功能的實現:
1.設置全局接收:
2.在子page設置接受回調:
3.數據在UI界面的展示以及音樂播放:
讓我們先看一下整體的UI設計布局:
頂部:button+label+imagebox控件。
中間:Listctrl的控件用于展示MV列表以及網絡專輯圖片列表。
那么js代碼中是怎么實現將網絡數據綁定到UI控件,播放視頻以及音樂的呢?
1.定義存儲視頻的數組:
2.綁定每一條Videoltem中的label,button, imagebox屬性(類似安卓中的Adapter),將每一條通過列表展示出來
(類似安卓中的RecyclerView):
3.fmData是我們在app.js中定義的數據,用于存放通過HTTP請求到的JSON數據。
具體JS代碼如下:
/*************Music Panel*****************/loadAlbum: function (Class) {if (fmData == 0)return;var that = this;/***加載music list***/{var MusicList = new Array();for (var i = 0, len = fmData.Music.length; i < len; i++) {var item = new Object();item.albumName = new Object();item.albumName.value = fmData.Music[i].albumName;var imageArr = fmData.Music[i].albumImage.split("/");item.albumImage = new Object();item.albumImage.norImg = imageArr[imageArr.length - 1];//圖片item.albumImage.customProperty = fmData.Music[i]; //MUSIC整個jsonconsole.log("@@===========>mp3-src:" + fmData.Music[0].albumList[0].src);item.albumImage.id = "Music" + i;MusicList.push(item);}this.setData({Music_list: {list: {page: that,items: [{xml: "Panels/AlbumItem",items: MusicList}]}}});}},音樂播放器設計界面如下:
通過暫停/播放等按鈕可以實現播放以及切換歌曲功能
播放音樂同時通過prograssbar控件展示播放進度,slider控件控制播放音量的大小。
點擊上/下一首歌曲,底部列表回進行相應滾動。
具體實現的JS代碼如下:
onLoad: function (event) {refreshDate(this); //獲取信號質量--app.jsthis.audioEvenDeinit();this.albumData = event;this.urlList = new Array(); //存放音樂數組var imageArr = this.albumData.albumImage.split("/");this.setData({ albumImage: imageArr[imageArr.length - 1] });this.setData({ albumInfo: this.albumData.albumName });this.setData({ volume_slider: { value: audio.getVolume() } });var listItems = new Array();for (var i = 0, len = this.albumData.albumList.length; i < len; i++) {var item = new Object();item.label1 = new Object();item.panel1 = new Object();item.panel1.id = "musicPanel" + i; //設置每一個列表前的圖標item.imagebox1 = new Object();item.imagebox1.id = "musicImage" + i; //設置每一個列表前的圖標iditem.label1.value = this.albumData.albumList[i].trackName;//每一條音樂名稱console.log("@@=======================TrackName=======================");console.log("@@=====>trackName is:" + this.albumData.albumList[i].trackName);//音樂名稱/*** 路徑 ***/this.urlList.push(this.albumData.albumList[i].src);console.log("@@=======================AlbumList_src=======================");console.log("@@=====>AlbumList is:" + this.albumData.albumList[i].src);//mp3文件listItems.push(item);}this.setData({List: {list: {page: this,items: [{xml: "Panels/PlayListItem",items: listItems}]}}});this.audioEventInit();},播放,暫停的具體JS代碼如下:
//播放音樂playMusic: function () {if (this.isPlay == false) {this.isPlay = true;this.setData({ Switch1: { value: true } })}if (this.playIndex < 0) {this.playIndex = this.urlList.length - 1;} else if (this.playIndex >= this.urlList.length) {this.playIndex = 0;}// set urlvar url = this.urlList[this.playIndex];audio.stop();audio.setSrc(url);if (this.isPlay && wifi.isConnected) {audio.play();} else {this.isPlay = false;this.setData({ Switch1: { value: false } });}},//暫停/播放--按鈕回調onSwitch: function (event) {this.isPlay = event.detail.value;if (this.isPlay) {this.playMusic();} else {audio.pause();}},說完了音樂播放,那么天氣數據的獲取以及語音播報是怎么實現的呢?
首先讓我們看一下天氣page的UI界面吧:
JS代碼實現了通過HTTP獲取到的json數據綁定在UI控件上面:
loadWeatherInfo: function () {if (weatherInfo == 0) { //沒有請求成功return;}this.setData({ currentTempeature_label: { value: weatherInfo.hourly.Temperature[0].value } });switch (weatherInfo.hourly.Skycon[0].value) {case "CLEAR_DAY":case "CLEAR_NIGHT":this.setData({ weather_img: { value: "clear_white.png" } })this.setData({ weather_label: { value: "晴" } })break;case "PARTLY_CLOUDY_DAY":case "PARTLY_CLOUDY_NIGHT":this.setData({ weather_img: { value: "cloudy_white.png" } })this.setData({ weather_label: { value: "多云" } })break;case "CLOUDY":this.setData({ weather_img: { value: "overcase_white.png" } })this.setData({ weather_label: { value: "陰" } })break;case "WIND":this.setData({ weather_img: { value: "windy_white.png" } })this.setData({ weather_label: { value: "大風" } })break;case "HAZE":this.setData({ weather_img: { value: "haze_white.png" } })this.setData({ weather_label: { value: "霧霾" } })break;case "RAIN":this.setData({ weather_img: { value: "rain_white.png" } })this.setData({ weather_label: { value: "雨" } })break;case "SNOW":this.setData({ weather_img: { value: "snow_white.png" } })this.setData({ weather_label: { value: "雪" } })break;}this.setData({ humidity_label: { value: parseInt(weatherInfo.hourly.Humidity[0].value * 100) + "%" } })this.setData({ weatherInfo_panel: { refresh: true } });},GET請求,將上一步我們獲取到的天氣數據拼接成鏈接,再次發送請求至百度語音合成API接口,就實現了點擊按鈕播報天氣:
//點擊按鈕語音播報onBroadcast: function (event) {var str = currentCity.name;console.log("weatherInfo======>" + weatherInfo.hourly.Skycon[0].value)switch (weatherInfo.hourly.Skycon[0].value) {case "CLEAR_DAY":case "CLEAR_NIGHT":str += "今天天氣晴朗"break;case "PARTLY_CLOUDY_DAY":case "PARTLY_CLOUDY_NIGHT":str += "今天多云"break;case "CLOUDY":str += "今天陰天"break;case "WIND":str += "今天有風"break;case "HAZE":str += "今天有霧霾"break;case "RAIN":str += "今天下雨"break;case "SNOW":}str += (",氣溫為" + weatherInfo.hourly.Temperature[0].value + "度,相對濕度為百分之" + parseInt(weatherInfo.hourly.Humidity[0].value * 100) + "。");var that = this;var http = require('http');http.request({url: 'http://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=uGmHtBFMOkme2XeGWzKLREDv&client_secret=xG7I0fy4GQLPpLqanq7pZAGtNXGUW564',success: function (res) {var jnews = res.data.jsonParse();//獲取access_token值var url = "http://tsn.baidu.com/text2audio?tex=" + str + "&lan=zh&cuid=44-b2-95-27-49-1f&ctp=1&per=4&tok=" + jnews.access_token;http.request({url: url,header: {"Content-Type": "application/json"},success: function (res) {console.log('request success');var file = pm.getFileSystemManager();file.writeFile({filePath: "forecast.mp3",data: res.data,success: function () {audio.stop();audio.setSrc("/mnt/sd0/filesystem/forecast.mp3");audio.play();},complete: function () { console.log("writeFile complete"); }});},})}})},通過上面的積累,這樣的一個網易云界面UI就出來了,網易云有的咱們也不能差(哈哈
來對比一下(滑稽
以上就是整個項目的分享,總體來說很有挑戰性創新性的一次作業,當真正做出來之后發現很有成就感。同時十分感謝柿餅UI的平臺給了我們這么便捷開發的工具,以最短的時間最簡單的方式區實現一個小項目。對于我個人而言意義很是重大,我很慶幸在當初迷茫如何去選擇一個能夠快速上手的嵌入式屏幕時我發現了Persimmon UI。時長1個月的柿餅UI的學習結束啦,感謝群里各位老師以及各位大佬的幫助與指導。未來我會使用柿餅做一些更加有趣的項目,同時開源在我的git以及RTT社區上面。
總結
以上是生活随笔為你收集整理的【12月原创】RT-thread - 柿饼UI —— 网络流媒体播放器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php 腾讯云 短信验证码发送
- 下一篇: 今晚直播 |现实环境中的强化学习如何解决