-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathBCH_Watchdog.ino
284 lines (235 loc) · 9.02 KB
/
BCH_Watchdog.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
/**************************************************************************************************/
// BCH Watchdog
// Description:
// Bot that monitorizes your addresses and alerts you if a movement of funds is detected.
// Disclaimer: This is beta software!
// Created on: 20 may 2020
// Last modified date: 20 may 2020
// Version: 0.1
/**************************************************************************************************/
/* Libraries */
#include <string.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <ArduinoJson.h> //Use V6
#include <utlgbotlib.h>
/**************************************************************************************************/
// SHA1 Fingerprint for Bitcoin.com URL.
const char fingerprint[] PROGMEM= "29 0D E5 3A 2A FA 7C 48 FA CB 4D 3D 97 02 2A 27 0F 31 20 0D";
String serverName = "http://rest.bitcoin.com/v2/address/details/";
//Put here your address or addresses to track them
String addresses[] = {"bitcoincash:qzftvp2d0ketld8uc2y9fryg45e4ll74my9yyxx9kg", "bitcoincash:qzs02v05l7qs5s24srqju498qu55dwuj0cx5ehjm2c", "bitcoincash:ppm39e48x3sjynxlqmhy3pcnhl90spk34ssje8jg6x"};
// WiFi Parameters
#define WIFI_SSID "YOUR_SSID"
#define WIFI_PASS "YOUR_PASSWORD"
#define MAX_CONN_FAIL 50
#define MAX_LENGTH_WIFI_SSID 31
#define MAX_LENGTH_WIFI_PASS 63
// Telegram Bot Token (Get from Botfather)
#define TLG_TOKEN "XXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXX"
// Enable Bot debug level (0 - None; 1 - Bot Level; 2 - Bot+HTTPS Level)
#define DEBUG_LEVEL_UTLGBOT 0
ESP8266WiFiMulti WiFiMulti;
/**************************************************************************************************/
/* Functions Prototypes */
void wifi_init_stat(void);
bool wifi_handle_connection(void);
/**************************************************************************************************/
/* Globals */
// Create Bot object
uTLGBot Bot(TLG_TOKEN);
DynamicJsonDocument myArray(512); //Here will be stored you addresses with each balance
char* chat_ID = NULL;
/**************************************************************************************************/
/* Main Function */
void setup(void)
{
// Enable Bot debug
Bot.set_debug(DEBUG_LEVEL_UTLGBOT);
// Initialize Serial
Serial.begin(115200);
// Initialize WiFi station connection
wifi_init_stat();
// Wait WiFi connection
Serial.println("Waiting for WiFi connection.");
while(!wifi_handle_connection())
{
Serial.println(".");
delay(1000);
}
StaticJsonDocument<200> doc;
StaticJsonDocument<64> filter;
filter["balanceSat"] = true;
WiFiClient client;
HTTPClient http;
//Here, we will fill myArray with the data: addresses and bavlances
Serial.print("[HTTPS] begin...\n");
for (byte idx = 0; idx < sizeof(addresses) / sizeof(addresses[0]); idx++){
if (http.begin(client, serverName + addresses[idx])) { // HTTPS
Serial.print("[HTTPS] GET...\n");
Serial.println(serverName + addresses[idx]);
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
long balance = doc["balanceSat"];
Serial.print("Balance: ");
Serial.println(balance);
myArray[addresses[idx]] = balance;
}
} else {
Serial.printf("[HTTPS] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
else {
Serial.printf("[HTTPS] Unable to connect\n");
}
}
//Display the data in a fancy mode
serializeJsonPretty(myArray, Serial);
}
void loop()
{
// Check if WiFi is connected
if(!wifi_handle_connection())
{
// Wait 100ms and check again
delay(100);
return;
}
StaticJsonDocument<512> doc;
StaticJsonDocument<64> filter;
filter["balanceSat"] = true;
filter["unconfirmedBalanceSat"] = true;
//If the ID of the Telegram chat is not available, just send any message to the bot
if (chat_ID == NULL) {
Bot.getMe();
Bot.getUpdates();
while(Bot.received_msg.chat.id[0] == '\0'){
Serial.println("Send a message to start the watchdog!");
delay(5000);
Bot.getUpdates();
}
chat_ID = Bot.received_msg.chat.id;
Bot.disconnect();
Serial.print("Chat ID is ");
Serial.println(chat_ID);
}
WiFiClient client;
HTTPClient http;
//It's time to compare the current balance with the balance registered for each address
JsonObject obj = myArray.as<JsonObject>();
for (JsonPair p : obj){
if (http.begin(client, serverName + p.key().c_str())); { // HTTPS
Serial.print("[HTTPS] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
// Test if parsing succeeds.
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
delay(1000);
return;
} else {
serializeJsonPretty(doc, Serial);
long balance = doc["balanceSat"];
long unconfirmed_balance = doc["unconfirmedBalanceSat"];
long current_balance = balance + unconfirmed_balance;
Serial.print("Balance: ");
Serial.println(balance);
Serial.print("Current balance: ");
Serial.println(current_balance);
Serial.print("Registered balance: ");
Serial.println(p.value().as<long>());
if (p.value().as<long>() != current_balance){
long funds = balance - p.value().as<long>();
char URL[128];
strcpy(URL, "https://explorer.bitcoin.com/bch/address/");
strcat(URL, p.key().c_str());
Bot.getMe();
Bot.getUpdates();
Bot.sendMessage(Bot.received_msg.chat.id, "ALERT! Movement of funds detected");
Bot.sendMessage(Bot.received_msg.chat.id, "Check it out now!");
Bot.sendMessage(Bot.received_msg.chat.id, URL);
myArray[p.key()] = current_balance;
yield();
Bot.disconnect();
}
}
}
} else {
Serial.printf("[HTTPS] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
delay(2000);
}
}
delay(30000); //Refresh the balance every 30 seconds
}
/**************************************************************************************************/
/* Functions */
// Init WiFi interface
void wifi_init_stat(void)
{
Serial.println("Initializing TCP-IP adapter...");
Serial.print("Wifi connecting to SSID: ");
Serial.println(WIFI_SSID);
WiFi.mode(WIFI_STA);
WiFiMulti.addAP(WIFI_SSID, WIFI_PASS);
Serial.println("TCP-IP adapter successfuly initialized.");
}
/**************************************************************************************************/
/* WiFi Change Event Handler */
bool wifi_handle_connection(void)
{
static bool wifi_connected = false;
// Device is not connected
if(WiFiMulti.run() != WL_CONNECTED)
{
// Was connected
if(wifi_connected)
{
Serial.println("WiFi disconnected.");
wifi_connected = false;
}
return false;
}
// Device connected
else
{
// Wasn't connected
if(!wifi_connected)
{
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
wifi_connected = true;
}
return true;
}
}
/**************************************************************************************************/