樹莓派+小程序開發(一)

目錄

樹莓派+小程序開發(一)
樹莓派+小程序開發(二)
五: 讓小程序連接樹莓派
六:小程序控制面板設計
七:樹莓派如何解析小程序的信息
八:樹莓派如何回信息給小程序
九:樹莓派與微信小程序通過websocket通信
十:小程序實時顯示樹莓派溫溼度
十一:python版 websocket服務器實現
十二:python版websocket 服務器如何整合led和beep
十三:Python版服務器整合dht11溫溼度傳感器

一:前言

作者:下家山
做這個項目的初衷是因爲騰訊關閉了微信的對外接口,導致我不能通過微信控制樹莓派,所以我開始學習小程序,我的最終目標是通過小程序能夠控制我樹莓派上接的設備,比如我點一下按鈕可以讓我樹莓派上的燈開,遠程關機,還可以把樹莓派上採集的數據比如溫溼度上傳到我手機的小程序上,我們的最終目標是手機能夠實時顯示溫溼度信息,並且能控制樹莓派上的燈和蜂鳴器,效果如圖:
在這裏插入圖片描述
通過這個項目,你將會學到很酷的應用,就是通過你的手機遠程控制你的樹莓派。打開了這個通道,就大大擴展了你樹莓派的邊界。

因爲最近的疫情,我可能每天都有進展,一般會一次上傳一個章節,但是後面上班了可能是一週,也許到那時這個項目已經完成了,但願。

好了,我們開工了,let’s go…

1.1 從註冊開始

第一步是要註冊一個小程序開發的賬號,就像所有第三方開發一樣,微信公衆號也需要,但是我們往往不記得小程序註冊的網址是多少,誰記得這個呢,沒關係,我們可以通過百度幫我們找,只需要我們知道在百度裏面搜微信小程序即可,所以我們從註冊開始吧。
在這裏插入圖片描述小程序註冊官方地址
前往註冊需要填入郵箱地址

一個郵箱只能綁定一個小程序賬號,郵箱不夠用可以在註冊一個騰訊qq郵箱,就是申請qq就有了qq郵箱。同樣的方法,你可以到百度搜索騰訊qq,然後找到官網進入,懶的人可以從這裏直接進去
騰訊qq註冊官網

填寫了小程序郵箱信息後,需要進去登陸激活一下

它會提示從這裏進入
激活連接像上面這樣

1.2 填寫主體信息

一個身份證可以註冊多個,同樣管理員手機號也沒有限制,不用擔心,一個手機號可以註冊多個小程序在這裏插入圖片描述

需要手機微信掃描驗證

看到下面的感嘆號,恭喜你OK 了

我們可以進入開發階段了
在這裏插入圖片描述

二. 工具下載

我們下載穩定版(預發佈版本和開發版本是給前沿探索者用的,如果像看看微信下程序的團隊又研究了什麼新東西出來了,可以去下載研究。)
如果你是windows系統,紅色框標註的,如果蘋果系統下載macos版本
在這裏插入圖片描述

安裝後在桌面上是這個圖片,不熟悉前端的人覺得這個log很醜,其實它是前端開發語言html的標誌行符號</>
在這裏插入圖片描述

三 .進入開發

第一打開需要手機掃碼(註冊的手機)
在這裏插入圖片描述

3.1 新建項目

在這裏插入圖片描述

3.2 文件結構

在這裏插入圖片描述

3.3 運行效果

在這裏插入圖片描述
pages,index,logs,utils,app.*五者的關係
1)pages,utils,app三者是並列關係
2)pages裏面包含index,logs兩個頁面
3) app.js, app.json, app.wxss是控制整個小程序的,頁面index,logs由app.json來配置
在這裏插入圖片描述

3.2.1 index.js負責頁面邏輯

在這裏插入圖片描述

3.2.2 index.json負責頁面配置

在這裏插入圖片描述

3.2.3 index.wxml負責頁面結構

在這裏插入圖片描述

3.2.4 index.wxss負責頁面樣式

在這裏插入圖片描述

3.3 app解析

App.json全局配置

微信官方文檔

{  
"pages": [    
"pages/index/index",   
"pages/logs/logs"  
],  
"window": {    
    "backgroundTextStyle": "light",    
    "navigationBarBackgroundColor": "#fff",    
    "navigationBarTitleText": "WeChat",    
    "navigationBarTextStyle": "black"  
},  
"style": "v2",  
"sitemapLocation": "sitemap.json"
}

