场景创建业务实现

更新时间:2024-01-22 08:38:15下载pdf

本文介绍场景创建的业务实现,包括条件创建和动作创建。

条件创建

总体流程

  1. 开发者(下文简称为 )可以通过 查询条件列表 获得涂鸦平台支持的条件类型,并可以考虑结合本地自定义的条件类型,展示可供用户选择的条件类型列表。

    ThingHomeSdk.getSceneServiceInstance().conditionService().getConditionAll(
                homeId, // 家庭 ID
                true, "", object : IResultCallback<ConditionItemList?>() {
                    override fun onSuccess(result: ConditionItemList?) {
                // 在 result 基础上可以继续添加本地自定义的条件类型
                    }
                    override fun onError(errorCode: String?, errorMessage: String?) {
    
                    }
                })
    
  2. 当用户点选具体的条件类型,应当提供不同的条件类型点选后的 UI 交互。

  3. 提供合适的条件设置完成的时机,此时根据用户的选设,采用 创建场景条件 提供的构建器拼装出场景的 条件模型

具体而言,涂鸦提供了一个开源的 示例项目,便于您理解上述的过程。尽管示例项目中部分细节交互进行了简化处理,但是依旧可以传递出上述的流程示意。

位置变化时条件

示例中直接构建了一个固定的地理围栏的场景条件。建议您提供基于 Google 或者华为的地理围栏组件完成地理围栏监控功能,并选用合适的地图进行围栏的圈选设置。当然您也可以选择涂鸦包装的地理围栏监控组件,下文将详细介绍接入方式。

具体而言,从您的地理围栏圈选页获得参数 radiuslatitudelongitudeaddress,并在用户选择地理围栏类型 geofenceType 后,然后将前述参数通过 创建位置变化时条件 创建出位置变化时条件。

val radius = 100
val latitude: Double = 30.30288959184809
val longitude: Double = 120.0640840491766
val address = "XX 影视"
val geofenceType = GeofencingType.GEOFENCING_TYPE_ENTER.type
val geofenceConditionBuilder = GeofenceConditionBuilder(radius, latitude, longitude, address, geofenceType)
val conditionBase = geofenceConditionBuilder.build() as ConditionBase
val geoCondition = SceneCondition(conditionBase).apply {
    this.entityName = address
}

目前基于 Google 和华为的两套地理围栏的实现都已经集成在业务拓展 SDK 组件中。两套实现的具体竞选规则:优先使用基于华为的地理围栏实现,其次是基于 Google 的地理围栏实现,两者只取其一,并非同时生效。

华为地理围栏组件接入

  1. 开发准备,直接依照 HMS Core 的 配置章节集成章节混淆配置包大小优化 操作。

  2. 组件接入。

    // 以下依赖若已包含在上述开发准备步骤内,则忽略,但版本以此处为准
    implementation 'com.huawei.hms:maps:6.0.0.301'
    implementation 'com.huawei.hms:location:6.0.0.302'
    
    implementation "com.thingclips.smart:thingsmart:${sdk_version}"
    // 业务拓展 SDK 组件
    implementation "com.thingclips.smart:thingsmart-expansion-sdk:${expansion_version}"
    
    // 以下依赖若有,则忽略
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.alibaba:fastjson:1.1.67.android'
    
  3. 编码。

    • 建议您在清单文件中声明位置相关权限,并在选择 位置变化时 的条件后,检查并按需立即处理运行时位置权限的申请。具体信息,参考 权限声明、权限申请的处理,否则可能会由于内部的权限检查而导致部分的 API 报错。
    • 建议您提供合适的地图,以便用户进行地理围栏的选设。
  4. 使用。

    对于地理围栏具体的使用方式,创建位置变化时条件 章节对 API 进行了详细的说明。更多的使用限制,参考 地理围栏开发-约束条件 以及 支持地理围栏的设备

