How To Set Up a Raspberry Pi as an IoT Device
2019-08-13 | By Maker.io Staff
While IoT devices are often low-powered SoC devices with a microcontroller as the core processor and a Wi-Fi module as the communications interface, they don’t have to be. For instance, a mainstream PC can be used as an IoT device, but doing so would prove to be difficult as PCs require mains power of many hundreds of watts. However, the Raspberry Pi, a computer far more powerful than many IoT devices, is a good candidate for IoT processing!
The Raspberry Pi range of systems is incredibly small, being only slightly larger than a credit card and use very little energy. They have some decent processing capabilities with some Pi computers (such as the 3 B+) having a 64-bit quad core. On top of this, they have up to 1GB of RAM, integrated Wi-Fi, and plenty of GPIO for interfacing with external hardware. But the real icing on top is that they can be programmed wirelessly and in easy-to-use languages like Python, which include a wide range of libraries ranging from face detection to speech-to-text. In this How-To, we will look at how to use a Raspberry Pi as an IoT device for your projects!
BOM
Scheme-It
Interfacing with IoT services
Each IoT service available is different and will use different methods of communication with IoT devices. Some will use REST, some will use MQTT, and others will use HTTP (very similar to REST). Unfortunately, the industry has not agreed to a standard yet, so IoT projects are not easily transferred to different services, but there is a way to help mitigate against difficulties.
When writing IoT code it is best to separate your code into several different blocks:
- Functional Code – This reads sensor data and handles hardware
- Wi-Fi Code – This connects and checks the Wi-Fi connection
- Server Interface Code – This sends data to the IoT server
By splitting your code into functional blocks, you can readily change one block while keeping the rest of the code still functional. For example, if a different IoT service is to be used and uses MQTT instead of HTTP, then only the server interface code block requires editing. So, let’s create a Python program on the Raspberry Pi that will act as an IoT device!
The Python Code
Below is the complete example of a working Python program that can send and retrieve data from our IoT dashboard.
import time import socket # Variables for our IoT Dashboard deviceKey = "KEY_G93JF9COWOLS03" host = "192.168.1.103" # ---------------------------------------------------------------------------------------- # Set variable on our IoT Dashboard def iot_setVariable(varName, varValue): # Create a socket connection for the communication sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = socket.getaddrinfo(host, 80)[0][-1] server_address = (address, 80) print('connecting to {} por {}'.format(*address)) # Connect the socket to the port where the server is listening try: sock.connect(address) # Create the parameters keyMessage = "apikey=" + deviceKey cmdMessage = "command=submit" varMessage = "variable=" + varName datToSend = "data=" + varValue # Combine the parameters to make the final string as well as the length of the packet dataPacket = keyMessage + "&" + cmdMessage + "&" + varMessage + "&" + datToSend dataLength = str(len(dataPacket)) # Send this data to the website POSTDATA = "POST /api.php HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: " + dataLength + "\r\n" + "\r\n" + dataPacket sock.send(POSTDATA.encode()) except Exception as e: print("something's wrong!") finally: sock.close() # ---------------------------------------------------------------------------------------- # Get variable from our IoT Dashboard def iot_getVariable(varName): # Create a socket connection for the communication sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = socket.getaddrinfo(host, 80)[0][-1] server_address = (address, 80) print('connecting to {} por {}'.format(*address)) dataVar = "" # Connect the socket to the port where the server is listening try: sock.connect(address) # Create the parameters keyMessage = "apikey=" + deviceKey cmdMessage = "command=get" varMessage = "variable=" + varName # Combine the parameters to make the final string as well as the length of the packet dataPacket = keyMessage + "&" + cmdMessage + "&" + varMessage dataLength = str(len(dataPacket)) # Send this data to the website POSTDATA = "POST /api.php HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: " + dataLength + "\r\n" + "\r\n" + dataPacket sock.send(POSTDATA.encode()) data = (sock.recv(1024)).decode("ASCII") dataParse = data.split("\r\n\r\n\r\n") dataVar = dataParse[1][0:len(dataParse[1]) - 5] except Exception as e: print("something's wrong!") finally: sock.close() return dataVar # ---------------------------------------------------------------------------------------- # Main program loop while(1): iot_setVariable("GPIO_STATE_0", "OFF") # Send GPIO variable to IoT Dashboard gpio_state = iot_getVariable("GPIO_STATE_1") # Receive GPIO requested state from IoT dashboard time.sleep(2) # Periodic sleeps prevent overloading server
IoT Initialize
The first few lines in our program define a few variables that are used by our IoT send and receive functions. The first variable that we define is the device key, and this is used to authorize our Python program so that it can access the IoT system. The second line is the IP address of the website host, and this is needed so that Python can connect to that IP address using TCP.
# Variables for our IoT Dashboard deviceKey = "KEY_G93JF9COWOLS03" host = "192.168.1.103"
IoT Set Variable
The set variable function requires only two parameters, which are the variable name (such as “temperature”) and the value of that variable (as a string). The function starts by creating a socket object and then the address that the socket will connect to. Then a try/except block attempts to connect to the IoT site, create our POST message, and submit that message to the api.php page for further processing. If this task fails, then an error message is printed in the except section of the try block. Once either of these has executed, the final task is to close the socket connection.
# ---------------------------------------------------------------------------------------- # Set varaible on our IoT Dashboard def iot_setVariable(varName, varValue): # Create a socket connection for the communication sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = socket.getaddrinfo(host, 80)[0][-1] server_address = (address, 80) print('connecting to {} por {}'.format(*address)) # Connect the socket to the port where the server is listening try: sock.connect(address) # Create the parameters keyMessage = "apikey=" + deviceKey cmdMessage = "command=submit" varMessage = "variable=" + varName datToSend = "data=" + varValue # Combine the parameters to make the final string as well as the length of the packet dataPacket = keyMessage + "&" + cmdMessage + "&" + varMessage + "&" + datToSend dataLength = str(len(dataPacket)) # Send this data to the website POSTDATA = "POST /api.php HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: " + dataLength + "\r\n" + "\r\n" + dataPacket sock.send(POSTDATA.encode()) except Exception as e: print("something's wrong!") finally: sock.close()
IoT Get Variable
Getting a variable is somewhat more complex, as we need to read the received data and correctly sanitize it so that it can be used in our Python program. Just like the set variable function, the get variable requires the variable name (but does not require the variable value). The POST message is created and then sent over a socket connection. However, once the POST message has been completed, the function waits for incoming data using the sock.recv() function. This function returns up to 1024 bytes of data, and this data is in the form of a binary array, so the .decode (“ASCII”) function is used to convert it into an ASCII string.
Once converted, the data needs to be parsed to extract the data from the other metadata. The data is separated between the meta data with a unique number of carriage return line feeds (3 x \r\n), so we split this string using this delimiter. However, the spliced data still has some carriage return line feeds at the end, but this is a known number (5 characters to be precise). Therefore, extracting the data from this string is very easy with the use of the [0:len(dataParse[1]) - 5] line, which returns all characters except for the last 5. This string is then returned at the end of the function, and the Python program can then use this returned data (as a string).
# ---------------------------------------------------------------------------------------- # Get variable from our IoT Dashboard def iot_getVariable(varName): # Create a socket connection for the communication sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) address = socket.getaddrinfo(host, 80)[0][-1] server_address = (address, 80) print('connecting to {} por {}'.format(*address)) dataVar = "" # Connect the socket to the port where the server is listening try: sock.connect(address) # Create the parameters keyMessage = "apikey=" + deviceKey cmdMessage = "command=get" varMessage = "variable=" + varName # Combine the parameters to make the final string as well as the length of the packet dataPacket = keyMessage + "&" + cmdMessage + "&" + varMessage dataLength = str(len(dataPacket)) # Send this data to the website POSTDATA = "POST /api.php HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n" + "Content-Length: " + dataLength + "\r\n" + "\r\n" + dataPacket sock.send(POSTDATA.encode()) data = (sock.recv(1024)).decode("ASCII") dataParse = data.split("\r\n\r\n\r\n") dataVar = dataParse[1][0:len(dataParse[1]) - 5] except Exception as e: print("something's wrong!") finally: sock.close() return dataVar
Main Program Loop
The main program loop in this example is simple and merely sets and retrieves a variable value, but it demonstrates the simplicity in using the get and receive functions. It is advised that a timer is used at the end of your Python loop so that the server is not overloaded with requests. This gives time for other devices to send and receive data from the IoT dashboard. In a real IoT example, the GPIO library can be used here to read from pins and set values of pins to read sensors and control devices.
# ---------------------------------------------------------------------------------------- # Main program loop while(1): iot_setVariable("GPIO_STATE_0", "OFF") # Send GPIO variable to IoT Dashboard gpio_state = iot_getVariable("GPIO_STATE_1") # Receive GPIO requested state from IoT dashboard time.sleep(2)
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum