浏览代码

增加cp/cpWind/temperatureEnvironment/tsr/tsrCpPower/tsrWindSpeed输出json格式

wei_lai 4 月之前
父节点
当前提交
a17ffd8acc

+ 126 - 9
dataAnalysisBusiness/algorithm/cpAnalyst.py

@@ -71,6 +71,9 @@ class CpAnalyst(AnalystWithGoodPoint):
         # Create Subplots
         fig = make_subplots(specs=[[{"secondary_y": False}]])
 
+        # 创建一个列表来存储各个风电机组的数据
+        turbine_data_list = []
+
         # colors = px.colors.sequential.Turbo
         # Plotting the turbine lines
         for turbineCode in grouped[Field_CodeOfTurbine].unique():
@@ -85,6 +88,15 @@ class CpAnalyst(AnalystWithGoodPoint):
                            name=currTurbineInfo[Field_NameOfTurbine])
             )
 
+            # 提取数据
+            turbine_data_total = {
+                "engineName": currTurbineInfo[Field_NameOfTurbine],
+                "engineCode": turbineCode,
+                "xData": turbine_data[Field_PowerFloor].tolist(),
+                "yData": turbine_data[Field_CpMedian].tolist(),
+            }
+            turbine_data_list.append(turbine_data_total)
+
         # Plotting the contract guarantee Cp curve
         fig.add_trace(
             go.Scatter(x=dataFrameOfContractPowerCurve[Field_PowerFloor],
@@ -124,31 +136,77 @@ class CpAnalyst(AnalystWithGoodPoint):
             )
         )
 
+        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+        if isinstance(engineTypeCode, pd.Series):
+            engineTypeCode = engineTypeCode.iloc[0]
+
+        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+        if isinstance(engineTypeName, pd.Series):
+            engineTypeName = engineTypeName.iloc[0]
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "风电机组风能利用系数分析",
+            "typecode": turbineModelInfo[Field_MillTypeCode],
+            "engineCode": engineTypeCode,
+            "engineTypeName": engineTypeName,
+            "title": f'风能利用系数分布-{turbineModelInfo[Field_MachineTypeCode]}',
+            "xaixs": "功率(kW)",
+            "yaixs": "风能利用系数",
+            "contract_Cp_curve_xData": dataFrameOfContractPowerCurve[Field_PowerFloor].tolist(),
+            "contract_Cp_curve_yData": dataFrameOfContractPowerCurve[Field_Cp].tolist(),
+            "data": turbine_data_list
+
+        }
+
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution_total.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+
         # 保存html
-        htmlFileName = f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution.html"
-        htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-        fig.write_html(htmlFilePath)
+        # htmlFileName = f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution.html"
+        # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+        # fig.write_html(htmlFilePath)
 
         result_rows = []
+        # result_rows.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: Const_Output_Total,
+        #    Field_Return_FilePath: htmlFilePath,
+        #    Field_Return_IsSaveDatabase: True
+        # })
+
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-            Field_CodeOfTurbine: Const_Output_Total,
-            Field_Return_FilePath: htmlFilePath,
+            Field_CodeOfTurbine: turbineModelInfo[Field_MillTypeCode],
+            Field_Return_FilePath: output_json_path,
             Field_Return_IsSaveDatabase: True
         })
 
+
         # Individual turbine graphs
         for turbineCode, group in grouped.groupby(Field_CodeOfTurbine):
             fig = go.Figure()
 
             currTurbineInfo = self.common.getTurbineInfo(
                 conf.dataContract.dataFilter.powerFarmID, turbineCode, self.turbineInfo)
+
+            # 创建一个列表来存储各个风电机组的数据
+            turbine_data_list_each = []
+
             # Flag to add legend only once
             # add_legend = True
             # Plot other turbines data
             for other_name, other_group in grouped[grouped[Field_CodeOfTurbine] != turbineCode].groupby(Field_CodeOfTurbine):
+                tempTurbineInfo = self.common.getTurbineInfo(
+                    conf.dataContract.dataFilter.powerFarmID, other_name, self.turbineInfo)
                 fig.add_trace(
                     go.Scatter(
                         x=other_group[Field_PowerFloor],
@@ -159,12 +217,31 @@ class CpAnalyst(AnalystWithGoodPoint):
                         showlegend=False
                     )
                 )
+
+                # 提取数据
+                turbine_data_other_each = {
+                    "engineName": tempTurbineInfo[Field_NameOfTurbine],
+                    "engineCode": other_name,
+                    "xData": other_group[Field_PowerFloor].tolist(),
+                    "yData": other_group[Field_CpMedian].tolist(),
+                }
+                turbine_data_list_each.append(turbine_data_other_each)
+
                 add_legend = False  # Only add legend item for the first other turbine
             # Add trace for the current turbine
             fig.add_trace(
                 go.Scatter(x=group[Field_PowerFloor], y=group[Field_CpMedian],
                            mode='lines', name=currTurbineInfo[Field_NameOfTurbine], line=dict(color='darkblue'))
             )
