Add brand and images, fileserver for images, start to add arm queue

This commit is contained in:
Cole Deck 2024-05-08 12:29:43 -05:00
parent eca65dc0e0
commit 36249058ac
17 changed files with 422 additions and 66 deletions

1
.gitignore vendored
View File

@ -3,6 +3,7 @@ venv
__pycache__ __pycache__
# cable data folder(s) # cable data folder(s)
cables cables
cables_old
cables-sample.zip cables-sample.zip
# meilisearch (mainly where I've put the data volume for the container) # meilisearch (mainly where I've put the data volume for the container)
meili_data meili_data

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

View File

@ -18,6 +18,9 @@ arm:
limb3: 0.1 limb3: 0.1
limb_wrist: 0.0997 limb_wrist: 0.0997
cables:
port: 7900
directory: ./cables/ # must include trailing slash
#cable_map: #cable_map:
cameras: cameras:
@ -30,7 +33,7 @@ led:
timeout: 1 timeout: 1
controllers: controllers:
- universe: 1 - universe: 1
ip: 192.168.1.5 ip: 192.168.1.200
ledstart: 0 ledstart: 0
ledend: 143 ledend: 143
mode: rgb mode: rgb
@ -74,11 +77,11 @@ led:
ledstart: 1152 ledstart: 1152
ledend: 1295 ledend: 1295
mode: rgb mode: rgb
- universe: 0 # - universe: 0
ip: 192.168.1.209 # ip: 192.168.1.209
ledstart: 1296 # ledstart: 1296
ledend: 1365 # ledend: 1365
mode: rgbw # mode: rgbw
map: map:
@ -427,12 +430,12 @@ led:
pos: [65.991, -190.5] pos: [65.991, -190.5]
# Strips # Strips
- type: strip # - type: strip
start: 1296 # start: 1296
size: 70 # size: 70
length: 600 # length: 600
angle: 270 # down # angle: 270 # down
pos: [375, 300] # pos: [375, 300]
global_position_offset: [0,0] # default coordinate spce below as center of arm at 0,0 - adjust if necessary global_position_offset: [0,0] # default coordinate spce below as center of arm at 0,0 - adjust if necessary
animation_time: 200 animation_time: 200

16
fileserver.py Normal file
View File

@ -0,0 +1,16 @@
import http.server
import socketserver
import os
def run_server(port, directory):
"""
Run a simple HTTP server serving files from the specified directory.
"""
# Change the working directory to the specified directory
os.chdir(directory)
# Create the HTTP server
handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", port), handler) as httpd:
print(f"Serving at port {port}")
httpd.serve_forever()

View File

@ -159,8 +159,9 @@ def touch(path):
def get_multi(partnums, delay=0.25, dir="cables/", cache=True, bar=None): def get_multi(partnums, delay, dir, webport, cache=True, bar=None):
#with alive_bar(len(partnums) * 2, dual_line=True, calibrate=30, bar="classic2", spinner="classic", disable=True, file=sys.stdout) as bar: #with alive_bar(len(partnums) * 2, dual_line=True, calibrate=30, bar="classic2", spinner="classic", disable=True, file=sys.stdout) as bar:
failed = list() failed = list()
actualpartnums = list() actualpartnums = list()
def _try_download_datasheet(partnum, output_dir, dstype): # Guess datasheet URL def _try_download_datasheet(partnum, output_dir, dstype): # Guess datasheet URL
@ -253,7 +254,7 @@ def get_multi(partnums, delay=0.25, dir="cables/", cache=True, bar=None):
os.remove(partnum + "/datasheet.pdf") os.remove(partnum + "/datasheet.pdf")
sys.exit() sys.exit()
def __use_cached_datasheet(partnum, path, output_dir, dstype): def __use_cached_datasheet(partnum, path, output_dir, dstype, weburl):
fprint("Using cached datasheet for " + partnum) fprint("Using cached datasheet for " + partnum)
# bar.text = "Using cached datasheet for " + partnum # bar.text = "Using cached datasheet for " + partnum
# bar(skipped=True) # bar(skipped=True)
@ -262,7 +263,7 @@ def get_multi(partnums, delay=0.25, dir="cables/", cache=True, bar=None):
fprint("Parsing Datasheet contents of " + partnum) fprint("Parsing Datasheet contents of " + partnum)
# bar.text = "Parsing Datasheet contents of " + partnum + ".pdf..." # bar.text = "Parsing Datasheet contents of " + partnum + ".pdf..."
out = read_datasheet.parse(path, output_dir, partnum, dstype) out = read_datasheet.parse(path, output_dir, partnum, dstype, weburl)
# bar(skipped=False) # bar(skipped=False)
return out return out
else: else:
@ -270,13 +271,13 @@ def get_multi(partnums, delay=0.25, dir="cables/", cache=True, bar=None):
# bar.text = "Datasheet already parsed for " + partnum + ".pdf" # bar.text = "Datasheet already parsed for " + partnum + ".pdf"
# bar(skipped=True) # bar(skipped=True)
def __downloaded_datasheet(partnum, path, output_dir, dstype): def __downloaded_datasheet(partnum, path, output_dir, dstype, weburl):
fprint("Downloaded " + path) fprint("Downloaded " + path)
# bar.text = "Downloaded " + path # bar.text = "Downloaded " + path
# bar(skipped=False) # bar(skipped=False)
fprint("Parsing Datasheet contents of " + partnum) fprint("Parsing Datasheet contents of " + partnum)
# bar.text = "Parsing Datasheet contents of " + partnum + ".pdf..." # bar.text = "Parsing Datasheet contents of " + partnum + ".pdf..."
out = read_datasheet.parse(path, output_dir, partnum, dstype) out = read_datasheet.parse(path, output_dir, partnum, dstype, weburl)
# bar(skipped=False) # bar(skipped=False)
return out return out
@ -289,6 +290,7 @@ def get_multi(partnums, delay=0.25, dir="cables/", cache=True, bar=None):
partnum = partnum.replace("/","_") partnum = partnum.replace("/","_")
output_dir = dir + partnum output_dir = dir + partnum
path = output_dir + "/datasheet.pdf" path = output_dir + "/datasheet.pdf"
weburl = ":" + str(webport) + "/" + partnum + "/"
bartext = "Downloading files for part " + partnum bartext = "Downloading files for part " + partnum
# bar.text = bartext # bar.text = bartext
partnum = oldpartnum.replace("_","/") partnum = oldpartnum.replace("_","/")
@ -311,26 +313,27 @@ def get_multi(partnums, delay=0.25, dir="cables/", cache=True, bar=None):
if _download_image(search_result["image"], output_dir): if _download_image(search_result["image"], output_dir):
fprint("Downloaded hi-res part image for " + partnum) fprint("Downloaded hi-res part image for " + partnum)
returnval = [partnum, dstype, True, False] returnval = [partnum, dstype, True, False]
os.remove(output_dir + "/parsed")
touch(output_dir + "/found_part_hires") touch(output_dir + "/found_part_hires")
else: else:
fprint("Using cached hi-res part image for " + partnum) fprint("Using cached hi-res part image for " + partnum)
# Download datasheet from provided URL if needed # Download datasheet from provided URL if needed
if os.path.exists(path) and os.path.getsize(path) > 1 and cache: if os.path.exists(path) and os.path.getsize(path) > 1 and cache:
out = __use_cached_datasheet(partnum, path, output_dir, dstype) out = __use_cached_datasheet(partnum, path, output_dir, dstype, weburl)
returnval = [partnum, dstype, True, out] returnval = [partnum, dstype, True, out]
elif _download_datasheet(search_result["datasheet"], output_dir) is not False: elif _download_datasheet(search_result["datasheet"], output_dir) is not False:
out = __downloaded_datasheet(partnum, path, output_dir, dstype) out = __downloaded_datasheet(partnum, path, output_dir, dstype, weburl)
returnval = [partnum, dstype, True, out] returnval = [partnum, dstype, True, out]
elif os.path.exists(path) and os.path.getsize(path) > 1 and cache: elif os.path.exists(path) and os.path.getsize(path) > 1 and cache:
out = __use_cached_datasheet(partnum, path, output_dir, dstype) out = __use_cached_datasheet(partnum, path, output_dir, dstype, weburl)
returnval = [partnum, dstype, True, out] returnval = [partnum, dstype, True, out]
# If search fails, and we don't already have the datasheet, guess datasheet URL and skip the hires image download # If search fails, and we don't already have the datasheet, guess datasheet URL and skip the hires image download
elif _try_download_datasheet(partnum, output_dir, dstype) is not False: elif _try_download_datasheet(partnum, output_dir, dstype) is not False:
out = __downloaded_datasheet(partnum, path, output_dir, dstype) out = __downloaded_datasheet(partnum, path, output_dir, dstype, weburl)
returnval = [partnum, dstype, False, out] returnval = [partnum, dstype, False, out]
# Failed to download with search or guess :( # Failed to download with search or guess :(
@ -342,7 +345,7 @@ def get_multi(partnums, delay=0.25, dir="cables/", cache=True, bar=None):
# We already have a hi-res image and the datasheet - perfect! # We already have a hi-res image and the datasheet - perfect!
else: else:
fprint("Using cached hi-res part image for " + partnum) fprint("Using cached hi-res part image for " + partnum)
out = __use_cached_datasheet(partnum, path, output_dir, dstype) out = __use_cached_datasheet(partnum, path, output_dir, dstype, weburl)
returnval = [partnum, dstype, False, out] returnval = [partnum, dstype, False, out]
actualpartnums.append(returnval) actualpartnums.append(returnval)
return True return True

@ -1 +1 @@
Subproject commit f3d8ec0cc421cb8f8b7bb4b30339f3663f70b297 Subproject commit 4cea1b08329761fa5485686e0ff0871730f73820

View File

@ -157,11 +157,12 @@ class LEDSystem():
# controller mapping # controller mapping
for ctrl in self.config["led"]["controllers"]: for ctrl in self.config["led"]["controllers"]:
if len(self.controllers) < ctrl["universe"]+1: if len(self.controllers) < ctrl["universe"]:
for x in range(ctrl["universe"]+1 - len(self.controllers)): print(ctrl["universe"])
for x in range(ctrl["universe"] - len(self.controllers)):
self.controllers.append(None) self.controllers.append(None)
self.controllers[ctrl["universe"]] = (ctrl["ledstart"],ctrl["ledend"]+1,ctrl["ip"]) self.controllers[ctrl["universe"]-1] = (ctrl["ledstart"],ctrl["ledend"]+1,ctrl["ip"])
for x in range(ctrl["ledstart"],ctrl["ledend"]+1): for x in range(ctrl["ledstart"],ctrl["ledend"]+1):
self.leds_size[x] = len(ctrl["mode"]) self.leds_size[x] = len(ctrl["mode"])
#fprint(controllers) #fprint(controllers)
@ -201,7 +202,7 @@ class LEDSystem():
time.sleep(1) time.sleep(1)
for x in range(len(self.controllers)): for x in range(len(self.controllers)):
print("Activating controller", x, "at", self.controllers[x][2], "with", self.controllers[x][1]-self.controllers[x][0], "LEDs.") print("Activating controller", x+1, "at", self.controllers[x][2], "with", self.controllers[x][1]-self.controllers[x][0], "LEDs.")
self.sender.activate_output(x+1) # start sending out data self.sender.activate_output(x+1) # start sending out data
self.sender[x+1].destination = self.controllers[x][2] self.sender[x+1].destination = self.controllers[x][2]
self.sender.manual_flush = True self.sender.manual_flush = True
@ -246,7 +247,7 @@ class LEDSystem():
def fastsendall(self, datain): def fastsendall(self, datain):
# send all LED data to all controllers # send all LED data to all controllers
# data must have all LED data in it as [(R,G,B,)] tuples in an array, 1 tuple per pixel # data must have all LED data in it as [(R,G,B,)] tuples in an array, 1 tuple per pixel
self.sender.manual_flush = False self.sender.manual_flush = True
#print(datain[self.controllers[0][0]:self.controllers[0][1]]) #print(datain[self.controllers[0][0]:self.controllers[0][1]])
for x in range(len(self.controllers)): for x in range(len(self.controllers)):
self.sender[x+1].dmx_data = list(sum(datain[self.controllers[x][0]:self.controllers[x][1]] , ())) # flatten the subsection of the data array self.sender[x+1].dmx_data = list(sum(datain[self.controllers[x][0]:self.controllers[x][1]] , ())) # flatten the subsection of the data array
@ -528,15 +529,21 @@ class LEDSystem():
self.sender.stop() self.sender.stop()
return self return self
def mapimage(self, image, fps=90): def mapimage(self, image, fps=30):
while uptime() - self.start < 1/fps:
time.sleep(0.00001)
#fprint(1 / (uptime() - self.start)) #fprint(1 / (uptime() - self.start))
self.start = uptime() self.start = uptime()
minsize = min(image.shape[0:2]) minsize = min(image.shape[0:2])
leds_normalized2 = [(x * minsize, if image.shape[1] > image.shape[0]:
offset = (image.shape[1] - image.shape[0])/2
leds_normalized2 = [(x * minsize + offset,
y * minsize) y * minsize)
for x, y in self.leds_normalized] for x, y in self.leds_normalized]
else:
offset = (image.shape[0] - image.shape[1])/2
leds_normalized2 = [(x * minsize,
y * minsize + offset)
for x, y in self.leds_normalized]
cv2.imshow("video", image) cv2.imshow("video", image)
cv2.waitKey(1) cv2.waitKey(1)
@ -563,6 +570,8 @@ class LEDSystem():
#avgy /= len(leds) #avgy /= len(leds)
#print((avgx,avgy, max([led[0] for led in leds_adj]), max([led[1] for led in leds_adj]) , min(image.shape[0:2]) )) #print((avgx,avgy, max([led[0] for led in leds_adj]), max([led[1] for led in leds_adj]) , min(image.shape[0:2]) ))
self.fastsendall(self.data) self.fastsendall(self.data)
while self.start + 1.0/fps > uptime():
time.sleep(0.00001)
return self return self
def mainloop(self, stmode, ring = -1, fps = 100, preview = False): def mainloop(self, stmode, ring = -1, fps = 100, preview = False):
@ -646,12 +655,12 @@ if __name__ == "__main__":
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
ledsys = LEDSystem() ledsys = LEDSystem()
ledsys.init() ledsys.init()
cap = cv2.VideoCapture('output.mp4') cap = cv2.VideoCapture('badapple.mp4')
while cap.isOpened(): while cap.isOpened():
ret, frame = cap.read() ret, frame = cap.read()
if not ret: if not ret:
break break
ledsys.mapimage(frame, fps=90) ledsys.mapimage(frame, fps=120)
show = False show = False
ring = 1 ring = 1

