-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathScubyD_LWRF_Macro.ino
285 lines (254 loc) · 7.74 KB
/
ScubyD_LWRF_Macro.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
// Last Updated by David Walker, 23 Nov 2013
//
// This xxxxxxxxx is based on the late-Nov 2013 version of
// RobertTidey's LWRF library.
//
// Nano = Board: Nano w/ Mega328 + Programmer: AVRISP mkII
// Mini = Pro Mini 5V 16Mhz w/ Mega328
#include <Tidey3_LwTx.h>
#include <Tidey3_LwRx.h>
#include <EEPROM.h>
char rxReturnHome1[11] = "0001GGGGG7"; // Mood On (0/1)
char rxReturnHome2[11] = "xx0xGGGGG7"; // Black Remote A1
char txReturnHome[1][11] = {
"82F2GGGGG1", //Rm2 All On (all networks on)
};
long txReturnHomeWaits[0];
int txNumReturnHome = 1;
char rxLeaveHouse1[11] = "4000GGGGG7"; // Mood Off (0/1)
char rxLeaveHouse2[11] = "xx2xGGGGG7"; // Black Remote A3
char txLeaveHouse[14][11] = {
"0041GGGGG0", //Rm1D5 On (front porch light)
"0051GGGGG0", //Rm1D6 On (front garage light)
"C000GGGGG6", //Rm7 AllOff (upstairs lights)
"4000GGGGG3", //Rm4D1 Off (TV unit off)
"4010GGGGG3", //Rm4D2 Off (Airplay off)
"4040GGGGG3", //Rm4D5 Off (iPhone charger off)
"C000GGGGG7", //Rm8 AllOff (unused sockets)
"C000GGGGG2", //Rm3 AllOff (living lights)
"4020GGGGG1", //Rm2D3 Off (extra network off)
"C000GGGGG5", //Rm6 AllOff (misc)
"WAIT ",
"C000GGGGG4", //Rm5 AllOff (downstairs lights)
"WAIT ",
"C000GGGGG0", //Rm1 AllOff (outside)
};
long txLeaveHouseWaits[2] = {10000, 90000};
int txNumLeaveHouse = 14;
char rxBedtime[11] = "84F2GGGGG7"; // Mood 3
char txBedtime[10][11] = {
"82F2GGGGG6", //Rm7 Mood1 (set upstairs lights)
"0041GGGGG3", //Rm4D5 On (iPhone charger)
"4000GGGGG3", //Rm4D1 Off (TV unit off)
"4010GGGGG3", //Rm4D2 Off (Airplay off)
"C000GGGGG0", //Rm1 AllOff (outside)
"C000GGGGG7", //Rm8 AllOff (unused sockets)
"C000GGGGG5", //Rm6 AllOff (misc)
"C000GGGGG2", //Rm3 AllOff (living lights)
"WAIT ",
"C000GGGGG4", //Rm5 AllOff (downstairs lights)
};
long txBedtimeWaits[1] = {10000};
int txNumBedtime = 10;
char rxAllOff1[11] = "C0F0GGGGG7"; // Mood All Off
char rxAllOff2[11] = "xx3xGGGGG7"; // Black Remote A4
char txAllOff[][11] = {
"C000GGGGG0", //Rm1 AllOff (outside)
"C000GGGGG3", //Rm4 AllOff (entertainment)
"C000GGGGG5", //Rm6 AllOff (misc)
"C000GGGGG7", //Rm8 AllOff (unused)
"C000GGGGG6", //Rm7 AllOff (lightsup)
"C000GGGGG2", //Rm3 AllOff (livinglights)
"C000GGGGG4", //Rm5 AllOff (lightsdown)
"C000GGGGG1", //Rm2 AllOff (networks)
};
long txAllOffWaits[0];
int txNumAllOff = 8;
// Setup variables for message queue
// NOTE: Queue is not emptied after sending, but earliestExec and numInQueue
// determine whether there is anything to be sent
char msgStrQueue[25][11]; // Queue of ASCII commands waiting to be sent
long earliestSend[25]; // Aligns to msgStrQueue, gives earliest time to send
boolean waitingToSend[25]; // Aligns to msgStrQueue, true if msg is pending
int numInQueue = 0; // Lists num pending messages in queue
long nextTxAllowed = 0; // Millis when next Tx allowed
long minGap = 1000; // Min gap between Tx messages
char waitStr[5] = "WAIT";
void setup() {
// set up with rx into pin 2
lwrx_setup(2);
// setup tx on pin 3
lwtx_setup(3, 10, 0, 140);
Serial.begin(9600);
Serial.println("Ready!");
}
void loop() {
// Define variables
byte rxmsg[10];
byte txmsg[10];
byte len = 10;
char rxmsgstr[10];
char txmsgstr[10];
// Receive messages and do immediate response
if (lwrx_message()) {
// Get the received message
lwrx_getmessage(rxmsg, len);
// Convert the message into a char string
msgToStr(rxmsgstr, rxmsg);
Serial.print("Received: ");
Serial.println(rxmsgstr);
// Check for triggers
if ((isMatch(rxmsgstr, rxLeaveHouse1, 10)) || (isMatch(rxmsgstr, rxLeaveHouse2, 10)))
{
Serial.println("Received: Leaving Home");
addToQueue(txLeaveHouse, txLeaveHouseWaits, txNumLeaveHouse);
}
else if ((isMatch(rxmsgstr, rxReturnHome1, 10)) || (isMatch(rxmsgstr, rxReturnHome2, 10)))
{
Serial.println("Received: Returning Home");
addToQueue(txReturnHome, txReturnHomeWaits, txNumReturnHome);
}
else if (isMatch(rxmsgstr, rxBedtime, 10))
{
Serial.println("Received: Bed Time");
addToQueue(txBedtime, txBedtimeWaits, txNumBedtime);
}
else if ((isMatch(rxmsgstr, rxAllOff1, 10)) || (isMatch(rxmsgstr, rxAllOff2, 10)))
{
Serial.println("Received: All Off");
addToQueue(txAllOff, txAllOffWaits, txNumAllOff);
}
}
// Do queued responses
if (nextTxAllowed <= millis())
{
if (numInQueue > 0)
{
for (int i=0; i<25; i++)
{
if (waitingToSend[i]==true){
if (earliestSend[i] <= millis())
{
strToMsg(txmsg, msgStrQueue[i]);
lwtx_send(txmsg);
Serial.print("Sent: ");
Serial.println(msgStrQueue[i]);
nextTxAllowed = millis() + minGap;
numInQueue--;
waitingToSend[i] = false;
earliestSend[i] = 0;
msgStrQueue[i][0] = ' ';
break;
}
}
}
}
}
}
// Work through the txList, adding msgs to the queue as needed,
// including any delays requested
void addToQueue(char txList[][11], long txListWaits[], int listLen)
{
// Note the current time as earliest
long earliestTime = millis();
// Keep track of whether any wait commands have been encountered
int waitNum = 0;
// Work through the txList in order
for (int iList=0; iList<listLen; iList++)
{
Serial.print(" Queuing message: ");
Serial.println(txList[iList]);
// If the entry is "WAIT", then get the next entry from txListWaits
if (isMatch(txList[iList], waitStr, 4))
{
earliestTime += txListWaits[waitNum];
waitNum++;
}
// If isn't a wait command, then add it to the queue
else
{
// Look through the queue to find the first empty gap
for (int i=0; i<25; i++)
{
// Need an entry that isn't currently pending
if (!waitingToSend[i])
{
// Add the txList entry to the queue
for (int j=0; j<10; j++)
{
msgStrQueue[i][j] = txList[iList][j];
}
// Save the earliest send time
earliestSend[i] = earliestTime;
// Flag as waiting to send
waitingToSend[i] = true;
// Increment the number in queue
numInQueue++;
// Finished, so drop out of the for loop
break;
}
}
}
}
}
// Compare two msg strings, return false if any
// character doesn't match (only first [len])
// 'x' is a wildcard
boolean isMatch(char *msg1, char *msg2, int len)
{
for (int i=0; i<len; i++)
{
if ((msg1[i] != msg2[i]) && (msg1[i] != 'x') && (msg2[i] != 'x'))
{
return false;
}
}
return true;
}
// Converts byte msg to char string
void msgToStr(char msgstr[10], byte *msg)
{
for(int i=0; i<10; i++)
{
msgstr[i] = getHexChar(msg[i]);
}
}
// Converts char string to byte msg
void strToMsg(byte msg[10], char* msgstr)
{
for (int i=0; i<10; i++)
{
msg[i] = getHexValue(msgstr[i]);
}
}
// Convert ASCII hex text to 0-15 integer values
// (for String to Message translation)
int getHexValue(char ascii)
{
if (ascii > 0x39) ascii -= 7;
return (ascii & 0xf);
}
// Convert 0-15 integer values to ASCII hex text
// (for Message to String translation)
char getHexChar(int hex)
{
switch (hex)
{
case 0: return '0'; break;
case 1: return '1'; break;
case 2: return '2'; break;
case 3: return '3'; break;
case 4: return '4'; break;
case 5: return '5'; break;
case 6: return '6'; break;
case 7: return '7'; break;
case 8: return '8'; break;
case 9: return '9'; break;
case 10: return 'A'; break;
case 11: return 'B'; break;
case 12: return 'C'; break;
case 13: return 'D'; break;
case 14: return 'E'; break;
case 15: return 'F'; break;
}
}