Skip to content

Board catalogue: Ruision's IP camera boards, current and archived - #541

Merged
openipc-ai merged 2 commits into
masterfrom
boards-ruision
Oct 31, 2026
Merged

openipc-ai merged 2 commits into
masterfrom
boards-ruision

Conversation

@openipc-ai

Copy link
Copy Markdown
Collaborator

Ruision (深圳市睿视科技有限公司, later 芯睿视, its 2025 site signed
Corevision) was not in the catalogue, nor its boards. We have its boards
in the lab; this gives them a maker and a catalogue to land on.

  • ruision.py captures the catalogue: the live site's public JSON API
    (the 31 modules of its IP camera category, with photos and spec sheets)
    and every product page of its earlier sites the Wayback Machine kept
    (2011-2016, 2017-2019, 2020-2023, 2025), with what each links.
    Wayback answers Python's HTTP client 429 within a few requests while
    serving curl, so its pages go through curl, paced; the 2025 site's CDN
    wants a referrer.
  • ruision_snapshot.py builds the snapshot in board-render:1. It keeps the
    IP camera boards only, by the category a page names or, where none, by
    what the text says the board is: 134 archived analog, AHD/TVI/CVI,
    hybrid, DVR/HVR/NVR boards and finished cameras are left out. The chip
    and sensor are taken where a page names them; a series whose pages name
    other variants (RS-T805) gets no sensor. The live modules name no chip:
    the PCB markings in their photos are kept verbatim as a "PCB marking"
    row, and three chips legible there (Hi3516CV608, Hi3516CV610-10B,
    Hi3519DV500) as "Chip (from the photo)".
  • 61 boards: 31 live, 30 discontinued; 13 with a chip, 6 with a sensor,
    61 with a photo, 257 files. Pinned at 86462735f1a0; two builds give the
    same bytes. A rehearsal import on a scratch database makes 61 models,
    61 units and 310 files; a second import adds nothing.
  • Migration 045 adds the source; Ruision joins the makers (also 睿视科技,
    芯睿视, Corevision) and the card summary order.
  • Hi3516CV610 as its package is marked (-10B, -20S, -00S) resolves to the
    catalogue's variants, which are named by memory with the u-boot each
    takes.

Ruision (深圳市睿视科技有限公司, later 芯睿视, its 2025 site signed
Corevision) was not in the catalogue, nor its boards. We have its boards
in the lab; this gives them a maker and a catalogue to land on.

- ruision.py captures the catalogue: the live site's public JSON API
  (the 31 modules of its IP camera category, with photos and spec sheets)
  and every product page of its earlier sites the Wayback Machine kept
  (2011-2016, 2017-2019, 2020-2023, 2025), with what each links.
  Wayback answers Python's HTTP client 429 within a few requests while
  serving curl, so its pages go through curl, paced; the 2025 site's CDN
  wants a referrer.
- ruision_snapshot.py builds the snapshot in board-render:1. It keeps the
  IP camera boards only, by the category a page names or, where none, by
  what the text says the board is: 134 archived analog, AHD/TVI/CVI,
  hybrid, DVR/HVR/NVR boards and finished cameras are left out. The chip
  and sensor are taken where a page names them; a series whose pages name
  other variants (RS-T805) gets no sensor. The live modules name no chip:
  the PCB markings in their photos are kept verbatim as a "PCB marking"
  row, and three chips legible there (Hi3516CV608, Hi3516CV610-10B,
  Hi3519DV500) as "Chip (from the photo)".
- 61 boards: 31 live, 30 discontinued; 13 with a chip, 6 with a sensor,
  61 with a photo, 257 files. Pinned at 86462735f1a0; two builds give the
  same bytes. A rehearsal import on a scratch database makes 61 models,
  61 units and 310 files; a second import adds nothing.
- Migration 045 adds the source; Ruision joins the makers (also 睿视科技,
  芯睿视, Corevision) and the card summary order.
- Hi3516CV610 as its package is marked (-10B, -20S, -00S) resolves to the
  catalogue's variants, which are named by memory with the u-boot each
  takes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add Ruision’s current and archived IP camera boards

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add 61 Ruision IP camera boards from current and archived catalogues, excluding non-IP products.
• Pin a reproducible snapshot with photos, documents, and sourced chip and sensor details.
• Register Ruision as a maker and source, with localized provenance notes and import coverage.
Diagram