BIN
map.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

After

Width:  |  Height:  |  Size: 340 KiB

View File

@ -37,7 +37,7 @@ def extract_table_name(table_start, searchpage, reader, dstype, fallbackname):
ymax = table_start + 10 ymax = table_start + 10
elif dstype == "Alphawire": elif dstype == "Alphawire":
ymin = table_start - 5 ymin = table_start - 5
ymax = table_start + 10 ymax = table_start + 20
page = reader.pages[searchpage - 1] page = reader.pages[searchpage - 1]
parts = [] parts = []
def visitor_body(text, cm, tm, fontDict, fontSize): def visitor_body(text, cm, tm, fontDict, fontSize):
@ -52,14 +52,30 @@ def extract_table_name(table_start, searchpage, reader, dstype, fallbackname):
return text_body return text_body
#fprint(text_body) #fprint(text_body)
def parse(filename, output_dir, partnum, dstype): def find_file_noext(directory, prefix="part-hires"):
"""
Find files in the specified directory that start with the given prefix and have any extension.
:param directory: The directory to search in.
:param prefix: The prefix to search for.
:return: A list of matching file names.
"""
# Get all files and directories in the specified directory
entries = os.listdir(directory)
# Filter files that match 'filename.EXTENSION'
matching_files = [file for file in entries if os.path.isfile(os.path.join(directory, file)) and file.split('.')[0] == prefix and len(file.split('.')) == 2]
print(directory, matching_files)
return matching_files
def parse(filename, output_dir, partnum, dstype, weburl):
tables = [] tables = []
# Extract table data # Extract table data
try: try:
if dstype == "Belden": if dstype == "Belden":
tables = camelot.read_pdf(filename, pages="1-end", flavor='lattice', backend="ghostscript", split_text=False, line_scale=100, process_background=True, resolution=600, interations=1, layout_kwargs={'detect_vertical': False, 'char_margin': 0.5}, shift_text=['r', 't']) tables = camelot.read_pdf(filename, pages="1-end", flavor='lattice', backend="ghostscript", split_text=False, line_scale=100, process_background=True, resolution=600, interations=1, layout_kwargs={'detect_vertical': False, 'char_margin': 0.5}, shift_text=['r', 't'])
elif dstype == "Alphawire": elif dstype == "Alphawire":
tables = camelot.read_pdf(filename, pages="1-end", flavor='lattice', backend="ghostscript", split_text=False, line_scale=50, process_background=True, resolution=600, interations=1, layout_kwargs={'detect_vertical': True, 'char_margin': 0.5}, shift_text=['l', 't']) tables = camelot.read_pdf(filename, pages="1-end", flavor='lattice', backend="ghostscript", split_text=False, line_scale=50, process_background=True, resolution=600, interations=1, layout_kwargs={'detect_vertical': True, 'char_margin': 0.5}, shift_text=['l', 'b'])
except (OSError, RuntimeError) as e: except (OSError, RuntimeError) as e:
print(e) print(e)
if win32: if win32:
@ -95,11 +111,26 @@ def parse(filename, output_dir, partnum, dstype):
#fprint(table_start) #fprint(table_start)
text_body = extract_table_name(table_start, table.page, reader, dstype, n) text_body = extract_table_name(table_start, table.page, reader, dstype, n)
#print(text_body)
table_list[text_body] = table.df table_list[text_body] = table.df
#print(table_list[text_body])
if dstype == "Alphawire": if dstype == "Alphawire":
table_list_raw[text_body] = table
def reorder_row(row):
# Filter out NaNs and compute the original non-NaN values
non_nans = row[~row.isnull()]
# Create a new row with NaNs filled at the end
new_row = pd.Series(index=row.index)
new_row[:len(non_nans)] = non_nans
return new_row
# Apply the function to each row and return a new DataFrame
#table_list[text_body] = table.df.apply(reorder_row, axis=1)
#print(table_list[text_body])
table_list_raw[text_body] = table
#print(tbl)
#table.to_html("table" + str(n) + ".html") #table.to_html("table" + str(n) + ".html")
#fprint(table.df) #fprint(table.df)
@ -134,6 +165,13 @@ def parse(filename, output_dir, partnum, dstype):
fp.write(image_file_object.data) fp.write(image_file_object.data)
count += 1 count += 1
if os.path.exists(output_dir + "/found_part_hires"):
img = weburl + find_file_noext(output_dir, prefix="part-hires")[0]
elif len(find_file_noext(output_dir, prefix="part")) > 0:
img = weburl + find_file_noext(output_dir, prefix="part")[0]
else:
img = None
# Table parsing and reordring # Table parsing and reordring
tables = dict() tables = dict()
torename = dict() torename = dict()
@ -141,6 +179,7 @@ def parse(filename, output_dir, partnum, dstype):
#print(table_list.keys()) #print(table_list.keys())
for table_name in table_list.keys(): for table_name in table_list.keys():
# determine shape: horizontal or vertical # determine shape: horizontal or vertical
#print(table_name)
table = table_list[table_name] table = table_list[table_name]
rows = table.shape[0] rows = table.shape[0]
cols = table.shape[1] cols = table.shape[1]
@ -177,11 +216,11 @@ def parse(filename, output_dir, partnum, dstype):
if dstype == "Alphawire" and table_name_2.find("\n") >= 0: if dstype == "Alphawire" and table_name_2.find("\n") >= 0:
torename[table_name_2] = table_name_2[0:table_name_2.find("\n")] torename[table_name_2] = table_name_2[0:table_name_2.find("\n")]
if dstype == "Alphawire" and table_name_2.find(table.iloc[-1, 0]) >= 0: # if dstype == "Alphawire" and table_name_2.find(table.iloc[-1, 0]) >= 0:
# Name taken from table directly above - this table does not have a name # # Name taken from table directly above - this table does not have a name
torename[table_name_2] = "Specs " + str(len(tables)) # torename[table_name_2] = "Specs " + str(len(tables))
#table_list["Specs " + str(len(tables))] = table_list[table_name_2] # rename table to arbitrary altername name # #table_list["Specs " + str(len(tables))] = table_list[table_name_2] # rename table to arbitrary altername name
break # break
if vertical: if vertical:
out = dict() out = dict()
@ -199,9 +238,9 @@ def parse(filename, output_dir, partnum, dstype):
out[col_data[0].replace("\n", " ")] = col_data[1:] out[col_data[0].replace("\n", " ")] = col_data[1:]
tables[table_name] = out tables[table_name] = out
#print(out)
# multi-page table check, Alphawire # multi-page table check, Alphawire
if dstype == "Alphawire" and table_name.isdigit(): if dstype == "Alphawire" and table_name.isdigit() and previous_table != "":
# table continues from previous page or has name on previous page # table continues from previous page or has name on previous page
thistbl = table_list_raw[table_name] thistbl = table_list_raw[table_name]
prevtbl = table_list_raw[previous_table] prevtbl = table_list_raw[previous_table]
@ -294,15 +333,20 @@ def parse(filename, output_dir, partnum, dstype):
tables = replace_newlines_in_dict(tables) tables = replace_newlines_in_dict(tables)
# summary # summary
#print(tables)
output_table = dict() output_table = dict()
output_table["partnum"] = partnum output_table["partnum"] = partnum
id = str(uuid.uuid4()) id = str(uuid.uuid4())
output_table["id"] = id output_table["id"] = id
#output_table["position"] = id #output_table["position"] = id
#output_table["brand"] = brand output_table["brand"] = dstype
output_table["fullspecs"] = {"partnum": partnum, "id": id, **tables} if img is not None:
output_table["searchspecs"] = {"partnum": partnum, **flatten(tables)} output_table["image"] = img
output_table["fullspecs"] = {"partnum": partnum, "id": id, "brand": dstype, "image": img, **tables}
output_table["searchspecs"] = {"partnum": partnum, "brand": dstype, "image": img, **flatten(tables)}
else:
output_table["fullspecs"] = {"partnum": partnum, "id": id, "brand": dstype, **tables}
output_table["searchspecs"] = {"partnum": partnum, "brand": dstype, **flatten(tables)}
output_table["searchspecs"]["id"] = id output_table["searchspecs"]["id"] = id
@ -380,4 +424,4 @@ def flatten(tables):
if __name__ == "__main__": if __name__ == "__main__":
print(parse("cables/3050/datasheet.pdf", "cables/3050", "3050", "Alphawire")) print(parse("cables/3050/datasheet-new.pdf", "cables/3050", "3050", "Alphawire"))

