Smart Home Lighting Control System

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.
- deviceID (
- 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”.
- time (
- 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 withstd::any_of
before creating a newLightDevice
viastd::make_unique
.removeDevice
usesstd::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 correspondingLightDevice
withstd::find_if
, and callsturnOn
orturnOff
. After execution, it removes those entries. - Display:
listDevices
iterates over each smart pointer, callingdisplay()
.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]