Skip to content

Instantly share code, notes, and snippets.

@franga2000
Last active May 14, 2024 20:17
Show Gist options
  • Save franga2000/1be2aa18cb3409e57af149883c06e34a to your computer and use it in GitHub Desktop.
Save franga2000/1be2aa18cb3409e57af149883c06e34a to your computer and use it in GitHub Desktop.
Xiaomi Yi

Xiaomi Yi camera

General info

  • OS: Buildroot
  • CPU: ARMv6-compatible processor rev 5 (v6l)
  • BogoMIPS: 524.28
  • Memory: 37MB

The root filesystem is rootfs, which is stored in memory and therefore wiped on reboot. The Micro SD card is mounted at /tmp/fuse_d/. Something is also mounted at /tmp/fuse_a and /tmp/fuse_z.

WiFi AP

  • SSID: YDXJ_[last 7 digits of SN]
  • Default pass: 1234567890
  • Securtiy: WPA2-Personal
  • Camera IP: 192.168.42.1

Nmap scan:

Opened ports on 192.168.42.1
Discovered open port 80/tcp on 192.168.42.1
Discovered open port 554/tcp on 192.168.42.1
Discovered open port 53/tcp on 192.168.42.1
Discovered open port 8787/tcp on 192.168.42.1
Discovered open port 7878/tcp on 192.168.42.1

##Shell access To enable shell access you must create an empty file on the SD card named enable_info_display.script. Then you can connect to the camera using telnet:

telnet 192.168.42.1 23

You will be presented a login promt:

buildroot login: 

Type root and hit enter. You are now connected to the camera's root Linux shell


Telnet commands

Technically just a raw TCP socket connection, but it's easier to just call it telnet.

telnet 192.168.42.1 7878

Meta

Error messages sent by the camera:

  • {"rval": -7} - Input is not a valid JSON object
  • {"rval":-4,"msg_id":0} - Input object is empty
  • {"rval":-9,"msg_id":0} - Input object is not a valid command

Token

All requests require a token you have to request when connecting to the camera:

Request:

{"msg_id":257, "token":0}

Response:

{ "rval": 0, "msg_id": 257, "param": 1 }

param is your token. All requests in this article have the token set to 1. This will be different for you.

Config

Request:

{"msg_id":3, "token":1} 

Response:

NOTE: The config is a list of objects of settings, not just an object of settings. You have to use a loop!

{
	"rval": 0,
	"msg_id": 3,
	"param": [
		{"camera_clock": "2015-04-07 02:32:29"},
		{"video_standard": "NTSC"},
		{"app_status": "idle"},
		{"video_resolution": "1920x1080 60P 16:9"},
		{"video_stamp": "off"},
		{"video_quality": "S.Fine"},
		{"timelapse_video": "off"},
		{"capture_mode": "precise quality"},
		{"photo_size": "16M (4608x3456 4:3)"},
		{"photo_stamp": "off"},
		{"photo_quality": "S.Fine"},
		{"timelapse_photo": "60"},
		{"preview_status": "on"},
		{"buzzer_volume": "mute"},
		{"buzzer_ring": "off"},
		{"capture_default_mode": "precise quality"},
		{"precise_cont_time": "60.0 sec"},
		{"burst_capture_number": "7 p / s"},
		{"restore_factory_settings": "on"},
		{"led_mode": "all enable"},
		{"dev_reboot": "on"},
		{"meter_mode": "center"},
		{"sd_card_status": "insert"},
		{"video_output_dev_type": "tv"},
		{"sw_version": "YDXJv22_1.0.7_build-20150330113749_b690_i446_s699"},
		{"hw_version": "YDXJ_v22"},
		{"dual_stream_status": "on"},
		{"streaming_status": "off"},
		{"precise_cont_capturing": "off"},
		{"piv_enable": "off"},
		{"auto_low_light": "on"},
		{"loop_record": "off"},
		{"warp_enable": "off"},
		{"support_auto_low_light": "on"},
		{"precise_selftime": "5s"},
		{"precise_self_running": "off"},
		{"auto_power_off": "5 minutes"},
		{"serial_number": "xxxxx"},
		{"system_mode": "capture"},
		{"system_default_mode": "capture"},
		{"start_wifi_while_booted": "off"},
		{"quick_record_time": "0"},
		{"precise_self_remain_time": "0"},
		{"sdcard_need_format": "no-need"},
		{"video_rotate": "off"}
	]
}

