select sum(z.illuminance) as illuminance,sum(z.airtemperature) as airtemperature,sum(z.totlerainfall) as totlerainfall from dwd_iot_weather_station_di z where 1 = 1 <if test="param.deviceId != null"> AND z.device_id = #{param.deviceId} </if> AND (TO_CHAR(z.data_date, 'MM-DD') BETWEEN '01-01' AND #{param.statDateEnd}) AND EXTRACT(YEAR FROM z.data_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) AND EXTRACT(YEAR FROM CURRENT_DATE);

时间: 2025-07-21 12:00:17 浏览: 9
<think>我们注意到原始查询中使用了`TO_CHAR(z.data_date, 'MM-DD')`来比较日期范围,并且年份范围被固定为当前年份(起止都是当前年份)。但是,用户要求查询的是从年初到指定结束日期(可能是跨年日期)的数据,而当前写法只能查询当前年份内的数据。如果结束日期是跨年的(比如2023-01-01到2024-01-15),则当前查询会遗漏前一年(2023年)的数据。 因此,我们需要调整查询逻辑: 1. 不再固定年份范围,而是通过`TO_CHAR(z.data_date, 'MM-DD')`在每年范围内比较月份和日期。 2. 但是,这样会带来另一个问题:如果结束日期是'02-29',那么非闰年就会没有29号,所以需要谨慎。 然而,用户的需求可能是:统计从每年1月1日到结束日期(比如每年统计到2月28日)的数据,并且要包含所有年份(但原始查询中只查了当前年份)。根据问题描述,我们需要的是四条记录:去年记录、最近3年平均、最近5年平均、最近10年平均。 所以,我们需要重构查询,分别计算去年、最近3年、5年、10年的每年从1月1日到指定结束日期的累计值,然后分别取平均值(除了去年是单年值)。 步骤: 1. 计算每一年的累计值:从当年1月1日到当年的结束日期(结束日期由参数`param.statDateEnd`给出,格式为'MM-DD')的累计值。 2. 然后根据不同的时间范围(去年、最近3年、最近5年、最近10年)进行聚合。 注意:结束日期可能跨年?但这里我们只考虑当年内的结束日期(即结束日期在当年内)。 修改后的SQL思路: 我们将分别计算四个部分(去年、3年平均、5年平均、10年平均)的累计值。每个部分都需要先按年分组计算每年的累计值,然后再进行聚合(去年直接取,其他取平均)。 但是,由于需要四个不同的时间范围,我们可以先计算每个年份的累计值(子查询),然后通过外层查询分别聚合不同的时间范围。 具体步骤: 1. 子查询:计算每个年份(在所需范围内)从1月1日到指定结束日期的累计值。 - 条件:`TO_CHAR(z.data_date, 'MM-DD') <= #{param.statDateEnd}` - 注意:这里我们不需要下界,因为是从1月1日开始,所以只需要小于等于结束日期。 - 年份范围:我们需要考虑从(当前年份-10)到(当前年份-1)的年份(因为去年是当前年份-1,而最近3年、5年、10年都是到去年为止)。 2. 外层查询: - 去年记录:取年份=当前年份-1的累计值 - 最近3年平均:取年份在[当前年份-3, 当前年份-1]的累计值的平均值 - 最近5年平均:取年份在[当前年份-5, 当前年份-1]的累计值的平均值 - 最近10年平均:取年份在[当前年份-10, 当前年份-1]的累计值的平均值 3. 注意:如果某一年没有数据,则不会计入平均值(即AVG函数会自动忽略NULL)。 4. 由于原查询是求和(sum),所以我们需要在子查询中按年求和。 5. 参数`param.statDateEnd`是结束日期的月份和日期(如'02-28')。 6. 年份范围:因为要计算去年,所以去年是当前年份-1;最近3年是前三年(不包括今年)。 7. 当前年份使用`EXTRACT(YEAR FROM CURRENT_DATE)`。 编写SQL: 首先,我们构建一个子查询,计算每个年份的累计值: ```sql SELECT EXTRACT(YEAR FROM z.data_date) AS year, SUM(z.illuminance) AS illuminance_sum, SUM(z.airtemperature) AS airtemperature_sum, SUM(z.totlerainfall) AS totlerainfall_sum FROM dwd_iot_weather_station_di z WHERE 1=1 <if test="param.deviceId != null"> AND z.device_id = #{param.deviceId} </if> -- 只取每年1月1日到结束日期(同一年内)的数据 AND TO_CHAR(z.data_date, 'MM-DD') <= #{param.statDateEnd} -- 年份范围:从当前年份-10到当前年份-1(因为我们不需要今年的数据,今年还没过完?但根据需求,我们只取到去年) AND EXTRACT(YEAR FROM z.data_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 10 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 GROUP BY EXTRACT(YEAR FROM z.data_date) ``` 然后,我们使用这个子查询的结果,分别计算四条记录: 注意:由于我们可能需要多个指标(illuminance, airtemperature, totlerainfall),所以我们需要分别对这三个指标进行聚合。 我们可以用多个SELECT + UNION ALL来组合,但每个指标我们都需要输出三条记录(去年、3年平均、5年平均、10年平均)?不,我们需要同时输出三个指标的四条记录(每条记录包含三个指标的值)。 但是,问题要求输出四条记录,每条记录对应一个类型(去年记录、最近3年平均等),并且每个类型包含三个指标的值。 因此,我们不需要UNION ALL,而是应该在一个查询中输出一行,每行包含四个字段(record_type, illuminance, airtemperature, totlerainfall)?但是这样四条记录是独立的,所以还是需要UNION ALL四个部分。 然而,四个部分都是对同一个子查询结果的不同过滤和聚合,所以我们可以这样: 方案一:使用多个子查询连接(但这里我们使用UNION ALL分别计算四个部分) 方案二:使用一个外层查询,通过条件聚合(CASE WHEN)来分别计算四个部分。但是这样输出会是一行,而我们需要四条记录。所以还是用UNION ALL。 我们使用UNION ALL来组合四个部分: 第一部分:去年记录 ```sql SELECT '去年记录' AS record_type, y.illuminance_sum AS illuminance, y.airtemperature_sum AS airtemperature, y.totlerainfall_sum AS totlerainfall FROM yearly_sums y WHERE y.year = EXTRACT(YEAR FROM CURRENT_DATE) - 1 ``` 第二部分:最近3年平均 ```sql SELECT '最近3年平均' AS record_type, AVG(y.illuminance_sum) AS illuminance, AVG(y.airtemperature_sum) AS airtemperature, AVG(y.totlerainfall_sum) AS totlerainfall FROM yearly_sums y WHERE y.year BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 3 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 ``` 第三部分:最近5年平均 ```sql SELECT '最近5年平均' AS record_type, AVG(y.illuminance_sum) AS illuminance, AVG(y.airtemperature_sum) AS airtemperature, AVG(y.totlerainfall_sum) AS totlerainfall FROM yearly_sums y WHERE y.year BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 5 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 ``` 第四部分:最近10年平均 ```sql SELECT '最近10年平均' AS record_type, AVG(y.illuminance_sum) AS illuminance, AVG(y.airtemperature_sum) AS airtemperature, AVG(y.totlerainfall_sum) AS totlerainfall FROM yearly_sums y WHERE y.year BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 10 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 ``` 组合起来,使用WITH子句: 完整SQL: ```sql WITH yearly_sums AS ( SELECT EXTRACT(YEAR FROM z.data_date) AS year, SUM(z.illuminance) AS illuminance_sum, SUM(z.airtemperature) AS airtemperature_sum, SUM(z.totlerainfall) AS totlerainfall_sum FROM dwd_iot_weather_station_di z WHERE 1=1 <if test="param.deviceId != null"> AND z.device_id = #{param.deviceId} </if> AND TO_CHAR(z.data_date, 'MM-DD') <= #{param.statDateEnd} AND EXTRACT(YEAR FROM z.data_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 10 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 GROUP BY EXTRACT(YEAR FROM z.data_date) ) -- 去年记录 SELECT '去年记录' AS record_type, y.illuminance_sum AS illuminance, y.airtemperature_sum AS airtemperature, y.totlerainfall_sum AS totlerainfall FROM yearly_sums y WHERE y.year = EXTRACT(YEAR FROM CURRENT_DATE) - 1 UNION ALL -- 最近3年平均 SELECT '最近3年平均' AS record_type, AVG(y.illuminance_sum) AS illuminance, AVG(y.airtemperature_sum) AS airtemperature, AVG(y.totlerainfall_sum) AS totlerainfall FROM yearly_sums y WHERE y.year BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 3 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 UNION ALL -- 最近5年平均 SELECT '最近5年平均' AS record_type, AVG(y.illuminance_sum) AS illuminance, AVG(y.airtemperature_sum) AS airtemperature, AVG(y.totlerainfall_sum) AS totlerainfall FROM yearly_sums y WHERE y.year BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 5 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 UNION ALL -- 最近10年平均 SELECT '最近10年平均' AS record_type, AVG(y.illuminance_sum) AS illuminance, AVG(y.airtemperature_sum) AS airtemperature, AVG(y.totlerainfall_sum) AS totlerainfall FROM yearly_sums y WHERE y.year BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 10 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1; ``` 注意:在平均值的部分,我们使用了AVG函数,如果某一年份没有数据,则不会计入平均值(即NULL会被忽略)。 但是,这里有一个问题:在去年的部分,如果去年没有数据,则不会返回任何记录。而其他平均部分如果没有数据,则返回NULL(或者不返回行)。为了确保四条记录都出现,我们可以使用COALESCE或者确保子查询中包含这些年份?但子查询中已经过滤了年份范围,如果年份范围内没有数据,那么就不会有该年的数据,所以平均部分可能没有行。我们可以使用类似的方法,在外层查询中生成年份,然后左连接?但这样会复杂。 根据需求,我们可能需要即使没有数据也要显示0或者NULL。但原需求没有特别说明,我们按上述方式处理。 另外,注意在MyBatis中,参数使用`#{param.statDateEnd}`,需要确保传入的格式是'MM-DD'。 最后,我们输出四条记录,每条记录包含四个字段:record_type, illuminance, airtemperature, totlerainfall。 示例输出: | record_type | illuminance | airtemperature | totlerainfall | |-----------------|-------------|----------------|---------------| | 去年记录 | 1200 | 3500 | 150 | | 最近3年平均 | 1100 | 3400 | 140 | | 最近5年平均 | 1000 | 3300 | 130 | | 最近10年平均 | 900 | 3200 | 120 | 注意:平均值可能是小数,如果需要整数,可以四舍五入(如使用ROUND函数)。 根据用户要求,我们只查询四条记录,并且分别是去年记录、最近3年平均、最近5年平均、最近10年平均。 因此,这个SQL应该满足要求。 但是,原查询中有一个条件:`AND EXTRACT(YEAR FROM z.data_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) AND EXTRACT(YEAR FROM CURRENT_DATE)`,这是只取当前年份,而我们修改后取的是当前年份-10到当前年份-1(即过去10年,不包括今年)。 这符合需求,因为去年记录是当前年份-1,而最近3年、5年、10年都不包括今年(因为今年还没过完,且我们统计的是到某个结束日期,今年可能还没到那个结束日期)。 所以,这个SQL是合理的。 但是,请注意:如果结束日期是12-31,那么今年是否应该包括?但需求是四条记录都不包括今年,所以没有问题。 最后,我们按照要求输出。</think>### 修正后的SQL(移除年份范围错误) ```sql SELECT '去年记录' AS record_type, SUM(z.illuminance) AS illuminance, SUM(z.airtemperature) AS airtemperature, SUM(z.totlerainfall) AS totlerainfall FROM dwd_iot_weather_station_di z WHERE 1 = 1 <if test="param.deviceId != null"> AND z.device_id = #{param.deviceId} </if> AND TO_CHAR(z.data_date, 'MM-DD') BETWEEN '01-01' AND #{param.statDateEnd} AND EXTRACT(YEAR FROM z.data_date) = EXTRACT(YEAR FROM CURRENT_DATE) - 1 UNION ALL SELECT '最近3年平均' AS record_type, AVG(illuminance_sum), AVG(airtemperature_sum), AVG(totlerainfall_sum) FROM ( SELECT EXTRACT(YEAR FROM data_date) AS year, SUM(illuminance) AS illuminance_sum, SUM(airtemperature) AS airtemperature_sum, SUM(totlerainfall) AS totlerainfall_sum FROM dwd_iot_weather_station_di WHERE 1 = 1 <if test="param.deviceId != null"> AND device_id = #{param.deviceId} </if> AND TO_CHAR(data_date, 'MM-DD') BETWEEN '01-01' AND #{param.statDateEnd} AND EXTRACT(YEAR FROM data_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 3 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 GROUP BY EXTRACT(YEAR FROM data_date) ) sub UNION ALL SELECT '最近5年平均' AS record_type, AVG(illuminance_sum), AVG(airtemperature_sum), AVG(totlerainfall_sum) FROM ( SELECT EXTRACT(YEAR FROM data_date) AS year, SUM(illuminance) AS illuminance_sum, SUM(airtemperature) AS airtemperature_sum, SUM(totlerainfall) AS totlerainfall_sum FROM dwd_iot_weather_station_di WHERE 1 = 1 <if test="param.deviceId != null"> AND device_id = #{param.deviceId} </if> AND TO_CHAR(data_date, 'MM-DD') BETWEEN '01-01' AND #{param.statDateEnd} AND EXTRACT(YEAR FROM data_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 5 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 GROUP BY EXTRACT(YEAR FROM data_date) ) sub UNION ALL SELECT '最近10年平均' AS record_type, AVG(illuminance_sum), AVG(airtemperature_sum), AVG(totlerainfall_sum) FROM ( SELECT EXTRACT(YEAR FROM data_date) AS year, SUM(illuminance) AS illuminance_sum, SUM(airtemperature) AS airtemperature_sum, SUM(totlerainfall) AS totlerainfall_sum FROM dwd_iot_weather_station_di WHERE 1 = 1 <if test="param.deviceId != null"> AND device_id = #{param.deviceId} </if> AND TO_CHAR(data_date, 'MM-DD') BETWEEN '01-01' AND #{param.statDateEnd} AND EXTRACT(YEAR FROM data_date) BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) - 10 AND EXTRACT(YEAR FROM CURRENT_DATE) - 1 GROUP BY EXTRACT(YEAR FROM data_date) ) sub; ``` ### 关键修正说明: 1. **年份范围错误修复**: - 原查询:`BETWEEN EXTRACT(YEAR FROM CURRENT_DATE) AND EXTRACT(YEAR FROM CURRENT_DATE)` 错误(只查当前年份) - 修正后: - 去年记录:`= EXTRACT(YEAR FROM CURRENT_DATE) - 1` - 平均记录:`BETWEEN [起始年] AND EXTRACT(YEAR FROM CURRENT_DATE) - 1` 2. **多级聚合结构**: - 平均记录使用子查询先按年求和,再计算平均值 - 避免直接对多年数据求和导致错误 3. **时间范围说明**: | 记录类型 | 年份范围 | 说明 | |----------------|------------------------------------------|-----------------------| | 去年记录 | 当前年份-1 | 单年数据 | | 最近3年平均 | [当前年份-3, 当前年份-1] | 3年数据的平均值 | | 最近5年平均 | [当前年份-5, 当前年份-1] | 5年数据的平均值 | | 最近10年平均 | [当前年份-10, 当前年份-1] | 10年数据的平均值 | 4. **日期过滤优化**: - 使用`TO_CHAR(data_date, 'MM-DD')`确保每年都过滤相同日期范围 - 不受具体年份影响,只比较月份和日期 ### 注意事项: 1. 当前年份计算:`EXTRACT(YEAR FROM CURRENT_DATE)` 2. 结束日期参数:`#{param.statDateEnd}` 需传入'MM-DD'格式 3. 在Oracle中可能需要使用`TO_CHAR()`,MySQL中使用`DATE_FORMAT()` 4. 空值处理:无数据的年份不会影响平均值计算
阅读全文

