V.06 11/3

Dependencies:   FT6206 SDFileSystem SPI_TFT_ILI9341 TFT_fonts

Fork of ATT_AWS_IoT_demo by attiot

Committer:
jilee
Date:
Fri Nov 03 20:28:02 2017 +0000
Revision:
29:f71a0be59b99
Parent:
25:91d771247ac8
v.06 11/03/2016

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ampembeng 17:46780b2de3e4 1 '''
ampembeng 17:46780b2de3e4 2 /*
ampembeng 17:46780b2de3e4 3 * Copyright 2010-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
ampembeng 17:46780b2de3e4 4 *
ampembeng 17:46780b2de3e4 5 * Licensed under the Apache License, Version 2.0 (the "License").
ampembeng 17:46780b2de3e4 6 * You may not use this file except in compliance with the License.
ampembeng 17:46780b2de3e4 7 * A copy of the License is located at
ampembeng 17:46780b2de3e4 8 *
ampembeng 17:46780b2de3e4 9 * http://aws.amazon.com/apache2.0
ampembeng 17:46780b2de3e4 10 *
ampembeng 17:46780b2de3e4 11 * or in the "license" file accompanying this file. This file is distributed
ampembeng 17:46780b2de3e4 12 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
ampembeng 17:46780b2de3e4 13 * express or implied. See the License for the specific language governing
ampembeng 17:46780b2de3e4 14 * permissions and limitations under the License.
ampembeng 17:46780b2de3e4 15 */
ampembeng 17:46780b2de3e4 16 '''
ampembeng 17:46780b2de3e4 17
ampembeng 17:46780b2de3e4 18 from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTShadowClient
ampembeng 17:46780b2de3e4 19 import sys
ampembeng 17:46780b2de3e4 20 import os.path
ampembeng 17:46780b2de3e4 21 import logging
ampembeng 17:46780b2de3e4 22 import time
ampembeng 17:46780b2de3e4 23 import json
ampembeng 19:488dad1e168e 24 import re
ampembeng 17:46780b2de3e4 25 import getopt
ampembeng 17:46780b2de3e4 26 import Tkinter
ampembeng 17:46780b2de3e4 27 import tkFont
ampembeng 17:46780b2de3e4 28 import time
ampembeng 17:46780b2de3e4 29 from threading import Timer
ampembeng 17:46780b2de3e4 30 from Tkinter import *
ampembeng 25:91d771247ac8 31 from PIL import Image, ImageTk
ampembeng 25:91d771247ac8 32
ampembeng 25:91d771247ac8 33 exePath = os.path.dirname(os.path.realpath(__file__))
ampembeng 25:91d771247ac8 34 assetPath = exePath + "\\assets\\"
ampembeng 17:46780b2de3e4 35
ampembeng 17:46780b2de3e4 36 #######################################################################################################################
ampembeng 17:46780b2de3e4 37 #
ampembeng 17:46780b2de3e4 38 # Set up our Tkinter based GUI
ampembeng 17:46780b2de3e4 39 #
ampembeng 17:46780b2de3e4 40 #######################################################################################################################
ampembeng 17:46780b2de3e4 41 accepted = ["0", "1", "2", "4", "7"]
ampembeng 17:46780b2de3e4 42 colorDict = {0 : 'off', 1 : 'red', 2 : 'green', 4 : "blue", 7 : "white"}
ampembeng 25:91d771247ac8 43 ledImgPaths = {0 : "LEDOff.png", 1 : 'LEDRed.png', 2 : 'LEDGreen.png', 4 : "LEDBlue.png", 7 : "LEDWhite.png"}
ampembeng 17:46780b2de3e4 44
ampembeng 17:46780b2de3e4 45 window = Tkinter.Tk()
ampembeng 25:91d771247ac8 46 window.wm_title("AT&T AWS IoT Starter Kit Demo")
ampembeng 25:91d771247ac8 47 window.iconbitmap(assetPath + "ATT_Icon.ico")
ampembeng 25:91d771247ac8 48 window.resizable(width=False, height=False)
ampembeng 25:91d771247ac8 49
ampembeng 25:91d771247ac8 50 buttonColor = 'dark slate gray'
ampembeng 25:91d771247ac8 51 buttonTxtColor = 'tv white'
ampembeng 25:91d771247ac8 52 headerBgColor = 'snow'
ampembeng 25:91d771247ac8 53 bgColor = 'steel blue'
ampembeng 25:91d771247ac8 54 fgTextColor = 'white'
ampembeng 17:46780b2de3e4 55
ampembeng 20:ee34856ae510 56 # Setup frames
ampembeng 25:91d771247ac8 57 def initFrames(_window, side, color=bgColor):
ampembeng 25:91d771247ac8 58 frame = Frame(_window, background=color)
ampembeng 25:91d771247ac8 59 frame.pack(fill=X, side=side)
ampembeng 25:91d771247ac8 60 return frame
ampembeng 25:91d771247ac8 61
ampembeng 25:91d771247ac8 62 headerframe = initFrames(window, TOP, headerBgColor)
ampembeng 25:91d771247ac8 63 frameR1 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 64 frameR2 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 65 frameR3 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 66 frameR4 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 67 frameR5 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 68 frameR6 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 69 frameR7 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 70 frameR8 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 71 frameR9 = initFrames(window, TOP)
ampembeng 25:91d771247ac8 72 buttonFrame = initFrames(window, BOTTOM)
ampembeng 25:91d771247ac8 73
ampembeng 25:91d771247ac8 74 # So we can loop through our frames
ampembeng 25:91d771247ac8 75 frameIndex = 0
ampembeng 25:91d771247ac8 76 frames = [headerframe,
ampembeng 25:91d771247ac8 77 frameR1, frameR2, frameR3, frameR4, frameR5,
ampembeng 25:91d771247ac8 78 frameR6, frameR7, frameR8, frameR9,
ampembeng 25:91d771247ac8 79 buttonFrame]
ampembeng 25:91d771247ac8 80
ampembeng 25:91d771247ac8 81 def curFrame():
ampembeng 25:91d771247ac8 82 return frames[frameIndex]
ampembeng 25:91d771247ac8 83
ampembeng 25:91d771247ac8 84 def nextFrame():
ampembeng 25:91d771247ac8 85 global frameIndex
ampembeng 25:91d771247ac8 86 frameIndex += 1
ampembeng 25:91d771247ac8 87 return frames[frameIndex]
ampembeng 17:46780b2de3e4 88
ampembeng 20:ee34856ae510 89 # Label vars (controls shown text)
ampembeng 20:ee34856ae510 90 ledStaticLabelTxt = StringVar()
ampembeng 20:ee34856ae510 91 ledStatusLabelTxt = StringVar()
ampembeng 20:ee34856ae510 92 tempStaticLabelTxt = StringVar()
ampembeng 20:ee34856ae510 93 tempStatusLabelTxt = StringVar()
ampembeng 20:ee34856ae510 94 humidStaticLabelTxt = StringVar()
ampembeng 20:ee34856ae510 95 humidStatusLabelTxt = StringVar()
ampembeng 20:ee34856ae510 96 versionStaticLabelTxt = StringVar()
ampembeng 20:ee34856ae510 97 versionStatusLabelTxt = StringVar()
ampembeng 20:ee34856ae510 98 versionLastValue = -1
ampembeng 17:46780b2de3e4 99
ampembeng 17:46780b2de3e4 100 # Control callbacks
ampembeng 20:ee34856ae510 101 def setStatus(ledStatus, tempStatus, humidStatus, version):
ampembeng 20:ee34856ae510 102 global versionLastValue
ampembeng 20:ee34856ae510 103
ampembeng 25:91d771247ac8 104 ledStatusLabelTxt.set(colorDict[ledStatus])
ampembeng 25:91d771247ac8 105 updateLEDImage(ledImgPaths[ledStatus])
ampembeng 20:ee34856ae510 106 tempStatusLabelTxt.set(str(tempStatus) + " (F)")
ampembeng 20:ee34856ae510 107 humidStatusLabelTxt.set(str(humidStatus) + " %")
ampembeng 20:ee34856ae510 108
ampembeng 20:ee34856ae510 109 isStale = ""
ampembeng 20:ee34856ae510 110 if (versionLastValue == version):
ampembeng 25:91d771247ac8 111 isStale = " (stale data)"
ampembeng 17:46780b2de3e4 112 else:
ampembeng 20:ee34856ae510 113 versionLastValue = version
ampembeng 20:ee34856ae510 114 versionStatusLabelTxt.set(str(version) + isStale)
ampembeng 17:46780b2de3e4 115
ampembeng 25:91d771247ac8 116 def updateLEDImage(path):
ampembeng 25:91d771247ac8 117 global ledPicture
ampembeng 25:91d771247ac8 118 img2 = ImageTk.PhotoImage(Image.open(assetPath + path))
ampembeng 25:91d771247ac8 119 ledPicture.configure(image=img2)
ampembeng 25:91d771247ac8 120 ledPicture.image = img2
ampembeng 25:91d771247ac8 121
ampembeng 17:46780b2de3e4 122 def offButtonCallBack():
ampembeng 17:46780b2de3e4 123 sendLEDRequest("0")
ampembeng 17:46780b2de3e4 124
ampembeng 17:46780b2de3e4 125 def redButtonCallBack():
ampembeng 17:46780b2de3e4 126 sendLEDRequest("1")
ampembeng 17:46780b2de3e4 127
ampembeng 17:46780b2de3e4 128 def greenButtonCallBack():
ampembeng 17:46780b2de3e4 129 sendLEDRequest("2")
ampembeng 17:46780b2de3e4 130
ampembeng 17:46780b2de3e4 131 def blueButtonCallBack():
ampembeng 17:46780b2de3e4 132 sendLEDRequest("4")
ampembeng 17:46780b2de3e4 133
ampembeng 17:46780b2de3e4 134 def whiteButtonCallBack():
ampembeng 17:46780b2de3e4 135 sendLEDRequest("7")
ampembeng 17:46780b2de3e4 136
ampembeng 25:91d771247ac8 137 # Photos
ampembeng 25:91d771247ac8 138 def initPhotoLabels(frame, photoName, color=bgColor, side=LEFT, pad=0):
ampembeng 25:91d771247ac8 139 image = Image.open(assetPath + photoName)
ampembeng 25:91d771247ac8 140 photo = ImageTk.PhotoImage(image)
ampembeng 25:91d771247ac8 141
ampembeng 25:91d771247ac8 142 label = Label(frame, image=photo, background=color)
ampembeng 25:91d771247ac8 143 label.image = photo # keep a reference!
ampembeng 25:91d771247ac8 144 label.pack(side=side, padx=pad)
ampembeng 25:91d771247ac8 145 return label
ampembeng 25:91d771247ac8 146
ampembeng 17:46780b2de3e4 147 # Create our Labels
ampembeng 25:91d771247ac8 148 headerLabel1 = initPhotoLabels(curFrame(), "attLogo.png", headerBgColor)
ampembeng 25:91d771247ac8 149 headerLabel2 = initPhotoLabels(curFrame(), "awsLogo.png", headerBgColor, pad=10)
ampembeng 25:91d771247ac8 150
ampembeng 25:91d771247ac8 151 starterKitBoxLabel = initPhotoLabels(nextFrame(), "starterKitBox.png")
ampembeng 25:91d771247ac8 152
ampembeng 25:91d771247ac8 153 labelFont = tkFont.Font(family='Times', size=14, weight='bold')
ampembeng 25:91d771247ac8 154 def initLargeTextLabels(frame, text):
ampembeng 25:91d771247ac8 155 label = Label(frame, font=labelFont, text=text, anchor=W, relief=FLAT, fg=fgTextColor, background=bgColor)
ampembeng 25:91d771247ac8 156 label.pack(side=LEFT)
ampembeng 25:91d771247ac8 157
ampembeng 25:91d771247ac8 158 setLEDColorLabel = initLargeTextLabels(nextFrame(),"Reported Values")
ampembeng 20:ee34856ae510 159
ampembeng 25:91d771247ac8 160 def initLabels(frame, lableVar, text):
ampembeng 25:91d771247ac8 161 lableVar.set(text)
ampembeng 25:91d771247ac8 162 label = Label(frame, textvariable=lableVar, anchor=W, relief=FLAT, fg=fgTextColor, background=bgColor)
ampembeng 25:91d771247ac8 163 label.pack(side = LEFT)
ampembeng 25:91d771247ac8 164 return label
ampembeng 25:91d771247ac8 165
ampembeng 25:91d771247ac8 166 ledStaticLabel = initLabels(nextFrame(), ledStaticLabelTxt, "LED Color: ")
ampembeng 25:91d771247ac8 167 ledStatusLabel = initLabels(curFrame(), ledStatusLabelTxt, "unknown (needs to sync)")
ampembeng 25:91d771247ac8 168
ampembeng 25:91d771247ac8 169 tempStaticLabel = initLabels(nextFrame(), tempStaticLabelTxt, "Temperature: ")
ampembeng 25:91d771247ac8 170 tempStatusLabel = initLabels(curFrame(), tempStatusLabelTxt, "unknown (needs to sync)")
ampembeng 17:46780b2de3e4 171
ampembeng 25:91d771247ac8 172 humidStaticLabel = initLabels(nextFrame(), humidStaticLabelTxt, "Humidity: ")
ampembeng 25:91d771247ac8 173 humidStatusLabel = initLabels(curFrame(), humidStatusLabelTxt, "unknown (needs to sync)")
ampembeng 25:91d771247ac8 174
ampembeng 25:91d771247ac8 175 versionStaticLabel = initLabels(nextFrame(), versionStaticLabelTxt, "Shadow Version: ")
ampembeng 25:91d771247ac8 176 versionStatusLabel = initLabels(curFrame(), versionStatusLabelTxt, "unknown (needs to sync)")
ampembeng 20:ee34856ae510 177
ampembeng 25:91d771247ac8 178 lineLabel = initLargeTextLabels(nextFrame(), "_______________________________________")
ampembeng 25:91d771247ac8 179 setLEDColorLabel = initLargeTextLabels(nextFrame(),"Set LED Color")
ampembeng 25:91d771247ac8 180
ampembeng 25:91d771247ac8 181 starterKitBoardLabel = initPhotoLabels(nextFrame(), "startKitBoard.png", side=TOP)
ampembeng 25:91d771247ac8 182
ampembeng 25:91d771247ac8 183 # Creates an LED label (image) that we can update.
ampembeng 25:91d771247ac8 184 ledPicture = Label(starterKitBoardLabel, background=bgColor, relief=FLAT, width=10, height=12)
ampembeng 25:91d771247ac8 185 ledPicture.place(relx=1.0, rely=1.0, x=(40-300), y=(85-245), anchor="se")
ampembeng 25:91d771247ac8 186 updateLEDImage("LEDOff.png")
ampembeng 17:46780b2de3e4 187
ampembeng 17:46780b2de3e4 188 # Create our Buttons
ampembeng 25:91d771247ac8 189 def buttonInit(text, bg, command):
ampembeng 25:91d771247ac8 190 return Tkinter.Button(buttonFrame, text =text, fg="snow", bg=bg, height=1, width=6, command=command)
ampembeng 25:91d771247ac8 191
ampembeng 25:91d771247ac8 192 O = buttonInit("OFF", buttonColor, offButtonCallBack)
ampembeng 25:91d771247ac8 193 R = buttonInit("RED", buttonColor, redButtonCallBack)
ampembeng 25:91d771247ac8 194 G = buttonInit("GREEN", buttonColor, greenButtonCallBack)
ampembeng 25:91d771247ac8 195 B = buttonInit("BLUE", buttonColor, blueButtonCallBack)
ampembeng 25:91d771247ac8 196 W = buttonInit("WHITE", buttonColor, whiteButtonCallBack)
ampembeng 25:91d771247ac8 197 ledButtons = [O, R, G, B, W]
ampembeng 17:46780b2de3e4 198
ampembeng 17:46780b2de3e4 199 # Set font
ampembeng 25:91d771247ac8 200 buttonFont = tkFont.Font(family='Arial', size=12, weight='bold')
ampembeng 25:91d771247ac8 201 for button in ledButtons:
ampembeng 25:91d771247ac8 202 button['font'] = buttonFont
ampembeng 17:46780b2de3e4 203
ampembeng 25:91d771247ac8 204 buttonPadX = 5
ampembeng 25:91d771247ac8 205 for button in ledButtons:
ampembeng 25:91d771247ac8 206 button.pack(side=LEFT, padx=buttonPadX)
ampembeng 25:91d771247ac8 207
ampembeng 25:91d771247ac8 208 # NOTE: If you want to test the GUI layout without running the AWS code comment these lines in
ampembeng 25:91d771247ac8 209 #window.mainloop()
ampembeng 25:91d771247ac8 210 #exit(0)
ampembeng 17:46780b2de3e4 211
ampembeng 17:46780b2de3e4 212 #######################################################################################################################
ampembeng 17:46780b2de3e4 213 #
ampembeng 17:46780b2de3e4 214 # These functions are for AWS
ampembeng 17:46780b2de3e4 215 #
ampembeng 17:46780b2de3e4 216 #######################################################################################################################
ampembeng 17:46780b2de3e4 217 # Shadow JSON schema:
ampembeng 20:ee34856ae510 218 '''
ampembeng 20:ee34856ae510 219 Name: AIT (AWS IoT Thing)
ampembeng 20:ee34856ae510 220 {
ampembeng 20:ee34856ae510 221 "state": {
ampembeng 20:ee34856ae510 222 "desired": {
ampembeng 20:ee34856ae510 223 "ledColor": <UINT8>
ampembeng 20:ee34856ae510 224 },
ampembeng 20:ee34856ae510 225 "reported": {
ampembeng 20:ee34856ae510 226 "ledColor": <UINT8>,
ampembeng 20:ee34856ae510 227 "temperature": <FLOAT>,
ampembeng 20:ee34856ae510 228 "humidity": <INT16>
ampembeng 20:ee34856ae510 229 }
ampembeng 20:ee34856ae510 230 }
ampembeng 20:ee34856ae510 231 }
ampembeng 20:ee34856ae510 232 '''
ampembeng 17:46780b2de3e4 233
ampembeng 17:46780b2de3e4 234 def sendLEDRequest(color_input):
ampembeng 17:46780b2de3e4 235 if (color_input in accepted):
ampembeng 17:46780b2de3e4 236 JSONPayload = '{"state":{"desired":{"ledColor":' + str(color_input) + '}}}'
ampembeng 20:ee34856ae510 237 AIT.shadowUpdate(JSONPayload, customShadowCallback_Update, 5)
ampembeng 17:46780b2de3e4 238 else:
ampembeng 17:46780b2de3e4 239 print("WARN: Color input invalid - " + color_input)
ampembeng 17:46780b2de3e4 240
ampembeng 17:46780b2de3e4 241 # Custom Shadow callback
ampembeng 17:46780b2de3e4 242 def customShadowCallback_Delta(payload, responseStatus, token):
ampembeng 17:46780b2de3e4 243 # payload is a JSON string ready to be parsed using json.loads(...)
ampembeng 17:46780b2de3e4 244 # in both Py2.x and Py3.x
ampembeng 17:46780b2de3e4 245 print(responseStatus)
ampembeng 17:46780b2de3e4 246 payloadDict = json.loads(payload)
ampembeng 17:46780b2de3e4 247 print("++++++++DELTA++++++++++")
ampembeng 17:46780b2de3e4 248 print("ledColor: " + str(payloadDict["state"]["ledColor"]))
ampembeng 17:46780b2de3e4 249 print("version: " + str(payloadDict["version"]))
ampembeng 17:46780b2de3e4 250 print("+++++++++++++++++++++++\n\n")
ampembeng 17:46780b2de3e4 251
ampembeng 17:46780b2de3e4 252 # Custom Shadow callback
ampembeng 17:46780b2de3e4 253 def customShadowCallback_Update(payload, responseStatus, token):
ampembeng 17:46780b2de3e4 254 # payload is a JSON string ready to be parsed using json.loads(...)
ampembeng 17:46780b2de3e4 255 # in both Py2.x and Py3.x
ampembeng 17:46780b2de3e4 256 if responseStatus == "timeout":
ampembeng 17:46780b2de3e4 257 print("Update request " + token + " time out!")
ampembeng 17:46780b2de3e4 258 if responseStatus == "accepted":
ampembeng 17:46780b2de3e4 259 payloadDict = json.loads(payload)
ampembeng 17:46780b2de3e4 260 print("~~~~~~~~~~~~~~~~~~~~~~~")
ampembeng 17:46780b2de3e4 261 print("Update request with token: " + token + " accepted!")
ampembeng 17:46780b2de3e4 262 print("ledColor: " + str(payloadDict["state"]["desired"]["ledColor"]))
ampembeng 17:46780b2de3e4 263 print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")
ampembeng 17:46780b2de3e4 264 if responseStatus == "rejected":
ampembeng 17:46780b2de3e4 265 print("Update request " + token + " rejected!")
ampembeng 17:46780b2de3e4 266
ampembeng 17:46780b2de3e4 267 def customShadowCallback_Delete(payload, responseStatus, token):
ampembeng 17:46780b2de3e4 268 if responseStatus == "timeout":
ampembeng 17:46780b2de3e4 269 print("Delete request " + token + " time out!")
ampembeng 17:46780b2de3e4 270 if responseStatus == "accepted":
ampembeng 17:46780b2de3e4 271 print("~~~~~~~~~~~~~~~~~~~~~~~")
ampembeng 17:46780b2de3e4 272 print("Delete request with token: " + token + " accepted!")
ampembeng 17:46780b2de3e4 273 print("~~~~~~~~~~~~~~~~~~~~~~~\n\n")
ampembeng 17:46780b2de3e4 274 if responseStatus == "rejected":
ampembeng 17:46780b2de3e4 275 print("Delete request " + token + " rejected!")
ampembeng 17:46780b2de3e4 276
ampembeng 17:46780b2de3e4 277 # Custom Shadow callback
ampembeng 17:46780b2de3e4 278 def customShadowCallback_Get(payload, responseStatus, token):
ampembeng 17:46780b2de3e4 279 print(responseStatus)
ampembeng 17:46780b2de3e4 280 payloadDict = json.loads(payload)
ampembeng 17:46780b2de3e4 281 reportedColor = payloadDict["state"]["reported"]["ledColor"]
ampembeng 20:ee34856ae510 282 reportedTemp = payloadDict["state"]["reported"]["temperature"]
ampembeng 20:ee34856ae510 283 reportedHumid = payloadDict["state"]["reported"]["humidity"]
ampembeng 20:ee34856ae510 284 reportedVersion = payloadDict["version"]
ampembeng 17:46780b2de3e4 285 print("++++++++GET++++++++++")
ampembeng 20:ee34856ae510 286 print("ledColor : " + str(reportedColor) + " (" + colorDict[reportedColor] + ")")
ampembeng 20:ee34856ae510 287 print("temperature: " + str(reportedTemp))
ampembeng 20:ee34856ae510 288 print("humidity : " + str(reportedHumid))
ampembeng 20:ee34856ae510 289 print("version: " + str(reportedVersion))
ampembeng 17:46780b2de3e4 290 print("+++++++++++++++++++++\n\n")
ampembeng 17:46780b2de3e4 291
ampembeng 17:46780b2de3e4 292 # Send payload to our status
ampembeng 25:91d771247ac8 293 setStatus(reportedColor, reportedTemp, reportedHumid, reportedVersion)
ampembeng 17:46780b2de3e4 294
ampembeng 17:46780b2de3e4 295 getTimerAlive = TRUE
ampembeng 17:46780b2de3e4 296 def customShadowTimer_Get():
ampembeng 17:46780b2de3e4 297 while (getTimerAlive):
ampembeng 20:ee34856ae510 298 AIT.shadowGet(customShadowCallback_Get, 5)
ampembeng 17:46780b2de3e4 299 time.sleep(3)
ampembeng 17:46780b2de3e4 300
ampembeng 17:46780b2de3e4 301 #######################################################################################################################
ampembeng 17:46780b2de3e4 302 #
ampembeng 17:46780b2de3e4 303 # Vars
ampembeng 17:46780b2de3e4 304 #
ampembeng 17:46780b2de3e4 305 #######################################################################################################################
ampembeng 17:46780b2de3e4 306 # Usage
ampembeng 17:46780b2de3e4 307 usageInfo = """Usage:
ampembeng 17:46780b2de3e4 308
ampembeng 17:46780b2de3e4 309 Use certificate based mutual authentication:
ampembeng 17:46780b2de3e4 310 python basicShadowDeltaListener.py -e <endpoint> -r <rootCAFilePath> -c <certFilePath> -k <privateKeyFilePath>
ampembeng 17:46780b2de3e4 311
ampembeng 17:46780b2de3e4 312 Use MQTT over WebSocket:
ampembeng 17:46780b2de3e4 313 python basicShadowDeltaListener.py -e <endpoint> -r <rootCAFilePath> -w
ampembeng 17:46780b2de3e4 314
ampembeng 17:46780b2de3e4 315 Type "python basicShadowDeltaListener.py -h" for available options.
ampembeng 17:46780b2de3e4 316
ampembeng 17:46780b2de3e4 317
ampembeng 17:46780b2de3e4 318 """
ampembeng 17:46780b2de3e4 319 # Help info
ampembeng 17:46780b2de3e4 320 helpInfo = """-e, --endpoint
ampembeng 17:46780b2de3e4 321 Your AWS IoT custom endpoint
ampembeng 17:46780b2de3e4 322 -r, --rootCA
ampembeng 17:46780b2de3e4 323 Root CA file path
ampembeng 17:46780b2de3e4 324 -c, --cert
ampembeng 17:46780b2de3e4 325 Certificate file path
ampembeng 17:46780b2de3e4 326 -k, --key
ampembeng 17:46780b2de3e4 327 Private key file path
ampembeng 17:46780b2de3e4 328 -w, --websocket
ampembeng 17:46780b2de3e4 329 Use MQTT over WebSocket
ampembeng 17:46780b2de3e4 330 -h, --help
ampembeng 17:46780b2de3e4 331 Help information
ampembeng 17:46780b2de3e4 332
ampembeng 17:46780b2de3e4 333
ampembeng 17:46780b2de3e4 334 """
ampembeng 17:46780b2de3e4 335
ampembeng 17:46780b2de3e4 336 #######################################################################################################################
ampembeng 17:46780b2de3e4 337 #
ampembeng 17:46780b2de3e4 338 # AWS IoT Config Parameters. The user needs to enter these (they should match the parameters in aws_iot_config.h)
ampembeng 17:46780b2de3e4 339 #
ampembeng 17:46780b2de3e4 340 #######################################################################################################################
ampembeng 19:488dad1e168e 341 useWebsocket = False # The FRDM-K64F demo isn't designed to work with web socket
ampembeng 19:488dad1e168e 342 hardCodeMQTT = False # Set this to true if you want to hard code the MQTT params below
ampembeng 19:488dad1e168e 343
ampembeng 19:488dad1e168e 344 # AWS parameters
ampembeng 19:488dad1e168e 345 AWS_IOT_MQTT_HOST = "TODO"
ampembeng 17:46780b2de3e4 346 AWS_IOT_MQTT_PORT = 8883
ampembeng 19:488dad1e168e 347 AWS_IOT_MQTT_CLIENT_ID = "TODO"
ampembeng 19:488dad1e168e 348 AWS_IOT_MY_THING_NAME = "TODO"
ampembeng 19:488dad1e168e 349 AWS_MQTT_CONFIG_FILENAME = "C:/Temp/certs/mqtt_config.txt"
ampembeng 17:46780b2de3e4 350 AWS_IOT_ROOT_CA_FILENAME = "C:/Temp/certs/rootCA-certificate.crt"
ampembeng 17:46780b2de3e4 351 AWS_IOT_PRIVATE_KEY_FILENAME = "C:/Temp/certs/private.pem.key"
ampembeng 17:46780b2de3e4 352 AWS_IOT_CERTIFICATE_FILENAME = "C:/Temp/certs/certificate.pem.crt"
ampembeng 17:46780b2de3e4 353
ampembeng 17:46780b2de3e4 354 #######################################################################################################################
ampembeng 17:46780b2de3e4 355 #
ampembeng 19:488dad1e168e 356 # Arg Parser (TODO)
ampembeng 17:46780b2de3e4 357 #
ampembeng 17:46780b2de3e4 358 #######################################################################################################################
ampembeng 17:46780b2de3e4 359 '''
ampembeng 17:46780b2de3e4 360 try:
ampembeng 17:46780b2de3e4 361 opts, args = getopt.getopt(sys.argv[1:], "hwe:k:c:r:", ["help", "endpoint=", "key=","cert=","rootCA=", "websocket"])
ampembeng 17:46780b2de3e4 362 if len(opts) == 0:
ampembeng 17:46780b2de3e4 363 raise getopt.GetoptError("No input parameters!")
ampembeng 17:46780b2de3e4 364 for opt, arg in opts:
ampembeng 17:46780b2de3e4 365 if opt in ("-h", "--help"):
ampembeng 17:46780b2de3e4 366 print(helpInfo)
ampembeng 17:46780b2de3e4 367 exit(0)
ampembeng 17:46780b2de3e4 368 if opt in ("-e", "--endpoint"):
ampembeng 17:46780b2de3e4 369 AWS_IOT_MQTT_HOST = arg
ampembeng 17:46780b2de3e4 370 if opt in ("-r", "--rootCA"):
ampembeng 17:46780b2de3e4 371 AWS_IOT_ROOT_CA_FILENAME = arg
ampembeng 17:46780b2de3e4 372 if opt in ("-c", "--cert"):
ampembeng 17:46780b2de3e4 373 AWS_IOT_CERTIFICATE_FILENAME = arg
ampembeng 17:46780b2de3e4 374 if opt in ("-k", "--key"):
ampembeng 17:46780b2de3e4 375 AWS_IOT_PRIVATE_KEY_FILENAME = arg
ampembeng 17:46780b2de3e4 376 if opt in ("-w", "--websocket"):
ampembeng 17:46780b2de3e4 377 useWebsocket = True
ampembeng 17:46780b2de3e4 378 except getopt.GetoptError:
ampembeng 17:46780b2de3e4 379 print(usageInfo)
ampembeng 17:46780b2de3e4 380 #exit(1)
ampembeng 17:46780b2de3e4 381
ampembeng 17:46780b2de3e4 382 # Missing configuration notification
ampembeng 17:46780b2de3e4 383 missingConfiguration = False
ampembeng 17:46780b2de3e4 384 if not AWS_IOT_MQTT_HOST:
ampembeng 17:46780b2de3e4 385 print("Missing '-e' or '--endpoint'")
ampembeng 17:46780b2de3e4 386 missingConfiguration = True
ampembeng 17:46780b2de3e4 387 if not AWS_IOT_ROOT_CA_FILENAME:
ampembeng 17:46780b2de3e4 388 print("Missing '-r' or '--rootCA'")
ampembeng 17:46780b2de3e4 389 missingConfiguration = True
ampembeng 17:46780b2de3e4 390 if not useWebsocket:
ampembeng 17:46780b2de3e4 391 if not AWS_IOT_CERTIFICATE_FILENAME:
ampembeng 17:46780b2de3e4 392 print("Missing '-c' or '--cert'")
ampembeng 17:46780b2de3e4 393 missingConfiguration = True
ampembeng 17:46780b2de3e4 394 if not AWS_IOT_PRIVATE_KEY_FILENAME:
ampembeng 17:46780b2de3e4 395 print("Missing '-k' or '--key'")
ampembeng 17:46780b2de3e4 396 missingConfiguration = True
ampembeng 17:46780b2de3e4 397 if missingConfiguration:
ampembeng 17:46780b2de3e4 398 exit(2)
ampembeng 17:46780b2de3e4 399 '''
ampembeng 17:46780b2de3e4 400
ampembeng 17:46780b2de3e4 401 # Configure logging
ampembeng 17:46780b2de3e4 402 logger = logging.getLogger("AWSIoTPythonSDK.core")
ampembeng 17:46780b2de3e4 403 logger.setLevel(logging.DEBUG)
ampembeng 17:46780b2de3e4 404 streamHandler = logging.StreamHandler()
ampembeng 17:46780b2de3e4 405 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ampembeng 17:46780b2de3e4 406 streamHandler.setFormatter(formatter)
ampembeng 17:46780b2de3e4 407 logger.addHandler(streamHandler)
ampembeng 17:46780b2de3e4 408
ampembeng 17:46780b2de3e4 409 #######################################################################################################################
ampembeng 17:46780b2de3e4 410 #
ampembeng 17:46780b2de3e4 411 # Main Code
ampembeng 17:46780b2de3e4 412 #
ampembeng 17:46780b2de3e4 413 #######################################################################################################################
ampembeng 19:488dad1e168e 414 # This block parses the MQTT file.
ampembeng 19:488dad1e168e 415 ''' Example format for mqtt_config.txt:
ampembeng 19:488dad1e168e 416 AWS_IOT_MQTT_HOST=1234asdf.iot.us-west-2.amazonaws.com
ampembeng 19:488dad1e168e 417 AWS_IOT_MQTT_PORT=8883
ampembeng 19:488dad1e168e 418 AWS_IOT_MQTT_CLIENT_ID=MyThingName
ampembeng 19:488dad1e168e 419 WS_IOT_MY_THING_NAME=MyThingName
ampembeng 19:488dad1e168e 420 '''
ampembeng 19:488dad1e168e 421
ampembeng 19:488dad1e168e 422 if (not hardCodeMQTT):
ampembeng 19:488dad1e168e 423 if not os.path.exists(AWS_MQTT_CONFIG_FILENAME):
ampembeng 19:488dad1e168e 424 print "ERROR: MQTT Config file not found, " + AWS_MQTT_CONFIG_FILENAME
ampembeng 19:488dad1e168e 425 exit(1)
ampembeng 19:488dad1e168e 426
ampembeng 19:488dad1e168e 427 mqtt_file = open(AWS_MQTT_CONFIG_FILENAME)
ampembeng 19:488dad1e168e 428 mqtt_tokens = re.split('=|\n', mqtt_file.read())
ampembeng 19:488dad1e168e 429 print mqtt_tokens
ampembeng 19:488dad1e168e 430
ampembeng 19:488dad1e168e 431 if (len(mqtt_tokens) != 8):
ampembeng 19:488dad1e168e 432 print "ERROR: Detected incorrect MQTT file format"
ampembeng 19:488dad1e168e 433 exit(1)
ampembeng 19:488dad1e168e 434
ampembeng 19:488dad1e168e 435 index = 0
ampembeng 19:488dad1e168e 436 for token in mqtt_tokens:
ampembeng 19:488dad1e168e 437 if (token == "AWS_IOT_MQTT_HOST"):
ampembeng 19:488dad1e168e 438 AWS_IOT_MQTT_HOST = mqtt_tokens[index+1]
ampembeng 19:488dad1e168e 439 if (token == "AWS_IOT_MQTT_PORT"):
ampembeng 19:488dad1e168e 440 AWS_IOT_MQTT_PORT = int(mqtt_tokens[index + 1])
ampembeng 19:488dad1e168e 441 if (token == "AWS_IOT_MQTT_CLIENT_ID"):
ampembeng 19:488dad1e168e 442 AWS_IOT_MQTT_CLIENT_ID = mqtt_tokens[index + 1]
ampembeng 19:488dad1e168e 443 if (token == "AWS_IOT_MY_THING_NAME"):
ampembeng 19:488dad1e168e 444 AWS_IOT_MY_THING_NAME = mqtt_tokens[index+1]
ampembeng 19:488dad1e168e 445
ampembeng 19:488dad1e168e 446 index += 1
ampembeng 19:488dad1e168e 447
ampembeng 19:488dad1e168e 448 print "MQTT Params:"
ampembeng 19:488dad1e168e 449 print "AWS_IOT_MQTT_HOST = " + AWS_IOT_MQTT_HOST
ampembeng 19:488dad1e168e 450 print "AWS_IOT_MQTT_PORT = " + str(AWS_IOT_MQTT_PORT)
ampembeng 19:488dad1e168e 451 print "AWS_IOT_MQTT_CLIENT_ID = " + AWS_IOT_MQTT_CLIENT_ID
ampembeng 19:488dad1e168e 452 print "AWS_IOT_MY_THING_NAME = " + AWS_IOT_MY_THING_NAME
ampembeng 19:488dad1e168e 453
ampembeng 19:488dad1e168e 454 # Makes sure cert/key files exist
ampembeng 17:46780b2de3e4 455 if not os.path.exists(AWS_IOT_ROOT_CA_FILENAME):
ampembeng 17:46780b2de3e4 456 print "ERROR: Root CA file not found, " + AWS_IOT_ROOT_CA_FILENAME
ampembeng 17:46780b2de3e4 457 exit(1)
ampembeng 17:46780b2de3e4 458 if not os.path.exists(AWS_IOT_PRIVATE_KEY_FILENAME):
ampembeng 17:46780b2de3e4 459 print "ERROR: Private Key file not found, " + AWS_IOT_PRIVATE_KEY_FILENAME
ampembeng 17:46780b2de3e4 460 exit(1)
ampembeng 17:46780b2de3e4 461 if not os.path.exists(AWS_IOT_CERTIFICATE_FILENAME):
ampembeng 17:46780b2de3e4 462 print "ERROR: AWS IOT cert file not found, " + AWS_IOT_CERTIFICATE_FILENAME
ampembeng 17:46780b2de3e4 463 exit(1)
ampembeng 17:46780b2de3e4 464
ampembeng 17:46780b2de3e4 465 # Init AWSIoTMQTTShadowClient
ampembeng 17:46780b2de3e4 466 myAWSIoTMQTTShadowClient = None
ampembeng 17:46780b2de3e4 467 if useWebsocket:
ampembeng 17:46780b2de3e4 468 myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("basicShadowDeltaListener", useWebsocket=True)
ampembeng 17:46780b2de3e4 469 myAWSIoTMQTTShadowClient.configureEndpoint(AWS_IOT_MQTT_HOST, 443)
ampembeng 17:46780b2de3e4 470 myAWSIoTMQTTShadowClient.configureCredentials(AWS_IOT_ROOT_CA_FILENAME)
ampembeng 17:46780b2de3e4 471 else:
ampembeng 17:46780b2de3e4 472 myAWSIoTMQTTShadowClient = AWSIoTMQTTShadowClient("basicShadowDeltaListener")
ampembeng 17:46780b2de3e4 473 myAWSIoTMQTTShadowClient.configureEndpoint(AWS_IOT_MQTT_HOST, AWS_IOT_MQTT_PORT)
ampembeng 17:46780b2de3e4 474 myAWSIoTMQTTShadowClient.configureCredentials(AWS_IOT_ROOT_CA_FILENAME, AWS_IOT_PRIVATE_KEY_FILENAME, AWS_IOT_CERTIFICATE_FILENAME)
ampembeng 17:46780b2de3e4 475
ampembeng 17:46780b2de3e4 476 # AWSIoTMQTTShadowClient configuration
ampembeng 17:46780b2de3e4 477 myAWSIoTMQTTShadowClient.configureAutoReconnectBackoffTime(1, 32, 20)
ampembeng 17:46780b2de3e4 478 myAWSIoTMQTTShadowClient.configureConnectDisconnectTimeout(10) # 10 sec
ampembeng 17:46780b2de3e4 479 myAWSIoTMQTTShadowClient.configureMQTTOperationTimeout(5) # 5 sec
ampembeng 17:46780b2de3e4 480
ampembeng 17:46780b2de3e4 481 # Connect to AWS IoT
ampembeng 17:46780b2de3e4 482 myAWSIoTMQTTShadowClient.connect()
ampembeng 17:46780b2de3e4 483
ampembeng 17:46780b2de3e4 484 # Create a deviceShadow with persistent subscription
ampembeng 20:ee34856ae510 485 AIT = myAWSIoTMQTTShadowClient.createShadowHandlerWithName(AWS_IOT_MY_THING_NAME, True)
ampembeng 17:46780b2de3e4 486
ampembeng 17:46780b2de3e4 487 # Listen on deltas
ampembeng 20:ee34856ae510 488 AIT.shadowRegisterDeltaCallback(customShadowCallback_Delta)
ampembeng 17:46780b2de3e4 489
ampembeng 17:46780b2de3e4 490 # Delete shadow JSON doc
ampembeng 20:ee34856ae510 491 #AIT.shadowDelete(customShadowCallback_Delete, 5)
ampembeng 17:46780b2de3e4 492
ampembeng 25:91d771247ac8 493 # NOTE: We make this slightly slower than the target loop (to prevent 'stale data')
ampembeng 25:91d771247ac8 494 getTimer = Timer(3.5, customShadowTimer_Get, ())
ampembeng 17:46780b2de3e4 495 getTimer.start()
ampembeng 17:46780b2de3e4 496
ampembeng 17:46780b2de3e4 497 # GUI loop (loops until closed)
ampembeng 17:46780b2de3e4 498 window.mainloop()
ampembeng 17:46780b2de3e4 499
ampembeng 17:46780b2de3e4 500 # Kill our timer after the GUI closes
ampembeng 17:46780b2de3e4 501 getTimerAlive = FALSE
ampembeng 19:488dad1e168e 502 getTimer.cancel()