IOT PRACTICAL EXAM - QUICK MEMORY SHEET
=======================================

1) PYTHON PIP INSTALL COMMANDS
------------------------------

A. Q3 - COAP AIR QUALITY + RANDOM FOREST
pip install pandas numpy scikit-learn requests aiocoap streamlit joblib kagglehub
- pandas: handles the Kaggle CSV dataset.
- numpy: numerical operations.
- scikit-learn: Random Forest model and evaluation.
- requests: fetches live air-quality API data.
- aiocoap: CoAP server/client communication.
- streamlit: dashboard.
- joblib: saves and loads the trained model.
- kagglehub: downloads the Kaggle air-quality dataset.

B. Q4 - COAP WEATHER + DECISION TREE
pip install pandas numpy scikit-learn requests aiocoap streamlit joblib
- pandas/numpy: historical weather data handling.
- scikit-learn: Decision Tree model and evaluation.
- requests: fetches historical weather API data.
- aiocoap: CoAP server/client communication.
- streamlit: dashboard.
- joblib: saves and loads the trained model.

C. MQTT PROGRAMS - PYTHON PUBLISHER/SUBSCRIBER, HIVEMQ PUBLIC BROKER,
   AND THINGSBOARD MQTT
pip install paho-mqtt
- paho-mqtt: Python MQTT publisher and subscriber communication.

D. THINGSBOARD HTTP / REST API PROGRAM
pip install requests
- requests: sends sensor data to the ThingsBoard HTTP API.

E. GENERAL NOTE
- Install packages in the same Python environment used to run the programs.
- If pip is not recognised, use:
  python -m pip install PACKAGE_NAME
- To run the Streamlit dashboards:
  python -m streamlit run dashboard.py


2) ESP32 SENSOR WIRING SHORTCUTS
--------------------------------

A. DHT22 TEMPERATURE + HUMIDITY SENSOR
ESP32 3V3  -> DHT22 VCC (+)
ESP32 GPIO 4 -> DHT22 DATA
ESP32 GND  -> DHT22 GND (-)

- Code pin: #define DHTPIN 4
- Use the DHT22 sensor library in Arduino IDE.
- If using a bare 4-pin DHT22 sensor, use a 10k pull-up resistor between
  DATA and VCC. Many 3-pin modules already include it.

B. LDR LIGHT SENSOR MODULE
ESP32 3V3   -> LDR module VCC
ESP32 GPIO 34 -> LDR module AO (Analog Output)
ESP32 GND   -> LDR module GND
- Code pin: #define LDR_PIN 34
- DO (Digital Output) is not used in this program.
- If using a bare LDR rather than a module, it needs a voltage-divider
  resistor circuit; do not connect the bare LDR alone to GPIO 34.

C. PIR MOTION SENSOR (HC-SR501 TYPE)
ESP32 VIN / 5V -> PIR VCC
ESP32 GPIO 27  -> PIR OUT
ESP32 GND      -> PIR GND
- Code pin: #define PIR_PIN 27
- Check the labels on the actual PIR module before connecting.
- HC-SR501 modules commonly accept 5V power; their OUT signal is suitable
  for ESP32 GPIO. Do not feed 5V directly into an ESP32 GPIO pin.

D. ESP32 + DHT22 + MQTT
- Same DHT22 wiring as section A:
  VCC -> 3V3, DATA -> GPIO 4, GND -> GND.
- Wi-Fi credentials are entered in the ESP32 code.
- MQTT broker in the record's example: broker.hivemq.com.


3) ARDUINO IDE - NOT PIP
------------------------

For ESP32 sensor programs:
- Install the ESP32 board package in Arduino IDE (Boards Manager).
- Select the correct ESP32 board and COM port.
- DHT22 programs: install "DHT sensor library" (Adafruit) through
  Arduino IDE Library Manager. Install "Adafruit Unified Sensor" too
  if the IDE reports that dependency is missing.
- ESP32 MQTT publisher program: install "PubSubClient" through
  Arduino IDE Library Manager.
- LDR and PIR programs use built-in ESP32/Arduino functions; no extra
  sensor library is required for the simple code used.


4) PROGRAM-TO-INSTALL-COMMAND QUICK LOOKUP
------------------------------------------

DHT22 with ESP32 (Serial Monitor):
- Arduino IDE + ESP32 board package + DHT sensor library.
- No Python pip package.

LDR with ESP32 (Serial Monitor):
- Arduino IDE + ESP32 board package.
- No Python pip package.

PIR with ESP32 (Serial Monitor):
- Arduino IDE + ESP32 board package.
- No Python pip package.

ESP32 DHT22 MQTT Publisher + Python Subscriber:
- Arduino IDE: ESP32 board package, DHT sensor library,
  Adafruit Unified Sensor (if required), PubSubClient.
- Python subscriber: pip install paho-mqtt

ThingsBoard HTTP / REST API:
- Python: pip install requests

ThingsBoard MQTT:
- Python: pip install paho-mqtt