Google 地理围栏组件接入

  1. 组件接入。

    implementation 'com.google.android.gms:play-services-maps:17.0.0'
    implementation 'com.google.android.gms:play-services-location:17.0.0'
    
    implementation "com.thingclips.smart:thingsmart:${sdk_version}"
    // 业务拓展 SDK 组件
    implementation("com.thingclips.smart:thingsmart-expansion-sdk:${expansion_version}"){
      // 注意:需要您在全局的依赖中排除基于华为的地理围栏的组件,这样可以采用基于 Google 的地理围栏的实现
      exclude group: "com.thingclips.smart", module: "thingsmart-geofence-huawei"
    }
    
    // 以下依赖若有,则忽略
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.alibaba:fastjson:1.1.67.android'
    
  2. 工程配置。

    • App 模块 build.gradle 全局依赖排除华为的地理围栏组件。

       android{
           configurations.all{
               exclude group: "com.thingclips.smart", module: "thingsmart-geofence-huawei"
           }
       }
      
    • App 模块 AndroidManifest.xml 清单文件配置。

      <!-- 请将以下 ${GOOGLE_MAP_KEY} 替换成您的应用从 Google 申请的地图 Key -->
      <meta-data
          android:name="com.google.android.geo.API_KEY"
          android:value="${GOOGLE_MAP_KEY}" />
      
  3. 编码。

    建议您在清单文件中声明位置相关权限,并在选择 位置变化时 的条件后,立即处理运行时位置权限的申请。具体信息,参考 位置信息权限声明、权限申请的处理,否则可能会由于内部的权限检查而导致部分的 API 报错。

  4. 使用。

    对于地理围栏具体的使用方式,创建位置变化时条件 章节已经对 API 进行了详细的说明。更多的使用指引,参考 创建和监控地理围栏-限制 以及 使用地理围栏最佳做法

定时条件

示例中直接构建了一个固定时间的场景条件。建议您提供时间 picker 组件进行定时的设置。

具体而言,从您的时间 picker 组件获得参数 timedate,通过 Calendar.getInstance().timeZone.idTimeZone.getDefault().id 获得参数 timeZoneId,并在用户选择重复类型 loops 后,将前述参数通过 创建定时条件 创建出定时条件。

val conditionBase: ConditionBase = TimingConditionBuilder(
    timeZoneId,
    loops,
    time,
    date,
).build() as ConditionBase
val timerCondition = SceneCondition(conditionBase).apply {
    entityName = "定时"
    exprDisplay = time
}

气象变化时条件

示例中直接构建了一处固定位置的特定气象类型的场景条件。建议您完整展示根据 查询条件列表 获得的气象变化条件列表 envConds,并在用户选择气象类型后,提供交互 UI 以供用户设置具体的气象目标值。接下来对每个气象类型进行细分讲解。

您可以将 定位的经纬度信息 通过调用 根据经纬度查询城市信息,获取当前所在城市的信息,取用 cityIdcity 字段。或者通过 查询城市列表 后,待用户选取城市后可得。

  • 温度

    val weatherConditionBuilder = WeatherConditionBuilder(
        cityId = cityId,
        cityName = city,
        entityType = 3,
        weatherType = WeatherType.WEATHER_TYPE_TEMP,
        operator = "<", // 用户设置
        chooseValue = chooseValue, // 用户设置
    )
    val conditionBase = weatherConditionBuilder.build() as ConditionBase
    val weatherCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的温度气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    
  • 风速

    val weatherConditionBuilder = WeatherConditionBuilder(
        cityId = cityId,
        cityName = city,
        entityType = 3,
        weatherType = WeatherType.WEATHER_TYPE_WIND,
        operator = "<", // 用户设置
        chooseValue = chooseValue, // 用户设置
    ).setWindSpeedUnit(unit) // 风速的单位,该字段使用条件列表的风速气象类型详情数据,具体是 property.property.unit
    val conditionBase = weatherConditionBuilder.build() as ConditionBase
    val weatherCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的风速气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    
  • 湿度

    val weatherConditionBuilder = WeatherConditionBuilder(
        cityId = cityId,
        cityName = city,
        entityType = 3,
        weatherType = WeatherType.WEATHER_TYPE_HUMIDITY,
        operator = null,
        chooseValue = chooseValue, // 用户选择
    )
    val conditionBase = weatherConditionBuilder.build() as ConditionBase
    val weatherCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的湿度气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    
  • 天气

    val weatherConditionBuilder = WeatherConditionBuilder(
        cityId = cityId,
        cityName = city,
        entityType = 3,
        weatherType = WeatherType.WEATHER_TYPE_CONDITION,
        operator = null,
        chooseValue = chooseValue, // 用户选择
    )
    val conditionBase = weatherConditionBuilder.build() as ConditionBase
    val weatherCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的天气气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    
  • PM2.5

    val weatherConditionBuilder = WeatherConditionBuilder(
        cityId = cityId,
        cityName = city,
        entityType = 3,
        weatherType = WeatherType.WEATHER_TYPE_PM,
        operator = null,
        chooseValue = chooseValue, // 用户选择
    )
    val conditionBase = weatherConditionBuilder.build() as ConditionBase
    val weatherCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的 PM2.5 气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    
  • 空气质量

    val weatherConditionBuilder = WeatherConditionBuilder(
        cityId = cityId,
        cityName = city,
        entityType = 3,
        weatherType = WeatherType.WEATHER_TYPE_AQI,
        operator = null,
        chooseValue = chooseValue, // 用户选择
    )
    val conditionBase = weatherConditionBuilder.build() as ConditionBase
    val weatherCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的空气质量气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    
  • 日出日落

    val weatherConditionBuilder = WeatherConditionBuilder(
        cityId = cityId,
        cityName = city,
        entityType = 3,
        weatherType = WeatherType.WEATHER_TYPE_SUN,
        operator = null,
        chooseValue = chooseValue, // 用户选择
    )
    val conditionBase = weatherConditionBuilder.build() as ConditionBase
    val weatherCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的日出日落气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    
  • 日出日落前后时间点

    val conditionBase: ConditionBase = SunRiseSetConditionBuilder(
        cityId,
        SunSetRiseRule.SunType.SUNSET, // 用户选择,SUNSET 或 SUNRISE
        20 // 前/后分钟数
    ).build() as ConditionBase
    val sunRiseSetCondition = SceneCondition(conditionBase).apply {
        entityName = city
        iconUrl = weatherData.icon // 选中气象类型的 icon,该字段使用条件列表的日出日落气象类型详情数据的 newIcon 字段
        exprDisplay = exprDis // 条件表达式的可视化展示
    }
    

