Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
mryel00 committed Feb 24, 2024
1 parent 31e6d1d commit 2d128db
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 48 deletions.
55 changes: 16 additions & 39 deletions crowsnest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,28 @@
from pylibs.crowsnest import Crowsnest
from pylibs.section import Section
from pylibs.core import get_module_class
import pylibs.logger as logger

import logging
import asyncio

parser = argparse.ArgumentParser(
prog='Crowsnest',
description='Crowsnest - A webcam daemon for Raspberry Pi OS distributions like MainsailOS'
)
config = configparser.ConfigParser()

parser.add_argument('-c', '--config', help='Path to config file', required=True)
parser.add_argument('-l', '--log_path', help='Path to log file', required=True)

args = parser.parse_args()

def setup_logging():
logging.basicConfig(
filename=args.log_path,
encoding='utf-8',
level=logging.INFO,
format='[%(asctime)s] %(levelname)s: %(message)s',
datefmt='%d/%m/%y %H:%M:%S'
)

# Change DEBUG to DEB and add custom DEBUG logging level.
logging.addLevelName(10, 'DEV')
logging.addLevelName(15, 'DEBUG')

# Read config
config_path = args.config

config = configparser.ConfigParser()
config.read(config_path)

# Example of printing section and values
# for section in config.sections():
# print("Section: " + section)
# for key in config[section]:
# print('Key: '+key+'\t\tValue: '+config[section][key].replace(' ', '').split('#')[0])
# print(config)


crowsnest = Crowsnest('crowsnest')
crowsnest.parse_config(config['crowsnest'])
logging.getLogger().setLevel(crowsnest.parameters['log_level'].value)

print('Log Level: ' + crowsnest.parameters['log_level'].value)

print(crowsnest.name)
def parse_config():
global crowsnest, config, args
config_path = args.config
config.read(config_path)
crowsnest = Crowsnest('crowsnest')
crowsnest.parse_config(config['crowsnest'])
logger.set_log_level(crowsnest.parameters['log_level'].value)

async def start_processes():
sec_objs = []
Expand All @@ -77,7 +51,7 @@ async def start_processes():
print(f"Section [{section}] couldn't get parsed")
sec_objs.append(section_object)
for task in sec_exec_tasks:
if task != None:
if task is not None:
await task
except Exception as e:
print(e)
Expand All @@ -86,7 +60,10 @@ async def start_processes():
if task != None:
task.cancel()

setup_logging()

# Run async as it will wait for all tasks to finish
logger.setup_logging(args.log_path)
logger.log_initial()
parse_config()
logger.log_host_info()
logger.log_config(args.config)
# Run async to wait for all tasks to finish
asyncio.run(start_processes())
11 changes: 5 additions & 6 deletions pylibs/core.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import importlib
import asyncio
import logging
import time
import os

from .logger import log_debug, log_error
# import logging

# Dynamically import module
# Requires module to have a load_module() function,
# as well as the same name as the section keyword
Expand All @@ -26,8 +28,8 @@ async def log_subprocess_output(stream, log_func, line_prefix = ''):

async def execute_command(
command: str,
info_log_func = logging.info,
error_log_func = logging.error,
info_log_func = log_debug,
error_log_func = log_error,
info_log_pre = '',
error_log_pre = ''):

