From e1f80c4f7d24c5792c0bb5e28e213e4b5daa1793 Mon Sep 17 00:00:00 2001 From: paspo Date: Wed, 14 Feb 2018 23:06:24 +0100 Subject: [PATCH] initial import --- .gitignore | 3 + APKBUILD | 26 +++++ etc/local.d/openpdu.start | 21 ++++ etc/openpdu/openpdu.conf | 22 +++++ openpdu | 195 ++++++++++++++++++++++++++++++++++++++ openpdu.post-install | 3 + 6 files changed, 270 insertions(+) create mode 100644 .gitignore create mode 100644 APKBUILD create mode 100644 etc/local.d/openpdu.start create mode 100644 etc/openpdu/openpdu.conf create mode 100755 openpdu create mode 100644 openpdu.post-install diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6860d29 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +packages/ +*.apk +.on-save.json diff --git a/APKBUILD b/APKBUILD new file mode 100644 index 0000000..90d7d17 --- /dev/null +++ b/APKBUILD @@ -0,0 +1,26 @@ +# Contributor: Paolo Asperti +# Maintainer: Paolo Asperti +pkgname=openpdu +pkgver=0.1 +pkgrel=1 +pkgdesc="OpenPDU project - main binary" +url="https://github.com/paspo/installinux" +arch="noarch" +license="GPL2" +depends="python, py-argh, apk-cron" +makedepends="" +install="openpdu.post-install" +subpackages="" +source="" + +build() { + : +} + +package() { + mkdir -p "$pkgdir" + install -Dm644 etc/openpdu/openpdu.conf "$pkgdir"/etc/openpdu/openpdu.conf + install -Dm755 etc/local.d/openpdu.start "$pkgdir"/etc/local.d/openpdu.start + + install -Dm755 openpdu "$pkgdir"/usr/sbin/openpdu +} diff --git a/etc/local.d/openpdu.start b/etc/local.d/openpdu.start new file mode 100644 index 0000000..de15e1f --- /dev/null +++ b/etc/local.d/openpdu.start @@ -0,0 +1,21 @@ +#!/bin/sh + +OUT1=1 +OUT2=2 +OUT3=3 +OUT4=7 +OUT5=8 +OUT6=9 +OUT7=11 +OUT8=12 + +for n in $(seq 1 8) ; do + eval "echo \$OUT$n > /sys/class/gpio/export" + eval "echo out > /sys/class/gpio/gpio\$OUT$n/direction" + + # 0=on 1=off :) + VAL=0 + + eval "echo $VAL > /sys/class/gpio/gpio\$OUT$n/value" + sleep 0.2 +done diff --git a/etc/openpdu/openpdu.conf b/etc/openpdu/openpdu.conf new file mode 100644 index 0000000..a430b00 --- /dev/null +++ b/etc/openpdu/openpdu.conf @@ -0,0 +1,22 @@ +[DEFAULT] + + +# EXAMPLE GPIO BOARD +# [board0] +# out0 = 1 +# out1 = 2 +# out2 = 3 +# out3 = 7 +# out4 = 8 +# out5 = 9 +# out6 = 11 +# out7 = 12 +# type = gpio-out +# channels = 8 + + +# EXAMPLE I2C BOARD +# [board1] +# type = i2c-out +# address = 20 +# channels = 8 diff --git a/openpdu b/openpdu new file mode 100755 index 0000000..2cb9def --- /dev/null +++ b/openpdu @@ -0,0 +1,195 @@ +#!/usr/bin/env python + +import os +import sys +import argh +from argh import arg +import re +import ConfigParser +import json as JSON + +VERSION = 0.1 +defaults = {} +boards = [] + + + +def version(): + 'show program version and quit' + return 'OpenPDU version %s - Copyright (C) 2018 by Paolo Asperti.' % VERSION + +@arg('-j', '--json', help="output in json") +def dumpcfg(json=False): + 'dump configuration' + if json: + b = [board.toJSON() for board in boards] + return JSON.dumps({'boards':b}) + else: + b = '' + for board in boards: + b += board.toSTR() + return '\nBoards:\n' + b + + +@arg("board", help="board number") +@arg("out", help="out number") +@arg("onoff", help="1=on [everything else]=off") +@arg('-j', '--json', help="output in json") +def setpower(board, out, onoff, json=False): + 'enable or disable power to a socket' + b = [b for b in boards if b.boardnum==int(board)] + if len(b) != 1: + print 'wrong board number: %s' % str(board) + sys.exit(1) + theBoard = b[0] + if int(out)>int(theBoard.channels)-1: + print 'wrong out number: %s, board has %s channels (0..%s)' % (str(out),str(theBoard.channels),str(int(theBoard.channels)-1)) + sys.exit(1) + status = (onoff == '1') + return theBoard.setpower(int(out),status) + + +@arg("board", help="board number") +@arg("out", help="out number") +@arg('-j', '--json', help="output in json") +def getpower(board, out, json=False): + 'get socket power status' + b = [b for b in boards if b.boardnum==int(board)] + if len(b) != 1: + print 'wrong board number: %s' % str(board) + sys.exit(1) + theBoard = b[0] + if int(out)>int(theBoard.channels)-1: + print 'wrong out number: %s, board has %s channels (0..%s)' % (str(out),str(theBoard.channels),str(int(theBoard.channels)-1)) + sys.exit(1) + return theBoard.getpower(int(out)) + + + + + + + + + + + +class BoardI2COut(object): + def __init__(self, boardnum, channels=None, address=None): + self.boardnum = boardnum + if channels is None: + self.channels = 0 + else: + self.channels = channels + if address is None: + self.address = 0x20 + else: + self.address = address + + def dumpcfg(json=False): + if json: + return {'boardnum':self.boardnum,'type':'i2c-out','channels':self.channels,'address':self.address} + else: + return 'Board %i\nType: i2c-out\nChannels: %i\nAddress: %i' % (self.boardnum,self.channels,self.address) + + def toJSON(self): + return {'boardnum':self.boardnum,'type':'i2c-out','channels':self.channels,'address':self.address} + + def toSTR(self): + return ' Board %s\n Type: i2c-out\n Channels: %s\n Address: %s\n\n' % (self.boardnum,self.channels,self.address) + + def setpower(self, channel, power): + return + + def getpower(self, channel): + return False + + +class BoardGpioOut(object): + gpios = [] + + def __init__(self, boardnum, channels=None, gpios=None): + self.boardnum = boardnum + if channels is None: + self.channels = 0 + else: + self.channels = int(channels) + if not isinstance(gpios, list): + print 'No gpios specified for gpio board %s' % self.boardnum + if len(gpios) != self.channels: + print 'Wrong number of gpios specified for gpio board %s' % self.boardnum + self.gpios = [int(gpio) for gpio in gpios] + + def dumpcfg(json=False): + if json: + return {'boardnum':self.boardnum,'type':'gpio-out','channels':self.channels} + else: + return 'Board %i\nType: gpio-out\nChannels: %i ' % (self.boardnum,self.channels) + + def toJSON(self): + return {'boardnum':self.boardnum,'type':'gpio-out','channels':self.channels} + + def toSTR(self): + return ' Board %s\n Type: gpio-out\n Channels: %s\n\n' % (self.boardnum,self.channels) + + def setpower(self, channel, power): + io = self.gpios[channel] + fn = '/sys/class/gpio/gpio%s/value' % io + f = open(fn,'w') + out = '0' if power else '1' + return f.write(out) + + def getpower(self, channel): + io = self.gpios[channel] + fn = '/sys/class/gpio/gpio%s/value' % io + f = open(fn,'r') + return int(f.read()) == 0 + + + + + + + + + + + + + + + + + + +configParser = ConfigParser.SafeConfigParser(defaults=defaults) + +configFile = '/etc/openpdu/openpdu.conf' +if os.path.isfile(configFile) and os.access(configFile, os.R_OK): + configParser.read(configFile) + +for s in configParser.sections(): + if re.match('^board.*',s): + bType = configParser.get(s, 'type') + num = int(re.sub(r'^board','',s)) + if bType=='gpio-out': + channels = int(configParser.get(s, 'channels')) + gpios = [] + for g in range(0,channels): + gpios.append(int(configParser.get(s, 'out%s' % g))) + b = BoardGpioOut(boardnum=num, channels=channels, gpios=gpios) + boards.append(b) + elif bType=='i2c-out': + channels = int(configParser.get(s, 'channels')) + address = configParser.get(s, 'address') + b = BoardI2COut(boardnum=num, channels=channels, address=address) + boards.append(b) + + +parser = argh.ArghParser() +parser.add_commands([setpower, getpower, dumpcfg, version]) + +# dispatching: + +if __name__ == '__main__': + parser.dispatch() diff --git a/openpdu.post-install b/openpdu.post-install new file mode 100644 index 0000000..c52d3c2 --- /dev/null +++ b/openpdu.post-install @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 0