SystemUI车载Hvac开发

架构概述

备注:以下分析基于Android 9.0

SystemUI 意即 系统界面,按照原生的职责划分,在车机上 SystemUI 更多是提供通用功能(与手机)的状态的展示,如状态栏对时间电量等的展示,导航栏对各功能页面提供跳转入口,仅此而已,至于其他的如 HVAC 等硬件相关的控制,都是交给对应的模块去做的.

HVAC是 Heating, Ventilation and Air Conditioning 的英文缩写,就是供热通风与空气调节, 而车机上对 HVAC 相关功能的控制是放到一个独立 apk - CarHvacApp 里面去做的,通过在 SystemUI 的导航栏中提供功能入口来实现跳转

如下,原生导航栏大部分的按钮均是其他功能模块的跳转入口,其中 HVAC 按钮的跳转页面是一个 HVAC 管理面板,该面板可设置诸如座椅温度,前后挡风玻璃除雾器的开关,主副驾的温度等

hvac_panel.png

但很多时候产商定制需要在导航栏直接提供对部分硬件相关功能的操作入口,如直接在导航栏操作座椅加热功能.而谷歌在开发的时候也已经对这种潜在的扩展提供了支持,即通过将硬件相关模块的操作封装成通用lib库,允许需要的应用直接进行导包引用

这些 lib 库封装了对底层 HAL模块(硬件抽象层模块) 的调用细节, 而底层的HAL模块则包含了对相应硬件的具体实现细节,下面看看其架构图

sysui_car_arch.png

一般的硬件开发流程是这样的:

  • 1 .在内核层开发硬件驱动程序
  • 2 .在硬件抽象层(HAL)开发对应的硬件抽象层模块
    • 2.1 说明: 硬件抽象层以模块的形式管理各个硬件访问接口,每一个硬件模块都对应有一个动态链接库文件,每一个hal模块在内核都对应有一个驱动程序,hal模块就是通过这些驱动程序来访问硬件设备的,它们是通过读写设备文件来进行通信
  • 3 .在framework层开发硬件访问服务
  • 4 .硬件上层访问者通过访问硬件访问服务进而间接操作硬件

对应上面的硬件开发流程,我们简述下该架构图,其中:

    1. 对于驱动层,暂未找到对应的驱动程序文件,先略过
    1. hardware/interfaces/automotive/vehicle/2.0/IVehicle.hal对应于硬件抽象层模块,对应实现在hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0下,其核心实现就是通过调用驱动接口函数open / read / write来实现设备文件的打开 / 读 / 写 从而实现与硬件设备的交互的。
    1. car-lib对应于硬件访问服务,其内部封装了对 HAL层的调用,例如对于HVAC硬件接口,car-lib对外提供了类CarHvacManager,而上层访问者均可通过该类对象直接查询/设置HVAC相关属性,下文展开介绍
    1. CarHvacApp 与 SystemUI 等应用对应于 硬件上层访问者,均通过访问硬件访问服务来实现与硬件的交互

了解了该架构之后,我们就可以知道,CarHvacApp / SystemUI 等应用其实就是对应于架构中的硬件上层访问者,我们的开发工作就是找到硬件对应的硬件访问服务,在用户操作我们的界面是将操作反馈给硬件访问服务即可,底层实现可以不关心

下面分别介绍:

  • 1.CarHvacApp 中与底层 Hvac 硬件的交互原理
  • 2.SystemUI 中与底层 Hvac 硬件的交互原理以及扩展实现

CarHvacApp 与硬件的交互

下面我们先来看看 CarHvacApp 这个应用是如何初始化 HVAC 面板 以及 在用户操作 HVAC 面板时,如何将用户操作结果反馈给底层硬件的

前面我们说到,谷歌将对 HVAC 相关功能的控制放到一个独立 apk - CarHvacApp 中,代码位于packags/apps/Car/Havc ,主体构成很简单,看下 manifest 文件

[packages/apps/Car/Hvac/AndroidManifest.xml]

    <application android:label="@string/hvac_label"
        android:icon="@drawable/ic_launcher_hvac"
        android:persistent="true">
        <service android:name=".HvacController"
            android:singleUser="true"
            android:exported="false" />

        <service android:name=".HvacUiService"
            android:singleUser="true"
            android:exported="false"/>

        <receiver android:name=".BootCompleteReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>
    </application>