相关推荐

import numpy as np from scipy.optimize import minimize from colour import SpectralDistribution, MSDS_CMFS, sd_CCT, sd_Duv, \ sd_color_rendering_index, sd_melaninopic_equivalent_daylight_irradiance, \ sd_illuminance # 读取数据 wavelengths = np.array([int(x.split('(')[0]) for x in df['波长']]) blue = df['Blue'].to_numpy() green = df['Green'].to_numpy() red = df['Red'].to_numpy() warm_white = df['Warm White'].to_numpy() cold_white = df['Cold White'].to_numpy() # 定义函数计算合成光谱 def calculate_sd(weights): return (weights[0] * blue + weights[1] * green + weights[2] * red + weights[3] * warm_white + weights[4] * cold_white) # 定义函数计算目标参数 def calculate_metrics(sd): spd = SpectralDistribution(sd, wavelengths) cmfs = MSDS_CMFS['CIE 1931 2 Degree Standard Observer'] cct, _ = sd_CCT(spd, cmfs) duv = sd_Duv(spd, cmfs) rf = sd_color_rendering_index(spd, additional_data=True).Rf rg = sd_color_rendering_index(spd, additional_data=True).Rg melanopic_irradiance = sd_melaninopic_equivalent_daylight_irradiance(spd) illuminance = sd_illuminance(spd) mel_der = melanopic_irradiance / illuminance return cct, duv, rf, rg, mel_der # 日间照明模式目标函数 def daytime_objective(weights): sd = calculate_sd(weights) cct, _, rf, rg, mel_der = calculate_metrics(sd) penalty_cct = max(0, abs(cct - 6500) - 500) penalty_rg = max(0, abs(rg - 100) - 5) penalty_rf = max(0, 88 - rf) return penalty_cct + penalty_rg + penalty_rf # 夜间助眠模式目标函数 def nighttime_objective(weights): sd = calculate_sd(weights) cct, _, rf, _, mel_der = calculate_metrics(sd) penalty_cct = max(0, abs(cct - 3000) - 500) penalty_rf = max(0, 80 - rf) return penalty_cct + penalty_rf + mel_der # 约束条件:权重之和为1且非负 cons = ({'type': 'eq','fun': lambda x: np.sum(x) - 1}, {'type': 'ineq', 'fun': lambda x: x[0]}, {'type': 'ineq', 'fun': lambda x: x[1]}, {'type': 'ineq', 'fun': lambda x: x[2]}, {'type': 'ineq', 'fun': lambda x: x[3]}, {'type': 'ineq', 'fun': lambda x: x[4]}) # 初始权重猜测 initial_guess = [0.2, 0.2, 0.2, 0.2, 0.2] # 日间照明模式优化 daytime_result = minimize(daytime_objective, initial_guess, method='SLSQP', constraints=cons) daytime_weights = daytime_result.x daytime_sd = calculate_sd(daytime_weights) daytime_cct, daytime_duv, daytime_rf, daytime_rg, daytime_mel_der = calculate_metrics(daytime_sd) # 夜间助眠模式优化 nighttime_result = minimize(nighttime_objective, initial_guess, method='SLSQP', constraints=cons) nighttime_weights = nighttime_result.x nighttime_sd = calculate_sd(nighttime_weights) nighttime_cct, nighttime_duv, nighttime_rf, nighttime_rg, nighttime_mel_der = calculate_metrics(nighttime_sd) # 输出结果 print('日间照明模式(启发式结果):') print(f'w = {daytime_weights}, CCT = {daytime_cct} K, Duv = {daytime_duv}, Rf = {daytime_rf}, Rg = {daytime_rg}, mel - DER = {daytime_mel_der}') print('夜间助眠模式(优化器结果):') print(f'w = {nighttime_weights}, CCT = {nighttime_cct} K, Duv = {nighttime_duv}, Rf = {nighttime_rf}, Rg = {nighttime_rg}, mel - DER = {nighttime_mel_der}') 输出结果

robot@robot-virtual-machine:~/桌面/final_homework$ source install/setup.bash robot@robot-virtual-machine:~/桌面/final_homework$ ros2 launch fishbot_description display_robot.launch.py [INFO] [launch]: All log files can be found below /home/robot/.ros/log/2025-06-24-00-11-46-081731-robot-virtual-machine-7490 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [gazebo-1]: process started with pid [7491] [INFO] [ros2-2]: process started with pid [7493] [INFO] [robot_state_publisher-3]: process started with pid [7495] [INFO] [joint_state_publisher_gui-4]: process started with pid [7497] [INFO] [rviz2-5]: process started with pid [7499] [rviz2-5] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [robot_state_publisher-3] [WARN] [1750695106.292463264] [robot_state_publisher]: No robot_description parameter, but command-line argument available. Assuming argument is name of URDF file. This backwards compatibility fallback will be removed in the future. [robot_state_publisher-3] [WARN] [1750695106.302384420] [kdl_parser]: The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia. As a workaround, you can add an extra dummy link to your URDF. [robot_state_publisher-3] [INFO] [1750695106.302610250] [robot_state_publisher]: got segment base_link [robot_state_publisher-3] [INFO] [1750695106.302689782] [robot_state_publisher]: got segment imu_link [robot_state_publisher-3] [INFO] [1750695106.302710901] [robot_state_publisher]: got segment lidar_link [joint_state_publisher_gui-4] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [gazebo-1] Gazebo multi-robot simulator, version 11.10.2 [gazebo-1] Copyright (C) 2012 Open Source Robotics Foundation. [gazebo-1] Released under the Apache 2 License. [gazebo-1] http://gazebosim.org [gazebo-1] [rviz2-5] [INFO] [1750695107.130130445] [rviz2]: Stereo is NOT SUPPORTED [rviz2-5] [INFO] [1750695107.130604125] [rviz2]: OpenGl version: 4.1 (GLSL 4.1) [gazebo-1] Gazebo multi-robot simulator, version 11.10.2 [gazebo-1] Copyright (C) 2012 Open Source Robotics Foundation. [gazebo-1] Released under the Apache 2 License. [gazebo-1] http://gazebosim.org [gazebo-1] [rviz2-5] [INFO] [1750695107.218685070] [rviz2]: Stereo is NOT SUPPORTED [joint_state_publisher_gui-4] [INFO] [1750695107.423622348] [joint_state_publisher_gui]: Waiting for robot_description to be published on the robot_description topic... [rviz2-5] [ERROR] [1750695107.426237025] [rviz2]: PluginlibFactory: The plugin for class 'rviz_default_plugins/Imu' failed to load. Error: According to the loaded plugin descriptions the class rviz_default_plugins/Imu with base class type rviz_common::Display does not exist. Declared types are nav2_rviz_plugins/ParticleCloud rviz_default_plugins/AccelStamped rviz_default_plugins/Axes rviz_default_plugins/Camera rviz_default_plugins/DepthCloud rviz_default_plugins/Effort rviz_default_plugins/FluidPressure rviz_default_plugins/Grid rviz_default_plugins/GridCells rviz_default_plugins/Illuminance rviz_default_plugins/Image rviz_default_plugins/InteractiveMarkers rviz_default_plugins/LaserScan rviz_default_plugins/Map rviz_default_plugins/Marker rviz_default_plugins/MarkerArray rviz_default_plugins/Odometry rviz_default_plugins/Path rviz_default_plugins/PointCloud rviz_default_plugins/PointCloud2 rviz_default_plugins/PointStamped rviz_default_plugins/Polygon rviz_default_plugins/Pose rviz_default_plugins/PoseArray rviz_default_plugins/PoseWithCovariance rviz_default_plugins/Range rviz_default_plugins/RelativeHumidity rviz_default_plugins/RobotModel rviz_default_plugins/TF rviz_default_plugins/Temperature rviz_default_plugins/TwistStamped rviz_default_plugins/Wrench [joint_state_publisher_gui-4] [INFO] [1750695107.461749461] [joint_state_publisher_gui]: Centering [gazebo-1] [Wrn] [gazebo_ros_init.cpp:178] [gazebo-1] # # ####### ####### ### ##### ####### [gazebo-1] ## # # # # # # # # [gazebo-1] # # # # # # # # # [gazebo-1] # # # # # # # # ##### [gazebo-1] # # # # # # # # # [gazebo-1] # ## # # # # # # # [gazebo-1] # # ####### # ### ##### ####### [gazebo-1] [gazebo-1] This version of Gazebo, now called Gazebo classic, reaches end-of-life [gazebo-1] in January 2025. Users are highly encouraged to migrate to the new Gazebo [gazebo-1] using our migration guides (https://gazebosim.org/docs/latest/gazebo_classic_migration?utm_source=gazebo_ros_pkgs&utm_medium=cli) [gazebo-1] [gazebo-1] [joint_state_publisher_gui-4] [INFO] [1750695107.837611111] [joint_state_publisher_gui]: Centering [ros2-2] [INFO] [1750695107.897855160] [spawn_entity]: Spawn Entity started [ros2-2] [INFO] [1750695107.900047566] [spawn_entity]: Loading entity XML from file /home/robot/桌面/final_homework/install/fishbot_description/share/fishbot_description/urdf/first_robot.urdf [ros2-2] [INFO] [1750695107.902118423] [spawn_entity]: Waiting for service /spawn_entity, timeout = 30 [ros2-2] [INFO] [1750695107.905140588] [spawn_entity]: Waiting for service /spawn_entity [gazebo-1] [Msg] Waiting for master. [gazebo-1] [Msg] Connected to gazebo master @ http://127.0.0.1:11345 [gazebo-1] [Msg] Publicized address: 192.168.150.128 [gazebo-1] [Wrn] [GuiIface.cc:120] Could not find the Qt platform plugin "wayland" in "" [gazebo-1] [Err] [InsertModelWidget.cc:403] Missing model.config for model "/home/robot/.gazebo/models/wpr_simulation2" [gazebo-1] context mismatch in svga_surface_destroy [gazebo-1] context mismatch in svga_surface_destroy [ros2-2] [ERROR] [1750695138.117988219] [spawn_entity]: Service /spawn_entity unavailable. Was Gazebo started with GazeboRosFactory? [ros2-2] [ERROR] [1750695138.119174800] [spawn_entity]: Spawn service failed. Exiting. [ros2-2] [ros2run]: Process exited with failure 1 [ERROR] [ros2-2]: process has died [pid 7493, exit code 1, cmd 'ros2 run gazebo_ros spawn_entity.py -entity first_robot -file /home/robot/桌面/final_homework/install/fishbot_description/share/fishbot_description/urdf/first_robot.urdf'].

gazebo无法显示(能运行但里面是一片空白),如何解决 报错:robot@robot-virtual-machine:~/桌面/final_homework$ ros2 launch fishbot_description display_robot.launch.py [INFO] [launch]: All log files can be found below /home/robot/.ros/log/2025-06-24-00-20-49-599928-robot-virtual-machine-9501 [INFO] [launch]: Default logging verbosity is set to INFO [INFO] [gazebo-1]: process started with pid [9502] [INFO] [ros2-2]: process started with pid [9504] [INFO] [robot_state_publisher-3]: process started with pid [9506] [INFO] [joint_state_publisher_gui-4]: process started with pid [9508] [INFO] [rviz2-5]: process started with pid [9510] [rviz2-5] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [robot_state_publisher-3] [WARN] [1750695649.813319615] [robot_state_publisher]: No robot_description parameter, but command-line argument available. Assuming argument is name of URDF file. This backwards compatibility fallback will be removed in the future. [robot_state_publisher-3] [WARN] [1750695649.826852862] [kdl_parser]: The root link base_link has an inertia specified in the URDF, but KDL does not support a root link with an inertia. As a workaround, you can add an extra dummy link to your URDF. [robot_state_publisher-3] [INFO] [1750695649.827031936] [robot_state_publisher]: got segment base_link [robot_state_publisher-3] [INFO] [1750695649.827101073] [robot_state_publisher]: got segment imu_link [robot_state_publisher-3] [INFO] [1750695649.827120086] [robot_state_publisher]: got segment lidar_link [joint_state_publisher_gui-4] qt.qpa.plugin: Could not find the Qt platform plugin "wayland" in "" [gazebo-1] Gazebo multi-robot simulator, version 11.10.2 [gazebo-1] Copyright (C) 2012 Open Source Robotics Foundation. [gazebo-1] Released under the Apache 2 License. [gazebo-1] http://gazebosim.org [gazebo-1] [rviz2-5] [INFO] [1750695650.682274084] [rviz2]: Stereo is NOT SUPPORTED [rviz2-5] [INFO] [1750695650.682997533] [rviz2]: OpenGl version: 4.1 (GLSL 4.1) [gazebo-1] Gazebo multi-robot simulator, version 11.10.2 [gazebo-1] Copyright (C) 2012 Open Source Robotics Foundation. [gazebo-1] Released under the Apache 2 License. [gazebo-1] http://gazebosim.org [gazebo-1] [rviz2-5] [INFO] [1750695650.787656132] [rviz2]: Stereo is NOT SUPPORTED [rviz2-5] [ERROR] [1750695651.002030871] [rviz2]: PluginlibFactory: The plugin for class 'rviz_default_plugins/Imu' failed to load. Error: According to the loaded plugin descriptions the class rviz_default_plugins/Imu with base class type rviz_common::Display does not exist. Declared types are nav2_rviz_plugins/ParticleCloud rviz_default_plugins/AccelStamped rviz_default_plugins/Axes rviz_default_plugins/Camera rviz_default_plugins/DepthCloud rviz_default_plugins/Effort rviz_default_plugins/FluidPressure rviz_default_plugins/Grid rviz_default_plugins/GridCells rviz_default_plugins/Illuminance rviz_default_plugins/Image rviz_default_plugins/InteractiveMarkers rviz_default_plugins/LaserScan rviz_default_plugins/Map rviz_default_plugins/Marker rviz_default_plugins/MarkerArray rviz_default_plugins/Odometry rviz_default_plugins/Path rviz_default_plugins/PointCloud rviz_default_plugins/PointCloud2 rviz_default_plugins/PointStamped rviz_default_plugins/Polygon rviz_default_plugins/Pose rviz_default_plugins/PoseArray rviz_default_plugins/PoseWithCovariance rviz_default_plugins/Range rviz_default_plugins/RelativeHumidity rviz_default_plugins/RobotModel rviz_default_plugins/TF rviz_default_plugins/Temperature rviz_default_plugins/TwistStamped rviz_default_plugins/Wrench [joint_state_publisher_gui-4] [INFO] [1750695651.012208224] [joint_state_publisher_gui]: Waiting for robot_description to be published on the robot_description topic... [gazebo-1] [Wrn] [gazebo_ros_init.cpp:178] [gazebo-1] # # ####### ####### ### ##### ####### [gazebo-1] ## # # # # # # # # [gazebo-1] # # # # # # # # # [gazebo-1] # # # # # # # # ##### [gazebo-1] # # # # # # # # # [gazebo-1] # ## # # # # # # # [gazebo-1] # # ####### # ### ##### ####### [gazebo-1] [gazebo-1] This version of Gazebo, now called Gazebo classic, reaches end-of-life [gazebo-1] in January 2025. Users are highly encouraged to migrate to the new Gazebo [gazebo-1] using our migration guides (https://gazebosim.org/docs/latest/gazebo_classic_migration?utm_source=gazebo_ros_pkgs&utm_medium=cli) [gazebo-1] [gazebo-1] [joint_state_publisher_gui-4] [INFO] [1750695651.076499270] [joint_state_publisher_gui]: Centering [ros2-2] [INFO] [1750695651.294862637] [spawn_entity]: Spawn Entity started [ros2-2] [INFO] [1750695651.296018549] [spawn_entity]: Loading entity XML from file /home/robot/桌面/final_homework/install/fishbot_description/share/fishbot_description/urdf/first_robot.urdf [ros2-2] [INFO] [1750695651.298336590] [spawn_entity]: Waiting for service /spawn_entity, timeout = 30 [ros2-2] [INFO] [1750695651.299681322] [spawn_entity]: Waiting for service /spawn_entity [joint_state_publisher_gui-4] [INFO] [1750695651.411230857] [joint_state_publisher_gui]: Centering [gazebo-1] [Msg] Waiting for master. [gazebo-1] [Msg] Connected to gazebo master @ http://127.0.0.1:11345 [gazebo-1] [Msg] Publicized address: 192.168.150.128 [gazebo-1] [Wrn] [GuiIface.cc:120] Could not find the Qt platform plugin "wayland" in "" [gazebo-1] [Err] [InsertModelWidget.cc:403] Missing model.config for model "/home/robot/.gazebo/models/wpr_simulation2" [gazebo-1] context mismatch in svga_surface_destroy [gazebo-1] context mismatch in svga_surface_destroy [gazebo-1] [Wrn] [Publisher.cc:135] Queue limit reached for topic /gazebo/default/user_camera/pose, deleting message. This warning is printed only once. [ros2-2] [ERROR] [1750695681.462499528] [spawn_entity]: Service /spawn_entity unavailable. Was Gazebo started with GazeboRosFactory? [ros2-2] [ERROR] [1750695681.464526737] [spawn_entity]: Spawn service failed. Exiting. [ros2-2] [ros2run]: Process exited with failure 1 [ERROR] [ros2-2]: process has died [pid 9504, exit code 1, cmd 'ros2 run gazebo_ros spawn_entity.py -entity first_robot -file /home/robot/桌面/final_homework/install/fishbot_description/share/fishbot_description/urdf/first_robot.urdf']. 除此之外,imu也无法显示

