mirror of
https://codeberg.org/langfingaz/bbb-status
synced 2024-11-23 20:39:33 +01:00
add main.py; Dockerfile: build dependencies; TZ
This commit is contained in:
parent
32d8158921
commit
5afe6af136
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
/secret/*.txt
|
/secret/*.txt
|
||||||
/data/*.xml
|
/data/*.xml
|
||||||
src/__pycache__/
|
/src/__pycache__/
|
||||||
|
/plot/*.png
|
||||||
|
@ -7,4 +7,7 @@
|
|||||||
<orderEntry type="jdk" jdkName="Python 3.8 (xfconf-backup)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.8 (xfconf-backup)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="PackageRequirementsSettings">
|
||||||
|
<option name="versionSpecifier" value="Greater or equal (>=x.y.z)" />
|
||||||
|
</component>
|
||||||
</module>
|
</module>
|
36
Dockerfile
36
Dockerfile
@ -2,11 +2,39 @@ FROM python:3.8-alpine
|
|||||||
|
|
||||||
WORKDIR /usr/src/
|
WORKDIR /usr/src/
|
||||||
|
|
||||||
COPY requirements.txt ./
|
RUN apk update && \
|
||||||
RUN pip3 install --no-cache-dir -r requirements.txt
|
apk add \
|
||||||
|
tzdata \
|
||||||
|
make automake gcc g++ subversion python3-dev \
|
||||||
|
zlib-dev jpeg-dev freetype-dev lcms2-dev libwebp-dev tcl-dev tk-dev harfbuzz-dev \
|
||||||
|
fribidi-dev libimagequant-dev libxcb-dev && \
|
||||||
|
rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
|
# source: https://serverfault.com/a/683651/537998
|
||||||
|
ENV TZ=Europe/Berlin
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
#COPY requirements.txt ./
|
||||||
|
#RUN pip3 install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
# LDFLAGS required for "pip install pillow"
|
||||||
|
# otherwise this would be necessary:
|
||||||
|
## RUN ln -s /usr/lib/x86_64-linux-gnu/libz.so /lib/
|
||||||
|
## RUN ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /lib/
|
||||||
|
# source: https://github.com/python-pillow/Pillow/issues/3103#issuecomment-382634946
|
||||||
|
ENV LDFLAGS=-L/usr/lib/x86_64-linux-gnu/
|
||||||
|
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pip
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade requests
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade setuptools
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade numpy
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade pillow
|
||||||
|
RUN python3 -m pip install --no-cache-dir --upgrade matplotlib
|
||||||
|
|
||||||
COPY ./src/ ./
|
COPY ./src/ ./
|
||||||
RUN chmod +x ./langfingaz/logMeetingData.py
|
RUN chmod +x ./langfingaz/main.py
|
||||||
|
|
||||||
# unbuffered output option otherwise script sleeps before any output appears
|
# unbuffered output option otherwise script sleeps before any output appears
|
||||||
CMD [ "python", "-u", "./langfingaz/logMeetingData.py" ]
|
# python -u
|
||||||
|
ENTRYPOINT [ "python", "-u", "./langfingaz/main.py" ]
|
||||||
|
CMD [ "log-verbose" ]
|
||||||
|
@ -2,9 +2,11 @@ version: '3.7'
|
|||||||
services:
|
services:
|
||||||
dk-gen:
|
dk-gen:
|
||||||
build: .
|
build: .
|
||||||
|
command: ["log"] # see main.py for available commandline arguments
|
||||||
environment:
|
environment:
|
||||||
# pythonpath is required to import from self created modules (langfingaz)
|
- PYTHONPATH=/usr/src/ # pythonpath is required to import from self created modules ("from langfingaz ...")
|
||||||
- PYTHONPATH=/usr/src/
|
- PYTHONUNBUFFERED=1
|
||||||
volumes:
|
volumes:
|
||||||
- ./secret:/usr/secret
|
- ./secret:/usr/secret
|
||||||
- ./data:/usr/data
|
- ./data:/usr/data
|
||||||
|
- ./plot:/usr/plot
|
||||||
|
@ -1 +1,2 @@
|
|||||||
requests>=2.25.0
|
requests>=2.25.0
|
||||||
|
matplotlib>=3.3.3
|
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@ -13,6 +14,8 @@ def sleepFiveMin(verbose=False):
|
|||||||
|
|
||||||
if verbose:
|
if verbose:
|
||||||
print(">> Sleeping for five minutes <<")
|
print(">> Sleeping for five minutes <<")
|
||||||
|
|
||||||
|
sys.stdout.flush()
|
||||||
time.sleep(fiveMinutes)
|
time.sleep(fiveMinutes)
|
||||||
|
|
||||||
|
|
||||||
@ -27,7 +30,7 @@ def v2(folder: Path = saveData.getDefaultFolder()):
|
|||||||
meetings = parseMeetings.parseMeetingsData(meetingsStr)
|
meetings = parseMeetings.parseMeetingsData(meetingsStr)
|
||||||
bbbStatus = parseMeetings.BbbStatus(meetings)
|
bbbStatus = parseMeetings.BbbStatus(meetings)
|
||||||
bbbStatusStr = str(bbbStatus)
|
bbbStatusStr = str(bbbStatus)
|
||||||
print(util.indentMultilineStr(bbbStatusStr))
|
print(util.indentMultilineStr(bbbStatusStr), flush=True)
|
||||||
|
|
||||||
sleepFiveMin(verbose=True)
|
sleepFiveMin(verbose=True)
|
||||||
|
|
||||||
@ -35,7 +38,7 @@ def v2(folder: Path = saveData.getDefaultFolder()):
|
|||||||
def v1(folder: Path = saveData.getDefaultFolder()):
|
def v1(folder: Path = saveData.getDefaultFolder()):
|
||||||
while True:
|
while True:
|
||||||
saveData.requestAndSaveMeetingData(folder)
|
saveData.requestAndSaveMeetingData(folder)
|
||||||
print('.', end='')
|
print('.', end='', flush=True)
|
||||||
sleepFiveMin()
|
sleepFiveMin()
|
||||||
|
|
||||||
|
|
||||||
|
34
src/langfingaz/main.py
Executable file
34
src/langfingaz/main.py
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
from langfingaz import plotMeetings
|
||||||
|
from langfingaz import logMeetingData
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
print("=== bbb-status ===")
|
||||||
|
print(">> given args: " + str(argv))
|
||||||
|
print()
|
||||||
|
|
||||||
|
usageStr = 'Usage:\n' + argv[0] + ' [log|log-verbose|plot]\n' + \
|
||||||
|
'\tlog: log BBB meeting data every 5 minutes;\n' + \
|
||||||
|
'\t prints one dot after each successfully saved file\n' + \
|
||||||
|
'\tlog-verbose: log BBB meeting every 5 minute and write current status to stdout\n' + \
|
||||||
|
'\tplot: saves a plot of the saved BBB meeting data\n'
|
||||||
|
|
||||||
|
if len(argv) != 2:
|
||||||
|
raise ValueError("Expected one commandline argument!")
|
||||||
|
|
||||||
|
if argv[1] == "log":
|
||||||
|
logMeetingData.v1()
|
||||||
|
elif argv[1] == "log-verbose":
|
||||||
|
logMeetingData.v2()
|
||||||
|
elif argv[1] == "plot":
|
||||||
|
plotMeetings.plotMeetings()
|
||||||
|
else:
|
||||||
|
print(usageStr)
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
@ -1,5 +1,6 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
import numpy
|
||||||
import matplotlib.pyplot as plt # TODO
|
import matplotlib.pyplot as plt # TODO
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@ -9,23 +10,28 @@ from langfingaz.parseMeetings import BbbStatus, Meeting
|
|||||||
from langfingaz.util import fileUtil
|
from langfingaz.util import fileUtil
|
||||||
|
|
||||||
|
|
||||||
def plotMeetings(folder: Path):
|
def getDefaultPlotFolder() -> Path:
|
||||||
|
return fileUtil.getProjectBaseDir().joinpath("plot")
|
||||||
|
|
||||||
|
|
||||||
|
def plotMeetings(dataDir: Path = fileUtil.getProjectBaseDir().joinpath("data")):
|
||||||
bbbStati: List[BbbStatus] = []
|
bbbStati: List[BbbStatus] = []
|
||||||
|
|
||||||
for file in folder.iterdir():
|
for file in dataDir.iterdir():
|
||||||
if file.name.endswith(".xml"):
|
if file.name.endswith(".xml"):
|
||||||
dataStr, t = loadData.loadData(file)
|
dataStr, t = loadData.loadData(file)
|
||||||
meetings: List[Meeting] = parseMeetings.parseMeetingsData(dataStr)
|
meetings: List[Meeting] = parseMeetings.parseMeetingsData(dataStr)
|
||||||
bbbStati.append(parseMeetings.BbbStatus(meetings, t))
|
bbbStati.append(parseMeetings.BbbStatus(meetings, t))
|
||||||
|
|
||||||
doPlotMeetings(bbbStati)
|
image: Path = doPlotMeetings(bbbStati)
|
||||||
|
print("saved image at " + str(image))
|
||||||
|
|
||||||
|
|
||||||
def doPlotMeetings(bbbStati: List[BbbStatus]):
|
def doPlotMeetings(bbbStati: List[BbbStatus]) -> Path:
|
||||||
time = [] # x-axis: time
|
time = [] # x-axis: time
|
||||||
participants = [] # yAxis (1)
|
participants = [] # yAxis (1)
|
||||||
videos = [] # yAxis (2)
|
videos = [] # yAxis (2)
|
||||||
voices = [] # yAxis (3)
|
voices = [] # yAxis (3)
|
||||||
|
|
||||||
for bbbStatus in bbbStati:
|
for bbbStatus in bbbStati:
|
||||||
time.append(bbbStatus.pointOfTime)
|
time.append(bbbStatus.pointOfTime)
|
||||||
@ -33,7 +39,6 @@ def doPlotMeetings(bbbStati: List[BbbStatus]):
|
|||||||
videos.append(bbbStatus.videoCount)
|
videos.append(bbbStatus.videoCount)
|
||||||
voices.append(bbbStatus.voiceParticipantCount)
|
voices.append(bbbStatus.voiceParticipantCount)
|
||||||
|
|
||||||
|
|
||||||
# Note that even in the OO-style, we use `.pyplot.figure` to create the figure.
|
# Note that even in the OO-style, we use `.pyplot.figure` to create the figure.
|
||||||
fig, ax = plt.subplots() # Create a figure and an axes.
|
fig, ax = plt.subplots() # Create a figure and an axes.
|
||||||
ax.plot(time, participants, label='participants') # Plot some data on the axes.
|
ax.plot(time, participants, label='participants') # Plot some data on the axes.
|
||||||
@ -44,9 +49,14 @@ def doPlotMeetings(bbbStati: List[BbbStatus]):
|
|||||||
ax.set_title("BigBlueButton Statistics") # Add a title to the axes.
|
ax.set_title("BigBlueButton Statistics") # Add a title to the axes.
|
||||||
ax.legend() # Add a legend.
|
ax.legend() # Add a legend.
|
||||||
|
|
||||||
fig.savefig(fileUtil.setDatetimePrefix(fileUtil.getProjectBaseDir().joinpath("plot"), datetime.now()))
|
image: Path = getDefaultPlotFolder().joinpath(
|
||||||
plt.show()
|
"{}_until_{}".format(fileUtil.asString(time[0]), fileUtil.asString(time[-1]))
|
||||||
|
)
|
||||||
|
fig.savefig(image)
|
||||||
|
# plt.show()
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
plotMeetings(fileUtil.getProjectBaseDir().joinpath("data"))
|
plotMeetings()
|
||||||
|
@ -24,9 +24,13 @@ def __getDatetimePrefixLength() -> int:
|
|||||||
return len("20200101_120030") # 1st January 2020, 12:00 and 30 seconds
|
return len("20200101_120030") # 1st January 2020, 12:00 and 30 seconds
|
||||||
|
|
||||||
|
|
||||||
|
def asString(t: datetime) -> str:
|
||||||
|
return t.strftime('%Y%m%d_%H%M%S')
|
||||||
|
|
||||||
|
|
||||||
def setDatetimePrefix(file: Path, t: datetime) -> Path:
|
def setDatetimePrefix(file: Path, t: datetime) -> Path:
|
||||||
# filename = file.name
|
# filename = file.name
|
||||||
prefix = t.strftime('%Y%m%d_%H%M%S')
|
prefix = asString(t)
|
||||||
filename = prefix + "_" + file.name
|
filename = prefix + "_" + file.name
|
||||||
return file.parent.joinpath(filename)
|
return file.parent.joinpath(filename)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user