Open Guenni75 opened 3 years ago
@Guenni75 Have you tried directly from bCNC first?
Make sure that you are connected to pendant and can run some code locally via bCNC through the pendant.
Personally, I stopped using Lubuntu a long time ago because of issues with camera, web, etc. I found Linux Mint XFCE versions to fit the bill a bit better, I use the 32-bit versions for my old machines and of course the 64-bit for the newer. I stay away from Cinnamon and Mate, because I prefer lightweight OSes myself.
@Guenni75 Did some further investigating on my end and it does have an issue when opening a file in pendant. It works in Python2, however it needs patching for Python3.
I will reply back as soon as I have a patch for it.
@Guenni75 @Harvie and anyone else that would like to test the following before a commit.
Tested in python 2.7.14 (already worked there) and 3.8.2 (lots of issues there) Pendant.py.zip
Pendant.py
for those that don't like to download anything suspicious:
# -*- coding: ascii -*-
# $Id$
#
# Author: Vasilis Vlachoudis
# Email: vvlachoudis@gmail.com
# Date: 24-Aug-2014
from __future__ import absolute_import
from __future__ import print_function
__author__ = "Vasilis Vlachoudis"
__email__ = "Vasilis.Vlachoudis@cern.ch"
import os
import re
import sys
#import cgi
import json
#import urllib
import tempfile
import threading
# ---------------------------------------
# For debugging issues
# ---------------------------------------
import traceback
from errno import EPIPE
try:
broken_pipe_error = BrokenPipeError # Python3 has: BrokenPipeError
except NameError:
broken_pipe_error = IOError
# ---------------------------------------
try:
import urllib.parse as urlparse
from urllib.parse import unquote
except ImportError:
import urlparse
from urllib import unquote as unquote
try:
import http.server as HTTPServer
except ImportError:
import BaseHTTPServer as HTTPServer
try:
from PIL import Image
except ImportError:
Image = None
from CNC import CNC
from Utils import prgpath
import Camera
HOSTNAME = "localhost"
port = 8080
httpd = None
webpath = "%s/pendant"%(prgpath)
iconpath = "%s/icons/"%(prgpath)
#==============================================================================
# Simple Pendant controller for CNC
#==============================================================================
class Pendant(HTTPServer.BaseHTTPRequestHandler):
camera = None
#----------------------------------------------------------------------
def log_message(self, fmt, *args):
# Only log requests to the main page, ignore the rest
if args[0].startswith("GET / ") or args[0].startswith("GET /send"):
args = list(args)
args[0] = "%s : %s"%(self.address_string(),args[0])
HTTPServer.BaseHTTPRequestHandler.log_message(self, fmt, *args)
#----------------------------------------------------------------------
def do_HEAD(self, rc=200, content="text/html", cl=0):
self.send_response(rc)
self.send_header("Content-type", content)
if cl != 0:
self.send_header("Content-length", cl)
self.end_headers()
#----------------------------------------------------------------------
def do_GET(self):
"""Respond to a GET request."""
if "?" in self.path:
page,arg = self.path.split("?",1)
arg = dict(urlparse.parse_qsl(arg))
else:
page = self.path
arg = None
# print(self.path,type(self.path))
# print(page)
# print(arg)
if page == "/send":
if arg is None: return
for (key,value) in arg.items():
if key=="gcode":
for line in value.split('\n'):
httpd.app.queue.put('%s\n'%(line))
elif key=="cmd":
httpd.app.pendant.put(unquote(value))
# Send empty response so browser does not generate errors
self.do_HEAD(200, "text/text", cl=len(""))
self.wfile.write("".encode())
elif page == "/state":
tmp = {}
for name in ["controller", "state", "pins", "color", "msg", "wx", "wy", "wz", "G", "OvFeed", "OvRapid", "OvSpindle"]:
tmp[name] = CNC.vars[name]
contentToSend = json.dumps(tmp)
self.do_HEAD(200, content="text/text", cl=len(contentToSend))
self.wfile.write(contentToSend.encode())
elif page == "/config":
snd = {}
snd["rpmmax"] = httpd.app.get("CNC","spindlemax")
contentToSend = json.dumps(snd)
self.do_HEAD(200, content="text/text", cl=len(contentToSend))
self.wfile.write(contentToSend.encode())
elif page == "/icon":
if arg is None: return
filename = os.path.join(iconpath, arg["name"]+".gif")
self.do_HEAD(200, content="image/gif", cl=os.path.getsize(filename))
try:
f = open(filename,"rb")
self.wfile.write(f.read())
f.close()
except:
pass
elif page == "/canvas":
if not Image: return
with tempfile.NamedTemporaryFile(suffix='.ps') as tmp:
httpd.app.canvas.postscript(
file=tmp.name,
colormode='color',
)
tmp.flush()
try:
with tempfile.NamedTemporaryFile(suffix='.gif') as out:
Image.open(tmp.name).save(out.name, 'GIF')
out.flush()
out.seek(0)
self.do_HEAD(200, content="image/gif", cl=os.path.getsize(tmp.name))
# self.wfile.write(out.read())
try:
self.wfile.write(out.read())
except broken_pipe_error as exc: # [Errno 32] Broken pipe
if broken_pipe_error == IOError:
if exc.errno != EPIPE:
raise
# print('do_GET:\n %s: %s [Errno %s] [EPIPE %s]'%(
# broken_pipe_error, exc, exc.errno, EPIPE))
# print(traceback.format_exc())
except:
filename = os.path.join(iconpath, "warn.gif")
self.do_HEAD(200, content="image/gif", cl=os.path.getsize(filename))
try:
f = open(filename,"rb")
self.wfile.write(f.read())
f.close()
except:
pass
elif page == "/camera":
if not Camera.hasOpenCV(): return
if Pendant.camera is None:
Pendant.camera = Camera.Camera("webcam")
Pendant.camera.start()
if Pendant.camera.read():
Pendant.camera.save("camera.jpg")
#cv.imwrite("camera.jpg",img)
self.do_HEAD(200, content="image/jpeg", cl=os.path.getsize("camera.jpg"))
try:
f = open("camera.jpg","rb")
self.wfile.write(f.read())
f.close()
except:
pass
else:
self.mainPage(page[1:])
#----------------------------------------------------------------------
def deal_post_data(self):
boundary = None # FIX: UnboundLocalError: local variable 'boundary' referenced before assignment
#boundary = self.headers.plisttext.split("=")[1] # AttributeError: 'HTTPMessage' object has no attribute 'plisttext'
try:
boundary = self.headers.plisttext.split("=")[1] # plisttext is from mimetools and has been deprecated in favor of email, but whatever!
except Exception as exc:
#print('deal_post_data:\n Exception: %s'%(exc))
boundary = self.headers.get_boundary() # HTTPMessage has this, though
if boundary is None:
return (False, "boundary is None")
remainbytes = int(self.headers['content-length'])
#line = self.rfile.readline()
line = self.rfile.readline().decode()
remainbytes -= len(line)
if not boundary in line:
return (False, "Content NOT begin with boundary")
#line = self.rfile.readline()
line = self.rfile.readline().decode()
remainbytes -= len(line)
fn = re.findall(r'Content-Disposition.*name="file"; filename="(.*)"', line)
if not fn:
return (False, "Can't find out file name...")
path = os.path.expanduser("~")
path = os.path.join(path, "bCNCUploads")
if not os.path.exists(path):
os.makedirs(path)
fn = os.path.join(path, fn[0])
#line = self.rfile.readline()
line = self.rfile.readline().decode()
remainbytes -= len(line)
#line = self.rfile.readline()
line = self.rfile.readline().decode()
remainbytes -= len(line)
try:
out = open(fn, 'wb')
# except IOError:
except Exception as exc:
print('deal_post_data:\n Exception: %s'%(exc))
return (False, "Can't create file to write, do you have permission to write?")
#preline = self.rfile.readline()
preline = self.rfile.readline().decode()
remainbytes -= len(preline)
while remainbytes > 0:
#line = self.rfile.readline()
line = self.rfile.readline().decode()
remainbytes -= len(line)
if boundary in line:
preline = preline[0:-1]
if preline.endswith('\r'):
preline = preline[0:-1]
#out.write(preline)
if isinstance(preline, bytes):
out.write(preline)
else:
out.write(preline.encode())
out.close()
return (True, "%s" % fn)
else:
#out.write(preline)
if isinstance(preline, bytes):
out.write(preline)
else:
out.write(preline.encode())
preline = line
return (False, "Unexpected End of data.")
#----------------------------------------------------------------------
def do_POST(self):
result,fMsg = self.deal_post_data()
if(result):
httpd.app._pendantFileUploaded = fMsg
# Send empty response so browser does not generate errors
#self.do_HEAD(200, "text/text")
try:
self.do_HEAD(200, "text/text")
except Exception as exc:
print('do_POST:\n Exception: %s'%(exc))
# ---------------------------------------------------------------------
def mainPage(self, page):
global webpath
# Handle certain filetypes
filetype = page.rpartition('.')[2]
if filetype == "css": self.do_HEAD(content="text/css")
elif filetype == "js": self.do_HEAD(content="application/x-javascript")
elif filetype == "json": self.do_HEAD(content="application/json")
elif filetype == "jpg" or filetype == "jpeg" : self.do_HEAD(content="image/jpeg")
elif filetype == "gif": self.do_HEAD(content="image/gif")
elif filetype == "png": self.do_HEAD(content="image/png")
elif filetype == "ico": self.do_HEAD(content="image/x-icon")
else: self.do_HEAD()
if page == "": page = "index.html"
try:
f = open(os.path.join(webpath,page),"rb")
self.wfile.write(f.read())
f.close()
# except IOError: # XXX: This was blocking: FileNotFoundError
except Exception as exc:
#FileNotFoundError: [Errno 2] No such file or directory: '/bCNC/pendant/favicon.ico'
print('mainPage:\n Exception: %s'%(exc))
self.wfile.write("""<!DOCTYPE html>
<html>
<head>
<title>Errortitle</title>
<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=yes" />
</head>
<body>
Page not found.
</body>
</html>
""".encode())
# -----------------------------------------------------------------------------
def _server(app):
global httpd
server_class = HTTPServer.HTTPServer
try:
httpd = server_class(('', port), Pendant)
httpd.app = app
httpd.serve_forever()
except:
httpd = None
# -----------------------------------------------------------------------------
def start(app):
global httpd
if httpd is not None: return False
thread = threading.Thread(target=_server, args=(app,))
thread.start()
return True
# -----------------------------------------------------------------------------
def stop():
global httpd
if httpd is None: return False
httpd.shutdown()
httpd = None
if Pendant.camera: Pendant.camera.stop()
return True
if __name__ == '__main__':
start()
Hi. After Updating to Ubuntu 20..., i made another try without the pendant.py above. Browser and bCNC were on the same PC. This is the Terminaltext:
Next i try the pendant.py above....
The same problem with the new pendant.py.
I installed the last bCNC with Python 2.7 on Win10 and the Pendant only shows a warning sign ;(
The same with the new pendant.py ;(
That is a common error that comes from socket (not bCNC) and can be ignored. But what about it actually working now with the patched file?
As I wrote above:
The same with the new pendant.py ;(
Do you have any issues with serial communication between bCNC and your CNC machine? How are you connected from android to the pendant? Have you tried connecting bCNC using spy:// from the terminal to see what's going on?
Lots of questions, but any info you can give would really be appreciated!
@Guenni75 At first, I didn't see that your video shows a part in it (it only flickered). It seems to me that something is happening at network level connection wise. Maybe, you can check out these #1072 and #1121 Possibly @qvisionsa or @PCSDIAS may have some info that can help you resolve this issue.
@GizHubCaps Ar first, yes.... it flickers and you can see the part not even a second. That's why I opened this issue.
A have one bCnc on lubuntu and one on Win10. Both with Python 2.7. The serial communication works without any issue. At the Linux Version i have this flickering with and without a connection to the CNC (pendant opened on the same PC and on a remote PC). At the Win10 Version the pendant shows no flickering, but a warning sign instead of the part. On both Versions, moving, homing and so on works fine. I don't know how to connect bCNC with Spy.
I noticed that the name of the file you were running is in unicode. Have you tested with an ascii formatted file and possibly using bCNC with English? May not be an issue, but wouldn't hurt to eliminate as much as possible.
As far as the error
and BrokenPipeError
py2/3 respectively, those can generally be ignored, (serial is negotiating connections) sometimes, I have a few show and other times non at all.
The flickering may be due to network connection issues (seeing that the part at least shows up) but not sure atm. Hopefully, if someone else has had this issue before, maybe we could get some more information.
In bCNC where you connect to usb File -> Serial -> Port:
is an option for spy://
Also, there's info in the README and manual.
Note: I will have something up soon to fix some encoding bugs (for both) and the file open in py3 Don't know if that will help you or not, but we'll see.
@Guenni75 Also, if you can, zip the file and upload it here (drag/drop into comment box) so I can test it directly to see if it gives me the same issue.
Just reporting in I am having the same issue. I'm running the latest dev on a pi3 using python3 (installed via pip yesterday). Both local browser and remote (chrome on win10) display the flickering issue. I have very little understanding to help troubleshoot any networking issues related to this, but I have seen in chrome Dev tools the same thing as pcsdias here: https://github.com/vlachoudis/bCNC/issues/1121#issuecomment-452682544
The canvas keeps failing to load, and I get the same error messages on the terminal of "An established connection was aborted by the software on the host computer". There is also a repeating message in chrome debug console Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH
I can share additional files/info if it would be helpful to fix this. I can say I have tried with several different gcode files and encoding does not appear to solve this. So I don't think it's anything to do with that. Also note I previously had installed bCNC with python2 a few months ago, and it was behaving the same way.
@GitHubCaps It doesn't matter which file i use. It's always the same. Even with files made in bCNC. Since a few months, i only get a warning sign.
I too am having the same issue as the op's video, I'm using chromium on a pi4 connecting to another pi4 running bCNC on the lan.
The "http://192.168.0.34:8080/canvas?1634910941466?1634910....." displays fine in another tab, but only occasionally on the Pendant page, most of the time it shows a "picture placeholder icon" that flashes about once a second. And everything below it on the page, leaps up and down.
The browser console fills up with GET http://192.168.0.34:8080/canvas?1634910941466?1634910942463?1634910943460?1634910944459?1634910945459?1634910946459?1634910947460?1634910948462?1634910949463?1634910950461?1634910951461?1634910952465?1634910953462?1634910954459?1634910955464?1634910956460?1634910957461?1634910958464?1634910959460?1634910960461?1634910961459?1634910962462?1634910963460?1634910964460?1634910965459?1634910966459?1634910968125?1634910969127?1634910970125?1634910971126?1634910972127?1634910973126?1634910974127?1634910975130?1634910976126?1634910977127?1634910978126?1634910979125?1634910980125?1634910981126?1634910982124?1634910983128?1634910984126?1634910985125?1634910985598?1634910986459?1634910987459?1634910988461?1634910989460?1634910990461?1634910991460?1634910992465?1634910993460?1634910994459?1634910995459?1634910996460?1634910997460?1634910998461?1634910999459?1634911000460?1634911001459?1634911002460?1634911003462?1634911005125?1634911006125?1634911007127?1634911008127?1634911009126?1634911010126?1634911011126?1634911012127?1634911013127?1634911014130?1634911015127?1634911015604?1634911016461?1634911017465?1634911018460?1634911019459?1634911020460?1634911021460?1634911022460?1634911023459?1634911024459?1634911025459?1634911026464?1634911027459?1634911028546?1634911029460?1634911030460?1634911031460?1634911032460?1634911033459?1634911034459?1634911035459?1634911036458?1634911037460?1634911038460?1634911039460?1634911040461?1634911041460?1634911042460?1634911043459?1634911044459?1634911045459?1634911046460?1634911047505?1634911048461?1634911049460?1634911050459?1634911051460?1634911052458?1634911053461?1634911054460?1634911055459?1634911056460?1634911057460?1634911058461?1634911059465?1634911060462?1634911062126?1634911063126?1634911064126?1634911065126?1634911066125?1634911067124?1634911068126?1634911069104?1634911069459?1634911070460?1634911071458?1634911072460?1634911073460?1634911074459?1634911075460?1634911076460?1634911077464?1634911078460?1634911079460?1634911080463?1634911081474?1634911082461?1634911083460?1634911084458?1634911085460?1634911086485?1634911087459?1634911088458?1634911089460?1634911090459?1634911091460?1634911092460?1634911093458?1634911094459?1634911095458?1634911096458?1634911097459?1634911098458?1634911099462?1634911100459?1634911101459?1634911102459?1634911103461?1634911104473?1634911105460?1634911106459?1634911107461?1634911108460?1634911109460?1634911110460?1634911111459?1634911112460?1634911113461?1634911114460?1634911115459?1634911116460?1634911117460?1634911118460?1634911119460?1634911120460?1634911121460?1634911122460?1634911123458?1634911124460?1634911125460?1634911126460?1634911127460?1634911128460?1634911129460?1634911130460?1634911131460?1634911132459?1634911133460?1634911134461?1634911135460?1634911136460?1634911137463?1634911138459?1634911139460?1634911140460?1634911141460?1634911142459?1634911143460?1634911144461?1634911145461?1634911146463?1634911147459?1634911148459?1634911150125?1634911151131?1634911152125?1634911153126?1634911154126?1634911155127?1634911156146?1634911157126?1634911158126?1634911159128?1634911160126?1634911161125?1634911162127?1634911163128?1634911164126?1634911165125?1634911166127?1634911167124?1634911168128?1634911169127?1634911170126?1634911171126?1634911172127?1634911173126?1634911174126?1634911175126?1634911176127?1634911177126?1634911178127?1634911179126?1634911180127?1634911181126?1634911182126?1634911183127?1634911184128?1634911185125?1634911186128?1634911187126?1634911188127?1634911189126?1634911190126?1634911191125?1634911192126?1634911193130?1634911194128?1634911195126?1634911196125?1634911197125?1634911198127?1634911199125?1634911200124?1634911201124?1634911202124?1634911203127?1634911204125?1634911205127?1634911206126?1634911207129?1634911208127?1634911209126?1634911210124?1634911211124?1634911212126?1634911213125?1634911214127?1634911215127?1634911216146?1634911217128?1634911218126?1634911219126?1634911220129?1634911221124?1634911222126?1634911223126?1634911224125?1634911225130?1634911226126?1634911227125?1634911228127?1634911229126?1634911230126?1634911231127?1634911232126?1634911233126?1634911234126?1634911235128?1634911236128?1634911237127?1634911238126?1634911239125?1634911240127?1634911241126?1634911242124?1634911243125?1634911244126?1634911245125?1634911246126?1634911247127?1634911248125?1634911249126?1634911250127?1634911251125?1634911252126?1634911253126?1634911254126?1634911255127?1634911256125?1634911257126?1634911258126?1634911259127?1634911260126?1634911261127?1634911262125?1634911263125?1634911264127?1634911265125?1634911266129?1634911267125?1634911268128?1634911269125?1634911270127?1634911271126?1634911272128?1634911273126?1634911274125?1634911275126?1634911276131?1634911277127?1634911278125?1634911279125?1634911280126?1634911281127?1634911282130?1634911283134?1634911284134?1634911285125?1634911286126?1634911287125?1634911288127?1634911289126?1634911290126?1634911291130?1634911292127?1634911293127?1634911294126?1634911295127?1634911296126?1634911297126?1634911298126?1634911299126?1634911300126?1634911301126?1634911302127?1634911303126?1634911304127?1634911305126?1634911306124?1634911307129?1634911308127?1634911309125?1634911310126?1634911311126?1634911312126?1634911313126?1634911314127?1634911315125?1634911316133?1634911317126?1634911318126?1634911319135?1634911320127?1634911321127?1634911322125?1634911323125?1634911324126?1634911325126?1634911326128?1634911327125?1634911328133?1634911329125?1634911330126?1634911331124?1634911332127?1634911333125?1634911334124?1634911335126?1634911336128?1634911337124?1634911338126?1634911339126?1634911340125?1634911341126?1634911342126?1634911343126?1634911344125?1634911345124?1634911346125?1634911347126?1634911348125?1634911349125?1634911350125?1634911351125?1634911352126?1634911353127?1634911354127?1634911355125?1634911356126?1634911357125?1634911358124?1634911359125?1634911360125?1634911361155?1634911362125?1634911363124?1634911364126?1634911365128?1634911366125?1634911367129?1634911368125?1634911369125?1634911370126?1634911371130?1634911372129?1634911373126?1634911374127?1634911375128?1634911376127?1634911377129?1634911378130?1634911379125?1634911380127?1634911381127?1634911382125?1634911383127?1634911384126?1634911385125?1634911386124?1634911387127?1634911388126?1634911389126?1634911390126?1634911391126?1634911392126?1634911393127?1634911394127?1634911395126?1634911396133?1634911397126?1634911398126?1634911399126?1634911400126?1634911401126?1634911402130?1634911403128?1634911404129?1634911405129?1634911406127?1634911407124?1634911408126?1634911409128?1634911410127?1634911411126?1634911412126?1634911413129?1634911414124?1634911415125?1634911416124?1634911417126?1634911418126?1634911419126?1634911420127?1634911421125?1634911422127?1634911423126?1634911424127?1634911425126?1634911426126?1634911427127?1634911428126?1634911429126?1634911430127?1634911431127?1634911432134?1634911433126?1634911434125?1634911435124?1634911436127?1634911437126?1634911438126?1634911439126?1634911440126?1634911441129?1634911442127?1634911443127?1634911444124?1634911445126?1634911446127?1634911447129?1634911448127?1634911456141?1634911516138?1634911576139?1634911636135?1634911696126?1634911756139?1634911816133?1634911876129?1634911936135?1634911996141?1634912056135?1634912064559?1634912065462?1634912066461?1634912067467?1634912068460?1634912069460?1634912070459?1634912071458?1634912072460?1634912073460?1634912074458?1634912075461?1634912076481?1634912077459?1634912078461?1634912079460?1634912080462?1634912081460?1634912082460?1634912083461?1634912084460?1634912085460?1634912086460?1634912087460?1634912088460?1634912089461?1634912090463?1634912091464?1634912092460?1634912093460?1634912094460?1634912095460?1634912096461?1634912097460?1634912098460?1634912099459?1634912100472?1634912101459?1634912102461?1634912103460?1634912104460?1634912105460?1634912106460?1634912107460?1634912108464?1634912109460?1634912110458?1634912111458?1634912112462?1634912113460?1634912114461?1634912115463?1634912116459?1634912117461?1634912118461?1634912119461?1634912120460?1634912121461?1634912122461?1634912123499?1634912124462?1634912125459?1634912126460?1634912127459?1634912128461?1634912129460?1634912130460?1634912131464?1634912132460?1634912133460?1634912134460?1634912135461?1634912136462?1634912137462?1634912139125?1634912140127?1634912141126?1634912142128?1634912143126?1634912144126?1634912145128?1634912146126?1634912147126?1634912148126?1634912149125?1634912150126?1634912151126?1634912152126?1634912153126?1634912154128?1634912155125?1634912156125?1634912157125?1634912158127?1634912159126?1634912160130?1634912161127?1634912162126?1634912163127?1634912164126?1634912165125?1634912166125?1634912167126?1634912168125?1634912169125?1634912170126?1634912171124?1634912172127?1634912173126?1634912174126?1634912175126?1634912176130?1634912177126?1634912178127?1634912179126?1634912180130?1634912181126?1634912182127?1634912183126?1634912184126?1634912185126?1634912186126?1634912187125?1634912188126?1634912189127?1634912190128?1634912191128?1634912192127?1634912193126?1634912194126?1634912195126?1634912196125?1634912197133?1634912198125?1634912199124?1634912200126?1634912201127?1634912202126?1634912203128?1634912204126?1634912205126?1634912206127?1634912207127?1634912208126?1634912209125?1634912210125?1634912211126?1634912212126?1634912213127?1634912214127?1634912215126?1634912216130?1634912217125?1634912218126?1634912219126?1634912220127?1634912221125?1634912222127?1634912223128?1634912224126?1634912225126?1634912226126?1634912227126?1634912228127?1634912229126?1634912230126?1634912231126?1634912232126?1634912233126?1634912234127?1634912235126?1634912236137?1634912237125?1634912238126?1634912239126?1634912240126?1634912241127?1634912242126?1634912243126?1634912244126?1634912245126?1634912246125?1634912247125?1634912248126?1634912249126?1634912249714?1634912250458?1634912251459?1634912252459?1634912253459?1634912254463?1634912255460?1634912256460?1634912257459?1634912258459?1634912259460?1634912260459?1634912261459?1634912262459?1634912263460?1634912264460 net::ERR_CONTENT_LENGTH_MISMATCH 200 (OK)
Which doesn't look good. I hope it helps.
I was having this problem with earlier builds but with the latest version it is working again, even with python3
Make sure to install all dependecies including numpy for the latest version and you should have no problems
Happy New year. I have a Problem with the Web Pendant. It is the same on Windows, Linux, Android and every Browser i can use. bCNC is installed on Lubuntu.
https://user-images.githubusercontent.com/14917841/104018878-dbe64400-51ba-11eb-83a2-b44c898ca375.mp4