Generic CoAP Server + Client:
- Python: pip install aiocoap

HiveMQ PUBLIC broker Python Publisher + Subscriber:
- Python: pip install paho-mqtt
- This is the public broker version, not HiveMQ Cloud login/cluster.

Q3 Air Quality CoAP + Random Forest:
- pip install pandas numpy scikit-learn requests aiocoap streamlit joblib kagglehub

Q4 Weather CoAP + Decision Tree:
- pip install pandas numpy scikit-learn requests aiocoap streamlit joblib


5) EXECUTION REMINDERS
----------------------

Q3:
1. python ml_model.py
2. Terminal 1: python coap_server.py
3. Terminal 2 (optional): python coap_client.py
4. Terminal 3: python -m streamlit run dashboard.py

Q4:
1. python ml_model.py
2. Terminal 1: python coap_server.py
3. Terminal 2 (optional): python coap_client.py
4. Terminal 3: python -m streamlit run dashboard.py

- Q3 and Q4 both use CoAP port 5683. Stop one server with Ctrl+C
  before starting the other.
- Start the CoAP server before running the client or dashboard.
- HiveMQ public broker and ThingsBoard MQTT require internet access.
- Open-Meteo API programs require internet access.
- Q3 Kaggle dataset download requires internet access; kagglehub may
  need Kaggle authentication depending on the environment/account.
- Sensor pin numbers above match the programs practised. Check the
  printed labels on the physical sensor/module before powering it.


6) Q3 vs Q4 - WHAT TO CHANGE IN EACH FILE
-----------------------------------------

IMPORTANT:
- Q3 and Q4 are separate folders. Keep each question's four files together.
- The code structure is almost the same, but the API, parameters, model,
  saved model filename, and CoAP resource path are different.
- Change only the values listed below. Leave the remaining code unchanged
  unless an error requires a fix.

A. ml_model.py - MODEL TRAINING FILE

Q3: AIR QUALITY + RANDOM FOREST
1. Dataset download line:
   path = kagglehub.dataset_download("rohanrao/air-quality-data-in-india")
   - Kaggle dataset identifier:
     "YOUR_KAGGLE_USERNAME/YOUR_DATASET_NAME"
   - For our exam program, keep:
     "rohanrao/air-quality-data-in-india"

2. CSV filename line:
   data = pd.read_csv(os.path.join(path, "city_day.csv"))
   - Placeholder: "YOUR_CSV_FILENAME.csv"
   - For Q3, use "city_day.csv".

3. Input feature line:
   features = ["PM2.5", "PM10", "NO2", "SO2", "O3"]
   - These are the five air-quality input columns.

4. Target line:
   target = "AQI_Bucket"
   - This is the column the model learns to predict.

5. Model creation line:
   model = RandomForestClassifier(n_estimators=100, random_state=42)
   - Q3 uses RandomForestClassifier.
   - n_estimators=100 means 100 decision trees in the forest.

6. Saved model line:
   joblib.dump((model, features), "random_forest_model.pkl")
   - Saved model filename: "random_forest_model.pkl"
   - The dashboard must load this exact same filename.


Q4: WEATHER + DECISION TREE
1. Historical API URL line:
   URL = "YOUR_HISTORICAL_WEATHER_API_URL"
   - Use the Open-Meteo Archive API URL supplied in the exam/program.
   - It must request the six weather features plus weather_code.

2. API request line:
   response = requests.get(URL)
   - Normally leave this unchanged; it fetches the historical data.

3. Column-renaming section:
   df = df.rename(columns={
       "temperature_2m": "temperature",
       "relative_humidity_2m": "humidity",
       "wind_speed_10m": "wind_speed"
   })
   - Keep these mappings consistent with the feature names below.

4. Weather-code classification function:
   def classify_weather(code):
       if code in [0, 1]:
           return "Clear"
       elif code in [2, 3]:
           return "Cloudy"
       elif code in [51, 53, 55]:
           return "Drizzle"
       elif code in [61, 63, 65]:
           return "Rain"
       else:
           return None
   - These code groups are the mapping specified in our exam paper.
   - Do not change them unless the question gives a different mapping.

5. Input feature line:
   features = [
       "temperature", "humidity", "precipitation",
       "cloud_cover", "wind_speed", "surface_pressure"
   ]
   - These are the six weather inputs.

6. Target line:
   y = df["weather_class"]
   - The target is created from weather_code using classify_weather().

7. Model creation line:
   model = DecisionTreeClassifier(random_state=42)
   - Q4 uses DecisionTreeClassifier, not RandomForestClassifier.

8. Saved model line:
   joblib.dump((model, features), "decision_tree_model.pkl")
   - Saved model filename: "decision_tree_model.pkl"
   - The dashboard must load this exact same filename.


B. coap_server.py - LIVE API + COAP SERVER

Q3: AIR QUALITY
1. API URL line:
   API_URL = "YOUR_LIVE_AIR_QUALITY_API_URL"
   - Use the air-quality API URL given in Q3.
   - It must request: pm10, pm2_5, nitrogen_dioxide,
     sulphur_dioxide, ozone.

