464 lines
9.6 KiB
Markdown
464 lines
9.6 KiB
Markdown
# FieldPOC
|
|
|
|
A simple to use, good enough phone system for medium sized DECT networks.
|
|
|
|
## Setup
|
|
|
|
FieldPOC requires a Mitel SIP DECT phone system, i.e. RFP L43 WLAN.
|
|
Make sure you have the equipment, else this software is quit useless.
|
|
|
|
This is more a sample setup.
|
|
Everything described here can be done on multiple different ways.
|
|
We just try to document a way that is proven to work.
|
|
|
|
Get a computer, i.e. an APU Board, and install Archlinux on it.
|
|
This can be a VM too, but you have to adapt stuff.
|
|
|
|
### Config
|
|
|
|
Create a file `fieldpoc_config.json`.
|
|
This is your FieldPOC config in JSON format.
|
|
You will add details to it with each step.
|
|
|
|
### Networking
|
|
|
|
We assume you use two network interfaces `enp2s0` and `enp3s0`.
|
|
Configuration examples are for systemd-networkd.
|
|
|
|
```
|
|
systemctl enable --now systemd-networkd.service
|
|
```
|
|
|
|
Your FieldPOC box will act as a normal DHCP Client on `enp2s0`.
|
|
This is the interface you connect to the internet and where you may connect to the box via SSH.
|
|
|
|
`/etc/systemd/network/20-wired.network`
|
|
```
|
|
[Match]
|
|
Name=enp2s0
|
|
|
|
[Network]
|
|
DHCP=yes
|
|
```
|
|
|
|
The other interface `enp3s0` will be the DECT network.
|
|
This is the network where you connect your RFPs.
|
|
We will run a dedicated DHCP Server on this network.
|
|
|
|
`/etc/systemd/network/30-dect.network`
|
|
```
|
|
[Match]
|
|
Name=enp3s0
|
|
|
|
[Network]
|
|
Address=10.222.222.1/24
|
|
```
|
|
|
|
As the DHCP Server for this network we use `kea`.
|
|
|
|
```
|
|
pacman -S kea
|
|
```
|
|
|
|
`/etc/kea/kea-dhcp4.conf`
|
|
```
|
|
{
|
|
"Dhcp4": {
|
|
"interfaces-config": {
|
|
"interfaces": [
|
|
"enp3s0"
|
|
]
|
|
},
|
|
"lease-database": {
|
|
"name": "/var/lib/kea/dhcp4.leases",
|
|
"persist": true,
|
|
"type": "memfile"
|
|
},
|
|
"option-def": [
|
|
{
|
|
"code": 43,
|
|
"encapsulate": "sipdect",
|
|
"name": "vendor-encapsulated-options",
|
|
"space": "dhcp4",
|
|
"type": "empty"
|
|
},
|
|
{
|
|
"code": 10,
|
|
"name": "ommip1",
|
|
"space": "sipdect",
|
|
"type": "ipv4-address"
|
|
},
|
|
{
|
|
"code": 19,
|
|
"name": "ommip2",
|
|
"space": "sipdect",
|
|
"type": "ipv4-address"
|
|
},
|
|
{
|
|
"code": 14,
|
|
"name": "syslogip",
|
|
"space": "sipdect",
|
|
"type": "ipv4-address"
|
|
},
|
|
{
|
|
"code": 15,
|
|
"name": "syslogport",
|
|
"space": "sipdect",
|
|
"type": "int16"
|
|
},
|
|
{
|
|
"code": 224,
|
|
"name": "magic_str",
|
|
"space": "dhcp4",
|
|
"type": "string"
|
|
}
|
|
],
|
|
"subnet4": [
|
|
{
|
|
"option-data": [
|
|
{
|
|
"data": "10.222.222.1",
|
|
"name": "routers"
|
|
}
|
|
],
|
|
"pools": [
|
|
{
|
|
"pool": "10.222.222.100 - 10.222.222.200"
|
|
}
|
|
],
|
|
"reservations": [
|
|
{
|
|
"hostname": "<name of your oom>",
|
|
"hw-address": "<mac address of your oom>",
|
|
"ip-address": "10.222.222.11",
|
|
"option-data": [
|
|
{
|
|
"data": "<name of your oom>",
|
|
"name": "host-name"
|
|
},
|
|
{
|
|
"name": "vendor-encapsulated-options"
|
|
},
|
|
{
|
|
"data": "10.222.222.11",
|
|
"name": "ommip1",
|
|
"space": "sipdect"
|
|
},
|
|
{
|
|
"data": "OpenMobilitySIP-DECT",
|
|
"name": "magic_str"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"subnet": "10.222.222.0/24"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
Start the service.
|
|
|
|
```
|
|
systemctl enable --now kea-dhcp4
|
|
```
|
|
|
|
### Database
|
|
|
|
```
|
|
pacman -S postgresql
|
|
```
|
|
|
|
Init database.
|
|
|
|
```
|
|
su - postgres -c "initdb --locale en_US.UTF-8 -D '/var/lib/postgres/data'"
|
|
```
|
|
|
|
```
|
|
systemctl enable --now postgresql
|
|
```
|
|
|
|
Open SQL shell
|
|
|
|
```
|
|
sudo -u postgres psql
|
|
```
|
|
|
|
Create database and user for routing engine.
|
|
Change the password.
|
|
|
|
```
|
|
CREATE USER fieldpoc WITH PASSWORD 'fieldpoc';
|
|
CREATE DATABASE fieldpoc WITH OWNER fieldpoc;
|
|
```
|
|
|
|
Add the database credetials to your `fieldpoc_config.json`.
|
|
|
|
```
|
|
{
|
|
"database": {
|
|
"host": "127.0.0.1",
|
|
"username": "fieldpoc",
|
|
"password": "fieldpoc",
|
|
"database": "fieldpoc"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Phone Server
|
|
|
|
```
|
|
pacman -S yate
|
|
```
|
|
|
|
Remove all files in `/etc/yate/` and add the following instead:
|
|
|
|
#### Dialout SIP connection
|
|
|
|
`accfile.conf`
|
|
```
|
|
[dialout]
|
|
enabled=yes
|
|
protocol=sip
|
|
registrar=10.222.222.254
|
|
username=dialout
|
|
password=xxx
|
|
```
|
|
|
|
#### Call deduplication
|
|
|
|
`cdrbuild.conf`
|
|
```
|
|
[parameters]
|
|
X-Eventphone-Id=false
|
|
```
|
|
|
|
#### Yate remote control socket
|
|
|
|
`extmodule.conf`
|
|
```
|
|
[listener fieldpoc]
|
|
type=tcp
|
|
addr=127.0.0.1
|
|
port=5039
|
|
```
|
|
|
|
Add the information for the remote control socket to `fieldpoc_config.json`:
|
|
|
|
```
|
|
{
|
|
"yate": {
|
|
"host": "127.0.0.1",
|
|
"port": 5039
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Database connection
|
|
|
|
Replace credentials with the ones you have choosen.
|
|
|
|
`pgsqldb.conf`
|
|
```
|
|
[default]
|
|
host=127.0.0.1
|
|
database=fieldpoc
|
|
user=fieldpoc
|
|
password=fieldpoc
|
|
```
|
|
|
|
#### Call routing
|
|
|
|
`regexroute.conf`
|
|
```
|
|
[default]
|
|
${username}^$=-;error=noauth
|
|
^iocaste$=goto dialin
|
|
^99991001$=tone/dial
|
|
^99991002$=tone/busy
|
|
^99991003$=tone/ring
|
|
^99991004$=tone/specdial
|
|
^99991005$=tone/congestion
|
|
^99991006$=tone/outoforder
|
|
^99991007$=tone/milliwatt
|
|
^99991008$=tone/info
|
|
^.*$=line/\0;line=dialout
|
|
|
|
[dialin]
|
|
${sip_x-called}^.*$=lateroute/\1
|
|
```
|
|
|
|
#### User registration
|
|
|
|
`register.conf`
|
|
```
|
|
[general]
|
|
expires=30
|
|
|
|
user.auth=yes
|
|
user.register=yes
|
|
user.unregister=yes
|
|
engine.timer=yes
|
|
;call.preroute=no
|
|
call.cdr=yes
|
|
linetracker=yes
|
|
|
|
[default]
|
|
priority=10
|
|
account=default
|
|
|
|
[user.auth]
|
|
query=SELECT password FROM users WHERE username='${username}' AND password IS NOT NULL AND password<>'' AND type='user' LIMIT 1;
|
|
result=password
|
|
|
|
[user.register]
|
|
query=INSERT INTO registrations (username, location, oconnection_id, expires) VALUES ('${username}', '${data}', '${oconnection_id}', NOW() + INTERVAL '${expires} s') ON CONFLICT ON CONSTRAINT uniq_registrations DO UPDATE SET expires = NOW() + INTERVAL '${expires} s'
|
|
|
|
[user.unregister]
|
|
query=DELETE FROM registrations WHERE (username = '${username}' AND location = '${data}' AND oconnection_id = '${connection_id}') OR ('${username}' = '' AND '${data}' = '' AND oconnection_id = '${connection_id}')
|
|
|
|
[engine.timer]
|
|
query=DELETE FROM registrations WHERE expires<=CURRENT_TIMESTAMP;
|
|
|
|
[call.cdr]
|
|
critical=no
|
|
|
|
[linetracker]
|
|
critical=yes
|
|
initquery=UPDATE users SET inuse=0 WHERE inuse is not NULL;DELETE from active_calls;
|
|
cdr_initialize=UPDATE users SET inuse=inuse+1 WHERE username='${external}';INSERT INTO active_calls SELECT username, x_eventphone_id FROM (SELECT '${external}' as username, '${X-Eventphone-Id}' as x_eventphone_id, '${direction}' as direction) as active_call WHERE x_eventphone_id != '' AND x_eventphone_id IS NOT NULL and direction = 'outgoing';
|
|
cdr_finalize=UPDATE users SET inuse=(CASE WHEN inuse>0 THEN inuse-1 ELSE 0 END) WHERE username='${external}';DELETE FROM active_calls WHERE username = '${external}' AND x_eventphone_id = '${X-Eventphone-Id}' AND '${direction}' = 'outgoing';
|
|
```
|
|
|
|
### DECT
|
|
|
|
Just choose one of your RFPs as your OMM.
|
|
Find out the MAC address and fill it in the according fields in the kea config before.
|
|
|
|
Please generate a 16-characters long hexadecimal string as `sipsecret`.
|
|
This allowes the SIP accounts used for DECT phones to get a deterministic, but somewhat secure internal password.
|
|
|
|
Create a privileged user account and add the credentials to `fieldpoc_config.json`:
|
|
|
|
```
|
|
{
|
|
"omm": {
|
|
"host": "10.222.222.11",
|
|
"username": "omm",
|
|
"password": "<password>"
|
|
"sipsecret": "<secret>"
|
|
}
|
|
}
|
|
```
|
|
|
|
### FieldPOC
|
|
|
|
Make sure Python is installed.
|
|
|
|
```
|
|
pacman -S python
|
|
```
|
|
|
|
Install FieldPOC:
|
|
|
|
```
|
|
pip install git+https://git.clerie.de/clerie/fieldpoc@main
|
|
```
|
|
|
|
FieldPOC provides a telnet socket for debugging and state mangement, add config for this to `fieldpoc_config.json` too:
|
|
|
|
```
|
|
{
|
|
"controller": {
|
|
"host": "127.0.0.1",
|
|
"port": 9437
|
|
}
|
|
}
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Init
|
|
|
|
Some datastructures have get prepared once:
|
|
|
|
```
|
|
fieldpoc -c /path/to/fieldpoc_config.json -e /path/to/fieldpoc_extensions.json --init
|
|
```
|
|
|
|
### Run
|
|
|
|
```
|
|
fieldpoc -c /path/to/fieldpoc_config.json -e /path/to/fieldpoc_extensions.json
|
|
```
|
|
|
|
## Debug
|
|
|
|
Show log messages:
|
|
|
|
```
|
|
fieldpoc -c /path/to/fieldpoc_config.json -e /path/to/fieldpoc_extensions.json --debug
|
|
```
|
|
|
|
## Development setup
|
|
|
|
Make sure you have [mitel_ommclient2](https://git.clerie.de/clerie/mitel_ommclient2) in your Python modules path.
|
|
|
|
Add user credentials to your OMM to `fieldpoc_config.json`.
|
|
|
|
Edit `fieldpoc_extensions.json` to meet your preferences.
|
|
|
|
Start FieldPOC:
|
|
|
|
```
|
|
python -m fieldpoc.run
|
|
```
|
|
|
|
List some options:
|
|
|
|
```
|
|
python -m fieldpoc.run --help
|
|
```
|
|
|
|
## Architecture
|
|
|
|
FieldPOC is daemon that takes a defined state and makes all connected services fit that state.
|
|
Each connected service is observed by a dedicated class executed in a seperate thread.
|
|
There exist some more classes and threads to just glue everything together.
|
|
|
|
### `extensions.json`
|
|
|
|
The `extensions.json` file is the core of the whole setup and defines the state.
|
|
It contains which extensions exist and for what they should be used.
|
|
|
|
### `fieldpoc.py`
|
|
|
|
This file containes the main class `FieldPOC`.
|
|
It spawns the mentioned threads, initializes other classes and provices communication queues between the threads/classes.
|
|
|
|
### `config.py`
|
|
|
|
This manages FieldPOCs configuration.
|
|
|
|
### `controller.py`
|
|
|
|
The controller provices an interactive interface to manage and debug FieldPOC.
|
|
|
|
### `run.py`
|
|
|
|
This is a thin wrapper to start FieldPOC.
|
|
|
|
### `dect.py`
|
|
|
|
This deals with the Mitel OMM and configures all phones based on the current state.
|
|
|
|
### `routing.py`
|
|
|
|
This part sets up Yate using Ywsd, registers all extensions and configures routing.
|
|
|
|
### `ywsd.py`
|
|
|
|
This starts Ywsd with FieldPOC so you don't have to start it seperately.
|