# HG changeset patch # User Michiel Broek # Date 1589211128 -7200 # Node ID 4b54d6f79d2518bbea08105af0bc87968be168e3 # Parent 638e7dd1d56077e769c0738da941658d4839e8aa Version 0.3.33 Added websockets framework. Added fermenter status messages to the websockets broadcast. diff -r 638e7dd1d560 -r 4b54d6f79d25 bmsd/Makefile --- a/bmsd/Makefile Thu May 07 14:59:50 2020 +0200 +++ b/bmsd/Makefile Mon May 11 17:32:08 2020 +0200 @@ -59,10 +59,10 @@ lock.o: lock.h bms.h futil.h nodes.o: bms.h xutil.h nodes.h mysql.h futil.o: bms.h futil.h -fermenters.o: bms.h xutil.h fermenters.h mysql.h +fermenters.o: bms.h xutil.h fermenters.h mysql.h websocket.h co2meters.o: bms.h xutil.h co2meters.h mysql.h ispindels.o: bms.h xutil.h ispindels.h mysql.h nodes.h -bms.o: bms.h xutil.h futil.h rdconfig.h lock.h mqtt.h mysql.h nodes.h +bms.o: bms.h xutil.h futil.h rdconfig.h lock.h mqtt.h mysql.h nodes.h websocket.h xutil.o: bms.h xutil.h rdconfig.o: bms.h xutil.h futil.h rdconfig.h mysql.o: bms.h xutil.h mysql.h nodes.h diff -r 638e7dd1d560 -r 4b54d6f79d25 bmsd/bms.c --- a/bmsd/bms.c Thu May 07 14:59:50 2020 +0200 +++ b/bmsd/bms.c Mon May 11 17:32:08 2020 +0200 @@ -1,5 +1,5 @@ /***************************************************************************** - * Copyright (C) 2017-2019 + * Copyright (C) 2017-2020 * * Michiel Broek * @@ -28,16 +28,19 @@ #include "mqtt.h" #include "mysql.h" #include "nodes.h" +#include "websocket.h" int my_shutdown = FALSE; int debug = FALSE; -static pid_t /*pgrp, */mypid; +static pid_t mypid; char *Private_Path = NULL; /* Users data path */ +pthread_t ws_thread; extern sys_config Config; + void help(void) { fprintf(stdout, "bmsd v%s starting\n\n", VERSION); @@ -128,19 +131,30 @@ goto endit2; } + rc = pthread_create(&ws_thread, NULL, ws_loop, NULL); + if (rc) { + fprintf(stderr, "ws_loop thread didn't start rc=%d\n", rc); + syslog(LOG_NOTICE, "ws_loop thread didn't start rc=%d", rc); + rc = 5; + goto endit3; + } + if (debug) fprintf(stdout, "[main] Entering main loop\n"); while (my_shutdown == FALSE) { - usleep(4000000); + usleep(3000000); nodes_check_online(); usleep(1000000); ispindel_mysql_check(); + usleep(1000000); + ws_check(); } if (debug) fprintf(stdout, "[main] Exit from main loop\n"); +endit3: /* * Remove our topics and close MQTT connection. */ @@ -212,17 +226,8 @@ } else { /* * Server initialization is complete. Now we can fork the - * daemon and return to the user. We need to do a setpgrp - * so that the daemon will no longer be assosiated with the - * users control terminal. This is done before the fork, so - * that the child will not be a process group leader. Otherwise, - * if the child were to open a terminal, it would become - * associated with that terminal as its control terminal. + * daemon and return to the user. */ -// if ((pgrp = setpgid(0, 0)) == -1) { -// syslog(LOG_NOTICE, "setpgid failed: %s", strerror(errno)); -// } - frk = fork(); switch (frk) { case -1: diff -r 638e7dd1d560 -r 4b54d6f79d25 bmsd/bms.h --- a/bmsd/bms.h Thu May 07 14:59:50 2020 +0200 +++ b/bmsd/bms.h Mon May 11 17:32:08 2020 +0200 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include diff -r 638e7dd1d560 -r 4b54d6f79d25 bmsd/fermenters.c --- a/bmsd/fermenters.c Thu May 07 14:59:50 2020 +0200 +++ b/bmsd/fermenters.c Mon May 11 17:32:08 2020 +0200 @@ -3,7 +3,7 @@ * @brief Handle fermenters status * @author Michiel Broek * - * Copyright (C) 2018-2019 + * Copyright (C) 2018-2020 * * This file is part of the bms (Brewery Management System) * @@ -27,6 +27,7 @@ #include "xutil.h" #include "fermenters.h" #include "mysql.h" +#include "websocket.h" sys_fermenter_list *fermenters = NULL; @@ -41,6 +42,7 @@ struct json_object *jobj, *val, *sensor, *temp; sys_fermenter_list *fermenter, *tmpp; bool new_fermenter = true; + char *msg = NULL, buf[65]; // fprintf(stdout, "fermenter_set: %s/%s %s %s\n", edge_node, alias, birth ? "BIRTH":"DATA", payload); @@ -318,6 +320,76 @@ } json_object_put(jobj); + msg = xstrcpy((char *)"{\"device\":\"fermenter\",\"node\":\""); + msg = xstrcat(msg, edge_node); + msg = xstrcat(msg, (char *)"\",\"unit\":\""); + msg = xstrcat(msg, alias); + msg = xstrcat(msg, (char *)"\",\"online\":"); + msg = xstrcat(msg, fermenter->online ? (char *)"1":(char *)"0"); + msg = xstrcat(msg, (char *)",\"mode\":\""); + msg = xstrcat(msg, fermenter->mode); + msg = xstrcat(msg, (char *)"\",\"yeast_lo\":"); + snprintf(buf, 64, "%.3f", fermenter->yeast_lo); + msg = xstrcat(msg, buf); + msg = xstrcat(msg, (char *)",\"yeast_hi\":"); + snprintf(buf, 64, "%.3f", fermenter->yeast_hi); + msg = xstrcat(msg, buf); + if (fermenter->air_address) { + msg = xstrcat(msg, (char *)",\"air\":"); + snprintf(buf, 64, "%.3f", fermenter->air_temperature); + msg = xstrcat(msg, buf); + } + if (fermenter->beer_address) { + msg = xstrcat(msg, (char *)",\"beer\":"); + snprintf(buf, 64, "%.3f", fermenter->beer_temperature); + msg = xstrcat(msg, buf); + } + if (fermenter->chiller_address) { + msg = xstrcat(msg, (char *)",\"chiller\":"); + snprintf(buf, 64, "%.3f", fermenter->chiller_temperature); + msg = xstrcat(msg, buf); + } + if (fermenter->heater_address) { + msg = xstrcat(msg, (char *)",\"heater\":"); + snprintf(buf, 64, "%d", fermenter->heater_state); + msg = xstrcat(msg, buf); + } + if (fermenter->cooler_address) { + msg = xstrcat(msg, (char *)",\"cooler\":"); + snprintf(buf, 64, "%d", fermenter->cooler_state); + msg = xstrcat(msg, buf); + } + if (fermenter->fan_address) { + msg = xstrcat(msg, (char *)",\"fan\":"); + snprintf(buf, 64, "%d", fermenter->fan_state); + msg = xstrcat(msg, buf); + } + if (fermenter->light_address) { + msg = xstrcat(msg, (char *)",\"light\":"); + snprintf(buf, 64, "%d", fermenter->light_state); + msg = xstrcat(msg, buf); + } + if (fermenter->door_address) { + msg = xstrcat(msg, (char *)",\"door\":"); + snprintf(buf, 64, "%d", fermenter->door_state); + msg = xstrcat(msg, buf); + } + msg = xstrcat(msg, (char *)",\"sp_lo\":"); + snprintf(buf, 64, "%.3f", fermenter->setpoint_low); + msg = xstrcat(msg, buf); + msg = xstrcat(msg, (char *)",\"sp_hi\":"); + snprintf(buf, 64, "%.3f", fermenter->setpoint_high); + msg = xstrcat(msg, buf); + msg = xstrcat(msg, (char *)",\"alarm\":"); + snprintf(buf, 64, "%d", fermenter->alarm); + msg = xstrcat(msg, buf); + msg = xstrcat(msg, (char *)",\"stage\":\""); + msg = xstrcat(msg, fermenter->stage); + msg = xstrcat(msg, (char *)"\"}"); + ws_broadcast(msg); + free(msg); + msg = NULL; + // fermenter_dump(fermenter); if (new_fermenter) { @@ -671,7 +743,7 @@ void fermenter_death(char *topic) { - char *edge_node, *alias; + char *edge_node, *alias, *msg = NULL; sys_fermenter_list *tmpp; printf("fermenter_death: %s\n", topic); @@ -689,6 +761,14 @@ if (tmpp->online) syslog(LOG_NOTICE, "Offline fermenter %s/%s", tmpp->node, tmpp->alias); tmpp->online = false; + msg = xstrcpy((char *)"{\"device\":\"fermenter\",\"node\":\""); + msg = xstrcat(msg, edge_node); + msg = xstrcat(msg, (char *)"\",\"unit\":\""); + msg = xstrcat(msg, alias); + msg = xstrcat(msg, (char *)"\",\"online\":0}"); + ws_broadcast(msg); + free(msg); + msg = NULL; break; } } @@ -698,6 +778,14 @@ if (tmpp->online) syslog(LOG_NOTICE, "Offline fermenter %s/%s", tmpp->node, tmpp->alias); tmpp->online = false; + msg = xstrcpy((char *)"{\"device\":\"fermenter\",\"node\":\""); + msg = xstrcat(msg, edge_node); + msg = xstrcat(msg, (char *)"\",\"unit\":\""); + msg = xstrcat(msg, tmpp->alias); + msg = xstrcat(msg, (char *)"\",\"online\":0}"); + ws_broadcast(msg); + free(msg); + msg = NULL; } } } diff -r 638e7dd1d560 -r 4b54d6f79d25 bmsd/websocket.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bmsd/websocket.c Mon May 11 17:32:08 2020 +0200 @@ -0,0 +1,246 @@ +/** + * @file websocket.c + * @brief WebSockets interface + * @author Michiel Broek + * + * Copyright (C) 2020 + * + * Michiel Broek + * + * This file is part of the bms (Brewery Management System) + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * bms is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ThermFerm; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "bms.h" +#include "xutil.h" +#include "websocket.h" +#include + + +extern sys_config Config; +extern int debug; +extern int my_shutdown; + +struct lws_context *context; +int ws_clients = 0; +time_t last_msg = 0; +pthread_mutex_t ws_mutex; + + +/* + * Based on lws-mirror-protocol from libwebsockets v2.0.x + * Debian ships v2.0.3, on Slackware we have 2.4.0 and there + * are lots of changes in the api. + */ +#define MAX_MESSAGE_QUEUE 512 + +/* + * one of these created for each message + */ +struct a_message { + void *payload; /* is malloc'd */ + size_t len; +}; + + +static struct a_message ringbuffer[MAX_MESSAGE_QUEUE]; +static int ringbuffer_head; + + + +static int callback_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) +{ + struct per_session_data__lws_mirror *pss = (struct per_session_data__lws_mirror *)user; + int n, m; + + switch (reason) { + + case LWS_CALLBACK_ESTABLISHED: { + ws_clients++; + syslog(LOG_NOTICE, "ws: new connection, total %d", ws_clients); + pss->ringbuffer_tail = ringbuffer_head; + pss->wsi = wsi; + break; + } + + case LWS_CALLBACK_PROTOCOL_DESTROY: + syslog(LOG_NOTICE, "ws: protocol cleaning up"); + for (n = 0; n < sizeof ringbuffer / sizeof ringbuffer[0]; n++) + if (ringbuffer[n].payload) + free(ringbuffer[n].payload); + break; + + case LWS_CALLBACK_SERVER_WRITEABLE: + while (pss->ringbuffer_tail != ringbuffer_head) { + m = ringbuffer[pss->ringbuffer_tail].len; + n = lws_write(wsi, (unsigned char *)ringbuffer[pss->ringbuffer_tail].payload + LWS_PRE, m, LWS_WRITE_TEXT); + if (n < 0) { + syslog(LOG_NOTICE, "ws: ERROR %d writing", n); + return -1; + } + if (n < m) + syslog(LOG_NOTICE, "ws: partial write %d vs %d", n, m); + + if (pss->ringbuffer_tail == (MAX_MESSAGE_QUEUE - 1)) + pss->ringbuffer_tail = 0; + else + pss->ringbuffer_tail++; + + if (((ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 15)) + lws_rx_flow_allow_all_protocol(lws_get_context(wsi), lws_get_protocol(wsi)); + + if (lws_send_pipe_choked(wsi)) { + lws_callback_on_writable(wsi); + break; + } + } + break; + + case LWS_CALLBACK_RECEIVE: + if (((ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1)) == (MAX_MESSAGE_QUEUE - 1)) { + syslog(LOG_NOTICE, "ws: dropping!"); + goto choke; + } + + if (ringbuffer[ringbuffer_head].payload) + free(ringbuffer[ringbuffer_head].payload); + + ringbuffer[ringbuffer_head].payload = malloc(LWS_PRE + len); + ringbuffer[ringbuffer_head].len = len; + memcpy((char *)ringbuffer[ringbuffer_head].payload + LWS_PRE, in, len); + if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1)) + ringbuffer_head = 0; + else + ringbuffer_head++; + + if (((ringbuffer_head - pss->ringbuffer_tail) & (MAX_MESSAGE_QUEUE - 1)) != (MAX_MESSAGE_QUEUE - 2)) + goto done; + +choke: + syslog(LOG_NOTICE, "ws: LWS_CALLBACK_RECEIVE: throttling"); + lws_rx_flow_control(wsi, 0); + +done: + lws_callback_on_writable_all_protocol(lws_get_context(wsi), lws_get_protocol(wsi)); + break; + + case LWS_CALLBACK_CLOSED: + ws_clients--; + syslog(LOG_NOTICE, "ws: connection closed, left %d", ws_clients); + break; + + default: + break; + } + + return 0; +} + + + +static struct lws_protocols protocols[] = { + { "bmsd-protocol", callback_ws, sizeof(struct per_session_data__lws_mirror), 128 }, + { NULL, NULL, 0, 0 } /* terminator */ +}; + + +/* + * {"device":"fermenter","node":"seaport","unit":"unit0","online":1,"mode":"FRIDGE","yeast_lo":12.0,"yeast_hi":24.0,"air":19.875,"beer":19.812,"chiller":1.500,"heater":100,"cooler":0,"fan":100,"light":0,"door":0,"sp_lo":17.0,"sp_hi":17.5,"alarm":0,"stage":"PRIMARY"} + */ +void ws_broadcast(char *msg) +{ + int len, err; + + err = pthread_mutex_lock(&ws_mutex); + if (err) { + syslog(LOG_NOTICE, "ws_broadcast pthread_mutex_lock error %d", err); + } else { + + len = strlen(msg); + if (ringbuffer[ringbuffer_head].payload) + free(ringbuffer[ringbuffer_head].payload); + + ringbuffer[ringbuffer_head].payload = malloc(LWS_PRE + len); + ringbuffer[ringbuffer_head].len = len; + memcpy((char *)ringbuffer[ringbuffer_head].payload + LWS_PRE, msg, len); + if (ringbuffer_head == (MAX_MESSAGE_QUEUE - 1)) + ringbuffer_head = 0; + else + ringbuffer_head++; + +// syslog(LOG_NOTICE, "ws: %d %s", ringbuffer_head, msg); + syslog(LOG_NOTICE, "ws: broadcast buffer=%d len=%d", ringbuffer_head, len); + + lws_callback_on_writable_all_protocol(context, &protocols[0]); + err = pthread_mutex_unlock(&ws_mutex); + if (err) { + syslog(LOG_NOTICE, "ws_broadcast pthread_mutex_unlock error %d", err); + } + last_msg = time(NULL); + } +} + + + +/* + * Called every 5 seconds. + */ +void ws_check(void) +{ + time_t now = time(NULL); + + if (((int)now - (int)last_msg) > 45) { + ws_broadcast((char *)"{\"ping\":1}"); + } +} + + + +void *ws_loop(void *threadid) +{ + struct lws_context_creation_info info; + int n = 0; + + syslog(LOG_NOTICE, "Thread ws_loop started"); + + memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ + info.port = 8010; + info.protocols = protocols; + info.gid = -1; + info.uid = -1; + info.keepalive_timeout = 900; + info.options = LWS_SERVER_OPTION_VALIDATE_UTF8; + + context = lws_create_context(&info); + + if (context == NULL) { + syslog(LOG_NOTICE, "libwebsocket_create_context() failed"); + } + + /* + * Loop forever until external shutdown variable is set. + */ + while (n >= 0 && ! my_shutdown) { + + n = lws_service(context, 50); + } + lws_context_destroy(context); + + syslog(LOG_NOTICE, "Thread ws_loop stopped"); + return 0; +} + + diff -r 638e7dd1d560 -r 4b54d6f79d25 bmsd/websocket.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bmsd/websocket.h Mon May 11 17:32:08 2020 +0200 @@ -0,0 +1,31 @@ +/** + * @file websocket.h + */ + +#ifndef _WEBSOCKET_H +#define _WEBSOCKET_H + + +struct per_session_data__lws_mirror { + struct lws *wsi; + int ringbuffer_tail; +}; + +/** + * @brief Broadcast messages to all connected websocket clients. + * @param msg The message to send. Messages are placed in a ringbuffer queue. + */ +void ws_broadcast(char *msg); + +/** + * @brief Check if a connection is idle for 45 seconds and if so send a ping like + * message to keep the connection alive. Call this function at regular intervals. + */ +void ws_check(void); + +/** + * @brief The websockets server thread. + */ +void *ws_loop(void *); + +#endif diff -r 638e7dd1d560 -r 4b54d6f79d25 config.status --- a/config.status Thu May 07 14:59:50 2020 +0200 +++ b/config.status Mon May 11 17:32:08 2020 +0200 @@ -621,13 +621,13 @@ S["CC"]="gcc" S["CYEARS"]="2016-2020" S["COPYRIGHT"]="Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved" -S["VERSION"]="0.3.32" +S["VERSION"]="0.3.33" S["PACKAGE"]="bms" S["SUBDIRS"]="bmsd doc script tools www" S["target_alias"]="" S["host_alias"]="" S["build_alias"]="" -S["LIBS"]=" -lm -lmosquitto -ljson-c -lmysqlclient -lxml2 -luuid" +S["LIBS"]=" -lm -lmosquitto -ljson-c -lmysqlclient -lxml2 -luuid -lwebsockets" S["ECHO_T"]="" S["ECHO_N"]="-n" S["ECHO_C"]="" @@ -710,7 +710,7 @@ D["PACKAGE_STRING"]=" \"\"" D["PACKAGE_BUGREPORT"]=" \"\"" D["PACKAGE_URL"]=" \"\"" -D["VERSION"]=" \"0.3.32\"" +D["VERSION"]=" \"0.3.33\"" D["COPYRIGHT"]=" \"Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved\"" D["STDC_HEADERS"]=" 1" D["HAVE_SYS_TYPES_H"]=" 1" @@ -727,6 +727,7 @@ D["HAVE_MARIADB_MYSQL_H"]=" 1" D["HAVE_LIBXML_XMLMEMORY_H"]=" 1" D["HAVE_UUID_UUID_H"]=" 1" +D["HAVE_LIBWEBSOCKETS_H"]=" 1" D["STDC_HEADERS"]=" 1" for (key in D) D_is_set[key] = 1 FS = "" diff -r 638e7dd1d560 -r 4b54d6f79d25 configure --- a/configure Thu May 07 14:59:50 2020 +0200 +++ b/configure Mon May 11 17:32:08 2020 +0200 @@ -2043,7 +2043,7 @@ PACKAGE="bms" -VERSION="0.3.32" +VERSION="0.3.33" COPYRIGHT="Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved" CYEARS="2016-2020" @@ -3790,6 +3790,67 @@ as_fn_error $? "libuuid not found" "$LINENO" 5 fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for lws_client_connect in -lwebsockets" >&5 +$as_echo_n "checking for lws_client_connect in -lwebsockets... " >&6; } +if ${ac_cv_lib_websockets_lws_client_connect+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lwebsockets $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char lws_client_connect (); +int +main () +{ +return lws_client_connect (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_websockets_lws_client_connect=yes +else + ac_cv_lib_websockets_lws_client_connect=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_websockets_lws_client_connect" >&5 +$as_echo "$ac_cv_lib_websockets_lws_client_connect" >&6; } +if test "x$ac_cv_lib_websockets_lws_client_connect" = xyes; then : + result=yes +else + result=no +fi + +if test "$result" = "yes"; then + LIBS="$LIBS -lwebsockets" + for ac_header in libwebsockets.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "libwebsockets.h" "ac_cv_header_libwebsockets_h" "$ac_includes_default" +if test "x$ac_cv_header_libwebsockets_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBWEBSOCKETS_H 1 +_ACEOF + +fi + +done + +else + as_fn_error $? "libwebsockets not found" "$LINENO" 5 +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } diff -r 638e7dd1d560 -r 4b54d6f79d25 configure.ac --- a/configure.ac Thu May 07 14:59:50 2020 +0200 +++ b/configure.ac Mon May 11 17:32:08 2020 +0200 @@ -8,7 +8,7 @@ dnl General settings dnl After changeing the version number, run autoconf! PACKAGE="bms" -VERSION="0.3.32" +VERSION="0.3.33" COPYRIGHT="Copyright (C) 2016-2020 Michiel Broek, All Rights Reserved" CYEARS="2016-2020" AC_SUBST(PACKAGE) @@ -89,6 +89,15 @@ AC_MSG_ERROR(libuuid not found) fi +AC_CHECK_LIB(websockets,lws_client_connect,result=yes,result=no) +if test "$result" = "yes"; then + LIBS="$LIBS -lwebsockets" + AC_CHECK_HEADERS(libwebsockets.h) +else + AC_MSG_ERROR(libwebsockets not found) +fi + + dnl Checks for header files. AC_HEADER_STDC diff -r 638e7dd1d560 -r 4b54d6f79d25 www/includes/global.inc.php --- a/www/includes/global.inc.php Thu May 07 14:59:50 2020 +0200 +++ b/www/includes/global.inc.php Mon May 11 17:32:08 2020 +0200 @@ -322,6 +322,7 @@
  • Informatie
  • +
  • ws: nc
  • diff -r 638e7dd1d560 -r 4b54d6f79d25 www/js/global.js --- a/www/js/global.js Thu May 07 14:59:50 2020 +0200 +++ b/www/js/global.js Mon May 11 17:32:08 2020 +0200 @@ -763,6 +763,37 @@ }); $('#jqxWidget').css('visibility', 'visible'); + var websocket = new WebSocket('ws://'+location.hostname+'/ws'); + + websocket.onopen = function(evt) { + console.log('WebSocket connection opened'); + document.getElementById("wsstatus").innerHTML = ""; + } + + websocket.onmessage = function(evt) { + var msg = evt.data; + var value; + + console.log('ws got: ' + msg); +// switch (msg.charAt(0)) { +// case '{': +// BrewBoard.p_msg(evt.data); +// break; +// default: +// document.getElementById("output").innerHTML = evt.data; +// break; +// } + } + + websocket.onclose = function(evt) { + console.log('Websocket connection closed'); +// $('#wsstatus').html('WebSocket closed'); + } + + websocket.onerror = function(event) { + console.log('Websocket error: ' + event.data); + $('#wsstatus').html('WebSocket error: ' + event.data); + } });