1.软件部分介绍

  微信小程序是一种新的应用,用户不需要下载应用只用通过扫二维码或者打开链接就能使用,使用完后不需要卸载,直接关闭就行了。微信在2017年初推出微信小程序开发环境。任何企业,媒体,个人都可以注册开发。是一种全新的 开发模式。微信也因此受到许多程序员的一致好评,尤其是微信小程序的云开发,提供大量数据处理接口,让初学者也可以很快入手。不需要后端数据库的支持,自己一个人就可以开发前端和后台。

微信小程序为蓝牙模块提供了18个API。其中低功率蓝牙9个,传统蓝牙9个。本次设计使用了其中的9个接口:

(1) openBluetoothAdapter,这个API用来初始化蓝牙适配器;

(2) startBluetoothDevicesDiscovery,开始搜索蓝牙设备;

(3) onBluetoothDeviceFound,判断搜索到的蓝牙设备的信号强度;

(4) createBLEConnection,连接搜索到的蓝牙设备;

(5) stopBluetoothDevicesDiscovery,关闭搜索蓝牙设备;

(6) getBLEDeviceServices,获取蓝牙的deviceId;

(7) getBLEDeviceCharacteristics,获取蓝牙设备服务的所有特征值;

(8) notycharacteristicsId,启用低功耗蓝牙特征值的notify功能;

