diff --git a/.gitignore b/.gitignore
index 3cd7bcc..423987e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
/secret/*.txt
/data/*.xml
-src/__pycache__/
+/src/__pycache__/
+/plot/*.png
diff --git a/.idea/bbb-status.iml b/.idea/bbb-status.iml
index 371977c..e0afde7 100644
--- a/.idea/bbb-status.iml
+++ b/.idea/bbb-status.iml
@@ -7,4 +7,7 @@
+
+
+
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index 8fc91a3..2b11a7e 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,11 +2,39 @@ FROM python:3.8-alpine
WORKDIR /usr/src/
-COPY requirements.txt ./
-RUN pip3 install --no-cache-dir -r requirements.txt
+RUN apk update && \
+ 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/ ./
-RUN chmod +x ./langfingaz/logMeetingData.py
+RUN chmod +x ./langfingaz/main.py
# 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" ]
diff --git a/docker-compose.yml b/docker-compose.yml
index a0c279d..1d1d6de 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -2,9 +2,11 @@ version: '3.7'
services:
dk-gen:
build: .
+ command: ["log"] # see main.py for available commandline arguments
environment:
- # pythonpath is required to import from self created modules (langfingaz)
- - PYTHONPATH=/usr/src/
+ - PYTHONPATH=/usr/src/ # pythonpath is required to import from self created modules ("from langfingaz ...")
+ - PYTHONUNBUFFERED=1
volumes:
- ./secret:/usr/secret
- ./data:/usr/data
+ - ./plot:/usr/plot
diff --git a/requirements.txt b/requirements.txt
index eed6988..9d7394f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1,2 @@
-requests>=2.25.0
\ No newline at end of file
+requests>=2.25.0
+matplotlib>=3.3.3
\ No newline at end of file
diff --git a/src/langfingaz/logMeetingData.py b/src/langfingaz/logMeetingData.py
index 96fdb26..dce29c5 100755
--- a/src/langfingaz/logMeetingData.py
+++ b/src/langfingaz/logMeetingData.py
@@ -1,5 +1,6 @@
#!/usr/bin/python3
+import sys
import time
from pathlib import Path
@@ -13,6 +14,8 @@ def sleepFiveMin(verbose=False):
if verbose:
print(">> Sleeping for five minutes <<")
+
+ sys.stdout.flush()
time.sleep(fiveMinutes)
@@ -27,7 +30,7 @@ def v2(folder: Path = saveData.getDefaultFolder()):
meetings = parseMeetings.parseMeetingsData(meetingsStr)
bbbStatus = parseMeetings.BbbStatus(meetings)
bbbStatusStr = str(bbbStatus)
- print(util.indentMultilineStr(bbbStatusStr))
+ print(util.indentMultilineStr(bbbStatusStr), flush=True)
sleepFiveMin(verbose=True)
@@ -35,7 +38,7 @@ def v2(folder: Path = saveData.getDefaultFolder()):
def v1(folder: Path = saveData.getDefaultFolder()):
while True:
saveData.requestAndSaveMeetingData(folder)
- print('.', end='')
+ print('.', end='', flush=True)
sleepFiveMin()
diff --git a/src/langfingaz/main.py b/src/langfingaz/main.py
new file mode 100755
index 0000000..68b6036
--- /dev/null
+++ b/src/langfingaz/main.py
@@ -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()
diff --git a/src/langfingaz/plotMeetings.py b/src/langfingaz/plotMeetings.py
index 43afb12..1799711 100644
--- a/src/langfingaz/plotMeetings.py
+++ b/src/langfingaz/plotMeetings.py
@@ -1,5 +1,6 @@
from pathlib import Path
from typing import List
+import numpy
import matplotlib.pyplot as plt # TODO
from datetime import datetime
@@ -9,23 +10,28 @@ from langfingaz.parseMeetings import BbbStatus, Meeting
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] = []
- for file in folder.iterdir():
+ for file in dataDir.iterdir():
if file.name.endswith(".xml"):
dataStr, t = loadData.loadData(file)
meetings: List[Meeting] = parseMeetings.parseMeetingsData(dataStr)
bbbStati.append(parseMeetings.BbbStatus(meetings, t))
- doPlotMeetings(bbbStati)
+ image: Path = doPlotMeetings(bbbStati)
+ print("saved image at " + str(image))
-def doPlotMeetings(bbbStati: List[BbbStatus]):
- time = [] # x-axis: time
- participants = [] # yAxis (1)
- videos = [] # yAxis (2)
- voices = [] # yAxis (3)
+def doPlotMeetings(bbbStati: List[BbbStatus]) -> Path:
+ time = [] # x-axis: time
+ participants = [] # yAxis (1)
+ videos = [] # yAxis (2)
+ voices = [] # yAxis (3)
for bbbStatus in bbbStati:
time.append(bbbStatus.pointOfTime)
@@ -33,7 +39,6 @@ def doPlotMeetings(bbbStati: List[BbbStatus]):
videos.append(bbbStatus.videoCount)
voices.append(bbbStatus.voiceParticipantCount)
-
# 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.
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.legend() # Add a legend.
- fig.savefig(fileUtil.setDatetimePrefix(fileUtil.getProjectBaseDir().joinpath("plot"), datetime.now()))
- plt.show()
+ image: Path = getDefaultPlotFolder().joinpath(
+ "{}_until_{}".format(fileUtil.asString(time[0]), fileUtil.asString(time[-1]))
+ )
+ fig.savefig(image)
+ # plt.show()
+
+ return image
if __name__ == '__main__':
- plotMeetings(fileUtil.getProjectBaseDir().joinpath("data"))
+ plotMeetings()
diff --git a/src/langfingaz/util/fileUtil.py b/src/langfingaz/util/fileUtil.py
index e256e2a..c4493c3 100644
--- a/src/langfingaz/util/fileUtil.py
+++ b/src/langfingaz/util/fileUtil.py
@@ -24,9 +24,13 @@ def __getDatetimePrefixLength() -> int:
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:
# filename = file.name
- prefix = t.strftime('%Y%m%d_%H%M%S')
+ prefix = asString(t)
filename = prefix + "_" + file.name
return file.parent.joinpath(filename)