Browse Source

pulled in the necessary python code from adafruit and my own daemon module

Helmut Pozimski 11 years ago
parent
commit
c79fcababf

+ 2 - 0
TODO

@@ -9,3 +9,5 @@
 * Add a setup.py
 * Add debian packaging
 ** Create a unprivileged user to run the daemon under
+* Add a man page
+* Add syslog logging

+ 52 - 0
adafruit_7segment/Adafruit_7Segment.py

@@ -0,0 +1,52 @@
+#!/usr/bin/python
+
+import time
+import datetime
+from Adafruit_LEDBackpack import LEDBackpack
+
+# ===========================================================================
+# 7-Segment Display
+# ===========================================================================
+
+# This class is meant to be used with the four-character, seven segment
+# displays available from Adafruit
+
+class SevenSegment:
+  disp = None
+ 
+  # Hexadecimal character lookup table (row 1 = 0..9, row 2 = A..F)
+  digits = [ 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, \
+             0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71 ]
+
+  # Constructor
+  def __init__(self, address=0x70, debug=False):
+    if (debug):
+      print "Initializing a new instance of LEDBackpack at 0x%02X" % address
+    self.disp = LEDBackpack(address=address, debug=debug)
+
+  def writeDigitRaw(self, charNumber, value):
+    "Sets a digit using the raw 16-bit value"
+    if (charNumber > 7):
+      return
+    # Set the appropriate digit
+    self.disp.setBufferRow(charNumber, value)
+
+  def writeDigit(self, charNumber, value, dot=False):
+    "Sets a single decimal or hexademical value (0..9 and A..F)"
+    if (charNumber > 7):
+      return
+    if (value > 0xF):
+      return
+    # Set the appropriate digit
+    self.disp.setBufferRow(charNumber, self.digits[value] | (dot << 7))
+
+  def setColon(self, state=True):
+    "Enables or disables the colon character"
+    # Warning: This function assumes that the colon is character '2',
+    # which is the case on 4 char displays, but may need to be modified
+    # if another display type is used
+    if (state):
+      self.disp.setBufferRow(2, 0xFFFF)
+    else:
+      self.disp.setBufferRow(2, 0)
+

+ 170 - 0
adafruit_7segment/Adafruit_I2C.py