(9) writeBLECharacteristicValue,通过微信小程序向蓝牙模块发送命令。

 js源代码

  1. Page({
  2. /**
  3. * 页面的初始数据
  4. */
  5. data: {
  6. connect: false,
  7. send_hex: false,
  8. send_string: true,
  9. send_string_val: 'Hex',
  10. recv_string: true,
  11. recv_string_val: 'Hex',
  12. recv_value: '',
  13. send_number: 0,
  14. recv_number: 0,
  15. recv_hex: true,
  16. wendu: 30,
  17. yanwu: 60
  18. },
  19. /*** 生命周期函数--监听页面加载 */
  20. onLoad: function (options) {
  21. wx.stopBluetoothDevicesDiscovery({
  22. success: function (res) {
  23. console.log('停止搜索设备', res)
  24. }
  25. })
  26. console.log(options);
  27. this.setData({
  28. deviceId: options.id,
  29. deviceName: options.name
  30. });
  31. console.log('设备的ID', this.data.deviceId);
  32. },
  33. /*** 生命周期函数--监听页面显示 */
  34. onShow: function () {
  35. wx.stopBluetoothDevicesDiscovery({
  36. success: function (res) {
  37. console.log('停止搜索设备', res)
  38. }
  39. })
  40. var that = this;
  41. /* 连接中动画 */
  42. wx.showLoading({
  43. title: '连接中...',
  44. });
  45. /* 开始连接蓝牙设备 */
  46. wx.createBLEConnection({
  47. deviceId: that.data.deviceId,
  48. success: function (res) {
  49. console.log('连接成功', res);
  50. wx.hideLoading();
  51. /* 获取设备的服务UUID */
  52. wx.getBLEDeviceServices({
  53. deviceId: that.data.deviceId,
  54. success: function (service) {
  55. that.setData({
  56. serviceId: "0000FFE0-0000-1000-8000-00805F9B34FB" //确定需要的服务UUID
  57. });
  58. console.log('需要的服务UUID', that.data.serviceId)
  59. that.Characteristics(); //调用获取特征值函数
  60. },
  61. });
  62. that.setData({
  63. connect: true
  64. })
  65. },
  66. })
  67. },
  68. Characteristics: function () {
  69. var that = this;
  70. var device_characteristics = [];
  71. var characteristics_uuid = {};
  72. wx.getBLEDeviceCharacteristics({
  73. deviceId: that.data.deviceId,
  74. serviceId: that.data.serviceId,
  75. success: function (res) {
  76. var characteristics = res.characteristics; //获取到所有特征值
  77. var characteristics_length = characteristics.length; //获取到特征值数组的长度
  78. console.log('获取到特征值', characteristics);
  79. console.log('获取到特征值数组长度', characteristics_length);
  80. that.setData({
  81. notycharacteristicsId: "0000FFE1-0000-1000-8000-00805F9B34FB", //需确定要的使能UUID
  82. characteristicsId: "0000FFE1-0000-1000-8000-00805F9B34FB" //暂时确定的写入UUID
  83. });
  84.  
  85. console.log('使能characteristicsId', that.data.notycharacteristicsId);
  86. console.log('写入characteristicsId', that.data.characteristicsId);
  87. that.notycharacteristicsId(); //使能事件
  88. },
  89. })
  90. },
  91. /* 使能函数 */
  92. notycharacteristicsId: function () {
  93. var that = this;
  94. var recv_value_ascii = "";
  95. var string_value = "";
  96. var recve_value = "";
  97. wx.notifyBLECharacteristicValueChange({
  98. deviceId: that.data.deviceId,
  99. serviceId: that.data.serviceId,
  100. characteristicId: that.data.notycharacteristicsId,
  101. state: true,
  102. success: function (res) {
  103. console.log('使能成功', res);
  104. /* 设备返回值 */
  105. wx.onBLECharacteristicValueChange(function (res) {
  106. var length_hex = [];
  107. var turn_back = "";
  108. var result = res.value;
  109. var hex = that.buf2hex(result);
  110. console.log('返回的值', hex);
  111. if (that.data.recv_string == true) {
  112. /* 成功接收到的值的展示 */
  113. that.setData({
  114. recv_value: that.data.recv_value + hex
  115. });
  116. /* 接收成功的值的字节 */
  117. var recv_number_1 = that.data.recv_number + hex.length / 2;
  118. var recv_number = Math.round(recv_number_1);
  119. that.setData({
  120. recv_number: recv_number
  121. });
  122. } else {
  123. console.log('设备返回来的值', hex);
  124. var f_hex = hex;
  125. var length_soy = f_hex.length / 2;
  126. var length = Math.round(length_soy);
  127. for (var i = 0; i < length; i++) {
  128. var hex_spalit = f_hex.slice(0, 2);
  129. length_hex.push(hex_spalit);
  130. f_hex = f_hex.substring(2);
  131. }
  132. console.log('length_hex', length_hex);
  133. for (var j = 0; j < length_hex.length; j++) {
  134.  
  135. var integar = length_hex[j]; //十六进制
  136. recve_value = parseInt(integar, 16); //十进制
  137. console.log('recve_value', recve_value);
  138.  
  139. turn_back = turn_back + String.fromCharCode(recve_value);
  140. console.log('turn_back', turn_back);
  141. }
  142.  
  143. console.log('最终转回来的值', turn_back)
  144. var recv_number_1 = that.data.recv_number + turn_back.length;
  145. var recv_number = Math.round(recv_number_1);
  146. that.setData({
  147. recv_number: recv_number,
  148. recv_value: that.data.recv_value + turn_back
  149. })
  150. }
  151. });
  152. },
  153. fail: function (res) {
  154. console.log('使能失败', res);
  155. }
  156. })
  157. },
  158. /* 断开连接 */
  159. DisConnectTap: function () {
  160. var that = this;
  161. wx.closeBLEConnection({
  162. deviceId: that.data.deviceId,
  163. success: function (res) {
  164. console.log('断开设备连接', res);
  165. wx.reLaunch({
  166. url: '../index/index',
  167. })
  168. }
  169. });
  170. },
  171. /*** 生命周期函数--监听页面卸载 */
  172. onUnload: function () {
  173. var that = this;
  174. wx.closeBLEConnection({
  175. deviceId: that.data.deviceId,
  176. success: function (res) {
  177. console.log('断开设备连接', res);
  178. }
  179. });
  180. },
  181. /* 清除Recv Bytes */
  182. CleanNumberRecv: function () {
  183. this.setData({
  184. recv_number: 0
  185. })
  186. },
  187. /* ArrayBuffer类型数据转为16进制字符串 */
  188. buf2hex: function (buffer) { // buffer is an ArrayBuffer
  189. var hexArr = Array.prototype.map.call(
  190. new Uint8Array(buffer),
  191. function (bit) {
  192. return ('00' + bit.toString(16)).slice(-2)
  193. }
  194. )
  195. return hexArr.join('');
  196. },
  197. switch1Change: function (e) {
  198. var that = this;
  199. let buffer = new ArrayBuffer(1)
  200. let dataView = new DataView(buffer)
  201. if (e.detail.value) {
  202. dataView.setUint8(0, 0)
  203. } else {
  204. dataView.setUint8(0, 1)
  205. }
  206.  
  207. wx.writeBLECharacteristicValue({
  208. deviceId: that.data.deviceId,
  209. serviceId: that.data.serviceId,
  210. characteristicId: that.data.characteristicsId,
  211. value: buffer,
  212. success: function (res) {
  213. console.log('数据发送成功', res);
  214. console.log(buffer);
  215. },
  216. fail: function (res) {
  217. console.log('调用失败', res);
  218. /* 调用失败时,再次调用 */
  219. wx.writeBLECharacteristicValue({
  220. deviceId: that.data.deviceId,
  221. serviceId: that.data.serviceId,
  222. characteristicId: that.data.characteristicsId,
  223. value: buffer,
  224. success: function (res) {
  225. console.log('第2次数据发送成功', res);
  226. }
  227. })
  228. }
  229. })
  230. },
  231. switch1Change1: function (e) {
  232. var that = this;
  233. let buffer = new ArrayBuffer(1)
  234. let dataView = new DataView(buffer)
  235. if (e.detail.value) {
  236. dataView.setUint8(0, 2)
  237. } else {
  238. dataView.setUint8(0, 3)
  239. }
  240. wx.writeBLECharacteristicValue({
  241. deviceId: that.data.deviceId,
  242. serviceId: that.data.serviceId,
  243. characteristicId: that.data.characteristicsId,
  244. value: buffer,
  245. success: function (res) {
  246. console.log('数据发送成功', res);
  247. console.log(buffer);
  248. },
  249. fail: function (res) {
  250. console.log('调用失败', res);
  251. /* 调用失败时,再次调用 */
  252. wx.writeBLECharacteristicValue({
  253. deviceId: that.data.deviceId,
  254. serviceId: that.data.serviceId,
  255. characteristicId: that.data.characteristicsId,
  256. value: buffer,
  257. success: function (res) {
  258. console.log('第2次数据发送成功', res);
  259. }
  260. })
  261. }
  262. })
  263. },
  264. add: function (e) {
  265. var id = e.target.id;
  266. if (this.data[id] > 98) {
  267. wx.showToast({
  268. title: '已超过最大数值',
  269. icon: 'loading',
  270. duration: 2000
  271. })
  272. return;
  273. }
  274. this.setData({
  275.       [id]: +this.data[id] + 1
  276. });
  277. this.numbers(id)
  278. },
  279. lessen: function (e) {
  280. var id = e.target.id;
  281. if (this.data[id] < 1) {
  282. wx.showToast({
  283. title: '已小于最小数值',
  284. icon: 'loading',
  285. duration: 2000
  286. })
  287. return;
  288. }
  289. this.setData({
  290.        [id]: +this.data[id] - 1
  291. });
  292. this.numbers(id)
  293. },
  294. changeVal: function (e) {
  295. var id = e.target.id;
  296. if (e.detail.value < 1 || e.detail.value > 100) {
  297. wx.showToast({
  298. title: '请输入有效数值',
  299. icon: 'loading',
  300. duration: 2000
  301. })
  302. return;
  303. }
  304. this.setData({
  305.       [id]: e.detail.value
  306. });
  307. this.numbers(id)
  308. },
  309. numbers: function (id) {
  310. var that = this;
  311. var number = '9';
  312. let buffer = new ArrayBuffer(1)
  313. let dataView = new DataView(buffer)
  314. console.log(id)
  315. if (id == 'wendu') {
  316. number = '8' + that.data[id];
  317. dataView.setUint8(0, 8)
  318. } else {
  319. number = number + that.data[id];
  320. dataView.setUint8(0, number)
  321. }
  322. wx.writeBLECharacteristicValue({
  323. deviceId: that.data.deviceId,
  324. serviceId: that.data.serviceId,
  325. characteristicId: that.data.characteristicsId,
  326. value: buffer,
  327. success: function (res) {
  328. console.log('数据发送成功', res);
  329. console.log(buffer);
  330. }
  331. })
  332. }
  333. })
  1. wxss源代码
  1. .connect_box {
  2. width: 100%;
  3. height: 30px;
  4. line-height: 30px;
  5. font-size: 32rpx;
  6. color: #666;
  7. font-family: "Microsoft YaHei";
  8. }
  9. .connect_device_name{
  10. float: left;
  11. padding-left: 10px;
  12. color: #39beff;
  13. }
  14.  
  15. .connect_state {
  16. float: right;
  17. padding-right: 10px;
  18. text-decoration: underline;
  19. color: #39beff;
  20. }
  21.  
  22. .fan{
  23. width: 2rem;
  24. height: 2rem;
  25. vertical-align: middle;
  26. margin-left: 2.25rem;
  27. margin-right: 0.25rem;
  28. }
  29. .water{
  30. width: 2.5rem;
  31. height: 2rem;
  32. vertical-align: middle;
  33. margin-left: 2rem;
  34. }
  35. .name{
  36. display: inline-block;
  37. width: 22%;
  38. margin-left: 1.5rem;
  39. font-size: 0.9rem;
  40. }
  41. .key{
  42. float: right;
  43. margin-right: 2rem;
  44. margin-top: 0.2rem;
  45. }
  46. .detail_box{
  47. padding: 1.5rem 0;
  48. border-bottom: 1px solid #ccc;
  49. }
  50.  
  51. .num {
  52. display: inline-block;
  53. width: 45%;
  54. text-align: right;
  55. vertical-align: middle;
  56. }
  57.  
  58. .num input {
  59. display: inline-block;
  60. width: 2rem;
  61. text-align: center;
  62. border: 1px solid #f2f2f2;
  63. border-left: none;
  64. border-right: none;
  65. color: #a2a2a2;
  66. }
  67.  
  68. .num text {
  69. display: inline-block;
  70. width: 1.4rem;
  71. height: 1.4rem;
  72. line-height: 1.4rem;
  73. text-align: center;
  74. border: 1px solid #f2f2f2;
  75. vertical-align: top;
  76. color: #dcdcdc;
  77. }
  78. .wendu{
  79. width:1.9rem;
  80. height:2rem;
  81. vertical-align:middle;
  82. margin-left:2.3rem;
  83. margin-right:.3rem;
  84. }
  1. wxml源代码
  1. <view class="connect_box">
  2. <text class='connect_device_name'>{{deviceName}}</text>
  3. <text wx:if="{{connect}}" class="connect_state" catchtap="DisConnectTap">已连接</text>
  4. <text wx:else class="connect_state">未连接</text>
  5. </view>
  6. <view >
  7. <view class="detail_box">
  8. <image src='../../images/airFan.png' class="fan"></image>
  9. <view class='name'>风扇</view>
  10. <switch bindchange="switch1Change" class='key' />
  11. </view>
  12. <view class="detail_box">
  13. <image src='../../images/waterPump.png' class="water"></image>
  14. <view class='name'>水泵</view>
  15. <switch bindchange="switch1Change1" class='key' />
  16. </view>
  17. <view class="detail_box">
  18. <image src='../../images/temperature.png' class="wendu"></image>
  19. <view class='name'>温度阀值</view>
  20. <view class='num'>
  21. <text style='border-radius: 3px 0 0 3px;' id='wendu' bindtap='lessen'>-</text>
  22. <input type='number' value='{{wendu}}' name='piece' id='wendu' bindblur="changeVal" />
  23. <text style='border-radius: 0 3px 3px 0;' id='wendu' bindtap='add'>+</text>
  24. </view>
  25. </view>
  26. <view class="detail_box">
  27. <image src='../../images/smog.png' class="water"></image>
  28. <view class='name'>烟雾阀值</view>
  29. <view class='num'>
  30. <text style='border-radius: 3px 0 0 3px;' id='yanwu' bindtap='lessen'>-</text>
  31. <input type='number' value='{{yanwu}}' name='piece' id='yanwu' bindblur="changeVal" />
  32. <text style='border-radius: 0 3px 3px 0;' id='yanwu' bindtap='add'>+</text>
  33. </view>
  34. </view>
  35.  
  36. </view>

