123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- #! /usr/bin/env python3
- # -*- coding: utf8 -*-
- #
- # This file is part of stdd, the simple time display daemon,
- # written by Helmut Pozimski <helmut@pozimski.eu> 2013-2014,
- # licensed under the 3-clause BSD license
- """ Main script for stdd, puts all the modules together, starts the daemon and
- takes care of sending the right values to the display.
- """
- import datetime
- import time
- import sys
- import signal
- import os
- import logging
- import logging.handlers
- from optparse import OptionParser
- import stddlib.configuration
- from stddlib import daemon
- from Adafruit_LED_Backpack import SevenSegment
- PARSER = OptionParser(prog="stdd", version="%prog 0.9.8", add_help_option=True)
- PARSER.add_option("-d", "--daemon", action="store_true", dest="daemon",
- help="run stdd as daemon")
- PARSER.add_option("-u", "--user", dest="user", help="define an unprivileged \
- user to run the daemon")
- PARSER.add_option("-g", "--group", dest="group", help="define an unprivileged\
- group to run the daemon")
- PARSER.add_option("-c", "--config", dest="config", help="define an\
- alternative path to the configuration file")
- (OPTIONS, ARGUMENTS) = PARSER.parse_args()
- """ define a sighandler to properly catch signals """
- def sighandler(signum, frame):
- """ Catches signals and ensures a clean exit. """
- if signum == 2:
- LOGGER.info("received SIGINT, stopping daemon")
- elif signum == 15:
- LOGGER.info("received SIGTERM, stopping daemon")
- DISPLAY.set_digit(0, 0)
- DISPLAY.set_digit(1, 0)
- DISPLAY.set_digit(2, 0)
- DISPLAY.set_digit(3, 0)
- DISPLAY.write_display()
- if OPTIONS.daemon:
- if DAEMON.stop():
- sys.exit(0)
- else:
- LOGGER.error("stopping daemon failed, PID file was not deleted!")
- sys.exit(1)
- sys.exit(0)
- # create the configuration object according to the given parameters and
- # read the file itself
- signal.signal(signal.SIGTERM, sighandler)
- signal.signal(signal.SIGINT, sighandler)
- CONFIG = stddlib.configuration.Conf()
- if OPTIONS.config is not None:
- CONFIG.read(OPTIONS.config)
- else:
- CONFIG.read()
- CONFIG.analyze()
- # create a logger to log errors according to configuration
- LOGGER = logging.getLogger("stdd")
- if CONFIG.syslog_level == "debug":
- LOGGER.setLevel(logging.DEBUG)
- elif CONFIG.syslog_level == "error":
- LOGGER.setLevel(logging.ERROR)
- else:
- LOGGER.setLevel(logging.INFO)
- if CONFIG.syslog_facility == "daemon":
- SYSLOG_HANDLER = logging.handlers.SysLogHandler(
- "/dev/log",
- facility=logging.handlers.SysLogHandler.LOG_DAEMON)
- else:
- SYSLOG_HANDLER = logging.handlers.SysLogHandler("/dev/log")
- CONSOLE_HANDLER = logging.StreamHandler()
- FORMATTER = logging.Formatter("%(name)s[" + str(os.getpid()) +
- "]: %(message)s")
- SYSLOG_HANDLER.setFormatter(FORMATTER)
- CONSOLE_HANDLER.setFormatter(FORMATTER)
- if OPTIONS.daemon:
- LOGGER.addHandler(SYSLOG_HANDLER)
- else:
- LOGGER.addHandler(CONSOLE_HANDLER)
- if OPTIONS.daemon:
- if os.access("/run", os.F_OK & os.W_OK):
- DAEMON = daemon.Daemon("/run/stdd", "stdd.pid")
- else:
- DAEMON = daemon.Daemon("/var/run/stdd", "stdd.pid")
- DAEMON.daemonize()
- DAEMON.start()
- LOGGER.info("daemon started")
- CMDLINE = ""
- CMDCOUNTER = 0
- for element in sys.argv:
- if CMDCOUNTER > 0:
- CMDLINE = CMDLINE + " " + element
- else:
- CMDLINE = CMDLINE + element
- CMDCOUNTER += 1
- DAEMON.set_name("stdd", CMDLINE)
- if OPTIONS.user is not None and OPTIONS.group is not None:
- DAEMON.drop_privileges(OPTIONS.user, OPTIONS.group)
- LOGGER.debug("dropped privileges, now running as " + OPTIONS.user +
- " and group" + OPTIONS.group)
- # Initialize the display object
- DISPLAY = SevenSegment.SevenSegment(address=int(CONFIG.hw_address))
- DISPLAY.begin()
- LOGGER.debug("opened hardware address %s", CONFIG.hw_address)
- # Set the brightness according to the configuration
- if CONFIG.set_brightness_high < datetime.datetime.now().time()\
- < CONFIG.set_brightness_low:
- LOGGER.debug("setting display brightness high")
- DISPLAY.set_brightness(CONFIG.brightness_high)
- else:
- LOGGER.debug("setting display brightness low")
- DISPLAY.set_brightness(CONFIG.brightness_low)
- # Define the main loop
- def main():
- """ Main loop of the daemon. """
- minute_written = 61
- while True:
- date_now = datetime.datetime.now()
- LOGGER.debug("got datetime: " + str(date_now))
- minute = date_now.minute
- hour = date_now.hour
- if CONFIG.blink_colon:
- LOGGER.debug("blinking middle colon")
- DISPLAY.set_colon(date_now.second % 2)
- else:
- DISPLAY.set_colon(True)
- # set the display brightness high or low when the point in time
- # defined is reached.
- if CONFIG.set_brightness_low.hour == hour:
- if CONFIG.set_brightness_low.minute == minute:
- LOGGER.debug("setting display brightness low")
- DISPLAY.set_brightness(CONFIG.brightness_low)
- if CONFIG.set_brightness_high.hour == hour:
- if CONFIG.set_brightness_high.minute == minute:
- LOGGER.debug("setting display brightness high")
- DISPLAY.set_brightness(CONFIG.brightness_high)
- if minute_written != minute:
- try:
- position2 = str(hour)[1]
- except IndexError:
- position2 = str(hour)[0]
- position1 = "0"
- else:
- position1 = str(hour)[0]
- try:
- position4 = str(minute)[1]
- except IndexError:
- position4 = str(minute)[0]
- position3 = "0"
- else:
- position3 = str(minute)[0]
- LOGGER.debug("writing time to display")
- DISPLAY.set_digit(0, position1)
- DISPLAY.set_digit(1, position2)
- DISPLAY.set_digit(2, position3)
- DISPLAY.set_digit(3, position4)
- minute_written = minute
- DISPLAY.write_display()
- time.sleep(1)
- if __name__ == "__main__":
- main()
|