·16 min read·BASHCAT 技術團隊·iot

Complete Student Project Development Guide: From Concept to Finished Product

Drawing from years of experience mentoring student projects, this guide covers everything from topic selection, architecture design, and hardware selection to final presentation, providing a complete development strategy and pitfall-avoidance guide.

#Student Project#Capstone Project#IoT#Arduino#ESP32#Project Development#Hands-on Tutorial

Complete Student Project Development Guide: From Concept to Finished Product

Having assisted dozens of student teams every year in completing their projects, we have witnessed many moments of success as well as numerous detours taken along the way. This article compiles the most practical project development experiences, with the goal of helping you successfully complete an impressive work.

Phase 1: Topic Selection and Planning (1-2 Weeks)

Three Traits of a Good Project

1. Practicality > Novelty

Many students pursue "never-before-seen" innovation, but evaluators value "something people would actually use" more.

Bad topic example:
"Blockchain-Based Smart Pet Feeder"
→ Blockchain adds no real value here

Good topic example:
"Living Alone Elderly Monitoring System"
→ Solves a real social problem with a clear target audience

2. Feasibility > Complexity

Do not attempt to build a "complete self-driving car system" when you are in your senior year. The project must be completable and demonstrable within the semester.

Assessing Project Difficulty:

def estimate_project_difficulty(project_idea):
    """
    Project difficulty assessment tool
    """
    factors = {
        'hardware_complexity': 0,  # Hardware complexity (1-10)
        'software_complexity': 0,  # Software complexity (1-10)
        'integration_effort': 0,   # Integration difficulty (1-10)
        'debugging_difficulty': 0, # Debugging difficulty (1-10)
        'team_experience': 0,      # Team experience (1-10, higher = more experienced)
    }

    # Calculate total difficulty score
    difficulty_score = (
        factors['hardware_complexity'] * 0.3 +
        factors['software_complexity'] * 0.25 +
        factors['integration_effort'] * 0.25 +
        factors['debugging_difficulty'] * 0.2
    ) / factors['team_experience']

    if difficulty_score < 0.5:
        return "Easy - Completable in 2-3 months"
    elif difficulty_score < 1.0:
        return "Moderate - Requires 4-5 months"
    elif difficulty_score < 1.5:
        return "Difficult - Requires 6+ months"
    else:
        return "Warning: Too difficult - Consider narrowing scope"

# Example
smart_greenhouse = {
    'hardware_complexity': 5,   # ESP32 + sensors
    'software_complexity': 6,   # Data processing + Web
    'integration_effort': 5,    # MQTT + database
    'debugging_difficulty': 6,  # Many environmental variables
    'team_experience': 6,       # Has basic experience
}

print(estimate_project_difficulty(smart_greenhouse))
# Output: "Moderate - Requires 4-5 months"

3. Demonstrability > Technical Depth

On presentation day you only have 5-10 minutes. The evaluators must be able to "see" the results.

Priority order:
1. Working physical demo > PowerPoint presentation
2. Real-time data display > Historical records
3. Interactive interface > Text-only output

Recommended Project Topics

Beginner Level (2-3 Months)

1. Smart Plant Monitoring System

Hardware Requirements:
- Arduino Uno / ESP8266
- Soil moisture sensor
- DHT22 temperature and humidity sensor
- Relay module (for water pump control)
- OLED display

Core Features:
- Real-time soil moisture and temperature monitoring
- Automatic watering (when moisture drops below threshold)
- LINE Bot push notifications
- Historical data logging and charting

Technical Highlights:
- IoT cloud integration
- Automated control
- Mobile device push notifications

Complete Code Architecture:

// smart_plant_monitor.ino
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

#define DHTPIN D4
#define SOIL_MOISTURE_PIN A0
#define PUMP_RELAY_PIN D1
#define MOISTURE_THRESHOLD 30

DHT dht(DHTPIN, DHT22);
WiFiClient espClient;
PubSubClient mqtt(espClient);

struct SensorData {
    float temperature;
    float humidity;
    int soilMoisture;
    unsigned long timestamp;
};

void setup() {
    Serial.begin(115200);
    pinMode(PUMP_RELAY_PIN, OUTPUT);
    digitalWrite(PUMP_RELAY_PIN, LOW);

    dht.begin();
    setupWiFi();
    setupMQTT();
}

