Skip to content
WildweaselMSPublic

About

Use a cheap WiFi ear camera / otoscope (Soulear app, Hopefox) on your PC without the phone app. ESP32-C3 USB bridge + Python viewer with recording and auto-rotation. Also a mini endoscope for electronics, DIY and machines.

Topics

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

NJFE - Not Just For Ears: USB bridge for cheap WiFi endoscopes

NJFE: Not Just For Ears

Use a cheap WiFi ear camera on your PC instead of the phone app. These cameras are sold as WiFi otoscope, ear wax removal camera or ear cleaner with camera and normally only work with a smartphone app such as Soulear. NJFE is an open-source alternative: an ESP32-C3 joins the camera's WiFi, speaks its i4season UDP protocol and forwards the live JPEG stream over USB to a Python GUI (tested on Windows). The same camera then also works as a mini endoscope / inspection camera for electronics, DIY and machines.

Note

Vibe-coded with Claude. The entire development of this project was done in conversation with Claude (Anthropic) via Claude Code: research, protocol implementation, ESP32 firmware, PC tools, tests and this documentation. The human part: the idea, the hardware, testing on the real device and the decisions. Read the code with that in mind, and please report anything that looks off.

Tested with the Hopefox Find T ("Ohrenschmalz Entferner mit Kamera", WiFi name Soulear-xxxxx, firmware HKV41B). Other cameras that use the Soulear app / i4season protocol will likely work too.

The camera reports itself as BK7231U-XRH-FBPRO (vendor "YPC"), but according to a teardown on Elektroda and EarCam the actual SoC is a Taixin TXW816-810 (Taixin hgSDK) with a HI708 image sensor; the Beken name seems to be a leftover product string. Not verified on our unit (the case is hard to open without damage). The sensor delivers 480×480 JPEG at ~17 fps; the "1080p" in product listings does not match the hardware.

Hence the name: Not Just For Ears. The camera is a mini endoscope: a slim, short probe with a camera and LED at the tip and a live image at ~17 fps. That makes it a cheap inspection tool for:

  • Electronics work: checking solder joints, reading tiny SMD markings, looking under connectors or into the gaps of closed housings
  • DIY and repairs: peeking into small openings, drill holes, crevices and mechanisms you can't get your eye close to
  • Mechanical engineering: inspecting bores, threads, gear teeth, bearings and hard-to-reach spots in machines and assemblies

With the PC GUI you get a bigger image than on a phone, plus photos and video recording.

flowchart LR
    PC["PC<br/>gui.py / viewer.py"]
    ESP["ESP32-C3 SuperMini<br/>bridge firmware<br/>192.168.1.10"]
    CAM["Endoscope<br/>(ear camera)<br/>192.168.1.1"]

    PC <-->|"USB serial<br/>commands ↓ · JPEG + IMU ↑"| ESP
    ESP <-->|"WiFi (camera's own AP)<br/>i4season UDP"| CAM

    subgraph isolated["Isolated camera WiFi: no internet, no phone, no app"]
        ESP
        CAM
    end
Loading

NJFE GUI: live image of a circuit board with an IC and SMD parts, round mask, auto-rotation

Electronics inspection: an IC and SMD parts on a PCB.

Why an ESP32 bridge? Security and privacy

The camera's USB port is charge-only, and it only offers an open WiFi access point. Normally you would install the vendor's app on your phone and join that WiFi. NJFE replaces both with a small, open-source USB bridge:

  • No third-party app on your phone. No closed-source app from an unknown vendor asking for camera, storage, location or network permissions on the device that holds your contacts, photos, messages and banking apps.
  • No account, no cloud, no telemetry. The images go from the camera over USB to your PC and nowhere else. Nothing needs internet access.
  • Your phone and PC stay on their own networks. Neither has to join the camera's open, unencrypted WiFi. The PC only sees a USB serial port, so the camera network never gets a route into your home network or the internet.
  • Images stay local. Photos and videos are plain files in a folder you control (and are git-ignored, since ear images are health data).
  • Auditable. Firmware and PC tools are under 1,000 lines of open source code that you can read, build and flash yourself.

What it does not fix: the camera's own WiFi is still open, so someone in radio range could join it while the camera is on. See SECURITY.md.

