Code Monkey home page Code Monkey logo

wfh_monitor's Introduction

Build Docs Common

Work from Home Monitor

おうち環境モニター

img

機能

  • Grove接続されたI2C I/Fを持つセンサ値を読み取る
  • LCDに現在の値を表示する
  • microSDカードからの設定の読み書き
  • microSDカードへのセンサ値保存
  • Ambient へのセンサ値送信
  • Taskことに分離された実装による拡張性
    • C/C++の実装経験があれば、自分の好みの機能を追加したり修正したりすることができます
  • Dockerを使ったビルド環境
    • ビルド環境構築に悩む必要はもうありません

必要なもの

接続方法

Wio Terminal 画面左下のGrove Connector に I2C Hub を接続し、 I2C Hub の Grove Connector に BME680 と TSL2561 を接続します。

書き込み方法

  1. Build - Github Actionsからビルド済バイナリをダウンロードします。
  2. Bootloaderモードで起動します
  3. PCに接続するとArduinoのストレージデバイスが見えるので、wfh_monitor.ino.uf2をドライブ上にコピーします
  4. 無事に起動したら完了

設定ファイル

SDカード直下にwfhm.jsonというファイルに設定を記述することで、挙動変更やWiFi機能の有効化を行うことができます。

設定内容

GlobalConfig.h を参照 wfhm.jsonが作成されていないFAT32で初期化されたSDカードを挿入した状態で起動することで、デフォルト設定の雛形が自動作成されます。

コンパイル時定数

SDカードでは設定できず、コンパイル時定数として埋め込まれる設定も存在します。 詳細は FixedConfig.h を参照

依存ライブラリ

素晴らしいライブラリをありがとうございます。

開発者向け情報

ドキュメント

doxygenを整備しています。 Docs - GitHub Actions から最新のものをDLするか、$ docker-compose run docs, $ doxygen等でビルドすることで入手することができます。

FWのビルド方法

Dockerを推奨しますが、同様の環境を作れば任意の環境で開発できます。 安定性確保のためにはlib下のモジュールとバージョンを合わせることを推奨します。

Docker

$ docker-compose run build

Arduino CLI & Python

.lib下にあるライブラリとSeeeduino:seeed_wio_terminalの追加が必要です。 詳しくは arduino-cli.Dockerfile をご参照ください

$ ./build.sh

Arduino IDE

  1. seeed_wio_terminalをボードマネージャから追加します
  2. ./lib下にあるライブラリをインストールします
  3. にwfh_monitor.inoを開いてコンパイルして書き込んでください。

License

MIT

wfh_monitor's People

Contributors

kamiyaowl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

jjzhang166

wfh_monitor's Issues

もう少しいい感じに書けるかも。Keys/DefaultValuesを内包する型パラメータの指定は考察...

もう少しいい感じに書けるかも。Keys/DefaultValuesを内包する型パラメータの指定は考察が必要

