2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.satel.internal.event;
15 import java.util.BitSet;
16 import java.util.HashMap;
18 import java.util.Objects;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.satel.internal.types.StateType;
24 * Event class describing current state of zones/partitions/outputs/doors/troubles.
26 * @author Krzysztof Goworek - Initial contribution
29 public class IntegraStateEvent implements SatelEvent {
32 private BitSet stateBits;
33 private boolean extendedData;
34 private Map<StateType, BitSet> stateBitsMap = new HashMap<>();
37 * Constructs new event instance from given state type and state bits.
39 * @param command the command byte
40 * @param stateBits state bits as byte array
41 * @param extendedData whether state bits are for extended command
43 public IntegraStateEvent(byte command, byte[] stateBits, boolean extendedData) {
44 this.command = command;
45 this.stateBits = BitSet.valueOf(stateBits);
46 this.extendedData = extendedData;
50 * Checks whether data in the event is valid for given type of state.
52 * @param stateType state type
53 * @return <code>true</code> if this event is valid for given stae
55 public boolean hasDataForState(StateType stateType) {
56 return stateType.getRefreshCommand() == this.command;
60 * Returns state bits as {@link BitSet}.
62 * @param stateType type of state
63 * @return bits for given state
64 * @throws IllegalArgumentException when wrong state type given
66 public BitSet getStateBits(StateType stateType) {
67 if (!hasDataForState(stateType)) {
68 throw new IllegalArgumentException("Event does not have data for " + stateType);
70 int bitsCount = stateType.getBytesCount(extendedData) * 8;
71 // whole payload is a single state
72 if (stateType.getStartByte() == 0 && bitsCount == stateBits.size()) {
75 return Objects.requireNonNull(stateBitsMap.computeIfAbsent(stateType, k -> {
76 int startBit = k.getStartByte() * 8;
77 return stateBits.get(startBit, startBit + bitsCount);
82 * Returns <code>true</code> if specified state bit is set for given state.
84 * @param stateType type of state
85 * @param nbr state bit number
86 * @return <code>true</code> if state bit is set
88 public boolean isSet(StateType stateType, int nbr) {
89 return getStateBits(stateType).get(nbr);
93 * Returns number of state bits that are active for given state.
95 * @param stateType type of state
96 * @return number of active states
98 public int statesSet(StateType stateType) {
99 return getStateBits(stateType).cardinality();
103 public String toString() {
104 return String.format("IntegraStateEvent: command = %02X, extended = %b, active = %s", command, extendedData,