@@ -0,0 +1,170 @@
+#!/usr/bin/python
+
+import smbus
+
+# ===========================================================================
+# Adafruit_I2C Class
+# ===========================================================================
+
+class Adafruit_I2C :
+
+  @staticmethod
+  def getPiRevision():
+    "Gets the version number of the Raspberry Pi board"
+    # Courtesy quick2wire-python-api
+    # https://github.com/quick2wire/quick2wire-python-api
+    try:
+      with open('/proc/cpuinfo','r') as f:
+        for line in f:
+          if line.startswith('Revision'):
+            return 1 if line.rstrip()[-1] in ['1','2'] else 2
+    except:
+      return 0
+
+  @staticmethod
+  def getPiI2CBusNumber():
+    # Gets the I2C bus number /dev/i2c#
+    return 1 if Adafruit_I2C.getPiRevision() > 1 else 0
+ 
+  def __init__(self, address, busnum=-1, debug=False):
+    self.address = address
+    # By default, the correct I2C bus is auto-detected using /proc/cpuinfo
+    # Alternatively, you can hard-code the bus version below:
+    # self.bus = smbus.SMBus(0); # Force I2C0 (early 256MB Pi's)
+    # self.bus = smbus.SMBus(1); # Force I2C1 (512MB Pi's)
+    self.bus = smbus.SMBus(
+      busnum if busnum >= 0 else Adafruit_I2C.getPiI2CBusNumber())
+    self.debug = debug
+
+  def reverseByteOrder(self, data):
+    "Reverses the byte order of an int (16-bit) or long (32-bit) value"
+    # Courtesy Vishal Sapre
+    byteCount = len(hex(data)[2:].replace('L','')[::2])
+    val       = 0
+    for i in range(byteCount):
+      val    = (val << 8) | (data & 0xff)
+      data >>= 8
+    return val
+
+  def errMsg(self):
+    print "Error accessing 0x%02X: Check your I2C address" % self.address
+    return -1
+
+  def write8(self, reg, value):
+    "Writes an 8-bit value to the specified register/address"
+    try:
+      self.bus.write_byte_data(self.address, reg, value)
+      if self.debug:
+        print "I2C: Wrote 0x%02X to register 0x%02X" % (value, reg)
+    except IOError, err:
+      return self.errMsg()
+
+  def write16(self, reg, value):
+    "Writes a 16-bit value to the specified register/address pair"
+    try:
+      self.bus.write_word_data(self.address, reg, value)
+      if self.debug:
+        print ("I2C: Wrote 0x%02X to register pair 0x%02X,0x%02X" %
+         (value, reg, reg+1))
+    except IOError, err:
+      return self.errMsg()
+
+  def writeList(self, reg, list):
+    "Writes an array of bytes using I2C format"
+    try:
+      if self.debug:
+        print "I2C: Writing list to register 0x%02X:" % reg
+        print list
+      self.bus.write_i2c_block_data(self.address, reg, list)
+    except IOError, err:
+      return self.errMsg()
+
+  def readList(self, reg, length):
+    "Read a list of bytes from the I2C device"
+    try:
+      results = self.bus.read_i2c_block_data(self.address, reg, length)
+      if self.debug:
+        print ("I2C: Device 0x%02X returned the following from reg 0x%02X" %
+         (self.address, reg))
+        print results
+      return results
+    except IOError, err:
+      return self.errMsg()
+
+  def readU8(self, reg):
+    "Read an unsigned byte from the I2C device"
+    try:
+      result = self.bus.read_byte_data(self.address, reg)
+      if self.debug:
+        print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
+         (self.address, result & 0xFF, reg))
+      return result
+    except IOError, err:
+      return self.errMsg()
+
+  def readS8(self, reg):
+    "Reads a signed byte from the I2C device"
+    try:
+      result = self.bus.read_byte_data(self.address, reg)
+      if result > 127: result -= 256
+      if self.debug:
+        print ("I2C: Device 0x%02X returned 0x%02X from reg 0x%02X" %
+         (self.address, result & 0xFF, reg))
+      return result
+    except IOError, err:
+      return self.errMsg()
+
+  def readU16(self, reg):
+    "Reads an unsigned 16-bit value from the I2C device"
+    try:
+      hibyte = self.readU8(reg)
+      lobyte = self.readU8(reg+1)
+      result = (hibyte << 8) + lobyte
+      if (self.debug):
+        print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg)
+      return result
+    except IOError, err:
+      return self.errMsg()
+
+  def readS16(self, reg):
+    "Reads a signed 16-bit value from the I2C device"
+    try:
+      hibyte = self.readS8(reg)
+      lobyte = self.readU8(reg+1)
+      result = (hibyte << 8) + lobyte
+      if (self.debug):
+        print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg)
+      return result
+    except IOError, err:
+      return self.errMsg()
+
+  def readU16Rev(self, reg):
+    "Reads an unsigned 16-bit value from the I2C device with rev byte order"
+    try:
+      lobyte = self.readU8(reg)
+      hibyte = self.readU8(reg+1)
+      result = (hibyte << 8) + lobyte
+      if (self.debug):
+        print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg)
+      return result
+    except IOError, err:
+      return self.errMsg()
+
+  def readS16Rev(self, reg):
+    "Reads a signed 16-bit value from the I2C device with rev byte order"
+    try:
+      lobyte = self.readS8(reg)
+      hibyte = self.readU8(reg+1)
+      result = (hibyte << 8) + lobyte
+      if (self.debug):
+        print "I2C: Device 0x%02X returned 0x%04X from reg 0x%02X" % (self.address, result & 0xFFFF, reg)
+      return result
+    except IOError, err:
+      return self.errMsg()
+
+if __name__ == '__main__':
+  try:
+    bus = Adafruit_I2C(address=0)
+    print "Default I2C bus is accessible"
+  except:
+    print "Error accessing default I2C bus"

+ 87 - 0
adafruit_7segment/Adafruit_LEDBackpack.py

@@ -0,0 +1,87 @@
+#!/usr/bin/python
+
+import time
+from copy import copy
+from Adafruit_I2C import Adafruit_I2C
+
+# ============================================================================
+# LEDBackpack Class
+# ============================================================================
+
+class LEDBackpack:
+  i2c = None
+
+  # Registers
+  __HT16K33_REGISTER_DISPLAY_SETUP        = 0x80
+  __HT16K33_REGISTER_SYSTEM_SETUP         = 0x20
+  __HT16K33_REGISTER_DIMMING              = 0xE0
+
+  # Blink rate
+  __HT16K33_BLINKRATE_OFF                 = 0x00
+  __HT16K33_BLINKRATE_2HZ                 = 0x01
+  __HT16K33_BLINKRATE_1HZ                 = 0x02
+  __HT16K33_BLINKRATE_HALFHZ              = 0x03
+
+  # Display buffer (8x16-bits)
+  __buffer = [0x0000, 0x0000, 0x0000, 0x0000, \
+              0x0000, 0x0000, 0x0000, 0x0000 ]
+
+  # Constructor
+  def __init__(self, address=0x70, debug=False):
+    self.i2c = Adafruit_I2C(address)
+    self.address = address
+    self.debug = debug
+
+    # Turn the oscillator on
+    self.i2c.write8(self.__HT16K33_REGISTER_SYSTEM_SETUP | 0x01, 0x00)
+
+    # Turn blink off
+    self.setBlinkRate(self.__HT16K33_BLINKRATE_OFF)
+
+    # Set maximum brightness
+    self.setBrightness(15)
+
+    # Clear the screen
+    self.clear()
+
+  def setBrightness(self, brightness):
+    "Sets the brightness level from 0..15"
+    if (brightness > 15):
+      brightness = 15
+    self.i2c.write8(self.__HT16K33_REGISTER_DIMMING | brightness, 0x00)
+
+  def setBlinkRate(self, blinkRate):
+    "Sets the blink rate"
+    if (blinkRate > self.__HT16K33_BLINKRATE_HALFHZ):
+       blinkRate = self.__HT16K33_BLINKRATE_OFF
+    self.i2c.write8(self.__HT16K33_REGISTER_DISPLAY_SETUP | 0x01 | (blinkRate << 1), 0x00)
+
+  def setBufferRow(self, row, value, update=True):
+    "Updates a single 16-bit entry in the 8*16-bit buffer"
+    if (row > 7):
+      return                    # Prevent buffer overflow
+    self.__buffer[row] = value  # value # & 0xFFFF
+    if (update):
+      self.writeDisplay()       # Update the display
+
+  def getBuffer(self):
+    "Returns a copy of the raw buffer contents"
+    bufferCopy = copy(self.__buffer)
+    return bufferCopy
+ 
+  def writeDisplay(self):
+    "Updates the display memory"
+    bytes = []
+    for item in self.__buffer:
+      bytes.append(item & 0xFF)
+      bytes.append((item >> 8) & 0xFF)
+    self.i2c.writeList(0x00, bytes)
+
+  def clear(self, update=True):
+    "Clears the display memory"
+    self.__buffer = [ 0, 0, 0, 0, 0, 0, 0, 0 ]
+    if (update):
+      self.writeDisplay()
+
+led = LEDBackpack(0x70)
+