// TODO: もう少しいい感じに書けるかも。Keys/DefaultValuesを内包する型パラメータの指定は考察が必要

        /**
         * @brief 指定された値をconfigVolatileに書き込みます
         * 
         * @tparam T 書き込むデータの型
         * @param isOverwrite すでに値がセットされている場合でも上書きする場合はtrue
         * @param key セット対象のKey
         * @param value セットする値
         */
        template<typename T>
        void write(bool isOverwrite, const char* key, T& value) {
            if (isOverwrite || !this->configVolatile.containsKey(key)) { 
                this->configVolatile[key] = value;
            }
        }

        /**
         * @brief 指定されたKeyの値を読み出します
         * 
         * @tparam T 読み出す型
         * @param key 読み出し対象のKey
         * @param value 読みだしたデータの書き込み先、Keyが存在しない場合は操作しません
         * @return true 読み出し成功
         * @return false 読み出し失敗
         */
        template<typename T>
        bool read(const char* key, T& value) {
            // Keyが存在しない
            if (!this->configVolatile.containsKey(key)) {
                return false;
            }
            // 値を読み出す
            value = this->configVolatile[key];
            return true;
        }
        /**
         * @brief すべての値を初期値で上書きします
         * @param isMigrate 存在しない値のみを上書きする場合はtrue
         * 
         * @note 完全新規のconfigを生成する場合はisMigrate=falseで実行する
         */
        void init(bool isMigrate) {
            // 一通り必要な初期値をセット
            // TODO: もう少しいい感じに書けるかも。Keys/DefaultValuesを内包する型パラメータの指定は考察が必要
            this->write(!isMigrate, GlobalConfigKeys::Identifier              , GlobalConfigDefaultValues::Identifier);
            this->write(!isMigrate, GlobalConfigKeys::Date                    , GlobalConfigDefaultValues::Date);
            this->write(!isMigrate, GlobalConfigKeys::Time                    , GlobalConfigDefaultValues::Time);
            this->write(!isMigrate, GlobalConfigKeys::GroveTaskFps            , GlobalConfigDefaultValues::GroveTaskFps);
            this->write(!isMigrate, GlobalConfigKeys::ButtonTaskFps           , GlobalConfigDefaultValues::ButtonTaskFps);
            this->write(!isMigrate, GlobalConfigKeys::UiTaskFps               , GlobalConfigDefaultValues::UiTaskFps);
            this->write(!isMigrate, GlobalConfigKeys::BrightnessHoldMs        , GlobalConfigDefaultValues::BrightnessHoldMs);
            this->write(!isMigrate, GlobalConfigKeys::BrightnessTransitionMs  , GlobalConfigDefaultValues::BrightnessTransitionMs);

            // migrationでなければNonVolatile側にも反映(this->clear()対策)
            if (!isMigrate) {
                this->configNonVolatile = this->configVolatile;
            }
        }

        /**
ndex ffbaee7..fffdaa7 100644
++ b/src/UiTask.cpp

ff16bf4e6a41f4415616df49d0e79100a6a39e5b

設定ファイルから色々できるといいなぁ...

設定ファイルから色々できるといいなぁ...

static constexpr BrightnessSetting brightnessSetting[N] = { // TODO: 設定ファイルから色々できるといいなぁ...

        void setup(void) override {
            // configure
            static constexpr BrightnessSetting brightnessSetting[N] = { // TODO: 設定ファイルから色々できるといいなぁ...
                { .visibleLux =  50.0f , .brightness = 20 },
                { .visibleLux = 120.0f , .brightness = 100 },
                { .visibleLux = 180.0f , .brightness = 200 },
                { .visibleLux = FLT_MAX, .brightness = 255 },
            };
            this->resource.config.operate([&](GlobalConfig<FixedConfig::ConfigAllocateSize>& config){
                // fps
                auto fps = GlobalConfigDefaultValues::UiTaskFps;
                config.read(GlobalConfigKeys::UiTaskFps, fps);
                this->setFps(fps);
                // auto brightness
                auto holdMs = GlobalConfigDefaultValues::BrightnessHoldMs;
                auto transitionMs = GlobalConfigDefaultValues::BrightnessTransitionMs;
                config.read(GlobalConfigKeys::UiTaskFps, holdMs);
                config.read(GlobalConfigKeys::UiTaskFps, transitionMs);

                this->brightness.configure(true, holdMs, transitionMs, brightnessSetting);
            });

            // initialize lcd
            this->lcd.setTextSize(1);

5874979dbc4ee830782d541d6690d2b511926274

#49 config.getReadPtr<char>(GlobalConfigKeys::ApPa...

#49 config.getReadPtr(GlobalConfigKeys::ApPassWord);

const char* pass = "pass"; //TODO: #49 config.getReadPtr<char>(GlobalConfigKeys::ApPassWord);

    }
}

static void setupWifi(void) {
    // 前回動いていた場合、一旦切断
    lcd.printf("[INFO] reset wifi module.\n");
    wifi.mode(WIFI_STA);
    wifi.disconnect();
    delay(FixedConfig::WaitForPorMs);

    // WiFi使わなければSkip
    bool useWifi = GlobalConfigDefaultValues::UseWiFi;
    config.read(GlobalConfigKeys::UseWiFi, useWifi);
    if (!useWifi) {
        lcd.printf("[INFO] skip AP Connection.\n");
        return;
    }

    // Wifi開始
    const char* ssid   = "ssid"; //TODO: #49 config.getReadPtr<char>(GlobalConfigKeys::ApSsid);
    const char* pass   = "pass"; //TODO: #49 config.getReadPtr<char>(GlobalConfigKeys::ApPassWord);
    uint32_t timeoutMs = GlobalConfigDefaultValues::ApTimeoutMs;
    config.read(GlobalConfigKeys::ApTimeoutMs, timeoutMs);

    lcd.printf("[INFO] connect to %s.\n", ssid);
    wifi.begin(ssid, pass);

    const uint32_t startMillis = millis();
    while (wifi.status() != WL_CONNECTED) {
        lcd.print(".");
        delay(FixedConfig::WaitForPorMs);
        // timeout
        const uint32_t elapsedMs = millis() - startMillis;
        if (elapsedMs > timeoutMs) {
            lcd.printf("\n[ERROR] timeout.\n");
            break;
        }
    }

    const bool isConnected = (wifi.status() == WL_CONNECTED);
    if (!isConnected) {
        lcd.printf("[ERROR] Error.\n");
        return;
    }

    lcd.printf("\n[INFO] done.");
    lcd.println(wifi.localIP());
}

static void setupRtos(void) {
    lcd.printf("[INFO] setup RTOS config\n");
    vSetErrorLed(FixedConfig::ErrorLedPinNum, FixedConfig::ErrorLedState);

3f2252b0891825d33d8a90799345fb04070a3ada

IpcQueue Stream Splitterを実装する

UI TaskとWiFi Taskどちらでもセンサーデータを使うが、データの共有はしないため
UI TaskからWifi Taskに送信するでもよいが、責務分担として微妙

FW Revを埋め込む

毎回書き換えるのとかだるいし、commit idあたりをビルドバイナリにうまく埋め込めると吉

設定ファイルから色々できるといいなぁ...

設定ファイルから色々できるといいなぁ...

static constexpr BrightnessSetting brightnessSetting[N] = { // TODO: 設定ファイルから色々できるといいなぁ...

        LGFX& lcd;
        LGFX_Sprite& sprite;
        BrightnessControl<N, LGFX> brightness;

        void setup(void) override {
            // fps control
            this->setFps(30);

            // initialize lcd
            this->lcd.setTextSize(1);

            // initial value
            this->latestMeasureData.visibleLux = 0.0f;
            this->latestMeasureData.tempature = 0.0f;
            this->latestMeasureData.pressure = 0.0f;
            this->latestMeasureData.humidity = 0.0f;
            this->latestMeasureData.gas = 0.0f;
            this->latestMeasureData.timestamp = 0x0;
            this->latestButtonState.raw = 0x0;
            this->latestButtonState.debounce = 0x0;
            this->latestButtonState.push = 0x0;
            this->latestButtonState.release = 0x0;

            // initialize submodules
            static constexpr BrightnessSetting brightnessSetting[N] = { // TODO: 設定ファイルから色々できるといいなぁ...
                { .visibleLux =  50.0f , .brightness = 20 },
                { .visibleLux = 120.0f , .brightness = 100 },
                { .visibleLux = 180.0f , .brightness = 200 },
                { .visibleLux = FLT_MAX, .brightness = 255 },
            };
            this->brightness.configure(true, 4000, 2000, brightnessSetting);
        }
        bool loop(void) override {
            // receive queue datas
            if (this->recvMeasureDataQueue.remainNum() > 0) {
                this->recvMeasureDataQueue.receive(&this->latestMeasureData, false);
            }
            if (this->recvButtonStateQueue.remainNum() > 0) {
                this->recvButtonStateQueue.receive(&this->latestButtonState, false);
            }

            // backlight
            brightness.update(this->latestMeasureData.visibleLux);

            // test
            this->lcd.setCursor(0,0);
            this->lcd.printf("#UiTask\n");
            this->lcd.printf("systick = %d\n", SysTimer::getTickCount());
            this->lcd.printf("counter = %d\n", this->counter);
            this->lcd.printf("maxFps  = %f\n", this->getFpsWithoutDelay());
            this->lcd.printf("\n");

            this->lcd.printf("#SensorData\n");
            this->lcd.printf("visibleLux = %f\n", this->latestMeasureData.visibleLux);
            this->lcd.printf("tempature  = %f\n", this->latestMeasureData.tempature);
            this->lcd.printf("pressure   = %f\n", this->latestMeasureData.pressure);
            this->lcd.printf("humidity   = %f\n", this->latestMeasureData.humidity);
            this->lcd.printf("gas        = %f\n", this->latestMeasureData.gas);
            this->lcd.printf("timestamp  = %u\n", this->latestMeasureData.timestamp);
            this->lcd.printf("\n");

            this->lcd.printf("#Button\n");
            this->lcd.printf("raw       = %08x\n", this->latestButtonState.raw);
            this->lcd.printf("debounce  = %08x\n", this->latestButtonState.debounce);
            this->lcd.printf("push      = %08x\n", this->latestButtonState.push);
            this->lcd.printf("release   = %08x\n", this->latestButtonState.release);
            this->lcd.printf("timestamp = %u\n", this->latestButtonState.timestamp);
            this->lcd.printf("\n");
            
            // for debug
            this->counter++;

            return false; /**< no abort */
        }
};