+
+            turbine_data_curr = {
+                "engineName": currTurbineInfo[Field_NameOfTurbine],
+                "engineCode": currTurbineInfo[Field_CodeOfTurbine],
+                "xData": group[Field_PowerFloor].tolist(),
+                "yData": group[Field_CpMedian].tolist(),
+            }
+            turbine_data_list_each.append(turbine_data_curr)
+
             fig.add_trace(
                 go.Scatter(x=dataFrameOfContractPowerCurve[Field_PowerFloor],
                            y=dataFrameOfContractPowerCurve[Field_Cp],
@@ -189,15 +266,44 @@ class CpAnalyst(AnalystWithGoodPoint):
                 legend=dict(x=1.05, y=0.5)
             )
 
+            engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+            if isinstance(engineTypeCode, pd.Series):
+                engineTypeCode = engineTypeCode.iloc[0]
+
+            engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+            if isinstance(engineTypeName, pd.Series):
+                engineTypeName = engineTypeName.iloc[0]
+            # 构建最终的JSON对象
+            json_output = {
+                "analysisTypeCode": "风电机组风能利用系数分析",
+                "typecode": turbineModelInfo[Field_MillTypeCode],
+                "engineCode": engineTypeCode,
+                "engineTypeName": engineTypeName,
+                "title": f'机组: {currTurbineInfo[Field_NameOfTurbine]}',
+                "xaixs": "功率(kW)",
+                "yaixs": "风能利用系数",
+                "contract_Cp_curve_xData": dataFrameOfContractPowerCurve[Field_PowerFloor].tolist(),
+                "contract_Cp_curve_yData": dataFrameOfContractPowerCurve[Field_Cp].tolist(),
+                "data": turbine_data_list_each
+
+            }
+
+            # 将JSON对象保存到文件
+            output_json_path_each = os.path.join(outputAnalysisDir,
+                                            f"{currTurbineInfo[Field_NameOfTurbine]}.json")
+            with open(output_json_path_each, 'w', encoding='utf-8') as f:
+                import json
+                json.dump(json_output, f, ensure_ascii=False, indent=4)
+
             # 保存图像
             pngFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.png"
             pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
             fig.write_image(pngFilePath, scale=3)
 
             # 保存HTML
-            htmlFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.html"
-            htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-            fig.write_html(htmlFilePath)
+            # htmlFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.html"
+            # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+            # fig.write_html(htmlFilePath)
 
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -208,14 +314,25 @@ class CpAnalyst(AnalystWithGoodPoint):
                 Field_Return_IsSaveDatabase: False
             })
 
+            # 如果需要返回DataFrame,可以包含文件路径
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
                 Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
                 Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
                 Field_CodeOfTurbine: turbineCode,
-                Field_Return_FilePath: htmlFilePath,
+                Field_Return_FilePath: output_json_path_each,
                 Field_Return_IsSaveDatabase: True
             })
 
+
+            # result_rows.append({
+            #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+            #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+            #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+            #    Field_CodeOfTurbine: turbineCode,
+            #    Field_Return_FilePath: htmlFilePath,
+            #    Field_Return_IsSaveDatabase: True
+            # })
+
         result_df = pd.DataFrame(result_rows)
         return result_df

+ 111 - 10
dataAnalysisBusiness/algorithm/cpWindSpeedAnalyst.py

@@ -68,6 +68,9 @@ class CpWindSpeedAnalyst(AnalystWithGoodPoint):
         fig = go.Figure()
         # colors = px.colors.sequential.Turbo
 
+        # 创建一个列表来存储各个风电机组的数据
+        turbine_data_list = []
+
         for turbineCode in dataFrameOfTurbines[Field_CodeOfTurbine].unique():
             group = dataFrameOfTurbines[dataFrameOfTurbines[Field_CodeOfTurbine] == turbineCode]
             currTurbineInfo = self.common.getTurbineInfo(
@@ -76,6 +79,16 @@ class CpWindSpeedAnalyst(AnalystWithGoodPoint):
                                      mode='lines',
                                      # line=dict(color=colors[idx % len(colors)]),
                                      name=currTurbineInfo[Field_NameOfTurbine]))
+            # 提取数据
+            turbine_data_total = {
+                "engineName": currTurbineInfo[Field_NameOfTurbine],
+                "engineCode": turbineCode,
+                "xData": group[Field_WindSpeedFloor].tolist(),
+                "yData": group[Field_Cp].tolist(),
+                }
+            turbine_data_list.append(turbine_data_total)
+
+
 
         fig.update_layout(title={'text': f'风能利用系数分布-{turbineModelInfo[Field_MachineTypeCode]}', 'x': 0.5},
                           xaxis_title='风速', yaxis_title='风能利用系数',
@@ -95,18 +108,52 @@ class CpWindSpeedAnalyst(AnalystWithGoodPoint):
                    self.axisUpperLimitCp]
         )
         )
+
+        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+        if isinstance(engineTypeCode, pd.Series):
+            engineTypeCode = engineTypeCode.iloc[0]
+
+        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+        if isinstance(engineTypeName, pd.Series):
+            engineTypeName = engineTypeName.iloc[0]
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "风电机组风能利用系数分析",
+            "typecode": turbineModelInfo[Field_MillTypeCode],
+            "engineCode": engineTypeCode,
+            "engineTypeName": engineTypeName,
+            "title": f'风能利用系数分布-{turbineModelInfo[Field_MachineTypeCode]}',
+            "xaixs": "风速",
+            "yaixs": "风能利用系数",
+            "data": turbine_data_list
+        }
+        output_json_path = os.path.join(outputAnalysisDir, f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution_total.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
         # 保存HTML
-        htmlFileName = f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution.html"
-        htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-        fig.write_html(htmlFilePath)
+        # htmlFileName = f"{self.powerFarmInfo[Field_PowerFarmName].iloc[0]}-{turbineModelInfo[Field_MillTypeCode]}-Cp-Distribution.html"
+        # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+        # fig.write_html(htmlFilePath)
 
         result_rows = []
+        # result_rows.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: Const_Output_Total,
+        #    Field_Return_FilePath: htmlFilePath,
+        #    Field_Return_IsSaveDatabase: True
+        # })
+
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-            Field_CodeOfTurbine: Const_Output_Total,
-            Field_Return_FilePath: htmlFilePath,
+            Field_CodeOfTurbine: turbineModelInfo[Field_MillTypeCode],
+            Field_Return_FilePath: output_json_path,
             Field_Return_IsSaveDatabase: True
         })
 