微信小程序展示页面

        

微信小程序不能在电脑上模拟,智能用手机操作,我们需要用手机打开我们的微信小程序。首先如果手机蓝牙没有打开回提醒打开蓝牙重新加载。如果手机蓝牙打开了就会去搜索附近的蓝牙模块,搜索到自己的低功率蓝牙,点击就可以连接到自己的蓝牙。我们就到了控制页面。
  我们可以通过微信小程序风扇和水泵。点击开关时会调用writeBLECharacteristicValue接口通过蓝牙模块给单片机发送指令,控制单片机上的风扇和水泵等硬件设备。

2.硬件设备介绍

  1.   硬件部分主要介绍单片机、低功率蓝牙、风扇和水泵。单片机用什么型号的都行,都能与蓝牙模块正常通信,收发数据。低功率蓝牙主要优点是功率低,寿命长,价格便宜。多用于硬件连接上位机软件。风扇和水泵是外接设备,由单片机控制。

1.单片机
  单片机的型号是stc89c52rc,STC89C52RC是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统的方法51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
2.蓝牙模块
  我用的是蓝牙型号是HC-06,给HC-06上电之后,HC-06的指示灯会不停地闪烁,这个时候就标志着进入AT模式了,配置的时候,HC-06的Rx和Tx 接到 51单片机的 Rx和 Tx,一般是P3.0,和P3.1,正常工作时,HC-06的Rx和Tx 接到 51单片机的 Tx和 Rx,8位数据位,1位结束位,无奇偶校验。一般HC-06模块的默认名称就是hc-06,默认配对密码是1234或0000。我们如果连接微信小程序,我们要把密码取消,这样微信小程序才能直接来连接。