#endif /* UITASK_H */
 No newline at end of file
ndex 1a33711..50dfcd4 100644
++ b/wfh_monitor.ino

8a2f19584475b9a588a657de18c40cc7c7b4d7eb

ambient送信に必要な情報も読み込んでおく

ambient送信に必要な情報も読み込んでおく

// TODO: ambient送信に必要な情報も読み込んでおく


void WifiTask::setup(void) {
    this->resource.config.operate([&](GlobalConfig<FixedConfig::ConfigAllocateSize>& config){
        auto fps = GlobalConfigDefaultValues::WifiTaskFps;
        config.read(GlobalConfigKeys::WifiTaskFps, fps);
        this->setFps(fps);
        // TODO: ambient送信に必要な情報も読み込んでおく
    });
}

bool WifiTask::invokeNop(const WifiTaskRequest& req, WifiTaskResponse& resp) {
    // do nothing
    return true;
}

bool WifiTask::invokeGetWifiStatus(const WifiTaskRequest& req, WifiTaskResponse& resp) {
    // set status
    resp.data.wifiStatus.status = wifi.status();
    // set ip addr
    const auto ip = this->wifi.localIP();
    resp.data.wifiStatus.ipAddr[0] = ip[0];
    resp.data.wifiStatus.ipAddr[1] = ip[1];
    resp.data.wifiStatus.ipAddr[2] = ip[2];
    resp.data.wifiStatus.ipAddr[3] = ip[3];
    // always success
    return true;
}

