remote-phone-control 0.1.0

Creator: bradpython12

Last updated:

0 purchases

TODO
Add to Cart

Description:

remotephonecontrol 0.1.0

Remote Phone Control - v0.1.0
Some SIP hardphone brands support the features Action URIs and Action URLs on some or all of their phone models. Action URIs are used to remote control a phone by sending it HTTP GET requests. E.g., place a call. Action URLs are used to communicate events occuring on a phone to an HTTP service. E.g. an incoming call.

This Python package primarily serves as a remote controller and a listener for the call related commands to and events from a phone. Its main intent and focus is to automate the testing of call scenarios.

Supported phones
In principle, Remote Phone Control, could be extended to support any phone that provides the Action URI and Action URL features. Currently, only the SNOM models noted under the Stack heading are tested and supported.
Action URIs and methods
These are HTTP GET requests with query parameters to control a phone, make it do something. remote_phone_control hides the URIs and query parameters in a phone class object, e.g. Snom, and its methods. The methods are mapped to and use corresponding URI and query parameters. The table below lists currently implemented methods for Snom class objects. The method names are quite self explanatory. A description is provided if more clarification is needed. Consult SNOM Remote phone control via http for reference.



Method
Arguments
Returns
Description




callout
number: str
bool



pickup
None
bool



hangup
None
bool



hangup_onhook
None
bool



hangup_all
None
bool



senddtmf
digits: str
bool
Send in-band DTMF


senddtmf_sipinfo
digits: str
bool
Send DTMF using SIP-INFO


expect
event: Literal['incoming', 'connect', 'disconnect'], timeout: int = event_wait_timeout
bool
Returns True if your expectation was correct. The default timeout to wait for the event is 15 seconds


clear_events
None
None
Call this together with hangup_all in case a test goes awry and phones are left with dangling, standing calls.


set_disable_speaker
value: Literal['on', 'off']
bool
Turn audible cues/ the speaker on or off


set_setting
setting: str, value: str
bool
setting is the name of the phone setting you want to set to value. For settings name reference browse to the phone's settings page: http://<phone's ip-address>/settings.htm


press_px
x: str
bool
Simulates pressing a free programmable function key


transfer
None
bool



reboot
None
bool



stop
None
None
When you're done consuming Snom, you MUST call stop to stop the Snom's Action Server



Action URLs and handled events
A phone will send an HTTP GET request to the Action URL when triggered by an event. The remote_phone_control package is the endpoint, target, of the request. It will parse and process the request.
Event to Action URL mappings
The events currently handled by remote_phone_control are per the following table.



Event
Description
Action URL used by the phone




Incoming call
There is an incomming call, the phone is ringing
http://<remote_phone_control ip-address>:<port>/event?ip=$phone_ip&event=incoming&local=$local&remote=$remote


On Connected
Fired when a call is established
http://<remote_phone_control ip-address>:<port>/event?ip=$phone_ip&event=connected&local=$local&remote=$remote


On Disconnected
A call is ended
http://<remote_phone_control ip-address>:<port>/event?ip=$phone_ip&event=disconnected&local=$local&remote=$remote



With remote_phone_control you can use these events as verification points when testing a call. E.g., when a phone is called, we can verify if there is an incoming call. When the call is answered, we can check if there's an established call.
For further reference on Action URL s consult SNOM Action URLs
Action URL, format and query parameters
The Action URL is configured on the phone. remote_phone_control will configure this automatically on the phone given the ip-address of the phone. See Usage for an example.
Below, the format used by remote_phone_control to set the Action URL on the phone.
http://<Remote Phone Controller ip-address>:<port>/event?ip=$phone_ip&event=<event>&local=$local&remote=$remote


<Remote Phone Controller ip-address>: The ip-address of the node where a remote_phone_control package is run.
<port>: The Action server port served by remote_phone_control
$phone_ip: A phone variable that will be replaced by the phone's ip-address
<event>: indicates to remote_phone_control what event triggered the request

Currently remote_phone_control parses and handles the following <event>s

incoming
connected
disconnected




$local: A phone variable that will be replaced by the local sip-id related to the event
$remote: A phone variable that will be replaced by the remote sip-id related to the event

Stack
This was used to develop and test the package. Not to say that other combinations of, e.g., Python, Ubuntu, phone models, phone firmware might also work. The SNOM models used are not very recent though. End of life even. So, no guarantees that the package will work for newer models unmodified. But my first impression after skimming through the documentation of recent SNOM models is that the Action URI and Action URL support looks very similar.

Python: 3.8.10
Ubuntu: 20.04.6 LTS
This Python package was tested with the following SIP hardphones


SNOM



Model
Firmware




