From bfaadd556cc3f8a3ebd7b65bd1b3921846f4ad4b Mon Sep 17 00:00:00 2001 From: Ivan Gerasimov Date: Sun, 27 Sep 2026 23:41:15 +0300 Subject: [PATCH] =?UTF-8?q?lct-51:=20=D0=B3=D0=BE=D0=BB=D0=BE=D1=81=D0=BE?= =?UTF-8?q?=D0=B2=D0=BE=D0=B9=20=D0=BC=D0=B0=D1=80=D1=88=D1=80=D1=83=D1=82?= =?UTF-8?q?=20=D0=94=D0=94=D0=A1=20=E2=80=94=20=D0=B2=D1=8B=D1=88=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=BE=D1=8F=D1=89=D0=B8=D0=B9=20=D0=BD=D0=B0=D1=87?= =?UTF-8?q?=D0=B0=D0=BB=D1=8C=D0=BD=D0=B8=D0=BA=20=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=20WebRTC=206103=20=D1=81=20=D0=B7=D0=B0=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D1=8C=D1=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 1 + Makefile | 2 +- docker-compose.sip.yml | 1 + frontend/src/features/sip/SipPhone.tsx | 13 ++++++++++++- frontend/src/pages/dds/Dds.tsx | 6 ++++-- frontend/src/pages/phone/Phone.tsx | 19 ++++++++++++++++--- sip/entrypoint.sh | 7 +++++-- sip/extensions.conf | 7 ++++--- sip/pjsip.conf.template | 19 +++++++++++++++++++ 9 files changed, 63 insertions(+), 12 deletions(-) diff --git a/.env.example b/.env.example index 486bd1a..1b64d3b 100644 --- a/.env.example +++ b/.env.example @@ -25,6 +25,7 @@ SIP_6002_PASSWORD= SIP_6003_PASSWORD= SIP_6101_PASSWORD= SIP_6102_PASSWORD= +SIP_6103_PASSWORD= # IP/DNS сервера, который WebRTC-клиенты видят в локальной сети. При запуске # только на той же машине оставьте 127.0.0.1; RTP-порты должны отображаться 1:1. SIP_EXTERNAL_MEDIA_ADDRESS=127.0.0.1 diff --git a/Makefile b/Makefile index ca17c3b..58e5f4c 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ sip: ## Собрать и поднять локальный Asterisk SIP/VoIP offline-sip: ## Поднять SIP из уже собранного образа без сети $(COMPOSE) -f docker-compose.yml -f docker-compose.sip.yml up --pull never --no-build -d sip -sip-credentials: ## Показать локальные пароли софтфонов 6001–6003 и WebRTC 6101–6102 +sip-credentials: ## Показать локальные пароли софтфонов 6001–6003 и WebRTC 6101–6103 $(COMPOSE) -f docker-compose.yml -f docker-compose.sip.yml exec -T sip cat /var/lib/lct-sip/credentials.env sip-test: ## Проверить регистрацию, звонок, RTP и задержку (args="--rtp-host-offset 1000") diff --git a/docker-compose.sip.yml b/docker-compose.sip.yml index 25f5160..79d23e6 100644 --- a/docker-compose.sip.yml +++ b/docker-compose.sip.yml @@ -9,6 +9,7 @@ services: SIP_6003_PASSWORD: ${SIP_6003_PASSWORD:-} SIP_6101_PASSWORD: ${SIP_6101_PASSWORD:-} SIP_6102_PASSWORD: ${SIP_6102_PASSWORD:-} + SIP_6103_PASSWORD: ${SIP_6103_PASSWORD:-} SIP_EXTERNAL_MEDIA_ADDRESS: ${SIP_EXTERNAL_MEDIA_ADDRESS:-127.0.0.1} SIP_RTP_START: ${SIP_RTP_START:-10000} SIP_RTP_END: ${SIP_RTP_END:-10099} diff --git a/frontend/src/features/sip/SipPhone.tsx b/frontend/src/features/sip/SipPhone.tsx index 74e506b..4e68a1d 100644 --- a/frontend/src/features/sip/SipPhone.tsx +++ b/frontend/src/features/sip/SipPhone.tsx @@ -12,12 +12,19 @@ const LABEL: Record = { error: "ошибка", }; +/** Абонент быстрого набора: пульт ДДС звонит бригаде и начальнику одной кнопкой. */ +export interface SipContact { + label: string; + number: string; +} + export function SipPhone({ - defaultExtension = "6101", defaultTarget = "6102", title = "Локальный SIP/WebRTC", + defaultExtension = "6101", defaultTarget = "6102", title = "Локальный SIP/WebRTC", contacts = [], }: { defaultExtension?: string; defaultTarget?: string; title?: string; + contacts?: SipContact[]; }) { const phone = useSipPhone(); const [extension, setExtension] = useState(defaultExtension); @@ -46,6 +53,10 @@ export function SipPhone({ {phone.status === "registered" && } + {phone.status === "registered" && contacts.map((contact) => )} {phone.status === "incoming" && } {inCall && phone.status !== "incoming" && {phone.peer || target}} {inCall && } diff --git a/frontend/src/pages/dds/Dds.tsx b/frontend/src/pages/dds/Dds.tsx index 59267b6..fbe6e47 100644 --- a/frontend/src/pages/dds/Dds.tsx +++ b/frontend/src/pages/dds/Dds.tsx @@ -604,9 +604,11 @@ export function Dds() {