void loop() {
    if (!mqtt.connected()) {
        reconnectMQTT();
    }
    mqtt.loop();

    // Read sensors every 30 seconds
    static unsigned long lastRead = 0;
    if (millis() - lastRead > 30000) {
        SensorData data = readSensors();
        publishData(data);
        checkAutoWatering(data);
        lastRead = millis();
    }
}

SensorData readSensors() {
    SensorData data;
    data.temperature = dht.readTemperature();
    data.humidity = dht.readHumidity();
    data.soilMoisture = map(analogRead(SOIL_MOISTURE_PIN), 0, 1023, 0, 100);
    data.timestamp = millis();

    Serial.printf("Temperature: %.1f°C, Humidity: %.1f%%, Soil Moisture: %d%%\n",
                  data.temperature, data.humidity, data.soilMoisture);

    return data;
}

void checkAutoWatering(SensorData data) {
    if (data.soilMoisture < MOISTURE_THRESHOLD) {
        Serial.println("Warning: Soil too dry, activating watering!");

        // Turn on pump for 5 seconds
        digitalWrite(PUMP_RELAY_PIN, HIGH);
        delay(5000);
        digitalWrite(PUMP_RELAY_PIN, LOW);

        // Send LINE notification
        sendLineNotification("Plant has been auto-watered");
    }
}

void publishData(SensorData data) {
    char payload[200];
    sprintf(payload,
            "{\"temperature\":%.1f,\"humidity\":%.1f,\"soil\":%d,\"time\":%lu}",
            data.temperature, data.humidity, data.soilMoisture, data.timestamp);

    mqtt.publish("plant/sensors", payload);
}

2. Smart Access Control System

Hardware Requirements:
- ESP32-CAM
- RFID-RC522 module
- Servo motor (door lock)
- Buzzer

Core Features:
- RFID card identification
- Facial recognition (OpenCV)
- Access logs uploaded to cloud
- Intrusion alert system

Technical Highlights:
- Multi-factor authentication
- Image recognition AI
- Security design

Intermediate Level (4-5 Months)

3. Factory Equipment Monitoring and Predictive Maintenance System

System Architecture:

┌─────────────────────────────────────────┐
│    Factory Equipment Monitoring System   │
├─────────────────────────────────────────┤
│                                          │
│  ┌──────────────┐  ┌──────────────┐    │
│  │Vibration Sensor│  │Temp. Sensor  │    │
│  └──────┬───────┘  └──────┬───────┘    │
│         │                  │             │
│         └────────┬─────────┘             │
│                  ↓                       │
│          ┌──────────────┐                │
│          │   ESP32      │                │
│          │  (Edge AI)   │                │
│          └──────┬───────┘                │
│                 │ MQTT                   │
│                 ↓                        │
│     ┌──────────────────────┐            │
│     │   Cloud Server        │            │
│     │  - Data storage       │            │
│     │  - AI prediction model│            │
│     │  - Dashboard         │            │
│     └──────────────────────┘            │
└─────────────────────────────────────────┘

Core Features:
- Multi-sensor real-time monitoring
- Anomaly pattern recognition (machine learning)
- Failure prediction (time-series forecasting models)
- Web Dashboard visualization
- Alert notifications (Email/LINE)

Technical Challenges:
- Sensor data fusion
- Edge computing implementation
- Machine learning model training
- Time-series data processing

Machine Learning Anomaly Detection Implementation:

# anomaly_detection.py
import numpy as np
from sklearn.ensemble import IsolationForest
from sklearn.preprocessing import StandardScaler
import joblib