@@ -114,14 +161,30 @@ class CpWindSpeedAnalyst(AnalystWithGoodPoint):
         for turbineCode, group in dataFrameOfTurbines.groupby(Field_CodeOfTurbine):
             currTurbineInfo = self.common.getTurbineInfo(
                 conf.dataContract.dataFilter.powerFarmID, turbineCode, self.turbineInfo)
+
+            # 创建一个列表来存储各个风电机组的数据
+            turbine_data_list_each = []
+
             fig = go.Figure()
             for turbineCode in dataFrameOfTurbines[Field_CodeOfTurbine].unique():
                 tempDataFrame = dataFrameOfTurbines[dataFrameOfTurbines[Field_CodeOfTurbine] == turbineCode]
+                tempTurbineInfo = self.common.getTurbineInfo(
+                    conf.dataContract.dataFilter.powerFarmID, turbineCode, self.turbineInfo)
                 fig.add_trace(go.Scatter(x=tempDataFrame[Field_WindSpeedFloor],
                                          y=tempDataFrame[Field_Cp],
                                          mode='lines',
                                          line=dict(color='lightgray', width=1),
                                          showlegend=False))
+
+                # 提取数据
+                turbine_data_other_each = {
+                    "engineName": tempTurbineInfo[Field_NameOfTurbine],
+                    "engineCode": turbineCode,
+                    "xData": tempDataFrame[Field_WindSpeedFloor].tolist(),
+                    "yData": tempDataFrame[Field_Cp].tolist(),
+                }
+                turbine_data_list_each.append(turbine_data_other_each)
+
             fig.add_trace(go.Scatter(x=group[Field_WindSpeedFloor], y=group[Field_Cp], mode='lines', line=dict(
                 color='darkblue'), showlegend=False))
             fig.update_layout(title=f'风机: {currTurbineInfo[Field_NameOfTurbine]}',
@@ -134,15 +197,43 @@ class CpWindSpeedAnalyst(AnalystWithGoodPoint):
                                          self.axisUpperLimitCp]
                               )
                               )
+
+            engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+            if isinstance(engineTypeCode, pd.Series):
+                engineTypeCode = engineTypeCode.iloc[0]
+
+            engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+            if isinstance(engineTypeName, pd.Series):
+                engineTypeName = engineTypeName.iloc[0]
+            # 构建最终的JSON对象
+            json_output = {
+                "analysisTypeCode": "风电机组风能利用系数分析",
+                "typecode": turbineModelInfo[Field_MillTypeCode],
+                "engineCode": engineTypeCode,
+                "engineTypeName": engineTypeName,
+                "title": f'风机: {currTurbineInfo[Field_NameOfTurbine]}',
+                "xaixs": "风速",
+                "yaixs": "风能利用系数",
+                "data": turbine_data_list_each
+
+            }
+
+            # 将JSON对象保存到文件
+            output_json_path_each = os.path.join(outputAnalysisDir,
+                                                 f"{currTurbineInfo[Field_NameOfTurbine]}.json")
+            with open(output_json_path_each, 'w', encoding='utf-8') as f:
+                import json
+                json.dump(json_output, f, ensure_ascii=False, indent=4)
+
             # 保存图像
             pngFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.png"
             pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
             fig.write_image(pngFilePath, scale=3)
 
             # 保存HTML
-            htmlFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.html"
-            htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-            fig.write_html(htmlFilePath)
+            # htmlFileName = f"{currTurbineInfo[Field_NameOfTurbine]}.html"
+            # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+            # fig.write_html(htmlFilePath)
 
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -153,15 +244,25 @@ class CpWindSpeedAnalyst(AnalystWithGoodPoint):
                 Field_Return_IsSaveDatabase: False
             })
 
+            # 如果需要返回DataFrame,可以包含文件路径
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
                 Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
                 Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-                Field_CodeOfTurbine: currTurbineInfo[Field_CodeOfTurbine],
-                Field_Return_FilePath: htmlFilePath,
+                Field_CodeOfTurbine: turbineCode,
+                Field_Return_FilePath: output_json_path_each,
                 Field_Return_IsSaveDatabase: True
             })
 
+            # result_rows.append({
+            #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+            #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+            #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+            #    Field_CodeOfTurbine: currTurbineInfo[Field_CodeOfTurbine],
+            #    Field_Return_FilePath: htmlFilePath,
+            #    Field_Return_IsSaveDatabase: True
+            # })
+
         result_df = pd.DataFrame(result_rows)
 
         return result_df

+ 103 - 29
dataAnalysisBusiness/algorithm/temperatureEnvironmentAnalyst.py

@@ -37,19 +37,8 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
         turbrineInfos = self.common.getTurbineInfos(
             conf.dataContract.dataFilter.powerFarmID, turbineCodes, self.turbineInfo)
 
-        groupedOfTurbineModel = turbrineInfos.groupby(Field_MillTypeCode)
-
-        returnDatas = []
-        for turbineModelCode, group in groupedOfTurbineModel:
-            currTurbineCodes = group[Field_CodeOfTurbine].unique().tolist()
-            currTurbineModeInfo = self.common.getTurbineModelByCode(
-                turbineModelCode, self.turbineModelInfo)
-            currDataFrameOfTurbines = dataFrameOfTurbines[dataFrameOfTurbines[Field_CodeOfTurbine].isin(
-                currTurbineCodes)]
-            returnData= self.draw(mergeData, outputAnalysisDir, conf,currTurbineModeInfo)
-            returnDatas.append(returnData)
-
-        returnResult = pd.concat(returnDatas, ignore_index=True) 
+        returnResult= self.draw(mergeData, outputAnalysisDir, conf,turbrineInfos)
+
         return returnResult
         # return self.draw(mergeData, outputAnalysisDir, conf)
 