设备状态变化时条件

示例中直接构建了一个固定设备的固定功能的场景条件。建议您完整展示根据 查询条件设备列表 获得的设备列表,并在用户选取设备后,通过 查询条件设备的 DP 列表 获得功能列表,将 条件设备功能数据模型转化为 DTO 模型 后进行功能展示以供用户设置,然后将用户选设通过 创建设备状态变化时条件 创建出设备条件。接下来对具体设备类型进行细分讲解。

deviceConditionData条件设备功能数据模型转化为 DTO 模型 而来,并要求在编辑后及时对其进行字段更新。例如,更新 ValueTypeData.valueValueTypeData.operatorsOtherTypeData.checkedConditionExtraInfo.timeWindow

  • 普通设备

    val builder = DeviceConditionBuilder(
        deviceId = deviceConditionData.deviceId,
        dpId = deviceConditionData.datapointId.toString(),
        entityType = deviceConditionData.entityType ?: CONDITION_TYPE_DEVICE,
        deviceConditionData = deviceConditionData, // 条件设备功能数据模型转化为 DTO 模型后就获得了 conditionData 的列表
        chooseValue = chooseValue // 用户设置
    )
    
    val conditionBase = builder.build() as ConditionBase
    val deviceCondition = SceneCondition(conditionBase).apply {
        entityName = deviceBean.name // 设备名称
        entitySubIds = deviceConditionData.datapointId.toString() // 设备功能 DP ID
        iconUrl = deviceBean.getIconUrl()// 设备 icon
        exprDisplay = displayString // 设备条件表达式的可视化展示
    }
    
  • 普通设备温度 DP

    • convertTemp map 结构内部需要存放不同温度单位的 DP 值。
    • originTempUnit 指定为当前 DP 的温度单位。
    • tempUnit 指定为当前应用偏好设置的温度单位。
    • dpScale 指定为当前 DP 的小数点系数。
    val builder = DeviceConditionBuilder(
        deviceId = deviceConditionData.deviceId,
        dpId = deviceConditionData.datapointId.toString(),
        entityType = deviceConditionData.entityType ?: CONDITION_TYPE_DEVICE,
        deviceConditionData = deviceConditionData, // 条件设备功能数据模型转化为 DTO 模型后就获得了 conditionData 的列表
        chooseValue = chooseValue // 用户设置
    )
    
    val originTempUnit = "celsius" // 当前功能点的温度单位
    val tempUnit = "fahrenheit" // 应用内偏好设置的温度展示单位
    val dpScale = 1
    val tempMap = mutableMapOf<String, Int>()
    tempMap[originTempUnit] = 120
    tempMap[tempUnit] = (120/10 * 1.8 + 32) * 10 // 摄氏度转换为华氏度
    
    builder.setConvertTemp(tempMap)
           .setTempUnit(tempUnit)
           .setOriginTempUnit(originTempUnit)
           .setDpScale(dpScale)
    
    val conditionBase = builder.build() as ConditionBase
    val deviceCondition = SceneCondition(conditionBase).apply {
        entityName = deviceBean.name // 设备名称
        entitySubIds = deviceConditionData.datapointId.toString() // 设备功能 DP ID
        iconUrl = deviceBean.getIconUrl()// 设备 icon
        exprDisplay = displayString // 设备条件表达式的可视化展示
    }
    
  • PIR 设备

    val builder = DeviceConditionBuilder(
        deviceId = deviceConditionData.deviceId,
        dpId = deviceConditionData.datapointId.toString(),
        entityType = deviceConditionData.entityType ?: CONDITION_TYPE_DEVICE,
        deviceConditionData = deviceConditionData, // 条件设备功能数据模型转化为 DTO 模型后就获得了 conditionData 的列表
        chooseValue = chooseValue // 用户设置
    ).setDelayTime(otherTypeData?.datapointKey ?: "") // 从 conditionData.otherTypeData.datapointKey 获得
    
    val conditionBase = builder.build() as ConditionBase
    val deviceCondition = SceneCondition(conditionBase).apply {
        entityName = deviceBean.name // 设备名称
        entitySubIds = deviceConditionData.datapointId.toString() // 设备功能 DP ID
        iconUrl = deviceBean.getIconUrl()// 设备 icon
        exprDisplay = displayString // 设备条件表达式的可视化展示
    }
    
  • 设备 DP 持续时间

    deviceConditionData.entityType = CONDITION_TYPE_WITH_TIME
    
    val builder = DeviceConditionBuilder(
        deviceId = deviceConditionData.deviceId,
        dpId = deviceConditionData.datapointId.toString(),
        entityType = deviceConditionData.entityType,
        deviceConditionData = deviceConditionData, // 条件设备功能数据模型转化为 DTO 模型后就获得了 conditionData 的列表
        chooseValue = chooseValue // 用户设置
    ).setCalType(COND_TYPE_DURATION)
            .setTimeWindow(conditionData.extraInfo?.timeWindow ?: 0)
    
    val conditionBase = builder.build() as ConditionBase
    val deviceCondition = SceneCondition(conditionBase).apply {
        entityName = deviceBean.name // 设备名称
        entitySubIds = deviceConditionData.datapointId.toString() // 设备功能 DP ID
        iconUrl = deviceBean.getIconUrl()// 设备 icon
        exprDisplay = displayString // 设备条件表达式的可视化展示
    }
    