+ 0 - 0
adafruit_7segment/__init__.py


+ 0 - 0
stddlib/__init__.py


+ 122 - 0
stddlib/daemon.py

@@ -0,0 +1,122 @@
+# -*- coding: utf-8-*-
+#
+# yfmd - your friendly monitoring daemon
+# a lightweight monitoring solution implemented in python
+# Written in 2013 by Helmut Pozimski <helmut@pozimski.eu>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import print_function, unicode_literals
+
+import os
+import sys
+
+
+class Daemon(object):
+	""" Tries to implement a well behaving unix daemon in a generic way,
+	so the code could be used in different projects.
+
+	"""
+
+	def __init__(self, pfile_path, pfile_name):
+		""" Initializes the object. """
+		self.__pfile_path = pfile_path
+		self.__pfile_name = pfile_name
+		self.__daemon = False
+
+	def Daemonize(self):
+		""" Turns the calling prozess into a daemon running on it's own """
+
+		try:
+			# Fork for the first time
+			self.__pid = os.fork()
+		except OSError:
+			sys.exit(os.EX_OSERR)
+		else:
+			if self.__pid > 0:
+				sys.exit(os.EX_OK)
+		# Become session and group leader
+		os.setsid()
+		try:
+			#Fork for the second time
+			self.__pid = os.fork()
+		except OSError:
+			sys.exit(os.EX_OSERR)
+		else:
+			if self.__pid > 0:
+				sys.exit(os.EX_OK)
+		# Change cwd to / to avoid interfering with other mounted file systems
+		os.chdir("/")
+		# Reset the umask
+		os.umask(0)
+
+		# Close possibly open file descriptors
+		os.close(0)
+		os.close(1)
+		os.close(2)
+
+		# And redirect them to /dev/null
+		os.open("/dev/null", 0)
+		os.open("/dev/null", 1)
+		os.open("/dev/null", 2)
+
+		self.__daemon = True
+
+	def DropPriv(self, uid, gid):
+		""" If the daemon is running as root user, drop privileges and continue
+		running as the defined unprivileged user """
+		if os.getuid() == 0:
+			os.setgid(gid)
+			os.setuid(uid)
+
+	def SetName(self, name, cmdline):
+		""" Sets the name of the process shown visible in ps and top,
+		this allows to make your daemon look more like a standalone
+		program instead of a python script.
+
+		"""
+		try:
+			# First check if prctl is available, otherwise this function does nothing
+			import prctl
+		except ImportError:
+			return False
+		else:
+			prctl.set_name(name)
+			prctl.set_proctitle(cmdline)
+			return True
+
+	def Start(self):
+		""" Performs the operations needed to "start" the daemon """
+		if self.__daemon is True:
+			if os.access(self.__pfile_path, os.F_OK & os.W_OK):
+				self.__pidfile = open(os.path.join(self.__pfile_path, self.__pfile_name),
+						"w")
+				self.__pidfile.write(unicode(os.getpid()) + "\n")
+				self.__pidfile.close()
+				return True
+			else:
+				return False
+		else:
+			return False
+
+	def Stop(self):
+		""" Performs the operations needed to stop the daemon """
+		if self.__daemon is True:
+			try:
+				os.remove(os.path.join(self.__pfile_path, self.__pfile_name))
+			except OSError:
+				return False
+			else:
+				return True
+		else:
+			return True