云中树莓派(3):通过 AWS IoT 控制树莓派上的 Led
云中树莓派(1):环境准备
云中树莓派(2):将传感器数据上传到AWS IoT 并利用Kibana进行展示
云中树莓派(3):通过 AWS IoT 控制树莓派上的Led
云中树莓派(4):利用声音传感器控制Led灯
1. Led 连接与测试
在某宝上买了几样配件,包括T型GPIO扩展板、40P排线、亚克力外壳、400孔面包板、若干杜邦线。现在我的树莓派长得这个样子了:
不由得感谢神奇的某宝,这些东西每一样都不超过三四块钱。
1.1 接线
以下几个简单步骤就完成了接线:
- 将排线一头插在树莓派的40个pin脚上,将另一头插在扩展板上。要注意方向,多试几次。还要注意在树莓派关机时候再插入。
- 把扩展板插在面包板上。
- 把Led 的长脚(正极)插在面包板第6行的任何一个孔内(对应GPIO18),将其短脚(负极或接地)插在第7行的任何一个孔内(对应GND)。
简单说下面包板。刚拿到手时还有点不知所措,稍微研究一下后就简单了。面包板为长方形,长边的两边是为了接电源的,每个长边都是联通的;中间区域内,每行内是联通的。
1.2 简单测试
下面的 python 能让led 灯每两秒钟亮一次:
import RPi.GPIO as GPIO import timePIN_NO=18 GPIO.setmode(GPIO.BCM) GPIO.setup(PIN_NO, GPIO.OUT) loopCount = 0 for x in xrange(500):print("Loop " + str(loopCount))GPIO.output(PIN_NO, GPIO.HIGH)time.sleep(2)GPIO.output(PIN_NO, GPIO.LOW)time.sleep(2)loopCount += 1GPIO.cleanup()
也就是通过控制GPIO18的电压为高还是低来控制Led 灯是亮还是灭。
2. AWS IoT Device Shadow
-
- UPDATE:如果设备的影子不存在,则创建一个该影子;如果存在,则使用请求中提供的数据更新设备的影子的内容。存储数据时使用时间戳信息,以指明最新更新时间。向所有订阅者发送消息,告知 desired 状态与 reported 状态之间的差异 (增量)。接收到消息的事物或应用程序可以根据 desired 状态和 reported 状态之间的差异执行操作。例如,设备可将其状态更新为预期状态,或者应用程序可以更新其 UI,以反映设备状态的更改。
- GET:检索设备的影子中存储的最新状态 (例如,在设备启动期间,检索配置和最新操作状态)。此操作将返回整个 JSON 文档,其中包括元数据。
- DELETE:删除设备的影子,包括其所有内容。这将从数据存储中删除 JSON 文档。您无法还原已删除的设备的影子,但可以创建具有相同名称的新影子。
也就是说,要通过 AWS IoT 来操作设备,需要通过设备影子进行。下图是控制Led 灯泡的示意图。外部应用和设备之间的交互通过设备影子进行。
Device Shadow 使用系统预留的 MQTT 主题来做应用程序和设备之间的通信:MQTT 主题 用途 $aws/things/myLightBulb/shadow/update/accepted
当设备的影子更新成功时,Device Shadow 服务将向此主题发送消息 $aws/things/myLightBulb/shadow/update/rejected
当设备的影子更新遭拒时,Device Shadow 服务将向此主题发送消息 $aws/things/myLightBulb/shadow/update/delta
当检测到设备的影子的“reported”部分与“desired”部分之间存在差异时,Device Shadow 服务将向此主题发送消息。 $aws/things/myLightBulb/shadow/get/accepted
当获取设备的影子的请求获批时,Device Shadow 服务将向此主题发送消息。
$aws/things/myLightBulb/shadow/get/rejected
当获取设备的影子的请求遭拒时,Device Shadow 服务将向此主题发送消息。
$aws/things/myLightBulb/shadow/delete/accepted
当设备的影子被删除时,Device Shadow 服务将向此主题发送消息。
$aws/things/myLightBulb/shadow/delete/rejected
当删除设备的影子的请求遭拒时,Device Shadow 服务将向此主题发送消息。
$aws/things/myLightBulb/shadow/update/documents
每次设备的影子更新成功执行时,Device Shadow 服务都会向此主题发布状态文档。
下图显示了控制流程:
- 连接着的 Led 灯发送封装在MQTT消息中的 reported 状态 『off』 到 AWS IoT
- AWS IoT 通过 led 灯使用的证书来确定它所属的虚拟事物
- AWS IoT 将 reported 状态保存在设备影子 JSON 文件中
- 一条 AWS IoT rule 正监控着 led 的 off 状态,它发送一个消息到某个 SNS topic
- 某 application 收到 SNS 消息。用户将 led 期望状态(desired state)设置为 on
- AWS IoT 收到该消息,它更新设备影子中的 desired state,同时发送包含期望状态的 message 到某些topic。此时,reported 和 desired 状态是 『Out of Sync』的
- led 收到 delta 消息,开始根据其中的 desired status 来设置其实际状态
- led 将其状态设置为 on,向 MQTT topic 发送新的 reported 状态
- AWS IoT 更新设备影子,现在该设备的 reported 和 desired 状态一致了
3. Python 代码
代码一共就两个文件。文件 ledController.py 充当Led 灯的控制器,它定期向Led 发出『开』或『关』的指令,并定期获取其状态;文件 ledSwitch.py 充当 Led 等的操纵器,它通过调用树莓派的 GPIO 接口来设置和获取 led 灯的状态,以及将其状态上报给 IoT 服务。
AWS IoT 提供了 Device Shadow python SDK,因此不需要直接操作各种 MQTT 主题,而可以使用 get,update 和 delete 这种API。其地址在 https://github.com/aws/aws-iot-device-sdk-python/tree/master/AWSIoTPythonSDK/core/shadow。
3.1 ledController.py
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient import logging import time import json import threading# Led shadow JSON Schema # # # Name: Led # {# "state: {# "desired": {# "light": <on|off> # } # } #} deviceShadowHandler = Nonedef getDeviceStatus():while True:print("Getting device status...\n")deviceShadowHandler.shadowGet(customShadowCallback_get, 50)time.sleep(60) def customShadowCallback_get(payload, responseStatus, token):if responseStatus == "timeout":print("Get request with token " + token + " time out!")if responseStatus == "accepted":print("========== Printing Device Current Status =========")print(payload)payloadDict = json.loads(payload)#{"state":{"desired":{"light":0},"reported":{"light":100}try:desired = payloadDict["state"]["desired"]["light"]desiredTime = payloadDict["metadata"]["desired"]["light"]["timestamp"]except Exception:print("Failed to get desired state and timestamp.")else:print("Desired status: " + str(desired) + " @ " + time.ctime(int(desiredTime)))try:reported = payloadDict["state"]["reported"]["light"]#"metadata":{"desired":{"light":{"timestamp":1533893848}},"reported":{"light":{"timestamp":1533893853}}}reportedTime = payloadDict["metadata"]["reported"]["light"]["timestamp"]except Exception:print("Failed to get reported time or timestamp")else:print("Reported status: " + str(reported) + " @ " + time.ctime(int(reportedTime)))print("=======================================\n\n")if responseStatus == "rejected":print("Get request with token " + token + " rejected!")def customShadowCallback_upate(payload, responseStatus, token):# payload is a JSON string which will be parsed by jason libif responseStatus == "timeout":print("Update request with " + token + " time out!")if responseStatus == "accepted":playloadDict = json.loads(payload)print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")print("Update request with token: " + token + " accepted!")print("light: " + str(playloadDict["state"]["desired"]["light"]))print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n")if responseStatus == "rejected":print("Update request " + token + " rejected!")def customShadowCallback_delete(payload, responseStatus, token):if responseStatus == "timeout":print("Delete request " + token + " time out!")if responseStatus == "accepted":print("Delete request with token " + token + " accepted!")if responseStatus == "rejected":print("Delete request with token " + token + " rejected!")# Cofigure logging logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.ERROR) streamHandler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) logger.addHandler(streamHandler)# AWS IoT Core endpoint. Need change some values to yours. awsiotHost = "**********.iot.*********.amazonaws.com" awsiotPort = 8883; # AWS IoT Root Certificate. Needn't change. rootCAPath = "/home/pi/awsiot/VeriSign-Class3-Public-Primary-Certification-Authority-G5.pem" # Device private key. Need change to yours. privateKeyPath = "/home/pi/awsiot/aec2731afd-private.pem.key" # Device certificate. Need change to yours. certificatePath = "/home/pi/awsiot/aec2731afd-certificate.pem.crt" myAWSIoTMQTTShadowClient = None; myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("RaspberryLedController") myAWSIoTMQTTShadowClient.configureEndpoint(awsiotHost, awsiotPort) myAWSIoTMQTTShadowClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20) myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(60) # 10sec myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(50) #5sec#connect to AWS IoT myAWSIoTMQTTShadowClient.connect()#create a devcie Shadow with persistent subscription thingName = "homepi" deviceShadowHandler = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(thingName, True)#Delete shadow JSON doc deviceShadowHandler.shadowDelete(customShadowCallback_delete, 50)#start a thread to get device status every 5 seconds statusLoopThread = threading.Thread(target=getDeviceStatus) statusLoopThread.start()#update shadow in a loop loopCount = 0 while True:desiredState = "off"if (loopCount % 2 == 0):desiredState = "on"print("To change Led desired status to \"" + desiredState + "\" ...\n")jsonPayload = '{"state":{"desired":{"light":"' + desiredState + '"}}}'print("payload is: " + jsonPayload + "\n")deviceShadowHandler.shadowUpdate(jsonPayload, customShadowCallback_upate, 60)loopCount += 1time.sleep(60)
3.2 ledSwitch.py
import RPi.GPIO as GPIO from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient import logging import time import json# Led shadow JSON Schema # # # Name: Led # {# "state: {# "desired": {# "light": <on|off> # } # } #} LED_PIN_NUM = 18 # GPIO Number of Led long pin. Change to yours. deviceShadowHandler = None #initialize GOPI GPIO.setmode(GPIO.BCM) GPIO.setup(LED_PIN_NUM, GPIO.OUT)def customShadowCallback_Delta(payload, responseStatus, token):# payload is a JSON string which will be parsed by jason libprint(responseStatus)print(payload)payloadDict = json.loads(payload)print("++++++++ Get DELTA data +++++++++++")desiredStatus = str(payloadDict["state"]["light"])print("desired status: " + desiredStatus)print("version: " + str(payloadDict["version"]))#get device current statuscurrentStatus = getDeviceStatus()print("Device current status is " + currentStatus)#udpate device current statusif (currentStatus != desiredStatus):# update device status as desired updateDeviceStatus(desiredStatus)# send current status to IoT service sendCurrentState2AWSIoT()print("+++++++++++++++++++++++++++\n")def updateDeviceStatus(status):print("=============================")print("Set device status to " + status)if (status == "on"):turnLedOn(LED_PIN_NUM)else:turnLedOff(LED_PIN_NUM)print("=============================\n")def getDeviceStatus():return getLedStatus(LED_PIN_NUM)def turnLedOn(gpionum):GPIO.output(gpionum, GPIO.HIGH)def turnLedOff(gpionum):GPIO.output(gpionum, GPIO.LOW)def getLedStatus(gpionum):outputFlag = GPIO.input(gpionum)print("outputFlag is " + str(outputFlag))if outputFlag:return "on"else:return "off" def sendCurrentState2AWSIoT():#check current status of devicecurrentStatus = getDeviceStatus()print("Device current status is " + currentStatus)print("Sending reported status to MQTT...")jsonPayload = '{"state":{"reported":{"light":"' + currentStatus + '"}}}'print("Payload is: " + jsonPayload + "\n")deviceShadowHandler.shadowUpdate(jsonPayload, customShadowCallback_upate, 50)def customShadowCallback_upate(payload, responseStatus, token):# payload is a JSON string which will be parsed by jason libif responseStatus == "timeout":print("Update request with " + token + " time out!")if responseStatus == "accepted":playloadDict = json.loads(payload)print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")print(payload)print("Update request with token: " + token + " accepted!")print("light: " + str(playloadDict["state"]["reported"]["light"]))print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n")if responseStatus == "rejected":print("Update request " + token + " rejected!")def customShadowCallback_Get(payload, responseStatus, token):print("responseStatus: " + responseStatus)print("payload: " + payload)payloadDict = json.loads(payload)# {"state":{"desired":{"light":37},"delta":{"light":37}},"metadata":{"desired":{"light":{"timestamp":1533888405}}},"version":54stateStr = "" try:stateStr = stateStr + "Desired: " + str(payloadDict["state"]["desired"]["light"]) + ", "except Exception:print("No desired state")try:stateStr = stateStr + "Delta: " + str(payloadDict["state"]["delta"]["light"]) + ", "except Exception:print("No delta state")try:stateStr = stateStr + "Reported: " + str(payloadDict["state"]["reported"]["light"]) + ", "except Exception:print("No reported state") print(stateStr + ", Version: " + str(payloadDict["version"]))def printDeviceStatus():print("=========================")status = getDeviceStatus()print(" Current status: " + str(status))print("=========================\n\n")# Cofigure logging logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) logger.addHandler(streamHandler)awsiotHost = "***********.iot.********.amazonaws.com" awsiotPort = 8883; rootCAPath = "/home/pi/awsiot/VeriSign-Class3-Public-Primary-Certification-Authority-G5.pem" privateKeyPath = "/home/pi/awsiot/aec2731afd-private.pem.key" certificatePath = "/home/pi/awsiot/aec2731afd-certificate.pem.crt" myAWSIoTMQTTShadowClient = None; myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("RaspberryLedSwitch") myAWSIoTMQTTShadowClient.configureEndpoint(awsiotHost, awsiotPort) myAWSIoTMQTTShadowClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20) myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(60) # 10sec myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(30) #5sec#connect to AWS IoT myAWSIoTMQTTShadowClient.connect()#create a devcie Shadow with persistent subscription thingName = "homepi" deviceShadowHandler = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(thingName, True)#listen on deleta deviceShadowHandler.shadowRegisterDeltaCallback(customShadowCallback_Delta)#print the intital status printDeviceStatus()#send initial status to IoT service sendCurrentState2AWSIoT()#get the shadow after started deviceShadowHandler.shadowGet(customShadowCallback_Get, 60)#update shadow in a loop loopCount = 0 while True:time.sleep(1)
3.3 主要过程
(1)ledSwitch.py 在运行后,获取led 的初始状态,并将其发给 AWS IoT 服务:
=========================outputFlag is 0Current status: off ========================= outputFlag is 0 Device current status is off Sending reported status to MQTT... Payload is: {"state":{"reported":{"light":"off"}}}
(2)ledController.py 开始运行后,它首先获取led 的当前状态,为 『off』
(3)Controller 将其 desired 状态设置为 on
To change Led desired status to "on" ... payload is: {"state":{"desired":{"light":"on"}}}
(4)Switch 收到 DELTA 消息,调用 GPIO 接口设置其状态,并向 IOT 服务报告其状态
{"version":513,"timestamp":1533983956,"state":{"light":"on"},"metadata":{"light":{"timestamp":1533983956}},"clientToken":"93dfc84c-c9f9-49fb-b844-d55203991208"} ++++++++ Get DELTA data +++++++++++ desired status: on version: 513 outputFlag is 0 Device current status is off ============================= Set device status to on ============================= outputFlag is 1 Device current status is on Sending reported status to MQTT... Payload is: {"state":{"reported":{"light":"on"}}}
(5)Controller 获取最新状态
{"state":{"desired":{"light":"on"},"reported":{"light":"on"}},"metadata":{"desired":{"light":{"timestamp":1533983956}},"reported":{"light":{"timestamp":1533983957}}},"version":514,"timestamp":1533983959,"clientToken":"f24bcbbb-4b24-4354-b1df-349afdf23422"} Desired status: on @ Sat Aug 11 18:39:16 2018 Reported status: on @ Sat Aug 11 18:39:17 2018
(6)循环往复
欢迎大家关注我的个人公众号:
参考链接:
- https://www.linkedin.com/pulse/understanding-internet-things-aws-iot-kay-lerch/
- https://iotbytes.wordpress.com/device-shadows-part-1-basics/
- https://github.com/pradeesi/AWS-IoT-Shadows
- https://github.com/aws/aws-iot-device-sdk-python/tree/master/samples/basicShadow
- https://raspi.tv/2013/rpi-gpio-basics-5-setting-up-and-using-outputs-with-rpi-gpio
转载于:https://www.cnblogs.com/sammyliu/p/9460109.html
云中树莓派(3):通过 AWS IoT 控制树莓派上的 Led相关推荐
- 手机控制树莓派linux,使用安卓手机控制树莓派
在特殊情况下,没有用于树莓派显示的显示器,用电脑控制树莓派也不方便,这时可以通过手中的手机来登陆树莓派,这种方法仅仅需要一部手机,条件非常容易满足.这篇文章教大家如何用手机的手机连接树莓派,并将手机的 ...
- 树莓派笔记15:手机控制树莓派小车
1 成果展示 花了点时间做了简单的手机控制树莓派小车项目,其实主要是对之前各种学习内容的一个综合利用,也特地抽出时间学习了一下最基本的Android开发.下面的图片是成果的展示,树莓派小车由树莓派.小 ...
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(八)使用domoticz+mosquitto+Android客户端实现控制mini2440上的LED(一)
本篇将在上一篇交叉编译paho.mqtt.embedded-c官方的源代码例程基础上,稍作修改,尝试实现domoticz+mosquitto联合做服务器,使用Android客户端APP或浏览器对min ...
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(九)使用domoticz+mosquitto+Android客户端实现控制mini2440上的LED(二)
为了充分利用domoticz平台的对MQTT客户端的控制功能,现在,受控设备端代码的核心任务转移到了对domoticz/out主题的MQTT消息解析上.本文将设计一个简单框架来实现对其消息的解析和功能 ...
- 云中树莓派(5):利用 AWS IoT Greengrass 进行 IoT 边缘计算
云中树莓派(5):利用 AWS IoT Greengrass 进行 IoT 边缘计算 云中树莓派(1):环境准备 云中树莓派(2):将传感器数据上传到AWS IoT 并利用Kibana进行展示 云中树 ...
- 基于树莓派+传感器+阿里云IoT的智能家居管理(代码实现)
视频教程已经放在B站 请大家狠狠地三连我 虽然我没有稚晖君那么强 教程!基于树莓派+传感器+阿里云IoT的智能家居管理(2) 主文件 #!/usr/bin/python3import aliLink, ...
- java gpio_Java控制树莓派GPIO口-Pi4J
Pi4J(http://pi4j.com/)是专门用来控制树莓派GPIO口以及通信的Java库.它有如下功能: Export & unexport GPIO pins Configure GP ...
- 启明云端esp32开发板直连亚马逊AWS IOT平台实例控制灯泡演示
ESP32通过AWS IOT物联网平台接入物联网,Alexa亚马逊音箱触发Lambda对乐鑫ESP32进行控制,实现ESP32接入Alexa亚马逊音箱. 登录亚马逊AWS IOT Core后台,可以创 ...
- matlab控制树莓派3b,树莓派3B+ 手机h5网页控制GPIO
ezgif-4-5d181e9b42.gif 本文介绍如何在H5页面控制树莓派GPIO 仅实现以BCM编码方式控制GPIO,其他方式未做. 演示地址:http://gpio.exmll.cn/ 点击B ...
- 树莓派输出pwm波c语言,树莓派Ubuntu18.04使用pigpio库产生PWM波实现舵机控制
树莓派Ubuntu18.04使用pigpio库产生PWM波实现舵机控制 树莓派Ubuntu18.04使用pigpio库产生PWM波实现舵机控制 一:pigpio库简介 pigpio是一个用于树莓派的库 ...
最新文章
- [OS复习]进程管理4
- 阿里云主机安装开发工具包报错处理
- [渝粤教育] 西南科技大学 程序设计语言VB 在线考试复习资料(1)
- Android中土司(Toast)的使用
- iOS-仿支付宝加载web网页添加进度条
- SLAM会议笔记(四)Lego-LOAM
- 让Apache Shiro保护你的应用[转]
- 访问图像元素(imagedata widthstep)
- 128根号e980计算机怎么打,我能想到最浪漫的事,就是鼓起勇气给了你一张纸条,上面写着:128根号e980...
- HP工作站如何在BIOS下开启、关闭安全芯片
- 'wx' is not defined no-undef
- 关于找不到www.jetbrains.com的服务器IP地址
- 对象实例数据和对象类型数据
- 有故事的书单:June, 2018
- windows服务器系统监控
- 阿里智能物联安全白皮书正式发布
- C++语言涉猎笔记(二)
- 什么是PHP高级工程师
- JVM学习笔记(Ⅰ):Class类文件结构解析(带你读懂Java字节码,这一篇就够了)
- [转] SONY图像传感器列表