| {%- macro encode_value(source, encodable, depth) -%} |
| {%- if encodable.is_nullable -%} |
| @Nullable {{encode_value(source, encodable.without_nullable(), depth + 1)}} |
| {%- elif encodable.is_optional -%} |
| Optional<{{encode_value(source, encodable.without_optional(), depth + 1)}}> |
| {%- elif encodable.is_list -%} |
| ArrayList<{{encode_value(source, encodable.without_list(), depth + 1)}}> |
| {%- elif encodable.is_struct -%} |
| {%- set struct = encodable.get_underlying_struct() -%} |
| ChipStructs.{{source.name}}Cluster{{struct.name}} |
| {%- else -%} |
| {{encodable.boxed_java_type}} |
| {%- endif -%} |
| {%- endmacro -%} |
| |
| {%- macro encode_value_without_optional(source, encodable, depth) -%} |
| {%- if encodable.is_nullable -%} |
| @Nullable {{encode_value_without_optional(source, encodable.without_nullable(), depth + 1)}} |
| {%- elif encodable.is_list -%} |
| List<{{encode_value_without_optional(source, encodable.without_list(), depth + 1)}}> |
| {%- elif encodable.is_struct -%} |
| {%- set struct = encodable.get_underlying_struct() -%} |
| ChipStructs.{{source.name}}Cluster{{struct.name}} |
| {%- else -%} |
| {{encodable.boxed_java_type}} |
| {%- endif -%} |
| {%- endmacro -%} |
| |
| {%- macro encode_value_without_optional_nullable(source, encodable, depth) -%} |
| {%- if encodable.is_list -%} |
| ArrayList<{{encode_value_without_optional_nullable(source, encodable.without_list(), depth + 1)}}> |
| {%- elif encodable.is_struct -%} |
| {%- set struct = encodable.get_underlying_struct() -%} |
| ChipStructs.{{source.name}}Cluster{{struct.name}} |
| {%- else -%} |
| {{encodable.boxed_java_type}} |
| {%- endif -%} |
| {%- endmacro -%} |
| |
| {%- macro encode_tlv(source, encodable, variable, depth) -%} |
| {%- if encodable.is_nullable -%} |
| {{variable}} != null ? {{encode_tlv(source, encodable.without_nullable(), variable, depth + 1)}} : new NullType() |
| {%- elif encodable.is_optional -%} |
| {{variable}}.<BaseTLVType>map(({{"nonOptional{}".format(variable)}}) -> {{encode_tlv(source, encodable.without_optional(), "nonOptional{}".format(variable), depth + 1)}}).orElse(new EmptyType()) |
| {%- elif encodable.is_list -%} |
| ArrayType.generateArrayType({{variable}}, ({{"element{}".format(variable)}}) -> {{encode_tlv(source, encodable.without_list(), "element{}".format(variable), depth + 1)}}) |
| {%- elif encodable.is_struct -%} |
| {%- set struct = encodable.get_underlying_struct() -%} |
| {{variable}}.encodeTlv() |
| {%- else -%} |
| new {{encodable.java_tlv_type}}Type({{variable}}) |
| {%- endif -%} |
| {%- endmacro -%} |
| |
| {%- macro decode_tlv(source, encodable, variable, depth) -%} |
| {%- if encodable.is_optional -%} |
| Optional.of({{decode_tlv(source, encodable.without_optional(), variable, depth + 1)}}) |
| {%- elif encodable.is_list -%} |
| {{variable}}.map(({{"element{}".format(variable)}}) -> {{decode_tlv(source, encodable.without_list(), "element{}".format(variable), depth + 1)}}) |
| {%- elif encodable.is_struct -%} |
| {%- set struct = encodable.get_underlying_struct() -%} |
| ChipStructs.{{source.name}}Cluster{{struct.name}}.decodeTlv({{variable}}) |
| {%- else -%} |
| {{variable}}.value({{encodable.boxed_java_type}}.class) |
| {%- endif -%} |
| {%- endmacro -%} |
| |
| {%- macro get_tlvType(encodable) -%} |
| {%- if encodable.is_list -%} |
| Array |
| {%- elif encodable.is_struct -%} |
| Struct |
| {%- else -%} |
| {{encodable.java_tlv_type}} |
| {%- endif -%} |
| {%- endmacro -%} |
| |
| /* |
| * |
| * Copyright (c) 2023 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package chip.devicecontroller; |
| |
| import chip.devicecontroller.model.AttributeState; |
| import chip.devicecontroller.model.AttributeWriteRequest; |
| import chip.devicecontroller.model.ChipAttributePath; |
| import chip.devicecontroller.model.ChipEventPath; |
| import chip.devicecontroller.model.ClusterState; |
| import chip.devicecontroller.model.EndpointState; |
| import chip.devicecontroller.model.InvokeElement; |
| import chip.devicecontroller.model.NodeState; |
| import chip.devicecontroller.model.Status; |
| |
| import javax.annotation.Nullable; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Optional; |
| |
| import javax.annotation.Nonnull; |
| import javax.annotation.Nullable; |
| |
| import static chip.devicecontroller.ChipTLVType.*; |
| |
| public class ChipClusters { |
| |
| public interface BaseClusterCallback { |
| void onError(Exception error); |
| } |
| |
| public interface DefaultClusterCallback extends BaseClusterCallback { |
| void onSuccess(); |
| } |
| |
| public interface BaseAttributeCallback { |
| void onError(Exception error); |
| default void onSubscriptionEstablished(long subscriptionId) {} |
| } |
| |
| public interface CharStringAttributeCallback extends BaseAttributeCallback { |
| /** Indicates a successful read for a CHAR_STRING attribute. */ |
| void onSuccess(String value); |
| } |
| |
| public interface OctetStringAttributeCallback extends BaseAttributeCallback { |
| /** Indicates a successful read for an OCTET_STRING attribute. */ |
| void onSuccess(byte[] value); |
| } |
| |
| public interface IntegerAttributeCallback extends BaseAttributeCallback { |
| void onSuccess(int value); |
| } |
| |
| public interface LongAttributeCallback extends BaseAttributeCallback { |
| void onSuccess(long value); |
| } |
| |
| public interface BooleanAttributeCallback extends BaseAttributeCallback { |
| void onSuccess(boolean value); |
| } |
| |
| public interface FloatAttributeCallback extends BaseAttributeCallback { |
| void onSuccess(float value); |
| } |
| |
| public interface DoubleAttributeCallback extends BaseAttributeCallback { |
| void onSuccess(double value); |
| } |
| |
| public static abstract class BaseChipCluster { |
| protected long chipClusterPtr; |
| |
| protected long devicePtr; |
| protected int endpointId; |
| protected long clusterId; |
| |
| private Optional<Long> timeoutMillis = Optional.empty(); |
| |
| public BaseChipCluster(long devicePtr, int endpointId, long clusterId) { |
| this.devicePtr = devicePtr; |
| this.endpointId = endpointId; |
| this.clusterId = clusterId; |
| } |
| |
| /** |
| * Sets the timeout, in milliseconds, after which commands sent through this cluster will fail |
| * with a timeout (regardless of whether or not a response has been received). If set to an |
| * empty optional, the default timeout will be used. |
| */ |
| public void setCommandTimeout(Optional<Long> timeoutMillis) { |
| this.timeoutMillis = timeoutMillis; |
| } |
| |
| /** Returns the current timeout (in milliseconds) for commands sent through this cluster. */ |
| public Optional<Long> getCommandTimeout() { |
| return timeoutMillis == null ? Optional.empty() : timeoutMillis; |
| } |
| |
| @Deprecated |
| public abstract long initWithDevice(long devicePtr, int endpointId); |
| |
| protected void readAttribute( |
| ReportCallbackImpl callback, |
| long attributeId, |
| boolean isFabricFiltered) { |
| ReportCallbackJni jniCallback = new ReportCallbackJni(null, callback, null); |
| ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, attributeId); |
| ChipInteractionClient.read(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, null, isFabricFiltered, timeoutMillis.orElse(0L).intValue(), null); |
| } |
| |
| protected void writeAttribute( |
| WriteAttributesCallbackImpl callback, |
| long attributeId, |
| BaseTLVType value, |
| int timedRequestTimeoutMs) { |
| WriteAttributesCallbackJni jniCallback = new WriteAttributesCallbackJni(callback); |
| byte[] tlv = encodeToTlv(value); |
| AttributeWriteRequest writeRequest = AttributeWriteRequest.newInstance(endpointId, clusterId, attributeId, tlv); |
| ChipInteractionClient.write(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(writeRequest), timedRequestTimeoutMs, timeoutMillis.orElse(0L).intValue()); |
| } |
| |
| protected void subscribeAttribute( |
| ReportCallbackImpl callback, |
| long attributeId, |
| int minInterval, |
| int maxInterval) { |
| ReportCallbackJni jniCallback = new ReportCallbackJni(callback, callback, callback); |
| ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, attributeId); |
| int fabricIndex = ChipInteractionClient.getFabricIndex(devicePtr); |
| long deviceId = ChipInteractionClient.getRemoteDeviceId(devicePtr); |
| ChipInteractionClient.subscribe(0, jniCallback.getCallbackHandle(), devicePtr, Arrays.asList(path), null, null, minInterval, maxInterval, false, true, timeoutMillis.orElse(0L).intValue(), null, ChipICDClient.isPeerICDClient(fabricIndex, deviceId)); |
| } |
| |
| protected void invoke( |
| InvokeCallbackImpl callback, |
| long commandId, |
| BaseTLVType value, |
| int timedRequestTimeoutMs) { |
| InvokeCallbackJni jniCallback = new InvokeCallbackJni(callback); |
| byte[] tlv = encodeToTlv(value); |
| InvokeElement element = InvokeElement.newInstance(endpointId, clusterId, commandId, tlv, null); |
| ChipInteractionClient.invoke(0, jniCallback.getCallbackHandle(), devicePtr, element, timedRequestTimeoutMs, timeoutMillis.orElse(0L).intValue()); |
| } |
| |
| private static native byte[] encodeToTlv(BaseTLVType value); |
| |
| static native BaseTLVType decodeFromTlv(byte[] tlv); |
| |
| @Deprecated |
| public void deleteCluster(long chipClusterPtr) {} |
| @SuppressWarnings("deprecation") |
| protected void finalize() throws Throwable { |
| super.finalize(); |
| |
| if (chipClusterPtr != 0) { |
| deleteCluster(chipClusterPtr); |
| chipClusterPtr = 0; |
| } |
| } |
| } |
| |
| abstract static class ReportCallbackImpl implements ReportCallback, SubscriptionEstablishedCallback, ResubscriptionAttemptCallback { |
| private BaseAttributeCallback callback; |
| private ChipAttributePath path; |
| |
| private static final long CHIP_ERROR_UNSUPPORTED_ATTRIBUTE = 0x86; |
| |
| ReportCallbackImpl(BaseAttributeCallback callback, ChipAttributePath path) { |
| this.callback = callback; |
| this.path = path; |
| } |
| |
| @Override |
| public void onError( |
| @Nullable ChipAttributePath attributePath, |
| @Nullable ChipEventPath eventPath, |
| @Nonnull Exception e) { |
| callback.onError(e); |
| } |
| |
| @Override |
| public void onReport(NodeState nodeState) { |
| if (nodeState == null) { |
| callback.onError(new ChipClusterException()); |
| return; |
| } |
| |
| EndpointState endpointState = nodeState.getEndpointState((int)path.getEndpointId().getId()); |
| if (endpointState == null) { |
| callback.onError(new ChipClusterException(CHIP_ERROR_UNSUPPORTED_ATTRIBUTE)); |
| return; |
| } |
| |
| ClusterState clusterState = endpointState.getClusterState(path.getClusterId().getId()); |
| if (clusterState == null) { |
| callback.onError(new ChipClusterException(CHIP_ERROR_UNSUPPORTED_ATTRIBUTE)); |
| return; |
| } |
| |
| AttributeState attributeState = clusterState.getAttributeState(path.getAttributeId().getId()); |
| if (attributeState == null) { |
| callback.onError(new ChipClusterException(CHIP_ERROR_UNSUPPORTED_ATTRIBUTE)); |
| return; |
| } |
| |
| byte[] tlv = attributeState.getTlv(); |
| if (tlv == null) { |
| callback.onError(new ChipClusterException(CHIP_ERROR_UNSUPPORTED_ATTRIBUTE)); |
| return; |
| } |
| |
| onSuccess(tlv); |
| } |
| |
| @Override |
| public void onSubscriptionEstablished(long subscriptionId) { |
| callback.onSubscriptionEstablished(subscriptionId); |
| } |
| |
| @Override |
| public void onResubscriptionAttempt(long terminationCause, long nextResubscribeIntervalMsec) {} |
| |
| public abstract void onSuccess(byte[] tlv); |
| } |
| |
| static class WriteAttributesCallbackImpl implements WriteAttributesCallback { |
| private DefaultClusterCallback callback; |
| |
| WriteAttributesCallbackImpl(DefaultClusterCallback callback) { |
| this.callback = callback; |
| } |
| |
| @Override |
| public void onResponse(ChipAttributePath attributePath, Status status) { |
| if (status.getStatus() == Status.Code.Success) |
| { |
| callback.onSuccess(); |
| } |
| else |
| { |
| callback.onError(new StatusException(status.getStatus())); |
| } |
| } |
| |
| @Override |
| public void onError(@Nullable ChipAttributePath attributePath, Exception e) { |
| callback.onError(e); |
| } |
| } |
| |
| abstract static class InvokeCallbackImpl implements InvokeCallback { |
| private BaseClusterCallback callback; |
| |
| private static final long CHIP_ERROR_UNSUPPORTED_COMMAND = 0x81; |
| |
| InvokeCallbackImpl(BaseClusterCallback callback) { |
| this.callback = callback; |
| } |
| |
| public void onError(Exception e) { |
| callback.onError(e); |
| } |
| |
| public void onResponse(InvokeElement invokeElement, long successCode) { |
| byte[] tlv = invokeElement.getTlvByteArray(); |
| if (tlv == null) { |
| onResponse(null); |
| return; |
| } |
| BaseTLVType value = BaseChipCluster.decodeFromTlv(tlv); |
| if (value == null || value.type() != TLVType.Struct) { |
| callback.onError(new ChipClusterException(CHIP_ERROR_UNSUPPORTED_COMMAND)); |
| return; |
| } |
| onResponse((StructType)value); |
| } |
| |
| public abstract void onResponse(StructType value); |
| } |
| {% for cluster in clientClusters | sort(attribute='code') %} |
| {%- set typeLookup = idl | createLookupContext(cluster) %} |
| public static class {{cluster.name}}Cluster extends BaseChipCluster { |
| public static final long CLUSTER_ID = {{cluster.code}}L; |
| {% for attribute in cluster.attributes | sort(attribute='code') %} |
| private static final long {{attribute.definition.name | constcase}}_ATTRIBUTE_ID = {{attribute.definition.code}}L; |
| {%- endfor %} |
| |
| public {{cluster.name}}Cluster(long devicePtr, int endpointId) { |
| super(devicePtr, endpointId, CLUSTER_ID); |
| } |
| |
| @Override |
| @Deprecated |
| public long initWithDevice(long devicePtr, int endpointId) { |
| return 0L; |
| } |
| {% for command in cluster.commands | sort(attribute='code') -%} |
| {%- set callbackName = command | javaCommandCallbackName() -%} |
| {%- if not command.is_timed_invoke %} |
| public void {{command.name | lowfirst_except_acronym}}({{callbackName}}Callback callback |
| {%- if command.input_param -%} |
| {%- for field in (cluster.structs | named(command.input_param)).fields -%} |
| {%- set encodable = field | asEncodable(typeLookup) -%} |
| , {{encode_value(cluster, encodable, 0)}} {{field.name | lowfirst_except_acronym}} |
| {%- endfor -%} |
| {%- endif -%} |
| ) { |
| {{command.name | lowfirst_except_acronym}}(callback |
| {%- if command.input_param -%} |
| {%- for field in (cluster.structs | named(command.input_param)).fields -%} |
| , {{field.name | lowfirst_except_acronym}} |
| {%- endfor -%} |
| {%- endif -%} |
| , 0); |
| } |
| {%- endif %} |
| |
| public void {{command.name | lowfirst_except_acronym}}({{callbackName}}Callback callback |
| {%- if command.input_param -%} |
| {%- for field in (cluster.structs | named(command.input_param)).fields -%} |
| {%- set encodable = field | asEncodable(typeLookup) -%} |
| , {{encode_value(cluster, encodable, 0)}} {{field.name | lowfirst_except_acronym}} |
| {%- endfor -%} |
| {%- endif -%} |
| , int timedInvokeTimeoutMs) { |
| final long commandId = {{command.code}}L; |
| |
| ArrayList<StructElement> elements = new ArrayList<>(); |
| {%- if command.input_param -%} |
| {%- for field in (cluster.structs | named(command.input_param)).fields -%} |
| {%- set encodable = field | asEncodable(typeLookup) %} |
| final long {{field.name | lowfirst_except_acronym}}FieldID = {{field.code}}L; |
| BaseTLVType {{field.name | lowfirst_except_acronym}}tlvValue = {{encode_tlv(cluster, encodable, (field.name | lowfirst_except_acronym), 0)}}; |
| elements.add(new StructElement({{field.name | lowfirst_except_acronym}}FieldID, {{field.name | lowfirst_except_acronym}}tlvValue)); |
| {% endfor -%} |
| {%- endif %} |
| StructType commandArgs = new StructType(elements); |
| invoke(new InvokeCallbackImpl(callback) { |
| @Override |
| public void onResponse(StructType invokeStructValue) { |
| {%- if command | isCommandNotDefaultCallback() %} |
| {%- for field in (cluster.structs | named(command.output_param)).fields -%} |
| {%- set encodable = field | asEncodable(typeLookup) %} |
| {%- set encodable2 = field | asEncodable(typeLookup) %} |
| final long {{field.name | lowfirst_except_acronym}}FieldID = {{field.code}}L; |
| {{encode_value(cluster, encodable, 0)}} {{field.name | lowfirst_except_acronym}} |
| {%- if encodable2.is_nullable -%} |
| {{" = null"}} |
| {%- elif encodable2.is_optional -%} |
| {{" = Optional.empty()"}} |
| {%- else -%} |
| {{" = null"}} |
| {%- endif -%} |
| ; |
| {%- endfor %} |
| for (StructElement element: invokeStructValue.value()) { |
| {%- for field in (cluster.structs | named(command.output_param)).fields -%} |
| {%- set encodable = field | asEncodable(typeLookup) %} |
| {% if loop.index0 > 0 -%}{{"} else "}}{%- endif -%}if (element.contextTagNum() == {{field.name | lowfirst_except_acronym}}FieldID) { |
| if (element.value(BaseTLVType.class).type() == TLVType.{{get_tlvType(encodable)}}) { |
| {{get_tlvType(encodable)}}Type castingValue = element.value({{get_tlvType(encodable)}}Type.class); |
| {{field.name | lowfirst_except_acronym}} = {{decode_tlv(cluster, encodable, "castingValue", 0)}}; |
| } |
| {%- endfor -%} |
| {% raw %} |
| } |
| {%- endraw %} |
| } |
| callback.onSuccess( |
| {%- for field in (cluster.structs | named(command.output_param)).fields -%} |
| {{field.name | lowfirst_except_acronym}} |
| {%- if loop.index0 < loop.length - 1 -%}{{", "}}{%- endif -%} |
| {%- endfor -%} |
| ); |
| {%- else %} |
| callback.onSuccess(); |
| {%- endif %} |
| }}, commandId, commandArgs, timedInvokeTimeoutMs); |
| } |
| {% endfor %} |
| {%- set already_handled_command = [] -%} |
| {%- for command in cluster.commands | sort(attribute='code') -%} |
| {%- if command | isCommandNotDefaultCallback() -%} |
| {%- set callbackName = command | javaCommandCallbackName() -%} |
| {%- if callbackName not in already_handled_command %} |
| public interface {{callbackName}}Callback extends BaseClusterCallback { |
| void onSuccess( |
| {%- for field in (cluster.structs | named(command.output_param)).fields -%} |
| {%- set encodable = field | asEncodable(typeLookup) -%} |
| {{encode_value(cluster, encodable, 0)}} {{field.name | lowfirst_except_acronym}} |
| {%- if loop.index0 < loop.length - 1 -%}{{", "}}{%- endif -%} |
| {%- endfor -%} |
| ); |
| } |
| {% if already_handled_command.append(callbackName) -%} |
| {#- This block does nothing, it only exists to append to already_handled_command. -#} |
| {%- endif -%} |
| {%- endif -%} |
| {%- endif -%} |
| {%- endfor %} |
| {%- set already_handled_attribute = [] -%} |
| {% for attribute in cluster.attributes | rejectattr('definition', 'is_field_global_name', typeLookup) %} |
| {%- set encodable = attribute.definition | asEncodable(typeLookup) -%} |
| {%- set interfaceName = attribute | javaAttributeCallbackName(typeLookup) -%} |
| {%- if interfaceName not in already_handled_attribute %} |
| public interface {{interfaceName}} extends BaseAttributeCallback { |
| void onSuccess({{encode_value_without_optional(cluster, encodable, 0)}} value); |
| } |
| {% if already_handled_attribute.append(interfaceName) -%} |
| {#- This block does nothing, it only exists to append to already_handled_attribute. -#} |
| {%- endif -%} |
| {%- endif -%} |
| {% endfor -%} |
| {% for attribute in cluster.attributes | sort(attribute='code') -%} |
| {%- if attribute | isFabricScopedList(typeLookup) %} |
| public void read{{attribute.definition.name | upfirst}}Attribute( |
| {{attribute | javaAttributeCallbackName(typeLookup) }} callback) { |
| read{{attribute.definition.name | upfirst}}AttributeWithFabricFilter(callback, true); |
| } |
| |
| public void read{{attribute.definition.name | upfirst}}AttributeWithFabricFilter( |
| {{attribute | javaAttributeCallbackName(typeLookup) }} callback, boolean isFabricFiltered) { |
| {%- else %} |
| public void read{{attribute.definition.name | upfirst}}Attribute( |
| {{attribute | javaAttributeCallbackName(typeLookup) }} callback) { |
| {%- endif %} |
| ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, {{attribute.definition.name | constcase}}_ATTRIBUTE_ID); |
| |
| readAttribute(new ReportCallbackImpl(callback, path) { |
| @Override |
| public void onSuccess(byte[] tlv) { |
| {%- set encodable = attribute.definition | asEncodable(typeLookup) %} |
| {{encode_value_without_optional(cluster, encodable, 0)}} value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); |
| callback.onSuccess(value); |
| } |
| }, {{attribute.definition.name | constcase}}_ATTRIBUTE_ID, {% if attribute | isFabricScopedList(typeLookup) -%}isFabricFiltered{%- else -%}true{%- endif -%}); |
| } |
| {% if attribute.is_writable %} |
| {%- set encodable = attribute.definition | asEncodable(typeLookup) -%} |
| {%- set encodable2 = attribute.definition | asEncodable(typeLookup) -%} |
| {%- set encodable3 = attribute.definition | asEncodable(typeLookup) -%} |
| {%- if not attribute.requires_timed_write %} |
| public void write{{attribute.definition.name | upfirst}}Attribute(DefaultClusterCallback callback, {{encode_value_without_optional_nullable(cluster, encodable, 0)}} value) { |
| write{{attribute.definition.name | upfirst}}Attribute(callback, value, 0); |
| } |
| {% endif %} |
| public void write{{attribute.definition.name | upfirst}}Attribute(DefaultClusterCallback callback, {{encode_value_without_optional_nullable(cluster, encodable2, 0)}} value, int timedWriteTimeoutMs) { |
| {%- if encodable3.is_optional %} |
| BaseTLVType tlvValue = {{encode_tlv(cluster, encodable3.without_optional(), "value", 0)}}; |
| {%- else %} |
| BaseTLVType tlvValue = {{encode_tlv(cluster, encodable3, "value", 0)}}; |
| {%- endif %} |
| writeAttribute(new WriteAttributesCallbackImpl(callback), {{attribute.definition.name | constcase}}_ATTRIBUTE_ID, tlvValue, timedWriteTimeoutMs); |
| } |
| {% endif %} |
| {%- if attribute.is_subscribable %} |
| public void subscribe{{attribute.definition.name | upfirst}}Attribute( |
| {{attribute | javaAttributeCallbackName(typeLookup) }} callback, int minInterval, int maxInterval) { |
| ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, {{attribute.definition.name | constcase}}_ATTRIBUTE_ID); |
| |
| subscribeAttribute(new ReportCallbackImpl(callback, path) { |
| @Override |
| public void onSuccess(byte[] tlv) { |
| {%- set encodable = attribute.definition | asEncodable(typeLookup) %} |
| {{encode_value_without_optional(cluster, encodable, 0)}} value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); |
| callback.onSuccess(value); |
| } |
| }, {{attribute.definition.name | constcase}}_ATTRIBUTE_ID, minInterval, maxInterval); |
| } |
| {% endif -%} |
| {%- endfor -%} |
| {% raw %} } |
| {% endraw %} |
| {%- endfor -%} |
| } |