負責頁面配置,json語法格式(都是字典形式,或者字典套字典),最外層的花括號{}表示一個無名字典,然後裏面是四個鍵值對,分別是
Key(鍵):value值)
“pages”:+列表,
”window”:+字典(也就是字典裏面套字典了)
“style”:+字符串
“sitemapLocation”:+字符串

關鍵字”pages”

關鍵字“pages”表示整個小程序的配置頁面,如果去掉"pages/index/index",則看不到第一頁,程序裝載後直接顯示的是第二頁,如圖

在這裏插入圖片描述

關鍵字”window”

關鍵字”window”是對整體窗體的控制,以及外觀配置
“backgroundTextStyle”:“light”,//用於控制view中的上拉下拉加載效果,只能是light/dark兩種選擇,一種亮色,一種暗色,如果設置其他,比如設置爲black,編譯出錯,提示:
ppJSON[“window”][“backgroundTextStyle”]
字段需爲 dark 或 light
“navigationBarBackgroundColor”: “#fff”,
“navigationBarTitleText”: “WeChat”,
“navigationBarTextStyle”: “black”
這三行,是設置導航欄的,我們可以改動一下,看看導航欄在哪個位置

在這裏插入圖片描述

關鍵字”style”

“style”: “v2”,是爲了說明組件庫版本採用的是新版v2
在下面的連接中可以找到所有基礎版本庫說明
https://developers.weixin.qq.com/miniprogram/dev/framework/release/v2.html
在這裏插入圖片描述

Style官方說明
基礎庫 2.8.0 開始支持,低版本需做兼容處理。
微信客戶端 7.0 開始,UI 界面進行了大改版。小程序也進行了基礎組件的樣式升級。app.json 中配置 “style”: "v2"可表明啓用新版的組件樣式。
本次改動涉及的組件有 button icon
radio checkbox switch slider。可前往小程序示例進行體驗。

關鍵字“sitemapLocation”

“sitemapLocation”: “sitemap.json”
文件sitemap.json內容

{  
"desc": "關於本文件的更多信息,請參考文檔 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",  
"rules": [{  "action": "allow",  "page": "*"  }]
}

關鍵字sitemapLocation的作用主要是設置是否允許微信能否搜索小程序內的頁面

官方說明:

微信現已開放小程序內搜索,開發者可以通過
sitemap.json 配置,或者管理後臺頁面收錄開關來配置其小程序頁面是否允許微信索引。當開發者允許微信索引時,微信會通過爬蟲的形式,爲小程序的頁面內容建立索引。當用戶的搜索詞條觸發該索引時,小程序的頁面將可能展示在搜索結果中。
爬蟲訪問小程序內頁面時,會攜帶特定的 user-agent:mpcrawler 及場景值:1129。需要注意的是,若小程序爬蟲發現的頁面數據和真實用戶的呈現不一致,那麼該頁面將不會進入索引中。

sitemap 配置

小程序根目錄下的 sitemap.json 文件用於配置小程序及其頁面是否允許被微信索引,文件內容爲一個 JSON 對象,如果沒有 sitemap.json ,則默認爲所有頁面都允許被索引;

app.wxss全局樣式

app.wxss作爲全局樣式,會作用於當前小程序的所有頁面,局部頁面樣式 page.wxss 僅對當前頁面生效。
/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;
} 

我們改動align-items做實驗,看變化結果
Align-items表示所有條目垂直對齊方式,我們這裏是居中對齊,它有以下對齊方式
在這裏插入圖片描述
如果我們改爲baseline,效果如下
在這裏插入圖片描述
App.wxss會作用於局部樣式文件index.wxss和logs.wxss,我們從index.wxss和logs.wxss中可以看到使用了container類。

在這裏插入圖片描述

App.js全局邏輯

官方說明
https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html

App()函數

App(Object object)
註冊小程序。接受一個 Object 參數,其指定小程序的生命週期回調等。
App() 必須在
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
  }
})

onLaunch(Object object)

小程序初始化完成時觸發,全局只觸發一次。參數也可以使用 wx.getLaunchOptionsSync 獲取。
在這裏插入圖片描述

Logs

// 展示本地存儲能力
在這裏插入圖片描述
這一段代碼的理解,就如註釋所說,是展示本地存儲能力,
var logs = wx.getStorageSync(‘logs’)|| []
這一句是通過名字logs獲取數組裏面的內容,如果是第一次(首次數組爲空,獲取到爲假),則把空數組[]複製給logs;
logs.unshift(Date.now())是獲取當前時間,並且插入數組logs中,unshift是前插,也叫頭部插入。
大家可以直接logs.unshift(1),看看效果
如果是1,則插入格林威治初始時間
在這裏插入圖片描述

