wip
This commit is contained in:
parent
3206a9b1ff
commit
d29cf0a884
17
benscript.sh
Executable file
17
benscript.sh
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
#./dependencies/mediamtx/mediamtx &
|
||||||
|
#./mediamtx.yml &
|
||||||
|
|
||||||
|
|
||||||
|
counter=1
|
||||||
|
while [ $counter -le 10 ]; do
|
||||||
|
ffmpeg -re -stream_loop -1 -i ./data/file.wav -c copy -f rtsp rtsp://localhost:8554/ben/${counter} &
|
||||||
|
((counter++))
|
||||||
|
sleep 2.1
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
#ffmpeg -re -stream_loop -1 -i file.ts -c copy -f rtsp rtsp://localhost:8554/mystreams
|
||||||
46
calling.py
Normal file
46
calling.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
from pyVoIP.VoIP import VoIPPhone, InvalidStateError, CallState
|
||||||
|
import time
|
||||||
|
import wave
|
||||||
|
|
||||||
|
|
||||||
|
def answer(call):
|
||||||
|
print("Call answered!")
|
||||||
|
|
||||||
|
try:
|
||||||
|
f = wave.open("data/sampleaudio/BabyElephantWalk60.wav", "rb")
|
||||||
|
frames = f.getnframes()
|
||||||
|
data = f.readframes(frames)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
call.answer()
|
||||||
|
call.write_audio(
|
||||||
|
data
|
||||||
|
) # This writes the audio data to the transmit buffer, this must be bytes.
|
||||||
|
|
||||||
|
stop = time.time() + (
|
||||||
|
frames / 8000
|
||||||
|
) # frames/8000 is the length of the audio in seconds. 8000 is the hertz of PCMU.
|
||||||
|
|
||||||
|
while time.time() <= stop and call.state == CallState.ANSWERED:
|
||||||
|
time.sleep(0.1)
|
||||||
|
call.hangup()
|
||||||
|
except InvalidStateError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
call.hangup()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
phone = VoIPPhone(
|
||||||
|
"localhost",
|
||||||
|
5060,
|
||||||
|
"john.doe",
|
||||||
|
"password",
|
||||||
|
myIP="127.0.0.1",
|
||||||
|
sipPort=25060,
|
||||||
|
callCallback=answer,
|
||||||
|
)
|
||||||
|
|
||||||
|
phone.start()
|
||||||
|
input("Press enter to disable the phone")
|
||||||
|
phone.stop()
|
||||||
18
centos.md
Normal file
18
centos.md
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Use the boot install:
|
||||||
|
- https://www.centos.org/download/
|
||||||
|
- Select CentOS **Stream**
|
||||||
|
- Select CentOS 8 Stream
|
||||||
|
- Why is anyone using this? EOL is right around the corner.
|
||||||
|
|
||||||
|
Install in VM environment of your choosing. You must have internet access inside the VM.
|
||||||
|
Set the installation source:
|
||||||
|
- http://mirror.centos.org/centos/8-stream/BaseOS/x86_64/os/
|
||||||
|
- repository url type
|
||||||
|
software selection:
|
||||||
|
- minimal install
|
||||||
|
- guest agents
|
||||||
|
|
||||||
|
|
||||||
|
sudo dnf groupinstall "Development Tools"
|
||||||
|
sudo yum install pulseaudio-libs
|
||||||
|
sudo yum install python3-devel
|
||||||
29
containers/asterisk/docker-compose.yml
Normal file
29
containers/asterisk/docker-compose.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
tele:
|
||||||
|
image: mlan/asterisk
|
||||||
|
network_mode: bridge # Only here to help testing
|
||||||
|
cap_add:
|
||||||
|
- sys_ptrace # Only here to help testing
|
||||||
|
- net_admin # Allow NFT, used by AutoBan
|
||||||
|
- net_raw # Allow NFT, used by AutoBan
|
||||||
|
ports:
|
||||||
|
- "${SMS_PORT-8081}:${WEBSMSD_PORT:-80}" # WEBSMSD port mapping
|
||||||
|
- "5060:5060/udp" # SIP UDP port
|
||||||
|
- "5060:5060" # SIP TCP port
|
||||||
|
- "5061:5061" # SIP TLS port
|
||||||
|
- "10000-10099:10000-10099/udp" # RTP ports
|
||||||
|
environment:
|
||||||
|
- SYSLOG_LEVEL=${SYSLOG_LEVEL-4} # Logging
|
||||||
|
- HOSTNAME=${TELE_SRV-tele}.${DOMAIN-docker.localhost}
|
||||||
|
- PULSE_SERVER=unix:/run/pulse/socket # Use host audio
|
||||||
|
- PULSE_COOKIE=/run/pulse/cookie # Use host audio
|
||||||
|
- WEBSMSD_PORT=${WEBSMSD_PORT-80} # WEBSMSD internal port
|
||||||
|
volumes:
|
||||||
|
- tele-conf:/srv # Persistent storage
|
||||||
|
- ./pulse:/run/pulse:rshared # Use host audio
|
||||||
|
- /etc/localtime:/etc/localtime:ro # Use host timezone
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
tele-conf: # Persistent storage
|
||||||
62
containers/kafka/docker-compose.yml
Normal file
62
containers/kafka/docker-compose.yml
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
kafka:
|
||||||
|
container_name: kafka
|
||||||
|
hostname: kafka
|
||||||
|
image: bitnami/kafka:latest
|
||||||
|
ports:
|
||||||
|
# Flip the ports around, external gets default.
|
||||||
|
- "9092:9094"
|
||||||
|
- "9094:9092"
|
||||||
|
#network_mode: host
|
||||||
|
networks:
|
||||||
|
- kafka-internal
|
||||||
|
volumes:
|
||||||
|
- "kafka_data:/bitnami"
|
||||||
|
environment:
|
||||||
|
- ALLOW_PLAINTEXT_LISTENER=yes
|
||||||
|
- KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094
|
||||||
|
- KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://localhost:9094
|
||||||
|
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,EXTERNAL:PLAINTEXT,PLAINTEXT:PLAINTEXT
|
||||||
|
- KAFKA_CFG_AUTO_CREATE_TOPICS_ENABLE=true
|
||||||
|
|
||||||
|
kafka-ui:
|
||||||
|
container_name: kafka-ui
|
||||||
|
image: provectuslabs/kafka-ui:latest
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
networks:
|
||||||
|
- kafka-internal
|
||||||
|
environment:
|
||||||
|
DYNAMIC_CONFIG_ENABLED: 'true'
|
||||||
|
KAFKA_CLUSTERS_0_NAME: test
|
||||||
|
KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka:9092
|
||||||
|
depends_on:
|
||||||
|
- kafka
|
||||||
|
volumes:
|
||||||
|
- ~/kui/config.yml:/etc/kafkaui/dynamic_config.yaml
|
||||||
|
|
||||||
|
|
||||||
|
# magic:
|
||||||
|
# image: "digitsy/kafka-magic"
|
||||||
|
# ports:
|
||||||
|
# - "8080:80"
|
||||||
|
# networks:
|
||||||
|
# - kafka-internal
|
||||||
|
# volumes:
|
||||||
|
# - .:/config
|
||||||
|
# environment:
|
||||||
|
# KMAGIC_ALLOW_TOPIC_DELETE: "true"
|
||||||
|
# KMAGIC_ALLOW_SCHEMA_DELETE: "true"
|
||||||
|
# KMAGIC_CONFIG_STORE_TYPE: "file"
|
||||||
|
# KMAGIC_CONFIG_STORE_CONNECTION: "Data Source=/config/KafkaMagicConfig.db;"
|
||||||
|
# KMAGIC_CONFIG_ENCRYPTION_KEY: "ENTER_YOUR_KEY_HERE"
|
||||||
|
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
kafka_data:
|
||||||
|
driver: local
|
||||||
|
|
||||||
|
networks:
|
||||||
|
kafka-internal:
|
||||||
88
data/kafkalogging.py
Normal file
88
data/kafkalogging.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
from kafka import KafkaProducer
|
||||||
|
from kafka.admin import KafkaAdminClient, NewTopic
|
||||||
|
import subprocess
|
||||||
|
from select import select
|
||||||
|
import os
|
||||||
|
|
||||||
|
kafka_servers = ['localhost:9092']
|
||||||
|
producers = {}
|
||||||
|
client = KafkaAdminClient(bootstrap_servers=kafka_servers)
|
||||||
|
|
||||||
|
|
||||||
|
# Inspired by gist:
|
||||||
|
# https://gist.github.com/krzemienski/8c7e8e76c8652984cca0da3fea5b5368
|
||||||
|
def check_io(process, process_name=None):
|
||||||
|
#if process.stdout is not None: os.set_blocking(process.stdout.fileno(), False)
|
||||||
|
#if process.stderr is not None: os.set_blocking(process.stderr.fileno(), False)
|
||||||
|
|
||||||
|
#ready_to_read, _, _ = select(
|
||||||
|
# [x for x in [process.stdout, process.stderr] if x is not None],
|
||||||
|
# [], [], 0
|
||||||
|
#)
|
||||||
|
|
||||||
|
#return
|
||||||
|
|
||||||
|
for pipe_name,pipe in {'stdout':process.stdout, 'stderr':process.stderr}.items():
|
||||||
|
if pipe is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if os.get_blocking(pipe):
|
||||||
|
os.set_blocking(pipe, False)
|
||||||
|
|
||||||
|
#if pipe not in ready_to_read:
|
||||||
|
# continue
|
||||||
|
|
||||||
|
topic_name = f"{process.pid if process_name is None else process_name}-{pipe_name}"
|
||||||
|
|
||||||
|
#if process.pid not in producers:
|
||||||
|
# producers[process.pid] = {}
|
||||||
|
#if pipe_name not in producers[process.pid]:
|
||||||
|
# #client.create_topics(
|
||||||
|
# # [
|
||||||
|
# # NewTopic(name=topic_name, num_partitions=1, replication_factor=1)
|
||||||
|
# # ]
|
||||||
|
# #)
|
||||||
|
# producers[process.pid][pipe_name] = KafkaProducer(bootstrap_servers=kafka_servers, max_block_ms=10)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
#print(topic_name)
|
||||||
|
#break
|
||||||
|
# The python official docs recommend using Popen.communicate()
|
||||||
|
# instead of reading from the pipes directly. This isn't applicable
|
||||||
|
# here, as the python docs assume you're shelling out to a short-lived
|
||||||
|
# process and retrieving the results, not starting a service and
|
||||||
|
# pulling the log output. Popen.communicate() is a blocking call and
|
||||||
|
# would die here forever waiting for the service to exit.
|
||||||
|
output = pipe.readline()
|
||||||
|
if output:
|
||||||
|
print(output)
|
||||||
|
#producers[process.pid][pipe_name].send(topic_name, value=output)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
#break anyway, i think we're dying in this loop
|
||||||
|
break
|
||||||
|
|
||||||
|
#producers[process.pid][pipe_name].flush()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import time
|
||||||
|
|
||||||
|
ping = subprocess.Popen(
|
||||||
|
[
|
||||||
|
'/usr/bin/ping',
|
||||||
|
'1.1.1.1',
|
||||||
|
],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE
|
||||||
|
)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
check_io(ping, 'ping')
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
ping.kill()
|
||||||
|
ping.wait()
|
||||||
|
ping = None
|
||||||
14
radio.py
14
radio.py
@ -25,6 +25,7 @@ class Radio(Streamer):
|
|||||||
raise RuntimeError("Failed to connect to radio device")
|
raise RuntimeError("Failed to connect to radio device")
|
||||||
|
|
||||||
self.capabilities = self._get_capabilities()
|
self.capabilities = self._get_capabilities()
|
||||||
|
self.stream_errors = 0
|
||||||
|
|
||||||
def configure(self, frequency):
|
def configure(self, frequency):
|
||||||
if self.is_streaming():
|
if self.is_streaming():
|
||||||
@ -59,8 +60,9 @@ class Radio(Streamer):
|
|||||||
"name": self.name,
|
"name": self.name,
|
||||||
"device": self.device_info,
|
"device": self.device_info,
|
||||||
"capabilities": self.capabilities,
|
"capabilities": self.capabilities,
|
||||||
"stream-path": self._stream_path(),
|
"stream-path": self.stream_path(),
|
||||||
"streaming": self.is_streaming(),
|
"streaming": self.is_streaming(),
|
||||||
|
"stream-errors": self.stream_errors,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _get_capabilities(self):
|
def _get_capabilities(self):
|
||||||
@ -100,9 +102,14 @@ class Radio(Streamer):
|
|||||||
continue
|
continue
|
||||||
elif result.ret < 0:
|
elif result.ret < 0:
|
||||||
error = SoapyError(result.ret)
|
error = SoapyError(result.ret)
|
||||||
if error is not SoapyError.Timeout:
|
if error is SoapyError.Timeout or error is SoapyError.Overflow:
|
||||||
|
self.stream_errors += 1
|
||||||
|
print("Non-fatal stream error:", error.name, file=sys.stderr)
|
||||||
|
else:
|
||||||
print(
|
print(
|
||||||
"Stream read failed, aborting stream:", error, file=sys.stderr
|
"Stream read failed, aborting stream:",
|
||||||
|
error.name,
|
||||||
|
file=sys.stderr,
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
continue
|
continue
|
||||||
@ -159,6 +166,7 @@ class Radio(Streamer):
|
|||||||
soapy.SOAPY_SDR_RX, FORMATS[Radio.FORMAT].soapy
|
soapy.SOAPY_SDR_RX, FORMATS[Radio.FORMAT].soapy
|
||||||
)
|
)
|
||||||
result = self.device.activateStream(self.stream)
|
result = self.device.activateStream(self.stream)
|
||||||
|
self.stream_errors = 0
|
||||||
|
|
||||||
if result != 0:
|
if result != 0:
|
||||||
raise RuntimeError(f"Error activating stream: {result}")
|
raise RuntimeError(f"Error activating stream: {result}")
|
||||||
|
|||||||
8
requirements.txt
Normal file
8
requirements.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
colorama==0.4.3
|
||||||
|
flasgger==0.9.5
|
||||||
|
Flask==2.2.3
|
||||||
|
numpy==1.17.4
|
||||||
|
prefixed==0.7.0
|
||||||
|
pyVoIP
|
||||||
|
PyYAML==6.0
|
||||||
|
requests==2.22.0
|
||||||
Loading…
Reference in New Issue
Block a user