├── .gitignore
├── JenkinsFile
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── nu
│ └── nethome
│ └── coders
│ ├── RollerTrol.java
│ ├── RollerTrolG.java
│ ├── decoders
│ ├── CRC8.java
│ ├── CRC8Table.java
│ ├── Decoders.java
│ ├── DeltronicDecoder.java
│ ├── EmotivaDecoder.java
│ ├── FineOffsetDecoder.java
│ ├── HKDecoder.java
│ ├── JVCDecoder.java
│ ├── NexaDecoder.java
│ ├── NexaFireDecoder.java
│ ├── NexaLDecoder.java
│ ├── OregonDecoder.java
│ ├── PioneerDecoder.java
│ ├── PrologueDecoder.java
│ ├── ProntoDecoder.java
│ ├── RC5Decoder.java
│ ├── RC6Decoder.java
│ ├── RisingSunDecoder.java
│ ├── RollerTrolDecoder.java
│ ├── RollerTrolGDecoder.java
│ ├── SIRCDecoder.java
│ ├── UPMDecoder.java
│ ├── ViasatDecoder.java
│ ├── WavemanDecoder.java
│ ├── X10Decoder.java
│ └── ZhejiangDecoder.java
│ └── encoders
│ ├── DeltronicEncoder.java
│ ├── EmotivaEncoder.java
│ ├── Encoders.java
│ ├── NexaEncoder.java
│ ├── NexaFireEncoder.java
│ ├── NexaLEncoder.java
│ ├── ProntoEncoder.java
│ ├── RisingSunEncoder.java
│ ├── RollerTrolEncoder.java
│ ├── RollerTrolGEncoder.java
│ ├── ShortBeepEncoder.java
│ ├── WavemanEncoder.java
│ ├── X10Encoder.java
│ └── ZhejiangEncoder.java
└── test
├── java
└── nu
│ └── nethome
│ └── coders
│ ├── decoders
│ ├── EmotivaDecoderTest.java
│ ├── FineOffsetDecoderTest.java
│ ├── OregonDecoderTest.java
│ ├── PrologueDecoderTest.java
│ ├── RisingSunDecoderTest.java
│ ├── RollerTrolDecoderTest.java
│ ├── RollerTrolGDecoderTest.java
│ ├── TestDeltronicDecoderEncoder.java
│ ├── TestNexaDecoder.java
│ ├── TestNexaFire.java
│ ├── TestNexaLDecoder.java
│ ├── TestProntoDecoder.java
│ ├── TestWaveman.java
│ ├── TestX10Decoder.java
│ ├── ZhejiangDecoderTest.java
│ └── util
│ │ └── JirFileTestPlayer.java
│ └── encoders
│ └── RollerTrolEncoderTest.java
└── resources
└── nu
└── nethome
└── coders
└── decoders
├── fine_offset.jir
├── fine_offset_neg.jir
├── nexa1.jir
├── nexa_fire.jir
├── nexal1.jir
├── nexal_dn.jir
├── oregon1.jir
├── prologue.jir
└── rollertrol_3_stop.jir
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | #IDEA
3 | target
4 | *.iml
5 | *.ipr
6 | *.iws
7 |
8 | *.class
9 | # Package Files #
10 | *.jar
11 | *.war
12 | *.ear
13 |
--------------------------------------------------------------------------------
/JenkinsFile:
--------------------------------------------------------------------------------
1 | #!groovy
2 |
3 | node {
4 | withEnv(["JAVA_HOME=${ tool 'Java8' }", "PATH+MAVEN=${tool 'Maven3'}/bin:${env.JAVA_HOME}/bin"]) {
5 | stage('Checkout') {
6 | git url: 'https://github.com/NetHome/Coders.git'
7 | }
8 | stage('Build') {
9 | sh "mvn --batch-mode -V -U -e clean install -Dsurefire.useFile=false"
10 | }
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Coders
2 | ======
3 | Encoders and Decoders for RF and IR protocols used for remote control and data acquisition.
4 | Both Encoders and Decoders can be supplied as plugins in the NetHome server to support new protocols.
5 | They can also be used as plugins in the ProtocolAnalyzer tool, which is designed to aid in reverse engineering of
6 | simple pulse length based protocols.
7 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 | coders
7 | nu.nethome
8 | 1.2
9 | coders
10 | http://www.nethome.nu
11 |
12 | UTF-8
13 |
14 |
15 | ${project.artifactId}
16 |
17 |
18 |
19 | org.apache.maven.plugins
20 | maven-compiler-plugin
21 | 2.3.2
22 |
23 | 1.6
24 | 1.6
25 |
26 |
27 |
28 | org.apache.maven.plugins
29 | maven-source-plugin
30 |
31 |
32 | attach-sources
33 |
34 | jar
35 |
36 |
37 |
38 |
39 |
40 | org.apache.maven.plugins
41 | maven-javadoc-plugin
42 |
43 |
44 | attach-javadocs
45 |
46 | jar
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | org.rxtx
56 | rxtx
57 | 2.1.7
58 |
59 |
60 | junit
61 | junit
62 | 4.8.1
63 | test
64 |
65 |
66 | org.mockito
67 | mockito-all
68 | 1.8.5
69 | test
70 |
71 |
72 | org.hamcrest
73 | hamcrest-all
74 | 1.1
75 | test
76 |
77 |
78 | nu.nethome
79 | utils
80 | 1.1
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/RollerTrol.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders;
2 |
3 | import nu.nethome.coders.decoders.RollerTrolDecoder;
4 | import nu.nethome.util.ps.BitString;
5 | import nu.nethome.util.ps.ProtocolInfo;
6 | import nu.nethome.util.ps.PulseLength;
7 |
8 | /**
9 | * Constants for the RollerTrol protocol
10 | *
11 | * My current understanding of the protocol is:
12 | *
13 | * h = House Code
14 | * d = Device Code (Channel)
15 | * c = Command
16 | * s = Check Sum
17 | *
18 | * Message is sent LSB first
19 | *
20 | * ____Byte 4_____ ____Byte 3_____ ____Byte 2_____ ____Byte 1_____ ____Byte 0_____
21 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
22 | * s s s s s s s s 0 0 0 0 0 0 0 1 c c c c d d d d h h h h h h h h h h h h h h h h
23 | */
24 |
25 |
26 | public class RollerTrol {
27 | public static final String ROLLER_TROL_PROTOCOL_NAME = "RollerTrol";
28 | public static final ProtocolInfo ROLLERTROL_PROTOCOL_INFO = new ProtocolInfo(ROLLER_TROL_PROTOCOL_NAME, "Mark Length", "RollerTrol", 40, 1);
29 | public static final int MESSAGE_BIT_LENGTH = 40;
30 |
31 | // This are the pulse length constants for the protocol. The default values may
32 | // be overridden by system properties
33 | public static final PulseLength LONG_PREAMBLE_MARK =
34 | new PulseLength(RollerTrolDecoder.class, "LONG_PREAMBLE_MARK", 4885, 4000, 5000);
35 | public static final PulseLength LONG_PREAMBLE_SPACE =
36 | new PulseLength(RollerTrolDecoder.class, "LONG_PREAMBLE_SPACE", 2450, 2300, 2600);
37 | public static final PulseLength SHORT_PREAMBLE_MARK =
38 | new PulseLength(RollerTrolDecoder.class, "SHORT_PREAMBLE_MARK", 1650, 1500, 1800);
39 | public static final PulseLength SHORT =
40 | new PulseLength(RollerTrolDecoder.class, "SHORT", 300, 200, 490);
41 | public static final PulseLength LONG =
42 | new PulseLength(RollerTrolDecoder.class, "LONG", 600, 500, 800);
43 | public static final PulseLength SHORT_MARK =
44 | new PulseLength(RollerTrolDecoder.class, "SHORT_MARK", 500, 300, 700);
45 |
46 | public static final PulseLength SPACE =
47 | new PulseLength(RollerTrolDecoder.class, "SPACE", 1000, 800, 1200);
48 | // These are the fields in the binary message
49 | public static final BitString.Field HOUSE_CODE = new BitString.Field(0, 16);
50 | public static final BitString.Field DEVICE_CODE = new BitString.Field(16, 4);
51 | public static final BitString.Field COMMAND = new BitString.Field(20, 4);
52 | public static final BitString.Field CHECK_SUM = new BitString.Field(32, 8);
53 | public static final BitString.Field CONSTANT_FIELD = new BitString.Field(24, 8);
54 |
55 | // Message field names
56 | public static final String HOUSE_CODE_NAME = "HouseCode";
57 | public static final String COMMAND_NAME = "Command";
58 | public static final String DEVICE_CODE_NAME = "DeviceCode";
59 |
60 | // Commands
61 | public static final int UP = 12;
62 | public static final int STOP = 5;
63 | public static final int DOWN = 1;
64 | public static final int REVERSE = 8;
65 | public static final int LIMIT = 3;
66 | public static final int CONFIRM = 4;
67 | public static final int ALL_CHANNELS = 15;
68 |
69 | public static int calculateChecksum(BitString binaryMessage) {
70 | int calculatedCheckSum = binaryMessage.extractInt(RollerTrolDecoder.BYTE0) +
71 | binaryMessage.extractInt(RollerTrolDecoder.BYTE1) +
72 | binaryMessage.extractInt(RollerTrolDecoder.BYTE2) +
73 | binaryMessage.extractInt(RollerTrolDecoder.BYTE3);
74 | calculatedCheckSum = (((calculatedCheckSum / 256) + 1) * 256 + 1) - calculatedCheckSum;
75 | return calculatedCheckSum;
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/RollerTrolG.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders;
2 |
3 | import nu.nethome.coders.decoders.RollerTrolGDecoder;
4 | import nu.nethome.util.ps.BitString;
5 | import nu.nethome.util.ps.ProtocolInfo;
6 | import nu.nethome.util.ps.PulseLength;
7 |
8 | public class RollerTrolG {
9 | public static final String ROLLER_TROL_G_PROTOCOL_NAME = "RollerTrolG";
10 | public static final int PROTOCOL_BIT_LENGTH = 40;
11 | public static final ProtocolInfo ROLLERTROL_PROTOCOL_INFO = new ProtocolInfo(ROLLER_TROL_G_PROTOCOL_NAME, "Mark Length", "RollerTrol", PROTOCOL_BIT_LENGTH, 1);
12 |
13 | public static final int COMMAND_STOP = 0x55;
14 | public static final int COMMAND_UP = 0x11;
15 | public static final int COMMAND_UP_END = 0x1E;
16 | public static final int COMMAND_DOWN = 0x33;
17 | public static final int COMMAND_DOWN_END = 0x3C;
18 | public static final int COMMAND_LEARN = 0xCC;
19 |
20 | public static final PulseLength LONG_PREAMBLE_MARK =
21 | new PulseLength(RollerTrolGDecoder.class, "LONG_PREAMBLE_MARK", 5170, 4000, 5900);
22 | public static final PulseLength LONG_PREAMBLE_SPACE =
23 | new PulseLength(RollerTrolGDecoder.class, "LONG_PREAMBLE_SPACE", 1665, 1000, 2000);
24 | public static final PulseLength SHORT =
25 | new PulseLength(RollerTrolGDecoder.class, "SHORT", 360, 200, 500);
26 | public static final PulseLength LONG =
27 | new PulseLength(RollerTrolGDecoder.class, "LONG", 770, 600, 900);
28 | public static final PulseLength REPEAT_SPACE =
29 | new PulseLength(RollerTrolGDecoder.class, "REPEAT_SPACE", 7400, 7000, 11000);
30 |
31 | public static final BitString.Field COMMAND = new BitString.Field(0, 8);
32 | public static final BitString.Field CHANNEL = new BitString.Field(8, 4);
33 | public static final BitString.Field ADDRESS = new BitString.Field(12, 28);
34 | public static final String COMMAND_NAME = "Command";
35 | public static final String CHANNEL_NAME = "Channel";
36 | public static final String ADDRESS_NAME = "Address";
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/CRC8.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 |
6 | public interface CRC8 {
7 |
8 | /**
9 | * Calculates a CRC8 from the given data block.
10 | * @param block the array from which the CRC is calculated
11 | * @param from the initial index of the range to be copied, inclusive
12 | * @param to the final index of the range to be copied, exclusive. (This index may lie outside the array.)
13 | * @return the calculated CRC8 (8-bit)
14 | */
15 | public abstract int calc(byte[] block, int from, int to);
16 |
17 | /**
18 | * Calculates a CRC8 from the given data block.
19 | * @param block the array from which the CRC is calculated
20 | * @param from the initial index of the range to be copied, inclusive
21 | * @param to the final index of the range to be copied, exclusive. (This index may lie outside the array.)
22 | * @param initial the initial CRC value (normally 0)
23 | * @return the calculated CRC8 (8-bit)
24 | */
25 | public abstract int calc(byte[] block, int from, int to, int initial);
26 |
27 | /**
28 | * Calculates a CRC8 from the given data block.
29 | * @param block the array from which the CRC is calculated
30 | * @param initial the initial CRC value (normally 0)
31 | * @return the calculated CRC8 (8-bit)
32 | */
33 | public abstract int calc(byte[] block, int initial);
34 |
35 | /**
36 | * Calculates a CRC8 from the given data block.
37 | * @param block the array from which the CRC is calculated
38 | * @return the calculated CRC8 (8-bit)
39 | */
40 | public abstract int calc(byte[] block);
41 |
42 | /**
43 | * Calculates a CRC8 from the given InputStream.
44 | * @param stream the stream to calculate the CRC8 from
45 | * @return the calculated CRC8 (8-bit)
46 | * @throws IOException if an I/O error occurs
47 | */
48 | public abstract int calc(InputStream stream) throws IOException;
49 |
50 | /**
51 | * Calculates a CRC8 from the given InputStream.
52 | * @param stream the stream to calculate the CRC8 from
53 | * @param initial the initial CRC value (normally 0)
54 | * @return the calculated CRC8 (8-bit)
55 | * @throws IOException if an I/O error occurs
56 | */
57 | public abstract int calc(InputStream stream, int initial)
58 | throws IOException;
59 |
60 | /**
61 | * Calculates a CRC8 from the given InputStream. Note that this function may return before count has been reached if an end of stream occurred.
62 | * @param stream the stream to calculate the CRC8 from
63 | * @param length the number of bytes to read
64 | * @param initial the initial CRC value (normally 0)
65 | * @return the calculated CRC8 (8-bit)
66 | * @throws IOException if an I/O error occurs
67 | */
68 | public abstract int calc(InputStream stream, int length, int initial)
69 | throws IOException;
70 | }
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/CRC8Table.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 |
6 | public class CRC8Table implements CRC8 {
7 |
8 | private final int[] table;
9 |
10 | public CRC8Table(int polynomial) {
11 | table = generateTable(polynomial);
12 | }
13 |
14 | public CRC8Table(int[] table) {
15 | this.table = table;
16 | }
17 |
18 | public static byte[] compress(int[] table) {
19 | byte[] tmp = new byte[table.length];
20 | for (int i = 0; i < table.length; ++i) {
21 | tmp[i] = (byte) table[i];
22 | }
23 | return tmp;
24 | }
25 |
26 | public static int[] decompress(byte[] table) {
27 | int[] tmp = new int[table.length];
28 | for (int i = 0; i < table.length; ++i) {
29 | tmp[i] = table[i] & 0xFF;
30 | }
31 | return tmp;
32 | }
33 |
34 | private static int pushByte(int b, int polynomial) {
35 | for (int i = 0; i < 8; ++i) {
36 | if ((b & 0x80) != 0) {
37 | int step1 = b << 1;
38 | b = step1 ^ polynomial;
39 | } else {
40 | b = b << 1;
41 | }
42 | }
43 | return b & 0xFF;
44 | }
45 |
46 | /**
47 | * Creates a CRC8 table given a polynomial.
48 | *
49 | * @param polynomial
50 | * @return
51 | */
52 | public static int[] generateTable(int polynomial) {
53 | int[] table = new int[256];
54 | for (int i = 0; i < 256; ++i) {
55 | table[i] = pushByte(i, polynomial);
56 | }
57 | return table;
58 | }
59 |
60 | private int calcImpl(byte[] block, int from, int to, int initial) {
61 | int crc = initial;
62 | for (int i = from; i < to; ++i) {
63 | crc = getTable()[crc ^ (block[i] & 0xFF)];
64 | }
65 | return crc;
66 | }
67 |
68 | /* (non-Javadoc)
69 | * @see CRC8#calc(byte[], int, int)
70 | */
71 | @Override
72 | public int calc(byte[] block, int from, int to) {
73 | return calcImpl(block, from, to, 0);
74 | }
75 |
76 | /* (non-Javadoc)
77 | * @see CRC8#calc(byte[], int, int, int)
78 | */
79 | @Override
80 | public int calc(byte[] block, int from, int to, int initial) {
81 | return calcImpl(block, from, to, initial);
82 | }
83 |
84 | /* (non-Javadoc)
85 | * @see CRC8#calc(byte[], int)
86 | */
87 | @Override
88 | public int calc(byte[] block, int initial) {
89 | return calcImpl(block, 0, block.length, initial);
90 | }
91 |
92 | /* (non-Javadoc)
93 | * @see CRC8#calc(byte[])
94 | */
95 | @Override
96 | public int calc(byte[] block) {
97 | return calc(block, 0, block.length, 0);
98 | }
99 |
100 | /* (non-Javadoc)
101 | * @see CRC8#calc(java.io.InputStream)
102 | */
103 | @Override
104 | public int calc(InputStream stream) throws IOException {
105 | return calc(stream, 0);
106 | }
107 |
108 | /* (non-Javadoc)
109 | * @see CRC8#calc(java.io.InputStream, int)
110 | */
111 | @Override
112 | public int calc(InputStream stream, int initial) throws IOException {
113 | int b;
114 | int crc = initial;
115 | while ((b = stream.read()) != -1) {
116 | crc = getTable()[crc ^ (b & 0xFF)];
117 | }
118 | return crc;
119 | }
120 |
121 | /* (non-Javadoc)
122 | * @see CRC8#calc(java.io.InputStream, int, int)
123 | */
124 | @Override
125 | public int calc(InputStream stream, int length, int initial) throws IOException {
126 | int b;
127 | int crc = initial;
128 | for (int i = 0; (b = stream.read()) != -1 || i < length; ++i) {
129 | crc = getTable()[crc ^ (b & 0xFF)];
130 | }
131 | return crc;
132 | }
133 |
134 | public int[] getTable() {
135 | return table;
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/Decoders.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.ps.ProtocolDecoder;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Collection;
26 |
27 | public class Decoders {
28 | public static Collection> getAllTypes() {
29 | Collection> result = new ArrayList>();
30 | result.add(DeltronicDecoder.class);
31 | result.add(EmotivaDecoder.class);
32 | result.add(HKDecoder.class);
33 | result.add(JVCDecoder.class);
34 | result.add(NexaDecoder.class);
35 | result.add(NexaFireDecoder.class);
36 | result.add(NexaLDecoder.class);
37 | result.add(PioneerDecoder.class);
38 | result.add(ProntoDecoder.class);
39 | result.add(RC5Decoder.class);
40 | result.add(RC6Decoder.class);
41 | result.add(RisingSunDecoder.class);
42 | result.add(SIRCDecoder.class);
43 | result.add(UPMDecoder.class);
44 | result.add(ViasatDecoder.class);
45 | result.add(WavemanDecoder.class);
46 | result.add(X10Decoder.class);
47 | result.add(ZhejiangDecoder.class);
48 | result.add(OregonDecoder.class);
49 | result.add(FineOffsetDecoder.class);
50 | result.add(RollerTrolDecoder.class);
51 | result.add(RollerTrolGDecoder.class);
52 | result.add(PrologueDecoder.class);
53 | return result;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/EmotivaDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.FieldValue;
24 | import nu.nethome.util.ps.ProtocolDecoder;
25 | import nu.nethome.util.ps.ProtocolInfo;
26 | import nu.nethome.util.ps.ProtocolMessage;
27 |
28 | @Plugin
29 | public class EmotivaDecoder extends PioneerDecoder implements ProtocolDecoder {
30 |
31 | protected int addressLo = 0;
32 | protected int addressHi = 0;
33 | protected int command = 0;
34 | protected int commandChecksum = 0;
35 |
36 | public ProtocolInfo getInfo() {
37 | return new ProtocolInfo("Emotiva", "Space Length", "Emotiva", 24, 5);
38 | }
39 |
40 | protected void addBit(int b) {
41 | if (m_BitCounter < 8) {
42 | addressLo >>= 1;
43 | addressLo |= (b << 7);
44 | } else if (m_BitCounter < 16) {
45 | addressHi >>= 1;
46 | addressHi |= (b << 7);
47 | } else if (m_BitCounter < 24) {
48 | command >>= 1;
49 | command |= (b << 7);
50 | } else if (m_BitCounter < 32) {
51 | commandChecksum >>= 1;
52 | commandChecksum |= (b << 7);
53 | }
54 | // Check if this is a complete message
55 | if (m_BitCounter == 31) {
56 |
57 | // It is, verify checksum
58 | if ((command != (commandChecksum ^ 0xFF))) {
59 | // Checksum error
60 | reportPartial();
61 | m_State = IDLE;
62 | return;
63 | }
64 |
65 | ProtocolMessage message = new ProtocolMessage("Emotiva", command, addressLo + (addressHi << 8), 3);
66 | message.setRawMessageByteAt(0, addressLo);
67 | message.setRawMessageByteAt(1, addressHi);
68 | message.setRawMessageByteAt(2, command);
69 | // It is, check if this really is a repeat
70 | if ((m_RepeatCount > 0) && (addressLo == m_LastCommand) && (command == m_LastAddress)) {
71 | message.setRepeat(m_RepeatCount);
72 | } else {
73 | // It is not a repeat, reset counter
74 | m_RepeatCount = 0;
75 | }
76 | message.addField(new FieldValue("Command", command));
77 | message.addField(new FieldValue("Address", addressLo + (addressHi << 8)));
78 | // Report the parsed message
79 | m_Sink.parsedMessage(message);
80 | m_State = TRAILING_BIT;
81 | }
82 | m_BitCounter++;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/HKDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 |
26 | @Plugin
27 | public class HKDecoder implements ProtocolDecoder {
28 | protected static final int IDLE = 0;
29 | protected static final int READING_HEADER = 1;
30 | protected static final int READING_BIT_MARK = 2;
31 | protected static final int READING_BIT_SPACE = 3;
32 | protected static final int TRAILING_BIT = 4;
33 | protected static final int REPEAT_SCAN = 5;
34 | protected static final int REPEAT_HEADER_SCAN = 6;
35 | protected static final int REPEAT_BODY_SPACE_SCAN = 7;
36 | protected static final int REPEAT_BODY_MARK_SCAN = 8;
37 | protected static final int REPEAT_REPEAT_SCAN = 9;
38 |
39 | protected int m_State = IDLE;
40 |
41 | protected int m_Command = 0;
42 | protected int m_CommandCheck = 0;
43 | protected int m_Address = 0;
44 | protected int m_AddressCheck = 0;
45 |
46 | protected int m_LastCommand = 0;
47 | protected int m_LastAddress = 0;
48 |
49 | protected int m_BitCounter = 0;
50 | protected int m_RepeatCount = 0;
51 | protected ProtocolDecoderSink m_Sink = null;
52 |
53 | public void setTarget(ProtocolDecoderSink sink) {
54 | m_Sink = sink;
55 | }
56 |
57 | public ProtocolInfo getInfo() {
58 | return new ProtocolInfo("HK", "Space Length", "Harman/Kardon", 16, 5);
59 | }
60 |
61 | protected boolean pulseCompare(double candidate, double standard) {
62 | return Math.abs(standard - candidate) < standard * 0.4;
63 | }
64 |
65 | protected boolean pulseCompare(double candidate, double min, double max) {
66 | return ((candidate > min) && (candidate < max));
67 | }
68 |
69 | protected void reportPartial() {
70 | if (m_BitCounter > 0) {
71 | m_Sink.partiallyParsedMessage("HK", m_BitCounter);
72 | }
73 | }
74 |
75 | protected void addBit(int b) {
76 | if (m_BitCounter < 8) {
77 | m_Address >>= 1;
78 | m_Address |= (b << 7);
79 | }
80 | else if (m_BitCounter < 16) {
81 | m_AddressCheck >>= 1;
82 | m_AddressCheck |= (b << 7);
83 | }
84 | else if (m_BitCounter < 24) {
85 | m_Command >>= 1;
86 | m_Command |= (b << 7);
87 | }
88 | else if (m_BitCounter < 32) {
89 | m_CommandCheck >>= 1;
90 | m_CommandCheck |= (b << 7);
91 | }
92 | // Check if this is a complete message
93 | if (m_BitCounter == 31){
94 | // It is, verify checksum
95 | if (((m_Address & 0xF0) != ((m_AddressCheck ^ 0xFF) & 0xF0)) ||
96 | ((m_AddressCheck & 0x0F) != 0) ||
97 | (m_Command != (m_CommandCheck ^ 0xFF))) {
98 | // Checksum error
99 | reportPartial();
100 | m_State = IDLE;
101 | return;
102 | }
103 | ProtocolMessage message = new ProtocolMessage("HK", m_Command, m_Address, 4);
104 | message.setRawMessageByteAt(0, m_Address);
105 | message.setRawMessageByteAt(1, m_AddressCheck);
106 | message.setRawMessageByteAt(2, m_Command);
107 | message.setRawMessageByteAt(3, m_CommandCheck);
108 | message.addField(new FieldValue("Command", m_Command));
109 | message.addField(new FieldValue("Address", m_Address));
110 | // Report the parsed message
111 | m_Sink.parsedMessage(message);
112 | m_State = TRAILING_BIT;
113 | }
114 | m_BitCounter++;
115 | }
116 |
117 | /* (non-Javadoc)
118 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
119 | */
120 | public int parse(double pulse, boolean state) {
121 | switch (m_State) {
122 | case IDLE: {
123 | if (pulseCompare(pulse, 8400.0 + 60) && state) {
124 | m_State = READING_HEADER;
125 | m_Command = 0;
126 | m_Address = 0;
127 | m_CommandCheck = 0;
128 | m_AddressCheck = 0;
129 | m_BitCounter = 0;
130 | }
131 | break;
132 | }
133 | case READING_HEADER: {
134 | if (pulseCompare(pulse, 4200.0 - 60)) {
135 | m_State = READING_BIT_MARK;
136 | }
137 | else {
138 | m_State = IDLE;
139 | reportPartial();
140 | }
141 | break;
142 | }
143 | case READING_BIT_MARK: {
144 | // The mark pulse seems to vary a lot in length
145 | if (pulseCompare(pulse, 50, 700)) {
146 | m_State = READING_BIT_SPACE;
147 | }
148 | else {
149 | m_State = IDLE;
150 | reportPartial();
151 | }
152 | break;
153 | }
154 | case READING_BIT_SPACE: {
155 | if (pulseCompare(pulse, 1575.0 - 60)) {
156 | m_State = READING_BIT_MARK;
157 | addBit(1);
158 | }
159 | else if (pulseCompare(pulse, 524.0 + 60)) {
160 | m_State = READING_BIT_MARK;
161 | addBit(0);
162 | }
163 | else {
164 | m_State = IDLE;
165 | reportPartial();
166 | }
167 | break;
168 | }
169 |
170 | case TRAILING_BIT: {
171 | // The mark pulse seems to vary a lot in length
172 | if (pulseCompare(pulse, 100, 700)) {
173 | m_State = REPEAT_SCAN;
174 | }
175 | else {
176 | m_State = IDLE;
177 | }
178 | break;
179 | }
180 | case REPEAT_SCAN: {
181 | if (pulseCompare(pulse, 45000.0)) {
182 | m_State = REPEAT_HEADER_SCAN;
183 | }
184 | else {
185 | m_RepeatCount = 0;
186 | m_State = IDLE;
187 | }
188 | break;
189 | }
190 | case REPEAT_HEADER_SCAN: {
191 | if (pulseCompare(pulse, 9000.0)) {
192 | m_State = REPEAT_BODY_SPACE_SCAN;
193 | }
194 | else {
195 | m_RepeatCount = 0;
196 | m_State = IDLE;
197 | }
198 | break;
199 | }
200 | case REPEAT_BODY_SPACE_SCAN: {
201 | if (pulseCompare(pulse, 2300.0 - 60)) {
202 | m_State = REPEAT_BODY_MARK_SCAN;
203 | }
204 | else {
205 | m_RepeatCount = 0;
206 | m_State = IDLE;
207 | }
208 | break;
209 | }
210 | case REPEAT_BODY_MARK_SCAN: {
211 | if (pulseCompare(pulse, 600.0 + 60)) {
212 | m_State = REPEAT_REPEAT_SCAN;
213 | // Ok, this was arepeat stub, create a fake new message
214 | m_RepeatCount++;
215 | ProtocolMessage message = new ProtocolMessage("HK", m_Command, m_Address, 4);
216 | message.setRepeat(m_RepeatCount);
217 | message.setRawMessageByteAt(0, m_Address);
218 | message.setRawMessageByteAt(1, m_AddressCheck);
219 | message.setRawMessageByteAt(2, m_Command);
220 | message.setRawMessageByteAt(3, m_CommandCheck);
221 | message.addField(new FieldValue("Command", m_Command));
222 | message.addField(new FieldValue("Address", m_Address));
223 | // Report the parsed message
224 | m_Sink.parsedMessage(message);
225 | }
226 | else {
227 | m_RepeatCount = 0;
228 | m_State = IDLE;
229 | }
230 | break;
231 | }
232 | case REPEAT_REPEAT_SCAN: {
233 | if (pulseCompare(pulse, 95000.0)) {
234 | m_State = REPEAT_HEADER_SCAN;
235 | }
236 | else {
237 | m_RepeatCount = 0;
238 | m_State = IDLE;
239 | }
240 | break;
241 | }
242 | }
243 | return m_State;
244 | }
245 | }
246 |
247 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/JVCDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 |
26 | @Plugin
27 | public class JVCDecoder implements ProtocolDecoder {
28 | protected static final int IDLE = 0;
29 | protected static final int READING_HEADER = 1;
30 | protected static final int READING_BIT_MARK = 2;
31 | protected static final int READING_BIT_SPACE = 3;
32 | protected static final int TRAILING_BIT = 4;
33 | protected static final int REPEAT_SCAN = 5;
34 |
35 | protected int m_State = IDLE;
36 |
37 | protected int m_Command = 0;
38 | protected int m_Address = 0;
39 |
40 | protected int m_LastCommand = 0;
41 | protected int m_LastAddress = 0;
42 |
43 | protected int m_BitCounter = 0;
44 | protected int m_RepeatCount = 0;
45 | protected ProtocolDecoderSink m_Sink = null;
46 |
47 | public void setTarget(ProtocolDecoderSink sink) {
48 | m_Sink = sink;
49 | }
50 |
51 | public ProtocolInfo getInfo() {
52 | return new ProtocolInfo("JVC", "Space Length", "JVC", 16, 5);
53 | }
54 |
55 | protected boolean pulseCompare(double candidate, double standard) {
56 | return Math.abs(standard - candidate) < standard * 0.4;
57 | }
58 |
59 | protected boolean pulseCompare(double candidate, double min, double max) {
60 | return ((candidate > min) && (candidate < max));
61 | }
62 |
63 | protected void reportPartial() {
64 | if (m_BitCounter > 0) {
65 | m_Sink.partiallyParsedMessage("JVC", m_BitCounter);
66 | }
67 | }
68 |
69 | protected void addBit(int b) {
70 | if (m_BitCounter < 8) {
71 | m_Address >>= 1;
72 | m_Address |= (b << 7);
73 | }
74 | else if (m_BitCounter < 16) {
75 | m_Command >>= 1;
76 | m_Command |= (b << 7);
77 | }
78 | // Check if this is a complete message
79 | if (m_BitCounter == 15){
80 | // It is, create the message
81 | ProtocolMessage message = new ProtocolMessage("JVC", m_Command, m_Address, 2);
82 | message.setRawMessageByteAt(0, m_Command);
83 | message.setRawMessageByteAt(1, m_Address);
84 | // It is, check if this really is a repeat
85 | if ((m_RepeatCount > 0) && (m_Command == m_LastCommand) && (m_Address == m_LastAddress)) {
86 | message.setRepeat(m_RepeatCount);
87 | }
88 | else {
89 | // It is not a repeat, reset counter
90 | m_RepeatCount = 0;
91 | }
92 | message.addField(new FieldValue("Command", m_Command));
93 | message.addField(new FieldValue("Address", m_Address));
94 | // Report the parsed message
95 | m_Sink.parsedMessage(message);
96 | m_State = TRAILING_BIT;
97 | }
98 | m_BitCounter++;
99 | }
100 |
101 | /* (non-Javadoc)
102 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
103 | */
104 | public int parse(double pulse, boolean state) {
105 | switch (m_State) {
106 | case IDLE: {
107 | if (pulseCompare(pulse, 8400.0 + 60) && state) {
108 | m_State = READING_HEADER;
109 | m_Command = 0;
110 | m_Address = 0;
111 | m_BitCounter = 0;
112 | }
113 | break;
114 | }
115 | case READING_HEADER: {
116 | if (pulseCompare(pulse, 4200.0 - 60)) {
117 | m_State = READING_BIT_MARK;
118 | }
119 | else {
120 | m_State = IDLE;
121 | reportPartial();
122 | }
123 | break;
124 | }
125 | case READING_BIT_MARK: {
126 | // The mark pulse seems to vary a lot in length
127 | if (pulseCompare(pulse, 50, 700 + 60)) {
128 | m_State = READING_BIT_SPACE;
129 | }
130 | else {
131 | m_State = IDLE;
132 | reportPartial();
133 | }
134 | break;
135 | }
136 | case READING_BIT_SPACE: {
137 | if (pulseCompare(pulse, 1575.0 - 60)) {
138 | m_State = READING_BIT_MARK;
139 | addBit(1);
140 | }
141 | else if (pulseCompare(pulse, 524.0 - 60)) {
142 | m_State = READING_BIT_MARK;
143 | addBit(0);
144 | }
145 | else {
146 | m_State = IDLE;
147 | reportPartial();
148 | }
149 | break;
150 | }
151 |
152 | case TRAILING_BIT: {
153 | // The mark pulse seems to vary a lot in length
154 | if (pulseCompare(pulse, 100, 700 + 60)) {
155 | m_State = REPEAT_SCAN;
156 | }
157 | else {
158 | m_State = IDLE;
159 | }
160 | break;
161 | }
162 | case REPEAT_SCAN: {
163 | if (pulseCompare(pulse, 16000.0, 23000.0)) {
164 | m_RepeatCount += 1; // Start repeat sequence
165 | // Save this sequence
166 | m_LastCommand = m_Command;
167 | m_LastAddress = m_Address;
168 | m_Command = 0;
169 | m_Address = 0;
170 | m_BitCounter = 0;
171 | m_State = READING_BIT_MARK;
172 | }
173 | else {
174 | m_RepeatCount = 0;
175 | m_State = IDLE;
176 | }
177 | break;
178 | }
179 | }
180 | return m_State;
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/NexaFireDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | /**
26 | * The NexaFireDecoder parses a set of pulse lengths and decodes a protocol used
27 | * by Nexa Fire Detector transmitted over 433MHz AM-modulated RF-signal.
28 | * The reception of the pulses may for example be made via the AudioProtocolSampler.
29 | * The NexaDecoder implements the ProtocolDecoder-interface and accepts the pulses
30 | * one by one. It contains a state machine, and when a complete message is decoded,
31 | * this is reported over the ProtocolDecoderSink-interface which is given at
32 | * construction.
33 | *
34 | * The protocol is mark length encoded and the protocol messages has the following
35 | * layout:
36 | *
37 | * a = Address
38 | *
39 | * ____Byte 2_____ ____Byte 1_____ ____Byte 0_____
40 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
41 | * a a a a a a a a a a a a a a a a a a a a a a a a
42 | *
43 | * @author Stefan
44 | *
45 | */
46 | @Plugin
47 | public class NexaFireDecoder implements ProtocolDecoder {
48 | protected static final int IDLE = 0;
49 | protected static final int READING_HEADER_SPACE = 1;
50 | protected static final int READING_BIT_MARK = 2;
51 | protected static final int READING_BIT_SPACE = 3;
52 | protected static final int READING_TRAILING_MARK = 4;
53 | protected static final int REPEAT_SCAN = 5;
54 |
55 | protected static final String s_StateNames[] = {"IDLE","READING_BIT_MARK","READING_BIT_SHORT_SPACE",
56 | "READING_BIT_LONG_SPACE","REPEAT_SCAN"};
57 |
58 | protected int m_State = IDLE;
59 |
60 | // This are the pulse length constants for the protocol. The default values may
61 | // be overridden by system properties
62 | public static final PulseLength NEXAF_HEADER_MARK =
63 | new PulseLength(NexaDecoder.class,"NEXAF_HEADER_MARK", 8100, 400);
64 | public static final PulseLength NEXAF_HEADER_SPACE =
65 | new PulseLength(NexaDecoder.class,"NEXAF_HEADER_SPACE", 900, 100);
66 | public static final PulseLength NEXAF_MARK =
67 | new PulseLength(NexaDecoder.class,"NEXAF_MARK", 800, 200);
68 | public static final PulseLength NEXAF_LONG_SPACE =
69 | new PulseLength(NexaDecoder.class,"NEXAF_LONG_SPACE", 2740, 300);
70 | public static final PulseLength NEXAF_SHORT_SPACE =
71 | new PulseLength(NexaDecoder.class,"NEXAF_SHORT_SPACE", 1400, 200);
72 | public static final PulseLength NEXAF_REPEAT =
73 | new PulseLength(NexaDecoder.class,"NEXAF_REPEAT", 14500, 2000);
74 |
75 | protected PulseLength HEADER_MARK = NEXAF_HEADER_MARK;
76 | protected PulseLength HEADER_SPACE = NEXAF_HEADER_SPACE;
77 | protected PulseLength MARK = NEXAF_MARK;
78 | protected PulseLength LONG_SPACE = NEXAF_LONG_SPACE;
79 | protected PulseLength SHORT_SPACE = NEXAF_SHORT_SPACE;
80 | protected PulseLength REPEAT = NEXAF_REPEAT;
81 |
82 | int m_Data = 0;
83 | int m_LastData = 0;
84 |
85 | protected int m_BitCounter = 0;
86 | protected int m_RepeatCount = 0;
87 | protected ProtocolDecoderSink m_Sink = null;
88 | private double m_LastPulse = REPEAT.length() / 2;
89 | public StatePulseAnalyzer analyzer = new StatePulseAnalyzer();
90 | private boolean m_PrintAnalyze = false;
91 | protected String m_ProtocolName;
92 |
93 | public void setTarget(ProtocolDecoderSink sink) {
94 | m_Sink = sink;
95 | }
96 |
97 | /**
98 | * Template method pattern. Used to initiate variables that may be modified by
99 | * subclasses.
100 | */
101 | public void setup() {
102 | m_ProtocolName = "NexaFire";
103 | }
104 |
105 | public NexaFireDecoder() {
106 | setup();
107 | }
108 |
109 | public ProtocolInfo getInfo() {
110 | return new ProtocolInfo(m_ProtocolName, "Space Length", m_ProtocolName, 24, 5);
111 | }
112 |
113 | /**
114 | *
115 | * a = Address
116 | *
117 | * ____Byte 2_____ ____Byte 1_____ ____Byte 0_____
118 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
119 | * a a a a a a a a a a a a a a a a a a a a a a a a
120 | *
121 | */
122 | protected void addBit(int b) {
123 | // Shift in data
124 | m_Data >>= 1;
125 | m_Data |= (b << 23);
126 | // Check if this is a complete message
127 | if (m_BitCounter == 23){
128 | // It is, create the message
129 | ProtocolMessage message = new ProtocolMessage(m_ProtocolName, 1, m_Data, 1);
130 | message.setRawMessageByteAt(0, m_Data);
131 |
132 | message.addField(new FieldValue("Address", m_Data));
133 |
134 | // It is, check if this really is a repeat
135 | if ((m_RepeatCount > 0) && (m_Data == m_LastData)) {
136 | message.setRepeat(m_RepeatCount);
137 | }
138 | else {
139 | // It is not a repeat, reset counter
140 | m_RepeatCount = 0;
141 | }
142 | // Report the parsed message
143 | m_Sink.parsedMessage(message);
144 | m_State = READING_TRAILING_MARK;
145 | if (m_PrintAnalyze) {
146 | analyzer.printPulses();
147 | }
148 | }
149 | m_BitCounter++;
150 | }
151 |
152 | /**
153 | * Report that part of a message was parsed, but aborted due to a non valid
154 | * pulse length.
155 | *
156 | * @param state Current state when parsing was aborted
157 | * @param length Length of the pulse which was not accepted
158 | */
159 | protected void partiallyParsed(String state, double length) {
160 | if (m_BitCounter > 1) {
161 | m_Sink.partiallyParsedMessage(m_ProtocolName + " " + state + ": " + Double.toString(length), m_BitCounter);
162 | }
163 | }
164 |
165 | /* (non-Javadoc)
166 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
167 | */
168 | public int parse(double pulse, boolean state) {
169 | switch (m_State) {
170 | case IDLE: {
171 | if (HEADER_MARK.matches(pulse) && state && (m_LastPulse > (REPEAT.length() / 2))) {
172 | m_State = READING_HEADER_SPACE;
173 | m_Data = 0;
174 | m_BitCounter = 0;
175 | }
176 | break;
177 | }
178 | case READING_HEADER_SPACE: {
179 | if (HEADER_SPACE.matches(pulse)) {
180 | m_State = READING_BIT_MARK;
181 | } else {
182 | m_State = IDLE;
183 | }
184 | break;
185 | }
186 | case READING_BIT_MARK: {
187 | if (MARK.matches(pulse) && state) {
188 | m_State = READING_BIT_SPACE;
189 | } else {
190 | partiallyParsed("M" ,pulse);
191 | m_State = IDLE;
192 | }
193 | break;
194 | }
195 | case READING_BIT_SPACE: {
196 | if (LONG_SPACE.matches(pulse)) {
197 | m_State = READING_BIT_MARK;
198 | addBit(1);
199 | } else if (SHORT_SPACE.matches(pulse)) {
200 | m_State = READING_BIT_MARK;
201 | addBit(0);
202 | } else {
203 | partiallyParsed("S", pulse);
204 | m_State = IDLE;
205 | }
206 | break;
207 | }
208 | case READING_TRAILING_MARK: {
209 | if (MARK.matches(pulse)) {
210 | m_State = REPEAT_SCAN;
211 | } else {
212 | m_State = IDLE;
213 | }
214 | break;
215 | }
216 | case REPEAT_SCAN: {
217 | if (REPEAT.matches(pulse)) {
218 | m_RepeatCount += 1; // Start repeat sequence
219 | // Save this sequence
220 | m_LastData = m_Data;
221 | }
222 | else {
223 | m_RepeatCount = 0;
224 | }
225 | m_State = IDLE;
226 | break;
227 | }
228 | }
229 | m_LastPulse = pulse;
230 | return m_State;
231 | }
232 | }
233 |
234 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/PioneerDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 |
26 | @Plugin
27 | public class PioneerDecoder implements ProtocolDecoder {
28 | protected static final int IDLE = 0;
29 | protected static final int READING_HEADER = 1;
30 | protected static final int READING_BIT_MARK = 2;
31 | protected static final int READING_BIT_SPACE = 3;
32 | protected static final int TRAILING_BIT = 4;
33 | protected static final int REPEAT_SCAN = 5;
34 |
35 | protected int m_State = IDLE;
36 |
37 | protected int m_Command = 0;
38 | protected int m_CommandCheck = 0;
39 | protected int m_Address = 0;
40 | protected int m_AddressCheck = 0;
41 |
42 | protected int m_LastCommand = 0;
43 | protected int m_LastAddress = 0;
44 |
45 | protected int m_BitCounter = 0;
46 | protected int m_RepeatCount = 0;
47 | protected ProtocolDecoderSink m_Sink = null;
48 |
49 | public void setTarget(ProtocolDecoderSink sink) {
50 | m_Sink = sink;
51 | }
52 |
53 | public ProtocolInfo getInfo() {
54 | return new ProtocolInfo("Pioneer", "Space Length", "Pioneer", 16, 5);
55 | }
56 |
57 | protected boolean pulseCompare(double candidate, double standard) {
58 | return Math.abs(standard - candidate) < standard * 0.4;
59 | }
60 |
61 | protected boolean pulseCompare(double candidate, double min, double max) {
62 | return ((candidate > min) && (candidate < max));
63 | }
64 |
65 | protected void reportPartial() {
66 | if (m_BitCounter > 0) {
67 | m_Sink.partiallyParsedMessage("Pioneer", m_BitCounter);
68 | }
69 | }
70 |
71 | protected void addBit(int b) {
72 | if (m_BitCounter < 8) {
73 | m_Address >>= 1;
74 | m_Address |= (b << 7);
75 | }
76 | else if (m_BitCounter < 16) {
77 | m_AddressCheck >>= 1;
78 | m_AddressCheck |= (b << 7);
79 | }
80 | else if (m_BitCounter < 24) {
81 | m_Command >>= 1;
82 | m_Command |= (b << 7);
83 | }
84 | else if (m_BitCounter < 32) {
85 | m_CommandCheck >>= 1;
86 | m_CommandCheck |= (b << 7);
87 | }
88 | // Check if this is a complete message
89 | if (m_BitCounter == 31){
90 | // It is, verify checksum
91 | if ((m_Address != (m_AddressCheck ^ 0xFF)) || (m_Command != (m_CommandCheck ^ 0xFF))) {
92 | // Checksum error
93 | reportPartial();
94 | m_State = IDLE;
95 | return;
96 | }
97 | ProtocolMessage message = new ProtocolMessage("Pioneer", m_Command, m_Address, 2);
98 | message.setRawMessageByteAt(0, m_Command);
99 | message.setRawMessageByteAt(1, m_Address);
100 | // It is, check if this really is a repeat
101 | if ((m_RepeatCount > 0) && (m_Command == m_LastCommand) && (m_Address == m_LastAddress)) {
102 | message.setRepeat(m_RepeatCount);
103 | }
104 | else {
105 | // It is not a repeat, reset counter
106 | m_RepeatCount = 0;
107 | }
108 | message.addField(new FieldValue("Command", m_Command));
109 | message.addField(new FieldValue("Address", m_Address));
110 | // Report the parsed message
111 | m_Sink.parsedMessage(message);
112 | m_State = TRAILING_BIT;
113 | }
114 | m_BitCounter++;
115 | }
116 |
117 | /* (non-Javadoc)
118 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
119 | */
120 | public int parse(double pulse, boolean state) {
121 | switch (m_State) {
122 | case IDLE: {
123 | if (pulseCompare(pulse, 8400.0 + 60) && state) {
124 | m_State = READING_HEADER;
125 | m_Command = 0;
126 | m_Address = 0;
127 | m_CommandCheck = 0;
128 | m_AddressCheck = 0;
129 | m_BitCounter = 0;
130 | }
131 | break;
132 | }
133 | case READING_HEADER: {
134 | if (pulseCompare(pulse, 4200.0 - 60)) {
135 | m_State = READING_BIT_MARK;
136 | }
137 | else {
138 | m_State = IDLE;
139 | reportPartial();
140 | }
141 | break;
142 | }
143 | case READING_BIT_MARK: {
144 | // The mark pulse seems to vary a lot in length
145 | if (pulseCompare(pulse, 50, 700)) {
146 | m_State = READING_BIT_SPACE;
147 | }
148 | else {
149 | m_State = IDLE;
150 | reportPartial();
151 | }
152 | break;
153 | }
154 | case READING_BIT_SPACE: {
155 | if (pulseCompare(pulse, 1575.0 - 60)) {
156 | m_State = READING_BIT_MARK;
157 | addBit(1);
158 | }
159 | else if (pulseCompare(pulse, 524.0 - 60)) {
160 | m_State = READING_BIT_MARK;
161 | addBit(0);
162 | }
163 | else {
164 | m_State = IDLE;
165 | reportPartial();
166 | }
167 | break;
168 | }
169 |
170 | case TRAILING_BIT: {
171 | // The mark pulse seems to vary a lot in length
172 | if (pulseCompare(pulse, 100, 700)) {
173 | m_State = REPEAT_SCAN;
174 | }
175 | else {
176 | m_State = IDLE;
177 | }
178 | break;
179 | }
180 | case REPEAT_SCAN: {
181 | if (pulseCompare(pulse, 24000.0, 28000.0)) {
182 | m_RepeatCount += 1; // Start repeat sequence
183 | // Save this sequence
184 | m_LastCommand = m_Command;
185 | m_LastAddress = m_Address;
186 | m_Command = 0;
187 | m_Address = 0;
188 | m_BitCounter = 0;
189 | m_State = READING_BIT_MARK;
190 | }
191 | else {
192 | m_RepeatCount = 0;
193 | m_State = IDLE;
194 | }
195 | break;
196 | }
197 | }
198 | return m_State;
199 | }
200 | }
201 |
202 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/PrologueDecoder.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import nu.nethome.util.ps.*;
4 | import nu.nethome.util.ps.BitString.Field;
5 |
6 | import java.util.HashMap;
7 | import java.util.Map;
8 |
9 | /**
10 | * The PrologueDecoder parses a set of pulse lengths and decodes a protocol used
11 | * by Prologue-thermometers which is transmitted over 433MHz AM-modulated RF-signal.
12 | * The reception of the pulses may for example be made via the AudioProtocolSampler.
13 | * The NexaDecoder implements the ProtocolDecoder-interface and accepts the pulses
14 | * one by one. It contains a state machine, and when a complete message is decoded,
15 | * this is reported over the ProtocolDecoderSink-interface which is given at
16 | * construction.
17 | *
18 | * The protocol is space length encoded and sent with MSB first.
19 | * the protocol messages has the following layout:
20 | *
21 | * h = Humidity
22 | * t = Temperature * 10
23 | * c = Channel 0 - 2
24 | * u = button
25 | * b = Battery (1 = low)
26 | * r = rolling id
27 | * i = id
28 | *
29 | * _Nyb 4_ ____Byte 3_____ ____Byte 2_____ ____Byte 1_____ ____Byte 0_____ _S_
30 | * 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0
31 | * i i i i r r r r r r r r b u c c t t t t t t t t t t t t h h h h h h h h x
32 | *
33 | * @author Stefan
34 | *
35 | */
36 | public class PrologueDecoder implements ProtocolDecoder {
37 |
38 | protected static final int IDLE = 0;
39 | protected static final int READING_MARK = 5;
40 | protected static final int READING_SPACE = 6;
41 | protected static final int REPEAT_SCAN = 10;
42 | protected static final int PROLOGUE_BIT_LENGTH = 36 + 1;
43 | private static final String PROTOCOL_NAME = "Prologue";
44 | public static final ProtocolInfo PROLOGUE_PROTOCOL_INFO = new ProtocolInfo(PROTOCOL_NAME, "Space Length", PROTOCOL_NAME, PROLOGUE_BIT_LENGTH, 1);
45 |
46 | public static final PulseLength PREAMBLE_SPACE =
47 | new PulseLength(PrologueDecoder.class, "PREAMBLE_SPACE", 8770, 7000, 10000);
48 | public static final PulseLength LONG_SPACE =
49 | new PulseLength(PrologueDecoder.class, "LONG_SPACE", 3880, 3000, 5000);
50 | public static final PulseLength SHORT_SPACE =
51 | new PulseLength(PrologueDecoder.class, "SHORT_SPACE", 1930, 1000, 2999);
52 | public static final PulseLength MARK =
53 | new PulseLength(PrologueDecoder.class, "MARK", 500, 300, 700);
54 |
55 | protected ProtocolDecoderSink m_Sink = null;
56 | BitString data = new BitString();
57 | BitString lastParsedData = new BitString();
58 | protected int state = IDLE;
59 | private int repeat = 0;
60 | private Map fields = new HashMap();
61 |
62 | public PrologueDecoder() {
63 | fields.put("Humidity", new Field(0, 8));
64 | fields.put("Temp", new Field(8, 12));
65 | fields.put("Channel", new Field(20, 2));
66 | fields.put("Button", new Field(22, 1));
67 | fields.put("Battery", new Field(23, 1));
68 | fields.put("RollingId", new Field(24, 8));
69 | fields.put("Id", new Field(32, 4));
70 | }
71 |
72 | public void setTarget(ProtocolDecoderSink sink) {
73 | m_Sink = sink;
74 | }
75 |
76 | public ProtocolInfo getInfo() {
77 | return PROLOGUE_PROTOCOL_INFO;
78 | }
79 |
80 | protected void addBit(boolean b) {
81 | data.addLsb(b);
82 | if (data.length() == PROLOGUE_BIT_LENGTH) {
83 | decodeMessage(data);
84 | }
85 | }
86 |
87 | public void decodeMessage(BitString binaryMessage) {
88 | binaryMessage.shiftRight(1); // last bit is ignored - parity?
89 | // Assure we get same data twice in a row as simple error detection strategy
90 | if (this.data.equals(lastParsedData)) {
91 | ProtocolMessage message = new ProtocolMessage(PROTOCOL_NAME, binaryMessage.extractInt(fields.get("Temp")), binaryMessage.extractInt(fields.get("Channel")), binaryMessage.toByteInts());
92 | for (String field : fields.keySet()) {
93 | message.addField(new FieldValue(field, binaryMessage.extractInt(fields.get(field))));
94 | }
95 | message.setRepeat(repeat - 1);
96 | m_Sink.parsedMessage(message);
97 | }
98 | lastParsedData.setValue(binaryMessage);
99 | state = REPEAT_SCAN;
100 | }
101 |
102 | public int parse(double pulse, boolean bitstate) {
103 | switch (state) {
104 | case IDLE: {
105 | if (PREAMBLE_SPACE.matches(pulse) && !bitstate) {
106 | data.clear();
107 | repeat = 0;
108 | state = READING_MARK;
109 | }
110 | break;
111 | }
112 | case READING_MARK: {
113 | if (MARK.matches(pulse)) {
114 | state = READING_SPACE;
115 | } else {
116 | quitParsing(pulse);
117 | }
118 | break;
119 | }
120 | case READING_SPACE: {
121 | if (SHORT_SPACE.matches(pulse)) {
122 | state = READING_MARK;
123 | addBit(false);
124 | } else if (LONG_SPACE.matches(pulse)) {
125 | state = READING_MARK;
126 | addBit(true);
127 | } else {
128 | quitParsing(pulse);
129 | }
130 | break;
131 | }
132 | case REPEAT_SCAN: {
133 | if (MARK.matches(pulse) && bitstate) {
134 | // Ok read mark
135 | } else if (PREAMBLE_SPACE.matches(pulse) && !bitstate) {
136 | data.clear();
137 | repeat++;
138 | state = READING_MARK;
139 | } else {
140 | state = IDLE;
141 | }
142 | break;
143 | }
144 | }
145 | return state;
146 | }
147 |
148 | private void quitParsing(double pulseLength) {
149 | if (data.length() > 5) {
150 | m_Sink.partiallyParsedMessage(String.format("Prologue Pulse: %g ms, State: %d", pulseLength, state), data.length());
151 | }
152 | state = IDLE;
153 | lastParsedData.clear();
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/ProntoDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | import java.util.LinkedList;
26 |
27 |
28 | /**
29 | * The PRONTO-format is named after a manufacturer of generic remote controls. It is a format
30 | * for describing raw IR-protocol messages. This decoder does not really decode the signal,
31 | * it formats the raw sampled pulses in the pronto-format.
32 | *
33 | * @author Stefan Str�mberg
34 | */
35 | @Plugin
36 | public class ProntoDecoder implements ProtocolDecoder {
37 | protected static final int IDLE = 0;
38 | protected static final int SAMPLING = 1;
39 | private static final int MIN_MESSAGELENGTH = 10;
40 |
41 | protected int m_State = IDLE;
42 |
43 | /** Modulation frequency set to use when calculating the burst length numbers */
44 | protected double m_Freq = 0;
45 |
46 | /**
47 | * Modulation frequency actually used when calculating the burst length numbers
48 | * Because of rounding this is not exactly same as the set frequency
49 | */
50 | protected double m_UsedFreq = 0;
51 |
52 |
53 | /** Constant for the pronto remote's internal clock frequency */
54 | protected double m_ProntoFreqConstant = .241246;
55 |
56 | /** Minimum time (in uS) to regard as space between protocol messages */
57 | protected int m_LeadOutMinTime = 9000;
58 |
59 | /** Amount of time (in uS) that has to be added to bursts to compensate for slow
60 | * reaction in the receivers
61 | */
62 | protected double m_PulseWidthModification = 0;
63 |
64 | protected ProtocolDecoderSink m_Sink = null;
65 |
66 | LinkedList m_Bursts = new LinkedList();
67 |
68 | public void setTarget(ProtocolDecoderSink sink) {
69 | m_Sink = sink;
70 | }
71 |
72 | public ProntoDecoder() {
73 | this.setModulationFrequency(40000);
74 | }
75 |
76 | public ProtocolInfo getInfo() {
77 | return new ProtocolInfo("Pronto", "None", "Pronto", 0, 5);
78 | }
79 |
80 | public void addBurst(double burstUs, boolean state) {
81 | // Adjust for imperfections in receiver
82 | burstUs = state ? burstUs - m_PulseWidthModification :
83 | burstUs + m_PulseWidthModification;
84 |
85 | int prontoBurst = (int)(0.5 + (burstUs * m_UsedFreq) / 1000000.0);
86 |
87 | // Trim if burst is VERY long
88 | if (prontoBurst > 0xFFFF) prontoBurst = 0xFFFF;
89 |
90 | // Add burst to burst pairs
91 | m_Bursts.add(prontoBurst);
92 |
93 | // Check if this was the Lead Out burst pair
94 | if (burstUs > m_LeadOutMinTime) {
95 | // Ok, this is possibly the end of the sequence
96 | // Check how long it is
97 | if (m_Bursts.size() < MIN_MESSAGELENGTH) {
98 | // This was to short to be a real message, it is probably noise - ignore it
99 | m_Bursts.clear();
100 | m_State = IDLE;
101 | return;
102 | }
103 | if ((m_Bursts.size() & 1) == 1) {
104 | // Something is wrong, there should be an even number of bursts to form
105 | // burst pairs. Add a dummy burst to be able to go on.
106 | m_Bursts.add(prontoBurst);
107 | }
108 | // Add leading 0 to signal this is a sampled signal
109 | String prontoMessage = "0000";
110 | // Add the burst frequency
111 | // No rounding here, Pronto takes pure integer part
112 | Integer prontoFreq = (int)(1000000.0 /(m_Freq * m_ProntoFreqConstant));
113 | prontoMessage += String.format(" %04x", prontoFreq);
114 | // Add zero to signal that we have no one time bursts
115 | prontoMessage += " 0000";
116 | // Add number of burst pairs in signal
117 | prontoMessage += String.format(" %04x", m_Bursts.size() / 2);
118 | // Add the burst pairs
119 | for (int burst : m_Bursts) {
120 | prontoMessage += String.format(" %04x", burst);
121 | }
122 | // Create a report of the message
123 | ProtocolMessage message = new ProtocolMessage("Pronto", 0, m_Bursts.size(), 1);
124 | message.setRawMessageByteAt(0, m_Bursts.size());
125 | message.addField(new FieldValue("Message", prontoMessage));
126 | // Report the parsed message
127 | m_Sink.parsedMessage(message);
128 | m_Bursts.clear();
129 | m_State = IDLE;
130 | }
131 | }
132 |
133 | /* (non-Javadoc)
134 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
135 | */
136 | public int parse(double pulse, boolean state) {
137 | switch (m_State) {
138 | case IDLE: {
139 | if ((pulse < m_LeadOutMinTime) && (pulse > 0)) {
140 | m_State = SAMPLING;
141 | addBurst(pulse, state);
142 | }
143 | }
144 | break;
145 |
146 | case SAMPLING: {
147 | addBurst(pulse, state);
148 | }
149 | break;
150 | }
151 | return m_State;
152 | }
153 |
154 | public double getModulationFrequency() {
155 | return m_Freq;
156 | }
157 |
158 | public void setModulationFrequency(double freq) {
159 | m_Freq = freq;
160 | Integer prontoFreq = (int)(1000000.0 /(m_Freq * m_ProntoFreqConstant));
161 | m_UsedFreq = 1000000.0 /(prontoFreq * m_ProntoFreqConstant);
162 | }
163 |
164 | public int getLeadOutTime() {
165 | return m_LeadOutMinTime;
166 | }
167 |
168 | public void setLeadOutTime(int leadOutMinTime) {
169 | m_LeadOutMinTime = leadOutMinTime;
170 | }
171 |
172 | public double getPulseWidthModification() {
173 | return m_PulseWidthModification;
174 | }
175 |
176 | public void setPulseWidthModification(double pulseWidthModification) {
177 | m_PulseWidthModification = pulseWidthModification;
178 | }
179 | }
180 |
181 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/RC5Decoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 |
26 | @Plugin
27 | public class RC5Decoder implements ProtocolDecoder {
28 | protected static final int IDLE = 0;
29 | protected static final int HI_IN = 2;
30 | protected static final int HI_BETWEEN = 3;
31 | protected static final int LO_IN = 4;
32 | protected static final int LO_BETWEEN = 5;
33 |
34 | protected static final int RC5SHORT = 889;
35 | protected static final int RC5LONG = 1778;
36 | protected static final int RC5REPEAT = 85000;
37 |
38 | protected int m_State = IDLE;
39 |
40 | protected int m_Header = 0;
41 | protected int m_Command = 0;
42 | protected int m_Address = 0;
43 |
44 | protected int m_LastHeader = 0;
45 | protected int m_LastCommand = 0;
46 | protected int m_LastAddress = 0;
47 |
48 | protected int m_BitCounter = 0;
49 | protected int m_RepeatCount = 0;
50 | protected double m_LastValue = 0;
51 | protected ProtocolDecoderSink m_Sink = null;
52 |
53 | public void setTarget(ProtocolDecoderSink sink) {
54 | m_Sink = sink;
55 | }
56 |
57 | public ProtocolInfo getInfo() {
58 | return new ProtocolInfo("RC5", "Manchester", "Philips", 14, 5);
59 | }
60 |
61 | protected boolean pulseCompare(double candidate, double standard) {
62 | return Math.abs(standard - candidate) < standard * 0.2;
63 | }
64 |
65 | protected void addBit(int b) {
66 | if (m_BitCounter < 3) {
67 | m_Header = (m_Header << 1) + b ;
68 | }
69 | else if (m_BitCounter < 8) {
70 | m_Address = (m_Address << 1) + b ;
71 | }
72 | else if (m_BitCounter < 14) {
73 | m_Command = (m_Command << 1) + b ;
74 | }
75 | // Check if this is a complete message
76 | if (m_BitCounter == 13){
77 | // It is, create the message
78 | ProtocolMessage message = new ProtocolMessage("RC5", m_Command, m_Address, 3);
79 | message.setRawMessageByteAt(2, m_Command);
80 | message.setRawMessageByteAt(1, m_Address);
81 | message.setRawMessageByteAt(0, m_Header);
82 |
83 | message.addField(new FieldValue("Header", m_Header));
84 | message.addField(new FieldValue("Address", m_Address));
85 | message.addField(new FieldValue("Command", m_Command));
86 |
87 | // Check if this is a repeat
88 | if ((m_Command == m_LastCommand) && (m_Address == m_LastAddress)
89 | && (m_Header == m_LastHeader)) {
90 | m_RepeatCount++;
91 | message.setRepeat(m_RepeatCount);
92 | }
93 | else {
94 | // It is not a repeat, reset counter
95 | m_RepeatCount = 0;
96 | }
97 | // Report the parsed message
98 | m_Sink.parsedMessage(message);
99 | // Reset state
100 | m_State = IDLE;
101 | // Save message for repeat check
102 | m_LastCommand = m_Command;
103 | m_LastAddress = m_Address;
104 | m_LastHeader = m_Header;
105 | }
106 | m_BitCounter++;
107 | }
108 |
109 |
110 | /* (non-Javadoc)
111 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
112 | */
113 | public int parse(double pulse, boolean state) {
114 | switch (m_State) {
115 | case IDLE: {
116 | if (pulseCompare(pulse, RC5SHORT) && state && (m_LastValue > 5000)) {
117 | m_Header = 0;
118 | m_Command = 0;
119 | m_Address = 0;
120 | m_BitCounter = 0;
121 | m_State = HI_BETWEEN;
122 | addBit(1);
123 | }
124 | else if (pulseCompare(pulse, RC5LONG) && state && (m_LastValue > 5000)) {
125 | m_Header = 0;
126 | m_Command = 0;
127 | m_Address = 0;
128 | m_BitCounter = 0;
129 | m_State = HI_IN;
130 | addBit(1);
131 | addBit(0);
132 | }
133 | if (pulseCompare(m_LastValue, RC5REPEAT) && (m_State != IDLE)) {
134 | m_RepeatCount++;
135 | }
136 | break;
137 | }
138 | case HI_IN: {
139 | if (pulseCompare(pulse, RC5SHORT)) {
140 | m_State = LO_BETWEEN;
141 | } else if (pulseCompare(pulse, RC5LONG)) {
142 | m_State = LO_IN;
143 | addBit(1);
144 | } else {
145 | m_State = IDLE;
146 | }
147 | break;
148 | }
149 | case HI_BETWEEN: {
150 | if (pulseCompare(pulse, RC5SHORT)) {
151 | m_State = LO_IN;
152 | addBit(1);
153 | } else {
154 | m_State = IDLE;
155 | }
156 | break;
157 | }
158 | case LO_IN: {
159 | if (pulseCompare(pulse, RC5SHORT)) {
160 | m_State = HI_BETWEEN;
161 | break;
162 | } else if (pulseCompare(pulse, RC5LONG)) {
163 | m_State = HI_IN;
164 | addBit(0);
165 | } else {
166 | m_State = IDLE;
167 | }
168 | break;
169 | }
170 | case LO_BETWEEN: {
171 | if (pulseCompare(pulse, RC5SHORT)) {
172 | m_State = HI_IN;
173 | addBit(0);
174 | } else {
175 | m_State = IDLE;
176 | }
177 | break;
178 | }
179 | }
180 | m_LastValue = pulse;
181 | return m_State;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/RC6Decoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | @Plugin
26 | public class RC6Decoder implements ProtocolDecoder {
27 | protected static final int IDLE = 0;
28 | protected static final int READING_HEADER = 1;
29 | protected static final int HI_IN = 2;
30 | protected static final int HI_BETWEEN = 3;
31 | protected static final int LO_IN = 4;
32 | protected static final int LO_BETWEEN = 5;
33 |
34 | protected static final int RC6SHORT = 444;
35 | protected static final int RC6LONG = 889;
36 |
37 | protected int m_State = IDLE;
38 |
39 | protected int m_Header = 0;
40 | protected int m_Command = 0;
41 | protected int m_Address = 0;
42 | protected int m_Extra = 0;
43 |
44 | protected int m_LastCommand = 0;
45 | protected int m_LastAddress = 0;
46 | protected int m_LastExtra = 0;
47 |
48 | protected int m_BitCounter = 0;
49 | protected int m_RepeatCount = 0;
50 | protected double m_LastValue = 0;
51 | protected ProtocolDecoderSink m_Sink = null;
52 |
53 | public void setTarget(ProtocolDecoderSink sink) {
54 | m_Sink = sink;
55 | }
56 |
57 | public ProtocolInfo getInfo() {
58 | return new ProtocolInfo("RC6", "Manchester", "Philips", 20, 5);
59 | }
60 |
61 | protected boolean pulseCompare(double candidate, double standard) {
62 | return Math.abs(standard - candidate) < standard * 0.2;
63 | }
64 |
65 | protected void addBit(int b) {
66 | if (m_BitCounter < 4) {
67 | m_Header = (m_Header << 1) + b ;
68 | }
69 | else if (m_BitCounter == 4){
70 | m_Extra = b;
71 | }
72 | else if (m_BitCounter < 13) {
73 | m_Address = (m_Address << 1) + b ;
74 | }
75 | else if (m_BitCounter < 21) {
76 | m_Command = (m_Command << 1) + b ;
77 | }
78 | // Check if this is a complete message
79 | if (m_BitCounter == 20){
80 | // It is, create the message
81 | ProtocolMessage message = new ProtocolMessage("RC6", m_Command, m_Address, 3);
82 | message.setRawMessageByteAt(0, m_Command);
83 | message.setRawMessageByteAt(1, m_Address);
84 | message.setRawMessageByteAt(2, m_Extra);
85 |
86 | message.addField(new FieldValue("Header", m_Header));
87 | message.addField(new FieldValue("Flip", m_Extra));
88 | message.addField(new FieldValue("Address", m_Address));
89 | message.addField(new FieldValue("Command", m_Command));
90 |
91 | // Check if this is a repeat
92 | if ((m_RepeatCount > 0) && (m_Command == m_LastCommand) && (m_Address == m_LastAddress)
93 | && (m_Extra == m_LastExtra)) {
94 | message.setRepeat(m_RepeatCount);
95 | }
96 | else {
97 | // It is not a repeat, reset counter
98 | m_RepeatCount = 0;
99 | }
100 | // Report the parsed message
101 | m_Sink.parsedMessage(message);
102 | // Reset state
103 | m_State = IDLE;
104 | // Save message for repeat check
105 | m_LastCommand = m_Command;
106 | m_LastAddress = m_Address;
107 | m_LastExtra = m_Extra;
108 | }
109 | m_BitCounter++;
110 | }
111 |
112 | /**
113 | * Corrects for the fact that the trailer bit is double as long as the other bits. We handle this
114 | * by adjusting the received puls lengths when we get to the trailer bit.
115 | * @param pulse The measured pulse
116 | * @param bitCounter Which bit we are currently processing
117 | * @return The adjusted pulse length
118 | */
119 | protected double trailerBitAdjust(double pulse, int bitCounter) {
120 | if ((bitCounter == 4) && ((m_State == HI_IN) || (m_State == LO_IN)) && pulseCompare(pulse, 1333)) {
121 | return RC6LONG;
122 | }
123 | else if ((bitCounter == 4) && ((m_State == HI_BETWEEN) || (m_State == LO_BETWEEN))) {
124 | return pulse / 2.0;
125 | }
126 | else if ((bitCounter == 5) && ((m_State == HI_IN) || (m_State == LO_IN))) {
127 | if (pulseCompare(pulse, 889)) {
128 | return RC6SHORT;
129 | }
130 | else if (pulseCompare(pulse, 1333)) {
131 | return RC6LONG;
132 | }
133 | }
134 | return pulse;
135 | }
136 |
137 |
138 | /* (non-Javadoc)
139 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
140 | */
141 | public int parse(double pulse, boolean state) {
142 | pulse = trailerBitAdjust(pulse, m_BitCounter);
143 | switch (m_State) {
144 | case IDLE: {
145 | if (pulseCompare(pulse, 2666.0) && state) {
146 | m_State = READING_HEADER;
147 | m_Header = 0;
148 | m_Command = 0;
149 | m_Address = 0;
150 | m_Extra = 0;
151 | m_BitCounter = 0;
152 |
153 | if (pulseCompare(m_LastValue, 85000.0)) {
154 | m_RepeatCount++;
155 | }
156 | else {
157 | m_RepeatCount = 0;
158 | }
159 | break;
160 | }
161 | }
162 | case READING_HEADER: {
163 | if (pulseCompare(pulse, 889.0)) {
164 | m_State = LO_BETWEEN;
165 | }
166 | else {
167 | m_State = IDLE;
168 | }
169 | break;
170 | }
171 | case HI_IN: {
172 | if (pulseCompare(pulse, RC6SHORT)) {
173 | m_State = LO_BETWEEN;
174 | } else if (pulseCompare(pulse, RC6LONG)) {
175 | m_State = LO_IN;
176 | addBit(0);
177 | } else {
178 | m_State = IDLE;
179 | }
180 | break;
181 | }
182 | case HI_BETWEEN: {
183 | if (pulseCompare(pulse, RC6SHORT)) {
184 | m_State = LO_IN;
185 | addBit(0);
186 | } else {
187 | m_State = IDLE;
188 | }
189 | break;
190 | }
191 | case LO_IN: {
192 | if (pulseCompare(pulse, RC6SHORT)) {
193 | m_State = HI_BETWEEN;
194 | break;
195 | } else if (pulseCompare(pulse, RC6LONG)) {
196 | m_State = HI_IN;
197 | addBit(1);
198 | } else {
199 | m_State = IDLE;
200 | }
201 | break;
202 | }
203 | case LO_BETWEEN: {
204 | if (pulseCompare(pulse, RC6SHORT)) {
205 | m_State = HI_IN;
206 | addBit(1);
207 | } else {
208 | m_State = IDLE;
209 | }
210 | break;
211 | }
212 | }
213 | m_LastValue = pulse;
214 | return m_State;
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/RisingSunDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.FieldValue;
24 | import nu.nethome.util.ps.ProtocolMessage;
25 | import nu.nethome.util.ps.PulseLength;
26 |
27 | /**
28 | * The RisingSunDecoder parses a set of pulse lengths and decodes a protocol used
29 | * by UPM-thermometers which is transmitted over 433MHz AM-modulated RF-signal.
30 | * The reception of the pulses may for example be made via the AudioProtocolSampler.
31 | * The RisingSunDecoder implements the ProtocolDecoder-interface and accepts the pulses
32 | * one by one. It contains a state machine, and when a complete message is decoded,
33 | * this is reported over the ProtocolDecoderSink-interface which is given at
34 | * construction.
35 | *
36 | * The protocol is mark length encoded and the protocol messages has the following
37 | * layout:
38 | *
39 | * s = Start bit = 0
40 | * a = Channel 1 not selected
41 | * b = Channel 2 not selected
42 | * c = Channel 3 not selected
43 | * d = Channel 4 not selected
44 | * e = Button 1 not pressed
45 | * f = Button 2 not pressed
46 | * g = Button 3 not pressed
47 | * h = Button 4 not pressed
48 | * o = On/Off-bit
49 | *
50 | * ____Byte 2_____ ____Byte 1_____ ____Byte 0_____ _S_
51 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0
52 | * x o x x x x x x x h x g x f x e x d x c x b x a s
53 | *
54 | * This protocol is almost exactly the same as NEXA, so the entire implementation is reused.
55 | *
56 | * @author Stefan
57 | *
58 | */
59 |
60 | @Plugin
61 | public class RisingSunDecoder extends NexaDecoder{
62 |
63 | protected final static int buttonmapping[] = {10,11,12,13,14,15,16,4,18,19,10,3,22,2,1,0};
64 |
65 | // This are the pulse length constants for the protocol. The default values may
66 | // be overridden by system properties
67 | public static final PulseLength RISING_SUN_LONG_MARK =
68 | new PulseLength(RisingSunDecoder.class,"RISING_SUN_LONG_MARK", 1300, 200);
69 | public static final PulseLength RISING_SUN_SHORT_MARK =
70 | new PulseLength(RisingSunDecoder.class,"RISING_SUN_SHORT_MARK", 450, 200);
71 | public static final PulseLength RISING_SUN_LONG_SPACE =
72 | new PulseLength(RisingSunDecoder.class,"RISING_SUN_LONG_SPACE", 1280, 200);
73 | public static final PulseLength RISING_SUN_SHORT_SPACE =
74 | new PulseLength(RisingSunDecoder.class,"RISING_SUN_SHORT_SPACE", 420, 150);
75 | public static final PulseLength RISING_SUN_REPEAT =
76 | new PulseLength(RisingSunDecoder.class,"RISING_SUN_REPEAT", 13400, 500);
77 |
78 | public void setup() {
79 | m_ProtocolName = "RisingSun";
80 | LONG_MARK = RISING_SUN_LONG_MARK;
81 | SHORT_MARK = RISING_SUN_SHORT_MARK;
82 | LONG_SPACE = RISING_SUN_LONG_SPACE;
83 | SHORT_SPACE = RISING_SUN_SHORT_SPACE;
84 | REPEAT = RISING_SUN_REPEAT;
85 | }
86 |
87 | protected int bytemap(int raw) {
88 | return buttonmapping[(raw & 1) + ((raw >> 1) & 2) + ((raw >> 2) & 4) + ((raw >> 3) & 8)];
89 | }
90 |
91 | protected void addBit(int b) {
92 | // Shift in data
93 | m_Data >>= 1;
94 | m_Data |= (b << 24);
95 | // Check if this is a complete message
96 | if (m_BitCounter == 24){
97 | // It is, create the message
98 | int command = (m_Data >> 23) & 1;
99 | int button = bytemap((m_Data >> 9) & 0xFF);
100 | int address = bytemap((m_Data >> 1) & 0xFF);
101 |
102 | // Sender ends a message sequence by a signal saying "no button is pressed".
103 | // We ignore that message.
104 | if (button == 0) {
105 | m_State = IDLE;
106 | m_RepeatCount = 0;
107 | return;
108 | }
109 |
110 | ProtocolMessage message = new ProtocolMessage(m_ProtocolName, command, (button << 4) + address, 4);
111 | message.setRawMessageByteAt(3, m_Data & 0x1);
112 | message.setRawMessageByteAt(0, (m_Data >> 17) & 0xFF);
113 | message.setRawMessageByteAt(1, (m_Data >> 9) & 0xFF);
114 | message.setRawMessageByteAt(2, (m_Data >> 1) & 0xFF);
115 |
116 | message.addField(new FieldValue("Command", command));
117 | message.addField(new FieldValue("Button", button));
118 | message.addField(new FieldValue("Channel", address));
119 |
120 | // It is, check if this really is a repeat
121 | if ((m_RepeatCount > 0) && (m_Data == m_LastData)) {
122 | message.setRepeat(m_RepeatCount);
123 | }
124 | else {
125 | // It is not a repeat, reset counter
126 | m_RepeatCount = 0;
127 | }
128 | // Report the parsed message
129 | m_Sink.parsedMessage(message);
130 | m_State = REPEAT_SCAN;
131 | }
132 | m_BitCounter++;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/RollerTrolDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2015, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.RollerTrol;
23 | import nu.nethome.util.plugin.Plugin;
24 | import nu.nethome.util.ps.*;
25 |
26 | import static nu.nethome.coders.RollerTrol.*;
27 |
28 | @Plugin
29 | public class RollerTrolDecoder implements ProtocolDecoder {
30 |
31 | protected static final int IDLE = 0;
32 | protected static final int READING_LONG_PREAMBLE_MARK = 1;
33 | protected static final int READING_LONG_PREAMBLE_SPACE = 2;
34 | protected static final int READING_SHORT_PREAMBLE_MARK = 3;
35 | protected static final int READING_SHORT_PREAMBLE_SPACE = 4;
36 | protected static final int READING_MARK = 5;
37 | protected static final int READING_SHORT_SPACE = 6;
38 | protected static final int READING_LONG_SPACE = 7;
39 | protected static final int REPEAT_SCAN = 10;
40 | /*This is the minimum repeat gap that Tellstick supports, so I accept this as a repeat gap too*/
41 | public static final PulseLength TELLSTICK_MIN_REPEAT_GAP =
42 | new PulseLength(RollerTrolDecoder.class, "TELLSTICK_MIN_REPEAT_GAP", 1000, 800, 1200);
43 |
44 | public static final BitString.Field BYTE4 = new BitString.Field(32, 8);
45 | public static final BitString.Field BYTE3 = new BitString.Field(24, 8);
46 | public static final BitString.Field BYTE2 = new BitString.Field(16, 8);
47 | public static final BitString.Field BYTE1 = new BitString.Field(8, 8);
48 | public static final BitString.Field BYTE0 = new BitString.Field(0, 8);
49 |
50 | protected ProtocolDecoderSink m_Sink = null;
51 | BitString data = new BitString();
52 | protected int state = IDLE;
53 | private int repeat;
54 |
55 | public void setTarget(ProtocolDecoderSink sink) {
56 | m_Sink = sink;
57 | }
58 |
59 | public ProtocolInfo getInfo() {
60 | return RollerTrol.ROLLERTROL_PROTOCOL_INFO;
61 | }
62 |
63 | protected void addBit(boolean b) {
64 | data.addMsb(b);
65 | if (data.length() == MESSAGE_BIT_LENGTH) {
66 | decodeMessage(data);
67 | }
68 | }
69 |
70 | public void decodeMessage(BitString binaryMessage) {
71 | int houseCode = binaryMessage.extractInt(HOUSE_CODE);
72 | int deviceCode = binaryMessage.extractInt(DEVICE_CODE);
73 | int command = binaryMessage.extractInt(COMMAND);
74 | int checkSum = binaryMessage.extractInt(CHECK_SUM);
75 | int calculatedCheckSum = calculateChecksum(binaryMessage);
76 | if (checkSum == calculatedCheckSum) {
77 | byte bytes[] = new byte[5];
78 | bytes[0] = (byte) binaryMessage.extractInt(BYTE4);
79 | bytes[1] = (byte) binaryMessage.extractInt(BYTE3);
80 | bytes[2] = (byte) binaryMessage.extractInt(BYTE2);
81 | bytes[3] = (byte) binaryMessage.extractInt(BYTE1);
82 | bytes[4] = (byte) binaryMessage.extractInt(BYTE0);
83 | ProtocolMessage message = new ProtocolMessage(ROLLER_TROL_PROTOCOL_NAME, command, deviceCode, 5);
84 | message.setRawMessageByteAt(0, bytes[0]);
85 | message.setRawMessageByteAt(1, bytes[1]);
86 | message.setRawMessageByteAt(2, bytes[2]);
87 | message.setRawMessageByteAt(3, bytes[3]);
88 | message.setRawMessageByteAt(4, bytes[4]);
89 |
90 | message.addField(new FieldValue(HOUSE_CODE_NAME, houseCode));
91 | message.addField(new FieldValue(DEVICE_CODE_NAME, deviceCode));
92 | message.addField(new FieldValue(COMMAND_NAME, command));
93 | message.setRepeat(repeat);
94 | m_Sink.parsedMessage(message);
95 | }
96 | state = REPEAT_SCAN;
97 | }
98 |
99 | public int parse(double pulse, boolean bitstate) {
100 | switch (state) {
101 | case IDLE: {
102 | if (RollerTrol.LONG_PREAMBLE_MARK.matches(pulse) && bitstate) {
103 | data.clear();
104 | repeat = 0;
105 | state = READING_LONG_PREAMBLE_SPACE;
106 | }
107 | break;
108 | }
109 | case READING_LONG_PREAMBLE_SPACE: {
110 | if (RollerTrol.LONG_PREAMBLE_SPACE.matches(pulse)) {
111 | state = READING_SHORT_PREAMBLE_MARK;
112 | } else {
113 | quitParsing(pulse);
114 | }
115 | break;
116 | }
117 | case READING_SHORT_PREAMBLE_MARK: {
118 | if (RollerTrol.SHORT_PREAMBLE_MARK.matches(pulse)) {
119 | state = READING_SHORT_PREAMBLE_SPACE;
120 | } else {
121 | quitParsing(pulse);
122 | }
123 | break;
124 | }
125 | case READING_SHORT_PREAMBLE_SPACE: {
126 | if (RollerTrol.SHORT.matches(pulse)) {
127 | state = READING_MARK;
128 | } else {
129 | quitParsing(pulse);
130 | }
131 | break;
132 | }
133 | case READING_MARK: {
134 | if (RollerTrol.SHORT.matches(pulse)) {
135 | state = READING_LONG_SPACE;
136 | } else if (RollerTrol.LONG.matches(pulse)) {
137 | state = READING_SHORT_SPACE;
138 | } else {
139 | quitParsing(pulse);
140 | }
141 | break;
142 | }
143 | case READING_SHORT_SPACE: {
144 | if (RollerTrol.SHORT.matches(pulse)) {
145 | state = READING_MARK;
146 | addBit(true);
147 | } else {
148 | quitParsing(pulse);
149 | }
150 | break;
151 | }
152 | case READING_LONG_SPACE: {
153 | if (RollerTrol.LONG.matches(pulse)) {
154 | state = READING_MARK;
155 | addBit(false);
156 | } else {
157 | quitParsing(pulse);
158 | }
159 | break;
160 | }
161 | case REPEAT_SCAN: {
162 | if (RollerTrol.LONG_PREAMBLE_MARK.matches(pulse) && bitstate) {
163 | data.clear();
164 | repeat++;
165 | state = READING_LONG_PREAMBLE_SPACE;
166 | } else if (!RollerTrol.LONG.matches(pulse) &&
167 | !RollerTrol.SHORT.matches(pulse) &&
168 | !TELLSTICK_MIN_REPEAT_GAP.matches(pulse)) {
169 | state = IDLE;
170 | }
171 | break;
172 | }
173 |
174 | }
175 | return state;
176 | }
177 |
178 | private void quitParsing(double pulseLength) {
179 | if (data.length() > 5) {
180 | m_Sink.partiallyParsedMessage(String.format("RollerTrol Pulse: %g ms, State: %d", pulseLength, state), data.length());
181 | }
182 | state = IDLE;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/RollerTrolGDecoder.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import nu.nethome.coders.RollerTrol;
4 | import nu.nethome.coders.RollerTrolG;
5 | import nu.nethome.util.ps.*;
6 |
7 | /**
8 | *
9 | */
10 | public class RollerTrolGDecoder implements ProtocolDecoder {
11 |
12 | protected static final int IDLE = 0;
13 | protected static final int READING_LONG_PREAMBLE_SPACE = 2;
14 | protected static final int READING_PREAMBLE_MARK = 3;
15 | protected static final int READING_MARK = 5;
16 | protected static final int READING_SHORT_SPACE = 6;
17 | protected static final int READING_LONG_SPACE = 7;
18 | protected static final int REPEAT_SCAN = 10;
19 |
20 |
21 | public static final BitString.Field BYTE4 = new BitString.Field(32, 8);
22 | public static final BitString.Field BYTE3 = new BitString.Field(24, 8);
23 | public static final BitString.Field BYTE2 = new BitString.Field(16, 8);
24 | public static final BitString.Field BYTE1 = new BitString.Field(8, 8);
25 | public static final BitString.Field BYTE0 = new BitString.Field(0, 8);
26 |
27 |
28 | protected ProtocolDecoderSink m_Sink = null;
29 | BitString data = new BitString();
30 | protected int state = IDLE;
31 | private int repeat = 0;
32 |
33 | public void setTarget(ProtocolDecoderSink sink) {
34 | m_Sink = sink;
35 | }
36 |
37 | public ProtocolInfo getInfo() {
38 | return RollerTrolG.ROLLERTROL_PROTOCOL_INFO;
39 | }
40 |
41 | protected void addBit(boolean b) {
42 | data.addLsb(b);
43 | if (data.length() == RollerTrolG.PROTOCOL_BIT_LENGTH) {
44 | decodeMessage(data);
45 | }
46 | }
47 |
48 | public void decodeMessage(BitString binaryMessage) {
49 | int channel = binaryMessage.extractInt(RollerTrolG.CHANNEL);
50 | int address = binaryMessage.extractInt(RollerTrolG.ADDRESS);
51 | int command = binaryMessage.extractInt(RollerTrolG.COMMAND);
52 | int bytes[] = new int[5];
53 | bytes[0] = binaryMessage.extractInt(BYTE4);
54 | bytes[1] = binaryMessage.extractInt(BYTE3);
55 | bytes[2] = binaryMessage.extractInt(BYTE2);
56 | bytes[3] = binaryMessage.extractInt(BYTE1);
57 | bytes[4] = binaryMessage.extractInt(BYTE0);
58 | ProtocolMessage message = new ProtocolMessage(RollerTrolG.ROLLER_TROL_G_PROTOCOL_NAME, command, channel, 5);
59 | message.setRawMessageByteAt(0, bytes[0]);
60 | message.setRawMessageByteAt(1, bytes[1]);
61 | message.setRawMessageByteAt(2, bytes[2]);
62 | message.setRawMessageByteAt(3, bytes[3]);
63 | message.setRawMessageByteAt(4, bytes[4]);
64 |
65 | message.addField(new FieldValue(RollerTrolG.COMMAND_NAME, command));
66 | message.addField(new FieldValue(RollerTrolG.CHANNEL_NAME, channel));
67 | message.addField(new FieldValue(RollerTrolG.ADDRESS_NAME, address));
68 | message.setRepeat(repeat);
69 | m_Sink.parsedMessage(message);
70 | state = REPEAT_SCAN;
71 | }
72 |
73 | public int parse(double pulse, boolean bitstate) {
74 | switch (state) {
75 | case IDLE: {
76 | if (RollerTrolG.LONG_PREAMBLE_MARK.matches(pulse) && bitstate) {
77 | data.clear();
78 | repeat = 0;
79 | state = READING_LONG_PREAMBLE_SPACE;
80 | }
81 | break;
82 | }
83 | case READING_LONG_PREAMBLE_SPACE: {
84 | if (RollerTrolG.LONG_PREAMBLE_SPACE.matches(pulse)) {
85 | state = READING_MARK;
86 | } else {
87 | quitParsing(pulse);
88 | }
89 | break;
90 | }
91 | case READING_MARK: {
92 | if (RollerTrolG.SHORT.matches(pulse)) {
93 | state = READING_LONG_SPACE;
94 | addBit(false);
95 | } else if (RollerTrolG.LONG.matches(pulse)) {
96 | state = READING_SHORT_SPACE;
97 | addBit(true);
98 | } else {
99 | quitParsing(pulse);
100 | }
101 | break;
102 | }
103 | case READING_SHORT_SPACE: {
104 | if (RollerTrolG.SHORT.matches(pulse)) {
105 | state = READING_MARK;
106 | } else {
107 | quitParsing(pulse);
108 | }
109 | break;
110 | }
111 | case READING_LONG_SPACE: {
112 | if (RollerTrolG.LONG.matches(pulse)) {
113 | state = READING_MARK;
114 | } else {
115 | quitParsing(pulse);
116 | }
117 | break;
118 | }
119 | case REPEAT_SCAN: {
120 | if (RollerTrolG.REPEAT_SPACE.matches(pulse)) {
121 | state = READING_PREAMBLE_MARK;
122 | } else {
123 | state = IDLE;
124 | }
125 | break;
126 | }
127 | case READING_PREAMBLE_MARK: {
128 | if (RollerTrolG.LONG_PREAMBLE_MARK.matches(pulse) && bitstate) {
129 | state = READING_LONG_PREAMBLE_SPACE;
130 | data.clear();
131 | repeat++;
132 | } else {
133 | state = IDLE;
134 | }
135 | break;
136 | }
137 | }
138 | return state;
139 | }
140 |
141 | private void quitParsing(double pulseLength) {
142 | if (data.length() > 5) {
143 | m_Sink.partiallyParsedMessage(String.format("RollerTrol Pulse: %g ms, State: %d", pulseLength, state), data.length());
144 | }
145 | state = IDLE;
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/SIRCDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | @Plugin
26 | public class SIRCDecoder implements ProtocolDecoder {
27 | protected static final int IDLE = 0;
28 | protected static final int READING_HEADER = 1;
29 | protected static final int READING_BIT_MARK = 2;
30 | protected static final int READING_BIT_SPACE = 3;
31 | protected static final int REPEAT_SCAN = 4;
32 |
33 | protected int m_State = IDLE;
34 |
35 | protected int m_Command = 0;
36 | protected int m_Address = 0;
37 | protected int m_Extra = 0;
38 |
39 | protected int m_LastCommand = 0;
40 | protected int m_LastAddress = 0;
41 | protected int m_LastExtra = 0;
42 |
43 | protected int m_BitCounter = 0;
44 | protected int m_RepeatCount = 0;
45 | protected ProtocolDecoderSink m_Sink = null;
46 |
47 | public void setTarget(ProtocolDecoderSink sink) {
48 | m_Sink = sink;
49 | }
50 |
51 | public ProtocolInfo getInfo() {
52 | return new ProtocolInfo("SIRC20", "Mark Length", "Sony", 20, 5);
53 | }
54 |
55 | protected boolean pulseCompare(double candidate, double standard) {
56 | return Math.abs(standard - candidate) < standard * 0.3;
57 | }
58 |
59 | protected void addBit(int b) {
60 | if (m_BitCounter < 7) {
61 | m_Command += b << m_BitCounter;
62 | }
63 | else if (m_BitCounter < 12) {
64 | m_Address += b << (m_BitCounter - 7);
65 | }
66 | else if (m_BitCounter < 20) {
67 | m_Extra += b << (m_BitCounter - 12);
68 | }
69 | // Check if this is a complete message
70 | if (m_BitCounter == 19){
71 | // It is, create the message
72 | ProtocolMessage message = new ProtocolMessage("SIRC20", m_Command, m_Address, 3);
73 | message.setRawMessageByteAt(0, m_Command);
74 | message.setRawMessageByteAt(1, m_Address);
75 | message.setRawMessageByteAt(2, m_Extra);
76 | message.addField(new FieldValue("Command", m_Command));
77 | message.addField(new FieldValue("Address", m_Address));
78 | message.addField(new FieldValue("Extended", m_Extra));
79 |
80 | // It is, check if this really is a repeat
81 | if ((m_RepeatCount > 0) && (m_Command == m_LastCommand) && (m_Address == m_LastAddress)
82 | && (m_Extra == m_LastExtra)) {
83 | message.setRepeat(m_RepeatCount);
84 | }
85 | else {
86 | // It is not a repeat, reset counter
87 | m_RepeatCount = 0;
88 | }
89 | // Report the parsed message
90 | m_Sink.parsedMessage(message);
91 | m_State = REPEAT_SCAN;
92 | }
93 | m_BitCounter++;
94 | }
95 |
96 | /* (non-Javadoc)
97 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
98 | */
99 | public int parse(double pulse, boolean state) {
100 | switch (m_State) {
101 | case IDLE: {
102 | if (pulseCompare(pulse, 2400.0 + 60) && state) {
103 | m_State = READING_HEADER;
104 | m_Command = 0;
105 | m_Address = 0;
106 | m_Extra = 0;
107 | m_BitCounter = 0;
108 | }
109 | break;
110 | }
111 | case READING_HEADER: {
112 | if (pulseCompare(pulse, 600.0 - 60)) {
113 | m_State = READING_BIT_MARK;
114 | }
115 | else {
116 | m_State = IDLE;
117 | }
118 | break;
119 | }
120 | case READING_BIT_MARK: {
121 | if (pulseCompare(pulse, 1200.0 + 60)) {
122 | m_State = READING_BIT_SPACE;
123 | addBit(1);
124 | }
125 | else if (pulseCompare(pulse, 600.0 + 60)) {
126 | m_State = READING_BIT_SPACE;
127 | addBit(0);
128 | }
129 | else {
130 | m_State = IDLE;
131 | }
132 | break;
133 | }
134 | case READING_BIT_SPACE: {
135 | if (pulseCompare(pulse, 600.0 - 60)) {
136 | m_State = READING_BIT_MARK;
137 | }
138 | else {
139 | m_State = IDLE;
140 | }
141 | break;
142 | }
143 | case REPEAT_SCAN: {
144 | if (pulseCompare(pulse, 12000.0)) {
145 | m_RepeatCount += 1; // Start repeat sequence
146 | // Save this sequence
147 | m_LastCommand = m_Command;
148 | m_LastAddress = m_Address;
149 | m_LastExtra = m_Extra ;
150 | }
151 | else {
152 | m_RepeatCount = 0;
153 | }
154 | m_State = IDLE;
155 | break;
156 | }
157 | }
158 | return m_State;
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/ViasatDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | @Plugin
26 | public class ViasatDecoder implements ProtocolDecoder {
27 | protected static final int IDLE = 0;
28 | protected static final int READING_HEADER = 1;
29 | protected static final int READING_HEADER2 = 6;
30 | protected static final int HI_IN = 2;
31 | protected static final int HI_BETWEEN = 3;
32 | protected static final int LO_IN = 4;
33 | protected static final int LO_BETWEEN = 5;
34 |
35 | protected static final int VIA_SHORT = 320;
36 | protected static final int VIA_LONG = 720;
37 |
38 | protected int m_State = IDLE;
39 |
40 | protected int m_Byte1 = 0;
41 | protected int m_Byte2 = 0;
42 | protected int m_Byte3 = 0;
43 | protected int m_Byte4 = 0;
44 | protected int m_LastWord = 0;
45 |
46 |
47 | protected int m_LastCommand = 0;
48 | protected int m_LastAddress = 0;
49 | protected int m_LastExtra = 0;
50 |
51 | protected int m_BitCounter = 0;
52 | protected int m_RepeatCount = 0;
53 | protected double m_LastValue = 0;
54 | protected ProtocolDecoderSink m_Sink = null;
55 |
56 | public void setTarget(ProtocolDecoderSink sink) {
57 | m_Sink = sink;
58 | }
59 |
60 | public ProtocolInfo getInfo() {
61 | return new ProtocolInfo("Viasat", "Diff Manchester", "Viasat", 32, 5);
62 | }
63 |
64 | protected boolean pulseCompare(double candidate, double standard) {
65 | return Math.abs(standard - candidate) < standard * 0.3;
66 | }
67 |
68 | protected void addBit(int b) {
69 | if (m_BitCounter < 8) {
70 | m_Byte1 = (m_Byte1 << 1) + b ;
71 | }
72 | else if (m_BitCounter < 16){
73 | m_Byte2 = (m_Byte2 << 1) + b ;
74 | }
75 | else if (m_BitCounter < 24) {
76 | m_Byte3 = (m_Byte3 << 1) + b ;
77 | }
78 | else if (m_BitCounter < 32) {
79 | m_Byte4 = (m_Byte4 << 1) + b ;
80 | }
81 | // Check if this is a complete message
82 | if (m_BitCounter == 31){
83 | // It is, create the message
84 | ProtocolMessage message = new ProtocolMessage("Viasat", m_Byte3, m_Byte4, 4);
85 | message.setRawMessageByteAt(0, m_Byte1);
86 | message.setRawMessageByteAt(1, m_Byte2);
87 | message.setRawMessageByteAt(2, m_Byte3);
88 | message.setRawMessageByteAt(3, m_Byte4);
89 |
90 | message.addField(new FieldValue("Header", m_Byte1));
91 | message.addField(new FieldValue("Flip", m_Byte2));
92 | message.addField(new FieldValue("Command", m_Byte3));
93 | message.addField(new FieldValue("Checksum?", m_Byte4));
94 |
95 | // Check if it is a repeat
96 | int newWord = m_Byte4 << 24 + m_Byte4 << 16 + m_Byte4 << 8 + m_Byte4;
97 | if ((newWord == m_LastWord) && m_RepeatCount != 0) {
98 | message.setRepeat(m_RepeatCount);
99 | }
100 | else {
101 | m_RepeatCount = 0;
102 | }
103 |
104 | // Report the parsed message
105 | m_Sink.parsedMessage(message);
106 | // Reset state
107 | m_State = IDLE;
108 | // Save message for repeat check
109 | m_LastWord = newWord;
110 | }
111 | m_BitCounter++;
112 | }
113 |
114 | public void parseMan(double pulse, boolean state) {
115 | switch (m_State) {
116 | case IDLE: {
117 | if (pulseCompare(pulse, 2666.0) && state) {
118 | m_State = READING_HEADER;
119 | m_Byte1 = 0;
120 | m_Byte2 = 0;
121 | m_Byte3 = 0;
122 | m_Byte4 = 0;
123 | m_BitCounter = 0;
124 |
125 | if (pulseCompare(m_LastValue, 75000.0)) {
126 | m_RepeatCount++;
127 | }
128 | else {
129 | m_RepeatCount = 0;
130 | }
131 | }
132 | break;
133 | }
134 | case READING_HEADER: {
135 | if (pulseCompare(pulse, 1850.0)) {
136 | m_State = LO_IN;
137 | }
138 | else {
139 | invalidMessage("Viasat h");
140 | }
141 | break;
142 | }
143 | case HI_IN: {
144 | if (pulseCompare(pulse, VIA_SHORT)) {
145 | m_State = LO_BETWEEN;
146 | } else if (pulseCompare(pulse, VIA_LONG)) {
147 | m_State = LO_IN;
148 | addBit(0);
149 | } else {
150 | invalidMessage("Viasat");
151 | }
152 | break;
153 | }
154 | case HI_BETWEEN: {
155 | if (pulseCompare(pulse, VIA_SHORT)) {
156 | m_State = LO_IN;
157 | addBit(0);
158 | } else {
159 | invalidMessage("Viasat");
160 | }
161 | break;
162 | }
163 | case LO_IN: {
164 | if (pulseCompare(pulse, VIA_SHORT)) {
165 | m_State = HI_BETWEEN;
166 | break;
167 | } else if (pulseCompare(pulse, VIA_LONG)) {
168 | m_State = HI_IN;
169 | addBit(1);
170 | } else {
171 | invalidMessage("Viasat");
172 | }
173 | break;
174 | }
175 | case LO_BETWEEN: {
176 | if (pulseCompare(pulse, VIA_SHORT)) {
177 | m_State = HI_IN;
178 | addBit(1);
179 | } else {
180 | invalidMessage("Viasat");
181 | }
182 | break;
183 | }
184 | }
185 | m_LastValue = pulse;
186 | }
187 |
188 | private void invalidMessage(String message) {
189 | if (m_BitCounter > 4) {
190 | m_Sink.partiallyParsedMessage(message, m_BitCounter);
191 | }
192 | m_State = IDLE;
193 | }
194 |
195 |
196 | /* (non-Javadoc)
197 | * @see ssg.ir.IRDecoder#parse(java.lang.Double)
198 | */
199 | public int parse(double pulse, boolean state) {
200 | switch (m_State) {
201 | case IDLE: {
202 | if (pulseCompare(pulse, 2666.0) && state) {
203 | m_State = READING_HEADER;
204 | m_Byte1 = 0;
205 | m_Byte2 = 0;
206 | m_Byte3 = 0;
207 | m_Byte4 = 0;
208 | m_BitCounter = 0;
209 |
210 | if (pulseCompare(m_LastValue, 85000.0)) {
211 | m_RepeatCount++;
212 | }
213 | else {
214 | m_RepeatCount = 0;
215 | }
216 | }
217 | break;
218 | }
219 | case READING_HEADER: {
220 | if (pulseCompare(pulse, 1850.0)) {
221 | m_State = HI_BETWEEN;
222 | }
223 | else {
224 | invalidMessage("Viasat h1");
225 | }
226 | break;
227 | }
228 | case READING_HEADER2: {
229 | if (pulseCompare(pulse, VIA_LONG)) {
230 | m_State = HI_BETWEEN;
231 | }
232 | else {
233 | invalidMessage("Viasat h2");
234 | }
235 | break;
236 | }
237 | case HI_IN: {
238 | if (pulseCompare(pulse, VIA_SHORT)) {
239 | m_State = LO_BETWEEN;
240 | addBit(0);
241 | } else if (pulseCompare(pulse, VIA_LONG)) {
242 | m_State = LO_IN;
243 | addBit(1);
244 | } else {
245 | invalidMessage("Viasat");
246 | }
247 | break;
248 | }
249 | case HI_BETWEEN: {
250 | if (pulseCompare(pulse, VIA_SHORT)) {
251 | m_State = LO_IN;
252 | } else if (pulseCompare(pulse, VIA_LONG)) {
253 | m_State = LO_BETWEEN;
254 | addBit(0);
255 | } else {
256 | invalidMessage("Viasat");
257 | }
258 | break;
259 | }
260 | case LO_IN: {
261 | if (pulseCompare(pulse, VIA_SHORT)) {
262 | m_State = HI_BETWEEN;
263 | addBit(0);
264 | break;
265 | } else if (pulseCompare(pulse, VIA_LONG)) {
266 | m_State = HI_IN;
267 | addBit(1);
268 | } else {
269 | invalidMessage("Viasat");
270 | }
271 | break;
272 | }
273 | case LO_BETWEEN: {
274 | if (pulseCompare(pulse, VIA_SHORT)) {
275 | m_State = HI_IN;
276 | } else if (pulseCompare(pulse, VIA_LONG)) {
277 | m_State = HI_BETWEEN;
278 | addBit(0);
279 | } else {
280 | invalidMessage("Viasat");
281 | }
282 | break;
283 | }
284 | }
285 | m_LastValue = pulse;
286 | return m_State;
287 | }
288 | }
289 |
290 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/WavemanDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.ProtocolDecoder;
24 |
25 | /**
26 | * The WavemanDecoder parses a set of pulse lengths and decodes a protocol used
27 | * by UPM-thermometers which is transmitted over 433MHz AM-modulated RF-signal.
28 | * The reception of the pulses may for example be made via the AudioProtocolSampler.
29 | * The WavemanDecoder implements the ProtocolDecoder-interface and accepts the pulses
30 | * one by one. It contains a state machine, and when a complete message is decoded,
31 | * this is reported over the ProtocolDecoderSink-interface which is given at
32 | * construction.
33 | *
34 | * The protocol is mark length encoded and the protocol messages has the following
35 | * layout:
36 | *
37 | * s = Start bit = 0
38 | * b = Button number
39 | * a = Address
40 | * o = On/Off-bit
41 | *
42 | * ____Byte 2_____ ____Byte 1_____ ____Byte 0_____ _S_
43 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0
44 | * x o x o x o x x x b x b x b x b x a x a x a x a s
45 | *
46 | * This protocol is almost exactly the same as NEXA, so the entire implementation is reused.
47 | * The difference is that bit 2 and 4 of Byte 2 is always 1 in NEXA.
48 | *
49 | * @author Stefan
50 | *
51 | */
52 | @Plugin
53 | public class WavemanDecoder extends NexaDecoder implements ProtocolDecoder{
54 |
55 | public void setup() {
56 | m_ProtocolName = "Waveman";
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/decoders/ZhejiangDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.FieldValue;
24 | import nu.nethome.util.ps.ProtocolDecoder;
25 | import nu.nethome.util.ps.ProtocolMessage;
26 | import nu.nethome.util.ps.PulseLength;
27 |
28 | /**
29 | * The ZhejiangDecoder parses a set of pulse lengths and decodes a protocol used
30 | * by lamp remote controls which is transmitted over 433MHz AM-modulated RF-signal.
31 | * The reception of the pulses may for example be made via the AudioProtocolSampler.
32 | * The ZhejiangDecoder implements the ProtocolDecoder-interface and accepts the pulses
33 | * one by one. It contains a state machine, and when a complete message is decoded,
34 | * this is reported over the ProtocolDecoderSink-interface which is given at
35 | * construction.
36 | *
37 | * The protocol is mark length encoded and the protocol messages has the following
38 | * layout:
39 | *
40 | * s = Start bit = 0
41 | * a = Channel 1 not selected
42 | * b = Channel 2 not selected
43 | * c = Channel 3 not selected
44 | * d = Channel 4 not selected
45 | * e = Channel 5 not selected
46 | * f = Button A not pressed
47 | * g = Button B not pressed
48 | * h = Button C not pressed
49 | * i = Button D not pressed
50 | * j = Button E not pressed
51 | * o = On/Off-bit
52 | *
53 | *_S_ ____Byte 2_____ ____Byte 1_____ ____Byte 0_____
54 | * 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
55 | * x o 0 1 0 j 0 i 0 h 0 g 0 f 0 1 e 1 d 1 c 1 b 1 a
56 | *
57 | * This protocol is almost exactly the same as NEXA, so the entire implementation is reused.
58 | *
59 | * @author Stefan
60 | */
61 | @Plugin
62 | public class ZhejiangDecoder extends NexaDecoder implements ProtocolDecoder{
63 |
64 | // This are the pulse length constants for the protocol. The default values may
65 | // be overridden by system properties
66 | public static final PulseLength ZHEJ_LONG_MARK =
67 | new PulseLength(ZhejiangDecoder.class, "ZHEJ_LONG_MARK", 430, 370, 550);
68 | public static final PulseLength ZHEJ_SHORT_MARK =
69 | new PulseLength(ZhejiangDecoder.class, "ZHEJ_SHORT_MARK", 140, 100, 220);
70 | public static final PulseLength ZHEJ_LONG_SPACE =
71 | new PulseLength(ZhejiangDecoder.class, "ZHEJ_LONG_SPACE", 450, 370, 550);
72 | public static final PulseLength ZHEJ_SHORT_SPACE =
73 | new PulseLength(ZhejiangDecoder.class, "ZHEJ_SHORT_SPACE", 170, 100, 220);
74 | public static final PulseLength ZHEJ_REPEAT =
75 | new PulseLength(ZhejiangDecoder.class, "ZHEJ_REPEAT", 4560, 500);
76 |
77 | public void setup() {
78 | m_ProtocolName = "Zhejiang";
79 | LONG_MARK = ZHEJ_LONG_MARK;
80 | SHORT_MARK = ZHEJ_SHORT_MARK;
81 | LONG_SPACE = ZHEJ_LONG_SPACE;
82 | SHORT_SPACE = ZHEJ_SHORT_SPACE;
83 | REPEAT = ZHEJ_REPEAT;
84 | }
85 |
86 | protected int bytemap(int raw) {
87 | return (raw & 1) + ((raw >> 1) & 2) + ((raw >> 2) & 4) + ((raw >> 3) & 8) + ((raw >> 4) & 0x10);
88 | }
89 |
90 | protected void addBit(int b) {
91 | // Shift in data
92 | m_Data >>= 1;
93 | m_Data |= (b << 24);
94 | // Check if this is a complete message
95 | if (m_BitCounter == 24) {
96 | // It is, create the message
97 | int command = ((m_Data >> 23) & 1) ^ 1;
98 | int rawButton = bytemap(((m_Data >> 11) ^ 0x3FF) & 0x3FF);
99 | int address = bytemap((m_Data ^ 0x3FF) & 0x3FF);
100 | int button = bitPosToInt(rawButton);
101 |
102 | // Sender ends a message sequence by a signal saying "no button is pressed".
103 | // We ignore that message.
104 | if (rawButton == 0) {
105 | m_State = IDLE;
106 | m_RepeatCount = 0;
107 | return;
108 | }
109 |
110 | ProtocolMessage message = new ProtocolMessage(m_ProtocolName, command, (rawButton << 8) + address, 4);
111 | message.setRawMessageByteAt(0, (m_Data >> 24) & 0x1);
112 | message.setRawMessageByteAt(1, (m_Data >> 16) & 0xFF);
113 | message.setRawMessageByteAt(2, (m_Data >> 8) & 0xFF);
114 | message.setRawMessageByteAt(3, (m_Data) & 0xFF);
115 |
116 | message.addField(new FieldValue("Command", command));
117 | message.addField(new FieldValue("Button", button));
118 | message.addField(new FieldValue("Address", address));
119 |
120 | // It is, check if this really is a repeat
121 | if ((m_RepeatCount > 0) && (m_Data == m_LastData)) {
122 | message.setRepeat(m_RepeatCount);
123 | } else {
124 | // It is not a repeat, reset counter
125 | m_RepeatCount = 0;
126 | }
127 | // Report the parsed message
128 | m_Sink.parsedMessage(message);
129 | m_State = REPEAT_SCAN;
130 | }
131 | m_BitCounter++;
132 | }
133 |
134 | private int bitPosToInt(int rawButton) {
135 | int shift = rawButton;
136 | for (int i = 0; i < 5; i++) {
137 | if ((shift & 1) == 1) {
138 | return i;
139 | }
140 | shift >>= 1;
141 | }
142 | return 5;
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/DeltronicEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | import java.util.ArrayList;
26 |
27 | /**
28 | * The DeltronicEncoder is an encoder for the RF-protocol used by
29 | * Deltronic products such as remote switches. The DeltronicEncoder
30 | * can take the data from a protocol message and encode that into a sequence
31 | * of pulse lengths which may be played by RF-transmitting hardware for instance
32 | * via the AudioPulsePlayer.
33 | *
34 | * @author Stefan
35 | */
36 | @Plugin
37 | public class DeltronicEncoder implements ProtocolEncoder {
38 |
39 | public int repeatCount = 3;
40 | private int address = 0;
41 | private int command = 1;
42 | private int button = 0;
43 |
44 | protected static final int DELTRONIC_HEADER_MARK = 330 - 60;
45 | protected static final int DELTRONIC_HEADER_SPACE = 830 + 60;
46 | protected static final int DELTRONIC_LONG_MARK = 835 - 60;
47 | protected static final int DELTRONIC_SHORT_MARK = 280 - 60;
48 | protected static final int DELTRONIC_LONG_SPACE = 845 + 60;
49 | protected static final int DELTRONIC_SHORT_SPACE = 300 + 60;
50 | protected static final int DELTRONIC_INTER_SPACE = 850 + 60;
51 | protected static final int DELTRONIC_REPEAT = 8810 + 60;
52 |
53 | protected static final int MESSAGE_LENGTH = 12;
54 | protected static final int HIGH_BIT = 1 << (MESSAGE_LENGTH - 1);
55 |
56 | static final int s_Buttons[] = {0x20, 0x10, 0x04, 0x08};
57 |
58 | /**
59 | * Encodes the current message according to the following protocol:
60 | *
61 | * a = Address
62 | * A = Button A
63 | * B = Button B
64 | * C = Button C
65 | * D = Button D
66 | * f = Off-bit
67 | * n = On-bit
68 | *
69 | * ____Byte 1_____ ____Byte 0_____
70 | * 3 2 1 0 7 6 5 4 3 2 1 0
71 | * a a a a a a A B D C f n
72 | */
73 | public int[] encode() {
74 | ArrayList result = new ArrayList();
75 | long message = 0;
76 |
77 | // encode message
78 | long messageTemplate = 0x00000000;
79 | messageTemplate |= (command == 1) ? 0x01 : 0x02;
80 | messageTemplate |= s_Buttons[button];
81 | messageTemplate |= (address << 6);
82 |
83 | // Start encoding the data pulses
84 | for (int i = 0; i < repeatCount; i++) {
85 | message = messageTemplate;
86 |
87 | // Encode header
88 | result.add(DELTRONIC_HEADER_MARK);
89 | result.add(DELTRONIC_HEADER_SPACE);
90 |
91 | // Encode message bits
92 | for (int j = 0; j < (MESSAGE_LENGTH); j++) {
93 | if ((message & HIGH_BIT) == HIGH_BIT) {
94 | result.add(DELTRONIC_SHORT_MARK);
95 | result.add(DELTRONIC_LONG_SPACE);
96 | }
97 | else {
98 | result.add(DELTRONIC_LONG_MARK);
99 | result.add(DELTRONIC_SHORT_SPACE);
100 | }
101 | result.add(DELTRONIC_SHORT_MARK);
102 | result.add(DELTRONIC_INTER_SPACE);
103 | message <<= 1;
104 | }
105 | // Add the repeat delay
106 | int last = result.size() - 1;
107 | // Add the repeat delay to the last space period
108 | result.set(last, DELTRONIC_REPEAT);
109 | }
110 | int resultArray[] = new int[result.size()];
111 | for (int i = 0; i < result.size(); i++) {
112 | resultArray[i] = result.get(i);
113 | }
114 | return resultArray;
115 | }
116 |
117 | public int getAddress() {
118 | return address;
119 | }
120 |
121 | public void setAddress(int address) {
122 | if ((address >= (1<<6)) || (address < 0)) {
123 | return;
124 | }
125 | this.address = address;
126 | }
127 |
128 | public int getCommand() {
129 | return command;
130 | }
131 |
132 | public void setCommand(int command) {
133 | if ((command > 1) || (command < 0)) {
134 | return;
135 | }
136 | this.command = command;
137 | }
138 |
139 | public int getRepeatCount() {
140 | return repeatCount;
141 | }
142 |
143 | public void setRepeatCount(int repeatCount) {
144 | if ((repeatCount < 1) || (repeatCount > 100)) {
145 | return;
146 | }
147 | this.repeatCount = repeatCount;
148 | }
149 |
150 | public int getButton() {
151 | return button;
152 | }
153 |
154 | public void setButton(int button) {
155 | if ((button < 0) || (button > 3)) {
156 | return;
157 | }
158 | this.button = button;
159 | }
160 |
161 | public ProtocolInfo getInfo() {
162 | return new ProtocolInfo("Deltronic", "Space Length", "Deltronic", 12, 5);
163 | }
164 |
165 | public int[] encode(Message message, Phase phase) throws BadMessageException {
166 | if (Phase.FIRST == phase) {
167 | return new int[0];
168 | }
169 | for (FieldValue field : message.getFields()) {
170 | if (field.getName().equals("Command")) {
171 | setCommand(field.getValue());
172 | } else if (field.getName().equals("Button")) {
173 | setButton(field.getValue());
174 | } else if (field.getName().equals("Address")) {
175 | setAddress(field.getValue());
176 | } else {
177 | throw new BadMessageException(field);
178 | }
179 | }
180 | setRepeatCount(1);
181 | return encode();
182 | }
183 |
184 | @Override
185 | public int modulationFrequency(Message message) {
186 | return 0;
187 | }
188 |
189 | public static Message buildCommandMessage(boolean on, int button, int address) {
190 | ProtocolMessage result = new ProtocolMessage("Deltronic", on ? 1 :0, address, 0);
191 | result.addField(new FieldValue("Command", on ? 1 : 0));
192 | result.addField(new FieldValue("Button", button));
193 | result.addField(new FieldValue("Address", address));
194 | return result;
195 | };
196 | }
197 |
198 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/EmotivaEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | import java.util.ArrayList;
26 |
27 | /**
28 | * User: Stefan
29 | * Date: 2013-01-27
30 | * Time: 21:06
31 | */
32 | @Plugin
33 | public class EmotivaEncoder implements ProtocolEncoder {
34 |
35 |
36 | public static final int EMOTIVA_RAW_MESSAGE_LENGTH = 32;
37 | public static final int EMOTIVA_HEADER_MARK = 9100;
38 | public static final int EMOTIVA_HEADER_SPACE = 4400;
39 | public static final int EMOTIVA_MARK = 630;
40 | public static final int EMOTIVA_LONG_SPACE = 1600;
41 | public static final int EMOTIVA_SHORT_SPACE = 500;
42 | public static final int EMOTIVA_REPEAT_SPACE = 9100;
43 |
44 | public ProtocolInfo getInfo() {
45 | return new ProtocolInfo("Emotiva", "Space Length", "Emotiva", 24, 5);
46 | }
47 |
48 | public int[] encode(Message message, Phase phase) throws BadMessageException {
49 | if (Phase.FIRST == phase) {
50 | return new int[0];
51 | }
52 | int command = 0;
53 | int address = 0;
54 | for (FieldValue field : message.getFields()) {
55 | if (field.getName().equals("Command")) {
56 | command = field.getValue();
57 | } else if (field.getName().equals("Address")) {
58 | address = field.getValue();
59 | } else {
60 | throw new BadMessageException(field);
61 | }
62 | }
63 | return encode(command, address);
64 | }
65 |
66 | @Override
67 | public int modulationFrequency(Message message) {
68 | return 40000;
69 | }
70 |
71 | public static Message buildMessage(int command, int address) {
72 | ProtocolMessage result = new ProtocolMessage("Emotiva", command, address, 0);
73 | result.addField(new FieldValue("Command", command));
74 | result.addField(new FieldValue("Address", address));
75 | return result;
76 | }
77 |
78 | private int[] encode(int command, int address) {
79 | ArrayList result = new ArrayList();
80 | long message = address + (command << 16) + ((command ^ 0xFF) << 24);
81 | // Encode header
82 | result.add(EMOTIVA_HEADER_MARK);
83 | result.add(EMOTIVA_HEADER_SPACE);
84 |
85 | // Encode message bits
86 | for (int j = 0; j < (EMOTIVA_RAW_MESSAGE_LENGTH); j++) {
87 | result.add(EMOTIVA_MARK);
88 | if ((message & 1) == 1) {
89 | result.add(EMOTIVA_LONG_SPACE);
90 | } else {
91 | result.add(EMOTIVA_SHORT_SPACE);
92 | }
93 | message >>= 1;
94 | }
95 | result.add(EMOTIVA_MARK);
96 | result.add(EMOTIVA_REPEAT_SPACE);
97 |
98 | int resultArray[] = new int[result.size()];
99 | for (int i = 0; i < result.size(); i++) {
100 | resultArray[i] = result.get(i);
101 | }
102 | return resultArray;
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/Encoders.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2015, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.util.ps.ProtocolEncoder;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Collection;
26 |
27 | public class Encoders {
28 | public static Collection> getAllTypes() {
29 | Collection> result = new ArrayList>();
30 | result.add(DeltronicEncoder.class);
31 | result.add(EmotivaEncoder.class);
32 | result.add(NexaEncoder.class);
33 | result.add(NexaFireEncoder.class);
34 | result.add(NexaLEncoder.class);
35 | result.add(ProntoEncoder.class);
36 | result.add(RisingSunEncoder.class);
37 | result.add(WavemanEncoder.class);
38 | result.add(X10Encoder.class);
39 | result.add(ZhejiangEncoder.class);
40 | result.add(RollerTrolEncoder.class);
41 | result.add(RollerTrolGEncoder.class);
42 | return result;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/NexaFireEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.coders.decoders.NexaFireDecoder;
23 | import nu.nethome.util.plugin.Plugin;
24 | import nu.nethome.util.ps.*;
25 |
26 | import java.util.ArrayList;
27 |
28 | /**
29 | * The NexaFireEncoder is an encoder for the RF-protocol used by NEXA Fire Detectors
30 | * with RF connection. The NexaFireEncoder can take the data from a protocol message
31 | * and encode that into a sequence of pulse lengths which may be played by
32 | * RF-transmitting hardware for instance via the AudioPulsePlayer.
33 | *
34 | * @author Stefan
35 | *
36 | */
37 | @Plugin
38 | public class NexaFireEncoder implements ProtocolEncoder {
39 |
40 | public int m_RepeatCount = 15;
41 | private int m_Address = 0;
42 |
43 | // Get the pulse lengths from the decoder
44 | protected int HEADER_MARK = NexaFireDecoder.NEXAF_HEADER_MARK.length();
45 | protected int HEADER_SPACE = NexaFireDecoder.NEXAF_HEADER_SPACE.length();
46 | protected int MARK = NexaFireDecoder.NEXAF_MARK.length();
47 | protected int LONG_SPACE = NexaFireDecoder.NEXAF_LONG_SPACE.length();
48 | protected int SHORT_SPACE = NexaFireDecoder.NEXAF_SHORT_SPACE.length();
49 | protected int REPEAT = NexaFireDecoder.NEXAF_REPEAT.length();
50 |
51 | public NexaFireEncoder() {
52 | setup();
53 | }
54 |
55 | /**
56 | * Template method pattern. This is called by the constructor in order to be able to let
57 | * subclasses change pulse lengths and other parameters
58 | */
59 | protected void setup() {
60 | }
61 |
62 | /**
63 | * Encodes the current message according to the following protocol:
64 | *
65 | * a = Address
66 | *
67 | * ____Byte 2_____ ____Byte 1_____ ____Byte 0_____
68 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
69 | * a a a a a a a a a a a a a a a a a a a a a a a a
70 | */
71 | public int[] encode() {
72 | ArrayList result = new ArrayList();
73 | long message = 0;
74 |
75 | // Start actually encoding the data pulses
76 | for (int i = 0; i < m_RepeatCount; i++) {
77 | message = m_Address;
78 |
79 | // Encode header
80 | result.add(HEADER_MARK);
81 | result.add(HEADER_SPACE);
82 |
83 | // 24 bits of data
84 | for (int j = 0; j < 24; j++) {
85 | result.add(MARK);
86 | if ((message & 1) == 1) {
87 | result.add(LONG_SPACE);
88 | }
89 | else {
90 | result.add(SHORT_SPACE);
91 | }
92 | message >>= 1;
93 | }
94 | // Add trailing mark and repeat space
95 | result.add(MARK);
96 | result.add(REPEAT);
97 | }
98 | int resultArray[] = new int[result.size()];
99 | for (int i = 0; i < result.size(); i++) {
100 | resultArray[i] = result.get(i);
101 | }
102 | return resultArray;
103 | }
104 |
105 | /**
106 | * @return the Address
107 | */
108 | public int getAddress() {
109 | return m_Address;
110 | }
111 |
112 | /**
113 | * @param address the Address to set
114 | */
115 | public void setAddress(int address) {
116 | if (address > 0xFFFFFF) return;
117 | this.m_Address = address;
118 | }
119 |
120 | public int getRepeatCount() {
121 | return m_RepeatCount;
122 | }
123 |
124 | public void setRepeatCount(int repeatCount) {
125 | if ((repeatCount < 1) || (repeatCount > 100)) {
126 | return;
127 | }
128 | this.m_RepeatCount = repeatCount;
129 | }
130 |
131 | @Override
132 | public ProtocolInfo getInfo() {
133 | return new ProtocolInfo("NexaFire", "Space Length", "NexaFire", 24, 15);
134 | }
135 |
136 | @Override
137 | public int[] encode(Message message, Phase phase) throws BadMessageException {
138 | if (Phase.FIRST == phase) {
139 | return new int[0];
140 | }
141 | for (FieldValue field : message.getFields()) {
142 | if (field.getName().equals("Address")) {
143 | setAddress(field.getValue());
144 | } else {
145 | throw new BadMessageException(field);
146 | }
147 | }
148 | setRepeatCount(1);
149 | return encode();
150 | }
151 |
152 | @Override
153 | public int modulationFrequency(Message message) {
154 | return 0;
155 | }
156 | }
157 |
158 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/ProntoEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.*;
24 |
25 | import java.util.NoSuchElementException;
26 | import java.util.Scanner;
27 |
28 | /**
29 | * Pronto Encoder takes a message string encoded in the Pronto-format
30 | * and decodes it into a format used to transmit messages via RF or IR.
31 | * Messages can be sent by {@link nu.nethome.util.ps.impl.AudioPulsePlayer}.
32 | *
33 | * @author Stefan
34 | */
35 | @Plugin
36 | public class ProntoEncoder implements ProtocolEncoder{
37 |
38 | /** Constant for the pronto remote's internal clock frequency */
39 | protected final double m_ProntoFreqConstant = .241246;
40 |
41 | protected String m_Message = "";
42 | protected int m_RepeatCount = 5;
43 |
44 | /**
45 | * Extract the modulation frequency in Hz from a Pronto message
46 | * @param prontoMessage
47 | * @return modulation frequency
48 | */
49 | public int modulationFrequency(Message prontoMessage) {
50 | if(prontoMessage.getFields().size() != 1 || !prontoMessage.getFields().get(0).getName().equals("Message")) {
51 | return 0;
52 | }
53 | Scanner scanner = new Scanner(prontoMessage.getFields().get(0).getStringValue());
54 | double period = 10;
55 | try {
56 | // Extract type, 0000 for sampled signal. This is the only format we support
57 | if (scanner.nextInt(16) != 0) return 0;
58 | // Extract modulation frequency period length
59 | period = scanner.nextInt(16) * m_ProntoFreqConstant;
60 | if (period < 10) return 0;
61 | }
62 | catch (NoSuchElementException e) {
63 | return 0;
64 | }
65 | return (int)(1000000 / period);
66 | }
67 |
68 | /**
69 | * Encode the current message as a sequence of pulse lengths. Note that this encodes
70 | * both sequence #1 and sequence #2 into the pulse sequence. Use getRepeatPoint() to find out
71 | * at what position sequence #2 begins.
72 | * @return list of pulse lengths in micro seconds
73 | */
74 | public int[] encode() {
75 | int fail[] = new int[0];
76 | int result[];
77 | Scanner scanner = new Scanner(m_Message);
78 | try {
79 | // Extract type, 0000 for sampled signal. This is the only format we support
80 | if (scanner.nextInt(16) != 0) return fail;
81 | // Extract modulation frequency period length
82 | double period = scanner.nextInt(16) * m_ProntoFreqConstant;
83 | // Number of burst pairs in sequence #1
84 | int count = scanner.nextInt(16) * 2;
85 | // Extract number of burst pairs in sequence #2 and add to the total
86 | count += scanner.nextInt(16) * 2;
87 | result = new int[count * m_RepeatCount];
88 | // Extract the burst pairs and convert the time to uS
89 | for (int i = 0; i < count; i++) {
90 | result[i] = (int)(period * scanner.nextInt(16) + 0.5);
91 | // fill in the repeat sequences
92 | for (int j = 1; j < m_RepeatCount; j++) {
93 | result[i + (j * count)] = result[i];
94 | }
95 | }
96 | }
97 | catch (NoSuchElementException e) {
98 | return fail;
99 | }
100 | return result;
101 | }
102 |
103 | public String getMessage() {
104 | return m_Message;
105 | }
106 |
107 | public void setMessage(String message) {
108 | m_Message = message;
109 | }
110 |
111 | public int getRepeatCount() {
112 | return m_RepeatCount;
113 | }
114 |
115 | public void setRepeatCount(int repeatCount) {
116 | if ((repeatCount > 0) && (repeatCount < 20)) {
117 | m_RepeatCount = repeatCount;
118 | }
119 | }
120 |
121 | public int getRepeatPoint() {
122 | Scanner scanner = new Scanner(m_Message);
123 | try {
124 | // Extract type, 0000 for sampled signal. This is the only format we support
125 | if (scanner.nextInt(16) != 0) return 0;
126 | // Extract modulation frequency period length, and ignore it
127 | scanner.nextInt(16);
128 | // Number of burst pairs in sequence #1, this is the repeat point
129 | return scanner.nextInt(16) * 2;
130 | }
131 | catch (NoSuchElementException e) {
132 | }
133 | return 0;
134 | }
135 |
136 | public ProtocolInfo getInfo() {
137 | return new ProtocolInfo("Pronto", "None", "Pronto", 0, 5);
138 | }
139 |
140 | public int[] encode(Message message, Phase phase) throws BadMessageException {
141 | int fail[] = new int[0];
142 | int result[];
143 | for (FieldValue field : message.getFields()) {
144 | if (field.getName().equals("Message")) {
145 | setMessage(field.getStringValue());
146 | } else {
147 | throw new BadMessageException(field);
148 | }
149 | }
150 | Scanner scanner = new Scanner(m_Message);
151 | try {
152 | // Extract type, 0000 for sampled signal. This is the only format we support
153 | if (scanner.nextInt(16) != 0) return fail;
154 | // Extract modulation frequency period length
155 | double period = scanner.nextInt(16) * m_ProntoFreqConstant;
156 | // Number of burst pairs in sequence #1
157 | int header = scanner.nextInt(16) * 2;
158 | // Extract number of burst pairs in sequence #2 and add to the total
159 | int body = scanner.nextInt(16) * 2;
160 | int length;
161 | int skip;
162 | if (phase == Phase.FIRST) {
163 | skip = 0;
164 | length = header;
165 | } else {
166 | skip = header;
167 | length = body;
168 | }
169 | result = new int[length];
170 | // Skip header (if needed)
171 | for (int i = 0; i < skip; i++) {
172 | scanner.nextInt(16);
173 | }
174 |
175 | // Extract the burst pairs and convert the time to uS
176 | for (int i = 0; i < length; i++) {
177 | result[i] = (int)(period * scanner.nextInt(16) + 0.5);
178 | }
179 | }
180 | catch (NoSuchElementException e) {
181 | return fail;
182 | }
183 | return result;
184 | }
185 |
186 | public static Message createMessage(String prontoString) {
187 | ProtocolMessage result = new ProtocolMessage("Pronto", 0, 0, 0);
188 | result.addField(new FieldValue("Message", prontoString));
189 | return result;
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/RisingSunEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.coders.decoders.RisingSunDecoder;
23 | import nu.nethome.util.plugin.Plugin;
24 | import nu.nethome.util.ps.*;
25 |
26 | import java.util.ArrayList;
27 |
28 | @Plugin
29 | public class RisingSunEncoder implements ProtocolEncoder{
30 |
31 | public int repeatCount = 5;
32 | private int channel = 1;
33 | private int button = 1;
34 | private int command = 1;
35 | protected int onCommandValue;
36 | protected int offCommandValue;
37 |
38 | // Get the pulse lengths from the decoder
39 | protected int LONG_MARK = RisingSunDecoder.RISING_SUN_LONG_MARK.length();
40 | protected int SHORT_MARK = RisingSunDecoder.RISING_SUN_SHORT_MARK.length();
41 | protected int LONG_SPACE = RisingSunDecoder.RISING_SUN_LONG_SPACE.length();
42 | protected int SHORT_SPACE = RisingSunDecoder.RISING_SUN_SHORT_SPACE.length();
43 | protected int REPEAT = RisingSunDecoder.RISING_SUN_REPEAT.length();
44 | protected static int BUTTON_MAP[] = {0x54, 0x51, 0x45, 0x15};
45 |
46 | public RisingSunEncoder() {
47 | setup();
48 | }
49 |
50 | protected void setup() {
51 | offCommandValue = 0x15 << 17;
52 | onCommandValue = 0x55 << 17;
53 | }
54 |
55 | /**
56 | * s = Start bit = 0
57 | * a = Channel 1 not selected
58 | * b = Channel 2 not selected
59 | * c = Channel 3 not selected
60 | * d = Channel 4 not selected
61 | * e = Button 1 not pressed
62 | * f = Button 2 not pressed
63 | * g = Button 3 not pressed
64 | * h = Button 4 not pressed
65 | * o = On/Off-bit
66 | *
67 | * ____Byte 2_____ ____Byte 1_____ ____Byte 0_____ _S_
68 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0
69 | * x o x x x x x x x h x g x f x e x d x c x b x a s
70 | *
71 | */
72 | public int[] encode() {
73 | ArrayList result = new ArrayList();
74 | long messageTemplate = 0;
75 | long message = 0;
76 |
77 | // encode message
78 | int sendChannel = this.channel - 1;
79 | int sendButton = this.button - 1;
80 | messageTemplate |= BUTTON_MAP[sendChannel] << 1;
81 | messageTemplate |= BUTTON_MAP[sendButton] << 9;
82 |
83 | messageTemplate |= (command == 0) ? offCommandValue : onCommandValue;
84 |
85 | // Start actually encoding the data pulses
86 | for (int i = 0; i < repeatCount; i++) {
87 | message = messageTemplate;
88 |
89 | // 25 bits of data including start bit
90 | for (int j = 0; j < 25; j++) {
91 | if ((message & 1) == 1) {
92 | result.add(LONG_MARK);
93 | result.add(SHORT_SPACE);
94 | }
95 | else {
96 | result.add(SHORT_MARK);
97 | result.add(LONG_SPACE);
98 | }
99 | message >>= 1;
100 | }
101 | int last = result.size() - 1;
102 | // Add the repeat delay as the last space period
103 | result.set(last, REPEAT);
104 | }
105 | int resultArray[] = new int[result.size()];
106 | for (int i = 0; i < result.size(); i++) {
107 | resultArray[i] = result.get(i);
108 | }
109 | return resultArray;
110 | }
111 |
112 | public int getChannel() {
113 | return channel;
114 | }
115 |
116 | public void setChannel(int channel) {
117 | if ((channel < 1) || (channel > 4)) {
118 | return;
119 | }
120 | this.channel = channel;
121 | }
122 |
123 | public int getButton() {
124 | return button;
125 | }
126 |
127 | public void setButton(int deviceCode) {
128 | if ((deviceCode < 1) || (deviceCode > 4)) {
129 | return;
130 | }
131 | button = deviceCode;
132 | }
133 |
134 | public int getCommand() {
135 | return command;
136 | }
137 |
138 | public void setCommand(int command) {
139 | if ((command < 0) || (command > 1)) {
140 | return;
141 | }
142 | this.command = command;
143 | }
144 |
145 | public int getRepeatCount() {
146 | return repeatCount;
147 | }
148 |
149 | public void setRepeatCount(int repeatCount) {
150 | if ((repeatCount < 1) || (repeatCount > 100)) {
151 | return;
152 | }
153 | this.repeatCount = repeatCount;
154 | }
155 |
156 | public ProtocolInfo getInfo() {
157 | return new ProtocolInfo("RisingSun", "Mark Length", "RisingSun", 25, 5);
158 | }
159 |
160 | public int[] encode(Message message, Phase phase) throws BadMessageException {
161 | if (Phase.FIRST == phase) {
162 | return new int[0];
163 | }
164 | for (FieldValue field : message.getFields()) {
165 | if (field.getName().equals("Command")) {
166 | setCommand(field.getValue());
167 | } else if (field.getName().equals("Button")) {
168 | setButton(field.getValue());
169 | } else if (field.getName().equals("Channel")) {
170 | setChannel(field.getValue());
171 | } else {
172 | throw new BadMessageException(field);
173 | }
174 | }
175 | setRepeatCount(1);
176 | return encode();
177 | }
178 |
179 | @Override
180 | public int modulationFrequency(Message message) {
181 | return 0;
182 | }
183 |
184 | /**
185 | * Build a correct protocol message for the Nexa protocol
186 | * @param command 0 or 1 meaning off or on
187 | * @param button which button is pressed 1-16
188 | * @param channel which address (or house code) to send to 0-15
189 | * @return a message with the specified parameters
190 | */
191 | public static Message buildMessage(int command, int button, int channel) {
192 | ProtocolMessage result = new ProtocolMessage("RisingSun", command, channel, 0);
193 | result.addField(new FieldValue("Command", command));
194 | result.addField(new FieldValue("Button", button));
195 | result.addField(new FieldValue("Channel", channel));
196 | return result;
197 | };
198 |
199 | }
200 |
201 |
202 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/RollerTrolEncoder.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.encoders;
2 |
3 | import nu.nethome.coders.RollerTrol;
4 | import nu.nethome.util.ps.*;
5 |
6 | import static nu.nethome.coders.RollerTrol.*;
7 |
8 | /**
9 | *
10 | */
11 | public class RollerTrolEncoder implements ProtocolEncoder {
12 |
13 | public static final int PREAMBLE_LENGTH = 4;
14 | public static final int CONSTANT_FIELD_VALUE = 1;
15 |
16 | @Override
17 | public ProtocolInfo getInfo() {
18 | return ROLLERTROL_PROTOCOL_INFO;
19 | }
20 |
21 | @Override
22 | public int[] encode(Message message, Phase phase) throws BadMessageException {
23 | int houseCode = 0;
24 | int deviceCode = 0;
25 | int command = 0;
26 | for (FieldValue f : message.getFields()) {
27 | if (f.getName().equals(HOUSE_CODE_NAME)) {
28 | houseCode = f.getValue();
29 | }
30 | if (f.getName().equals(DEVICE_CODE_NAME)) {
31 | deviceCode = f.getValue();
32 | }
33 | if (f.getName().equals(COMMAND_NAME)) {
34 | command = f.getValue();
35 | }
36 | }
37 | return encode(houseCode, deviceCode, command);
38 | }
39 |
40 | private int[] encode(int houseCode, int deviceCode, int command) {
41 | int[] result = new int[PREAMBLE_LENGTH + MESSAGE_BIT_LENGTH * 2];
42 | result[0] = RollerTrol.LONG_PREAMBLE_MARK.length();
43 | result[1] = RollerTrol.LONG_PREAMBLE_SPACE.length();
44 | result[2] = RollerTrol.SHORT_PREAMBLE_MARK.length();
45 | result[3] = RollerTrol.SHORT.length();
46 | BitString message = new BitString(MESSAGE_BIT_LENGTH);
47 | message.insert(RollerTrol.COMMAND, command);
48 | message.insert(RollerTrol.HOUSE_CODE, houseCode);
49 | message.insert(RollerTrol.DEVICE_CODE, deviceCode);
50 | message.insert(CONSTANT_FIELD, CONSTANT_FIELD_VALUE);
51 | message.insert(CHECK_SUM, RollerTrol.calculateChecksum(message));
52 | int resultPosition = PREAMBLE_LENGTH;
53 | for (int i = 0; i < MESSAGE_BIT_LENGTH; i++) {
54 | if (message.getBit(i)) {
55 | result[resultPosition++] = LONG.length();
56 | result[resultPosition++] = SHORT.length();
57 | } else {
58 | result[resultPosition++] = SHORT.length();
59 | result[resultPosition++] = LONG.length();
60 | }
61 | }
62 | return result;
63 | }
64 |
65 | @Override
66 | public int modulationFrequency(Message message) {
67 | return 0;
68 | }
69 |
70 | public static Message buildMessage(int command, int houseCode, int deviceCode) {
71 | ProtocolMessage result = new ProtocolMessage(ROLLER_TROL_PROTOCOL_NAME, command, deviceCode, 0);
72 | result.addField(new FieldValue(COMMAND_NAME, command));
73 | result.addField(new FieldValue(HOUSE_CODE_NAME, houseCode));
74 | result.addField(new FieldValue(DEVICE_CODE_NAME, deviceCode));
75 | return result;
76 | }
77 |
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/RollerTrolGEncoder.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.encoders;
2 |
3 | import nu.nethome.coders.RollerTrolG;
4 | import nu.nethome.util.ps.*;
5 |
6 | import static nu.nethome.coders.RollerTrolG.*;
7 |
8 | /**
9 | *
10 | */
11 | public class RollerTrolGEncoder implements ProtocolEncoder {
12 |
13 | public static final int PREAMBLE_LENGTH = 2;
14 | public static final int CONSTANT_FIELD_VALUE = 1;
15 |
16 | @Override
17 | public ProtocolInfo getInfo() {
18 | return ROLLERTROL_PROTOCOL_INFO;
19 | }
20 |
21 | @Override
22 | public int[] encode(Message message, Phase phase) throws BadMessageException {
23 | int address = 0;
24 | int channel = 0;
25 | int command = 0;
26 | for (FieldValue f : message.getFields()) {
27 | if (RollerTrolG.ADDRESS_NAME.equals(f.getName())) {
28 | address = f.getValue();
29 | }
30 | if (RollerTrolG.CHANNEL_NAME.equals(f.getName())) {
31 | channel = f.getValue();
32 | }
33 | if (RollerTrolG.COMMAND_NAME.equals(f.getName())) {
34 | command = f.getValue();
35 | }
36 | }
37 | return encode(address, channel, command);
38 | }
39 |
40 | private int[] encode(int address, int channel, int command) {
41 | int[] result = new int[PREAMBLE_LENGTH + RollerTrolG.PROTOCOL_BIT_LENGTH * 2 + 1];
42 | result[0] = RollerTrolG.LONG_PREAMBLE_MARK.length();
43 | result[1] = RollerTrolG.LONG_PREAMBLE_SPACE.length();
44 | BitString message = new BitString(RollerTrolG.PROTOCOL_BIT_LENGTH);
45 | message.insert(RollerTrolG.COMMAND, command);
46 | message.insert(RollerTrolG.ADDRESS, address);
47 | message.insert(RollerTrolG.CHANNEL, channel);
48 | int resultPosition = PREAMBLE_LENGTH;
49 | for (int i = 0; i < RollerTrolG.PROTOCOL_BIT_LENGTH; i++) {
50 | if (message.getBit(PROTOCOL_BIT_LENGTH - i - 1)) {
51 | result[resultPosition++] = LONG.length();
52 | result[resultPosition++] = SHORT.length();
53 | } else {
54 | result[resultPosition++] = SHORT.length();
55 | result[resultPosition++] = LONG.length();
56 | }
57 | }
58 | result[resultPosition] = RollerTrolG.REPEAT_SPACE.length();
59 | return result;
60 | }
61 |
62 | @Override
63 | public int modulationFrequency(Message message) {
64 | return 0;
65 | }
66 |
67 | public static Message buildMessage(int command, int address, int channel) {
68 | ProtocolMessage result = new ProtocolMessage(RollerTrolG.ROLLER_TROL_G_PROTOCOL_NAME, command, channel, 0);
69 | result.addField(new FieldValue(COMMAND_NAME, command));
70 | result.addField(new FieldValue(ADDRESS_NAME, address));
71 | result.addField(new FieldValue(CHANNEL_NAME, channel));
72 | return result;
73 | }
74 |
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/ShortBeepEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import java.util.ArrayList;
23 |
24 | /**
25 | * Encodes a signal that when played with an AudioPulseTransmitter will be heard
26 | * as a short beep if speakers are attached to the audio output used. This is
27 | * used for testing setup and configuration and should NOT be used when an
28 | * RF-Transmitting device is attached to the output.
29 | *
30 | * @author Stefan
31 | */
32 | public class ShortBeepEncoder {
33 |
34 | private static final float MICROSECS_PER_SEC = 1000000;
35 | private int m_Frequency = 2000;
36 | private float m_Duration = 0.8F;
37 | private ArrayList result = new ArrayList();
38 |
39 | /**
40 | * Encode a pulse set which will be heard as a short beep if played by
41 | * an AudioProtocolTransmitter.
42 | * @return
43 | */
44 | public int[] encode() {
45 | int noFlanks = (int)(m_Duration * MICROSECS_PER_SEC * 2F) / m_Frequency;
46 | int flank = ((int)MICROSECS_PER_SEC / m_Frequency) / 2;
47 | for (int i = 0; i < noFlanks; i++) {
48 | result.add(flank);
49 | }
50 | int resultArray[] = new int[result.size()];
51 | for (int i = 0; i < result.size(); i++) {
52 | resultArray[i] = result.get(i);
53 | }
54 | return resultArray;
55 | }
56 |
57 | public int getFrequency() {
58 | return m_Frequency;
59 | }
60 |
61 | /**
62 | * @param frequency Frequency of the beep,1 - 18000 Hz
63 | */
64 | public void setFrequency(int frequency) {
65 | if ((frequency < 0) || (frequency > 18000)) {
66 | throw new IllegalArgumentException("Bad frequence value");
67 | }
68 | m_Frequency = frequency;
69 | }
70 |
71 | public float getDuration() {
72 | return m_Duration;
73 | }
74 |
75 | /**
76 | * @param duration Duration of the Beep, 0 - 1 Second
77 | */
78 | public void setDuration(float duration) {
79 | if ((duration < 0) || (duration > 1)) {
80 | throw new IllegalArgumentException("Bad duration value");
81 | }
82 | m_Duration = duration;
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/WavemanEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.util.plugin.Plugin;
23 | import nu.nethome.util.ps.ProtocolInfo;
24 |
25 | /**
26 | * The Waveman Encoder is an encoder for the RF-protocol used by Waveman products
27 | * such as remote switches, dimmers, PIR-detectors and so on. The WavemanEncoder
28 | * can take the data from a protocol message and encode that into a sequence
29 | * of pulse lengths which may be played by RF-transmitting hardware for instance
30 | * via the AudioPulsePlayer.
31 | *
32 | * @author Stefan
33 | */
34 | @Plugin
35 | public class WavemanEncoder extends NexaEncoder {
36 |
37 | public WavemanEncoder() {
38 | super();
39 | }
40 |
41 | /**
42 | * The protocol for Waveman is the same as for Nexa, except for the off
43 | * command encoding, where all three bits in the command byte are set to 0.
44 | *
45 | * s = Start bit = 0
46 | * b = Button number
47 | * a = Address
48 | * o = On/Off-bit
49 | *
50 | * ____Byte 2_____ ____Byte 1_____ ____Byte 0_____ _S_
51 | * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 0
52 | * x o x o x o x x x b x b x b x b x a x a x a x a s
53 | *
54 | */
55 | protected void setup() {
56 | offCommandValue = 0x00;
57 | onCommandValue = 0x54 << 17;
58 | }
59 |
60 | public ProtocolInfo getInfo() {
61 | return new ProtocolInfo("Waveman", "Space Length", "Waveman", 32, 5);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/nu/nethome/coders/encoders/ZhejiangEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.encoders;
21 |
22 | import nu.nethome.coders.decoders.ZhejiangDecoder;
23 | import nu.nethome.util.plugin.Plugin;
24 | import nu.nethome.util.ps.*;
25 |
26 | import java.util.ArrayList;
27 |
28 | @Plugin
29 | public class ZhejiangEncoder implements ProtocolEncoder {
30 |
31 | public static final int ZHEJIANG_RAW_MESSAGE_LENGTH = 25;
32 |
33 | public ProtocolInfo getInfo() {
34 | return new ProtocolInfo("Zhejiang", "Mark Length", "Zhejiang", 25, 5);
35 | }
36 |
37 | public int[] encode(Message message, Phase phase) throws BadMessageException {
38 | if (Phase.FIRST == phase) {
39 | return new int[0];
40 | }
41 | int command = 0;
42 | int address = 0;
43 | int button = 0;
44 | for (FieldValue field : message.getFields()) {
45 | if (field.getName().equals("Command")) {
46 | command = field.getValue();
47 | } else if (field.getName().equals("Address")) {
48 | address = field.getValue();
49 | } else if (field.getName().equals("Button")) {
50 | button = field.getValue();
51 | } else {
52 | throw new BadMessageException(field);
53 | }
54 | }
55 | if (command < 0 || command > 1 || address < 0 || address > 31 || button < 0 || button > 4) {
56 | throw new BadMessageException(null);
57 | }
58 | return encode(command, button, address);
59 | }
60 |
61 | @Override
62 | public int modulationFrequency(Message message) {
63 | return 0;
64 | }
65 |
66 | public static Message buildMessage(int command, int button, int address) {
67 | ProtocolMessage result = new ProtocolMessage("Zhejiang", command, address, 0);
68 | result.addField(new FieldValue("Command", command));
69 | result.addField(new FieldValue("Address", address));
70 | result.addField(new FieldValue("Button", button));
71 | return result;
72 | }
73 |
74 | private int[] encode(int command, int button, int address) {
75 | ArrayList result = new ArrayList();
76 | long message = 0x2003FF;
77 | message = copyBit(command, 0, message, 21, false);
78 | message = copyBit(command, 0, message, 23, true);
79 | int buttonBit = 1 << button;
80 | message = copyBit(buttonBit, 0, message, 11, true);
81 | message = copyBit(buttonBit, 1, message, 13, true);
82 | message = copyBit(buttonBit, 2, message, 15, true);
83 | message = copyBit(buttonBit, 3, message, 17, true);
84 | message = copyBit(buttonBit, 4, message, 19, true);
85 |
86 | message = copyBit(address, 0, message, 0, true);
87 | message = copyBit(address, 1, message, 2, true);
88 | message = copyBit(address, 2, message, 4, true);
89 | message = copyBit(address, 3, message, 6, true);
90 | message = copyBit(address, 4, message, 8, true);
91 |
92 | // Encode message bits
93 | for (int j = 0; j < (ZHEJIANG_RAW_MESSAGE_LENGTH); j++) {
94 | if ((message & 1) == 1) {
95 | result.add(ZhejiangDecoder.ZHEJ_LONG_MARK.length());
96 | result.add(ZhejiangDecoder.ZHEJ_SHORT_SPACE.length());
97 | } else {
98 | result.add(ZhejiangDecoder.ZHEJ_SHORT_MARK.length());
99 | result.add(ZhejiangDecoder.ZHEJ_LONG_SPACE.length());
100 | }
101 | message >>= 1;
102 | }
103 | result.remove(result.size() - 1);
104 | result.add(ZhejiangDecoder.ZHEJ_REPEAT.length());
105 |
106 | int resultArray[] = new int[result.size()];
107 | for (int i = 0; i < result.size(); i++) {
108 | resultArray[i] = result.get(i);
109 | }
110 | return resultArray;
111 | }
112 |
113 | private long copyBit(int source, int sourceBit, long destination, int destinationBit, boolean invert) {
114 | if ((((source >> sourceBit) & 1) == 1) ^ invert) {
115 | return destination | (1L << destinationBit);
116 | }
117 | return destination & ~(1L << destinationBit);
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/EmotivaDecoderTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.encoders.EmotivaEncoder;
23 | import nu.nethome.util.ps.BadMessageException;
24 | import nu.nethome.util.ps.FieldValue;
25 | import nu.nethome.util.ps.Message;
26 | import nu.nethome.util.ps.ProtocolEncoder;
27 | import nu.nethome.util.ps.impl.PulseTestPlayer;
28 | import org.junit.Before;
29 | import org.junit.Test;
30 |
31 | import static org.hamcrest.Matchers.hasItem;
32 | import static org.hamcrest.Matchers.is;
33 | import static org.junit.Assert.assertEquals;
34 | import static org.junit.Assert.assertThat;
35 |
36 | /**
37 | * User: Stefan
38 | * Date: 2013-01-27
39 | * Time: 21:53
40 | */
41 | public class EmotivaDecoderTest {
42 |
43 | private EmotivaEncoder encoder;
44 | private EmotivaDecoder decoder;
45 | private PulseTestPlayer player;
46 |
47 | @Before
48 | public void setUp() throws Exception {
49 | encoder = new EmotivaEncoder();
50 | player = new PulseTestPlayer();
51 | decoder = new EmotivaDecoder();
52 | decoder.setTarget(player);
53 | player.setDecoder(decoder);
54 | player.setPulseWidthModification(0);
55 | }
56 |
57 | @Test
58 | public void canCreateCommand() {
59 | Message message = EmotivaEncoder.buildMessage(1, 0x5533);
60 | assertThat(message.getFields().size(), is(2));
61 | assertThat(message.getFields(), hasItem(new FieldValue("Command", 1)));
62 | assertThat(message.getFields(), hasItem(new FieldValue("Address", 0x5533)));
63 | }
64 |
65 | @Test
66 | public void canDecodeEncodedMessage() throws BadMessageException {
67 | player.playMessage(encoder.encode(EmotivaEncoder.buildMessage(17, 6543), ProtocolEncoder.Phase.REPEATED));
68 | assertEquals(1, player.getMessageCount());
69 | assertEquals(17, player.getMessageField(0, "Command"));
70 | assertEquals(6543, player.getMessageField(0, "Address"));
71 | assertEquals(0, player.getMessages()[0].getRepeat());
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/FineOffsetDecoderTest.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import nu.nethome.coders.decoders.util.JirFileTestPlayer;
4 | import org.junit.Before;
5 | import org.junit.Test;
6 |
7 | import static org.hamcrest.MatcherAssert.assertThat;
8 | import static org.hamcrest.Matchers.is;
9 |
10 |
11 | public class FineOffsetDecoderTest {
12 | @Before
13 | public void setUp() throws Exception {
14 |
15 | }
16 |
17 | @Test
18 | public void basicJir() {
19 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.FINE_OFFSET_DECODER);
20 |
21 | // Using a known test vector
22 | player.playFile(this.getClass().getClassLoader()
23 | .getResourceAsStream("nu/nethome/coders/decoders/fine_offset.jir"));
24 |
25 | assertThat(player.getMessageField(0, "Identity"), is(0x4B1));
26 | assertThat(player.getMessageField(0, "Temp"), is(225));
27 | }
28 |
29 | @Test
30 | public void negativeJir() {
31 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.FINE_OFFSET_DECODER);
32 |
33 | // Using a known test vector
34 | player.playFile(this.getClass().getClassLoader()
35 | .getResourceAsStream("nu/nethome/coders/decoders/fine_offset_neg.jir"));
36 |
37 | assertThat(player.getMessageField(0, "Identity"), is(0x46D));
38 | assertThat(player.getMessageField(0, "Temp"), is(-14));
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/OregonDecoderTest.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import nu.nethome.coders.decoders.util.JirFileTestPlayer;
4 | import nu.nethome.util.ps.FieldValue;
5 | import nu.nethome.util.ps.ProtocolDecoderSink;
6 | import nu.nethome.util.ps.ProtocolMessage;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 | import org.mockito.ArgumentCaptor;
10 |
11 | import java.util.List;
12 |
13 | import static org.hamcrest.MatcherAssert.assertThat;
14 | import static org.hamcrest.Matchers.is;
15 | import static org.junit.Assert.assertEquals;
16 | import static org.mockito.Mockito.mock;
17 | import static org.mockito.Mockito.times;
18 | import static org.mockito.Mockito.verify;
19 |
20 | /**
21 | *
22 | */
23 | public class OregonDecoderTest {
24 |
25 | OregonDecoder decoder;
26 | ProtocolDecoderSink sink;
27 | ArgumentCaptor messageCaptor;
28 |
29 | @Before
30 | public void setUp() throws Exception {
31 | decoder = new OregonDecoder();
32 | sink = mock(ProtocolDecoderSink.class);
33 | messageCaptor = ArgumentCaptor.forClass(ProtocolMessage.class);
34 | decoder.setTarget(sink);
35 | }
36 |
37 | @Test
38 | public void tempHumiditySensor1D20WithKnownTestVector() throws Exception {
39 | receiveMessage("A1D2016B1091073A14");
40 | verifyTemperature(0x1D20, 190);
41 | assertThat(getMessageField("Moisture"), is(37));
42 | }
43 |
44 | @Test
45 | public void tempHumiditySensor1D20WithKnownTestVectorDirectly() throws Exception {
46 | final byte message[] = {0xA, 0x1, 0xD, 0x2, 0x0, 0x1, 0x6, 0xB, 0x1, 0x0, 0x9, 0x1, 0x0, 0x7, 0x3, 0xA, 0x1, 0x4};
47 | decoder.decodeMessage(message);
48 | verifyTemperature(0x1D20, 190);
49 | assertThat(getMessageField("Moisture"), is(37));
50 | }
51 |
52 | @Test
53 | public void tempHumiditySensor1D20WithLowBattery() throws Exception {
54 | receiveMessage("A1D2016B5091073A54");
55 | verify(sink, times(1)).parsedMessage(messageCaptor.capture());
56 | assertThat(getMessageField("LowBattery"), is(1));
57 | }
58 |
59 | @Test
60 | public void tempHumiditySensorF824WithKnownTestVector() throws Exception {
61 | receiveMessage("AF82416B1091073AE4");
62 | verifyTemperature(0xF824, 190);
63 | assertThat(getMessageField("Moisture"), is(37));
64 | }
65 |
66 | @Test
67 | public void tempHumiditySensorF8B4WithKnownTestVector() throws Exception {
68 | receiveMessage("AF8B416B1091073A75");
69 | verifyTemperature(0xF8B4, 190);
70 | assertThat(getMessageField("Moisture"), is(37));
71 | }
72 |
73 | @Test
74 | public void tempSensorEC40WithKnownTestVector() throws Exception {
75 | receiveMessage("AEC4016B1091834");
76 | verifyTemperature(0xEC40, -190);
77 | }
78 |
79 | @Test
80 | public void tempSensorC844WithKnownTestVector() throws Exception {
81 | receiveMessage("AC84416B1091814");
82 | verifyTemperature(0xC844, -190);
83 | }
84 |
85 | @Test
86 | public void windSensor1984WithKnownTestVector() throws Exception {
87 | receiveMessage("A198416B1800063892D4");
88 | verifyWind(0x1984);
89 | }
90 |
91 | @Test
92 | public void windSensor1994WithKnownTestVector() throws Exception {
93 | receiveMessage("A199416B1800063892E4");
94 | verifyWind(0x1994);
95 | }
96 |
97 | @Test
98 | public void rainSensor2D10WithKnownTestVector() throws Exception {
99 | receiveMessage("A2D1016B15211235063");
100 | verifyRain(0x2D10);
101 | }
102 |
103 | @Test
104 | public void tempHumidityPressureSensor5D60WithKnownTestVector() throws Exception {
105 | receiveMessage("A5D6016B109107300FF1E5");
106 | verifyTemperature(0x5D60, 190);
107 | assertThat(getMessageField("Moisture"), is(37));
108 | assertThat(getMessageField("Pressure"), is(511));
109 | }
110 |
111 | private void verifyTemperature(int sensorId, int temperature) {
112 | verify(sink, times(1)).parsedMessage(messageCaptor.capture());
113 | assertThat(getMessageField("SensorId"), is(sensorId));
114 | assertThat(getMessageField("Channel"), is(1));
115 | assertThat(getMessageField("Id"), is(0x6B));
116 | assertThat(getMessageField("Temp"), is(temperature));
117 | assertThat(getMessageField("LowBattery"), is(0));
118 | }
119 |
120 | private void verifyWind(int sensorId) {
121 | verify(sink, times(1)).parsedMessage(messageCaptor.capture());
122 | assertThat(getMessageField("SensorId"), is(sensorId));
123 | assertThat(getMessageField("Channel"), is(1));
124 | assertThat(getMessageField("Id"), is(0x6B));
125 | assertThat(getMessageField("LowBattery"), is(0));
126 | assertThat(getMessageField("Direction"), is(8));
127 | assertThat(getMessageField("Wind"), is(360));
128 | assertThat(getMessageField("AverageWind"), is(298));
129 | }
130 |
131 | private void verifyRain(int sensorId) {
132 | verify(sink, times(1)).parsedMessage(messageCaptor.capture());
133 | assertThat(getMessageField("SensorId"), is(sensorId));
134 | assertThat(getMessageField("Channel"), is(1));
135 | assertThat(getMessageField("Id"), is(0x6B));
136 | assertThat(getMessageField("LowBattery"), is(0));
137 | assertThat(getMessageField("RainRate"), is(125));
138 | assertThat(getMessageField("TotalRain"), is(5321));
139 | }
140 |
141 | private void receiveMessage(String s) {
142 | for(char c : s.toCharArray()) {
143 | decoder.addNibble(Byte.parseByte("" + c, 16));
144 | }
145 | }
146 |
147 | public int getMessageField(String fieldName) {
148 | List fields = messageCaptor.getValue().getFields();
149 | for (FieldValue field : fields) {
150 | if (fieldName.equals(field.getName())) {
151 | return field.getValue();
152 | }
153 | }
154 | return -1;
155 | }
156 |
157 | @Test
158 | public void basicJir() {
159 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.OREGON_DECODER);
160 |
161 | // Using a known test vector
162 | player.playFile(this.getClass().getClassLoader()
163 | .getResourceAsStream("nu/nethome/coders/decoders/oregon1.jir"));
164 |
165 | assertThat(player.getMessageField(0, "SensorId"), is(0x1D20));
166 | assertThat(player.getMessageField(0, "Channel"), is(1));
167 | assertThat(player.getMessageField(0, "Id"), is(0xEB));
168 | assertThat(player.getMessageField(0, "Temp"), is(263));
169 | assertThat(player.getMessageField(0, "Moisture"), is(20));
170 | assertThat(player.getMessageField(0, "LowBattery"), is(0));
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/PrologueDecoderTest.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import nu.nethome.coders.decoders.util.JirFileTestPlayer;
4 | import org.junit.Before;
5 | import org.junit.Test;
6 |
7 | import static org.hamcrest.MatcherAssert.assertThat;
8 | import static org.hamcrest.Matchers.is;
9 | import static org.junit.Assert.*;
10 |
11 | public class PrologueDecoderTest {
12 |
13 | @Before
14 | public void setUp() throws Exception {
15 | }
16 |
17 | @Test
18 | public void basicJir() {
19 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.PROLOGUE_DECODER);
20 |
21 | // Using a known test vector
22 | player.playFile(this.getClass().getClassLoader()
23 | .getResourceAsStream("nu/nethome/coders/decoders/prologue.jir"));
24 |
25 | assertThat(player.m_Messages.size(), is(5));
26 | assertThat(player.m_Messages.get(4).getRepeat(), is(4));
27 | assertThat(player.getMessageField(0, "Temp"), is(261));
28 | assertThat(player.getMessageField(0, "Button"), is(1));
29 | assertThat(player.getMessageField(0, "Battery"), is(0));
30 | assertThat(player.getMessageField(0, "RollingId"), is(80));
31 | assertThat(player.getMessageField(0, "Channel"), is(0));
32 | assertThat(player.getMessageField(0, "Humidity"), is(204));
33 | assertThat(player.getMessageField(0, "Id"), is(9));
34 | }
35 | }
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/RollerTrolDecoderTest.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import nu.nethome.coders.RollerTrol;
4 | import nu.nethome.coders.decoders.util.JirFileTestPlayer;
5 | import org.junit.Test;
6 |
7 | import static nu.nethome.coders.RollerTrol.*;
8 | import static org.hamcrest.MatcherAssert.assertThat;
9 | import static org.hamcrest.Matchers.is;
10 |
11 | public class RollerTrolDecoderTest {
12 | public void setUp() throws Exception {
13 |
14 | }
15 |
16 | @Test
17 | public void basicJir() {
18 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.ROLLERTROL_DECODER);
19 |
20 | // Using a known test vector
21 | player.playFile(this.getClass().getClassLoader()
22 | .getResourceAsStream("nu/nethome/coders/decoders/rollertrol_3_stop.jir"));
23 |
24 | assertThat(player.getMessageField(0, DEVICE_CODE_NAME), is(3));
25 | assertThat(player.getMessageField(0, COMMAND_NAME), is(STOP));
26 | assertThat(player.getMessageField(0, HOUSE_CODE_NAME), is(36600));
27 | assertThat(player.m_Messages.size(), is(15));
28 | assertThat(player.m_Messages.get(14).getRepeat(), is(14));
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/RollerTrolGDecoderTest.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.decoders;
2 |
3 | import nu.nethome.coders.RollerTrolG;
4 | import nu.nethome.coders.encoders.RisingSunEncoder;
5 | import nu.nethome.coders.encoders.RollerTrolGEncoder;
6 | import nu.nethome.util.ps.BadMessageException;
7 | import nu.nethome.util.ps.Message;
8 | import nu.nethome.util.ps.MessageRepeater;
9 | import nu.nethome.util.ps.impl.PulseTestPlayer;
10 | import org.junit.Before;
11 | import org.junit.Test;
12 |
13 | import static org.hamcrest.MatcherAssert.assertThat;
14 | import static org.hamcrest.Matchers.is;
15 | import static org.junit.Assert.assertEquals;
16 |
17 |
18 | public class RollerTrolGDecoderTest {
19 |
20 | public static final int CHANNEL = 3;
21 | public static final int ADDRESS = 123456;
22 | private RollerTrolGEncoder encoder;
23 | private PulseTestPlayer player;
24 | private RollerTrolGDecoder decoder;
25 |
26 | @Before
27 | public void setUp() throws Exception {
28 | encoder = new RollerTrolGEncoder();
29 | player = new PulseTestPlayer();
30 | decoder = new RollerTrolGDecoder();
31 | decoder.setTarget(player);
32 | player.setDecoder(decoder);
33 | player.setPulseWidthModification(0);
34 |
35 | }
36 |
37 | @Test
38 | public void testNewEncoderInterface() throws BadMessageException {
39 | Message toSend = RollerTrolGEncoder.buildMessage(RollerTrolG.COMMAND_STOP, ADDRESS, CHANNEL);
40 | player.playMessage(MessageRepeater.repeat(encoder, toSend, 1));
41 | assertThat(player.getMessageCount(), is(1));
42 | assertThat(player.getMessageField(0, RollerTrolG.COMMAND_NAME), is(RollerTrolG.COMMAND_STOP));
43 | assertThat(player.getMessageField(0, RollerTrolG.ADDRESS_NAME), is(ADDRESS));
44 | assertThat(player.getMessageField(0, RollerTrolG.CHANNEL_NAME), is(CHANNEL));
45 | assertThat(player.getMessages()[0].getRepeat(), is(0));
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/TestDeltronicDecoderEncoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.encoders.DeltronicEncoder;
23 | import nu.nethome.util.ps.BadMessageException;
24 | import nu.nethome.util.ps.Message;
25 | import nu.nethome.util.ps.MessageRepeater;
26 | import nu.nethome.util.ps.ProtocolInfo;
27 | import nu.nethome.util.ps.impl.PulseTestPlayer;
28 | import org.junit.After;
29 | import org.junit.Before;
30 | import org.junit.Test;
31 |
32 | import static org.hamcrest.CoreMatchers.is;
33 | import static org.junit.Assert.assertEquals;
34 | import static org.junit.Assert.assertThat;
35 |
36 | /**
37 | * Unit tests for DeltronicEncoder and DeltronicDecoder.
38 | * @author �garen
39 | *
40 | */
41 | public class TestDeltronicDecoderEncoder {
42 |
43 | private DeltronicEncoder m_Encoder;
44 | private DeltronicDecoder m_Decoder;
45 | private PulseTestPlayer m_Player;
46 |
47 | @Before
48 | public void setUp() throws Exception {
49 | m_Encoder = new DeltronicEncoder();
50 | m_Player = new PulseTestPlayer();
51 | m_Decoder = new DeltronicDecoder();
52 | m_Decoder.setTarget(m_Player);
53 | m_Player.setDecoder(m_Decoder);
54 | m_Player.setPulseWidthModification(0);
55 | }
56 |
57 | @After
58 | public void tearDown() throws Exception {
59 | }
60 |
61 | @Test
62 | public void testSetAddress() {
63 | assertEquals(0, m_Encoder.getAddress());
64 | m_Encoder.setAddress(0x3F);
65 | assertEquals(0x3F, m_Encoder.getAddress());
66 | m_Encoder.setAddress(0x40);
67 | assertEquals(0x3F, m_Encoder.getAddress());
68 | }
69 |
70 | @Test
71 | public void testSetButton() {
72 | assertEquals(0, m_Encoder.getButton());
73 | m_Encoder.setButton(2);
74 | assertEquals(2, m_Encoder.getButton());
75 | m_Encoder.setButton(-1);
76 | assertEquals(2, m_Encoder.getButton());
77 | m_Encoder.setButton(4);
78 | assertEquals(2, m_Encoder.getButton());
79 | }
80 |
81 | @Test
82 | public void testSetCommand() {
83 | assertEquals(1, m_Encoder.getCommand());
84 | m_Encoder.setCommand(0);
85 | assertEquals(0, m_Encoder.getCommand());
86 | m_Encoder.setCommand(2);
87 | assertEquals(0, m_Encoder.getCommand());
88 | }
89 |
90 | @Test
91 | public void testSetRepeatCount() {
92 | assertEquals(3, m_Encoder.getRepeatCount());
93 | m_Encoder.setRepeatCount(5);
94 | assertEquals(5, m_Encoder.getRepeatCount());
95 | m_Encoder.setRepeatCount(0);
96 | assertEquals(5, m_Encoder.getRepeatCount());
97 | }
98 |
99 | @Test
100 | public void testSingleMessage() {
101 | m_Encoder.setRepeatCount(1);
102 | m_Encoder.setAddress(1);
103 | m_Encoder.setButton(2);
104 | m_Encoder.setCommand(1);
105 | m_Player.playMessage(m_Encoder.encode());
106 | assertEquals(1, m_Player.getMessageCount());
107 | assertEquals(1, m_Player.getMessageField(0, "Address"));
108 | assertEquals(2, m_Player.getMessageField(0, "Button"));
109 | assertEquals(1, m_Player.getMessageField(0, "Command"));
110 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
111 | }
112 |
113 | @Test
114 | public void testSingleMessageNewInterface() throws BadMessageException {
115 | Message toSend = DeltronicEncoder.buildCommandMessage(true, 2, 1);
116 | m_Player.playMessage(MessageRepeater.repeat(m_Encoder, toSend, 1));
117 | assertEquals(1, m_Player.getMessageCount());
118 | assertEquals(1, m_Player.getMessageField(0, "Address"));
119 | assertEquals(2, m_Player.getMessageField(0, "Button"));
120 | assertEquals(1, m_Player.getMessageField(0, "Command"));
121 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
122 | }
123 |
124 | @Test
125 | public void testTwoMessages() {
126 | m_Encoder.setRepeatCount(2);
127 | m_Encoder.setAddress(0x1A);
128 | m_Encoder.setButton(3);
129 | m_Encoder.setCommand(0);
130 | m_Player.playMessage(m_Encoder.encode());
131 | assertEquals(2, m_Player.getMessageCount());
132 | assertEquals(0x1A, m_Player.getMessageField(0, "Address"));
133 | assertEquals(3, m_Player.getMessageField(0, "Button"));
134 | assertEquals(0, m_Player.getMessageField(0, "Command"));
135 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
136 | assertEquals(0x1A, m_Player.getMessageField(1, "Address"));
137 | assertEquals(3, m_Player.getMessageField(1, "Button"));
138 | assertEquals(0, m_Player.getMessageField(1, "Command"));
139 | assertEquals(1, m_Player.getMessages()[1].getRepeat());
140 | }
141 |
142 | @Test
143 | public void testTwoMessagesNewInterface() throws BadMessageException {
144 | Message toSend = DeltronicEncoder.buildCommandMessage(false, 3, 0x1a);
145 | m_Player.playMessage(MessageRepeater.repeat(m_Encoder, toSend, 2));
146 | assertEquals(2, m_Player.getMessageCount());
147 | assertEquals(0x1A, m_Player.getMessageField(0, "Address"));
148 | assertEquals(3, m_Player.getMessageField(0, "Button"));
149 | assertEquals(0, m_Player.getMessageField(0, "Command"));
150 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
151 | assertEquals(0x1A, m_Player.getMessageField(1, "Address"));
152 | assertEquals(3, m_Player.getMessageField(1, "Button"));
153 | assertEquals(0, m_Player.getMessageField(1, "Command"));
154 | assertEquals(1, m_Player.getMessages()[1].getRepeat());
155 | }
156 |
157 | @Test
158 | public void info() {
159 | ProtocolInfo info = m_Encoder.getInfo();
160 | assertThat(info.getName(), is("Deltronic"));
161 | }
162 | }
163 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/TestNexaFire.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.decoders.util.JirFileTestPlayer;
23 | import nu.nethome.coders.encoders.NexaFireEncoder;
24 | import nu.nethome.util.ps.impl.PulseTestPlayer;
25 | import org.junit.After;
26 | import org.junit.Before;
27 | import org.junit.Test;
28 |
29 | import static org.junit.Assert.assertEquals;
30 |
31 | /**
32 | * Unit tests for NexaFireEncoder and NexaFireDecoder
33 | * @author Stefan
34 | *
35 | */
36 | public class TestNexaFire {
37 |
38 | private NexaFireEncoder m_Encoder;
39 | private NexaFireDecoder m_Decoder;
40 | private PulseTestPlayer m_Player;
41 |
42 | @Before
43 | public void setUp() throws Exception {
44 | m_Encoder = new NexaFireEncoder();
45 | m_Player = new PulseTestPlayer();
46 | m_Decoder = new NexaFireDecoder();
47 | m_Decoder.setTarget(m_Player);
48 | m_Player.setDecoder(m_Decoder);
49 | }
50 |
51 | @After
52 | public void tearDown() throws Exception {
53 | }
54 |
55 | @Test
56 | public void testSetAddress() {
57 | assertEquals(0, m_Encoder.getAddress());
58 | m_Encoder.setAddress(255);
59 | assertEquals(255, m_Encoder.getAddress());
60 | m_Encoder.setAddress(0x0FFFFFFF);
61 | assertEquals(255, m_Encoder.getAddress());
62 | }
63 |
64 | @Test
65 | public void testSetRepeatCount() {
66 | assertEquals(15, m_Encoder.getRepeatCount());
67 | m_Encoder.setRepeatCount(4);
68 | assertEquals(4, m_Encoder.getRepeatCount());
69 | m_Encoder.setRepeatCount(0);
70 | assertEquals(4, m_Encoder.getRepeatCount());
71 | }
72 |
73 | @Test
74 | public void testSingleMessage() {
75 | m_Encoder.setRepeatCount(1);
76 | m_Encoder.setAddress(1);
77 | m_Player.playMessage(m_Encoder.encode());
78 | assertEquals(1, m_Player.getMessageCount());
79 | assertEquals(1, m_Player.getMessageField(0, "Address"));
80 | }
81 |
82 | @Test
83 | public void testTwoMessages() {
84 | m_Encoder.setRepeatCount(2);
85 | m_Encoder.setAddress(0xFFFEFD);
86 | m_Player.playMessage(m_Encoder.encode());
87 | assertEquals(2, m_Player.getMessageCount());
88 | // Verify first message
89 | assertEquals(0xFFFEFD, m_Player.getMessageField(0, "Address"));
90 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
91 | // Verify second message
92 | assertEquals(0xFFFEFD, m_Player.getMessageField(1, "Address"));
93 | assertEquals(1, m_Player.getMessages()[1].getRepeat());
94 | }
95 |
96 | @Test
97 | public void JirWalterK() {
98 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.ALL_DECODERS);
99 | player.m_FlankDetector.setFlankSwing(50);
100 | player.m_FlankDetector.setFlankLength(4);
101 | player.m_FlankDetector.setPulseWidthCompensation(0);
102 |
103 | // This file contains a NexaFire message repeated 11 times
104 | player.playFile(this.getClass().getClassLoader()
105 | .getResourceAsStream("nu/nethome/coders/decoders/nexa_fire.jir"));
106 |
107 | // Verify result
108 | assertEquals(8, player.m_Messages.size());
109 | assertEquals("NexaFire", player.m_Messages.get(7).getProtocol());
110 | assertEquals(7, player.m_Messages.get(7).getRepeat());
111 | assertEquals(0x0BD6BC, player.getMessageField(7, "Address"));
112 |
113 | // assertEquals(0xBC, player.getMessageField(7, "Raw1"));
114 | // assertEquals(0xD6, player.getMessageField(7, "Raw2"));
115 | // assertEquals(0x0B, player.getMessageField(7, "Raw3"));
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/TestNexaLDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.decoders.util.JirFileTestPlayer;
23 | import nu.nethome.coders.encoders.NexaLEncoder;
24 | import nu.nethome.util.ps.BadMessageException;
25 | import nu.nethome.util.ps.Message;
26 | import nu.nethome.util.ps.MessageRepeater;
27 | import nu.nethome.util.ps.impl.PulseTestPlayer;
28 | import org.junit.After;
29 | import org.junit.Before;
30 | import org.junit.Test;
31 |
32 | import static org.junit.Assert.assertEquals;
33 |
34 | /**
35 | * Unit tests for NexaLEncoder and NexaLDecoder
36 | * @author Stefan
37 | *
38 | */
39 | public class TestNexaLDecoder {
40 |
41 | private NexaLEncoder m_Encoder;
42 | private NexaLDecoder m_Decoder;
43 | private PulseTestPlayer m_Player;
44 |
45 | @Before
46 | public void setUp() throws Exception {
47 | m_Encoder = new NexaLEncoder();
48 | m_Player = new PulseTestPlayer();
49 | m_Decoder = new NexaLDecoder();
50 | m_Decoder.setTarget(m_Player);
51 | m_Player.setDecoder(m_Decoder);
52 | }
53 |
54 | @After
55 | public void tearDown() throws Exception {
56 | }
57 |
58 | @Test
59 | public void testSetAddress() {
60 | assertEquals(0, m_Encoder.getAddress());
61 | m_Encoder.setAddress(0xaabbcc);
62 | assertEquals(0xaabbcc, m_Encoder.getAddress());
63 | }
64 |
65 | @Test
66 | public void testSetButton() {
67 | assertEquals(1, m_Encoder.getButton());
68 | m_Encoder.setButton(3);
69 | assertEquals(3, m_Encoder.getButton());
70 | m_Encoder.setButton(16);
71 | assertEquals(16, m_Encoder.getButton());
72 | m_Encoder.setButton(17);
73 | assertEquals(17, m_Encoder.getButton());
74 | }
75 |
76 | @Test
77 | public void testSetCommand() {
78 | assertEquals(1, m_Encoder.getCommand());
79 | m_Encoder.setCommand(0);
80 | assertEquals(0, m_Encoder.getCommand());
81 | m_Encoder.setCommand(2);
82 | assertEquals(0, m_Encoder.getCommand());
83 | }
84 |
85 | @Test
86 | public void testSetRepeatCount() {
87 | assertEquals(5, m_Encoder.getRepeatCount());
88 | m_Encoder.setRepeatCount(4);
89 | assertEquals(4, m_Encoder.getRepeatCount());
90 | m_Encoder.setRepeatCount(0);
91 | assertEquals(4, m_Encoder.getRepeatCount());
92 | }
93 |
94 | @Test
95 | public void testSingleMessage() {
96 | m_Encoder.setRepeatCount(1);
97 | m_Encoder.setAddress(0xaabbcc);
98 | m_Encoder.setButton(3);
99 | m_Encoder.setCommand(1);
100 | m_Player.playMessage(m_Encoder.encode());
101 | assertEquals(1, m_Player.getMessageCount());
102 | assertEquals(0xaabbcc, m_Player.getMessageField(0, "Address"));
103 | assertEquals(3, m_Player.getMessageField(0, "Button"));
104 | assertEquals(1, m_Player.getMessageField(0, "Command"));
105 | }
106 |
107 | @Test
108 | public void testSingleMessageNewEncoder() throws BadMessageException {
109 | Message toSend = NexaLEncoder.buildMessage(1, 3, 0xaabbcc);
110 | m_Player.playMessage(MessageRepeater.repeat(m_Encoder, toSend, 1));
111 | assertEquals(1, m_Player.getMessageCount());
112 | assertEquals(0xaabbcc, m_Player.getMessageField(0, "Address"));
113 | assertEquals(3, m_Player.getMessageField(0, "Button"));
114 | assertEquals(1, m_Player.getMessageField(0, "Command"));
115 | }
116 |
117 | @Test
118 | public void testTwoMessages() {
119 | m_Encoder.setRepeatCount(2);
120 | m_Encoder.setAddress(0x3ffffff);
121 | m_Encoder.setButton(17);
122 | m_Encoder.setCommand(0);
123 | m_Player.playMessage(m_Encoder.encode());
124 | assertEquals(2, m_Player.getMessageCount());
125 | assertEquals(0x3ffffff, m_Player.getMessageField(0, "Address"));
126 | assertEquals(17, m_Player.getMessageField(0, "Button"));
127 | assertEquals(0, m_Player.getMessageField(0, "Command"));
128 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
129 | assertEquals(0x3ffffff, m_Player.getMessageField(1, "Address"));
130 | //assertEquals(17, m_Player.getMessageField(1, "Button"));
131 | assertEquals(0, m_Player.getMessageField(1, "Command"));
132 | assertEquals(1, m_Player.getMessages()[1].getRepeat());
133 | }
134 |
135 | @Test
136 | public void testThreeMessages() {
137 | m_Encoder.setRepeatCount(3);
138 | m_Encoder.setAddress(0x248a957);
139 | m_Encoder.setButton(17);
140 | m_Encoder.setCommand(0);
141 | m_Player.playMessage(m_Encoder.encode());
142 | assertEquals(3, m_Player.getMessageCount());
143 | assertEquals(0x248a957, m_Player.getMessageField(0, "Address"));
144 | assertEquals(17, m_Player.getMessageField(0, "Button"));
145 | assertEquals(0, m_Player.getMessageField(0, "Command"));
146 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
147 | assertEquals(0x248a957, m_Player.getMessageField(1, "Address"));
148 | //assertEquals(17, m_Player.getMessageField(1, "Button"));
149 | //assertEquals(0, m_Player.getMessageField(1, "Command"));
150 | assertEquals(1, m_Player.getMessages()[1].getRepeat());
151 | assertEquals(0x248a957, m_Player.getMessageField(2, "Address"));
152 | assertEquals(17, m_Player.getMessageField(2, "Button"));
153 | assertEquals(0, m_Player.getMessageField(2, "Command"));
154 | assertEquals(2, m_Player.getMessages()[2].getRepeat());
155 | }
156 |
157 | @Test
158 | public void basicJir() {
159 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.ALL_DECODERS);
160 |
161 | // This file contains a NexaL message repeated 11 times
162 | player.playFile(this.getClass().getClassLoader()
163 | .getResourceAsStream("nu/nethome/coders/decoders/nexal1.jir"));
164 |
165 | // Verify result
166 | assertEquals(11, player.m_Messages.size());
167 | assertEquals("NexaL", player.m_Messages.get(10).getProtocol());
168 | assertEquals(10, player.m_Messages.get(10).getRepeat());
169 | assertEquals(0x155be6, player.getMessageField(10, "Address"));
170 | assertEquals(10, player.getMessageField(10, "Button"));
171 | }
172 |
173 | @Test
174 | public void JirDavidNaslund() {
175 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.ALL_DECODERS);
176 | player.m_FlankDetector.setFlankSwing(40);
177 | player.m_FlankDetector.setFlankLength(4);
178 | player.m_FlankDetector.setPulseWidthCompensation(0);
179 |
180 | // This file contains a NexaL message repeated 11 times
181 | player.playFile(this.getClass().getClassLoader()
182 | .getResourceAsStream("nu/nethome/coders/decoders/nexal_dn.jir"));
183 |
184 | // Verify result
185 | assertEquals(5, player.m_Messages.size());
186 | assertEquals("NexaL", player.m_Messages.get(4).getProtocol());
187 | assertEquals(4, player.m_Messages.get(4).getRepeat());
188 | assertEquals(0x2b38aa, player.getMessageField(4, "Address"));
189 | assertEquals(11, player.getMessageField(4, "Button"));
190 | }
191 |
192 | }
193 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/TestProntoDecoder.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.encoders.ProntoEncoder;
23 | import nu.nethome.util.ps.BadMessageException;
24 | import nu.nethome.util.ps.Message;
25 | import nu.nethome.util.ps.MessageRepeater;
26 | import nu.nethome.util.ps.ProtocolEncoder;
27 | import nu.nethome.util.ps.impl.PulseTestPlayer;
28 | import org.junit.After;
29 | import org.junit.Before;
30 | import org.junit.Test;
31 |
32 | import static org.hamcrest.CoreMatchers.is;
33 | import static org.junit.Assert.*;
34 |
35 | /**
36 | * Unit tests for X10Encoder and X10Decoder.
37 | * @author �garen
38 | *
39 | */
40 | public class TestProntoDecoder {
41 |
42 | private ProntoEncoder m_Encoder;
43 | private ProntoDecoder m_Decoder;
44 | private PulseTestPlayer m_Player;
45 |
46 | @Before
47 | public void setUp() throws Exception {
48 | m_Encoder = new ProntoEncoder();
49 | m_Player = new PulseTestPlayer();
50 | m_Decoder = new ProntoDecoder();
51 | m_Decoder.setTarget(m_Player);
52 | m_Player.setDecoder(m_Decoder);
53 | }
54 |
55 | @After
56 | public void tearDown() throws Exception {
57 | }
58 |
59 | @Test
60 | public void testGeneral() {
61 | m_Decoder.addBurst(10000, false);
62 | }
63 | @Test
64 | public void testSetCommand() {
65 | assertEquals("", m_Encoder.getMessage());
66 | m_Encoder.setMessage("0000 1111 2222");
67 | assertEquals("0000 1111 2222", m_Encoder.getMessage());
68 | }
69 |
70 | @Test
71 | public void testSetRepeatCount() {
72 | assertEquals(5, m_Encoder.getRepeatCount());
73 | m_Encoder.setRepeatCount(6);
74 | assertEquals(6, m_Encoder.getRepeatCount());
75 | m_Encoder.setRepeatCount(0);
76 | assertEquals(6, m_Encoder.getRepeatCount());
77 | }
78 |
79 | protected final String sonyMessage1 =
80 | "0000 0067 0000 0015 0060 0018 0018 0018 0030 0018 0030 0018 0030 " +
81 | "0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 " +
82 | "0030 0018 0030 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 " +
83 | "0018 0018 0018 0030 0018 0018 03f6";
84 |
85 | protected final String sonyMessage2 =
86 | "0000 0067 0001 0014 0060 0018 0018 0018 0030 0018 0030 0018 0030 " +
87 | "0018 0018 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 0018 " +
88 | "0030 0018 0030 0018 0030 0018 0018 0018 0018 0018 0030 0018 0018 " +
89 | "0018 0018 0018 0030 0018 0018 03f6";
90 |
91 | @Test
92 | public void testSingleEncodingNoHeader() throws BadMessageException {
93 | Message toSend = ProntoEncoder.createMessage(sonyMessage1);
94 | int header[] = m_Encoder.encode(toSend, ProtocolEncoder.Phase.FIRST);
95 | int body[] = m_Encoder.encode(toSend, ProtocolEncoder.Phase.REPEATED);
96 | assertThat(header.length, is(0));
97 | assertThat(body.length, is(42));
98 | }
99 |
100 | @Test
101 | public void testSingleEncodingWithHeader() throws BadMessageException {
102 | Message toSend = ProntoEncoder.createMessage(sonyMessage2);
103 | int header[] = m_Encoder.encode(toSend, ProtocolEncoder.Phase.FIRST);
104 | int body[] = m_Encoder.encode(toSend, ProtocolEncoder.Phase.REPEATED);
105 | assertThat(header.length, is(2));
106 | assertThat(body.length, is(40));
107 | }
108 |
109 |
110 | @Test
111 | public void testSingleMessageNoMod() {
112 | m_Encoder.setRepeatCount(1);
113 | m_Encoder.setMessage(sonyMessage1);
114 | m_Player.setPulseWidthModification(0);
115 | m_Decoder.setPulseWidthModification(0);
116 | m_Player.playMessage(m_Encoder.encode());
117 | assertEquals(1, m_Player.getMessageCount());
118 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(0, "Message"));
119 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
120 | }
121 |
122 | @Test
123 | public void testSingleMessageMod() {
124 | m_Encoder.setRepeatCount(1);
125 | m_Encoder.setMessage(sonyMessage1);
126 | m_Player.setPulseWidthModification(60);
127 | m_Decoder.setPulseWidthModification(60);
128 | m_Player.playMessage(m_Encoder.encode());
129 | assertEquals(1, m_Player.getMessageCount());
130 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(0, "Message"));
131 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
132 | }
133 |
134 | @Test
135 | public void testSingleMessageFailMod() {
136 | m_Encoder.setRepeatCount(1);
137 | m_Encoder.setMessage(sonyMessage1);
138 | m_Player.setPulseWidthModification(0);
139 | m_Decoder.setPulseWidthModification(60);
140 | m_Player.playMessage(m_Encoder.encode());
141 | assertEquals(1, m_Player.getMessageCount());
142 | assertFalse(sonyMessage1.equals(m_Player.getMessageFieldString(0, "Message")));
143 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
144 | }
145 |
146 | @Test
147 | public void testThreeMessages() {
148 | m_Encoder.setRepeatCount(3);
149 | m_Encoder.setMessage(sonyMessage1);
150 | m_Player.setPulseWidthModification(60);
151 | m_Decoder.setPulseWidthModification(60);
152 | m_Player.playMessage(m_Encoder.encode());
153 | assertEquals(3, m_Player.getMessageCount());
154 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(0, "Message"));
155 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
156 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(1, "Message"));
157 | assertEquals(0, m_Player.getMessages()[1].getRepeat());
158 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(2, "Message"));
159 | assertEquals(0, m_Player.getMessages()[2].getRepeat());
160 | }
161 |
162 | @Test
163 | public void testThreeMessagesNewInterface() throws BadMessageException {
164 | Message toSend = ProntoEncoder.createMessage(sonyMessage1);
165 | m_Player.playMessage(MessageRepeater.repeat(m_Encoder, toSend, 3));
166 | assertEquals(3, m_Player.getMessageCount());
167 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(0, "Message"));
168 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
169 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(1, "Message"));
170 | assertEquals(0, m_Player.getMessages()[1].getRepeat());
171 | assertEquals(sonyMessage1, m_Player.getMessageFieldString(2, "Message"));
172 | assertEquals(0, m_Player.getMessages()[2].getRepeat());
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/TestWaveman.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.decoders.util.JirFileTestPlayer;
23 | import nu.nethome.coders.encoders.WavemanEncoder;
24 | import nu.nethome.util.ps.impl.PulseTestPlayer;
25 | import org.junit.After;
26 | import org.junit.Before;
27 | import org.junit.Test;
28 |
29 | import static org.junit.Assert.assertEquals;
30 |
31 | /**
32 | * Unit tests for WavemanEncoder and WavemanDecoder.
33 | * @author Stefan
34 | *
35 | */
36 | public class TestWaveman {
37 |
38 | private WavemanEncoder m_Encoder;
39 | private WavemanDecoder m_Decoder;
40 | private PulseTestPlayer m_Player;
41 |
42 | @Before
43 | public void setUp() throws Exception {
44 | m_Encoder = new WavemanEncoder();
45 | m_Player = new PulseTestPlayer();
46 | m_Decoder = new WavemanDecoder();
47 | m_Decoder.setTarget(m_Player);
48 | m_Player.setDecoder(m_Decoder);
49 | m_Player.setPulseWidthModification(0);
50 | }
51 |
52 | @After
53 | public void tearDown() throws Exception {
54 | }
55 |
56 | @Test
57 | public void testSetAddress() {
58 | assertEquals('A', m_Encoder.getAddress());
59 | m_Encoder.setAddress('F');
60 | assertEquals('F', m_Encoder.getAddress());
61 | }
62 |
63 | @Test
64 | public void testSetButton() {
65 | assertEquals(1, m_Encoder.getButton());
66 | m_Encoder.setButton(2);
67 | assertEquals(2, m_Encoder.getButton());
68 | m_Encoder.setButton(0);
69 | assertEquals(2, m_Encoder.getButton());
70 | }
71 |
72 | @Test
73 | public void testSetCommand() {
74 | assertEquals(1, m_Encoder.getCommand());
75 | m_Encoder.setCommand(0);
76 | assertEquals(0, m_Encoder.getCommand());
77 | m_Encoder.setCommand(2);
78 | assertEquals(0, m_Encoder.getCommand());
79 | }
80 |
81 | @Test
82 | public void testSetRepeatCount() {
83 | assertEquals(5, m_Encoder.getRepeatCount());
84 | m_Encoder.setRepeatCount(6);
85 | assertEquals(6, m_Encoder.getRepeatCount());
86 | m_Encoder.setRepeatCount(0);
87 | assertEquals(6, m_Encoder.getRepeatCount());
88 | }
89 |
90 | @Test
91 | public void testSingleMessage() {
92 | m_Encoder.setRepeatCount(1);
93 | m_Encoder.setAddress('B');
94 | m_Encoder.setButton(2);
95 | m_Encoder.setCommand(1);
96 | m_Player.playMessage(m_Encoder.encode());
97 | assertEquals(1, m_Player.getMessageCount());
98 | assertEquals(1, m_Player.getMessageField(0, "HouseCode"));
99 | assertEquals(2, m_Player.getMessageField(0, "Button"));
100 | assertEquals(1, m_Player.getMessageField(0, "Command"));
101 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
102 | }
103 |
104 | @Test
105 | public void testTwoMessages() {
106 | m_Encoder.setRepeatCount(2);
107 | m_Encoder.setAddress('H');
108 | m_Encoder.setButton(8);
109 | m_Encoder.setCommand(0);
110 | m_Player.playMessage(m_Encoder.encode());
111 | assertEquals(2, m_Player.getMessageCount());
112 | assertEquals(7, m_Player.getMessageField(0, "HouseCode"));
113 | assertEquals(8, m_Player.getMessageField(0, "Button"));
114 | assertEquals(0, m_Player.getMessageField(0, "Command"));
115 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
116 | assertEquals(7, m_Player.getMessageField(1, "HouseCode"));
117 | assertEquals(8, m_Player.getMessageField(1, "Button"));
118 | assertEquals(0, m_Player.getMessageField(1, "Command"));
119 | assertEquals(1, m_Player.getMessages()[1].getRepeat());
120 | }
121 |
122 | @Test
123 | public void testThreeMessages() {
124 | m_Encoder.setRepeatCount(3);
125 | m_Encoder.setAddress('H');
126 | m_Encoder.setButton(8);
127 | m_Encoder.setCommand(0);
128 | m_Player.playMessage(m_Encoder.encode());
129 | assertEquals(3, m_Player.getMessageCount());
130 | assertEquals(7, m_Player.getMessageField(0, "HouseCode"));
131 | assertEquals(8, m_Player.getMessageField(0, "Button"));
132 | assertEquals(0, m_Player.getMessageField(0, "Command"));
133 | assertEquals(0, m_Player.getMessages()[0].getRepeat());
134 | assertEquals(7, m_Player.getMessageField(1, "HouseCode"));
135 | assertEquals(8, m_Player.getMessageField(1, "Button"));
136 | assertEquals(0, m_Player.getMessageField(1, "Command"));
137 | assertEquals(1, m_Player.getMessages()[1].getRepeat());
138 | assertEquals(7, m_Player.getMessageField(2, "HouseCode"));
139 | assertEquals(8, m_Player.getMessageField(2, "Button"));
140 | assertEquals(0, m_Player.getMessageField(2, "Command"));
141 | assertEquals(2, m_Player.getMessages()[2].getRepeat());
142 | }
143 |
144 | @Test
145 | public void basicJir() {
146 | JirFileTestPlayer player = new JirFileTestPlayer(JirFileTestPlayer.ALL_DECODERS - JirFileTestPlayer.Nexa_DECODER);
147 |
148 | // This file contains a Waveman message repeated 6 times
149 | player.playFile(this.getClass().getClassLoader()
150 | .getResourceAsStream("nu/nethome/coders/decoders/nexa1.jir"));
151 |
152 | // Verify result
153 | assertEquals(6, player.m_Messages.size());
154 | assertEquals("Waveman", player.m_Messages.get(5).getProtocol());
155 | assertEquals(5, player.m_Messages.get(5).getRepeat());
156 | assertEquals(1, player.getMessageField(5, "Command"));
157 | assertEquals(3, player.getMessageField(5, "Button"));
158 | assertEquals(2, player.getMessageField(5, "HouseCode"));
159 | }
160 |
161 | }
162 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/ZhejiangDecoderTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders;
21 |
22 | import nu.nethome.coders.encoders.ZhejiangEncoder;
23 | import nu.nethome.util.ps.BadMessageException;
24 | import nu.nethome.util.ps.FieldValue;
25 | import nu.nethome.util.ps.Message;
26 | import nu.nethome.util.ps.ProtocolEncoder;
27 | import nu.nethome.util.ps.impl.PulseTestPlayer;
28 | import org.junit.Before;
29 | import org.junit.Test;
30 |
31 | import static org.hamcrest.Matchers.hasItem;
32 | import static org.hamcrest.Matchers.is;
33 | import static org.junit.Assert.assertThat;
34 |
35 | /**
36 | * User: Stefan
37 | * Date: 2013-03-24
38 | * Time: 22:26
39 | */
40 | public class ZhejiangDecoderTest {
41 | private ZhejiangEncoder encoder;
42 | private ZhejiangDecoder decoder;
43 | private PulseTestPlayer player;
44 |
45 | @Before
46 | public void setUp() throws Exception {
47 | encoder = new ZhejiangEncoder();
48 | player = new PulseTestPlayer();
49 | decoder = new ZhejiangDecoder();
50 | decoder.setTarget(player);
51 | player.setDecoder(decoder);
52 | player.setPulseWidthModification(0);
53 | }
54 |
55 | @Test
56 | public void canCreateCommand() {
57 | Message message = ZhejiangEncoder.buildMessage(1, 2, 3);
58 | assertThat(message.getFields().size(), is(3));
59 | assertThat(message.getFields(), hasItem(new FieldValue("Command", 1)));
60 | assertThat(message.getFields(), hasItem(new FieldValue("Button", 2)));
61 | assertThat(message.getFields(), hasItem(new FieldValue("Address", 3)));
62 | }
63 |
64 | @Test
65 | public void canDecodeEncodedMessage() throws BadMessageException {
66 | player.playMessage(encoder.encode(ZhejiangEncoder.buildMessage(1, 2, 3), ProtocolEncoder.Phase.REPEATED));
67 | assertThat(player.getMessageCount(), is(1));
68 | assertThat(player.getMessageField(0, "Command"), is(1));
69 | assertThat(player.getMessageField(0, "Button"), is(2));
70 | assertThat(player.getMessageField(0, "Address"), is(3));
71 | assertThat(player.getMessages()[0].getRepeat(), is(0));
72 | }
73 |
74 | @Test
75 | public void CompareWithKnownOnTestVector() throws BadMessageException {
76 | player.playMessage(encoder.encode(ZhejiangEncoder.buildMessage(1, 2, 0), ProtocolEncoder.Phase.REPEATED));
77 | assertThat(player.getMessageCount(), is(1));
78 | assertThat(player.getMessages()[0].getRawMessage()[0], is(0));
79 | assertThat(player.getMessages()[0].getRawMessage()[1], is(0x2A));
80 | assertThat(player.getMessages()[0].getRawMessage()[2], is(0x2B));
81 | assertThat(player.getMessages()[0].getRawMessage()[3], is(0xFF));
82 | }
83 |
84 | @Test
85 | public void CompareWithKnownOffTestVector() throws BadMessageException {
86 | player.playMessage(encoder.encode(ZhejiangEncoder.buildMessage(0, 2, 0), ProtocolEncoder.Phase.REPEATED));
87 | assertThat(player.getMessageCount(), is(1));
88 | assertThat(player.getMessages()[0].getRawMessage()[0], is(0));
89 | assertThat(player.getMessages()[0].getRawMessage()[1], is(0x8A));
90 | assertThat(player.getMessages()[0].getRawMessage()[2], is(0x2B));
91 | assertThat(player.getMessages()[0].getRawMessage()[3], is(0xFF));
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/decoders/util/JirFileTestPlayer.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2005-2013, Stefan Strömberg
3 | *
4 | * This file is part of OpenNetHome (http://www.nethome.nu).
5 | *
6 | * OpenNetHome is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * OpenNetHome is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 |
20 | package nu.nethome.coders.decoders.util;
21 |
22 | import nu.nethome.coders.decoders.*;
23 | import nu.nethome.util.ps.FieldValue;
24 | import nu.nethome.util.ps.ProtocolDecoderSink;
25 | import nu.nethome.util.ps.ProtocolMessage;
26 | import nu.nethome.util.ps.RawProtocolMessage;
27 | import nu.nethome.util.ps.impl.FIRFilter6000;
28 | import nu.nethome.util.ps.impl.ProtocolDecoderGroup;
29 | import nu.nethome.util.ps.impl.SimpleFlankDetector;
30 |
31 | import java.io.IOException;
32 | import java.io.InputStream;
33 | import java.io.ObjectInputStream;
34 | import java.util.ArrayList;
35 | import java.util.List;
36 |
37 | public class JirFileTestPlayer implements ProtocolDecoderSink{
38 |
39 | public static final int SIRC_DECODER = 1 << 0;
40 | public static final int RC6_DECODER = 1 << 1;
41 | public static final int RC5_DECODER = 1 << 2;
42 | public static final int JVC_DECODER = 1 << 3;
43 | public static final int Viasat_DECODER = 1 << 4;
44 | public static final int Pioneer_DECODER = 1 << 5;
45 | public static final int HK_DECODER = 1 << 6;
46 | public static final int UPM_DECODER = 1 << 7;
47 | public static final int Nexa_DECODER = 1 << 8;
48 | public static final int NexaL_DECODER = 1 << 9;
49 | public static final int Deltronic_DECODER = 1 << 10;
50 | public static final int X10_DECODER = 1 << 11;
51 | public static final int Waveman_DECODER = 1 << 12;
52 | public static final int NexaFire_DECODER = 1 << 13;
53 | public static final int OREGON_DECODER = 1 << 14;
54 | public static final int FINE_OFFSET_DECODER = 1 << 15;
55 | public static final int ROLLERTROL_DECODER = 1 << 16;
56 | public static final int ROLLERTROL_G_DECODER = 1 << 17;
57 | public static final int PROLOGUE_DECODER = 1 << 18;
58 |
59 | public static final int ALL_DECODERS = 0x7FFFFFFF;
60 |
61 |
62 | public SimpleFlankDetector m_FlankDetector;
63 | public ProtocolDecoderGroup m_ProtocolDecoders = new ProtocolDecoderGroup();
64 | public FIRFilter6000 m_Filter;
65 |
66 | public ArrayList m_Messages = new ArrayList();
67 | public boolean m_PartlyParsedMessage = false;
68 |
69 | public JirFileTestPlayer(int decoders) {
70 |
71 | // Create the Protocol-Decoders and add them to the decoder group
72 | if ((decoders & SIRC_DECODER) != 0) m_ProtocolDecoders.add(new SIRCDecoder());
73 | if ((decoders & RC6_DECODER) != 0) m_ProtocolDecoders.add(new RC6Decoder());
74 | if ((decoders & RC5_DECODER) != 0) m_ProtocolDecoders.add(new RC5Decoder());
75 | if ((decoders & JVC_DECODER) != 0) m_ProtocolDecoders.add(new JVCDecoder());
76 | if ((decoders & Viasat_DECODER) != 0) m_ProtocolDecoders.add(new ViasatDecoder());
77 | if ((decoders & Pioneer_DECODER) != 0) m_ProtocolDecoders.add(new PioneerDecoder());
78 | if ((decoders & HK_DECODER) != 0) m_ProtocolDecoders.add(new HKDecoder());
79 | if ((decoders & UPM_DECODER) != 0) m_ProtocolDecoders.add(new UPMDecoder());
80 | if ((decoders & Nexa_DECODER) != 0) m_ProtocolDecoders.add(new NexaDecoder());
81 | if ((decoders & NexaL_DECODER) != 0) m_ProtocolDecoders.add(new NexaLDecoder());
82 | if ((decoders & Deltronic_DECODER) != 0) m_ProtocolDecoders.add(new DeltronicDecoder());
83 | if ((decoders & X10_DECODER) != 0) m_ProtocolDecoders.add(new X10Decoder());
84 | if ((decoders & Waveman_DECODER) != 0) m_ProtocolDecoders.add(new WavemanDecoder());
85 | if ((decoders & NexaFire_DECODER) != 0) m_ProtocolDecoders.add(new NexaFireDecoder());
86 | if ((decoders & OREGON_DECODER) != 0) m_ProtocolDecoders.add(new OregonDecoder());
87 | if ((decoders & FINE_OFFSET_DECODER) != 0) m_ProtocolDecoders.add(new FineOffsetDecoder());
88 | if ((decoders & ROLLERTROL_DECODER) != 0) m_ProtocolDecoders.add(new RollerTrolDecoder());
89 | if ((decoders & ROLLERTROL_G_DECODER) != 0) m_ProtocolDecoders.add(new RollerTrolGDecoder());
90 | if ((decoders & PROLOGUE_DECODER) != 0) m_ProtocolDecoders.add(new PrologueDecoder());
91 |
92 | // Set the Sink - which is this class
93 | m_ProtocolDecoders.setTarget(this);
94 |
95 | // Create The Flank Detector and attach the decoders
96 | m_FlankDetector = new SimpleFlankDetector();
97 | m_FlankDetector.setProtocolDecoder(m_ProtocolDecoders);
98 |
99 | // Create the FIR-Filter and attach to the samplers
100 | m_Filter = new FIRFilter6000(m_FlankDetector);
101 |
102 | m_FlankDetector.setSampleRate(44100);
103 |
104 | }
105 |
106 | public void playFile(InputStream fileStream) {
107 | ObjectInputStream ois;
108 |
109 | // Add a quiet period (200ms) before signal
110 | int numberOfEndSamples = m_FlankDetector.getSampleRate() / 5;
111 | for (int i = 0; i < numberOfEndSamples; i++) {
112 | m_FlankDetector.addSample(0);
113 | }
114 |
115 | int lastSample = 0;
116 | try {
117 | ois = new ObjectInputStream(fileStream);
118 |
119 | int length = ois.readInt();
120 | for (int i = 0; i < length; i++) {
121 | ProtocolMessage irm = (ProtocolMessage) ois.readObject();
122 | // Check that it is a raw sample
123 | if (irm.getProtocol().equals("Raw")) {
124 | RawProtocolMessage mess = (RawProtocolMessage) irm;
125 | for (int sample : mess.m_Samples) {
126 | // Push sample into decoders
127 | m_FlankDetector.addSample(sample);
128 | lastSample = sample;
129 | }
130 | }
131 |
132 | }
133 | ois.close();
134 | } catch (IOException e) {
135 | e.printStackTrace();
136 | } catch (ClassNotFoundException e) {
137 | e.printStackTrace();
138 | }
139 |
140 | // Add a quiet period (200ms)to end detection
141 | numberOfEndSamples = m_FlankDetector.getSampleRate() / 5;
142 | for (int i = 0; i < numberOfEndSamples; i++) {
143 | m_FlankDetector.addSample(lastSample);
144 | }
145 |
146 |
147 | }
148 |
149 | public int getMessageField(int messageNumber, String fieldName) {
150 | if (messageNumber >= m_Messages.size()) {
151 | return -1;
152 | }
153 | List fields = m_Messages.get(messageNumber).getFields();
154 | for (FieldValue field : fields) {
155 | if (fieldName.equals(field.getName())) {
156 | return field.getValue();
157 | }
158 | }
159 | return -1;
160 | }
161 |
162 | public String getMessageFieldString(int messageNumber, String fieldName) {
163 | if (messageNumber >= m_Messages.size()) {
164 | return "";
165 | }
166 | List fields = m_Messages.get(messageNumber).getFields();
167 | for (FieldValue field : fields) {
168 | if (fieldName.equals(field.getName()) && (field.getStringValue() != null)) {
169 | return field.getStringValue();
170 | }
171 | }
172 | return "";
173 | }
174 |
175 | public void parsedMessage(ProtocolMessage message) {
176 | m_Messages.add(message);
177 | }
178 |
179 | public void partiallyParsedMessage(String protocol, int bits) {
180 | m_PartlyParsedMessage = true;
181 | }
182 |
183 | public void reportLevel(int level) {
184 | // Nothing to do
185 | }
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/src/test/java/nu/nethome/coders/encoders/RollerTrolEncoderTest.java:
--------------------------------------------------------------------------------
1 | package nu.nethome.coders.encoders;
2 |
3 | import nu.nethome.coders.RollerTrol;
4 | import nu.nethome.coders.decoders.RollerTrolDecoder;
5 | import nu.nethome.util.ps.ProtocolEncoder;
6 | import nu.nethome.util.ps.impl.PulseTestPlayer;
7 | import org.junit.Before;
8 | import org.junit.Test;
9 |
10 | import static nu.nethome.coders.RollerTrol.*;
11 | import static org.hamcrest.MatcherAssert.assertThat;
12 | import static org.hamcrest.Matchers.greaterThanOrEqualTo;
13 | import static org.hamcrest.Matchers.is;
14 |
15 | /**
16 | *
17 | */
18 | public class RollerTrolEncoderTest {
19 |
20 | private RollerTrolEncoder rollerTrolEncoder;
21 | private PulseTestPlayer player;
22 | private RollerTrolDecoder rollerTrolDecoder;
23 |
24 | @Before
25 | public void setUp() throws Exception {
26 | rollerTrolEncoder = new RollerTrolEncoder();
27 | player = new PulseTestPlayer();
28 | rollerTrolDecoder = new RollerTrolDecoder();
29 | rollerTrolDecoder.setTarget(player);
30 | player.setDecoder(rollerTrolDecoder);
31 | player.setPulseWidthModification(0);
32 |
33 | }
34 |
35 | @Test
36 | public void encodesPreamble() throws Exception {
37 | int[] data = rollerTrolEncoder.encode(RollerTrolEncoder.buildMessage(1, 1, 1), ProtocolEncoder.Phase.FIRST);
38 | assertThat(data.length, is(greaterThanOrEqualTo(4)));
39 | assertThat(data[0], is(LONG_PREAMBLE_MARK.length()));
40 | assertThat(data[1], is(LONG_PREAMBLE_SPACE.length()));
41 | assertThat(data[2], is(SHORT_PREAMBLE_MARK.length()));
42 | assertThat(data[3], is(SHORT.length()));
43 | }
44 |
45 | @Test
46 | public void encodes40BitsPlusPreamble() throws Exception {
47 | int[] data = rollerTrolEncoder.encode(RollerTrolEncoder.buildMessage(1, 1, 1), ProtocolEncoder.Phase.FIRST);
48 | assertThat(data.length, is(4 + 40 * 2));
49 | }
50 |
51 | @Test
52 | public void canEncodeHouseCode() throws Exception {
53 | player.playMessage(rollerTrolEncoder.encode(RollerTrolEncoder.buildMessage(1, 12345, 1), ProtocolEncoder.Phase.FIRST));
54 | assertThat(player.getMessageCount(), is(1));
55 | assertThat(player.getMessageField(0, RollerTrol.HOUSE_CODE_NAME), is(12345));
56 | }
57 |
58 | @Test
59 | public void canEncodeDeviceCode() throws Exception {
60 | player.playMessage(rollerTrolEncoder.encode(RollerTrolEncoder.buildMessage(1, 12345, 9), ProtocolEncoder.Phase.FIRST));
61 | assertThat(player.getMessageCount(), is(1));
62 | assertThat(player.getMessageField(0, RollerTrol.DEVICE_CODE_NAME), is(9));
63 | }
64 |
65 | @Test
66 | public void canEncodeCommand() throws Exception {
67 | player.playMessage(rollerTrolEncoder.encode(RollerTrolEncoder.buildMessage(5, 12345, 9), ProtocolEncoder.Phase.FIRST));
68 | assertThat(player.getMessageCount(), is(1));
69 | assertThat(player.getMessageField(0, RollerTrol.COMMAND_NAME), is(5));
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/fine_offset.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/fine_offset.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/fine_offset_neg.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/fine_offset_neg.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/nexa1.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/nexa1.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/nexa_fire.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/nexa_fire.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/nexal1.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/nexal1.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/nexal_dn.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/nexal_dn.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/oregon1.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/oregon1.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/prologue.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/prologue.jir
--------------------------------------------------------------------------------
/src/test/resources/nu/nethome/coders/decoders/rollertrol_3_stop.jir:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NetHome/Coders/b476ce7b9e65f2d4ce9a02db3d8ec775e9c1a82a/src/test/resources/nu/nethome/coders/decoders/rollertrol_3_stop.jir
--------------------------------------------------------------------------------