Logs.push(1)則是尾部插入,每次時間會累加歷使數據
在這裏插入圖片描述

logs.shift()頭部刪除 logs.unshift()頭部插入
logs.pop()尾部刪除 logs.push()尾部插入

wx對象

Object wx
小程序 API 全局對象,用於承載小程序能力相關 API。具體請參考小程序 API 參考文檔。

wx.env

小程序環境變量對象

wx.login()

在這裏插入圖片描述
Res=>是一個函數,叫箭頭函數
X=>xx
相當於
Function(x)
{
Return x
x;
}
所以res=>{}相當於function(res){}
我們修改一下代碼,添加一條打印語句

// 登錄
    wx.login({
      success: res => {
        console.log("登陸信息:",res)
        // 發送 res.code 到後臺換取 openId, sessionKey, unionId
      }
    })

我們通過console.log打印出登陸成功的返回值得到:
登陸信息:
{errMsg: “login:ok”, code:
“02167XtM1w2bE9161KsM12wkuM167Xtm”}
Login:ok表示成功登陸,你可以試試不用手機掃碼登陸,看看返回值

wx.getSetting獲取用戶信息

// 獲取用戶信息
    wx.getSetting({
      success: res => {
        console.log("認證信息:", res)
        if(res.authSetting['scope.userInfo']) {
          // 已經授權,可以直接調用 getUserInfo 獲取頭像暱稱,不會彈框
          wx.getUserInfo({
            success: res => {
              // 可以將 res 發送給後臺解碼出 unionId
              console.log("用戶信息:", res)
              this.globalData.userInfo= res.userInfo
              // 由於 getUserInfo 是網絡請求,可能會在 Page.onLoad 之後才返回
              // 所以此處加入 callback 以防止這種情況
              if (this.userInfoReadyCallback){
                this.userInfoReadyCallback(res)
              }
            }
          })
        }
      }
    })
  }

我添加了兩條語句,爲了獲取認證信息和用戶信息
console.log(“認證信息:”, res)
console.log(“用戶信息:”, res)
運行結果:
在這裏插入圖片描述
globalData全局變量
globalData: {
userInfo: null
}
globalData是字典,裏面的userInfo初值爲Null空,等待後續賦值。

3.4 index解析

Index.js解析

//index.js
//獲取應用實例
const app = getApp()

Page({
  data: {
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },
  //事件處理函數
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad: function () {
    if (app.globalData.userInfo) {
      this.setData({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true
      })
    } else if (this.data.canIUse){
      // 由於 getUserInfo 是網絡請求,可能會在 Page.onLoad 之後才返回
      // 所以此處加入 callback 以防止這種情況
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    } else {
      // 在沒有 open-type=getUserInfo 版本的兼容處理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        }
      })
    }
  },
  getUserInfo: function(e) {
    console.log(e)
    app.globalData.userInfo = e.detail.userInfo
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })
  }
})

Index.wxml 頁面結構

Button標籤

在這裏插入圖片描述
這裏面的邏輯關係,在index.wxml代碼第4行
獲取頭像暱稱
Wx:if是一個判斷語句,hasUserInfo第一次裝載頁面時時false,canIUse是一個字典中的key,它的值value是有定義的,所以這裏&&後面應該時爲真的,但前面hasUserInfo再非一次(!表示取反)則爲真,因此,wx:if裏面爲真,因此會顯示“獲取頭像暱稱”字樣在界面上。
在這裏插入圖片描述
如果我們點擊按鈕”獲取頭像暱稱”,則會觸發綁定的函數調用getUserInfo
該函數定義在Index.js中的第46行。

在這裏插入圖片描述
其中,hasUserInfo會賦值爲真true.
這樣再次刷新頁面時,不會再顯示“獲取圖像暱稱”,而會顯示真實圖像了
,注意需要微信掃碼登陸
在這裏插入圖片描述

Image標籤

 <block wx:else>
      <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>

Wx:else是和button中的wx:if對應的,當if條件不成立時則會進入else,即顯示image
Image通過Bindtap綁定到函數bindViewTap,bindtap是一個點擊事件,這樣當點擊了頭像時,則執行bindViewTap函數,該函數定義在index.js中的13行

 //事件處理函數
  bindViewTap: function() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },

在這個函數中,wx.navigateTo()是一個界面切換函數,url:’…/logs/logs’則會告訴wx.navigateTo切換到上級目錄下面的logs文件夾下面的logs.js從而裝載下一個頁面logs.js

Text標籤

{{userInfo.nickName}}
這一段控制的是頭像下面的暱稱名稱
在這裏插入圖片描述
字體和顏色的控制是通過index.wxss中的userinfo-nickname類來控制的

Index.wxss文件解析

/**index.wxss**/
.userinfo {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.userinfo-avatar {
  width: 128rpx;
  height: 128rpx;
  margin: 20rpx;
  border-radius: 50%;
}
.userinfo-nickname {
  color: #aaa;
}
.usermotto {
  margin-top: 200px;
}

Motto顯示

Motto:是座右銘,格言,警句的意思

<view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
Class=”usermotto”表示使用index.wxss中的usermotto樣式控制
.usermotto {
  margin-top: 200px;//表示別名顯示離上面的圖片image200個像素距離
}
{{motto}}中的motto是微信小程序中的對變量的引用語法格式,這個變量定義在index.js中
Page({
  data: {
    motto: 'Hello World',//變量motto的定義和初始化,它其實也是一個鍵值對
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },

Index.wxml視圖層view

在這裏插入圖片描述
Index.wxml負責頁面結構,這種結構通常通過view來管理,這裏有三個view(第一層view),一個大view,包含兩個小view(第二層view控制)
而這些view層的樣式控制是通過app.wxss和index.wxss文件來控制的,
App.wxss負責大view的樣式,index.wxss負責小view的樣式。這三個文件的關係如下:
在這裏插入圖片描述

3.5 logs解析

Logs整個的頁面是爲了展現本地存儲能力的,所以是通過日誌(打印當前時間,每次加載子頁面的時間)
效果如圖
在這裏插入圖片描述

Logs.js子頁面邏輯

//logs.js
const util = require('../../utils/util.js')
//requre包含另一個文件,相當於include和import
Page({
  data: {
    logs: []//空列表,方便後面追加
  },
  onLoad: function () {
    console.log("裝載logs頁面....")
    this.setData({
      //在app.js中已經調用wx.setStorageSync('logs', logs)設置了當前時間
      logs: (wx.getStorageSync('logs') || []).map(log => {
        //通過util.js中的格式化操作把時間轉成字符串
        return util.formatTime(new Date(log))
      })
    })
  }
})

Logs.json解析
{
“navigationBarTitleText”: “查看啓動日誌”,
“usingComponents”: {}
}
頁面配置文件,設置導航欄標題,切換到logs頁面時的“查看啓動日誌”就是這裏設置的
在這裏插入圖片描述

Logs.wxml解析

Logs頁面結構設計,即打印日誌的格式,樣式

<!--logs.wxml-->
<view class="container log-list">
  <block wx:for="{{logs}}" wx:for-item="log">
    <text class="log-item">{{index + 1}}. {{log}}</text>
  </block>
</view>

這裏有循環語句wx:for,會統計日誌的行數,index從0開始計數,所以+1,方便用戶看

Logs.wxss解析

.log-list {
  display: flex;
  flex-direction: column;
  padding: 40rpx;
}
.log-item {
  margin: 10rpx;
}

負責logs.wxml結構顯示的樣式

3.6 util.js解析

formatTime是一個函數,參數就是date
=>後面的花括號是函數體,其中的year,month,day,hour,minute,second每個變量佔用一條語句,js中的語句不需要分號,換行就行了

const formatTime = date => {
  const year = date.getFullYear()  //取得參數date中的年
  const month = date.getMonth() + 1//取得參數date中的月,因爲月從0開始,所以要+1
  const day = date.getDate()    //得到天
  const hour = date.getHours()  //得到小時
  const minute = date.getMinutes() //得到分鐘
  const second = date.getSeconds()  //得到秒
  //返回年月日,時分秒,年月日以/隔開,時分秒以:隔開,形如2020/02/25 20:21:34
  return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
}
//把列表轉成字符串
const formatNumber = n => {
  n = n.toString()
  return n[1] ? n : '0' + n   //這一句沒有什麼意義,去掉也沒問題
}

module.exports = {
  formatTime: formatTime//導出函數,供外部調用(logs.js)
}

接下來:我們將推倒微信小程序例程,從頭再來
樹莓派+小程序開發(二)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章