Sensor/Switch (sensor.{h,cpp}, switch.{h.cpp})#

class Sensor#

#pragma once

#include <filesystem>


class Sensor
{
public:
    Sensor(const std::filesystem::path& celsius_temperature_file);

    void turn_on() { _on = true; }
    void turn_off() { _on = false; }

    long get_temperature();

    std::string path() const { return _celsius_temperature_file.string(); }

private:
    std::filesystem::path _celsius_temperature_file;
    bool _on;
};
#include "sensor.h"

#include <print>
#include <string>
#include <cassert>
#include <fcntl.h>
#include <unistd.h>


Sensor::Sensor(const std::filesystem::path& celsius_temperature_file)
: _celsius_temperature_file(celsius_temperature_file)
{}

long Sensor::get_temperature()
{
    if (! _on) {
        std::println("switching sensor on again -> BOOM!");
        return 666'666'666'666;
    }

    int fd = open(_celsius_temperature_file.c_str(), O_RDONLY);
    if (fd == -1) {
        perror(std::format("open(\"{}\", O_RDONLY)", _celsius_temperature_file.string()).c_str());
        assert(false);
    }
    
    char tmp[16] = {};
    ssize_t nread = read(fd, tmp, sizeof(tmp)-1);
    if (nread == -1) {
        perror("read");
        assert(false);
    }

    close(fd);

    try {
        return std::stoi(tmp);
    }
    catch (const std::exception& e) {
        std::println(stderr, "content of file {} ({}) is not an integer", _celsius_temperature_file.string(), tmp);
        assert(false);
    }
}

class Switch#

#pragma once

#include <filesystem>


class Switch
{
public:
    Switch(const std::filesystem::path& control_file);
    
    void set_state(bool);
    bool get_state() const;

    std::string path() const { return _control_file.string(); }

private:
    std::filesystem::path _control_file;
};
#include "switch.h"

#include <cassert>
#include <fcntl.h>
#include <unistd.h>


static bool read_state(const std::filesystem::path& control_file)
{
    int fd = open(control_file.c_str(), O_RDONLY);
    if (fd == -1) {
        perror(std::format("open(\"{}\", O_RDONLY)", control_file.string()).c_str());
        assert(false);
    }

    char c;
    ssize_t nread = read(fd, &c, 1);
    if (nread == -1) {
        perror("read");
        assert(false);
    }

    close(fd);

    return (c == '1');
}

static void write_state(const std::filesystem::path& control_file, bool state)
{
    int fd = open(control_file.c_str(), O_WRONLY|O_TRUNC);
    if (fd == -1) {
        perror(std::format("open(\"{}\", O_WRONLY|O_TRUNC)", control_file.string()).c_str());
        assert(false);
    }

    static const char on = '1';
    static const char off = '0';

    ssize_t nwritten = write(fd, state?&on:&off, 1);
    if (nwritten == -1) {
        perror("write");
        assert(false);
    }
}

Switch::Switch(const std::filesystem::path& control_file)
: _control_file(control_file)
{
    write_state(_control_file, false);  // Initialize to OFF
}

void Switch::set_state(bool state)
{
    if (state != get_state())
        write_state(_control_file, state);
}

bool Switch::get_state() const
{
    return read_state(_control_file);
}