2. CoAP resource registration:
   site.add_resource(["airquality"], AirQualityResource())
   - Resource name: "airquality".
   - Keep this same name in coap_client.py and dashboard.py.

3. Reading conversion:
   "PM2.5": current["pm2_5"]
   "PM10": current["pm10"]
   "NO2": current["nitrogen_dioxide"]
   "SO2": current["sulphur_dioxide"]
   "O3": current["ozone"]
   - These map API field names to the feature names used by the model.

Q4: WEATHER
1. API URL line:
   API_URL = "YOUR_LIVE_WEATHER_API_URL"
   - Use the live forecast API URL given in Q4.
   - It must request: temperature_2m, relative_humidity_2m,
     precipitation, cloud_cover, wind_speed_10m, surface_pressure.

2. CoAP resource registration:
   site.add_resource(["weather"], WeatherResource())
   - Resource name: "weather".
   - Keep this same name in coap_client.py and dashboard.py.

3. Reading conversion:
   "temperature": current["temperature_2m"]
   "humidity": current["relative_humidity_2m"]
   "precipitation": current["precipitation"]
   "cloud_cover": current["cloud_cover"]
   "wind_speed": current["wind_speed_10m"]
   "surface_pressure": current["surface_pressure"]
   - These names must match the Q4 model feature names.


C. coap_client.py - COAP CLIENT

Q3 request line:
   request = Message(code=GET,
       uri="coap://127.0.0.1:5683/airquality")
   - Resource path at the end: /airquality

Q4 request line:
   request = Message(code=GET,
       uri="coap://127.0.0.1:5683/weather")
   - Resource path at the end: /weather

IMPORTANT:
- The client URI path must match the resource name registered by the server.
- Keep 127.0.0.1 and port 5683 for the local practical setup.


D. dashboard.py - STREAMLIT DASHBOARD

Q3: AIR QUALITY
1. CoAP request URI:
   uri="coap://127.0.0.1:5683/airquality"
2. Model loading line:
   model, features = joblib.load("random_forest_model.pkl")
3. Input values:
   data[feature] for feature in features
4. Displayed readings:
   PM2.5, PM10, NO2, SO2, O3
5. Prediction heading:
   "Predicted Air Quality"

Q4: WEATHER
1. CoAP request URI:
   uri="coap://127.0.0.1:5683/weather"
2. Model loading line:
   model, features = joblib.load("decision_tree_model.pkl")
3. Input values:
   data[feature] for feature in features
4. Displayed readings:
   temperature, humidity, precipitation, cloud_cover,
   wind_speed, surface_pressure
5. Prediction heading:
   "Predicted Weather Condition"

IMPORTANT:
- The model filename in dashboard.py must exactly match the filename
  saved by ml_model.py.
- The feature names in the dashboard input DataFrame must match the
  feature names saved with the model.
- The CoAP URI in dashboard.py must match the server resource path.


E. QUICK COMPARISON - REMEMBER THESE DIFFERENCES

File             Q3 - Air Quality             Q4 - Weather
ml_model.py      Random Forest                Decision Tree
Input features   5 air-quality values         6 weather values
Target           AQI_Bucket                   weather_class
Training data    Kaggle city_day.csv          Open-Meteo Archive API
Saved model      random_forest_model.pkl      decision_tree_model.pkl
Server resource  airquality                   weather
Client URI       /airquality                  /weather
Dashboard        Air Quality                  Weather

F. PLACEHOLDERS - WHAT YOU MAY NEED TO FILL IN DURING THE EXAM

- YOUR_KAGGLE_USERNAME/YOUR_DATASET_NAME
  Replace with the Kaggle dataset identifier if the question gives
  a different dataset. For our Q3, use:
  rohanrao/air-quality-data-in-india

- YOUR_CSV_FILENAME.csv
  Replace with the dataset CSV filename. For our Q3, use:
  city_day.csv

- YOUR_HISTORICAL_WEATHER_API_URL
  Replace with the historical/archive API URL given in Q4.

- YOUR_LIVE_AIR_QUALITY_API_URL
  Replace with the live air-quality API URL given in Q3.

- YOUR_LIVE_WEATHER_API_URL
  Replace with the live weather forecast API URL given in Q4.

- /YOUR_RESOURCE_NAME
  If you rename a CoAP resource on the server, use the same path in
  both the client and dashboard. For our programs:
  Q3 = /airquality
  Q4 = /weather

- YOUR_MODEL_FILENAME.pkl
  The model save filename in ml_model.py and load filename in
  dashboard.py must be identical:
  Q3 = random_forest_model.pkl
  Q4 = decision_tree_model.pkl

EXAM TIP:
If the question is exactly Q3 or Q4 from our practised paper, do not
invent new values or rename things. Use the Q3/Q4 values listed above.
Only replace a URL, dataset, feature, target, or resource name if the
exam question explicitly provides a different one.
