]> git.basschouten.com Git - openhab-addons.git/blob
0fad90fb09251750fa11ed03235627c0f639e16d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.satel.internal.event;
14
15 import java.util.BitSet;
16 import java.util.HashMap;
17 import java.util.Map;
18 import java.util.Objects;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.satel.internal.types.StateType;
22
23 /**
24  * Event class describing current state of zones/partitions/outputs/doors/troubles.
25  *
26  * @author Krzysztof Goworek - Initial contribution
27  */
28 @NonNullByDefault
29 public class IntegraStateEvent implements SatelEvent {
30
31     private byte command;
32     private BitSet stateBits;
33     private boolean extendedData;
34     private Map<StateType, BitSet> stateBitsMap = new HashMap<>();
35
36     /**
37      * Constructs new event instance from given state type and state bits.
38      *
39      * @param command the command byte
40      * @param stateBits state bits as byte array
41      * @param extendedData whether state bits are for extended command
42      */
43     public IntegraStateEvent(byte command, byte[] stateBits, boolean extendedData) {
44         this.command = command;
45         this.stateBits = BitSet.valueOf(stateBits);
46         this.extendedData = extendedData;
47     }
48
49     /**
50      * Checks whether data in the event is valid for given type of state.
51      *
52      * @param stateType state type
53      * @return <code>true</code> if this event is valid for given stae
54      */
55     public boolean hasDataForState(StateType stateType) {
56         return stateType.getRefreshCommand() == this.command;
57     }
58
59     /**
60      * Returns state bits as {@link BitSet}.
61      *
62      * @param stateType type of state
63      * @return bits for given state
64      * @throws IllegalArgumentException when wrong state type given
65      */
66     public BitSet getStateBits(StateType stateType) {
67         if (!hasDataForState(stateType)) {
68             throw new IllegalArgumentException("Event does not have data for " + stateType);
69         }
70         int bitsCount = stateType.getBytesCount(extendedData) * 8;
71         // whole payload is a single state
72         if (stateType.getStartByte() == 0 && bitsCount == stateBits.size()) {
73             return stateBits;
74         }
75         return Objects.requireNonNull(stateBitsMap.computeIfAbsent(stateType, k -> {
76             int startBit = k.getStartByte() * 8;
77             return stateBits.get(startBit, startBit + bitsCount);
78         }));
79     }
80
81     /**
82      * Returns <code>true</code> if specified state bit is set for given state.
83      *
84      * @param stateType type of state
85      * @param nbr state bit number
86      * @return <code>true</code> if state bit is set
87      */
88     public boolean isSet(StateType stateType, int nbr) {
89         return getStateBits(stateType).get(nbr);
90     }
91
92     /**
93      * Returns number of state bits that are active for given state.
94      *
95      * @param stateType type of state
96      * @return number of active states
97      */
98     public int statesSet(StateType stateType) {
99         return getStateBits(stateType).cardinality();
100     }
101
102     @Override
103     public String toString() {
104         return String.format("IntegraStateEvent: command = %02X, extended = %b, active = %s", command, extendedData,
105                 stateBits);
106     }
107 }