This commit is contained in:
zhoumengru
2025-09-15 17:04:18 +08:00
64 changed files with 2372 additions and 1414 deletions

Binary file not shown.

View File

@@ -0,0 +1,109 @@
{
"EMS":{
"deviceType":101,
"addr_YC":[
["A相电压", "0x107E", "0.0", " V", "0.1"],
["A相电流", "0x1084", "0.0", " A"],
["B相电压", "0x1080", "0.0", " V", "0.1"],
["B相电流", "0x1086", "0.0", " A"],
["C相电压", "0x1082", "0.0", " V", "0.1"],
["C相电流", "0x1088", "0.0", " A"]
],
"addr_YX": [ ]
},
"PCS":{
"deviceType":102,
"addr_YC":[
["A相电压", "0x0010", "0.0", " V", "0.1"],
["A相电流", "0x0019", "0.0", " A"],
["B相电压", "0x0011", "0.0", " V", "0.1"],
["B相电流", "0x001A", "0.0", " A"],
["C相电压", "0x0011", "0.0", " V", "0.1"],
["C相电流", "0x001B", "0.0", " A"]
],
"addr_YX": [ ]
},
"PCU":{
"deviceType":103,
"addr_YC":[
["A相电压", "0x0013", "0.0", " V", "0.1"],
["A相电流", "0x001C", "0.0", " A"],
["B相电压", "0x0014", "0.0", " V", "0.1"],
["B相电流", "0x001D", "0.0", " A"],
["C相电压", "0x0015", "0.0", " V", "0.1"],
["C相电流", "0x001E", "0.0", " A"]
],
"addr_YX": [ ]
},
"BMS":{
"deviceType":104,
"addr_YC":[
["SOC", "0x0001", "0", " %"],
["SOH", "0x0002", "0", " %"],
["电压", "0x0003", "0.0", " V", "0.1"],
["电流", "0x0005", "0.0", " A"],
["单体最大电压", "0x0021", "0.0", " V", "0.1"],
["单体最小电压", "0x0024", "0.0", " V", "0.1"],
["单体最大温度", "0x0029", "0.0", " ℃"],
["单体最小温度", "0x002C", "0.0", " ℃"]
],
"addr_YX": [ ]
},
"BCU":{
"deviceType":105,
"addr_YC":[
["簇电压", "0x0003", "0.0", " V"],
["簇电流", "0x0005", "0", " A"],
["簇温度", "0x0007", "0.0", " ℃"],
["簇电阻", "0x0009", "0.0", " Ω"],
["簇SOC", "0x000B", "0", " %"],
["簇SOH", "0x000C", "0", " %"]
],
"addr_YX": [ ]
},
"MEM":{
"deviceType":3,
"addr_YC":[
["A相电压", "0x000B", "0.0", " V"],
["A相电流", "0x000D", "0.0", " A"],
["B相电压", "0x000F", "0.0", " V"],
["B相电流", "0x0011", "0.0", " A"],
["C相电压", "0x0013", "0.0", " V"],
["C相电流", "0x0015", "0.0", " A"]
],
"addr_YX": [ ]
},
"TH": {
"deviceType":10,
"addr_YC":[
["温度", "0x0003", "0.0", " ℃", "0.1"],
["湿度", "0x0004", "0.0", " %", "0.1"]
],
"addr_YX": [ ]
},
"Cooling": {
"deviceType":14,
"addr_YC":[
["开关", "0x1003", "0", "", "1"],
["采样模式", "0x1004", "0", "", "1"],
["制冷状态", "0x1005", "0", "", "1"],
["制热状态", "0x1006", "0", "", "1"],
["高温告警", "0x1007", "0", "", "1"],
["低温告警", "0x1008", "0", "", "1"],
["高压告警", "0x1009", "0", "", "1"],
["低压告警", "0x100A", "0", "", "1"]
]
},
"Charger": {
"deviceType":106,
"addr_YC":[
["需求电压", "31071", "0.0", " V"],
["需求电流", "31073", "0.0", " A"],
["需求功率", "31075", "0.0", " kW"],
["功率限值", "31077", "0.0", " kW"],
["输出电压", "31079", "0.0", " V"],
["输出电流", "31081", "0.0", " A"],
["输出功率", "31083", "0.0", " kW"]
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
{
"103":{
"addr":[
{"key": "0x1009", "datatype": "uint16", "remark": "EPO急停1故障0正常"},
{"key": "0x100A", "datatype": "uint16", "remark": "防雷器异常1告警0正常"},
{"key": "0x100B", "datatype": "uint16", "remark": "负载电压反序1故障0正常"},
{"key": "0x100C", "datatype": "uint16", "remark": "市电电压反序1故障0正常"},
{"key": "0x100D", "datatype": "uint16", "remark": "输出相反序1故障0正常"},
{"key": "0x100E", "datatype": "uint16", "remark": "过载告警1告警0正常"},
{"key": "0x100F", "datatype": "uint16", "remark": "过载超时1故障0正常"},
{"key": "0x1010", "datatype": "uint16", "remark": "交流过流保护1故障0正常"},
{"key": "0x1011", "datatype": "uint16", "remark": "逆变电压异常1故障0正常"},
{"key": "0x1012", "datatype": "uint16", "remark": "内部串口异常1故障0正常"},
{"key": "0x1013", "datatype": "uint16", "remark": "485通信故障1故障0正常"},
{"key": "0x1014", "datatype": "uint16", "remark": "CAN通信故障1故障0正常"},
{"key": "0x1015", "datatype": "uint16", "remark": "E2PROM故障1故障0正常"},
{"key": "0x1016", "datatype": "uint16", "remark": "电网过压1故障0正常"},
{"key": "0x1017", "datatype": "uint16", "remark": "电网欠压1故障0正常"},
{"key": "0x1018", "datatype": "uint16", "remark": "电网过频1故障0正常"},
{"key": "0x1019", "datatype": "uint16", "remark": "电网欠频1故障0正常"},
{"key": "0x101A", "datatype": "uint16", "remark": "电网快检综合异常1故障0正常"},
{"key": "0x101B", "datatype": "uint16", "remark": "电网幅值快检异常1故障0正常"},
{"key": "0x101C", "datatype": "uint16", "remark": "电网拖尾异常1故障0正常"},
{"key": "0x101E", "datatype": "uint16", "remark": "急停按钮信号NC1急停0正常"},
{"key": "0x101F", "datatype": "uint16", "remark": "避雷器NC1故障0正常"},
{"key": "0x1020", "datatype": "uint16", "remark": "避雷器断路器NC1故障0正常"},
{"key": "0x102F", "datatype": "uint16", "remark": "PCS_01下发设置1故障0正常"},
{"key": "0x1030", "datatype": "uint16", "remark": "PCS_02下发设置1故障0正常"},
{"key": "0x1031", "datatype": "uint16", "remark": "PCS_03下发设置1故障0正常"},
{"key": "0x1032", "datatype": "uint16", "remark": "PCS_04下发设置1故障0正常"},
{"key": "0x1033", "datatype": "uint16", "remark": "PCS_05下发设置1故障0正常"},
{"key": "0x1034", "datatype": "uint16", "remark": "PCS_06下发设置1故障0正常"},
{"key": "0x1035", "datatype": "uint16", "remark": "PCS_07下发设置1故障0正常"},
{"key": "0x1036", "datatype": "uint16", "remark": "PCS_08下发设置1故障0正常"},
{"key": "0x1037", "datatype": "uint16", "remark": "PCS_09下发设置1故障0正常"},
{"key": "0x1038", "datatype": "uint16", "remark": "PCS_10下发设置1:故障0正常"},
{"key": "0x1039", "datatype": "uint16", "remark": "内部DSP通信故障1:故障0正常"},
{"key": "0x103A", "datatype": "uint16", "remark": "BMS CAN通信故障1:故障0正常"}
]
},
"104":{
"addr":[
{"key": "0x1010", "datatype": "uint16", "remark": "绝缘故障1:故障0正常"},
{"key": "0x1011", "datatype": "uint16", "remark": "漏电保护1:故障0正常"},
{"key": "0x1012", "datatype": "uint16", "remark": "直流过压1:故障0正常"},
{"key": "0x1013", "datatype": "uint16", "remark": "市电幅值异常1:故障0正常"},
{"key": "0x1014", "datatype": "uint16", "remark": "市电相序异常1:故障0正常"},
{"key": "0x1015", "datatype": "uint16", "remark": "温度开关异常1:故障0正常"},
{"key": "0x1016", "datatype": "uint16", "remark": "市电频率异常1:故障0正常"},
{"key": "0x1017", "datatype": "uint16", "remark": "IGBT过温1:故障0正常"},
{"key": "0x1018", "datatype": "uint16", "remark": "交流接地故障1:故障0正常"},
{"key": "0x1019", "datatype": "uint16", "remark": "逆变过流异常1:故障0正常"},
{"key": "0x101A", "datatype": "uint16", "remark": "直流缓起故障1:故障0正常"},
{"key": "0x101B", "datatype": "uint16", "remark": "直流主继电器故障1:故障0正常"},
{"key": "0x101C", "datatype": "uint16", "remark": "风机异常1:故障0正常"},
{"key": "0x101D", "datatype": "uint16", "remark": "主接触器异常1:故障0正常"},
{"key": "0x101E", "datatype": "uint16", "remark": "均浮充切换超时1:故障0正常"},
{"key": "0x101F", "datatype": "uint16", "remark": "硬件故障1:故障0正常"},
{"key": "0x1020", "datatype": "uint16", "remark": "机内过温1:故障0正常"},
{"key": "0x1021", "datatype": "uint16", "remark": "软启动故障1:故障0正常"},
{"key": "0x1022", "datatype": "uint16", "remark": "触摸屏通讯故障1:故障0正常"},
{"key": "0x1023", "datatype": "uint16", "remark": "防雷器故障1:故障0正常"},
{"key": "0x1024", "datatype": "uint16", "remark": "急停故障1:故障0正常"},
{"key": "0x1025", "datatype": "uint16", "remark": "BMS系统故障1:故障0正常"},
{"key": "0x1026", "datatype": "uint16", "remark": "BMS通讯故障1:故障0正常"},
{"key": "0x1027", "datatype": "uint16", "remark": "BMS干接点通讯故障1:故障0正常"},
{"key": "0x1028", "datatype": "uint16", "remark": "远程通讯故障1:故障0正常"},
{"key": "0x1029", "datatype": "uint16", "remark": "门禁告警1:故障0正常"},
{"key": "0x102A", "datatype": "uint16", "remark": "锁相异常1:故障0正常"},
{"key": "0x102B", "datatype": "uint16", "remark": "IGBT过温告警1:故障0正常"},
{"key": "0x102C", "datatype": "uint16", "remark": "硬件过流保护1:故障0正常"},
{"key": "0x102D", "datatype": "uint16", "remark": "驱动故障1:故障0正常"},
{"key": "0x102E", "datatype": "uint16", "remark": "ID冲突1:故障0正常"},
{"key": "0x102F", "datatype": "uint16", "remark": "电池过压1:故障0正常"},
{"key": "0x1030", "datatype": "uint16", "remark": "电池欠压1:故障0正常"},
{"key": "0x1031", "datatype": "uint16", "remark": "直流过流保护1:故障0正常"},
{"key": "0x1032", "datatype": "uint16", "remark": "输出电压异常1:故障0正常"},
{"key": "0x1033", "datatype": "uint16", "remark": "离网输出电压不符合1:故障0正常"},
{"key": "0x1034", "datatype": "uint16", "remark": "输出过载保护1:故障0正常"},
{"key": "0x1035", "datatype": "uint16", "remark": "输出短路保护1:故障0正常"},
{"key": "0x1036", "datatype": "uint16", "remark": "并机通信异常1:故障0正常"},
{"key": "0x1037", "datatype": "uint16", "remark": "电池保险异常1:故障0正常"},
{"key": "0x1038", "datatype": "uint16", "remark": "电池重载低压1:故障0正常"},
{"key": "0x1039", "datatype": "uint16", "remark": "电池低压告警1:故障0正常"},
{"key": "0x103A", "datatype": "uint16", "remark": "一拖二压差过大1:故障0正常"},
{"key": "0x103B", "datatype": "uint16", "remark": "电池反接故障1:故障0正常"},
{"key": "0x103C", "datatype": "uint16", "remark": "电池电压异常1:故障0正常"},
{"key": "0x103D", "datatype": "uint16", "remark": "过载告警1:故障0正常"},
{"key": "0x103E", "datatype": "uint16", "remark": "外部接触器异常1:故障0正常"},
{"key": "0x103F", "datatype": "uint16", "remark": "IGBT温度传感器异常1:故障0正常"},
{"key": "0x1040", "datatype": "uint16", "remark": "整机温度传感器异常1:故障0正常"},
{"key": "0x1041", "datatype": "uint16", "remark": "市电CT异常1:故障0正常"},
{"key": "0x1042", "datatype": "uint16", "remark": "逆变电流三相不平衡1:故障0正常"},
{"key": "0x1043", "datatype": "uint16", "remark": "逆变电流直流分量异常1:故障0正常"},
{"key": "0x1044", "datatype": "uint16", "remark": "母线不平衡1:故障0正常"},
{"key": "0x1045", "datatype": "uint16", "remark": "逆变电压直流分量异常1:故障0正常"},
{"key": "0x1046", "datatype": "uint16", "remark": "主接触器控制异常1:故障0正常"},
{"key": "0x1047", "datatype": "uint16", "remark": "逆变电压控制异常1:故障0正常"},
{"key": "0x1048", "datatype": "uint16", "remark": "直流霍尔异常1:故障0正常"},
{"key": "0x1049", "datatype": "uint16", "remark": "电池单体过压1:故障0正常"},
{"key": "0x104A", "datatype": "uint16", "remark": "电池单体欠压1:故障0正常"},
{"key": "0x104B", "datatype": "uint16", "remark": "电网过压1:故障0正常"},
{"key": "0x104C", "datatype": "uint16", "remark": "电网欠压1:故障0正常"},
{"key": "0x104D", "datatype": "uint16", "remark": "电网过频1:故障0正常"},
{"key": "0x104E", "datatype": "uint16", "remark": "电网欠频1:故障0正常"},
{"key": "0x104F", "datatype": "uint16", "remark": "市电不平衡1:故障0正常"},
{"key": "0x1050", "datatype": "uint16", "remark": "参数设置不匹配1:故障0正常"},
{"key": "0x1051", "datatype": "uint16", "remark": "SPI通信异常1:故障0正常"},
{"key": "0x1052", "datatype": "uint16", "remark": "SCI通信异常1:故障0正常"},
{"key": "0x1053", "datatype": "uint16", "remark": "IIC通信异常1:故障0正常"},
{"key": "0x1054", "datatype": "uint16", "remark": "Xintf通信异常1:故障0正常"},
{"key": "0x1055", "datatype": "uint16", "remark": "零偏校准异常1:故障0正常"},
{"key": "0x1056", "datatype": "uint16", "remark": "烟雾告警1:故障0正常"},
{"key": "0x1057", "datatype": "uint16", "remark": "无电池组故障1异常0正常"},
{"key": "0x1058", "datatype": "uint16", "remark": "环温降频1异常0正常"},
{"key": "0x1059", "datatype": "uint16", "remark": "交流过载1异常0正常"},
{"key": "0x105A", "datatype": "uint16", "remark": "采样异常1异常0正常"},
{"key": "0x105B", "datatype": "uint16", "remark": "24V辅源故障1异常0正常"},
{"key": "0x105C", "datatype": "uint16", "remark": "直流欠压异常1异常0正常"},
{"key": "0x105D", "datatype": "uint16", "remark": "散热器过温1异常0正常"},
{"key": "0x105E", "datatype": "uint16", "remark": "CAN配置故障1异常0正常"},
{"key": "0x105F", "datatype": "uint16", "remark": "3.3V辅源故障1异常0正常"},
{"key": "0x1060", "datatype": "uint16", "remark": "环境过温1异常0正常"},
{"key": "0x1061", "datatype": "uint16", "remark": "A相IGBT逆变过流1异常0正常"},
{"key": "0x1062", "datatype": "uint16", "remark": "B相IGBT逆变过流1异常0正常"}
]
}
}

View File

@@ -0,0 +1,77 @@
import re
import json
def parse_datatype(text):
datatypes = ["int16", "uint16", "int32", "uint32", "int64", "uint64"]
for index, datatype in enumerate(datatypes):
left, separator, right = text.partition(datatype)
if len(separator) != 0:
return datatype, left + right
return "", text
def parse_from_file(filename):
data = ""
with open(filename, "r", encoding='utf-8') as f: # 打开文件
linedata = ""
for line in f: # 行遍历
line = line.strip()
#linedata = f.readline() # 读取文件的一行
flag = bool(re.search(r'0x[0-9A-Fa-f]{4}', line))
linedata += line.strip()
if flag:
# print(linedata)
# left, separator, right = linedata.partition("0x")
parts = re.split(r'(0x[0-9A-Fa-f]{4})', linedata)
linedata = ""
key = parts[1]
datatype, remark = parse_datatype(parts[0].strip())
remark = remark.replace("\t", " ").replace("\"", "")
item = {}
item["key"] = key
item["datatype"] = datatype
item["remark"] = remark
if len(data) > 0:
data += ",\n"
data += ("\t\t\t" + json.dumps(item, ensure_ascii=False))
return data
addritems = {}
addritems["EMS_YT"] = ["EMS遥调.txt", 1]
addritems["BCU_YX"] = ["BCU电池簇遥信.txt", 1]
addritems["BCU_YC"] = ["BCU电池簇遥测.txt", 1]
addritems["BMS_YC"] = ["BMS电池堆遥测.txt", 1]
addritems["EMS_YX"] = ["EMS遥信.txt", 1]
addritems["EMS_YC"] = ["EMS遥测.txt", 1]
addritems["EMS_YT"] = ["EMS遥调.txt", 1]
addritems["PCS_YX"] = ["PCS遥信.txt", 1]
addritems["PCS_YC"] = ["PCS遥测.txt", 1]
addritems["PCU_YX"] = ["PCU遥信.txt", 1]
addritems["PCU_YC"] = ["PCU遥测.txt", 1]
addritems["MEM_YC"] = ["多功能电表遥测.txt", 1]
addritems["TH_YC"] = ["温湿度状态遥测.txt", 1]
addritems["Fire40_YX"] = ["消防4.0遥信.txt", 1]
addritems["Cooling_YX"] = ["冷机遥信.txt", 1]
addritems["Cooling_YC"] = ["冷机遥测.txt", 1]
with open('registeraddr.json', 'w', encoding='utf-8') as f:
f.write("{")
index = 0
for key in addritems:
filename = addritems[key][0]
count = addritems[key][1]
print("parse: ", key, filename)
data = parse_from_file(filename)
if len(data) > 0:
data = "\n" + data + "\n\t"
if index != 0:
f.write(",")
f.write("\n\t\"" + key + "\": {\n\t\t\"count\":" + str(count) + ",\n\t\t\"addr\":[" + data + "\t]\n\t}")
index+=1
f.write("\n}")

View File

@@ -1,77 +1,89 @@
import re from openpyxl import load_workbook
import json
def parse_datatype(text): def read_cell(sheet, row, col):
datatypes = ["int16", "uint16", "int32", "uint32", "int64", "uint64"] val = str(sheet.cell(row, col).value)
for index, datatype in enumerate(datatypes): if val == "None":
left, separator, right = text.partition(datatype) val = ""
if len(separator) != 0: return val.strip()
return datatype, left + right
return "", text def read_sheet(wb, topic, sht_name):
sheet = wb[sht_name]
text = ""
for i in range(1, sheet.max_row):
# print(str(sheet.cell(i, 1).value))
addr = read_cell(sheet, i, 8)
name = read_cell(sheet,i, 2)
datatype = read_cell(sheet,i, 4)
unit = read_cell(sheet, i, 5)
remark = read_cell(sheet, i, 6)
remark = name + remark
if (len(addr) == 6):
if (len(unit)>0):
remark += '(' + unit + ')'
if (len(text)>0):
text += ',\n'
text += '\t\t\t{"key": "%s", "datatype": "%s", "remark": "%s"}' % (addr, datatype, remark.replace("\n", ""))
def parse_from_file(filename): if (len(text)>0):
data = "" text = "\n" + text + "\n\t\t"
with open(filename, "r", encoding='utf-8') as f: # 打开文件 text = '\t"%s":{\n\t\t"addr":[%s]\n\t}' % (topic, text)
linedata = "" return text
for line in f: # 行遍历
line = line.strip()
#linedata = f.readline() # 读取文件的一行
flag = bool(re.search(r'0x[0-9A-Fa-f]{4}', line))
linedata += line.strip()
if flag:
# print(linedata)
# left, separator, right = linedata.partition("0x")
parts = re.split(r'(0x[0-9A-Fa-f]{4})', linedata)
linedata = ""
key = parts[1]
datatype, remark = parse_datatype(parts[0].strip())
remark = remark.replace("\t", " ").replace("\"", "")
item = {}
item["key"] = key
item["datatype"] = datatype
item["remark"] = remark
if len(data) > 0:
data += ",\n"
data += ("\t\t\t" + json.dumps(item, ensure_ascii=False))
return data
addritems = {} wb = load_workbook('EMU对外通信点表最终修改1版_v9.xlsx', data_only=True)
addritems["EMS_YT"] = ["EMS遥调.txt", 1]
addritems["BCU_YX"] = ["BCU电池簇遥信.txt", 1]
addritems["BCU_YC"] = ["BCU电池簇遥测.txt", 1]
addritems["BMS_YC"] = ["BMS电池堆遥测.txt", 1]
addritems["EMS_YX"] = ["EMS遥信.txt", 1]
addritems["EMS_YC"] = ["EMS遥测.txt", 1]
addritems["EMS_YT"] = ["EMS遥调.txt", 1]
addritems["PCS_YX"] = ["PCS遥信.txt", 1]
addritems["PCS_YC"] = ["PCS遥测.txt", 1]
addritems["PCU_YX"] = ["PCU遥信.txt", 1]
addritems["PCU_YC"] = ["PCU遥测.txt", 1]
addritems["MEM_YC"] = ["多功能电表遥测.txt", 1]
addritems["TH_YC"] = ["温湿度状态遥测.txt", 1]
addritems["Fire40_YX"] = ["消防4.0遥信.txt", 1]
addritems["Cooling_YX"] = ["冷机遥信.txt", 1]
addritems["Cooling_YC"] = ["冷机遥测.txt", 1]
text = ""
text = read_sheet(wb, "EMS_YT", "EMS遥调")
text += ',\n' + read_sheet(wb, "EMS_YX", "EMS遥信")
text += ',\n' + read_sheet(wb, "EMS_YC", "EMS遥测")
text += ',\n' + read_sheet(wb, "PCU_YC", "PCU遥测")
text += ',\n' + read_sheet(wb, "PCU_YX", "PCU遥信")
text += ',\n' + read_sheet(wb, "PCS_YC", "PCS遥测")
text += ',\n' + read_sheet(wb, "PCS_YX", "PCS遥信")
text += ',\n' + read_sheet(wb, "BMS_YC", "BMS电池堆遥测")
text += ',\n' + read_sheet(wb, "BCU_YC", "BCU电池簇遥测")
text += ',\n' + read_sheet(wb, "BCU_YX", "BCU电池簇遥信")
# text += ',\n' + read_sheet(wb, "AirC_YC", "空调遥测")
# text += ',\n' + read_sheet(wb, "AirC_YX", "空调遥信")
text += ',\n' + read_sheet(wb, "MEM_YC", "多功能电表遥测")
text += ',\n' + read_sheet(wb, "TH_YC", "温湿度状态遥测")
text += ',\n' + read_sheet(wb, "Fire40_YX", "消防4.0遥信")
text += ',\n' + read_sheet(wb, "Cooling_YC", "冷机遥测")
text += ',\n' + read_sheet(wb, "Cooling_YX", "冷机遥信")
with open('registeraddr.json', 'w', encoding='utf-8') as f: with open('registeraddr.json', 'w', encoding='utf-8') as f:
f.write("{") f.write("{\n" + text + "\n}")
index = 0
for key in addritems:
filename = addritems[key][0]
count = addritems[key][1]
print("parse: ", key, filename)
data = parse_from_file(filename)
if len(data) > 0:
data = "\n" + data + "\n\t"
if index != 0:
f.write(",")
f.write("\n\t\"" + key + "\": {\n\t\t\"count\":" + str(count) + ",\n\t\t\"addr\":[" + data + "\t]\n\t}")
index+=1
f.write("\n}")
def read_sheet_alarm(wb, device_type, sht_name):
sheet = wb[sht_name]
text = ""
for i in range(1, sheet.max_row):
addr = read_cell(sheet, i, 8)
is_alarm = (read_cell(sheet, i, 7) == "告警")
if (len(addr) == 6 and is_alarm) :
name = read_cell(sheet,i, 2)
datatype = read_cell(sheet,i, 4)
unit = read_cell(sheet, i, 5)
remark = read_cell(sheet, i, 6)
remark = name + remark
if (len(unit)>0):
remark += '(' + unit + ')'
if (len(text)>0):
text += ',\n'
text += '\t\t\t{"key": "%s", "datatype": "%s", "remark": "%s"}' % (addr, datatype, remark.replace("\n", ""))
if (len(text)>0):
text = "\n" + text + "\n\t\t"
text = '\t"%s":{\n\t\t"addr":[%s]\n\t}' % (device_type, text)
return text;
text_err = ""
text_err = read_sheet_alarm(wb, 103, "PCU遥信")
text_err += ',\n' + read_sheet_alarm(wb, 104, "PCS遥信")
with open('registeraddrErr.json', 'w', encoding='utf-8') as f:
f.write("{\n" + text_err + "\n}")

View File

@@ -0,0 +1,84 @@
0x100F 绝缘故障 1:故障0正常
0x1010 漏电保护 1:故障0正常
0x1011 直流过压 1:故障0正常
0x1012 市电幅值异常 1:故障0正常
0x1013 市电相序异常 1:故障0正常
0x1014 温度开关异常 1:故障0正常
0x1015 市电频率异常 1:故障0正常
0x1016 IGBT过温 1:故障0正常
0x1017 交流接地故障 1:故障0正常
0x1018 逆变过流异常 1:故障0正常
0x1019 直流缓起故障 1:故障0正常
0x101A 直流主继电器故障 1:故障0正常
0x101B 风机异常 1:故障0正常
0x101C 主接触器异常 1:故障0正常
0x101D 均浮充切换超时 1:故障0正常
0x101E 硬件故障 1:故障0正常
0x101F 机内过温 1:故障0正常
0x1020 软启动故障 1:故障0正常
0x1021 触摸屏通讯故障 1:故障0正常
0x1022 防雷器故障 1:故障0正常
0x1023 急停故障 1:故障0正常
0x1024 BMS系统故障 1:故障0正常
0x1025 BMS通讯故障 1:故障0正常
0x1026 BMS干接点通讯故障 1:故障0正常
0x1027 远程通讯故障 1:故障0正常
0x1028 门禁告警 1:故障0正常
0x1029 锁相异常 1:故障0正常
0x102A IGBT过温告警 1:故障0正常
0x102B 硬件过流保护 1:故障0正常
0x102C 驱动故障 1:故障0正常
0x102D ID冲突 1:故障0正常
0x102E 电池过压 1:故障0正常
0x102F 电池欠压 1:故障0正常
0x1030 直流过流保护 1:故障0正常
0x1031 输出电压异常 1:故障0正常
0x1032 离网输出电压不符合 1:故障0正常
0x1033 输出过载保护 1:故障0正常
0x1034 输出短路保护 1:故障0正常
0x1035 并机通信异常 1:故障0正常
0x1036 电池保险异常 1:故障0正常
0x1037 电池重载低压 1:故障0正常
0x1038 电池低压告警 1:故障0正常
0x1039 一拖二压差过大 1:故障0正常
0x103A 电池反接故障 1:故障0正常
0x103B 电池电压异常 1:故障0正常
0x103C 过载告警 1:故障0正常
0x103D 外部接触器异常 1:故障0正常
0x103E IGBT温度传感器异常 1:故障0正常
0x103F 整机温度传感器异常 1:故障0正常
0x1040 市电CT异常 1:故障0正常
0x1041 逆变电流三相不平衡 1:故障0正常
0x1042 逆变电流直流分量异常 1:故障0正常
0x1043 母线不平衡 1:故障0正常
0x1044 逆变电压直流分量异常 1:故障0正常
0x1045 主接触器控制异常 1:故障0正常
0x1046 逆变电压控制异常 1:故障0正常
0x1047 直流霍尔异常 1:故障0正常
0x1048 电池单体过压 1:故障0正常
0x1049 电池单体欠压 1:故障0正常
0x104A 电网过压 1:故障0正常
0x104B 电网欠压 1:故障0正常
0x104C 电网过频 1:故障0正常
0x104D 电网欠频 1:故障0正常
0x104E 市电不平衡 1:故障0正常
0x104F 参数设置不匹配 1:故障0正常
0x1050 SPI通信异常 1:故障0正常
0x1051 SCI通信异常 1:故障0正常
0x1052 IIC通信异常 1:故障0正常
0x1053 Xintf通信异常 1:故障0正常
0x1054 零偏校准异常 1:故障0正常
0x1055 烟雾告警 1:故障0正常
0x1056 无电池组故障 1异常0正常
0x1057 环温降频 1异常0正常
0x1058 交流过载 1异常0正常
0x1059 采样异常 1异常0正常
0x105A 24V辅源故障 1异常0正常
0x105B 直流欠压异常 1异常0正常
0x105C 散热器过温 1异常0正常
0x105D CAN配置故障 1异常0正常
0x105E 3.3V辅源故障 1异常0正常
0x105F 环境过温 1异常0正常
0x1060 A相IGBT逆变过流 1异常0正常
0x1061 B相IGBT逆变过流 1异常0正常
0x1062 C相IGBT逆变过流 1异常0正常

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

View File

@@ -33,13 +33,13 @@ std::string ElectPeriod::dump()
} }
void AppData::initFromDB() bool AppData::initFromDB()
{ {
auto dao = DaoEntity::create(""); auto dao = DaoEntity::create("");
if (!dao->isConnected()) if (!dao->isConnected())
{ {
spdlog::error("Init app data failed, database connected error."); spdlog::error("Init app data failed, database connected error.");
return; return false;
} }
std::string str; std::string str;
@@ -106,7 +106,8 @@ void AppData::initFromDB()
} }
{ // 数据库读取场站信息 { // 数据库读取场站信息
str = "", result.clear(); str = "", result.clear();
DAO::queryStationList(dao, result); std::string sql = "SELECT s.*, p.name policy_name, p.`type` policy_type, p.value FROM station s LEFT JOIN policy p ON s.policy_id=p.policy_id;";
dao->exec(sql, result);
for (auto& fields: result) for (auto& fields: result)
{ {
auto station = std::make_shared<Station>(); auto station = std::make_shared<Station>();
@@ -127,8 +128,7 @@ void AppData::initFromDB()
auto station = this->getStation(stationId); auto station = this->getStation(stationId);
if (station) if (station)
{ {
auto device = Device::create(fields); station->addDevice(fields);
station->addDevice(deviceId, device);
} }
else else
{ {
@@ -141,7 +141,7 @@ void AppData::initFromDB()
DAO::queryPolicyList(dao, result); DAO::queryPolicyList(dao, result);
for (auto& fields: result) for (auto& fields: result)
{ {
auto policy = std::make_shared<MyPolicy>(); auto policy = std::make_shared<SysPolicy>();
policy->policyId = fields.get<int>(DMPolicy::POLICY_ID); policy->policyId = fields.get<int>(DMPolicy::POLICY_ID);
policy->type = fields.get<int>(DMPolicy::TYPE); policy->type = fields.get<int>(DMPolicy::TYPE);
policy->name = fields.value(DMPolicy::NAME); policy->name = fields.value(DMPolicy::NAME);
@@ -236,28 +236,17 @@ void AppData::initFromDB()
} }
} }
} }
return true;
} }
void AppData::init() bool AppData::init()
{ {
this->initFromDB(); bool ret = this->initFromDB();
if (!ret) { return false; }
auto& optionMqtt = Config::option.mqtt;
if (!optionMqtt.host.empty())
{
for (auto& item : mapStation)
{
auto& station = item.second;
if (station->status == 1)
{
// "tcp://localhost:1883"
station->mqttCli->init(optionMqtt.host, station->code, optionMqtt.username, optionMqtt.password);
}
}
}
this->launchDate = Config::option.lunchDate; this->launchDate = Config::option.lunchDate;
return true;
} }
std::shared_ptr<Station> AppData::getStation(int stationId) std::shared_ptr<Station> AppData::getStation(int stationId)