graph TD
  Live["Live API"] --> Capture["Ruision capture"] --> Builder["Snapshot builder"] --> Tar["Pinned snapshot"] --> Importer["Board importer"] --> DB[("Board database")] --> Cards["Board cards"]
  Archive["Wayback archive"] --> Capture
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Import only the live catalogue
  • ➕ Avoids Wayback retrieval and historical-page classification.
  • ➖ Omits 30 discontinued boards and their archived evidence.
2. Maintain a hand-curated board manifest
  • ➕ Makes each inclusion decision explicit without an archival parser.
  • ➖ Makes source capture and repeatable regeneration harder to audit.

Recommendation: Keep the capture-to-pinned-snapshot approach: it follows the existing donor import architecture while preserving evidence for discontinued boards. The alternatives reduce complexity but lose either historical coverage or reproducibility.

Files changed (13) +912 / -2

Enhancement (5) +868 / -2
api.goInclude Ruision in board-card summary priority +1/-1

Include Ruision in board-card summary priority

• Adds Ruision to the source ordering used to choose names and descriptions for board cards.

service/internal/boards/api.go

parse.goRegister Ruision as a board maker +5/-1

Register Ruision as a board maker

• Defines Ruision’s maker identity, aliases, and position alongside existing manufacturers.

service/internal/boards/parse.go

snapshot.goPin the Ruision snapshot and resolve marked SoC variants +10/-0

Pin the Ruision snapshot and resolve marked SoC variants

• Registers the snapshot hash and maps three Hi3516CV610 package markings to the catalogue’s memory-specific SoC variants.

service/internal/boards/snapshot.go

ruision.pyCapture live and archived Ruision catalogues +286/-0

Capture live and archived Ruision catalogues

• Fetches current API products and files plus Wayback product pages and linked assets into a logged, resumable capture. Archived requests use paced curl retrieval, and CDN requests include a referrer.

tools/board-donors/ruision.py

ruision_snapshot.pyBuild a reproducible IP camera board snapshot +566/-0

Build a reproducible IP camera board snapshot

• Filters out non-IP products, merges live and archived records by board code, and retains supported specifications, photos, documents, markings, and sourced chip and sensor details. Writes a deterministic donor archive for import.

tools/board-donors/ruision_snapshot.py

Tests (1) +32 / -0
snapshot_test.goTest Ruision snapshot import +32/-0

Test Ruision snapshot import

• Checks maker aliases, SoC resolution, and source units for an archived board and a current board without a named chip.

service/internal/boards/snapshot_test.go

Other (7) +12 / -0
boards.en.ymlAdd English Ruision source note +1/-0

Add English Ruision source note

• Describes the current and archived Ruision catalogues and the provenance of chip and sensor information.

data/locales/boards.en.yml

boards.ru.ymlAdd Russian Ruision source note +1/-0

Add Russian Ruision source note

• Provides the Ruision catalogue provenance note in Russian.

data/locales/boards.ru.yml

boards.zh.ymlAdd Chinese Ruision source note +1/-0

Add Chinese Ruision source note

• Provides the Ruision catalogue provenance note in Chinese.

data/locales/boards.zh.yml

boards.en.jsonExpose English Ruision provenance on the site +1/-0

Expose English Ruision provenance on the site

• Adds the Ruision source note to the site’s English board translations.

frontend/apps/site/src/i18n/boards.en.json

boards.ru.jsonExpose Russian Ruision provenance on the site +1/-0

Expose Russian Ruision provenance on the site

• Adds the Ruision source note to the site’s Russian board translations.

frontend/apps/site/src/i18n/boards.ru.json

boards.zh.jsonExpose Chinese Ruision provenance on the site +1/-0

Expose Chinese Ruision provenance on the site

• Adds the Ruision source note to the site’s Chinese board translations.

frontend/apps/site/src/i18n/boards.zh.json

045_board_ruision.sqlAllow Ruision as a board source +6/-0

Allow Ruision as a board source

• Extends the database’s board_source enum so imported Ruision records can identify their source.

service/internal/db/migrations/045_board_ruision.sql

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Archived links can read local files ✓ Resolved
Description
links() accepts file:// and arbitrary network URLs from archived HTML, and fetch_linked()
passes non-Ruision links to Capture.get() without validating their destination. A crafted product
page can make the capture process read a local file or request a private-network address, with a
successful response retained in the capture and potentially packaged into the snapshot.
Code

tools/board-donors/ruision.py[R252-255]

+    host = urllib.parse.urlsplit(u).hostname or ""
+    if "ruision.com" not in host:
+        e, body = cap.get(u, headers=REFERER)
+        if body is not None:
Evidence
The new archive link extractor filters by filename and page furniture, not by scheme or destination.
Its direct-fetch branch sends external links to the shared fetcher, which opens supplied URLs and
stores successful bodies; the snapshot builder subsequently consumes captured linked files.