class VibrationAnomalyDetector:
    def __init__(self):
        self.model = IsolationForest(
            contamination=0.1,  # Expected anomaly ratio: 10%
            random_state=42
        )
        self.scaler = StandardScaler()
        self.is_trained = False

    def train(self, normal_data):
        """
        Train the model with normal operating data

        normal_data: shape (n_samples, n_features)
        features = [vibration_frequency, amplitude, temperature, rpm]
        """
        # Standardize
        X_scaled = self.scaler.fit_transform(normal_data)

        # Train model
        self.model.fit(X_scaled)
        self.is_trained = True

        print(f"Model training complete, using {len(normal_data)} data points")

    def predict(self, sensor_data):
        """
        Predict whether data is anomalous

        Returns:
            is_anomaly: bool
            anomaly_score: float (lower = more anomalous)
        """
        if not self.is_trained:
            raise ValueError("Model has not been trained yet")

        # Standardize
        X_scaled = self.scaler.transform(sensor_data.reshape(1, -1))

        # Predict
        prediction = self.model.predict(X_scaled)[0]
        score = self.model.score_samples(X_scaled)[0]

        is_anomaly = (prediction == -1)

        if is_anomaly:
            print(f"Anomaly detected! Score: {score:.4f}")

        return is_anomaly, score

    def save_model(self, filepath):
        """Save the trained model"""
        joblib.dump({
            'model': self.model,
            'scaler': self.scaler
        }, filepath)
        print(f"Model saved to {filepath}")

    @classmethod
    def load_model(cls, filepath):
        """Load a trained model"""
        data = joblib.load(filepath)
        detector = cls()
        detector.model = data['model']
        detector.scaler = data['scaler']
        detector.is_trained = True
        return detector

# Usage example
if __name__ == "__main__":
    # 1. Collect normal operating data (simulated)
    normal_data = np.random.randn(1000, 4) * [50, 2, 60, 1500] + [200, 5, 40, 3000]

    # 2. Train model
    detector = VibrationAnomalyDetector()
    detector.train(normal_data)

    # 3. Real-time monitoring
    while True:
        # Read sensor data
        sensor_reading = np.array([210, 5.2, 42, 3100])  # [frequency, amplitude, temperature, rpm]

        is_anomaly, score = detector.predict(sensor_reading)

        if is_anomaly:
            send_alert_notification(sensor_reading, score)

4. Smart Parking Lot Management System

Complete Features:
- Ultrasonic sensor parking spot detection
- LED indicator lights (red/green)
- LCD display showing available spots
- Mobile app real-time query
- License plate recognition (advanced)
- Automatic billing system

AI/ML Projects (5-6 Months)

5. Smart Waste Classification Recognition System

# trash_classifier.py
import tensorflow as tf
from tensorflow.keras.applications import MobileNetV2
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D, Dropout
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing.image import ImageDataGenerator

class TrashClassifier:
    def __init__(self, num_classes=6):
        """
        Waste classification model

        Categories:
        0: General waste
        1: Recyclable (paper)
        2: Recyclable (plastic)
        3: Recyclable (metal)
        4: Food waste
        5: Hazardous waste
        """
        self.num_classes = num_classes
        self.model = self._build_model()
        self.class_names = [
            'General Waste', 'Paper', 'Plastic', 'Metal', 'Food Waste', 'Hazardous Waste'
        ]

    def _build_model(self):
        # Use MobileNetV2 as backbone (suitable for embedded deployment)
        base_model = MobileNetV2(
            input_shape=(224, 224, 3),
            include_top=False,
            weights='imagenet'
        )

        # Freeze the first 100 layers of the base model
        for layer in base_model.layers[:100]:
            layer.trainable = False

        # Add classification layers
        x = base_model.output
        x = GlobalAveragePooling2D()(x)
        x = Dense(256, activation='relu')(x)
        x = Dropout(0.5)(x)
        x = Dense(128, activation='relu')(x)
        x = Dropout(0.3)(x)
        predictions = Dense(self.num_classes, activation='softmax')(x)

        model = Model(inputs=base_model.input, outputs=predictions)

        model.compile(
            optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
            loss='categorical_crossentropy',
            metrics=['accuracy']
        )

        return model

    def train(self, train_dir, val_dir, epochs=30, batch_size=32):
        """Train the model"""
        # Data augmentation
        train_datagen = ImageDataGenerator(
            rescale=1./255,
            rotation_range=20,
            width_shift_range=0.2,
            height_shift_range=0.2,
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True,
            fill_mode='nearest'
        )

        val_datagen = ImageDataGenerator(rescale=1./255)

        train_generator = train_datagen.flow_from_directory(
            train_dir,
            target_size=(224, 224),
            batch_size=batch_size,
            class_mode='categorical'
        )

        val_generator = val_datagen.flow_from_directory(
            val_dir,
            target_size=(224, 224),
            batch_size=batch_size,
            class_mode='categorical'
        )

        # Train
        history = self.model.fit(
            train_generator,
            epochs=epochs,
            validation_data=val_generator,
            callbacks=[
                tf.keras.callbacks.EarlyStopping(patience=5, restore_best_weights=True),
                tf.keras.callbacks.ReduceLROnPlateau(factor=0.5, patience=3)
            ]
        )

        return history

    def convert_to_tflite(self, output_path='trash_model.tflite'):
        """
        Convert to TensorFlow Lite format
        For deployment on ESP32-CAM or Raspberry Pi
        """
        converter = tf.lite.TFLiteConverter.from_keras_model(self.model)

        # Quantize to reduce model size
        converter.optimizations = [tf.lite.Optimize.DEFAULT]

        tflite_model = converter.convert()

        with open(output_path, 'wb') as f:
            f.write(tflite_model)

        print(f"TFLite model saved: {output_path}")
        print(f"  Model size: {len(tflite_model) / 1024:.2f} KB")