@@ -132,7 +121,7 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
             row=1, col=1
         )
         fig1.update_layout(
-            title={'text': f'温度偏差-{turbineModelInfo[Field_MachineTypeCode]}', 'x': 0.5},
+            title={'text': f'温度偏差', 'x': 0.5},
             xaxis_title='机组名称',
             yaxis_title='温度偏差',
             shapes=[
@@ -144,6 +133,30 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
             xaxis=dict(tickangle=-45)  # 设置x轴刻度旋转角度为45度
         )
 
+        # 确保从 Series 中提取的是具体的值
+        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+        if isinstance(engineTypeCode, pd.Series):
+            engineTypeCode = engineTypeCode.iloc[0]
+
+        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+        if isinstance(engineTypeName, pd.Series):
+            engineTypeName = engineTypeName.iloc[0]
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "风电机组环境温度传感器分析",
+            "engineCode": engineTypeCode,
+            "engineTypeName": engineTypeName,
+            "xaixs": "机组名称",
+            "yaixs": "温度偏差",
+            "data": [{
+                "engineName": "",  # Field_NameOfTurbine
+                "engineCode": "",  # Field_CodeOfTurbine
+                "title": f'温度偏差',
+                "xData": res[Field_NameOfTurbine].tolist(),
+                "yData": res[self.fieldTemperatureDiff].tolist(),
+            }]
+        }
+
         result_rows = []
         # 保存图像
         pngFileName = '{}环境温差Bias.png'.format(
@@ -152,18 +165,27 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
         fig1.write_image(pngFilePath, scale=3)
 
         # 保存HTML
-        htmlFileName = '{}环境温差Bias.html'.format(
+        # htmlFileName = '{}环境温差Bias.html'.format(
+        #    self.powerFarmInfo[Field_PowerFarmName].iloc[0])
+        # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+        # fig1.write_html(htmlFilePath)
+
+        # 将JSON对象保存到文件
+        jsonFileName = '{}环境温差Bias.json'.format(
             self.powerFarmInfo[Field_PowerFarmName].iloc[0])
-        htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-        fig1.write_html(htmlFilePath)
+        output_json_path = os.path.join(outputAnalysisDir, jsonFileName)
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
 
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
             Field_CodeOfTurbine: Const_Output_Total,
-            Field_Return_FilePath: pngFilePath,
-            Field_Return_IsSaveDatabase: False
+            Field_Return_FilePath: output_json_path,
+            Field_Return_IsSaveDatabase: True
         })
 
         result_rows.append({
@@ -171,10 +193,19 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
             Field_CodeOfTurbine: Const_Output_Total,
-            Field_Return_FilePath: htmlFilePath,
-            Field_Return_IsSaveDatabase: True
+            Field_Return_FilePath: pngFilePath,
+            Field_Return_IsSaveDatabase: False
         })
 
+        # result_rows.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: Const_Output_Total,
+        #    Field_Return_FilePath: htmlFilePath,
+        #    Field_Return_IsSaveDatabase: True
+        # })
+
         # 环境温度中位数条形图
         fig2 = make_subplots(rows=1, cols=1)
         fig2.add_trace(
@@ -183,12 +214,37 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
             row=1, col=1
         )
         fig2.update_layout(
-            title={'text': f'平均温度-{turbineModelInfo[Field_MachineTypeCode]}', 'x': 0.5},
+            title={'text': f'平均温度', 'x': 0.5},
             xaxis_title='机组名称',
             yaxis_title=' 温度',
             xaxis=dict(tickangle=-45)  # 为x轴也设置旋转角度
         )
 
+        # 确保从 Series 中提取的是具体的值
+        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+        if isinstance(engineTypeCode, pd.Series):
+            engineTypeCode = engineTypeCode.iloc[0]
+
+        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+        if isinstance(engineTypeName, pd.Series):
+            engineTypeName = engineTypeName.iloc[0]
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "风电机组环境温度传感器分析",
+            "engineCode": engineTypeCode,
+            "engineTypeName": engineTypeName,
+            "xaixs": "机组名称",
+            "yaixs": "温度",
+            "data": [{
+                "engineName": "",  # Field_NameOfTurbine
+                "engineCode": "",  # Field_CodeOfTurbine
+                "title": f'平均温度',
+                "xData": res[Field_NameOfTurbine].tolist(),
+                "yData": res['当前机组温度'].tolist(),
+            }]
+        }
+
+
         # 保存图像
         pngFileName = '{}环境温度中位数.png'.format(
             self.powerFarmInfo[Field_PowerFarmName].iloc[0])
@@ -196,18 +252,27 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
         fig2.write_image(pngFilePath, scale=3)
 
         # 保存HTML
-        htmlFileName = '{}环境温度中位数.html'.format(
+        # htmlFileName = '{}环境温度中位数.html'.format(
+        #     self.powerFarmInfo[Field_PowerFarmName].iloc[0])
+        # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+        # fig2.write_html(htmlFilePath)
+
+        # 将JSON对象保存到文件
+        jsonFileName = '{}环境温度中位数.json'.format(
             self.powerFarmInfo[Field_PowerFarmName].iloc[0])
-        htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-        fig2.write_html(htmlFilePath)
+        output_json_path = os.path.join(outputAnalysisDir, jsonFileName)
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
 
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
             Field_CodeOfTurbine: Const_Output_Total,
-            Field_Return_FilePath: pngFilePath,
-            Field_Return_IsSaveDatabase: False
+            Field_Return_FilePath: output_json_path,
+            Field_Return_IsSaveDatabase: True
         })
 
         result_rows.append({
@@ -215,10 +280,19 @@ class TemperatureEnvironmentAnalyst(AnalystWithGoodBadLimitPoint):
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
             Field_CodeOfTurbine: Const_Output_Total,
-            Field_Return_FilePath: htmlFilePath,
-            Field_Return_IsSaveDatabase: True
+            Field_Return_FilePath: pngFilePath,
+            Field_Return_IsSaveDatabase: False
         })
 