tools/board-donors/ruision.py[184-194]
tools/board-donors/ruision.py[249-265]
tools/board-donors/capture.py[66-100]
tools/board-donors/ruision_snapshot.py[377-384]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Archived product pages can supply local-file or private-network URLs that the capture process fetches and stores.
## Fix Focus Areas
- tools/board-donors/ruision.py[184-194]
- tools/board-donors/ruision.py[249-265]
- tools/board-donors/ruision.py[167-179]
## Recommended Fix
Accept only HTTP(S) URLs on the vendor and explicitly approved asset hosts. Reject private and loopback destinations, and enforce the same restrictions after redirects before retaining a response. Apply the policy to live API assets as well as archived links.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. A codec mention can attach the wrong sheet ✓ Resolved
Description
archived() selects a standalone PDF's model using c in norm(name) or c in norm(text), so the
existing model code H2 matches an unrelated occurrence of H264. When a sheet contains that codec
but no actual model code, the builder attaches it to H2 without checking a code boundary.
Code

tools/board-donors/ruision_snapshot.py[R420-421]

+        known = sorted(set(out) | set(skipped), key=len, reverse=True)
+        code = next((c for c in known if c in norm(name) or c in norm(text)), None)
Evidence
norm leaves H264 unchanged, H2 is a Ruision model, and the PDF lookup searches for model codes
as substrings of normalized text before appending the PDF to the selected model.

tools/board-donors/ruision_snapshot.py[90-91]
tools/board-donors/ruision_snapshot.py[420-433]
service/internal/boards/snapshot_test.go[1116-1126]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Substring matching can attribute a standalone specification sheet to an unrelated short model code such as H2.
## Fix Focus Areas
- tools/board-donors/ruision_snapshot.py[419-433]
## Recommended Fix
Extract complete board-code tokens from the filename and PDF text, then match those tokens to models rather than searching normalized prose for arbitrary substrings. Preserve the explicit revision-suffix fallback only after a full code token has been identified.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Archived office documents disappear ✓ Resolved
Description
archived() classifies only links ending in .pdf as documents and sends every other captured link
through the photo path. Word and Excel files accepted by the capture script cannot be decoded by
picture(), so their captured specification files never enter the snapshot.
Code

tools/board-donors/ruision_snapshot.py[R381-384]

+            if re.search(r"\.pdf$", f["url"], re.I):
+                docs.append((src, os.path.basename(f["url"])))
+            else:
+                photos.append(src)
Evidence
The capture's file pattern expressly includes Office extensions. The builder routes anything other
than a URL ending in .pdf to photos, while picture() returns no output for non-images; only
files that survive these paths are added to the manifest.

tools/board-donors/ruision.py[62-63]
tools/board-donors/ruision_snapshot.py[377-384]
tools/board-donors/ruision_snapshot.py[146-164]
tools/board-donors/ruision_snapshot.py[503-525]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The capture retains Word and Excel links, but the snapshot treats them as photos and drops them.
## Fix Focus Areas
- tools/board-donors/ruision_snapshot.py[376-384]
- tools/board-donors/ruision_snapshot.py[503-525]
## Recommended Fix
Classify supported document extensions, including Word and Excel formats, as documents before building the photo list. Determine the extension from the URL path so a document link with query parameters is classified consistently.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Findings visible per group, which tucks the rest behind a View link

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread tools/board-donors/ruision.py Resolved
Comment thread tools/board-donors/ruision_snapshot.py Resolved
Comment thread tools/board-donors/ruision_snapshot.py Resolved
…s match whole codes

Review of #541.

- The capture fetched any address a page linked: archived pages link
  their authors' file:///C:/ paths, which urllib would read from the
  local disk. Only http(s) on a public host is fetched now, before and
  after redirects (curl may not redirect off http(s)).
- A sheet archived on its own was matched to a board by substring, so
  RS-H612-A0's sheet, whose text has "F8" in it, went to the F8 module.
  The codes a sheet names are now taken whole; RS-H612-A0 (Hi3516D,
  AR0130) is a board of its own: 62 boards, 14 with a chip, 7 with a
  sensor. Re-pinned at be6f5bf024c5; two builds give the same bytes.
- Word and Excel files a page links are documents, not pictures that
  fail to decode (none is linked today).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@openipc-ai
openipc-ai merged commit 9d7f533 into master Oct 31, 2026
2 checks passed
@openipc-ai
openipc-ai deleted the boards-ruision branch October 31, 2026 11:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant