# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
# Modified by Johan Michalove, 2021 and SoCy 2021 Cohort!
# Updated by Myrna Kennedy, 2021 cohort for Fortnight 5 Homework
# Task 2 Networked sensor system pt 1: Hardware and software
"""
This code connects the PM2.5 Sensor to the Raspberry Pi, and then
can send data to a server. Our cohort decided the following data should be sent by defining a standard:
1. "uid" (unique student ID)
2. "first_name" (student first name)
3. "student_ip" (student IP address allocated by Roboroo)
4. "date" (data collection date)
5. "particles 03um" (the smallest particle reading)
"""
# pylint: disable=unused-import
import time
import board
import busio
from digitalio import DigitalInOut, Direction, Pull
from adafruit_pm25.i2c import PM25_I2C
from datetime import date
# Server code
import socket
import json
# The server's HOST name or IP address and the PORT number
# After the Raspberry Pi is setup, connect to the hotspot SSID: Tarski network to test the air quality sensor pm25 using the following HOST and PORT number
# HOST = '127.0.0.1' # The local host address for testing
# PORT = 65432 # The port for logging the data
# Make sure these HOST and PORT details are the same with the one on the echo-server for testing
# For the homework, we use the following HOST and PORT
# Connect to the 'Roboroo I'm a robot robot' wifi network
HOST = '192.168.1.15' # The server's host name on Roboroo wifi network
PORT = 65432 # The port used by the server (use this for logging server pm25-client.py)
# To find your personal IP address, type in 'ifconfig' on the Terminal when connected to Roboroo wifi network
# The IP address can be found on the section where it says 'wlan0:' and your IP address is the inet number
# Save and add this personal IP address on the dictionary for send_data later on.
# To see your data on the web server, use the following HOST and PORT number plus your 'uid' on csv format
# Note: 'uid' need to be added on the dictionary that you define for send_data later on
# HOST = '192.168.1.15' # Standard loopback interface address (localhost)
# PORT = 8080 # Port to listen on (non-privileged ports are > 1023) to get our data from server
# Example for me: "http://192.168.1.15:8080/u7252238.csv"
reset_pin = None
# If you have a GPIO, its not a bad idea to connect it to the RESET pin
# reset_pin = DigitalInOut(board.D18)
# reset_pin.direction = Direction.OUTPUT
# reset_pin.value = False
# For use with Raspberry Pi/Linux:
import serial
uart = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=0.25)
# Connect to a PM2.5 sensor over UART
from adafruit_pm25.uart import PM25_UART
pm25 = PM25_UART(uart, reset_pin)
print("Found PM2.5 sensor, reading data...")
# adding date to see when we run the sensor and collecting the data:
today = date.today()
formatted_date = today.strftime("%d/%m/%y") # date is in dd/mm/yy format as per our standard
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
time.sleep(1)
try:
aq_data = pm25.read()
print(aq_data)
except RuntimeError as e:
print("Unable to read from sensor, retrying...")
print(e)
continue
send_data = {
# Make a dictionary for sending data
# YOUR CODE HERE
"uid" : "u7252238", # My student ID
"first_name" : "Myrna", # My first name
"student_ip" : "192.168.1.31",
# My personal IP address that I was allocated to on Roboroo wifi network using 'ifconfig' command on the Terminal
"date" : formatted_date,
# adding date for our send_data to see when we're collecting the air quality data.
"particles 03um" : aq_data["particles 03um"]
# I tried to make the dictionary format for send_data uniform by writing the "particles 03um" code this way
}
# The data logging server expects that you will send the data in the format of key-value pairs,
# including at least one key-value pair that serves as a unique id. To do this,
# where the key is "uid" and the value is the unique ID.
# Another way of writing the dictionary:
# send_data["uid"] = "u7252238"
# send_data["name"] = "Myrna"
# send_data["ip"] = "192.168.1.31"
# but I choose to use the simple dictionary in { } format because I think it looks better and neater.
# I choose to include this code here because this is what I did earlier when Chloe and I testing the server logging.
# Thank you to Matthew (tutor) for helping Chloe and I to work on the dictionary, so then we can help the other cohorts.
# For the purposes of demonstration, below we have just created a single key-value pair to send.
# send_data["particles 03um"] = aq_data["particles 03um"] # Copies relevant aq data into send_data
# Serialize the data as 'json' format, and then incode as a byte string
b_data = json.dumps(send_data).encode('utf-8')
# Send the data to the server
s.sendall(b_data)
data = s.recv(1024)
print('Received', repr(data))
print()
print("Concentration Units (standard)")
print("---------------------------------------")
print(
"PM 1.0: %d\tPM2.5: %d\tPM10: %d"
% (aq_data["pm10 standard"], aq_data["pm25 standard"], aq_data["pm100 standard"])
)
print("Concentration Units (environmental)")
print("---------------------------------------")
print(
"PM 1.0: %d\tPM2.5: %d\tPM10: %d"
% (aq_data["pm10 env"], aq_data["pm25 env"], aq_data["pm100 env"])
)
print("---------------------------------------")
print("Particles > 0.3um / 0.1L air:", aq_data["particles 03um"])
print("Particles > 0.5um / 0.1L air:", aq_data["particles 05um"])
print("Particles > 1.0um / 0.1L air:", aq_data["particles 10um"])
print("Particles > 2.5um / 0.1L air:", aq_data["particles 25um"])
print("Particles > 5.0um / 0.1L air:", aq_data["particles 50um"])
print("Particles > 10 um / 0.1L air:", aq_data["particles 100um"])
print("---------------------------------------")