This commit is contained in:
ym1026
2025-09-15 15:47:45 +08:00
53 changed files with 2324 additions and 1389 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
import json
from openpyxl import load_workbook
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 read_cell(sheet, row, col):
val = str(sheet.cell(row, col).value)
if val == "None":
val = ""
return val.strip()
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):
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
if (len(text)>0):
text = "\n" + text + "\n\t\t"
text = '\t"%s":{\n\t\t"addr":[%s]\n\t}' % (topic, text)
return text
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]
wb = load_workbook('EMU对外通信点表最终修改1版_v9.xlsx', data_only=True)
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:
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}")
f.write("{\n" + text + "\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("");
if (!dao->isConnected())
{
spdlog::error("Init app data failed, database connected error.");
return;
return false;
}
std::string str;
@@ -106,7 +106,8 @@ void AppData::initFromDB()
}
{ // 数据库读取场站信息
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)
{
auto station = std::make_shared<Station>();
@@ -127,8 +128,7 @@ void AppData::initFromDB()
auto station = this->getStation(stationId);
if (station)
{
auto device = Device::create(fields);
station->addDevice(deviceId, device);
station->addDevice(fields);
}
else
{
@@ -141,7 +141,7 @@ void AppData::initFromDB()
DAO::queryPolicyList(dao, 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->type = fields.get<int>(DMPolicy::TYPE);
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;
return true;
}
std::shared_ptr<Station> AppData::getStation(int stationId)

View File

@@ -11,7 +11,7 @@
class Station;
class Device;
class MyPolicy;
class SysPolicy;
using VecPairSS = std::vector<std::pair<std::string, std::string>>;
@@ -57,8 +57,8 @@ public:
class AppData
{
public:
void init();
void initFromDB();
bool init();
bool initFromDB();
// 读取统计数据: 今日统计数据,累计统计数据
void loadStatData();
@@ -155,7 +155,7 @@ public:
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个时段)
std::vector<std::vector<std::string>> vecElectPeriods;

View File

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

View File

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

View File

@@ -7,6 +7,19 @@
#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 bool CheckCacheType(int type)
{
@@ -16,30 +29,72 @@ static bool CheckCacheType(int type)
std::shared_ptr<Device> Device::create(Fields& fields)
{
auto device = std::make_shared<Device>();
device->deviceId = fields.get<int>("device_id");
device->type = fields.get<int>("type");
device->name = fields.value("name");
device->code = fields.value("code");
device->isOpen = fields.get<int>("is_open");
device->attrsJson = fields.value("attrs");
device->category = fields.get<int>("category");
device->setFields(fields);
return device;
}
void Device::loadParamAddr(std::string filename)
{
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字符串转换成键值对
njson jsonroot;
bool ret = JSON::parse(device->attrsJson, jsonroot);
bool ret = JSON::parse(this->attrsJson, jsonroot);
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
{
this->attrs.clear();
for (auto& [key, val] : jsonroot.items()) {
std::string valType = val.type_name();
if (valType == "string") {
device->attrs.set(key, val.get<std::string>());
this->attrs.set(key, val.get<std::string>());
}
else if (valType == "number") {
device->attrs.set(key, val.get<int>());
this->attrs.set(key, val.get<int>());
}
else {
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;
//for (int i = 0; i*600<86400; ++i)
//{
// double voltage = double(Utils::random(20000, 30000))*0.01;
// 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;
auto& vecAddrs = GetDeviceParamAddrs(this->type);
for (auto& item: vecAddrs)
{
this->mapMyParams[item.addr] = &item;
}
}
int Device::startComm()
{
if (!isOpen)
@@ -182,42 +228,47 @@ void Device::storeDB(int npos)
{
}
void Device::setParam(std::string k, std::string v)
void Device::setParam(std::string k, int 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 (k == "") this->err = Utils::toInt(v);
if (k == "") this->err = v;
}
else if (type == 101) // EMS
{
}
else if (type == 102) // PCS
{
if (k == "0x1003") err = Utils::toInt(v); // 故障状态 R uint16 1故障0正常 0 0x1003
if (k == "0x1005") online = Utils::toInt(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 == "0x1003") err = v; // 故障状态 R uint16 1故障0正常 0 0x1003
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
}
else if (type == 103) // PCU
{
if (k == "0x1002") err = Utils::toInt(v); //故障状态 R uint16 1故障0正常 0 0x1002
if (k == "0x1004") online = Utils::toInt(v); //设备在线 R uint16 1在线0无效 1 0x1004
if (k == "0x1006") running = Utils::toInt(v); //启停状态 R uint16 1开机0关机 1 0x1006
if (k == "0x1002") err = v; //故障状态 R uint16 1故障0正常 0 0x1002
if (k == "0x1004") online = v; //设备在线 R uint16 1在线0无效 1 0x1004
if (k == "0x1006") running = v; //启停状态 R uint16 1开机0关机 1 0x1006
}
else if (type == 104) // BMS
{
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 == "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
}
else if (type == 105) // BCU
{
if (k == "0xA003") running = (v=="51" || v=="68"); //蓄电池充放电状态 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 == "0xA003") running = (v==0x33 || v==0x44); //蓄电池充放电状态 R uint16 "0x11开路,0x22待机,0x33充电,0x44放电" 34 0xA003
if (k == "0xA004") err = (v==0x55); online=1; //电池组运行状态 R uint16 "0x11跳机,0x22待机,0x33放空,0x44充满,0x55预警,0x66正常" 102 0xA004
}
else if (type == 106) // 充电桩
{
@@ -237,7 +288,6 @@ std::string Device::getParam(std::string k, std::string defaultVal)
return defaultVal;
}
void Device::getRuntimeParams(std::vector<std::pair<std::string, std::string>>& params)
{
// 3 电表
@@ -248,71 +298,23 @@ void Device::getRuntimeParams(std::vector<std::pair<std::string, std::string>>&
// 105 BCU
// 106 充电桩
// 109 光伏板
if (this->type == 3)
auto& vecAddr = s_mapDeviceParamAddr[this->type];
for (auto& itemAddr: vecAddr)
{
params.push_back({"A相电压", getParam("0x000B", "0.0") + " V"});
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"});
params.push_back({"C相电流", getParam("0x0015", "0.0") + " A"});
}
else if (this->type == 101) // EMS
{
params.push_back({"A相电压", getParam("0x107E", "0.0") + " V"});
params.push_back({"A相电流", getParam("0x1084", "0.0") + " A"});
params.push_back({"B相电压", getParam("0x1080", "0.0") + " V"});
params.push_back({"B相电流", getParam("0x1086", "0.0") + " A"});
params.push_back({"C相电压", getParam("0x1082", "0.0") + " V"});
params.push_back({"C相电流", getParam("0x1088", "0.0") + " A"});
}
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"});
params.push_back({itemAddr.name, getParam(itemAddr.addr, itemAddr.defaultVal) + itemAddr.unit});
}
}
void Device::getRuntimeParams1(std::vector<std::pair<std::string, std::string>>& params)
{
if (type == 106)
{
params.push_back({"需求电压", getParam("31072", "0.0") + " V"});
params.push_back({"需求电流", getParam("31074", "0.0") + " A"});
params.push_back({"需求功率", getParam("31076", "0.0") + " kW"});
params.push_back({"功率限值", getParam("31078", "0.0") + " kW"});
params.push_back({"输出电压", getParam("31080", "0.0") + " V"});
params.push_back({"输出电流", getParam("31082", "0.0") + " A"});
params.push_back({"输出功率", getParam("31084", "0.0") + " kW"});
}
}

View File

@@ -1,20 +1,41 @@
#pragma once
#include <string>
#include <set>
#include <map>
#include <vector>
#include <memory>
#include <string>
#include <unordered_map>
#include "common/Fields.h"
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
{
public:
static std::shared_ptr<Device> create(Fields& fields);
static void loadParamAddr(std::string filename);
void setFields(Fields& fields);
int startComm();
@@ -28,13 +49,15 @@ public:
bool cache(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 = "");
void getRuntimeParams(std::vector<std::pair<std::string, std::string>>& params);
void getRuntimeParams1(std::vector<std::pair<std::string, std::string>>& params);
public:
static std::map<int, std::vector<DeviceParamAddr>> s_mapDeviceParamAddr;
int deviceId = -1;
int type = -1;
std::string name;
@@ -58,4 +81,8 @@ public:
std::map<int, double> mapCacheCurrent;
std::map<int, double> mapCachePower;
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
#include <string>
#include <vector>
#include "common/Fields.h"
#include "common/JsonN.h"
class MyPolicy
class SysPolicy
{
public:
int policyId {0};
// 1峰谷套利2配网增容3应急供电4并网保电5自定时段
int type {0};
std::string name;
std::string value;
int isOpen {0};
int isOpen {1};
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 "protocol/MqttEntity.h"
#include "common/JsonN.h"
#include "app/Config.h"
Station::Station() : stationId(0)
{
@@ -35,10 +36,13 @@ void Station::setFields(Fields& fields)
{
this->stationId = fields.get<int>(DMStation::STATION_ID);
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->code = fields.value(DMStation::CODE);
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)
@@ -47,6 +51,22 @@ void Station::addDevice(int deviceId, std::shared_ptr<Device> 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)
{
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;
}
@@ -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 <unordered_map>
#include "common/Fields.h"
#include "Policy.h"
class Device;
class MqttClient;
@@ -95,48 +96,53 @@ public:
void setFields(Fields& fields);
void addDevice(int deviceId, std::shared_ptr<Device> device);
void addDevice(Fields& fields);
std::shared_ptr<Device> getDevice(int deviceId);
std::shared_ptr<Device> getDeviceByType(int deviceType, std::string code);
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 setWorkMode(int modeId);
void setPolicy(int policyId);
void writeRuntimeData(std::string dt, int npos);
void initMqtt();
void polling();
void setGarewayWorkMode();
public:
int stationId {};
std::string name;
std::string code;
bool isOpen {false};
int status {0};
std::string operationDate;
SysPolicy policy;
bool isConnected {false};
int workModeId {}; // 运行模式
int runPolicyId {}; // 运行策略
// 储能容量
double energyCapacity {};
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 系统统计 ===
// 累计发电量单位kWh
double electGenTatal {};
double electGenTotal {};
// 累计入网电量单位kWh
double electGridTotal {};
// 累计收益,单位:元
double incomeTotal {};
// 碳减排量, 单位:吨
double ccers {};
// 累计储能充电电量
double electStorageIn {};
// 累计储能放电电量
double electStorageOut {};
// 储能容量
double capacity {};
///////////////////////////////////////////////////////////////////////////////////////////////
/// === 日统计 ===
double storageIn {}; // 储能充电电量

View File

@@ -22,7 +22,7 @@ public:
Fields() {};
template <typename T>
void set(string key, T val, int precision=6)
void set(string key, T val, int precision=2)
{
stringstream ss;
ss.precision(precision);
@@ -31,7 +31,7 @@ public:
}
template <typename T>
T get(string key, int precision = 6)
T get(string key, int precision = 2)
{
T val {};
auto iter = mapFields.find(key);
@@ -44,6 +44,18 @@ public:
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] 索引名称

View File

@@ -99,10 +99,10 @@ public:
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();
bool res = tick_now - tickMS_ > ms;
bool res = tick_now - tickMS_ > second;
if (res && reset)
{
tickMS_ = tick_now;

View File

@@ -280,7 +280,7 @@ Errcode DAO::deleteUserById(std::string userId)
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);
}
@@ -342,6 +342,9 @@ Errcode DAO::insertRole(Fields& params)
auto err = DAO::insert(dao, DMRole::TABLENAME, params);
if (err == Errcode::OK && !permission.empty())
{
njson jsonarray;
if (JSON::parse(permission, jsonarray))
{
// 查询获取 roleId
std::vector<Fields> res;
@@ -349,8 +352,22 @@ Errcode DAO::insertRole(Fields& params)
err = DAO::exec(dao, sql, res);
if (err == Errcode::OK && res.size() > 0)
{
//std::string roleId = res[0].value("role_id");
//err = DAO::updateRolePermission(dao, roleId, permission);
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;

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 queryWorkModeDef(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 CODE = "code";
const string ATTR = "attr";
const string OPERATION_DATE = "operation_date";
}
namespace DMDefDeviceType

View File

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

View File

@@ -118,22 +118,22 @@ void memberJsonTest()
}
int main(int argc, char** argv)
{
// 设置控制台输出为 UTF-8 编码
SetConsoleOutputCP(CP_UTF8);
// 设置控制台输入为 UTF-8 编码(如果需要输入中文)
SetConsoleCP(CP_UTF8);
// 初始化日志
Spdlogger::init(spdlog::level::debug, "");
spdlog::info("[main] start ... ======================================================================");
spdlog::info("");
std::cout << Snowflake::instance().getId() << std::endl;
for (int i = 0; i<=10; ++i) {
std::cout << Snowflake::instance().getId() << std::endl;
}
njson json;
json = {1, 2, 3, 4};
spdlog::info(json.dump());
// 运行后台服务
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_float: { fields.set(key, json[key].get<float>()); } break;
case njson::value_t::null: {} break;
case njson::value_t::object: {} break;
case njson::value_t::array: {} break;
case njson::value_t::object: { fields.set(key, json[key].dump()); } break;
case njson::value_t::array: { fields.set(key, json[key].dump()); } break;
case njson::value_t::binary: {} break;
case njson::value_t::discarded: {} break;
default:
@@ -165,6 +165,7 @@ static std::map<std::string, HandlerOptions> g_mapHttpHandlerGet =
{"/queryPredictionDetail", HandlerOptions(&HttpEntity::queryPredictionDetail, {})},
{"/queryStatSystem", HandlerOptions(&HttpEntity::queryStatSystem, {})},
{"/queryStatStation", HandlerOptions(&HttpEntity::queryStatStation, {})},
{"/queryStatTotal", HandlerOptions(&HttpEntity::queryStatTotal, {})},
{"/queryStatDayList", HandlerOptions(&HttpEntity::queryStatDayList, {})},
{"/queryStatCharts", HandlerOptions(&HttpEntity::queryStatCharts, {})},
@@ -340,7 +341,7 @@ Errcode HttpEntity::login(const httplib::Request& req, njson& json, std::string&
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;
}
@@ -357,7 +358,7 @@ Errcode HttpEntity::queryUserList(const httplib::Request& req, njson& json, std:
{
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;
}
@@ -390,6 +391,38 @@ Errcode HttpEntity::queryPermissionList(const httplib::Request& req, njson& json
std::vector<Fields> result;
auto err = DAO::queryPermissionList(pageinfo, result);
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;
}
@@ -423,6 +456,8 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
std::vector<Fields> result;
auto err = DAO::queryRoleList(pageinfo, result);
HttpHelper::setPagination(pageinfo, result, json);
// 查询所有的角色权限关联
if (err == Errcode::OK)
{
@@ -432,8 +467,8 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
{
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)
{
auto& item = vecPermission[i];
@@ -444,7 +479,6 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
mapP[roleId].push_back(vecPermission[i]);
}
HttpHelper::setPagination(pageinfo, result, json);
for (auto& item : json["data"])
{
auto jsonpermission = njson::array();
@@ -487,6 +521,14 @@ Errcode HttpEntity::queryRoleList(const httplib::Request& req, njson& json, std:
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)
{
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)
{
Fields 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);
GetRequestParam(req, {"role_id", "name", "describe", "is_open", "permission"}, params);
auto roleId = params.value("role_id");
std::string permission = params.remove("permission");
auto dao = DaoEntity::create("");
auto err = DAO::updateRoleById(dao, params);
if (err == Errcode::OK && jsonparam.contains("permission"))
auto err = Errcode::OK;
if (params.size() > 1)
{
if (jsonparam["permission"].is_array())
err = DAO::updateRoleById(dao, params);
}
if (err == Errcode::OK && !permission.empty())
{
auto& jsonPermission = jsonparam["permission"];
std::vector<Fields> vecFields(jsonPermission.size());
int i = 0;
for (auto& item: jsonPermission)
njson jsonarray;
if (JSON::parse(permission, jsonarray))
{
auto& fields = vecFields[i];
i++;
JsonToFields(item, {"permission_id", "is_add", "is_del", "is_edit", "is_view"}, fields);
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);
}
@@ -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)
{
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("lon", "", "0.0");
params.check("lat", "", "0.0");
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)
@@ -704,13 +773,31 @@ Errcode HttpEntity::insertDevice(const httplib::Request& req, njson& json, std::
{
Fields 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)
{
Fields 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)
{
@@ -737,12 +824,14 @@ Errcode HttpEntity::queryDevicByCategory(const httplib::Request& req, njson& jso
njson jsondata = njson::array();
auto station = Application::data().getStation(stationId);
if (station)
if (station && station->status == 1)
{
std::vector<std::shared_ptr<Device>> vecDevice;
station->getDeviceByGroup(category, vecDevice);
for(auto& device: vecDevice)
{
if (device->isOpen)
{
njson jsonnode;
jsonnode["stationId"] = stationId;
@@ -753,23 +842,34 @@ Errcode HttpEntity::queryDevicByCategory(const httplib::Request& req, njson& jso
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);
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);
}
}
}
json["data"] = jsondata;
return Errcode::OK;
}
@@ -906,21 +1006,63 @@ Errcode HttpEntity::queryStatSystem(const httplib::Request& req, njson& json, st
{
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;
jsondata["launch_date"] = appdata.launchDate; //: 系统上线启用日期格式yyyy-mm-dd
jsondata["income_total"] = std::to_string(Utils::random(100, 200)); // : 累计收益精度0.01
jsondata["station_num"] = Utils::toStr(appdata.getStationCount()); // : 能源站数量
jsondata["storage_device_num "] = Utils::toStr(appdata.getStationCount()); //: 储能设备数量
jsondata["solar_device_num"] = "0"; // : 光伏设备数量
jsondata["capacity_total"] = std::to_string(Utils::random(100, 200)); // : 储能总容量kWh精度0.001
jsondata["solar_elect_gen"] = std::to_string(Utils::random(100, 200)); // : 发电总电量kWh精度0.001
jsondata["solar_elect_grid"] = std::to_string(Utils::random(100, 200)); // : 入网种电量kWh精度0.001
jsondata["storage_elect_in"] = std::to_string(Utils::random(100, 200)); // : 储能充电总电量kWh精度0.001
jsondata["storage_elect_out"] = std::to_string(Utils::random(100, 200)); // : 储能放电总电量kWh精度0.001
jsondata["income_total"] = incomeTotal; // : 累计收益精度0.01
jsondata["station_num"] = station_num; // : 能源站数量
jsondata["storage_device_num"] = station_num; //: 储能设备数量
jsondata["solar_device_num"] = solarDeviceNum; //: 光伏设备数量
jsondata["capacity_total"] = capacityTotal; // : 储能总容量kWh精度0.001
jsondata["solar_elect_gen"] = electGenTotal; // : 发电总电量kWh精度0.001
jsondata["solar_elect_grid"] = electGridTotal; // : 入网种电量kWh精度0.001
jsondata["storage_elect_in"] = electStorageIn; // : 储能充电总电量kWh精度0.001
jsondata["storage_elect_out"] = electStorageOut; // : 储能放电总电量kWh精度0.001
json["data"] = jsondata;
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)
{
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
}
json["data"] = jsondata;
return Errcode::OK;
}
Errcode HttpEntity::queryStatDayList(const httplib::Request& req, njson& json, std::string& errmsg)
{
std::string station_id = req.get_param_value("station_id");
std::string category = req.get_param_value("category");
std::string dt_start = req.get_param_value("start_date");
std::string dt_end = req.get_param_value("end_date");
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)
//std::string stationId = req.get_param_value("station_id");
//std::string category = req.get_param_value("category");
std::string dtStart = req.get_param_value("start_date");
std::string dtEnd = req.get_param_value("end_date");
if (dtEnd.empty())
{
njson jnode;
jnode["station_id"] = station_id;
if (!category.empty()) jnode["category"] = category;
jnode["dt"] = Utils::dateStr(t*1000); //日期
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);
if (dtStart.empty())
{
dtEnd = Utils::dateStr();
dtStart = Utils::dateStr(Utils::date() - 86400*7);
}
json["data"] = jsondata;
else
{
dtEnd = Utils::dateStr(Utils::time(dtStart + " 00:00:00") + 86400*7);
}
}
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;
}
@@ -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 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 (category.empty()) { errmsg = "参数[category]错误"; return Errcode::ERR_PARAM; }
if (dt.empty()) { dt=Utils::dateStr(); }
njson jsondata;
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 queryRolePermission(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 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 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);
// 场站按类别按天统计

View File

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

View File

@@ -25,16 +25,16 @@ struct REGInfo
}
};
//struct TopicInfo
//{
// std::string name;
// std::string topic;
// int deviceType;
// TopicInfo() {};
// TopicInfo(std::string name, std::string topic, int deviceType)
// :name(name), topic(topic), deviceType(deviceType)
// {};
//};
struct TopicInfo
{
std::string name;
int deviceType {0};
int polling {0}; // 召测
TopicInfo() {};
TopicInfo(std::string name, int deviceType, int polling=0)
:name(name), deviceType(deviceType), polling(polling)
{};
};
using namespace std;
@@ -47,8 +47,7 @@ public:
void destory();
void subscribe();
//int publish();
int publish(std::string topic, std::string text);
int polling();
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);
public:
// MQTT clientId (使用station 的 code)
std::string clientId;
MQTTAsync client = nullptr;
@@ -69,7 +69,7 @@ public:
bool isConnected {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 <QAction>
#include <QToolBar>
#include <QMouseEvent>
#include <QHBoxLayout>
#include "common/Spdlogger.h"
void MySplash(MainWeb* mainWin)
{
@@ -44,6 +48,47 @@ MainWeb::MainWeb()
this->setWindowTitle("光储充站监控与运营管理平台");
this->setGeometry(0, 0, 1920, 1080);
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();
@@ -52,19 +97,33 @@ MainWeb::MainWeb()
//settings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true);
//settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true); // 解决http资源加载问题
//settings->setAttribute(QWebEngineSettings::PluginsEnabled, true);
webView.setGeometry(0, 0, 1920, 1080);
// 默认设置透明, 解决加载时的白屏闪烁
//webView.page()->setBackgroundColor(Qt::transparent);
//webView.setContextMenuPolicy(Qt::NoContextMenu);
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"));
QCoreApplication::processEvents();
label1.setParent(splash.get());
label1.setStyleSheet("background-color: gray");
@@ -78,11 +137,6 @@ MainWeb::MainWeb()
label1.show();
labelProgress.show();
QObject::connect(&webView, &QWebEngineView::loadFinished, [=](bool ok)
{
if (ok)
{
int i = 0;
while ((++i)<100)
{
@@ -92,14 +146,61 @@ MainWeb::MainWeb()
QThread::msleep(20);
}
splash->finish(this);//程序启动画面结束
this->show();
}
void MainWeb::showDevTools()
{
if (layout)
{
//webView.setParent(this);
//QLayoutItem* item;
//while ((item = layout->takeAt(0)) != nullptr) { // 不断取出第一个项
// //if (item->widget()) {
// // delete item->widget(); // 删除控件
// //}
// //else if (item->layout()) { // 如果是子QLayout
// // delete item->layout(); // 删除子布局
// //}
// delete item; // 最后删除QLayoutItem本身
//}
//delete layout;
//layout = NULL;
}
else
{
qDebug() << "页面加载失败!";
// 这里可以执行加载失败后的处理
// 如果你需要先导航主页面,然后在某个事件(如按钮点击)后显示开发者工具,可以将这行代码放在事件处理函数中。
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()));
}
});
//this->show();
}

View File

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

View File

@@ -7,16 +7,17 @@
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
<script type="text/JavaScript" src="codebase/jsPlugin/jquery.min.js"></script>
<script type="text/JavaScript" src="codebase/encryption/AES.js"></script>
<script type="text/JavaScript" src="codebase/encryption/cryptico.min.js"></script>
<script type="text/JavaScript" src="codebase/encryption/crypto-3.1.2.min.js"></script>
<script type="text/JavaScript" src="codebase/webVideoCtrl.js"></script>
<script type="text/javascript" src="<%= BASE_URL %>codebase/jsPlugin/jquery.min.js"></script>
<script type="text/javascript" src="<%= BASE_URL %>codebase/encryption/AES.js"></script>
<script
type="text/javascript"
src="<%= BASE_URL %>codebase/encryption/cryptico.min.js"
></script>
<script
type="text/javascript"
src="<%= BASE_URL %>codebase/encryption/crypto-3.1.2.min.js"
></script>
<script type="text/javascript" src="<%= BASE_URL %>codebase/webVideoCtrl.js"></script>
</head>
<body>
<noscript>

View File

@@ -82,11 +82,7 @@
<template #headerCell="{ column }">
<template v-if="column.key === 'action'">
<span>
<!-- <i
class="iconfont icon-add"
@click="handleAdd"
:style="{ cursor: formStatus == 'read' ? 'not-allowed' : 'pointer' }"
></i> -->
<PlusOutlined
@click="handleAdd"
:style="{ cursor: formStatus == 'read' ? 'not-allowed' : 'pointer' }"