socket_switcher 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.utilsrc +26 -0
  5. data/Gemfile +8 -0
  6. data/README.md +0 -0
  7. data/Rakefile +54 -0
  8. data/VERSION +1 -0
  9. data/arduino-receiver/receiver/receiver.ino +36 -0
  10. data/arduino/lib/.holder +0 -0
  11. data/arduino/lib/RCSwitch/RCSwitch.cpp +823 -0
  12. data/arduino/lib/RCSwitch/RCSwitch.h +144 -0
  13. data/arduino/lib/RCSwitch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde +24 -0
  14. data/arduino/lib/RCSwitch/examples/ReceiveDemo_Advanced/helperfunctions.ino +20 -0
  15. data/arduino/lib/RCSwitch/examples/ReceiveDemo_Advanced/output.ino +52 -0
  16. data/arduino/lib/RCSwitch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde +35 -0
  17. data/arduino/lib/RCSwitch/examples/SendDemo/SendDemo.pde +57 -0
  18. data/arduino/lib/RCSwitch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde +40 -0
  19. data/arduino/lib/RCSwitch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino +43 -0
  20. data/arduino/lib/RCSwitch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde +40 -0
  21. data/arduino/lib/RCSwitch/examples/TypeC_Intertechno/TypeC_Intertechno.pde +40 -0
  22. data/arduino/lib/RCSwitch/examples/TypeD_REV/TypeD_REV.ino +41 -0
  23. data/arduino/lib/RCSwitch/examples/Webserver/Webserver.pde +154 -0
  24. data/arduino/lib/RCSwitch/keywords.txt +57 -0
  25. data/arduino/src/switcher/switcher.ino.erb +79 -0
  26. data/config/default.yml +11 -0
  27. data/config/traffic_lights.yml +8 -0
  28. data/examples/blinkenlights.rb +25 -0
  29. data/lib/socket_switcher.rb +7 -0
  30. data/lib/socket_switcher/device.rb +24 -0
  31. data/lib/socket_switcher/errors.rb +26 -0
  32. data/lib/socket_switcher/port.rb +134 -0
  33. data/lib/socket_switcher/version.rb +8 -0
  34. data/socket_switcher.gemspec +49 -0
  35. data/spec/socket_switcher/device_spec.rb +37 -0
  36. data/spec/socket_switcher/port_spec.rb +216 -0
  37. data/spec/spec_helper.rb +9 -0
  38. metadata +176 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: daf5b77490111b5a65ed2bfdaf01d3695a574985
