User Tools

Site Tools


articles:pentax_k-1_wifi

Pentax K-1 WiFi analysis

This article documents my findings of analyzing the Pentax K-1 WiFi protocol. The camera has built-in WiFi functionality. An app on a phone (Android and iOS) allows one to remote control the camera and browse images. Here, I want to figure out how it's implemented.

Preparation

The first step to analyzing the protocol is to be able to intercept the communication between the app and the camera. Therefore, I installed the Image Sync app on my phone and extracted the APK from it.

Extracting the APK

In short, install ADB on a computer, connect the phone with USB debugging enabled and run the following command:

adb shell 'pm list packages -f com.ricohimaging.imagesync'

It should output the path of the apk, as in:

package:/data/app/com.ricohimaging.imagesync-2/base.apk=com.ricohimaging.imagesync

Now, download that file to the current directory:

adb pull /data/app/com.ricohimaging.imagesync-2/base.apk .

See the second half of http://android.stackexchange.com/a/75436/34272 for good instructions.

ARC Welder

ARC Welder is a Chrome app that provides an Android runtime environment inside Chrome. Install that and load the base.apk downloaded from the phone.

Connect computer to WiFi

Next, enable WiFi on the camera and connect the computer to that network. Start wireshark to generate a trace of the connection and then start the Ricoh app in Chrome.

Protocol

The app talks HTTP to the camera. First, it gets general information about the camera's capabilities and then switches to a WebSocket connection to stream requests/responses. Here's an overview of the end points it exports.

/v1/props

GET /v1/props HTTP/1.1

The first request is sent to /v1/props. It returns a Json file describing the camera:

