|

Smart Home Lighting Control System

Spread the love

Project Description

Develop a C++ console application to manage and automate lighting in a smart home environment. The system should track individual light devices, group them by rooms, and allow scheduling of on/off events. Required features:

  • Device Representation: Create a LightDevice class containing:
    • deviceID (std::string): unique identifier for each light (e.g., “LD001”).
    • room (std::string): name of the room where the device is located.
    • isOn (bool): current state of the light (on/off).
    • Methods:
      • turnOn(): sets isOn to true and logs the action.
      • turnOff(): sets isOn to false and logs the action.
      • display(): prints deviceID, room, and current state.
  • Scheduler Representation: Implement a ScheduleEntry struct containing:
    • time (std::string): scheduled time in HH:MM format.
    • deviceID (std::string): target light device.
    • action (std::string): either “ON” or “OFF”.
  • LightingManager: A class to manage devices and schedules:
    • addDevice(deviceID, room): register a new light device.
    • removeDevice(deviceID): remove an existing device and its scheduled entries.
    • listDevices(): display all registered devices.
    • scheduleAction(time, deviceID, action): add a new ScheduleEntry to run at the specified time.
    • cancelSchedule(time, deviceID): remove a matching schedule entry.
    • runSchedule(currentTime): execute all actions scheduled at currentTime, turning devices on/off accordingly.
    • displaySchedule(): list all pending schedule entries sorted by time.
  • Behavioral Requirements:
    • Prevent scheduling actions for non-existent devices.
    • Ensure schedule entries are sorted by time for display.
    • Use std::vector<std::unique_ptr> for devices and std::vector for schedules, ensuring clear ownership and simple iteration.

Solution :

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
#include <string>
#include <iomanip>

// Represents a single smart light device
class LightDevice {
public:
    std::string deviceID;    // Unique light ID
    std::string room;        // Location of the device
    bool isOn;               // Current state

    // Constructor initializes fields
    LightDevice(const std::string& id, const std::string& r)
        : deviceID(id), room(r), isOn(false) {}

    // Turn the light on and log action
    void turnOn() {
        isOn = true;
        std::cout << "Device " << deviceID << " in " << room << " turned ON\n";
    }

    // Turn the light off and log action
    void turnOff() {
        isOn = false;
        std::cout << "Device " << deviceID << " in " << room << " turned OFF\n";
    }

    // Display device details
    void display() const {
        std::cout << "ID: " << deviceID
                  << " | Room: " << room
                  << " | State: " << (isOn ? "ON" : "OFF") << "\n";
    }
};

// Schedule entry for timed actions
struct ScheduleEntry {
    std::string time;        // HH:MM format
    std::string deviceID;    // Target device
    std::string action;      // "ON" or "OFF"
};

// Manages light devices and scheduled actions
class LightingManager {
    std::vector<std::unique_ptr<LightDevice>> devices;
    std::vector<ScheduleEntry> schedule;

public:
    // Add a new light device
    void addDevice(const std::string& id, const std::string& room) {
        if (std::any_of(devices.begin(), devices.end(),
            [&](const auto& d){ return d->deviceID == id; })) {
            std::cerr << "Device already exists: " << id << "\n";
            return;
        }
        devices.push_back(std::make_unique<LightDevice>(id, room));
        std::cout << "Added device " << id << " in " << room << "\n";
    }

    // Remove device and its schedules
    void removeDevice(const std::string& id) {
        // Remove schedules for this device
        schedule.erase(
            std::remove_if(schedule.begin(), schedule.end(),
                [&](const auto& e){ return e.deviceID == id; }),
            schedule.end()
        );
        // Remove device itself
        devices.erase(
            std::remove_if(devices.begin(), devices.end(),
                [&](const auto& d){ return d->deviceID == id; }),
            devices.end()
        );
        std::cout << "Removed device and its schedules: " << id << "\n";
    }