3.风扇和水泵  
  风扇和水泵是直接供电就可以使用,我们只需要一个继电器就可以控制这两个设备,我选择了P3.5,P3.4这两个引脚来控制,高电平驱动,低电平关闭,这两个外接设备主要是测试数据有没有接受成功。

单片机程序主程序

  1. void ctrl(unsigned char a) //单字节数据接收
  2. { //注意:若单片机TXD(P3.1)无上拉能力,必须在P3.1端接上拉电阻。本次测试需要接上拉电阻
  3. TI=;
  4. SBUF=a;
  5. while(TI==);
  6. TI=;
  7. Mode=;
  8. if(SBUF==){
  9. LED_yanwu=;
  10. baojing=;
  11. fs=;
  12. led1=;
  13. led2=;
  14. }else if(SBUF==){
  15. LED_yanwu=;
  16. baojing=;
  17. fs=;
  18. Mode=;
  19. }else if(SBUF==){
  20. baojing=;
  21. LED_wendu=;
  22. fs1=;
  23. }else if(SBUF==){
  24. baojing=;
  25. LED_wendu=;
  26. fs1=;
  27. led1=;
  28. led2=;
  29. Mode=;
  30. }
  31. }
  32. void main()
  33. {
  34. check_wendu();
  35. check_wendu();
  36. Init1602();
  37. ES=; //关中断
  38. SCON = 0x50; // REN=1允许串行接受状态,串口工作模式1,
  39. //10位UART(1位起始位,8位数据位,1位停止位,无奇偶校验),波特率可变
  40. TMOD = 0x20; // 定时器1工作于方式2,8位自动重载模式, 用于产生波特率
  41. TH1=TL1=0xFD; // 波特率9600 (本次测试采用晶振为11.0592)
  42. PCON &= 0x7f; // 波特率不倍增
  43. TR1 = ; //定时器1开始工作,产生波特率
  44. TI=; //接收标志位置0
  45. RI=;
  46.  
  47. ES=;
  48. while()
  49. {
  50. temp=ADC0809();
  51. check_wendu();
  52. Key();
  53. if(RI==) // 是否有数据到来
  54. {
  55. RI = ;
  56. ctrl(SBUF);
  57. }
  58. Display_1602(yushe_wendu,yushe_yanwu,c,temp); //c温度值,temp烟雾值
  59. if(Mode==)
  60. {
  61. if(temp>=yushe_yanwu)
  62. {
  63. LED_yanwu=;
  64. baojing=;
  65. fs=;
  66. }
  67. else
  68. {
  69. LED_yanwu=;
  70. }
  71. if(c>){
  72. c = ;
  73. }
  74. if(c>=(yushe_wendu*))
  75. {
  76. baojing=;
  77. LED_wendu=;
  78. fs1=;
  79. }
  80. else
  81. {
  82. LED_wendu=;
  83. }
  84. if((temp<yushe_yanwu)&&(c<(yushe_wendu*)))
  85. {
  86. baojing=;
  87. fs=;
  88. fs1=;
  89. }
  90. }
  91. }
  92. }