Expand Down Expand Up @@ -59,6 +61,3 @@ async def execute_command(
# Wait for the output handling tasks to finish
#await stdout_task
#await stderr_task

def log_debug(msg):
logging.log(15, msg)
2 changes: 1 addition & 1 deletion pylibs/crowsnest.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def parse_config(self, section: SectionProxy):
super().parse_config(section)
log_level = self.parameters['log_level'].value.lower()
if log_level == 'quiet':
self.parameters['log_level'].value = 'WARNING'
self.parameters['log_level'].value = 'QUIET'
elif log_level == 'debug':
self.parameters['log_level'].value = 'DEBUG'
elif log_level == 'dev':
Expand Down
129 changes: 129 additions & 0 deletions pylibs/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import logging
import re # log_config
import os, subprocess # log_host_info
import sys # log_cams

DEV = 10
DEBUG = 15
QUIET = 25

def setup_logging(log_path):
logging.basicConfig(
filename=log_path,
encoding='utf-8',
level=logging.INFO,
format='[%(asctime)s] %(message)s',
datefmt='%d/%m/%y %H:%M:%S'
)

# Change DEBUG to DEB and add custom logging level.
logging.addLevelName(DEV, 'DEV')
logging.addLevelName(DEBUG, 'DEBUG')
logging.addLevelName(QUIET, 'QUIET')

def set_log_level(level):
logging.getLogger().setLevel(level)

def log_quiet(msg):
logging.log(QUIET, msg)

def log_info(msg, prefix='INFO: '):
logging.info(prefix + msg)

def log_debug(msg, prefix='DEBUG: '):
logging.log(DEBUG, prefix + msg)

def log_error(msg, prefix='ERROR: '):
logging.error(prefix + msg)


def log_initial():
log_quiet('crowsnest - A webcam Service for multiple Cams and Stream Services.')
command = 'git describe --always --tags'
version = subprocess.check_output(command, shell=True).decode('utf-8').strip()
log_quiet(f'Version: {version}')
log_quiet('Prepare Startup ...')

def log_config(config_path):
log_info("Print Configfile: '" + config_path + "'")
with open(config_path, 'r') as file:
config_txt = file.read()
# Remove comments
config_txt = re.sub(r'#.*$', "", config_txt, flags=re.MULTILINE)
config_txt = config_txt.strip()
# Split the config file into lines
lines = config_txt.split('\n')
for line in lines:
log_info(5*' ' + line.strip(), '')

def log_host_info():
log_info("Host Information:")
log_pre = "Host Info: "

### OS Infos
# OS Version
with open('/etc/os-release', 'r') as file:
lines = file.readlines()
for line in lines:
if line.startswith('PRETTY_NAME'):
distribution = line.strip().split('=')[1].strip('"')
log_info(f'Distribution: {distribution}', log_pre)

# Release Version of MainsailOS (if file present)
try:
with open('/etc/mainsailos-release', 'r') as file:
content = file.read()
log_info(f'Release: {content.strip()}', log_pre)
except FileNotFoundError:
pass

# Kernel Version
uname = os.uname()
log_info(f'Kernel: {uname.sysname} {uname.release} {uname.machine}', log_pre)


### Host Machine Infos
# Host model
command = 'grep "Model" /proc/cpuinfo | cut -d\':\' -f2'
model = subprocess.check_output(command, shell=True).decode('utf-8').strip()
if model == '':
command = 'grep "model name" /proc/cpuinfo | cut -d\':\' -f2 | awk NR==1'
model = subprocess.check_output(command, shell=True).decode('utf-8').strip()
if model == '':
model = 'Unknown'
log_info(f'Model: {model}', log_pre)

# CPU count
cpu_count = os.cpu_count()
log_info(f"Available CPU Cores: {cpu_count}", log_pre)

# Avail mem
# psutil.virtual_memory().total
command = 'grep "MemTotal:" /proc/meminfo | awk \'{print $2" "$3}\''
memtotal = subprocess.check_output(command, shell=True).decode('utf-8').strip()
log_info(f'Available Memory: {memtotal}', log_pre)

# Avail disk size
# Alternative psutil.disk_usage('/').total
command = 'LC_ALL=C df -h / | awk \'NR==2 {print $4" / "$2}\''
disksize = subprocess.check_output(command, shell=True).decode('utf-8').strip()
log_info(f'Diskspace (avail. / total): {disksize}', log_pre)

def log_cams():
log_info("INFO: Detect available Devices")
libcamera = 0
v4l = 0
legacy = 0
total = libcamera + legacy + v4l

if total == 0:
log_error("No usable Devices Found. Stopping ")
sys.exit()

log_info(f"Found {total} Devices (V4L: {v4l}, libcamera: {libcamera}, Legacy: {legacy})")
if libcamera > 0:
log_info(f"Detected 'libcamera' device -> {-1}")
if legacy > 0:
pass
if v4l > 0:
pass
9 changes: 7 additions & 2 deletions pylibs/streamer/ustreamer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from configparser import SectionProxy
from .streamer import Streamer
from ..parameter import Parameter
from ..core import execute_command, log_debug
from ..core import execute_command
from ..logger import log_debug

class Ustreamer(Streamer):
keyword = 'ustreamer'
Expand Down Expand Up @@ -42,7 +43,11 @@ async def execute(self):
cmd = streamer_args
log_pre = f'ustreamer [cam {self.name}]: '

process,_,_ = await execute_command(' '.join(cmd), error_log_pre=log_pre, error_log_func=log_debug)
process,_,_ = await execute_command(
' '.join(cmd),
error_log_pre=log_pre,
error_log_func=log_debug
)

return process

Expand Down

0 comments on commit 2d128db

Please sign in to comment.