ESP32-CAM Integration:

// trash_classifier_esp32cam.ino
#include "esp_camera.h"
#include "tensorflow/lite/micro/all_ops_resolver.h"
#include "tensorflow/lite/micro/micro_interpreter.h"
#include "tensorflow/lite/schema/schema_generated.h"

// Model storage
#include "trash_model.h"  // Converted TFLite model

const char* classNames[] = {
    "General Waste", "Paper", "Plastic", "Metal", "Food Waste", "Hazardous Waste"
};

void setup() {
    Serial.begin(115200);

    // Initialize camera
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    // ... other camera settings

    esp_err_t err = esp_camera_init(&config);
    if (err != ESP_OK) {
        Serial.printf("Camera init failed: 0x%x", err);
        return;
    }

    // Initialize TensorFlow Lite
    setupTFLite();
}

void loop() {
    // Capture photo
    camera_fb_t * fb = esp_camera_fb_get();
    if (!fb) {
        Serial.println("Photo capture failed");
        return;
    }

    // Image preprocessing (resize to 224x224, normalize)
    uint8_t* processed_image = preprocessImage(fb->buf, fb->len);

    // Run inference
    int predicted_class = runInference(processed_image);

    // Display result
    Serial.printf("Classification result: %s\n", classNames[predicted_class]);

    // Free memory
    esp_camera_fb_return(fb);

    delay(2000);  // Classify every 2 seconds
}

Phase 2: Hardware Selection and Procurement (1 Week)

Common Development Board Comparison

Development Board Price Advantages Use Case
Arduino Uno ~$6 Beginner-friendly, abundant resources Simple sensor control
ESP8266 ~$3 Built-in WiFi, inexpensive Basic IoT applications
ESP32 ~$5 Dual-core, BLE+WiFi Advanced IoT applications
Raspberry Pi 4 ~$50 Full Linux system AI/image processing
STM32 ~$10 Industrial-grade, high stability Professional applications
Nordic nRF52 ~$15 Low-power Bluetooth Wearable devices

Budget Planning Recommendations

Total Budget: $100 - $150

Basic Configuration:
- Development board: $15
- Sensor modules: $25
- Power/cables: $10
- PCB fabrication: $15
- Enclosure/structure: $20
- Spare parts: $10
Total: ~$95

Advanced Configuration (+AI/Image):
+ Raspberry Pi: $50
+ Camera Module: $15
Total: ~$160

Procurement Checklist Template

## Smart Plant Monitoring System - Procurement Checklist

### Main Components
- [ ] ESP8266 NodeMCU x 1 ($4)
- [ ] DHT22 Temperature/Humidity Sensor x 1 ($5)
- [ ] Soil Moisture Sensor x 1 ($2)
- [ ] 0.96" OLED Display x 1 ($3)
- [ ] 5V Relay Module x 1 ($1.50)
- [ ] Small Water Pump x 1 ($3)

### Power and Cables
- [ ] Micro USB Cable x 1 ($2)
- [ ] 5V 2A Power Adapter x 1 ($3)
- [ ] Dupont Wires (M-M/F-F/M-F 20 each) ($2)
- [ ] Breadboard x 1 ($2)