仅由两个服务以及一个开机广播组成,其中开机广播负责在开机的时候启动服务HvacUiService

HvacUiService

[packages/apps/Car/Hvac/src/com/android/car/hvac/HvacUiService.java]
public class HvacUiService extends Service {}

该服务主要做了以下几件事:

  • 1.在layoutHvacUi()方法中完成HVAC面板的构建,该页面由五个窗口组成,窗口类型皆为WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY,会盖在sysui上面,分别是
    • 1.1 界面中间部分座椅加热,前后挡风除雾开关等元素构成的窗口,对应布局hvac_panel
    • 1.2 左边的主驾温度控制条窗口,对应布局hvac_temperature_bar_overlay,下同
    • 1.3 左边的主驾温度控制条收起(Collapsed)窗口,代码中通过配置config_showCollapsedBars字段来控制该窗口显示与否,默认为false,该窗口其实就是在控制面板收起时提供一个非完全收起的温度控制条以便调起控制面板
    • 1.4 右边的副驾温度控制条窗口
    • 1.5 右边的副驾温度控制条收起(Collapsed)窗口,同上

hvac_panel.png

  • 2.注册监听广播android.car.intent.action.TOGGLE_HVAC_CONTROLS,后续sysui会通过该广播来通知该服务做展开/收起HVAC面板
    @Override
    public void onCreate() { 
        ......
        IntentFilter filter = new IntentFilter();
        filter.addAction(CAR_INTENT_ACTION_TOGGLE_HVAC_CONTROLS);
        // Register receiver such that any user with climate control permission can call it.
        registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter,
                Car.PERMISSION_CONTROL_CAR_CLIMATE, null);
    }

  • 3.创建HvacPanelController对象,将以上构建的五个窗口对应的View传进去
    private void layoutHvacUi() {
        ......
        mHvacPanelController = new HvacPanelController(this /* context */, mContainer,
                mWindowManager, mDriverTemperatureBar, mPassengerTemperatureBar,
                mDriverTemperatureBarCollapsed, mPassengerTemperatureBarCollapsed
        );
        Intent bindIntent = new Intent(this /* context */, HvacController.class);
        if (!bindService(bindIntent, mServiceConnection, Context.BIND_AUTO_CREATE)) {
            Log.e(TAG, "Failed to connect to HvacController.");
        }
    }

  • 4.绑定服务HvacController,并在绑定成功时将服务对象HvacController给到HvacPanelController,这里可以看到,相对于sysui,HvacUiService是服务端,而相对于HvacUiService,HvacController才是服务端

HvacPanelController

[packages/apps/Car/Hvac/src/com/android/car/hvac/controllers/HvacPanelController.java]
public class HvacPanelController {}

该控制器是一个HVAC UI 布局元素状态机,负责整个 HVAC 面板UI元素的初始化,响应各布局元素的事件(用户点击 & 系统内部硬件属性变化)以及执行状态切换(如出现消失动画)

上文介绍HvacUiService时我们看到,HvacUiService在创建了各个窗口之后,将各窗口的View对象传了进来,而HvacPanelController则进一步对这些View对象做初始化,下面看看这个类的主要职责:

  • 1.在构造方法中取出各个子元素(findViewById),并设置其Icon资源
  • 2.前面说到,当HvacUiService成功绑定服务HvacController后,会将HvacController服务对象传进HvacPanelController,此时HvacPanelController会构造各类子元素View对应的控制器,去HvacController中获取各子元素的初始状态并设置给各子元素,以及设置各子元素的点击事件
