微信小程式實現樹莓派(raspberry pi)小車控制
阿新 • • 發佈:2020-02-13
本文是基於上一篇“網頁版樹莓派小車控制程式”改造而成。主要也練習了一下微信小程式的開發。這裡簡單記錄一下主要程式碼片段。也是趟過了許多的坑,例如:微信小程式不支援完全全屏,微信小程式不能橫屏展示。所以開發過程中也用了一些非常手段。可以說這只是一個很基本的demo,所以裡面很多東西,比如攝像頭監控ip、頁面元素定位我都使用了寫死的值。特別是介面,我只是在iPhone 6上面做的實驗,所以換到其他手機上時,介面就會變型了。
1. 基本思路
- 進入小程式時展示index頁,可以讓使用者輸入服務端url(模擬上一篇中在瀏覽器獲取get請求)
- 然後跳轉到實際的小車控制介面,並可以通過點選按鈕實現小車控制
- 控制小車的移動,主要是在control.js中定義了介面按鈕事件的響應,在響應事件的過程中實現http請求的傳送
index頁面如下:
進去之後的頁面如下(其中中間空白處會展示攝像頭監控,不過我並沒有啟動,所以看不見):
2. 程式碼結構如下:
其中,index下面是首頁,control是控制頁面,res目錄下存放的是圖片資源
3. index目錄
index.js
//index.js //獲取應用例項 const app = getApp() Page({ data: { logo: "/res/rasp-logo.png",welcome: "歡迎使用樹莓小車",enterBtn: "進入",PromoteMsg: "Please enter the server address (eg: http://x.x.x.x:8080)",reqURL: "" },// 從輸入框中獲取使用者輸入的伺服器地址資訊 getURL: function (e) { this.setData({ reqURL: e.detail.value }) },enterClicked: function (e) { /* * 當按下進入按鈕,需要做以下事情: * 1. 首先判斷使用者是否已經在輸入框中輸入完整的伺服器地址 * 2. 發起一個到伺服器的GET請求,並分析伺服器的響應結果 * 3. 跳轉到小車控制介面 */ console.log(this.data.reqURL) if (this.data.reqURL == '') { wx.showModal({ title: '提示',content: '請先輸入正確的伺服器地址!',}) return } // 發起到伺服器的GET請求 wx.request({ url: this.data.reqURL,success: function (res) { // 在這裡獲取POST請求地址,以及視訊流地址,然後賦值給全域性變數,供control頁面呼叫 console.log(res.data.match(/url = \"(\S*)\"/)[1]) console.log(res.data.match(/src=\"(\S*)\"/)[1]) app.globalData.postURL = res.data.match(/url = \"(\S*)\"/)[1] app.globalData.cameraURL = res.data.match(/src=\"(\S*)\"/)[1] // 跳轉到control頁面 wx.navigateTo({ url: '/pages/control/control',}) },fail: function(res) { wx.showModal({ title: '提示',content: '請檢查輸入的伺服器地址!',}) } }) } })
index.json:無資料,只有一對打括號
index.wxml
<!--index.wxml--> <view> <view class="welcome"> <view class="logo"> <image style="width: 250rpx; height: 250rpx" src="{{logo}}"></image> </view> <view> <text class="words">{{welcome}}</text> </view> </view> <input class="requestURL" type="text" placeholder="{{PromoteMsg}}" focus='1' cursor='10' confirm-type="done" bindinput='getURL'></input> <button class='enter' bindtap='enterClicked'>{{enterBtn}}</button> </view>
index.wxss
/**index.wxss**/ .welcome{ display: flex; margin-top: 50rpx; flex-direction: column; align-items: center; justify-content: space-between; } .requestURL{ margin: 50rpx 10rpx 30rpx 10rpx; border: 1px solid gray; font-style: italic; font-size: small } .enter{ margin-right: 10rpx; width: 150rpx; height: 60rpx; font-size: small }
4. control目錄
control.js
// pages/control/control.js const app = getApp() Page({ /** * 頁面的初始資料 */ data: { // Car control images "forwardBtn": "/res/forward.png","leftBtn": "/res/left.png","rightBtn": "/res/right.png","backLeftBtn": "/res/back-left.png","backRightBtn": "/res/back-right.png","backBtn": "/res/backward.png",// Camera control images "upBtn": "/res/forward.png","camLeftBtn": "/res/camLeft.png","camRightBtn": "/res/camRight.png","downBtn": "/res/backward.png","resetBtn": "/res/reset.png" },carMove: function(event) { wx.request({ url: this.data.postURL,data: event.currentTarget.dataset.direction,method: "POST",success: function(res){ },fail: function(res){ } }) },carStop: function(event) { wx.request({ url: this.data.postURL,data: "S",success: function (res) { },fail: function (res) { } }) },camMove: function(event) { wx.request({ url: this.data.postURL,/** * 生命週期函式--監聽頁面載入 */ onLoad: function (options) { //this.data.cameraURL = app.globalData.cameraURL this.setData({ cameraURL: app.globalData.cameraURL,postURL: app.globalData.postURL }) console.log(this.data.cameraURL) console.log("post url in control page: " + app.globalData.postURL) },/** * 生命週期函式--監聽頁面初次渲染完成 */ onReady: function () { },/** * 生命週期函式--監聽頁面顯示 */ onShow: function () { //console.log(wx.getSystemInfoSync().windowWidth) //console.log(wx.getSystemInfoSync().windowHeight) },/** * 生命週期函式--監聽頁面隱藏 */ onHide: function () { },/** * 生命週期函式--監聽頁面解除安裝 */ onUnload: function () { },/** * 頁面相關事件處理函式--監聽使用者下拉動作 */ onPullDownRefresh: function () { },/** * 頁面上拉觸底事件的處理函式 */ onReachBottom: function () { },/** * 使用者點選右上角分享 */ onShareAppMessage: function () { } })
control.json
{ "navigationBarBackgroundColor": "#ffffff","navigationBarTextStyle": "black","navigationBarTitleText": "樹莓小車","backgroundColor": "#eeeeee","backgroundTextStyle": "light","enablePullDownRefresh": false,"navigationStyle": "custom","disableScroll": true }
control.wxml
<!--pages/control/control.wxml--> <view class='control'> <!-- This image shows the camera view --> <image class='cameraView' src='http://192.168.1.104:8080/?action=stream' style="z-index:1"></image> <!-- The following six images control the car move --> <image class='button' id='forward' src='{{forwardBtn}}' style="position:absolute;z-index:2" bindtouchstart='carMove' data-direction='F' bindtouchend='carStop'></image> <image class='button' id='left' src='{{leftBtn}}' style="position:absolute;z-index:2" bindtouchstart='carMove' data-direction='L' bindtouchend='carStop'></image> <image class='button' id='right' src='{{rightBtn}}' style="position:absolute;z-index:2" bindtouchstart='carMove' data-direction='R' bindtouchend='carStop'></image> <image class='button' id='backLeft' src='{{backLeftBtn}}' style="position:absolute;z-index:2" bindtouchstart='carMove' data-direction='BL' bindtouchend='carStop'></image> <image class='button' id='backRight' src='{{backRightBtn}}' style="position:absolute;z-index:2" bindtouchstart='carMove' data-direction='BR' bindtouchend='carStop'></image> <image class='button' id='back' src='{{backBtn}}' style="position:absolute;z-index:2" bindtouchstart='carMove' data-direction='B' bindtouchend='carStop'></image> <!-- The following images control the camera move --> <image class='button' id='up' src='{{upBtn}}' style="position:absolute;z-index:2" bindtouchstart='camMove' data-direction='VU'></image> <image class='button' id='camLeft' src='{{camLeftBtn}}' style="position:absolute;z-index:2" bindtouchstart='camMove' data-direction='HL'></image> <image class='button' id='camRight' src='{{camRightBtn}}' style="position:absolute;z-index:2" bindtouchstart='camMove' data-direction='HR'></image> <image class='button' id='down' src='{{downBtn}}' style="position:absolute;z-index:2" bindtouchstart='camMove' data-direction='VD'></image> <image class='button' id='reset' src='{{resetBtn}}' style="position:absolute;z-index:2" bindtouchstart='camMove' data-direction='RESET'></image> </view>
control.wxss
/* pages/control/control.wxss */ .control { width: 100%; height: 100%; transform: rotate(90deg); background-color: #eee; justify-content: center; } .cameraView { margin-left: 0px; width: 603px; height: 375px; background-color: #eee; justify-content: center; } .button { height: 60px; width: 60px; opacity: 0.3; } #forward { left: 60px; top: 135px; } #left { left: 0px; top: 195px; } #right { left: 120px; top: 195px; } #backLeft { left: 0px; top: 255px; } #backRight { left: 120px; top: 255px; } #back { left: 60px; top: 315px; } #up { left: 480px; top: 195px; } #camLeft { left: 420px; top: 255px; } #camRight { left: 540px; top: 255px; } #down { left: 480px; top: 315px; } #reset{ left: 480px; top: 135px }
5. 工程全域性控制
app.js:實際似乎並沒有用到,裡面都是工程建立時的預設程式碼
//app.js App({ onLaunch: function () { // 展示本地儲存能力 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs',logs) // 登入 wx.login({ success: res => { // 傳送 res.code 到後臺換取 openId,sessionKey,unionId } }) // 獲取使用者資訊 wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) { // 已經授權,可以直接呼叫 getUserInfo 獲取頭像暱稱,不會彈框 wx.getUserInfo({ success: res => { // 可以將 res 傳送給後臺解碼出 unionId this.globalData.userInfo = res.userInfo // 由於 getUserInfo 是網路請求,可能會在 Page.onLoad 之後才返回 // 所以此處加入 callback 以防止這種情況 if (this.userInfoReadyCallback) { this.userInfoReadyCallback(res) } } }) } } }) },globalData: { userInfo: null,postURL: null,cameraURL: null } })
app.json:
{ "pages": [ "pages/index/index","pages/control/control" ],"window": { "backgroundTextStyle": "light","navigationBarBackgroundColor": "#fff","showStatusBar": false } }
app.wxss:
/**app.wxss**/ .container { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 200rpx 0; box-sizing: border-box; } project.control.json: { "description": "專案配置檔案。","packOptions": { "ignore": [] },"setting": { "urlCheck": false,"es6": true,"postcss": true,"minified": true,"newFeature": true },"compileType": "miniprogram","libVersion": "2.0.4","appid": "wx18414b9f85bfc895","projectname": "wechat-control","isGameTourist": false,"condition": { "search": { "current": -1,"list": [] },"conversation": { "current": -1,"game": { "currentL": -1,"miniprogram": { "current": -1,"list": [] } } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。