diff --git a/README.md b/README.md index b23d263..085442c 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,401 @@ 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. + +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": "", + "hw-address": "", + "ip-address": "10.222.222.11", + "option-data": [ + { + "data": "", + "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. + +Create a privileged user account and add the credentials to `fieldpoc_config.json`: + +``` +{ + "omm": { + "host": "10.222.222.11", + "username": "omm", + "password": "" + } +} +``` + +### 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]() in your Python modules path. +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`. diff --git a/fieldpoc_config.json b/fieldpoc_config.json index d50da62..7ad91a7 100644 --- a/fieldpoc_config.json +++ b/fieldpoc_config.json @@ -4,7 +4,7 @@ "port": 9437 }, "dect": { - "host": "192.168.0.100", + "host": "10.222.222.11", "username": "omm", "password": "xxx" },