public void updateHvacController(HvacController controller) {
        // 构造各类子元素View对应的控制器
        mFanSpeedBarController = new FanSpeedBarController(mFanSpeedBar, mHvacController);
        mSeatWarmerController = new SeatWarmerController(mPassengerSeatWarmer,
                mDriverSeatWarmer, mHvacController);
        ......
        // 初始化按钮状态,并设置点击事件
        mAcButton.setIsOn(mHvacController.getAcState());
        mAcButton.setToggleListener(new ToggleButton.ToggleListener() {
            @Override
            public void onToggled(boolean isOn) {
                mHvacController.setAcState(isOn);
            }
        });
        // 注册回调
        mHvacController.registerCallback(mToggleButtonCallbacks);
    }

  • 3.负责View的 show/hide 以及 动画的执行(transition),前面介绍HvacUiService时第2点我们说过,HvacUiService会去监听一个广播来展开/收起HVAC面板,相关逻辑如下,其中transitionState就是最终展开/收起面板的地方
[packages/apps/Car/Hvac/src/com/android/car/hvac/HvacUiService.java]
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(action.equals(CAR_INTENT_ACTION_TOGGLE_HVAC_CONTROLS)){
                mHvacPanelController.toggleHvacUi();
            }
        }
    };

[packages/apps/Car/Hvac/src/com/android/car/hvac/controllers/HvacPanelController.java]
    public void toggleHvacUi() {
        if(mCurrentState != STATE_COLLAPSED) {
            mCollapseHvac.onClick(null);
        } else {
            mExpandHvac.onClick(null);
        }
    }

    public View.OnClickListener mExpandHvac = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
             if (mInAnimation) {
                return;
            }
            if (mCurrentState != STATE_FULL_EXPANDED) {
                transitionState(mCurrentState, STATE_FULL_EXPANDED);
            }
        }
    };

car-lib库

前面介绍架构时我们说过,car-lib对应于硬件访问服务,其内部封装了对 HAL层的调用,例如对于HVAC硬件接口,car-lib对外提供了类CarHvacManager,而上层访问者均可通过该类对象直接查询/设置HVAC相关属性

介绍HvacController之前我们先来看看car-lib库下的两个关键类

[packages/services/Car/car-lib/src/android/car/Car.java]
// 源码对该类的说明:针对Android车载开发的顶级car API
public final class Car {
    // 1.外界获取硬件访问服务的入口
    public static Car createCar(Context context, ServiceConnection serviceConnectionListener,@Nullable Handler handler) {
          return new Car(context, serviceConnectionListener, handler);
    }
    // 2.缓存起来的 mServiceConnectionListenerClient 后面会用到
    private Car(Context context, ServiceConnection serviceConnectionListener,@Nullable Handler handler) {
        mServiceConnectionListenerClient = serviceConnectionListener;
    }
    // 3.调用该函数时会触发 startCarService 去创建 CarService服务
    public void connect() throws IllegalStateException {
            startCarService();
    }

    private void startCarService() {
        // 4.intent 指向了CarService服务,该服务真正的实现在ICarImpl中,这里不展开
        boolean bound = mContext.bindServiceAsUser(intent, mServiceConnectionListener,Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF);
    }

    private final ServiceConnection mServiceConnectionListener = new ServiceConnection () {
        public void onServiceConnected(ComponentName name, IBinder service) {
            synchronized (Car.this) {
                mService = ICar.Stub.asInterface(service);
                mConnectionState = STATE_CONNECTED;
            }
            // 5.连接成功时通知 mServiceConnectionListenerClient, 即前面createCar时传进来的服务连接监听器,
           // 进而上层访问者可以开始获取诸如 CarHvacManager 等对象
            mServiceConnectionListenerClient.onServiceConnected(name, service);
        }
    };
}

上面第5点中连接CarService成功时会通知调用者,意在告诉调用者你可以获取诸如 CarHvacManager 等对象了,因为诸如CarHvacManager 等对象的获取需要依赖到 CarService.

同时Car类中不仅可以获取CarHvacManager对象,还可以获取Android Car开发相关的各种管理类,如CarAudioManager,CarSensorManager等,详见其createCarManager函数

整个Car主要的功能就是

  • 1.作为外界获取硬件访问服务的入口,上层调用者可通过createCar来获取一个Car对象
  • 2.当调用者调用其connect函数时去连接CarService服务,这个服务是连接车载底层模块的桥梁,并在连接成功时通知调用者(通过ServiceConnection)
  • 3.提供入口供开发者获取所需的Manager,比如HVAC模块中所需的CarHvacManager,这是调用者后续操作相关硬件属性的入口