19
run.py
View File

@ -29,6 +29,7 @@ from search import JukeboxSearch
#multiprocessing.set_start_method('spawn', True) #multiprocessing.set_start_method('spawn', True)
from pyModbusTCP.client import ModbusClient from pyModbusTCP.client import ModbusClient
from uptime import uptime from uptime import uptime
import fileserver
# set to false to run without real hardware for development # set to false to run without real hardware for development
real = False real = False
@ -161,7 +162,11 @@ def check_server():
tmp = list() tmp = list()
for idx in range(len(cable_list)): for idx in range(len(cable_list)):
if cable_list[idx] is not False: if cable_list[idx] is not False:
tmp1 = {"part_number": cable_list[idx], "position": idx, "name": cable_list[idx], "brand": "Belden", "description": "Blah", "short_description": "Bla"} cabledata = jbs.get_position(str(idx))
if "image" in cabledata:
tmp1 = {"part_number": cable_list[idx], "position": idx, "name": cable_list[idx], "brand": cabledata["brand"], "image": cabledata["image"], "description": "Blah", "short_description": "Bla"}
else:
tmp1 = {"part_number": cable_list[idx], "position": idx, "name": cable_list[idx], "brand": cabledata["brand"], "description": "Blah", "short_description": "Bla"}
tmp.append(tmp1) tmp.append(tmp1)
out = {"map": tmp} out = {"map": tmp}
fprint(out) fprint(out)
@ -354,6 +359,9 @@ def setup_server(pool):
fprint("Starting websocket server...", sendqueue=to_server_queue) fprint("Starting websocket server...", sendqueue=to_server_queue)
websocket_process = server.start_websocket_server(to_server_queue, from_server_queue) websocket_process = server.start_websocket_server(to_server_queue, from_server_queue)
fprint("Starting image file server...", sendqueue=to_server_queue)
image_server_process = Process(target=fileserver.run_server, args=(config["cables"]["port"], config["cables"]["directory"]))
image_server_process.start()
return True return True
def handle_error(error): def handle_error(error):
@ -379,13 +387,18 @@ def get_sensors():
out = list() out = list()
if real: if real:
for reg in [352, 288, 304, 368]: for reg in [352, 288, 304, 368]:
val = mbconn.read_holding_registers(reg)[0] val = mbconn.read_holding_registers(reg)
if val is not None:
val = val[0]
if val == 1: if val == 1:
out.append(1) out.append(1)
else: else:
out.append(0) out.append(0)
else: else:
out = [0, 0, 0, 0] out = [0, 0, 0, 0]
if len(out) != 4:
return -1
sensors = out sensors = out
#fprint("Values: " + str(sensors)) #fprint("Values: " + str(sensors))
#mbconn.close() #mbconn.close()
@ -538,7 +551,7 @@ def mainloop_server(pool):
for idx in range(len(cable_list)): for idx in range(len(cable_list)):
cable_list_state.append(True) cable_list_state.append(True)
pool.apply_async(get_specs.get_multi, (cable_list, 0.3), callback=cable_search_callback, error_callback=handle_error) pool.apply_async(get_specs.get_multi, (cable_list, 0.3, config["cables"]["directory"], config["cables"]["port"]), callback=cable_search_callback, error_callback=handle_error)
mode = "Parsing" mode = "Parsing"
fprint("All cables scanned. Finding & parsing datasheets...") fprint("All cables scanned. Finding & parsing datasheets...")
if mode == "Parsing": if mode == "Parsing":

