Skip to content

Fix 6 functional bugs#10

Open
richstokes wants to merge 5 commits intoclyang:masterfrom
richstokes:fix/gr3-api-bugs
Open

Fix 6 functional bugs#10
richstokes wants to merge 5 commits intoclyang:masterfrom
richstokes:fix/gr3-api-bugs

Conversation

@richstokes
Copy link

@richstokes richstokes commented Mar 14, 2026

Summary

Six functional bug fixes.

Bugs Fixed

1. NameError crash in getDeviceModel() and getBatteryLevel()
The error handlers on lines 37 and 52 referenced an undefined variable photoDict instead of the correct props. This causes a NameError crash whenever the camera returns errCode != 200, hiding the actual error message.

2. File regex rejects .DNG files
The -f argument validator accepted .RAW but the GR III/IIIx cameras produce .DNG files (Adobe DNG format). Confirmed by firmware analysis: the webapid binary uses the format identifier rawdng and serves these files with Content-Type: image/x-adobe-dng. This prevented users from starting a sync from a DNG file. As far as I can tell, Ricoh never used a .RAW file

3. Socket timeout too short for large file downloads (2s → 30s)
The 2-second global socket timeout caused downloads to fail for large files. The camera's WiFi AP is 2.4 GHz only, delivering ~3-6 MB/s real-world throughput. Full JPEGs are 15-30 MB and DNG raws are 30-40 MB, meaning individual file transfers can take 5-10+ seconds. Increased to 30 seconds.

4. Post-sync action powers off camera instead of disconnecting WiFi
shutdownGR() called POST /v1/device/finish which powers off the entire camera. Firmware analysis confirmed this endpoint triggers a full shutdown via sysmgrd. Changed to POST /v1/device/wlan/finish which only disconnects WiFi, allowing the user to continue shooting.

5. --last counter decrements on already-downloaded files
The download_last_n_pictures counter decremented for every file encountered, including files that were skipped because they already existed locally. With --last 5, if 3 of those 5 files already existed, only 2 new files would be downloaded. Fixed to only decrement on files that were actually new.

6. Float division in Python 3 progress display
count/2 produces a float in Python 3 (showing e.g. 2.5/10 in progress output). Changed to count//2 for integer division.

1. Fix NameError crash in getDeviceModel() and getBatteryLevel()
   Error handlers referenced undefined 'photoDict' instead of 'props',
   causing a NameError crash whenever the camera returns errCode != 200.

2. Fix file regex rejecting .DNG files
   The -f argument validator used '\.RAW$' but GR III cameras produce
   .DNG files (Adobe DNG raw format), not .RAW. This prevented starting
   a sync from a DNG file.

3. Increase socket timeout from 2s to 30s
   The 2-second global timeout caused downloads to fail for large files.
   The camera's 2.4 GHz WiFi delivers ~3-6 MB/s. Full JPEGs are 15-30 MB
   and DNG raws are 30-40 MB, requiring 5-10+ seconds per file.

4. Use /v1/device/wlan/finish instead of /v1/device/finish
   The previous endpoint (/v1/device/finish) powers off the entire camera
   after every sync. Changed to /v1/device/wlan/finish which only
   disconnects WiFi, allowing the user to keep shooting.

5. Fix --last counter decrementing on already-downloaded files
   The download_last_n_pictures counter decremented even for files that
   were skipped (already exist locally). With --last 5, if 3 files
   already existed, only 2 new files would be downloaded instead of 5.

6. Fix float division in Python 3 progress display
   count/2 produces a float in Python 3 (e.g. '2.5/10'), changed to
   count//2 for integer division.

Co-Authored-By: Oz <oz-agent@warp.dev>
Copilot AI review requested due to automatic review settings March 14, 2026 02:46
@richstokes richstokes changed the title Fix 6 functional bugs (found via GR IIIx firmware reverse engineering) Fix 6 functional bugs Mar 14, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the GRsync script to improve correctness of error reporting, make post-sync behavior less destructive, and improve reliability/UX for large transfers from the camera over Wi‑Fi.

Changes:

  • Fix incorrect variables used in /v1/props error logging.
  • Replace camera power-off call with a Wi‑Fi disconnect endpoint after sync completion.
  • Improve download behavior and UX (integer progress formatting, --last logic, longer socket timeout, .DNG validation).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

richstokes and others added 2 commits March 13, 2026 19:49
The original shutdownGR() hardcoded 'http://192.168.0.1/' instead of
using the GR_HOST constant. Now uses GR_HOST consistently with the
rest of the script.

Co-Authored-By: Oz <oz-agent@warp.dev>
disconnectGR():
- Wrap in try/except and close the response. This endpoint tears
  down the WiFi connection we're communicating over, so the HTTP
  response may never arrive. Without this, the script could crash
  with a network error after an otherwise successful sync.

--last counter:
- Only decrement download_last_n_pictures after a successful
  fetchPhoto(). Previously it decremented on any new file
  (including failed downloads), so transient transfer errors
  would cause the loop to stop early with fewer than N photos.

Co-Authored-By: Oz <oz-agent@warp.dev>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the GRsync script’s post-sync behavior and download limiting logic, aiming to improve usability when syncing from Ricoh GR cameras over Wi‑Fi.

Changes:

  • Fix incorrect error reporting in getDeviceModel() / getBatteryLevel() when the props API returns a non-200 errCode.
  • Replace camera power-off behavior with a “graceful Wi‑Fi disconnect” call after downloads complete.
  • Adjust --last handling, progress counting, socket timeout, and update raw filename matching from .RAW to .DNG.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

…ntics

- disconnectGR(): pass explicit 3s timeout to urlopen() so post-sync
  teardown can't hang for 30s (the global default). Narrow the except
  clause to (IOError, OSError) — covers URLError, socket.timeout, and
  OS-level network errors — instead of catching all exceptions.

- --last N: decrement the counter for every encountered photo (skipped,
  failed, or successfully downloaded) so the flag means 'process the
  last N photos from the list', not 'successfully download N new photos'.
  Photos filtered out by --jpg/--raw still don't count against the limit.

Co-Authored-By: Oz <oz-agent@warp.dev>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates GRsync.py to improve reliability and usability when syncing photos from Ricoh GR cameras over Wi‑Fi, including safer post-sync behavior and better Python 3 compatibility.

Changes:

  • Fixes incorrect error reporting in device property fetches (getDeviceModel, getBatteryLevel).
  • Replaces camera power-off behavior with a Wi‑Fi disconnect call (disconnectGR) after downloads complete.
  • Improves Python 3 behavior and user options: integer progress math, --last handling, longer socket timeout, and .DNG start-file validation.
Comments suppressed due to low confidence (1)

GRsync.py:258

  • Now that .DNG is accepted as a valid start file, the validation failure message below still says the filename should look like R0999999.JPG only. Update the error message (and/or argparse help text) to mention .DNG as well so users aren’t misled.
            match = re.match(r"^R0\d{6}\.DNG$", args.file)
        if match:
            STARTFILE = args.file
        else :
            print("Incorrect file name. It should be something like R0999999.JPG. (all in CAPITAL)")

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

totalPhoto / 2 produces a float in Python 3, which then raises
TypeError when formatted with %d in the progress/skip messages.
Use // to keep it an int.

Co-Authored-By: Oz <oz-agent@warp.dev>
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.

2 participants