+        # result_rows.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: Const_Output_Total,
+        #    Field_Return_FilePath: htmlFilePath,
+        #    Field_Return_IsSaveDatabase: True
+        # })
+
         result_df = pd.DataFrame(result_rows)
 
         return result_df

+ 111 - 10
dataAnalysisBusiness/algorithm/tsrAnalyst.py

@@ -131,6 +131,9 @@ class TSRAnalyst(AnalystWithGoodPoint):
 
         upLimitOfTSR = 20
 
+        # 创建一个列表来存储各个风电机组的数据
+        turbine_data_list = []
+
         # 绘制全场TSR分布图
         fig = go.Figure()
         # colors = px.colors.sequential.Turbo
@@ -141,6 +144,15 @@ class TSRAnalyst(AnalystWithGoodPoint):
                                      mode='lines',
                                      # line=dict(color=colors[idx % len(colors)]),
                                      name=turbine))
+            # 提取数据
+            turbine_data_total = {
+                "engineName": turbine,
+                "engineCode": turbine_data[Field_CodeOfTurbine].iloc[0],
+                "xData": turbine_data[x_name].tolist(),
+                "yData": turbine_data[y_name].tolist(),
+                }
+            turbine_data_list.append(turbine_data_total)
+
 
         fig.update_layout(
             title={
@@ -172,28 +184,69 @@ class TSRAnalyst(AnalystWithGoodPoint):
         # 设置x轴标签旋转
         fig.update_xaxes(tickangle=-45)
 
+        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+        if isinstance(engineTypeCode, pd.Series):
+            engineTypeCode = engineTypeCode.iloc[0]
+
+        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+        if isinstance(engineTypeName, pd.Series):
+            engineTypeName = engineTypeName.iloc[0]
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "风电机组叶尖速比分析",
+            "typecode": turbineModelInfo[Field_MillTypeCode],
+            "engineCode": engineTypeCode,
+            "engineTypeName": engineTypeName,
+            "title": f'叶尖速比分布-{turbineModelInfo[Field_MachineTypeCode]}',
+            "xaixs": "最小功率(kW)",
+            "yaixs": "叶尖速比",
+            "data": turbine_data_list
+
+        }
+
         # 保存图形
         # fig.write_image(csvFileDirOfCp + r"/{}-TSR-Distibute.png".format(confData.farm_name),format='png',width=800, height=500,scale=3)
         # fig.show()
 
         # 保存HTML
-        htmlFileName = f"{dataFrameMerge[Field_PowerFarmName].iloc[0]}-TSR-Distribution-{turbineModelInfo[Field_MillTypeCode]}.html"
-        htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-        fig.write_html(htmlFilePath)
+        # htmlFileName = f"{dataFrameMerge[Field_PowerFarmName].iloc[0]}-TSR-Distribution-{turbineModelInfo[Field_MillTypeCode]}.html"
+        #htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+        #fig.write_html(htmlFilePath)
 
         result_rows = []
+        # result_rows.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: 'total',
+        #    Field_Return_FilePath: htmlFilePath,
+        #        Field_Return_IsSaveDatabase: True
+        # })
+
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, f"{dataFrameMerge[Field_PowerFarmName].iloc[0]}-TSR-Distribution-{turbineModelInfo[Field_MillTypeCode]}.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-            Field_CodeOfTurbine: 'total',
-            Field_Return_FilePath: htmlFilePath,
-                Field_Return_IsSaveDatabase: True
+            Field_CodeOfTurbine: turbineModelInfo[Field_MillTypeCode],
+            Field_Return_FilePath: output_json_path,
+            Field_Return_IsSaveDatabase: True
         })
 
+
         # 绘制每个设备的TSR分布图
         for name, group in dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine]):
             fig = go.Figure()
+
+            # 创建一个列表来存储各个风电机组的数据
+            turbine_data_list_each = []
+
             # 循环绘制turbine的线条
             for turbine in dataFrameMerge[Field_NameOfTurbine].unique():
                 turbine_data = dataFrameMerge[dataFrameMerge[Field_NameOfTurbine] == turbine]
@@ -202,6 +255,15 @@ class TSRAnalyst(AnalystWithGoodPoint):
                                          mode='lines',
                                          line=dict(color='lightgrey'),
                                          showlegend=False))
