Skip to content

Commit

Permalink
Webassembly/emscripten build
Browse files Browse the repository at this point in the history
  • Loading branch information
gabonator committed Oct 10, 2023
1 parent e826a46 commit 85226d3
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ if(WIN32)
add_definitions(-D_USE_MATH_DEFINES)
endif()

ADD_DEFINITIONS(-DSERVER)

########################################################################
# Use pkg-config
########################################################################
Expand Down
111 changes: 111 additions & 0 deletions do_wasm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/bin/bash
set -e
mkdir -p build
cd build

cat > wasmapi.c <<-EOF
#include "rtl_433.h"
#include "r_private.h"
#include "r_api.h"
uint32_t analyseBuffer[1024];
int analyse(uint32_t* pulse, int count)
{
r_cfg_t g_cfg;
r_cfg_t* cfg = &g_cfg;
r_init_cfg(cfg);
cfg->report_time = REPORT_TIME_OFF;
register_all_protocols(cfg, 0);
pulse_data_t data = {0};
data.sample_rate = 1000000;
for (int i=0; i<count; i+=2)
{
data.pulse[i/2] = pulse[i];
data.gap[i/2] = i < count ? pulse[i+1] : 0;
data.num_pulses++;
}
add_json_output(cfg, NULL);
return run_ook_demods(&cfg->demod->r_devs, &data);
}
EOF

cat > wasmtest.html <<-EOF
<script src="wasm.js"></script>
<script>
var HEAPU8;
var HEAPU32;
var TOTAL_MEMORY = 67108864;
var WASM_PAGE_SIZE = 4096;
var env = {
emscripten_memcpy_big: (dest, src, num) => {
HEAPU8.copyWithin(dest, src, src + num);
},
emscripten_date_now: () => { return Date.now(); },
fd_write:(fd, iov, iovcnt, pnum) => {
var ret = 0;
for (var i = 0; i < iovcnt; i++) {
var ptr = HEAPU32[iov>>2];
var len = HEAPU32[(iov+4)>>2];
iov += 8;
var msg = "";
for (var j=ptr; j<ptr+len; j++)
msg += String.fromCharCode(HEAPU8[j]);
if (msg != "" && msg != "\n")
console.log(msg);
ret += len;
}
HEAPU32[pnum>>2] = ret;
return 0;
},
emscripten_resize_heap: () => { throw "emscripten_resize_heap not implemented" },
memory:new WebAssembly.Memory({ 'initial': TOTAL_MEMORY / WASM_PAGE_SIZE, 'maximum': TOTAL_MEMORY / WASM_PAGE_SIZE }),
};
for (var i of ["__assert_fail", "exit", "strftime", "fd_close", "_tzset_js", "_mktime_js",
"_localtime_js", "__syscall_fcntl64", "__syscall_openat", "__syscall_ioctl", "fd_read",
"emscripten_resize_heap", "fd_seek"])
{
env[i] = () => { throw "not implemented" };
}
WebAssembly.instantiate(wasmBinary, {env:env, wasi_snapshot_preview1: env}).then(obj =>
{
var exports = obj.instance.exports;
HEAPU8 = new Uint8Array(exports.memory.buffer);
HEAPU32 = new Uint32Array(exports.memory.buffer);
exports.__wasm_call_ctors();
var analyseBuffer = new Uint32Array(
exports.memory.buffer,
exports.analyseBuffer.value,
1024*4
);
var testSignal = [520, 500, 420, 520, 400, 520, 440, 520, 400, 520, 400, 540, 400, 520, 440, 500, 440, 480, 440, 500, 440, 500, 460, 440, 460, 500, 420, 500, 440, 520, 420, 520, 420, 500, 460, 460, 480, 440, 480, 440, 500, 460, 480, 460, 460, 460, 480, 920, 980, 940, 960, 460, 500, 440, 500, 440, 480, 460, 480, 920, 500, 460, 500, 420, 980, 920, 980, 940, 480, 440, 500, 460, 460, 460, 960, 940, 980, 920, 500, 460, 480, 440, 480, 440, 960, 460, 520, 920, 960, 480, 480, 420, 500, 460, 480, 440, 500, 920, 480, 440, 500, 440, 500, 420, 500, 440, 500, 440, 980, 960, 440, 460, 480, 460, 500, 420, 520, 440, 480, 460, 480, 420, 500, 460, 480, 440, 500, 440, 500, 440, 480, 440, 480, 460, 980, 440, 480, 960, 960, 440, 500, 460, 460, 960, 460, 460, 500, 420, 980, 440, 500, 440, 500, 920, 960, 960, 960, 940, 980, 920, 960, 460, 500, 940, 960, 960, 460, 460, 960, 460, 480, 0]
for (var i=0; i<testSignal.length; i++)
analyseBuffer[i] = testSignal[i];
console.log("result", exports.analyse(exports.analyseBuffer.value, testSignal.length));
});
</script>
EOF

INCLUDES="-I ../include"
SOURCES1=$(find ../src -maxdepth 1 -name '*.c' -print)
SOURCES2=$(find ../src/devices -maxdepth 1 -name '*.c' -print)
SOURCES="$SOURCES1 $SOURCES2 wasmapi.c"
EXPORTED="['_analyse', '_analyseBuffer']"
emcc ${INCLUDES} ${SOURCES} -gsource-map -g3 -O3 -s TOTAL_STACK=1048576 -s TOTAL_MEMORY=67108864 -s MINIMAL_RUNTIME=1 -s WASM=1 -s EXPORTED_FUNCTIONS="${EXPORTED}" -o rtl433.js -DEMSCRIPTEN -s ERROR_ON_UNDEFINED_SYMBOLS=0 --source-map-base http://localhost:8081/build/

node <<-EOF
var fs = require("fs");
var prefix = 'wasmBinary = (() => { var wasmcode="';
var suffix = '"; return Uint8Array.from(atob(wasmcode), c => c.charCodeAt(0));})();';
fs.writeFileSync("wasm.js", prefix + fs.readFileSync("rtl433.wasm").toString("base64") + suffix);
EOF
3 changes: 2 additions & 1 deletion src/data_tag.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/

#ifdef SERVER
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
Expand Down Expand Up @@ -329,3 +329,4 @@ data_t *data_tag_apply(data_tag_t *tag, data_t *data, char const *filename)

return data;
}
#endif
3 changes: 2 additions & 1 deletion src/output_influx.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/

#ifdef SERVER
// note: our unit header includes unistd.h for gethostname() via data.h
#include "output_influx.h"
#include "optparse.h"
Expand Down Expand Up @@ -517,3 +517,4 @@ struct data_output *data_output_influx_create(struct mg_mgr *mgr, char *opts)

return &influx->output;
}
#endif
3 changes: 2 additions & 1 deletion src/output_mqtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/

#ifdef SERVER
// note: our unit header includes unistd.h for gethostname() via data.h
#include "output_mqtt.h"
#include "optparse.h"
Expand Down Expand Up @@ -601,3 +601,4 @@ struct data_output *data_output_mqtt_create(struct mg_mgr *mgr, char *param, cha

return &mqtt->output;
}
#endif
3 changes: 2 additions & 1 deletion src/output_udp.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/

#ifdef SERVER
#include "output_udp.h"

#include "data.h"
Expand Down Expand Up @@ -237,3 +237,4 @@ struct data_output *data_output_syslog_create(int log_level, const char *host, c

return &syslog->output;
}
#endif
23 changes: 16 additions & 7 deletions src/r_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,10 @@ char const *version_string(void)
#else
" version unknown"
#endif
" inputs file rtl_tcp"
" inputs file"
#ifdef SERVER
" rtl_tcp"
#endif
#ifdef RTLSDR
" RTL-SDR"
#endif
Expand All @@ -92,7 +95,7 @@ char const *version_string(void)
}

/* helper */

#ifdef SERVER
struct mg_mgr *get_mgr(r_cfg_t *cfg)
{
if (!cfg->mgr) {
Expand All @@ -104,7 +107,7 @@ struct mg_mgr *get_mgr(r_cfg_t *cfg)

return cfg->mgr;
}

#endif
void set_center_freq(r_cfg_t *cfg, uint32_t center_freq)
{
cfg->frequencies = 1;
Expand Down Expand Up @@ -232,16 +235,17 @@ void r_free_cfg(r_cfg_t *cfg)
r_logger_set_log_handler(NULL, NULL);

list_free_elems(&cfg->output_handler, (list_elem_free_fn)data_output_free);

#ifdef SERVER
list_free_elems(&cfg->data_tags, (list_elem_free_fn)data_tag_free);

#endif
list_free_elems(&cfg->in_files, NULL);

free(cfg->demod);

free(cfg->devices);

#ifdef SERVER
mg_mgr_free(cfg->mgr);
#endif
free(cfg->mgr);

//free(cfg);
Expand Down Expand Up @@ -888,11 +892,13 @@ void data_acquired_handler(r_device *r_dev, data_t *data)
NULL);
}

#ifdef SERVER
// apply all tags
for (void **iter = cfg->data_tags.elems; iter && *iter; ++iter) {
data_tag_t *tag = *iter;
data = data_tag_apply(tag, data, cfg->in_filename);
}
#endif