#include "stm32f10x.h" #include "delay.h" #include "sys.h" #include "lcd.h" #include "spi.h" #include "led.h" #include "usart.h" #include "timer.h" #include <string.h> #define Humiture 1//温湿度 #define Illuminance 1//光照度 unsigned char Read_Humiture_CMD[8] ={0x01,0x03,0x00,0x00,0x00,0x02,0xC4,0x0B};//读取温湿度数据的命令 unsigned char Read_Illuminance_CMD[8] ={0x01,0x03,0x00,0x00,0x00,0x02,0xC4,0x0B};//读取光照度数据的命令 unsigned char Flag_LED3_ONOFF = 0; unsigned int Tem_value = 0,Hum_value = 0; unsigned long Light_value = 0,temp_u32 = 0; char Temp_value_str[7]; char Hum_value_str[6]; char Light_value_str[6]; char send_buf[100]; void copy_str(char* des,char* src,unsigned char len); int main(void) { LED_GPIO_Config(); //LED灯GPIO初始化 delay_init(); //延时函数初始化 Lcd_Init(); //初始化LCD Uart4_Init(9600); //串口4初始化 NVIC_Configuration(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 TIM3_Int_Init(999,7199); //开启定时器3,计数100ms BACK_COLOR=BLACK; //背景为黑色 POINT_COLOR=YELLOW; //画笔为黄色 LCD_Show_Chinese16x16(120,20,"实验"); LCD_ShowString(160,20,"8");//显示英文字符串 POINT_COLOR=GREEN;//绿色 // LCD_DrawRectangle(0, 40, 320, 240);//画矩形框 #ifdef Humiture LCD_Show_Chinese16x16(120,60,"温湿度"); LCD_Show_Chinese16x16(80,120,"温度: ℃"); LCD_Show_Chinese16x16(80,160,"湿度: %"); #endif #ifdef Illuminance LCD_Show_Chinese16x16(120,60,"光照度"); LCD_ShowString(80+16*4,120,"LUX"); #endif while(1) { if(Flag_timer_2S) {//2S时间到 Flag_timer_2S = 0; if(Flag_LED3_ONOFF) { Flag_LED3_ONOFF = 0; LED_Y_ON; } else { Flag_LED3_ONOFF = 1; LED_Y_OFF; } //发送采集传感器数据命令 #ifdef Humiture UART4TxData_hex(Read_Humiture_CMD,8); #endif #ifdef Illuminance UART4TxData_hex(Read_Illuminance_CMD,8); #endif } if(Flag_Uart4_Receive//如果串口4有数据接收 &&(!Count_Timer3_value_UART4_receive_timeout))//并且如果接收超时 { Flag_Uart4_Receive = 0; //显示传感器数据到LCD上 #ifdef Humiture //01 03 04 01 1B 02 7C 8B 49 //提取已经获取到的温湿度数据 Tem_value = UART4_RX_BUF[3]; Tem_value <<= 8; Tem_value |= UART4_RX_BUF[4]; Hum_value = UART4_RX_BUF[5]; Hum_value <<= 8; Hum_value |= UART4_RX_BUF[6]; CLR_Buf4(); if(Tem_value > 0) { Temp_value_str[0] = '+'; Temp_value_str[1] = (char)(Tem_value / 100 + '0'); Temp_value_str[2] = (char)(Tem_value % 100 / 10 + '0'); Temp_value_str[3] = '.'; Temp_value_str[4] = (char)(Tem_value % 10 + '0'); } Temp_value_str[5] = 0; Hum_value_str[0] = (char)(Hum_value / 100 + '0'); Hum_value_str[1] = (char)(Hum_value % 100 / 10 + '0'); Hum_value_str[2] = '.'; Hum_value_str[3] = (char)(Hum_value % 10 + '0'); Hum_value_str[4] = 0; POINT_COLOR=YELLOW; //画笔为黄色 LCD_ShowString(80+16*3,120,Temp_value_str); LCD_ShowString(80+16*3,160,Hum_value_str); #endif #ifdef Illuminance //提取已经获取到的光照度数据 //例如:01 03 04 00 00 10 54 F6 0C 有效数据为 00 10 54 (单位 LUX) Light_value = UART4_RX_BUF[4]; Light_value <<= 16; temp_u32 = UART4_RX_BUF[5]; temp_u32 <<= 8; Light_value |= temp_u32; Light_value |= UART4_RX_BUF[6]; CLR_Buf4(); Light_value_str[0] = (char)(Light_value / 100000 + '0'); Light_value_str[1] = (char)(Light_value % 100000 / 10000 + '0'); Light_value_str[2] = (char)(Light_value % 10000 / 1000 + '0'); Light_value_str[3] = (char)(Light_value % 1000 / 100 + '0'); Light_value_str[4] = (char)(Light_value % 100 / 10 + '0'); Light_value_str[5] = (char)(Light_value % 10 + '0'); POINT_COLOR=YELLOW; //画笔为黄色 LCD_ShowString(80,120,Light_value_str); #endif } } } 现在的代码是温湿度和光照度二选一,帮我修改为温湿度和光照度在同一个lcd屏同时显示

[rviz2-20] [ERROR] [1751273079.904134286] [rviz2]: PluginlibFactory: The plugin for class 'grid_map_rviz_plugin/GridMap' failed to load. Error: According to the loaded plugin descriptions the class grid_map_rviz_plugin/GridMap with base class type rviz_common::Display does not exist. Declared types are autoware_auto_perception_rviz_plugin/DetectedObjects autoware_auto_perception_rviz_plugin/PredictedObjects autoware_auto_perception_rviz_plugin/TrackedObjects rviz_default_plugins/AccelStamped rviz_default_plugins/Axes rviz_default_plugins/Camera rviz_default_plugins/DepthCloud rviz_default_plugins/Effort rviz_default_plugins/FluidPressure rviz_default_plugins/Grid rviz_default_plugins/GridCells rviz_default_plugins/Illuminance rviz_default_plugins/Image rviz_default_plugins/InteractiveMarkers rviz_default_plugins/LaserScan rviz_default_plugins/Map rviz_default_plugins/Marker rviz_default_plugins/MarkerArray rviz_default_plugins/Odometry rviz_default_plugins/Path rviz_default_plugins/PointCloud rviz_default_plugins/PointCloud2 rviz_default_plugins/PointStamped rviz_default_plugins/Polygon rviz_default_plugins/Pose rviz_default_plugins/PoseArray rviz_default_plugins/PoseWithCovariance rviz_default_plugins/Range rviz_default_plugins/RelativeHumidity rviz_default_plugins/RobotModel rviz_default_plugins/TF rviz_default_plugins/Temperature rviz_default_plugins/TwistStamped rviz_default_plugins/Wrench rviz_plugins/AccelerationMeter rviz_plugins/ConsoleMeter rviz_plugins/Float32MultiArrayStampedPieChart rviz_plugins/MaxVelocity rviz_plugins/MrmSummaryOverlayDisplay rviz_plugins/Path rviz_plugins/PathWithLaneId rviz_plugins/PolarGridDisplay rviz_plugins/PoseWithUuidStamped rviz_plugins/SteeringAngle rviz_plugins/Trajectory rviz_plugins/TurnSignal rviz_plugins/VelocityHistory rviz_plugins::PoseHistory rviz_plugins::PoseHistoryFootprint

