-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[rfxcom] Add support for receiving RAW messages #10833
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/** | ||
* Copyright (c) 2010-2021 Contributors to the openHAB project | ||
* | ||
* See the NOTICE file(s) distributed with this work for additional | ||
* information. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0 | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*/ | ||
package org.openhab.binding.rfxcom.internal.messages; | ||
|
||
import static org.openhab.binding.rfxcom.internal.RFXComBindingConstants.*; | ||
import static org.openhab.binding.rfxcom.internal.messages.RFXComBaseMessage.PacketType.RAW; | ||
|
||
import java.nio.ByteBuffer; | ||
|
||
import org.openhab.binding.rfxcom.internal.exceptions.RFXComException; | ||
import org.openhab.binding.rfxcom.internal.exceptions.RFXComMessageTooLongException; | ||
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedChannelException; | ||
import org.openhab.binding.rfxcom.internal.exceptions.RFXComUnsupportedValueException; | ||
import org.openhab.binding.rfxcom.internal.handler.DeviceState; | ||
import org.openhab.core.library.types.StringType; | ||
import org.openhab.core.types.State; | ||
import org.openhab.core.types.Type; | ||
import org.openhab.core.util.HexUtils; | ||
|
||
/** | ||
* RFXCOM data class for raw messages. | ||
* | ||
* @author James Hewitt-Thomas - New addition to the PRO RFXCom firmware | ||
*/ | ||
public class RFXComRawMessage extends RFXComDeviceMessageImpl<RFXComRawMessage.SubType> { | ||
|
||
public enum SubType implements ByteEnumWrapper { | ||
RAW_PACKET1(0x00), | ||
RAW_PACKET2(0x01), | ||
RAW_PACKET3(0x02), | ||
RAW_PACKET4(0x03), | ||
|
||
UNKNOWN(0xFF); | ||
|
||
private final int subType; | ||
|
||
SubType(int subType) { | ||
this.subType = subType; | ||
} | ||
|
||
@Override | ||
public byte toByte() { | ||
return (byte) subType; | ||
} | ||
|
||
public static SubType fromByte(int input) { | ||
for (SubType c : SubType.values()) { | ||
if (c.subType == input) { | ||
return c; | ||
} | ||
} | ||
|
||
return SubType.UNKNOWN; | ||
} | ||
} | ||
|
||
public SubType subType; | ||
public byte repeat; | ||
public short[] pulses; | ||
|
||
public RFXComRawMessage() { | ||
super(RAW); | ||
pulses = new short[0]; | ||
} | ||
|
||
public RFXComRawMessage(byte[] message) throws RFXComException { | ||
encodeMessage(message); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
String str = super.toString(); | ||
|
||
str += ", Sub type = " + subType; | ||
|
||
return str; | ||
} | ||
|
||
@Override | ||
public void encodeMessage(byte[] message) throws RFXComException { | ||
super.encodeMessage(message); | ||
|
||
final int pulsesByteLen = rawMessage.length - 5; | ||
if (pulsesByteLen % 4 != 0) { | ||
throw new RFXComException("Incorrect byte length for pulses - must be divisible by 4"); | ||
} | ||
|
||
subType = SubType.fromByte(super.subType); | ||
repeat = rawMessage[4]; | ||
pulses = new short[pulsesByteLen / 2]; | ||
ByteBuffer.wrap(rawMessage, 5, rawMessage.length - 5).asShortBuffer().get(pulses); | ||
} | ||
|
||
@Override | ||
public byte[] decodeMessage() throws RFXComException { | ||
if (pulses.length > 124) { | ||
throw new RFXComMessageTooLongException("Longest payload according to RFXtrx SDK is 124 shorts."); | ||
} | ||
|
||
final int pulsesByteLen = pulses.length * 2; | ||
byte[] data = new byte[5 + pulsesByteLen]; | ||
|
||
data[0] = (byte) (data.length - 1); | ||
data[1] = RAW.toByte(); | ||
data[2] = subType.toByte(); | ||
data[3] = seqNbr; | ||
data[4] = repeat; | ||
|
||
ByteBuffer.wrap(data, 5, pulsesByteLen).asShortBuffer().put(pulses); | ||
|
||
return data; | ||
} | ||
|
||
@Override | ||
public String getDeviceId() { | ||
return "RAW"; | ||
} | ||
|
||
@Override | ||
public State convertToState(String channelId, DeviceState deviceState) throws RFXComUnsupportedChannelException { | ||
switch (channelId) { | ||
case CHANNEL_RAW_MESSAGE: | ||
return new StringType(HexUtils.bytesToHex(rawMessage)); | ||
|
||
case CHANNEL_RAW_PAYLOAD: | ||
byte[] payload = new byte[pulses.length * 2]; | ||
ByteBuffer.wrap(payload).asShortBuffer().put(pulses); | ||
return new StringType(HexUtils.bytesToHex(payload)); | ||
|
||
default: | ||
throw new RFXComUnsupportedChannelException("Nothing relevant for " + channelId); | ||
} | ||
} | ||
|
||
@Override | ||
public void setSubType(SubType subType) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
@Override | ||
public void setDeviceId(String deviceId) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
@Override | ||
public void convertFromState(String channelId, Type type) throws RFXComUnsupportedChannelException { | ||
switch (channelId) { | ||
case CHANNEL_RAW_MESSAGE: | ||
if (type instanceof StringType) { | ||
// TODO: Check the raw message for validity (length, no more than 124 shorts, multiple of 4 bytes in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a TODO, what should be done and can it be completed before merging the PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is really a TODO for when I implement tx, which is next. There is value in merging rx. |
||
// payload) | ||
throw new RFXComUnsupportedChannelException("Channel " + channelId + " inot yet implemented"); | ||
} else { | ||
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type); | ||
} | ||
|
||
case CHANNEL_RAW_PAYLOAD: | ||
if (type instanceof StringType) { | ||
// TODO: Check the payload for validity (no more than 124 shorts, multiple of 4 bytes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a TODO, what should be done and can it be completed before merging the PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is really a TODO for when I implement tx, which is next. There is value in merging rx. |
||
throw new RFXComUnsupportedChannelException("Channel " + channelId + " not yet implemented"); | ||
} else { | ||
throw new RFXComUnsupportedChannelException("Channel " + channelId + " does not accept " + type); | ||
} | ||
|
||
default: | ||
throw new RFXComUnsupportedChannelException("Channel " + channelId + " is not relevant here"); | ||
} | ||
} | ||
|
||
@Override | ||
public SubType convertSubType(String subType) throws RFXComUnsupportedValueException { | ||
return ByteEnumUtil.convertSubType(SubType.class, subType); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<thing:thing-descriptions bindingId="rfxcom" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0" | ||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> | ||
|
||
<thing-type id="raw"> | ||
<supported-bridge-type-refs> | ||
<bridge-type-ref id="bridge"/> | ||
<bridge-type-ref id="tcpbridge"/> | ||
<bridge-type-ref id="RFXtrx433"/> | ||
<bridge-type-ref id="RFXrec433"/> | ||
</supported-bridge-type-refs> | ||
|
||
<label>RFXCOM Raw Messages</label> | ||
<description>Raw messages.</description> | ||
|
||
<channels> | ||
<channel id="rawMessage" typeId="rawmessage"/> | ||
<channel id="rawPayload" typeId="rawpayload"/> | ||
</channels> | ||
|
||
<config-description> | ||
<parameter name="deviceId" type="text" required="true"> | ||
<label>Device Id</label> | ||
<description>Raw items cannot provide a device ID, so this value is always RAW.</description> | ||
</parameter> | ||
<parameter name="subType" type="text" required="true"> | ||
<label>Sub Type</label> | ||
<description>Specifies device sub type.</description> | ||
<options> | ||
<option value="RAW_PACKET1">RAW_PACKET1</option> | ||
<option value="RAW_PACKET2">RAW_PACKET2</option> | ||
<option value="RAW_PACKET3">RAW_PACKET3</option> | ||
<option value="RAW_PACKET4">RAW_PACKET4</option> | ||
</options> | ||
</parameter> | ||
</config-description> | ||
</thing-type> | ||
|
||
</thing:thing-descriptions> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just out of curiosity what is the difference with
undecoded
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UNDECODED is where the RFXCOM understands the type, but just hasn't broken it down into values. RAW is where the RFXCOM has received an RF message and hasn't tried to do anything to it at all, so the values are the ms pulse timings that would need to be processed into stable bytes before they could even be decoded.