4
0

2 Коміти 2e15351ea0 ... 8f01e1fa3b

Автор SHA1 Опис Дата
  wei_lai 8f01e1fa3b 修改cp/cpWind/temperatureEnvironment/tsr/tsrCpPower/tsrWindSpeed输出json保存到库格式,添加temperatureLargeComponents输出json 4 місяців тому
  wei_lai a17ffd8acc 增加cp/cpWind/temperatureEnvironment/tsr/tsrCpPower/tsrWindSpeed输出json格式 4 місяців тому

+ 127 - 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,78 @@ 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: 'total',
+            Field_MillTypeCode: 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 +218,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 +267,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 +315,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

+ 112 - 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,53 @@ 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: 'total',
+            Field_MillTypeCode: turbineModelInfo[Field_MillTypeCode],
+            Field_Return_FilePath: output_json_path,
             Field_Return_IsSaveDatabase: True
         })
 
@@ -114,14 +162,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 +198,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 +245,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

+ 107 - 31
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,28 @@ 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_CodeOfTurbine: 'total',
+            Field_MillTypeCode: 'total',
+            Field_Return_FilePath: output_json_path,
+            Field_Return_IsSaveDatabase: True
         })
 
         result_rows.append({
@@ -171,10 +194,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 +215,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 +253,28 @@ 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_CodeOfTurbine: 'total',
+            Field_MillTypeCode: 'total',
+            Field_Return_FilePath: output_json_path,
+            Field_Return_IsSaveDatabase: True
         })
 
         result_rows.append({
@@ -215,10 +282,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

+ 203 - 17
dataAnalysisBusiness/algorithm/temperatureLargeComponentsAnalyst.py

@@ -132,7 +132,7 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
         outputDir = os.path.join(outputAnalysisDir, "GeneratorTemperature")
         dir.create_directory(outputDir)
         # 按设备名分组数据
-        grouped = dataFrameMerge.groupby(Field_NameOfTurbine)
+        grouped = dataFrameMerge.groupby(Field_CodeOfTurbine)
 
         result_rows = []
         # Create output directories if they don't exist
@@ -148,16 +148,30 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
             # 获取 Plotly Express 中的颜色序列
             colors = px.colors.sequential.Turbo
 
+            # 创建一个列表来存储各个风电机组的数据
+            turbine_data_list = []
+
             # Add traces for each turbine
             for idx, (name, group) in enumerate(grouped):
+                currTurbineInfo_group = self.common.getTurbineInfo(
+                    conf.dataContract.dataFilter.powerFarmID, name, self.turbineInfo)
                 fig.add_trace(go.Scatter(
                     x=group[Field_PowerFloor],
                     y=group[column],
                     mode='lines',
-                    name=name,
+                    name=currTurbineInfo_group[Field_NameOfTurbine],
                     # 从 'Rainbow' 色组中循环选择颜色
                     line=dict(color=colors[idx % len(colors)])
                 ))
+                # 提取数据
+                turbine_data_total = {
+                    "engineName": currTurbineInfo_group[Field_NameOfTurbine],
+                    "engineCode": name,
+                    "xData": group[Field_PowerFloor].tolist(),
+                    "yData": group[column].tolist(),
+                    "color": colors[idx % len(colors)]
+                }
+                turbine_data_list.append(turbine_data_total)
 
             # Update layout and axes
             fig.update_layout(
@@ -190,8 +204,33 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
             # Save the plot as a PNG/HTML file
             filePathOfImage = os.path.join(outputPath, f"{columnZH}-{turbineModelInfo[Field_MillTypeCode]}.png")
             fig.write_image(filePathOfImage, scale=3)
-            filePathOfHtml = os.path.join(outputPath, f"{columnZH}-{turbineModelInfo[Field_MillTypeCode]}.html")
-            fig.write_html(filePathOfHtml)
+            # filePathOfHtml = os.path.join(outputPath, f"{columnZH}-{turbineModelInfo[Field_MillTypeCode]}.html")
+            #fig.write_html(filePathOfHtml)
+
+            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'{columnZH}分布-{turbineModelInfo[Field_MachineTypeCode]}',
+                "xaixs": "功率(kW)",
+                "yaixs": y_name,
+                "data": turbine_data_list
+            }
+
+            # 将JSON对象保存到文件
+            output_json_path = os.path.join(outputPath,f"{columnZH}-{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)
 
             result_rows.append({
                 Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -202,12 +241,23 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
                 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: filePathOfHtml,
+            #    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: filePathOfHtml,
+                Field_CodeOfTurbine: 'total',
+                Field_MillTypeCode: turbineModelInfo[Field_MillTypeCode],
+                Field_Return_FilePath: output_json_path,
                 Field_Return_IsSaveDatabase: True
             })
 
@@ -215,19 +265,34 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
             # for name, group in grouped:
             for idx, (name, group) in enumerate(grouped):
                 single_fig = go.Figure()
+                currTurbineInfo_each = self.common.getTurbineInfo(
+                    conf.dataContract.dataFilter.powerFarmID, name, self.turbineInfo)
+
+                # 创建一个列表来存储各个风电机组的数据
+                turbine_data_list_each = []
 
                 # Add all other turbines in grey first
                 # for other_name, other_group in grouped:
                 for idx, (other_name, other_group) in enumerate(grouped):
                     if other_name != name:
+                        tempTurbineInfo = self.common.getTurbineInfo(
+                            conf.dataContract.dataFilter.powerFarmID, other_name, self.turbineInfo)
                         single_fig.add_trace(go.Scatter(
                             x=other_group[Field_PowerFloor],
                             y=other_group[column],
                             mode='lines',
-                            name=other_name,
+                            name=tempTurbineInfo[Field_NameOfTurbine],
                             line=dict(color='lightgrey', width=1),
                             showlegend=False
                         ))
+                        # 提取数据
+                        turbine_data_other_each = {
+                            "engineName": tempTurbineInfo[Field_NameOfTurbine],
+                            "engineCode": other_name,
+                            "xData": other_group[Field_PowerFloor].tolist(),
+                            "yData": other_group[column].tolist(),
+                        }
+                        turbine_data_list_each.append(turbine_data_other_each)
 
                 # Add the turbine of interest in dark blue
                 single_fig.add_trace(go.Scatter(
@@ -239,10 +304,18 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
                     showlegend=False  # Disable legend for cleaner look
                 ))
 
+                turbine_data_curr = {
+                    "engineName": currTurbineInfo_each[Field_NameOfTurbine],
+                    "engineCode": currTurbineInfo_each[Field_CodeOfTurbine],
+                    "xData": group[Field_PowerFloor].tolist(),
+                    "yData": group[column].tolist(),
+                }
+                turbine_data_list_each.append(turbine_data_curr)
+
                 # Update layout and axes for the individual plot
                 single_fig.update_layout(
                     # title={'text': f'Turbine: {name}', 'x': 0.5},
-                    title={'text': f'{columnZH}分布: {name}', 'x': 0.5},
+                    title={'text': f'{columnZH}分布: {currTurbineInfo_each[Field_NameOfTurbine]}', 'x': 0.5},
                     xaxis_title='功率',
                     yaxis_title=y_name,
                     xaxis=dict(
@@ -255,12 +328,37 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
                     )
                 )
 
+                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'{columnZH}分布: {currTurbineInfo_each[Field_NameOfTurbine]}',
+                    "xaixs": "功率(kW)",
+                    "yaixs": y_name,
+                    "data": turbine_data_list_each
+                }
+
+                # 将JSON对象保存到文件
+                output_json_path_each = os.path.join(outputPath, f"{currTurbineInfo_each[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)
+
                 filePathOfImage = os.path.join(
-                    outputPath, f"{name}.png")
+                    outputPath, f"{currTurbineInfo_each[Field_NameOfTurbine]}.png")
                 single_fig.write_image(filePathOfImage, scale=3)
-                filePathOfHtml = os.path.join(
-                    outputPath, f"{name}.html")
-                single_fig.write_html(filePathOfHtml)
+                # filePathOfHtml = os.path.join(
+                #     outputPath, f"{name}.html")
+                # single_fig.write_html(filePathOfHtml)
 
                 result_rows.append({
                     Field_Return_TypeAnalyst: self.typeAnalyst(),
@@ -271,15 +369,25 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
                     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: group[Field_CodeOfTurbine].iloc[0],
-                    Field_Return_FilePath: filePathOfHtml,
+                    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: group[Field_CodeOfTurbine].iloc[0],
+                #    Field_Return_FilePath: filePathOfHtml,
+                #    Field_Return_IsSaveDatabase: True
+                # })
+
         for idx, (name, group) in enumerate(grouped):
             # 绘制每台机组发电机的,驱动轴承温度、非驱动轴承温度、发电机轴承温度BIAS、发电机轴承温度和机舱温度BIAS 均与有功功率的折线图
             if not Field_GeneratorDE in group.columns or not Field_GeneratorNDE in group.columns or group[Field_GeneratorDE].isna().all()  or group[Field_GeneratorNDE].isna().all():
@@ -295,7 +403,10 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
 
         return result_df
 
-    def drawGeneratorTemperature(self, dataFrame: pd.DataFrame, conf: Contract, yAxisDE, yAxisNDE, diffTemperature, xAxis, turbineName, outputDir):
+    def drawGeneratorTemperature(self, dataFrame: pd.DataFrame, conf: Contract, yAxisDE, yAxisNDE, diffTemperature, xAxis, turbineCode, outputDir):
+        tempTurbineInfo1 = self.common.getTurbineInfo(
+            conf.dataContract.dataFilter.powerFarmID, turbineCode, self.turbineInfo)
+        turbineName = tempTurbineInfo1[Field_NameOfTurbine]
         # 发电机驱动轴承温度 和 发电机非驱动轴承 温差
         fieldBIAS_DE_NDE = 'BIAS_DE-NDE'
         fieldBIAS_DE = 'BIAS_DE'
@@ -311,25 +422,73 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
         # Create a plot with dual y-axes
         fig = make_subplots(specs=[[{"secondary_y": True}]])
 
+        plot_data_list_each = []
+
         # Plot DE Bearing Temperature
         fig.add_trace(go.Scatter(x=dataFrame[xAxis], y=dataFrame[yAxisDE], name='驱动端轴承温度', line=dict(
             color='blue')), secondary_y=False)
 
+        plot_data_curr = {
+            "Name": '驱动端轴承温度',
+            "xData": dataFrame[xAxis].tolist(),
+            "yData": dataFrame[yAxisDE].tolist(),
+            "color": 'blue',
+        }
+        plot_data_list_each.append(plot_data_curr)
+
         # Plot NDE Bearing Temperature
         fig.add_trace(go.Scatter(x=dataFrame[xAxis], y=dataFrame[yAxisNDE], name='非驱动端轴承温度', line=dict(
             color='green')), secondary_y=False)
 
+        plot_data_curr = {
+            "Name": '非驱动端轴承温度',
+            "xData": dataFrame[xAxis].tolist(),
+            "yData": dataFrame[yAxisNDE].tolist(),
+            "color": 'green',
+        }
+        plot_data_list_each.append(plot_data_curr)
+
         # Plot Temperature Differences
         fig.add_trace(go.Scatter(x=dataFrame[xAxis], y=dataFrame[fieldBIAS_DE], name='驱动端轴承温度与机舱温度偏差', line=dict(
             color='blue', dash='dot')), secondary_y=False)
+        plot_data_curr = {
+            "Name": '驱动端轴承温度与机舱温度偏差',
+            "xData": dataFrame[xAxis].tolist(),
+            "yData": dataFrame[fieldBIAS_DE].tolist(),
+            "color": 'blue',
+        }
+        plot_data_list_each.append(plot_data_curr)
+
         fig.add_trace(go.Scatter(x=dataFrame[xAxis], y=dataFrame[fieldBIAS_NDE], name='非驱动端轴承温度与机舱温度偏差', line=dict(
             color='green', dash='dot')), secondary_y=False)
+        plot_data_curr = {
+            "Name": '非驱动端轴承温度与机舱温度偏差',
+            "xData": dataFrame[xAxis].tolist(),
+            "yData": dataFrame[fieldBIAS_NDE].tolist(),
+            "color": 'green',
+        }
+        plot_data_list_each.append(plot_data_curr)
+
         fig.add_trace(go.Scatter(x=dataFrame[xAxis], y=dataFrame[fieldBIAS_DE_NDE],
                       name='驱动端轴承与非驱动端轴承温度偏差', line=dict(color='black', dash='dash')), secondary_y=False)
+        plot_data_curr = {
+            "Name": '驱动端轴承与非驱动端轴承温度偏差',
+            "xData": dataFrame[xAxis].tolist(),
+            "yData": dataFrame[fieldBIAS_DE_NDE].tolist(),
+            "color": 'black',
+        }
+        plot_data_list_each.append(plot_data_curr)
 
         # Plot Nacelle Temperature
         fig.add_trace(go.Scatter(x=dataFrame[xAxis], y=dataFrame[diffTemperature],
                       name='机舱温度', line=dict(color='orange')), secondary_y=False)
+        plot_data_curr = {
+            "Name": '机舱温度',
+            "xData": dataFrame[xAxis].tolist(),
+            "yData": dataFrame[diffTemperature].tolist(),
+            "color": 'orange',
+        }
+        plot_data_list_each.append(plot_data_curr)
 
         # Add horizontal reference lines
         fig.add_hline(y=5, line_dash="dot", line_color="#FFDB58")
@@ -350,11 +509,28 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
 
         fig.update_yaxes(range=[-20, 100], secondary_y=False)
 
+
+        # 构建最终的JSON对象
+        json_output = {
+            "analysisTypeCode": "发电机温度传感器分析",
+            "turbineName": tempTurbineInfo1[Field_NameOfTurbine],
+            "turbineCode": tempTurbineInfo1[Field_CodeOfTurbine],
+            "title": f'发电机温度偏差: {turbineName}',
+            "xaixs": "功率(kW)",
+            "yaixs": '轴承温度 & 偏差',
+            "data": plot_data_list_each
+        }
+
+        # 将JSON对象保存到文件
+        output_json_path_each = os.path.join(outputDir, f"{turbineName}.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)
         # Save the plot as a PNG/HTML file
         filePathOfImage = os.path.join(outputDir, f"{turbineName}.png")
         fig.write_image(filePathOfImage,  width=800, height=600, scale=3)
-        filePathOfHtml = os.path.join(outputDir, f"{turbineName}.html")
-        fig.write_html(filePathOfHtml)
+        # filePathOfHtml = os.path.join(outputDir, f"{turbineName}.html")
+        # fig.write_html(filePathOfHtml)
 
         result_rows1 = []
         result_rows1.append({
@@ -366,13 +542,23 @@ class TemperatureLargeComponentsAnalyst(AnalystWithGoodBadLimitPoint):
             Field_Return_IsSaveDatabase: False
         })
 
+        # 如果需要返回DataFrame,可以包含文件路径
         result_rows1.append({
             Field_Return_TypeAnalyst: self.typeAnalyst(),
             Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
             Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
             Field_CodeOfTurbine: dataFrame[Field_CodeOfTurbine].iloc[0],
-            Field_Return_FilePath: filePathOfHtml,
+            Field_Return_FilePath: output_json_path_each,
             Field_Return_IsSaveDatabase: True
         })
 
+        # result_rows1.append({
+        #    Field_Return_TypeAnalyst: self.typeAnalyst(),
+        #    Field_PowerFarmCode: conf.dataContract.dataFilter.powerFarmID,
+        #    Field_Return_BatchCode: conf.dataContract.dataFilter.dataBatchNum,
+        #    Field_CodeOfTurbine: dataFrame[Field_CodeOfTurbine].iloc[0],
+        #    Field_Return_FilePath: filePathOfHtml,
+        #    Field_Return_IsSaveDatabase: True
+        # })
+
         return result_rows1

+ 111 - 9
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,70 @@ 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_MillTypeCode: 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 +256,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 +293,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 +334,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 - 9
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,66 @@ 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_MillTypeCode: 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 +268,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 +311,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 +346,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 - 15
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,69 @@ 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_MillTypeCode: 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 +274,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 +311,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 +366,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