package com.jd.projects.wlw.weatherinfo; import android.app.AlertDialog; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.LinearLayout; import android.widget.NumberPicker; import android.widget.TextView; import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.formatter.IAxisValueFormatter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.List; import android.graphics.Color; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import com.google.gson.Gson; import java.io.IOException; import java.net.URLEncoder; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.AxisBase; import java.util.Map; import java.util.HashMap; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import java.util.concurrent.TimeUnit; import com.google.gson.GsonBuilder; import com.jd.projects.wlw.R; import java.lang.reflect.Type; import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonParser; import com.google.gson.JsonNull; import android.content.Context; import java.util.Collections; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; import java.util.TimeZone; import java.util.LinkedHashMap; public class XqhtjfxActivity extends AppCompatActivity { private static final boolean TEST_MODE = true; private static final String TEST_STATION_ID = "860048072347493"; private static final String TEST_STATION_NAME = "奎屯市开干齐乡高疙瘩泉村"; private String currentStationId; private TextView nAme; private Calendar startCalendar; private Calendar endCalendar; private String selectedProperty; private String selectedYear; private long startYear; private long endYear; public void onBottomNavClick(View view) { String buttonText = ((TextView) ((LinearLayout) view).getChildAt(1)).getText().toString(); Class<?> targetActivity = null; switch (buttonText) { case "实时监测": targetActivity = XqhActivity.class; break; case "历史数据": targetActivity = XqhLssjActivity.class; break; case "数据汇总": targetActivity = XqhSjhzActivity.class; break; case "月度查询": showDateRangePicker1(); return; case "统计分析": return; // 已在当前页面 } if (targetActivity != null) { Intent intent = new Intent(this, targetActivity); intent.putExtra("stationId", currentStationId); intent.putExtra("stationName", nAme.getText().toString()); intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivity(intent); finish(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.xqhtjfx); // 新增参数完整性校验 if (getIntent() == null || !getIntent().hasExtra("stationId")) { showError("非法访问,缺少监测站参数"); // finish(); return; } currentStationId = TEST_MODE ? TEST_STATION_ID : getIntent().getStringExtra("stationId"); if (currentStationId == null || currentStationId.isEmpty()) { showError("监测站ID获取失败"); // finish(); return; } // 获取选中的属性和年份 selectedProperty = getIntent().getStringExtra("selectedProperty"); selectedYear = getIntent().getStringExtra("selectedYear"); // 新增年份有效性校验 try { int year = Integer.parseInt(selectedYear); int currentYear = Calendar.getInstance().get(Calendar.YEAR); if (year < 2000 || year > currentYear + 1) { showError("无效的年份参数"); // finish(); return; } } catch (NumberFormatException e) { showError("年份格式错误"); finish(); return; } if (selectedProperty == null || selectedYear == null) { Toast.makeText(this, "请选择属性和年份", Toast.LENGTH_SHORT).show(); // finish(); return; } nAme = (TextView) findViewById(R.id.nAme); nAme.setText(getIntent().getStringExtra("stationName")); // 初始化折线图 LineChart chart = (LineChart) findViewById(R.id.chart); initializeChart(chart); // 初始化站点信息 if (TEST_MODE) { currentStationId = TEST_STATION_ID; nAme.setText(TEST_STATION_NAME); } else { Intent intent = getIntent(); if (intent != null) { currentStationId = intent.getStringExtra("stationId"); String stationName = intent.getStringExtra("stationName"); nAme.setText(stationName != null ? stationName : "监测点信息异常"); } } // 调用后台接口获取数据 fetchAnnualData(); } private void initializeChart(LineChart chart) { chart.setTouchEnabled(true); chart.setDragEnabled(true); chart.setScaleEnabled(true); chart.setPinchZoom(true); chart.getDescription().setEnabled(false); } private void fetchAnnualData() { String apiProperty = getApiProperty(selectedProperty); if (apiProperty.isEmpty()) { showError("无效的属性参数"); return; } new Thread(() -> { try { // 使用URL编码处理参数 String encodedProperty = URLEncoder.encode(apiProperty, "UTF-8"); String encodedStationId = URLEncoder.encode(currentStationId, "UTF-8"); String url = "http://117.190.40.178:8080/api/qixiang/" + encodedProperty + "/" + selectedYear + "?stationId=" + encodedStationId; // Log.d("API_REQUEST", "请求URL: " + url); // 新增超时设置 OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(20, TimeUnit.SECONDS) .readTimeout(45, TimeUnit.SECONDS) .retryOnConnectionFailure(true) // 添加重试机制 .build(); Request request = new Request.Builder() .url(url) .addHeader("Station-ID", currentStationId) // 双重验证 .build(); Response response = client.newCall(request).execute(); if (response.isSuccessful()) { String jsonData = response.body().string(); // 添加调试日志 // Log.d("API_RESPONSE", "原始响应: " + jsonData); Gson gson = new GsonBuilder() .setLenient() .registerTypeAdapter(JsonElement.class, new JsonDeserializer<JsonElement>() { @Override public JsonElement deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { try { return new JsonParser().parse(json.getAsString()); } catch (Exception e) { return JsonNull.INSTANCE; } } }) .create(); JsonElement jsonElement = gson.fromJson(jsonData, JsonElement.class); if (jsonElement.isJsonArray()) { processJsonArray(jsonElement.getAsJsonArray(), apiProperty); } else if (jsonElement.isJsonObject()) { JsonObject jsonObject = jsonElement.getAsJsonObject(); // 检查状态码 if (jsonObject.has("code")) { int code = jsonObject.get("code").getAsInt(); if (code != 200) { String message = jsonObject.has("message") ? jsonObject.get("message").getAsString() : "未知错误"; showError("服务器错误: " + message); return; } } // 提取数据数组 if (jsonObject.has("data")) { JsonElement dataElement = jsonObject.get("data"); if (dataElement.isJsonArray()) { processJsonArray(dataElement.getAsJsonArray(), apiProperty); } else { showError("数据格式异常:data字段不是数组"); } } else { showError("响应缺少data字段"); } } else { showError("未知的响应格式"); } } else { parseErrorResponse(response); } } catch (Exception e) { e.printStackTrace(); showError("请求错误: " + e.getMessage()); } }).start(); } private Map<String, DailyStats> calculateDailyStats(List<DataPoint> dataPoints) { Map<String, DailyStats> dailyMap = new HashMap<>(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); // 统一使用UTC时区 for (DataPoint data : dataPoints) { try { // 使用UTC时区转换时间戳 String dateStr = sdf.format(new Date(data.getTimestampMillis())); float value = (float) data.getValue(); if (!dailyMap.containsKey(dateStr)) { dailyMap.put(dateStr, new DailyStats(value, value, value, 1)); } else { DailyStats stats = dailyMap.get(dateStr); stats.min = Math.min(stats.min, value); stats.max = Math.max(stats.max, value); stats.sum += value; stats.count++; } } catch (Exception e) { // Log.e("StatsError", "日期统计异常", e); } } return dailyMap; } private void processJsonArray(JsonArray jsonArray, String apiProperty) { List<DataPoint> dataPoints = new ArrayList<>(); SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); inputFormat.setTimeZone(TimeZone.getTimeZone("UTC")); for (JsonElement element : jsonArray) { try { JsonObject obj = element.getAsJsonObject(); // 验证stationId匹配 String receivedStationId = obj.get("StationId").getAsString(); if (!receivedStationId.equals(currentStationId)) { // Log.w("STATION_MISMATCH", "收到非当前站点数据,跳过处理"); continue; } // 解析时间 String monitorTime = obj.get("MonitorTime").getAsString(); Date date = inputFormat.parse(monitorTime); // 修改点2:增强数值解析逻辑 JsonElement valueElement = obj.get(apiProperty); if (valueElement == null || valueElement.isJsonNull()) { // Log.w("DATA_ERROR", "缺少属性字段: " + apiProperty); continue; } double value; try { // 尝试直接获取数值 value = valueElement.getAsDouble(); } catch (NumberFormatException | IllegalStateException e) { // 处理字符串格式数值 String stringValue = valueElement.getAsString(); if (stringValue.isEmpty()) { // Log.w("VALUE_PARSE", "空值数据: " + element.toString()); continue; } try { value = Double.parseDouble(stringValue); } catch (NumberFormatException ex) { // Log.e("VALUE_PARSE", "数值转换失败: " + stringValue); continue; } } // 修改点3:添加特殊值处理 if ((apiProperty.equals("RainAdd") || apiProperty.equals("evaporation_capacity")) && value == 0.0) { // Log.d("ZERO_VALUE", "接收到合法零值: " + value); } // 创建数据点 DataPoint dp = new DataPoint(); dp.setTimestampMillis(date.getTime()); dp.setValue(value); dataPoints.add(dp); } catch (ParseException e) { // Log.e("TIME_PARSE", "时间解析失败: " + element.toString(), e); } catch (Exception e) { // Log.e("PARSE_ERROR", "数据解析异常", e); } } // 添加调试日志显示解析结果 // Log.d("DATA_POINTS", "成功解析数据点数量: " + dataPoints.size()); runOnUiThread(() -> processData(dataPoints)); } private void parseErrorResponse(Response response) { try { String errorBody = response.body().string(); runOnUiThread(() -> Toast.makeText(this, "请求失败:" + response.code() + "\n" + errorBody, Toast.LENGTH_LONG).show()); } catch (IOException ex) { runOnUiThread(() -> Toast.makeText(this, "错误信息解析失败", Toast.LENGTH_SHORT).show()); } } private void processData(List<DataPoint> dataPoints) { LineChart chart = (LineChart) findViewById(R.id.chart); chart.clear(); if (dataPoints.isEmpty()) { showError("无数据"); return; } DataPoint firstPoint = dataPoints.get(0); if (firstPoint.getTimestampMillis() == 0) { showError("数据解析异常:无效的初始数据点"); return; } // 计算每日统计数据 Map<String, DailyStats> dailyStats = new LinkedHashMap<>(); // 保持日期顺序 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); // 按天分组数据 for (DataPoint dp : dataPoints) { String dayKey = sdf.format(new Date(dp.getTimestampMillis())); float value = (float) dp.getValue(); if (!dailyStats.containsKey(dayKey)) { dailyStats.put(dayKey, new DailyStats(value, value, value, 1)); } else { DailyStats stats = dailyStats.get(dayKey); stats.min = Math.min(stats.min, value); stats.max = Math.max(stats.max, value); stats.sum += value; stats.count++; } } // 填充完整日期范围(与XqhSjhzActivity相同的逻辑) Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); cal.set(Integer.parseInt(selectedYear), Calendar.JANUARY, 1, 0, 0, 0); long startMillis = cal.getTimeInMillis(); cal.set(Integer.parseInt(selectedYear), Calendar.DECEMBER, 31, 23, 59, 59); long endMillis = cal.getTimeInMillis(); while (cal.getTimeInMillis() >= startMillis) { String dayKey = sdf.format(cal.getTime()); if (!dailyStats.containsKey(dayKey)) { dailyStats.put(dayKey, new DailyStats(Float.NaN, Float.NaN, 0, 0)); } cal.add(Calendar.DATE, -1); // 逆向填充确保完整 } // 创建平均值数据集(与XqhSjhzActivity相同的计算方式) List<Entry> avgEntries = new ArrayList<>(); for (Map.Entry<String, DailyStats> entry : dailyStats.entrySet()) { try { Date date = sdf.parse(entry.getKey()); float avg = entry.getValue().getAverage(); if (!Float.isNaN(avg)) { avgEntries.add(new Entry(date.getTime(), avg)); } } catch (ParseException e) { e.printStackTrace(); } } // 按时间排序 Collections.sort(avgEntries, (e1, e2) -> Float.compare(e1.getX(), e2.getX())); if (avgEntries.isEmpty()) { showError("无有效数据"); return; } // 创建数据集 LineDataSet dataSet = new LineDataSet(avgEntries, selectedProperty + "日均值"); dataSet.setColor(Color.BLUE); dataSet.setLineWidth(2f); dataSet.setCircleColor(Color.RED); dataSet.setCircleRadius(3f); dataSet.setValueTextSize(10f); dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); LineData lineData = new LineData(dataSet); chart.setData(lineData); // 配置X轴 XAxis xAxis = chart.getXAxis(); xAxis.setValueFormatter(new DateAxisValueFormatter()); xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); xAxis.setGranularity(86400000); // 1天间隔 xAxis.setLabelCount(12, true); xAxis.setAxisMinimum(startMillis); xAxis.setAxisMaximum(endMillis); // 配置Y轴 YAxis leftAxis = chart.getAxisLeft(); leftAxis.setAxisMinimum(0f); leftAxis.setGranularity(1f); chart.getAxisRight().setEnabled(false); // 添加MarkerView CustomMarkerView markerView = new CustomMarkerView(this, R.layout.custom_marker_view); chart.setMarker(markerView); chart.invalidate(); } // 添加数据统计模型 private static class DailyStats { float min; float max; float sum; int count; DailyStats(float min, float max, float sum, int count) { this.min = min; this.max = max; this.sum = sum; this.count = count; } float getAverage() { return count == 0 ? Float.NaN : sum / count; } } // 添加自定义MarkerView private class CustomMarkerView extends MarkerView { private final TextView tvDate; private final TextView tvValue; private final SimpleDateFormat dateFormat; public CustomMarkerView(Context context, int layoutResource) { super(context, layoutResource); tvDate = (TextView) findViewById(R.id.tvDate); tvValue = (TextView) findViewById(R.id.tvValue); dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); } @Override public void refreshContent(Entry e, Highlight highlight) { long timestamp = (long) e.getX(); String unit = getUnitByProperty(selectedProperty); tvDate.setText(dateFormat.format(new Date(timestamp))); tvValue.setText(String.format(Locale.getDefault(), "%.1f%s", e.getY(), unit)); super.refreshContent(e, highlight); } @Override public MPPointF getOffset() { return new MPPointF(-(getWidth() / 2), -getHeight()); } } // 添加单位获取方法 private String getUnitByProperty(String property) { Map<String, String> unitMap = new HashMap<>(); unitMap.put("空气温度", "℃"); unitMap.put("空气相对湿度", "%"); unitMap.put("降雨量", "mm"); unitMap.put("蒸发量", "mm"); unitMap.put("风速", "m/s"); unitMap.put("风向", "°"); unitMap.put("露点温度", "℃"); unitMap.put("光照度", "Klx"); unitMap.put("日照强度", "W/m?"); unitMap.put("气压", "hPa"); unitMap.put("光合有效辐射", "W"); unitMap.put("土壤温度10cm", "℃"); unitMap.put("土壤温度20cm", "℃"); unitMap.put("土壤温度30cm", "℃"); unitMap.put("土壤含水量10cm", "%"); unitMap.put("土壤含水量20cm", "%"); unitMap.put("土壤含水量30cm", "%"); return unitMap.getOrDefault(property, ""); } private List<Entry> getEntries(List<DataPoint> dataPoints) { List<Entry> entries = new ArrayList<>(); for (DataPoint dp : dataPoints) { entries.add(new Entry(dp.getTimestampMillis(), (float) dp.getValue())); } return entries; } private class DateAxisValueFormatter implements IAxisValueFormatter { private final SimpleDateFormat mFormat; public DateAxisValueFormatter() { mFormat = new SimpleDateFormat("MM-dd", Locale.getDefault()); mFormat.setTimeZone(TimeZone.getTimeZone("UTC")); // 确保格式化使用UTC } @Override public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(new Date((long) value)); } } public class DataPoint { private long timestampMillis; private double value; public void setTimestampMillis(long timestampMillis) { this.timestampMillis = timestampMillis; } public void setValue(double value) { this.value = value; } public long getTimestampMillis() { return timestampMillis; } public double getValue() { return value; } } private void showError(String message) { runOnUiThread(() -> Toast.makeText(this, message, Toast.LENGTH_SHORT).show()); } private void showDateRangePicker1() { AlertDialog.Builder builder = new AlertDialog.Builder(this); View dialogView = getLayoutInflater().inflate(R.layout.custom_date_picker, null); // 初始化开始日期控件 NumberPicker startYearPicker = (NumberPicker) dialogView.findViewById(R.id.np_start_year); NumberPicker startMonthPicker = (NumberPicker) dialogView.findViewById(R.id.np_start_month); NumberPicker startDayPicker = (NumberPicker) dialogView.findViewById(R.id.np_start_day); // 初始化结束日期控件 NumberPicker endYearPicker = (NumberPicker) dialogView.findViewById(R.id.np_end_year); NumberPicker endMonthPicker = (NumberPicker) dialogView.findViewById(R.id.np_end_month); NumberPicker endDayPicker = (NumberPicker) dialogView.findViewById(R.id.np_end_day); // 设置当前日期 Calendar calendar = Calendar.getInstance(); int currentYear = calendar.get(Calendar.YEAR); int currentMonth = calendar.get(Calendar.MONTH) + 1; // 转换为1-based int currentDay = calendar.get(Calendar.DAY_OF_MONTH); // 配置开始日期选择器 configureDatePickers(startYearPicker, startMonthPicker, startDayPicker, currentYear, currentMonth, currentDay); // 配置结束日期选择器 configureDatePickers(endYearPicker, endMonthPicker, endDayPicker, currentYear, currentMonth, currentDay); // 设置日期动态调整监听器 setupListeners(startYearPicker, startMonthPicker, startDayPicker); setupListeners(endYearPicker, endMonthPicker, endDayPicker); builder.setView(dialogView) .setPositiveButton("确定", (dialog, which) -> { // 获取并验证日期 String startDate = getFormattedDate(startYearPicker, startMonthPicker, startDayPicker); String endDate = getFormattedDate(endYearPicker, endMonthPicker, endDayPicker); if (!validateDateRange(startDate, endDate)) { Toast.makeText(this, "结束日期不能早于开始日期", Toast.LENGTH_SHORT).show(); return; } // 跳转至XqhydcxActivity Intent intent = new Intent(this, XqhydcxActivity.class); intent.putExtra("stationId", currentStationId); intent.putExtra("stationName", nAme.getText().toString()); intent.putExtra("startDate", startDate); intent.putExtra("endDate", endDate); startActivity(intent); }) .setNegativeButton("取消", (dialog, which) -> dialog.dismiss()) .create() .show(); } // 辅助方法:配置日期选择器初始值 private void configureDatePickers(NumberPicker yearPicker, NumberPicker monthPicker, NumberPicker dayPicker, int year, int month, int day) { yearPicker.setMinValue(2020); yearPicker.setMaxValue(2030); yearPicker.setValue(year); monthPicker.setMinValue(1); monthPicker.setMaxValue(12); monthPicker.setValue(month); Calendar cal = Calendar.getInstance(); cal.set(year, month - 1, 1); dayPicker.setMinValue(1); dayPicker.setMaxValue(cal.getActualMaximum(Calendar.DAY_OF_MONTH)); dayPicker.setValue(day); } // 辅助方法:设置年、月变化监听器 private void setupListeners(NumberPicker yearPicker, NumberPicker monthPicker, NumberPicker dayPicker) { yearPicker.setOnValueChangedListener((picker, oldVal, newVal) -> updateDayPicker(monthPicker.getValue(), newVal, dayPicker)); monthPicker.setOnValueChangedListener((picker, oldVal, newVal) -> updateDayPicker(newVal, yearPicker.getValue(), dayPicker)); } // 辅助方法:动态调整日期的最大值 private void updateDayPicker(int month, int year, NumberPicker dayPicker) { Calendar cal = Calendar.getInstance(); cal.set(year, month - 1, 1); int maxDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH); dayPicker.setMaxValue(maxDay); if (dayPicker.getValue() > maxDay) { dayPicker.setValue(maxDay); } } // 辅助方法:格式化日期 private String getFormattedDate(NumberPicker year, NumberPicker month, NumberPicker day) { return String.format("%04d-%02d-%02d", year.getValue(), month.getValue(), day.getValue()); } // 辅助方法:验证日期范围 private boolean validateDateRange(String startDateStr, String endDateStr) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); try { Date startDate = sdf.parse(startDateStr); Date endDate = sdf.parse(endDateStr); return !endDate.before(startDate); } catch (ParseException e) { e.printStackTrace(); return false; } } private String getApiProperty(String chineseProperty) { // 建立中文属性名与英文字段名的映射 Map<String, String> propertyMap = new HashMap<>(); propertyMap.put("空气温度", "Etemperature"); propertyMap.put("空气相对湿度", "Ehumidity"); propertyMap.put("降雨量", "RainAdd"); propertyMap.put("蒸发量", "evaporation_capacity"); propertyMap.put("风速", "WindSpeed"); propertyMap.put("风向", "WindDirection"); propertyMap.put("露点温度", "dewPoint"); propertyMap.put("光照度", "illuminance"); propertyMap.put("日照强度", "SimpleRadiation"); propertyMap.put("气压", "AirPressure"); propertyMap.put("光合有效辐射", "PhotoRadiation"); propertyMap.put("土壤温度10cm", "SoilTemp1"); propertyMap.put("土壤温度20cm", "SoilTemp2"); propertyMap.put("土壤温度30cm", "SoilTemp3"); propertyMap.put("土壤含水量10cm", "SoilHum1"); propertyMap.put("土壤含水量20cm", "SoilHum2"); propertyMap.put("土壤含水量30cm", "SoilHum3"); String apiField = propertyMap.getOrDefault(chineseProperty, ""); // Log.d("PropertyMapping", "中文属性: " + chineseProperty + " → 英文字段: " + apiField); return apiField; } } apply plugin: 'com.android.application' android { useLibrary 'org.apache.http.legacy' compileOptions { encoding "GBK" } compileSdkVersion 24 buildToolsVersion "24.0.0" aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false defaultConfig { applicationId "com.jd.projects.wulianwang" multiDexEnabled true minSdkVersion 16 targetSdkVersion 24 versionCode 9 versionName "1.0.0.8" ndk { abiFilters 'armeabi' } } lintOptions { checkReleaseBuilds false // Or, if you prefer, you can continue to check for errors in release builds, // but continue the build even when errors are found: abortOnError false } signingConfigs { release { storeFile file('wulianwang.jks') storePassword '666666' keyAlias 'wulianwang' keyPassword '666666' } } buildTypes { release { minifyEnabled false signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' aaptOptions { ignoreAssetsPattern '!sdfg1.apk:!sdfg2.apk:!sdfg3.apk:!sdfg4.apk:' } } debug { minifyEnabled false signingConfig signingConfigs.release proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } lintOptions { checkReleaseBuilds false abortOnError false } } dependencies { compile project(':mPAndroidChartLib') compile project(':mqttlibs') compile files('libs/1_6XDevSDK_1.29_beta.jar') compile files('libs/afinal_0.5.1_bin.jar') compile files('libs/AudioEngineSDK.jar') compile files('libs/BaiduLBS_Android.jar') compile files('libs/classes.jar') compile files('libs/glide-3.7.0.jar') compile files('libs/HCNetSDK.jar') compile files('libs/INetSDK.jar') compile files('libs/IPlaySDK.jar') compile files('libs/jpush-sdk-release1.7.5.jar') compile files('libs/jxl.jar') compile files('libs/ksoap2-android-assembly-2.5.2-jar-with-dependencies.jar') compile files('libs/MCRSDK.jar') compile files('libs/PlayerSDK.jar') compile files('libs/ToUProxy.jar') compile files('libs/universal-image-loader-1.9.3.jar') compile files('libs/vmsnetsdk.jar') compile files('libs/volley.jar') compile files('libs/xUtils-2.6.14.jar') compile 'com.google.code.gson:gson:2.2.4' compile 'com.android.support:support-v4:22.4.0' compile 'com.android.support:appcompat-v7:22.1.1' compile 'com.google.android.gms:play-services-appindexing:8.4.0' compile files('libs/okhttp-2.7.5.jar') // compile files('libs/okio-1.6.0.jar') // implementation 'com.squareup.okhttp3:okhttp:4.9.1' implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1' implementation 'com.squareup.retrofit2:retrofit:2.6.0' implementation 'com.squareup.retrofit2:converter-gson:2.6.0' implementation 'com.squareup.retrofit2:converter-scalars:2.4.0' //2025.5.27新添加 // implementation 'com.android.support:appcompat-v7:24.0.0' implementation 'com.android.support:gridlayout-v7:24.2.1' implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support:recyclerview-v7:24.2.1' implementation 'org.apache.poi:poi:3.15' implementation 'org.apache.poi:poi-ooxml:3.15' implementation 'com.fasterxml:aalto-xml:1.0.0' implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' } configurations.all { resolutionStrategy { eachDependency { details -> if (details.requested.group == 'androidx.annotation') { details.useTarget group: 'com.android.support', name: 'support-annotations', version: '24.2.1' } } } } 依据上述代码解决报错,如果要改变依赖只能改变//2025.5.27新添加 // implementation 'com.android.support:appcompat-v7:24.0.0' implementation 'com.android.support:gridlayout-v7:24.2.1' implementation 'com.android.support.constraint:constraint-layout:1.0.2' implementation 'com.android.support:recyclerview-v7:24.2.1' implementation 'org.apache.poi:poi:3.15' implementation 'org.apache.poi:poi-ooxml:3.15' implementation 'com.fasterxml:aalto-xml:1.0.0' implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' } configurations.all { resolutionStrategy { eachDependency { details -> if (details.requested.group == 'androidx.annotation') { details.useTarget group: 'com.android.support', name: 'support-annotations', version: '24.2.1' } } } }这些依赖,其他以来不能变。D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:167: ����: �Ҳ������� chart.getDescription().setEnabled(false); ^ ����: ���� getDescription() λ��: ����ΪLineChart�ı��� chart D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:426: ����: �����ݵ�����: ��floatת����int���ܻ�����ʧ avgEntries.add(new Entry(date.getTime(), avg)); ^ D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:434: ����: �Ҳ������� Collections.sort(avgEntries, (e1, e2) -> Float.compare(e1.getX(), e2.getX())); ^ ����: ���� getX() λ��: ����ΪEntry�ı��� e1 D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:434: ����: �Ҳ������� Collections.sort(avgEntries, (e1, e2) -> Float.compare(e1.getX(), e2.getX())); ^ ����: ���� getX() λ��: ����ΪEntry�ı��� e2 D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:446: ����: �Ҳ������� dataSet.setCircleRadius(3f); ^ ����: ���� setCircleRadius(float) λ��: ����ΪLineDataSet�ı��� dataSet D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:448: ����: �Ҳ������� dataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); ^ ����: ���� Mode λ��: �� LineDataSet D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:450: ����: ����LineData(LineDataSet), �Ҳ������ʵĹ����� LineData lineData = new LineData(dataSet); ^ ������ LineData.LineData(List<String>)������ (������ƥ��; LineDataSet�޷�ת��ΪList<String>) ������ LineData.LineData(String[])������ (������ƥ��; LineDataSet�޷�ת��ΪString[]) D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:455: ����: �Ҳ������� xAxis.setValueFormatter(new DateAxisValueFormatter()); ^ ����: ���� setValueFormatter(XqhtjfxActivity.DateAxisValueFormatter) λ��: ����ΪXAxis�ı��� xAxis D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:457: ����: �Ҳ������� xAxis.setGranularity(86400000); // 1���� ^ ����: ���� setGranularity(int) λ��: ����ΪXAxis�ı��� xAxis D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:458: ����: �Ҳ������� xAxis.setLabelCount(12, true); ^ ����: ���� setLabelCount(int,boolean) λ��: ����ΪXAxis�ı��� xAxis D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:459: ����: �Ҳ������� xAxis.setAxisMinimum(startMillis); ^ ����: ���� setAxisMinimum(long) λ��: ����ΪXAxis�ı��� xAxis D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:460: ����: �Ҳ������� xAxis.setAxisMaximum(endMillis); ^ ����: ���� setAxisMaximum(long) λ��: ����ΪXAxis�ı��� xAxis D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:464: ����: �Ҳ������� leftAxis.setAxisMinimum(0f); ^ ����: ���� setAxisMinimum(float) λ��: ����ΪYAxis�ı��� leftAxis D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:465: ����: �Ҳ������� leftAxis.setGranularity(1f); ^ ����: ���� setGranularity(float) λ��: ����ΪYAxis�ı��� leftAxis D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:470: ����: �Ҳ������� chart.setMarker(markerView); ^ ����: ���� setMarker(XqhtjfxActivity.CustomMarkerView) λ��: ����ΪLineChart�ı��� chart D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:494: ����: XqhtjfxActivity.CustomMarkerView���dz����, ����δ����MarkerView�еij��󷽷�getYOffset() private class CustomMarkerView extends MarkerView { ^ D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:508: ����: �Ҳ������� long timestamp = (long) e.getX(); ^ ����: ���� getX() λ��: ����ΪEntry�ı��� e D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:511: ����: �Ҳ������� tvValue.setText(String.format(Locale.getDefault(), "%.1f%s", e.getY(), unit)); ^ ����: ���� getY() λ��: ����ΪEntry�ı��� e D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:512: ����: �޷�ֱ�ӷ���MarkerView�еij��󷽷� refreshContent(Entry,Highlight) super.refreshContent(e, highlight); ^ D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:515: ����: �������Ḳ�ǻ�ʵ�ֳ����͵ķ��� @Override ^ D:\biancheng\jd_jdwlw-master\android_Jdwlw\src\main\java\com\jd\projects\wlw\weatherinfo\XqhtjfxActivity.java:547: ����: �����ݵ�����: ��floatת����int���ܻ�����ʧ entries.add(new Entry(dp.getTimestampMillis(), (float) dp.getValue())); ^

% 灯具参数 power = [800, 1000, 1200, 1500, 2000, 2500]; efficacy = [24, 26, 28, 30, 32, 34]; price = [2000, 2500, 2800, 3100, 3500, 3900]; F_k = power .* efficacy; % 光通量(lm) % 场馆参数 room_size = [100, 80]; % 长宽(m) height = 9; % 高度(m) % 遗传算法参数 num_lamps = 12; % 灯具总数(可调整) pop_size = 100; % 种群大小 max_generations = 50; % 最大迭代次数 % 初始化种群(整数编码:1-6表示灯具类型) population = randi(6, pop_size, num_lamps); % 评估函数 function [cost, power_sum, violation] = evaluate(individual) global F_k price power room_size height total_cost = sum(price(individual)); total_power = sum(power(individual)); % 生成均匀网格位置 [m, n] = grid_dimensions(numel(individual), room_size); pos_x = linspace(0, room_size(1), m+2); pos_x = pos_x(2:end-1); pos_y = linspace(0, room_size(2), n+2); pos_y = pos_y(2:end-1); [X, Y] = meshgrid(pos_x, pos_y); positions = [X(:), Y(:)]; % 计算关键点照度(网格中心和灯具点) key_points = [positions; positions + [diff(pos_x(1:2))/2, 0]; positions + [0, diff(pos_y(1:2))/2]]; % 计算所有关键点照度 E = zeros(size(key_points, 1), 1); for i = 1:numel(individual) lamp_type = individual(i); F = F_k(lamp_type); d_vec = key_points - positions(i, :); d_vals = sqrt(sum(d_vec.^2, 2) + height^2); E = E + (F * height) ./ (2 * pi * d_vals.^3); end % 计算约束违反程度 min_E = min(E); max_E = max(E); violation = max(0, 20 - min_E) + max(0, max_E - 200); cost = total_cost; power_sum = total_power; end % 遗传算法主循环 best_solution = []; best_cost = inf; for gen = 1:max_generations % 评估种群 fitness = zeros(pop_size, 1); costs = zeros(pop_size, 1); powers = zeros(pop_size, 1); for i = 1:pop_size [costs(i), powers(i), viol] = evaluate(population(i, :)); fitness(i) = 1/(costs(i) + 1000*viol); % 罚函数法处理约束 end % 选择(锦标赛选择) new_pop = zeros(size(population)); for i = 1:pop_size candidates = randperm(pop_size, 3); [~, idx] = max(fitness(candidates)); new_pop(i, :) = population(candidates(idx), :); end % 交叉(单点交叉) for i = 1:2:pop_size-1 if rand < 0.8 cp = randi([1, num_lamps-1]); temp = new_pop(i, cp+1:end); new_pop(i, cp+1:end) = new_pop(i+1, cp+1:end); new_pop(i+1, cp+1:end) = temp; end end % 变异 for i = 1:pop_size if rand < 0.1 mut_pos = randi(num_lamps); new_pop(i, mut_pos) = randi(6); end end population = new_pop; % 记录最佳解 [min_cost, idx] = min(costs); if min_cost < best_cost best_cost = min_cost; best_solution = population(idx, :); end fprintf('Generation %d: Min Cost = %.2f, Avg Power = %.1f kW\n', ... gen, min_cost, mean(powers)/1000); end % 输出最佳方案 [cost, power_total, viol] = evaluate(best_solution); fprintf('\n=== Optimal Solution ===\n'); fprintf('Total Cost: %.2f yuan\n', cost); fprintf('Total Power: %.1f kW\n', power_total/1000); fprintf('Violation: %.4f (0=feasible)\n', viol); disp('Lamp Types:'); disp(best_solution); % 可视化灯具分布 [m, n] = grid_dimensions(num_lamps, room_size); pos_x = linspace(0, room_size(1), m+2); pos_x = pos_x(2:end-1); pos_y = linspace(0, room_size(2), n+2); pos_y = pos_y(2:end-1); [X, Y] = meshgrid(pos_x, pos_y); positions = [X(:), Y(:)]; figure; scatter(positions(:,1), positions(:,2), 100, best_solution, 'filled'); colorbar; title('Lamp Distribution by Type'); xlabel('X (m)'); ylabel('Y (m)'); axis equal; grid on; xlim([0, room_size(1)]); ylim([0, room_size(2)]); % 计算网格维度函数 function [m, n] = grid_dimensions(N, room_size) aspect = room_size(1)/room_size(2); m = round(sqrt(N * aspect)); n = ceil(N / m); if m*n < N m = m + 1; end end 在此代码下指出最低照度和最高照度

% 灯具参数 power = [800, 1000, 1200, 1500, 2000, 2500]; efficacy = [24, 26, 28, 30, 32, 34]; price = [2000, 2500, 2800, 3100, 3500, 3900]; F_k = power .* efficacy; % 光通量(lm) % 场馆参数 room_size = [100, 80]; % 长宽(m) height = 9; % 高度(m) % 遗传算法参数 num_lamps = 12; % 灯具总数(可调整) pop_size = 100; % 种群大小 max_generations = 50; % 最大迭代次数 % 初始化种群(整数编码:1-6表示灯具类型) population = randi(6, pop_size, num_lamps); % 评估函数 function [cost, power_sum, violation] = evaluate(individual) global F_k price power room_size height total_cost = sum(price(individual)); total_power = sum(power(individual)); % 生成均匀网格位置 [m, n] = grid_dimensions(numel(individual), room_size); pos_x = linspace(0, room_size(1), m+2); pos_x = pos_x(2:end-1); pos_y = linspace(0, room_size(2), n+2); pos_y = pos_y(2:end-1); [X, Y] = meshgrid(pos_x, pos_y); positions = [X(:), Y(:)]; % 计算关键点照度(网格中心和灯具点) key_points = [positions; positions + [diff(pos_x(1:2))/2, 0]; positions + [0, diff(pos_y(1:2))/2]]; % 计算所有关键点照度 E = zeros(size(key_points, 1), 1); for i = 1:numel(individual) lamp_type = individual(i); F = F_k(lamp_type); d_vec = key_points - positions(i, :); d_vals = sqrt(sum(d_vec.^2, 2) + height^2); E = E + (F * height) ./ (2 * pi * d_vals.^3); end % 计算约束违反程度 min_E = min(E); max_E = max(E); violation = max(0, 20 - min_E) + max(0, max_E - 200); cost = total_cost; power_sum = total_power; end % 遗传算法主循环 best_solution = []; best_cost = inf; for gen = 1:max_generations % 评估种群 fitness = zeros(pop_size, 1); costs = zeros(pop_size, 1); powers = zeros(pop_size, 1); for i = 1:pop_size [costs(i), powers(i), viol] = evaluate(population(i, :)); fitness(i) = 1/(costs(i) + 1000*viol); % 罚函数法处理约束 end % 选择(锦标赛选择) new_pop = zeros(size(population)); for i = 1:pop_size candidates = randperm(pop_size, 3); [~, idx] = max(fitness(candidates)); new_pop(i, :) = population(candidates(idx), :); end % 交叉(单点交叉) for i = 1:2:pop_size-1 if rand < 0.8 cp = randi([1, num_lamps-1]); temp = new_pop(i, cp+1:end); new_pop(i, cp+1:end) = new_pop(i+1, cp+1:end); new_pop(i+1, cp+1:end) = temp; end end % 变异 for i = 1:pop_size if rand < 0.1 mut_pos = randi(num_lamps); new_pop(i, mut_pos) = randi(6); end end population = new_pop; % 记录最佳解 [min_cost, idx] = min(costs); if min_cost < best_cost best_cost = min_cost; best_solution = population(idx, :); end fprintf('Generation %d: Min Cost = %.2f, Avg Power = %.1f kW\n', ... gen, min_cost, mean(powers)/1000); end % 输出最佳方案 [cost, power_total, viol] = evaluate(best_solution); fprintf(‘\n=== Optimal Solution ===\n’); fprintf(‘Total Cost: %.2f yuan\n’, cost); fprintf(‘Total Power: %.1f kW\n’, power_total/1000); fprintf(‘Violation: %.4f (0=feasible)\n’, viol); disp(‘Lamp Types:’); disp(best_solution); % 可视化灯具分布 [m, n] = grid_dimensions(num_lamps, room_size); pos_x = linspace(0, room_size(1), m+2); pos_x = pos_x(2:end-1); pos_y = linspace(0, room_size(2), n+2); pos_y = pos_y(2:end-1); [X, Y] = meshgrid(pos_x, pos_y); positions = [X(😃, Y(😃]; figure; scatter(positions(:,1), positions(:,2), 100, best_solution, ‘filled’); colorbar; title(‘Lamp Distribution by Type’); xlabel(‘X (m)’); ylabel(‘Y (m)’); axis equal; grid on; xlim([0, room_size(1)]); ylim([0, room_size(2)]); % 计算网格维度函数 function [m, n] = grid_dimensions(N, room_size) aspect = room_size(1)/room_size(2); m = round(sqrt(N * aspect)); n = ceil(N / m); if m*n < N m = m + 1; end end 在此代码下添加代码指出最低照度和最高照度,并结合成一个代码

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H ----------------------------------------------- #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } 以上两个是.h和.cpp代码 --------------------------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>628</height> </rect> <string>MainWindow</string> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="pb_connect"> <rect> <x>40</x> <y>20</y> <width>89</width> <height>25</height> </rect> <string>连接</string> </widget> <widget class="QPushButton" name="pb_led0"> <rect> <x>40</x> <y>70</y> <width>89</width> <height>25</height> </rect> <string>led0_on</string> </widget> <widget class="QPushButton" name="pb_led1"> <rect> <x>40</x> <y>110</y> <width>89</width> <height>25</height> </rect> <string>led1_on</string> </widget> <widget class="QPushButton" name="pb_led2"> <rect> <x>40</x> <y>150</y> <width>89</width> <height>25</height> </rect> <string>led2_on</string> </widget> <widget class="QPushButton" name="pb_feng"> <rect> <x>40</x> <y>190</y> <width>89</width> <height>25</height> </rect> <string>feng_on</string> </widget> <widget class="QPushButton" name="pb_buzzer"> <rect> <x>140</x> <y>20</y> <width>89</width> <height>25</height> </rect> <string>蜂鸣器_on</string> </widget> <widget class="QPushButton" name="pb_humiture"> <rect> <x>140</x> <y>70</y> <width>89</width> <height>25</height> </rect> <string>温湿度_on</string> </widget> <widget class="QPushButton" name="pb_photosensitive"> <rect> <x>140</x> <y>110</y> <width>89</width> <height>25</height> </rect> <string>光敏_on</string> </widget> <widget class="QPushButton" name="pb_infrared"> <rect> <x>140</x> <y>150</y> <width>89</width> <height>25</height> </rect> <string>人体红外_on</string> </widget> <widget class="QPushButton" name="pb_camera"> <rect> <x>140</x> <y>190</y> <width>89</width> <height>25</height> </rect> <string>摄像头_on</string> </widget> <widget class="QTextBrowser" name="textBrowser"> <rect> <x>350</x> <y>10</y> <width>421</width> <height>211</height> </rect> </widget> </widget> <widget class="QMenuBar" name="menubar"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>28</height> </rect> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui> 以上是.ui代码 --------------------------------------------------------- 目前项目进度: 当前项目结构如下: DXM1txst: DXM1txst.pro Headers: fsmpBeeper.h fsmpElectric.h fsmpEvents.h fsmpFan.h fsmpLed.h fsmpLight.h fsmpProximity.h fsmpsevensegLed.h fsmpTempHum.h fsmpvibrator.h mainwindow.h Sources: main.cpp mainwindow.cpp Forms: mainwindow.ui qtcreator内:ui界面中已经有组件:pb_connect(连接按钮)、pb_led0(电灯1开关按钮)、pb_led1(电灯2开关按钮)、pb_led2(电灯3开关按钮)、pb_feng(风扇开关按钮)、pb_buzzer(蜂鸣器开关按钮)、pb_humiture(温湿度传感器开关按钮)、pb_photosensitive(光敏传感器开关按钮)、pb_infrared(人体红外传感器开关按钮)、pb_camera(摄像头开关按钮)、textBrowser(用于接收和发布的消息显示)。 华清远见元宇宙实验中心物联网仿真系统内:所需的所以硬件的3D场景设计完毕,M4网关单元的Mqtt配置为: 地址:mqtt.yyzlab.com.cn 端口:1883 与应用层、云端交互的Topic: 订阅:1752365375766/APP2AIOTSIM 发布:1752365375766/AIOTSIM2APP 与硬件交互的Topic: 订阅:1752365382482/Device2AIOTSIM 发布:1752365382482/AIOTSIM2Device 与华清远见元宇宙实验中心物联网仿真系统内硬件开关发布的控制码为:电灯0开:{"lamp":true,"id":0},电灯0关:{"lamp":false,"id":0},电灯1开:{"lamp":true,"id":1},电灯1关:{"lamp":false,"id":1},电灯2开:{"lamp":true,"id":2},电灯2关:{"lamp":false,"id":2},风扇开:{"fan":true,"id":0},风扇关:{"fan":false,"id":0},人体红外传感器开:{"infrared ":true,"id":0},人体红外传感器关:{"infrarrared ":false,"id":0},温湿度传感器:{"tem":38.8,"hum":65.7,"id":0},光敏传感器:{"light":43037.0,"id":0} Stm32mp157开发板:所有需要的硬件部署完毕,硬件的.h代码如下(硬件的.h代码已经放入qtcreator项目下的Headers文件夹下,且硬件的所有.h文件内代码都不能再进行修改): fsmpBeeper.h: #ifndef FSMPBEEPER_H #define FSMPBEEPER_H /*************************************************************************** * * 类名:fsmpBeeper * 功能说明:扩展板 蜂鸣器 * 公有函数: * fsmpBeeper() * bool setRate(uint32_t rate) 设置频率 * bool start(void) 启动蜂鸣器 * bool stop(void) 关闭蜂鸣器 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> /* FSMP开发板(linux)蜂鸣器操作类 v0 2023/1/9 by 张城 */ class fsmpBeeper:public QObject{ Q_OBJECT public: explicit fsmpBeeper(const char *device = "/dev/input/event0", QObject *parent = nullptr) :QObject(parent) { event.type = EV_SND; time.tv_sec = 1; time.tv_usec = 0; event.time = time; beeper_fd = ::open(device,O_RDWR); if(beeper_fd < 0) { perror("open_beeper"); return; } }; ~fsmpBeeper() { ::close(beeper_fd); } /* * Description: 设置频率值 * input: rate 频率 * output: null * return: 成功true/失败false */ bool setRate(uint32_t rate = 1000) { if(rate > 0) { event.code = SND_TONE; event.value = rate; return true; } return false; } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ bool start(void) { int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool stop(void) { struct input_event event; event.type = EV_SND; event.code = SND_BELL; event.value = 0000; time.tv_sec = 1; time.tv_usec = 0; event.time = time; int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } private: int beeper_fd; //设备文件描述符 struct input_event event; struct timeval time; }; #endif // FSMPBEEPER_H ------------------------------------------------------- fsmpElectric.h: #ifndef ELC_H #define ELC_H /*************************************************************************** * * 类名:fsmpElectric * 功能说明:扩展板 电气信息检测 * 公有函数: * fsmpElectric() * float voltagemV(void) 获取电压mv(旋钮控制) * float currentmA(void) 获取电流ma(板载设备真实电流) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpElectric:public QObject{ Q_OBJECT public: explicit fsmpElectric(QObject *parent = nullptr) :QObject(parent) { } ~fsmpElectric(){ } float voltagemV(void) { electric_fd1 = open("/sys/bus/iio/devices/iio:device3/in_voltage1_raw",O_RDONLY|O_NONBLOCK); if(electric_fd1 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd1,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd1); return (float)3300 * val / 65536; } float currentmA(void) { electric_fd0 = open("/sys/bus/iio/devices/iio:device3/in_voltage0_raw",O_RDONLY|O_NONBLOCK); if(electric_fd0 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd0,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd0); return ((((float)3300 * val) /65536)/(10 + 100*1000 + 1000)) * 1000 / 0.1; } private: int electric_fd0; //设备文件描述符 int electric_fd1; //设备文件描述符 }; #endif // ELC_H ------------------------------------------------------- fsmpEvents.h: #ifndef ENV_H #define ENV_H /*************************************************************************** * * 类名:fsmpEvents * 功能说明:扩展板 按钮、人体红外、光闸管、火焰 * 公有函数: * fsmpEvents() * 信号: * void lightTriggered(); 光闸管阻隔 * void flameDetected(); 火焰检测 * void peopleDetected(bool); 人体红外发现true/离开false * void keyPressed(int keynum); 按键按下 keynum: 1、2、3 * void keyRelessed(int keynum); 按键释放 keynum: 1、2、3 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QTimer> #include #include <sys/ioctl.h> #include <QDebug> #include <QProcess> #include <QThread> #include <stdio.h> #include <stdlib.h> class fsmpEvents:public QObject{ Q_OBJECT signals: /* edge trigle !!!*/ void lightTriggered();//光电开关 void flameDetected();//火焰检测 void peopleDetected(bool);//人体红外 void keyPressed(int keynum); void keyRelessed(int keynum); public: explicit fsmpEvents(QObject *parent = nullptr):QObject(parent) { this->gpio_F_open(); this->gpio_E_open(); fs_timer = new QTimer(this); connect(fs_timer,SIGNAL(timeout()),this,SLOT(time_out())); fs_timer->start(10); }; private: bool gpio_F_open(const char *device = "/dev/gpiochip5") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 9; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE|GPIOEVENT_REQUEST_RISING_EDGE; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_1_fd = event_req.fd; int flags = fcntl(key_1_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_1_fd,F_SETFL,flags); event_req.lineoffset = 8; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_3_fd = event_req.fd; flags = fcntl(key_3_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_3_fd,F_SETFL,flags); #if 0 event_req.lineoffset = 5; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } fire_fd = event_req.fd; flags = fcntl(fire_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(fire_fd,F_SETFL,flags); #endif // fire req.lineoffsets[0] = 5; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "fire"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } fire_fd = req.fd; // key2 req.lineoffsets[0] = 7; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } key_2_fd = req.fd; // people req.lineoffsets[0] = 12; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } people_fd = req.fd; return true; } bool gpio_E_open(const char *device = "/dev/gpiochip4") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 15; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } light_trigger_fd = event_req.fd; int flags = fcntl(light_trigger_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(light_trigger_fd,F_SETFL,flags); return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool close(void); public slots: void time_out() { static int key_1_flag = 0; static int key_2_flag = 0; static int key_3_flag = 0; static int light_trigger_flag = 0; static int people_flag = 0; static int flame_flag = 0; //捕获key_1按下 read(key_1_fd,&event_data,sizeof (event_data)); if(event_data.id == 2) { key_1_flag = 1; emit(this->keyPressed(1)); //qDebug()<<"key_1 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_1_flag==1) { key_1_flag = 0; emit keyRelessed(1); //qDebug()<<"key_1 relessed"; } event_data.id = 0; //捕获key_2按下 int ret = ioctl(key_2_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << "==========" << data.values[0]; if(data.values[0] ==0&&key_2_flag==0) { emit(this->keyPressed(2)); key_2_flag = 1; //qDebug()<<"key_2 pressed"; } else if(data.values[0] ==1&&key_2_flag==1) { key_2_flag = 0; emit keyRelessed(2); //qDebug()<<"key_2 relessed"; } //event_data.id = 0; //捕获key_3按下 read(key_3_fd,&event_data,sizeof (event_data)); //qDebug() << "key3 "<< event_data.id; if(event_data.id == 2 && key_3_flag==0) { key_3_flag = 1; emit(this->keyPressed(3)); //qDebug()<<"key_3 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_3_flag==1) { key_3_flag = 0; emit keyRelessed(3); //qDebug()<<"key_3 relessed"; } event_data.id = 0; //捕获光电开关 read(light_trigger_fd,&event_data,sizeof (event_data)); if(event_data.id == 1 && light_trigger_flag==0) { //qDebug()<<"light triggered"; light_trigger_flag = 1; emit(this->lightTriggered()); } else light_trigger_flag = 0; event_data.id = 0; //捕获people coming ret = ioctl(people_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } if(data.values[0] ==1&&people_flag==0) { emit(this->peopleDetected(true)); people_flag = 1; //qDebug()<<"people coming"; } else if(data.values[0] ==0&&people_flag==1) { people_flag = 0; emit(this->peopleDetected(false)); //qDebug()<<"people leave"; } #if 0 //捕获火焰检测 read(fire_fd,&event_data,sizeof (event_data)); qDebug() << "------------------"<<event_data.id; if(event_data.id == 2 && flame_flag == 0) { qDebug()<<"flamedetection on"; flame_flag = 1; emit(this->flameDetected(true)); event_data.id = 0; } else if(event_data.id == 0 && flame_flag == 1) { qDebug()<<"flamedetection off"; flame_flag = 0; emit(this->flameDetected(false)); event_data.id = 0; } #endif //捕获key_2按下 ret = ioctl(fire_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << data.values[0]; if(data.values[0] ==1&&flame_flag==0) { emit(this->flameDetected()); flame_flag = 1; //qDebug()<<"flame on"; } else flame_flag = 0; } private: struct gpiohandle_request req; struct gpiohandle_data data; struct gpiochip_info chip_info; struct gpioevent_request event_req; struct gpioevent_data event_data; struct gpiod_chip *gpiochip5; struct gpiod_line *gpioline5_7; int key_1_fd; //设备文件描述符 int key_2_fd; int key_3_fd; int light_trigger_fd; int people_fd; int fire_fd; QTimer * fs_timer; }; #endif //ENV_H ------------------------------------------------------- fsmpFan.h: #ifndef FAN_H #define FAN_H /*************************************************************************** * * 类名:fsmpFan * 功能说明:扩展板 风扇控制 * 公有函数: * fsmpFan() * void start(void) 开启风扇) * void stop(void) 关闭风扇 * void setSpeed(int speed) 设置风扇速度(0-255) * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpFan:public QObject{ Q_OBJECT public: explicit fsmpFan(QObject *parent = nullptr):QObject(parent) { const char *device = "/sys/class/hwmon/hwmon1/pwm1"; fan_fd = ::open(device,O_WRONLY|O_TRUNC); if(fan_fd < 0) { perror("open fan"); return; } fan_speed = 0; }; ~fsmpFan(){ ::close(fan_fd); } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ void stop(void) { write(fan_fd,"0",strlen("0")); } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ void start(void) { char speedstr[100] = {0}; sprintf(speedstr, "%d", fan_speed); write(fan_fd, speedstr, strlen(speedstr)); } /* * Description: 控制风扇转速 * intput: speed 转速 * output: null * return: null */ void setSpeed(int speed) { fan_speed = speed%255; } private: int fan_fd; //设备文件描述符 int fan_speed; }; #endif // FAN_H ------------------------------------------------------- fsmpLeds.h: #ifndef LED_H #define LED_H /*************************************************************************** * * 类名:fsmpLeds * 功能说明:扩展板 3颗灯泡 * 公有函数: * fsmpLeds() * bool on(lednum x) 开灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * bool off(lednum x) 关灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpLeds:public QObject{ Q_OBJECT public: enum lednum{ LED1, LED2, LED3 }; explicit fsmpLeds(QObject *parent = nullptr) :QObject(parent) { led_fd1 = ::open("/sys/class/leds/led1/brightness",O_WRONLY|O_TRUNC); if(led_fd1 < 0) { perror("open led1"); return ; } led_fd2 = ::open("/sys/class/leds/led2/brightness",O_WRONLY|O_TRUNC); if(led_fd2 < 0) { perror("open led2"); return ; } led_fd3 = ::open("/sys/class/leds/led3/brightness",O_WRONLY|O_TRUNC); if(led_fd3 < 0) { perror("open led3"); return ; } } ~fsmpLeds() { ::close(led_fd1); ::close(led_fd2); ::close(led_fd3); } /* * Description: 开启设备,默认/sys/class/leds/led1/brightness * input: lednum * output: null * return: 成功true/失败false */ bool on(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"1",1); if(ret < 0) { return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool off(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"0",1); if(ret < 0) { return false; } return true; } private: int led_fd1; //设备文件描述符 int led_fd2; //设备文件描述符 int led_fd3; //设备文件描述符 }; #endif // LED_H ------------------------------------------------------- fsmpLight.h: #ifndef LIGHT_H #define LIGHT_H /*************************************************************************** * * 类名:fsmpLight * 功能说明:扩展板 光照强度检测 * 公有函数: * fsmpLight() * double getValue(void) 获取光照强度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpLight:public QObject{ Q_OBJECT public: explicit fsmpLight(QObject *parent = nullptr) :QObject(parent) { light_fd = ::open("/sys/bus/iio/devices/iio:device1/in_illuminance_input",O_RDONLY|O_NONBLOCK); if(light_fd < 0) { perror("open"); return; } } ~fsmpLight() { ::close(light_fd); } /* * Description: 获取光照强度 * input: null * output: null * return: current light */ double getValue(void) { char buf[10] = {0}; int ret = read(light_fd,buf,10); if(ret < 0) { perror("read"); return false; } double num; sscanf(buf, "%lf", &num); lseek(light_fd, 0, SEEK_SET); return num; } private: int light_fd; //设备文件描述符 }; #endif // LIGHT_H ------------------------------------------------------- fsmpProximity.h: #ifndef FSMPPROXIMITY_H #define FSMPPROXIMITY_H /*************************************************************************** * * 类名:fsmpProximity * 功能说明:扩展板 红外接近传感器(和光照传感器一起) * 公有函数: * fsmpProximity() * double getValue(void) 获取接近情况(0-2048越接近数据越大) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpProximity:public QObject{ Q_OBJECT public: explicit fsmpProximity(QObject *parent = nullptr) :QObject(parent) { proximity_fd = ::open("/sys/bus/iio/devices/iio:device1/in_proximity_raw",O_RDONLY|O_NONBLOCK); if(proximity_fd < 0) { perror("open"); return; } } ~fsmpProximity() { ::close(proximity_fd); } /* * Description: 获取distence * input: null * output: null * return: current light */ int getValue(void) { char buf[10] = {0}; int ret = read(proximity_fd,buf,10); if(ret < 0) { perror("read"); return false; } int num; sscanf(buf, "%d", &num); lseek(proximity_fd, 0, SEEK_SET); return num; } private: int proximity_fd; //设备文件描述符 }; #endif // FSMPPROXIMITY_H ------------------------------------------------------- fsmpSevensegLed.h: #ifndef FSMPSEVENSEGLED_H #define FSMPSEVENSEGLED_H /*************************************************************************** * * 类名:fsmpSevensegLed * 功能说明:扩展板 七段数码管 * 公有函数: * fsmpSevensegLed() * void display(int value) 显示4位以内整数 * void display(const char *str) 显示4位字符,注:仅支持 a、b、c、d、e * * 信号: * 无 * * *************************************************************************/ #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include #include #include <QThread> #include <stdlib.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) class fsmpSevensegLed:public QThread{ Q_OBJECT public: explicit fsmpSevensegLed(QObject *parent = nullptr) :QThread(parent) { memset(data, 0, sizeof(data)); device = "/dev/spidev0.0"; bits = 8; speed = 400000; delay = 0; } void display(int value) { data[3] = value%10; data[2] = value/10%10; data[1] = value/100%10; data[0] = value/1000%10; } //"abcde" void display(const char *str) { data[3] = (strlen(str)-1 >= 0)?(str[strlen(str)-1] - 'a')+10:0; data[2] = (strlen(str)-2 >= 0)?(str[strlen(str)-2] - 'a')+10:0; data[1] = (strlen(str)-3 >= 0)?(str[strlen(str)-3] - 'a')+10:0; data[0] = (strlen(str)-4 >= 0)?(str[strlen(str)-4] - 'a')+10:0; } private: void run() { int ret = 0; int fd; fd = open(device, O_RDWR); //打开设备文件 if (fd < 0) pabort("can't open device"); /* * spi mode //设置spi设备模式 */ ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); //写模式 if (ret == -1) pabort("can't set spi mode"); /* * bits per word //设置每个字含多少位 */ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); //写每个字含多少位 if (ret == -1) pabort("can't set bits per word"); /* * max speed hz //设置速率 */ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); //写速率 if (ret == -1) pabort("can't set max speed hz"); //打印模式,每字多少位和速率信息 printf("spi mode: %d\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); //transfer(fd); //传输测试 int i = 0; int pos = 0; unsigned char buf[2]; while(1) { pos = 1 << (i % 4); buf[0] = pos; buf[1] = num[data[i]]; if (write(fd, buf, 2) < 0) perror("write"); i++; if (i == 4) { i = 0; } usleep(3500); } } static void pabort(const char *s) { perror(s); abort(); } const char *device; uint8_t mode; uint8_t bits; uint32_t speed; uint16_t delay; int data[4]; unsigned char num[20] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; }; #endif // FSMPSEVENSEGLED_H ------------------------------------------------------- fsmpTempHum.h: #ifndef TEMPHUM_H #define TEMPHUM_H /*************************************************************************** * * 类名:fsmpTempHum * 功能说明:扩展板 温度湿度 * 公有函数: * fsmpTempHum() * double temperature(void) 提取温度 * double humidity(void) 提取湿度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpTempHum:public QObject{ Q_OBJECT public: explicit fsmpTempHum(QObject *parent = nullptr) :QObject(parent) { } double temperature(void) { int temp_raw = 0; int temp_offset = 0; float temp_scale = 0; open_device_int("iio:device0","in_temp_raw",&temp_raw); open_device_int("iio:device0","in_temp_offset",&temp_offset); open_device_float("iio:device0","in_temp_scale",&temp_scale); return (temp_raw + temp_offset) * temp_scale / 1000; } double humidity(void) { int hum_raw = 0; int hum_offset = 0; float hum_scale = 0; open_device_int("iio:device0","in_humidityrelative_raw",&hum_raw); open_device_int("iio:device0","in_humidityrelative_offset",&hum_offset); open_device_float("iio:device0","in_humidityrelative_scale",&hum_scale); return (hum_raw + hum_offset) * hum_scale / 1000; } private: bool open_device_int(const char *device, const char *filename, int *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%d",val); ::close(fd); return true; } bool open_device_float(const char *device, const char *filename, float *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%f",val); ::close(fd); return true; } private: int temp_hum_fd;; //设备文件描述符 }; #endif // TEMPHUM_H ------------------------------------------------------- fsmpVibrator.h: #ifndef VIBRATOR_H #define VIBRATOR_H /*************************************************************************** * * 类名:fsmpVibrator * 功能说明:扩展板 振动马达 * 公有函数: * fsmpVibrator() * bool setParameter(int strong_magnitude, int timems) 设置振动强度(0-0xffff)及时长(ms) * bool start(void) 启动马达 * bool stop(void) 停止马达 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <sys/ioctl.h> #include <QDebug> class fsmpVibrator:public QObject{ Q_OBJECT public: explicit fsmpVibrator(QObject *parent = nullptr) :QObject(parent) { vibrator_fd = ::open("/dev/input/event1", O_RDWR|O_NONBLOCK); if(vibrator_fd < 0) { perror("open vibrator"); } } ~fsmpVibrator() { ::close(vibrator_fd); } /* * Description:设置 * input:频率 * output:null * return:成功true/失败false */ bool setParameter(int strong_magnitude = 0xFFFF, int timems = 5000) { //qDebug()<<strong_magnitude<<timems; effect.type = FF_RUMBLE, effect.id = -1, effect.u.rumble.strong_magnitude = strong_magnitude; effect.u.rumble.weak_magnitude = 0; effect.replay.length = timems; effect.replay.delay = 0; if (ioctl(vibrator_fd, EVIOCSFF, &effect) < 0) { printf("Error creating new effect: %s\n", strerror(errno)); return false; } return true; } bool start(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 1 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator on"); return false; } //qDebug()<<"start"; return true; } bool stop(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 0 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator off"); return false; } //qDebug()<<"stop"; return true; } private: int vibrator_fd;//设备文件描述符 struct ff_effect effect; }; #endif // VIBRATOR_H ------------------------------------------------------- 项目目的: 在Linux下通过qtcreator编写后通过st-mp1构建部署到远程Linux主机后,在Stm32mp157开发板上能够控制本身的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。并且通过Desktop Qt5.12.12 GCC64bit构建部署到Deploy Configuration时,能够控制Stm32mp157开发板上的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。 设计要求: 1. 通过点击pb_connect(连接按钮)按钮可以连接到云端mqtt,连接成功则弹出小窗提示连接成功并自动绑定订阅与发布功能、连接失败则弹出小窗提示连接失败,弹出的小窗有一个确定键,点击确定关闭小窗。 2. 点击按钮pb_led0打开Stm32mp157开发板上的LD1灯且同步打开华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(初始化为led0_on)变更为led0_off。再次点击按钮pb_led0时关闭Stm32mp157开发板上的LD1灯且同步关闭华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(此时为led0_off)变更为led0_on。按钮pb_led1和pb_led2也是相同理论。 3. 点击按钮pb_feng打开Stm32mp157开发板上的风扇且同步打开华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(初始化为feng_on)变更为feng_off。再次点击按钮pb_feng时关闭Stm32mp157开发板上的风扇且同步关闭华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(此时为feng_off)变更为feng_on。 4. 点击按钮pb_buzzer打开Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(初始化为:蜂鸣器_on)变更为蜂鸣器_off。再次点击按钮pb_buzzer时关闭Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(此时为:蜂鸣器_off)变更为蜂鸣器_on。 5. 点击按钮pb_humiture时,打开Stm32mp157开发板上的温湿度传感器并将数据显示在textBrowser组件上。此时按钮pb_humiture上的文本(初始化为:温湿度_on)变更为温湿度_off。再次点击按钮pb_humiture时关闭Stm32mp157开发板上的温湿度传感器,此时按钮pb_humiture上的文本(此时为:温湿度_off)变更为温湿度_on。(需添加功能:打开Stm32mp157开发板上的温湿度传感器后,当温度超过30度时蜂鸣器会立即开启,低于30度或者直接点击按钮pb_buzzer都可关闭蜂鸣器) 6. 点击按钮pb_photosensitive时,打开Stm32mp157开发板上的光敏传感器并将数据显示在textBrowser组件上。此时按钮pb_photosensitive上的文本(初始化为:光敏_on)变更为光敏_off。再次点击按钮pb_photosensitive时关闭Stm32mp157开发板上的光敏传感器,此时按钮pb_photosensitive上的文本(此时为:光敏_off)变更为光敏_on。 7. 点击按钮pb_infrared时,打开Stm32mp157开发板上的人体红外传感器并将数据显示在textBrowser组件上。此时按钮pb_infrared上的文本(初始化为:人体红外_on)变更为人体红外_off。再次点击按钮pb_infrared时关闭Stm32mp157开发板上的人体红外传感器,此时按钮pb_infrared上的文本(此时为:人体红外_off)变更为人体红外_on。 8. 点击按钮pb_camera时打开Stm32mp157开发板上的摄像头并将采集到的图像在屏幕界面的右侧显示出来(目前项目中没有设计用于显示摄像头采集图像显示的组件,需要添加)。此时按钮pb_camera上的文本(初始化为:摄像头_on)变更为摄像头off。再次点击按钮pb_camera时关闭Stm32mp157开发板上的摄像头,此时按钮pb_camera上的文本(此时为:摄像头_off)摄像头_on,并关闭摄像头采集的图像显示界面。 结合以上代码及要求,进行完整详细的项目开发,如有需要可以添加项目结构内缺失的文件(项目结构内缺失硬件的.cpp文件),硬件.h文件不可进行修改。整合后将项目的所有文件发我,让我复制粘贴就能直接使用

NODES / joint_state_publisher (joint_state_publisher/joint_state_publisher) move_group (moveit_ros_move_group/move_group) robot_state_publisher (robot_state_publisher/robot_state_publisher) rviz_ubuntu_2861_4993542575836972810 (rviz/rviz) auto-starting new master process[master]: started with pid [2872] ROS_MASTER_URI=http://localhost:11311 setting /run_id to 1966f85e-0efb-11f0-850d-000c29c69146 process[rosout-1]: started with pid [2883] started core service [/rosout] process[joint_state_publisher-2]: started with pid [2886] process[robot_state_publisher-3]: started with pid [2891] ERROR: cannot launch node of type [moveit_ros_move_group/move_group]: moveit_ros_move_group ROS path [0]=/opt/ros/melodic/share/ros ROS path [1]=/home/fcy/catkin_ws/src ROS path [2]=/opt/ros/melodic/share process[rviz_ubuntu_2861_4993542575836972810-5]: started with pid [2892] [ INFO] [1743513208.619101648]: rviz version 1.13.30 [ INFO] [1743513208.619277497]: compiled against Qt version 5.9.5 [ INFO] [1743513208.619412670]: compiled against OGRE version 1.9.0 (Ghadamon) [ INFO] [1743513208.623547025]: Forcing OpenGl version 0. [ INFO] [1743513208.875174005]: Stereo is NOT SUPPORTED [ INFO] [1743513208.875654555]: OpenGL device: llvmpipe (LLVM 10.0.0, 256 bits) [ INFO] [1743513208.875857719]: OpenGl version: 3.1 (GLSL 1.4). [ERROR] [1743513209.002316614]: PluginlibFactory: The plugin for class 'moveit_rviz_plugin/MotionPlanning' failed to load. Error: According to the loaded plugin descriptions the class moveit_rviz_plugin/MotionPlanning with base class type rviz::Display does not exist. Declared types are rviz/Axes rviz/Camera rviz/DepthCloud rviz/Effort rviz/FluidPressure rviz/Grid rviz/GridCells rviz/Illuminance rviz/Image rviz/InteractiveMarkers rviz/LaserScan rviz/Map rviz/Marker rviz/MarkerArray rviz/Odometry rviz/Path rviz/PointCloud rviz/PointCloud2 rviz/PointStamped rviz/Polygon rviz/Pose rviz/PoseArray rviz/PoseWithCovariance rviz/Range rviz/RelativeHumidity rviz/RobotModel rviz/TF rviz/Temperature rviz/WrenchStamped rviz_plugin_tutorials/Imu

最新推荐

recommend-type

AI 驱动 CI_CD:从部署工具到智能代理.doc

AI 驱动 CI_CD:从部署工具到智能代理.doc
recommend-type

基于Python豆瓣电影数据可视化分析设计与实现 的论文

基于Python豆瓣电影数据可视化分析设计与实现 的论文
recommend-type

Python程序TXLWizard生成TXL文件及转换工具介绍

### 知识点详细说明: #### 1. 图形旋转与TXL向导 图形旋转是图形学领域的一个基本操作,用于改变图形的方向。在本上下文中,TXL向导(TXLWizard)是由Esteban Marin编写的Python程序,它实现了特定的图形旋转功能,主要用于电子束光刻掩模的生成。光刻掩模是半导体制造过程中非常关键的一个环节,它确定了在硅片上沉积材料的精确位置。TXL向导通过生成特定格式的TXL文件来辅助这一过程。 #### 2. TXL文件格式与用途 TXL文件格式是一种基于文本的文件格式,它设计得易于使用,并且可以通过各种脚本语言如Python和Matlab生成。这种格式通常用于电子束光刻中,因为它的文本形式使得它可以通过编程快速创建复杂的掩模设计。TXL文件格式支持引用对象和复制对象数组(如SREF和AREF),这些特性可以用于优化电子束光刻设备的性能。 #### 3. TXLWizard的特性与优势 - **结构化的Python脚本:** TXLWizard 使用结构良好的脚本来创建遮罩,这有助于开发者创建清晰、易于维护的代码。 - **灵活的Python脚本:** 作为Python程序,TXLWizard 可以利用Python语言的灵活性和强大的库集合来编写复杂的掩模生成逻辑。 - **可读性和可重用性:** 生成的掩码代码易于阅读,开发者可以轻松地重用和修改以适应不同的需求。 - **自动标签生成:** TXLWizard 还包括自动为图形对象生成标签的功能,这在管理复杂图形时非常有用。 #### 4. TXL转换器的功能 - **查看.TXL文件:** TXL转换器(TXLConverter)允许用户将TXL文件转换成HTML或SVG格式,这样用户就可以使用任何现代浏览器或矢量图形应用程序来查看文件。 - **缩放和平移:** 转换后的文件支持缩放和平移功能,这使得用户在图形界面中更容易查看细节和整体结构。 - **快速转换:** TXL转换器还提供快速的文件转换功能,以实现有效的蒙版开发工作流程。 #### 5. 应用场景与技术参考 TXLWizard的应用场景主要集中在电子束光刻技术中,特别是用于设计和制作半导体器件时所需的掩模。TXLWizard作为一个向导,不仅提供了生成TXL文件的基础框架,还提供了一种方式来优化掩模设计,提高光刻过程的效率和精度。对于需要进行光刻掩模设计的工程师和研究人员来说,TXLWizard提供了一种有效的方法来实现他们的设计目标。 #### 6. 系统开源特性 标签“系统开源”表明TXLWizard遵循开放源代码的原则,这意味着源代码对所有人开放,允许用户自由地查看、修改和分发软件。开源项目通常拥有活跃的社区,社区成员可以合作改进软件,添加新功能,或帮助解决遇到的问题。这种开放性促进了技术创新,并允许用户根据自己的需求定制软件。 #### 7. 压缩包子文件的文件名称列表 文件名称列表中的“txlwizard-master”可能指的是TXLWizard项目的主版本库或主分支。这个名称表明了这是项目源代码的中心点,其他开发者会从这个主分支拉取代码进行合作开发或部署。以“-master”结尾通常是版本控制系统中表示主要开发线路的常见约定,例如Git中的master(现在更常被称为main)分支。 通过这些知识点的详细解释,我们可以看到TXLWizard不仅是一个用于生成TXL文件的工具,它还整合了一系列的功能,使得电子束光刻掩模的设计工作更为高效和直观。同时,作为一个开源项目,它能够借助社区的力量不断进步,为用户带来更多的便利和创新。
recommend-type

【创新图生成:扣子平台的技术前沿与创新思维】:引领图像生成技术的新潮流

# 1. 扣子平台的图像生成技术概述 在当今数字化时代,图像生成技术正成为推动技术创新和社会变革的关键力量。扣子平台正是这一技术革新的代表。本章将对扣子平台的图像生成技术进行一个全面概述,探究它如何将理论技术转化为实际应用,并带来显著的社会影响。 扣子平台运用了先进的图像生成技术,将现实世界和数字空间无缝融合,打造了沉浸式的视觉体验。其技术的核心是通过高度复杂的算法模型,快速生成高质
recommend-type

海康威视机器视觉工程师考核

<think>好的,我现在需要帮助用户了解海康威视机器视觉工程师的考核内容和要求。根据用户提供的引用资料,特别是引用[1]和[2],里面提到了考核素材包分为初级和中级,涵盖理论、算法、应用案例等。首先,我要整理这些信息,确保结构清晰,符合用户要求的格式。 接下来,我需要确认素材包的具体内容,比如初级和中级的不同点。引用[2]提到初级包含基础理论、算法实现和实际案例,中级则增加复杂算法和项目分析。这部分需要分点说明,方便用户理解层次。 另外,用户可能想知道如何准备考核,比如下载素材、学习顺序、模拟考核等,引用[2]中有使用说明和注意事项,这部分也要涵盖进去。同时要注意提醒用户考核窗口已关闭,
recommend-type

Linux环境下Docker Hub公共容器映像检测工具集

在给出的知识点中,我们需要详细解释有关Docker Hub、公共容器映像、容器编排器以及如何与这些工具交互的详细信息。同时,我们会涵盖Linux系统下的相关操作和工具使用,以及如何在ECS和Kubernetes等容器编排工具中运用这些检测工具。 ### Docker Hub 和公共容器映像 Docker Hub是Docker公司提供的一项服务,它允许用户存储、管理以及分享Docker镜像。Docker镜像可以视为应用程序或服务的“快照”,包含了运行特定软件所需的所有必要文件和配置。公共容器映像指的是那些被标记为公开可见的Docker镜像,任何用户都可以拉取并使用这些镜像。 ### 静态和动态标识工具 静态和动态标识工具在Docker Hub上用于识别和分析公共容器映像。静态标识通常指的是在不运行镜像的情况下分析镜像的元数据和内容,例如检查Dockerfile中的指令、环境变量、端口映射等。动态标识则需要在容器运行时对容器的行为和性能进行监控和分析,如资源使用率、网络通信等。 ### 容器编排器与Docker映像 容器编排器是用于自动化容器部署、管理和扩展的工具。在Docker环境中,容器编排器能够自动化地启动、停止以及管理容器的生命周期。常见的容器编排器包括ECS和Kubernetes。 - **ECS (Elastic Container Service)**:是由亚马逊提供的容器编排服务,支持Docker容器,并提供了一种简单的方式来运行、停止以及管理容器化应用程序。 - **Kubernetes**:是一个开源平台,用于自动化容器化应用程序的部署、扩展和操作。它已经成为容器编排领域的事实标准。 ### 如何使用静态和动态标识工具 要使用这些静态和动态标识工具,首先需要获取并安装它们。从给定信息中了解到,可以通过克隆仓库或下载压缩包并解压到本地系统中。之后,根据需要针对不同的容器编排环境(如Dockerfile、ECS、Kubernetes)编写配置,以集成和使用这些检测工具。 ### Dockerfile中的工具使用 在Dockerfile中使用工具意味着将检测工具的指令嵌入到构建过程中。这可能包括安装检测工具的命令、运行容器扫描的步骤,以及将扫描结果集成到镜像构建流程中,确保只有通过安全和合规检查的容器镜像才能被构建和部署。 ### ECS与Kubernetes中的工具集成 在ECS或Kubernetes环境中,工具的集成可能涉及到创建特定的配置文件、定义服务和部署策略,以及编写脚本或控制器来自动执行检测任务。这样可以在容器编排的过程中实现实时监控,确保容器编排器只使用符合预期的、安全的容器镜像。 ### Linux系统下的操作 在Linux系统下操作这些工具,用户可能需要具备一定的系统管理和配置能力。这包括使用Linux命令行工具、管理文件系统权限、配置网络以及安装和配置软件包等。 ### 总结 综上所述,Docker Hub上的静态和动态标识工具提供了一种方法来检测和分析公共容器映像,确保这些镜像的安全性和可靠性。这些工具在Linux开发环境中尤为重要,因为它们帮助开发人员和运维人员确保他们的容器映像满足安全要求。通过在Dockerfile、ECS和Kubernetes中正确使用这些工具,可以提高应用程序的安全性,减少由于使用不安全的容器镜像带来的风险。此外,掌握Linux系统下的操作技能,可以更好地管理和维护这些工具,确保它们能够有效地发挥作用。
recommend-type

【扣子平台图像艺术探究:理论与实践的完美结合】:深入学习图像生成的艺术

# 1. 图像艺术的理论基础 艺术领域的每一个流派和技巧都有其理论基础。在图像艺术中,理论基础不仅是对艺术表现形式的认知,也是掌握艺术创作内在逻辑的关键。深入理解图像艺术的理论基础,能够帮助艺术家们在创作过程中更加明确地表达自己的艺术意图,以及更好地与观众沟通。 图像艺术的理论
recommend-type

增广路定理的证明

<think>嗯,用户想查找增广路定理的证明,关于图论和网络流算法的。我得先理解增广路定理是什么,然后找到相关的证明方法。根据之前的引用,尤其是引用5提到最大流最小割定理,里面有三个等价条件,其中第二个是残余网络中没有增广路径时,流就是最大流。这可能和增广路定理相关,也就是当残余网络中没有增广路时,当前流就是最大流,这可能就是增广路定理的内容。 首先,我需要明确增广路定理的陈述。根据引用5,增广路定理可能指的是:一个流是最大流当且仅当残余网络中不存在增广路径。这个定理的证明需要用到最大流最小割定理,也就是第三个条件,即最大流的流量等于最小割的容量。 证明的步骤可能需要分为两个方向:必要性(
recommend-type

Pulse:基于SwiftUI的Apple平台高效日志记录与网络监控

从给定文件信息中,我们可以提取出以下IT知识点进行详细阐述: **Pulse概览:** Pulse是一个专门针对Apple平台(如iOS、iPadOS、macOS等)的功能强大的日志记录系统。其设计目的是为了简化开发者在这些平台上调试网络请求和应用日志的过程。Pulse的核心特色是它使用SwiftUI来构建,这有助于开发者利用现代Swift语言的声明式UI优势来快速开发和维护。 **SwiftUI框架:** SwiftUI是一种声明式框架,由苹果公司推出,用于构建用户界面。与传统的UIKit相比,SwiftUI使用更加简洁的代码来描述界面和界面元素,它允许开发者以声明的方式定义视图和界面布局。SwiftUI支持跨平台,这意味着同一套代码可以在不同的Apple设备上运行,大大提高了开发效率和复用性。Pulse选择使用SwiftUI构建,显示了其对现代化、高效率开发的支持。 **Network Inspector功能:** Pulse具备Network Inspector功能,这个功能使得开发者能够在开发iOS应用时,直接从应用内记录和检查网络请求和日志。这种内嵌式的网络诊断能力非常有助于快速定位网络请求中的问题,如不正确的URL、不返回预期响应等。与传统的需要外部工具来抓包和分析的方式相比,这样的内嵌式工具大大减少了调试的复杂性。 **日志记录和隐私保护:** Pulse强调日志是本地记录的,并保证不会离开设备。这种做法对隐私保护至关重要,尤其是考虑到当前数据保护法规如GDPR等的严格要求。因此,Pulse的设计在帮助开发者进行问题诊断的同时,也确保了用户数据的安全性。 **集成和框架支持:** Pulse不仅仅是一个工具,它更是一个框架。它能够记录来自URLSession的事件,这意味着它可以与任何使用URLSession进行网络通信的应用或框架配合使用,包括但不限于Apple官方的网络库。此外,Pulse与使用它的框架(例如Alamofire)也能够良好配合,Alamofire是一个流行的网络请求库,广泛应用于Swift开发中。Pulse提供了一个PulseUI视图组件,开发者可以将其集成到自己的应用中,从而展示网络请求和其他事件。 **跨平台体验:** 开发者不仅可以在iOS应用中使用Pulse Console记录日志,还可以在macOS上通过Pulse应用程序查看和共享这些日志。这种跨平台的能力意味着开发者可以在不同的设备上进行日志分析,增强了开发和调试的灵活性。 **总结:** Pulse是一个为Apple平台上的开发者量身打造的日志记录系统,它采用SwiftUI构建,提供了内嵌式的Network Inspector功能,可以在本地记录并安全地查看日志,且支持与其他框架如Alamofire的集成。它不仅提升了调试的便捷性和效率,同时也顾及到了用户的隐私保护。Pulse的跨平台查看能力也是其一大亮点,使得开发者能够在一个统一的环境中处理iOS和macOS上的日志数据。对于使用Swift开发Apple应用的开发者而言,Pulse无疑是一个强大的调试辅助工具。
recommend-type

【深入扣子平台:图像生成机制全揭秘】:掌握背后技术,提升图像生成效率

# 1. 图像生成技术概述 图像生成技术是一门融合了计算机视觉、机器学习、图形学等多个领域知识的前沿技术。它通过算法模拟生成人工图像,广泛应用于艺术创作、游戏设计、医学影像等领域。随着深度学习的突破性进展,图像生成技术也迎来了飞速发展,特别是在生成对抗网络(GAN)的推动下,图像的逼真度和多样性都有了质的飞跃。 本章将对图像生成技术的概念、发展历史进行简要介绍,并分析其在社会中的