for (size_t i = 0; i < cfg->output_handler.len; ++i) { // list might contain NULLs
data_output_t *output = cfg->output_handler.elems[i];
Expand Down Expand Up @@ -1092,6 +1098,7 @@ void add_kv_output(r_cfg_t *cfg, char *param)
list_push(&cfg->output_handler, data_output_kv_create(log_level, fopen_output(param)));
}

#ifdef SERVER
void add_mqtt_output(r_cfg_t *cfg, char *param)
{
list_push(&cfg->output_handler, data_output_mqtt_create(get_mgr(cfg), param, cfg->dev_query));
Expand Down Expand Up @@ -1129,6 +1136,7 @@ void add_http_output(r_cfg_t *cfg, char *param)

list_push(&cfg->output_handler, data_output_http_create(get_mgr(cfg), host, port, cfg));
}
#endif

void add_trigger_output(r_cfg_t *cfg, char *param)
{
Expand Down Expand Up @@ -1237,8 +1245,9 @@ void add_infile(r_cfg_t *cfg, char *in_file)
{
list_push(&cfg->in_files, in_file);
}

#ifdef SERVER
void add_data_tag(struct r_cfg *cfg, char *param)
{
list_push(&cfg->data_tags, data_tag_create(param, get_mgr(cfg)));
}
#endif
15 changes: 14 additions & 1 deletion src/rtl_433.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,6 +1186,7 @@ static void parse_conf_option(r_cfg_t *cfg, int opt, char *arg)
add_kv_output(cfg, arg_param(arg));
cfg->has_logout = 1;
}
#ifdef SERVER
else if (strncmp(arg, "mqtt", 4) == 0) {
add_mqtt_output(cfg, arg);
}
Expand All @@ -1198,6 +1199,7 @@ static void parse_conf_option(r_cfg_t *cfg, int opt, char *arg)
else if (strncmp(arg, "http", 4) == 0) {
add_http_output(cfg, arg_param(arg));
}
#endif
else if (strncmp(arg, "trigger", 7) == 0) {
add_trigger_output(cfg, arg_param(arg));
}
Expand All @@ -1212,11 +1214,13 @@ static void parse_conf_option(r_cfg_t *cfg, int opt, char *arg)
usage(1);
}
break;
#ifdef SERVER
case 'K':
if (!arg)
help_tags();
add_data_tag(cfg, arg);
break;
#endif
case 'C':
if (!arg)
usage(1);
Expand Down Expand Up @@ -1416,6 +1420,7 @@ static void sdr_handler(struct mg_connection *nc, int ev_type, void *ev_data)
}
}

#ifdef SERVER
// note that this function is called in a different thread
static void acquire_callback(sdr_event_t *ev, void *ctx)
{
Expand Down Expand Up @@ -1481,6 +1486,7 @@ static int start_sdr(r_cfg_t *cfg)
cfg->dev_state = DEVICE_STATE_STARTING;
return r;
}
#endif

static void timer_handler(struct mg_connection *nc, int ev, void *ev_data)
{
Expand Down Expand Up @@ -1542,7 +1548,9 @@ static void timer_handler(struct mg_connection *nc, int ev, void *ev_data)
cfg->exit_async = 1;
}
if (cfg->dev_mode == DEVICE_MODE_RESTART) {
#ifdef SERVER
start_sdr(cfg);
#endif
}
// do nothing for DEVICE_MODE_PAUSE or DEVICE_MODE_MANUAL

Expand Down Expand Up @@ -1982,7 +1990,11 @@ int main(int argc, char **argv) {
print_log(LOG_NOTICE, "Input", "The internals of input handling changed, read about and report problems on PR #1978");

if (cfg->dev_mode != DEVICE_MODE_MANUAL) {
#ifdef SERVER
r = start_sdr(cfg);
#else
r = -1;
#endif
if (r < 0) {
exit(2);
}
Expand All @@ -1995,15 +2007,16 @@ int main(int argc, char **argv) {

time(&cfg->hop_start_time);

#ifdef SERVER
// add dummy socket to receive broadcasts
struct mg_add_sock_opts opts = {.user_data = cfg};
struct mg_connection *nc = mg_add_sock_opt(get_mgr(cfg), INVALID_SOCKET, timer_handler, opts);
// Send us MG_EV_TIMER event after 2.5 seconds
mg_set_timer(nc, mg_time() + 2.5);

while (!cfg->exit_async) {
mg_mgr_poll(cfg->mgr, 500);
}
#endif
if (cfg->verbosity >= LOG_INFO)
print_log(LOG_INFO, "rtl_433", "stopping...");
// final polls to drain the broadcast
Expand Down

0 comments on commit 85226d3

Please sign in to comment.