| pyws_clock | ||
| .gitignore | ||
| config.ini.inc | ||
| logrotate_pyws_clock.inc | ||
| nginx_server.conf | ||
| pyws_clock.service.inc | ||
| README.md | ||
| requirements.txt | ||
| run_server.sh | ||
pyws_clock
Websocket clock server, handling timezones, alarms and sessions.
TODO
Add some test using unittest.
Replace dateutil by pytz in order to implement a command listing available timezones.
Send an array of alarms instead of 1 message per ringing alarm.
Replace dirty & quick session implementation with something like werkzeug sessions.
Dependencies
- Python >= 3.9
- python3-dateutil 2.8.1
- python3-websockets 8.1
Debian-based dependencies installation
apt install python3-dateutil python3-websockets
Installing dependencies using pip
pip3 install -r requirements.txt
Running the server
python3 -m pyws_clock
Get some help using python3 -m pyws_clock --help
Deployment
Systemd service will run the server using the run_server.sh script. This
script runs python3 -m pyws_clock -C config.ini allowing to configure the
daemon with a config.ini file.
Create a configuration file
cp config.ini.inc config.ini; edit config.ini
Create a systemd service
cp pyws_clock.service.inc pyws_clock.service
edit pyws_clock.service
cp pyws_clock.service /etc/systemd/system/
systemctl enable pyws_clock.service
systemctl start pyws_clock.service
systemctl status pyws_clock.service
Testing the websocket server
Run this command and send a dummy session id by pressing enter.
python3 -m websockets ws://127.0.0.1:8901
Example deployment on Debian 11
adduser --system pyws_clock
cp -R pyws_clock /home/pyws_clock/
cd /home/pyws_clock/pyws_clock/
cp config.ini.inc config.ini
echo "session_directory=/var/run/pyws_clock/sessions/
logfile=/var/log/pyws_clock/pyws_clock.log" >> config.ini
cp pyws_clock.service.inc pyws_clock.service
echo -e "User=pyws_clock
Group=nogroup
WorkingDirectory=/home/pyws_clock/pyws_clock/
ExecStart=/home/pyws_clock/pyws_clock/run_server.sh" >> pyws_clock.service
mv pyws_clock.service /etc/systemd/system/
# log dir & rotation config
mkdir /var/log/pyws_clock/
chown pyws_clock: /var/log/pyws_clock
cp logrotate_pyws_clock.inc /etc/logrotate.d/pyws_clock
systemctl restart logrotate
# session directory creation
mkdir -p /var/run/pyws_clock/sessions/
chown -R pyws_clock: /var/run/pyws_clock
# Enabling & starting the systemd service
systemctl enable pyws_clock.service
systemctl start pyws_clock.service
systemctl status pyws_clock.service
Nginx configuration
A sample configuration is available in nginx_server.conf.
Websocket server protocol description
The server replies on any URL.
Before entering the main loop, the listening server waits for 1st message
containing a session ID. If an empty/dummy/invalid/unknown session ID is sent by the
client, the server replies with a new, valid, session ID and enter the main loop.
If a valid session ID is sent, the server reply the same session ID and enter
the main loop, formated using SESSION:<SESSION_ID>.
Main loop
The server send the current time (ISO 8601 format) every second.
Command results
The client can interact with the server sending one of the command listed using
python3 -m pyws_clock -L.
When a client send a command, the next message from the server will be a command
result. Results are string formatted using <STATUS>:<DETAILS>. Status can be
one of 'ERR' or 'OK', details are optionnale for OK statuses.
Alarms rings
When an alarm is ringing, after sending time, the server send messages formatted
using ALRM:<NAME> where NAME is the name of the ringing alarm.
If multiple alarms are ringing, multiple ALRM: messages are sent every second.
Timezone informations
Before the first time is sent and every time the timezone changes (inclucing
summer/winter transitions), the clock. Timezones messages are formatted using
TZN:<TZNAME>
Messages types summary
- Session ID
SESSION:<SESSION_ID>
- Clock tick
ISO8601_Datetime
- Timezone name
TZN:<TZNAME>
- Alarm rings
ALRM:<JSON_ARRAY>
- Command results
OK:<DETAILS>ERR:<REASON>