cloudpss 3.2.0a2__py3-none-any.whl → 4.0.0a5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cloudpss/__init__.py +6 -4
- cloudpss/dslab/DSLabFinancialResult.py +96 -0
- cloudpss/dslab/__init__.py +2 -0
- cloudpss/dslab/dataManageModel.py +267 -0
- cloudpss/dslab/dslab.py +145 -0
- cloudpss/dslab/files/__init__.py +2 -0
- cloudpss/dslab/files/curveData.py +140205 -0
- cloudpss/dslab/files/files.py +19 -0
- cloudpss/dslab/financialAnalysisModel.py +137 -0
- cloudpss/function/functionExecution.py +0 -2
- cloudpss/ieslab/DataManageModel.py +415 -0
- cloudpss/ieslab/EvaluationModel.py +189 -0
- cloudpss/ieslab/IESLabPlan.py +132 -0
- cloudpss/ieslab/IESLabSimulation.py +54 -0
- cloudpss/ieslab/PlanModel.py +143 -0
- cloudpss/ieslab/__init__.py +4 -0
- cloudpss/model/jobDefinitions.py +34 -0
- cloudpss/model/model.py +202 -15
- cloudpss/model/revision.py +2 -2
- cloudpss/project/project.py +4 -3
- cloudpss/runner/DSLabResult.py +92 -0
- cloudpss/runner/IESLabEvaluationResult.py +143 -0
- cloudpss/runner/IESLabPlanResult.py +195 -0
- cloudpss/runner/IESLabTypicalDayResult.py +142 -0
- cloudpss/runner/MessageStreamReceiver.py +193 -0
- cloudpss/runner/receiver.py +3 -3
- cloudpss/runner/result.py +38 -4
- cloudpss/runner/runner.py +61 -18
- cloudpss/utils/IO.py +153 -0
- cloudpss/utils/httprequests.py +14 -11
- cloudpss/verify.py +27 -14
- cloudpss/version.py +1 -0
- {cloudpss-3.2.0a2.dist-info → cloudpss-4.0.0a5.dist-info}/METADATA +2 -4
- cloudpss-4.0.0a5.dist-info/RECORD +54 -0
- {cloudpss-3.2.0a2.dist-info → cloudpss-4.0.0a5.dist-info}/WHEEL +1 -1
- cloudpss-3.2.0a2.dist-info/RECORD +0 -33
- {cloudpss-3.2.0a2.dist-info → cloudpss-4.0.0a5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,195 @@
|
|
1
|
+
import json
|
2
|
+
from math import fabs
|
3
|
+
from ..utils.httprequests import request
|
4
|
+
|
5
|
+
|
6
|
+
class IESLabPlanResult(object):
|
7
|
+
taskId = None
|
8
|
+
|
9
|
+
def __init__(self, simulationId, taskId=None, **kwargs) -> None:
|
10
|
+
"""
|
11
|
+
初始化
|
12
|
+
获得taskId
|
13
|
+
"""
|
14
|
+
self.simulationId = simulationId
|
15
|
+
if taskId is not None:
|
16
|
+
self.taskId = taskId
|
17
|
+
else:
|
18
|
+
self.taskId = self.__getLastTask()
|
19
|
+
pass
|
20
|
+
|
21
|
+
def __getLastTask(self):
|
22
|
+
'''
|
23
|
+
获取最后一次运行的taskID
|
24
|
+
|
25
|
+
:return: string 类型
|
26
|
+
'''
|
27
|
+
try:
|
28
|
+
r=request('GET','api/ieslab-plan/taskmanager/getSimuLastTasks',params={
|
29
|
+
'simuid':self.simulationId
|
30
|
+
})
|
31
|
+
result= json.loads(r.text)
|
32
|
+
return result['data'].get('task_id',None)
|
33
|
+
except:
|
34
|
+
return None
|
35
|
+
|
36
|
+
def status(self):
|
37
|
+
'''
|
38
|
+
获取运行状态
|
39
|
+
|
40
|
+
:return: boolean 类型
|
41
|
+
'''
|
42
|
+
log = self.GetLogs()
|
43
|
+
for l in log:
|
44
|
+
if l['data'] == 'run ends':
|
45
|
+
return True
|
46
|
+
return False
|
47
|
+
|
48
|
+
def GetLogs(self):
|
49
|
+
'''
|
50
|
+
获取运行日志
|
51
|
+
|
52
|
+
:return: dict 类型,代表日志信息
|
53
|
+
'''
|
54
|
+
if self.taskId is None:
|
55
|
+
raise Exception('未开始运行')
|
56
|
+
r = request('GET',
|
57
|
+
'api/ieslab-plan/taskmanager/getOptimizationLog',
|
58
|
+
params={
|
59
|
+
'simuid': self.simulationId,
|
60
|
+
'taskid': self.taskId
|
61
|
+
})
|
62
|
+
result = json.loads(r.text)
|
63
|
+
return result['msg']
|
64
|
+
|
65
|
+
def GetPlanNum(self):
|
66
|
+
'''
|
67
|
+
获取当前result实例对应的优化方案数量
|
68
|
+
|
69
|
+
:return: int类型,代表优化方案的数量
|
70
|
+
'''
|
71
|
+
if self.taskId is None:
|
72
|
+
raise Exception('未开始运行')
|
73
|
+
r = request('GET',
|
74
|
+
'api/ieslab-plan/taskmanager/getOptimizationResult',
|
75
|
+
params={
|
76
|
+
'simuid': self.simulationId,
|
77
|
+
'taskid': self.taskId,
|
78
|
+
'resultType': 0
|
79
|
+
})
|
80
|
+
result = json.loads(r.text)
|
81
|
+
return len(result['data'])
|
82
|
+
|
83
|
+
def GetPlanInfo(self, planID):
|
84
|
+
'''
|
85
|
+
获取planID对应的优化方案的基础信息
|
86
|
+
|
87
|
+
:param: planID int类型,表示优化方案的ID,数值位于 0~优化方案数量 之间
|
88
|
+
|
89
|
+
:return: dict类型,代表该方案的基础信息,包括投资、运行成本、负荷总量等信息
|
90
|
+
'''
|
91
|
+
if self.taskId is None:
|
92
|
+
raise Exception('未开始运行')
|
93
|
+
r = request('GET',
|
94
|
+
'api/ieslab-plan/taskmanager/getOptimizationResult',
|
95
|
+
params={
|
96
|
+
'simuid': self.simulationId,
|
97
|
+
'taskid': self.taskId,
|
98
|
+
'resultType': 0
|
99
|
+
})
|
100
|
+
data = json.loads(r.text).get('data', [])
|
101
|
+
result = data[planID].get('data', {}).get('data', [])[0]
|
102
|
+
header = data[planID].get('data', {}).get('headerDesc', [])
|
103
|
+
dict_result = {val.get('hearderName', ''): result.get(val.get('key', ''), '') for val in header}
|
104
|
+
return dict_result
|
105
|
+
|
106
|
+
|
107
|
+
def GetPlanConfiguration(self, planID):
|
108
|
+
'''
|
109
|
+
获取planID对应的优化方案的配置信息
|
110
|
+
|
111
|
+
:param: planID int类型,表示优化方案的ID,数值位于 0~优化方案数量 之间
|
112
|
+
|
113
|
+
:return: dict类型,代表该方案的配置信息,包括每种设备的选型配置、容量配置、成本等相关信息
|
114
|
+
'''
|
115
|
+
len = self.GetPlanNum()
|
116
|
+
if int(planID) > len:
|
117
|
+
raise Exception('计算方案id未产生')
|
118
|
+
r = request('GET',
|
119
|
+
'api/ieslab-plan/taskmanager/getOptimizationResult',
|
120
|
+
params={
|
121
|
+
'simuid': self.simulationId,
|
122
|
+
'taskid': self.taskId,
|
123
|
+
"planId": planID,
|
124
|
+
'resultType': 1
|
125
|
+
})
|
126
|
+
d = json.loads(r.text)
|
127
|
+
result = {}
|
128
|
+
for val in d['data']:
|
129
|
+
result[val['u_name']] = val['data']['data']
|
130
|
+
return result
|
131
|
+
|
132
|
+
def GetComponentResult(self, planID, componentID, typicalDayName=''):
|
133
|
+
'''
|
134
|
+
获取planID对应的优化方案下componentID对应元件的运行信息
|
135
|
+
|
136
|
+
:param: planID int 类型,表示优化方案的ID,数值位于 0~优化方案数量 之间
|
137
|
+
:param: componentID str 类型,表示元件的标识符
|
138
|
+
:param typicalDayName str 类型,代表典型日的名称
|
139
|
+
|
140
|
+
:return: dict类型,代表该元件在不同典型日下的运行信息
|
141
|
+
'''
|
142
|
+
len = self.GetPlanNum()
|
143
|
+
if int(planID) > len:
|
144
|
+
raise Exception('计算方案id未产生')
|
145
|
+
r = request('GET',
|
146
|
+
'api/ieslab-plan/taskmanager/getOptimizationResult',
|
147
|
+
params={
|
148
|
+
'simuid': self.simulationId,
|
149
|
+
'taskid': self.taskId,
|
150
|
+
'resultType': 3,
|
151
|
+
'typicalDay': typicalDayName,
|
152
|
+
"planId": planID,
|
153
|
+
'u_name': componentID
|
154
|
+
})
|
155
|
+
d = json.loads(r.text)
|
156
|
+
dict_result = dict()
|
157
|
+
for val in d['data']:
|
158
|
+
for k, v in val.items():
|
159
|
+
dict_result[k] = v
|
160
|
+
return dict_result
|
161
|
+
|
162
|
+
def GetComponentTypiDays(self, planId, componentID):
|
163
|
+
'''
|
164
|
+
获取当前result实例对应的优化方案数量
|
165
|
+
|
166
|
+
:param: planID int 类型,表示优化方案的ID,数值位于 0~优化方案数量 之间
|
167
|
+
:param: componentID str 类型,表示元件的标识符
|
168
|
+
|
169
|
+
:return: int类型,代表优化方案的数量
|
170
|
+
'''
|
171
|
+
if self.taskId is None:
|
172
|
+
raise Exception('未开始运行')
|
173
|
+
r = request('GET',
|
174
|
+
'api/ieslab-plan/taskmanager/getOptimizationResult',
|
175
|
+
params={
|
176
|
+
'simuid': self.simulationId,
|
177
|
+
'taskid': self.taskId,
|
178
|
+
"planId": planId,
|
179
|
+
'u_name': componentID,
|
180
|
+
'resultType': 2
|
181
|
+
})
|
182
|
+
result = json.loads(r.text)
|
183
|
+
return result['data']
|
184
|
+
|
185
|
+
def getLastTaskResult(self):
|
186
|
+
'''
|
187
|
+
获取最后一次运行的taskID的运行结果
|
188
|
+
|
189
|
+
:return: dict 类型
|
190
|
+
'''
|
191
|
+
r=request('GET','api/ieslab-plan/taskmanager/getSimuLastTasks',params={
|
192
|
+
'simuid':self.simulationId
|
193
|
+
})
|
194
|
+
result= json.loads(r.text)
|
195
|
+
return result
|
@@ -0,0 +1,142 @@
|
|
1
|
+
from .result import Result
|
2
|
+
import re
|
3
|
+
import copy
|
4
|
+
class IESLabTypicalDayResult(Result):
|
5
|
+
def __init__(self, *args, **kwargs):
|
6
|
+
"""
|
7
|
+
初始化
|
8
|
+
"""
|
9
|
+
Result.__init__(self, *args, **kwargs)
|
10
|
+
self.__plotIndex = 0
|
11
|
+
self.__typicalIndex = 0
|
12
|
+
self.__type_list =['电负荷', '热负荷','冷负荷','总辐射','散射辐射', '直射辐射', '天顶角', '环境温度', '土壤温度', '10m风速', '50m风速', '建筑物高度风速', '风机高度风速']
|
13
|
+
self.result = {'TypicalMonth': [],'TypicalDay': []}
|
14
|
+
for i in range(12):
|
15
|
+
self.result['TypicalMonth'].append({'月份': int, '持续天数': [],'电负荷': [], '热负荷': [],'冷负荷':[],'总辐射': [],'直射辐射': [],'散射辐射': [],'天顶角': [],
|
16
|
+
'环境温度': [], '土壤温度': [], '建筑物高度风速': [], '风机高度风速': [],'10m风速': [], '50m风速': [] })
|
17
|
+
|
18
|
+
|
19
|
+
def __readPlotResult(self):
|
20
|
+
length = self.db.getMessageLength()
|
21
|
+
if (length > self.__plotIndex):
|
22
|
+
for num in range(self.__plotIndex, length):# update TypicalMonth
|
23
|
+
val = self.db.getMessage(num)
|
24
|
+
if val['type'] == 'plot':
|
25
|
+
key_list = re.split('-month',val['key'])#分别为类型和月份
|
26
|
+
# print(key_list)
|
27
|
+
self.result['TypicalMonth'][int(key_list[1])-1]['月份'] = int(key_list[1])
|
28
|
+
if key_list[0] in ['总辐射','散射辐射']:#从第一类数据中分析每个月各个典型日的天数
|
29
|
+
typicalNum = len(val['data']['traces'])
|
30
|
+
for i in range(typicalNum):
|
31
|
+
self.result['TypicalMonth'][int(key_list[1])-1]['持续天数'].append(int(re.findall('\d+',val['data']['traces'][i]['name'])[1]))
|
32
|
+
# 每个月各类型数据的各个典型日的数据,由于部分月份可能没有电冷热负荷,某月的某个典型日可能缺少冷热负荷
|
33
|
+
for i in range(typicalNum):
|
34
|
+
self.result['TypicalMonth'][int(key_list[1])-1][key_list[0]].append([])
|
35
|
+
for i in range(len(val['data']['traces'])):
|
36
|
+
self.result['TypicalMonth'][int(key_list[1])-1][key_list[0]][int(re.findall('\d+',val['data']['traces'][i]['name'])[0])-1] = copy.deepcopy(val['data']['traces'][i]['y'])
|
37
|
+
self.__plotIndex = length
|
38
|
+
# update TypicalDay based on TypicalMonth
|
39
|
+
for m in range(12):
|
40
|
+
for i in range(len(self.result['TypicalMonth'][m]['持续天数'])):
|
41
|
+
self.result['TypicalDay'].append({'info':{'typicalDayID': int, 'name': str, 'duration': int, 'maxElectricalLoad': 0.0, 'maxHeatLoad': 0.0, 'maxCoolLoad': 0.0},
|
42
|
+
'data': {'电负荷': [], '热负荷': [],'冷负荷':[],'总辐射': [],'直射辐射': [],'散射辐射': [],'天顶角': [],
|
43
|
+
'环境温度': [], '土壤温度': [], '建筑物高度风速': [], '风机高度风速': [],'10m风速': [], '50m风速': []}})
|
44
|
+
self.result['TypicalDay'][-1]['info']['typicalDayID'] = self.__typicalIndex
|
45
|
+
self.result['TypicalDay'][-1]['info']['name'] = str(m+1) + '月典型日' + str(i+1)
|
46
|
+
self.result['TypicalDay'][-1]['info']['duration'] = self.result['TypicalMonth'][m]['持续天数'][i]
|
47
|
+
if self.result['TypicalMonth'][m]['电负荷']:
|
48
|
+
if self.result['TypicalMonth'][m]['电负荷'][i]:
|
49
|
+
self.result['TypicalDay'][-1]['info']['maxElectricalLoad'] = max(self.result['TypicalMonth'][m]['电负荷'][i])
|
50
|
+
if self.result['TypicalMonth'][m]['热负荷']:
|
51
|
+
if self.result['TypicalMonth'][m]['热负荷'][i]:
|
52
|
+
self.result['TypicalDay'][-1]['info']['maxHeatLoad'] = max(self.result['TypicalMonth'][m]['热负荷'][i])
|
53
|
+
if self.result['TypicalMonth'][m]['冷负荷']:
|
54
|
+
if self.result['TypicalMonth'][m]['冷负荷'][i]:
|
55
|
+
self.result['TypicalDay'][-1]['info']['maxCoolLoad'] = max(self.result['TypicalMonth'][m]['冷负荷'][i])
|
56
|
+
for type_i in self.__type_list:
|
57
|
+
if self.result['TypicalMonth'][m][type_i]:
|
58
|
+
self.result['TypicalDay'][-1]['data'][type_i] = self.result['TypicalMonth'][m][type_i][i]
|
59
|
+
self.__typicalIndex += 1
|
60
|
+
|
61
|
+
def GetTypical(self):
|
62
|
+
'''
|
63
|
+
获取所有的 GetTypical 典型日数据
|
64
|
+
|
65
|
+
>>> result.GetTypical()
|
66
|
+
{...}
|
67
|
+
'''
|
68
|
+
self.__readPlotResult()
|
69
|
+
return self.result['TypicalDay']
|
70
|
+
|
71
|
+
|
72
|
+
def GetTypicalDayNum(self):
|
73
|
+
'''
|
74
|
+
获取当前result的典型日数量
|
75
|
+
|
76
|
+
:return: int类型,代表典型日数量
|
77
|
+
'''
|
78
|
+
self.__readPlotResult()
|
79
|
+
return self.__typicalIndex
|
80
|
+
|
81
|
+
def GetTypicalDayInfo(self,dayID):
|
82
|
+
'''
|
83
|
+
获取dayID对应典型日的基础信息
|
84
|
+
|
85
|
+
:params: dayID int类型,表示典型日的ID,数值位于 0~典型日数量 之间
|
86
|
+
|
87
|
+
:return: dict类型,代表典型日的基础信息,包括典型日所代表的日期范围、典型日的名称等
|
88
|
+
'''
|
89
|
+
self.__readPlotResult()
|
90
|
+
return self.result['TypicalDay'][dayID].get('info','没有该数据')
|
91
|
+
|
92
|
+
|
93
|
+
def GetTypicalDayCurve(self,dayID, dataType):
|
94
|
+
'''
|
95
|
+
获取dayID对应典型日下dataType参数的时序曲线
|
96
|
+
|
97
|
+
:params: dayID int类型,表示典型日的ID,数值位于 0~典型日数量 之间
|
98
|
+
:params: dataType enum类型,标识总辐射、环境温度、土壤温度、建筑物高度风速、风机高度风速、电负荷、热负荷、冷负荷的参数类型
|
99
|
+
|
100
|
+
:return: list<float>类型,代表以1h为时间间隔的该参数的日内时序曲线
|
101
|
+
'''
|
102
|
+
self.__readPlotResult()
|
103
|
+
return self.result['TypicalDay'][dayID]['data'].get(dataType,'没有该类型数据')
|
104
|
+
|
105
|
+
|
106
|
+
def GetTypicalMonth(self):
|
107
|
+
'''
|
108
|
+
获取所有的 GetTypicalMonth 数据
|
109
|
+
|
110
|
+
>>> result.GetTypicalMonth()
|
111
|
+
|
112
|
+
:return: list<dict>类型,代表各月各类型的典型日数据
|
113
|
+
'''
|
114
|
+
self.__readPlotResult()
|
115
|
+
return self.result['TypicalMonth']
|
116
|
+
|
117
|
+
def GetTypicalMonthNum(self,monthID):
|
118
|
+
'''
|
119
|
+
获取第monthID月各类型的典型日数据
|
120
|
+
|
121
|
+
>>> result.GetTypicalMonthNum()
|
122
|
+
|
123
|
+
:params: monthID int类型,表示典型月的ID,数值位于 1-12 之间
|
124
|
+
|
125
|
+
:return: dict类型,代表第monthID月各类型的典型日数据
|
126
|
+
{...}
|
127
|
+
'''
|
128
|
+
self.__readPlotResult()
|
129
|
+
return self.result['TypicalMonth'][monthID-1]
|
130
|
+
|
131
|
+
|
132
|
+
def GetTypicalMonthCurve(self,monthID, dataType):
|
133
|
+
'''
|
134
|
+
获取dayID对应典型日下dataType参数的时序曲线
|
135
|
+
|
136
|
+
:params: monthID int类型,表示典型月的ID,数值位于 1-12 之间
|
137
|
+
:params: dataType enum类型,标识总辐射、环境温度、土壤温度、建筑物高度风速、风机高度风速、电负荷、热负荷、冷负荷的参数类型
|
138
|
+
|
139
|
+
:return: list<list>类型,代表以1h为时间间隔的该参数的典型日内时序曲线
|
140
|
+
'''
|
141
|
+
self.__readPlotResult()
|
142
|
+
return self.result['TypicalMonth'][monthID-1].get(dataType,'没有该类型数据')
|
@@ -0,0 +1,193 @@
|
|
1
|
+
import os
|
2
|
+
from urllib.parse import urlparse
|
3
|
+
import requests
|
4
|
+
import websocket
|
5
|
+
import datetime
|
6
|
+
import pytz
|
7
|
+
utc_tz = pytz.timezone('UTC')
|
8
|
+
|
9
|
+
from ..utils.IO import IO
|
10
|
+
|
11
|
+
|
12
|
+
class Message(object):
|
13
|
+
|
14
|
+
def __init__(self, id, token):
|
15
|
+
self.id = id
|
16
|
+
self.token = token
|
17
|
+
|
18
|
+
|
19
|
+
class MessageStreamReceiver(object):
|
20
|
+
"""消息流读取函数结果"""
|
21
|
+
|
22
|
+
def __init__(self, id, db):
|
23
|
+
self.origin = os.environ.get('CLOUDPSS_API_URL',
|
24
|
+
'https://cloudpss.net/')
|
25
|
+
self.id = id
|
26
|
+
self.db = db
|
27
|
+
self._status = 0
|
28
|
+
self.error = None
|
29
|
+
self.isOpen = False
|
30
|
+
|
31
|
+
def create(self, type, comment=None, durability=1):
|
32
|
+
"""
|
33
|
+
创建消息流
|
34
|
+
type: 消息流类型 'object' or 'binary'
|
35
|
+
comment: 消息流描述
|
36
|
+
durability: 消息流的数据将在多少天后被删除,其取值范围从 0 ~ MAX_DURABILITY
|
37
|
+
MAX_DURABILITY 默认为20
|
38
|
+
"""
|
39
|
+
param = {}
|
40
|
+
if type != 'object' and type != 'binary':
|
41
|
+
raise Exception('type must be object or binary')
|
42
|
+
param['type'] = type
|
43
|
+
param['comment'] = comment
|
44
|
+
param['durability'] = durability
|
45
|
+
r = requests.post(self.origin + 'api/streams', json=param)
|
46
|
+
r.raise_for_status()
|
47
|
+
res = r.json()
|
48
|
+
print(res)
|
49
|
+
message = Message(res['id'], res['token'])
|
50
|
+
return message
|
51
|
+
|
52
|
+
def createBulk(self, param):
|
53
|
+
"""
|
54
|
+
批量创建消息流
|
55
|
+
param: [{ "type": "{{type}}", "comment": "{{comment}}" , "durability": {{durability}}, "volume": {{volume}} }, ... ]
|
56
|
+
type: 消息流类型 'object' or 'binary'
|
57
|
+
comment: 消息流描述
|
58
|
+
durability: 消息流的数据将在多少天后被删除,其取值范围从 0 ~ MAX_DURABILITY
|
59
|
+
MAX_DURABILITY 默认为20
|
60
|
+
|
61
|
+
状态码说明:
|
62
|
+
201 返回流信息数组
|
63
|
+
400 不支持的 type,或其他输入错误
|
64
|
+
"""
|
65
|
+
r = requests.post(self.origin + 'api/streams/bulk', json=param)
|
66
|
+
r.raise_for_status()
|
67
|
+
res = r.json()
|
68
|
+
messages = []
|
69
|
+
for item in res:
|
70
|
+
message = Message(item['id'], item['token'])
|
71
|
+
messages.append(message)
|
72
|
+
return messages
|
73
|
+
|
74
|
+
def info(self, id):
|
75
|
+
"""
|
76
|
+
获取消息流信息
|
77
|
+
"""
|
78
|
+
if id is None:
|
79
|
+
raise Exception('id is None')
|
80
|
+
r = requests.get(self.origin + 'api/streams/id/' + id + '/info')
|
81
|
+
r.raise_for_status()
|
82
|
+
return r.json()
|
83
|
+
|
84
|
+
def infoByToken(self, token):
|
85
|
+
"""
|
86
|
+
获取消息流信息
|
87
|
+
相较于id获取消息流信息,token能够额外获取到handler的信息
|
88
|
+
"""
|
89
|
+
if token is None:
|
90
|
+
raise Exception('token is None')
|
91
|
+
r = requests.get(self.origin + 'api/streams/token/' + token + '/info')
|
92
|
+
r.raise_for_status()
|
93
|
+
return r.json()
|
94
|
+
|
95
|
+
def freeze(self, token):
|
96
|
+
"""
|
97
|
+
冻结消息流
|
98
|
+
|
99
|
+
状态码说明:
|
100
|
+
201 冻结成功
|
101
|
+
204 流已经被冻结
|
102
|
+
409 流正在活动中
|
103
|
+
404 未找到对应流
|
104
|
+
"""
|
105
|
+
if token is None:
|
106
|
+
raise Exception('token is None')
|
107
|
+
r = requests.put(self.origin + 'api/streams/token/' + token +
|
108
|
+
'/freeze')
|
109
|
+
r.raise_for_status()
|
110
|
+
return r.status_code
|
111
|
+
|
112
|
+
def delete(self, token):
|
113
|
+
"""
|
114
|
+
删除消息流
|
115
|
+
|
116
|
+
状态码说明:
|
117
|
+
204 删除成功
|
118
|
+
409 流正在活动中
|
119
|
+
404 未找到对应流
|
120
|
+
"""
|
121
|
+
if token is None:
|
122
|
+
raise Exception('token is None')
|
123
|
+
r = requests.delete(self.origin + 'api/streams/token/' + token)
|
124
|
+
r.raise_for_status()
|
125
|
+
return r.status_code
|
126
|
+
|
127
|
+
def receive(self, id, fr0m, on_open, on_message, on_error, on_close):
|
128
|
+
"""
|
129
|
+
读取消息流中的数据
|
130
|
+
id: 消息流id
|
131
|
+
fr0m: 从哪个位置开始读取,如果为0则从头开始读取
|
132
|
+
on_open: 连接建立时的回调函数
|
133
|
+
on_message: 收到消息时的回调函数
|
134
|
+
on_error: 发生错误时的回调函数
|
135
|
+
on_close: 连接关闭时的回调函数
|
136
|
+
"""
|
137
|
+
if id is None:
|
138
|
+
raise Exception('id is None')
|
139
|
+
u = list(urlparse(self.origin))
|
140
|
+
head = 'wss' if u[0] == 'https' else 'ws'
|
141
|
+
|
142
|
+
path = head + '://' + str(u[1]) + '/api/streams/id/' + id
|
143
|
+
if fr0m is not None:
|
144
|
+
path = path + '&from=' + str(fr0m)
|
145
|
+
ws = websocket.WebSocketApp(path,
|
146
|
+
on_open=on_open,
|
147
|
+
on_message=on_message,
|
148
|
+
on_error=on_error,
|
149
|
+
on_close=on_close)
|
150
|
+
ws.run_forever()
|
151
|
+
return ws
|
152
|
+
|
153
|
+
###下面是兼容Receiver部分功能实现
|
154
|
+
def on_message(self, ws, message):
|
155
|
+
data = IO.deserialize(message, 'ubjson')
|
156
|
+
msg = IO.deserialize(data['data'], 'ubjson')
|
157
|
+
if "when" not in msg:
|
158
|
+
msg['when']= datetime.datetime.now()
|
159
|
+
self.db.storeMessage(msg)
|
160
|
+
|
161
|
+
def on_error(self, ws, error):
|
162
|
+
msg = {
|
163
|
+
'type': 'log',
|
164
|
+
'verb': 'create',
|
165
|
+
'version': 1,
|
166
|
+
'data': {
|
167
|
+
'level': 'error',
|
168
|
+
'content': "websocket error",
|
169
|
+
},
|
170
|
+
}
|
171
|
+
self.db.storeMessage(msg)
|
172
|
+
self.error = error
|
173
|
+
self._status = -1
|
174
|
+
|
175
|
+
|
176
|
+
def on_close(self, ws,*args,**kwargs):
|
177
|
+
self.db.finished = datetime.datetime.now(tz=utc_tz).isoformat()
|
178
|
+
self._status = 1
|
179
|
+
|
180
|
+
def on_open(self, ws):
|
181
|
+
self.isOpen = True
|
182
|
+
|
183
|
+
def close(self, ws):
|
184
|
+
ws.close()
|
185
|
+
|
186
|
+
def status(self):
|
187
|
+
return self._status
|
188
|
+
|
189
|
+
def connect(self):
|
190
|
+
self._status = 0
|
191
|
+
self.ws = self.receive(self.id, None, self.on_open, self.on_message, self.on_error, self.on_close)
|
192
|
+
|
193
|
+
|
cloudpss/runner/receiver.py
CHANGED
@@ -16,7 +16,7 @@ class Receiver(object):
|
|
16
16
|
'''
|
17
17
|
socket 接收服务
|
18
18
|
'''
|
19
|
-
def __init__(self, taskId, db, url
|
19
|
+
def __init__(self, taskId, db, url = None, **kwargs):
|
20
20
|
'''
|
21
21
|
连接远程服务器接收结果数据
|
22
22
|
|
@@ -113,7 +113,7 @@ class Receiver(object):
|
|
113
113
|
self.db.storeMessage(msg)
|
114
114
|
self.error = error
|
115
115
|
|
116
|
-
def on_close(self,
|
116
|
+
def on_close(self, *args,**kwargs):
|
117
117
|
msg = {
|
118
118
|
'type': 'log',
|
119
119
|
'verb': 'create',
|
@@ -130,7 +130,7 @@ class Receiver(object):
|
|
130
130
|
|
131
131
|
def connect(self):
|
132
132
|
self._status = 0
|
133
|
-
url = requests.compat.urljoin(self.url, self.taskId)
|
133
|
+
url = requests.compat.urljoin(self.url, self.taskId) # type: ignore
|
134
134
|
self.ws = websocket.WebSocketApp(url + '?subscribe-broadcast',
|
135
135
|
on_open=self.on_open,
|
136
136
|
on_message=self.on_message,
|
cloudpss/runner/result.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
import copy
|
2
2
|
import re
|
3
3
|
import collections
|
4
|
-
from .storage import Storage
|
5
4
|
|
5
|
+
from cloudpss.utils.httprequests import request
|
6
|
+
from .storage import Storage
|
6
7
|
|
7
8
|
class Result(object):
|
8
9
|
"""
|
@@ -333,8 +334,12 @@ class IESResult(Result):
|
|
333
334
|
'''
|
334
335
|
获取元件ID为compID的元件,对应标签为labelName、图例名称为traceName的plot 数据的第index项
|
335
336
|
|
336
|
-
|
337
|
-
|
337
|
+
:params: compID string类型,代表元件的标识符
|
338
|
+
:params: labelName string类型,代表plot曲线的分组标签
|
339
|
+
:params: traceName string类型,代表Plot曲线对应分组下的图例名称,当为'all'时,返回所有图例的数据
|
340
|
+
:params: index int类型,代表对应图例时序数据中的第index项,当小于0时,返回该图例所有的时序数据
|
341
|
+
|
342
|
+
:return: dict类型
|
338
343
|
'''
|
339
344
|
self.__readPlotResult()
|
340
345
|
key = compID + '_' + labelName
|
@@ -389,4 +394,33 @@ class IESResult(Result):
|
|
389
394
|
>>> result.getSankeyNum()
|
390
395
|
'''
|
391
396
|
self.__readPlotResult()
|
392
|
-
return len(self.result['Sankey'])
|
397
|
+
return len(self.result['Sankey'])
|
398
|
+
|
399
|
+
class IESLabSimulationResult(IESResult):
|
400
|
+
pass
|
401
|
+
|
402
|
+
class IESLabTypicalDayResult(IESResult):
|
403
|
+
def GetTypicalDayNum():
|
404
|
+
'''
|
405
|
+
获取当前result的典型日数量
|
406
|
+
|
407
|
+
:return: int类型,代表典型日数量
|
408
|
+
'''
|
409
|
+
def GetTypicalDayInfo(dayID):
|
410
|
+
'''
|
411
|
+
获取dayID对应典型日的基础信息
|
412
|
+
|
413
|
+
:params: dayID int类型,表示典型日的ID,数值位于 0~典型日数量 之间
|
414
|
+
|
415
|
+
:return: dict类型,代表典型日的基础信息,包括典型日所代表的日期范围、典型日的名称等
|
416
|
+
'''
|
417
|
+
def GetTypicalDayCurve(dayID, dataType):
|
418
|
+
'''
|
419
|
+
获取dayID对应典型日下dataType参数的时序曲线
|
420
|
+
|
421
|
+
:params: dayID int类型,表示典型日的ID,数值位于 0~典型日数量 之间
|
422
|
+
:params: dataType enum类型,标识辐照强度、环境温度、土壤温度、建筑物高度风速、风机高度风速、电负荷、热负荷、冷负荷的参数类型
|
423
|
+
|
424
|
+
:return: list<float>类型,代表以1h为时间间隔的该参数的日内时序曲线
|
425
|
+
'''
|
426
|
+
pass
|