76
table0.html Normal file
View File

@ -0,0 +1,76 @@
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>
<tbody>
<tr>
<th>2</th>
<td></td>
<td></td>
<td></td>
<td>Diameters\n(In)</td>
</tr>
<tr>
<th>4</th>
<td>1) Component\n1\n1 X 1 HOOKUP</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>6</th>
<td>a) Conductor\n24\n(7/32) AWG Tinned Copper</td>
<td></td>
<td></td>
<td>0.024</td>
</tr>
<tr>
<th>8</th>
<td>b)\nInsulation\n0.016" Wall, Nom. PVC</td>
<td></td>
<td></td>
<td>0.056+/-\n0.002</td>
</tr>
<tr>
<th>10</th>
<td></td>
<td>(1) Print</td>
<td>ALPHA WIRE\nE163869-* RU AWM STYLES\n1569\n105C\nOR 1007\n80C 300V VW-1\nIEC 60332-2\n24 AWG\nOR CRU TR-64\n90C FT1 CE ROHS\n{0}\n* = Factory Code</td>
<td></td>
</tr>
<tr>
<th>12</th>
<td></td>
<td>(2) Color(s)</td>
<td>WHITE, BLACK, GREEN,\nYELLOW, BLUE, BROWN, ORANGE\nSLATE, VIOLET, WHITE/BLACK, WHITE/RED</td>
<td></td>
</tr>
<tr>
<th>13</th>
<td></td>
<td></td>
<td>WHITE/GREEN, WHITE/YELLOW, WHITE/BLUE\nWHITE/BROWN, WHITE/ORANGE, WHITE/SLATE\nWHITE/VIOLET, GREEN/YELLOW,\nPINK, DK. BLUE</td>
<td></td>
</tr>
<tr>
<th>14</th>
<td></td>
<td></td>
<td>BROWN/BLACK, WHITE/PINK, BROWN/GREEN, BROWN/BLUE</td>
<td></td>
</tr>
<tr>
<th>15</th>
<td></td>
<td></td>
<td>RED</td>
<td></td>
</tr>
</tbody>
</table>

