From 16551d71e54e2bbdbc0a654e32bcb235d257053a Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Sun, 14 May 2017 15:48:39 -0700 Subject: [PATCH] Added non-Sockjs websocket support, don't jog disabled axes, save and restore gcode state through AVR reset --- avr/src/command.c | 48 +++++++++++++-- avr/src/gcode_state.c | 136 +++++++++++++++++++++++++++++++++--------- avr/src/gcode_state.h | 6 ++ avr/src/machine.c | 32 +++++++--- avr/src/machine.h | 2 + avr/src/plan/jog.c | 4 ++ avr/src/varcb.c | 60 ++++++++++++++++--- avr/src/vars.c | 1 + avr/src/vars.def | 30 +++++----- src/js/app.js | 2 +- src/py/bbctrl/AVR.py | 18 +++++- src/py/bbctrl/LCD.py | 10 ++-- src/py/bbctrl/Web.py | 47 +++++++++++++-- 13 files changed, 321 insertions(+), 75 deletions(-) diff --git a/avr/src/command.c b/avr/src/command.c index 1df7e56..4c4f14f 100644 --- a/avr/src/command.c +++ b/avr/src/command.c @@ -170,6 +170,48 @@ int command_exec(int argc, char *argv[]) { } +char *_parse_arg(char **p) { + char *start = *p; + char *next = *p; + + bool inQuote = false; + bool escape = false; + + while (**p) { + char c = *(*p)++; + + switch (c) { + case '\\': + if (!escape) { + escape = true; + continue; + } + break; + + case ' ': case '\t': + if (!inQuote && !escape) goto done; + break; + + case '"': + if (!escape) { + inQuote = !inQuote; + continue; + } + break; + + default: break; + } + + *next++ = c; + escape = false; + } + + done: + *next = 0; + return start; +} + + int command_parser(char *cmd) { // Parse line char *p = cmd + 1; // Skip `$` @@ -186,10 +228,8 @@ int command_parser(char *cmd) { while (*p && isspace(*p)) *p++ = 0; // Start of token - if (*p) argv[argc++] = p; - - // Find end - while (*p && !isspace(*p)) p++; + char *arg = _parse_arg(&p); + if (*arg) argv[argc++] = arg; } // Exec command diff --git a/avr/src/gcode_state.c b/avr/src/gcode_state.c index 2a00555..7807e56 100644 --- a/avr/src/gcode_state.c +++ b/avr/src/gcode_state.c @@ -28,70 +28,152 @@ #include "gcode_state.h" +static const char INVALID_PGMSTR[] PROGMEM = "INVALID"; + +static const char INCHES_PGMSTR[] PROGMEM = "IN"; +static const char MILLIMETERS_PGMSTR[] PROGMEM = "MM"; +static const char DEGREES_PGMSTR[] PROGMEM = "DEG"; + +static const char INVERSE_TIME_MODE_PGMSTR[] PROGMEM = "INVERSE TIME"; +static const char UNITS_PER_MINUTE_MODE_PGMSTR[] PROGMEM = "PER MIN"; +static const char UNITS_PER_REVOLUTION_MODE_PGMSTR[] PROGMEM = "PER REV"; + +static const char PLANE_XY_PGMSTR[] PROGMEM = "XY"; +static const char PLANE_XZ_PGMSTR[] PROGMEM = "XZ"; +static const char PLANE_YZ_PGMSTR[] PROGMEM = "YZ"; + +static const char ABSOLUTE_COORDS_PGMSTR[] PROGMEM = "ABS"; +static const char G54_PGMSTR[] PROGMEM = "G54"; +static const char G55_PGMSTR[] PROGMEM = "G55"; +static const char G56_PGMSTR[] PROGMEM = "G56"; +static const char G57_PGMSTR[] PROGMEM = "G57"; +static const char G58_PGMSTR[] PROGMEM = "G58"; +static const char G59_PGMSTR[] PROGMEM = "G59"; + +static const char PATH_EXACT_PATH_PGMSTR[] PROGMEM = "EXACT PATH"; +static const char PATH_EXACT_STOP_PGMSTR[] PROGMEM = "EXACT STOP"; +static const char PATH_CONTINUOUS_PGMSTR[] PROGMEM = "CONTINUOUS"; + +static const char ABSOLUTE_MODE_PGMSTR[] PROGMEM = "ABSOLUTE"; +static const char INCREMENTAL_MODE_PGMSTR[] PROGMEM = "INCREMENTAL"; + + PGM_P gs_get_units_pgmstr(units_t mode) { switch (mode) { - case INCHES: return PSTR("IN"); - case MILLIMETERS: return PSTR("MM"); - case DEGREES: return PSTR("DEG"); + case INCHES: return INCHES_PGMSTR; + case MILLIMETERS: return MILLIMETERS_PGMSTR; + case DEGREES: return DEGREES_PGMSTR; } - return PSTR("INVALID"); + return INVALID_PGMSTR; +} + + +units_t gs_parse_units(const char *s) { + if (!strcmp_P(s, INCHES_PGMSTR)) return INCHES; + if (!strcmp_P(s, MILLIMETERS_PGMSTR)) return MILLIMETERS; + if (!strcmp_P(s, DEGREES_PGMSTR)) return DEGREES; + return -1; } PGM_P gs_get_feed_mode_pgmstr(feed_mode_t mode) { switch (mode) { - case INVERSE_TIME_MODE: return PSTR("INVERSE TIME"); - case UNITS_PER_MINUTE_MODE: return PSTR("PER MIN"); - case UNITS_PER_REVOLUTION_MODE: return PSTR("PER REV"); + case INVERSE_TIME_MODE: return INVERSE_TIME_MODE_PGMSTR; + case UNITS_PER_MINUTE_MODE: return UNITS_PER_MINUTE_MODE_PGMSTR; + case UNITS_PER_REVOLUTION_MODE: return UNITS_PER_REVOLUTION_MODE_PGMSTR; } - return PSTR("INVALID"); + return INVALID_PGMSTR; +} + + +feed_mode_t gs_parse_feed_mode(const char *s) { + if (!strcmp_P(s, INVERSE_TIME_MODE_PGMSTR)) return INVERSE_TIME_MODE; + if (!strcmp_P(s, UNITS_PER_MINUTE_MODE_PGMSTR)) return UNITS_PER_MINUTE_MODE; + if (!strcmp_P(s, UNITS_PER_REVOLUTION_MODE_PGMSTR)) + return UNITS_PER_REVOLUTION_MODE; + return -1; } PGM_P gs_get_plane_pgmstr(plane_t plane) { switch (plane) { - case PLANE_XY: return PSTR("XY"); - case PLANE_XZ: return PSTR("XZ"); - case PLANE_YZ: return PSTR("YZ"); + case PLANE_XY: return PLANE_XY_PGMSTR; + case PLANE_XZ: return PLANE_XZ_PGMSTR; + case PLANE_YZ: return PLANE_YZ_PGMSTR; } - return PSTR("INVALID"); + return INVALID_PGMSTR; +} + + +plane_t gs_parse_plane(const char *s) { + if (!strcmp_P(s, PLANE_XY_PGMSTR)) return PLANE_XY; + if (!strcmp_P(s, PLANE_XZ_PGMSTR)) return PLANE_XZ; + if (!strcmp_P(s, PLANE_YZ_PGMSTR)) return PLANE_YZ; + return -1; } PGM_P gs_get_coord_system_pgmstr(coord_system_t cs) { switch (cs) { - case ABSOLUTE_COORDS: return PSTR("ABS"); - case G54: return PSTR("G54"); - case G55: return PSTR("G55"); - case G56: return PSTR("G56"); - case G57: return PSTR("G57"); - case G58: return PSTR("G58"); - case G59: return PSTR("G59"); + case ABSOLUTE_COORDS: return ABSOLUTE_COORDS_PGMSTR; + case G54: return G54_PGMSTR; + case G55: return G55_PGMSTR; + case G56: return G56_PGMSTR; + case G57: return G57_PGMSTR; + case G58: return G58_PGMSTR; + case G59: return G59_PGMSTR; } - return PSTR("INVALID"); + return INVALID_PGMSTR; +} + + +coord_system_t gs_parse_coord_system(const char *s) { + if (!strcmp_P(s, ABSOLUTE_COORDS_PGMSTR)) return ABSOLUTE_COORDS; + if (!strcmp_P(s, G54_PGMSTR)) return G54; + if (!strcmp_P(s, G55_PGMSTR)) return G55; + if (!strcmp_P(s, G56_PGMSTR)) return G56; + if (!strcmp_P(s, G57_PGMSTR)) return G57; + if (!strcmp_P(s, G58_PGMSTR)) return G58; + if (!strcmp_P(s, G59_PGMSTR)) return G59; + return -1; } PGM_P gs_get_path_mode_pgmstr(path_mode_t mode) { switch (mode) { - case PATH_EXACT_PATH: return PSTR("EXACT PATH"); - case PATH_EXACT_STOP: return PSTR("EXACT STOP"); - case PATH_CONTINUOUS: return PSTR("CONTINUOUS"); + case PATH_EXACT_PATH: return PATH_EXACT_PATH_PGMSTR; + case PATH_EXACT_STOP: return PATH_EXACT_STOP_PGMSTR; + case PATH_CONTINUOUS: return PATH_CONTINUOUS_PGMSTR; } - return PSTR("INVALID"); + return INVALID_PGMSTR; +} + + +path_mode_t gs_parse_path_mode(const char *s) { + if (!strcmp_P(s, PATH_EXACT_PATH_PGMSTR)) return PATH_EXACT_PATH; + if (!strcmp_P(s, PATH_EXACT_STOP_PGMSTR)) return PATH_EXACT_STOP; + if (!strcmp_P(s, PATH_CONTINUOUS_PGMSTR)) return PATH_CONTINUOUS; + return -1; } PGM_P gs_get_distance_mode_pgmstr(distance_mode_t mode) { switch (mode) { - case ABSOLUTE_MODE: return PSTR("ABSOLUTE"); - case INCREMENTAL_MODE: return PSTR("INCREMENTAL"); + case ABSOLUTE_MODE: return ABSOLUTE_MODE_PGMSTR; + case INCREMENTAL_MODE: return INCREMENTAL_MODE_PGMSTR; } - return PSTR("INVALID"); + return INVALID_PGMSTR; +} + + +distance_mode_t gs_parse_distance_mode(const char *s) { + if (!strcmp_P(s, ABSOLUTE_MODE_PGMSTR)) return ABSOLUTE_MODE; + if (!strcmp_P(s, INCREMENTAL_MODE_PGMSTR)) return INCREMENTAL_MODE; + return -1; } diff --git a/avr/src/gcode_state.h b/avr/src/gcode_state.h index 8e15416..214469b 100644 --- a/avr/src/gcode_state.h +++ b/avr/src/gcode_state.h @@ -189,8 +189,14 @@ typedef struct { PGM_P gs_get_units_pgmstr(units_t mode); +units_t gs_parse_units(const char *units); PGM_P gs_get_feed_mode_pgmstr(feed_mode_t mode); +feed_mode_t gs_parse_feed_mode(const char *mode); PGM_P gs_get_plane_pgmstr(plane_t plane); +plane_t gs_parse_plane(const char *plane); PGM_P gs_get_coord_system_pgmstr(coord_system_t cs); +coord_system_t gs_parse_coord_system(const char *cs); PGM_P gs_get_path_mode_pgmstr(path_mode_t mode); +path_mode_t gs_parse_path_mode(const char *mode); PGM_P gs_get_distance_mode_pgmstr(distance_mode_t mode); +distance_mode_t gs_parse_distance_mode(const char *mode); diff --git a/avr/src/machine.c b/avr/src/machine.c index dae6527..bf8a4fc 100644 --- a/avr/src/machine.c +++ b/avr/src/machine.c @@ -366,22 +366,26 @@ void machine_init() { // These functions assume input validation occurred upstream. /// G17, G18, G19 select axis plane -void mach_set_plane(plane_t plane) {mach.gm.plane = plane;} +void mach_set_plane(plane_t plane) { + if (plane != (plane_t)-1) mach.gm.plane = plane; +} /// G20, G21 -void mach_set_units(units_t mode) {mach.gm.units = mode;} +void mach_set_units(units_t mode) { + if (mode != (units_t)-1) mach.gm.units = mode; +} /// G90, G91 void mach_set_distance_mode(distance_mode_t mode) { - mach.gm.distance_mode = mode; + if (mode != (distance_mode_t)-1) mach.gm.distance_mode = mode; } /// G90.1, G91.1 void mach_set_arc_distance_mode(distance_mode_t mode) { - mach.gm.arc_distance_mode = mode; + if (mode != (distance_mode_t)-1) mach.gm.arc_distance_mode = mode; } @@ -400,8 +404,8 @@ void mach_set_coord_offsets(coord_system_t coord_system, float offset[], /// G54-G59 -void mach_set_coord_system(coord_system_t coord_system) { - mach.gm.coord_system = coord_system; +void mach_set_coord_system(coord_system_t cs) { + if (cs != (coord_system_t)-1) mach.gm.coord_system = cs; } @@ -614,7 +618,7 @@ void mach_set_feed_rate(float feed_rate) { /// G93, G94 void mach_set_feed_mode(feed_mode_t mode) { - if (mach.gm.feed_mode == mode) return; + if (mode == (feed_mode_t)-1 || mach.gm.feed_mode == mode) return; mach.gm.feed_rate = 0; // Force setting feed rate after changing modes mach.gm.feed_mode = mode; } @@ -622,7 +626,7 @@ void mach_set_feed_mode(feed_mode_t mode) { /// G61, G61.1, G64 void mach_set_path_mode(path_mode_t mode) { - mach.gm.path_mode = mode; + if (mode != (path_mode_t)-1) mach.gm.path_mode = mode; } @@ -705,6 +709,18 @@ void mach_flood_coolant_control(bool flood_coolant) { * http://www.linuxcnc.org/docs/2.4/html/gcode_main.html#sec:M50:-Feed-Override */ +void mach_set_feed_override(float value) { + mach.gm.feed_override = value; + mach.gm.feed_override_enable = !fp_ZERO(value); +} + + +void mach_set_spindle_override(float value) { + mach.gm.spindle_override = value; + mach.gm.spindle_override_enable = !fp_ZERO(value); +} + + /// M48, M49 void mach_override_enables(bool flag) { mach.gm.feed_override_enable = flag; diff --git a/avr/src/machine.h b/avr/src/machine.h index ba8591b..d3b09a2 100644 --- a/avr/src/machine.h +++ b/avr/src/machine.h @@ -123,6 +123,8 @@ void mach_change_tool(bool x); void mach_mist_coolant_control(bool mist_coolant); void mach_flood_coolant_control(bool flood_coolant); +void mach_set_feed_override(float override); +void mach_set_spindle_override(float override); void mach_override_enables(bool flag); void mach_feed_override_enable(bool flag); void mach_spindle_override_enable(bool flag); diff --git a/avr/src/plan/jog.c b/avr/src/plan/jog.c index af5a8af..e2a9682 100644 --- a/avr/src/plan/jog.c +++ b/avr/src/plan/jog.c @@ -68,6 +68,8 @@ static stat_t _exec_jog(mp_buffer_t *bf) { bool done = true; if (!jr.writing) for (int axis = 0; axis < AXES; axis++) { + if (!axis_is_enabled(axis)) continue; + float Vn = jr.next_velocity[axis] * axis_get_velocity_max(axis); float Vi = jr.velocity[axis]; float Vt = jr.target_velocity[axis]; @@ -90,6 +92,8 @@ static stat_t _exec_jog(mp_buffer_t *bf) { // Compute per axis velocities for (int axis = 0; axis < AXES; axis++) { + if (!axis_is_enabled(axis)) continue; + float V = fabs(jr.velocity[axis]); float Vt = fabs(jr.target_velocity[axis]); diff --git a/avr/src/varcb.c b/avr/src/varcb.c index cb3a076..ecbd56a 100644 --- a/avr/src/varcb.c +++ b/avr/src/varcb.c @@ -42,19 +42,13 @@ void set_position(int axis, float position) { } -// GCode +// GCode getters int32_t get_line() {return mp_runtime_get_line();} PGM_P get_unit() {return gs_get_units_pgmstr(mach_get_units());} float get_speed() {return spindle_get_speed();} float get_feed() {return mach_get_feed_rate();} // TODO get runtime value uint8_t get_tool() {return mp_runtime_get_tool();} - - -PGM_P get_feed_mode() { - return gs_get_feed_mode_pgmstr(mach_get_feed_mode()); -} - - +PGM_P get_feed_mode() {return gs_get_feed_mode_pgmstr(mach_get_feed_mode());} PGM_P get_plane() {return gs_get_plane_pgmstr(mach_get_plane());} @@ -82,6 +76,56 @@ float get_speed_override() {return mach_get_spindle_override();} bool get_mist_coolant() {return coolant_get_mist();} bool get_flood_coolant() {return coolant_get_flood();} + +// GCode setters +void set_unit(const char *units) {mach_set_units(gs_parse_units(units));} +void set_speed(float speed) {spindle_set_speed(speed);} +void set_feed(float feed) {mach_set_feed_rate(feed);} + + +void set_tool(uint8_t tool) { + mp_runtime_set_tool(tool); + mach_select_tool(tool); +} + + +void set_feed_mode(const char *mode) { + mach_set_feed_mode(gs_parse_feed_mode(mode)); +} + + +void set_plane(const char *plane) {mach_set_plane(gs_parse_plane(plane));} + + +void set_coord_system(const char *cs) { + mach_set_coord_system(gs_parse_coord_system(cs)); +} + + +void set_abs_override(bool enable) {mach_set_absolute_mode(enable);} + + +void set_path_mode(const char *mode) { + mach_set_path_mode(gs_parse_path_mode(mode)); +} + + +void set_distance_mode(const char *mode) { + mach_set_distance_mode(gs_parse_distance_mode(mode)); +} + + +void set_arc_dist_mode(const char *mode) { + mach_set_arc_distance_mode(gs_parse_distance_mode(mode)); +} + + +void set_feed_override(float value) {mach_set_feed_override(value);} +void set_speed_override(float value) {mach_set_spindle_override(value);} +void set_mist_coolant(bool enable) {coolant_set_mist(enable);} +void set_flood_coolant(bool enable) {coolant_set_flood(enable);} + + // System float get_velocity() {return mp_runtime_get_velocity();} bool get_echo() {return usart_is_set(USART_ECHO);} diff --git a/avr/src/vars.c b/avr/src/vars.c index d1dfe57..2af5d46 100644 --- a/avr/src/vars.c +++ b/avr/src/vars.c @@ -72,6 +72,7 @@ static void var_print_string(string s) {printf_P(PSTR("\"%s\""), s);} // Program string static void var_print_pstring(pstring s) {printf_P(PSTR("\"%"PRPSTR"\""), s);} +static const char *var_parse_pstring(const char *value) {return value;} // Flags diff --git a/avr/src/vars.def b/avr/src/vars.def index 763d5d2..15e88a2 100644 --- a/avr/src/vars.def +++ b/avr/src/vars.def @@ -100,21 +100,21 @@ VAR(huanyang_connected, he, bool, 0, 0, 1, "Huanyang connected") // GCode VAR(line, ln, int32_t, 0, 0, 1, "Last GCode line executed") -VAR(unit, u, pstring, 0, 0, 1, "Current unit of measure") -VAR(speed, s, float, 0, 0, 1, "Current spindle speed") -VAR(feed, f, float, 0, 0, 1, "Current feed rate") -VAR(tool, t, uint8_t, 0, 0, 1, "Current tool") -VAR(feed_mode, fm, pstring, 0, 0, 1, "Current feed rate mode") -VAR(plane, pa, pstring, 0, 0, 1, "Current plane") -VAR(coord_system, cs, pstring, 0, 0, 1, "Current coordinate system") -VAR(abs_override, ao, bool, 0, 0, 1, "Absolute override enabled") -VAR(path_mode, pc, pstring, 0, 0, 1, "Current path control mode") -VAR(distance_mode, dm, pstring, 0, 0, 1, "Current distance mode") -VAR(arc_dist_mode, ad, pstring, 0, 0, 1, "Current arc distance mode") -VAR(mist_coolant, mc, bool, 0, 0, 1, "Mist coolant enabled") -VAR(flood_coolant, fc, bool, 0, 0, 1, "Flood coolant enabled") -VAR(feed_override, fo, float, 0, 0, 1, "Feed rate override") -VAR(speed_override, so, float, 0, 0, 1, "Spindle speed override") +VAR(unit, u, pstring, 0, 1, 1, "Current unit of measure") +VAR(speed, s, float, 0, 1, 1, "Current spindle speed") +VAR(feed, f, float, 0, 1, 1, "Current feed rate") +VAR(tool, t, uint8_t, 0, 1, 1, "Current tool") +VAR(feed_mode, fm, pstring, 0, 1, 1, "Current feed rate mode") +VAR(plane, pa, pstring, 0, 1, 1, "Current plane") +VAR(coord_system, cs, pstring, 0, 1, 1, "Current coordinate system") +VAR(abs_override, ao, bool, 0, 1, 1, "Absolute override enabled") +VAR(path_mode, pc, pstring, 0, 1, 1, "Current path control mode") +VAR(distance_mode, dm, pstring, 0, 1, 1, "Current distance mode") +VAR(arc_dist_mode, ad, pstring, 0, 1, 1, "Current arc distance mode") +VAR(feed_override, fo, float, 0, 1, 1, "Feed rate override") +VAR(speed_override, so, float, 0, 1, 1, "Spindle speed override") +VAR(mist_coolant, mc, bool, 0, 1, 1, "Mist coolant enabled") +VAR(flood_coolant, fc, bool, 0, 1, 1, "Flood coolant enabled") // System VAR(velocity, v, float, 0, 0, 1, "Current velocity") diff --git a/src/js/app.js b/src/js/app.js index a5092ef..a4fc937 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -77,7 +77,7 @@ module.exports = new Vue({ connect: function () { - this.sock = new Sock('//' + window.location.host + '/ws'); + this.sock = new Sock('//' + window.location.host + '/sockjs'); this.sock.onmessage = function (e) { var msg = e.data; diff --git a/src/py/bbctrl/AVR.py b/src/py/bbctrl/AVR.py index 824093b..a238b53 100644 --- a/src/py/bbctrl/AVR.py +++ b/src/py/bbctrl/AVR.py @@ -30,6 +30,11 @@ I2C_REBOOT = 10 I2C_ZERO = 11 +machine_state_vars = ''' + xp yp zp ap bp cp u s f t fm pa cs ao pc dm ad fo so mc fc +'''.split() + + class AVR(): def __init__(self, ctrl): self.ctrl = ctrl @@ -81,6 +86,7 @@ class AVR(): # Reset AVR communication self.stop(); self.ctrl.config.config_avr() + self._restore_machine_state() self.report() except Exception as e: @@ -121,6 +127,16 @@ class AVR(): raise + def _restore_machine_state(self): + for var in machine_state_vars: + if var in self.vars: + value = self.vars[var] + if isinstance(value, str): value = '"' + value + '"' + if isinstance(value, bool): value = int(value) + + self.queue_command('${}={}'.format(var, value)) + + def report(self): self._i2c_command(I2C_REPORT) @@ -157,7 +173,7 @@ class AVR(): self.command = None # Load next command from queue - if len(self.queue): self.load_next_command(self.queue.pop()) + if len(self.queue): self.load_next_command(self.queue.popleft()) # Load next GCode command, if running or paused elif self.stream is not None: diff --git a/src/py/bbctrl/LCD.py b/src/py/bbctrl/LCD.py index ec9eeba..e3f015d 100644 --- a/src/py/bbctrl/LCD.py +++ b/src/py/bbctrl/LCD.py @@ -112,12 +112,12 @@ class LCD: self.text('%-9s' % state, 0, 0) - if 'xp' in msg: self.text('% 10.4fX' % msg['xp'], 9, 0) - if 'yp' in msg: self.text('% 10.4fY' % msg['yp'], 9, 1) - if 'zp' in msg: self.text('% 10.4fZ' % msg['zp'], 9, 2) - if 'ap' in msg: self.text('% 10.4fA' % msg['ap'], 9, 3) + if 'xp' in msg: self.text('% 10.3fX' % msg['xp'], 9, 0) + if 'yp' in msg: self.text('% 10.3fY' % msg['yp'], 9, 1) + if 'zp' in msg: self.text('% 10.3fZ' % msg['zp'], 9, 2) + if 'ap' in msg: self.text('% 10.3fA' % msg['ap'], 9, 3) if 't' in msg: self.text('%2uT' % msg['t'], 6, 1) - if 'u' in msg: self.text('%s' % msg['u'], 0, 1) + if 'u' in msg: self.text('%-6s' % msg['u'], 0, 1) if 'f' in msg: self.text('%8uF' % msg['f'], 0, 2) if 's' in msg: self.text('%8dS' % msg['s'], 0, 3) diff --git a/src/py/bbctrl/Web.py b/src/py/bbctrl/Web.py index 001509a..6bcf721 100644 --- a/src/py/bbctrl/Web.py +++ b/src/py/bbctrl/Web.py @@ -92,7 +92,38 @@ class OverrideSpeedHandler(bbctrl.APIHandler): def put_ok(self, value): self.ctrl.avr.override_speed(float(value)) -class Connection(sockjs.tornado.SockJSConnection): +class WSConnection(tornado.websocket.WebSocketHandler): + def __init__(self, app, request, **kwargs): + super(WSConnection, self).__init__(app, request, **kwargs) + self.ctrl = app.ctrl + self.timer = None + + + def heartbeat(self): + self.timer = self.ctrl.ioloop.call_later(3, self.heartbeat) + self.write_message({'heartbeat': self.count}) + self.count += 1 + + + def open(self): + self.clients = self.ctrl.web.ws_clients + + self.timer = self.ctrl.ioloop.call_later(3, self.heartbeat) + self.count = 0; + + self.clients.append(self) + self.write_message(self.ctrl.avr.vars) + + + def on_close(self): + if self.timer is not None: self.ctrl.ioloop.remove_timeout(self.timer) + self.clients.remove(self) + + + def on_message(self, msg): pass + + +class SockJSConnection(sockjs.tornado.SockJSConnection): def heartbeat(self): self.timer = self.ctrl.ioloop.call_later(3, self.heartbeat) self.send({'heartbeat': self.count}) @@ -101,7 +132,7 @@ class Connection(sockjs.tornado.SockJSConnection): def on_open(self, info): self.ctrl = self.session.server.ctrl - self.clients = self.ctrl.web.clients + self.clients = self.ctrl.web.sockjs_clients self.timer = self.ctrl.ioloop.call_later(3, self.heartbeat) self.count = 0; @@ -128,9 +159,11 @@ class StaticFileHandler(tornado.web.StaticFileHandler): class Web(tornado.web.Application): def __init__(self, ctrl): self.ctrl = ctrl - self.clients = [] + self.ws_clients = [] + self.sockjs_clients = [] handlers = [ + (r'/websocket', WSConnection), (r'/api/config/load', ConfigLoadHandler), (r'/api/config/download', ConfigDownloadHandler), (r'/api/config/save', ConfigSaveHandler), @@ -154,7 +187,7 @@ class Web(tornado.web.Application): "default_filename": "index.html"}), ] - router = sockjs.tornado.SockJSRouter(Connection, '/ws') + router = sockjs.tornado.SockJSRouter(SockJSConnection, '/sockjs') router.ctrl = ctrl tornado.web.Application.__init__(self, router.urls + handlers) @@ -171,5 +204,7 @@ class Web(tornado.web.Application): def broadcast(self, msg): - if len(self.clients): - self.clients[0].broadcast(self.clients, msg) + if len(self.sockjs_clients): + self.sockjs_clients[0].broadcast(self.sockjs_clients, msg) + + for client in self.ws_clients: client.write_message(msg) -- 2.27.0