OUTPUT_FILE = mt-rfid
LIBRARIES = -lev -luFCoder-armhf
-all: $(SOURCE_FILES)
+all: mt-rfid mt-server
+
+mt-rfid: $(SOURCE_FILES)
$(CC) $(CFLAGS) -o $(OUTPUT_FILE) $(SOURCE_FILES) $(LIBRARIES)
+mt-server: mt_server.c
+ $(CC) $(CFLAGS) -o mt-server mt_server.c $(LIBRARIES) -lwebsockets
+
.PHONY: clean
clean:
--- /dev/null
+<!DOCTYPE html>
+<html>
+<title>Websocket example</title>
+
+<script>
+ var socket = new WebSocket(
+ "ws://" + document.domain + ':' + location.port,
+ "dumb-increment-protocol"
+ );
+
+ function update(id, msg) {
+ document.getElementById(id).innerHTML = msg;
+ }
+
+ socket.onopen = function() {
+ console.log("socket open");
+ update("text", "open");
+ }
+
+ socket.onclose = function() {
+ console.log("socket close");
+ update("text", "closed");
+ }
+
+ socket.onmessage = function(json) {
+ var msg = JSON.parse(json.data);
+
+ update("json", JSON.stringify(msg))
+
+ switch(msg.type) {
+ case "rfid":
+ update("text", msg.uid + " " + msg.size);
+ break;
+ }
+ }
+
+ function sendReset() {
+ socket.send("reset\n");
+ console.log("reset");
+ }
+
+ function sendClose() {
+ socket.send("close\n");
+ console.log("close");
+ }
+</script>
+
+
+
+<body>
+
+<p id="json"></p>
+<p id="text"></p>
+
+<a href="https://time.is/" id="time_is_link" rel="nofollow"></a>
+<span id="Czechia_z721"></span>
+<script src="//widget.time.is/t.js"></script>
+<script>
+time_is_widget.init({Czechia_z721:{}});
+</script>
+
+<button onclick="sendReset()">reset</button>
+<button onclick="sendClose()">close</button>
+</body>
+</html>
int set_nonblock(int fd)
{
int flags = fcntl(fd, F_GETFL, 0);
- if (flags == -1){
+ if (flags == -1) {
perror("fcntl (get)");
return -1;
}
- if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
perror("fcntl (set)");
return -1;
}
return 0;
}
-int set_rts(int fd, int level) {
- int uart_status;
+int set_rts(int fd, int level)
+{
+ int uart_status;
- if (ioctl(fd, TIOCMGET, &uart_status) == -1) {
- perror("ioctl (TIOCMGET)");
- return -1;
- }
+ if (ioctl(fd, TIOCMGET, &uart_status) == -1) {
+ perror("ioctl (TIOCMGET)");
+ return -1;
+ }
- if (level) {
- uart_status |= TIOCM_RTS;
+ if (level) {
+ uart_status |= TIOCM_RTS;
} else {
- uart_status &= ~TIOCM_RTS;
+ uart_status &= ~TIOCM_RTS;
}
- if (ioctl(fd, TIOCMSET, &uart_status) == -1) {
- perror("TIOCMSET");
+ if (ioctl(fd, TIOCMSET, &uart_status) == -1) {
+ perror("TIOCMSET");
return -1;
- }
+ }
fprintf(stderr, "set rts %d\n", level);
return 0;
}
-void set_baud_rate(int fd, int br) {
- struct termios options;
+void set_baud_rate(int fd, int br)
+{
+ struct termios options;
- tcgetattr(fd, &options);
- cfsetispeed(&options, br);
- cfsetospeed(&options, br);
- tcsetattr(fd, TCSANOW, &options);
+ tcgetattr(fd, &options);
+ cfsetispeed(&options, br);
+ cfsetospeed(&options, br);
+ tcsetattr(fd, TCSANOW, &options);
}
-int tty_open(const char *port, int baud_rate) {
+int tty_open(const char *port, int baud_rate)
+{
- int fd = open(port, O_RDONLY | O_NOCTTY);
- if (fd < 0) {
+ int fd = open(port, O_RDONLY | O_NOCTTY);
+ if (fd < 0) {
perror("open");
return fd;
- } else {
+ } else {
fprintf(stderr, "opened %s as %d\n", port, fd);
}
set_nonblock(fd);
- set_rts(fd, 0);
- set_baud_rate(fd, baud_rate);
- usleep(1200000); //value by d-logic
- tcflush(fd, TCIFLUSH);
+ set_rts(fd, 0);
+ set_baud_rate(fd, baud_rate);
+ usleep(1200000); //value by d-logic
+ tcflush(fd, TCIFLUSH);
- return fd;
+ return fd;
}
typedef struct ev_io_ufr {
ev_io w;
+ //lws_context *context;
+ //ufr_session_data *session_data;
char uid_data[24];
char *uid;
+ int fd;
} ev_io_ufr;
static void sigint_cb(EV_P_ ev_signal *w, int revents)
{
- ev_break (EV_A_ EVBREAK_ALL);
+ ev_break(EV_A_ EVBREAK_ALL);
}
-static void ufr_read(char *uid)
+static void ufr_read(char *uid, int fd)
{
UFR_STATUS status;
uint8_t card_type;
- uint8_t sak; //select acknowledge
+ uint8_t sak; //select acknowledge
uint8_t uid_bytes[10]; //uid as bytes
- uint8_t uid_size;
+ uint8_t size;
+ char *type = "rfid";
status = GetDlogicCardType(&card_type);
if (status != UFR_OK) {
return;
}
- status = GetCardIdEx(&sak, uid_bytes, &uid_size);
+ status = GetCardIdEx(&sak, uid_bytes, &size);
if (status != UFR_OK) {
fprintf(stderr, "GetCardIdEx: %s\n", UFR_Status2String(status));
return;
}
JSON_START();
- JSON_NUM(card_type); JSON_NEXT();
- JSON_NUM(sak); JSON_NEXT();
- JSON_NUM(uid_size); JSON_NEXT();
- JSON_STR(uid); JSON_END();
+ JSON_STR(type);
+ JSON_NEXT();
+ JSON_NUM(card_type);
+ JSON_NEXT();
+ JSON_NUM(sak);
+ JSON_NEXT();
+ JSON_NUM(size);
+ JSON_NEXT();
+ JSON_STR(uid);
+ JSON_END();
#ifdef UFR_BEEP
- ReaderUISignal(0, 1);
+ ReaderUISignal(0, 1); // no light, one beep
#endif
+
+ /*lws_callback_on_writable_all_protocol(self->context,
+ &protocols[PROTOCOL_DUMB_INCREMENT]);*/
}
static void ufr_cb(EV_P_ ev_io *w_, int revents)
if (uid == ASYNC_SUFFIX) {
//*(w->uid - 1) = 0;
w->uid = w->uid_data;
- ufr_read(w->uid);
+ ufr_read(w->uid, w->fd);
}
//for one-shot events, one must manually stop the watcher with its corresponding stop function.
struct ev_loop *loop = EV_DEFAULT;
ufr_watcher.uid = ufr_watcher.uid_data;
- ev_io_init (&(ufr_watcher.w), ufr_cb, fd, EV_READ);
- ev_io_start (loop, (ev_io *)&ufr_watcher);
+ ufr_watcher.fd = 1;
+ ev_io_init(&(ufr_watcher.w), ufr_cb, fd, EV_READ);
+ ev_io_start(loop, (ev_io *)&ufr_watcher);
- ev_signal_init (&int_watcher, sigint_cb, SIGINT);
- ev_signal_start (loop, &int_watcher);
- ev_signal_init (&term_watcher, sigint_cb, SIGTERM);
- ev_signal_start (loop, &term_watcher);
+ ev_signal_init(&int_watcher, sigint_cb, SIGINT);
+ ev_signal_start(loop, &int_watcher);
+ ev_signal_init(&term_watcher, sigint_cb, SIGTERM);
+ ev_signal_start(loop, &term_watcher);
- ev_run (loop, 0);
+ ev_run(loop, 0);
return 0;
}
fprintf(stderr, "%s\n", GetReaderDescription());
status = SetAsyncCardIdSendConfig(
- 1, //enable send
- 0, //disable prefix
- 0, //prefix
- ASYNC_SUFFIX, //suffix
- 0, //disable send removed
- ASYNC_BAUD_RATE
- );
+ 1, //enable send
+ 0, //disable prefix
+ 0, //prefix
+ ASYNC_SUFFIX, //suffix
+ 0, //disable send removed
+ ASYNC_BAUD_RATE
+ );
fprintf(stderr, "SetAsyncCardIdSendConfig: %s\n", UFR_Status2String(status));
if (status != UFR_OK) {
return -1;
return -1;
}
- int fd = tty_open(PORT_NAME, CONCAT(B,ASYNC_BAUD_RATE));
+ int fd = tty_open(PORT_NAME, CONCAT(B, ASYNC_BAUD_RATE));
if (fd < 0) {
return -2;
}
- libev_run(fd);
+ libev_run(fd);
if (close(fd) == 0) {
fprintf(stderr, "closed %d\n", fd);
#define UFR_BEEP // define this to annoy people
// really simple JSON helpers
-#define JSON_START() printf("{\n")
-#define JSON_NUM(NAME) printf("\"" #NAME "\": %d", NAME)
-#define JSON_NEXT() printf(",\n")
-#define JSON_STR(NAME) printf("\"" #NAME "\": \"%s\"", NAME)
-#define JSON_END() printf("\n}\n")
+#define JSON_START() dprintf(fd,"{")
+#define JSON_NUM(NAME) dprintf(fd,"\"" #NAME "\": %d", NAME)
+#define JSON_NEXT() dprintf(fd,",")
+#define JSON_STR(NAME) dprintf(fd,"\"" #NAME "\": \"%s\"", NAME)
+#define JSON_END() dprintf(fd,"}\n")
#endif
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <libwebsockets.h>
+#include <string.h>
+#include <ev.h>
+
+char *uids[10] = {
+ "evelyn",
+ "sera",
+ "solas",
+ "iron bull",
+ "cassandra",
+ "varric",
+ "dorian",
+ "vivienne",
+ "blackwall",
+ "cole"
+};
+
+#define JSON_STRING "{" \
+ "\"type\": \"rfid\"," \
+ "\"uid\": \"%s\"," \
+ "\"size\": %d" \
+ "}\n"
+
+static const struct lws_http_mount mount = {
+ /* .mount_next */ NULL, /* linked-list "next" */
+ /* .mountpoint */ "/", /* mountpoint URL */
+ /* .origin */ "/usr/share/mt-server", /* serve from dir */
+ /* .def */ "index.html", /* default filename */
+ /* .protocol */ NULL,
+ /* .cgienv */ NULL,
+ /* .extra_mimetypes */ NULL,
+ /* .interpret */ NULL,
+ /* .cgi_timeout */ 0,
+ /* .cache_max_age */ 0,
+ /* .auth_mask */ 0,
+ /* .cache_reusable */ 0,
+ /* .cache_revalidate */ 0,
+ /* .cache_intermediaries */ 0,
+ /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */
+ /* .mountpoint_len */ 1, /* char count */
+ /* .basic_auth_login_file */ NULL,
+};
+
+typedef struct per_vhost_data__dumb_increment {
+ struct lws_context *context;
+ struct lws_vhost *vhost;
+ const struct lws_protocols *protocol;
+} per_vhost_data__dumb_increment;
+
+typedef struct per_session_data__dumb_increment {
+ uint8_t card_type;
+ uint8_t sak;
+ uint8_t uid_size;
+ char *uid;
+ int number;
+} per_session_data__dumb_increment;
+
+typedef struct user_data {
+ //ev_ufr_io *ufr;
+} user_data;
+
+ static char line[512];
+
+static int callback_dumb_increment(struct lws *wsi,
+ enum lws_callback_reasons reason,
+ void *user, void *in, size_t len)
+{
+ per_session_data__dumb_increment *pss =
+ (per_session_data__dumb_increment *)user;
+ per_vhost_data__dumb_increment *vhd =
+ (per_vhost_data__dumb_increment *)
+ lws_protocol_vh_priv_get(lws_get_vhost(wsi), lws_get_protocol(wsi));
+
+ struct lws_context *context = lws_get_context(wsi);
+ user_data *data = (user_data *)lws_context_user(context);
+
+
+ unsigned char buf[LWS_PRE + 512];
+ unsigned char *p = &buf[LWS_PRE];
+ int n, m;
+
+ switch (reason) {
+ case LWS_CALLBACK_PROTOCOL_INIT:
+ vhd = lws_protocol_vh_priv_zalloc(
+ lws_get_vhost(wsi),
+ lws_get_protocol(wsi),
+ sizeof(struct per_vhost_data__dumb_increment)
+ );
+ vhd->context = lws_get_context(wsi);
+ vhd->protocol = lws_get_protocol(wsi);
+ vhd->vhost = lws_get_vhost(wsi);
+ break;
+
+ case LWS_CALLBACK_PROTOCOL_DESTROY:
+ if (!vhd) {
+ break;
+ }
+ break;
+
+ case LWS_CALLBACK_ESTABLISHED:
+ pss->number = 0;
+ break;
+
+ case LWS_CALLBACK_SERVER_WRITEABLE:
+ n = sprintf((char *)p, JSON_STRING, uids[pss->number % 10], pss->number);
+ pss->number++;
+ n = strlen(line);
+ m = lws_write(wsi, line, n, LWS_WRITE_TEXT);
+ if (m < n) {
+ printf("ERROR %d writing to di socket\n", n);
+ return -1;
+ }
+ break;
+
+ case LWS_CALLBACK_RECEIVE:
+ if (len < 6) {
+ break;
+ }
+ if (strcmp((const char *)in, "reset\n") == 0) {
+ pss->number = 0;
+ }
+ if (strcmp((const char *)in, "close\n") == 0) {
+ printf("dumb_inc: closing as requested\n");
+ lws_close_reason(wsi, LWS_CLOSE_STATUS_GOINGAWAY,
+ (unsigned char *)"seeya", 5);
+ return -1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+enum demo_protocols {
+ /* always first */
+ PROTOCOL_HTTP = 0,
+
+ PROTOCOL_DUMB_INCREMENT,
+ PROTOCOL_LWS_MIRROR,
+ PROTOCOL_LWS_STATUS,
+
+ /* always last */
+ DEMO_PROTOCOL_COUNT
+};
+
+/* list of supported protocols and callbacks */
+
+static struct lws_protocols protocols[] = {
+ /* first protocol must always be HTTP handler */
+ {"http", lws_callback_http_dummy, 0, 0},
+ {
+ "dumb-increment-protocol",
+ callback_dumb_increment,
+ sizeof(struct per_session_data__dumb_increment),
+ 128, /* rx buf size must be >= permessage-deflate rx size
+ * dumb-increment only sends very small packets, so we set
+ * this accordingly. If your protocol will send bigger
+ * things, adjust this to match */
+ },
+ {NULL, NULL, 0, 0} /* terminator */
+};
+
+struct lws_context *context;
+
+static void ev_timeout_cb(EV_P_ ev_timer *w, int revents)
+{
+ lws_callback_on_writable_all_protocol(context,
+ &protocols[PROTOCOL_DUMB_INCREMENT]);
+}
+
+static void signal_cb(EV_P_ ev_signal *w, int revents)
+{
+ fprintf(stderr, "signal caught, terminating\n");
+ switch (w->signum) {
+ case SIGTERM:
+ case SIGINT:
+ ev_break(loop, EVBREAK_ALL);
+ break;
+ default:
+ signal(SIGABRT, SIG_DFL);
+ abort();
+ break;
+ }
+}
+
+
+
+int server_init(void *user)
+{
+ struct lws_context_creation_info info;
+
+ protocols[PROTOCOL_DUMB_INCREMENT].user = (void *)line;
+
+ memset(&info, 0, sizeof info);
+ info.port = 80;
+ info.mounts = &mount;
+ info.protocols = protocols;
+ info.max_http_header_pool = 1;
+ info.options |= LWS_SERVER_OPTION_LIBEV;
+ info.user = user;
+
+ context = lws_create_context(&info);
+ if (!context) {
+ fprintf(stderr, "lws_create_context failed\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static void stdin_cb(EV_P_ ev_io *w, int revents)
+{
+ static int pos = 0;
+
+ read(w->fd, &line[pos++], 1);
+
+ if (line[pos-1] == '\n') {
+ line[pos] = 0;
+ pos = 0;
+// puts(line);
+ lws_callback_on_writable_all_protocol(context,
+ &protocols[PROTOCOL_DUMB_INCREMENT]);
+ }
+
+}
+
+int main(int argc, const char **argv)
+{
+ int sigs[] = { SIGINT, SIGKILL, SIGTERM, SIGSEGV, SIGFPE };
+ struct ev_signal signals[ARRAY_SIZE(sigs)];
+ ev_io stdin_watcher;
+ struct ev_loop *loop = ev_default_loop(0);
+ ev_timer timeout_watcher;
+
+ for (int n = 0; n < ARRAY_SIZE(sigs); n++) {
+ ev_init(&signals[n], signal_cb);
+ ev_signal_set(&signals[n], sigs[n]);
+ ev_signal_start(loop, &signals[n]);
+ }
+
+ if (server_init(NULL) == -1) {
+ return -1;
+ }
+ lws_ev_initloop(context, loop, 0);
+
+ ev_io_init(&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
+ ev_io_start(loop, &stdin_watcher);
+
+ ev_timer_init(&timeout_watcher, ev_timeout_cb, 1, 1);
+ //ev_timer_start(loop, &timeout_watcher);
+
+ ev_run(loop, 0);
+
+ lws_context_destroy(context);
+
+ return 0;
+}
--- /dev/null
+#ifndef MT_SERVER_H
+#define MT_SERVER_H
+
+#include <ev.h>
+
+int mt_server_init(struct ev_loop *loop, int fd);
+void mt_server_deinit();
+
+#endif