123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- #! /usr/bin/env python
- # -*- 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
- import datetime
- import time
- import sys
- import signal
- import os
- import logging
- import logging.handlers
- from optparse import OptionParser
- import stddlib.daemon
- import stddlib.configuration
- from adafruit_7segment.Adafruit_7Segment import SevenSegment
- """Create the OptionParser object, define and parse all options and
- parameters, only 3 are currently defined:
- * --daemon (shall stdd be run as daemon)
- * --user (user to change to)
- * --group (group to change to)
- * --config (path to configuration file)
- """
- parser = OptionParser(prog="stdd", version="%prog 0.9.1", 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):
- if signum == 2:
- logger.info("received SIGINT, stopping daemon")
- elif signum == 15:
- logger.info("received SIGTERM, stopping daemon")
- display.writeDigit(0, 0)
- display.writeDigit(1, 0)
- display.writeDigit(3, 0)
- display.writeDigit(4, 0)
- if options.daemon is True:
- if daemon.Stop() is True:
- 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 is True:
- logger.addHandler(syslog_handler)
- else:
- logger.addHandler(console_handler)
- if options.daemon is True:
- if os.access("/run", os.F_OK & os.W_OK) is True:
- daemon = stddlib.daemon.Daemon("/run", "stdd")
- else:
- daemon = stddlib.daemon.Daemon("/var/run", "stdd")
- 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.SetName("stdd", cmdline)
- if options.user is not None and options.group is not None:
- daemon.DropPriv(options.user, options.group)
- logger.debug("dropped privileges, now running as " + options.user +
- " and group" + options.group)
- """Initialize the display object"""
- display = SevenSegment(config.hw_address)
- logger.debug("opened hardware address")
- """Set the brightness according to the configuration"""
- if datetime.datetime.now().time() > config.set_brightness_high and \
- datetime.datetime.now().time() < config.set_brightness_low:
- logger.debug("setting display brightness high")
- display.setBrightness(config.brightness_high)
- else:
- logger.debug("setting display brightness low")
- display.setBrightness(config.brightness_low)
- """Define the main loop"""
- def main():
- 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 is True:
- logger.debug("blinking middle colon")
- display.setColon(date_now.second % 2)
- else:
- display.setColon(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.setBrightness(config.brightness_low)
- if config.set_brightness_high.hour == hour:
- if config.set_brightness_high.minute == minute:
- logger.debug("setting display brightness high")
- display.setBrightness(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.writeDigit(0, int(position1))
- display.writeDigit(1, int(position2))
- display.writeDigit(3, int(position3))
- display.writeDigit(4, int(position4))
- minute_written = minute
- time.sleep(1)
- if __name__ == "__main__":
- main()
|