    // List all devices
    void listDevices() const {
        std::cout << "\nRegistered Devices:\n";
        for (const auto& d : devices) d->display();
    }

    // Schedule an on/off action
    void scheduleAction(const std::string& time,
                        const std::string& id,
                        const std::string& action) {
        // Validate device existence
        if (!std::any_of(devices.begin(), devices.end(),
            [&](const auto& d){ return d->deviceID == id; })) {
            std::cerr << "Cannot schedule: unknown device " << id << "\n";
            return;
        }
        schedule.push_back({time, id, action});
        std::cout << "Scheduled " << action << " for " << id
                  << " at " << time << "\n";
    }

    // Cancel a scheduled action
    void cancelSchedule(const std::string& time, const std::string& id) {
        auto it = std::remove_if(schedule.begin(), schedule.end(),
            [&](const auto& e){ return e.time == time && e.deviceID == id; });
        if (it == schedule.end()) {
            std::cerr << "No matching schedule to cancel\n";
            return;
        }
        schedule.erase(it, schedule.end());
        std::cout << "Canceled schedule for " << id << " at " << time << "\n";
    }

    // Run all actions scheduled at the current time
    void runSchedule(const std::string& currentTime) {
        for (const auto& entry : schedule) {
            if (entry.time == currentTime) {
                // Find device and execute action
                auto it = std::find_if(devices.begin(), devices.end(),
                    [&](const auto& d){ return d->deviceID == entry.deviceID; });
                if (it != devices.end()) {
                    if (entry.action == "ON") (*it)->turnOn();
                    else (*it)->turnOff();
                }
            }
        }
        // Optionally, remove executed entries
        schedule.erase(
            std::remove_if(schedule.begin(), schedule.end(),
                [&](const auto& e){ return e.time == currentTime; }),
            schedule.end()
        );
    }

    // Display all pending schedule entries sorted by time
    void displaySchedule() const {
        std::cout << "\nPending Schedule:\n";
        // Copy and sort
        auto sorted = schedule;
        std::sort(sorted.begin(), sorted.end(), [](auto& a, auto& b){
            return a.time < b.time;
        });
        for (const auto& e : sorted) {
            std::cout << e.time << " | " << e.deviceID
                      << " -> " << e.action << "\n";
        }
    }
};

// Example usage
int main() {
    LightingManager lm;
    // Add devices
    lm.addDevice("LD001", "Living Room");
    lm.addDevice("LD002", "Kitchen");

    // Schedule actions
    lm.scheduleAction("18:30", "LD001", "ON");
    lm.scheduleAction("23:00", "LD001", "OFF");
    lm.scheduleAction("19:00", "LD002", "ON");

    // Display and run schedule
    lm.displaySchedule();
    std::cout << "\n-- Running schedule at 18:30 --\n";
    lm.runSchedule("18:30");
    lm.listDevices();

    return 0;
}

Detailed Explanation of Logic

The LightingManager orchestrates LightDevice instances stored in a std::vector<std::unique_ptr<LightDevice>>, ensuring each device’s lifetime is managed automatically. The schedule is maintained as a std::vector<ScheduleEntry>, where each entry records a time, target device, and action.

  • Device Management: addDevice checks for duplicates with std::any_of before creating a new LightDevice via std::make_unique. removeDevice uses std::remove_if to purge both the device and any associated schedule entries.
  • Scheduling: scheduleAction validates the device exists, then appends a new ScheduleEntry. cancelSchedule similarly removes matching entries.
  • Execution: runSchedule iterates through scheduled entries that match the current time, locates the corresponding LightDevice with std::find_if, and calls turnOn or turnOff. After execution, it removes those entries.
  • Display: listDevices iterates over each smart pointer, calling display(). displaySchedule makes and sorts a copy of the schedule, then prints entries in time order, ensuring clear visibility of pending actions.

If you have any questions , feel free to contact us at [email protected]

Similar Posts