BW3-Core/bw_client.py

183 lines
7.1 KiB
Python
Raw Normal View History

2018-06-15 22:20:20 +02:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
____ ____ ______ __ __ __ _____
/ __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ /
/ __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ <
/ /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ /
/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/
German BOS Information Script
by Bastian Schroll
@file: bw_client.py
@date: 09.12.2017
@author: Bastian Schroll
@description: BOSWatch client application
"""
2019-03-03 19:14:00 +01:00
# pylint: disable=wrong-import-position
# pylint: disable=wrong-import-order
2018-06-15 22:20:20 +02:00
from boswatch.utils import paths
if not paths.makeDirIfNotExist(paths.LOG_PATH):
print("cannot find/create log directory: %s", paths.LOG_PATH)
exit(1)
import logging.config
logging.config.fileConfig(paths.CONFIG_PATH + "logger_client.ini")
logging.debug("")
logging.debug("######################## NEW LOG ############################")
logging.debug("BOSWatch client has started ...")
logging.debug("Import python modules")
import argparse
logging.debug("- argparse")
2019-09-21 17:35:26 +02:00
import threading
logging.debug("- threading")
import queue
logging.debug("- queue")
import time
logging.debug("- time")
logging.debug("Import BOSWatch modules")
from boswatch.configYaml import ConfigYAML
from boswatch.network.client import TCPClient
from boswatch.network.broadcast import BroadcastClient
2019-09-21 17:35:26 +02:00
from boswatch.processManager import ProcessManager
from boswatch.decoder.decoder import Decoder
from boswatch.utils import header
2019-03-11 07:47:51 +01:00
from boswatch.utils import misc
header.logoToLog()
header.infoToLog()
logging.debug("parse args")
# With -h or --help you get the Args help
parser = argparse.ArgumentParser(prog="bw_client.py",
description="""BOSWatch is a Python Script to receive and
decode german BOS information with rtl_fm and multimon-NG""",
epilog="""More options you can find in the extern client.ini
file in the folder /config""")
parser.add_argument("-c", "--config", help="Name to configuration File", required=True)
2019-09-21 17:35:26 +02:00
parser.add_argument("-t", "--test", help="Start Client with testdata-set")
args = parser.parse_args()
bwConfig = ConfigYAML()
if not bwConfig.loadConfigFile(paths.CONFIG_PATH + args.config):
logging.error("cannot load config file")
2018-06-15 22:20:20 +02:00
exit(1)
2019-09-21 17:35:26 +02:00
# ========== CLIENT CODE ==========
try:
ip = bwConfig.get("server", "ip", default="127.0.0.1")
port = bwConfig.get("server", "port", default="8080")
if bwConfig.get("client", "useBroadcast", default=False):
broadcastClient = BroadcastClient()
if broadcastClient.getConnInfo():
ip = broadcastClient.serverIP
port = broadcastClient.serverPort
2018-06-15 22:20:20 +02:00
2019-09-21 17:35:26 +02:00
inputQueue = queue.Queue()
2019-10-10 19:34:03 +02:00
inputThreadRunning = True
2019-09-21 17:35:26 +02:00
# ========== INPUT CODE ==========
def handleSDRInput(dataQueue, config):
2019-09-21 20:02:23 +02:00
sdrProc = ProcessManager("/usr/bin/rtl_fm")
2019-10-10 20:55:25 +02:00
sdrProc.addArgument("-d " + str(config.get("device", default="0"))) # device id
2019-10-10 19:34:03 +02:00
for freq in config.get("frequencies"):
2019-10-10 20:55:25 +02:00
sdrProc.addArgument("-f " + freq) # frequencies
sdrProc.addArgument("-p " + str(config.get("error", default="0"))) # frequency error in ppm
sdrProc.addArgument("-l " + str(config.get("squelch", default="1"))) # squelch
2019-10-18 09:19:13 +02:00
sdrProc.addArgument("-g " + str(config.get("gain", default="100"))) # gain
sdrProc.addArgument("-M fm") # set mode to fm
sdrProc.addArgument("-E DC") # set DC filter
2019-10-10 20:55:25 +02:00
sdrProc.addArgument("-s 22050") # bit rate of audio stream
2019-10-10 19:34:03 +02:00
if not sdrProc.start():
exit(0)
# sdrProc.skipLines(20)
2019-09-21 20:02:23 +02:00
2019-09-21 17:35:26 +02:00
mmProc = ProcessManager("/opt/multimon/multimon-ng", textMode=True)
2019-10-10 19:34:03 +02:00
mmProc.addArgument("-a FMSFSK -a POCSAG512 -a POCSAG1200 -a POCSAG2400 -a ZVEI1")
2019-09-21 20:02:23 +02:00
mmProc.addArgument("-f aplha")
2019-10-10 19:34:03 +02:00
mmProc.addArgument("-t raw -")
2019-09-21 20:02:23 +02:00
mmProc.setStdin(sdrProc.stdout)
2019-10-10 19:34:03 +02:00
if not mmProc.start():
exit(0)
2019-09-21 17:35:26 +02:00
mmProc.skipLines(5)
2019-10-10 19:34:03 +02:00
while inputThreadRunning:
if not sdrProc.isRunning:
logging.warning("rtl_fm was down - try to restart")
sdrProc.start()
2019-10-18 09:19:13 +02:00
sdrProc.skipLinesUntil("Output at") # last line form rtl_fm before data
2019-10-10 20:55:25 +02:00
elif not mmProc.isRunning:
2019-09-21 17:35:26 +02:00
logging.warning("multimon was down - try to restart")
mmProc.start()
2019-10-18 09:19:13 +02:00
mmProc.skipLinesUntil("Enabled Demodulators:") # last line from mm before data
2019-10-10 20:55:25 +02:00
elif sdrProc.isRunning and mmProc.isRunning:
2019-10-10 19:34:03 +02:00
line = mmProc.readline()
if line:
dataQueue.put_nowait((line, time.time()))
logging.debug("Add data to queue")
print(line)
2019-10-10 20:55:25 +02:00
logging.debug("stopping thread")
2019-10-10 19:34:03 +02:00
mmProc.stop()
sdrProc.stop()
2019-09-21 17:35:26 +02:00
# ========== INPUT CODE ==========
2019-09-21 20:02:23 +02:00
mmThread = threading.Thread(target=handleSDRInput, name="mmReader", args=(inputQueue, bwConfig.get("inputSource", "sdr")))
2019-09-21 17:35:26 +02:00
mmThread.daemon = True
mmThread.start()
2019-02-27 22:05:59 +01:00
2019-09-21 17:35:26 +02:00
bwClient = TCPClient()
bwClient.connect(ip, port)
while 1:
if not bwClient.isConnected:
logging.warning("connection to server lost - sleep %d seconds", bwConfig.get("client", "reconnectDelay", default="3"))
time.sleep(bwConfig.get("client", "reconnectDelay", default="3"))
bwClient.connect(ip, port)
2019-03-05 12:32:56 +01:00
2019-09-21 17:35:26 +02:00
elif not inputQueue.empty():
data = inputQueue.get()
logging.info("get data from queue (waited %0.3f sec.)", time.time() - data[1])
logging.debug("%s packet(s) still waiting in queue", inputQueue.qsize())
2018-06-15 22:20:20 +02:00
2019-09-21 17:35:26 +02:00
bwPacket = Decoder.decode(data[0])
inputQueue.task_done()
2018-06-15 22:20:20 +02:00
2019-09-21 17:35:26 +02:00
if bwPacket is None:
continue
2018-06-15 22:20:20 +02:00
2019-09-21 17:35:26 +02:00
bwPacket.printInfo()
misc.addClientDataToPacket(bwPacket, bwConfig)
2018-06-15 22:20:20 +02:00
2019-09-21 17:35:26 +02:00
for sendCnt in range(bwConfig.get("client", "sendTries", default="3")):
bwClient.transmit(str(bwPacket))
if bwClient.receive() == "[ack-]":
2018-06-15 22:20:20 +02:00
logging.debug("ack ok")
2019-09-21 17:35:26 +02:00
break
logging.warning("cannot send packet - sleep %d seconds", bwConfig.get("client", "sendDelay", default="3"))
time.sleep(bwConfig.get("client", "sendDelay", default="3"))
else:
time.sleep(0.1) # reduce cpu load (wait 100ms)
# in worst case a packet have to wait 100ms until it will be processed
2018-06-15 22:20:20 +02:00
except KeyboardInterrupt: # pragma: no cover
logging.warning("Keyboard interrupt")
except SystemExit: # pragma: no cover
logging.error("BOSWatch interrupted by an error")
except: # pragma: no cover
logging.exception("BOSWatch interrupted by an error")
2019-09-21 17:35:26 +02:00
finally:
logging.debug("Starting shutdown routine")
bwClient.disconnect()
2019-10-10 19:34:03 +02:00
inputThreadRunning = False
mmThread.join()
2019-09-21 17:35:26 +02:00
logging.debug("BOSWatch client has stopped ...")