“无线电子冰箱贴”项目提交1. 说明
这个电子冰箱贴是一个无线连接的演示项目,实现的功能是用手机发送信息,远程显示在电子冰箱贴上。可以显示提醒的事件备忘,还可以显示当日菜谱和需要在冰箱里补充的食品。具体显示的内容是可以扩展的。
但是这个项目其实相对比较复杂,采用了wifi协议,还有z-wave协议。其中z-wave协议是通过一个UZB实现的,这一部分只是在这里展示,完整的功能并没有调试通过。
整个项目是基于树莓派实现的,在这个树莓派上同时运行着z-wave的gateway,还有本电子冰箱贴程序,也放在启动的服务项中了。
对于数据分发,使用的是pubnub协议。这个协议国内对应的产品是野狗,提供类似的一点订阅多点分发的功能。
2. 采用的硬件和服务
2.1 树莓派3
2.2 电子墨水屏
2.3 备用的使用IDT充电系统的3W无线充电套件(发送接收套件)和锂电池及充电升压模块,这部分调试通过了。不过没有包括在本项目说明中。这个也是采用电子墨水屏的原因,当系统没电时,仍然可以显示数据。
2.4 使用了pubnub服务(具体使用见后面)
2.5 z-Wave协议
2.6 基于树莓派的Raspbian
2.7 Cordova手机开发环境
3. 开发原理说明
3.1 这里用手机做一个APP,使用cordova,这样调试时直接可以用网页启动调试,不一定需要build
3.2 因为采用了pubnub协议,所以这个手机可以同时给所有定于了这条消息的显示屏同时显示。显示屏订阅了这个消息,当新消息到来就可以立刻显示出来。
4. 手机APP
4.1 首先安装好cordova,android Studio并下载需要的插件和工具。
4.2 执行“cordova create esticker”
4.3 编辑其中的index.html,
其中最重要的语句是
这个文件我下载到了本地,所以在程序中注释掉了,如果使用需要取消注释。这个是启动pubnub服务的重要文件。
源码如下
- <!DOCTYPE html>
- <html>
- <!--
-
- -->
- <head>
-
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, user-scalable=no
- initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
-
- <title>eSticker</title>
-
- <style>
- [url=home.php?mod=space&uid=568594]@import[/url] 'ui/css/evothings-app.css';
- </style>
-
-
- <script src="cordova.js"></script>
- <script src="libs/jquery/jquery.js"></script>
- <script src="libs/evothings/evothings.js"></script>
- <script src="libs/evothings/ui/ui.js"></script>
- <script src="libs/evothings/arduinoble/arduinoble.js"></script>
- <script src="libs/pubnub.4.18.0.js"></script>
- <!-- or <script src="https://cdn.pubnub.com/sdk/javascript/pubnub.4.18.0.js"></script> -->
-
-
- </head>
-
- <body><!-- enables low-delay CSS transitions. -->
-
- <header>
- <button class="back">
- <img src="./ui/images/arrow-left.svg" />
- </button>
-
- <img class="logotype" src="./ui/images/logoesticker.png" alt="eSticker" />
-
- <!--<button class="menu"><img src="ui/images/menu.svg" /></button>-->
- </header>
-
- <h1>eSticker</h1>
-
- <p id="info">Initializing...</p>
-
- <!--
- <button class="yellow wide">CONNECT</button>
- //New empty Keys
- pubnub = new PubNub({
- publishKey: 'pub-c-218bb0fd-bdb4-45c6-a1c4-77d7674c8caf',
- subscribeKey: 'sub-c-383e74cc-d0e3-11e7-b07a-4e4fd9aca72d'
- })
- -->
-
- <br />
-
- <input type="text" id="txtag" value="input text...">
-
- <button class="green wide big">Sent Text</button>
-
- <br />
-
- <button class="red wide big">Clear Text</button>
-
- <script>
- // Application object.
- var app = {}
-
- var pubnub = new PubNub({
- subscribeKey: 'sub-c-81c369ca-5ba6-11e7-a298-xxxxxxxxxxx', // always required
- publishKey: 'pub-c-6a7a7381-128c-4d9b-b3af-xxxxxxxxxxxxxx' // only required if publishing
- });
-
- // Function PublishMessage.
- function publishMessage(txMessage) {
- console.log("Since we're publishing on subscribe connectEvent, we're sure we'll receive the following publish.");
- var publishConfig = {
- channel : "flood_alarm_signal",
- message : txMessage
- }
- pubnub.publish(publishConfig, function(status, response) {
- console.log(status, response);
- })
- };
-
-
- // Connected device.
- app.device = null;
- var count=0;
-
- // Add listener and subscribing
- pubnub.addListener({
- status: function(statusEvent) {
- if (statusEvent.category === "PNConnectedCategory") {
- publishMessage("PNConnected!");
- }
- },
- message: function(message) {
- console.log("New Message!!", message);
- count=count+1;
- //app.showMessage(message.message);
- app.showMessage(message.message);
- },
- presence: function(presenceEvent) {
- // handle presence
- }
- });
- pubnub.subscribe({
- channels: ['flood_alarm_signal']
- });
-
-
-
-
- // Turn on LED.
- app.sentTX = function()
- {
- var txSent=new Uint8Array();
- txSent=document.getElementById('txtag').value;
- app.device && app.device.writeDataArray(new Uint8Array([txSent]), '19b10001-e8f2-537e-4f6c-d104768a1214');
-
- var txMessage = txSent;
- publishMessage(txMessage) ;
-
- //app.showMessage(txMessage.text);
- }
-
- // Turn off LED.
- app.clearTX = function()
- {
- document.getElementById('txtag').value = " ";
- app.device && app.device.writeDataArray(new Uint8Array([0]), '19b10001-e8f2-537e-4f6c-d104768a1214');
- }
-
- app.showMessage = function(info)
- {
- document.getElementById('info').innerHTML = info
- };
-
- // Called when BLE and other native functions are available.
- app.onDeviceReady = function()
- {
- app.showMessage('Touch the connect button to begin.');
- };
-
- app.connect = function()
- {
- evothings.arduinoble.close();
-
- app.showMessage('Connecting...');
-
- evothings.arduinoble.connect(
- 'TAG', // Advertised name of BLE device.
- function(device)
- {
- app.device = device;
- app.showMessage('Connected! Touch buttons to turn LED on/off.');
- },
- function(errorCode)
- {
- app.showMessage('Connect error: ' + errorCode + '.');
- });
- };
-
- document.addEventListener(
- 'deviceready',
- function() { evothings.scriptsLoaded(app.onDeviceReady) },
- false);
- </script>
-
- </body>
-
- </html>
4.4 生成android可执行文件apk,执行
cordova platform add android
cordova build android
这样可以测试文件
cordova run android
这个是模拟器启动的情况,可以看到pubnub也启动并连接了,显示"PNConnected!",然后点击数据就可以显示在显示屏上,
生成的apk文件见附件。
实现文件发送的只有一句
publishMessage(txMessage) ;
这样的过程也太简单了了。这个完全依赖于pubnub服务的产生。
5. 使用树莓派驱动电子墨水屏
5.1 这个是waveshare微雪的1.54吋屏,随机提供了基于SPI的范例程序,不过其引脚分散在树莓派的不同位置,我就重新定义一下,尽可能接近。并定义了自己的页面,是ztag,z-wave,如下图
旋转后显示,文字就出现在空白的地方。
在使用前,还需要安装RPi驱动,和Image,SPIdev,python-pip等需要的packages,这样才能正确运行。
电子屏需要先初始化,然后刷新内存,最后把内存的数据显示出来,可以全屏刷新,也可以局部刷新。
5.2 源码如下
- ##
- # @filename : main.cpp
- # @brief : 1.54inch e-paper display demo
- ##
-
- import epd1in54
- import time
- import Image
- import ImageDraw
- import ImageFont
-
- from pubnub.callbacks import SubscribeCallback
- from pubnub.enums import PNStatusCategory
- from pubnub.pnconfiguration import PNConfiguration
- from pubnub.pubnub import PubNub
- pnconfig = PNConfiguration()
- pnconfig.subscribe_key = 'sub-c-81c369ca-5ba6-11e7-a298-xxxxxxxxxxxxxx'
- pnconfig.publish_key = 'pub-c-xxxxxxxxxxxxxxxxxxxxxxxxxx'
- pubnub = PubNub(pnconfig)
-
-
- def main():
- epd = epd1in54.EPD()
- epd.init(epd.lut_full_update)
- image = Image.new('1', (epd1in54.EPD_WIDTH, epd1in54.EPD_HEIGHT), 255) # 255: clear the frame
- draw = ImageDraw.Draw(image)
- font = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf', 24)
- draw.rectangle((0, 10, 200, 34), fill = 0)
- epd.clear_frame_memory(0xFF)
- epd.set_frame_memory(image, 0, 0)
- epd.display_frame()
- epd.delay_ms(2000)
-
- # for partial update
- epd.init(epd.lut_partial_update)
- image = Image.open('/home/pi/zTag/python/monocolor.bmp')
- epd.set_frame_memory(image, 0, 0)
- epd.display_frame()
- epd.set_frame_memory(image, 0, 0)
- epd.display_frame()
-
- time_image = Image.new('1', (96, 48), 255) # 255: clear the frame
- draw = ImageDraw.Draw(time_image)
- font = ImageFont.truetype('/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf', 32)
- image_width, image_height = time_image.size
-
- def indisplay(txdata):
- draw.rectangle((0, 0, 96, 48), fill = 255)
- draw.text((0, 0), txdata, font = font, fill = 0)
- epd.set_frame_memory(time_image.rotate(90), 80, 80)
- epd.display_frame()
-
- # Pubnub start...
- def my_publish_callback(envelope, status):
- if not status.is_error():
- pass
- else:
- pass
-
- class MySubscribeCallback(SubscribeCallback):
- def presence(self, pubnub, presence):
- pass
- def status(self, pubnub, status):
- # print("Status category", status.category)
- if status.category == PNStatusCategory.PNUnexpectedDisconnectCategory:
- pass
- elif status.category == PNStatusCategory.PNConnectedCategory:
- pubnub.publish().channel("flood_alarm_signal").message("Hi...").async(my_publish_callback)
- elif status.category == PNStatusCategory.PNReconnectedCategory:
- pass
- def message(self, pubnub, message):
- txdata=message.message
- #jdata=json.dumps(txdata)
- print(txdata)
- indisplay(txdata)
-
- pubnub.add_listener(MySubscribeCallback())
- pubnub.subscribe().channels('flood_alarm_signal').execute()
-
对于pubnub的引用,需要先订阅subscribe,
pubnub.subscribe().channels('flood_alarm_signal').execute()
这样在channel上的消息就可以随时接收了。这个连接是TCP连接,而且根据pubnub的说明,可以并发上千个订阅,响应速度是非常快的,而且也非常可靠。
6. 运行演示
6.1 启动树莓派的页面
可以看到z-Wave也启动了,这个版本是预制了zwave协议的版本。
6.2 执行python main.py
启动,显示连接
输入cool
显示在硬件上
其右侧是无线充电套件,直接输出的是4.85-5.25V直接的电压,可以直接在VCC和GND之间连接给树莓派和电子墨水屏供电,这个只要做一个外壳就可以的。
6.3 这项目最有意义的地方,就是使用了pubnub协议,可以实现一对多的演示,在多个手机和多个电子屏上都实现信息的广播和传输。因此应用起来就很有意义。
7. 补充说明
7.1 pubnub协议说明
这个是一个很有意思的协议,需要注册一个账号,然后申请一对key,分别实现发送和订阅,并不需要其他注册的环节,非常简便。
7.2 z-wave协议说明
这个是一个类似zigbee的低功耗协议,不过是和TI-CC1350一样是sub1GHz的协议,远距离传输更有效。但在国内几乎没有应用的领域。
此内容由EEWORLD论坛网友北方原创,如需转载或用于商业用途需征得作者同意并注明出处
本帖最后由 北方 于 2017-12-8 15:17 编辑