bool WifiTask::invokeSend(const WifiTaskRequest& req, WifiTaskResponse& resp) {
    // TODO: #27 Ambient送信を行う
    return false;
}

bool WifiTask::loop(void) {
    WifiTaskRequest req;
    WifiTaskResponse resp;
    // 応答Queueに空きができるまでは処理しても仕方ないので待つ
    if (this->sendQueue.emptyNum() == 0) {
        return false; // no abort
    }
    // 受信できるまでは永久に待機
    const bool isSuccess = this->recvQueue.receive(&req, true); 
    if (!isSuccess) { 
        return false; // no abort
    }
    // いい感じに処理
    resp.id = req.id;
    switch (req.id) {
        case WifiTaskRequestId::Nop:
            resp.isSuccess = this->invokeNop(req, resp);
            break;
        case WifiTaskRequestId::GetWifiStatus:
            resp.isSuccess = this->invokeGetWifiStatus(req, resp);
            break;
        case WifiTaskRequestId::SendSensorData:
            resp.isSuccess = this->invokeSend(req, resp);
            break;
        default:
            resp.isSuccess = false;
            break;
    }
    // 応答
    this->sendQueue.send(&resp);

    return false; // no abort
}
ew file mode 100644
ndex 0000000..5ff8c5d
++ b/src/WifiTask.h

