diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 6249558..d828549 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -5,7 +5,7 @@ "includePath": [ "${workspaceFolder}/**", "${workspaceFolder}/src", - "${workspaceFolder}/iflytoplinuxsdk/src/", + "${workspaceFolder}/iflytoplinuxsdk/src/**" ], "compilerPath": "/usr/bin/g++", "cStandard": "gnu11", diff --git a/.vscode/settings.json b/.vscode/settings.json index be51cd0..9a2eed7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -64,6 +64,7 @@ "typeindex": "cpp", "typeinfo": "cpp", "valarray": "cpp", - "variant": "cpp" + "variant": "cpp", + "codecvt": "cpp" } } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f9dbb86..7ffb194 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,5 +78,8 @@ zadd_executable( ./app/ SRC test_src/testsqldb.cpp # + INCLUDE_DIRECTORIES + iflytoplinuxsdk/src/iflytop/core/spdlog/include/ + iflytoplinuxsdk/src/ LINK_LIBRARIES sqlite3) diff --git a/README.md b/README.md index dfcd45f..323262c 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,32 @@ SensorDataDB DisinfectionRecordDB DeviceConfigDB + +2. 完善功能管理 + +1. 磁盘空间管理 +2. 日志过期自动删除 +3. DB过期记录自动删除 + ---------------------------------- ``` + + + ``` sudo apt-get install sqlite3 libsqlite3-dev sudo apt-get install sqlite3:arm64 libsqlite3-dev:arm64 + +sqlite可视化 +sudo apt-get install sqlitebrowser ``` ``` https://www.sqlite.org/docs.html +``` + +``` + ``` \ No newline at end of file diff --git a/iflytoplinuxsdk b/iflytoplinuxsdk index 3671588..e248cbe 160000 --- a/iflytoplinuxsdk +++ b/iflytoplinuxsdk @@ -1 +1 @@ -Subproject commit 3671588f43030f703af6e2f39bcc3f578f45f6e9 +Subproject commit e248cbe39e9a9c4dc448c5e354b1f5ea352275cb diff --git a/src/db/db_service.cpp b/src/db/db_service.cpp new file mode 100644 index 0000000..ae167b1 --- /dev/null +++ b/src/db/db_service.cpp @@ -0,0 +1,369 @@ +#include + +// +#include + +#include "db_service.hpp" + +// +#include "iflytop/components/sqlite_orm/sqlite_orm.hpp" + +using namespace std; +using namespace iflytop; +using namespace iflytop::db; +using namespace sqlite_orm; +using namespace nlohmann; + +// 数据库工具使用手册 +// auto notJohn = storage.get_all(where(c(&User::firstName) != "John")); +// 主键必须是int,或者不要主键 + +#define USER_DB_STRUCT \ + USER_DB, /**/ \ + make_table("users", /**/ \ + make_column("uid", &User::uid), /**/ \ + make_column("passwd", &User::passwd), /**/ \ + make_column("permission_level", &User::permission_level), /**/ \ + make_column("visible", &User::visible)) + +#define SETTING_DB_STRUCT \ + make_table("settings", /**/ \ + make_column("id", &Setting::id), /**/ \ + make_column("name", &Setting::name), /**/ \ + make_column("name_ch", &Setting::name_ch), /**/ \ + make_column("val_upper_limit", &Setting::val_upper_limit), /**/ \ + make_column("val_lower_limit", &Setting::val_lower_limit), /**/ \ + make_column("permission_level", &Setting::permission_level), /**/ \ + make_column("val", &Setting::val)) + +// int id; +// string disinfection_id; +// string date; +// int heating_strip; +// int air_compressor; +// int sprinkler_pump; +// int disinfectant_volume; +// int h2o2_1; +// int temp_1; +// int humid_1; +// int saturation_1; +// int h2o2_2; +// int temp_2; +// int humid_2; +// int saturation_2; +// int h2o2_3; +// int temp_3; +// int humid_3; +// int saturation_3; + +#define DISINFECTION_RECORD_DB_STRUCT \ + DISINFECTION_RECORD_DB, \ + make_table("disinfection_records", /**/ \ + make_column("id", &DisinfectionRecord::id), /**/ \ + make_column("uuid", &DisinfectionRecord::uuid), /**/ \ + make_column("uid", &DisinfectionRecord::uid), /**/ \ + make_column("date", &DisinfectionRecord::date), /**/ \ + make_column("loglevel", &DisinfectionRecord::loglevel), /**/ \ + make_column("duration", &DisinfectionRecord::duration)), /**/ \ + make_table("sensor_records", /**/ \ + make_column("id", &SensorRecord::id), /**/ \ + make_column("disinfection_id", &SensorRecord::disinfection_id), /**/ \ + make_column("date", &SensorRecord::date), /**/ \ + make_column("heating_strip", &SensorRecord::heating_strip), /**/ \ + make_column("air_compressor", &SensorRecord::air_compressor), /**/ \ + make_column("sprinkler_pump", &SensorRecord::sprinkler_pump), /**/ \ + make_column("disinfectant_volume", &SensorRecord::disinfectant_volume), /**/ \ + make_column("h2o2_1", &SensorRecord::h2o2_1), /**/ \ + make_column("temp_1", &SensorRecord::temp_1), /**/ \ + make_column("humid_1", &SensorRecord::humid_1), /**/ \ + make_column("saturation_1", &SensorRecord::saturation_1), /**/ \ + make_column("h2o2_2", &SensorRecord::h2o2_2), /**/ \ + make_column("temp_2", &SensorRecord::temp_2), /**/ \ + make_column("humid_2", &SensorRecord::humid_2), /**/ \ + make_column("saturation_2", &SensorRecord::saturation_2), /**/ \ + make_column("h2o2_3", &SensorRecord::h2o2_3), /**/ \ + make_column("temp_3", &SensorRecord::temp_3), /**/ \ + make_column("humid_3", &SensorRecord::humid_3), /**/ \ + make_column("saturation_3", &SensorRecord::saturation_3)) + +DBService::DBService(/* args */) {} + +void DBService::initialize() { + /** + * @brief 初始化用户表 + */ + + // + init_usr_db(); + init_setting_db(); +} + +void DBService::init_usr_db() { + bool suc = false; + do { + try { + logger->info("init user db"); + auto storage = make_storage(USER_DB_STRUCT); + storage.sync_schema(); + auto root = storage.get_all(where(c(&User::uid) == "root")); + if (root.size() == 0) { + storage.insert(User{"root", "iflytop.com#9973", 0, 0}); // 超级用户 + } + auto vendor = storage.get_all(where(c(&User::uid) == "vendor")); + if (vendor.size() == 0) { + storage.insert({"vendor", "9973", 1, true}); // 厂商 + } + + auto admin = storage.get_all(where(c(&User::uid) == "admin")); + if (admin.size() == 0) { + storage.insert({"admin", "9973", 2, true}); // 管理员 + } + + auto user = storage.get_all(where(c(&User::uid) == "user")); + if (user.size() == 0) { + storage.insert({"user", "0000", 3, true}); // 普通用户 + } + suc = true; + } catch (const std::exception& e) { + logger->error("init user db failed: {}", e.what()); + system("rm -rf user.db"); + sleep(1); + } + } while (!suc); +} +void DBService::init_setting_db() { + bool suc = false; +#if 0 +id setting_name setting_name_ch val_upper_limit val_lower_limit permission_level val +0 stoped_gs 消毒停止过氧化氢溶度 0 2000 1 1000 +1 continued_gs 消毒继续过氧化氢溶度 0 2000 1 800 +2 stoped_satur 消毒停止过氧化氢相对饱和度 0 100 1 80 +3 continued_satur 消毒继续过氧化氢相对饱和度 0 100 1 60 +4 max_humidity 允许消毒最大湿度 0 100 1 90 +5 drainage_pump_speed 排液蠕动泵转速 0 2000 2 500 +6 injection_pump_speed 喷射蠕动泵转速 0 2000 2 500 +#endif + + do { + try { + logger->info("init setting db"); + auto storage = make_storage(SETTING_DB, SETTING_DB_STRUCT); + storage.sync_schema(); + + auto s0 = storage.get_all(where(c(&Setting::id) == 0)); + if (s0.size() == 0) storage.insert(Setting{0, "stoped_gs", "消毒停止过氧化氢溶度", 0, 2000, 1, 1000}); + auto s1 = storage.get_all(where(c(&Setting::id) == 1)); + if (s1.size() == 0) storage.insert(Setting{1, "continued_gs", "消毒继续过氧化氢溶度", 0, 2000, 1, 800}); + auto s2 = storage.get_all(where(c(&Setting::id) == 2)); + if (s2.size() == 0) storage.insert(Setting{2, "stoped_satur", "消毒停止过氧化氢相对饱和度", 0, 100, 1, 80}); + auto s3 = storage.get_all(where(c(&Setting::id) == 3)); + if (s3.size() == 0) storage.insert(Setting{3, "continued_satur", "消毒继续过氧化氢相对饱和度", 0, 100, 1, 60}); + auto s4 = storage.get_all(where(c(&Setting::id) == 4)); + if (s4.size() == 0) storage.insert(Setting{4, "max_humidity", "允许消毒最大湿度", 0, 100, 1, 90}); + auto s5 = storage.get_all(where(c(&Setting::id) == 5)); + if (s5.size() == 0) storage.insert(Setting{5, "drainage_pump_speed", "排液蠕动泵转速", 0, 2000, 2, 500}); + auto s6 = storage.get_all(where(c(&Setting::id) == 6)); + if (s6.size() == 0) storage.insert(Setting{6, "injection_pump_speed", "喷射蠕动泵转速", 0, 2000, 2, 500}); + + suc = true; + } catch (const std::exception& e) { + logger->error("init setting db failed: {}", e.what()); + system("rm -rf setting.db"); + sleep(1); + } + } while (!suc); +} + +void DBService::init_disinfection_record_db() { + bool suc = false; + do { + try { + logger->info("init disinfection record db"); + auto storage = make_storage(DISINFECTION_RECORD_DB_STRUCT); + storage.sync_schema(); + suc = true; + } catch (const std::exception& e) { + logger->error("init disinfection record db failed: {}", e.what()); + system("rm -rf disinfection_record.db"); + sleep(1); + } + } while (!suc); +} + +list> DBService::getAllUser() { + list> users; + auto usertable = make_storage(USER_DB_STRUCT); + usertable.sync_schema(); + auto all = usertable.get_all(); + for (auto& u : all) { + users.push_back(make_shared(u)); + } + return users; +} +json DBService::getAllUserJson() { + json j_users; + auto usertable = make_storage(USER_DB_STRUCT); + usertable.sync_schema(); + auto all = usertable.get_all(); + for (auto& u : all) { + json j_user; + j_user["uid"] = u.uid; + j_user["passwd"] = u.passwd; + j_user["permission_level"] = u.permission_level; + j_user["visible"] = u.visible; + j_users.push_back(j_user); + } + return j_users; +} + +shared_ptr DBService::getUser(string uid) { + auto usertable = make_storage(USER_DB_STRUCT); + usertable.sync_schema(); + auto user = usertable.get_all(where(c(&User::uid) == uid)); + if (user.size() == 0) { + return nullptr; + } + return make_shared(user[0]); +} + +list> DBService::getAllSetting() { + list> settings; + auto settingtable = make_storage(SETTING_DB, SETTING_DB_STRUCT); + settingtable.sync_schema(); + auto all = settingtable.get_all(); + for (auto& s : all) { + settings.push_back(make_shared(s)); + } + return settings; +} +json DBService::getAllSettingJson() { + json j_settings; + auto settingtable = make_storage(SETTING_DB, SETTING_DB_STRUCT); + settingtable.sync_schema(); + auto all = settingtable.get_all(); + for (auto& s : all) { + json j_setting; + j_setting["id"] = s.id; + j_setting["name"] = s.name; + j_setting["name_ch"] = s.name_ch; + j_setting["val"] = s.val; + j_setting["val_lower_limit"] = s.val_lower_limit; + j_setting["val_upper_limit"] = s.val_upper_limit; + j_setting["permission_level"] = s.permission_level; + j_setting["val"] = s.val; + j_settings.push_back(j_setting); + } + return j_settings; +} + +bool DBService::setSettingVal(int id, int val) { + auto settingtable = make_storage(SETTING_DB, SETTING_DB_STRUCT); + settingtable.sync_schema(); + auto setting = settingtable.get_all(where(c(&Setting::id) == id)); + if (setting.size() == 0) { + return false; + } + if (setting[0].val < setting[0].val_lower_limit || setting[0].val > setting[0].val_upper_limit) { + return false; + } + setting[0].val = val; + settingtable.update(setting[0]); + return true; +} +bool DBService::setSettingVal(string setting_name, int val) { + auto settingtable = make_storage(SETTING_DB, SETTING_DB_STRUCT); + settingtable.sync_schema(); + auto setting = settingtable.get_all(where(c(&Setting::name) == setting_name)); + if (setting.size() == 0) { + logger->error("set setting val failed: {} not found", setting_name); + return false; + } + if (setting[0].val < setting[0].val_lower_limit || setting[0].val > setting[0].val_upper_limit) { + logger->error("set setting val failed: {} out of range", setting_name); + return false; + } + setting[0].val = val; + settingtable.update(setting[0]); + return true; +} + +json DBService::getAllRecords(string disinfection_id) { + json j_records; + auto recordtable = make_storage(DISINFECTION_RECORD_DB_STRUCT); + + // int id; + // string disinfection_id; + // string date; + // int heating_strip; + // int air_compressor; + // int sprinkler_pump; + // int disinfectant_volume; + // int h2o2_1; + // int temp_1; + // int humid_1; + // int saturation_1; + // int h2o2_2; + // int temp_2; + // int humid_2; + // int saturation_2; + // int h2o2_3; + // int temp_3; + // int humid_3; + // int saturation_3; + + recordtable.sync_schema(); + auto all = recordtable.get_all(where(c(&SensorRecord::disinfection_id) == disinfection_id)); + for (auto& r : all) { + json j_record; + j_record["id"] = r.id; + j_record["disinfection_id"] = r.disinfection_id; + j_record["date"] = r.date; + j_record["heating_strip"] = r.heating_strip; + j_record["air_compressor"] = r.air_compressor; + j_record["sprinkler_pump"] = r.sprinkler_pump; + j_record["disinfectant_volume"] = r.disinfectant_volume; + j_record["h2o2_1"] = r.h2o2_1; + j_record["temp_1"] = r.temp_1; + j_record["humid_1"] = r.humid_1; + j_record["saturation_1"] = r.saturation_1; + j_record["h2o2_2"] = r.h2o2_2; + j_record["temp_2"] = r.temp_2; + j_record["humid_2"] = r.humid_2; + j_record["saturation_2"] = r.saturation_2; + j_record["h2o2_3"] = r.h2o2_3; + j_record["temp_3"] = r.temp_3; + j_record["humid_3"] = r.humid_3; + j_record["saturation_3"] = r.saturation_3; + j_records.push_back(j_record); + } + return j_records; +} +void DBService::insertSensorRecord(shared_ptr record) { + if (!record) { + logger->error("insert sensor record failed: record is null"); + return; + } + auto recordtable = make_storage(DISINFECTION_RECORD_DB_STRUCT); + recordtable.sync_schema(); + recordtable.insert(*record); +} +void DBService::insertDisinfectionRecord(shared_ptr record) { + if (!record) { + logger->error("insert disinfection record failed: record is null"); + return; + } + auto recordtable = make_storage(DISINFECTION_RECORD_DB_STRUCT); + recordtable.sync_schema(); + recordtable.insert(*record); +} +void DBService::setDisinfectionRecordDuration(string disinfection_id, int duration) { + auto recordtable = make_storage(DISINFECTION_RECORD_DB_STRUCT); + recordtable.sync_schema(); + auto record = recordtable.get_all(where(c(&DisinfectionRecord::uuid) == disinfection_id)); + if (record.size() == 0) { + logger->error("set disinfection record duration failed: {} not found", disinfection_id); + return; + } + record[0].duration = duration; + recordtable.update(record[0]); +} \ No newline at end of file diff --git a/src/db/db_service.hpp b/src/db/db_service.hpp new file mode 100644 index 0000000..9ed8a18 --- /dev/null +++ b/src/db/db_service.hpp @@ -0,0 +1,147 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iflytop/core/spdlogfactory/logger.hpp" +#include "iflytop/core/thread/thread.hpp" + +#define USER_DB "user.db" +#define SETTING_DB "setting.db" +#define DISINFECTION_RECORD_DB "disinfection_record.db" +/** + * @brief + * + * USER_DB + * table: user + * id uid passwd permission_level + * + * + * SETTING_DB + * table: setting + * id setting_name setting_name_ch val_upper_limit val_lower_limit permission_level val + * + * DISINFECTION_RECORD_DB + * table: disinfection_record + * id uuid uid date loglevel duration + * + * + * table: sensor_record + * id disinfection_id date heating_strip air_compressor sprinkler_pump disinfectant_volume h2o2_1 temp_1 humid_1 saturation_1 h2o2_2 temp_2 humid_2 + * saturation_2 h2o2_3 temp_3 humid_3 saturation_3 + * + */ + +namespace iflytop { +using namespace std; +using namespace std; +using namespace core; +using namespace nlohmann; +namespace db { + +struct User { + public: + string uid; + string passwd; + int permission_level; + int visible; +}; + +struct Setting { + public: + int id; + string name; + string name_ch; + int val_upper_limit; + int val_lower_limit; + int permission_level; + int val; +}; + +struct DisinfectionRecord { + public: + int id; + string uuid; + string uid; + string date; + string loglevel; + int duration; +}; + +struct SensorRecord { + public: + int id; + string disinfection_id; + string date; + int heating_strip; + int air_compressor; + int sprinkler_pump; + int disinfectant_volume; + int h2o2_1; + int temp_1; + int humid_1; + int saturation_1; + int h2o2_2; + int temp_2; + int humid_2; + int saturation_2; + int h2o2_3; + int temp_3; + int humid_3; + int saturation_3; +}; +} // namespace db +using namespace db; +class DBService : public enable_shared_from_this { + ENABLE_LOGGER(DBService); + + public: + DBService(); + void initialize(); + + public: + /******************************************************************************* + * USER_DB * + *******************************************************************************/ + list> getAllUser(); + json getAllUserJson(); + shared_ptr getUser(string uid); + vector getUserNames(); + + public: + /******************************************************************************* + * SETTING_DB * + *******************************************************************************/ + list> getAllSetting(); + json getAllSettingJson(); + bool setSettingVal(int id, int val); + bool setSettingVal(string name, int val); + + public: + /******************************************************************************* + * SensorRecord_operation * + *******************************************************************************/ + + json getAllRecords(string disinfection_id); + void insertSensorRecord(shared_ptr record); + void insertDisinfectionRecord(shared_ptr record); + void setDisinfectionRecordDuration(string disinfection_id, int duration); + + private: + void init_usr_db(); + void init_setting_db(); + void init_disinfection_record_db(); +}; + +}; // namespace iflytop diff --git a/src/db/sqldb_service.hpp b/src/db/sqldb_service.hpp deleted file mode 100644 index 13f07cc..0000000 --- a/src/db/sqldb_service.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#include -#include - -// int main(int argc, char* argv[]) -// { -// sqlite3 *db; -// char *zErrMsg = 0; -// int rc; - -// rc = sqlite3_open("test.db", &db); - -// if( rc ){ -// fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); -// exit(0); -// }else{ -// fprintf(stderr, "Opened database successfully\n"); -// } -// sqlite3_close(db); -// } \ No newline at end of file diff --git a/test_src/testsqldb.cpp b/test_src/testsqldb.cpp index edae4f6..681c79f 100644 --- a/test_src/testsqldb.cpp +++ b/test_src/testsqldb.cpp @@ -2,17 +2,77 @@ #include #include #include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iflytop/components/sqlite_orm/sqlite_orm.hpp" +using namespace sqlite_orm; + +struct User { + int id; + std::string firstName; + int lastName; + std::string birthDate; + std::unique_ptr imageUrl; + int typeId; +}; + +struct UserType { + int id; + std::string name; +}; + int main(int argc, char const *argv[]) { sqlite3 *db; char *zErrMsg = 0; int rc; - rc = sqlite3_open("test.db", &db); - if (rc) { - fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); - exit(0); - } else { - fprintf(stderr, "Opened database successfully\n"); + // rc = sqlite3_open("test.db", &db); + // if (rc) { + // fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); + // exit(0); + // } else { + // fprintf(stderr, "Opened database successfully\n"); + // } + // sqlite3_close(db); + { + auto storage = make_storage("./db.sqlite", // + make_table("users", // + make_column("id", &User::id), // + make_column("first_name", &User::firstName), // + make_column("last_name", &User::lastName), // + make_column("birth_date", &User::birthDate), // + make_column("image_url", &User::imageUrl), // + make_column("type_id", &User::typeId)), // + make_table("user_types", // + make_column("id", &UserType::id, primary_key().autoincrement()), // + make_column("name", &UserType::name, default_value("name_placeholder")))); + // storage.dump(); + // storage.sync_schema( + storage.sync_schema(); + + storage.filename(); + std::cout << "storage.filename():" << storage.filename() << std::endl; + storage.sync_schema(); + + storage.insert(User{1, "Nicola", 2, "1856", nullptr, 0}); + storage.insert(User{-1, "Linus", 2, "1969", nullptr, 0}); + storage.insert(User{-1, "Mark", 3, "1984", nullptr, 0}); + + auto allEmployees = storage.get_all(); + for (auto &employee : allEmployees) { + std::cout << employee.id << ' ' << employee.firstName << ' ' << employee.lastName << std::endl; + } + // storage.sync_schema(); } - sqlite3_close(db); + return 0; }