View File

@@ -11,7 +11,7 @@
class Station; class Station;
class Device; class Device;
class MyPolicy; class SysPolicy;
using VecPairSS = std::vector<std::pair<std::string, std::string>>; using VecPairSS = std::vector<std::pair<std::string, std::string>>;
@@ -57,8 +57,8 @@ public:
class AppData class AppData
{ {
public: public:
void init(); bool init();
void initFromDB(); bool initFromDB();
// 读取统计数据: 今日统计数据,累计统计数据 // 读取统计数据: 今日统计数据,累计统计数据
void loadStatData(); void loadStatData();
@@ -155,7 +155,7 @@ public:
std::unordered_map<int, std::string> mapPolicyType; std::unordered_map<int, std::string> mapPolicyType;
// 策略信息 // 策略信息
std::unordered_map<int, std::shared_ptr<MyPolicy>> mapPolicy; std::unordered_map<int, std::shared_ptr<SysPolicy>> mapPolicy;
// 电力峰谷分段 (12个月每个月按小时分成24个时段) // 电力峰谷分段 (12个月每个月按小时分成24个时段)
std::vector<std::vector<std::string>> vecElectPeriods; std::vector<std::vector<std::string>> vecElectPeriods;

View File

@@ -18,6 +18,8 @@ void Application::init()
// MQTT 数据结构 // MQTT 数据结构
MqttClient::loadDataStruct("assets/config/registeraddr.json"); MqttClient::loadDataStruct("assets/config/registeraddr.json");
// 设备读取寄存器的地址定义
Device::loadParamAddr("assets/config/monitoraddr.json");
// 设置数据库配置 // 设置数据库配置
DaoEntity::setOption(Config::option.database.host, DaoEntity::setOption(Config::option.database.host,
@@ -34,7 +36,7 @@ void Application::init()
// 连接数据库,读取基础信息 // 连接数据库,读取基础信息
// 初始化系统基础数据 // 初始化系统基础数据
appdata.init(); this->isInit = appdata.init();
// 创建设备处理线程 // 创建设备处理线程
std::thread([=]() { runThreadDevice(); }).detach(); std::thread([=]() { runThreadDevice(); }).detach();
@@ -47,11 +49,11 @@ void Application::init()
} }
}).detach(); }).detach();
// 创建主业务循环线程
std::thread([=]() { runThreadMain(); }).detach();
// 统计分析 // 统计分析
std::thread([=]() { runThreadStat(); }).detach(); std::thread([=]() { runThreadStat(); }).detach();
// 创建主业务循环线程
std::thread([=]() { runThreadMain(); }).detach();
} }
@@ -71,37 +73,38 @@ void Application::runThreadMain()
while (!isQuit) while (!isQuit)
{ {
//// 连接场站 if (!this->isInit) // 初始化失败
//static TimeTick ttStation; {
//if (ttStation.elapse(10000)) std::this_thread::sleep_for(std::chrono::milliseconds(10000));
//{ this->isInit = appdata.init();
// if (!mqttCli->isConnected) if (!this->isInit) { continue; }
// { }
// }
// else
// {
// for (auto& item: appdata.mapStation)
// {
// auto station = item.second;
// if (station && !station->isConnected)
// {
// std::string stationCode = station->code;
// std::vector<std::string> vecTopics = {
// "up/json" + stationCode + "/EMS_YX",
// "up/json" + stationCode + "/EMS_YC",
// "up/json" + stationCode + "/PCU_YX",
// "up/json" + stationCode + "/PCU_YC",
// };
// mqttCli->subscribe(vecTopics, [=](int id)
// {
// station->isConnected = (id == 0);
// });
// }
// break;
// }
// }
//}
static TimeTick ttMqtt;
// 检查 场站的 MQTT 连接
if (ttMqtt.elapse(10))
{
auto& optionMqtt = Config::option.mqtt;
if (!optionMqtt.host.empty())
{
for (auto& item : appdata.mapStation)
{
if (item.second)
{
item.second->initMqtt();
//item.second->polling();
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////
/// 召测
static TimeTick tt1;
if (tt1.elapse(10))
{
}
std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::this_thread::sleep_for(std::chrono::milliseconds(10));
} }
} }
@@ -131,6 +134,16 @@ void Application::runThreadStat()
{ {
//spdlog::info("保存历史数据倒计时: {}", 600 - offset); //spdlog::info("保存历史数据倒计时: {}", 600 - offset);
} }
for (auto& station : appdata.mapStation)
{
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
} }
} }

View File

@@ -33,6 +33,7 @@ public:
public: public:
bool isQuit = false; bool isQuit = false;
bool isInit = false;
// 登录的管理员信息 // 登录的管理员信息
Operator op; Operator op;

View File

@@ -7,6 +7,19 @@
#include <unordered_set> #include <unordered_set>
std::map<int, std::vector<DeviceParamAddr>> Device::s_mapDeviceParamAddr;
static std::vector<DeviceParamAddr>& GetDeviceParamAddrs(int deviceType)
{
static std::vector<DeviceParamAddr> vecAddrs = {};
auto iter = Device::s_mapDeviceParamAddr.find(deviceType);
if (iter != Device::s_mapDeviceParamAddr.end())
{
return iter->second;
}
return vecAddrs;
}
static std::unordered_set<int> g_setCacheDeviceType = {3, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110}; static std::unordered_set<int> g_setCacheDeviceType = {3, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110};
static bool CheckCacheType(int type) static bool CheckCacheType(int type)
{ {
@@ -16,30 +29,72 @@ static bool CheckCacheType(int type)
std::shared_ptr<Device> Device::create(Fields& fields) std::shared_ptr<Device> Device::create(Fields& fields)
{ {
auto device = std::make_shared<Device>(); auto device = std::make_shared<Device>();
device->deviceId = fields.get<int>("device_id"); device->setFields(fields);
device->type = fields.get<int>("type"); return device;
device->name = fields.value("name"); }
device->code = fields.value("code");
device->isOpen = fields.get<int>("is_open");
device->attrsJson = fields.value("attrs"); void Device::loadParamAddr(std::string filename)
device->category = fields.get<int>("category"); {
try
{
njson json;
if (!JSON::load(filename, json))
{
spdlog::error("[device] json load param addr error, filename={}", filename);
}
for (auto& jsonitem : json.items())
{
std::string key = jsonitem.key();
auto& jsonnodeItem = jsonitem.value();
spdlog::info(jsonnodeItem.dump());
int type = jsonnodeItem["deviceType"];
auto& vec = s_mapDeviceParamAddr[type];
for (auto& v : jsonnodeItem["addr_YC"])
{
std::string name = JSON::get<std::string>(v[0]);
std::string addr = JSON::get<std::string>(v[1]);
std::string defaultVal = JSON::get<std::string>(v[2]);
std::string unit = JSON::get<std::string>(v[3]);
float ratio = Utils::toFloat(JSON::get<string>(v[4]));
vec.push_back(DeviceParamAddr(name, addr, defaultVal, unit, ratio));
}
}
}
catch (nlohmann::json::parse_error& e)
{
spdlog::error("[device] parse [{}] error: ", filename, e.what());
}
}
void Device::setFields(Fields& fields)
{
fields.get("device_id", this->deviceId);
fields.get("type", this->type);
fields.get("name", this->name);
fields.get("code", this->code);
fields.get("is_open", this->isOpen);
fields.get("attrs", this->attrsJson);
fields.get("category", this->category);
// 解析属性的JSON字符串转换成键值对 // 解析属性的JSON字符串转换成键值对
njson jsonroot; njson jsonroot;
bool ret = JSON::parse(device->attrsJson, jsonroot); bool ret = JSON::parse(this->attrsJson, jsonroot);
if (!ret) // 解析错误 if (!ret) // 解析错误
{ {
spdlog::error("[device] device attr json parse error, device_id={}", device->deviceId); spdlog::error("[device] device attr json parse error, device_id={}", this->deviceId);
} }
else else
{ {
this->attrs.clear();
for (auto& [key, val] : jsonroot.items()) { for (auto& [key, val] : jsonroot.items()) {
std::string valType = val.type_name(); std::string valType = val.type_name();
if (valType == "string") { if (valType == "string") {
device->attrs.set(key, val.get<std::string>()); this->attrs.set(key, val.get<std::string>());
} }
else if (valType == "number") { else if (valType == "number") {
device->attrs.set(key, val.get<int>()); this->attrs.set(key, val.get<int>());
} }
else { else {
spdlog::error("[device] device attr unknown type: key={}, valtype={}", key, valType); spdlog::error("[device] device attr unknown type: key={}, valtype={}", key, valType);
@@ -47,22 +102,13 @@ std::shared_ptr<Device> Device::create(Fields& fields)
} }
} }
//int step = 600; auto& vecAddrs = GetDeviceParamAddrs(this->type);
//for (int i = 0; i*600<86400; ++i) for (auto& item: vecAddrs)
//{ {
// double voltage = double(Utils::random(20000, 30000))*0.01; this->mapMyParams[item.addr] = &item;
// double current = double(Utils::random(1000, 2000))*0.01; }
// device->mapCacheVoltage[i*step] = voltage;
// device->mapCacheCurrent[i*step] = current;
// device->mapCachePower[i*step] = voltage * current;
//}
// 启动通讯该函数中会自动判断isOpen状态选择是否进行通讯连接
//device->startComm();
return device;
} }
int Device::startComm() int Device::startComm()
{ {
if (!isOpen) if (!isOpen)
@@ -182,42 +228,47 @@ void Device::storeDB(int npos)
{ {
} }
void Device::setParam(std::string k, int v)
void Device::setParam(std::string k, std::string v)
{ {
mapParams[k] = v; float ratio = 1.0;
auto iter = mapMyParams.find(k);
if (iter != mapMyParams.end())
{
ratio = iter->second->ratio;
spdlog::info("[device] set param: {} {}={}, ratio={}", iter->second->name, k, v, ratio);
}
int precision = (ratio != 1.0f) ? 2 : 0;
mapParams[k] = Utils::toStr(v*ratio, precision);
if (type == 3 ) // 电表 if (type == 3 ) // 电表
{ {
if (k == "") this->err = Utils::toInt(v); if (k == "") this->err = v;
} }
else if (type == 101) // EMS else if (type == 101) // EMS
{ {
} }
else if (type == 102) // PCS else if (type == 102) // PCS
{ {
if (k == "0x1003") err = Utils::toInt(v); // 故障状态 R uint16 1故障0正常 0 0x1003 if (k == "0x1003") err = v; // 故障状态 R uint16 1故障0正常 0 0x1003
if (k == "0x1005") online = Utils::toInt(v); // 设备在线 R uint16 1在线0无效 1 0x1005 if (k == "0x1005") online = v; // 设备在线 R uint16 1在线0无效 1 0x1005
if (k == "0x1009") running = (v=="1" || v=="2"); //充放状态 R uint16 0待机, 1充电, 2放电, 3搁置 0 0x1009 if (k == "0x1009") running = (v==1 || v==2); //充放状态 R uint16 0待机, 1充电, 2放电, 3搁置 0 0x1009
} }
else if (type == 103) // PCU else if (type == 103) // PCU
{ {
if (k == "0x1002") err = Utils::toInt(v); //故障状态 R uint16 1故障0正常 0 0x1002 if (k == "0x1002") err = v; //故障状态 R uint16 1故障0正常 0 0x1002
if (k == "0x1004") online = Utils::toInt(v); //设备在线 R uint16 1在线0无效 1 0x1004 if (k == "0x1004") online = v; //设备在线 R uint16 1在线0无效 1 0x1004
if (k == "0x1006") running = Utils::toInt(v); //启停状态 R uint16 1开机0关机 1 0x1006 if (k == "0x1006") running = v; //启停状态 R uint16 1开机0关机 1 0x1006
} }
else if (type == 104) // BMS else if (type == 104) // BMS
{ {
if (k == "0x004A") { err = (v=="1"); online = 1; } //运行状态 R uint16 0 运行状态 0-正常 1-告警 2-保护 0x004A if (k == "0x004A") { err = (v==1); online = 1; } //运行状态 R uint16 0 运行状态 0-正常 1-告警 2-保护 0x004A
if (k == "0x004B") running = (v=="1" || v=="2"); //充放电状态 R uint16 0 0-待机 1-充电 2-放电 0x004B if (k == "0x004B") running = (v==1 || v==2); //充放电状态 R uint16 0 0-待机 1-充电 2-放电 0x004B
} }
else if (type == 105) // BCU else if (type == 105) // BCU
{ {
if (k == "0xA003") running = (v=="51" || v=="68"); //蓄电池充放电状态 R uint16 "0x11开路,0x22待机,0x33充电,0x44放电" 34 0xA003 if (k == "0xA003") running = (v==0x33 || v==0x44); //蓄电池充放电状态 R uint16 "0x11开路,0x22待机,0x33充电,0x44放电" 34 0xA003
if (k == "0xA004") err = (v=="85"); online=1; //电池组运行状态 R uint16 "0x11跳机,0x22待机,0x33放空,0x44充满,0x55预警,0x66正常" 102 0xA004 if (k == "0xA004") err = (v==0x55); online=1; //电池组运行状态 R uint16 "0x11跳机,0x22待机,0x33放空,0x44充满,0x55预警,0x66正常" 102 0xA004
} }
else if (type == 106) // 充电桩 else if (type == 106) // 充电桩
{ {
@@ -237,7 +288,6 @@ std::string Device::getParam(std::string k, std::string defaultVal)
return defaultVal; return defaultVal;
} }
void Device::getRuntimeParams(std::vector<std::pair<std::string, std::string>>& params) void Device::getRuntimeParams(std::vector<std::pair<std::string, std::string>>& params)
{ {
// 3 电表 // 3 电表
@@ -248,71 +298,23 @@ void Device::getRuntimeParams(std::vector<std::pair<std::string, std::string>>&
// 105 BCU // 105 BCU
// 106 充电桩 // 106 充电桩
// 109 光伏板 // 109 光伏板
auto& vecAddr = s_mapDeviceParamAddr[this->type];
for (auto& itemAddr: vecAddr)
if (this->type == 3)
{ {
params.push_back({"A相电压", getParam("0x000B", "0.0") + " V"}); params.push_back({itemAddr.name, getParam(itemAddr.addr, itemAddr.defaultVal) + itemAddr.unit});
params.push_back({"A相电流", getParam("0x000D", "0.0") + " A"}); }
params.push_back({"B相电压", getParam("0x000F", "0.0") + " V"}); }
params.push_back({"B相电流", getParam("0x0011", "0.0") + " A"});
params.push_back({"C相电压", getParam("0x0013", "0.0") + " V"}); void Device::getRuntimeParams1(std::vector<std::pair<std::string, std::string>>& params)
params.push_back({"C相电流", getParam("0x0015", "0.0") + " A"}); {
} if (type == 106)
else if (this->type == 101) // EMS {
{ params.push_back({"需求电压", getParam("31072", "0.0") + " V"});
params.push_back({"A相电压", getParam("0x107E", "0.0") + " V"}); params.push_back({"需求电流", getParam("31074", "0.0") + " A"});
params.push_back({"A相电流", getParam("0x1084", "0.0") + " A"}); params.push_back({"需求功率", getParam("31076", "0.0") + " kW"});
params.push_back({"B相电压", getParam("0x1080", "0.0") + " V"}); params.push_back({"功率限值", getParam("31078", "0.0") + " kW"});
params.push_back({"B相电流", getParam("0x1086", "0.0") + " A"}); params.push_back({"输出电压", getParam("31080", "0.0") + " V"});
params.push_back({"C相电压", getParam("0x1082", "0.0") + " V"}); params.push_back({"输出电流", getParam("31082", "0.0") + " A"});
params.push_back({"C相电流", getParam("0x1088", "0.0") + " A"}); params.push_back({"输出功率", getParam("31084", "0.0") + " kW"});
}
else if (this->type == 102) // PCS
{
params.push_back({"A相电压", getParam("0x0010", "0.0") + " V"});
params.push_back({"A相电流", getParam("0x0019", "0.0") + " A"});
params.push_back({"B相电压", getParam("0x0011", "0.0") + " V"});
params.push_back({"B相电流", getParam("0x001A", "0.0") + " A"});
params.push_back({"C相电压", getParam("0x0011", "0.0") + " V"});
params.push_back({"C相电流", getParam("0x001B", "0.0") + " A"});
}
else if (this->type == 103) // PCU
{
params.push_back({"A相电压", getParam("0x0013", "0.0") + " V"});
params.push_back({"A相电流", getParam("0x001C", "0.0") + " A"});
params.push_back({"B相电压", getParam("0x0014", "0.0") + " V"});
params.push_back({"B相电流", getParam("0x001D", "0.0") + " A"});
params.push_back({"C相电压", getParam("0x0015", "0.0") + " V"});
params.push_back({"C相电流", getParam("0x001E", "0.0") + " A"});
}
else if (this->type == 104) // BMS
{
params.push_back({"SOC", getParam("0x0001", "0") + " %"});
params.push_back({"SOH", getParam("0x0002", "0") + " %"});
params.push_back({"电压", getParam("0x0003", "0.0") + " V"});
params.push_back({"电流", getParam("0x0005", "0.0") + " A"});
params.push_back({"单体最大电压", getParam("0x0021", "0.0") + " V"});
params.push_back({"单体最小电压", getParam("0x0024", "0.0") + " V"});
params.push_back({"单体最大温度", getParam("0x0029", "0.0") + ""});
params.push_back({"单体最小温度", getParam("0x002C", "0.0") + ""});
}
else if (this->type == 105) // BCU
{
params.push_back({"簇电压", getParam("0x0003", "0.0") + " V"});
params.push_back({"簇电流", getParam("0x0005", "0") + " A"});
params.push_back({"簇温度", getParam("0x0007", "0.0") + ""});
params.push_back({"簇电阻", getParam("0x0009", "0.0") + " Ω"});
params.push_back({"簇SOC", getParam("0x000B", "0") + " %"});
params.push_back({"簇SOH", getParam("0x000C", "0") + " %"});
}
else
{
params.push_back({"额定电压", getParam("0x0001", "0.0") + " V"});
params.push_back({"实时电压", getParam("0x0001", "0.0") + " V"});
params.push_back({"额定电流", getParam("0x0001", "0.0") + " A"});
params.push_back({"实时电流", getParam("0x0001", "0.0") + " A"});
params.push_back({"额定功率", getParam("0x0001", "0.0") + " W"});
params.push_back({"实时功率", getParam("0x0001", "0.0") + " W"});
} }
} }

View File

@@ -1,20 +1,41 @@
#pragma once #pragma once
#include <string> #include <set>
#include <map> #include <map>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <string>
#include <unordered_map> #include <unordered_map>
#include "common/Fields.h" #include "common/Fields.h"
class CommEntity; class CommEntity;
struct DeviceParamAddr
{
std::string name;
std::string addr;
std::string defaultVal;
std::string unit;
float ratio {1.0};
DeviceParamAddr() {};
DeviceParamAddr(std::string name, std::string addr, std::string defaultVal, std::string unit, float ratio=1.0f)
: name(name), addr(addr), defaultVal(defaultVal), unit(unit), ratio(ratio)
{
if (this->ratio == 0.0)
{
this->ratio = 1.0f;
}
};
};
class Device class Device
{ {
public: public:
static std::shared_ptr<Device> create(Fields& fields); static std::shared_ptr<Device> create(Fields& fields);
static void loadParamAddr(std::string filename);
void setFields(Fields& fields);
int startComm(); int startComm();
@@ -28,13 +49,15 @@ public:
bool cache(int npos); bool cache(int npos);
void storeDB(int npos); void storeDB(int npos);
void setParam(std::string k, std::string v); void setParam(std::string k, int v);
std::string getParam(std::string k, std::string defaultVal = ""); std::string getParam(std::string k, std::string defaultVal = "");
void getRuntimeParams(std::vector<std::pair<std::string, std::string>>& params); void getRuntimeParams(std::vector<std::pair<std::string, std::string>>& params);
void getRuntimeParams1(std::vector<std::pair<std::string, std::string>>& params);
public: public:
static std::map<int, std::vector<DeviceParamAddr>> s_mapDeviceParamAddr;
int deviceId = -1; int deviceId = -1;
int type = -1; int type = -1;
std::string name; std::string name;
@@ -58,4 +81,8 @@ public:
std::map<int, double> mapCacheCurrent; std::map<int, double> mapCacheCurrent;
std::map<int, double> mapCachePower; std::map<int, double> mapCachePower;
std::map<std::string, std::string> mapParams; std::map<std::string, std::string> mapParams;
std::map<std::string, DeviceParamAddr*> mapMyParams;
}; };

View File

@@ -0,0 +1,146 @@
#include "Policy.h"
#include "common/Spdlogger.h"
#include "Utils.h"
void SysPolicy::setFields(Fields& fields)
{
this->policyId = fields.get<int>("policy_id");
this->type = fields.get<int>("policy_type");
this->name = fields.value("policy_name");
this->value = fields.value("value");
this->parseValue(value);
}
/// type=1: 峰谷套利
static void ParseJsonType1(njson& json)
{
}
void SysPolicy::getGatewayJsonPrice(njson& json)
{
}
// 1峰谷套利2配网增容3应急供电4并网保电5自定时段
void SysPolicy::parseValue(std::string jsonstr)
{
njson jsonroot;
if (!JSON::parse(jsonstr, jsonroot))
{
spdlog::error("[policy] json parse policy value error, policy_id={}, value={}", policyId, jsonstr);
return;
}
// 读取电价
if (jsonroot.contains("price"))
{
auto& jsonArrayPrice = jsonroot["price"];
for (int i = 0; i<vecPrice.size(); ++i)
{
if (i<jsonArrayPrice.size())
{
vecPrice[i] = Utils::toFloat(jsonArrayPrice[i].get<std::string>());
}
}
}
if (this->type == 1 || this->type == 5)
{
this->parseJsonPeriods(jsonroot);
}
}
void SysPolicy::parseJsonPeriods(njson& jsonroot)
{
if (!jsonroot.contains("period"))
{
spdlog::error("[policy] json parse policy value error, [period] is not exist, value={}", jsonroot.dump());
return;
}
auto& json = jsonroot["period"];
if (!json.is_array())
{
spdlog::error("[policy] json parse policy value error, [period] is not array, value={}", json.dump());
return;
}
// 1: 谷234
if (this->type == 1) // 峰谷套利
{
vecPeriods1.clear();
for (int i = 0; i<json.size() && i<12; ++i) // 月份信息最多12个月
{
if (json[i].size() > 0)
{
vecPeriods1.push_back(std::vector<std::pair<std::string, std::string>>());
for (auto& itemMonth: json[i])
{
if (itemMonth.size() >=2) { vecPeriods1[i].push_back({itemMonth[0], itemMonth[1]}); }
}
}
}
}
else if (this->type == 5)
{
//{
// "period":[
// {"charge_time":[],"discharge_time":[],"charge_power":"","discharge_power":""},
// {"charge_time":[],"discharge_time":[],"charge_power":"","discharge_power":""}
// ],
// "price":["0.00","0.00","0.00","0.00"]
//}
vecPeriods1.clear();
for (int i = 0; i<json.size(); ++i) // 一充一放或二充二放
{
vecPeriods1.push_back(std::vector<std::pair<std::string, std::string>>());
auto& item = json[i];
if (item.contains("charge_time") && item["charge_time"].size() >= 2)
{
auto& jsonP = item["charge_time"];
vecPeriods1[i].push_back({jsonP[0], ""}); // 第一/二次充电开始
vecPeriods1[i].push_back({jsonP[1], ""}); // 第一/二次充电结束
}
if (item.contains("discharge_time") && item["discharge_time"].size() >= 2)
{
auto& jsonP = item["discharge_time"];
vecPeriods1[i].push_back({jsonP[0], ""}); // 第一/二次放电开始
vecPeriods1[i].push_back({jsonP[1], ""}); // 第一/二次放电结束
}
}
}
}
static void PeriodsTimeStrToInt(std::string str, int& h, int& m)
{
int pos = str.find(":");
if (pos != std::string::npos)
{
h = Utils::toInt(str.substr(0, pos));
m = Utils::toInt(str.substr(pos+1));
}
}
void SysPolicy::getGatewayJsonPeriods(njson& json)
{
if (type == 1 || type == 5)
{
// std::vector<std::vector<std::pair<std::string, std::string>>>
for (auto& itemMonth: vecPeriods1)
{
njson jsonArrayMonth = njson::array();
for (auto& item: itemMonth)
{
int h = 0; int m = 0;
PeriodsTimeStrToInt(item.first, h, m);
int p = 1;
if (item.second == "") p = 1;
else if (item.second == "") p = 2;
else if (item.second == "") p = 3;
else if (item.second == "") p = 4;
jsonArrayMonth.push_back({h, m, p});
}
json.push_back(jsonArrayMonth);
}
}
}

View File

@@ -1,15 +1,32 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
#include "common/Fields.h" #include "common/Fields.h"
#include "common/JsonN.h"
class MyPolicy class SysPolicy
{ {
public: public:
int policyId {0}; int policyId {0};
// 1峰谷套利2配网增容3应急供电4并网保电5自定时段
int type {0}; int type {0};
std::string name; std::string name;
std::string value; std::string value;
int isOpen {0}; int isOpen {1};
Fields fields; Fields fields;
std::vector<float> vecPrice {0.0f, 0.0f, 0.0f, 0.0f};
std::vector<std::vector<std::pair<std::string, std::string>>> vecPeriods1;
void setFields(Fields& fields);
void parseValue(std::string jsonstr);
void parseJsonPeriods(njson& json);
void getGatewayJsonPrice(njson& json);
void getGatewayJsonPeriods(njson& json);
}; };

View File

@@ -7,6 +7,7 @@
#include "common/Utils.h" #include "common/Utils.h"
#include "protocol/MqttEntity.h" #include "protocol/MqttEntity.h"
#include "common/JsonN.h" #include "common/JsonN.h"
#include "app/Config.h"
Station::Station() : stationId(0) Station::Station() : stationId(0)
{ {
@@ -35,10 +36,13 @@ void Station::setFields(Fields& fields)
{ {
this->stationId = fields.get<int>(DMStation::STATION_ID); this->stationId = fields.get<int>(DMStation::STATION_ID);
this->name = fields.value(DMStation::NAME); this->name = fields.value(DMStation::NAME);
this->energyCapacity = fields.get<double>(DMStation::CAPACITY); this->capacity = fields.get<double>(DMStation::CAPACITY);
this->workModeId = fields.get<int>(DMStation::WORK_MODE); this->workModeId = fields.get<int>(DMStation::WORK_MODE);
this->code = fields.value(DMStation::CODE); this->code = fields.value(DMStation::CODE);
this->status = fields.get<int>(DMStation::STATUS); this->status = fields.get<int>(DMStation::STATUS);
this->operationDate = fields.value(DMStation::OPERATION_DATE);
this->policy.setFields(fields);
} }
void Station::addDevice(int deviceId, std::shared_ptr<Device> device) void Station::addDevice(int deviceId, std::shared_ptr<Device> device)
@@ -47,6 +51,22 @@ void Station::addDevice(int deviceId, std::shared_ptr<Device> device)
mapDeviceGroup[device->category].push_back(device); mapDeviceGroup[device->category].push_back(device);
} }
void Station::addDevice(Fields& fields)
{
int deviceId = fields.get<int>(DMDevice::DEVICE_ID);
int stationId = fields.get<int>(DMDevice::STATION_ID);
if (mapDevice.find(deviceId) != mapDevice.end())
{
mapDevice[deviceId]->setFields(fields);
}
else
{
auto device = Device::create(fields);
mapDevice[deviceId] = device;
mapDeviceGroup[device->category].push_back(device);
}
}
std::shared_ptr<Device> Station::getDevice(int deviceId) std::shared_ptr<Device> Station::getDevice(int deviceId)
{ {
auto iter = mapDevice.find(deviceId); auto iter = mapDevice.find(deviceId);
@@ -82,8 +102,13 @@ void Station::getDeviceByType(int deviceType, std::vector<std::shared_ptr<Device
} }
} }
int Station::getDeviceNumByGroup(int category) int Station::getDeviceCount(int category)
{ {
auto iter = mapDeviceGroup.find(category);
if (iter != mapDeviceGroup.end())
{
return iter->second.size();
}
return 0; return 0;
} }
@@ -159,3 +184,48 @@ void Station::writeRuntimeData(std::string dt, int npos)
} }
} }
} }
void Station::initMqtt()
{
if (status!=0 && mqttCli)
{
auto& optionMqtt = Config::option.mqtt;
mqttCli->init(optionMqtt.host, code, optionMqtt.username, optionMqtt.password);
}
}
void Station::polling()
{
if (mqttCli)
{
mqttCli->polling();
}
}
void Station::setGarewayWorkMode()
{
if (!mqttCli)
{
return;
}
njson json;
json["ts"] = Utils::time();
json["no"] = 1; // 设备编号
json["40001"] = this->workModeId;
if (policy.type == 1)
{
json["40002"] = njson::array(); // 峰谷套利
policy.getGatewayJsonPeriods(json["40002"]);
}
else if (policy.type == 5)
{
json["40021"] = njson::array(); // 自定时段
policy.getGatewayJsonPeriods(json["40021"]);
}
std::string text = json.dump();
spdlog::info(text);
mqttCli->publish("Gateway_YT", text);
}

View File

@@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include "common/Fields.h" #include "common/Fields.h"
#include "Policy.h"
class Device; class Device;
class MqttClient; class MqttClient;
@@ -95,48 +96,53 @@ public:
void setFields(Fields& fields); void setFields(Fields& fields);
void addDevice(int deviceId, std::shared_ptr<Device> device); void addDevice(int deviceId, std::shared_ptr<Device> device);
void addDevice(Fields& fields);
std::shared_ptr<Device> getDevice(int deviceId); std::shared_ptr<Device> getDevice(int deviceId);
std::shared_ptr<Device> getDeviceByType(int deviceType, std::string code); std::shared_ptr<Device> getDeviceByType(int deviceType, std::string code);
void getDeviceByType(int typeId, std::vector<std::shared_ptr<Device>>& res); void getDeviceByType(int typeId, std::vector<std::shared_ptr<Device>>& res);
int getDeviceNumByGroup(int category); int getDeviceCount(int category);
void getDeviceByGroup(int category, std::vector<std::shared_ptr<Device>>& res); void getDeviceByGroup(int category, std::vector<std::shared_ptr<Device>>& res);
void setWorkMode(int modeId); void setWorkMode(int modeId);
void setPolicy(int policyId); void setPolicy(int policyId);
void writeRuntimeData(std::string dt, int npos); void writeRuntimeData(std::string dt, int npos);
void initMqtt();
void polling();
void setGarewayWorkMode();
public: public:
int stationId {}; int stationId {};
std::string name; std::string name;
std::string code; std::string code;
bool isOpen {false};
int status {0}; int status {0};
std::string operationDate;
SysPolicy policy;
bool isConnected {false}; bool isConnected {false};
int workModeId {}; // 运行模式 int workModeId {}; // 运行模式
int runPolicyId {}; // 运行策略 int runPolicyId {}; // 运行策略
// 储能容量
double energyCapacity {};
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// === 系统统计 === /// === 系统统计 ===
// 累计发电量单位kWh // 累计发电量单位kWh
double electGenTatal {}; double electGenTotal {};
// 累计入网电量单位kWh // 累计入网电量单位kWh
double electGridTotal {}; double electGridTotal {};
// 累计收益,单位:元 // 累计收益,单位:元
double incomeTotal {}; double incomeTotal {};
// 碳减排量, 单位:吨
double ccers {};
// 累计储能充电电量 // 累计储能充电电量
double electStorageIn {}; double electStorageIn {};
// 累计储能放电电量 // 累计储能放电电量
double electStorageOut {}; double electStorageOut {};
// 储能容量
double capacity {};
/////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////
/// === 日统计 === /// === 日统计 ===
double storageIn {}; // 储能充电电量 double storageIn {}; // 储能充电电量

View File

@@ -22,7 +22,7 @@ public:
Fields() {}; Fields() {};
template <typename T> template <typename T>
void set(string key, T val, int precision=6) void set(string key, T val, int precision=2)
{ {
stringstream ss; stringstream ss;
ss.precision(precision); ss.precision(precision);
@@ -31,7 +31,7 @@ public:
} }
template <typename T> template <typename T>
T get(string key, int precision = 6) T get(string key, int precision = 2)
{ {
T val {}; T val {};
auto iter = mapFields.find(key); auto iter = mapFields.find(key);
@@ -44,6 +44,18 @@ public:
return val; return val;
} }
template <typename T>
void get(string key, T& val, int precision = 2)
{
auto iter = mapFields.find(key);
if (iter != mapFields.end())
{
stringstream ss(iter->second);
ss.precision(precision);
ss >> val;
}
}
/** /**
* 获取值 * 获取值
* @param: [string key] 索引名称 * @param: [string key] 索引名称

View File

@@ -99,10 +99,10 @@ public:
if (t !=0) { tickMS_ = Utils::time(); } if (t !=0) { tickMS_ = Utils::time(); }
} }
bool elapse(int64_t ms, bool reset = true) bool elapse(int64_t second, bool reset = true)
{ {
auto tick_now = Utils::time(); auto tick_now = Utils::time();
bool res = tick_now - tickMS_ > ms; bool res = tick_now - tickMS_ > second;
if (res && reset) if (res && reset)
{ {
tickMS_ = tick_now; tickMS_ = tick_now;

View File

@@ -280,7 +280,7 @@ Errcode DAO::deleteUserById(std::string userId)
Errcode DAO::queryPermissionList(PageInfo& pageInfo, vector<Fields>& result) Errcode DAO::queryPermissionList(PageInfo& pageInfo, vector<Fields>& result)
{ {
std::string sqlFrom = "FROM " + DMPermission::TABLENAME; std::string sqlFrom = "FROM permission WHERE permission.parent_id IS NULL OR permission.parent_id=''";
return QueryPagination("*", sqlFrom, pageInfo, result); return QueryPagination("*", sqlFrom, pageInfo, result);
} }
@@ -343,14 +343,31 @@ Errcode DAO::insertRole(Fields& params)
if (err == Errcode::OK && !permission.empty()) if (err == Errcode::OK && !permission.empty())
{ {
// 查询获取 roleId njson jsonarray;
std::vector<Fields> res; if (JSON::parse(permission, jsonarray))
std::string sql = "SELECT * FROM " + DMRole::TABLENAME + " WHERE name='" + name + "';";
err = DAO::exec(dao, sql, res);
if (err == Errcode::OK && res.size() > 0)
{ {
//std::string roleId = res[0].value("role_id"); // 查询获取 roleId
//err = DAO::updateRolePermission(dao, roleId, permission); std::vector<Fields> res;
std::string sql = "SELECT * FROM " + DMRole::TABLENAME + " WHERE name='" + name + "';";
err = DAO::exec(dao, sql, res);
if (err == Errcode::OK && res.size() > 0)
{
std::string roleId = res[0].value("role_id");
std::vector<Fields> vecFields;
for (auto& item: jsonarray)
{
Fields fields;
fields.set("role_id", roleId);
fields.set("permission_id", item["permission_id"].get<std::string>());
fields.set("is_open", item["is_open"].get<std::string>());
fields.set("is_view", item["is_view"].get<std::string>());
fields.set("is_add", item["is_add"].get<std::string>());
fields.set("is_edit", item["is_edit"].get<std::string>());
fields.set("is_del", item["is_del"].get<std::string>());
vecFields.push_back(fields);
}
err = DAO::updateRolePermission(dao, roleId, vecFields);
}
} }
} }
return err; return err;

View File

@@ -113,7 +113,6 @@ public:
// === 统计数据管理 === // === 统计数据管理 ===
static Errcode queryStatDataList(std::shared_ptr<DaoEntity> dao, std::string startDate, std::string endDate, vector<Fields>& result); static Errcode queryStatDataList(std::shared_ptr<DaoEntity> dao, std::string startDate, std::string endDate, vector<Fields>& result);
static Errcode queryWorkModeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result); static Errcode queryWorkModeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result);
static Errcode queryPolicyTypeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result); static Errcode queryPolicyTypeDef(std::shared_ptr<DaoEntity> dao, vector<Fields>& result);

View File

@@ -93,6 +93,7 @@ namespace DMStation
const string POLICY_ID = "policy_id"; const string POLICY_ID = "policy_id";
const string CODE = "code"; const string CODE = "code";
const string ATTR = "attr"; const string ATTR = "attr";
const string OPERATION_DATE = "operation_date";
} }
namespace DMDefDeviceType namespace DMDefDeviceType

View File

@@ -1,7 +1,6 @@
#include "MysqlClient.h" #include "MysqlClient.h"
#include "common/Utils.h" #include "common/Utils.h"
//#include "Spdlogger.h" #include "Spdlogger.h"
#include "Logger.h"
#include <chrono> #include <chrono>
using namespace std; using namespace std;
@@ -28,7 +27,7 @@ int MysqlClient::conn()
{ {
return 0; return 0;
} }
if (GetTimestamp() - g_tickErr <= 5) if (GetTimestamp() - g_tickErr <= 10)
{ {
return 1; return 1;
} }
@@ -73,19 +72,19 @@ static int MysqlQuery(MYSQL* mysql, const std::string& sql)
int err = 0; int err = 0;
if (!mysql) if (!mysql)
{ {
XLOGE() << "Mysql exec error, database is not connected."; spdlog::error("Mysql exec error, database is not connected.");
return err; return err;
} }
if (sql.empty()) if (sql.empty())
{ {
XLOGE() << "Mysql exec error, sql is empty."; spdlog::error("Mysql exec error, sql is empty.");
return err; return err;
} }
err = mysql_query(mysql, sql.c_str()); err = mysql_query(mysql, sql.c_str());
if (0 != err) if (0 != err)
{ {
err = mysql_errno(mysql); err = mysql_errno(mysql);
XLOGE() << "Mysql exec error: " << err << "," << mysql_error(mysql) << ", sql=" << sql; spdlog::error("Mysql exec error: {}, {}, sql={}", err, mysql_error(mysql), sql);
return err; return err;
} }
return err; return err;

View File

@@ -118,22 +118,22 @@ void memberJsonTest()
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
// 设置控制台输出为 UTF-8 编码 // 设置控制台输出为 UTF-8 编码
SetConsoleOutputCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);
// 设置控制台输入为 UTF-8 编码(如果需要输入中文) // 设置控制台输入为 UTF-8 编码(如果需要输入中文)
SetConsoleCP(CP_UTF8); SetConsoleCP(CP_UTF8);
// 初始化日志
Spdlogger::init(spdlog::level::debug, ""); Spdlogger::init(spdlog::level::debug, "");
spdlog::info("[main] start ... ======================================================================"); spdlog::info("[main] start ... ======================================================================");
spdlog::info(""); njson json;
json = {1, 2, 3, 4};
std::cout << Snowflake::instance().getId() << std::endl; spdlog::info(json.dump());
for (int i = 0; i<=10; ++i) {
std::cout << Snowflake::instance().getId() << std::endl;
}
// 运行后台服务 // 运行后台服务
Application::instance().init(); Application::instance().init();

View File

@@ -39,8 +39,8 @@ static void JsonToFields(njson& json, std::vector<std::string> vecKeys, Fields&
case njson::value_t::number_unsigned: { fields.set(key, json[key].get<int>()); } break; case njson::value_t::number_unsigned: { fields.set(key, json[key].get<int>()); } break;
case njson::value_t::number_float: { fields.set(key, json[key].get<float>()); } break; case njson::value_t::number_float: { fields.set(key, json[key].get<float>()); } break;
case njson::value_t::null: {} break; case njson::value_t::null: {} break;
case njson::value_t::object: {} break; case njson::value_t::object: { fields.set(key, json[key].dump()); } break;
case njson::value_t::array: {} break; case njson::value_t::array: { fields.set(key, json[key].dump()); } break;
case njson::value_t::binary: {} break; case njson::value_t::binary: {} break;
case njson::value_t::discarded: {} break; case njson::value_t::discarded: {} break;
default: default:
@@ -165,6 +165,7 @@ static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet =
{"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {})}, {"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {})},
{"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {})}, {"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {})},
{"/queryStatStation", HandlerOptions(&HttpEntity::queryStatStation, {})},
{"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {})}, {"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {})},
{"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {})}, {"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {})},
{"/queryStatCharts", HandlerOptions(&HttpEntity::queryStatCharts, {})}, {"/queryStatCharts", HandlerOptions(&HttpEntity::queryStatCharts, {})},
@@ -340,7 +341,7 @@ Errcode HttpEntity::login(const httplib::Request& req, njson& json, std::string&
json["permission"] = nodePermission; json["permission"] = nodePermission;
} }
DAO::insertSystemLogUser(token, "用户登录:" + ErrcodeStr(err), (err==Errcode::OK) ? 0: 1); DAO::insertSystemLogUser(token, "用户登录:" + ErrcodeStr(err), (err==Errcode::OK) ? 1: 0);
return err; return err;
} }
@@ -357,7 +358,7 @@ Errcode HttpEntity::queryUserList(const httplib::Request& req, njson& json, std:
{ {
HttpHelper::setPagination(pageinfo, result, json); HttpHelper::setPagination(pageinfo, result, json);
} }
DAO::insertSystemLogUser(token, "查询用户列表:" + ErrcodeStr(err), (err==Errcode::OK) ? 0 : 1); //DAO::insertSystemLogUser(token, "查询用户列表:" + ErrcodeStr(err), (err==Errcode::OK) ? 1 : 0);
return err; return err;
} }
@@ -390,6 +391,38 @@ Errcode HttpEntity::queryPermissionList(const httplib::Request& req, njson& json
std::vector<Fields> result; std::vector<Fields> result;
auto err = DAO::queryPermissionList(pageinfo, result); auto err = DAO::queryPermissionList(pageinfo, result);
HttpHelper::setPagination(pageinfo, result, json); HttpHelper::setPagination(pageinfo, result, json);
// 查询所有的角色权限关联
if (err == Errcode::OK)
{
std::map<std::string, int> mapP;
for (int i = 0; i<result.size(); ++i)
{
auto& item = result[i];
std::string id = item.value("permission_id");
mapP[id] = json["data"].size() - 1;
}
std::vector<Fields> vecSubPermission;
DaoEntity::execOnce("SELECT * FROM permission WHERE permission.parent_id IS NOT NULL AND permission.parent_id!='';", vecSubPermission);
for (int i = 0; i<vecSubPermission.size(); ++i)
{
auto& item = vecSubPermission[i];
std::string parentId = item.value("parent_id");
std::string id = item.value("permission_id");
if (!parentId.empty())
{
if (mapP.count(parentId) > 0)
{
int index = mapP[parentId];
njson jsonnode;
FieldsToJson(item, jsonnode);
json["data"][index]["children"].push_back(jsonnode);
}
}
}
}
return err; return err;
} }
@@ -423,6 +456,8 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
std::vector<Fields> result; std::vector<Fields> result;
auto err = DAO::queryRoleList(pageinfo, result); auto err = DAO::queryRoleList(pageinfo, result);
HttpHelper::setPagination(pageinfo, result, json);
// 查询所有的角色权限关联 // 查询所有的角色权限关联
if (err == Errcode::OK) if (err == Errcode::OK)
{ {
@@ -432,8 +467,8 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
{ {
return err; return err;
} }
std::map<std::string, std::vector<Fields>> mapP;
std::map<std::string, std::vector<Fields>> mapP;
for (int i = 0; i<vecPermission.size(); ++i) for (int i = 0; i<vecPermission.size(); ++i)
{ {
auto& item = vecPermission[i]; auto& item = vecPermission[i];
@@ -444,7 +479,6 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
mapP[roleId].push_back(vecPermission[i]); mapP[roleId].push_back(vecPermission[i]);
} }
HttpHelper::setPagination(pageinfo, result, json);
for (auto& item : json["data"]) for (auto& item : json["data"])
{ {
auto jsonpermission = njson::array(); auto jsonpermission = njson::array();
@@ -487,6 +521,14 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
return err; return err;
} }
Errcode HttpEntity::queryRolePermission(const httplib::Request& req, njson& json, std::string& errmsg)
{
Fields params;
GetRequestParam(req, {"role_id"}, params);
if (!params.contains("role_id")) { errmsg = "缺少参数[role_id]"; return Errcode::ERR_PARAM; }
return Errcode::OK;
}
Errcode HttpEntity::insertRole(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::insertRole(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
Fields params; Fields params;
@@ -496,33 +538,34 @@ Errcode HttpEntity::insertRole(const httplib::Request& req, njson& json, std::st
Errcode HttpEntity::updateRole(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::updateRole(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
Fields params; Fields params;
//GetRequestParam(req, {"role_id", "name", "describe", "is_open", "permission"}, params); GetRequestParam(req, {"role_id", "name", "describe", "is_open", "permission"}, params);
njson jsonparam;
if (!JSON::parse(req.body, jsonparam))
{
return Errcode::ERR_PARAM;
}
JsonToFields(jsonparam, {"role_id", "name", "describe", "is_open"}, params);
auto roleId = params.value("role_id"); auto roleId = params.value("role_id");
std::string permission = params.remove("permission");
auto dao = DaoEntity::create(""); auto dao = DaoEntity::create("");
auto err = DAO::updateRoleById(dao, params); auto err = Errcode::OK;
if (err == Errcode::OK && jsonparam.contains("permission")) if (params.size() > 1)
{ {
if (jsonparam["permission"].is_array()) err = DAO::updateRoleById(dao, params);
}
if (err == Errcode::OK && !permission.empty())
{
njson jsonarray;
if (JSON::parse(permission, jsonarray))
{ {
std::vector<Fields> vecFields;
auto& jsonPermission = jsonparam["permission"]; for (auto& item: jsonarray)
std::vector<Fields> vecFields(jsonPermission.size());
int i = 0;
for (auto& item: jsonPermission)
{ {
auto& fields = vecFields[i]; Fields fields;
i++;
JsonToFields(item, {"permission_id", "is_add", "is_del", "is_edit", "is_view"}, fields);
fields.set("role_id", roleId); fields.set("role_id", roleId);
fields.set("permission_id", item["permission_id"].get<std::string>());
fields.set("is_open", item["is_open"].get<std::string>());
fields.set("is_view", item["is_view"].get<std::string>());
fields.set("is_add", item["is_add"].get<std::string>());
fields.set("is_edit", item["is_edit"].get<std::string>());
fields.set("is_del", item["is_del"].get<std::string>());
vecFields.push_back(fields);
} }
err = DAO::updateRolePermission(dao, roleId, vecFields); err = DAO::updateRolePermission(dao, roleId, vecFields);
} }
@@ -558,12 +601,38 @@ Errcode HttpEntity::insertStation(const httplib::Request& req, njson& json, std:
Errcode HttpEntity::updateStation(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::updateStation(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
Fields params; Fields params;
GetRequestParam(req, {"station_id", "name", "address", "lon", "lat", "tel", "capacity", "status", "work_mode"}, params); GetRequestParam(req, {"station_id", "name", "address", "lon", "lat", "tel", "capacity", "status", "work_mode", "policy_id"}, params);
std::string stationId = params.value("station_id");
params.check("capacity", "", "0.0"); params.check("capacity", "", "0.0");
params.check("lon", "", "0.0"); params.check("lon", "", "0.0");
params.check("lat", "", "0.0"); params.check("lat", "", "0.0");
params.check("status", "", "1"); params.check("status", "", "1");
return DAO::updateStationById(params); Errcode err = DAO::updateStationById(params);
if (err == Errcode::OK)
{
std::string sql = "SELECT s.*, p.name policy_name, p.`type` policy_type, p.value FROM station s LEFT JOIN policy p ON s.policy_id=p.policy_id"
" WHERE s.station_id='" + stationId + "';";
std::vector<Fields> result;
int ret = DaoEntity::execOnce(sql, result);
if (ret != 0)
{
spdlog::error("[http] update station success, set station cache error, station_id={}", stationId);
}
else
{
if (result.size() > 0)
{
auto station = Application::data().getStation(Utils::toInt(stationId));
if (station)
{
station->setFields(result[0]);
station->setGarewayWorkMode();
}
}
}
}
return err;
}; };
Errcode HttpEntity::deleteStation(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::deleteStation(const httplib::Request& req, njson& json, std::string& errmsg)
@@ -704,13 +773,31 @@ Errcode HttpEntity::insertDevice(const httplib::Request& req, njson& json, std::
{ {
Fields params; Fields params;
GetRequestParam(req, {"station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params); GetRequestParam(req, {"station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params);
return DAO::insertDevice(params); if (!params.contains("station_id")) { errmsg = "缺少参数[station_id]"; return Errcode::ERR_PARAM; }
Errcode err = DAO::insertDevice(params);
if (err == Errcode::OK)
{
int stationId = params.get<int>("station_id");
auto station = Application::data().getStation(stationId);
if (station) { station->addDevice(params); }
}
return err;
}; };
Errcode HttpEntity::updateDevice(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::updateDevice(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
Fields params; Fields params;
GetRequestParam(req, {"device_id", "station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params); GetRequestParam(req, {"device_id", "station_id", "type", "name", "code", "model", "factory", "factory_tel", "is_open", "attrs"}, params);
return DAO::updateDeviceById(params);
Errcode err = DAO::updateDeviceById(params);
if (err == Errcode::OK)
{
int stationId = params.get<int>("station_id");
auto station = Application::data().getStation(stationId);
if (station) { station->addDevice(params); }
}
return err;
}; };
Errcode HttpEntity::deleteDevice(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::deleteDevice(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
@@ -737,37 +824,50 @@ Errcode HttpEntity::queryDevicByCategory(const httplib::Request& req, njson& jso
njson jsondata = njson::array(); njson jsondata = njson::array();
auto station = Application::data().getStation(stationId); auto station = Application::data().getStation(stationId);
if (station) if (station && station->status == 1)
{ {
std::vector<std::shared_ptr<Device>> vecDevice; std::vector<std::shared_ptr<Device>> vecDevice;
station->getDeviceByGroup(category, vecDevice); station->getDeviceByGroup(category, vecDevice);
for(auto& device: vecDevice) for(auto& device: vecDevice)
{ {
njson jsonnode; if (device->isOpen)
jsonnode["stationId"] = stationId;
jsonnode["category"] = category;
jsonnode["device_id"] = device->deviceId;
jsonnode["name"] = device->name;
jsonnode["code"] = device->code;
jsonnode["type"] = device->type;
jsonnode["typename"] = Application::data().getDeviceNameById(device->type);
jsonnode["view"] = 1;
jsonnode["is_online"] = device->online;// ? "在线" : "离线";
jsonnode["is_error"] = device->err;// ? "故障" : "正常";
jsonnode["is_running"] = device->running;// ? "工作" : "空闲";
njson jsonarrayParams = njson::array();
VecPairSS vec;
device->getRuntimeParams(vec);
for (auto& item: vec)
{ {
jsonarrayParams.push_back({{"k", item.first}, {"v", item.second}}); njson jsonnode;
jsonnode["stationId"] = stationId;
jsonnode["category"] = category;
jsonnode["device_id"] = device->deviceId;
jsonnode["name"] = device->name;
jsonnode["code"] = device->code;
jsonnode["type"] = device->type;
jsonnode["typename"] = Application::data().getDeviceNameById(device->type);
jsonnode["view"] = 1;
jsonnode["is_online"] = device->online;// ? "在线" : "离线";
jsonnode["is_error"] = device->err;// ? "故障" : "正常";
jsonnode["is_running"] = device->running;// ? "工作" : "空闲";
{
VecPairSS vec;
device->getRuntimeParams(vec);
njson jsonarrayParams = njson::array();
for (auto& item: vec)
{
jsonarrayParams.push_back({{"k", item.first}, {"v", item.second}});
}
jsonnode["params"] = jsonarrayParams;
}
if (device->type == 106)
{
VecPairSS vec;
device->getRuntimeParams1(vec);
njson jsonarrayParams = njson::array();
for (auto& item: vec)
{
jsonarrayParams.push_back({{"k", item.first}, {"v", item.second}});
}
jsonnode["params1"] = jsonarrayParams;
}
jsondata.push_back(jsonnode);
} }
jsonnode["params"] = jsonarrayParams;
jsondata.push_back(jsonnode);
} }
} }
json["data"] = jsondata; json["data"] = jsondata;
@@ -906,21 +1006,63 @@ Errcode HttpEntity::queryStatSystem(const httplib::Request& req, njson& json, st
{ {
auto& appdata = Application::data(); auto& appdata = Application::data();
double incomeTotal {};
double station_num = appdata.getStationCount();
double solarDeviceNum {};
double capacityTotal {};
double electGenTotal {};
double electGridTotal {};
double electStorageIn {};
double electStorageOut {};
for (auto& item : appdata.mapStation)
{
auto& station = item.second;
solarDeviceNum += station->getDeviceCount(3);
capacityTotal += station->capacity;
electGenTotal += station->electGenTotal;
electGridTotal += station->electGridTotal;
electStorageIn += station->electStorageIn;
electStorageOut += station->electStorageOut;
}
njson jsondata; njson jsondata;
jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd
jsondata["income_total"] = std::to_string(Utils::random(100, 200)); // : 累计收益精度0.01 jsondata["income_total"] = incomeTotal; // : 累计收益精度0.01
jsondata["station_num"] = Utils::toStr(appdata.getStationCount()); // : 能源站数量 jsondata["station_num"] = station_num; // : 能源站数量
jsondata["storage_device_num "] = Utils::toStr(appdata.getStationCount()); //: 储能设备数量 jsondata["storage_device_num"] = station_num; //: 储能设备数量
jsondata["solar_device_num"] = "0"; // : 光伏设备数量 jsondata["solar_device_num"] = solarDeviceNum; //: 光伏设备数量
jsondata["capacity_total"] = std::to_string(Utils::random(100, 200)); // : 储能总容量kWh精度0.001 jsondata["capacity_total"] = capacityTotal; // : 储能总容量kWh精度0.001
jsondata["solar_elect_gen"] = std::to_string(Utils::random(100, 200)); // : 发电总电量kWh精度0.001 jsondata["solar_elect_gen"] = electGenTotal; // : 发电总电量kWh精度0.001
jsondata["solar_elect_grid"] = std::to_string(Utils::random(100, 200)); // : 入网种电量kWh精度0.001 jsondata["solar_elect_grid"] = electGridTotal; // : 入网种电量kWh精度0.001
jsondata["storage_elect_in"] = std::to_string(Utils::random(100, 200)); // : 储能充电总电量kWh精度0.001 jsondata["storage_elect_in"] = electStorageIn; // : 储能充电总电量kWh精度0.001
jsondata["storage_elect_out"] = std::to_string(Utils::random(100, 200)); // : 储能放电总电量kWh精度0.001 jsondata["storage_elect_out"] = electStorageOut; // : 储能放电总电量kWh精度0.001
json["data"] = jsondata; json["data"] = jsondata;
return Errcode::OK; return Errcode::OK;
} }
Errcode HttpEntity::queryStatStation(const httplib::Request& req, njson& json, std::string& errmsg)
{
njson jsondata = njson::array();
auto dao = DaoEntity::create("");
std::string sql = R"(SELECT s.station_id, s.name station_name, ss.income_elect, ss.income_charge, ss.usage_rate FROM station s LEFT JOIN
(SELECT station_id, SUM(income_elect ) income_elect , SUM(income_charge) income_charge, avg(usage_rate) usage_rate FROM stat_staion GROUP BY station_id) AS ss
ON ss.station_id = s.station_id)";
std::vector<Fields> vecStations;
auto err = dao->exec(sql, vecStations);
for (auto& fields: vecStations)
{
njson jsonnode;
jsonnode["station_name"] = fields.value("station_name");
jsonnode["income"] = fields.get<float>("income_elect") + fields.get<float>("income_charge");
jsonnode["usage_rate"] = fields.get<float>("usage_rate");
jsondata.push_back(jsonnode);
}
json["data"] = jsondata;
return Errcode(err);
}
Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
std::string station_id = req.get_param_value("station_id"); std::string station_id = req.get_param_value("station_id");
@@ -948,48 +1090,61 @@ Errcode HttpEntity::queryStatTotal(const httplib::Request& req, njson& json, std
jsondata["income_charge"] = "123.123"; //充电收益精度0.01 jsondata["income_charge"] = "123.123"; //充电收益精度0.01
} }
json["data"] = jsondata; json["data"] = jsondata;
return Errcode::OK; return Errcode::OK;
} }
Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg) Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg)
{ {
std::string station_id = req.get_param_value("station_id"); //std::string stationId = req.get_param_value("station_id");
std::string category = req.get_param_value("category"); //std::string category = req.get_param_value("category");
std::string dt_start = req.get_param_value("start_date"); std::string dtStart = req.get_param_value("start_date");
std::string dt_end = req.get_param_value("end_date"); std::string dtEnd = req.get_param_value("end_date");
if (dtEnd.empty())
int64_t t1 = Utils::time(dt_start)/1000;
int64_t t2 = Utils::time(dt_end)/1000;
int64_t tMax = t1+ 86400 * 30;
njson jsondata = njson::array();
for (int64_t t = t1; t<=t2 && t<=tMax; t += 86400)
{ {
njson jnode; if (dtStart.empty())
jnode["station_id"] = station_id; {
if (!category.empty()) jnode["category"] = category; dtEnd = Utils::dateStr();
jnode["dt"] = Utils::dateStr(t*1000); //日期 dtStart = Utils::dateStr(Utils::date() - 86400*7);
jnode["storage_elect_in"] = std::to_string(Utils::random(100, 200)); //储能充电电量kWh精度0.001 }
jnode["storage_elect_out"] = std::to_string(Utils::random(100, 200)); //储能放电电量kWh精度0.001 else
jnode["storage_num_in"] = std::to_string(Utils::random(1,5)); //储能设备充电次数 {
jnode["storage_num_out"] = std::to_string(Utils::random(1, 5)); //储能设备放电次数 dtEnd = Utils::dateStr(Utils::time(dtStart + " 00:00:00") + 86400*7);
jnode["storage_num_err"] = std::to_string(Utils::random(1, 5)); //储能设备故障次数 }
jnode["solar_elect_gen"] = std::to_string(Utils::random(100, 200)); //光伏发电电量kWh精度0.001
jnode["solar_elect_grid "] = std::to_string(Utils::random(100, 200)); //光伏入网电量kWh精度0.001
jnode["solar_num_err"] = std::to_string(Utils::random(1, 5)); //光伏设备故障次数
jnode["charge_elect"] = std::to_string(Utils::random(100, 200)); //充电设备充电电量kWh精度0.001
jnode["charge_num"] = std::to_string(Utils::random(1, 5)); //充电设备充电次数
jnode["charge_num_err"] = std::to_string(Utils::random(1, 5)); //充电设备故障次数
jnode["income_elect"] = std::to_string(Utils::random(100, 200)); //发电收益精度0.01
jnode["income_charge"] = std::to_string(Utils::random(100, 200)); //充电收益精度0.01
jnode["usage_rate"] = std::to_string(Utils::random(10, 50)); //利用率
jsondata.push_back(jnode);
} }
json["data"] = jsondata;
std::vector<Fields> result;
Errcode err = DAO::queryStatDataList(NULL, dtStart, dtEnd, result);
json["data"] = FieldsToJsonArray(result);
return err;
//int64_t t1 = Utils::time(dtStart);
//int64_t t2 = Utils::time(dtEnd);
//int64_t tMax = t1+ 86400 * 30;
//njson jsondata = njson::array();
//for (int64_t t = t1; t<=t2 && t<=tMax; t += 86400)
//{
// njson jnode;
// jnode["station_id"] = station_id;
// if (!category.empty()) jnode["category"] = category;
// jnode["dt"] = Utils::dateStr(t); //日期
// jnode["storage_elect_in"] = std::to_string(Utils::random(100, 200)); //储能充电电量kWh精度0.001
// jnode["storage_elect_out"] = std::to_string(Utils::random(100, 200)); //储能放电电量kWh精度0.001
// jnode["storage_num_in"] = std::to_string(Utils::random(1,5)); //储能设备充电次数
// jnode["storage_num_out"] = std::to_string(Utils::random(1, 5)); //储能设备放电次数
// jnode["storage_num_err"] = std::to_string(Utils::random(1, 5)); //储能设备故障次数
// jnode["solar_elect_gen"] = std::to_string(Utils::random(100, 200)); //光伏发电电量kWh精度0.001
// jnode["solar_elect_grid "] = std::to_string(Utils::random(100, 200)); //光伏入网电量kWh精度0.001
// jnode["solar_num_err"] = std::to_string(Utils::random(1, 5)); //光伏设备故障次数
// jnode["charge_elect"] = std::to_string(Utils::random(100, 200)); //充电设备充电电量kWh精度0.001
// jnode["charge_num"] = std::to_string(Utils::random(1, 5)); //充电设备充电次数
// jnode["charge_num_err"] = std::to_string(Utils::random(1, 5)); //充电设备故障次数
// jnode["income_elect"] = std::to_string(Utils::random(100, 200)); //发电收益精度0.01
// jnode["income_charge"] = std::to_string(Utils::random(100, 200)); //充电收益精度0.01
// jnode["usage_rate"] = std::to_string(Utils::random(10, 50)); //利用率
// jsondata.push_back(jnode);
//}
//json["data"] = jsondata;
return Errcode::OK; return Errcode::OK;
} }
@@ -999,10 +1154,11 @@ Errcode HttpEntity::queryStatCharts(const httplib::Request& req, njson& json, st
std::string stationId = req.get_param_value("station_id"); std::string stationId = req.get_param_value("station_id");
std::string category = req.get_param_value("category"); std::string category = req.get_param_value("category");
if (dt.empty()) { errmsg = "参数[dt]错误"; return Errcode::ERR_PARAM; }
if (stationId.empty()) { errmsg = "参数[station_id]错误"; return Errcode::ERR_PARAM; } if (stationId.empty()) { errmsg = "参数[station_id]错误"; return Errcode::ERR_PARAM; }
if (category.empty()) { errmsg = "参数[category]错误"; return Errcode::ERR_PARAM; } if (category.empty()) { errmsg = "参数[category]错误"; return Errcode::ERR_PARAM; }
if (dt.empty()) { dt=Utils::dateStr(); }
njson jsondata; njson jsondata;
std::string sql = R"(SELECT hd.*, d.`type` device_type, ddt.category FROM history_day hd std::string sql = R"(SELECT hd.*, d.`type` device_type, ddt.category FROM history_day hd

View File

@@ -43,6 +43,7 @@ public:
Errcode queryRoleList(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryRoleList(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryRolePermission(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode insertRole(const httplib::Request& req, njson& json, std::string& errmsg); Errcode insertRole(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode updateRole(const httplib::Request& req, njson& json, std::string& errmsg); Errcode updateRole(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode deleteRole(const httplib::Request& req, njson& json, std::string& errmsg); Errcode deleteRole(const httplib::Request& req, njson& json, std::string& errmsg);
@@ -80,8 +81,10 @@ public:
Errcode queryPredictionDetail(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryPredictionDetail(const httplib::Request& req, njson& json, std::string& errmsg);
// 系统总览所有场站统计 // 系统总览所有场站统计 (总览页 运行状况)
Errcode queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryStatSystem(const httplib::Request& req, njson& json, std::string& errmsg);
Errcode queryStatStation(const httplib::Request& req, njson& json, std::string& errmsg);
// 一个场站的累计统计 // 一个场站的累计统计
Errcode queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg); Errcode queryStatTotal(const httplib::Request& req, njson& json, std::string& errmsg);
// 场站按类别按天统计 // 场站按类别按天统计

View File

@@ -28,8 +28,8 @@ void MqttClient::loadDataStruct(std::string filename)
for (auto& jsonitem : json.items()) for (auto& jsonitem : json.items())
{ {
std::string name = jsonitem.key(); std::string name = jsonitem.key();
auto jsonnodeItem = jsonitem.value(); auto& jsonnodeItem = jsonitem.value();
int count = jsonnodeItem["count"]; //int count = jsonnodeItem["count"];
auto jsonaddrs = jsonnodeItem["addr"]; auto jsonaddrs = jsonnodeItem["addr"];
auto& mapItem = g_mapRegInfo[name]; auto& mapItem = g_mapRegInfo[name];
@@ -56,26 +56,34 @@ void MqttClient::loadDataStruct(std::string filename)
int MqttClient::init(string addr, string clientId, string username, string password) int MqttClient::init(string addr, string clientId, string username, string password)
{ {
if (isConnected)
{
return MQTTASYNC_SUCCESS;
}
if (addr.empty())
{
return MQTTASYNC_FAILURE;
}
this->addr = addr; this->addr = addr;
this->clientId = clientId; this->clientId = clientId;
this->mapTopicInfo["EMS_YX"] = 101; this->mapTopicInfo["EMS_YX"] = TopicInfo("EMS_YX", 101);
this->mapTopicInfo["EMS_YX"] = 101; this->mapTopicInfo["EMS_YC"] = TopicInfo("EMS_YC", 101);
this->mapTopicInfo["EMS_YC"] = 101; this->mapTopicInfo["EMS_YT"] = TopicInfo("EMS_YT", 101);
this->mapTopicInfo["EMS_YT"] = 101; this->mapTopicInfo["PCS_YX"] = TopicInfo("PCS_YX", 102, 1);
this->mapTopicInfo["PCS_YX"] = 102; this->mapTopicInfo["PCS_YC"] = TopicInfo("PCS_YC", 102, 1);
this->mapTopicInfo["PCS_YC"] = 102; this->mapTopicInfo["PCU_YX"] = TopicInfo("PCU_YX", 103);
this->mapTopicInfo["PCU_YX"] = 103; this->mapTopicInfo["PCU_YC"] = TopicInfo("PCU_YC", 103);
this->mapTopicInfo["PCU_YC"] = 103; this->mapTopicInfo["BMS_YX"] = TopicInfo("BMS_YX", 104);
this->mapTopicInfo["BMS_YX"] = 104; this->mapTopicInfo["BMS_YC"] = TopicInfo("BMS_YC", 104);
this->mapTopicInfo["BMS_YC"] = 104; this->mapTopicInfo["BCU_YX"] = TopicInfo("BCU_YX", 105, 1);
this->mapTopicInfo["BCU_YX"] = 105; this->mapTopicInfo["BCU_YC"] = TopicInfo("BCU_YC", 105, 1);
this->mapTopicInfo["BCU_YC"] = 105; this->mapTopicInfo["MEM_YC"] = TopicInfo("MEM_YC", 3);
this->mapTopicInfo["MEM_YC"] = 3; this->mapTopicInfo["Cooling_YC"] = TopicInfo("Cooling_YC", 110);
this->mapTopicInfo["Cooling_YC"] = 110; this->mapTopicInfo["TH_YC"] = TopicInfo("TH_YC", 111);
this->mapTopicInfo["TH_YC"] = 111; this->mapTopicInfo["Gateway_YX"] = TopicInfo("Gateway_YX", 112);
this->mapTopicInfo["Gateway_YX"] = 112; this->mapTopicInfo["Charger_YC"] = TopicInfo("Charger_YC", 113);
this->mapTopicInfo["Charger_YC"] = 113;
MQTTAsync_connectOptions option = MQTTAsync_connectOptions_initializer; MQTTAsync_connectOptions option = MQTTAsync_connectOptions_initializer;
MQTTAsync_message pubmsg = MQTTAsync_message_initializer; MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
@@ -168,25 +176,6 @@ void MqttClient::subscribe()
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer; MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
options.onSuccess = funcSuccess; options.onSuccess = funcSuccess;
options.onFailure = funcFailure; options.onFailure = funcFailure;
std::vector<std::string> vecTopic = {
//"up/json/" + clientId + "/EMS_YX",
"up/json/" + clientId + "/EMS_YC",
//"up/json/" + clientId + "/EMS_YT",
//"up/json/" + clientId + "/PCU_YX",
//"up/json/" + clientId + "/PCU_YC",
//"up/json/" + clientId + "/PCS_YX",
"up/json/" + clientId + "/PCS_YC",
//"up/json/" + clientId + "/BCU_YX",
//"up/json/" + clientId + "/BCU_YC",
//"up/json/" + clientId + "/BMS_YX",
//"up/json/" + clientId + "/BMS_YC",
//"up/json/" + clientId + "/MEM_YC",
//"up/json/" + clientId + "/Cooling_YC",
//"up/json/" + clientId + "/TH_YC",
//"up/json/" + clientId + "/Gateway_YX",
//"up/json/" + clientId + "/Charger_YC",
};
for (auto& item: mapTopicInfo) for (auto& item: mapTopicInfo)
{ {
std::string topic = "up/json/" + clientId + "/" + item.first; std::string topic = "up/json/" + clientId + "/" + item.first;
@@ -196,41 +185,20 @@ void MqttClient::subscribe()
{ {
spdlog::error("[mqtt] subscribe [{},{}] failed, err={}", topic, qos, rc); spdlog::error("[mqtt] subscribe [{},{}] failed, err={}", topic, qos, rc);
} }
else
{
spdlog::info("[mqtt] subscribe [{},{}] ", topic, qos);
}
} }
} }
int MqttClient::publish(std::string topic, std::string text)
int MqttClient::polling()
{ {
// 召测 发布 if (!client) return 0;
std::vector<std::string> vecTopic = {
"down/json/" + clientId + "/EMS_YX",
"down/json/" + clientId + "/EMS_YC",
//"down/json/" + clientId + "/EMS_YT",
//"down/json/" + clientId + "/PCU_YX",
//"down/json/" + clientId + "/PCU_YC",
//"down/json/" + clientId + "/PCS_YX",
"down/json/" + clientId + "/PCS_YC",
//"down/json/" + clientId + "/BCU_YX",
//"down/json/" + clientId + "/BCU_YC",
//"down/json/" + clientId + "/BMS_YX",
//"down/json/" + clientId + "/BMS_YC",
//"down/json/" + clientId + "/MEM_YC",
//"down/json/" + clientId + "/Cooling_YC",
//"down/json/" + clientId + "/TH_YC",
//"down/json/" + clientId + "/Gateway_YX",
//"down/json/" + clientId + "/Charger_YC",
};
njson json;
json["ts"] = Utils::time();
json["no"] = 1;
std::string text = json.dump();
MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer; MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
//options.onSuccess = onSend; options.onSuccess = [](void* context, MQTTAsync_successData* response) {};
//options.onFailure = onSendFailure; options.onFailure = [](void* context, MQTTAsync_failureData* response) {};
options.context = this; options.context = this;
MQTTAsync_message msg = MQTTAsync_message_initializer; MQTTAsync_message msg = MQTTAsync_message_initializer;
@@ -239,16 +207,48 @@ int MqttClient::polling()
msg.payloadlen = text.size(); msg.payloadlen = text.size();
msg.retained = 0; msg.retained = 0;
for (auto& topic: vecTopic) std::string topicName = "down/json/" + clientId + "/" + topic;
int rc = MQTTAsync_sendMessage(client, topicName.c_str(), &msg, &options);
if (rc == MQTTASYNC_SUCCESS)
{ {
int rc = MQTTAsync_sendMessage(client, topic.c_str(), &msg, &options); spdlog::info("[mqtt] publish MQTTAsync_sendMessage success, topic={}, text={}", topicName, text);
if (rc == MQTTASYNC_SUCCESS) }
else
{
spdlog::error("[mqtt] publish MQTTAsync_sendMessage error, topic={}, text={}", topicName, text);
}
return 0;
}
int MqttClient::polling()
{
if (!isConnected)
{
return 0;
}
njson json;
json["ts"] = Utils::time();
json["no"] = 0; // 设备编号
auto& appdata = Application::data();
auto station = appdata.getStationByCode(clientId);
for (auto& item: mapTopicInfo)
{
auto& topicInfo = item.second;
if (topicInfo.polling)
{ {
spdlog::info("MQTT send message success, topic={}, text={}", topic, msg.payload); if (station)
} {
else std::vector<std::shared_ptr<Device>> vecDevice;
{ station->getDeviceByType(topicInfo.deviceType, vecDevice);
spdlog::error("MQTT send message error, topic={}, text={}", topic, msg.payload); for (auto device: vecDevice)
{
json["no"] = Utils::toInt(device->code);
this->publish(topicInfo.name, json.dump());
}
}
} }
} }
return 0; return 0;
@@ -292,8 +292,7 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
std::string command = GetSubStr("/", topicStr); std::string command = GetSubStr("/", topicStr);
std::string deviceCode = GetSubStr("/", topicStr); std::string deviceCode = GetSubStr("/", topicStr);
spdlog::info("[mqtt] message arrived: topic=[{},{}], len={}, payload={}", topic, msg->qos, len, payload); spdlog::info("[mqtt] <<<<<<<<<< message arrived: topic=[{},{}], len={}, payload={}", topic, msg->qos, len, payload);
spdlog::info("[mqtt] parse topic: {}, stationNo={}, command={}", topic, stationNo, command);
njson json; njson json;
bool ret = JSON::parse(payload, json); bool ret = JSON::parse(payload, json);
@@ -317,16 +316,23 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
} }
std::map<std::string, REGInfo>& mapRegInfo = iter->second; std::map<std::string, REGInfo>& mapRegInfo = iter->second;
auto iterTopic = mapTopicInfo.find(command);
if (iterTopic == mapTopicInfo.end())
{
spdlog::error("[mqtt] get topic info error, clientId={}, stationId={}, command={}", clientId, stationNo, command);
return 1;
}
TopicInfo& topicInfo = iterTopic->second;
int deviceNo = -1; int deviceNo = -1;
JSON::read(json, "no", deviceNo); JSON::read(json, "no", deviceNo);
auto device = station->getDeviceByType(mapTopicInfo[command], Utils::toStr(deviceNo)); auto device = station->getDeviceByType(topicInfo.deviceType, Utils::toStr(deviceNo));
if (!device) if (!device)
{ {
return 1; return 1;
} }
spdlog::info("[mqtt] deviceNo={}", deviceNo);
for (auto& item: json.items()) for (auto& item: json.items())
{ {
std::string key = item.key(); std::string key = item.key();
@@ -341,8 +347,8 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
if (iter != mapRegInfo.end()) if (iter != mapRegInfo.end())
{ {
auto addr = iter->first; auto addr = iter->first;
std::string val = JSON::toStr(data[i]); auto& val = data[i];
spdlog::info("[mqtt] read register addr: [{}]={}, {}", addr, val, iter->second.remark); //spdlog::info("[mqtt] read register addr: [{}]={}, {}", addr, val, iter->second.remark);
device->setParam(addr, val); device->setParam(addr, val);
++iter; ++iter;
} }
@@ -350,11 +356,11 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m
} }
else if (data.is_number()) else if (data.is_number())
{ {
device->setParam(key, Utils::toStr(data.get<int>())); device->setParam(key, data.get<int>());
} }
else if (data.is_string()) else if (data.is_string())
{ {
device->setParam(key, Utils::toStr(data.get<int>())); device->setParam(key, Utils::toInt(data.get<std::string>()));
} }
} }
} }
@@ -371,36 +377,13 @@ void MqttClient::onDeliveryComplete(MQTTAsync_token token)
//spdlog::info("MQTT delivery complete, token={}", token); //spdlog::info("MQTT delivery complete, token={}", token);
} }
void MqttClient::onConnectSuccess( MQTTAsync_successData* resp) void MqttClient::onConnectSuccess( MQTTAsync_successData* resp)
{ {
spdlog::info("[mqtt] connect to {} success, clientId={}.", addr, clientId); spdlog::info("[mqtt] connect to {} success, clientId={}.", addr, clientId);
this->isConnected = true; this->isConnected = true;
this->subscribe(); this->subscribe();
//MQTTAsync_responseOptions options = MQTTAsync_responseOptions_initializer;
//options.context = this;
//options.onSuccess = [](void* context, MQTTAsync_successData* response)
// {
// spdlog::info("[mqtt] subscribe success.");
// };
//options.onFailure = [](void* context, MQTTAsync_failureData* response)
// {
// spdlog::info("[mqtt] subscribe failed.");
// };
//
//for (auto& topic: vecTopic)
//{
// int rc = MQTTAsync_subscribe(client, topic.c_str(), qos, &options);
// if (rc != MQTTASYNC_SUCCESS)
// {
// spdlog::error("[mqtt] subscribe [{},{}] failed, err={}", topic, qos, rc);
// }
// else
// {
// spdlog::info("[mqtt] subscribe [{},{}] success", topic, qos);
// }
//}
} }
void MqttClient::onConnectFaiure(MQTTAsync_failureData* resp) void MqttClient::onConnectFaiure(MQTTAsync_failureData* resp)
{ {
spdlog::error("[mqtt] connect to {} error, clientId={}.", addr, clientId); spdlog::error("[mqtt] connect to {} error, clientId={}.", addr, clientId);

View File

@@ -25,16 +25,16 @@ struct REGInfo
} }
}; };
//struct TopicInfo struct TopicInfo
//{ {
// std::string name; std::string name;
// std::string topic; int deviceType {0};
// int deviceType; int polling {0}; // 召测
// TopicInfo() {}; TopicInfo() {};
// TopicInfo(std::string name, std::string topic, int deviceType) TopicInfo(std::string name, int deviceType, int polling=0)
// :name(name), topic(topic), deviceType(deviceType) :name(name), deviceType(deviceType), polling(polling)
// {}; {};
//}; };
using namespace std; using namespace std;
@@ -47,8 +47,7 @@ public:
void destory(); void destory();
void subscribe(); void subscribe();
//int publish(); int publish(std::string topic, std::string text);
int polling(); int polling();
void onConnectionLost(char* cause); void onConnectionLost(char* cause);
@@ -61,6 +60,7 @@ public:
void parseEMS_YX(std::shared_ptr<Station> station, njson& json, std::map<std::string, REGInfo>& mapRegInfo); void parseEMS_YX(std::shared_ptr<Station> station, njson& json, std::map<std::string, REGInfo>& mapRegInfo);
public: public:
// MQTT clientId (使用station 的 code)
std::string clientId; std::string clientId;
MQTTAsync client = nullptr; MQTTAsync client = nullptr;
@@ -69,7 +69,7 @@ public:
bool isConnected {false}; bool isConnected {false};
bool isSubscribed {false}; bool isSubscribed {false};
std::map<std::string, int> mapTopicInfo; std::map<std::string, TopicInfo> mapTopicInfo;
}; };

View File

@@ -8,6 +8,10 @@
#include <QWebEngineProfile> #include <QWebEngineProfile>
#include <QAction> #include <QAction>
#include <QToolBar> #include <QToolBar>
#include <QMouseEvent>
#include <QHBoxLayout>
#include "common/Spdlogger.h"
void MySplash(MainWeb* mainWin) void MySplash(MainWeb* mainWin)
{ {
@@ -44,6 +48,47 @@ MainWeb::MainWeb()
this->setWindowTitle("光储充站监控与运营管理平台"); this->setWindowTitle("光储充站监控与运营管理平台");
this->setGeometry(0, 0, 1920, 1080); this->setGeometry(0, 0, 1920, 1080);
this->hide(); this->hide();
//this->setMouseTracking(true);
this->setAttribute(Qt::WA_Hover, true);
this->initWebview();
this->mySplash();
btnFullscreen.setParent(this);
btnFullscreen.raise();
btnFullscreen.setGeometry(0, 0, 34, 34);
btnFullscreen.setStyleSheet("background: transparent; background-image: url(./assets/ui/iconFullscreen.png);");
QObject::connect(&btnFullscreen, &QPushButton::clicked, [=](bool checked)
{
isFullscreen ? this->showNormal() : this->showFullScreen();
isFullscreen = !isFullscreen;
if (isFullscreen)
{
btnFullscreen.setStyleSheet("background: transparent; background-image: url(./assets/ui/iconFullscreenExit.png);");
}
else
{
btnFullscreen.setStyleSheet("background: transparent; background-image: url(./assets/ui/iconFullscreen.png);");
}
});
this->show();
}
void MainWeb::initWebview()
{
labelWebErr.setParent(this);
labelWebErr.setGeometry(180, 100, 800, 50);
labelWebErr.setText("WEB服务异常");
labelWebErr.setStyleSheet("font: bold 20px;");
labelWebErr.hide();
qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "9222"); // 即使内置视图,有时也需要开启调试端口
//this->setCentralWidget(&webView);
webView.setParent(this);
webView.setGeometry(0, 0, 1920, 1080);
// 在加载页面之前清除缓存 // 在加载页面之前清除缓存
//QWebEngineProfile::defaultProfile()->clearHttpCache(); //QWebEngineProfile::defaultProfile()->clearHttpCache();
@@ -52,19 +97,33 @@ MainWeb::MainWeb()
//settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true); //settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
//settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); // 解决http资源加载问题 //settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); // 解决http资源加载问题
//settings->setAttribute(QWebEngineSettings::PluginsEnabled, true); //settings->setAttribute(QWebEngineSettings::PluginsEnabled, true);
webView.setGeometry(0, 0, 1920, 1080);
// 默认设置透明, 解决加载时的白屏闪烁 // 默认设置透明, 解决加载时的白屏闪烁
//webView.page()->setBackgroundColor(Qt::transparent); //webView.page()->setBackgroundColor(Qt::transparent);
//webView.setContextMenuPolicy(Qt::NoContextMenu); //webView.setContextMenuPolicy(Qt::NoContextMenu);
webView.load(QUrl(Config::option.webSrvUrl.c_str())); webView.load(QUrl(Config::option.webSrvUrl.c_str()));
this->setCentralWidget(&webView); webView.hide();
// 将主 Web 页面的开发者工具页面设置为 devToolsView 的页面
webView.page()->setDevToolsPage(devTools.page());
QObject::connect(&webView, &QWebEngineView::loadFinished, [=](bool ok)
{
if (ok)
{
webView.show();
labelWebErr.hide();
}
else
{
spdlog::error("[web] webview load failed, url={}", Config::option.webSrvUrl);
webView.hide();
labelWebErr.show();
}
});
}
void MainWeb::mySplash()
{
//===动态程序启动画面=== //===动态程序启动画面===
splash = std::make_shared<QSplashScreen>(QPixmap("./assets/ui/splash.png")); splash = std::make_shared<QSplashScreen>(QPixmap("./assets/ui/splash.png"));
QCoreApplication::processEvents(); QCoreApplication::processEvents();
label1.setParent(splash.get()); label1.setParent(splash.get());
label1.setStyleSheet("background-color: gray"); label1.setStyleSheet("background-color: gray");
@@ -78,28 +137,70 @@ MainWeb::MainWeb()
label1.show(); label1.show();
labelProgress.show(); labelProgress.show();
int i = 0;
QObject::connect(&webView, &QWebEngineView::loadFinished, [=](bool ok) while ((++i)<100)
{ {
if (ok) splash->showMessage(QString("Loading... %1 ms").arg(i), Qt::AlignBottom | Qt::AlignRight, Qt::black);
{ labelProgress.setGeometry(100, 480, i*10*0.8, 20);
int i = 0; QCoreApplication::processEvents();
while ((++i)<100) QThread::msleep(20);
{ }
splash->showMessage(QString("Loading... %1 ms").arg(i), Qt::AlignBottom | Qt::AlignRight, Qt::black); splash->finish(this);//程序启动画面结束
labelProgress.setGeometry(100, 480, i*10*0.8, 20); }
QCoreApplication::processEvents();
QThread::msleep(20); void MainWeb::showDevTools()
} {
splash->finish(this);//程序启动画面结束 if (layout)
this->show(); {
} //webView.setParent(this);
else //QLayoutItem* item;
{ //while ((item = layout->takeAt(0)) != nullptr) { // 不断取出第一个项
qDebug() << "页面加载失败!"; // //if (item->widget()) {
// 这里可以执行加载失败后的处理 // // delete item->widget(); // 删除控件
} // //}
}); // //else if (item->layout()) { // 如果是子QLayout
// // delete item->layout(); // 删除子布局
//this->show(); // //}
// delete item; // 最后删除QLayoutItem本身
//}
//delete layout;
//layout = NULL;
}
else
{
// 如果你需要先导航主页面,然后在某个事件(如按钮点击)后显示开发者工具,可以将这行代码放在事件处理函数中。
layout = new QHBoxLayout(this);
// 将两个视图添加到布局中
layout->addWidget(&webView);
layout->addWidget(&devTools);
layout->setStretch(0, 2); // 主视图占2份
layout->setStretch(1, 1); // 开发者工具视图占1份
}
}
bool MainWeb::event(QEvent* e)
{
if (QEvent::HoverMove == e->type())//鼠标移动
{
QHoverEvent* hoverEvent = static_cast<QHoverEvent*>(e);
int x = hoverEvent->pos().x();
int y = hoverEvent->pos().y();
if (x > 40 || y > 40) { btnFullscreen.hide(); }
else { btnFullscreen.show(); }
}
return QWidget::event(e);
}
void MainWeb::keyPressEvent(QKeyEvent* e)
{
auto key = e->key();
if (key == Qt::Key_F12)
{
this->showDevTools();
}
else if (key == Qt::Key_F5)
{
webView.load(QUrl(Config::option.webSrvUrl.c_str()));
}
} }

View File

@@ -2,15 +2,36 @@
#include <QtWebEngineWidgets/QWebEngineView> #include <QtWebEngineWidgets/QWebEngineView>
#include <QSplashScreen> #include <QSplashScreen>
#include <QLabel> #include <QLabel>
#include <QPushButton>
#include <QHBoxLayout>
class MainWeb : public QMainWindow class MainWeb : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
MainWeb(); MainWeb();
void initWebview();
void mySplash();
void showDevTools();
bool event(QEvent* e);
void keyPressEvent(QKeyEvent* event);
public:
QLabel labelWebErr;
QWebEngineView webView; QWebEngineView webView;
std::shared_ptr<QSplashScreen> splash {}; QWebEngineView devTools;
std::shared_ptr<QSplashScreen> splash;
QLabel label1; QLabel label1;
QLabel labelProgress; QLabel labelProgress;
QLabel labelFullscreen;
QPushButton btnFullscreen;
bool isFullscreen = false;
QHBoxLayout* layout = NULL;
}; };

View File

@@ -277,7 +277,6 @@
/> />
<a-tree-select <a-tree-select
:allow-clear="true"
:disabled="props.disabled" :disabled="props.disabled"
v-if="item.type === 'tree-check-org'" v-if="item.type === 'tree-check-org'"
v-model:value="propsInfo.ruleForm.value[item.key]" v-model:value="propsInfo.ruleForm.value[item.key]"
@@ -515,7 +514,11 @@ function cascaderChange(value, cascaderItem) {
function filter(inputValue, path) { function filter(inputValue, path) {
return path.some((option) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1) return path.some((option) => option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1)
} }
function getBase64(img, callback) {
const reader = new FileReader()
reader.addEventListener('load', () => callback(reader.result))
reader.readAsDataURL(img)
}
function avatarUploadChange(info) { function avatarUploadChange(info) {
if (info.file.status === 'uploading') { if (info.file.status === 'uploading') {
data.loading = true data.loading = true
@@ -532,11 +535,7 @@ function avatarUploadChange(info) {
function onFieldsChange() {} function onFieldsChange() {}
function handleSubmit() {} function handleSubmit() {}
function getBase64(img, callback) {
const reader = new FileReader()
reader.addEventListener('load', () => callback(reader.result))
reader.readAsDataURL(img)
}
// 主动暴露方法 // 主动暴露方法
defineExpose({ defineExpose({

View File

@@ -56,17 +56,17 @@
scroll: { y: 500 } scroll: { y: 500 }
}" }"
> >
<template #is_add="{ record, index }"> <template #is_add="{ record }">
<a-checkbox v-model:checked="record.is_add"></a-checkbox> <a-checkbox v-model:checked="record.is_add"></a-checkbox>
</template> </template>
<template #is_del="{ record, index }"> <template #is_del="{ record }">
<a-checkbox v-model:checked="record.is_del"></a-checkbox> <a-checkbox v-model:checked="record.is_del"></a-checkbox>
</template> </template>
<template #is_edit="{ record, index }"> <template #is_edit="{ record }">
<a-checkbox v-model:checked="record.is_edit"></a-checkbox> <a-checkbox v-model:checked="record.is_edit"></a-checkbox>
</template> </template>
<template #is_view="{ record, index }"> <template #is_view="{ record }">
<a-checkbox v-model:checked="record.is_view"></a-checkbox> <a-checkbox v-model:checked="record.is_view"></a-checkbox>
</template> </template>
</TreeTable> </TreeTable>

View File

@@ -29,28 +29,28 @@ export default {
return { return {
curList: [ curList: [
{ {
name: '光伏设备告警', name: '光伏设备告警',
key: 'solar_num_err', key: 'solar_num_err',
lineColor: '#22E4FF', lineColor: '#22E4FF',
value: 1111, value: 1111,
d: '' d: ''
}, },
{ {
name: '储能设备告警', name: '储能设备告警',
key: 'storage_num_err', key: 'storage_num_err',
lineColor: '#0E68E4', lineColor: '#0E68E4',
value: 0, value: 0,
d: '' d: ''
}, },
{ {
name: '充电设备告警', name: '充电设备告警',
key: 'charge_num_err', key: 'charge_num_err',
lineColor: '#00BAAD', lineColor: '#00BAAD',
value: 0, value: 0,
d: '' d: ''
}, },
// { // {
// name: '负荷设备告警', // name: '负荷设备告警',
// key: 'key4', // key: 'key4',
// lineColor: '#FF8D1A', // lineColor: '#FF8D1A',
// value: 0, // value: 0,

View File

@@ -30,7 +30,7 @@ export default {
return { return {
curList: [ curList: [
{ {
name: '充电电量', name: '充电电量',
key: 'charge_elect', key: 'charge_elect',
lineColor: '#00BBA3', lineColor: '#00BBA3',
colorStart: ' rgba(10, 250, 106, 0.15)', colorStart: ' rgba(10, 250, 106, 0.15)',
@@ -39,7 +39,7 @@ export default {
d: 'kW·h' d: 'kW·h'
}, },
{ {
name: '充电次数', name: '充电次数',
key: 'charge_num', key: 'charge_num',
lineColor: '#3F80F2', lineColor: '#3F80F2',
colorStart: ' rgba(99, 151, 235, 0.3)', colorStart: ' rgba(99, 151, 235, 0.3)',
@@ -50,7 +50,7 @@ export default {
], ],
curListEcharts: [ curListEcharts: [
{ {
name: '充电电量', name: '充电电量',
key: 'charge_elect', key: 'charge_elect',
lineColor: '#00BBA3', lineColor: '#00BBA3',
colorStart: ' rgba(10, 250, 106, 0.15)', colorStart: ' rgba(10, 250, 106, 0.15)',
@@ -59,7 +59,7 @@ export default {
d: 'kW·h' d: 'kW·h'
}, },
{ {
name: '充电收益', name: '充电收益',
key: 'income_charge', key: 'income_charge',
lineColor: '#3F80F2', lineColor: '#3F80F2',
colorStart: ' rgba(99, 151, 235, 0.3)', colorStart: ' rgba(99, 151, 235, 0.3)',

View File

@@ -33,14 +33,14 @@ export default {
uid:'1', uid:'1',
curList: [ curList: [
{ {
name: '充电电量', name: '充电电量',
key: 'storage_elect_in', key: 'storage_elect_in',
lineColor: '#22E4FF', lineColor: '#22E4FF',
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
}, },
{ {
name: '放电电量', name: '放电电量',
key: 'storage_elect_out', key: 'storage_elect_out',
lineColor: '#0E68E4', lineColor: '#0E68E4',
value: 0, value: 0,

View File

@@ -177,6 +177,7 @@ export default {
:deep(.ant-modal-root .ant-modal-mask) { :deep(.ant-modal-root .ant-modal-mask) {
background-color: #000 !important; background-color: #000 !important;
} }
:deep(.modal.ant-modal) { :deep(.modal.ant-modal) {
width: 68% !important; width: 68% !important;
height: 80% !important; height: 80% !important;
@@ -195,7 +196,7 @@ export default {
width: 96%; width: 96%;
margin: auto; margin: auto;
box-shadow: none; box-shadow: none;
background: transparent; background: transparent!important;
.ant-modal-close { .ant-modal-close {
position: absolute; position: absolute;
right: 0; right: 0;

View File

@@ -12,7 +12,7 @@
:props-info="modalInfo[item.infoKey]" :props-info="modalInfo[item.infoKey]"
:props-total=" :props-total="
['prefab', 'dataTotal'].includes(item.infoKey) ['prefab', 'dataTotal'].includes(item.infoKey)
? item.key == 'prefab' ? item.infoKey == 'prefab'
? modalInfo.prefabTotal ? modalInfo.prefabTotal
: modalInfo.dataTotal : modalInfo.dataTotal
: modalInfo.allTotal : modalInfo.allTotal

View File

@@ -19,14 +19,14 @@ export default {
return { return {
curList: [ curList: [
{ {
name: '充电电量', name: '充电电量',
key: 'storage_elect_in', key: 'storage_elect_in',
lineColor: '#9BD801', lineColor: '#9BD801',
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
}, },
{ {
name: '放电电量', name: '放电电量',
key: 'storage_elect_out', key: 'storage_elect_out',
lineColor: '#3DFEFA', lineColor: '#3DFEFA',
value: 0, value: 0,

View File

@@ -31,14 +31,14 @@ export default {
return { return {
curList: [ curList: [
{ {
name: '发电量', name: '发电量',
key: 'solar_elect_gen', key: 'solar_elect_gen',
lineColor: '#22E4FF', lineColor: '#22E4FF',
value: 0, value: 0,
d: 'kW·h' d: 'kW·h'
}, },
{ {
name: '入网电量', name: '入网电量',
key: 'solar_elect_grid', key: 'solar_elect_grid',
lineColor: '#0E68E4', lineColor: '#0E68E4',
value: 0, value: 0,

View File

@@ -97,12 +97,12 @@ $page-border: #cad2dd;
opacity: 0.8; opacity: 0.8;
} }
&:active { &:active {
background: #0f6f6a; background: $btn-confirm;
} }
&:disabled { &:disabled {
border: none; border: none;
// color: #fff; color: #fff;
background: $btn-confirm; background: $btn-confirm;
} }
} }
@@ -115,6 +115,11 @@ $page-border: #cad2dd;
&:active { &:active {
background: $btn-del; background: $btn-del;
} }
&:disabled {
border: none;
color: #fff;
background: $btn-del;
}
} }
.btn-edit { .btn-edit {
background: $btn-edit; background: $btn-edit;
@@ -125,6 +130,11 @@ $page-border: #cad2dd;
&:active { &:active {
background: $btn-edit; background: $btn-edit;
} }
&:disabled {
border: none;
color: #fff;
background: $btn-edit;
}
} }
//modal样式 //modal样式
// 删除弹框 // 删除弹框

View File

@@ -5,23 +5,33 @@ const btnList = [
{ label: '修改', type: 'edit', disFlag: 'is_edit' }, { label: '修改', type: 'edit', disFlag: 'is_edit' },
{ label: '删除', type: 'del', disFlag: 'is_del', icon: 'icon-del' } { label: '删除', type: 'del', disFlag: 'is_del', icon: 'icon-del' }
] ]
function findNodeByRoute(tree, targetRoute) {
for (const node of tree) {
if (node.route === targetRoute) {
return node // 找到目标节点
}
if (node.children && node.children.length > 0) {
const found = findNodeByRoute(node.children, targetRoute) // 递归检查子节点
if (found) return found
}
}
return null // 未找到
}
function getBtns(arr) { function getBtns(arr) {
// console.log(this.$route, JSON.parse(localStorage.getItem('permission')), 'this.$route') const curPermission = findNodeByRoute(JSON.parse(localStorage.getItem('permission')), '/user')
// const curPermission = // console.log(findNodeByRoute(JSON.parse(localStorage.getItem('permission')), '/user'), '55')
// JSON.parse(localStorage.getItem('permission')).find(
// (item) => item.route == '/' + this.$route.name
// ) || {}
// console.log(this.$route, curPermission, localStorage.getItem('permission'), 'curPermission') // console.log(this.$route, curPermission, localStorage.getItem('permission'), 'curPermission')
const btns = [] const btns = []
// console.log(curPermission, 'curPermission') // console.log(curPermission, 'curPermission')
btnList.forEach((item) => { btnList.forEach((item) => {
if (arr.includes(item.label)) { if (arr.includes(item.label)) {
// item.disabled = !Boolean(+curPermission[item.disFlag]) // item.disabled = true
item.disabled = !Boolean(+curPermission[item.disFlag])
btns.push(item) btns.push(item)
} }
}) })
return btns return btns
} }
export { btnList, getBtns } export { btnList, getBtns }

View File

@@ -18,7 +18,7 @@
:title-option="{ title: '', info: '' }" :title-option="{ title: '', info: '' }"
@onSearch="onSearch" @onSearch="onSearch"
> >
<template #stationSelect="item"> <template #stationSelect="">
<a-select <a-select
style="width: 200px" style="width: 200px"
:dropdown-match-select-width="false" :dropdown-match-select-width="false"

View File

@@ -119,9 +119,9 @@ export default {
this.getStatDayList(3) this.getStatDayList(3)
]).then((r) => { ]).then((r) => {
if ( if (
this.deviceInfo.energy.length && this.deviceInfo.energy &&
this.deviceInfo.charge.length && this.deviceInfo.charge &&
this.deviceInfo.pv.length this.deviceInfo.pv
) { ) {
const newArr = this.mergedArray( const newArr = this.mergedArray(
this.deviceInfo.energy, this.deviceInfo.energy,