4
+ data.tar.gz: 628c4fd57e894154ffb26dcadf42de8a2da98035
5
+ SHA512:
6
+ metadata.gz: 75c7adcc370ea31b715a6fee5345022390668b7581a2725b580c8569f651279007c20f215abb85f405facfbe869f4cddf83030c01e197d139d1d054dddd56531
7
+ data.tar.gz: 058dd055a29300e10e94b8b93ab3693e694c0302c3179f1fdebb047208a6f814218036c9dea23675cdcd110d202b5a5462ab0642071cc70b39b9551368074f51
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ .*.sw[pon]
2
+ .DS_Store
3
+ .build
4
+ .bundle
5
+ .rvmrc
6
+ Gemfile.lock
7
+ coverage
8
+ pkg
9
+ tags
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format d
data/.utilsrc ADDED
@@ -0,0 +1,26 @@
1
+ # vim: set ft=ruby:
2
+
3
+ search do
4
+ prune_dirs /\A(\.svn|\.git|CVS|tmp|tags|coverage|pdf_documents|uploads|paperclip|pkg)\z/
5
+ skip_files /(\A\.|\.sw[pon]\z|\.(log|fnm|jpg|jpeg|png|pdf|svg)\z|tags|~\z)/i
6
+ end
7
+
8
+ discover do
9
+ prune_dirs /\A(\.svn|\.git|CVS|tmp|tags|coverage|pdf_documents|uploads|paperclip|pkg)\z/
10
+ skip_files /(\A\.|\.sw[pon]\z|\.log\z|~\z)/
11
+ binary false
12
+ end
13
+
14
+ strip_spaces do
15
+ prune_dirs /\A(\..*|CVS|pkg)\z/
16
+ skip_files /(\A\.|\.sw[pon]\z|\.log\z|~\z)/
17
+ end
18
+
19
+ probe do
20
+ test_framework :'rspec'
21
+ #include_dirs 'features'
22
+ end
23
+
24
+ ssh_tunnel do
25
+ terminal_multiplexer :tmux
26
+ end
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ gem 'byebug', group: :development
8
+ gem 'complex_config', path: '~/scm/complex_config'
data/README.md ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,54 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ require 'gem_hadar'
4
+
5
+ GemHadar do
6
+ name 'socket_switcher'
7
+ author 'Florian Frank'
8
+ email 'flori@ping.de'
9
+ homepage "http://github.com/flori/#{name}"
10
+ summary 'Switches devices on and off'
11
+ description "#{summary}. Yes, it does…"
12
+ licenses << 'GPL-2'
13
+ test_dir 'spec'
14
+ ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.rvmrc', 'coverage',
15
+ 'tags', '.bundle', '.DS_Store', '.build'
16
+
17
+ readme 'README.md'
18
+ executables.merge Dir['bin/*'].map { |x| File.basename(x) }
19
+
20
+ dependency 'tins', '~>1.0'
21
+ dependency 'serialport', '~>1.3'
22
+ dependency 'complex_config'
23
+ development_dependency 'simplecov', '~>0.9'
24
+ development_dependency 'rspec', '~>3.0'
25
+
26
+ default_task_dependencies :spec
27
+ end
28
+
29
+
30
+ arduino_src = 'arduino/src/switcher/switcher.ino.erb'
31
+ arduino_dst = 'arduino/src/switcher/switcher.ino'
32
+ CLOBBER.include arduino_dst
33
+
34
+ template arduino_src do
35
+ require 'complex_config/rude'
36
+ config = complex_config(ENV['CONFIG'] || 'default')
37
+ device_on config.devices.map(&:enable)
38
+ device_off config.devices.map(&:disable)
39
+ device_max config.devices.size - 1
40
+ transmit_pin config.transmit_pin
41
+ end
42
+
43
+ desc 'Compile and upload arduino code'
44
+ task :arduino => arduino_dst do
45
+ cd 'arduino' do
46
+ if `which ino`.empty?
47
+ fail 'install ino command line toolkit with "pip install ino" or "easy_install ino"'
48
+ end
49
+ sh 'ino clean'
50
+ model = ENV['MODEL'] || 'uno'
51
+ sh "ino build -m #{model}"
52
+ sh "ino upload -m #{model}#{' -p ' + ENV['PORT'] if ENV.key?('PORT')}"
53
+ end
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,36 @@
1
+ /*
2
+ Simple example for receiving
3
+
4
+ http://code.google.com/p/rc-switch/
5
+ */
6
+
7
+ #include <RCSwitch.h>
8
+
9
+ RCSwitch mySwitch = RCSwitch();
10
+
11
+ void setup() {
12
+ Serial.begin(9600);
13
+ mySwitch.enableReceive(0); // Receiver on inerrupt 0 => that is pin #2
14
+ Serial.println("RDY");
15
+ }
16
+
17
+ void loop() {
18
+ if (mySwitch.available()) {
19
+
20
+ int value = mySwitch.getReceivedValue();
21
+
22
+ if (value == 0) {
23
+ Serial.print("Unknown encoding");
24
+ } else {
25
+ Serial.print("Received ");
26
+ Serial.print( mySwitch.getReceivedValue() );
27
+ Serial.print(" / ");
28
+ Serial.print( mySwitch.getReceivedBitlength() );
29
+ Serial.print("bit ");
30
+ Serial.print("Protocol: ");
31
+ Serial.println( mySwitch.getReceivedProtocol() );
32
+ }
33
+
34
+ mySwitch.resetAvailable();
35
+ }
36
+ }
File without changes
@@ -0,0 +1,823 @@
1
+ /*
2
+ RCSwitch - Arduino libary for remote control outlet switches
3
+ Copyright (c) 2011 Suat �zg�r. All right reserved.
4
+
5
+ Contributors:
6
+ - Andre Koehler / info(at)tomate-online(dot)de
7
+ - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
8
+ - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
9
+ - Dominik Fischer / dom_fischer(at)web(dot)de
10
+ - Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
11
+ - Andreas Steinel / A.<lastname>(at)gmail(dot)com
12
+
13
+ Project home: http://code.google.com/p/rc-switch/
14
+
15
+ This library is free software; you can redistribute it and/or
16
+ modify it under the terms of the GNU Lesser General Public
17
+ License as published by the Free Software Foundation; either
18
+ version 2.1 of the License, or (at your option) any later version.
19
+
20
+ This library is distributed in the hope that it will be useful,
21
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23
+ Lesser General Public License for more details.
24
+
25
+ You should have received a copy of the GNU Lesser General Public
26
+ License along with this library; if not, write to the Free Software
27
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28
+ */
29
+
30
+ #include "RCSwitch.h"
31
+
32
+ #if not defined( RCSwitchDisableReceiving )
33
+ unsigned long RCSwitch::nReceivedValue = NULL;
34
+ unsigned int RCSwitch::nReceivedBitlength = 0;
35
+ unsigned int RCSwitch::nReceivedDelay = 0;
36
+ unsigned int RCSwitch::nReceivedProtocol = 0;
37
+ int RCSwitch::nReceiveTolerance = 60;
38
+ #endif
39
+ unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
40
+
41
+ RCSwitch::RCSwitch() {
42
+ this->nTransmitterPin = -1;
43
+ this->setPulseLength(350);
44
+ this->setRepeatTransmit(10);
45
+ this->setProtocol(1);
46
+ #if not defined( RCSwitchDisableReceiving )
47
+ this->nReceiverInterrupt = -1;
48
+ this->setReceiveTolerance(60);
49
+ RCSwitch::nReceivedValue = NULL;
50
+ #endif
51
+ }
52
+
53
+ /**
54
+ * Sets the protocol to send.
55
+ */
56
+ void RCSwitch::setProtocol(int nProtocol) {
57
+ this->nProtocol = nProtocol;
58
+ if (nProtocol == 1){
59
+ this->setPulseLength(350);
60
+ }
61
+ else if (nProtocol == 2) {
62
+ this->setPulseLength(650);
63
+ }
64
+ else if (nProtocol == 3) {
65
+ this->setPulseLength(100);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Sets the protocol to send with pulse length in microseconds.
71
+ */
72
+ void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
73
+ this->nProtocol = nProtocol;
74
+ this->setPulseLength(nPulseLength);
75
+ }
76
+
77
+
78
+ /**
79
+ * Sets pulse length in microseconds
80
+ */
81
+ void RCSwitch::setPulseLength(int nPulseLength) {
82
+ this->nPulseLength = nPulseLength;
83
+ }
84
+
85
+ /**
86
+ * Sets Repeat Transmits
87
+ */
88
+ void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
89
+ this->nRepeatTransmit = nRepeatTransmit;
90
+ }
91
+
92
+ /**
93
+ * Set Receiving Tolerance
94
+ */
95
+ #if not defined( RCSwitchDisableReceiving )
96
+ void RCSwitch::setReceiveTolerance(int nPercent) {
97
+ RCSwitch::nReceiveTolerance = nPercent;
98
+ }
99
+ #endif
100
+
101
+
102
+ /**
103
+ * Enable transmissions
104
+ *
105
+ * @param nTransmitterPin Arduino Pin to which the sender is connected to
106
+ */
107
+ void RCSwitch::enableTransmit(int nTransmitterPin) {
108
+ this->nTransmitterPin = nTransmitterPin;
109
+ pinMode(this->nTransmitterPin, OUTPUT);
110
+ }
111
+
112
+ /**
113
+ * Disable transmissions
114
+ */
115
+ void RCSwitch::disableTransmit() {
116
+ this->nTransmitterPin = -1;
117
+ }
118
+
119
+ /**
120
+ * Switch a remote switch on (Type D REV)
121
+ *
122
+ * @param sGroup Code of the switch group (A,B,C,D)
123
+ * @param nDevice Number of the switch itself (1..3)
124
+ */
125
+ void RCSwitch::switchOn(char sGroup, int nDevice) {
126
+ this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) );
127
+ }
128
+
129
+ /**
130
+ * Switch a remote switch off (Type D REV)
131
+ *
132
+ * @param sGroup Code of the switch group (A,B,C,D)
133
+ * @param nDevice Number of the switch itself (1..3)
134
+ */
135
+ void RCSwitch::switchOff(char sGroup, int nDevice) {
136
+ this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) );
137
+ }
138
+
139
+ /**
140
+ * Switch a remote switch on (Type C Intertechno)
141
+ *
142
+ * @param sFamily Familycode (a..f)
143
+ * @param nGroup Number of group (1..4)
144
+ * @param nDevice Number of device (1..4)
145
+ */
146
+ void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
147
+ this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
148
+ }
149
+
150
+ /**
151
+ * Switch a remote switch off (Type C Intertechno)
152
+ *
153
+ * @param sFamily Familycode (a..f)
154
+ * @param nGroup Number of group (1..4)
155
+ * @param nDevice Number of device (1..4)
156
+ */
157
+ void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
158
+ this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
159
+ }
160
+
161
+ /**
162
+ * Switch a remote switch on (Type B with two rotary/sliding switches)
163
+ *
164
+ * @param nAddressCode Number of the switch group (1..4)
165
+ * @param nChannelCode Number of the switch itself (1..4)
166
+ */
167
+ void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
168
+ this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
169
+ }
170
+
171
+ /**
172
+ * Switch a remote switch off (Type B with two rotary/sliding switches)
173
+ *
174
+ * @param nAddressCode Number of the switch group (1..4)
175
+ * @param nChannelCode Number of the switch itself (1..4)
176
+ */
177
+ void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
178
+ this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
179
+ }
180
+
181
+ /**
182
+ * Deprecated, use switchOn(char* sGroup, char* sDevice) instead!
183
+ * Switch a remote switch on (Type A with 10 pole DIP switches)
184
+ *
185
+ * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
186
+ * @param nChannelCode Number of the switch itself (1..5)
187
+ */
188
+ void RCSwitch::switchOn(char* sGroup, int nChannel) {
189
+ char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
190
+ this->switchOn(sGroup, code[nChannel]);
191
+ }
192
+
193
+ /**
194
+ * Deprecated, use switchOff(char* sGroup, char* sDevice) instead!
195
+ * Switch a remote switch off (Type A with 10 pole DIP switches)
196
+ *
197
+ * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
198
+ * @param nChannelCode Number of the switch itself (1..5)
199
+ */
200
+ void RCSwitch::switchOff(char* sGroup, int nChannel) {
201
+ char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
202
+ this->switchOff(sGroup, code[nChannel]);
203
+ }
204
+
205
+ /**
206
+ * Switch a remote switch on (Type A with 10 pole DIP switches)
207
+ *
208
+ * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
209
+ * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
210
+ */
211
+ void RCSwitch::switchOn(char* sGroup, char* sDevice) {
212
+ this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
213
+ }
214
+
215
+ /**
216
+ * Switch a remote switch off (Type A with 10 pole DIP switches)
217
+ *
218
+ * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
219
+ * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
220
+ */
221
+ void RCSwitch::switchOff(char* sGroup, char* sDevice) {
222
+ this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
223
+ }
224
+
225
+ /**
226
+ * Returns a char[13], representing the Code Word to be send.
227
+ * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used.
228
+ * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
229
+ *
230
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
231
+ * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit |
232
+ * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | F | F | on=FF off=F0 | S |
233
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
234
+ *
235
+ * @param nAddressCode Number of the switch group (1..4)
236
+ * @param nChannelCode Number of the switch itself (1..4)
237
+ * @param bStatus Wether to switch on (true) or off (false)
238
+ *
239
+ * @return char[13]
240
+ */
241
+ char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, boolean bStatus) {
242
+ int nReturnPos = 0;
243
+ static char sReturn[13];
244
+
245
+ char* code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
246
+ if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
247
+ return '\0';
248
+ }
249
+ for (int i = 0; i<4; i++) {
250
+ sReturn[nReturnPos++] = code[nAddressCode][i];
251
+ }
252
+
253
+ for (int i = 0; i<4; i++) {
254
+ sReturn[nReturnPos++] = code[nChannelCode][i];
255
+ }
256
+
257
+ sReturn[nReturnPos++] = 'F';
258
+ sReturn[nReturnPos++] = 'F';
259
+ sReturn[nReturnPos++] = 'F';
260
+
261
+ if (bStatus) {
262
+ sReturn[nReturnPos++] = 'F';
263
+ } else {
264
+ sReturn[nReturnPos++] = '0';
265
+ }
266
+
267
+ sReturn[nReturnPos] = '\0';
268
+
269
+ return sReturn;
270
+ }
271
+
272
+ /**
273
+ * Returns a char[13], representing the Code Word to be send.
274
+ *
275
+ * getCodeWordA(char*, char*)
276
+ *
277
+ */
278
+ char* RCSwitch::getCodeWordA(char* sGroup, char* sDevice, boolean bOn) {
279
+ static char sDipSwitches[13];
280
+ int i = 0;
281
+ int j = 0;
282
+
283
+ for (i=0; i < 5; i++) {
284
+ if (sGroup[i] == '0') {
285
+ sDipSwitches[j++] = 'F';
286
+ } else {
287
+ sDipSwitches[j++] = '0';
288
+ }
289
+ }
290
+
291
+ for (i=0; i < 5; i++) {
292
+ if (sDevice[i] == '0') {
293
+ sDipSwitches[j++] = 'F';
294
+ } else {
295
+ sDipSwitches[j++] = '0';
296
+ }
297
+ }
298
+
299
+ if ( bOn ) {
300
+ sDipSwitches[j++] = '0';
301
+ sDipSwitches[j++] = 'F';
302
+ } else {
303
+ sDipSwitches[j++] = 'F';
304
+ sDipSwitches[j++] = '0';
305
+ }
306
+
307
+ sDipSwitches[j] = '\0';
308
+
309
+ return sDipSwitches;
310
+ }
311
+
312
+ /**
313
+ * Like getCodeWord (Type C = Intertechno)
314
+ */
315
+ char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus) {
316
+ static char sReturn[13];
317
+ int nReturnPos = 0;
318
+
319
+ if ( (byte)sFamily < 97 || (byte)sFamily > 112 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
320
+ return '\0';
321
+ }
322
+
323
+ char* sDeviceGroupCode = dec2binWzerofill( (nDevice-1) + (nGroup-1)*4, 4 );
324
+ char familycode[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" };
325
+ for (int i = 0; i<4; i++) {
326
+ sReturn[nReturnPos++] = familycode[ (int)sFamily - 97 ][i];
327
+ }
328
+ for (int i = 0; i<4; i++) {
329
+ sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0');
330
+ }
331
+ sReturn[nReturnPos++] = '0';
332
+ sReturn[nReturnPos++] = 'F';
333
+ sReturn[nReturnPos++] = 'F';
334
+ if (bStatus) {
335
+ sReturn[nReturnPos++] = 'F';
336
+ } else {
337
+ sReturn[nReturnPos++] = '0';
338
+ }
339
+ sReturn[nReturnPos] = '\0';
340
+ return sReturn;
341
+ }
342
+
343
+ /**
344
+ * Decoding for the REV Switch Type
345
+ *
346
+ * Returns a char[13], representing the Tristate to be send.
347
+ * A Code Word consists of 7 address bits and 5 command data bits.
348
+ * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high)
349
+ *
350
+ * +-------------------------------+--------------------------------+-----------------------+
351
+ * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) |
352
+ * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | on=00010 off=00001 |
353
+ * +-------------------------------+--------------------------------+-----------------------+
354
+ *
355
+ * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
356
+ *
357
+ * @param sGroup Name of the switch group (A..D, resp. a..d)
358
+ * @param nDevice Number of the switch itself (1..3)
359
+ * @param bStatus Wether to switch on (true) or off (false)
360
+ *
361
+ * @return char[13]
362
+ */
363
+
364
+ char* RCSwitch::getCodeWordD(char sGroup, int nDevice, boolean bStatus){
365
+ static char sReturn[13];
366
+ int nReturnPos = 0;
367
+
368
+ // Building 4 bits address
369
+ // (Potential problem if dec2binWcharfill not returning correct string)
370
+ char *sGroupCode;
371
+ switch(sGroup){
372
+ case 'a':
373
+ case 'A':
374
+ sGroupCode = dec2binWcharfill(8, 4, 'F'); break;
375
+ case 'b':
376
+ case 'B':
377
+ sGroupCode = dec2binWcharfill(4, 4, 'F'); break;
378
+ case 'c':
379
+ case 'C':
380
+ sGroupCode = dec2binWcharfill(2, 4, 'F'); break;
381
+ case 'd':
382
+ case 'D':
383
+ sGroupCode = dec2binWcharfill(1, 4, 'F'); break;
384
+ default:
385
+ return '\0';
386
+ }
387
+
388
+ for (int i = 0; i<4; i++)
389
+ {
390
+ sReturn[nReturnPos++] = sGroupCode[i];
391
+ }
392
+
393
+
394
+ // Building 3 bits address
395
+ // (Potential problem if dec2binWcharfill not returning correct string)
396
+ char *sDevice;
397
+ switch(nDevice) {
398
+ case 1:
399
+ sDevice = dec2binWcharfill(4, 3, 'F'); break;
400
+ case 2:
401
+ sDevice = dec2binWcharfill(2, 3, 'F'); break;
402
+ case 3:
403
+ sDevice = dec2binWcharfill(1, 3, 'F'); break;
404
+ default:
405
+ return '\0';
406
+ }
407
+
408
+ for (int i = 0; i<3; i++)
409
+ sReturn[nReturnPos++] = sDevice[i];
410
+
411
+ // fill up rest with zeros
412
+ for (int i = 0; i<5; i++)
413
+ sReturn[nReturnPos++] = '0';
414
+
415
+ // encode on or off
416
+ if (bStatus)
417
+ sReturn[10] = '1';
418
+ else
419
+ sReturn[11] = '1';
420
+
421
+ // last position terminate string
422
+ sReturn[12] = '\0';
423
+ return sReturn;
424
+
425
+ }
426
+
427
+ /**
428
+ * @param sCodeWord /^[10FS]*$/ -> see getCodeWord
429
+ */
430
+ void RCSwitch::sendTriState(char* sCodeWord) {
431
+ for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
432
+ int i = 0;
433
+ while (sCodeWord[i] != '\0') {
434
+ switch(sCodeWord[i]) {
435
+ case '0':
436
+ this->sendT0();
437
+ break;
438
+ case 'F':
439
+ this->sendTF();
440
+ break;
441
+ case '1':
442
+ this->sendT1();
443
+ break;
444
+ }
445
+ i++;
446
+ }
447
+ this->sendSync();
448
+ }
449
+ }
450
+
451
+ void RCSwitch::send(unsigned long Code, unsigned int length) {
452
+ this->send( this->dec2binWzerofill(Code, length) );
453
+ }
454
+
455
+ void RCSwitch::send(char* sCodeWord) {
456
+ for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
457
+ int i = 0;
458
+ while (sCodeWord[i] != '\0') {
459
+ switch(sCodeWord[i]) {
460
+ case '0':
461
+ this->send0();
462
+ break;
463
+ case '1':
464
+ this->send1();
465
+ break;
466
+ }
467
+ i++;
468
+ }
469
+ this->sendSync();
470
+ }
471
+ }
472
+
473
+ void RCSwitch::transmit(int nHighPulses, int nLowPulses) {
474
+ #if not defined ( RCSwitchDisableReceiving )
475
+ boolean disabled_Receive = false;
476
+ int nReceiverInterrupt_backup = nReceiverInterrupt;
477
+ #endif
478
+ if (this->nTransmitterPin != -1) {
479
+ #if not defined( RCSwitchDisableReceiving )
480
+ if (this->nReceiverInterrupt != -1) {
481
+ this->disableReceive();
482
+ disabled_Receive = true;
483
+ }
484
+ #endif
485
+ digitalWrite(this->nTransmitterPin, HIGH);
486
+ delayMicroseconds( this->nPulseLength * nHighPulses);
487
+ digitalWrite(this->nTransmitterPin, LOW);
488
+ delayMicroseconds( this->nPulseLength * nLowPulses);
489
+
490
+ #if not defined( RCSwitchDisableReceiving )
491
+ if(disabled_Receive){
492
+ this->enableReceive(nReceiverInterrupt_backup);
493
+ }
494
+ #endif
495
+ }
496
+ }
497
+ /**
498
+ * Sends a "0" Bit
499
+ * _
500
+ * Waveform Protocol 1: | |___
501
+ * _
502
+ * Waveform Protocol 2: | |__
503
+ */
504
+ void RCSwitch::send0() {
505
+ if (this->nProtocol == 1){
506
+ this->transmit(1,3);
507
+ }
508
+ else if (this->nProtocol == 2) {
509
+ this->transmit(1,2);
510
+ }
511
+ else if (this->nProtocol == 3) {
512
+ this->transmit(4,11);
513
+ }
514
+ }
515
+
516
+ /**
517
+ * Sends a "1" Bit
518
+ * ___
519
+ * Waveform Protocol 1: | |_
520
+ * __
521
+ * Waveform Protocol 2: | |_
522
+ */
523
+ void RCSwitch::send1() {
524
+ if (this->nProtocol == 1){
525
+ this->transmit(3,1);
526
+ }
527
+ else if (this->nProtocol == 2) {
528
+ this->transmit(2,1);
529
+ }
530
+ else if (this->nProtocol == 3) {
531
+ this->transmit(9,6);
532
+ }
533
+ }
534
+
535
+
536
+ /**
537
+ * Sends a Tri-State "0" Bit
538
+ * _ _
539
+ * Waveform: | |___| |___
540
+ */
541
+ void RCSwitch::sendT0() {
542
+ this->transmit(1,3);
543
+ this->transmit(1,3);
544
+ }
545
+
546
+ /**
547
+ * Sends a Tri-State "1" Bit
548
+ * ___ ___
549
+ * Waveform: | |_| |_
550
+ */
551
+ void RCSwitch::sendT1() {
552
+ this->transmit(3,1);
553
+ this->transmit(3,1);
554
+ }
555
+
556
+ /**
557
+ * Sends a Tri-State "F" Bit
558
+ * _ ___
559
+ * Waveform: | |___| |_
560
+ */
561
+ void RCSwitch::sendTF() {
562
+ this->transmit(1,3);
563
+ this->transmit(3,1);
564
+ }
565
+
566
+ /**
567
+ * Sends a "Sync" Bit
568
+ * _
569
+ * Waveform Protocol 1: | |_______________________________
570
+ * _
571
+ * Waveform Protocol 2: | |__________
572
+ */
573
+ void RCSwitch::sendSync() {
574
+
575
+ if (this->nProtocol == 1){
576
+ this->transmit(1,31);
577
+ }
578
+ else if (this->nProtocol == 2) {
579
+ this->transmit(1,10);
580
+ }
581
+ else if (this->nProtocol == 3) {
582
+ this->transmit(1,71);
583
+ }
584
+ }
585
+
586
+ #if not defined( RCSwitchDisableReceiving )
587
+ /**
588
+ * Enable receiving data
589
+ */
590
+ void RCSwitch::enableReceive(int interrupt) {
591
+ this->nReceiverInterrupt = interrupt;
592
+ this->enableReceive();
593
+ }
594
+
595
+ void RCSwitch::enableReceive() {
596
+ if (this->nReceiverInterrupt != -1) {
597
+ RCSwitch::nReceivedValue = NULL;
598
+ RCSwitch::nReceivedBitlength = NULL;
599
+ attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
600
+ }
601
+ }
602
+
603
+ /**
604
+ * Disable receiving data
605
+ */
606
+ void RCSwitch::disableReceive() {
607
+ detachInterrupt(this->nReceiverInterrupt);
608
+ this->nReceiverInterrupt = -1;
609
+ }
610
+
611
+ bool RCSwitch::available() {
612
+ return RCSwitch::nReceivedValue != NULL;
613
+ }
614
+
615
+ void RCSwitch::resetAvailable() {
616
+ RCSwitch::nReceivedValue = NULL;
617
+ }
618
+
619
+ unsigned long RCSwitch::getReceivedValue() {
620
+ return RCSwitch::nReceivedValue;
621
+ }
622
+
623
+ unsigned int RCSwitch::getReceivedBitlength() {
624
+ return RCSwitch::nReceivedBitlength;
625
+ }
626
+
627
+ unsigned int RCSwitch::getReceivedDelay() {
628
+ return RCSwitch::nReceivedDelay;
629
+ }
630
+
631
+ unsigned int RCSwitch::getReceivedProtocol() {
632
+ return RCSwitch::nReceivedProtocol;
633
+ }
634
+
635
+ unsigned int* RCSwitch::getReceivedRawdata() {
636
+ return RCSwitch::timings;
637
+ }
638
+
639
+ /**
640
+ *
641
+ */
642
+ bool RCSwitch::receiveProtocol1(unsigned int changeCount){
643
+
644
+ unsigned long code = 0;
645
+ unsigned long delay = RCSwitch::timings[0] / 31;
646
+ unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;
647
+
648
+ for (int i = 1; i<changeCount ; i=i+2) {
649
+
650
+ if (RCSwitch::timings[i] > delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*3-delayTolerance && RCSwitch::timings[i+1] < delay*3+delayTolerance) {
651
+ code = code << 1;
652
+ } else if (RCSwitch::timings[i] > delay*3-delayTolerance && RCSwitch::timings[i] < delay*3+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) {
653
+ code+=1;
654
+ code = code << 1;
655
+ } else {
656
+ // Failed
657
+ i = changeCount;
658
+ code = 0;
659
+ }
660
+ }
661
+ code = code >> 1;
662
+ if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise
663
+ RCSwitch::nReceivedValue = code;
664
+ RCSwitch::nReceivedBitlength = changeCount / 2;
665
+ RCSwitch::nReceivedDelay = delay;
666
+ RCSwitch::nReceivedProtocol = 1;
667
+ }
668
+
669
+ if (code == 0){
670
+ return false;
671
+ }else if (code != 0){
672
+ return true;
673
+ }
674
+
675
+
676
+ }
677
+
678
+ bool RCSwitch::receiveProtocol2(unsigned int changeCount){
679
+
680
+ unsigned long code = 0;
681
+ unsigned long delay = RCSwitch::timings[0] / 10;
682
+ unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;
683
+
684
+ for (int i = 1; i<changeCount ; i=i+2) {
685
+
686
+ if (RCSwitch::timings[i] > delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*2-delayTolerance && RCSwitch::timings[i+1] < delay*2+delayTolerance) {
687
+ code = code << 1;
688
+ } else if (RCSwitch::timings[i] > delay*2-delayTolerance && RCSwitch::timings[i] < delay*2+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) {
689
+ code+=1;
690
+ code = code << 1;
691
+ } else {
692
+ // Failed
693
+ i = changeCount;
694
+ code = 0;
695
+ }
696
+ }
697
+ code = code >> 1;
698
+ if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise
699
+ RCSwitch::nReceivedValue = code;
700
+ RCSwitch::nReceivedBitlength = changeCount / 2;
701
+ RCSwitch::nReceivedDelay = delay;
702
+ RCSwitch::nReceivedProtocol = 2;
703
+ }
704
+
705
+ if (code == 0){
706
+ return false;
707
+ }else if (code != 0){
708
+ return true;
709
+ }
710
+
711
+ }
712
+
713
+ /** Protocol 3 is used by BL35P02.
714
+ *
715
+ */
716
+ bool RCSwitch::receiveProtocol3(unsigned int changeCount){
717
+
718
+ unsigned long code = 0;
719
+ unsigned long delay = RCSwitch::timings[0] / PROTOCOL3_SYNC_FACTOR;
720
+ unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;
721
+
722
+ for (int i = 1; i<changeCount ; i=i+2) {
723
+
724
+ if (RCSwitch::timings[i] > delay*PROTOCOL3_0_HIGH_CYCLES - delayTolerance
725
+ && RCSwitch::timings[i] < delay*PROTOCOL3_0_HIGH_CYCLES + delayTolerance
726
+ && RCSwitch::timings[i+1] > delay*PROTOCOL3_0_LOW_CYCLES - delayTolerance
727
+ && RCSwitch::timings[i+1] < delay*PROTOCOL3_0_LOW_CYCLES + delayTolerance) {
728
+ code = code << 1;
729
+ } else if (RCSwitch::timings[i] > delay*PROTOCOL3_1_HIGH_CYCLES - delayTolerance
730
+ && RCSwitch::timings[i] < delay*PROTOCOL3_1_HIGH_CYCLES + delayTolerance
731
+ && RCSwitch::timings[i+1] > delay*PROTOCOL3_1_LOW_CYCLES - delayTolerance
732
+ && RCSwitch::timings[i+1] < delay*PROTOCOL3_1_LOW_CYCLES + delayTolerance) {
733
+ code+=1;
734
+ code = code << 1;
735
+ } else {
736
+ // Failed
737
+ i = changeCount;
738
+ code = 0;
739
+ }
740
+ }
741
+ code = code >> 1;
742
+ if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise
743
+ RCSwitch::nReceivedValue = code;
744
+ RCSwitch::nReceivedBitlength = changeCount / 2;
745
+ RCSwitch::nReceivedDelay = delay;
746
+ RCSwitch::nReceivedProtocol = 3;
747
+ }
748
+
749
+ if (code == 0){
750
+ return false;
751
+ }else if (code != 0){
752
+ return true;
753
+ }
754
+ }
755
+
756
+ void RCSwitch::handleInterrupt() {
757
+
758
+ static unsigned int duration;
759
+ static unsigned int changeCount;
760
+ static unsigned long lastTime;
761
+ static unsigned int repeatCount;
762
+
763
+
764
+ long time = micros();
765
+ duration = time - lastTime;
766
+
767
+ if (duration > 5000 && duration > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) {
768
+ repeatCount++;
769
+ changeCount--;
770
+ if (repeatCount == 2) {
771
+ if (receiveProtocol1(changeCount) == false){
772
+ if (receiveProtocol2(changeCount) == false){
773
+ if (receiveProtocol3(changeCount) == false){
774
+ //failed
775
+ }
776
+ }
777
+ }
778
+ repeatCount = 0;
779
+ }
780
+ changeCount = 0;
781
+ } else if (duration > 5000) {
782
+ changeCount = 0;
783
+ }
784
+
785
+ if (changeCount >= RCSWITCH_MAX_CHANGES) {
786
+ changeCount = 0;
787
+ repeatCount = 0;
788
+ }
789
+ RCSwitch::timings[changeCount++] = duration;
790
+ lastTime = time;
791
+ }
792
+ #endif
793
+
794
+ /**
795
+ * Turns a decimal value to its binary representation
796
+ */
797
+ char* RCSwitch::dec2binWzerofill(unsigned long Dec, unsigned int bitLength){
798
+ return dec2binWcharfill(Dec, bitLength, '0');
799
+ }
800
+
801
+ char* RCSwitch::dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill){
802
+ static char bin[64];
803
+ unsigned int i=0;
804
+
805
+ while (Dec > 0) {
806
+ bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
807
+ Dec = Dec >> 1;
808
+ }
809
+
810
+ for (unsigned int j = 0; j< bitLength; j++) {
811
+ if (j >= bitLength - i) {
812
+ bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
813
+ }else {
814
+ bin[j] = fill;
815
+ }
816
+ }
817
+ bin[bitLength] = '\0';
818
+
819
+ return bin;
820
+ }
821
+
822
+
823
+