Contact me: hankecnc@gmail.com

网状挂件,画面闪烁 #1509

推推 grbl 3年前 (2023-02-02) 255次浏览
打开
Guenni75 打开了这个问题 2021 年 1 月 8 日 · 19条评论
打开

网状挂件,画面闪烁#1509

Guenni75 打开了这个问题 2021 年 1 月 8 日 · 19条评论

评论

网状挂件,画面闪烁 #1509

新年快乐。
我对 Web Pendant 有疑问。
在 Windows、Linux、Android 和我可以使用的每个浏览器上都是一样的。
bCNC 安装在 Lubuntu 上。

 Screen_Recording_20210108-135911_Chrome.mp4 

网状挂件,画面闪烁 #1509
贡献者

@Guenni75您是否首先直接从 bCNC 尝试过?

确保您已连接到 pendant,并且可以通过 bCNC 通过 pendant 在本地运行一些代码。

就个人而言,由于摄像头、网络等问题,我很久以前就停止使用 Lubuntu。我发现 Linux Mint XFCE 版本更符合要求,我在我的旧机器上使用 32 位版本,当然还有 64 位版本-位较新。我远离 Cinnamon 和 Mate,因为我自己更喜欢轻量级操作系统。

网状挂件,画面闪烁 #1509
贡献者

@Guenni75在我这边做了一些进一步的调查,当打开一个挂件文件时确实有问题。它在 Python2 中工作,但是它需要为 Python3 打补丁。

一旦我有补丁,我会尽快回复。

网状挂件,画面闪烁 #1509
贡献者
GitHubCaps 评论了 2021 年 1 月 10 日  

@Guenni75 @Harvie以及任何其他想要在提交之前测试以下内容的人。

在 python 2.7.14(已经在那里工作)和 3.8.2(那里有很多问题)
中测试 Pendant.py.zip

Pendant.py对于那些不喜欢下载任何可疑内容的人:

# -*- 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()
网状挂件,画面闪烁 #1509
作者

你好。更新到 Ubuntu 20 之后…,我在没有上面的 pendant.py 的情况下再次尝试。
浏览器和 bCNC 在同一台 PC 上。
这是终端文本:

处理来自 (‘127.0.0.1’, 46364) 的请求时发生异常
Traceback(最近调用最后一次):
文件“/usr/lib/python2.7/SocketServer.py”,第 293 行,在 _handle_request_noblock
self.process_request(request , client_address)
文件“/usr/lib/python2.7/SocketServer.py”,第 321 行,在 process_request
self.finish_request(request, client_address)
文件“/usr/lib/python2.7/SocketServer.py”,第 334 行,在 finish_request
self.RequestHandlerClass(request, client_address, self)
文件“/usr/lib/python2.7/SocketServer.py”,第 657 行,在init
self.finish()
文件“/usr/lib/python2.7/ SocketServer.py”,第 716 行,完成
self.wfile.close()
文件“/usr/lib/python2.7/socket.py”,第 283 行,在关闭
self.flush()
文件“/usr/lib/python2.7/socket.py”,第 307 行,在 flush
self._sock .sendall(view[write_offset:write_offset+buffer_size])
错误:[Errno 32] 管道损坏

接下来我尝试上面的 pendant.py ….

网状挂件,画面闪烁 #1509
作者

新的 pendant.py 也有同样的问题。

网状挂件,画面闪烁 #1509
作者