硬件实物图

 数据采集显示正常,微信小程序可以正常控制单片机的水泵和风扇,通信正常无异常。硬件部分我就简单的拿出来说了一下,所涉及到的知识肯定比我展示到的多,软件部分主要是对低功率蓝牙的搜索,连接,发送数据比较麻烦。

视频链接:http://v.youku.com/v_show/id_XNDE1ODI1NzI2NA==.html?x&sharefrom=android&sharekey=f051256eda08cc3764d9d6d7a5d231788

微信小程序连接低功率蓝牙控制单片机上硬件设备的更多相关文章

  1. 微信小程序电商实战-首页(上)

    嗨,大家好!经过近两周的精心准备终于开始微信小程序电商实战之路喽.那么最终会做成什么样呢?当然可以肯定不会只做一个静态demo哦,先把我们小程序电商实战的整体架构发出来晒一下,请看下图:   架构图. ...

  2. 微信小程序把玩(三十八)获取设备信息 API

    原文:微信小程序把玩(三十八)获取设备信息 API 获取设备信息这里分为四种, 主要属性: 网络信息wx.getNetWorkType, 系统信息wx.getSystemInfo, 重力感应数据wx. ...

  3. 用微信小程序连接WordPress网站

    随着微信小程序的功能越来越强,特别对个人开发者的开放,让个人开发者有机会尝试微信小程序.如果你有自己的个人网站,就可以把个人网站搬到微信小程序里,通过小程序直接访问网站的内容. 要想微信小程序可以获取 ...

  4. 微信小程序连接本地接口(转)

    原文地址 最近的一个项目就是微信小程序 第一次接触微信开发者工具,并进行小程序的后端开发, 于是想看一下小程序如何请求本地的后台服务接口 wx.request({ url: 'http://local ...

  5. 微信小程序里如何用阿里云上传视频,图片。。

    纯手写,踩了半天多的坑干出来了... 网上也有对于阿里云如何在微信小程序里使用,但是很不全,包括阿里云文档的最佳实践里. 话不多说上代码了. upvideo(){ var aliOssParams = ...

  6. 微信小程序开发注意事项总结:上拉加载失效、转义字符等

    1.上拉加载失效 问题背景:部分页面上拉加载失效.当使用flex布局,底部固定,中间采用自适应撑满全屏实现滚动时,发现上拉加载失效,不知道是什么原因. 解决问题: 在小程序中,官方为我们提供了原生的下 ...

  7. 转:【微信小程序】 微信小程序-拍照或选择图片并上传文件

    调用拍照API:https://mp.weixin.qq.com/debug/wxadoc/dev/api/media-picture.html?t=20161222#wxchooseimageobj ...

  8. [转]微信小程序开发(二)图片上传+服务端接收

    本文转自:http://blog.csdn.net/sk719887916/article/details/54312573 文/YXJ 地址:http://blog.csdn.net/sk71988 ...

  9. 微信小程序连接Java后台

    有人问我小程序怎么连后台,这里直接贴代码 在app.js里 // api request request(url, params) { return new Promise((resolve, rej ...

随机推荐

  1. 二叉树的建立&&前中后遍历(递归实现)&&层次遍历

    下面代码包含了二叉树的建立过程,以及三种遍历方法了递归实现,代码中还利用队列实现了层次遍历. import java.util.LinkedList; import java.util.Queue; ...

  2. Python中 * 与 **, *args 与 **kwargs的用法

    * 用于传递位置参数(positional argument) ** 用于传递关键字参数(keyword argument) 首先,先通过一个简单的例子来介绍 * 的用法: def add_funct ...

  3. 什么是RESTful?RESTfule风格

    导读 理解什么是REST之前,先去脑补以下什么是HTTP,参考[Http协议] 什么是REST? REST(英文:Representational State Transfer,简称REST,意思:表 ...

  4. Swift Playground词法分析器DEMO

    正在看极客时间宫文学老师的编译原理之美,用swift playground写了一个第二课"int age >= 45"的词法解析DEMO 为了保持原课程代码,DEMO用了顺序 ...

  5. Python基础第一课

    Python基础 安装软件并配置环境变量 1.第一句python --初学后缀名可以是任何数 --后期学习需要导入模块时不是py后缀名会报错 2.两种执行方式 Python解释器 py文件路径 Pyt ...

  6. art-template循环无法显示出数据

    art-template循环遍历无法显示数据原因 1.语法问题:循环语句导致的问题 2.插件问题: 用标准语法时循环数据如果引入第一个插件,会导致数据显示不出来只有引入第二个插件才可循环出数据 用原生 ...

  7. VS编译命令

    一.前言 由于公司要求项目需要走CI构建平台,抛弃掉之前的人工编译打包方式,所以需要调研一下项目怎么通过命令行编译出产物. 二.准备工作 在构建机器上安装vs(本文示例为vs2017) 将代码上传版本 ...

  8. kubernetes-部署harbor

    Habor是由VMWare中国团队开源的容器镜像仓库.事实上,Habor是在Docker Registry上进行了相应的企业级扩展,从而获得了更加广泛的应用,这些新的企业级特性包括:管理用户界面,基于 ...

  9. 【Java8流】使用学习

    [Java8流]使用学习 ============================================= 1.删除子目录及文件 ============================== ...

  10. 关于页面打印window.print()的样式问题

    当我们打印网页的时候.有时候会发现.打印出来的.跟网页上看到的样式的差别有点大.这其中可能有的问题是.样式问题. 当调用打印(window.print())方法时.打印机会在网页的样式中查找 @med ...