### Miscellaneous
- [ ] Plant for the project x 1 ($2)
- [ ] Tubing and connectors ($2)
- [ ] Enclosure (acrylic or 3D printed) ($10)

Total: ~$40

Phase 3: Development and Integration (8-12 Weeks)

Development Timeline

Week 1-2: Hardware Testing

# Test checklist
hardware_tests = {
    'power': {
        'description': 'Power supply testing',
        'tests': [
            'Voltage stability test',
            'Current consumption measurement',
            'Battery life estimation'
        ]
    },
    'sensors': {
        'description': 'Sensor functionality testing',
        'tests': [
            'Reading accuracy verification',
            'Response time testing',
            'Environmental interference testing'
        ]
    },
    'actuators': {
        'description': 'Actuator testing',
        'tests': [
            'Motor/relay control',
            'Load capacity testing',
            'Continuous operation stability'
        ]
    },
    'communication': {
        'description': 'Communication module testing',
        'tests': [
            'WiFi connection stability',
            'MQTT message transmission',
            'Reconnection mechanism'
        ]
    }
}

Week 3-6: Core Feature Development

Focus on the 2-3 most important core features and ensure they work completely.

Week 7-9: System Integration

Integrate all individual modules into a complete system.

Week 10-11: Testing and Optimization

Week 12: Documentation and Presentation Preparation

Common Problem Solutions

Problem 1: Unstable Sensor Readings

// Solution: Multiple sampling with averaging
float readStableSensorValue(int pin, int samples = 10) {
    float sum = 0;

    for (int i = 0; i < samples; i++) {
        sum += analogRead(pin);
        delay(10);  // Wait for stabilization
    }

    return sum / samples;
}

// Advanced: Median filter
float readWithMedianFilter(int pin, int samples = 9) {
    float readings[samples];

    // Collect data
    for (int i = 0; i < samples; i++) {
        readings[i] = analogRead(pin);
        delay(10);
    }

    // Sort
    std::sort(readings, readings + samples);

    // Return median
    return readings[samples / 2];
}

Problem 2: Unstable WiFi Connection

// WiFi auto-reconnection mechanism
void ensureWiFiConnected() {
    static unsigned long lastCheck = 0;

    // Check every 30 seconds
    if (millis() - lastCheck < 30000) {
        return;
    }
    lastCheck = millis();

    if (WiFi.status() != WL_CONNECTED) {
        Serial.println("WiFi disconnected, attempting reconnection...");

        WiFi.disconnect();
        delay(1000);
        WiFi.begin(ssid, password);

        int timeout = 0;
        while (WiFi.status() != WL_CONNECTED && timeout < 20) {
            delay(500);
            Serial.print(".");
            timeout++;
        }

        if (WiFi.status() == WL_CONNECTED) {
            Serial.println("\nWiFi reconnected successfully");
        } else {
            Serial.println("\nWiFi reconnection failed");
        }
    }
}

Problem 3: Insufficient Memory

// ESP8266/ESP32 memory optimization tips

// 1. Use F() macro to store strings in Flash
Serial.println(F("This string won't occupy RAM"));

// 2. Free unused variables
void processData() {
    String largeData = downloadData();
    // Process data...
    largeData = "";  // Free memory
}

// 3. Monitor memory usage
void printMemoryUsage() {
    Serial.printf("Free Heap: %d bytes\n", ESP.getFreeHeap());
    Serial.printf("Heap Fragmentation: %d%%\n", ESP.getHeapFragmentation());
}

Phase 4: Presentation Preparation (1-2 Weeks)

Secrets to a Successful Demo

1. Prepare Plan B

Primary Demo: Live cloud-connected demonstration
Backup Plan A: Local offline demonstration
Backup Plan B: Pre-recorded video playback
Backup Plan C: Slide presentation + photos

2. Oral Presentation Structure

## 5-Minute Presentation Structure

[30 sec] Problem Statement
- What problem does this project solve?
- Why is it important?

[1 min] System Introduction
- System architecture diagram
- Core technologies

[2 min] Live Demo
- Operation flow
- Feature demonstration

[1 min] Technical Highlights
- Technologies used
- Challenges overcome

[30 sec] Summary and Future Outlook