+                # 提取数据
+                turbine_data_each = {
+                    "engineName": turbine,
+                    "engineCode": turbine_data[Field_CodeOfTurbine].iloc[0],
+                    "xData": turbine_data[x_name].tolist(),
+                    "yData": turbine_data[y_name].tolist(),
+                }
+                turbine_data_list_each.append(turbine_data_each)
+
             fig.add_trace(go.Scatter(x=group[x_name],
                                      y=group[y_name],
                                      mode='lines',
@@ -230,15 +292,37 @@ class TSRAnalyst(AnalystWithGoodPoint):
             )
             fig.update_xaxes(tickangle=-45)
 
+
+            engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+            if isinstance(engineTypeCode, pd.Series):
+                engineTypeCode = engineTypeCode.iloc[0]
+
+            engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+            if isinstance(engineTypeName, pd.Series):
+                engineTypeName = engineTypeName.iloc[0]
+            # 构建最终的JSON对象
+            json_output = {
+                "analysisTypeCode": "风电机组叶尖速比分析",
+                "typecode": turbineModelInfo[Field_MillTypeCode],
+                "engineCode": engineTypeCode,
+                "engineTypeName": engineTypeName,
+                "title": f'机组:{format(name[0])}',
+                "xaixs": "功率(kW)",
+                "yaixs": "叶尖速比",
+                "data": turbine_data_list_each
+
+            }
+
+
             # 保存图像
             pngFileName = f"{name[0]}.png"
             pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
             fig.write_image(pngFilePath, scale=3)
 
             # 保存HTML
-            htmlFileName = f"{name[0]}.html"
-            htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-            fig.write_html(htmlFilePath)
+            # htmlFileName = f"{name[0]}.html"
+            # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+            # fig.write_html(htmlFilePath)
 
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -249,15 +333,32 @@ class TSRAnalyst(AnalystWithGoodPoint):
                 Field_Return_IsSaveDatabase: False
             })
 
+            # 将JSON对象保存到文件
+            output_json_path_each = os.path.join(outputAnalysisDir, f"{name[0]}.json")
+            with open(output_json_path_each, 'w', encoding='utf-8') as f:
+                import json
+                json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+            # 如果需要返回DataFrame,可以包含文件路径
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
                 Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
                 Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
                 Field_CodeOfTurbine: name[1],
-                Field_Return_FilePath: htmlFilePath,
+                Field_Return_FilePath: output_json_path_each,
                 Field_Return_IsSaveDatabase: True
             })
 
+
+            # result_rows.append({
+            #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+            #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+            #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+            #    Field_CodeOfTurbine: name[1],
+            #    Field_Return_FilePath: htmlFilePath,
+            #    Field_Return_IsSaveDatabase: True
+            # })
+
         result_df = pd.DataFrame(result_rows)
         return result_df
 

+ 109 - 10
dataAnalysisBusiness/algorithm/tsrCpPowerAnalyst.py

@@ -145,6 +145,10 @@ class TSRCpPowerAnalyst(AnalystWithGoodPoint):
         # 绘制全场TSR分布图
         fig = go.Figure()
         # colors = px.colors.sequential.Turbo
+
+        # 创建一个列表来存储各个风电机组的数据
+        turbine_data_list = []
+
         # 遍历不同的turbine来添加线条
         for turbine in dataFrameMerge[Field_NameOfTurbine].unique():
             turbine_data = dataFrameMerge[dataFrameMerge[Field_NameOfTurbine] == turbine]
@@ -153,6 +157,14 @@ class TSRCpPowerAnalyst(AnalystWithGoodPoint):
                                      line=dict(width=1.2),
                                      # line=dict(color=colors[idx % len(colors)]),
                                      name=turbine))
+            # 提取数据
+            turbine_data_total = {
+                "engineName": turbine,
+                "engineCode": turbine_data[Field_CodeOfTurbine].iloc[0],
+                "xData": turbine_data[x_name].tolist(),
+                "yData": turbine_data[y_name].tolist(),
+                }
+            turbine_data_list.append(turbine_data_total)
 
         fig.update_layout(
             title={
@@ -188,25 +200,65 @@ class TSRCpPowerAnalyst(AnalystWithGoodPoint):
         # fig.write_image(outputAnalysisDir + r"/{}-TSR-Distibute.png".format(confData.farm_name),format='png',width=800, height=500,scale=3)
         # fig.show()
 
+        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+        if isinstance(engineTypeCode, pd.Series):
+            engineTypeCode = engineTypeCode.iloc[0]
+
+        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+        if isinstance(engineTypeName, pd.Series):
+            engineTypeName = engineTypeName.iloc[0]
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "叶尖速比-风能利用系数分析-功率分布",
+            "typecode": turbineModelInfo[Field_MillTypeCode],
+            "engineCode": engineTypeCode,
+            "engineTypeName": engineTypeName,
+            "title": f'叶尖速比-风能利用系数分析-功率分布图-{turbineModelInfo[Field_MachineTypeCode]}',
+            "xaixs": "功率(kW)",
+            "yaixs": "叶尖速比/风能利用系数分析^(1/3)",
+            "data": turbine_data_list
+
+        }
+
         # 保存HTML
         # htmlFileName = f"{dataFrameMerge[Field_PowerFarmName].iloc[0]}-TSR-Cp-Power-Distribution.html"
-        htmlFileName = f"{turbineModelInfo[Field_MillTypeCode]}-TSR-Cp-Power-Distribution.html"
-        htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-        fig.write_html(htmlFilePath)
+        # htmlFileName = f"{turbineModelInfo[Field_MillTypeCode]}-TSR-Cp-Power-Distribution.html"
+        #htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+        # fig.write_html(htmlFilePath)
 
         result_rows = []
+        # result_rows.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: 'total',
+        #    Field_Return_FilePath: htmlFilePath,
+        #        Field_Return_IsSaveDatabase: True
+        # })
+
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, f"{turbineModelInfo[Field_MillTypeCode]}-TSR-Cp-Power-Distribution_total.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-            Field_CodeOfTurbine: 'total',
-            Field_Return_FilePath: htmlFilePath,
-                Field_Return_IsSaveDatabase: True
+            Field_CodeOfTurbine: turbineModelInfo[Field_MillTypeCode],
+            Field_Return_FilePath: output_json_path,
+            Field_Return_IsSaveDatabase: True
         })
 
         # 绘制每个设备的TSR分布图
         for name, group in dataFrameMerge.groupby([Field_NameOfTurbine, Field_CodeOfTurbine]):
             fig = go.Figure()