46
table1.html Normal file
View File

@ -0,0 +1,46 @@
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>1</th>
<th>2</th>
</tr>
</thead>
<tbody>
<tr>
<th>2</th>
<td>1) UL</td>
<td>AWM/STYLE\n1007\n80°C /\n300 VRMS</td>
</tr>
<tr>
<th>4</th>
<td></td>
<td>AWM/STYLE\n1569\n105°C /\n300 VRMS</td>
</tr>
<tr>
<th>6</th>
<td></td>
<td>VW-1</td>
</tr>
<tr>
<th>8</th>
<td>2) CSA International</td>
<td>TR-64\n90°C</td>
</tr>
<tr>
<th>10</th>
<td></td>
<td>FT1</td>
</tr>
<tr>
<th>12</th>
<td>3)\nIEC</td>
<td>EN 60332-2\nFlame Behavior</td>
</tr>
<tr>
<th>14</th>
<td>4) CE:</td>
<td>EU Low Voltage Directive\n2014/35/EU</td>
</tr>
</tbody>
</table>

60
table2.html Normal file
View File

@ -0,0 +1,60 @@
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>1</th>
<th>2</th>
<th>4</th>
</tr>
</thead>
<tbody>
<tr>
<th>2</th>
<td>1)\nEU Directive\n2011/65/EU(RoHS2),\nEU Directive\n2015/863/EU (RoHS3):</td>
<td></td>
<td></td>
</tr>
<tr>
<th>4</th>
<td></td>
<td></td>
<td>All materials used in the manufacture of\nthis part\nare\nin compliance with European Directive\n2011/65/EU</td>
</tr>
<tr>
<th>5</th>
<td></td>
<td></td>
<td>and the\namending Directive\n2015/863/EU of\n4\nJune\n2015\nregarding the\nrestriction of use of\ncertain</td>
</tr>
<tr>
<th>6</th>
<td></td>
<td></td>
<td>hazardous\nsubstances\nin electrical\nand electronic\nequipment.</td>
</tr>
<tr>
<th>7</th>
<td>2) REACH Regulation (EC 1907/2006):</td>
<td></td>
<td></td>
</tr>
<tr>
<th>8</th>
<td></td>
<td></td>
<td>This product does not\ncontain Substances of Very High Concern (SVHC)\nlisted on the\nEuropean Union's</td>
</tr>
<tr>
<th>9</th>
<td></td>
<td></td>
<td>REACH candidate\nlist\nin excess of\n0.1% mass of\nthe\nitem.</td>
</tr>
<tr>
<th>11</th>
<td></td>
<td>3) California Proposition 65:</td>
<td>This product may\ncontain substances\nknown to the\nState of California\nto cause Cancer or Reproductive\nHarm, but\nis\nexempt\nfrom labeling based on the Consent\nJudgement.\nSee\nthe Alpha Wire website\nfor more\ninformation.</td>
</tr>
</tbody>
</table>

60
table3.html Normal file
View File

@ -0,0 +1,60 @@
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<th>2</th>
<td></td>
<td>Physical &amp; Mechanical Properties</td>
<td></td>
</tr>
<tr>
<th>4</th>
<td>1)\nTemperature Range</td>
<td></td>
<td>-40\nto 105°C</td>
</tr>
<tr>
<th>6</th>
<td>2) Bend Radius</td>
<td></td>
<td>10X Cable Diameter</td>
</tr>
<tr>
<th>8</th>
<td>3) Pull\nTension</td>
<td></td>
<td>3.5\nLbs, Maximum</td>
</tr>
<tr>
<th>9</th>
<td></td>
<td>Electrical Properties\n(For\nEngineering purposes only)</td>
<td></td>
</tr>
<tr>
<th>11</th>
<td>1) Voltage Rating</td>
<td></td>
<td>300 VRMS</td>
</tr>
<tr>
<th>13</th>
<td>2)\nInductance</td>
<td></td>
<td>0.07 μH/ft, Nominal</td>
</tr>
<tr>
<th>15</th>
<td>3) Conductor DCR</td>
<td></td>
<td>25 Ω/1000ft @20°C, Nominal</td>
</tr>
</tbody>
</table>