300
8.7.3.19, 8.7.3.25 8.7.5.17


320
8.7.3.19, 8.7.3.25 8.7.5.17


360
8.7.3.19, 8.7.3.25







Installation
From PyPI
(venv) $ pip install remote-phone-control

From GibHub
(venv) $ pip install git+https://github.com/p4irin/remote_phone_control.git

Verify
(venv) $ python
Python 3.8.10 (default, May 26 2023, 14:05:08)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import remote_phone_control
>>> remote_phone_control.__version__
'0.0.1'
>>> import remote_phone_control.snom
>>> dir(remote_phone_control.snom)
['ActionServer', 'Literal', 'Snom', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'requests']
>>>

Usage
Preconditions
A list of what to account for in order to remote control phones for test automation.

Networking

Preferably use a setup where the node, on which remote_phone_control is running, the phones, the registrar and the call proxy are on the same subnet
If remote_phone_control, the phones, the registrar and the call proxy are on different subnets, make sure they can see, reach each other. E.g., look at you're routing configuration.
No firewall between remote_phone_control and phones
No firewall on remote_phone_control 's node, Ubuntu, as mentioned under Stack
No NAT between remote_phone_control and phones


The phones MUST be provisioned and working

Are registered
Can call each other
Can, optionally, call out to PSTN
Can, optionally, receive incoming calls originating from the PSTN


What data you need

ip addresses of the phones
the username and password of the phones
allocate, list an Action server port for each phone. Each phone will be controlled by a separate instance of a phone class object, e.g. Snom, that will also handle a phone's events through an Action URL
ip address of remote_phone_control 's node. This will be used as the Action server's ip-address for each phone object as you can control several phones from the same node.
a sip-id (outgoing URI) on the phone to use for call operations.



Basic examples
The examples given are included in the package's source as unit tests, in the tests sub directory. The package's tests use Python's standard library unit testing framework. For simplicity's sake, the examples below do not.
Imports and Snom instances
These imports and Snom instantiations must precede all the standalone examples.
import time
from remote_phone_control.snom import Snom


snom_a = Snom(
"nnn.nnn.nnn.nnn", # ip-address of a SNOM phone
"nnn.nnn.nnn.nnn", # Action Server's ip-address
nnnn, # Action Server's listening port
"username", # username to access the SNOM
"password", # password to access the SNOM
"outgoing URI", # a sip-id configured on the SNOM
"extension" # the SNOM's extension
)

snom_b = Snom(
"nnn.nnn.nnn.nnn",
"nnn.nnn.nnn.nnn",
nnnn,
"username",
"password",
"outgoing URI",
"extension"
)

N.B.

The Action Server's ip-address is the ip-address of the node where remote_phone_control is used. Remember, the Action Server is served by remote_phone_control.
The Action Server's listening port MUST be unique for each Snom instance
The outgoing URI is the sip account used for calling

Example: Call out to PSTN
E.g., set your mobile phone to auto answer and call it.
assert snom_a.callout('PSTN number to call') == True
assert snom_a.expect('connect') == True
time.sleep(5) # Represents a 5 seconds conversation
assert snom_a.hangup() == True
assert snom_a.expect('disconnect') == True

snom_a.stop()

SNOM A calls SNOM B, B answers, call is established, B ends the call
snom_a.callout("Extension of SNOM B")
assert snom_b.expect('incoming') == True
snom_b.pickup()
assert snom_b.expect('connect') == True
time.sleep(5) # Represents a 5 seconds conversation
snom_b.hangup()
assert snom_b.expect('disconnect') == True

snom_a.stop()
snom_b.stop()

A calls B, B rejects the call
snom_a.callout("Extension of SNOM B")
assert snom_b.expect('incoming') == True
# Reject the incoming call
snom_b.hangup()
assert snom_a.expect('disconnect')

snom_a.stop()
snom_b.stop()

An actual use case
To get a feel of how you can use this package. It proofed very useful in automating end to end regression tests of a cloud hosted call center web app where an agent is tied to a browser interface, the GUI, and a SIP phone. Call actions displayed and performed on the GUI should be in sync with the actual state of the phone and vice versa. Using Selenium, call actions are executed on the GUI and the state of the phone checked against the expectation using the package. Using the package, call actions are executed on the phone and the GUI state checked using Selenium. Inbound calls, with an external origin, i.e. PSTN, and several other scenarios are checked against both the state of the GUI and the phone. Gluing it all together with Python's standard library unittest framework.
Reference

SNOM

Remote phone control via http
Action URLs
http://<phone's ip-address>/settings.htm


Yealink

Action URI
How to dial or place a call using remote control?


Python

Requests: HTTP for Humans

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Files:

Customer Reviews

There are no reviews.