下面看看CarHvacManager的功能

CarHvacManager使用了一个数据结构,这是一个可跨进程传输的数据结构,封装了车辆相关的属性
[packages/services/Car/car-lib/src/android/car/hardware/CarPropertyValue.java]
public class CarPropertyValue<T> implements Parcelable {
    private final int mPropertyId;
    private final int mAreaId;
    private final int mStatus;
    private final long mTimestamp;
    private final T mValue;
}


[packages/services/Car/car-lib/src/android/car/hardware/hvac/CarHvacManager.java]
// 源码对该类的说明:用于控制HVAC系统的API
public final class CarHvacManager implements CarManagerBase {
    // 步骤1 : 定义了一系列常量,用来对应车辆各个区域(zone)的属性
    // 空调温度
    public static final int ID_ZONED_TEMP_SETPOINT = 0x15600503;
    // 座椅温度,负值制冷,正值制热,
    public static final int ID_ZONED_SEAT_TEMP = 0x1540050b;
    // 镜子除雾器,布尔值
    public static final int ID_MIRROR_DEFROSTER_ON = 0x1440050c;
    // 窗口除雾器,布尔值
    public static final int ID_WINDOW_DEFROSTER_ON = 0x13200504;
    
    // 步骤2 : 回调 可通过注册该回调来监听各 CarPropertyValue 的变化
    public interface CarHvacEventCallback {
        void onChangeEvent(CarPropertyValue value);
    }
    public synchronized void registerCallback(CarHvacEventCallback callback) {}
    public synchronized void unregisterCallback(CarHvacEventCallback callback) {}

    // 步骤3 : 提供对各 HVAC 属性的 状态查询 与 状态设置接口
    public boolean getBooleanProperty(@PropertyId int propertyId, int area)
            throws CarNotConnectedException {
        return mCarPropertyMgr.getBooleanProperty(propertyId, area);
    }

    public float getFloatProperty(@PropertyId int propertyId, int area)
            throws CarNotConnectedException {
        return mCarPropertyMgr.getFloatProperty(propertyId, area);
    }
}

首先封装了一个可序列化的类CarPropertyValue, 其对应一个车辆属性,一个车辆属性主要由两部分构成:[propertyId, area]

  • propertyId定义了车辆属性,如空调温度,座椅温度等,具体值定义在CarHvacManager类中,见步骤1
  • area定义了属性对应的区域,因为同一个属性会有多个位置需要控制,如同是座椅温度,有主驾座椅温度,副驾座椅温度,所以就通过该值来对同一属性的不同位置做区分.

CarHvacManager主要做了以下三件事

  • 步骤1 : 定义车辆属性
  • 步骤2 : 提供CarHvacEventCallback回调器及其注册接口,其会去监听底层硬件的状态变化,以便在底层硬件属性变化时告诉上层调用者,可想而知,这个就是我们开发时需要关注的一个接口
  • 步骤3 : 提供查询/设置硬件属性的上层接口,同样这也是我们开发时需要关注的一个接口

这两个类均位于packages/services/Car/car-lib下,我们看下其mk文件

[packages/services/Car/car-lib/Android.mk]

...
LOCAL_MODULE := android.car
...

即该模块会被编译成共享库android.car,可被其他应用引用,例如CarHvacApp中就引用了该库

[packages/apps/Car/Hvac/Android.mk]

LOCAL_JAVA_LIBRARIES += android.car

HvacController

回到前面对 CarHvacApp 的分析,前面介绍HvacPanelController第2点中的updateHvacController()方法时我们看到,HvacController对象会被传进各类子元素View对应的控制器中,同时也是获取/设置各类子元素View状态的地方,很明显,这是个总控制器,同时维护了各开关的状态

来看看这个类的主要职责是什么

  • 1.服务启动时利用car-lib库去创建一个Car对象并调用其connect()函数,并在连接成功时通过该对象获取一个CarHvacManager对象
