-
Notifications
You must be signed in to change notification settings - Fork 5
/
ArduinoTHSensor.cpp
163 lines (140 loc) · 4.62 KB
/
ArduinoTHSensor.cpp
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
// Copyright 2014-2015 the project authors as listed in the AUTHORS file.
// All rights reserved. Use of this source code is governed by the
// license that can be found in the LICENSE file.
#include "ArduinoTHSensor.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
#define DEVICE_ID 7
#define DEVICE_NAME "ArduinoTHSensor"
#define MIN_PULSE_LENGTH 100
#define SYNC_DURATION_MIN 700
#define SYNC_DURATION_MAX 1200
#define EXPECTED_MESSAGE_BITS 32
#define ONE_PULSE_MIN_LENGTH 450
ArduinoTHSensor::ArduinoTHSensor() : Device() {
syncCount = 0;
syncFound = false;
bitCount = 0;
code = 0;
this->houseCode = houseCode;
memset(durations,0,sizeof(int)*BITS_IN_MESSAGE);
pulseCount = 0;
}
int ArduinoTHSensor::deviceType(void) {
return DEVICE_ID;
};
char* ArduinoTHSensor::deviceName(void) {
return (char*) DEVICE_NAME;
};
void ArduinoTHSensor::processPulse(long duration) {
// any pulse less than MIN_PULSE_LENGTH means we have noise so we are not in the middle
// of a transmision
if (duration < MIN_PULSE_LENGTH) {
syncFound = false;
syncCount = 0;
return;
}
// capture the next bit and decode if we are at the end of the transmission
if (syncFound) {
pulseCount++;
if (0 != (pulseCount%2)) {
// we only look at every other pulse which is the one at the high level
return;
}
// we are processing a message record the duration of the pulse which
// we will use to build the overall message
durations[bitCount] = duration;
bitCount++;
// ok we have all 32 bits that we expect
if (BITS_IN_MESSAGE == bitCount) {
for (int i=0; i < BITS_IN_MESSAGE; i++) {
code = code << 1;
if (ONE_PULSE_MIN_LENGTH > durations[i]) {
code = code | 0x1;
}
}
if (validateChecksum(code)) {
Message* newMessage = queue->getFreeMessage();
if (NULL != newMessage) {
memset(newMessage, 0, sizeof(Message));
newMessage->device = (void*) this;
newMessage->timestamp = time(NULL);
newMessage->code = code;
queue->enqueueMessage(newMessage);
} else {
// no messages available so just drop this value
}
}
// ok wait for the next message
syncFound = false;
}
} else {
if ((duration > SYNC_DURATION_MIN) && (duration < SYNC_DURATION_MAX)) {
syncCount++;
if (syncCount == 10 ) {
code = 0;
syncFound = true;
syncCount = 0;
bitCount = 0;
pulseCount = 0;
}
} else {
syncCount = 0;
}
}
};
void ArduinoTHSensor::decodeMessage(Message* message) {
char* bytes = (char*) &message->code;
message->type = 1;
sprintf(message->text, "%ld, %x - temp: %d,humidity: %d",
message->timestamp,
message->code,
(int) bytes[1] - 128,
(int) bytes[2] );
};
void ArduinoTHSensor::publishTopic(Message* message, char* buffer, int maxLength) {
// will not be called but still has to be implemented
// until we remove and update the rest of the devices
}
int ArduinoTHSensor::numMessages(void) {
return 2;
}
void ArduinoTHSensor::publishTopic(int messageNum, Message* message, char* buffer, int maxLength) {
char* bytes = (char*) &message->code;
if (messageNum == 0) {
snprintf(buffer, maxLength, "house/arduinoTHSensor/%x/temp", bytes[3]);
} else {
snprintf(buffer, maxLength, "house/arduinoTHSensor/%x/humidity", bytes[3]);
}
}
void ArduinoTHSensor::getMessageText(int messageNum, Message* message, char* buffer, int maxLength) {
char* bytes = (char*) &message->code;
if (messageNum == 0) {
sprintf(buffer, "%ld, %x - temp: %d",
message->timestamp,
message->code,
(int) bytes[1] - 128);
} else {
sprintf(buffer, "%ld, %x - humidity: %d",
message->timestamp,
message->code,
(int) bytes[2]);
}
}
// to calculate the checksum first reverse the nibbles in each byte
// including the checksum
// then add the 3 message bytes together and add 0x77 to get the
// expected checksum which is in byte 0
bool ArduinoTHSensor::validateChecksum(int code) {
char* bytes = (char*) & code;
char calcChecksum = 0x77;
char checksum = ((bytes[0] >> 4) & 0x0F) + ((bytes[0] & 0x0F) << 4);
for (int i = 1;i<4;i++) {
calcChecksum += ((bytes[i] >> 4) & 0x0F) + ((bytes[i] & 0x0F) << 4);
}
if (calcChecksum == checksum) {
return true;
}
return false;
}