+
+            # 创建一个列表来存储各个风电机组的数据
+            turbine_data_list_each = []
+
             # 循环绘制turbine的线条
             for turbine in dataFrameMerge[Field_NameOfTurbine].unique():
                 turbine_data = dataFrameMerge[dataFrameMerge[Field_NameOfTurbine] == turbine]
@@ -215,6 +267,16 @@ class TSRCpPowerAnalyst(AnalystWithGoodPoint):
                                          mode='lines',
                                          line=dict(color='lightgrey', width=1.2),
                                          showlegend=False))
+
+                # 提取数据
+                turbine_data_each = {
+                    "engineName": turbine,
+                    "engineCode": turbine_data[Field_CodeOfTurbine].iloc[0],
+                    "xData": turbine_data[x_name].tolist(),
+                    "yData": turbine_data[y_name].tolist(),
+                }
+                turbine_data_list_each.append(turbine_data_each)
+
             fig.add_trace(go.Scatter(x=group[x_name],
                                      y=group[y_name],
                                      mode='lines',
@@ -248,10 +310,31 @@ class TSRCpPowerAnalyst(AnalystWithGoodPoint):
             pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
             fig.write_image(pngFilePath, scale=3)
 
+
+            engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+            if isinstance(engineTypeCode, pd.Series):
+                engineTypeCode = engineTypeCode.iloc[0]
+
+            engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+            if isinstance(engineTypeName, pd.Series):
+                engineTypeName = engineTypeName.iloc[0]
+            # 构建最终的JSON对象
+            json_output = {
+                "analysisTypeCode": "叶尖速比-风能利用系数分析-功率分布",
+                "typecode": turbineModelInfo[Field_MillTypeCode],
+                "engineCode": engineTypeCode,
+                "engineTypeName": engineTypeName,
+                "title": f'机组:{format(name[0])}',
+                "xaixs": "功率(kW)",
+                "yaixs": "叶尖速比/风能利用系数分析^(1/3)",
+                "data": turbine_data_list_each
+
+            }
+
             # 保存HTML
-            htmlFileName = f"{name[0]}.html"
-            htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-            fig.write_html(htmlFilePath)
+            # htmlFileName = f"{name[0]}.html"
+            # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+            #fig.write_html(htmlFilePath)
 
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -262,14 +345,30 @@ class TSRCpPowerAnalyst(AnalystWithGoodPoint):
                 Field_Return_IsSaveDatabase: False
             })
 
+            # 将JSON对象保存到文件
+            output_json_path_each = os.path.join(outputAnalysisDir, f"叶尖速比风能利用系数功率分布{name[0]}.json")
+            with open(output_json_path_each, 'w', encoding='utf-8') as f:
+                import json
+                json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+            # 如果需要返回DataFrame,可以包含文件路径
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
                 Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
                 Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
                 Field_CodeOfTurbine: name[1],
-                Field_Return_FilePath: htmlFilePath,
+                Field_Return_FilePath: output_json_path_each,
                 Field_Return_IsSaveDatabase: True
             })
 
+            # result_rows.append({
+            #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+            #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+            #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+            #    Field_CodeOfTurbine: name[1],
+            #    Field_Return_FilePath: htmlFilePath,
+            #    Field_Return_IsSaveDatabase: True
+            # })
+
         result_df = pd.DataFrame(result_rows)
         return result_df

+ 119 - 16
dataAnalysisBusiness/algorithm/tsrWindSpeedAnalyst.py

@@ -136,6 +136,10 @@ class TSRWindSpeedAnalyst(AnalystWithGoodPoint):
         # 绘制全场TSR分布图
         fig = go.Figure()
         # colors = px.colors.sequential.Turbo
+
+        # 创建一个列表来存储各个风电机组的数据
+        turbine_data_list = []
+
         # 遍历不同的turbine来添加线条
         for turbine in dataFrame[Field_NameOfTurbine].unique():
             turbine_data = dataFrame[dataFrame[Field_NameOfTurbine] == turbine]
@@ -143,6 +147,16 @@ class TSRWindSpeedAnalyst(AnalystWithGoodPoint):
                                      mode='lines',
                                      # line=dict(color=colors[idx % len(colors)]),
                                      name=turbine))