[packages/apps/Car/Hvac/src/com/android/car/hvac/HvacController.java]
public class HvacController extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
        if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
            mCarApiClient = Car.createCar(this, mCarConnectionCallback);
            mCarApiClient.connect();
        }
    }

    private final CarConnectionCallback mCarConnectionCallback = new CarConnectionCallback() {
                @Override
                public void onConnected(Car car) {
                    synchronized (mHvacManagerReady) {
                        try {
                            initHvacManager((CarHvacManager) mCarApiClient.getCarManager(android.car.Car.HVAC_SERVICE));
                            mHvacManagerReady.notifyAll();
                            ......
                    }

    private void initHvacManager(CarHvacManager carHvacManager) {
        mHvacManager = carHvacManager;
        List<CarPropertyConfig> properties = null;
        try {
            properties = mHvacManager.getPropertyList();
            mPolicy = new HvacPolicy(HvacController.this, properties);
            mHvacManager.registerCallback(mHardwareCallback);
        }
    }
}

    1. 提供接口供查询 / 设置 各HVAC开关的状态值,这里便是利用了CarHvacManager去获取状态值并保存到mDataStore中的,以及利用CarHvacManager将属性变化告知底层硬件的
    public boolean getAirCirculationState() {
        return mDataStore.getAirCirculationState();
    }

    public void setFanDirection(final int direction) {
        mDataStore.setAirflow(SEAT_ALL, direction);
        setFanDirection(SEAT_ALL, direction);
    }

  • 3.向CarHvacManager注册一个监听器监听硬件状态变化,并通知各子元素去做UI刷新
    private void initHvacManager(CarHvacManager carHvacManager) {
          ......
          mHvacManager.registerCallback(mHardwareCallback);
          ......
    }

    private final CarHvacManager.CarHvacEventCallback mHardwareCallback =
            new CarHvacManager.CarHvacEventCallback() {
                @Override
                public void onChangeEvent(final CarPropertyValue val) {
                    int areaId = val.getAreaId();
                    switch (val.getPropertyId()) {
                        case CarHvacManager.ID_ZONED_AC_ON:
                            handleAcStateUpdate(getValue(val));
                            break;
                        ......
                    }
                }
};

简单总结下就是,CarHvacApp 利用 CarHvacManager 完成了对 HVAC 硬件的状态查询,状态设置以及状态监听

SystemUI 与硬件的交互

其实看懂上文CarHvacApp 与硬件的交互之后,这一节的内容也就就十分简单了,跟 CarHvacApp一样,无非就是利用car-lib库来获取Car对象,连接服务,获取CarHvacManager 对象,查询硬件状态,用户操作UI时设置硬件状态,监听硬件的内部变化

下面我们围绕"如何在SystemUI导航栏中实现 直接操作座椅加热功能"这一目的,来看看实现方案:

  • 1.导入car-lib库(原生已导入)
[frameworks/base/packages/SystemUI/Android.mk]

LOCAL_JAVA_LIBRARIES := android.car

  • 2.获取Car对象,连接服务,获取CarHvacManager对象,同时向CarHvacManager注册监听硬件的内部变化
[frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java]
    public void start() {
            Dependency.get(HvacController.class).connectToCarService();
    }

[frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java]
    public void connectToCarService() {
        // 获取 Car 对象
        mCar = Car.createCar(mContext, mServiceConnection, mHandler);
        if (mCar != null) {
            // 连接服务
            mCar.connect();
        }
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            try {
                // 获取 CarHvacManager 对象
                mHvacManager = (CarHvacManager) mCar.getCarManager(Car.HVAC_SERVICE);
                // 注册监听硬件的内部变化
                mHvacManager.registerCallback(mHardwareCallback);
            }
        }
    };

代码很简单,看注释即可,其中HvacController是原生提供的用于处理与 Hvac 相关事物的一个类,可将对 Hvac 相关功能的扩展放到这个类中

原生在SystemUI中做的与Hvac硬件相关的操作很少,只有一个查询空调温度的逻辑,流程很简单,就是利用上面连接服务成功时获取到的CarHvacManager对象去查询温度状态,并利用向CarHvacManager注册的回调监听温度变化

    private void initComponent(TemperatureView view) {
        int id = view.getPropertyId();
        int zone = view.getAreaId();
        // 调 CarHvacManager 的 getFloatProperty 去查询指定位置的温度
        view.setTemp(mHvacManager.getFloatProperty(id, zone));
    }

    private final CarHvacEventCallback mHardwareCallback = new CarHvacEventCallback() {
        @Override
        public void onChangeEvent(final CarPropertyValue val) {
            try {
                // 温度属性上报变化时,刷新UI
                int areaId = val.getAreaId();
                int propertyId = val.getPropertyId();
                List<TemperatureView> temperatureViews = mTempComponents.get(new HvacKey(propertyId, areaId));
                if (temperatureViews != null && !temperatureViews.isEmpty()) {
                    float value = (float) val.getValue();
                    for (TemperatureView tempView : temperatureViews) {
                        tempView.setTemp(value);
                    }
                }
        }

而我们想要实现"在SystemUI导航栏中实现 直接操作座椅加热功能",只需要做简单的扩展:

  • 1.UI构建
  • 2.在HvacController中新增座椅加热状态 查询 / 设置 接口,如
    private static final int DRIVER_ZONE_ID = VehicleAreaSeat.SEAT_ROW_1_LEFT |
            VehicleAreaSeat.SEAT_ROW_2_LEFT | VehicleAreaSeat.SEAT_ROW_2_CENTER;

    public float getDriverZoneTemperature() {
        if (mHvacManager != null) {
            try {
                return mHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, DRIVER_ZONE_ID);
            }
        }
        return -1;
    }

    public void setDriverSeatWarmerLevel(int level) {
        setSeatWarmerLevel(DRIVER_ZONE_ID, level);
    }

    public void setSeatWarmerLevel(final int zone, final int level) {
        final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
            protected Void doInBackground(Void... unused) {
                if (mHvacManager != null) {
                    try {
                        mHvacManager.setIntProperty(CarHvacManager.ID_ZONED_SEAT_TEMP, zone, level);
                    }
                }
                return null;
            }
        };
        task.execute();
    }

  • 3.在向CarHvacManager注册的监听器回调中 新增对座椅加热状态的处理
    private final CarHvacEventCallback mHardwareCallback = new CarHvacEventCallback() {
        @Override
        public void onChangeEvent(final CarPropertyValue val) {
            try {
                int areaId = val.getAreaId();
                int propertyId = val.getPropertyId();
                switch (propertyId) {
                    case CarHvacManager.ID_ZONED_SEAT_TEMP:
                        handleSeatWarmerUpdate(areaId, getValue(val));
                        break;
                }
        }

至此,我们就实现了该功能了,而扩展其他功能时如法炮制即可

链接:https://juejin.cn/post/6997290650794197022
作者:有痣青年

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
在这里插入图片描述
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

全套视频资料:

一、面试合集
在这里插入图片描述
二、源码解析合集

在这里插入图片描述
三、开源框架合集

在这里插入图片描述
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HVAC Solution Pro 是一种针对暖通空调工程设计的专业解决方案。它提供了一套全面的工具和功能,帮助工程师和设计师更高效地设计和规划暖通空调系统。 首先,HVAC Solution Pro具有强大的建筑模块,可以实现高度定制化的建筑平面布局设计。这些模块包括房间、楼层和整栋建筑,用户可以轻松添加、编辑和调整这些模块,以实现最佳的系统设计。 其次,该软件提供了丰富的设备库,包括空调机组、风机、冷却塔等各种暖通设备。用户可以根据项目需求选择合适的设备,进行布置和调整参数,以确保系统的运行效率和性能。 另外,HVAC Solution Pro还具备精确的热负荷计算和管道系统设计功能。用户可以输入建筑参数,如面积、材料等,进行热负荷计算,以确定系统的能耗和供暖/制冷需求。对于管道系统设计,该软件能够提供自动布置和尺寸化的功能,以确保管道的合理布局和流体的均匀分配。 此外,HVAC Solution Pro还支持现场调试和优化功能。在系统安装完成后,用户可以利用该软件进行调试和优化,通过监测数据和模拟分析,找出系统存在的问题,并提出针对性的改进措施。 总之,HVAC Solution Pro是一个功能强大、全面的暖通空调工程设计解决方案。它不仅可以协助工程师和设计师高效地完成系统设计和规划,还能有效提高系统的性能和能耗效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值