diff --git a/common/global.hpp b/common/global.hpp index 0cf2043..0defe3f 100644 --- a/common/global.hpp +++ b/common/global.hpp @@ -18,7 +18,7 @@ enum enumZigBeeTransmitStatus { //#define NR5G_MODULE -//#define Q4G_MODULE +#define Q4G_MODULE //#define WIFI_MODULE //#define NR5G_MEIGE diff --git a/common/parameter_defination.hpp b/common/parameter_defination.hpp index 5e3c660..7ab4960 100644 --- a/common/parameter_defination.hpp +++ b/common/parameter_defination.hpp @@ -2,6 +2,7 @@ #define PARAMETER_DEFINATION_HPP_ #include +#include "scheduler/wave_feature_set.hpp" struct Param_01 { int mMode; // 0:登陆 1:更改密码 @@ -343,5 +344,18 @@ struct Param_62 { int mPackageFlag; Param_62() : MeasurementID(""),timeStart(""),timeEnd(""),mPackageFlag(0){}; }; - +struct Param_63 { + + int mMode; + bool partial; + std::vector cfg; + Param_63() : mMode(0),partial(false){}; +}; +struct Param_64 { + + int mMode; + bool partial; + std::vector cfg; + Param_64() : mMode(0),partial(false){}; +}; #endif // PARAMETER_DEFINATION_HPP_ diff --git a/jsonparse/communication_cmd.hpp b/jsonparse/communication_cmd.hpp index 7855c0f..c8a662c 100644 --- a/jsonparse/communication_cmd.hpp +++ b/jsonparse/communication_cmd.hpp @@ -71,6 +71,8 @@ public: std::string JsonCmd_Cgi_60(Param_60 ¶m); std::string JsonCmd_Cgi_61(Param_61 ¶m); std::string JsonCmd_Cgi_62(Param_62 ¶m); + std::string JsonCmd_Cgi_63(Param_63 ¶m); + std::string JsonCmd_Cgi_64(Param_64 ¶m); std::string JsonCmd_Cgi_default(); private: diff --git a/jsonparse/web_cmd_parse3.cpp b/jsonparse/web_cmd_parse3.cpp index 6e0cd31..9869a81 100644 --- a/jsonparse/web_cmd_parse3.cpp +++ b/jsonparse/web_cmd_parse3.cpp @@ -955,3 +955,96 @@ std::string JsonData::JsonCmd_Cgi_62(Param_62 ¶m){ } return show_value_.write(jsonVal); } +std::string JsonData::JsonCmd_Cgi_63(Param_63 ¶m) +{ + Json::Value jsonVal; + jsonVal.clear(); + Json::Value jsBody; + jsonVal[JSON_FIELD_CMD] = "63"; + jsonVal["success"] = true; + jsonVal["message"] = ""; + if (param.mMode == 0) + { + std::vector cfg; + wave_feature_set_inst::instance().GetAllFeatureCfg(cfg); + if (cfg.size() > 0) + { + for (size_t i = 0; i < cfg.size(); i++) + { + Json::Value xyz_status; + xyz_status.append(cfg[i].x); + xyz_status.append(cfg[i].y); + xyz_status.append(cfg[i].z); + if (cfg[i].short_addr == 0) + { + jsBody["global"] = xyz_status; + }else{ + char buf[8] = {0}; + snprintf(buf, 8, "%02x%02x", UINT16_HIGH(cfg[i].short_addr), UINT16_LOW(cfg[i].short_addr)); + jsBody[buf] = xyz_status; + } + } + }else{ + jsonVal["success"] = false; + jsonVal["message"] = ""; + } + }else if(param.mMode == 1){ + if (param.partial) + { + zlog_info(zct, "63 short_addr = %d,x = %d,y = %d,z = %d", param.cfg[0].short_addr, param.cfg[0].x, param.cfg[0].y, param.cfg[0].z); + wave_feature_set_inst::instance().SetFeatureCfg(param.cfg[0].short_addr, param.cfg[0].x, param.cfg[0].y, param.cfg[0].z); + }else{ + wave_feature_set_inst::instance().SetAllFeatureCfg(param.cfg); + } + + } + jsonVal["cmdBody"] = jsBody; + return show_value_.write(jsonVal); +} +std::string JsonData::JsonCmd_Cgi_64(Param_64 ¶m) +{ + Json::Value jsonVal; + jsonVal.clear(); + Json::Value jsBody; + jsonVal[JSON_FIELD_CMD] = "64"; + jsonVal["success"] = true; + jsonVal["message"] = ""; + if (param.mMode == 0) + { + std::vector cfg; + wave_feature_set_inst::instance().GetAllWaveCfg(cfg); + zlog_info(zct,"cfg size = %d",cfg.size()); + if (cfg.size() > 0) + { + for (size_t i = 0; i < cfg.size(); i++) + { + Json::Value xyz_status; + xyz_status.append(cfg[i].x); + xyz_status.append(cfg[i].y); + xyz_status.append(cfg[i].z); + if (cfg[i].short_addr == 0) + { + jsBody["global"] = xyz_status; + }else{ + char buf[8] = {0}; + snprintf(buf, 8, "%02x%02x", UINT16_HIGH(cfg[i].short_addr), UINT16_LOW(cfg[i].short_addr)); + jsBody[buf] = xyz_status; + } + } + }else{ + jsonVal["success"] = false; + jsonVal["message"] = ""; + } + }else if(param.mMode == 1){ + if (param.partial) + { + zlog_info(zct, "64 short_addr = %d,x = %d,y = %d,z = %d", param.cfg[0].short_addr, param.cfg[0].x, param.cfg[0].y, param.cfg[0].z); + wave_feature_set_inst::instance().SetWaveCfg(param.cfg[0].short_addr, param.cfg[0].x, param.cfg[0].y, param.cfg[0].z); + }else{ + wave_feature_set_inst::instance().SetAllWaveCfg(param.cfg); + } + + } + jsonVal["cmdBody"] = jsBody; + return show_value_.write(jsonVal); +} \ No newline at end of file diff --git a/localserver/local_server.hpp b/localserver/local_server.hpp index 807bf30..82d19f4 100644 --- a/localserver/local_server.hpp +++ b/localserver/local_server.hpp @@ -51,7 +51,9 @@ enum WebCommand { kLostRecords = 59, kTransducerUpgrade = 60, kWaveRecords = 61, - kWaveReceive = 62 + kWaveReceive = 62, + kWaveSend = 63, + kFeatureSend = 64 }; class LocalServer { diff --git a/localserver/web_cmd.cpp b/localserver/web_cmd.cpp index 2281c90..fad305f 100644 --- a/localserver/web_cmd.cpp +++ b/localserver/web_cmd.cpp @@ -438,6 +438,78 @@ std::string LocalServer::HandleCgi_cmd(std::string &pData) { std::string data = jd.JsonCmd_Cgi_62(param); return data; }break; + case kWaveSend:{ + JsonData jd; + Param_63 param; + param.mMode = recvBody["sub_cmd"].asInt(); + param.partial = recvBody["partial"].asBool(); + if (param.mMode == 1) + { + for (const auto &key : recvBody.getMemberNames()) + { + if (key != "sub_cmd" && key != "partial") + { + FeatureEntryUploadCfg tmpCfg; + char *end_ptr; + if (key == "global") + { + tmpCfg.short_addr = 0; + }else{ + tmpCfg.short_addr = strtol(key.c_str(), &end_ptr, 16); + } + Json::Value xyz_status = recvBody[key]; + for (size_t i = 0; i < xyz_status.size(); ++i) { + if (i == 0) { + tmpCfg.x = xyz_status[i].asInt(); + } else if (i == 1) { + tmpCfg.y = xyz_status[i].asInt(); + } else if (i == 2) { + tmpCfg.z = xyz_status[i].asInt(); + } + } + param.cfg.push_back(tmpCfg); + } + } + } + std::string data = jd.JsonCmd_Cgi_63(param); + return data; + }break; + case kFeatureSend:{ + JsonData jd; + Param_64 param; + param.mMode = recvBody["sub_cmd"].asInt(); + param.partial = recvBody["partial"].asBool(); + if (param.mMode == 1) + { + for (const auto &key : recvBody.getMemberNames()) + { + if (key != "sub_cmd" && key != "partial") + { + FeatureEntryUploadCfg tmpCfg; + char *end_ptr; + if (key == "global") + { + tmpCfg.short_addr = 0; + }else{ + tmpCfg.short_addr = strtol(key.c_str(), &end_ptr, 16); + } + Json::Value xyz_status = recvBody[key]; + for (size_t i = 0; i < xyz_status.size(); ++i) { + if (i == 0) { + tmpCfg.x = xyz_status[i].asInt(); + } else if (i == 1) { + tmpCfg.y = xyz_status[i].asInt(); + } else if (i == 2) { + tmpCfg.z = xyz_status[i].asInt(); + } + } + param.cfg.push_back(tmpCfg); + } + } + } + std::string data = jd.JsonCmd_Cgi_64(param); + return data; + }break; default: JsonData jd; std::string data = jd.JsonCmd_Cgi_default(); diff --git a/scheduler/schedule.cpp b/scheduler/schedule.cpp index 38c98eb..d1fea65 100644 --- a/scheduler/schedule.cpp +++ b/scheduler/schedule.cpp @@ -1,670 +1,694 @@ -#include "schedule.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "short_addr_cfg.hpp" -#include "update_cfg.hpp" - -extern zlog_category_t *zct; -extern zlog_category_t *zbt; - -int SensorScheduler::StartSchedule(int short_addr, int &next_duration) { - int id = 0; - auto iter = short_addr_map_.find(short_addr); - if (iter == short_addr_map_.end()) { - id = GetAvailableId(short_addr); - } else { - id = iter->second; - } - - current_ts_ = GetLocalTs(); - CleanIdleOccupiedSet(current_ts_); - - nth_wave_start_slice_ = (current_ts_ - start_timestamp_) / wave_form_send_interval_; - current_wave_start_ts_ = nth_wave_start_slice_ * wave_form_send_interval_ + start_timestamp_; - seconds_in_current_wave_slice_ = current_ts_ - current_wave_start_ts_; - nth_eigen_value_slice_ = seconds_in_current_wave_slice_ / eigen_value_send_interval_; - seconds_in_current_eigen_slice_ = seconds_in_current_wave_slice_ % eigen_value_send_interval_; - ts_in_eigen_slice_ = false; - if (seconds_in_current_eigen_slice_ < eigen_value_slice_total_seconds_ - 3) { - ts_in_eigen_slice_ = true; - } - - if (ts_in_eigen_slice_) { - nth_eigen_slice_ = (seconds_in_current_eigen_slice_ + 2) / eigen_value_send_duration_; - } else { - nth_wave_slice_ = (seconds_in_current_eigen_slice_ - eigen_value_slice_total_seconds_ + 3) / seconds_per_wave_slice_; - } - zlog_warn(zct, "[%d:%x] ts:%ld, current utc:%s, nth eigen_value slice:%d, seconds in eigen slice:%d, eigen slice:%d", - id, short_addr, current_ts_, GetUTCTime(current_ts_).c_str(), nth_eigen_value_slice_+1, seconds_in_current_eigen_slice_, ts_in_eigen_slice_); - if (ts_in_eigen_slice_) { - if (id == nth_eigen_slice_ + 1) { - // 传感器需要执行上送特征值任务, 如果有配置需要下发的话,下发配置 - if (update_.count(id)) { - // execute config - zlog_warn(zct, "[%d:%x] update config in eigen slice", id, short_addr); - current_request_ = kScheduleConfigSensor; - return kScheduleConfigSensor; - } else { - // 执行上送特征值任务 - zlog_warn(zct, "[%d:%x] send eigen value in eigen slice", id, short_addr); - current_request_ = kScheduleEigenValue; - return kScheduleEigenValue; - } - } else { - zlog_warn(zct, "[%d:%x] Invalid request, revive in %d eigen slice", id, short_addr, nth_eigen_slice_ + 1); - if (id < nth_eigen_slice_ + 1) { - // 不正确的请求 - long available_ts = current_wave_start_ts_ + (nth_eigen_value_slice_ + 1) * eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; - next_duration = available_ts - current_ts_; - zlog_warn(zct, "[%d:%x] wrong time in eigen slice, next feature in next interval send utc time:[%s], duration:%d", id, short_addr, GetUTCTime(available_ts).c_str(), next_duration); - } else { - long available_ts = current_wave_start_ts_ + nth_eigen_value_slice_ * eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; - next_duration = available_ts - current_ts_; - zlog_warn(zct, "[%d:%x] wrong time in eigen slice, next feature in current interval send utc time:[%s], duration:%d", id, short_addr, GetUTCTime(available_ts).c_str(), next_duration); - } - return kScheduleWrongTime; - } - } else { - int nth_wave_slice = nth_eigen_value_slice_ * wave_slice_num_per_eigen_interval_ + nth_wave_slice_ + 1; - auto wave_slice_iter = sensor_id_nth_slice_.find(id); - if (wave_slice_iter == sensor_id_nth_slice_.end()) { - zlog_error(zct, "[%d:%x]invaild id, not find wave slice id, need to check further", id, short_addr); - return kScheduleUnknownSensor; - } - - if (nth_wave_slice == wave_slice_iter->second) { - // 需要发送波形, 需要判断是否有配置,升级需求 - auto upgrade_iter = upgrade_.find(id); - if (upgrade_iter != upgrade_.end()) { - if (upgrade_iter->second.try_times < 10) { - current_request_ = kScheduleUpgrade; - UpdateUpgradeInfo(id); - zlog_warn(zct, "[%d:%x] in wave slice to upgrade now from version:%s to %s, try time:%d", - id, short_addr, upgrade_iter->second.current_sw_version.c_str(), - upgrade_iter->second.upgrade_sw_version.c_str(), upgrade_iter->second.try_times); - return kScheduleUpgrade; - } - } - - if (update_.count(id)) { - // execute config - zlog_warn(zct, "[%d:%x] in wave slice to update config", id, short_addr); - current_request_ = kScheduleConfigSensor; - return kScheduleConfigSensor; - } - zlog_warn(zct, "[%d:%x] it is wave time", id, short_addr); - current_request_ = kScheduleWaveForm; - return kScheduleWaveForm; - } else { - if (slice_sensor_id_[nth_wave_slice-1] == 0) { - zlog_warn(zct, "[%d:%x] in idle time", id, short_addr); - // idle time - auto upgrade_iter = upgrade_.find(id); - if (upgrade_iter != upgrade_.end()) { - if (upgrade_iter->second.try_times < 10) { - current_request_ = kScheduleUpgrade; - UpdateUpgradeInfo(id); - zlog_warn(zct, "[%d:%x] in idle to upgrade now from version:%s to %s, try time:%d", - id, short_addr, upgrade_iter->second.current_sw_version.c_str(), - upgrade_iter->second.upgrade_sw_version.c_str(), upgrade_iter->second.try_times); - return kScheduleUpgrade; - } - } - - if (update_.count(id)) { - // execute config - zlog_warn(zct, "[%d:%x] in idle time to update config", id, short_addr); - current_request_ = kScheduleConfigSensor; - return kScheduleConfigSensor; - } - } - // wrong time to come - long available_ts = current_wave_start_ts_ + (nth_eigen_value_slice_ + 1) * eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; - next_duration = available_ts - current_ts_; - zlog_warn(zct, "[%d:%x] wrong time in wave slice, next feature send utc time:[%s], duration:%d", id, short_addr, GetUTCTime(available_ts).c_str(), next_duration); - return kScheduleWrongTime; - } - } -} - -long SensorScheduler::CalcNextTimestamp(int id, uint16_t short_addr) { - // current_ts_ = GetLocalTs(); - if (ts_in_eigen_slice_) { - int forward_wave_slice_num = nth_eigen_value_slice_ * wave_slice_num_per_eigen_interval_; - auto wave_slice_iter = sensor_id_nth_slice_.find(id); - if (wave_slice_iter == sensor_id_nth_slice_.end()) { - zlog_error(zct, "[Nxt] invaild id:%d, not find wave slice id", id); - long available_ts = current_wave_start_ts_ + eigen_value_send_interval_ + nth_eigen_slice_ * eigen_value_send_duration_; - zlog_error(zct, "[Nxt] [%d] next feature send utc time:[%s]", id, GetUTCTime(available_ts).c_str()); - return available_ts; - } - int wave_slice = wave_slice_iter->second; // 从1开始 - long send_wave_ts = 0; - if (wave_slice > forward_wave_slice_num && - wave_slice <= forward_wave_slice_num + wave_slice_num_per_eigen_interval_) { - // 发送波的时间窗也在本次特征值发送间隔中 - for (int i = forward_wave_slice_num; i <= forward_wave_slice_num + wave_slice_num_per_eigen_interval_; ++i) { - if (wave_slice - 1 == i) { - send_wave_ts = current_wave_start_ts_ + nth_eigen_value_slice_ * eigen_value_send_interval_ + eigen_value_slice_total_seconds_ + (i - forward_wave_slice_num) * seconds_per_wave_slice_; - zlog_warn(zct, "[Nxt] [%d:%x] send wave time:[%s]", id, short_addr, GetUTCTime(send_wave_ts).c_str()); - break; - } - } - } - - long available_ts = 0; - auto upgrade_iter = upgrade_.find(id); - if (upgrade_iter != upgrade_.end()) { - if (upgrade_iter->second.try_times < 10) { - for (int i = 0; i < wave_slice_num_per_eigen_interval_; ++i) { - if (slice_sensor_id_[i+forward_wave_slice_num] == 0) { - // 判断此空闲位置是否被占用 - long current_wave_slice_ts = current_wave_start_ts_ + nth_eigen_value_slice_ * eigen_value_send_interval_ + eigen_value_slice_total_seconds_ + i * seconds_per_wave_slice_; - if (free_slice_ocuppied_.count(current_wave_slice_ts) == 0) { - available_ts = current_wave_slice_ts; - free_slice_ocuppied_.insert(available_ts); - zlog_warn(zct, "[Nxt][%d:%x] %d nth free wave slice will be used to upgrade, utc time:[%s]", id, short_addr, i+forward_wave_slice_num, GetUTCTime(available_ts).c_str()); - break; - } - } - } - } - } - if (send_wave_ts > 0 && available_ts > 0) { - long min_ts = std::min(send_wave_ts, available_ts); - zlog_warn(zct, "[Nxt] [%d:%x] next feature send utc time1:%s", id, short_addr, GetUTCTime(min_ts).c_str()); - return min_ts; - } - if (send_wave_ts + available_ts > 0) { - long max_ts = std::max(send_wave_ts, available_ts); - zlog_warn(zct, "[Nxt] [%d:%x] next feature send utc time2:%s", id, short_addr, GetUTCTime(max_ts).c_str()); - return max_ts; - } - } - - // 如果是在当前波形时间窗中,不管是空闲时间窗,还是发送波形的时间窗,下一个时间窗是特征值 - long available_ts = current_wave_start_ts_ + (nth_eigen_value_slice_ + 1)* eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; - zlog_warn(zct, "[Nxt] [%d:%x] next feature send utc time3:[%s]", id, short_addr, GetUTCTime(available_ts).c_str()); - return available_ts; -} - -int SensorScheduler::GetNextDuration(int short_addr) { - int id = 0; - auto iter = short_addr_map_.find(short_addr); - if (iter == short_addr_map_.end()) { - zlog_error(zct, "cannot find id for short_addr %x", short_addr); - return 0; - } else { - id = iter->second; - } - long current_ts = GetLocalTs(); - long next_ts = CalcNextTimestamp(id, short_addr); - int duration = next_ts - current_ts; - if (duration <= 10 || duration > eigen_value_send_interval_) { - zlog_warn(zct, "[Nxt] exception duration: %d", duration); - duration = eigen_value_send_interval_; - } - zlog_warn(zct, "[Nxt] [%d:%x] next duration is %d", id, short_addr, duration); - return duration; -} - -SensorScheduler::SensorScheduler() { - support_modification_ = true; - std::ifstream schedule_file(SCHEDULE_CONFIG); - if (schedule_file.good()) { - zlog_info(zbt, "exist configuration file"); - Json::Reader reader; - Json::Value root; - if (!reader.parse(schedule_file, root, false)) { - zlog_error(zbt, "invalid format, fail to parse %s", SCHEDULE_CONFIG); - schedule_file.close(); - return; - } - schedule_file.close(); - if (!root.isObject()) { - zlog_error(zbt, "invalid format, not an object: %s", SCHEDULE_CONFIG); - return; - } - start_timestamp_ = std::stol(root["schedule_start_timestamp"].asString()); - start_ts_str_ = root["schedule_start_time"].asString(); - long current_ts = GetLocalTs(); - if (current_ts < start_timestamp_) { - zlog_warn(zbt, "current ts: %ld less than start ts: %ld, go to adjust it", current_ts, start_timestamp_); - start_timestamp_ = current_ts; - start_ts_str_ = GetUTCTime(current_ts); - root["schedule_start_timestamp"] = std::to_string(start_timestamp_); - root["schedule_start_time"] = start_ts_str_; - - Json::StyledStreamWriter streamWriter; - std::ofstream out_file(SCHEDULE_CONFIG); - streamWriter.write(out_file, root); - out_file.close(); - } - - eigen_value_send_interval_ = root["eigen_value_send_interval"].asInt(); - eigen_value_send_duration_ = root["eigen_value_send_duration"].asInt(); - wave_form_send_interval_ = root["wave_form_send_interval"].asInt(); - wave_form_send_duration_ = root["wave_form_send_duration"].asInt(); - max_sensor_num_ = root["max_sensor_num"].asInt(); - available_slice_ = root["available_slice"].asInt(); - free_slice_ = root["free_slice"].asInt(); - support_modification_ = root["support_modification"].asBool(); - - const Json::Value ids = root["id"]; - int sensor_id = 0; - int i = 0; - for (const auto& id : ids) { - sensor_id = id.asInt(); - slice_sensor_id_.push_back(sensor_id); - if (sensor_id != 0) { - sensor_id_nth_slice_[sensor_id] = i+1; - } - ++i; - } - - eigen_value_slice_total_seconds_ = eigen_value_send_duration_ * max_sensor_num_; - int rest_duration = eigen_value_send_interval_ - eigen_value_slice_total_seconds_; - wave_slice_num_per_eigen_interval_ = rest_duration / wave_form_send_duration_; - seconds_per_wave_slice_ = rest_duration / wave_slice_num_per_eigen_interval_; - } else { - zlog_info(zbt, "use default configuration"); - int eigen_value_send_interval = 300; - int wave_form_send_interval = 7200; - int eigen_value_send_duration = 6; - int wave_form_send_duration = 50; - int max_sensor_num = 32; - - // int eigen_value_send_interval = 120; - // int wave_form_send_interval = 240; - // int eigen_value_send_duration = 6; - // int wave_form_send_duration = 40; - // int max_sensor_num = 4; - std::string error_msg; - Config(eigen_value_send_interval, - wave_form_send_interval, - eigen_value_send_duration, - wave_form_send_duration, - max_sensor_num, - error_msg); - } - - short_addr_map_.clear(); - ShortAddrCfg::ReadCfg(short_addr_map_); - - // read upgrade config file: UPGRADE_CONFIG - UpgradeCfg::ReadCfg(upgrade_); - - // read config update file: CONFIG_UPDATE - UpdateCfg::ReadCfg(update_); -} - -long SensorScheduler::GetBaseTimestamp(int short_addr) { - int id = 0; - auto iter = short_addr_map_.find(short_addr); - if (iter == short_addr_map_.end()) { - zlog_error(zct, "cannot find id for short_addr %x", short_addr); - return 0; - } else { - id = iter->second; - } - return start_timestamp_ + (id - 1) * eigen_value_send_duration_; -} - -int SensorScheduler::GetAvailableId(int short_addr) { - int max_support_sensor[128] = {0}; - for (auto it = short_addr_map_.begin(); it != short_addr_map_.end(); ++it) { - max_support_sensor[it->second] = 1; - } - int available_id = 0; - for (int i = 1; i < 128; ++i) { - if (max_support_sensor[i] == 0) { - available_id = i; - break; - } - } - zlog_warn(zct, "[GetAvailableId][%d] short addr : %x", available_id, short_addr); - short_addr_map_[short_addr] = available_id; - ShortAddrCfg::WriteCfg(short_addr_map_); - return available_id; -} - -int SensorScheduler::WriteScheduleCfg(long &ts, std::string &world_time) { - Json::Value root; - - root["schedule_start_timestamp"] = std::to_string(ts); - root["schedule_start_time"] = world_time; - root["eigen_value_send_interval"] = eigen_value_send_interval_; - root["eigen_value_send_duration"] = eigen_value_send_duration_; - root["wave_form_send_interval"] = wave_form_send_interval_; - root["wave_form_send_duration"] = wave_form_send_duration_; - root["max_sensor_num"] = max_sensor_num_; - root["available_slice"] = available_slice_; - root["free_slice"] = free_slice_; - root["support_modification"] = true; - - int *slice_allocation = new int[available_slice_]; - int slice_index = 0; // 有时间片的索引 - int no_slice_index = 0; // 没有时间片的索引 - int k = 1; - slice_sensor_id_.clear(); - - for (int i = 0; i < available_slice_; ++i) { - if (slice_index < max_sensor_num_ && (i % 2 == 0 || no_slice_index >= free_slice_)) { - slice_allocation[i] = k; - sensor_id_nth_slice_[k] = i + 1; - slice_sensor_id_.push_back(k); - k = k + 1; - slice_index++; - } else if (no_slice_index < free_slice_) { - slice_sensor_id_.push_back(0); - slice_allocation[i] = 0; - no_slice_index++; - } - } - - Json::Value ids; - for (int i = 0; i < available_slice_; ++i) { - ids.append(slice_allocation[i]); - } - delete []slice_allocation; - root["id"] = ids; - Json::StyledStreamWriter streamWriter; - std::ofstream out_file(SCHEDULE_CONFIG); - streamWriter.write(out_file, root); - out_file.close(); - return 0; -} - -int SensorScheduler::Config(int eigen_value_send_interval, int wave_form_send_interval, int eigen_value_send_duration, - int wave_form_send_duration, int max_sensor_num, std::string &error_msg) { - if (!support_modification_) { - zlog_warn(zct, "not support modification"); - return 1; - } - - int available_slice = 0; - int free_slice = 0; - int ret = CalcAvailableSlice(eigen_value_send_interval, - wave_form_send_interval, - eigen_value_send_duration, - wave_form_send_duration, - max_sensor_num, - available_slice, - free_slice, - error_msg); - if (ret != 0) { - return ret; - } - - eigen_value_send_interval_ = eigen_value_send_interval; - eigen_value_send_duration_ = eigen_value_send_duration; - wave_form_send_interval_ = wave_form_send_interval; - wave_form_send_duration_ = wave_form_send_duration; - max_sensor_num_ = max_sensor_num; - available_slice_ = available_slice; - free_slice_ = free_slice; - support_modification_ = true; - - eigen_value_slice_total_seconds_ = eigen_value_send_duration_ * max_sensor_num_; - int rest_duration = eigen_value_send_interval_ - eigen_value_slice_total_seconds_; - wave_slice_num_per_eigen_interval_ = rest_duration / wave_form_send_duration_; - seconds_per_wave_slice_ = rest_duration / wave_slice_num_per_eigen_interval_; - - std::string world_time; - long current_ts = GetLocalWorldTime(world_time); - - ret = WriteScheduleCfg(current_ts, world_time); - if (ret != 0) { - return ret; - } - start_timestamp_ = current_ts; - start_ts_str_ = world_time; - return 0; -} - -// 特征值发送间隔300秒,波形发送间隔为7200秒 -// 一次特征值发送时长为6秒,波形发送时长为60秒 -int SensorScheduler::CalcAvailableSlice(int eigen_value_send_interval, int wave_form_send_interval, - int eigen_value_send_duration, int wave_form_send_duration, - int max_sensor_num, int &available_slice, int &free_slice, - std::string &error_msg) { - if (max_sensor_num <= 0) { - error_msg = "max_sensor_num:" + std::to_string(max_sensor_num) + " must bigger than 0"; - zlog_error(zbt, "%s", error_msg.c_str()); - return 1; - } - - if (max_sensor_num * eigen_value_send_duration > eigen_value_send_interval) { - error_msg = "invalid max_sensor_num:" + std::to_string(max_sensor_num) + - " * eigen_value_send_duration:" + std::to_string(eigen_value_send_duration) + " > eigen_value_send_interval" + std::to_string(eigen_value_send_interval); - zlog_error(zbt, "%s", error_msg.c_str()); - return 2; - } - - if (max_sensor_num * wave_form_send_duration > wave_form_send_interval) { - error_msg = "invalid wave_form_send_duration:" + std::to_string(wave_form_send_duration) + - " * max_sensor_num:" + std::to_string(max_sensor_num) + " > wave_form_send_interval:" + std::to_string(wave_form_send_interval); - zlog_error(zbt, "%s", error_msg.c_str()); - return 3; - } - - if (wave_form_send_interval % eigen_value_send_interval != 0) { - error_msg = "wave_form_send_interval:" + std::to_string(wave_form_send_interval) + " %% eigen_value_send_interval:" + std::to_string(eigen_value_send_interval) + - " != 0"; - zlog_error(zbt, "%s", error_msg.c_str()); - return 4; - } - - int total_eigen_value_send_duration = eigen_value_send_duration * max_sensor_num; - int rest_duration = eigen_value_send_interval - total_eigen_value_send_duration; - int slice_per_eigen_value_interval = rest_duration / wave_form_send_duration; - available_slice = wave_form_send_interval / eigen_value_send_interval * slice_per_eigen_value_interval; - free_slice = available_slice - max_sensor_num; - if (free_slice < 0) { - error_msg = "invalid config, available slice:" + std::to_string(available_slice) + ", required slice:" + std::to_string(max_sensor_num); - zlog_error(zbt, "%s", error_msg.c_str()); - return 5; - } - return 0; -} - -int SensorScheduler::GetScheduleConfig(int &eigen_value_send_interval, int &wave_form_send_interval, - int &eigen_value_send_duration, int &wave_form_send_duration, - int &max_sensor_num) { - eigen_value_send_interval = eigen_value_send_interval_; - wave_form_send_interval = wave_form_send_interval_; - eigen_value_send_duration = eigen_value_send_duration_; - wave_form_send_duration = wave_form_send_duration_; - max_sensor_num = max_sensor_num_; - return 0; -} - -int SensorScheduler::UpdateSensorConfig(int short_addr) { - int id = 0; - auto iter = short_addr_map_.find(short_addr); - if (iter == short_addr_map_.end()) { - zlog_info(zct, "cannot find id for short_addr %d", short_addr); - return 1; - } else { - id = iter->second; - } - if (update_.count(id) > 0) { - return 0; - } - update_.insert(id); - UpdateCfg::WriteCfg(update_); - return 0; -} - -int SensorScheduler::UpdateConfigResult(int short_addr, int result) { - int id = 0; - auto iter = short_addr_map_.find(short_addr); - if (iter == short_addr_map_.end()) { - zlog_info(zct, "cannot find id for short_addr %x", short_addr); - return 1; - } else { - id = iter->second; - } - if (result != 0) { - return 0; - } - zlog_info(zbt, "[%d] short addr:%d update successfully", id, short_addr); - update_.erase(id); - UpdateCfg::WriteCfg(update_); - return 0; -} - -int SensorScheduler::UpgradeSensor(int short_addr, std::string sensor_type, int hw_version, - std::string current_sw_version, std::string upgrade_sw_version) { - int id = 0; - auto iter = short_addr_map_.find(short_addr); - if (iter == short_addr_map_.end()) { - zlog_error(zct, "cannot find id for short_addr %x", short_addr); - return 1; - } else { - id = iter->second; - } - UpgradeInfo info; - info.try_times = 0; - info.sensor_type = sensor_type; - info.hw_version = hw_version; - info.current_sw_version = current_sw_version; - info.upgrade_sw_version = upgrade_sw_version; - long ts = GetLocalTs(); - info.submit_time = GetUTCTime(ts); - upgrade_[id] = info; - zlog_info(zbt, "[%d] short addr:%x add upgrade info", id, short_addr); - UpgradeCfg::WriteCfg(upgrade_); - return 0; -} - -int SensorScheduler::UpgradeResult(int short_addr, int result) { - int id = 0; - auto iter = short_addr_map_.find(short_addr); - if (iter == short_addr_map_.end()) { - zlog_info(zct, "cannot find id for short_addr %x", short_addr); - return 1; - } else { - id = iter->second; - } - - if (result == kUpgradeSuccess || - result == kProductTypeMismatch || - result == kZigbeeHWMismatch || - result == kUpgradeDoneBefore) { - upgrade_.erase(id); - zlog_info(zbt, "[%d] short addr:%x upgrade successfully", id, short_addr); - UpgradeCfg::WriteCfg(upgrade_); - } else { - auto upgrade_iter = upgrade_.find(id); - if (upgrade_iter->second.try_times >= 10) { - zlog_error(zct, "[%d] short addr:%x upgrade 10 time failure", id, short_addr); - upgrade_.erase(id); - UpgradeCfg::WriteCfg(upgrade_); - // TODO: call interface to write into database - } - } - return 0; -} - -long SensorScheduler::GetLocalTs() { - auto now = std::chrono::system_clock::now(); - auto timestamp = std::chrono::duration_cast(now.time_since_epoch()).count(); - // zlog_debug(zct, "current timestamp:%lld", timestamp); - return timestamp; -} - -long SensorScheduler::GetLocalWorldTime(std::string &world_time) { - auto now = std::chrono::system_clock::now(); - std::time_t now_c = std::chrono::system_clock::to_time_t(now); - std::tm *local_time = std::localtime(&now_c); - char str[100] = {0}; - snprintf(str, sizeof(str), "%04d-%02d-%02d %02d:%02d:%02d", - local_time->tm_year + 1900, local_time->tm_mon+1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec); - world_time = str; - auto timestamp = std::chrono::duration_cast(now.time_since_epoch()).count(); - // zlog_debug(zct, "world time:%s, timestamp:%lld", world_time.c_str(), timestamp); - return timestamp; -} - -std::string SensorScheduler::GetUTCTime(long ts) { - std::chrono::time_point timePoint = std::chrono::system_clock::from_time_t(ts); - std::time_t utcTime = std::chrono::system_clock::to_time_t(timePoint); - std::tm* local_time = std::gmtime(&utcTime); - local_time->tm_hour = local_time->tm_hour + 8; - if (local_time->tm_hour > 24) { - local_time->tm_hour -= 24; - local_time->tm_mday += 1; - } - char str[100] = {0}; - snprintf(str, sizeof(str), "%04d-%02d-%02d %02d:%02d:%02d", - local_time->tm_year + 1900, local_time->tm_mon+1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec); - std::string world_time = str; - return world_time; -} - -void SensorScheduler::UpdateUpgradeInfo(int id) { - auto upgrade_iter = upgrade_.find(id); - upgrade_iter->second.try_times++; - long ts = GetLocalTs(); - upgrade_iter->second.try_world_time1.push_back(GetUTCTime(ts)); - UpgradeCfg::WriteCfg(upgrade_); -} - -void SensorScheduler::ModifyScheduleTs(int diff_ts) { - zlog_warn(zbt, "[ModifyScheduleTs] adjust ts:%d, from:%ld to:%ld", diff_ts, start_timestamp_, start_timestamp_ + diff_ts); - start_timestamp_ += diff_ts; - start_ts_str_ = GetUTCTime(start_timestamp_); - std::ifstream schedule_file(SCHEDULE_CONFIG); - Json::Reader reader; - Json::Value root; - if (!reader.parse(schedule_file, root, false)) { - zlog_error(zbt, "[ModifyScheduleTs] invalid format, fail to parse %s", SCHEDULE_CONFIG); - schedule_file.close(); - return; - } - schedule_file.close(); - root["schedule_start_timestamp"] = std::to_string(start_timestamp_); - root["schedule_start_time"] = start_ts_str_; - - Json::StyledStreamWriter streamWriter; - std::ofstream out_file(SCHEDULE_CONFIG); - streamWriter.write(out_file, root); - out_file.close(); -} - -void SensorScheduler::ClearScheduleCfg(int short_addr) { - zlog_warn(zbt, "[ClearScheduleCfg] clear all schedule config, short_addr:%x", short_addr); - if (short_addr == 0) { - zlog_warn(zbt, "[ClearScheduleCfg] clear all"); - update_.clear(); - upgrade_.clear(); - short_addr_map_.clear(); - ShortAddrCfg::ClearCfg(); - UpdateCfg::ClearCfg(); - UpgradeCfg::ClearCfg(); - } else { - UpdateConfigResult(short_addr, 0); - UpgradeResult(short_addr, kUpgradeSuccess); - short_addr_map_.erase(short_addr); - ShortAddrCfg::WriteCfg(short_addr_map_); - } - -} - -void SensorScheduler::CleanIdleOccupiedSet(long ts) { - if (free_slice_ocuppied_.size() > 5) { - for (auto it = free_slice_ocuppied_.begin(); it != free_slice_ocuppied_.end();) { - if ((*it) < ts) { - it = free_slice_ocuppied_.erase(it); - } else ++it; - } - } -} +#include "schedule.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "short_addr_cfg.hpp" +#include "update_cfg.hpp" +#include "wave_feature_set.hpp" + +extern zlog_category_t *zct; +extern zlog_category_t *zbt; + +uint8_t g_x, g_y, g_z; + +int SensorScheduler::StartSchedule(int short_addr, int &next_duration) { + int id = 0; + auto iter = short_addr_map_.find(short_addr); + if (iter == short_addr_map_.end()) { + id = GetAvailableId(short_addr); + } else { + id = iter->second; + } + + current_ts_ = GetLocalTs(); + CleanIdleOccupiedSet(current_ts_); + + nth_wave_start_slice_ = (current_ts_ - start_timestamp_) / wave_form_send_interval_; + current_wave_start_ts_ = nth_wave_start_slice_ * wave_form_send_interval_ + start_timestamp_; + seconds_in_current_wave_slice_ = current_ts_ - current_wave_start_ts_; + nth_eigen_value_slice_ = seconds_in_current_wave_slice_ / eigen_value_send_interval_; + seconds_in_current_eigen_slice_ = seconds_in_current_wave_slice_ % eigen_value_send_interval_; + ts_in_eigen_slice_ = false; + if (seconds_in_current_eigen_slice_ < eigen_value_slice_total_seconds_ - 3) { + ts_in_eigen_slice_ = true; + } + + if (ts_in_eigen_slice_) { + nth_eigen_slice_ = (seconds_in_current_eigen_slice_ + 2) / eigen_value_send_duration_; + } else { + nth_wave_slice_ = (seconds_in_current_eigen_slice_ - eigen_value_slice_total_seconds_ + 3) / seconds_per_wave_slice_; + } + zlog_warn(zct, "[%d:%x] ts:%ld, current utc:%s, nth eigen_value slice:%d, seconds in eigen slice:%d, eigen slice:%d", + id, short_addr, current_ts_, GetUTCTime(current_ts_).c_str(), nth_eigen_value_slice_+1, seconds_in_current_eigen_slice_, ts_in_eigen_slice_); + if (ts_in_eigen_slice_) { + if (id == nth_eigen_slice_ + 1) { + // 传感器需要执行上送特征值任务, 如果有配置需要下发的话,下发配置 + if (update_.count(id)) { + // execute config + zlog_warn(zct, "[%d:%x] update config in eigen slice", id, short_addr); + current_request_ = kScheduleConfigSensor; + return kScheduleConfigSensor; + } else { + wave_feature_set_inst::instance().GetFeatureCfg(short_addr, g_x, g_y, g_z); + if (g_x || g_y || g_z) { + // 执行上送特征值任务 + zlog_warn(zct, "[%d:%x] send eigen value in eigen slice", id, short_addr); + current_request_ = kScheduleEigenValue; + return kScheduleEigenValue; + } else { + next_duration = GetNextDuration(short_addr); + zlog_warn(zct, "[%d:%x] no need for eigen", id, short_addr); + return kScheduleWrongTime; + } + } + } else { + zlog_warn(zct, "[%d:%x] Invalid request, revive in %d eigen slice", id, short_addr, nth_eigen_slice_ + 1); + if (id < nth_eigen_slice_ + 1) { + // 不正确的请求 + long available_ts = current_wave_start_ts_ + (nth_eigen_value_slice_ + 1) * eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; + next_duration = available_ts - current_ts_; + zlog_warn(zct, "[%d:%x] wrong time in eigen slice, next feature in next interval send utc time:[%s], duration:%d", id, short_addr, GetUTCTime(available_ts).c_str(), next_duration); + } else { + long available_ts = current_wave_start_ts_ + nth_eigen_value_slice_ * eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; + next_duration = available_ts - current_ts_; + zlog_warn(zct, "[%d:%x] wrong time in eigen slice, next feature in current interval send utc time:[%s], duration:%d", id, short_addr, GetUTCTime(available_ts).c_str(), next_duration); + } + return kScheduleWrongTime; + } + } else { + int nth_wave_slice = nth_eigen_value_slice_ * wave_slice_num_per_eigen_interval_ + nth_wave_slice_ + 1; + auto wave_slice_iter = sensor_id_nth_slice_.find(id); + if (wave_slice_iter == sensor_id_nth_slice_.end()) { + zlog_error(zct, "[%d:%x]invaild id, not find wave slice id, need to check further", id, short_addr); + return kScheduleUnknownSensor; + } + + if (nth_wave_slice == wave_slice_iter->second) { + // 需要发送波形, 需要判断是否有配置,升级需求 + auto upgrade_iter = upgrade_.find(id); + if (upgrade_iter != upgrade_.end()) { + if (upgrade_iter->second.try_times < 10) { + current_request_ = kScheduleUpgrade; + UpdateUpgradeInfo(id); + zlog_warn(zct, "[%d:%x] in wave slice to upgrade now from version:%s to %s, try time:%d", + id, short_addr, upgrade_iter->second.current_sw_version.c_str(), + upgrade_iter->second.upgrade_sw_version.c_str(), upgrade_iter->second.try_times); + return kScheduleUpgrade; + } + } + + if (update_.count(id)) { + // execute config + zlog_warn(zct, "[%d:%x] in wave slice to update config", id, short_addr); + current_request_ = kScheduleConfigSensor; + return kScheduleConfigSensor; + } + wave_feature_set_inst::instance().GetWaveCfg(short_addr, g_x, g_y, g_z); + if (g_x || g_y || g_z) { + zlog_warn(zct, "[%d:%x] it is wave time", id, short_addr); + current_request_ = kScheduleWaveForm; + return kScheduleWaveForm; + } else { + next_duration = GetNextDuration(short_addr); + zlog_warn(zct, "[%d:%x] no need for wave", id, short_addr); + return kScheduleWrongTime; + } + } else { + if (slice_sensor_id_[nth_wave_slice-1] == 0) { + zlog_warn(zct, "[%d:%x] in idle time", id, short_addr); + // idle time + auto upgrade_iter = upgrade_.find(id); + if (upgrade_iter != upgrade_.end()) { + if (upgrade_iter->second.try_times < 10) { + current_request_ = kScheduleUpgrade; + UpdateUpgradeInfo(id); + zlog_warn(zct, "[%d:%x] in idle to upgrade now from version:%s to %s, try time:%d", + id, short_addr, upgrade_iter->second.current_sw_version.c_str(), + upgrade_iter->second.upgrade_sw_version.c_str(), upgrade_iter->second.try_times); + return kScheduleUpgrade; + } + } + + if (update_.count(id)) { + // execute config + zlog_warn(zct, "[%d:%x] in idle time to update config", id, short_addr); + current_request_ = kScheduleConfigSensor; + return kScheduleConfigSensor; + } + } + // wrong time to come + long available_ts = current_wave_start_ts_ + (nth_eigen_value_slice_ + 1) * eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; + next_duration = available_ts - current_ts_; + zlog_warn(zct, "[%d:%x] wrong time in wave slice, next feature send utc time:[%s], duration:%d", id, short_addr, GetUTCTime(available_ts).c_str(), next_duration); + return kScheduleWrongTime; + } + } +} + +long SensorScheduler::CalcNextTimestamp(int id, uint16_t short_addr) { + // current_ts_ = GetLocalTs(); + if (ts_in_eigen_slice_) { + int forward_wave_slice_num = nth_eigen_value_slice_ * wave_slice_num_per_eigen_interval_; + auto wave_slice_iter = sensor_id_nth_slice_.find(id); + if (wave_slice_iter == sensor_id_nth_slice_.end()) { + zlog_error(zct, "[Nxt] invaild id:%d, not find wave slice id", id); + long available_ts = current_wave_start_ts_ + eigen_value_send_interval_ + nth_eigen_slice_ * eigen_value_send_duration_; + zlog_error(zct, "[Nxt] [%d] next feature send utc time:[%s]", id, GetUTCTime(available_ts).c_str()); + return available_ts; + } + int wave_slice = wave_slice_iter->second; // 从1开始 + long send_wave_ts = 0; + wave_feature_set_inst::instance().GetWaveCfg(short_addr, g_x, g_y, g_z); + if (g_x || g_y || g_z) { + if (wave_slice > forward_wave_slice_num && + wave_slice <= forward_wave_slice_num + wave_slice_num_per_eigen_interval_) { + // 发送波的时间窗也在本次特征值发送间隔中 + for (int i = forward_wave_slice_num; i <= forward_wave_slice_num + wave_slice_num_per_eigen_interval_; ++i) { + if (wave_slice - 1 == i) { + send_wave_ts = current_wave_start_ts_ + nth_eigen_value_slice_ * eigen_value_send_interval_ + eigen_value_slice_total_seconds_ + (i - forward_wave_slice_num) * seconds_per_wave_slice_; + zlog_warn(zct, "[Nxt] [%d:%x] send wave time:[%s]", id, short_addr, GetUTCTime(send_wave_ts).c_str()); + break; + } + } + } + } + + long available_ts = 0; + auto upgrade_iter = upgrade_.find(id); + if (upgrade_iter != upgrade_.end()) { + if (upgrade_iter->second.try_times < 10) { + for (int i = 0; i < wave_slice_num_per_eigen_interval_; ++i) { + if (slice_sensor_id_[i+forward_wave_slice_num] == 0) { + // 判断此空闲位置是否被占用 + long current_wave_slice_ts = current_wave_start_ts_ + nth_eigen_value_slice_ * eigen_value_send_interval_ + eigen_value_slice_total_seconds_ + i * seconds_per_wave_slice_; + if (free_slice_ocuppied_.count(current_wave_slice_ts) == 0) { + available_ts = current_wave_slice_ts; + free_slice_ocuppied_.insert(available_ts); + zlog_warn(zct, "[Nxt][%d:%x] %d nth free wave slice will be used to upgrade, utc time:[%s]", id, short_addr, i+forward_wave_slice_num, GetUTCTime(available_ts).c_str()); + break; + } + } + } + } + } + if (send_wave_ts > 0 && available_ts > 0) { + long min_ts = std::min(send_wave_ts, available_ts); + zlog_warn(zct, "[Nxt] [%d:%x] next feature send utc time1:%s", id, short_addr, GetUTCTime(min_ts).c_str()); + return min_ts; + } + if (send_wave_ts + available_ts > 0) { + long max_ts = std::max(send_wave_ts, available_ts); + zlog_warn(zct, "[Nxt] [%d:%x] next feature send utc time2:%s", id, short_addr, GetUTCTime(max_ts).c_str()); + return max_ts; + } + } + + // 如果是在当前波形时间窗中,不管是空闲时间窗,还是发送波形的时间窗,下一个时间窗是特征值 + long available_ts = current_wave_start_ts_ + (nth_eigen_value_slice_ + 1)* eigen_value_send_interval_ + (id - 1) * eigen_value_send_duration_; + zlog_warn(zct, "[Nxt] [%d:%x] next feature send utc time3:[%s]", id, short_addr, GetUTCTime(available_ts).c_str()); + return available_ts; +} + +int SensorScheduler::GetNextDuration(int short_addr) { + int id = 0; + auto iter = short_addr_map_.find(short_addr); + if (iter == short_addr_map_.end()) { + zlog_error(zct, "cannot find id for short_addr %x", short_addr); + return 0; + } else { + id = iter->second; + } + long current_ts = GetLocalTs(); + long next_ts = CalcNextTimestamp(id, short_addr); + int duration = next_ts - current_ts; + if (duration < 0 || duration > eigen_value_send_interval_) { + zlog_warn(zct, "[Nxt] exception duration: %d", duration); + duration = eigen_value_send_interval_; + } + zlog_warn(zct, "[Nxt] [%d:%x] next duration is %d", id, short_addr, duration); + return duration; +} + +SensorScheduler::SensorScheduler() { + support_modification_ = true; + std::ifstream schedule_file(SCHEDULE_CONFIG); + if (schedule_file.good()) { + zlog_info(zbt, "exist configuration file"); + Json::Reader reader; + Json::Value root; + if (!reader.parse(schedule_file, root, false)) { + zlog_error(zbt, "invalid format, fail to parse %s", SCHEDULE_CONFIG); + schedule_file.close(); + return; + } + schedule_file.close(); + if (!root.isObject()) { + zlog_error(zbt, "invalid format, not an object: %s", SCHEDULE_CONFIG); + return; + } + start_timestamp_ = std::stol(root["schedule_start_timestamp"].asString()); + start_ts_str_ = root["schedule_start_time"].asString(); + long current_ts = GetLocalTs(); + if (current_ts < start_timestamp_) { + zlog_warn(zbt, "current ts: %ld less than start ts: %ld, go to adjust it", current_ts, start_timestamp_); + start_timestamp_ = current_ts; + start_ts_str_ = GetUTCTime(current_ts); + root["schedule_start_timestamp"] = std::to_string(start_timestamp_); + root["schedule_start_time"] = start_ts_str_; + + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(SCHEDULE_CONFIG); + streamWriter.write(out_file, root); + out_file.close(); + } + + eigen_value_send_interval_ = root["eigen_value_send_interval"].asInt(); + eigen_value_send_duration_ = root["eigen_value_send_duration"].asInt(); + wave_form_send_interval_ = root["wave_form_send_interval"].asInt(); + wave_form_send_duration_ = root["wave_form_send_duration"].asInt(); + max_sensor_num_ = root["max_sensor_num"].asInt(); + available_slice_ = root["available_slice"].asInt(); + free_slice_ = root["free_slice"].asInt(); + support_modification_ = root["support_modification"].asBool(); + + const Json::Value ids = root["id"]; + int sensor_id = 0; + int i = 0; + for (const auto& id : ids) { + sensor_id = id.asInt(); + slice_sensor_id_.push_back(sensor_id); + if (sensor_id != 0) { + sensor_id_nth_slice_[sensor_id] = i+1; + } + ++i; + } + + eigen_value_slice_total_seconds_ = eigen_value_send_duration_ * max_sensor_num_; + int rest_duration = eigen_value_send_interval_ - eigen_value_slice_total_seconds_; + wave_slice_num_per_eigen_interval_ = rest_duration / wave_form_send_duration_; + seconds_per_wave_slice_ = rest_duration / wave_slice_num_per_eigen_interval_; + } else { + zlog_info(zbt, "use default configuration"); + int eigen_value_send_interval = 300; + int wave_form_send_interval = 7200; + int eigen_value_send_duration = 6; + int wave_form_send_duration = 50; + int max_sensor_num = 32; + + // int eigen_value_send_interval = 120; + // int wave_form_send_interval = 240; + // int eigen_value_send_duration = 6; + // int wave_form_send_duration = 40; + // int max_sensor_num = 4; + std::string error_msg; + Config(eigen_value_send_interval, + wave_form_send_interval, + eigen_value_send_duration, + wave_form_send_duration, + max_sensor_num, + error_msg); + } + + short_addr_map_.clear(); + ShortAddrCfg::ReadCfg(short_addr_map_); + + // read upgrade config file: UPGRADE_CONFIG + UpgradeCfg::ReadCfg(upgrade_); + + // read config update file: CONFIG_UPDATE + UpdateCfg::ReadCfg(update_); +} + +long SensorScheduler::GetBaseTimestamp(int short_addr) { + int id = 0; + auto iter = short_addr_map_.find(short_addr); + if (iter == short_addr_map_.end()) { + zlog_error(zct, "cannot find id for short_addr %x", short_addr); + return 0; + } else { + id = iter->second; + } + return start_timestamp_ + (id - 1) * eigen_value_send_duration_; +} + +int SensorScheduler::GetAvailableId(int short_addr) { + int max_support_sensor[128] = {0}; + for (auto it = short_addr_map_.begin(); it != short_addr_map_.end(); ++it) { + max_support_sensor[it->second] = 1; + } + int available_id = 0; + for (int i = 1; i < 128; ++i) { + if (max_support_sensor[i] == 0) { + available_id = i; + break; + } + } + zlog_warn(zct, "[GetAvailableId][%d] short addr : %x", available_id, short_addr); + short_addr_map_[short_addr] = available_id; + ShortAddrCfg::WriteCfg(short_addr_map_); + return available_id; +} + +int SensorScheduler::WriteScheduleCfg(long &ts, std::string &world_time) { + Json::Value root; + + root["schedule_start_timestamp"] = std::to_string(ts); + root["schedule_start_time"] = world_time; + root["eigen_value_send_interval"] = eigen_value_send_interval_; + root["eigen_value_send_duration"] = eigen_value_send_duration_; + root["wave_form_send_interval"] = wave_form_send_interval_; + root["wave_form_send_duration"] = wave_form_send_duration_; + root["max_sensor_num"] = max_sensor_num_; + root["available_slice"] = available_slice_; + root["free_slice"] = free_slice_; + root["support_modification"] = true; + + int *slice_allocation = new int[available_slice_]; + int slice_index = 0; // 有时间片的索引 + int no_slice_index = 0; // 没有时间片的索引 + int k = 1; + slice_sensor_id_.clear(); + + for (int i = 0; i < available_slice_; ++i) { + if (slice_index < max_sensor_num_ && (i % 2 == 0 || no_slice_index >= free_slice_)) { + slice_allocation[i] = k; + sensor_id_nth_slice_[k] = i + 1; + slice_sensor_id_.push_back(k); + k = k + 1; + slice_index++; + } else if (no_slice_index < free_slice_) { + slice_sensor_id_.push_back(0); + slice_allocation[i] = 0; + no_slice_index++; + } + } + + Json::Value ids; + for (int i = 0; i < available_slice_; ++i) { + ids.append(slice_allocation[i]); + } + delete []slice_allocation; + root["id"] = ids; + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(SCHEDULE_CONFIG); + streamWriter.write(out_file, root); + out_file.close(); + return 0; +} + +int SensorScheduler::Config(int eigen_value_send_interval, int wave_form_send_interval, int eigen_value_send_duration, + int wave_form_send_duration, int max_sensor_num, std::string &error_msg) { + if (!support_modification_) { + zlog_warn(zct, "not support modification"); + return 1; + } + + int available_slice = 0; + int free_slice = 0; + int ret = CalcAvailableSlice(eigen_value_send_interval, + wave_form_send_interval, + eigen_value_send_duration, + wave_form_send_duration, + max_sensor_num, + available_slice, + free_slice, + error_msg); + if (ret != 0) { + return ret; + } + + eigen_value_send_interval_ = eigen_value_send_interval; + eigen_value_send_duration_ = eigen_value_send_duration; + wave_form_send_interval_ = wave_form_send_interval; + wave_form_send_duration_ = wave_form_send_duration; + max_sensor_num_ = max_sensor_num; + available_slice_ = available_slice; + free_slice_ = free_slice; + support_modification_ = true; + + eigen_value_slice_total_seconds_ = eigen_value_send_duration_ * max_sensor_num_; + int rest_duration = eigen_value_send_interval_ - eigen_value_slice_total_seconds_; + wave_slice_num_per_eigen_interval_ = rest_duration / wave_form_send_duration_; + seconds_per_wave_slice_ = rest_duration / wave_slice_num_per_eigen_interval_; + + std::string world_time; + long current_ts = GetLocalWorldTime(world_time); + + ret = WriteScheduleCfg(current_ts, world_time); + if (ret != 0) { + return ret; + } + start_timestamp_ = current_ts; + start_ts_str_ = world_time; + return 0; +} + +// 特征值发送间隔300秒,波形发送间隔为7200秒 +// 一次特征值发送时长为6秒,波形发送时长为60秒 +int SensorScheduler::CalcAvailableSlice(int eigen_value_send_interval, int wave_form_send_interval, + int eigen_value_send_duration, int wave_form_send_duration, + int max_sensor_num, int &available_slice, int &free_slice, + std::string &error_msg) { + if (max_sensor_num <= 0) { + error_msg = "max_sensor_num:" + std::to_string(max_sensor_num) + " must bigger than 0"; + zlog_error(zbt, "%s", error_msg.c_str()); + return 1; + } + + if (max_sensor_num * eigen_value_send_duration > eigen_value_send_interval) { + error_msg = "invalid max_sensor_num:" + std::to_string(max_sensor_num) + + " * eigen_value_send_duration:" + std::to_string(eigen_value_send_duration) + " > eigen_value_send_interval" + std::to_string(eigen_value_send_interval); + zlog_error(zbt, "%s", error_msg.c_str()); + return 2; + } + + if (max_sensor_num * wave_form_send_duration > wave_form_send_interval) { + error_msg = "invalid wave_form_send_duration:" + std::to_string(wave_form_send_duration) + + " * max_sensor_num:" + std::to_string(max_sensor_num) + " > wave_form_send_interval:" + std::to_string(wave_form_send_interval); + zlog_error(zbt, "%s", error_msg.c_str()); + return 3; + } + + if (wave_form_send_interval % eigen_value_send_interval != 0) { + error_msg = "wave_form_send_interval:" + std::to_string(wave_form_send_interval) + " %% eigen_value_send_interval:" + std::to_string(eigen_value_send_interval) + + " != 0"; + zlog_error(zbt, "%s", error_msg.c_str()); + return 4; + } + + int total_eigen_value_send_duration = eigen_value_send_duration * max_sensor_num; + int rest_duration = eigen_value_send_interval - total_eigen_value_send_duration; + int slice_per_eigen_value_interval = rest_duration / wave_form_send_duration; + available_slice = wave_form_send_interval / eigen_value_send_interval * slice_per_eigen_value_interval; + free_slice = available_slice - max_sensor_num; + if (free_slice < 0) { + error_msg = "invalid config, available slice:" + std::to_string(available_slice) + ", required slice:" + std::to_string(max_sensor_num); + zlog_error(zbt, "%s", error_msg.c_str()); + return 5; + } + return 0; +} + +int SensorScheduler::GetScheduleConfig(int &eigen_value_send_interval, int &wave_form_send_interval, + int &eigen_value_send_duration, int &wave_form_send_duration, + int &max_sensor_num) { + eigen_value_send_interval = eigen_value_send_interval_; + wave_form_send_interval = wave_form_send_interval_; + eigen_value_send_duration = eigen_value_send_duration_; + wave_form_send_duration = wave_form_send_duration_; + max_sensor_num = max_sensor_num_; + return 0; +} + +int SensorScheduler::UpdateSensorConfig(int short_addr) { + int id = 0; + auto iter = short_addr_map_.find(short_addr); + if (iter == short_addr_map_.end()) { + zlog_info(zct, "cannot find id for short_addr %d", short_addr); + return 1; + } else { + id = iter->second; + } + if (update_.count(id) > 0) { + return 0; + } + update_.insert(id); + UpdateCfg::WriteCfg(update_); + return 0; +} + +int SensorScheduler::UpdateConfigResult(int short_addr, int result) { + int id = 0; + auto iter = short_addr_map_.find(short_addr); + if (iter == short_addr_map_.end()) { + zlog_info(zct, "cannot find id for short_addr %x", short_addr); + return 1; + } else { + id = iter->second; + } + if (result != 0) { + return 0; + } + zlog_info(zbt, "[%d] short addr:%d update successfully", id, short_addr); + update_.erase(id); + UpdateCfg::WriteCfg(update_); + return 0; +} + +int SensorScheduler::UpgradeSensor(int short_addr, std::string sensor_type, int hw_version, + std::string current_sw_version, std::string upgrade_sw_version) { + int id = 0; + auto iter = short_addr_map_.find(short_addr); + if (iter == short_addr_map_.end()) { + zlog_error(zct, "cannot find id for short_addr %x", short_addr); + return 1; + } else { + id = iter->second; + } + UpgradeInfo info; + info.try_times = 0; + info.sensor_type = sensor_type; + info.hw_version = hw_version; + info.current_sw_version = current_sw_version; + info.upgrade_sw_version = upgrade_sw_version; + long ts = GetLocalTs(); + info.submit_time = GetUTCTime(ts); + upgrade_[id] = info; + zlog_info(zbt, "[%d] short addr:%x add upgrade info", id, short_addr); + UpgradeCfg::WriteCfg(upgrade_); + return 0; +} + +int SensorScheduler::UpgradeResult(int short_addr, int result) { + int id = 0; + auto iter = short_addr_map_.find(short_addr); + if (iter == short_addr_map_.end()) { + zlog_info(zct, "cannot find id for short_addr %x", short_addr); + return 1; + } else { + id = iter->second; + } + + if (result == kUpgradeSuccess || + result == kProductTypeMismatch || + result == kZigbeeHWMismatch || + result == kUpgradeDoneBefore) { + upgrade_.erase(id); + zlog_info(zbt, "[%d] short addr:%x upgrade successfully", id, short_addr); + UpgradeCfg::WriteCfg(upgrade_); + } else { + auto upgrade_iter = upgrade_.find(id); + if (upgrade_iter->second.try_times >= 10) { + zlog_error(zct, "[%d] short addr:%x upgrade 10 time failure", id, short_addr); + upgrade_.erase(id); + UpgradeCfg::WriteCfg(upgrade_); + // TODO: call interface to write into database + } + } + return 0; +} + +long SensorScheduler::GetLocalTs() { + auto now = std::chrono::system_clock::now(); + auto timestamp = std::chrono::duration_cast(now.time_since_epoch()).count(); + // zlog_debug(zct, "current timestamp:%lld", timestamp); + return timestamp; +} + +long SensorScheduler::GetLocalWorldTime(std::string &world_time) { + auto now = std::chrono::system_clock::now(); + std::time_t now_c = std::chrono::system_clock::to_time_t(now); + std::tm *local_time = std::localtime(&now_c); + char str[100] = {0}; + snprintf(str, sizeof(str), "%04d-%02d-%02d %02d:%02d:%02d", + local_time->tm_year + 1900, local_time->tm_mon+1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec); + world_time = str; + auto timestamp = std::chrono::duration_cast(now.time_since_epoch()).count(); + // zlog_debug(zct, "world time:%s, timestamp:%lld", world_time.c_str(), timestamp); + return timestamp; +} + +std::string SensorScheduler::GetUTCTime(long ts) { + std::chrono::time_point timePoint = std::chrono::system_clock::from_time_t(ts); + std::time_t utcTime = std::chrono::system_clock::to_time_t(timePoint); + std::tm* local_time = std::gmtime(&utcTime); + local_time->tm_hour = local_time->tm_hour + 8; + if (local_time->tm_hour > 24) { + local_time->tm_hour -= 24; + local_time->tm_mday += 1; + } + char str[100] = {0}; + snprintf(str, sizeof(str), "%04d-%02d-%02d %02d:%02d:%02d", + local_time->tm_year + 1900, local_time->tm_mon+1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min, local_time->tm_sec); + std::string world_time = str; + return world_time; +} + +void SensorScheduler::UpdateUpgradeInfo(int id) { + auto upgrade_iter = upgrade_.find(id); + upgrade_iter->second.try_times++; + long ts = GetLocalTs(); + upgrade_iter->second.try_world_time1.push_back(GetUTCTime(ts)); + UpgradeCfg::WriteCfg(upgrade_); +} + +void SensorScheduler::ModifyScheduleTs(int diff_ts) { + zlog_warn(zbt, "[ModifyScheduleTs] adjust ts:%d, from:%ld to:%ld", diff_ts, start_timestamp_, start_timestamp_ + diff_ts); + start_timestamp_ += diff_ts; + start_ts_str_ = GetUTCTime(start_timestamp_); + std::ifstream schedule_file(SCHEDULE_CONFIG); + Json::Reader reader; + Json::Value root; + if (!reader.parse(schedule_file, root, false)) { + zlog_error(zbt, "[ModifyScheduleTs] invalid format, fail to parse %s", SCHEDULE_CONFIG); + schedule_file.close(); + return; + } + schedule_file.close(); + root["schedule_start_timestamp"] = std::to_string(start_timestamp_); + root["schedule_start_time"] = start_ts_str_; + + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(SCHEDULE_CONFIG); + streamWriter.write(out_file, root); + out_file.close(); +} + +void SensorScheduler::ClearScheduleCfg(int short_addr) { + zlog_warn(zbt, "[ClearScheduleCfg] clear all schedule config, short_addr:%x", short_addr); + if (short_addr == 0) { + zlog_warn(zbt, "[ClearScheduleCfg] clear all"); + update_.clear(); + upgrade_.clear(); + short_addr_map_.clear(); + ShortAddrCfg::ClearCfg(); + UpdateCfg::ClearCfg(); + UpgradeCfg::ClearCfg(); + wave_feature_set_inst::instance().RemoveAllFeatureCfg(); + wave_feature_set_inst::instance().RemoveAllWaveCfg(); + } else { + UpdateConfigResult(short_addr, 0); + UpgradeResult(short_addr, kUpgradeSuccess); + short_addr_map_.erase(short_addr); + ShortAddrCfg::WriteCfg(short_addr_map_); + wave_feature_set_inst::instance().RemoveFeatureCfg(short_addr); + wave_feature_set_inst::instance().RemoveWaveCfg(short_addr); + } + +} + +void SensorScheduler::CleanIdleOccupiedSet(long ts) { + if (free_slice_ocuppied_.size() > 5) { + for (auto it = free_slice_ocuppied_.begin(); it != free_slice_ocuppied_.end();) { + if ((*it) < ts) { + it = free_slice_ocuppied_.erase(it); + } else ++it; + } + } +} \ No newline at end of file diff --git a/scheduler/schedule.hpp b/scheduler/schedule.hpp index f3b72ad..73e0d84 100644 --- a/scheduler/schedule.hpp +++ b/scheduler/schedule.hpp @@ -1,152 +1,152 @@ -#ifndef SCHEDULE_HPP_ -#define SCHEDULE_HPP_ - -#include -#include -#include -#include -#include -#include -#include "upgrade_cfg.hpp" - -#define SCHEDULE_CONFIG "/opt/configenv/schedule.json" - -typedef enum { - kScheduleResultNone = 0, - kScheduleUnknownSensor = 1, - kScheduleConfigSensor = 2, - kScheduleEigenValue = 3, - kScheduleWaveForm = 4, - kScheduleUpgrade = 5, - kScheduleWrongTime = 6 -} ScheduleResult; - -typedef enum { - kUpgradeSuccess = 0, // 成功 - kProductTypeMismatch = 1, // 包有问题,不再重试 - kZigbeeHWMismatch = 2, // 包有问题,不再重试 - kTransmitFileCrcError = 3, // 此返回值时,要重试 - kRecvDataLenError = 4, // 此返回值时,要重试 - kUpgradeDoneBefore = 5 // 当前就是这个版本,不需要升级了 -} FirmFileCheckResult; - -class SensorScheduler { -public: - SensorScheduler(); - - // kScheduleConfigSensor kScheduleUpgrade 等有结果,调我接口通知结果 - // kScheduleEigenValue kScheduleWaveForm - // 上面4个结束,调GetNextDuration()获取休眠时间 - // 如果是kScheduleWrongTime, 此函数next_duration表明休眠时间 - int StartSchedule(int short_addr, int &next_duration); - int GetNextDuration(int short_addr); - - long GetBaseTimestamp(int id); - long CalcNextTimestamp(int id, uint16_t short_addr); - - // 当有传感器需要更新配置时调用 - int UpdateSensorConfig(int short_addr); - // 当更新结束后,调用此接口,result为0是成功,其它值为失败 - int UpdateConfigResult(int short_addr, int result); - - /** - * @brief 当有传感器需要升级时调用 - * sensor_type: DN101, DN102 - * hw_version: 3, 4 - * current_sw_version: 1.1 - * upgrade_sw_version: 1.2 - */ - int UpgradeSensor(int short_addr, std::string sensor_type, int hw_version, - std::string current_sw_version, std::string upgrade_sw_version); - /** - * @brief 升级后,无线传感器发回来的返回值 - * - * @param short_addr - * @param result 参考:FirmFileCheckResult - * 返回值表明操作是否成功,0成功,其它失败 - */ - int UpgradeResult(int short_addr, int result); - - int Config(int eigen_value_send_interval, int wave_form_send_interval, - int eigen_value_send_duration, int wave_form_send_duration, - int max_sensor_num, std::string &error_msg); - - int CalcAvailableSlice(int eigen_value_send_interval, int wave_form_send_interval, - int eigen_value_send_duration, int wave_form_send_duration, - int max_sensor_num, int &available_slice, int &free_slice, - std::string &error_msg); - - int GetScheduleConfig(int &eigen_value_send_interval, int &wave_form_send_interval, - int &eigen_value_send_duration, int &wave_form_send_duration, - int &max_sensor_num); - // ======schedule.json操作开始====== - // 无线网关程序重启时 - // void ReadScheduleCfg(); - // 配置完成后 - int WriteScheduleCfg(long &ts, std::string &world_time); - - // 当系统进行校时时,输入参数为新的时间戳与以前时间戳的差值 - void ModifyScheduleTs(int diff_ts); - - // 当接入传感器时,设置为不可修改; 当停用所有传感器后,修改为可修改 - void AdjustSupportModification(bool support_modification); - // ======schedule.json操作结束====== - - void ClearScheduleCfg(int short_addr = 0); - - long GetLocalTs(); - long GetLocalWorldTime(std::string &world_time); - std::string GetUTCTime(long ts); - int GetAvailableId(int short_addr); - -private: - void UpdateUpgradeInfo(int id); - void CleanIdleOccupiedSet(long ts); - - // user config - int eigen_value_send_interval_; - int eigen_value_send_duration_; - int wave_form_send_interval_; - int wave_form_send_duration_; - int max_sensor_num_; - - // calc result - long start_timestamp_; - std::string start_ts_str_; - int available_slice_; - int free_slice_; - int wave_slice_num_per_eigen_interval_; // 每个特征值窗口中有几个波形发送窗口 - int seconds_per_wave_slice_; // 波形窗口时长 - int eigen_value_slice_total_seconds_; // 特征值窗口总时长 - std::vector slice_sensor_id_; // 每个时间窗是哪个传感器使用的 - - bool support_modification_; - std::map sensor_id_nth_slice_; // 传感器编号与第几个波形发送窗口对应关系 - std::map short_addr_map_; // base_relation.json - - // 空闲时间戳被占用 - std::unordered_set free_slice_ocuppied_; - - // sensor config update - std::unordered_set update_; - - // sensor upgrade - std::map upgrade_; - - // temp variables - long current_ts_; // 当前时间戳 - long current_wave_start_ts_; // 当前所在的波形发送间隔的开始时间戳 - long nth_wave_start_slice_; // 第几个波形发送窗口 - long seconds_in_current_wave_slice_; // 时间戳相对波形开始时间戳的秒数 - int nth_eigen_value_slice_; // 第几个特征值发送窗口 - int seconds_in_current_eigen_slice_; // 相对特征值发送间隔的秒数 - bool ts_in_eigen_slice_; // 时间位于特征值发送窗口中 - int nth_eigen_slice_; // 如果ts_in_eigen_slice_是真的话,此值表明是第几个特征值窗口 - bool nth_wave_slice_; // 如果ts_in_eigen_slice_是假的话,此值表明是第几个波形窗口 - - int current_request_; -}; - -typedef boost::container::dtl::singleton_default scheduler; - +#ifndef SCHEDULE_HPP_ +#define SCHEDULE_HPP_ + +#include +#include +#include +#include +#include +#include +#include "upgrade_cfg.hpp" + +#define SCHEDULE_CONFIG "/opt/configenv/schedule.json" + +typedef enum { + kScheduleResultNone = 0, + kScheduleUnknownSensor = 1, + kScheduleConfigSensor = 2, + kScheduleEigenValue = 3, + kScheduleWaveForm = 4, + kScheduleUpgrade = 5, + kScheduleWrongTime = 6 +} ScheduleResult; + +typedef enum { + kUpgradeSuccess = 0, // 成功 + kProductTypeMismatch = 1, // 包有问题,不再重试 + kZigbeeHWMismatch = 2, // 包有问题,不再重试 + kTransmitFileCrcError = 3, // 此返回值时,要重试 + kRecvDataLenError = 4, // 此返回值时,要重试 + kUpgradeDoneBefore = 5 // 当前就是这个版本,不需要升级了 +} FirmFileCheckResult; + +class SensorScheduler { +public: + SensorScheduler(); + + // kScheduleConfigSensor kScheduleUpgrade 等有结果,调我接口通知结果 + // kScheduleEigenValue kScheduleWaveForm + // 上面4个结束,调GetNextDuration()获取休眠时间 + // 如果是kScheduleWrongTime, 此函数next_duration表明休眠时间 + int StartSchedule(int short_addr, int &next_duration); + int GetNextDuration(int short_addr); + + long GetBaseTimestamp(int id); + long CalcNextTimestamp(int id, uint16_t short_addr); + + // 当有传感器需要更新配置时调用 + int UpdateSensorConfig(int short_addr); + // 当更新结束后,调用此接口,result为0是成功,其它值为失败 + int UpdateConfigResult(int short_addr, int result); + + /** + * @brief 当有传感器需要升级时调用 + * sensor_type: DN101, DN102 + * hw_version: 3, 4 + * current_sw_version: 1.1 + * upgrade_sw_version: 1.2 + */ + int UpgradeSensor(int short_addr, std::string sensor_type, int hw_version, + std::string current_sw_version, std::string upgrade_sw_version); + /** + * @brief 升级后,无线传感器发回来的返回值 + * + * @param short_addr + * @param result 参考:FirmFileCheckResult + * 返回值表明操作是否成功,0成功,其它失败 + */ + int UpgradeResult(int short_addr, int result); + + int Config(int eigen_value_send_interval, int wave_form_send_interval, + int eigen_value_send_duration, int wave_form_send_duration, + int max_sensor_num, std::string &error_msg); + + int CalcAvailableSlice(int eigen_value_send_interval, int wave_form_send_interval, + int eigen_value_send_duration, int wave_form_send_duration, + int max_sensor_num, int &available_slice, int &free_slice, + std::string &error_msg); + + int GetScheduleConfig(int &eigen_value_send_interval, int &wave_form_send_interval, + int &eigen_value_send_duration, int &wave_form_send_duration, + int &max_sensor_num); + // ======schedule.json操作开始====== + // 无线网关程序重启时 + // void ReadScheduleCfg(); + // 配置完成后 + int WriteScheduleCfg(long &ts, std::string &world_time); + + // 当系统进行校时时,输入参数为新的时间戳与以前时间戳的差值 + void ModifyScheduleTs(int diff_ts); + + // 当接入传感器时,设置为不可修改; 当停用所有传感器后,修改为可修改 + void AdjustSupportModification(bool support_modification); + // ======schedule.json操作结束====== + + void ClearScheduleCfg(int short_addr = 0); + + long GetLocalTs(); + long GetLocalWorldTime(std::string &world_time); + std::string GetUTCTime(long ts); + int GetAvailableId(int short_addr); + +private: + void UpdateUpgradeInfo(int id); + void CleanIdleOccupiedSet(long ts); + + // user config + int eigen_value_send_interval_; + int eigen_value_send_duration_; + int wave_form_send_interval_; + int wave_form_send_duration_; + int max_sensor_num_; + + // calc result + long start_timestamp_; + std::string start_ts_str_; + int available_slice_; + int free_slice_; + int wave_slice_num_per_eigen_interval_; // 每个特征值窗口中有几个波形发送窗口 + int seconds_per_wave_slice_; // 波形窗口时长 + int eigen_value_slice_total_seconds_; // 特征值窗口总时长 + std::vector slice_sensor_id_; // 每个时间窗是哪个传感器使用的 + + bool support_modification_; + std::map sensor_id_nth_slice_; // 传感器编号与第几个波形发送窗口对应关系 + std::map short_addr_map_; // base_relation.json + + // 空闲时间戳被占用 + std::unordered_set free_slice_ocuppied_; + + // sensor config update + std::unordered_set update_; + + // sensor upgrade + std::map upgrade_; + + // temp variables + long current_ts_; // 当前时间戳 + long current_wave_start_ts_; // 当前所在的波形发送间隔的开始时间戳 + long nth_wave_start_slice_; // 第几个波形发送窗口 + long seconds_in_current_wave_slice_; // 时间戳相对波形开始时间戳的秒数 + int nth_eigen_value_slice_; // 第几个特征值发送窗口 + int seconds_in_current_eigen_slice_; // 相对特征值发送间隔的秒数 + bool ts_in_eigen_slice_; // 时间位于特征值发送窗口中 + int nth_eigen_slice_; // 如果ts_in_eigen_slice_是真的话,此值表明是第几个特征值窗口 + bool nth_wave_slice_; // 如果ts_in_eigen_slice_是假的话,此值表明是第几个波形窗口 + + int current_request_; +}; + +typedef boost::container::dtl::singleton_default scheduler; + #endif // SCHEDULE_HPP_ \ No newline at end of file diff --git a/scheduler/short_addr_cfg.cpp b/scheduler/short_addr_cfg.cpp index 7c5b308..10f2dd1 100644 --- a/scheduler/short_addr_cfg.cpp +++ b/scheduler/short_addr_cfg.cpp @@ -1,68 +1,68 @@ -#include "short_addr_cfg.hpp" -#include -#include -#include -#include "common/common_func.hpp" - -extern zlog_category_t *zct; -extern zlog_category_t *zbt; - -int ShortAddrCfg::ReadCfg(std::map& short_addr_map) { - std::ifstream base_relation_file(BASE_RELATION); - if (!base_relation_file.good()) { - zlog_info(zbt, "[ShortAddrCfg] no file %s", BASE_RELATION); - return 0; - } - Json::Reader reader; - Json::Value root; - if (!reader.parse(base_relation_file, root, false)) { - zlog_error(zbt, "[ShortAddrCfg] invalid format, fail to parse %s", BASE_RELATION); - base_relation_file.close(); - return 1; - } - base_relation_file.close(); - if (!root.isArray()) { - zlog_error(zbt, "[ShortAddrCfg] invalid format, not an array: %s", BASE_RELATION); - return 2; - } - if (root.size() == 0) { - zlog_info(zbt, "[ShortAddrCfg] no element in %s", BASE_RELATION); - return 0; - } - - uint16_t short_addr; - int index = 0; - std::string short_addr_str; - char *end_ptr; - for (const auto &item : root) { - short_addr_str = item["short_addr"].asString(); - short_addr = strtol(short_addr_str.c_str(), &end_ptr, 16); - index = item["id"].asInt(); - zlog_info(zbt, "[ShortAddrCfg] index:%d, short addr:%02x", index, short_addr); - short_addr_map[short_addr] = index; - } - return 0; -} - -int ShortAddrCfg::WriteCfg(std::map &short_addr_map) { - Json::Value root; - char buf[8] = {0}; - for (auto it = short_addr_map.begin(); it != short_addr_map.end(); ++it) { - Json::Value item; - item["id"] = it->second; - memset(buf, 0, 8); - snprintf(buf, 8, "%02x%02x", UINT16_HIGH(it->first),UINT16_LOW(it->first)); - item["short_addr"] = buf; - root.append(item); - } - Json::StyledStreamWriter streamWriter; - std::ofstream out_file(BASE_RELATION); - streamWriter.write(out_file, root); - return 0; -} - -void ShortAddrCfg::ClearCfg() { - std::string clear_cmd = "rm -rf "; - clear_cmd.append(BASE_RELATION); - system(clear_cmd.c_str()); -} +#include "short_addr_cfg.hpp" +#include +#include +#include +#include "common/common_func.hpp" + +extern zlog_category_t *zct; +extern zlog_category_t *zbt; + +int ShortAddrCfg::ReadCfg(std::map& short_addr_map) { + std::ifstream base_relation_file(BASE_RELATION); + if (!base_relation_file.good()) { + zlog_info(zbt, "[ShortAddrCfg] no file %s", BASE_RELATION); + return 0; + } + Json::Reader reader; + Json::Value root; + if (!reader.parse(base_relation_file, root, false)) { + zlog_error(zbt, "[ShortAddrCfg] invalid format, fail to parse %s", BASE_RELATION); + base_relation_file.close(); + return 1; + } + base_relation_file.close(); + if (!root.isArray()) { + zlog_error(zbt, "[ShortAddrCfg] invalid format, not an array: %s", BASE_RELATION); + return 2; + } + if (root.size() == 0) { + zlog_info(zbt, "[ShortAddrCfg] no element in %s", BASE_RELATION); + return 0; + } + + uint16_t short_addr; + int index = 0; + std::string short_addr_str; + char *end_ptr; + for (const auto &item : root) { + short_addr_str = item["short_addr"].asString(); + short_addr = strtol(short_addr_str.c_str(), &end_ptr, 16); + index = item["id"].asInt(); + zlog_info(zbt, "[ShortAddrCfg] index:%d, short addr:%02x", index, short_addr); + short_addr_map[short_addr] = index; + } + return 0; +} + +int ShortAddrCfg::WriteCfg(std::map &short_addr_map) { + Json::Value root; + char buf[8] = {0}; + for (auto it = short_addr_map.begin(); it != short_addr_map.end(); ++it) { + Json::Value item; + item["id"] = it->second; + memset(buf, 0, 8); + snprintf(buf, 8, "%02x%02x", UINT16_HIGH(it->first),UINT16_LOW(it->first)); + item["short_addr"] = buf; + root.append(item); + } + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(BASE_RELATION); + streamWriter.write(out_file, root); + return 0; +} + +void ShortAddrCfg::ClearCfg() { + std::string clear_cmd = "rm -rf "; + clear_cmd.append(BASE_RELATION); + system(clear_cmd.c_str()); +} diff --git a/scheduler/short_addr_cfg.hpp b/scheduler/short_addr_cfg.hpp index 1839d42..cf2a43a 100644 --- a/scheduler/short_addr_cfg.hpp +++ b/scheduler/short_addr_cfg.hpp @@ -1,15 +1,15 @@ -#ifndef SHORT_ADDR_CFG_HPP_ -#define SHORT_ADDR_CFG_HPP_ -#include -#include - -#define BASE_RELATION "/opt/configenv/base_relation.json" - -class ShortAddrCfg { -public: - static int ReadCfg(std::map &short_addr_map); - static int WriteCfg(std::map &short_addr_map); - static void ClearCfg(); -}; - +#ifndef SHORT_ADDR_CFG_HPP_ +#define SHORT_ADDR_CFG_HPP_ +#include +#include + +#define BASE_RELATION "/opt/configenv/base_relation.json" + +class ShortAddrCfg { +public: + static int ReadCfg(std::map &short_addr_map); + static int WriteCfg(std::map &short_addr_map); + static void ClearCfg(); +}; + #endif // SHORT_ADDR_CFG_HPP_ \ No newline at end of file diff --git a/scheduler/update_cfg.cpp b/scheduler/update_cfg.cpp index 341d1d9..b89718e 100644 --- a/scheduler/update_cfg.cpp +++ b/scheduler/update_cfg.cpp @@ -1,54 +1,54 @@ -#include "update_cfg.hpp" -#include -#include -#include - -extern zlog_category_t *zct; -extern zlog_category_t *zbt; - -int UpdateCfg::ReadCfg(std::unordered_set& update) { - std::ifstream config_update_file(CONFIG_UPDATE); - if (!config_update_file.good()) { - zlog_info(zbt, "[UpdateCfg] no file"); - return 0; - } - Json::Reader reader; - Json::Value root; - if (!reader.parse(config_update_file, root, false)) { - zlog_error(zbt, "[UpdateCfg] invalid format, fail to parse %s", CONFIG_UPDATE); - config_update_file.close(); - return 1; - } - config_update_file.close(); - if (!root.isArray()) { - zlog_error(zbt, "[UpdateCfg] invalid format, not an array: %s", CONFIG_UPDATE); - return 2; - } - if (root.size() > 0) { - zlog_info(zbt, "[UpdateCfg] element in %s", CONFIG_UPDATE); - for (const auto &item : root) { - update.insert(item.asInt()); - zlog_info(zbt, "[UpdateCfg] sensor id:%d need to update", item.asInt()); - } - } - - return 0; -} - -int UpdateCfg::WriteCfg(std::unordered_set &update) { - Json::Value root; - for (auto item : update) { - root.append(item); - } - Json::StyledStreamWriter streamWriter; - std::ofstream out_file(CONFIG_UPDATE); - streamWriter.write(out_file, root); - out_file.close(); - return 0; -} - -void UpdateCfg::ClearCfg() { - std::string clear_cmd = "rm -rf "; - clear_cmd.append(CONFIG_UPDATE); - system(clear_cmd.c_str()); -} +#include "update_cfg.hpp" +#include +#include +#include + +extern zlog_category_t *zct; +extern zlog_category_t *zbt; + +int UpdateCfg::ReadCfg(std::unordered_set& update) { + std::ifstream config_update_file(CONFIG_UPDATE); + if (!config_update_file.good()) { + zlog_info(zbt, "[UpdateCfg] no file"); + return 0; + } + Json::Reader reader; + Json::Value root; + if (!reader.parse(config_update_file, root, false)) { + zlog_error(zbt, "[UpdateCfg] invalid format, fail to parse %s", CONFIG_UPDATE); + config_update_file.close(); + return 1; + } + config_update_file.close(); + if (!root.isArray()) { + zlog_error(zbt, "[UpdateCfg] invalid format, not an array: %s", CONFIG_UPDATE); + return 2; + } + if (root.size() > 0) { + zlog_info(zbt, "[UpdateCfg] element in %s", CONFIG_UPDATE); + for (const auto &item : root) { + update.insert(item.asInt()); + zlog_info(zbt, "[UpdateCfg] sensor id:%d need to update", item.asInt()); + } + } + + return 0; +} + +int UpdateCfg::WriteCfg(std::unordered_set &update) { + Json::Value root; + for (auto item : update) { + root.append(item); + } + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(CONFIG_UPDATE); + streamWriter.write(out_file, root); + out_file.close(); + return 0; +} + +void UpdateCfg::ClearCfg() { + std::string clear_cmd = "rm -rf "; + clear_cmd.append(CONFIG_UPDATE); + system(clear_cmd.c_str()); +} diff --git a/scheduler/update_cfg.hpp b/scheduler/update_cfg.hpp index 03d3bb3..963263b 100644 --- a/scheduler/update_cfg.hpp +++ b/scheduler/update_cfg.hpp @@ -1,15 +1,15 @@ -#ifndef UPDATE_CFG_HPP_ -#define UPDATE_CFG_HPP_ -#include - -#define CONFIG_UPDATE "/opt/configenv/config_update.json" - -class UpdateCfg { -public: - static int ReadCfg(std::unordered_set &update); - static int WriteCfg(std::unordered_set &update); - static void ClearCfg(); -}; - - +#ifndef UPDATE_CFG_HPP_ +#define UPDATE_CFG_HPP_ +#include + +#define CONFIG_UPDATE "/opt/configenv/config_update.json" + +class UpdateCfg { +public: + static int ReadCfg(std::unordered_set &update); + static int WriteCfg(std::unordered_set &update); + static void ClearCfg(); +}; + + #endif // UPDATE_CFG_HPP_ \ No newline at end of file diff --git a/scheduler/upgrade_cfg.cpp b/scheduler/upgrade_cfg.cpp index 00f137a..1ae8386 100644 --- a/scheduler/upgrade_cfg.cpp +++ b/scheduler/upgrade_cfg.cpp @@ -1,94 +1,82 @@ -#include "upgrade_cfg.hpp" -#include -#include -#include - -extern zlog_category_t *zct; -extern zlog_category_t *zbt; - -int UpgradeCfg::ReadCfg(std::map &upgrade) { - std::ifstream upgrade_file(UPGRADE_CONFIG); - if (!upgrade_file.good()) { - zlog_info(zbt, "[UpgradeCfg] no such file"); - return 0; - } - - upgrade_file.seekg(0, std::ios::end); - std::streampos file_size = upgrade_file.tellg(); - if (file_size > 256000) { - zlog_error(zct, "upgrade file exception, will remove it"); - ClearCfg(); - return 1; - } - upgrade_file.seekg(0, std::ios::beg); - Json::Reader reader; - Json::Value root; - if (!reader.parse(upgrade_file, root, false)) { - zlog_error(zbt, "[UpgradeCfg] invalid format, fail to parse %s", UPGRADE_CONFIG); - upgrade_file.close(); - return 1; - } - upgrade_file.close(); - if (!root.isArray()) { - zlog_error(zbt, "[UpgradeCfg] invalid format, not an array: %s", UPGRADE_CONFIG); - return 2; - } - - if (root.size() == 0) { - zlog_info(zbt, "[UpgradeCfg] no element"); - return 0; - } - - UpgradeInfo info; - for (const auto &item : root) { - info.try_times = item["try_times"].asInt(); - info.sensor_type = item["type"].asString(); - info.hw_version = item["hw_version"].asInt(); - info.current_sw_version = item["current_sw_version"].asString(); - info.upgrade_sw_version = item["upgrade_sw_version"].asString(); - info.submit_time = item["submit_time"].asString(); - for (const auto &time_item : item["try_world_time"]) { - info.try_world_time1.push_back(time_item.asString()); - } - upgrade[item["id"].asInt()] = info; - zlog_info(zbt, "[UpgradeCfg] id:%d need to upgrade from:%s to %s", item["id"].asInt(), - info.current_sw_version.c_str(), info.upgrade_sw_version.c_str()); - } - - return 0; -} - -int UpgradeCfg::WriteCfg(std::map &upgrade) { - if (upgrade.size() == 0) { - ClearCfg(); - return 0; - } - Json::Value root; - for (auto item : upgrade) { - Json::Value upgrade_item; - upgrade_item["id"] = item.first; - upgrade_item["try_times"] = item.second.try_times; - upgrade_item["type"] = item.second.sensor_type; - upgrade_item["hw_version"] = item.second.hw_version; - upgrade_item["current_sw_version"] = item.second.current_sw_version; - upgrade_item["upgrade_sw_version"] = item.second.upgrade_sw_version; - upgrade_item["submit_time"] = item.second.submit_time; - Json::Value try_world_time; - for (auto entry : item.second.try_world_time1) { - try_world_time.append(entry); - } - upgrade_item["try_world_time"] = try_world_time; - root.append(upgrade_item); - } - Json::StyledStreamWriter streamWriter; - std::ofstream out_file(UPGRADE_CONFIG); - streamWriter.write(out_file, root); - out_file.close(); - return 0; -} - -void UpgradeCfg::ClearCfg() { - std::string clear_cmd = "rm -rf "; - clear_cmd.append(UPGRADE_CONFIG); - system(clear_cmd.c_str()); -} +#include "upgrade_cfg.hpp" +#include +#include +#include + +extern zlog_category_t *zct; +extern zlog_category_t *zbt; + +int UpgradeCfg::ReadCfg(std::map &upgrade) { + std::ifstream upgrade_file(UPGRADE_CONFIG); + if (!upgrade_file.good()) { + zlog_info(zbt, "[UpgradeCfg] no such file"); + return 0; + } + + Json::Reader reader; + Json::Value root; + if (!reader.parse(upgrade_file, root, false)) { + zlog_error(zbt, "[UpgradeCfg] invalid format, fail to parse %s", UPGRADE_CONFIG); + upgrade_file.close(); + return 1; + } + upgrade_file.close(); + if (!root.isArray()) { + zlog_error(zbt, "[UpgradeCfg] invalid format, not an array: %s", UPGRADE_CONFIG); + return 2; + } + + if (root.size() == 0) { + zlog_info(zbt, "[UpgradeCfg] no element"); + return 0; + } + + UpgradeInfo info; + for (const auto &item : root) { + info.try_times = item["try_times"].asInt(); + info.sensor_type = item["type"].asString(); + info.hw_version = item["hw_version"].asInt(); + info.current_sw_version = item["current_sw_version"].asString(); + info.upgrade_sw_version = item["upgrade_sw_version"].asString(); + info.submit_time = item["submit_time"].asString(); + for (const auto &time_item : item["try_world_time"]) { + info.try_world_time1.push_back(time_item.asString()); + } + upgrade[item["id"].asInt()] = info; + zlog_info(zbt, "[UpgradeCfg] id:%d need to upgrade from:%s to %s", item["id"].asInt(), + info.current_sw_version.c_str(), info.upgrade_sw_version.c_str()); + } + + return 0; +} + +int UpgradeCfg::WriteCfg(std::map &upgrade) { + Json::Value root; + for (auto item : upgrade) { + Json::Value upgrade_item; + upgrade_item["id"] = item.first; + upgrade_item["try_times"] = item.second.try_times; + upgrade_item["type"] = item.second.sensor_type; + upgrade_item["hw_version"] = item.second.hw_version; + upgrade_item["current_sw_version"] = item.second.current_sw_version; + upgrade_item["upgrade_sw_version"] = item.second.upgrade_sw_version; + upgrade_item["submit_time"] = item.second.submit_time; + Json::Value try_world_time; + for (auto entry : item.second.try_world_time1) { + try_world_time.append(entry); + } + upgrade_item["try_world_time"] = try_world_time; + root.append(upgrade_item); + } + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(UPGRADE_CONFIG); + streamWriter.write(out_file, root); + out_file.close(); + return 0; +} + +void UpgradeCfg::ClearCfg() { + std::string clear_cmd = "rm -rf "; + clear_cmd.append(UPGRADE_CONFIG); + system(clear_cmd.c_str()); +} diff --git a/scheduler/upgrade_cfg.hpp b/scheduler/upgrade_cfg.hpp index da00c94..0bf8e1a 100644 --- a/scheduler/upgrade_cfg.hpp +++ b/scheduler/upgrade_cfg.hpp @@ -1,26 +1,26 @@ -#ifndef UPGRADE_CFG_HPP_ -#define UPGRADE_CFG_HPP_ -#include -#include -#include - -#define UPGRADE_CONFIG "/opt/configenv/upgrade.json" - -typedef struct { - int try_times; - std::string sensor_type; - int hw_version; - std::string current_sw_version; - std::string upgrade_sw_version; - std::string submit_time; - std::vector try_world_time1; -} UpgradeInfo; - -class UpgradeCfg { -public: - static int ReadCfg(std::map &upgrade); - static int WriteCfg(std::map &upgrade); - static void ClearCfg(); -}; - +#ifndef UPGRADE_CFG_HPP_ +#define UPGRADE_CFG_HPP_ +#include +#include +#include + +#define UPGRADE_CONFIG "/opt/configenv/upgrade.json" + +typedef struct { + int try_times; + std::string sensor_type; + int hw_version; + std::string current_sw_version; + std::string upgrade_sw_version; + std::string submit_time; + std::vector try_world_time1; +} UpgradeInfo; + +class UpgradeCfg { +public: + static int ReadCfg(std::map &upgrade); + static int WriteCfg(std::map &upgrade); + static void ClearCfg(); +}; + #endif // UPGRADE_CFG_HPP_ \ No newline at end of file diff --git a/scheduler/wave_feature_set.cpp b/scheduler/wave_feature_set.cpp new file mode 100644 index 0000000..f9cb8e1 --- /dev/null +++ b/scheduler/wave_feature_set.cpp @@ -0,0 +1,370 @@ +#include "wave_feature_set.hpp" +#include +#include "common/common_func.hpp" +#include + +extern zlog_category_t *zct; +extern zlog_category_t *zbt; + +WaveFeatureSetting::WaveFeatureSetting() { + std::ifstream feature_filter_file(FEATURE_FILTER_CFG); + if (!feature_filter_file.good()) { + zlog_info(zbt, "[WaveFeatureSetting] no file %s", FEATURE_FILTER_CFG); + global_feature_.short_addr = 0; + global_feature_.x = 1; + global_feature_.y = 1; + global_feature_.z = 1; + } else { + Json::Reader reader; + Json::Value root; + if (!reader.parse(feature_filter_file, root, false)) { + zlog_error(zbt, "[WaveFeatureSetting] invalid format, fail to parse %s", FEATURE_FILTER_CFG); + feature_filter_file.close(); + global_feature_.short_addr = 0; + global_feature_.x = 1; + global_feature_.y = 1; + global_feature_.z = 1; + } else { + uint16_t short_addr; + char *end_ptr; + for (const auto &key : root.getMemberNames()) { + if (key == "global") { + Json::Value v = root[key]; + global_feature_.short_addr = 0; + for (size_t i = 0; i < v.size(); ++i) { + if (i == 0) { + global_feature_.x = v[i].asInt(); + } else if (i == 1) { + global_feature_.y = v[i].asInt(); + } else if (i == 2) { + global_feature_.z = v[i].asInt(); + } + } + } else { + short_addr = strtol(key.c_str(), &end_ptr, 16); + Json::Value v = root[key]; + FeatureEntryPrivateCfg item; + for (size_t i = 0; i < v.size(); ++i) { + if (i == 0) { + item.x = v[i].asInt(); + } else if (i == 1) { + item.y = v[i].asInt(); + } else if (i == 2) { + item.z = v[i].asInt(); + } + } + eigen_map_[short_addr] = item; + } + } + } + } + + std::ifstream wave_filter_file(WAVE_FILTER_CFG); + if (!wave_filter_file.good()) { + zlog_info(zbt, "[WaveFeatureSetting] no file %s", WAVE_FILTER_CFG); + global_wave_.short_addr = 0; + global_wave_.x = 1; + global_wave_.y = 1; + global_wave_.z = 1; + } else { + Json::Reader reader; + Json::Value root; + if (!reader.parse(wave_filter_file, root, false)) { + zlog_error(zbt, "[WaveFeatureSetting] invalid format, fail to parse %s", WAVE_FILTER_CFG); + wave_filter_file.close(); + global_wave_.short_addr = 0; + global_wave_.x = 1; + global_wave_.y = 1; + global_wave_.z = 1; + } else { + uint16_t short_addr; + char *end_ptr; + for (const auto &key : root.getMemberNames()) { + if (key == "global") { + Json::Value v = root[key]; + global_wave_.short_addr = 0; + for (size_t i = 0; i < v.size(); ++i) { + if (i == 0) { + global_wave_.x = v[i].asInt(); + } else if (i == 1) { + global_wave_.y = v[i].asInt(); + } else if (i == 2) { + global_wave_.z = v[i].asInt(); + } + } + } else { + short_addr = strtol(key.c_str(), &end_ptr, 16); + Json::Value v = root[key]; + FeatureEntryPrivateCfg item; + for (size_t i = 0; i < v.size(); ++i) { + if (i == 0) { + item.x = v[i].asInt(); + } else if (i == 1) { + item.y = v[i].asInt(); + } else if (i == 2) { + item.z = v[i].asInt(); + } + } + + wave_map_[short_addr] = item; + } + } + } + } +} + +int WaveFeatureSetting::GetFeatureCfg(uint16_t short_addr, uint8_t &x, uint8_t &y, uint8_t &z) { + if (short_addr == 0) { + x = global_feature_.x; + y = global_feature_.y; + z = global_feature_.z; + return 0; + } + auto iter = eigen_map_.find(short_addr); + if (iter == eigen_map_.end()) { + x = global_feature_.x; + y = global_feature_.y; + z = global_feature_.z; + return 0; + } + + x = iter->second.x; + y = iter->second.y; + z = iter->second.z; + return 0; +} + +void WaveFeatureSetting::SetFeatureCfg(uint16_t short_addr, uint8_t x, uint8_t y, uint8_t z) { + bool need_submit = false; + if (short_addr == 0) { + if (global_feature_.x == x && global_feature_.y == y && global_feature_.z == z) { + return; + } + need_submit = true; + global_feature_.x = x; + global_feature_.y = y; + global_feature_.z = z; + } else { + auto iter = eigen_map_.find(short_addr); + if (iter == eigen_map_.end()) { + FeatureEntryPrivateCfg cfg; + cfg.x = x; + cfg.y = y; + cfg.z = z; + eigen_map_[short_addr] = cfg; + need_submit = true; + } else { + if (iter->second.x == x && iter->second.y == y && iter->second.z == z) { + return; + } + + iter->second.x = x; + iter->second.y = y; + iter->second.z = z; + need_submit = true; + } + } + + if (need_submit) { + WriteFeatureCfgFile(); + } +} + +void WaveFeatureSetting::SetAllFeatureCfg(std::vector cfg) { + eigen_map_.clear(); + for (auto item : cfg) { + if (item.short_addr == 0) { + global_feature_.short_addr = 0; + global_feature_.x = item.x; + global_feature_.y = item.y; + global_feature_.z = item.z; + } else { + FeatureEntryPrivateCfg entry; + entry.x = item.x; + entry.y = item.y; + entry.z = item.z; + eigen_map_[item.short_addr] = entry; + } + } + WriteFeatureCfgFile(); +} + +int WaveFeatureSetting::GetAllFeatureCfg(std::vector &cfg) { + cfg.clear(); + cfg.push_back(global_feature_); + for (auto item : eigen_map_) { + FeatureEntryUploadCfg current; + current.short_addr = item.first; + current.x = item.second.x; + current.y = item.second.y; + current.z = item.second.z; + cfg.push_back(current); + } + return 0; +} + +void WaveFeatureSetting::RemoveFeatureCfg(uint16_t short_addr) { + auto iter = eigen_map_.find(short_addr); + if (iter == eigen_map_.end()) { + return; + } + eigen_map_.erase(short_addr); + WriteFeatureCfgFile(); +} + +void WaveFeatureSetting::RemoveAllFeatureCfg() { + std::string clear_cmd = "rm -rf "; + clear_cmd.append(FEATURE_FILTER_CFG); + system(clear_cmd.c_str()); +} + +void WaveFeatureSetting::WriteFeatureCfgFile() { + Json::Value root; + Json::Value global_arr; + global_arr.append(global_feature_.x); + global_arr.append(global_feature_.y); + global_arr.append(global_feature_.z); + root["global"] = global_arr; + + char buf[8] = {0}; + for (auto item : eigen_map_) { + memset(buf, 0, 8); + snprintf(buf, 8, "%02x%02x", UINT16_HIGH(item.first), UINT16_LOW(item.first)); + Json::Value arr; + arr.append(item.second.x); + arr.append(item.second.y); + arr.append(item.second.z); + root[buf] = arr; + } + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(FEATURE_FILTER_CFG); + streamWriter.write(out_file, root); +} + +void WaveFeatureSetting::WriteWaveCfgFile() { + Json::Value root; + Json::Value global_arr; + global_arr.append(global_wave_.x); + global_arr.append(global_wave_.y); + global_arr.append(global_wave_.z); + root["global"] = global_arr; + + char buf[8] = {0}; + for (auto item : wave_map_) { + memset(buf, 0, 8); + snprintf(buf, 8, "%02x%02x", UINT16_HIGH(item.first), UINT16_LOW(item.first)); + Json::Value arr; + arr.append(item.second.x); + arr.append(item.second.y); + arr.append(item.second.z); + root[buf] = arr; + } + Json::StyledStreamWriter streamWriter; + std::ofstream out_file(WAVE_FILTER_CFG); + streamWriter.write(out_file, root); +} + +int WaveFeatureSetting::GetWaveCfg(uint16_t short_addr, uint8_t &x, uint8_t &y, uint8_t &z) { + if (short_addr == 0) { + x = global_wave_.x; + y = global_wave_.y; + z = global_wave_.z; + return 0; + } + auto iter = wave_map_.find(short_addr); + if (iter == wave_map_.end()) { + x = global_wave_.x; + y = global_wave_.y; + z = global_wave_.z; + return 0; + } + + x = iter->second.x; + y = iter->second.y; + z = iter->second.z; + return 0; +} + +void WaveFeatureSetting::SetWaveCfg(uint16_t short_addr, uint8_t x, uint8_t y, uint8_t z) { + bool need_submit = false; + if (short_addr == 0) { + if (global_wave_.x == x && global_wave_.y == y && global_wave_.z == z) { + return; + } + need_submit = true; + global_wave_.x = x; + global_wave_.y = y; + global_wave_.z = z; + } else { + auto iter = wave_map_.find(short_addr); + if (iter == wave_map_.end()) { + FeatureEntryPrivateCfg cfg; + cfg.x = x; + cfg.y = y; + cfg.z = z; + wave_map_[short_addr] = cfg; + need_submit = true; + } else { + if (iter->second.x == x && iter->second.y == y && iter->second.z == z) { + return; + } + + iter->second.x = x; + iter->second.y = y; + iter->second.z = z; + need_submit = true; + } + } + + if (need_submit) { + WriteWaveCfgFile(); + } +} + +void WaveFeatureSetting::SetAllWaveCfg(std::vector cfg) { + eigen_map_.clear(); + for (auto item : cfg) { + if (item.short_addr == 0) { + global_wave_.short_addr = 0; + global_wave_.x = item.x; + global_wave_.y = item.y; + global_wave_.z = item.z; + } else { + FeatureEntryPrivateCfg entry; + entry.x = item.x; + entry.y = item.y; + entry.z = item.z; + wave_map_[item.short_addr] = entry; + } + } + WriteWaveCfgFile(); +} + +int WaveFeatureSetting::GetAllWaveCfg(std::vector &cfg) { + cfg.clear(); + cfg.push_back(global_wave_); + for (auto item : wave_map_) { + FeatureEntryUploadCfg current; + current.short_addr = item.first; + current.x = item.second.x; + current.y = item.second.y; + current.z = item.second.z; + cfg.push_back(current); + } + return 0; +} + +void WaveFeatureSetting::RemoveWaveCfg(uint16_t short_addr) { + auto iter = wave_map_.find(short_addr); + if (iter == wave_map_.end()) { + return; + } + wave_map_.erase(short_addr); + WriteWaveCfgFile(); +} + +void WaveFeatureSetting::RemoveAllWaveCfg() { + std::string clear_cmd = "rm -rf "; + clear_cmd.append(WAVE_FILTER_CFG); + system(clear_cmd.c_str()); +} diff --git a/scheduler/wave_feature_set.hpp b/scheduler/wave_feature_set.hpp new file mode 100644 index 0000000..1ff3b58 --- /dev/null +++ b/scheduler/wave_feature_set.hpp @@ -0,0 +1,56 @@ +#ifndef WAVE_FEATURE_SET_HPP_ +#define WAVE_FEATURE_SET_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#define FEATURE_FILTER_CFG "/opt/configenv/feature_filter.json" +#define WAVE_FILTER_CFG "/opt/configenv/wave_filter.json" + +typedef struct { + uint16_t short_addr; // 全局配置的短地址写0 + uint8_t x, y, z; +} FeatureEntryUploadCfg; + +typedef struct { + uint8_t x, y, z; +} FeatureEntryPrivateCfg; + +class WaveFeatureSetting { +public: + WaveFeatureSetting(); + + // Feature set + int GetFeatureCfg(uint16_t short_addr, uint8_t &x, uint8_t &y, uint8_t &z); // 获取单个 + void SetFeatureCfg(uint16_t short_addr, uint8_t x, uint8_t y, uint8_t z); // 设置单个传感器 + void SetAllFeatureCfg(std::vector cfg); // 设置所有的 + int GetAllFeatureCfg(std::vector &cfg); // 获取所有的 + void RemoveFeatureCfg(uint16_t short_addr); + void RemoveAllFeatureCfg(); + + // Wave set + int GetWaveCfg(uint16_t short_addr, uint8_t &x, uint8_t &y, uint8_t &z); // 获取单个 + void SetWaveCfg(uint16_t short_addr, uint8_t x, uint8_t y, uint8_t z); // 设置单个传感器 + void SetAllWaveCfg(std::vector cfg); // 设置所有的 + int GetAllWaveCfg(std::vector &cfg); // 获取所有的 + void RemoveWaveCfg(uint16_t short_addr); + void RemoveAllWaveCfg(); + +private: + void WriteFeatureCfgFile(); + FeatureEntryUploadCfg global_feature_; + std::map eigen_map_; + + void WriteWaveCfgFile(); + FeatureEntryUploadCfg global_wave_; + std::map wave_map_; +}; + +typedef boost::container::dtl::singleton_default wave_feature_set_inst; + +#endif // WAVE_FEATURE_SET_HPP_ \ No newline at end of file diff --git a/uart/uart_feature_parse.cpp b/uart/uart_feature_parse.cpp index 1182b0a..9cd81a7 100644 --- a/uart/uart_feature_parse.cpp +++ b/uart/uart_feature_parse.cpp @@ -52,11 +52,12 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) { if (flag == 1) { zlog_info(zct, "DealDataNodeFeature %02x%02x, %d", pRecvData->ShortAddr[0], pRecvData->ShortAddr[1], flag); } - - if (bSendTimeStamp) //波形处理中 - return; + uint8_t Feature_x,Feature_y,Feature_z; + char *end_ptr; + uint16_t u_short_addr = strtol(buf, &end_ptr, 16); + wave_feature_set_inst::instance().GetFeatureCfg(u_short_addr,Feature_x,Feature_y,Feature_z); std::string strShortAddr = std::string(buf); - zlog_info(zct, "zigbeeShortAddr='%s'", strShortAddr.c_str()); + zlog_info(zct, "zigbeeShortAddr='%s',Feature_x = %d,Feature_y = %d,Feature_z = %d", strShortAddr.c_str(),Feature_x,Feature_y,Feature_z); char getLongAddr_sql[32] = {0}; //根据数据包中的传感器的短地址获取数据库中长地址(MAC),在下面判断该传感器是否存在,如果不存在则把数据包丢弃 sprintf(getLongAddr_sql, "zigbeeShortAddr='%s'", strShortAddr.c_str()); @@ -343,7 +344,10 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) { valNodeFeature["Phase3"] = dataDymX.Phase3; valNodeFeature["Phase4"] = dataDymX.Phase4; valNodeFeature["timeStamp"] = nowTimetamp; - valNodeData.append(valNodeFeature); + if (Feature_x) + { + valNodeData.append(valNodeFeature); + } DataRecvDym dataDymY; DataExtract(pRecvData, 34, lowbit, n); @@ -430,7 +434,10 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) { valNodeFeature["Phase3"] = dataDymY.Phase3; valNodeFeature["Phase4"] = dataDymY.Phase4; valNodeFeature["timeStamp"] = nowTimetamp; - valNodeData.append(valNodeFeature); + if (Feature_y) + { + valNodeData.append(valNodeFeature); + } DataRecvDym dataDymZ; DataExtract(pRecvData, 52, lowbit, n); @@ -527,7 +534,10 @@ void Uart::DealDataNodeFeature(const char *pData, int flag) { valNodeFeature["Phase3"] = dataDymZ.Phase3; valNodeFeature["Phase4"] = dataDymZ.Phase4; valNodeFeature["timeStamp"] = nowTimetamp; - valNodeData.append(valNodeFeature); + if (Feature_z) + { + valNodeData.append(valNodeFeature); + } memset(whereCon, 0, 1024); sprintf(whereCon, "MeasurementID='%s'", strMeasurementID.c_str()); diff --git a/uart/uart_parameter_config.cpp b/uart/uart_parameter_config.cpp index 9032a3d..9ea0ec4 100644 --- a/uart/uart_parameter_config.cpp +++ b/uart/uart_parameter_config.cpp @@ -9,6 +9,8 @@ #include #include "common/common_func.hpp" #include "minilzo/minilzo.h" +#include "scheduler/wave_feature_set.hpp" + extern zlog_category_t* zct; extern zlog_category_t* zbt; @@ -560,13 +562,20 @@ int Uart::TaskResp(ScheduleTask scheduleTask){ { UpdateData[7] = UINT16_LOW(scheduleTask.duration); UpdateData[8] = UINT16_HIGH(scheduleTask.duration); - } - if (scheduleTask.cmd == MEAS_EVAL) + }else if (scheduleTask.cmd == MEAS_EVAL) { UpdateData[9] = UINT32_LOW_2(scheduleTask.timeStamp); UpdateData[10] = UINT32_LOW_1(scheduleTask.timeStamp); UpdateData[11] = UINT32_HIGH_2(scheduleTask.timeStamp); UpdateData[12] = UINT32_HIGH_1(scheduleTask.timeStamp); + }else if (scheduleTask.cmd == WAVE_CMD) + { + uint8_t x,y,z; + wave_feature_set_inst::instance().GetWaveCfg(scheduleTask.shortAddr,x,y,z); + zlog_info(zct,"wave x = %d,y = %d,z = %d\n",x,y,z); + UpdateData[17] = (x^1) & 0xFF; + UpdateData[18] = (y^1) & 0xFF; + UpdateData[19] = (z^1) & 0xFF; } unsigned char tmp = 0x00; for (int k = 0; k < 99; k++) {