Skip to content

Commit bb8f331

Browse files
committed
Support extended components
1 parent d33608f commit bb8f331

File tree

5 files changed

+79
-2
lines changed

5 files changed

+79
-2
lines changed

.github/workflows/update_components.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ jobs:
5454
jlcparts getlibrary --age 10000 \
5555
--limit 15000 \
5656
parts.csv cache.sqlite3
57+
jlcparts updatepreferred cache.sqlite3
5758
jlcparts buildtables --jobs 0 \
5859
--ignoreoldstock 120 \
5960
cache.sqlite3 web/build/data

jlcparts/datatables.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,13 @@ def pullExtraAttributes(component):
193193
a dictionary
194194
"""
195195
status = "Discontinued" if component["extra"] == {} else "Active"
196+
type = "Extended"
197+
if component["basic"]:
198+
type = "Basic"
199+
if component["preferred"]:
200+
type = "Preferred"
196201
return {
197-
"Basic/Extended": "Basic" if component["basic"] else "Extended",
202+
"Basic/Extended": type,
198203
"Package": component["package"],
199204
"Status": status
200205
}

jlcparts/lcsc.py

+36
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
import requests
23
import os
34
import time
@@ -28,6 +29,41 @@ def makeLcscRequest(url, payload=None):
2829

2930
return requests.get(url, params=newPayload)
3031

32+
def pullPreferredComponents():
33+
resp = requests.get("https://jlcpcb.com/api/overseas-pcb-order/v1/getAll")
34+
token = resp.cookies.get_dict()["XSRF-TOKEN"]
35+
36+
headers = {
37+
"Content-Type": "application/json",
38+
"X-XSRF-TOKEN": token,
39+
}
40+
PAGE_SIZE = 1000
41+
42+
currentPage = 1
43+
components = set()
44+
while True:
45+
body = {
46+
"currentPage": currentPage,
47+
"pageSize": PAGE_SIZE,
48+
"preferredComponentFlag": True
49+
}
50+
51+
resp = requests.post(
52+
"https://jlcpcb.com/api/overseas-pcb-order/v1/shoppingCart/smtGood/selectSmtComponentList",
53+
headers=headers,
54+
json=body
55+
)
56+
57+
body = resp.json()
58+
for c in [x["componentCode"] for x in body["data"]["componentPageInfo"]["list"]]:
59+
components.add(c)
60+
61+
if not body["data"]["componentPageInfo"]["hasNextPage"]:
62+
break
63+
currentPage += 1
64+
65+
return components
66+
3167
if __name__ == "__main__":
3268
r = makeLcscRequest("https://ips.lcsc.com/rest/wmsc2agent/product/info/C7063")
3369
print(r.json())

jlcparts/partLib.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ def dbToComp(comp):
3535
comp["lcsc"] = lcscFromDb(comp["lcsc"])
3636
comp["price"] = json.loads(comp["price"])
3737
comp["extra"] = json.loads(comp["extra"])
38+
comp["basic"] = bool(comp["basic"])
39+
comp["preferred"] = bool(comp["preferred"])
3840
return comp
3941

4042
class PartLibraryDb:
@@ -54,6 +56,7 @@ def __init__(self, filepath=None):
5456
joints INTEGER NOT NULL,
5557
manufacturer_id INTEGER NOT NULL,
5658
basic INTEGER NOT NULL,
59+
preferred INTEGER NOT NULL DEFAULT 0,
5760
description TEXT NOT NULL,
5861
datasheet TEXT NOT NULL,
5962
stock INTEGER NOT NULL,
@@ -64,11 +67,22 @@ def __init__(self, filepath=None):
6467
)""")
6568

6669
# Perform migration if we miss last on stock
67-
columns = self.conn.execute("pragma table_info(components)")
70+
migrated = False
71+
columns = list(self.conn.execute("pragma table_info(components)"))
6872
if "last_on_stock" not in [x[1] for x in columns]:
6973
self.conn.execute("""
7074
ALTER TABLE components ADD COLUMN last_on_stock INTEGER NOT NULL DEFAULT 0;
7175
""")
76+
migrated = True
77+
78+
# Perform migration if we miss the preferred flag
79+
if "preferred" not in [x[1] for x in columns]:
80+
self.conn.execute("""
81+
ALTER TABLE components ADD COLUMN preferred INTEGER NOT NULL DEFAULT 0;
82+
""")
83+
migrated = True
84+
85+
if migrated:
7286
self.conn.execute("DROP VIEW v_components")
7387

7488
self.conn.execute("""
@@ -104,6 +118,7 @@ def __init__(self, filepath=None):
104118
c.joints AS joints,
105119
m.name AS manufacturer,
106120
c.basic AS basic,
121+
c.preferred as preferred,
107122
c.description AS description,
108123
c.datasheet AS datasheet,
109124
c.stock AS stock,
@@ -292,6 +307,12 @@ def updateJlcPart(self, component, flag=None):
292307
""", data)
293308
self._commit()
294309

310+
def setPreferred(self, lcscSet):
311+
cursor = self.conn.cursor()
312+
cursor.execute("UPDATE components SET preferred = 0")
313+
cursor.execute(f"UPDATE components SET preferred = 1 WHERE lcsc IN ({','.join(len(lcscSet) * ['?'])})",
314+
[lcscToDb(x) for x in lcscSet])
315+
self._commit()
295316

296317
def categories(self):
297318
res = {}

jlcparts/ui.py

+14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import click
55

66
from jlcparts.datatables import buildtables, normalizeAttribute
7+
from jlcparts.lcsc import pullPreferredComponents
78
from jlcparts.partLib import (PartLibrary, PartLibraryDb, getLcscExtraNew,
89
loadJlcTable, loadJlcTableLazy)
910

@@ -62,6 +63,18 @@ def getLibrary(source, db, age, limit):
6263
# db.vacuum()
6364

6465

66+
67+
@click.command()
68+
@click.argument("db", type=click.Path(dir_okay=False, writable=True))
69+
def updatePreferred(db):
70+
"""
71+
Download list of preferred components from JLC PCB and mark them into the DB.
72+
"""
73+
preferred = pullPreferredComponents()
74+
lib = PartLibraryDb(db)
75+
lib.setPreferred(preferred)
76+
77+
6578
@click.command()
6679
@click.argument("libraryFilename")
6780
def listcategories(libraryfilename):
@@ -152,6 +165,7 @@ def cli():
152165
cli.add_command(listcategories)
153166
cli.add_command(listattributes)
154167
cli.add_command(buildtables)
168+
cli.add_command(updatePreferred)
155169
cli.add_command(fetchDetails)
156170
cli.add_command(fetchTable)
157171
cli.add_command(testComponent)

0 commit comments

Comments
 (0)