家人回家条件

示例中直接构建了一个固定门锁设备的固定成员的场景条件。建议您完整展示家庭下的门锁设备列表,并在用户选取设备后,完整展示家庭成员列表以供用户选设。

devConds查询条件列表 处获得。

val membersString = "zhangsan,lisi" // 将选中的家庭成员名称联合,以逗号分隔
val memberIds = "123,345" // 将选中的家庭成员 ID 联合,以逗号分隔
val conditionBase = DeviceConditionBuilder(
    deviceId = deviceId ?: "", // 门锁设备 ID
    dpId = devConds?.find { it.entityType == ConditionEntityType.LOCK_MEMBER_GO_HOME.type }?.entitySubId ?: "",
    entityType = ConditionEntityType.LOCK_MEMBER_GO_HOME.type,
    deviceConditionData = null,
    chooseValue = memberIds
).setMembers(membersString)
      .build() as ConditionBase

val lockCondition = SceneCondition(conditionBase).apply {
    entityName = membersString
    exprDisplay = display // 设备条件表达式的可视化展示
}

动作创建

总体流程

  1. 展示可供用户选择的动作类型列表。

  2. 当用户点选具体的动作类型,应当提供不同的动作类型点选后的 UI 交互。

  3. 提供合适的动作设置完成的时机,此时根据用户的选设,采用 创建场景动作 提供的构建器拼装出场景的 动作模型