Features

  • Live image, ~17 fps, 480×480 JPEG
  • Photo (original JPEG) and video recording (MJPG AVI)
  • Auto-rotation from the camera's accelerometer, manual 90° rotation and mirroring
  • Round mask (hides the corners that appear when the image is rotated)
  • LED on/off, battery level
  • WiFi selection: scan, pick a network, stored on the ESP32 across reboots
  • OLED status on the ESP32 (connection, fps, data rate, battery)

Hardware

Part Notes
ESP32-C3 SuperMini with 0.42" OLED 72×40 SSD1306, I²C SDA=GPIO5, SCL=GPIO6, native USB (USB-Serial-JTAG)
i4season/Soulear WiFi ear camera camera must be switched on (AP appears as Soulear-*)

No wiring needed. The ESP32 is only connected to the PC via USB.

ESP32-C3 SuperMini on USB next to the WiFi ear camera with its probe LED on ESP32-C3 SuperMini close-up, the OLED shows fps 17, 640x480, 339 kB/s, bat 93%

Left: the whole setup, camera on, bridge plugged into the PC. Right: the bridge's OLED with live stats (fps, header resolution, data rate, camera battery).

Quick start

  1. Flash the bridge firmware (see below).
  2. pip install -r wifi_scanner/tools/requirements.txt
  3. Switch on the camera.
  4. python wifi_scanner/tools/gui.py, select the ESP32 port, click Connect.

The ESP32 connects automatically to the strongest Soulear-* network.

Firmware (PlatformIO)

wifi_scanner/platformio.ini has three environments:

Environment Source Purpose
esp32c3_supermini src/ WiFi scanner, highlights camera networks on the OLED
soulear_probe src_probe/ TCP port probe of the camera (diagnostics; set TARGET_SSID first)
soulear_stream src_i4season/ The bridge used by the PC tools
cd wifi_scanner
pio run -e soulear_stream -t upload --upload-port COM10

If the upload stops with "No serial data received" after the baud change, flash without the stub loader:

python ~/.platformio/packages/tool-esptoolpy/esptool.py --chip esp32c3 --port COM10 \
  --baud 115200 --no-stub write_flash -z 0x10000 .pio/build/soulear_stream/firmware.bin

Toolchain: PlatformIO espressif32@6.11.0 (Arduino core 2.0.17), library U8g2.

PC tools

GUI (wifi_scanner/tools/gui.py)

Tkinter:

Control Function
Port, ↻, Connect/Disconnect choose and open the ESP32 serial port (Espressif ports are listed first)
WiFi, Scan, Apply scan networks (camera networks first), choose one and store it on the ESP32; (auto: Soulear-*) = strongest camera network
LED on/off switch the camera LED, the button shows the state reported by the camera
Round mask circular mask over the image
Auto-rotate (IMU) rotate the image so that "up" stays up, based on the accelerometer
Photo / Record save a JPEG / start and stop an AVI recording
Rotate 90°, Mirror manual orientation; the rotation is remembered in wifi_scanner/tools/gui.ini
Folder open the output folder

Photos and videos are saved to wifi_scanner/snapshots/ (git-ignored). Photos are the original JPEG unless the image was transformed. The status line shows fps, resolution, battery and the IMU angle.

Minimal viewer (wifi_scanner/tools/viewer.py)

python wifi_scanner/tools/viewer.py --port COM10
python wifi_scanner/tools/viewer.py --port COM10 --test 50   # no window, receive 50 frames, print fps

Keys: q/Esc quit, s snapshot, r rotate 90°, m mirror.

Serial interface (ESP32 ↔ PC)

USB CDC, the baud rate setting is ignored.

PC → ESP32, text, one command per line:

Command Effect
LED 1 / LED 0 camera LED on/off, reply led on=<0/1> bright=<n>
SCAN reply SCAN-BEGIN, lines AP <rssi> <ssid>, SCAN-END
STATUS connected to <ssid>, own IP <ip> plus LED state, or not connected, target '<ssid>'
SSID <name> store the target network in flash and reconnect; SSID alone = automatic

ESP32 → PC: text log lines (one stats line per second) interleaved with binary frame records, all little-endian:

AA 55 'J' 'P' 'G' | u32 jpegLen | u32 gsensor | u8 flags | u8 packetType | JPEG bytes

flags bit 0 = gsensor valid. The viewer resyncs on the magic and checks the JPEG markers (FFD8 … FFD9), so corrupted frames are dropped instead of shown.

