From 4ce1368321f93dacc31fb5e5f39d349a76f202a1 Mon Sep 17 00:00:00 2001 From: lixiaoyuan Date: Fri, 26 Sep 2025 16:51:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=BF=90=E8=A1=8C=E7=9B=91?= =?UTF-8?q?=E6=8E=A7=E6=98=BE=E7=A4=BA=E4=BF=A1=E6=81=AF,=E6=8F=90?= =?UTF-8?q?=E4=BA=A4electron=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/config/conf.json | 3 + ...erialSymbolsEnergyProgramTimeUsedSharp.png | Bin 0 -> 1953 bytes electron/icons/favicon.ico | Bin 0 -> 67646 bytes electron/icons/icon.ico | Bin 0 -> 1293 bytes electron/icons/yhicon.ico | Bin 0 -> 67646 bytes electron/main.js | 85 ++++++++ electron/package.json | 17 ++ src/app/AppData.h | 2 +- src/app/Station.cpp | 181 +++++++++++++----- src/app/Station.h | 98 +++++----- src/main.cpp | 6 + src/protocol/HttpEntity.cpp | 48 +++-- src/protocol/MqttEntity.cpp | 22 +-- 13 files changed, 337 insertions(+), 125 deletions(-) create mode 100644 electron/config/conf.json create mode 100644 electron/icons/MaterialSymbolsEnergyProgramTimeUsedSharp.png create mode 100644 electron/icons/favicon.ico create mode 100644 electron/icons/icon.ico create mode 100644 electron/icons/yhicon.ico create mode 100644 electron/main.js create mode 100644 electron/package.json diff --git a/electron/config/conf.json b/electron/config/conf.json new file mode 100644 index 0000000..2d84846 --- /dev/null +++ b/electron/config/conf.json @@ -0,0 +1,3 @@ +{ + "weburl": "http://118.195.161.113" +} \ No newline at end of file diff --git a/electron/icons/MaterialSymbolsEnergyProgramTimeUsedSharp.png b/electron/icons/MaterialSymbolsEnergyProgramTimeUsedSharp.png new file mode 100644 index 0000000000000000000000000000000000000000..bbc55abe9494706383dcdd8590f90d2ab474c089 GIT binary patch literal 1953 zcmV;S2VVGzP)Fh^dc56U{C#_^mEh0SL<+!#O2l&@Sirx#c-VbwQ~jf^ zzEySgYO3m4D^1q}Q;6i2LIU#&|@p$_T!a;CVSNCG_vQ3iZvr_;OxoC)g*u4tj zucof9#WYBlEZ?01h`l6mfAW;bM=L1+pb(fa z=S$I(==su)W_JnzPp@!Wb5cnjyEZMJ`3IQDg0J{Fzu$bP0L+>B!{9;2DJ8V2-}=B~ z+~*rSwhb&_QZcsxN@{^Zta6|Ktl%c83!iZcz=uqGUgrI+yhM`h^mYnhgj1RKPqz1? z=@bA^@FeN|cXH`clE%IlCkIKYI|VQRxAcCzqc>0@+NJ&5=f^8a8?mS=0t!G7ckRu} z-x!VF-;i(GOcw5f~tP8$8++rIuw8dAsPNt&iz5;+pyktPd6r^2q*xHv`#*Wd>c|D z0%LHSXku>^fCJI$-J}=+W|41Xljjkbj*#Ri?oI(X@T||w?~c<;PAwu|7NoCBoDbEd z0EWNEd$5MVP^^)D{c^%7z;zs~HB@0T^NpFX z?#Vea6)%8MHs%(XIh0#>AtF#B-^jG&9nmNN%UD03FlF?s+T$S+XpwJY@#PeN2bp#q zFnb!XW?drCCSQjCFE*ZjP66~0=^ihf2CS*B2vU=8eRlFe5mNvir1~$D1h8Mn zcMK8WU+pAUUG2;Kf8&b@=P3Z7;7R}Oo(=+_cLC+8=0A;pwew$1ab+*VzjO6(olyW5 z2~YmXn6Gjv$|xXqRQL0$9_;-Hh5`Tz0|}#miL@3Na1;HKj9m9k>?4*bfDwSOXpycu)UB-hStY1dsq5uXU0{PmDwt;YhFG=qo9r~>?3cw=K%L^v|YHZ=xZ7K!OMWcOP zBKZhidj9Iey6#H0_dV4uVv0J?)w0w=VREPOujT%RR9OMoq7pM zp3ko#;M7UL!~*J&+D|0=cu)oM2Ostf`O+H!8Ylvga0OvY`6~%iW8~Pw*W2eu_!F1Qb_&3Q->3+x z`lU+(%FFS_)Xn49y~pg5(+AiVAB%?kegG6eACb;6NR{69aZLd7F;#WS+L!no0Z5X1 zSMAiWY*Y|muq8G(ux0)N&%$7wHT`uKrvLM36ugzgKIHXDS%?A zN)sprkOtS}R%1D!0Ae9os2vKRP~u{Ry&3`F>tFH1Paz3qLjex4H?_$fVQ@)!w#2(5tAGi!fv#Op^CnSZM%(a}J0CGiO<#AB}6u`<6Sb6g~0#E=e zM_}d6=LkRntQ>(%o39lXM*uCPGxb9OWJ-)ySQLO3(wX|905T;;D=Z2?3+YV#Pym?{ zqZJkfpoMg%ekg#(Z)dQ7sH@2rvPw)Nf&`*d7}W1g?uJ{ zDS%9fI93=Gz_F0e#4iPq2@%H%g911f@|pOh05T!sSYc2A$3i|6zZAfci8!|V{{a91 n|Nk+F<6Qs%00v1!K~w_(5t@ulMjyOR00000NkvXXu0mjfZ98w{ literal 0 HcmV?d00001 diff --git a/electron/icons/favicon.ico b/electron/icons/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a10b03e1f835864fc55871e250c81badc7cb2f53 GIT binary patch literal 67646 zcmeHQJ96Vj5FHk!(q`JoDL35Ep)>I)4&@s-a21*P1hzsSg}T8WfjWZ24OGkR1~9;I z#7{TS17J80Drne1b3X6AZVU&Yf00e*l5C8%|00;m9AOHk_01yBIg(C3$a<_i|=l*x>6JhZ3>C2STdw#k9 z?~i})57?){fa4DQPlNp&G!OpE<(~Bi{=q-;f4Le!{Flo;@_*UfgMaXk{9m>Pz(4rM z{J&fcApXnc9`nDlxd;E?ANjv*4S;{}kNJPO8bJJ)%RT0QWpfYy!9VhU*&4V-{`r|w z>6}*c{HeH3dZvI?qm@h9a}=lvJx4{fXG==!jhpQAl1^+2f&8JTApAT0ldJ6tipqfve;6ER(QuGx3e?-;)Pppq; zZtn>AKjxIVr_Z^2{;b<)ZT^|pp80>Oz1(f6j$Kn1*H_iqlsm?~+Iby#!Zl#<-|-)E zPdpuXXM8%3)30j2tNR$94ry6y;%q(y3YYYKneF zx)ra#$VSx9%Mu5FJ!U@ojOa2Xs3KGXWzLY{giU=`!j|HxDDUlwK6CEr9APNu8rHDA9C&2a^JR@_;UgHABTU^ zW3M$A)Zxf{YgzZd*#_^+P%QpJ~&A8{VA;2!+z^v`Q?gxOBXsa7vn zH9+m}t@?oYm&bpz7Q3;+{z5%xHDJj-w-5fc{3pK#_Mwf1Un0{&`Em19Nd= zZ#9srO~k)0{+WMXGe5!ADgG>u?NV{iV*vkp{zuLM78*KR2l(&Df69CEBjy&wzvB5H zj{9&Uo;Ww3jjbHcA^!WtKkK0R9#A>_)BO+D%T4Xd=Rd>vuQZV6p3rET(!_r}cGxun zBYz$+)du*tQE{$w0q}3bKi86@2Ee}^|2b*^{M+)+wdFJ)0RQ&TZiR`DyUbS}pzQ@+4)@gfa?H`rBY;BS&ZGpXI zdl8*?XYIN^xAFZY`!iJ#+P{T1_2)0LpS(ZWTt#3nxJ!-gR`1leZN)Vmt;&bPYh=G2 z*-OT3RoBmDHI~432Wm64H`Ia9exeS9_KG?X+K<$M(0+){a|&qBQ(KF$ezINIKHGl= z{tU*ikxhr%`f9!|*jw@r{bT!;PrFsETKfGK*|p%h^EHs2%^eQk&m9i!x`UlRvv+j< UEwZZy0{^Ol&}N6wKFo3Z2_@|cwEzGB literal 0 HcmV?d00001 diff --git a/electron/icons/icon.ico b/electron/icons/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4c1689ee0f3c9b5cf8e3b8c500ffb341bfd7fd66 GIT binary patch literal 1293 zcmV+o1@ig;0096203aX$0000W0QUp{02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|AOHXW zAP5Ek0047(dh`GQ00d`2O+f$vv5yP z0Dy!50Qvv`0D$NK0Cg|`0P0`>06Lfe02gqax=}m;00ebOL_t(oh3%HlYg|YNKxC)j8`f7d1f*+ z$pDC0v)vwxs|$_he+rN<=OS@dKr9PH((7s60Goz2GznMt3bQM~sd8=wq0n=bo+#3R z=m)YUCdG38+UmaoaPsm@8JI@~97Wf~Y(qqDo7p2GGKJWrkS;&f|^5>`d-BW z%%rX+sCMF*pe7krmRdfzF;~t-_XJQQn|2gT-TGd|0k*=Vn80)b(`wB7E>QYLmIP~a z7gC6@+v#X&E*cA6L5+C<%)nHB`#S)QbczSztH&-J%Ss?+fe0khPzu0;bj4i|uBDA> z+NBHUr>~!_t-o}6rUdZ$%k||^f}J!hjcQYq#+8Le9UymME()FAOf|q%ryYRFSlLvf zfoZB(!r|*@YwG}Q?`GQG&1?^T4Ve;5`=w~N_ zJGZv>F_d~9cV3JoOHc605VdoPAR?G)@rO5t#Q|DL*vr?GSknm^r{m{p zi;ZP~BOje|z@xrBeyjf4*YWmPjm290?8hen!ypP(-6R5H-~%_Zh_wAsvScy+!vTV8 zB60vp_YOd!0b)ig85OBB3rbTYtsSA7L_%8AHkK# zJFtQuDLz%oXUvjJx&+pAY7(oahsMR@Z%jyOk4`N+(j>ke4GHA3?=%()rF04Y87?kk%=zI}0MBYJan+P>QTt}QlVU}Y3+ zNKo^}uUp(1TF$9bK1$TqL|le+{@1^M{mXR$c=EkhZvc}bX>MSwf^4X}yCWm+Wjn_U z1Y{60g5*V*hhFuIePGiY%hgx_o+zA&Y|PdKiRhey{W58tt5@gWaE0sm+P3!ozkaNa zj}Tj;(;IJA;{kU#RLEz>gZ)=K7tdkQ`#|-DM?($A(u$}SyW&FtU3>hUGg*|ZI1WkY z`kmHH9ddR9voQ=Z3@*-MGu!a^^`8fXAJ_wXU|stQNc1^U0HI!C00000NkvXXu0mjf Dj_*B-a`5*rK=%Y)xU4BW+ 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 O191$*G4Nl9f&UN07GA&r literal 0 HcmV?d00001 diff --git a/electron/main.js b/electron/main.js new file mode 100644 index 0000000..ee8832d --- /dev/null +++ b/electron/main.js @@ -0,0 +1,85 @@ +const { app, BrowserWindow, Menu, globalShortcut } = require('electron') + +// 在主进程中 +const fs = require('fs').promises; // 使用 Promise 版本的 fs API +const path = require('path'); + +const configPath = path.join(__dirname, 'config/conf.json'); // 建议使用 path.join 构造路径 + + +async function readConfig() { + try { + const data = await fs.readFile(configPath, 'utf8'); + const config = JSON.parse(data); + return config; + } catch (error) { + console.error('read config file error:', error); + // 处理错误,例如返回默认配置或抛出异常 + throw error; + } +} + +// 保持一个对于 window 对象的全局引用, +// window 会被自动地关闭 +var mainWindow = null +Menu.setApplicationMenu(null); + +function createWindow() { + //当app准备好后,执行createWindow创建窗口 + mainWindow = new BrowserWindow({ + x: 0, //窗口位置x坐标 + y: 0, //窗口位置y坐标 + width: 1920, //窗口宽度 + height: 1080, //窗口高度 + title: '能源站监控与运行管理平台', + autoHideMenuBar: true, //自动隐藏菜单档 + alwaysOnTop: false, //置顶 + show: false, // hide the window + webPreferences: { + partition: String(+new Date()) + }, + }) + + readConfig().then((data) => { + console.log('read CONFIG:', data); + //加载页面 + mainWindow.loadURL(data.weburl) // 'http://127.0.0.1:19601' + }); + + mainWindow.once('ready-to-show', () => { + mainWindow.show(); + }) + + //注册Ctr+x事件 + const ret = globalShortcut.register('CommandOrControl+F12', () => { + console.log('CommandOrControl+F12 is pressed') + mainWindow.setFullScreen(!mainWindow.isFullScreen()) + }) + + if (!ret) { + console.log('registration failed') + } + + // 验证是否注册成功 + console.log("regist Ctrl+F12:", globalShortcut.isRegistered('CommandOrControl+F12')) + // app.on('activate', function () { + // // On macOS it's common to re-create a window in the app when the + // // dock icon is clicked and there are no other windows open. + // if (BrowserWindow.getAllWindows().length === 0) createWindow() + // }) +} + +app.on('ready', () => { createWindow() }) +app.whenReady().then(); + +// Quit when all windows are closed. +app.on('window-all-closed', function () { + // Unregister a shortcut. + globalShortcut.unregister('F12') + + // Unregister all shortcuts. + globalShortcut.unregisterAll() + // On macOS it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin') app.quit() +}) \ No newline at end of file diff --git a/electron/package.json b/electron/package.json new file mode 100644 index 0000000..fa4afb8 --- /dev/null +++ b/electron/package.json @@ -0,0 +1,17 @@ +{ + "name": "essclient", + "version": "1.0.0", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "electron .", + "package": "electron-packager . essclient --win --arch=x64 --out=dist --icon=icons/icon.ico --ignore=node_modules --overwrite --asar --electron-zip-dir=C:/Users/lixy/AppData/Local/electron/Cache/" + }, + "author": "", + "license": "ISC", + "description": "", + "devDependencies": { + "electron": "^38.1.0", + "electron-packager": "^17.1.2" + } +} \ No newline at end of file diff --git a/src/app/AppData.h b/src/app/AppData.h index 36691d6..09a1f35 100644 --- a/src/app/AppData.h +++ b/src/app/AppData.h @@ -141,7 +141,7 @@ public: //std::vector> vecElectPeriods; // 场站信息 - std::unordered_map> mapStation; + std::map> mapStation; // 角色信息 std::unordered_map> mapRole; diff --git a/src/app/Station.cpp b/src/app/Station.cpp index b739544..8ded1d9 100644 --- a/src/app/Station.cpp +++ b/src/app/Station.cpp @@ -207,15 +207,69 @@ void Station::setGarewayWorkMode() string Station::getGatewayMode() { // 0:手动,1:峰谷套利,2:增网配容,3:应急供电,4:并网保电,5:自定时段 - if (workModeGateway == 0) { return "手动"; } - else if (workModeGateway == 1) { return "峰谷套利"; } - else if (workModeGateway == 2) { return "增网配容"; } - else if (workModeGateway == 3) { return "应急供电"; } - else if (workModeGateway == 4) { return "并网保电"; } - else if (workModeGateway == 5) { return "自定时段"; } + if (gatewayParam.mode == 0) { return "手动"; } + else if (gatewayParam.mode == 1) { return "峰谷套利"; } + else if (gatewayParam.mode == 2) { return "增网配容"; } + else if (gatewayParam.mode == 3) { return "应急供电"; } + else if (gatewayParam.mode == 4) { return "并网保电"; } + else if (gatewayParam.mode == 5) { return "自定时段"; } else { return "--"; }; } +static map mapPeriodType = +{ + {1, "谷"}, {2, "平"}, {3, "峰"}, {4, "尖"} +}; +static map mapPeriodOper = +{ + {0, "停"}, {1, "充"}, {2, "充"}, {3, "放"}, {4, "放"} +}; + +string Station::getGatewayParam() +{ + stringstream ss; + std::string str1 = "峰谷套利时段:
"; + std::string str2 = "自定时段:
"; + { + njson json; + if (JSON::parse(gatewayParam.param1, json)) + { + for (int i = 0; i(); + ss << ":" << setw(2) << setfill('0') << jsonitem[1].get() << " "; + ss << mapPeriodType[jsonitem[2].get()] << ") "; + } + str1 += ss.str() + "
"; + } + } + } + { + njson json; + if (JSON::parse(gatewayParam.param2, json)) + { + for (int i = 0; i(); + ss << ":" << setw(2) << setfill('0') << jsonitem[1].get() << " "; + ss << mapPeriodOper[jsonitem[2].get()] << ") "; + } + str2 += ss.str() + "
"; + } + } + } + return str1 + "
" + str2; +} + void Station::checkDevice() { for (auto& item: mapDevice) @@ -263,14 +317,37 @@ void Station::readRuntimeData(int deviceNo, string addr, int val) statData.ts = Utils::time(); if (addr == "0x002F") { statData.dayElectIn = val; } //日充电电量 R uint32 1kWh 0x002F else if (addr == "0x0031") { statData.dayElectOut = val; } //日放电电量 R uint32 1kWh 0x0031 - else if (addr == "0x0033") { statData.dayFeeIn = val; } //日充电费用 R uint32 1RMB 0x0033 + else if (addr == "0x0033") { statData.dayFeeIn = val; } //日充电费用 R uint32 1RMB 0x0033 else if (addr == "0x0035") { statData.dayFeeOut = val; } //日放电费用 R uint32 1RMB 0x0035 else if (addr == "0x0037") { statData.dayIncome = val; } //日收益 R int32 1RMB 0x0037 else if (addr == "0x004D") { statData.totalElectIn = val; } //总充电电量 R uint32 1kWh 0x004D else if (addr == "0x004F") { statData.totalElectOut = val; } //总放电电量 R uint32 1kWh 0x004F - else if (addr == "0x0051") { statData.totalFeeIn = val; } //总充电费用 R uint32 1RMB 0x0051 - else if (addr == "0x0053") { statData.totalFeeOut = val; } //总放电费用 R uint32 1RMB 0x0053 + else if (addr == "0x0051") { statData.totalFeeIn = val; } //总充电费用 R uint32 1RMB 0x0051 + else if (addr == "0x0053") { statData.totalFeeOut = val; } //总放电费用 R uint32 1RMB 0x0053 else if (addr == "0x0055") { statData.totalIncome = val; } //总收益 R int32 1RMB 0x0055 + + else if (addr == "0x0039") { statData.dayElectIn_J = val; } //日正向尖有功电能 R uint32 1kWh 0x0039 + else if (addr == "0x003B") { statData.dayElectIn_F = val; } //日正向峰有功电能 R uint32 1kWh 0x003B + else if (addr == "0x003D") { statData.dayElectIn_P = val; } //日正向平有功电能 R uint32 1kWh 0x003D + else if (addr == "0x003F") { statData.dayElectIn_G = val; } //日正向谷有功电能 R uint32 1kWh 0x003F + else if (addr == "0x0041") { statData.dayElectIn_Total = val; } //日正向总有功电能 R uint32 1kWh 0x0041 + + else if (addr == "0x0043") { statData.dayElectOut_J = val; } //日反向尖有功电能 R uint32 1kWh 0x0043 + else if (addr == "0x0045") { statData.dayElectOut_F = val; } //日反向峰有功电能 R uint32 1kWh 0x0045 + else if (addr == "0x0047") { statData.dayElectOut_P = val; } //日反向平有功电能 R uint32 1kWh 0x0047 + else if (addr == "0x0049") { statData.dayElectOut_G = val; } //日反向谷有功电能 R uint32 1kWh 0x0049 + else if (addr == "0x004B") { statData.dayElectOut_Total = val; } //日反向总有功电能 R uint32 1kWh 0x004B + + else if (addr == "0x0057") { statData.totalElectIn_J = val; } //总正向尖有功电能 R uint32 1kWh 0x0057 + else if (addr == "0x0059") { statData.totalElectIn_F = val; } //总正向峰有功电能 R uint32 1kWh 0x0059 + else if (addr == "0x005B") { statData.totalElectIn_P = val; } //总正向平有功电能 R uint32 1kWh 0x005B + else if (addr == "0x005D") { statData.totalElectIn_G = val; } //总正向谷有功电能 R uint32 1kWh 0x005D + else if (addr == "0x005F") { statData.totalElectIn_Total = val; } //总正向总有功电能 R uint32 1kWh 0x005F + else if (addr == "0x0061") { statData.totalElectOut_J = val; } //总反向尖有功电能 R uint32 1kWh 0x0061 + else if (addr == "0x0063") { statData.totalElectOut_F = val; } //总反向峰有功电能 R uint32 1kWh 0x0063 + else if (addr == "0x0065") { statData.totalElectOut_P = val; } //总反向平有功电能 R uint32 1kWh 0x0065 + else if (addr == "0x0067") { statData.totalElectOut_G = val; } //总反向谷有功电能 R uint32 1kWh 0x0067 + else if (addr == "0x0069") { statData.totalElectOut_Total = val; } //总反向总有功电能 R uint32 1kWh 0x0069 } } @@ -342,9 +419,12 @@ void Station::readCoolingData(int deviceNo, string addr, int val) else if (addr == "0x100E") { ; }// 出水压力传感器 R uint16 0:正常,1:告警 0x100E } -void Station::readGatewayMode(int mode) +void Station::readGatewayMode(int mode, string p1, string p2, string p3) { - this->workModeGateway = mode; + this->gatewayParam.mode = mode; + this->gatewayParam.param1 = p1; + this->gatewayParam.param2 = p2; + this->gatewayParam.param3 = p3; if (mode != this->workMode) { //this->setGarewayWorkMode(); @@ -464,34 +544,6 @@ void Station::writeStatistic() if (statData.ts > 0) { - Fields fields; - fields.set("dt", Utils::dateStr(statData.ts)); - fields.set("station_id", this->stationId); - fields.set("device_id", 0); - fields.set("elect_in", statData.dayElectIn); - fields.set("elect_out", statData.dayElectOut); - fields.set("fee_in", statData.dayFeeIn); - fields.set("fee_out", statData.dayFeeOut); - fields.set("income", statData.dayIncome); - //fields.set("num_in", ""); - //fields.set("num_out", ""); - //fields.set("num_err", ""); - //fields.set("t_in", ""); - //fields.set("t_out", ""); - //fields.set("usage_rate", ""); - fields.set("elect_in_total", statData.totalElectIn); - fields.set("elect_out_total", statData.totalElectOut); - fields.set("fee_in_total", statData.totalFeeIn); - fields.set("fee_out_total", statData.totalFeeOut); - fields.set("income_total", statData.totalIncome); - - dao->setTableName("stat_storage"); - std::vector vecKeys = { - "elect_in", "elect_out", "num_in", "num_out", "num_err", "t_in", "t_out", "usage_rate", "fee_in", "fee_out", - "elect_in_total", "elect_out_total", "fee_in_total", "fee_out_total", "income_total" - }; - dao->duplicateUpdate(fields, vecKeys); - { // stat_day Fields fields; fields.set("dt", Utils::dateStr(statData.ts)); @@ -503,14 +555,54 @@ void Station::writeStatistic() } { Fields fields; + fields.set("dt", Utils::dateStr(statData.ts)); fields.set("station_id", this->stationId); - fields.set("elect_in", statData.dayElectIn); - fields.set("elect_out", statData.dayElectOut); - fields.set("income", statData.dayIncome); + fields.set("E_in", statData.totalElectIn); + fields.set("E_in_J", statData.totalElectIn_J); + fields.set("E_in_F", statData.totalElectIn_F); + fields.set("E_in_P", statData.totalElectIn_P); + fields.set("E_in_G", statData.totalElectIn_G); + fields.set("E_out", statData.totalElectOut); + fields.set("E_out_J", statData.totalElectOut_J); + fields.set("E_out_F", statData.totalElectOut_F); + fields.set("E_out_P", statData.totalElectOut_P); + fields.set("E_out_G", statData.totalElectOut_G); + fields.set("fee_in", statData.totalFeeIn); + fields.set("fee_Out", statData.totalFeeOut); + fields.set("income", statData.totalIncome); dao->setTableName("stat_total"); - dao->duplicateUpdate(fields, {"elect_in", "elect_out", "income"}); - } + dao->duplicateUpdate(fields, { + "E_in", "E_in_J", "E_in_F", "E_in_P", "E_in_G", + "E_out", "E_out_J", "E_out_F", "E_out_P", "E_out_G", + "fee_in", "fee_Out", "income" + }); + } + { + Fields fields; + fields.set("dt", Utils::dateStr(statData.ts)); + fields.set("station_id", this->stationId); + fields.set("E_in", statData.dayElectIn); + fields.set("E_in_J", statData.dayElectIn_J); + fields.set("E_in_F", statData.dayElectIn_F); + fields.set("E_in_P", statData.dayElectIn_P); + fields.set("E_in_G", statData.dayElectIn_G); + fields.set("E_out", statData.dayElectOut); + fields.set("E_out_J", statData.dayElectOut_J); + fields.set("E_out_F", statData.dayElectOut_F); + fields.set("E_out_P", statData.dayElectOut_P); + fields.set("E_out_G", statData.dayElectOut_G); + fields.set("fee_in", statData.dayFeeIn); + fields.set("fee_Out", statData.dayFeeOut); + fields.set("income", statData.dayIncome); + dao->setTableName("stat_total_day"); + + dao->duplicateUpdate(fields, { + "E_in", "E_in_J", "E_in_F", "E_in_P", "E_in_G", + "E_out", "E_out_J", "E_out_F", "E_out_P", "E_out_G", + "fee_in", "fee_Out", "income" + }); + } } { @@ -532,5 +624,4 @@ void Station::writeStatistic() fields.set("value", MapValueToJson(npos, mapCacheElectCharger)); dao->duplicateUpdate(fields, {"value"}); } - } diff --git a/src/app/Station.h b/src/app/Station.h index f12f207..30d72c6 100644 --- a/src/app/Station.h +++ b/src/app/Station.h @@ -116,13 +116,14 @@ public: void checkDevice(); string getGatewayMode(); + string getGatewayParam(); void readAlert(std::shared_ptr device, std::string addr, int v, std::string text); void readRuntimeData(int deviceNo, string addr, int val); void readTHData(int deviceNo, string addr, int val); void readFire40Data(int deviceNo, string addr, int val); void readCoolingData(int deviceNo, string addr, int val); - void readGatewayMode(int mode); + void readGatewayMode(int mode, string p1, string p2, string p3); void readGatewayStatus(int cdzStatus, int emuStatus); void setCache(int datatype, std::vector& vd); @@ -144,9 +145,16 @@ public: bool isConnected {false}; int workMode {}; // 运行模式 - int workModeGateway { -1 }; // 运行模式 int runPolicyId {}; // 运行策略 + + struct { + int mode {-1}; // 运行模式 + std::string param1; + std::string param2; + std::string param3; + } gatewayParam; + /////////////////////////////////////////////////////////////////////////////////////////////// /// === 系统统计 === // 累计发电量,单位:kWh @@ -163,22 +171,6 @@ public: // 储能容量 double capacity {}; - /////////////////////////////////////////////////////////////////////////////////////////////// - /// === 日统计 === - //double storageIn {}; // 储能充电电量 - //double storageOut {}; // 储能放电电量 - //int storageNumIn {}; // 储能充电次数 - //int storageNumOut {}; // 储能放电次数 - //int storageNumErr {}; // 储能故障次数 - //double solarGen {}; // 光伏发电电量 - //double solarGrid {}; // 光伏入网电量 - //int solarNumErr {}; // 光伏故障次数 - //double chargeElect {}; // 充电设备充电电量 - //int chargeNum {}; // 充电设备充电次数 - //int chargeNumErr {}; // 充电设备故障次数 - //double incomeElect {}; // 发电收益金额 - //double incomeCharge {}; // 充电收益金额 - /////////////////////////////////////////////////////////////////////////////////////////////// /// === 环境 === // 光照度 @@ -220,45 +212,41 @@ public: struct { int64_t ts {0}; - float totalElectIn {0.0}; //总充电电量 R uint32 1kWh 6659(0x112D) 0x112C - float totalElectOut {0.0}; //总放电电量 R uint32 1kWh 4925(0x112F) 0x112E - float totalFeeIn {0.0}; //总充电费用 R uint32 1RMB 6605(0x1131) 0x1130 - float totalFeeOut {0.0}; //总放电费用 R uint32 1RMB 4949(0x1133) 0x1132 - float totalIncome {0.0}; //总收益 R int32 1RMB -1 0x1134 - //储能充放电时段hh R uint16 时 336 0x01 0x121C - //储能充放电时段mm R uint16 分 0 0x01 0x121D - //储能充放电时段ss R uint16 秒 0 0x01 0x121E + float dayElectIn {0.0}; // 日充电电量 R uint32 1kWh 0x002F + float dayElectOut {0.0}; // 日放电电量 R uint32 1kWh 0x0031 + float dayFeeIn {0.0}; // 日充电费用 R uint32 1RMB 0x0033 + float dayFeeOut {0.0}; // 日放电费用 R uint32 1RMB 0x0035 + float dayIncome {0.0}; // 日收益 R int32 1RMB 0x0037 + + float dayElectIn_J {0.0}; //日正向尖有功电能 R uint32 1kWh 0x0039 + float dayElectIn_F {0.0}; //日正向峰有功电能 R uint32 1kWh 0x003B + float dayElectIn_P {0.0}; //日正向平有功电能 R uint32 1kWh 0x003D + float dayElectIn_G {0.0}; //日正向谷有功电能 R uint32 1kWh 0x003F + float dayElectIn_Total {0.0};//日正向总有功电能 R uint32 1kWh 0x0041 - float totalDurationIn {0.0}; - float totalDurationOut {0.0}; + float dayElectOut_J {0.0}; //日反向尖有功电能 R uint32 1kWh 0x0043 + float dayElectOut_F {0.0}; //日反向峰有功电能 R uint32 1kWh 0x0045 + float dayElectOut_P {0.0}; //日反向平有功电能 R uint32 1kWh 0x0047 + float dayElectOut_G {0.0}; //日反向谷有功电能 R uint32 1kWh 0x0049 + float dayElectOut_Total {0.0}; //日反向总有功电能 R uint32 1kWh 0x004B - float dayElectIn {0.0}; // 日充电电量 R uint32 1kWh 0 0x110E - float dayElectOut {0.0}; // 日放电电量 R uint32 1kWh 0 0x1110 - float dayFeeIn {0.0}; // 日充电费用 R uint32 1RMB 0 0x1112 - float dayFeeOut {0.0}; // 日放电费用 R uint32 1RMB 0 0x1114 - float dayIncome {0.0}; // 日收益 R int32 1RMB 0 0x1116 + float totalElectIn {0.0}; // 总充电电量 R uint32 1kWh 0x004D + float totalElectOut {0.0}; // 总放电电量 R uint32 1kWh 0x004F + float totalFeeIn {0.0}; // 总充电费用 R uint32 1RMB 0x0051 + float totalFeeOut {0.0}; // 总放电费用 R uint32 1RMB 0x0053 + float totalIncome {0.0}; // 总收益 R int32 1RMB 0x0055 - //日正向尖有功电能 R uint32 1kWh 0x0039 - //日正向峰有功电能 R uint32 1kWh 0x003B - //日正向平有功电能 R uint32 1kWh 0x003D - //日正向谷有功电能 R uint32 1kWh 0x003F - //日正向总有功电能 R uint32 1kWh 0x0041 - //日反向尖有功电能 R uint32 1kWh 0x0043 - //日反向峰有功电能 R uint32 1kWh 0x0045 - //日反向平有功电能 R uint32 1kWh 0x0047 - //日反向谷有功电能 R uint32 1kWh 0x0049 - //日反向总有功电能 R uint32 1kWh 0x004B + float totalElectIn_J {0.0}; //总正向尖有功电能 R uint32 1kWh 0x0057 + float totalElectIn_F {0.0}; //总正向峰有功电能 R uint32 1kWh 0x0059 + float totalElectIn_P {0.0}; //总正向平有功电能 R uint32 1kWh 0x005B + float totalElectIn_G {0.0}; //总正向谷有功电能 R uint32 1kWh 0x005D + float totalElectIn_Total {0.0}; //总正向总有功电能 R uint32 1kWh 0x005F - //总正向尖有功电能 R uint32 1kWh 0x0057 - //总正向峰有功电能 R uint32 1kWh 0x0059 - //总正向平有功电能 R uint32 1kWh 0x005B - //总正向谷有功电能 R uint32 1kWh 0x005D - //总正向总有功电能 R uint32 1kWh 0x005F - //总反向尖有功电能 R uint32 1kWh 0x0061 - //总反向峰有功电能 R uint32 1kWh 0x0063 - //总反向平有功电能 R uint32 1kWh 0x0065 - //总反向谷有功电能 R uint32 1kWh 0x0067 - //总反向总有功电能 R uint32 1kWh 0x0069 + float totalElectOut_J {0.0}; //总反向尖有功电能 R uint32 1kWh 0x0061 + float totalElectOut_F {0.0}; //总反向峰有功电能 R uint32 1kWh 0x0063 + float totalElectOut_P {0.0}; //总反向平有功电能 R uint32 1kWh 0x0065 + float totalElectOut_G {0.0}; //总反向谷有功电能 R uint32 1kWh 0x0067 + float totalElectOut_Total {0.0}; //总反向总有功电能 R uint32 1kWh 0x0069 } statData; @@ -267,8 +255,8 @@ public: } runtimeData; - int cdzStatus {-1}; - int emuStatus {-1}; + int cdzStatus {-1}; // 充电桩 1:在线,0:离线 + int emuStatus {-1}; // 储能 1:在线,0:离线 std::map mapAlertCache; diff --git a/src/main.cpp b/src/main.cpp index bcfa9a7..a07845a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,6 +29,7 @@ int SM2_test() { + // 未压缩格式(最常见) // 前缀 : 04 (1字节) X坐标 : 32字节(64个十六进制字符), Y坐标 : 32字节(64个十六进制字符),总长度 : 1 + 32 + 32 = 65字节 = 130个十六进制字符 std::string hex_pub_key = "04661013d0b881d817085a251f0c0a7024e72c76e6eb0fd22c0170a508b123864ef7514df30cecb45deecf9b35810d0315b5164d63199c971ac3323c228ab48606"; @@ -166,6 +167,11 @@ void OpensslSM2_test() int main(int argc, char** argv) { + stringstream ss; + + ss << "(" << setw(2) << setfill('0') << 1; + std::cout << ss.str(); + // 设置控制台输出为 UTF-8 编码 SetConsoleOutputCP(CP_UTF8); // 设置控制台输入为 UTF-8 编码(如果需要输入中文) diff --git a/src/protocol/HttpEntity.cpp b/src/protocol/HttpEntity.cpp index 9b754d0..aa6b352 100644 --- a/src/protocol/HttpEntity.cpp +++ b/src/protocol/HttpEntity.cpp @@ -711,13 +711,18 @@ Errcode HttpEntity::queryStationOverview(const httplib::Request& req, njson& jso { return Errcode(ret); } - njson jsonStorage = njson::parse(R"({"category":1, "gateway":0, "count":0, "power":0.0})"); - auto station = Application::data().getStation(Utils::toInt(stationId)); - jsonStorage["workmode"] = station ? station->getGatewayMode() : "--"; - + njson jsonStorage = njson::parse(R"({"category":1, "count":0, "power":0.0})"); njson jsonCharge = njson::parse(R"({"category":2, "count":0, "power":0.0})"); njson jsonSolar = njson::parse(R"({"category":3, "count":0, "power":0.0})"); njson jsonSecurity = njson::parse(R"({"category":4, "count":0, "power":0.0})"); + //auto station = Application::data().getStation(Utils::toInt(stationId)); + //if (station) + //{ + // jsonStorage["msg"] = station->getGatewayParam(); + // jsonStorage["workmode"] = station->getGatewayMode(); + // jsonStorage["emu"] = station->emuStatus == 1 ? "在线" : (station->emuStatus == 0 ? "离线" : "--"); + // jsonStorage["cdz"] = station->cdzStatus == 1 ? "在线" : (station->cdzStatus == 0 ? "离线" : "--"); + //} auto videoInfo = Config::getVideoInfo(stationId); if (videoInfo) { @@ -922,6 +927,16 @@ Errcode HttpEntity::queryDevicByCategory(const httplib::Request& req, njson& jso } } json["data"] = jsondata; + + njson jsongateway = njson::object(); + if (station) + { + jsongateway["msg"] = station->getGatewayParam(); + jsongateway["workmode"] = station->getGatewayMode(); + jsongateway["emu"] = station->emuStatus == 1 ? "在线" : (station->emuStatus == 0 ? "离线" : "--"); + jsongateway["cdz"] = station->cdzStatus == 1 ? "在线" : (station->cdzStatus == 0 ? "离线" : "--"); + } + json["gateway"] = jsongateway; return Errcode::OK; } @@ -1011,6 +1026,7 @@ Errcode HttpEntity::queryPolicyByType(const httplib::Request& req, njson& json, std::string sql = "SELECT policy_id, `type`, name from policy WHERE `type`='" + type + "';"; std::vector result; int ret = DaoEntity::execOnce(sql, result); + json["data"] = FieldsToJsonArray(result); return Errcode(ret); } @@ -1080,14 +1096,14 @@ 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 {}; + float incomeTotal {}; + float station_num = appdata.getStationCount(); + float solarDeviceNum {}; + float capacityTotal {}; + float electGenTotal {}; + float electGridTotal {}; + float electStorageIn {}; + float electStorageOut {}; for (auto& item : appdata.mapStation) { auto& station = item.second; @@ -1111,6 +1127,14 @@ Errcode HttpEntity::queryStatSystem(const httplib::Request& req, njson& json, st jsondata["storage_elect_in"] = electStorageIn; // : 储能充电总电量(kWh),精度0.001 jsondata["storage_elect_out"] = electStorageOut; // : 储能放电总电量(kWh),精度0.001 + std::string sql = "SELECT SUM(income_elect) income_total FROM stat_day;"; + std::vector result; + DAO::exec(NULL, sql, result); + if (result.size() > 0) + { + jsondata["income_total"] = result[0].get("income_total"); + } + json["data"] = jsondata; return Errcode::OK; } diff --git a/src/protocol/MqttEntity.cpp b/src/protocol/MqttEntity.cpp index dd8d078..ab55a5d 100644 --- a/src/protocol/MqttEntity.cpp +++ b/src/protocol/MqttEntity.cpp @@ -298,18 +298,16 @@ int MqttClient::onMessageArrived(char* topic, int topicLen, MQTTAsync_message* m if (command == "Gateway_YC") { - for (auto& item: json.items()) - { - std::string key = item.key(); - auto& val = item.value(); - if (key == "40001") - { - station->readGatewayMode(val.get()); - } - //else if (key == "40002") { spdlog::info("[mqtt] read register addr: [{}]={}, {}", key, val.dump(), "峰谷时间段"); } - //else if (key == "40021") { spdlog::info("[mqtt] read register addr: [{}]={}, {}", key, val.dump(), "自定时间段"); } - //else if (key == "40038") { spdlog::info("[mqtt] read register addr: [{}]={}, {}", key, val.dump(), "其他参数"); } - } + int mode = -1; + std::string param1; + std::string param2; + std::string param3 = json.dump(); + + JSON::read(json, "40001", mode); + if (json.contains("40002")) { param1 = json["40002"].dump(); } + if (json.contains("40021")) { param2 = json["40021"].dump(); } + if (json.contains("40038")) { param3 = json["40038"].dump(); } + station->readGatewayMode(mode, param1, param2, param3); } else if (command == "Gateway_YX") {