Skip to content

Commit 7c068c7

Browse files
committed
Add demo using javascript
1 parent 50dac00 commit 7c068c7

File tree

3 files changed

+1804
-0
lines changed

3 files changed

+1804
-0
lines changed

websocket/debug_javascript.h

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
#include <Arduino.h>
2+
#include <WiFi.h>
3+
#include <FS.h>
4+
#include <SD_MMC.h> // For SD card access
5+
#include <stdio.h>
6+
7+
// Define SD card pins (adjust these pins according to your hardware setup)
8+
#define PIN_SD_CMD 13 // CMD
9+
#define PIN_SD_CLK 11 // CLK
10+
#define PIN_SD_D0 12 // Data0
11+
12+
// Include elk.h with extern "C" to ensure correct linkage
13+
extern "C" {
14+
#include "elk.h"
15+
}
16+
17+
// Ensure that 'elk.c' is included in your project and being compiled.
18+
19+
// Elk JavaScript engine instance
20+
struct js *js;
21+
22+
// Native function to print to the Serial Monitor
23+
static jsval_t js_print(struct js *js, jsval_t *args, int nargs) {
24+
for (int i = 0; i < nargs; i++) {
25+
const char *str = js_str(js, args[i]);
26+
if (str != NULL) {
27+
Serial.println(str);
28+
} else {
29+
Serial.println("print: argument is not a string");
30+
}
31+
}
32+
return js_mknull();
33+
}
34+
35+
// Native function to connect to Wi-Fi
36+
static jsval_t js_wifi_connect(struct js *js, jsval_t *args, int nargs) {
37+
if (nargs != 2) {
38+
Serial.println("wifi_connect: expected 2 arguments");
39+
return js_mkfalse();
40+
}
41+
const char *ssid_with_quotes = js_str(js, args[0]);
42+
const char *password_with_quotes = js_str(js, args[1]);
43+
if (ssid_with_quotes == NULL || password_with_quotes == NULL) {
44+
Serial.println("wifi_connect: arguments must be strings");
45+
return js_mkfalse();
46+
}
47+
48+
// Strip the surrounding quotes from SSID and password
49+
String ssid = String(ssid_with_quotes);
50+
if (ssid.startsWith("\"") && ssid.endsWith("\"")) {
51+
ssid = ssid.substring(1, ssid.length() - 1);
52+
}
53+
54+
String password = String(password_with_quotes);
55+
if (password.startsWith("\"") && password.endsWith("\"")) {
56+
password = password.substring(1, password.length() - 1);
57+
}
58+
59+
Serial.printf("Connecting to Wi-Fi SSID: %s\n", ssid.c_str());
60+
WiFi.begin(ssid.c_str(), password.c_str());
61+
62+
int max_attempts = 20;
63+
while (WiFi.status() != WL_CONNECTED && max_attempts > 0) {
64+
delay(500);
65+
Serial.print(".");
66+
max_attempts--;
67+
}
68+
Serial.println();
69+
70+
if (WiFi.status() == WL_CONNECTED) {
71+
Serial.println("Wi-Fi connected");
72+
return js_mktrue();
73+
} else {
74+
Serial.println("Failed to connect to Wi-Fi");
75+
return js_mkfalse();
76+
}
77+
}
78+
79+
// Native function to check Wi-Fi connection status
80+
static jsval_t js_wifi_status(struct js *js, jsval_t *args, int nargs) {
81+
return (WiFi.status() == WL_CONNECTED) ? js_mktrue() : js_mkfalse();
82+
}
83+
84+
// Native function to delay execution
85+
static jsval_t js_delay(struct js *js, jsval_t *args, int nargs) {
86+
if (nargs != 1) {
87+
Serial.println("delay: expected 1 argument");
88+
return js_mknull();
89+
}
90+
double ms = js_getnum(args[0]);
91+
delay((unsigned long)ms);
92+
return js_mknull();
93+
}
94+
95+
// Native function to read a file from the SD card
96+
static jsval_t js_sd_read_file(struct js *js, jsval_t *args, int nargs) {
97+
if (nargs != 1) {
98+
Serial.println("sd_read_file: expected 1 argument");
99+
return js_mknull();
100+
}
101+
const char *path = js_str(js, args[0]);
102+
if (path == NULL) {
103+
Serial.println("sd_read_file: argument is not a string");
104+
return js_mknull();
105+
}
106+
107+
File file = SD_MMC.open(path);
108+
if (!file) {
109+
Serial.println("Failed to open file");
110+
return js_mknull();
111+
}
112+
113+
String content = file.readString();
114+
file.close();
115+
116+
return js_mkstr(js, content.c_str(), content.length());
117+
}
118+
119+
// Native function to write data to a file on the SD card
120+
static jsval_t js_sd_write_file(struct js *js, jsval_t *args, int nargs) {
121+
if (nargs != 2) {
122+
Serial.println("sd_write_file: expected 2 arguments");
123+
return js_mkfalse();
124+
}
125+
const char *path = js_str(js, args[0]);
126+
const char *data = js_str(js, args[1]);
127+
if (path == NULL || data == NULL) {
128+
Serial.println("sd_write_file: arguments must be strings");
129+
return js_mkfalse();
130+
}
131+
132+
File file = SD_MMC.open(path, FILE_WRITE);
133+
if (!file) {
134+
Serial.println("Failed to open file for writing");
135+
return js_mkfalse();
136+
}
137+
138+
file.write((const uint8_t *)data, strlen(data));
139+
file.close();
140+
141+
return js_mktrue();
142+
}
143+
144+
// Native function to list files in a directory on the SD card
145+
static jsval_t js_sd_list_dir(struct js *js, jsval_t *args, int nargs) {
146+
if (nargs != 1) {
147+
Serial.println("sd_list_dir: expected 1 argument");
148+
return js_mknull();
149+
}
150+
const char *path_with_quotes = js_str(js, args[0]);
151+
if (path_with_quotes == NULL) {
152+
Serial.println("sd_list_dir: argument is not a string");
153+
return js_mknull();
154+
}
155+
156+
// Strip the surrounding quotes from path
157+
String path = String(path_with_quotes);
158+
if (path.startsWith("\"") && path.endsWith("\"")) {
159+
path = path.substring(1, path.length() - 1);
160+
}
161+
162+
File root = SD_MMC.open(path);
163+
if (!root) {
164+
Serial.println("Failed to open directory");
165+
return js_mknull();
166+
}
167+
if (!root.isDirectory()) {
168+
Serial.println("Not a directory");
169+
root.close();
170+
return js_mknull();
171+
}
172+
173+
// Use a fixed-size buffer
174+
char fileList[512]; // Adjust size as needed
175+
int fileListLen = 0;
176+
177+
File file = root.openNextFile();
178+
while (file) {
179+
const char* type = file.isDirectory() ? "DIR: " : "FILE: ";
180+
const char* name = file.name();
181+
int len = snprintf(fileList + fileListLen, sizeof(fileList) - fileListLen, "%s%s\n", type, name);
182+
if (len < 0 || len >= (int)(sizeof(fileList) - fileListLen)) {
183+
// Buffer full, break
184+
break;
185+
}
186+
fileListLen += len;
187+
file = root.openNextFile();
188+
}
189+
root.close();
190+
191+
return js_mkstr(js, fileList, fileListLen);
192+
}
193+
194+
// Native function to get the IP address
195+
static jsval_t js_wifi_get_ip(struct js *js, jsval_t *args, int nargs) {
196+
if (WiFi.status() != WL_CONNECTED) {
197+
Serial.println("Not connected to Wi-Fi");
198+
return js_mknull();
199+
}
200+
201+
IPAddress ip = WiFi.localIP();
202+
String ipStr = ip.toString();
203+
return js_mkstr(js, ipStr.c_str(), ipStr.length());
204+
}
205+
206+
// Native function to set GPIO mode
207+
static jsval_t js_gpio_mode(struct js *js, jsval_t *args, int nargs) {
208+
if (nargs != 2) {
209+
Serial.println("gpio_mode: expected 2 arguments");
210+
return js_mknull();
211+
}
212+
int pin = (int)js_getnum(args[0]);
213+
int mode = (int)js_getnum(args[1]);
214+
pinMode(pin, mode);
215+
return js_mknull();
216+
}
217+
218+
// Native function to write to a GPIO pin
219+
static jsval_t js_gpio_write(struct js *js, jsval_t *args, int nargs) {
220+
if (nargs != 2) {
221+
Serial.println("gpio_write: expected 2 arguments");
222+
return js_mknull();
223+
}
224+
int pin = (int)js_getnum(args[0]);
225+
int value = (int)js_getnum(args[1]);
226+
digitalWrite(pin, value);
227+
return js_mknull();
228+
}
229+
230+
// Function to register native functions with Elk
231+
void register_js_functions() {
232+
jsval_t global = js_glob(js);
233+
234+
// Register global functions
235+
js_set(js, global, "print", js_mkfun(js_print));
236+
js_set(js, global, "wifi_connect", js_mkfun(js_wifi_connect));
237+
js_set(js, global, "wifi_status", js_mkfun(js_wifi_status));
238+
js_set(js, global, "sd_read_file", js_mkfun(js_sd_read_file));
239+
js_set(js, global, "sd_write_file", js_mkfun(js_sd_write_file));
240+
js_set(js, global, "wifi_get_ip", js_mkfun(js_wifi_get_ip));
241+
js_set(js, global, "delay", js_mkfun(js_delay));
242+
js_set(js, global, "sd_list_dir", js_mkfun(js_sd_list_dir)); // Add this line
243+
244+
// Create 'gpio' object
245+
jsval_t gpio = js_mkobj(js);
246+
js_set(js, global, "gpio", gpio);
247+
js_set(js, gpio, "mode", js_mkfun(js_gpio_mode));
248+
js_set(js, gpio, "write", js_mkfun(js_gpio_write));
249+
}
250+
251+
// Function to load and execute a JavaScript script from the SD card
252+
bool load_and_execute_js_script(const char* path) {
253+
Serial.printf("Loading JavaScript script from: %s\n", path);
254+
255+
File file = SD_MMC.open(path);
256+
if (!file) {
257+
Serial.println("Failed to open JavaScript script file");
258+
return false;
259+
}
260+
261+
// Read the entire file into a String
262+
String jsScript = file.readString();
263+
file.close();
264+
265+
// Execute the JavaScript script
266+
jsval_t res = js_eval(js, jsScript.c_str(), jsScript.length());
267+
if (js_type(res) == JS_ERR) {
268+
const char *error = js_str(js, res);
269+
Serial.printf("Error executing script: %s\n", error);
270+
return false;
271+
}
272+
273+
Serial.println("JavaScript script executed successfully");
274+
return true;
275+
}
276+
277+
void setup() {
278+
Serial.begin(115200);
279+
delay(1000);
280+
281+
// Set SD card pins
282+
SD_MMC.setPins(PIN_SD_CLK, PIN_SD_CMD, PIN_SD_D0);
283+
284+
// Initialize SD card
285+
if (!SD_MMC.begin("/sdcard", true)) {
286+
Serial.println("Card Mount Failed");
287+
return;
288+
}
289+
290+
// Initialize Wi-Fi
291+
WiFi.mode(WIFI_STA);
292+
293+
// Initialize Elk with a memory buffer
294+
static uint8_t elk_memory[4096]; // Adjust size as needed
295+
js = js_create(elk_memory, sizeof(elk_memory));
296+
if (js == NULL) {
297+
Serial.println("Failed to initialize Elk");
298+
return;
299+
}
300+
301+
// Register functions with Elk
302+
register_js_functions();
303+
304+
// Load and execute the JavaScript script from the SD card
305+
if (!load_and_execute_js_script("/script.js")) {
306+
Serial.println("Failed to load and execute JavaScript script");
307+
}
308+
}
309+
310+
void loop() {
311+
// Your main code here
312+
}

0 commit comments

Comments
 (0)