3. Common Evaluator Questions to Prepare For

Q: Why not use an existing commercial product?
A: (Explain customization needs, cost considerations, learning objectives)

Q: How do you ensure system stability?
A: (Show stress test results, error handling mechanisms)

Q: What was the biggest challenge you faced?
A: (Technical difficulty + solution + lessons learned)

Q: Can this system be commercialized?
A: (Market analysis, cost estimates, improvement directions)

Bonus Tips

1. Build a Professional Enclosure

Material Choices:
- 3D printing (most recommended)
- Laser-cut acrylic
- Modified off-the-shelf electronics enclosures
- Avoid cardboard boxes (not professional enough)

2. Create a Project Website

<!-- Simple project website template -->
<!DOCTYPE html>
<html>
<head>
    <title>Smart Plant Monitoring System</title>
    <style>
        body { font-family: Arial; max-width: 800px; margin: 0 auto; }
        .hero { background: #4CAF50; color: white; padding: 50px; text-align: center; }
        .feature { padding: 20px; border-bottom: 1px solid #ddd; }
        img { max-width: 100%; height: auto; }
    </style>
</head>
<body>
    <div class="hero">
        <h1>Smart Plant Monitoring System</h1>
        <p>Keep your plants in optimal condition at all times</p>
    </div>

    <div class="feature">
        <h2>Project Overview</h2>
        <p>This system monitors soil moisture, ambient temperature and humidity in real time...</p>
    </div>

    <div class="feature">
        <h2>System Architecture</h2>
        <img src="architecture.png" alt="System Architecture Diagram">
    </div>

    <div class="feature">
        <h2>Demo Video</h2>
        <iframe width="560" height="315" src="demo.mp4"></iframe>
    </div>
</body>
</html>

3. Write a Technical Blog

Share your development process on Medium or HackMD to:

  • Build your personal brand
  • Get community feedback
  • Build a portfolio for job applications

4. Enter Competitions

Recommended Competitions:
- Ministry of Education Information Application Innovation Competition
- ITSA Programming Competition
- MakeNTU Hardware Hackathon
- AWS DeepRacer Autonomous Driving Competition
- University-level internal competitions

Time Management and Team Collaboration

Using Git for Version Control

# Project development Git workflow

# 1. Create project repository
git init smart-plant-monitor
cd smart-plant-monitor

# 2. Establish branching strategy
git checkout -b develop        # Development branch
git checkout -b feature/sensor # Feature branch
git checkout -b feature/webapp

# 3. Daily workflow
git add .
git commit -m "feat: Add soil moisture sensor driver"
git push origin feature/sensor

# 4. Merge into main branch
git checkout develop
git merge feature/sensor

# 5. Release version
git tag -a v1.0 -m "First presentation version"
git push origin v1.0

Project Management Tools

## Using Trello/Notion to Track Progress

### To Do
- [ ] Complete sensor calibration
- [ ] Implement MQTT connection
- [ ] Design Web interface

### In Progress
- [ ] Integrate LINE Bot notifications

### Done
- [x] Complete hardware assembly
- [x] Test basic functionality

Final Reminders

Things to Do

  1. Start early - Do not wait until the last two weeks
  2. Test frequently - Test after adding each feature
  3. Write clear comments - Your future self will thank you
  4. Backup, backup, backup - Git + cloud storage for double insurance
  5. Document the process - Take photos, record videos, write notes

Mistakes to Avoid

  1. Do not pursue perfection - Working > Perfect but incomplete
  2. Do not reinvent the wheel - Leverage existing libraries
  3. Do not pull all-nighters - Low efficiency and error-prone
  4. Do not go it alone - Utilize professors and senior students as resources
  5. Do not be afraid of failure - Mistakes are the best teachers

Conclusion

A successful project = Clear goals + Reasonable planning + Consistent execution

Remember: Evaluators are not only looking at your technical skills, but also your problem-solving ability and learning attitude.

At BASHCAT, we have helped over 100 student teams successfully complete their projects, providing comprehensive technical guidance from concept, hardware selection, and software development to final presentation. If you encounter difficulties with your project, feel free to contact us!

Additional Resources

$ tail -n 1 /var/log/bashcat/posts

More from the workshop.