fc89aeb5492bd82e77549649e30db1a709912b7b

FOTAを実装する

これは必須ではない。Actions最新の結果をSelf Updateできたら面白そうってだけ

Parserの実装ができるまでは...

Parserの実装ができるまでは...

return false; // TODO: Parserの実装ができるまでは...


void GlobalConfig::clear(void) {
    this->onfigVolatile = this->configNonVolatile;
}

bool GlobalConfig::load(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで読み込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_READ);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を読み出してParseする
        // TODO: versionが異なる場合のMigrationも必要

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    // return result;
    return false; // TODO: Parserの実装ができるまでは...
}

bool GlobalConfig::save(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで書き込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_WRITE);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を不揮発化する
        f.println("TODO: generate configure json file!");

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    return result;
}
ndex 4b17914..d1b8f9c 100644
++ b/src/GlobalConfig.h

b5d21e5fe92e0bf33010b07c26dc193aadeb039c

Timerを実装する

xTimerCreate, xTimerStartするだけのクラスを用意して、周期処理が必要なタスクに渡す

#49 config.getReadPtr<char>(GlobalConfigKeys::ApSs...

#49 config.getReadPtr(GlobalConfigKeys::ApSsid);

const char* ssid = "ssid"; //TODO: #49 config.getReadPtr<char>(GlobalConfigKeys::ApSsid);

        }
    }
}

static void setupWifi(void) {
    // 前回動いていた場合、一旦切断
    lcd.printf("[INFO] reset wifi module.\n");
    wifi.mode(WIFI_STA);
    wifi.disconnect();
    delay(FixedConfig::WaitForPorMs);

    // WiFi使わなければSkip
    bool useWifi = GlobalConfigDefaultValues::UseWiFi;
    config.read(GlobalConfigKeys::UseWiFi, useWifi);
    if (!useWifi) {
        lcd.printf("[INFO] skip AP Connection.\n");
        return;
    }

    // Wifi開始
    const char* ssid   = "ssid"; //TODO: #49 config.getReadPtr<char>(GlobalConfigKeys::ApSsid);
    const char* pass   = "pass"; //TODO: #49 config.getReadPtr<char>(GlobalConfigKeys::ApPassWord);
    uint32_t timeoutMs = GlobalConfigDefaultValues::ApTimeoutMs;
    config.read(GlobalConfigKeys::ApTimeoutMs, timeoutMs);

    lcd.printf("[INFO] connect to %s.\n", ssid);
    wifi.begin(ssid, pass);

    const uint32_t startMillis = millis();
    while (wifi.status() != WL_CONNECTED) {
        lcd.print(".");
        delay(FixedConfig::WaitForPorMs);
        // timeout
        const uint32_t elapsedMs = millis() - startMillis;
        if (elapsedMs > timeoutMs) {
            lcd.printf("\n[ERROR] timeout.\n");
            break;
        }
    }

    const bool isConnected = (wifi.status() == WL_CONNECTED);
    if (!isConnected) {
        lcd.printf("[ERROR] Error.\n");
        return;
    }

    lcd.printf("\n[INFO] done.");
    lcd.println(wifi.localIP());
}

static void setupRtos(void) {
    lcd.printf("[INFO] setup RTOS config\n");
    vSetErrorLed(FixedConfig::ErrorLedPinNum, FixedConfig::ErrorLedState);

51db967c09e5fe67c7b4cbbddbaff2a0e7fb1599

configVolatileの内容を読み出してParseする

configVolatileの内容を読み出してParseする

// TODO: configVolatileの内容を読み出してParseする

    return configVolatile;
}

void GlobalConfig::clear(void) {
    this->onfigVolatile = this->configNonVolatile;
}

