finish dz function
This commit is contained in:
@@ -2737,34 +2737,34 @@ bool compare_qvvr_and_file(const std::string& cfg_path, const std::vector<qvvr_d
|
||||
// DataArrayItem to_json
|
||||
void to_json(nlohmann::json& j, const DataArrayItem& d) {
|
||||
j = nlohmann::json{
|
||||
{"DataAttr", d.DataAttr},
|
||||
{"DataTimeSec", d.DataTimeSec},
|
||||
{"DataTimeUSec", d.DataTimeUSec},
|
||||
{"DataTag", d.DataTag},
|
||||
{"Data", d.Data}
|
||||
{"dataAttr", d.DataAttr},
|
||||
{"dataTimeSec", d.DataTimeSec},
|
||||
{"dataTimeUSec", d.DataTimeUSec},
|
||||
{"dataTag", d.DataTag},
|
||||
{"data", d.Data}
|
||||
};
|
||||
}
|
||||
|
||||
// MsgObj to_json
|
||||
void to_json(nlohmann::json& j, const MsgObj& m) {
|
||||
j = nlohmann::json{
|
||||
{"Cldid", m.Cldid},
|
||||
{"DataType", m.DataType},
|
||||
{"DataAttr", m.DataAttr},
|
||||
{"DsNameIdx", m.DsNameIdx},
|
||||
{"DataArray", m.DataArray}
|
||||
{"clDid", m.Cldid},
|
||||
{"dataType", m.DataType},
|
||||
{"dataAttr", m.DataAttr},
|
||||
{"dsNameIdx", m.DsNameIdx},
|
||||
{"dataArray", m.DataArray}
|
||||
};
|
||||
}
|
||||
|
||||
// FullObj to_json
|
||||
void to_json(nlohmann::json& j, const FullObj& f) {
|
||||
j = nlohmann::json{
|
||||
{"Id", f.mac},
|
||||
{"Mid", f.Mid},
|
||||
{"Did", f.Did},
|
||||
{"Pri", f.Pri},
|
||||
{"Type", f.Type},
|
||||
{"Msg", f.Msg}
|
||||
{"id", f.mac},
|
||||
{"mid", f.Mid},
|
||||
{"did", f.Did},
|
||||
{"pri", f.Pri},
|
||||
{"type", f.Type},
|
||||
{"msg", f.Msg}
|
||||
};
|
||||
}
|
||||
std::string generate_json(
|
||||
@@ -3379,7 +3379,7 @@ bool save_set_value(const std::string &dev_id, unsigned char mp_index, const std
|
||||
return true;
|
||||
}
|
||||
|
||||
bool save_internal_value(const std::string &dev_id, const std::vector<float> &fabsf) {
|
||||
bool save_internal_value(const std::string &dev_id, const std::vector<ushort> &fabsf) {
|
||||
// 找到对应 terminal_dev
|
||||
std::lock_guard<std::mutex> lock(ledgermtx);
|
||||
|
||||
@@ -3474,6 +3474,12 @@ bool send_set_value_reply(const std::string &dev_id, unsigned char mp_index, con
|
||||
return false;
|
||||
}
|
||||
|
||||
//将dz_info存入监测点
|
||||
pMon->dz_info_list.clear();
|
||||
for (const auto &dz : dz_info) {
|
||||
pMon->dz_info_list.push_back(dz);
|
||||
}
|
||||
|
||||
// 4) 取该监测点的 set_values,严格按顺序用于 DZ_Value
|
||||
std::vector<float> ordered_vals;
|
||||
ordered_vals.reserve(pMon->set_values.size());
|
||||
@@ -3565,47 +3571,175 @@ bool send_set_value_reply(const std::string &dev_id, unsigned char mp_index, con
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_internal_value_reply(const std::string &dev_id, const std::vector<DZ_kzz_bit> &control_words) {
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////回复内部定值响应读取
|
||||
|
||||
|
||||
bool send_internal_value_reply(const std::string &dev_id, const std::vector<DZ_kzz_bit> &control_words)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(ledgermtx);
|
||||
|
||||
// 1) 找终端
|
||||
auto it = std::find_if(terminal_devlist.begin(), terminal_devlist.end(),
|
||||
[&](const terminal_dev &d) { return d.terminal_id == dev_id; });
|
||||
if (it == terminal_devlist.end()) {
|
||||
std::cerr << "[send_set_value_reply] device not found: " << dev_id << std::endl;
|
||||
std::cerr << "[send_internal_value_reply] device not found: " << dev_id << std::endl;
|
||||
return false;
|
||||
}
|
||||
terminal_dev &dev = *it;
|
||||
|
||||
// 2) 校验状态:发送“定值读取结果”回复,应处于 READING_INTERFIXEDVALUE;isbusy == 1
|
||||
if (dev.isbusy != 1 || dev.busytype != static_cast<int>(DeviceState::READING_INTERFIXEDVALUE)) { //定值读取
|
||||
std::cerr << "[send_set_value_reply] device not in READING_INTERFIXEDVALUE state." << std::endl;
|
||||
// 2) 校验状态:发送“内部定值读取结果”回复,应处于 READING_INTERFIXEDVALUE;isbusy == 1
|
||||
if (dev.isbusy != 1 || dev.busytype != static_cast<int>(DeviceState::READING_INTERFIXEDVALUE)) {
|
||||
std::cerr << "[send_internal_value_reply] device not in READING_INTERFIXEDVALUE state." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5) 生成 JSON(结构严格贴合你给的样例)
|
||||
nlohmann::json j;
|
||||
//将control_words存入dev
|
||||
dev.control_words.clear();
|
||||
for (const auto &cw : control_words) {
|
||||
dev.control_words.push_back(cw);
|
||||
}
|
||||
|
||||
// 顶层
|
||||
// -------------------- [新增] 建立 internal_values 与 dz_internal_info_list 的一一对应 --------------------
|
||||
// 说明:按索引次序一一对应(第 i 个 NameFixValue 对应 internal_values 的第 i 个)
|
||||
// 若数量不同,按 min 对齐,忽略多出来的一边并告警。
|
||||
std::vector<float> internal_vals; // [新增]
|
||||
internal_vals.reserve(dev.internal_values.size()); // [新增]
|
||||
for (float v : dev.internal_values) internal_vals.push_back(v); // [新增]
|
||||
|
||||
const size_t n_dz = dev.dz_internal_info_list.size(); // [新增]
|
||||
const size_t n_val = internal_vals.size(); // [新增]
|
||||
const size_t n_use = std::min(n_dz, n_val); // [新增]
|
||||
if (n_dz != n_val) { // [新增]
|
||||
std::cerr << "[send_internal_value_reply] WARN: dz_internal_info_list size("
|
||||
<< n_dz << ") != internal_values size(" << n_val
|
||||
<< "), will use min(" << n_use << ")." << std::endl;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
|
||||
// 3) 组包顶层
|
||||
nlohmann::json j;
|
||||
j["guid"] = dev.guid;
|
||||
j["FrontIP"] = FRONT_IP; // 你的前置机 IP(项目已有常量/变量)
|
||||
j["Node"] = g_front_seg_index; // 节点号(项目已有变量)
|
||||
j["FrontIP"] = FRONT_IP;
|
||||
j["Node"] = g_front_seg_index;
|
||||
j["Dev_mac"] = normalize_mac(dev.addr_str);
|
||||
|
||||
// Detail
|
||||
nlohmann::json detail;
|
||||
detail["Type"] = 0x2106; // 设备数据
|
||||
|
||||
// Msg
|
||||
nlohmann::json msg;
|
||||
msg["DataType"] = 0x0D; //内部定值
|
||||
msg["DataType"] = 0x0D; // 内部定值
|
||||
|
||||
// DataArray(对象数组):逐个填充,DZ_Value 严格按 set_values 顺序
|
||||
nlohmann::json dataArray = nlohmann::json::array();
|
||||
// 4) === 将 C# 的拼接逻辑移植为 DataArray ===
|
||||
// C# 变量对应关系:
|
||||
// DevInfo.nDevIndex -> 这里用 1
|
||||
// DevInfo.strGuId -> 这里用 装置id
|
||||
// DevInfo.controlwordlist -> 这里用参数 control_words(DZ_kzz_bit 含 kzz_bit/bit_enable)
|
||||
//
|
||||
// NameFixValue 列表:使用 dev.dz_internal_info_list
|
||||
//
|
||||
// 关键逻辑:
|
||||
// - 遍历每个 NameFixValue,k 从 1 递增,nStep 每个定值递增 1
|
||||
// - 若 DataType == 1:将 Max/Min/Default 都 /100,并 property 输出一个空对象 [{}](保持与 C# 一致)
|
||||
// - 否则:为该定值构建 property 位数组,范围 [nStep*16, (nStep+1)*16),
|
||||
// 名称为空则提前结束本定值的 property;flag = (DefaultValue >> j) & 0x01
|
||||
//
|
||||
|
||||
//拼接逻辑
|
||||
nlohmann::json dataArray = nlohmann::json::array(); // [新增]
|
||||
|
||||
// 6) 入队发送
|
||||
int nStep = 0; // [新增] 每个 NameFixValue 递增
|
||||
int kSort = 1; // [新增] 排序号,从 1 开始
|
||||
|
||||
// 保护:dz_internal_info_list 是引用成员,确保不会因并发被改动(当前已在 ledgermtx 下)
|
||||
//for (const auto& nf : dev.dz_internal_info_list) { // [新增]
|
||||
for (size_t idxNF = 0; idxNF < n_use; ++idxNF) { // [修改] 使用 idxNF 控制索引
|
||||
const auto& nf = dev.dz_internal_info_list[idxNF];
|
||||
// 取字段
|
||||
const uint16_t dataType = nf.DataType;
|
||||
const uint16_t minRaw = nf.MinValue;
|
||||
const uint16_t maxRaw = nf.MaxValue;
|
||||
const uint16_t defaultRaw = nf.DefaultValue;
|
||||
const std::string unit = trim_cstr(nf.sDimension, sizeof(nf.sDimension));
|
||||
const std::string name = trim_cstr(nf.sFixValueName, sizeof(nf.sFixValueName));
|
||||
|
||||
// 取对应内部值
|
||||
const float internal_v_raw = internal_vals[idxNF]; // [新增]
|
||||
const double internal_v_out = static_cast<double>(internal_v_raw); // [新增] 直接转 double 输出,不缩放
|
||||
|
||||
// 构造一条记录
|
||||
nlohmann::json one;
|
||||
one["cpu_no"] = 1; // [新增] C#: DevInfo.nDevIndex 填设备号,固定为1
|
||||
one["dev_type"] = dev_id; // [新增] C#: DevInfo.strGuId 填装置id
|
||||
one["type"] = 90; // [新增] 固定 "90"
|
||||
one["unit"] = unit; // [新增]
|
||||
one["describe"] = name; // [新增]
|
||||
one["sort"] = kSort; // [新增]
|
||||
one["Internal_Value"] = internal_v_out; // [新增] 精确对应 internal_values 的值(含必要缩放)
|
||||
|
||||
// 数值:DataType == 1 时缩放 /100
|
||||
if (dataType == 1) { // [新增] 缩放分支
|
||||
int ChangeMaxValue = static_cast<int>(maxRaw) / 100;
|
||||
int ChangeMinValue = static_cast<int>(minRaw) / 100;
|
||||
int ChangeDefaultValue = static_cast<int>(defaultRaw) / 100;
|
||||
|
||||
one["maxvalue"] = ChangeMaxValue;
|
||||
one["minvalue"] = ChangeMinValue;
|
||||
one["defaultvalue"] = ChangeDefaultValue;
|
||||
one["value"] = ChangeDefaultValue;
|
||||
|
||||
// C# 在该分支 property 写成 [{ }](一个空对象的数组)
|
||||
nlohmann::json prop = nlohmann::json::array();
|
||||
prop.push_back(nlohmann::json::object()); // [{}]
|
||||
one["property"] = std::move(prop);
|
||||
} else { // [新增] 未缩放分支 + property 位描述
|
||||
one["maxvalue"] = static_cast<int>(maxRaw);
|
||||
one["minvalue"] = static_cast<int>(minRaw);
|
||||
one["defaultvalue"] = static_cast<int>(defaultRaw);
|
||||
one["value"] = static_cast<int>(defaultRaw);
|
||||
|
||||
// 构建 property:16 位窗口,从 nStep*16 到 (nStep+1)*16 - 1
|
||||
nlohmann::json prop = nlohmann::json::array();
|
||||
bool hasAny = false;
|
||||
|
||||
const int begin = nStep * 16;
|
||||
const int end = (nStep + 1) * 16; // 不含 end
|
||||
|
||||
for (int idx = begin, jbit = 0; idx < end; ++idx, ++jbit) {
|
||||
if (idx < 0 || static_cast<size_t>(idx) >= control_words.size()) break;
|
||||
|
||||
// 名称空则提前退出(仿 C#:temp=="" break)
|
||||
const std::string cw_name = trim_cstr(control_words[idx].kzz_bit, sizeof(control_words[idx].kzz_bit));
|
||||
if (cw_name.empty()) {
|
||||
// 注意:C# 如果 j==0 则设置了 flag2=1,仅用于逗号处理,这里不需要
|
||||
break;
|
||||
}
|
||||
|
||||
int flag = (defaultRaw >> jbit) & 0x01; // 取该位默认值
|
||||
nlohmann::json bitItem;
|
||||
bitItem["type_num"] = jbit;
|
||||
bitItem["bit0"] = ""; // 保持与 C# 一致
|
||||
bitItem["bit1"] = "";
|
||||
bitItem["describe"] = cw_name;
|
||||
bitItem["flag"] = (flag ? "1" : "0"); // C# 用字符串
|
||||
prop.push_back(std::move(bitItem));
|
||||
hasAny = true;
|
||||
}
|
||||
|
||||
if (!hasAny) {
|
||||
// 与 C# 对齐:如果一个都没有,就给 [{}] 以避免 "property":[] 的结构差异
|
||||
prop.push_back(nlohmann::json::object());
|
||||
}
|
||||
one["property"] = std::move(prop);
|
||||
}
|
||||
|
||||
dataArray.push_back(std::move(one)); // [新增]
|
||||
++nStep; // [新增] 进入下一个 16 位窗口
|
||||
++kSort; // [新增]
|
||||
}
|
||||
|
||||
msg["DataArray"] = std::move(dataArray); // [新增]
|
||||
detail["Msg"] = std::move(msg);
|
||||
j["Detail"] = std::move(detail);
|
||||
|
||||
// 5) 入队发送(保持你的队列逻辑)
|
||||
queue_data_t connect_info;
|
||||
connect_info.strTopic = Topic_Reply_Topic;
|
||||
connect_info.strText = j.dump(); // 序列化为字符串
|
||||
@@ -3618,15 +3752,15 @@ bool send_internal_value_reply(const std::string &dev_id, const std::vector<DZ_k
|
||||
// 调试打印
|
||||
std::cout << "[send_internal_value_reply] queued JSON:\n" << j.dump(4) << std::endl;
|
||||
|
||||
// 7) 发送后更新终端状态(按你现有规则)
|
||||
// 6) 发送后更新终端状态(保持你现有规则)
|
||||
if (dev.isbusy > 0) {
|
||||
dev.isbusy--;
|
||||
}
|
||||
if (dev.isbusy == 0) {
|
||||
dev.guid.clear();
|
||||
dev.busytype = 0;
|
||||
dev.internal_values.clear();//清理本次定值记录
|
||||
dev.dz_internal_info_list.clear();//清理本次定值描述记录
|
||||
dev.internal_values.clear(); // 清理本次定值记录
|
||||
dev.dz_internal_info_list.clear(); // 清理本次定值描述记录(注意:如果这是引用成员,确保其实际容器存在)
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user