我在 Win10 上用 Python 2.7 安装了最后一个 bCNC,Pendant 只显示警告标志;(

网状挂件,画面闪烁 #1509
作者

与新的 pendant.py 相同;(

网状挂件,画面闪烁 #1509
贡献者

这是来自套接字(不是 bCNC)的常见错误,可以忽略。但是它现在实际使用修补文件呢?

网状挂件,画面闪烁 #1509
作者

正如我上面写的:

与新的 pendant.py 相同;(

网状挂件,画面闪烁 #1509
贡献者

bCNC 和您的 CNC 机床之间的串行通信有任何问题吗?你是如何从安卓连接到吊坠的?您是否尝试过从终端使用 spy:// 连接 bCNC 以查看发生了什么?

很多问题,但是您能提供的任何信息将不胜感激!

网状挂件,画面闪烁 #1509
贡献者
GitHubCaps 评论了 2021 年 1 月 13 日  

@Guenni75起初,我没有看到您的视频显示其中的一部分(它只是闪烁)。
在我看来,在网络级连接方面正在发生某些事情。
也许,你可以看看这些#1072#1121
可能@qvisionsa或者@PCSDIAS可能有一些信息可以帮助您解决此问题。

网状挂件,画面闪烁 #1509
作者

@GizHubCaps Ar 首先,是的……它在闪烁,您甚至连一秒钟都看不到零件。这就是我打开这个问题的原因。

网状挂件,画面闪烁 #1509
作者

A 在 lubuntu 上有一个 bCnc,在 Win10 上有一个。两者都使用 Python 2.7。
串行通信工作没有任何问题。
在 Linux 版本中,无论是否连接到 CNC(在同一台 PC 和远程 PC 上打开的挂件),我都会出现这种闪烁。
在 Win10 版本中,吊坠没有闪烁,而是警告标志,而不是零件。
在这两个版本上,移动、归位等都可以正常工作。
我不知道如何将 bCNC 与 Spy 连接起来。

网状挂件,画面闪烁 #1509
贡献者
GitHubCaps 评论了 2021 年 1 月 15 日  

我注意到您正在运行的文件的名称是 unicode。您是否测试过 ascii 格式的文件并可能使用英语的 bCNC?可能不是问题,但尽可能多地消除也无妨。

至于errorBrokenPipeErrorpy2/3,这些通常可以忽略,(串行正在协商连接)有时,我有一些节目,而其他时候根本没有。

闪烁可能是由于网络连接问题(看到该部分至少出现)但不确定 atm。希望如果其他人以前遇到过这个问题,也许我们可以获得更多信息。

在连接到 usb 的 bCNC 中,还有File -> Serial -> Port:一个选项,spy://
自述文件和手册中有信息。

注意:我很快就会有一些东西来修复一些编码错误(对于两者)和在 py3 中打开的文件
不知道这是否对你有帮助,但我们会看到。

网状挂件,画面闪烁 #1509
贡献者

@Guenni75另外,如果可以的话,压缩文件并上传到这里(拖/放到评论框中),这样我就可以直接测试它,看看它是否给我同样的问题。

网状挂件,画面闪烁 #1509

只是报告我有同样的问题。我正在使用 python3(昨天通过 pip 安装)在 pi3 上运行最新的开发。本地浏览器和远程(win10 上的 chrome)都显示闪烁问题。我对帮助解决与此相关的任何网络问题知之甚少,但我在 chrome 开发工具中看到了与 pcsdias 相同的东西:
#1121(评论)

画布一直无法加载,我在“已建立的连接被主机上的软件中止”的终端上收到相同的错误消息。chrome 调试控制台中也有一条重复消息Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH

如果有助于解决此问题,我可以共享其他文件/信息。我可以说我尝试了几个不同的 gcode 文件,但编码似乎无法解决这个问题。所以我认为这与此无关。另请注意,几个月前我已经用 python2 安装了 bCNC,它的行为方式相同。

网状挂件,画面闪烁 #1509 Harvie 将此添加到 0.9.16里程碑 2021 年 2 月 25 日
网状挂件,画面闪烁 #1509 哈维 补充道 挂件api 标签 2021 年 2 月 25 日
网状挂件,画面闪烁 #1509
作者
古尼75 评论了 2021 年 10 月 6 日  

@GitHubCaps我使用哪个文件并不重要。总是一样的。即使使用 bCNC 制作的文件。
几个月以来,我只收到警告标志。

网状挂件,画面闪烁 #1509

网状挂件,画面闪烁 #1509

我也遇到了与操作视频相同的问题,我在 pi4 上使用铬连接到另一个在局域网上运行 bCNC 的 pi4。
“ http://192.168.0.34:8080/canvas?1634910941466?1634910 …..”在另一个选项卡中显示正常,但只是偶尔在吊坠页面上显示,大多数时候它显示一个“图片占位符图标”大约每秒闪烁一次。页面上它下面的所有内容都会上下跳跃。
浏览器控制台填满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?

喜欢 (0)