+            # 提取数据
+            turbine_data_total = {
+                "engineName": turbine,
+                "engineCode": turbine_data[Field_CodeOfTurbine].iloc[0],
+                "xData": turbine_data[x_name].tolist(),
+                "yData": turbine_data[y_name].tolist(),
+                }
+            turbine_data_list.append(turbine_data_total)
+
+
         fig.update_layout(
             title={
                 "text": f'叶尖速比分布图-{turbineModelInfo[Field_MachineTypeCode]}',
@@ -189,24 +203,68 @@ class TSRWindSpeedAnalyst(AnalystWithGoodPoint):
         # fig.write_image(csvFileDirOfCp + r"/{}-TSR-Distibute.png".format(confData.farm_name),format='png',width=800, height=500,scale=3)
         # fig.show()
 
+
+        engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+        if isinstance(engineTypeCode, pd.Series):
+            engineTypeCode = engineTypeCode.iloc[0]
+
+        engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+        if isinstance(engineTypeName, pd.Series):
+            engineTypeName = engineTypeName.iloc[0]
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "风电机组叶尖速比和风速分析",
+            "typecode": turbineModelInfo[Field_MillTypeCode],
+            "engineCode": engineTypeCode,
+            "engineTypeName": engineTypeName,
+            "title": f'叶尖速比分布图-{turbineModelInfo[Field_MachineTypeCode]}',
+            "xaixs": "风速",
+            "yaixs": "叶尖风速比",
+            "data": turbine_data_list
+
+        }
+
+
         # 保存HTML
-        htmlFileName = f"{dataFrame[Field_PowerFarmName].iloc[0]}-TSR-Distribution-{turbineModelInfo[Field_MillTypeCode]}.html"
-        htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-        fig.write_html(htmlFilePath)
+        # htmlFileName = f"{dataFrame[Field_PowerFarmName].iloc[0]}-TSR-Distribution-{turbineModelInfo[Field_MillTypeCode]}.html"
+        # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+        # fig.write_html(htmlFilePath)
 
         result_rows = []
+        # result_rows.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: 'total',
+        #    Field_Return_FilePath: htmlFilePath,
+        #    Field_Return_IsSaveDatabase: True
+        # })
+
+        # 将JSON对象保存到文件
+        output_json_path = os.path.join(outputAnalysisDir, f"{dataFrame[Field_PowerFarmName].iloc[0]}-TSR-Distribution-{turbineModelInfo[Field_MillTypeCode]}.json")
+        with open(output_json_path, 'w', encoding='utf-8') as f:
+            import json
+            json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-            Field_CodeOfTurbine: 'total',
-            Field_Return_FilePath: htmlFilePath,
+            Field_CodeOfTurbine: turbineModelInfo[Field_MillTypeCode],
+            Field_Return_FilePath: output_json_path,
             Field_Return_IsSaveDatabase: True
         })
 
+
+
         # 绘制每个设备的TSR分布图
         for name, group in dataFrame.groupby([Field_NameOfTurbine, Field_CodeOfTurbine]):
             fig = go.Figure()
+
+            # 创建一个列表来存储各个风电机组的数据
+            turbine_data_list_each = []
+
             # 循环绘制turbine的线条
             for turbine in dataFrame[Field_NameOfTurbine].unique():
                 turbine_data = dataFrame[dataFrame[Field_NameOfTurbine] == turbine]
@@ -215,6 +273,15 @@ class TSRWindSpeedAnalyst(AnalystWithGoodPoint):
                                          mode='lines',
                                          line=dict(color='lightgrey'),
                                          showlegend=False))
+                # 提取数据
+                turbine_data_each = {
+                    "engineName": turbine,
+                    "engineCode": turbine_data[Field_CodeOfTurbine].iloc[0],
+                    "xData": turbine_data[x_name].tolist(),
+                    "yData": turbine_data[y_name].tolist(),
+                }
+                turbine_data_list_each.append(turbine_data_each)
+
             fig.add_trace(go.Scatter(x=group[x_name],
                                      y=group[y_name],
                                      mode='lines',
@@ -243,15 +310,51 @@ class TSRWindSpeedAnalyst(AnalystWithGoodPoint):
             )
             fig.update_xaxes(tickangle=-45)
 
+
+            engineTypeCode = turbineModelInfo.get(Field_MillTypeCode, "")
+            if isinstance(engineTypeCode, pd.Series):
+                engineTypeCode = engineTypeCode.iloc[0]
+
+            engineTypeName = turbineModelInfo.get(Field_MachineTypeCode, "")
+            if isinstance(engineTypeName, pd.Series):
+                engineTypeName = engineTypeName.iloc[0]
+            # 构建最终的JSON对象
+            json_output = {
+                "analysisTypeCode": "风电机组叶尖速比和风速分析",
+                "typecode": turbineModelInfo[Field_MillTypeCode],
+                "engineCode": engineTypeCode,
+                "engineTypeName": engineTypeName,
+                "title": f'机组:{format(name[0])}',
+                "xaixs": "功率(kW)",
+                "yaixs": "叶尖速比",
+                "data": turbine_data_list_each
+
+            }
+            # 将JSON对象保存到文件
+            output_json_path_each = os.path.join(outputAnalysisDir, f"{name[0]}.json")
+            with open(output_json_path_each, 'w', encoding='utf-8') as f:
+                import json
+                json.dump(json_output, f, ensure_ascii=False, indent=4)
+
+            # 如果需要返回DataFrame,可以包含文件路径
+            result_rows.append({
+                Field_Return_TypeAnalyst: self.typeAnalyst(),
+                Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+                Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+                Field_CodeOfTurbine: name[1],
+                Field_Return_FilePath: output_json_path_each,
+                Field_Return_IsSaveDatabase: True
+            })
+
             # 保存图像
             pngFileName = f"{name[0]}.png"
             pngFilePath = os.path.join(outputAnalysisDir, pngFileName)
             fig.write_image(pngFilePath, scale=3)
 
             # 保存HTML
-            htmlFileName = f"{name[0]}.html"
-            htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
-            fig.write_html(htmlFilePath)
+            # htmlFileName = f"{name[0]}.html"
+            # htmlFilePath = os.path.join(outputAnalysisDir, htmlFileName)
+            # fig.write_html(htmlFilePath)
 
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -262,14 +365,14 @@ class TSRWindSpeedAnalyst(AnalystWithGoodPoint):
                 Field_Return_IsSaveDatabase: False
             })
 
-            result_rows.append({
-                Field_Return_TypeAnalyst: self.typeAnalyst(),
-                Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
-                Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
-                Field_CodeOfTurbine: name[1],
-                Field_Return_FilePath: htmlFilePath,
-                Field_Return_IsSaveDatabase: True
-            })
+            # result_rows.append({
+            #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+            #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+            #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+            #    Field_CodeOfTurbine: name[1],
+            #    Field_Return_FilePath: htmlFilePath,
+            #    Field_Return_IsSaveDatabase: True
+            # })
 
         result_df = pd.DataFrame(result_rows)
         return result_df