18
table4.html Normal file
View File

@ -0,0 +1,18 @@
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>1</th>
</tr>
</thead>
<tbody>
<tr>
<th>2</th>
<td>Packaging\nFlange\nx\nTraverse\nx Barrel\n(inches)</td>
</tr>
<tr>
<th>3</th>
<td>a)\n32800\nFT\n23\nx\n15\nx\n0 Max.\n4\nseparate pieces; Min length/piece\n10000\nFT.\nb)\n10000\nFT\n12\nx\n5.94\nx\n5 Max.\n3\nseparate pieces; Min length/piece\n1000\nFT.\nc)\n5000\nFT\n10.5\nx\n5\nx\n3.5 Continuous\nlength\nd)\n1000\nFT\n6.5\nx\n2\nx\n1.9 Continuous\nlength\ne)\n100\nFT\n2.75\nx\n2\nx\n1.125 Continuous\nlength\n \n[Spool\ndimensions may\nvary\nslightly]\nNotes:\na) Certain color\nand put-up combinations may only be\navailable by\nspecial order. Minimums may\napply.\nb)\nTolerance on 32800\nft. Put-Up is +/-\n10%</td>
</tr>
</tbody>
</table>

View File

@ -10,7 +10,7 @@ import yaml
import sys import sys
from util import fprint from util import fprint
from pyModbusTCP.client import ModbusClient from pyModbusTCP.client import ModbusClient
from multiprocessing import Queue
import subprocess import subprocess
from util import win32 from util import win32
@ -20,6 +20,7 @@ class Rob():
robot = None robot = None
#offset_x, offset_y, offset_z = (0, 0, 0.14) # Tool offset #offset_x, offset_y, offset_z = (0, 0, 0.14) # Tool offset
# #
pos_updates = Queue()
def __init__(self, config): def __init__(self, config):
self.config = config self.config = config
armc = config["arm"] armc = config["arm"]
@ -91,7 +92,6 @@ def connect(robot):
def init_arm(robot): def init_arm(robot):
robot = connect(robot) robot = connect(robot)
# init urx # init urx
#rob.set_payload(2, (0, 0, 0.1)) #rob.set_payload(2, (0, 0, 0.1))
@ -510,7 +510,7 @@ def holder_routine(robot, holder_index, pick_up, verbose=False):
goto_holder_index(robot, holder_index, 0.05, use_closest_path=False) goto_holder_index(robot, holder_index, 0.05, use_closest_path=False)
else: else:
goto_holder_index(robot, holder_index, 0.2, use_closest_path=False) goto_holder_index(robot, holder_index, 0.2, use_closest_path=False)
robot.pos_updates.put(1)
if pick_up: if pick_up:
open_gripper() open_gripper()
@ -530,7 +530,7 @@ def holder_routine(robot, holder_index, pick_up, verbose=False):
new_pos[2] = 0.2 new_pos[2] = 0.2
rob.movel(new_pos, vel=2, acc=1) rob.movel(new_pos, vel=2, acc=1)
was_flipped = is_flipped(robot) was_flipped = is_flipped(robot)
robot.pos_updates.put(2)
# goto_holder_index(robot, 25, z=0.2) # goto_holder_index(robot, 25, z=0.2)
def pick_up_holder(robot, holder_index, verbose=False): def pick_up_holder(robot, holder_index, verbose=False):
holder_routine(robot, holder_index, True, verbose=verbose) holder_routine(robot, holder_index, True, verbose=verbose)
@ -613,6 +613,7 @@ def drop_off_tray(robot, slot=0):
def return_routine(robot, slot, holder_index=None, verbose=False): def return_routine(robot, slot, holder_index=None, verbose=False):
# OLD UNUSED
robot = connect(robot) robot = connect(robot)
rob = robot.robot rob = robot.robot
@ -697,6 +698,12 @@ def close_gripper():
c.close() c.close()
# #
def get_position_thread(robot):
robot = connect(robot)
rob = robot.robot
vals = rob.getl()
robot.pos_updates.put(tuple(vals))
if __name__ == "__main__": if __name__ == "__main__":
#init("192.168.1.145") #init("192.168.1.145")

View File

@ -150,7 +150,7 @@
setInterval(updateClock, 100); setInterval(updateClock, 100);
</script> </script>
<iframe src="http://192.168.1.12:3000/d-solo/cdiqwmlr8c9ogf/sensors?orgId=1&refresh=5s&from=1714431825720&to=1714433625721&theme=light&panelId=7" width="450" height="200" frameborder="0"></iframe>
</body> </body>
</html> </html>