延时执行动作

示例中直接构建了一个固定的延时动作。建议您提供时间 picker 组件进行延时的设置。

具体而言,从您的时间 picker 组件获得时分秒三个单位体系的设置,并转换成两个单位体系参数 minutesseconds,然后将前述参数通过 创建延时执行动作 创建出延时动作。

val minutes = 62
val seconds = 20
val actionBase: ActionBase = DelayActionBuilder(minutes, seconds).build() as ActionBase
val delayAction = SceneAction(actionBase).apply {
    entityName = "延时执行"
}

发送通知提醒动作

示例中直接构建了一个消息中心的动作。建议您根据不同的通知类型,提供交互以供用户选设。

具体而言,参数 notifyType 由用户选设具体的类型决定,消息中心为常量 ACTION_TYPE_MESSAGE,短信提醒为常量 ACTION_TYPE_SMS,电话提醒为常量 ACTION_TYPE_PHONE,这些常量定义在 package: com.thingclips.smart.scene.model.constant.* 内。然后将前述参数通过 创建发送通知提醒动作 创建出通知型动作。

短信和电话提醒是增值服务,需要您在涂鸦 IoT 开发平台上购买开通后,方可正常使用。此处仅指导您创建出具体通知类型的场景动作数据模型。

  • 消息中心

    val actionBase: ActionBase = NotifyActionBuilder(ACTION_TYPE_MESSAGE).build() as ActionBase
    val notifyAction = SceneAction(actionBase).apply {
        entityName = "消息中心"
    }
    
  • 短信提醒

    关于增值服务的状态显示,您可以通过对场景动作 actionDisplayNew 属性中置入合适的文案提醒。当您在 UI 上需要显示通知类型场景动作副标题时,即可从 actionDisplayNew 中解析出展示。具体请见下述示例代码:

    val unableTip = "短信提醒增值服务不可用的提示文案"
    val actionBase: ActionBase = NotifyActionBuilder(ACTION_TYPE_SMS).build() as ActionBase
    val notifyAction = SceneAction(actionBase).apply {
        entityName = "短信通知"
        actionDisplayNew = mutableMapOf(
            "package_has_expired" to listOf(unableTip)
        )
    }
    
  • 电话提醒

    val unableTip = "电话提醒增值服务不可用的提示文案"
    val actionBase: ActionBase = NotifyActionBuilder(ACTION_TYPE_PHONE).build() as ActionBase
    val notifyAction = SceneAction(actionBase).apply {
        entityName = "电话提醒"
        actionDisplayNew = mutableMapOf(
            "voice_package_has_expired" to listOf(unableTip)
        )
    }
    

选择已有智能场景动作

示例中首先将 查询简易场景列表 获得的包含一键执行和自动化的场景列表进行展示,待用户完成勾选后构建出智能场景的动作。建议您可以选择从本地数据源获取场景数据,但前提是您已经做了列表数据的本地缓存,已经完成了增删改对本地缓存的更新,并提供不同类型场景数据的交互,以供用户选设。

具体而言,您将从选中的场景条目中获得场景 ID 参数 linkageRuleId,参数 linkageOperator 由用户选择的场景类型决定,一键执行为常量 ACTION_TYPE_TRIGGER,自动化启用为常量 ACTION_TYPE_ENABLE_AUTOMATION,自动化禁用为常量 ACTION_TYPE_DISABLE_AUTOMATION。然后将前述参数通过 创建选择已有智能场景动作 创建出智能场景动作。

  • 选择 一键执行 动作

    val actionExecutor = ACTION_TYPE_TRIGGER
    val actionBase: ActionBase = LinkageRuleActionBuilder(checkedItem.id, actionExecutor).build() as ActionBase // checkedItem.id 是一键执行的 ID
    SceneAction(actionBase).apply {
        entityName = checkedItem.name // 一键执行的名称
    }
    
  • 选择 自动化 动作

    val actionExecutor = ACTION_TYPE_ENABLE_AUTOMATION
    val actionBase: ActionBase = LinkageRuleActionBuilder(checkedItem.id, actionExecutor).build() as ActionBase
    // checkedItem.id 是自动化的 ID
    SceneAction(actionBase).apply {
       entityName = checkedItem.name // 自动化的名称
    }
    

