PM2.5 Client Code

# 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("---------------------------------------")