bool GlobalConfig::load(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで読み込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_READ);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を読み出してParseする
        // TODO: versionが異なる場合のMigrationも必要

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    // return result;
    return false; // TODO: Parserの実装ができるまでは...
}

bool GlobalConfig::save(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで書き込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_WRITE);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を不揮発化する
        f.println("TODO: generate configure json file!");

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    return result;
}
ndex 4b17914..d1b8f9c 100644
++ b/src/GlobalConfig.h

412f56a78319dc9c0a97ee099414c7b08737f756

Error表示を出すか検討

Error表示を出すか検討

DeserializationError desError; // TODO: Error表示を出すか検討

    /* load configure from SD card */
    lcd.println("[INFO] load config from SD card\n");

    DeserializationError desError; // TODO: Error表示を出すか検討
    if (config.load(nullptr, desError)) {
        lcd.println("[INFO] done.\n");
    } else {
        lcd.println("[ERROR] failed, init default value.\n");
        // initialize and save to SD card
        config.init(false);

        lcd.println("[INFO] save config to SD card\n");
        if (config.save(nullptr)) {

6fb4bb030af43ee1ef1b304446849e79cbc3f853

generate configure json file!");

generate configure json file!");

f.println("TODO: generate configure json file!");

    this->onfigVolatile = this->configNonVolatile;
}

bool GlobalConfig::load(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで読み込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_READ);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を読み出してParseする
        // TODO: versionが異なる場合のMigrationも必要

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    // return result;
    return false; // TODO: Parserの実装ができるまでは...
}

bool GlobalConfig::save(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで書き込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_WRITE);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を不揮発化する
        f.println("TODO: generate configure json file!");

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    return result;
}
ndex 4b17914..d1b8f9c 100644
++ b/src/GlobalConfig.h

b6f52e75efc99dc7044bf804377aa54ea887c35a

configVolatileの内容を不揮発化する

configVolatileの内容を不揮発化する

// TODO: configVolatileの内容を不揮発化する

void GlobalConfig::clear(void) {
    this->onfigVolatile = this->configNonVolatile;
}

bool GlobalConfig::load(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで読み込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_READ);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を読み出してParseする
        // TODO: versionが異なる場合のMigrationも必要

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    // return result;
    return false; // TODO: Parserの実装ができるまでは...
}

bool GlobalConfig::save(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで書き込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_WRITE);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を不揮発化する
        f.println("TODO: generate configure json file!");

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    return result;
}
ndex 4b17914..d1b8f9c 100644
++ b/src/GlobalConfig.h

fe5db6372c43bb518bb8eb2cb4a414d817858f77

versionが異なる場合のMigrationも必要

versionが異なる場合のMigrationも必要

// TODO: versionが異なる場合のMigrationも必要

}

void GlobalConfig::clear(void) {
    this->onfigVolatile = this->configNonVolatile;
}

bool GlobalConfig::load(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで読み込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_READ);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を読み出してParseする
        // TODO: versionが異なる場合のMigrationも必要

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    // return result;
    return false; // TODO: Parserの実装ができるまでは...
}

bool GlobalConfig::save(const char* filePath) {
    const char* path = (filePath == nullptr) ? this->baseFilePath : filePath;
    // baseFilePath == nullptrの対策
    if (path == nullptr) {
        return false;
    }

    // take mutex & crititcal sectionで書き込みは行う
    bool result = false;
    this->sharedSd.operateCritial([&](SDFS& sd) {
        File f = sd.open(path, FILE_WRITE);
        // Fileが開けなければ失敗
        if (!f) return;
        
        // TODO: configVolatileの内容を不揮発化する
        f.println("TODO: generate configure json file!");

        // 成功していればconfigNonVolatileの内容を上書き
        this->configNonVolatile = this->configVolatile;
        // 成功
        result = true;
    });

    return result;
}
ndex 4b17914..d1b8f9c 100644
++ b/src/GlobalConfig.h

9b67f18915a410054eef63868828e680bce29dbd

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.