11
22##
3- # @file mpy_rgb_ramp .py
3+ # @file mpy_tmp117_server_ap .py
44# @brief This MicroPython file contains a full implementation of a web server that reads
55# temperature data from a TMP117 sensor and sends it to a client via a websocket.
66# The complementary client code that is served can be found in the static directory.
1919# @license MIT
2020#
2121
22+ # -------------------- Import the necessary modules --------------------
2223from microdot import Microdot , send_file
2324from microdot .websocket import with_websocket
2425import json
2526import asyncio
2627import wlan_ap
2728import qwiic_tmp117
2829
29- # defines
30+ # -------------------- Constants --------------------
3031kDoAlerts = True # Set to False to disable checking alerts. This will speed up temperature reads.
31- kApSsid = "iot_redboard_tmp117"
32- kApPass = "thermo_wave2"
32+ kApSsid = "iot_redboard_tmp117" # This will be the SSID of the AP, the "Network Name" that you'll see when you scan for networks on your client device
33+ kApPass = "thermo_wave2" # This will be the password for the AP, that you'll use when you connect to the network from your client device
3334
34- # fahrenheit to celcius
35+ # -------------------- Shared Variables --------------------
36+ # Create instance of our TMP117 device
37+ myTMP117 = qwiic_tmp117 .QwiicTMP117 ()
38+
39+ # Use the Microdot framework to create a web server
40+ app = Microdot ()
41+
42+ # -------------------- Fahrenheit to Celcius --------------------
3543def f_to_c (degreesF ):
3644 return (degreesF - 32 ) * 5 / 9
3745
3846def c_to_f (degreesC ):
3947 return (degreesC * 9 / 5 ) + 32
4048
41- # Set up the AP
42- print ("Formatting WIFI" )
43- accessPointIp = wlan_ap .config_wlan_as_ap (kApSsid , kApPass )
44- print ("WiFi Configured!" )
45- # print("Active config: ", config)
46-
47- # Set up the TMP117
48- print ("Setting up TMP117" )
49- # Create instance of device
50- myTMP117 = qwiic_tmp117 .QwiicTMP117 ()
49+ # -------------------- Set up the TMP117 --------------------
50+ def config_TMP117 (tmp117Device , doAlerts ):
51+ """
52+ @brief Function to configure the TMP117 sensor
5153
52- # Check if it's connected
53- if myTMP117 .is_connected () == False :
54- print ("The TMP117 device isn't connected to the system. Please check your connection" )
55- exit ()
54+ @param tmp117Device The QwiicTMP117 object to be configured.
5655
57- print ("TMP117 device connected!" )
58-
59- # Initialize the device
60- myTMP117 .begin ()
56+ @details
57+ - This function initializes the TMP117 sensor and sets the high and low temperature limits.
58+ - If doAlerts is set to True, the TMP117 will be set to alert mode.
59+ """
60+ print ("Setting up TMP117" )
61+ # Create instance of device
62+ tmp117Device = qwiic_tmp117 .QwiicTMP117 ()
6163
62- if kDoAlerts :
63- myTMP117 .set_high_limit (25.50 )
64- myTMP117 .set_low_limit (25 )
64+ # Check if it's connected
65+ if tmp117Device .is_connected () == False :
66+ print ("The TMP117 device isn't connected to the system. Please check your connection" )
67+ exit ()
6568
66- # Set to kAlertMode or kThermMode
67- myTMP117 .set_alert_function_mode (myTMP117 .kAlertMode )
69+ print ("TMP117 device connected!" )
70+
71+ # Initialize the device
72+ tmp117Device .begin ()
6873
69- print ("TMP117 Configured!" )
74+ if doAlerts :
75+ tmp117Device .set_high_limit (25.50 )
76+ tmp117Device .set_low_limit (25 )
7077
71- print ("\n Navigate to http://" + accessPointIp + ":5000/ to view the TMP117 temperature readings\n " )
78+ # Set to kAlertMode or kThermMode
79+ tmp117Device .set_alert_function_mode (tmp117Device .kAlertMode )
7280
73- # Use the Microdot framework to create a web server
74- app = Microdot ()
81+ print ("TMP117 Configured!" )
7582
76- # Route our root page to the index.html file
83+ # -------------------- Asynchronous Microdot Functions --------------------
7784@app .route ('/' )
7885async def index (request ):
86+ """
87+ @brief Function/Route to the index.html file to serve it as the root page
88+
89+ @param request The Microdot "Request" object containing details about a client HTTP request.
90+
91+ @details
92+ - This function is asynchronous and is called when a client requests the root "/" path from our server.
93+ - The requested file is located in the "static" directory.
94+ - The requested file is sent to the client.
95+ """
7996 return send_file ('static/index.html' )
80-
81- gTempSocket = None
8297
8398# Create server-side coroutine for websocket to send temperature data to the client
84- async def send_temperature ():
99+ async def send_temperature (tempSocket ):
100+ """
101+ @brief Server-side coroutine for websocket to send temperature data to the client.
102+
103+ @param tempSocket The Microdot "WebSocket" object containing details about the websocket connection.
104+
105+ @details
106+ - This coroutine is asynchronous and is started when the client connects to the websocket.
107+ - It sends temperature data to the client every 0.5 seconds.
108+ """
85109 print ("Spawned send_temperature coroutine" )
86110 while True :
87111 if myTMP117 .data_ready ():
@@ -99,23 +123,35 @@ async def send_temperature():
99123 data ['limitH' ] = c_to_f (myTMP117 .get_high_limit ())
100124
101125 data = json .dumps (data ) # Convert to a json string to be parsed by client
102- await gTempSocket .send (data )
126+ await tempSocket .send (data )
103127 await asyncio .sleep (0.5 )
104128
105- # Create server-side coroutine for websocket to receive changes to the high and low temperature limits from the client
106- # Since our client code creates a websocket connection to the /temperature route, we'll define our websocket coroutine there
107129@app .route ('/temperature' )
108130@with_websocket
109131async def handle_limits (request , ws ):
132+ """
133+ @brief Server-side coroutine for websocket to receive changes to the high and low temperature limits from the client
134+
135+ Since our client code creates a websocket connection to the /temperature route, we'll define our websocket coroutine there
136+
137+ @param request The Microdot "Request" object containing details about a client HTTP request.
138+ @param ws The Microdot "WebSocket" object containing details about the websocket connection.
139+
140+ @details
141+ - This function is asynchronous and is called when a client requests a file from the server.
142+ - The requested file is located in the "static" directory.
143+ - The requested file is sent to the client.
144+ """
110145 print ("Spawned handle_limits coroutine" )
111- global gTempSocket
112- gTempSocket = ws # Let's save the websocket object so we can send data to it from our send_temperature coroutine
113146 # We won't start sending data until now, when we know the client has connected to the websocket
114- asyncio .create_task (send_temperature ())
147+ # Let's start the send_temperature coroutine and pass it the websocket object
148+ asyncio .create_task (send_temperature (ws ))
115149 while True :
150+ # Lets block here until we receive a message from the client
116151 data = await ws .receive ()
117152 print ("Received new limit: " + data )
118153 limitJson = json .loads (data )
154+ # Check if the client sent a new high or low limit, and update the TMP117 accordingly
119155 if 'low_input' in limitJson :
120156 toSet = f_to_c (limitJson ['low_input' ])
121157 print ("setting low limit to: " + str (toSet ))
@@ -127,18 +163,41 @@ async def handle_limits(request, ws):
127163 myTMP117 .set_high_limit (toSet )
128164 print ("New high limit: " + str (myTMP117 .get_high_limit ()))
129165
130- # Route to the static folder to serve up the HTML and CSS files
131166@app .route ('/static/<path:path>' )
132167async def static (request , path ):
168+ """
169+ @brief Function/Route to the static folder to serve up the HTML and CSS files
170+
171+ @param request The Microdot "Request" object containing details about a client HTTP request.
172+ @param path The path to the requested file.
173+
174+ @details
175+ - This function is asynchronous and is called when a client requests a file from the server.
176+ - The requested file is located in the "static" directory.
177+ - The requested file is sent to the client.
178+ """
133179 if '..' in path :
134180 # directory traversal is not allowed
135181 return 'Not found' , 404
136182 return send_file ('static/' + path )
137183
138184def run ():
139185 """
140- @brief Run the web server
141- """
186+ @brief Configure the WLAN, and TMP117 and run the web server
187+ """
188+ # Set up the AP
189+ print ("Formatting WIFI" )
190+ accessPointIp = wlan_ap .config_wlan_as_ap (kApSsid , kApPass )
191+ print ("WiFi Configured!" )
192+
193+ # Set up the TMP117
194+ config_TMP117 (myTMP117 , kDoAlerts )
195+
196+ # Print the IP address of the server, port 5000 is the default port for Microdot
197+ print ("\n Navigate to http://" + accessPointIp + ":5000/ to view the TMP117 temperature readings\n " )
198+
199+ # Start the web server
142200 app .run ()
143201
202+ # Finally after we've defined all our functions, we'll call the run function to start the server!
144203run ()
0 commit comments