Camera protocol (summary)

UDP, camera at 192.168.1.1. Every message starts with a 12-byte header: u32 0xFFEEFFEE | u16 seq | u16 cmd | u8 1 | u8 status | u16 payloadLen.

Cmd Port Meaning
0x0001 10005 device info: vendor, product, firmware, SSID, MAC, battery
0x0002 10005 licence query (sent like the vendor app)
0x0004 10006 open video: u16 picPort, u16 audioPort, u32 clientId, repeated while no video arrives
0x000A 10005 LED: u8 op (1 = read, 0x11 = write), u8 on, u8 brightness

Video arrives on picPort (40000) as chunked JPEG. Each chunk carries a 16-byte (type 1) or 28-byte (type 6) header with sequence, frame id, last-chunk flag and a packed 3-axis accelerometer sample (9-bit magnitude + sign per axis, ~130 counts/g). Roll angle = atan2(y, z), plus 180° for products whose sensor is mounted upside down.

Details and the original reverse engineering: otoscope.

Troubleshooting

Symptom Cause / fix
OLED shows "waiting for Soulear-*" camera off or out of range; it is retried automatically
GUI connected, but no image camera was just switched on, wait a few seconds; check the log for open video -> ok
Port busy close other programs using the port (GUI, viewer, serial monitor) before flashing
Upload fails after baud change use the --no-stub command above
Status line cut off widen the window (happens with 150 % display scaling)
Wrong auto-rotation direction not verified on every model, use manual rotation and report the product name

Security notes

The camera's WiFi is open (no password), and its protocol has no authentication. See SECURITY.md.

Disclaimer

  • Not a medical device. NJFE is not intended for diagnosis or treatment. Do not use it as a substitute for a doctor. Inserting objects into the ear canal can injure the ear; if you use the camera in your ear, follow the manufacturer's instructions.
  • No liability for damage to people or machines. This project is provided "as is", without warranty of any kind. To the extent permitted by law, the authors accept no liability for any injury to people or animals, or for damage to equipment, machines, devices or data resulting from building or using it (see sections 15 and 16 of the GPL-3.0). This includes damage to the camera, the ESP32, your PC or the object you inspect, e.g. by shorting live electronics with the metal probe or by pushing it into moving or energized machinery. Switch machines off and disconnect power before inspecting them.
  • AI-assisted code, limited testing. The code was written with AI assistance (Claude) and tested on one device only.
  • No affiliation. Not affiliated with or endorsed by Hopefox or the makers of the Soulear app; names are used only to identify compatible hardware.

Use at your own risk.

Acknowledgements

This project stands on the shoulders of people who did the hard reverse-engineering work first. Big thanks to:

  • otoscope by rubec: an open Android app for cheap WiFi otoscopes. Its i4season implementation was the blueprint for the whole bridge: packet header, commands, video chunking, the accelerometer bit layout, the roll formula, the LED command and the 180° mount offset. Without it this would have taken weeks of packet sniffing. (GPL-3.0, which is why this project is GPL too.)
  • Suear Web Viewer by Sean Pesce: research on the closely related Suear/i4season cameras that helped identify the device family and confirm the protocol direction.
  • NE3-Scope by haxko: work on another family of cheap WiFi ear cameras; its network names went into the WiFi scanner's list of known camera prefixes.
  • EarCam by jduanen: command table probing of the same Soulear camera (including the warning that command 0x0008 powers the camera off) and the chip identification.
  • Elektroda teardown of the Taixin TXW816-810 based otoscopes: PCB pinout, UART logs and flash dump.
  • wifi-otoscope-viewer by TJRSchmidbauer: browser viewer tested on the identical BK7231U-XRH-FBPRO / HKV41B unit, which confirmed the 480×480 sensor resolution.

And to the projects this is built with: U8g2 (OLED), Arduino core for ESP32 / ESP-IDF, PlatformIO, pySerial, OpenCV, NumPy and Pillow.

License

GPL-3.0-or-later, see LICENSE. The protocol implementation is derived from the GPL-3.0 project otoscope, see NOTICE.

About

Use a cheap WiFi ear camera / otoscope (Soulear app, Hopefox) on your PC without the phone app. ESP32-C3 USB bridge + Python viewer with recording and auto-rotation. Also a mini endoscope for electronics, DIY and machines.

Topics

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages