-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWebSocketTelemetry.ino
More file actions
145 lines (117 loc) · 5.44 KB
/
Copy pathWebSocketTelemetry.ino
File metadata and controls
145 lines (117 loc) · 5.44 KB
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
/**
* WebSocketTelemetry - Real-time telemetry over WebSocket (Arduino)
*
* The Arduino counterpart to examples/esp32_websocket. Streams metrics to your
* Plexus dashboard over a persistent WebSocket connection (<100ms latency)
* instead of one-shot HTTPS POSTs.
*
* Requires:
* - The "WebSockets" library by Markus Sattler (Links2004) — install via
* Library Manager (Arduino IDE) or lib_deps (PlatformIO).
* - WebSocket support enabled at compile time: this transport is OFF by
* default on Arduino, so build with the flag:
* Arduino IDE : add -DPLEXUS_ENABLE_WEBSOCKET=1 to your build flags
* PlatformIO : build_flags = -DPLEXUS_ENABLE_WEBSOCKET=1
*
* Hardware: ESP32 (recommended) or ESP8266 with WiFi.
*
* Setup:
* 1. Set WIFI_SSID / WIFI_PASSWORD below
* 2. Get an API key from https://app.plexus.company → Add Device
* 3. Set PLEXUS_API_KEY, SOURCE_ID, and ORG_ID (your org, e.g. "org_abc123")
* 4. Upload and open Serial Monitor at 115200 baud
* 5. Watch data appear live in your Plexus dashboard
*/
#if defined(ESP32)
#include <WiFi.h>
#include <time.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <time.h>
#endif
#include "plexus.hpp"
#if !PLEXUS_ENABLE_WEBSOCKET
#error "Enable the WebSocket transport: build with -DPLEXUS_ENABLE_WEBSOCKET=1 and install the WebSockets library."
#endif
// ── Configuration ──────────────────────────────────────────────────────────
const char* WIFI_SSID = "YourWiFiSSID";
const char* WIFI_PASSWORD = "YourWiFiPassword";
const char* PLEXUS_API_KEY = "plx_your_api_key_here";
const char* SOURCE_ID = "esp32-ws";
// org_id is OPTIONAL: the gateway resolves your org from the API key. Only set
// it (and uncomment the plexus_set_org_id call below) for a self-hosted gateway
// that requires explicit org routing.
// const char* ORG_ID = "org_your_org_id";
// ── Globals ────────────────────────────────────────────────────────────────
PlexusClient plexus(PLEXUS_API_KEY, SOURCE_ID);
unsigned long lastReadMs = 0;
const unsigned long READ_INTERVAL_MS = 1000;
// ── NTP time sync (timestamps require a real clock) ──────────────────────────
static void syncTime() {
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
Serial.print("Syncing time");
time_t now = time(nullptr);
while (now < 1700000000) { // wait until clock is past 2023
delay(250);
Serial.print(".");
now = time(nullptr);
}
Serial.println(" done");
}
// ── Setup ──────────────────────────────────────────────────────────────────
void setup() {
Serial.begin(115200);
delay(100);
Serial.println("\n--- Plexus WebSocket Telemetry ---");
// Connect to WiFi
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.printf("\nConnected! IP: %s\n", WiFi.localIP().toString().c_str());
// NTP — needed for accurate metric timestamps
syncTime();
if (!plexus.isValid()) {
Serial.println("ERROR: Failed to initialize Plexus client");
return;
}
Serial.printf("Plexus SDK v%s ready\n", plexus_version());
plexus_client_t* px = plexus.handle();
// Responsive flushing for a live dashboard
plexus_set_flush_interval(px, 500);
// Dual transport: WebSocket for real-time + HTTP for persistence &
// first-time device creation. Keep http_persist on (mirrors esp32_websocket).
plexus_set_http_persist(px, true);
// Self-hosted gateways only — explicit org routing:
// plexus_set_org_id(px, ORG_ID);
// Open the WebSocket. Non-blocking — plexus.tick() drives the handshake.
plexus_err_t wsErr = plexus_ws_connect(px);
if (wsErr != PLEXUS_OK) {
Serial.printf("WS connect failed: %s — will retry / fall back to HTTP\n",
plexus_strerror(wsErr));
}
}
// ── Loop ───────────────────────────────────────────────────────────────────
void loop() {
unsigned long now = millis();
if (now - lastReadMs >= READ_INTERVAL_MS) {
lastReadMs = now;
// Replace with your actual sensor reading
float temperature = 20.0 + random(0, 100) / 10.0;
float humidity = 40.0 + random(0, 200) / 10.0;
plexus.send("temperature", temperature);
plexus.send("humidity", humidity);
// Surface WS connection state for diagnostics
plexus_ws_state_t state = plexus_ws_state(plexus.handle());
plexus.send("ws_connected", state == PLEXUS_WS_CONNECTED ? 1.0 : 0.0);
}
// tick() drives auto-flush AND the WebSocket state machine. On Arduino it
// also pumps the synchronous WebSocket client, so call it frequently.
plexus_err_t err = plexus.tick();
if (err != PLEXUS_OK && err != PLEXUS_ERR_NO_DATA) {
Serial.printf("Error: %s\n", plexus_strerror(err));
}
delay(20);
}