控制单个设备动作

示例中创建了一个固定设备固定功能点的场景动作。建议您完整展示通过 查询动作设备列表 获得的设备、群组列表,并在用户选取设备或群组后,通过 查询动作设备的 DP 列表查询动作设备群组的 DP 列表 获得功能列表,将 动作设备功能数据模型转化为 DTO 模型 并进行功能展示以供用户设置,然后将用户选设通过 创建控制单个设备动作 创建出设备动作。接下来对具体设备类型进行细分讲解。

deviceActionDetailBean动作设备功能数据模型转化为 DTO 模型 而来。selDpValue 为选择的 DP 值,selDpDisplayValue 为选择的 DP 值的可视化展示。

  • 普通设备

    val builder = DeviceActionBuilder(deviceId, deviceActionDetailBean, selDpValue, selDpDisplayValue ?: "")
    val actionBase: ActionBase = builder.build() as ActionBase
    SceneAction(actionBase).apply {
        actionDisplayNew = actionDisplayMap // 同样是 DP 功能选择后的可视化展示
        extService?.getDevice(deviceId)?.let {
            this.devIcon = it.iconUrl // 设备 icon
            this.isDevOnline = it.isOnline // 设备在线状态
            this.entityName = it.name // 设备名称
        }
    }
    
  • 普通设备步进 DP

    val type = DeviceStepType.HIGH
    val builder = DeviceActionBuilder(deviceId, deviceActionDetailBean, selDpValue, selDpDisplayValue ?: "", isStep = true)
          .apply{
                this.setType(type)
        }
    val actionBase: ActionBase = builder.build() as ActionBase
    SceneAction(actionBase).apply {
        actionDisplayNew = actionDisplayMap // 同样是 DP 功能选择后的可视化展示
        extService?.getDevice(deviceId)?.let {
            this.devIcon = it.iconUrl // 设备 icon
            this.isDevOnline = it.isOnline // 设备在线状态
            this.entityName = it.name // 设备名称
        }
    }
    
  • 普通设备温度 DP

    • convertTemp map 结构内部需要存放不同温度单位的 DP 值。
    • originTempUnit 指定为当前 DP 的温度单位。
    • tempUnit 指定为当前应用偏好设置的温度单位。
    • dpScale 指定为当前 DP 的小数点系数。
    val originTempUnit = "celsius" // 当前功能点的温度单位
    val tempUnit = "fahrenheit" // 应用内偏好设置的温度展示单位
    val dpScale = 1
    val convertTemp = mutableMapOf<String, Int>()
    convertTemp[originTempUnit] = 120
    convertTemp[tempUnit] = (120/10 * 1.8 + 32) * 10 // 摄氏度转换为华氏度
    
    val builder = DeviceActionBuilder(deviceId, deviceActionDetailBean, selDpValue, selDpDisplayValue ?: "")
        .apply {
            originTempUnit?.let {
                this.setOriginTempUnit(it)
            }
            dpScale?.let {
                this.setDpScale(it)
            }
            convertTemp?.let {
                this.setConvertTemp(it)
            }
        }
    val actionBase: ActionBase = builder.build() as ActionBase
        SceneAction(actionBase).apply {
        actionDisplayNew = actionDisplayMap // 同样是 DP 功能选择后的可视化展示
        extService?.getDevice(deviceId)?.let {
            this.devIcon = it.iconUrl // 设备 icon
            this.isDevOnline = it.isOnline // 设备在线状态
            this.entityName = it.name // 设备名称
        }
    }
    
  • 群组动作

    val builder = DeviceActionBuilder(groupId.toString(), deviceActionDetailBean, selDpValue, selDpDisplayValue ?: "")
    val actionBase: ActionBase = builder.build() as ActionBase
    SceneAction(actionBase).apply {
        actionDisplayNew = actionDisplayMap // 同样是 DP 功能选择后的可视化展示
        this.actionExecutor = ACTION_TYPE_DEVICE_GROUP // actionExecutor 调整为群组动作 actionExecutor
        extService?.getGroupDevice(groupId)?.let {
            this.devIcon = it.iconUrl // 群组 icon
            this.isDevOnline = it.isOnline // 群组在线状态
            this.entityName = it.name // 群组名称
        }
    }