{"errCode": 200,
 "errMsg": "OK",
 "resoList": [ "1080x720", "720x480"],
 "movieResoList": [ "1280x720", "720x404"],
 "WBModeList": [ "auto", "multiAuto", "daylight", "shade", "cloud", "daylightFluorescent", "dayWhiteFluorescent", "coolWhiteFluorescent", "warmWhiteFluorescent", "tungsten", "cte", "manual1", "manual2", "manual3", "colorTemp1", "colorTemp2", "colorTemp3"],
 "stillSizeList": [ "L3", "L2", "L1", "M3", "M2", "M1", "S3", "S2", "S1", "XS3", "XS2", "XS1"],
 "movieSizeList": [ "FHD30p", "FHD25p", "FHD24p", "HD60p", "HD50p", "FHD60i", "FHD50i"],
 "shootModeList": [ "single", "continuousH", "continuousM", "continuousL", "self12s", "self2s", "selfCotinuous", "remocon", "remocon3s", "remoconContinous", "bracket", "bracketSelf", "bracketRemocon", "multiExp", "multiExpContinuous", "multiExpSelf", "multiExpRemocon", "interval", "intervalSelf", "intervalRemocon", "intervalComp", "intervalCompSelf", "intervalCompRemocon", "intervalMovie", "intervalMovieSelf", "intervalMovieRemocon", "starstream", "starstreamSelf", "starstreamRemocon", "mirrorUp", "mirrorUpRemcon"],
 "effectList": [ "cim_natural", "cim_bright", "cim_portrait", "cim_landscape", "cim_vibrant", "cim_radiant", "cim_muted", "cim_bleachBypass", "cim_reversal", "cim_monochrome", "cim_crossProcess", "cim_auto", "cim_flat"],
 "filterList": ["off", "dfl_extractColor", "dfl_replaceColor", "dfl_toyCamera", "dfl_retro", "dfl_highContrast", "dfl_shading", "dfl_negaPosi", "dfl_solidMonoColor", "dfl_hardMonochrome", "hdr_auto", "hdr_mode1", "hdr_mode2", "hdr_mode3", "hdr_modeA"],
 "exposureModeList": [ "P", "SV", "TV", "AV", "TAV", "M", "B", "X", "U1", "U2", "U3", "U4", "U5", "auto", "gps", "movie"],
 "avList": [ "4.0", "4.5", "5.0", "5.6", "6.3", "7.1", "8.0", "9.0", "10", "11", "13", "14", "16", "18", "20", "22", "25", "29"],
 "tvList": [ "30.1", "25.1", "20.1", "15.1", "13.1", "10.1", "8.1", "6.1", "5.1", "4.1", "3.1", "25.10", "2.1", "16.10", "13.10", "1.1", "8.10", "6.10", "5.10", "4.10", "3.10", "1.4", "1.5", "1.6", "1.8", "1.10", "1.13", "1.15", "1.20", "1.25", "1.30", "1.40", "1.50", "1.60", "1.80", "1.100", "1.125", "1.160", "1.200", "1.250", "1.320", "1.400", "1.500", "1.640", "1.800", "1.1000", "1.1250", "1.1600", "1.2000", "1.2500", "1.3200", "1.4000", "1.5000", "1.6400", "1.8000"],
 "svList": ["auto", "100", "200", "400", "800", "1600", "3200", "6400", "12800", "25600", "51200", "102400", "204800"],
 "xvList": [ "+5.0", "+4.7", "+4.3", "+4.0", "+3.7", "+3.3", "+3.0", "+2.7", "+2.3", "+2.0", "+1.7", "+1.3", "+1.0", "+0.7", "+0.3", "0.0", "-0.3", "-0.7", "-1.0", "-1.3", "-1.7", "-2.0", "-2.3", "-2.7", "-3.0", "-3.3", "-3.7", "-4.0", "-4.3", "-4.7", "-5.0"],
 "exposureModeOption": "",
 "state": "idle",
 "av": "4.0",
 "tv": "4.1",
 "sv": "200",
 "xv": "0.0",
 "WBMode": "auto",
 "shootMode": "single",
 "exposureMode": "U1",
 "stillSize": "L3",
 "movieSize": "FHD30p",
 "effect": "cim_natural",
 "filter": "off",
 "timerExposure": false,
 "focused": false,
 "focusCenters": [],
 "focusEffectiveArea": [70,64],
 "focusMode": "af",
 "model": "PENTAX K-1",
 "firmwareVersion": "01.40",
 "macAddress": "AC:3F:A4:(hidden)",
 "serialNo": "(hidden)",
 "channelList": [0,1,2,3,4,5,6,7,8,9,10,11],
 "hot": false,
 "battery": 100,
 "stillFormatList": [ "jpeg", "pef", "rawpef"],
 "storages" : [
 {"name":"sd1",
 "equipped": true,
 "writable": true,
 "available": true,
 "active": true,
 "format": "rawpef",
 "reservePriority": "high",
 "remain": 1177
 }
,
 {"name":"sd2",
 "equipped": false,
 "writable": false,
 "available": false,
 "active": false,
 "format": "rawpef",
 "reservePriority": "low",
 "remain": 0
 }
 ],
 "ssid": "PENTAX_(hidden)",
 "key": "(hidden)",
 "channel": "6",
 "slotMode": "reserve",
 "liveState": "idle"}

/v1/changes

GET /v1/changes HTTP/1.1

This command is used to upgrade the connection to websocket.

/v1/photos

GET /v1/photos?storage=sd1 HTTP/1.1

List the photos on SD1.

{"errCode": 200,
 "errMsg": "OK",
 "dirs": [
 {
 "name": "100_1112",
 "files": [ "IMGP1774.JPG", "IMGP1774.PEF"]
 },
 {
 "name": "101_1113",
 "files": [ "IMGP1775.JPG", "IMGP1775.PEF"]
 },
 {
 "name": "102_1117",
 "files": [ "IMGP1856.JPG"]
 }
 ]
}

/v1/photos/...

GET /v1/photos/102_1117/IMGP1856.JPG?size=thumb&storage=sd1 HTTP/1.1

Reads a specific thumbnail image from the SD card. The camera replies with a HTTP 200 OK and sends a jpeg encoded image.

GET /v1/photos/102_1117/IMGP1857.JPG?size=view&storage=sd1 HTTP/1.1

Reads a larger resolution image from the SD card.

GET /v1/photos/102_1117/IMGP1857.JPG/info?storage=sd1 HTTP/1.1

Get meta information on an image.

{"errCode": 200,
 "errMsg": "OK",
 "captured": true,
 "dir": "102_1117",
 "file": "IMGP1857.JPG",
 "av": "4.0",
 "sv": "200",
 "xv": "0",
 "tv": "1.8",
 "orientation": 1,
 "cameraModel": "PENTAX K-1",
 "latlng": "47.000000,8.000000",
 "datetime": "2016-11-17T23:00:00"}

/v1/liveview

GET /v1/liveview HTTP/1.1

Seems to initiate live viewing. It didn't really work in the app.

/v1//lens/focus

POST /v1/lens/focus HTTP/1.1

Parameters are pos=52,52. I think they refer to where the focus point is set. The camera sends the following reply:

{"errCode": 200,
 "errMsg": "OK",
 "focused": true,
 "focusCenters": [],
 "focusEffectiveArea": [70,64]}

/v1/camera/shoot

POST /v1/camera/shoot HTTP/1.1

Parameters are af=off. It shoots a picture.

{"errCode": 200,
 "errMsg": "OK",
 "focused": true,
 "focusCenters": [],
 "focusEffectiveArea": [70,64],
 "captured": false}

/v1/params/camera

PUT /v1/params/camera HTTP/1.1

Sets various camera paramters. Here are some examples:

sv=auto
xv=0.0

Without form encoded data, it replies:

{"errCode": 200,
 "errMsg": "OK",
 "avList": [ "4.0", "4.5", "5.0", "5.6", "6.3", "7.1", "8.0", "9.0", "10", "11", "13", "14", "16", "18", "20", "22", "25", "29"],
 "tvList": [ "30.1", "25.1", "20.1", "15.1", "13.1", "10.1", "8.1", "6.1", "5.1", "4.1", "3.1", "25.10", "2.1", "16.10", "13.10", "1.1", "8.10", "6.10", "5.10", "4.10", "3.10", "1.4", "1.5", "1.6", "1.8", "1.10", "1.13", "1.15", "1.20", "1.25", "1.30", "1.40", "1.50", "1.60", "1.80", "1.100", "1.125", "1.160", "1.200", "1.250", "1.320", "1.400", "1.500", "1.640", "1.800", "1.1000", "1.1250", "1.1600", "1.2000", "1.2500", "1.3200", "1.4000", "1.5000", "1.6400", "1.8000"],
 "svList": ["auto", "100", "200", "400", "800", "1600", "3200", "6400", "12800", "25600", "51200", "102400", "204800"],
 "xvList": [ "+5.0", "+4.7", "+4.3", "+4.0", "+3.7", "+3.3", "+3.0", "+2.7", "+2.3", "+2.0", "+1.7", "+1.3", "+1.0", "+0.7", "+0.3", "0.0", "-0.3", "-0.7", "-1.0", "-1.3", "-1.7", "-2.0", "-2.3", "-2.7", "-3.0", "-3.3", "-3.7", "-4.0", "-4.3", "-4.7", "-5.0"],
 "exposureModeOption": "",
 "state": "idle",
 "av": "4.0",
 "tv": "1.40",
 "sv": "800",
 "xv": "0.0",
 "WBMode": "auto",
 "shootMode": "single",
 "exposureMode": "U1",
 "stillSize": "L3",
 "movieSize": "FHD30p",
 "effect": "cim_natural",
 "filter": "off",
 "timerExposure": false}

/v1/photos/latest/...

GET /v1/photos/latest/info?storage=sd1 HTTP/1.1

Gets information about the latest picture. Camera replies

{"errCode": 200,
 "errMsg": "OK",
 "captured": true,
 "dir": "102_1117",
 "file": "IMGP1857.JPG",
 "av": "4.0",
 "sv": "200",
 "xv": "0",
 "tv": "1.8",
 "orientation": 1,
 "cameraModel": "PENTAX K-1",
 "latlng": "47.000000,8.000000",
 "datetime": "2016-11-17T23:20:17"}
articles/pentax_k-1_wifi.txt · Last modified: 2016/11/17 23:16 by moritz