Using a Raspberry Pi to end an iPhone phone call
Headphone breakout switch
A user can end a phone call by clicking the headphone switch.
A program can end a phone call by closing a headphone breakout switch.
Advantages
- Fun!
Disadvantages
- Overly complicated compared to springboard solution.
- Not very general, clicking switch works for only a few actions
- Requires some hardware
- Could accidentally damage phone or raspberry pi or yourself. If you are careful I think the risks are low, but no warranty!
- Not directly applicable to phone without a headphone jack, but could substitute an actuator to mechanically press switch.
Prototype system
The system has several parts
- Phoney app
- Phoney XCUITest
- iPhone
- Raspberry Pi
- pi_gpio_service
- Relay
- Cable, relay to breakout switch
- Headphone breakout switch
- Headphone
- Cable, breakout switch to phone
Phoney app, request_web_service_end_call branch
https://github.com/beepscore/Phoney
It has a button to call a phone number.
Phoney XCUITest
XCUITest runs the test from Swift on iOS. It needs a way to ask the raspberry pi to end the call.
I didn't see an easy way to issue a system call or spawn a process.
So XCUITest makes an http request to an external web server, ask it to close switch.
iPhone
Making a phone call requires a device, not a simulator.
Raspberry Pi
The Raspberry Pi runs a web service and connects to a relay board.pi_gpio_service
runs on the local wifi network.
https://github.com/beepscore/pi_gpio_service
Server security
Currently the prototype service runs on the local network, and is not very secured.
By default an iOS app that talks with a web service requires https and TLS 1.2.
Apparently XCUITest doesn't require this, at least when talking with a service on the local network.
Relay
The relay acts like the headset "end call" switch, momentarily shorting the headset microphone contact to ground.
Cable, relay to breakout switch
Coaxial splitter, 1 female to 2 males (female unused)
Headphone breakout switch
Making an iPhone Headphone Breakout Switch
Headphone
A standard iPhone wired headphone with a 4 connector plug.
Cable, breakout switch to phone
Connects breakout switch to phone. 3.5 mm 4 conductor male to 3.5 mm 4 conductor male
Test Flow
- The XCUITest starts the Phoney app on the iOS device
- The test taps the alert "Call" button
- iOS calls callObserver callChanged with call.hasConnected
- The iOS XCUITest sends an http request to the pi web service to end the call.
let urlString = "https://10.0.0.4:5000/api/v1/gpio/end-phone-call/"
let url = URL(string: urlString)!
var request = URLRequest(url: url)
request.setValue("application/json", forHTTPHeaderField: “Content-Type")
request.httpMethod = "POST"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
// ...
}
task.resume()
# POST but not GET because GET should not change any state on the server
@app.route("/api/v1/gpio/end-phone-call/", methods=['POST'])
def gpio_end_phone_call():
return end_phone_call()
def end_phone_call():
"""
simulate manually clicking headphone switch to end a phone call
:return: result of last pin_update
"""
relay0 = pfd.output_pins[0]
relay1 = pfd.output_pins[1]
# turn relay0 on
relay0.value = 1
delay_seconds = 0.4
sleep(delay_seconds)
# turn relay0 off
relay0.value = 0
Test failure
The test adds a UIInterruptionMonitor, then interacts with the app UI via swipeUp or tap.
Without this, the iOS phone call alert handler doesn't fire.
But with it, the test usually ends with error ~ "Application for Target Application 0x1c40af060 is not foreground.".
I fixed the failure by switching to springboard. That made this approach obsolete.
References
XCUITest iOS app phone call
Phoney
Phoney is an iOS application to experiment with testing phone calls.
https://github.com/beepscore/Phoney
request_web_service_end_call branch
Uses XCUITest to make an http request to an external web server, asks it to end call by closing switch.
master branch
Uses XCUITest with Springboard to tap End call button.
pi_gpio_service
Make a simple Python flask web service to read and write Raspberry Pi GPIO.
https://github.com/beepscore/pi_gpio_service
Relay
PiFace Digital 2
purchased from Vetco Electronics
https://www.element14.com/community/docs/DOC-69001/l/piface-digital-2-for-raspberry-phttps://www.piface.org.uk/products/piface_digital/