Photo capture

Request:

{"msg_id":769,"token":1}

Response:

{ "msg_id": 7, "type": "start_photo_capture", "param":"precise quality;off"}
{ "msg_id": 7, "type": "photo_taken", "param":"/tmp/fuse_d/DCIM/100MEDIA/YDXJ0047.jpg"}
  • param is the full path of the image

NOTE: To get the download URL of the image, replace /tmp/fuse_d/ with http://192.168.42.1/.

Telnet events

All messages with msg_id: 7 are events and are sent automatically by the camera.

{ "msg_id": 7, "type": "<string: event name>"}

Some events also provide additional data in the param attribute:

{ "msg_id": 7, "type": "<string: event name>", "param":"<int: event data>"}

Below is a list of known events, their parameters and an example for each

Battery

Fired when the battery level changes

{ "msg_id": 7, "type": "battery", "param":"20"}
  • type is battery when discharging and adapter when charging
  • param is the battery charge percentage (int 1-100, obviously)

Charger status

Fired when the USB charging cable is connected/disconnected

{ "msg_id": 7, "type": "adapter_status" ,"param":"1"}
  • param:0 - cable disconnected
  • param:1 - cable connected

Camera mode switched

Fired when the recording mode is changed (big button on the front)

{ "msg_id": 7, "type": "switch_to_rec_mode" }
  • type:"switch_to_rec_mode" - switched to video mode
  • type:"switch_to_cap_mode" - switched to photo mode

Photo taken

{ "msg_id": 7, "type": "start_photo_capture" ,"param":"precise quality;off"}
{ "msg_id": 7, "type": "precise_capture_data_ready" }
{ "msg_id": 7, "type": "photo_taken" ,"param":"/tmp/fuse_d/DCIM/100MEDIA/YDXJ0513.jpg"}

SD Card status

Fired when the SD card is inserted/removed

{ "msg_id": 7, "type": "sd_card_status" ,"param":"insert"}
  • type:"insert" - SD card inserted
  • type:"remove" - SD card removed When SD card is removed, the following event also fires:
{ "msg_id": 7, "type": "CARD_REMOVED" }

Live view

After you've successfully authenticated through telnet, you can connect to rtsp://192.168.42.1:554/live with VLC (or similar) to see the live view of the camera.

This doesn't always work. The only 100% way I know is to first connect with the official app.

Unknown events

Photo taken vf_start/stop

Fired after start_photo_capture Best guess: stop live view

{ "msg_id": 7, "type": "vf_stop" }

Fired after photo_taken Best guess: start live view

{ "msg_id": 7, "type": "vf_start" }

vf == "viewfinder" ?

Battery status

This message has been observed when taking out the battery with the cam on USB power, but I haven't been able to reproduce it so far.

{ "msg_id": 7, "type": "battery_status" ,"param":"0"}
  • param - observed values0 and -1
@franga2000
Copy link
Author

I hope this helps anyone who wants to hack on it further. I've been trying to reverse how it works for almost a year and it never ceases to amaze me how the giant mess that is this camera's firmware somehow still manages to work fairly well. Good luck! :D

@muzzol
Copy link

muzzol commented Oct 25, 2017

can you give an example with nc reading from stdin more than one line?
I'm trying without any success something like this:

(
echo '{"msg_id":257,"token":0}'
echo '{"msg_id":513,"token":1}'
) | nc -i 1 192.168.42.1 7878

@cara
Copy link

cara commented Nov 29, 2018

What's the best way to log / sniff the responses returned to the app (iOS/Android). I have the YI Action Camera with 1.5.12 and it seems like some msgs were changed.. Thank you in advance!

@flleeppyy
Copy link

Is this up to date anymore? I'm trying to fiddle around with my Yi Lite Camera. I'm trying to turn it into a Webcam instead of having to stream over wifi which has delay

@franga2000
Copy link
Author

I don't know if it is, but getting the latency much lower than WiFi probably isn't easy. If the hardware allows it, you could try to forward the socket over USB using Linux gadgets, but the latency probably comes earlier in the pipeline. An HDMI capture card will be your best bet there - you can get some surprisingly good ones for 12$ on various Chinese sites.

@piranha771
Copy link

@franga2000 I think vf_start + vf_stop stands for video feed. Is the live video feed stopped when vf_stop occurs? That would explain it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment