<commit_before>#!/usr/bin/python

from pyb import I2C
import time

# ===========================================================================
# BMP085 Class
# Based mostly on Adafruit_BMP085.py
# For use with a Micro Python pyboard http://micropython.org
# and a BMP180 Barometric Pressure/Temperature/Altitude Sensor
# tested with http://www.adafruit.com/products/1603
# ===========================================================================

class BMP085 :
  i2c = None

  # Operating Modes
  __BMP085_ULTRALOWPOWER     = 0
  __BMP085_STANDARD          = 1
  __BMP085_HIGHRES           = 2
  __BMP085_ULTRAHIGHRES      = 3

  # BMP085 Registers
  __BMP085_CAL_AC1           = 0xAA  # R   Calibration data (16 bits)
  __BMP085_CAL_AC2           = 0xAC  # R   Calibration data (16 bits)
  __BMP085_CAL_AC3           = 0xAE  # R   Calibration data (16 bits)
  __BMP085_CAL_AC4           = 0xB0  # R   Calibration data (16 bits)
  __BMP085_CAL_AC5           = 0xB2  # R   Calibration data (16 bits)
  __BMP085_CAL_AC6           = 0xB4  # R   Calibration data (16 bits)
  __BMP085_CAL_B1            = 0xB6  # R   Calibration data (16 bits)
  __BMP085_CAL_B2            = 0xB8  # R   Calibration data (16 bits)
  __BMP085_CAL_MB            = 0xBA  # R   Calibration data (16 bits)
  __BMP085_CAL_MC            = 0xBC  # R   Calibration data (16 bits)
  __BMP085_CAL_MD            = 0xBE  # R   Calibration data (16 bits)
  __BMP085_CONTROL           = 0xF4
  __BMP085_TEMPDATA          = 0xF6
  __BMP085_PRESSUREDATA      = 0xF6
  __BMP085_READTEMPCMD       = 0x2E
  __BMP085_READPRESSURECMD   = 0x34

  # Private Fields
  _cal_AC1 = 0
  _cal_AC2 = 0
  _cal_AC3 = 0
  _cal_AC4 = 0
  _cal_AC5 = 0
  _cal_AC6 = 0
  _cal_B1 = 0
  _cal_B2 = 0
  _cal_MB = 0
  _cal_MC = 0
  _cal_MD = 0

  # Constructor
  def __init__(self, port = 1, address=0x77, mode=1, debug=False):
    self.i2c = I2C(port, I2C.MASTER)

    self.address = address
    self.debug = debug
    # Make sure the specified mode is in the appropriate range
    if ((mode < 0) | (mode > 3)):
      if (self.debug):
        print("Invalid Mode: Using STANDARD by default")
      self.mode = self.__BMP085_STANDARD
    else:
      self.mode = mode
    # Read the calibration data
    self.readCalibrationData()

  def readS16(self, register):
    "Reads a signed 16-bit value"
    hi = ord(self.i2c.mem_read(1, self.address, register))
    if hi > 127: hi -= 256
    lo = ord(self.i2c.mem_read(1, self.address, register+1))
    return (hi << 8) + lo

  def readU16(self, register):
    "Reads an unsigned 16-bit value"
    hi = ord(self.i2c.mem_read(1, self.address, register))
    lo = ord(self.i2c.mem_read(1, self.address, register+1))
    return (hi << 8) + lo

  def readCalibrationData(self):
    "Reads the calibration data from the IC"
    self._cal_AC1 = self.readS16(self.__BMP085_CAL_AC1)   # INT16
    self._cal_AC2 = self.readS16(self.__BMP085_CAL_AC2)   # INT16
    self._cal_AC3 = self.readS16(self.__BMP085_CAL_AC3)   # INT16
    self._cal_AC4 = self.readU16(self.__BMP085_CAL_AC4)   # UINT16
    self._cal_AC5 = self.readU16(self.__BMP085_CAL_AC5)   # UINT16
    self._cal_AC6 = self.readU16(self.__BMP085_CAL_AC6)   # UINT16
    self._cal_B1 = self.readS16(self.__BMP085_CAL_B1)     # INT16
    self._cal_B2 = self.readS16(self.__BMP085_CAL_B2)     # INT16
    self._cal_MB = self.readS16(self.__BMP085_CAL_MB)     # INT16
    self._cal_MC = self.readS16(self.__BMP085_CAL_MC)     # INT16
    self._cal_MD = self.readS16(self.__BMP085_CAL_MD)     # INT16
    if (self.debug):
      self.showCalibrationData()

  def showCalibrationData(self):
      "Displays the calibration values for debugging purposes"
      print("DBG: AC1 = %6d" % (self._cal_AC1))
      print("DBG: AC2 = %6d" % (self._cal_AC2))
      print("DBG: AC3 = %6d" % (self._cal_AC3))
      print("DBG: AC4 = %6d" % (self._cal_AC4))
      print("DBG: AC5 = %6d" % (self._cal_AC5))
      print("DBG: AC6 = %6d" % (self._cal_AC6))
      print("DBG: B1  = %6d" % (self._cal_B1))
      print("DBG: B2  = %6d" % (self._cal_B2))
      print("DBG: MB  = %6d" % (self._cal_MB))
      print("DBG: MC  = %6d" % (self._cal_MC))
      print("DBG: MD  = %6d" % (self._cal_MD))

  def readRawTemp(self):
    "Reads the raw (uncompensated) temperature from the sensor"
    self.i2c.mem_write(self.__BMP085_READTEMPCMD, self.address, self.__BMP085_CONTROL)
    time.sleep(0.005)  # Wait 5ms
    raw = self.readU16(self.__BMP085_TEMPDATA)
    if (self.debug):
      print("DBG: Raw Temp: 0x%04X (%d)" % (raw & 0xFFFF, raw))
    return raw

  def readRawPressure(self):
    "Reads the raw (uncompensated) pressure level from the sensor"
    self.i2c.mem_write(self.__BMP085_READPRESSURECMD + (self.mode << 6), self.address, self.__BMP085_CONTROL)
    if (self.mode == self.__BMP085_ULTRALOWPOWER):
      time.sleep(0.005)
    elif (self.mode == self.__BMP085_HIGHRES):
      time.sleep(0.014)
    elif (self.mode == self.__BMP085_ULTRAHIGHRES):
      time.sleep(0.026)
    else:
      time.sleep(0.008)

    msb = ord(self.i2c.mem_read(1, self.address, self.__BMP085_PRESSUREDATA))
    lsb = ord(self.i2c.mem_read(1, self.address, self.__BMP085_PRESSUREDATA+1))
    xlsb = ord(self.i2c.mem_read(1, self.address, self.__BMP085_PRESSUREDATA+2))
    raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.mode)
    if (self.debug):
      print("DBG: Raw Pressure: 0x%04X (%d)" % (raw & 0xFFFF, raw))
    return raw

  def readTemperature(self):
    "Gets the compensated temperature in degrees celcius"
    UT = 0
    X1 = 0
    X2 = 0
    B5 = 0
    temp = 0.0

    # Read raw temp before aligning it with the calibration values
    UT = self.readRawTemp()
    X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
    X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
    B5 = int(X1 + X2)
    temp = ((B5 + 8) >> 4) / 10.0
    if (self.debug):
      print("DBG: Calibrated temperature = %f C" % temp)
    return temp

  def readPressure(self):
    "Gets the compensated pressure in pascal"
    UT = 0
    UP = 0
    B3 = 0
    B5 = 0
    B6 = 0
    X1 = 0
    X2 = 0
    X3 = 0
    p = 0
    B4 = 0
    B7 = 0

    UT = self.readRawTemp()
    UP = self.readRawPressure()

    # You can use the datasheet values to test the conversion results
    # dsValues = True
    dsValues = False

    if (dsValues):
      UT = 27898
      UP = 23843
      self._cal_AC6 = 23153
      self._cal_AC5 = 32757
      self._cal_MB = -32768;
      self._cal_MC = -8711
      self._cal_MD = 2868
      self._cal_B1 = 6190
      self._cal_B2 = 4
      self._cal_AC3 = -14383
      self._cal_AC2 = -72
      self._cal_AC1 = 408
      self._cal_AC4 = 32741
      self.mode = self.__BMP085_ULTRALOWPOWER
      if (self.debug):
        self.showCalibrationData()

    # True Temperature Calculations
    X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
    X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
    B5 = int(X1 + X2)
    if (self.debug):
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))
      print("DBG: B5 = %d" % (B5))
      print("DBG: True Temperature = %.2f C" % (((B5 + 8) >> 4) / 10.0))

    # Pressure Calculations
    B6 = B5 - 4000
    X1 = (self._cal_B2 * (B6 * B6) >> 12) >> 11
    X2 = (self._cal_AC2 * B6) >> 11
    X3 = X1 + X2
    B3 = (((self._cal_AC1 * 4 + X3) << self.mode) + 2) / 4
    if (self.debug):
      print("DBG: B6 = %d" % (B6))
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))
      print("DBG: X3 = %d" % (X3))

    X1 = (self._cal_AC3 * B6) >> 13
    X2 = (self._cal_B1 * ((B6 * B6) >> 12)) >> 16
    X3 = ((X1 + X2) + 2) >> 2
    B4 = (self._cal_AC4 * (X3 + 32768)) >> 15
    B7 = (UP - B3) * (50000 >> self.mode)
    if (self.debug):
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))
      print("DBG: X3 = %d" % (X3))
      print("DBG: B4 = %d" % (B4))
      print("DBG: B7 = %d" % (B7))

    if (B7 < 0x80000000):
      p = int((B7 * 2) / B4)
    else:
      p = int((B7 / B4) * 2)

    if (self.debug):
      print("DBG: X1 = %d" % (X1))

    X1 = (p >> 8) * (p >> 8)
    X1 = (X1 * 3038) >> 16
    X2 = (-7357 * p) >> 16
    if (self.debug):
      print("DBG: p  = %d" % (p))
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))

    p = p + ((X1 + X2 + 3791) >> 4)
    if (self.debug):
      print("DBG: Pressure = %d Pa" % (p))

    return p

  def readAltitude(self, seaLevelPressure=101325):
    "Calculates the altitude in meters"
    altitude = 0.0
    pressure = float(self.readPressure())
    altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903))
    if (self.debug):
      print("DBG: Altitude = %d" % (altitude))
    return altitude

    return 0
<commit_msg>Update BMP085.py<commit_after>#!/usr/bin/python

from pyb import I2C
import time

# ===========================================================================
# BMP085 Class
# Based mostly on Adafruit_BMP085.py
# For use with a Micro Python pyboard http://micropython.org
# and a BMP180 Barometric Pressure/Temperature/Altitude Sensor
# tested with http://www.adafruit.com/products/1603
# ===========================================================================

class BMP085 :
  i2c = None
  # I guess these can be public
  # Operating Modes
  BMP085_ULTRALOWPOWER     = 0
  BMP085_STANDARD          = 1
  BMP085_HIGHRES           = 2
  BMP085_ULTRAHIGHRES      = 3

  # BMP085 Registers
  __BMP085_CAL_AC1           = 0xAA  # R   Calibration data (16 bits)
  __BMP085_CAL_AC2           = 0xAC  # R   Calibration data (16 bits)
  __BMP085_CAL_AC3           = 0xAE  # R   Calibration data (16 bits)
  __BMP085_CAL_AC4           = 0xB0  # R   Calibration data (16 bits)
  __BMP085_CAL_AC5           = 0xB2  # R   Calibration data (16 bits)
  __BMP085_CAL_AC6           = 0xB4  # R   Calibration data (16 bits)
  __BMP085_CAL_B1            = 0xB6  # R   Calibration data (16 bits)
  __BMP085_CAL_B2            = 0xB8  # R   Calibration data (16 bits)
  __BMP085_CAL_MB            = 0xBA  # R   Calibration data (16 bits)
  __BMP085_CAL_MC            = 0xBC  # R   Calibration data (16 bits)
  __BMP085_CAL_MD            = 0xBE  # R   Calibration data (16 bits)
  __BMP085_CONTROL           = 0xF4
  __BMP085_TEMPDATA          = 0xF6
  __BMP085_PRESSUREDATA      = 0xF6
  __BMP085_READTEMPCMD       = 0x2E
  __BMP085_READPRESSURECMD   = 0x34

  # Private Fields
  _cal_AC1 = 0
  _cal_AC2 = 0
  _cal_AC3 = 0
  _cal_AC4 = 0
  _cal_AC5 = 0
  _cal_AC6 = 0
  _cal_B1 = 0
  _cal_B2 = 0
  _cal_MB = 0
  _cal_MC = 0
  _cal_MD = 0

  # Constructor
  def __init__(self, port = 1, address=0x77, mode=1, debug=False):
    self.i2c = I2C(port, I2C.MASTER)

    self.address = address
    self.debug = debug
    # Make sure the specified mode is in the appropriate range
    if ((mode < 0) | (mode > 3)):
      if (self.debug):
        print("Invalid Mode: Using STANDARD by default")
      self.mode = self.BMP085_STANDARD
    else:
      self.mode = mode
    # Read the calibration data
    self.readCalibrationData()

  def readS16(self, register):
    "Reads a signed 16-bit value"
    hi = ord(self.i2c.mem_read(1, self.address, register))
    if hi > 127: hi -= 256
    lo = ord(self.i2c.mem_read(1, self.address, register+1))
    return (hi << 8) + lo

  def readU16(self, register):
    "Reads an unsigned 16-bit value"
    hi = ord(self.i2c.mem_read(1, self.address, register))
    lo = ord(self.i2c.mem_read(1, self.address, register+1))
    return (hi << 8) + lo

  def readCalibrationData(self):
    "Reads the calibration data from the IC"
    self._cal_AC1 = self.readS16(self.__BMP085_CAL_AC1)   # INT16
    self._cal_AC2 = self.readS16(self.__BMP085_CAL_AC2)   # INT16
    self._cal_AC3 = self.readS16(self.__BMP085_CAL_AC3)   # INT16
    self._cal_AC4 = self.readU16(self.__BMP085_CAL_AC4)   # UINT16
    self._cal_AC5 = self.readU16(self.__BMP085_CAL_AC5)   # UINT16
    self._cal_AC6 = self.readU16(self.__BMP085_CAL_AC6)   # UINT16
    self._cal_B1 = self.readS16(self.__BMP085_CAL_B1)     # INT16
    self._cal_B2 = self.readS16(self.__BMP085_CAL_B2)     # INT16
    self._cal_MB = self.readS16(self.__BMP085_CAL_MB)     # INT16
    self._cal_MC = self.readS16(self.__BMP085_CAL_MC)     # INT16
    self._cal_MD = self.readS16(self.__BMP085_CAL_MD)     # INT16
    if (self.debug):
      self.showCalibrationData()

  def showCalibrationData(self):
      "Displays the calibration values for debugging purposes"
      print("DBG: AC1 = %6d" % (self._cal_AC1))
      print("DBG: AC2 = %6d" % (self._cal_AC2))
      print("DBG: AC3 = %6d" % (self._cal_AC3))
      print("DBG: AC4 = %6d" % (self._cal_AC4))
      print("DBG: AC5 = %6d" % (self._cal_AC5))
      print("DBG: AC6 = %6d" % (self._cal_AC6))
      print("DBG: B1  = %6d" % (self._cal_B1))
      print("DBG: B2  = %6d" % (self._cal_B2))
      print("DBG: MB  = %6d" % (self._cal_MB))
      print("DBG: MC  = %6d" % (self._cal_MC))
      print("DBG: MD  = %6d" % (self._cal_MD))

  def readRawTemp(self):
    "Reads the raw (uncompensated) temperature from the sensor"
    self.i2c.mem_write(self.__BMP085_READTEMPCMD, self.address, self.__BMP085_CONTROL)
    time.sleep(0.005)  # Wait 5ms
    raw = self.readU16(self.__BMP085_TEMPDATA)
    if (self.debug):
      print("DBG: Raw Temp: 0x%04X (%d)" % (raw & 0xFFFF, raw))
    return raw

  def readRawPressure(self):
    "Reads the raw (uncompensated) pressure level from the sensor"
    self.i2c.mem_write(self.__BMP085_READPRESSURECMD + (self.mode << 6), self.address, self.__BMP085_CONTROL)
    if (self.mode == self.BMP085_ULTRALOWPOWER):
      time.sleep(0.005)
    elif (self.mode == self.BMP085_HIGHRES):
      time.sleep(0.014)
    elif (self.mode == self.BMP085_ULTRAHIGHRES):
      time.sleep(0.026)
    else:
      time.sleep(0.008)

    msb = ord(self.i2c.mem_read(1, self.address, self.__BMP085_PRESSUREDATA))
    lsb = ord(self.i2c.mem_read(1, self.address, self.__BMP085_PRESSUREDATA+1))
    xlsb = ord(self.i2c.mem_read(1, self.address, self.__BMP085_PRESSUREDATA+2))
    raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.mode)
    if (self.debug):
      print("DBG: Raw Pressure: 0x%04X (%d)" % (raw & 0xFFFF, raw))
    return raw

  def readTemperature(self):
    "Gets the compensated temperature in degrees celcius"
    UT = 0
    X1 = 0
    X2 = 0
    B5 = 0
    temp = 0.0

    # Read raw temp before aligning it with the calibration values
    UT = self.readRawTemp()
    X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
    X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
    B5 = int(X1 + X2)
    temp = ((B5 + 8) >> 4) / 10.0
    if (self.debug):
      print("DBG: Calibrated temperature = %f C" % temp)
    return temp

  def readPressure(self):
    "Gets the compensated pressure in pascal"
    UT = 0
    UP = 0
    B3 = 0
    B5 = 0
    B6 = 0
    X1 = 0
    X2 = 0
    X3 = 0
    p = 0
    B4 = 0
    B7 = 0

    UT = self.readRawTemp()
    UP = self.readRawPressure()

    # You can use the datasheet values to test the conversion results
    # dsValues = True
    dsValues = False

    if (dsValues):
      UT = 27898
      UP = 23843
      self._cal_AC6 = 23153
      self._cal_AC5 = 32757
      self._cal_MB = -32768;
      self._cal_MC = -8711
      self._cal_MD = 2868
      self._cal_B1 = 6190
      self._cal_B2 = 4
      self._cal_AC3 = -14383
      self._cal_AC2 = -72
      self._cal_AC1 = 408
      self._cal_AC4 = 32741
      self.mode = self.BMP085_ULTRALOWPOWER
      if (self.debug):
        self.showCalibrationData()

    # True Temperature Calculations
    X1 = ((UT - self._cal_AC6) * self._cal_AC5) >> 15
    X2 = (self._cal_MC << 11) / (X1 + self._cal_MD)
    B5 = int(X1 + X2)
    if (self.debug):
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))
      print("DBG: B5 = %d" % (B5))
      print("DBG: True Temperature = %.2f C" % (((B5 + 8) >> 4) / 10.0))

    # Pressure Calculations
    B6 = B5 - 4000
    X1 = (self._cal_B2 * (B6 * B6) >> 12) >> 11
    X2 = (self._cal_AC2 * B6) >> 11
    X3 = X1 + X2
    B3 = (((self._cal_AC1 * 4 + X3) << self.mode) + 2) / 4
    if (self.debug):
      print("DBG: B6 = %d" % (B6))
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))
      print("DBG: X3 = %d" % (X3))

    X1 = (self._cal_AC3 * B6) >> 13
    X2 = (self._cal_B1 * ((B6 * B6) >> 12)) >> 16
    X3 = ((X1 + X2) + 2) >> 2
    B4 = (self._cal_AC4 * (X3 + 32768)) >> 15
    B7 = (UP - B3) * (50000 >> self.mode)
    if (self.debug):
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))
      print("DBG: X3 = %d" % (X3))
      print("DBG: B4 = %d" % (B4))
      print("DBG: B7 = %d" % (B7))

    if (B7 < 0x80000000):
      p = int((B7 * 2) / B4)
    else:
      p = int((B7 / B4) * 2)

    if (self.debug):
      print("DBG: X1 = %d" % (X1))

    X1 = (p >> 8) * (p >> 8)
    X1 = (X1 * 3038) >> 16
    X2 = (-7357 * p) >> 16
    if (self.debug):
      print("DBG: p  = %d" % (p))
      print("DBG: X1 = %d" % (X1))
      print("DBG: X2 = %d" % (X2))

    p = p + ((X1 + X2 + 3791) >> 4)
    if (self.debug):
      print("DBG: Pressure = %d Pa" % (p))

    return p

  def readAltitude(self, seaLevelPressure=101325):
    "Calculates the altitude in meters"
    altitude = 0.0
    pressure = float(self.readPressure())
    altitude = 44330.0 * (1.0 - pow(pressure / seaLevelPressure, 0.1903))
    if (self.debug):
      print("DBG: Altitude = %d" % (altitude))
    return altitude

    return 0
<|endoftext|>


<commit_before>import numpy as np
import uncertainties.unumpy as unp
from uncertainties.unumpy import (nominal_values as noms, std_devs as stds)
import matplotlib.pyplot as plt
import matplotlib as mpl
from scipy.optimize import curve_fit
plt.rcParams['figure.figsize'] = (15, 10)
plt.rcParams['font.size'] = 13
plt.rcParams['lines.linewidth'] = 1
csfont = {'fontname': 'Times New Roman'}

s,a = np.genfromtxt('alu_rund1.txt', unpack=True)

def f(s, m, n):
    return m * s + n
    #m = 0.107415584417 ± 0.00239018301449
    #n = -2.04478354984 ± 0.0848991748478

params, covariance = curve_fit(f, s, a)

errors = np.sqrt(np.diag(covariance))

print('m =', params[0], '±', errors[0])
print('n =', params[1], '±', errors[1])

s_plot = np.linspace(20, 45)

plt.plot(s, a, 'rx', label="example data")
plt.plot(s_plot, f(s_plot, *params), 'b-', label='linearer Ausgleich', linewidth=3)
plt.xlabel('Strecke/cm')
plt.ylabel('Auslenkung/mm')
plt.legend(loc="best")
plt.show()
<commit_msg>np.linspace geändert<commit_after>import numpy as np
import uncertainties.unumpy as unp
from uncertainties.unumpy import (nominal_values as noms, std_devs as stds)
import matplotlib.pyplot as plt
import matplotlib as mpl
from scipy.optimize import curve_fit
plt.rcParams['figure.figsize'] = (15, 10)
plt.rcParams['font.size'] = 13
plt.rcParams['lines.linewidth'] = 1
csfont = {'fontname': 'Times New Roman'}

s,a = np.genfromtxt('alu_rund1.txt', unpack=True)

def f(s, m, n):
    return m * s + n
    #m = 0.107415584417 ± 0.00239018301449
    #n = -2.04478354984 ± 0.0848991748478

params, covariance = curve_fit(f, s, a)

errors = np.sqrt(np.diag(covariance))

print('m =', params[0], '±', errors[0])
print('n =', params[1], '±', errors[1])

s_plot = np.linspace(25, 45)

plt.plot(s, a, 'rx', label="example data")
plt.plot(s_plot, f(s_plot, *params), 'b-', label='linearer Ausgleich', linewidth=3)
plt.xlabel('Strecke/cm')
plt.ylabel('Auslenkung/mm')
plt.legend(loc="best")
plt.show()
<|endoftext|>


<commit_before>#!/usr/bin/python

import serial
import io
import datetime
import time

# Reference for NexStar commands:
# http://www.nexstarsite.com/download/manuals/NexStarCommunicationProtocolV1.2.zip
class NexStar:

    def __init__(self, device):
        self.serial = serial.Serial(device, baudrate=9600, timeout=1)
        garbage_bytes = self.serial.inWaiting()
        self.serial.read(garbage_bytes)
        self.DIR_AZIMUTH = 0
        self.DIR_ELEVATION = 1

    # Send a command to the hand controller and get a response. The command
    # argument gives the ASCII command to send. The response_len is an integer
    # giving the number of characters expected in the response, excluding the
    # the terminating '#' character. The response received from the hand
    # controller is validated and returned, excluding the termination character.
    def _send_command(self, command, response_len = 0):
        self.serial.write(command)
        response = self.serial.read(response_len + 1)
        assert response[-1] == '#', 'Command failed'
        return response[0:-1]

    # Helper function to convert precise angular values in command responses
    # to degrees. See NexStar command reference for details.
    def _precise_to_degrees(self, string):
        return int(string, 16) / 2.**32 * 360.

    # Helper function to convert degrees to precise angular values for commands.
    # There are no restrictions on the range of the input. Both positive and
    # negative angles are supported.
    def _degrees_to_precise(self, degrees):
        return '%08X' % round((degrees % 360.) / 360. * 2.**32)

    # Generic get position helper function. Expects the precise version of
    # these commands.
    def _get_position(self, command):
        assert command in ['e', 'z']
        response = self._send_command(command, 17)
        return (self._precise_to_degrees(response[:8]),
                self._precise_to_degrees(response[9:17]))

    # Returns a tuple with current (azimuth, elevation) in degrees
    # Azimuth range is [0,360) and elevation range is [-180,180)
    def get_azel(self):
        (az, el) = self._get_position('z')
        # adjust range of elevation from [0,360) to [-180,180)
        el = (el + 180.0) % 360.0 - 180.0
        return (az, el)

    # Returns a tuple with current (right ascension, declination) in degrees
    def get_radec(self):
        return self._get_position('e')

    # Generic goto helper function. Expects the precise version of these
    # commands.
    def _goto_command(self, char, values):
        assert char in ['b', 'r', 's']
        command = (char + self._degrees_to_precise(values[0]) + ','
                   + self._degrees_to_precise(values[1]))
        self._send_command(command)

    # Commands the telescope to slew to the provided azimuth/elevation
    # coordinates in degrees
    def goto_azel(self, az, el):
        self._goto_command('b', (az, el))

    # Commands the telescope to slew to the provided right ascension and
    # declination coordinates in degrees
    def goto_radec(self, ra, dec):
        self._goto_command('r', (ra, dec))

    # Informs the hand controller that the telescope is currently pointed at
    # the provided right ascension and declination coordinates to improve
    # accuracy of future goto commands. See command reference for details.
    def sync(self, ra, dec):
        self._goto_command('s', (ra, dec))

    # Returns the current tracking mode as an integer:
    # 0 = Off
    # 1 = Alt/Az (elevation/azimuth)
    # 2 = EQ North
    # 3 = EQ South
    def get_tracking_mode(self):
        response = self._send_command('t', 1)
        return ord(response[0])

    # Sets the tracking mode, 0-3, as a integer. See list in comments for
    # get_tracking_mode.
    def set_tracking_mode(self, mode):
        assert mode in [0,1,2,3]
        command = 'T' + chr(mode)
        self._send_command(command)

    # Generic variable-rate slew command. Variable-rate simply means that
    # the angular rate can be specified precisely in arcseconds per second,
    # in contrast to the small number of fixed rates available on the hand-
    # controller. Direction is either self.DIR_AZIMUTH or self.DIR_ELEVATION.
    # Rate has units of arcseconds per second and may be positive or negative.
    def _var_slew_command(self, direction, rate):
        assert direction in [self.DIR_AZIMUTH, self.DIR_ELEVATION]
        negative_rate = True if rate < 0 else False
        track_rate_high = (int(abs(rate)) * 4) / 256
        track_rate_low = (int(abs(rate)) * 4) % 256
        direction_char = chr(16) if direction == self.DIR_AZIMUTH else chr(17)
        sign_char = chr(7) if negative_rate == True else chr(6)
        command = ('P' + chr(3) + direction_char + sign_char
                  + chr(track_rate_high) + chr(track_rate_low) + chr(0)
                  + chr(0))
        self._send_command(command)

    # Commands the telescope to slew at the azimuth and elevation rates
    # provided in units of arcseconds per second. Rates may be positive or
    # negative. Max advertised rate is 3 deg/s, max commandable rate is 16319
    # arcseconds per second or ~4.5 deg/s.
    def slew_var(self, az_rate, el_rate):
       self._var_slew_command(self.DIR_AZIMUTH, az_rate)
       self._var_slew_command(self.DIR_ELEVATION, el_rate)

    # Generic fixed-rate slew command. Fixed-rate means that only the nine
    # rates supported on the hand controller are available. Direction is
    # either self.DIR_AZIMUTH or self.DIR_ELEVATION. Rate is an integer
    # from -9 to +9, where 0 is stop and +/-9 is the maximum slew rate.
    def _fixed_slew_command(self, direction, rate):
        negative_rate = True if rate < 0 else False
        sign_char = chr(37) if negative_rate == True else chr(36)
        direction_char = chr(16) if direction == self.DIR_AZIMUTH else chr(17)
        rate_char = chr(int(abs(rate)))
        command = ('P' + chr(2) + direction_char + sign_char + rate_char
                   + chr(0) + chr(0) + chr(0))
        self._send_command(command)

    # Commands the telescope to slew at the azimuth and elevation rates
    # provided as integers in the range -9 to +9, corresponding to the
    # rates available on the hand controller.
    def slew_fixed(self, az_rate, el_rate):
        assert (az_rate >= -9) and (az_rate <= 9), 'az_rate out of range'
        assert (el_rate >= -9) and (el_rate <= 9), 'el_rate out of range'
        self._fixed_slew_command(self.DIR_AZIMUTH, az_rate)
        self._fixed_slew_command(self.DIR_ELEVATION, el_rate)

    # Returns the location of the telescope as a tuple of (latitude,
    # longitude) in signed degrees format.
    def get_location(self):
        response = self._send_command('w', 8)
        lat_deg = ord(response[0])
        lat_min = ord(response[1])
        lat_sec = ord(response[2])
        lat_north = True if ord(response[3]) == 0 else False
        lat = lat_deg + lat_min / 60.0 + lat_sec / 3600.0
        if lat_north == False:
            lat = -lat
        lon_deg = ord(response[4])
        lon_min = ord(response[5])
        lon_sec = ord(response[6])
        lon_east = True if ord(response[7]) == 0 else False
        lon = lon_deg + lon_min / 60.0 + lon_sec / 3600.0
        if lon_east == False:
            lon = -lon
        return (lat, lon)

    # Set the location of the telescope with latitude and longitude coordinates
    # in signed degrees format.
    def set_location(self, lat, lon):
        lat_deg = int(abs(lat))
        lat_min = int((abs(lat) - lat_deg) * 60.0)
        lat_sec = int((abs(lat) - lat_deg - lat_min / 60.0) * 3600.0)
        lon_deg = int(abs(lon))
        lon_min = int((abs(lon) - lon_deg) * 60.0)
        lon_sec = int((abs(lon) - lon_deg - lon_min / 60.0) * 3600.0)
        command = ('W'
            + chr(lat_deg)
            + chr(lat_min)
            + chr(lat_sec)
            + chr(lat < 0)
            + chr(lon_deg)
            + chr(lon_min)
            + chr(lon_sec)
            + chr(lon < 0))
        self._send_command(command)

    # Returns the telescope current time in seconds since the Unix epoch
    # (1 Jan 1970). Timezone information and daylight savings time are not
    # currently supported.
    def get_time(self):
        response = self._send_command('h', 8)
        t = datetime.datetime(
            2000 + ord(response[5]), # year
            ord(response[3]),        # month
            ord(response[4]),        # day
            ord(response[0]),        # hour
            ord(response[1]),        # minute
            ord(response[2]),        # second
            0,                       # microseconds
        )
        return time.mktime(t.timetuple())

    # Set the time on the telescope. The timestamp argument is given in seconds
    # since the Unix epoch (1 Jan 1970). Timezone information and daylight
    # savings time are not currently supported, so the GMT/UTC offset will be
    # set to zero and Daylight Savings will be disabled (Standard Time).
    def set_time(self, timestamp):
        t = datetime.datetime.fromtimestamp(timestamp)
        command = ('H'
            + chr(t.hour)
            + chr(t.minute)
            + chr(t.second)
            + chr(t.month)
            + chr(t.day)
            + chr(t.year - 2000)
            + chr(0)
            + chr(0)
        )
        self._send_command(command)

    # Returns device version as a floating point value.
    def get_version(self):
        response = self._send_command('V', 2)
        return ord(response[0]) + ord(response[1]) / 10.0

    # Returns model as an integer. See NexStar command reference for decoding
    # table.
    def get_model(self):
        response = self._send_command('m', 1)
        return ord(response)

    # Sends a character to the telescope hand controller, which the hand
    # controller will echo back in response. The argument to the function
    # is an integer in the range 0 to 255. If the command is successful, the
    # return value will match the argument.
    def echo(self, x):
        command = 'K' + chr(x)
        response = self._send_command(command, 1)
        assert ord(response) == x, 'echo failed to return sent character'
        return ord(response)

    # Returns True if alignment has been performed, False otherwise.
    def alignment_complete(self):
        response = self._send_command('J', 1)
        return True if ord(response) == 1 else False

    # Returns True if the telescope is slewing to execute a goto command. Note
    # that this will return False if the telescope is slewing for any other
    # reason.
    def goto_in_progress(self):
        response = self._send_command('L', 1)
        return True if int(response) == 1 else False

    # Cancels a goto command that is in progress.
    def cancel_goto(self):
        self._send_command('M')

<commit_msg>Improvements to comments<commit_after>#!/usr/bin/python

import serial
import io
import datetime
import time

# Reference for NexStar commands:
# http://www.nexstarsite.com/download/manuals/NexStarCommunicationProtocolV1.2.zip
class NexStar:

    # The constructor argument is a string giving the serial device connected to the
    # NexStar hand controller. For example, '/dev/ttyUSB0'.
    def __init__(self, device):
        self.serial = serial.Serial(device, baudrate=9600, timeout=1)
        garbage_bytes = self.serial.inWaiting()
        self.serial.read(garbage_bytes)
        self.DIR_AZIMUTH = 0
        self.DIR_ELEVATION = 1

    # Send a command to the hand controller and get a response. The command
    # argument gives the ASCII command to send. The response_len is an integer
    # giving the number of characters expected in the response, excluding the
    # the terminating '#' character. The response received from the hand
    # controller is validated and returned, excluding the termination character.
    def _send_command(self, command, response_len = 0):
        self.serial.write(command)
        response = self.serial.read(response_len + 1)
        assert response[-1] == '#', 'Command failed'
        return response[0:-1]

    # Helper function to convert precise angular values in command responses
    # to degrees. See NexStar command reference for details. Return value
    # will be in range [0,360).
    def _precise_to_degrees(self, string):
        return int(string, 16) / 2.**32 * 360.

    # Helper function to convert degrees to precise angular values for commands.
    # There are no restrictions on the range of the input. Both positive and
    # negative angles are supported.
    def _degrees_to_precise(self, degrees):
        return '%08X' % round((degrees % 360.) / 360. * 2.**32)

    # Generic get position helper function. Expects the precise version of
    # these commands.
    def _get_position(self, command):
        assert command in ['e', 'z']
        response = self._send_command(command, 17)
        return (self._precise_to_degrees(response[:8]),
                self._precise_to_degrees(response[9:17]))

    # Returns a tuple with current (azimuth, elevation) in degrees
    # Azimuth range is [0,360) and elevation range is [-180,180)
    def get_azel(self):
        (az, el) = self._get_position('z')
        # adjust range of elevation from [0,360) to [-180,180)
        el = (el + 180.0) % 360.0 - 180.0
        return (az, el)

    # Returns a tuple with current (right ascension, declination) in degrees
    def get_radec(self):
        return self._get_position('e')

    # Generic goto helper function. Expects the precise version of these
    # commands.
    def _goto_command(self, char, values):
        assert char in ['b', 'r', 's']
        command = (char + self._degrees_to_precise(values[0]) + ','
                   + self._degrees_to_precise(values[1]))
        self._send_command(command)

    # Commands the telescope to slew to the provided azimuth/elevation
    # coordinates in degrees
    def goto_azel(self, az, el):
        self._goto_command('b', (az, el))

    # Commands the telescope to slew to the provided right ascension and
    # declination coordinates in degrees
    def goto_radec(self, ra, dec):
        self._goto_command('r', (ra, dec))

    # Informs the hand controller that the telescope is currently pointed at
    # the provided right ascension and declination coordinates to improve
    # accuracy of future goto commands. See command reference for details.
    def sync(self, ra, dec):
        self._goto_command('s', (ra, dec))

    # Returns the current tracking mode as an integer:
    # 0 = Off
    # 1 = Alt/Az (elevation/azimuth)
    # 2 = EQ North
    # 3 = EQ South
    def get_tracking_mode(self):
        response = self._send_command('t', 1)
        return ord(response[0])

    # Sets the tracking mode, 0-3, as a integer. See list in comments for
    # get_tracking_mode.
    def set_tracking_mode(self, mode):
        assert mode in [0,1,2,3]
        command = 'T' + chr(mode)
        self._send_command(command)

    # Generic variable-rate slew command. Variable-rate simply means that
    # the angular rate can be specified precisely in arcseconds per second,
    # in contrast to the small number of fixed rates available on the hand-
    # controller. Direction is either self.DIR_AZIMUTH or self.DIR_ELEVATION.
    # Rate has units of arcseconds per second and may be positive or negative.
    def _var_slew_command(self, direction, rate):
        assert direction in [self.DIR_AZIMUTH, self.DIR_ELEVATION]
        negative_rate = True if rate < 0 else False
        track_rate_high = (int(abs(rate)) * 4) / 256
        track_rate_low = (int(abs(rate)) * 4) % 256
        direction_char = chr(16) if direction == self.DIR_AZIMUTH else chr(17)
        sign_char = chr(7) if negative_rate == True else chr(6)
        command = ('P' + chr(3) + direction_char + sign_char
                  + chr(track_rate_high) + chr(track_rate_low) + chr(0)
                  + chr(0))
        self._send_command(command)

    # Commands the telescope to slew at the azimuth and elevation rates
    # provided in units of arcseconds per second. Rates may be positive or
    # negative. Max advertised rate is 3 deg/s, max commandable rate is 16319
    # arcseconds per second or ~4.5 deg/s.
    def slew_var(self, az_rate, el_rate):
       self._var_slew_command(self.DIR_AZIMUTH, az_rate)
       self._var_slew_command(self.DIR_ELEVATION, el_rate)

    # Generic fixed-rate slew command. Fixed-rate means that only the nine
    # rates supported on the hand controller are available. Direction is
    # either self.DIR_AZIMUTH or self.DIR_ELEVATION. Rate is an integer
    # from -9 to +9, where 0 is stop and +/-9 is the maximum slew rate.
    def _fixed_slew_command(self, direction, rate):
        negative_rate = True if rate < 0 else False
        sign_char = chr(37) if negative_rate == True else chr(36)
        direction_char = chr(16) if direction == self.DIR_AZIMUTH else chr(17)
        rate_char = chr(int(abs(rate)))
        command = ('P' + chr(2) + direction_char + sign_char + rate_char
                   + chr(0) + chr(0) + chr(0))
        self._send_command(command)

    # Commands the telescope to slew at the azimuth and elevation rates
    # provided as integers in the range -9 to +9, corresponding to the
    # rates available on the hand controller.
    def slew_fixed(self, az_rate, el_rate):
        assert (az_rate >= -9) and (az_rate <= 9), 'az_rate out of range'
        assert (el_rate >= -9) and (el_rate <= 9), 'el_rate out of range'
        self._fixed_slew_command(self.DIR_AZIMUTH, az_rate)
        self._fixed_slew_command(self.DIR_ELEVATION, el_rate)

    # Returns the location of the telescope as a tuple of (latitude,
    # longitude) in signed degrees format.
    def get_location(self):
        response = self._send_command('w', 8)
        lat_deg = ord(response[0])
        lat_min = ord(response[1])
        lat_sec = ord(response[2])
        lat_north = True if ord(response[3]) == 0 else False
        lat = lat_deg + lat_min / 60.0 + lat_sec / 3600.0
        if lat_north == False:
            lat = -lat
        lon_deg = ord(response[4])
        lon_min = ord(response[5])
        lon_sec = ord(response[6])
        lon_east = True if ord(response[7]) == 0 else False
        lon = lon_deg + lon_min / 60.0 + lon_sec / 3600.0
        if lon_east == False:
            lon = -lon
        return (lat, lon)

    # Set the location of the telescope with latitude and longitude coordinates
    # in signed degrees format.
    def set_location(self, lat, lon):
        lat_deg = int(abs(lat))
        lat_min = int((abs(lat) - lat_deg) * 60.0)
        lat_sec = int((abs(lat) - lat_deg - lat_min / 60.0) * 3600.0)
        lon_deg = int(abs(lon))
        lon_min = int((abs(lon) - lon_deg) * 60.0)
        lon_sec = int((abs(lon) - lon_deg - lon_min / 60.0) * 3600.0)
        command = ('W'
            + chr(lat_deg)
            + chr(lat_min)
            + chr(lat_sec)
            + chr(lat < 0)
            + chr(lon_deg)
            + chr(lon_min)
            + chr(lon_sec)
            + chr(lon < 0))
        self._send_command(command)

    # Returns the telescope current time in seconds since the Unix epoch
    # (1 Jan 1970). Timezone information and daylight savings time are not
    # currently supported.
    def get_time(self):
        response = self._send_command('h', 8)
        t = datetime.datetime(
            2000 + ord(response[5]), # year
            ord(response[3]),        # month
            ord(response[4]),        # day
            ord(response[0]),        # hour
            ord(response[1]),        # minute
            ord(response[2]),        # second
            0,                       # microseconds
        )
        return time.mktime(t.timetuple())

    # Set the time on the telescope. The timestamp argument is given in seconds
    # since the Unix epoch (1 Jan 1970). Timezone information and daylight
    # savings time are not currently supported, so the GMT/UTC offset will be
    # set to zero and Daylight Savings will be disabled (Standard Time).
    def set_time(self, timestamp):
        t = datetime.datetime.fromtimestamp(timestamp)
        command = ('H'
            + chr(t.hour)
            + chr(t.minute)
            + chr(t.second)
            + chr(t.month)
            + chr(t.day)
            + chr(t.year - 2000)
            + chr(0)
            + chr(0)
        )
        self._send_command(command)

    # Returns device version as a floating point value.
    def get_version(self):
        response = self._send_command('V', 2)
        return ord(response[0]) + ord(response[1]) / 10.0

    # Returns model as an integer. See NexStar command reference for decoding
    # table.
    def get_model(self):
        response = self._send_command('m', 1)
        return ord(response)

    # Sends a character to the telescope hand controller, which the hand
    # controller will echo back in response. The argument to the function
    # is an integer in the range 0 to 255. If the command is successful, the
    # return value will match the argument.
    def echo(self, x):
        command = 'K' + chr(x)
        response = self._send_command(command, 1)
        assert ord(response) == x, 'echo failed to return sent character'
        return ord(response)

    # Returns True if alignment has been performed, False otherwise.
    def alignment_complete(self):
        response = self._send_command('J', 1)
        return True if ord(response) == 1 else False

    # Returns True if the telescope is slewing to execute a goto command. Note
    # that this will return False if the telescope is slewing for any other
    # reason.
    def goto_in_progress(self):
        response = self._send_command('L', 1)
        return True if int(response) == 1 else False

    # Cancels a goto command that is in progress.
    def cancel_goto(self):
        self._send_command('M')

<|endoftext|>


<commit_before>#!/usr/bin/python3

import json
import platform
import subprocess
import traceback
import os
import argparse

#if any impacting changes to this plugin kindly increment the plugin version here.
PLUGIN_VERSION = "4"

#Setting this to true will alert you when there is a communication problem while posting plugin data to server
HEARTBEAT="true"

METRIC_UNITS = {
    "client_ip_address" : "ip",
    "mount_point" : "path",
    "disk_usage" : "%",
    "nfs_version" : "version",
    "shared_directory" : "path",
    "server_ip_address" : "ip"
}

ERROR_MSG=[]

MOUNT = ""

result = {}

def nfs_details (output):
    data = {}
    try:
        output = ' '.join(output.split())
        output = output.split(" ")
        output[5] = output[5].replace('%%1', '')
        output[5] = output[5].replace('%%0', '')
        server = output[0].split(":")
        data['server_ip_address'] = str(server[0])
        data['shared_directory'] = str(server[1])
        data['mount_point'] = str(output[5])
        data['disk_usage'] = int(output[4].replace('%', ''))

    except Exception as e:
        data['status'] = 0
        data['msg'] = str(e)

    return data

def mount_metrics (output):
    data = {}
    try:
        output = ' '.join(output.split())
        output = output.split(" ")
        for out in output:
            if "vers" in out and "clientaddr" in out:
                out = out.split(",")
                for each in out:
                    if "vers" in each:
                        each = each.split("=")
                        data['nfs_version'] = str(each[1])
                    if "clientaddr" in each:
                        each = each.split("=")
                        data['client_ip_address'] = str(each[1])
                    if each=="rw":
                        data['mount_permission'] = "read/write"
                    if each=="ro":
                        data['mount_permission'] = "read only"

    except Exception as e:
        data['status'] = 0
        data['msg'] = str(e)

    return data

def metricCollector():
    data = {}

    try:

        os.chmod("/opt/site24x7/monagent/plugins/nfs/nfs_check.sh", 0o775)
        proc = subprocess.Popen(['/opt/site24x7/monagent/plugins/nfs/nfs_check.sh ' + MOUNT], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
        top_output = proc.communicate()[0]
        top_output=top_output.strip()
        top_output=top_output.decode("utf-8")
        if "@@@@@@" in top_output:
            output = top_output.split("@@@@@@")
            top_output = output[1]
            output = output[0]
        if '%%' in top_output:
            data.update(nfs_details(top_output))
            data.update(mount_metrics(output))
        elif '-1' in top_output:
            data['status']=0
            data['msg']= MOUNT+" is unmounted"
        elif '-2' in top_output:
            data['status']=0
            data['msg']= MOUNT+" - NFS Server Host is not reachable"
    except Exception as e:
        data['status']=0
        data['msg']=str(e)

    return data

if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('--mount_folder', help="nfs mount point", type=str)

    args = parser.parse_args()
    if args.mount_folder:
        MOUNT = args.mount_folder

    result = metricCollector()

    result['plugin_version'] = PLUGIN_VERSION
    result['heartbeat_required']=HEARTBEAT
    result['units'] = METRIC_UNITS

    print(json.dumps(result, indent=4, sort_keys=True))
<commit_msg>Update nfs.py<commit_after>#!/usr/bin/python3

import json
import platform
import subprocess
import traceback
import os
import argparse

#if any impacting changes to this plugin kindly increment the plugin version here.
PLUGIN_VERSION = "1"

#Setting this to true will alert you when there is a communication problem while posting plugin data to server
HEARTBEAT="true"

METRIC_UNITS = {
    "client_ip_address" : "ip",
    "mount_point" : "path",
    "disk_usage" : "%",
    "nfs_version" : "version",
    "shared_directory" : "path",
    "server_ip_address" : "ip"
}

ERROR_MSG=[]

MOUNT = ""

result = {}

def nfs_details (output):
    data = {}
    try:
        output = ' '.join(output.split())
        output = output.split(" ")
        output[5] = output[5].replace('%%1', '')
        output[5] = output[5].replace('%%0', '')
        server = output[0].split(":")
        data['server_ip_address'] = str(server[0])
        data['shared_directory'] = str(server[1])
        data['mount_point'] = str(output[5])
        data['disk_usage'] = int(output[4].replace('%', ''))

    except Exception as e:
        data['status'] = 0
        data['msg'] = str(e)

    return data

def mount_metrics (output):
    data = {}
    try:
        output = ' '.join(output.split())
        output = output.split(" ")
        for out in output:
            if "vers" in out and "clientaddr" in out:
                out = out.split(",")
                for each in out:
                    if "vers" in each:
                        each = each.split("=")
                        data['nfs_version'] = str(each[1])
                    if "clientaddr" in each:
                        each = each.split("=")
                        data['client_ip_address'] = str(each[1])
                    if each=="rw":
                        data['mount_permission'] = "read/write"
                    if each=="ro":
                        data['mount_permission'] = "read only"

    except Exception as e:
        data['status'] = 0
        data['msg'] = str(e)

    return data

def metricCollector():
    data = {}

    try:

        os.chmod("/opt/site24x7/monagent/plugins/nfs/nfs_check.sh", 0o775)
        proc = subprocess.Popen(['/opt/site24x7/monagent/plugins/nfs/nfs_check.sh ' + MOUNT], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
        top_output = proc.communicate()[0]
        top_output=top_output.strip()
        top_output=top_output.decode("utf-8")
        if "@@@@@@" in top_output:
            output = top_output.split("@@@@@@")
            top_output = output[1]
            output = output[0]
        if '%%' in top_output:
            data.update(nfs_details(top_output))
            data.update(mount_metrics(output))
        elif '-1' in top_output:
            data['status']=0
            data['msg']= MOUNT+" is unmounted"
        elif '-2' in top_output:
            data['status']=0
            data['msg']= MOUNT+" - NFS Server Host is not reachable"
    except Exception as e:
        data['status']=0
        data['msg']=str(e)

    return data

if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('--mount_folder', help="nfs mount point", type=str)

    args = parser.parse_args()
    if args.mount_folder:
        MOUNT = args.mount_folder

    result = metricCollector()

    result['plugin_version'] = PLUGIN_VERSION
    result['heartbeat_required']=HEARTBEAT
    result['units'] = METRIC_UNITS

    print(json.dumps(result, indent=4, sort_keys=True))
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""

bump
----

An automated way to follow the Semantic Versioning Specification

"""

__title__ = 'bump'
__package_name__ = 'bump'
__author__ = 'Reuben Cummings'
__description__ = 'An automated way to follow the Semantic Versioning Specification'
__email__ = 'reubano@gmail.com'
__version__ = '1.0.0'
__license__ = 'MIT'
__copyright__ = 'Copyright 2014 Reuben Cummings'

import os
from fnmatch import fnmatch
from subprocess import call, check_output, CalledProcessError

def sh(cmd, output=False):
	if output:
		return check_output(cmd, shell=True)
	else:
		return call(cmd, shell=True) is 0

class Project(object):
	"""
	class representing a project object.
	"""

	def __init__(self, dir, **kwargs):
		"""
		Parameters
		----------
		dir : str
			the project directory
		"""
		self.current_tag = None
		self.bumped = False
		self.dir = dir

	@property
	def has_tag(self):
		# Check if repo has any git tags.
		if os.path.isdir(self.dir):
			return sh('cd %s; git tag' % (self.dir), True)
		else:
			raise Exception('%s is not a directory' % (self.dir))

	@property
	def versioned_files(self):
		# Get list of files with version metadata.
		cmd = "git ls-tree --full-tree --name-only -r HEAD"
		git_files = sh(cmd, True).splitlines()
		versioned_files = []
		file_names = [
			'pearfarm.spec', 'setup.cfg', 'setup.py', '*/__init__.py',
			'*.xml', 'package.json']

		for git_file in git_files:
			if any(fnmatch(git_file, file) for file in file_names):
				versioned_files.append(git_file)

		return versioned_files

	@property
	def version(self):
		# Get the current release version from git.
		if os.path.isdir(self.dir):
			cmd = 'cd %s; git tag | grep v' % (self.dir)
			versions = sh(cmd, True).splitlines()
			versions = [v.lstrip('v').rstrip() for v in versions]
			versions.sort(key=lambda s: map(int, s.split('.')))
			return versions[-1]
		else:
			raise Exception('%s is not a directory' % (self.dir))

	@property
	def fmt_version(self):
		# split the version into a list of ints.
		return map(int, self.version.split('.'))

	@property
	def is_clean(self):
		"""
		Returns
		-------
		boolean if there is a dirty index.
		"""
		return sh("cd %s; git diff --quiet" % self.dir)

	@property
	def is_dirty(self):
		"""
		Returns
		-------
		boolean if there is a dirty index.
		"""
		return not self.is_clean

	@property
	def dirty_files(self):
		"""
		Returns
		-------
		list of string names of the dirty files.
		"""
		files = sh("cd %s; git diff --minimal --numstat" % self.dir, True)
		return [x.split("\t")[-1] for x in files.splitlines()]

	def set_versions(self, new_version, pattern=None, i=0):
		try:
			file = self.versioned_files[i]
			i += 1
		except IndexError:
			return

		if not self.version:
			if pattern: # find lines in file containing pattern
				cmd = 'cd %s; grep -ine "%s" %s' % (self.dir, pattern, file)
			else: # get all lines in file
				cmd = 'cd %s; grep -ine "" %s' % (self.dir, file)

			try:
				lines = sh(cmd, True)
			except CalledProcessError:
				lines = None

			if lines:
				# escape double quotes
				escaped = lines.replace('"', '\\"')
				# find first line containing a version number
				cmd = 'echo "%s" | grep -m1 "[0-9]*\.[0-9]*\.[0-9]*"' % escaped
				try:
					rep_line = sh(cmd, True)
				except Exception:
					cmd = None
				else:
					rep_line_num = rep_line.split(':')[0]
					# replace with new version number
					sh("cd %s" % self.dir)
					cmd = ("sed -i '' '%ss/[0-9]*\.[0-9]*\.[0-9]*/%s/g' %s"
						% (rep_line_num, new_version, file))
			else:
				cmd = None
		else:
			# search for current version number and replace with new version
			# number
			cmd = ("cd %s; sed -i '' 's/%s/%s/g' %s"
				% (self.dir, self.version, new_version, file))

		sh(cmd) if cmd else None
		self.bumped = self.is_dirty
		return self.set_versions(new_version, pattern, i)

	def check_version(self, new_version):
			cmd = ("echo %s | sed 's/[0-9]*\.[0-9]*\.[0-9]*/@/g'"
				% new_version)
			return sh(cmd, True).splitlines()[0] is '@'

	def bump(self, bump_type):
		"""
		Parameters
		----------
		version_num: string version name.
		bump_type: version bump type. one of:
			m = major - [x].0.0
			n = minor - x.[y].0
			p = patch - x.y.[z]
		Returns
		-------
		concatenated string of the incremented version name.
		"""
		version = self.fmt_version

		try:
			switch = {
				'm': lambda: [version[0] + 1, 0, 0],
				'n': lambda: [version[0], version[1] + 1, 0],
				'p': lambda: [version[0], version[1], version[2] + 1]}
		except ValueError:
			raise Exception(
				'Invalid version: %i. Please use x.y.z format.' % self.version)
		else:
			return '.'.join(map(str, switch.get(bump_type)()))

class Git(object):
	"""
	class representing Git commands.
	"""
	def __init__(self, dir):
		"""
		Parameters
		----------
		dir: directory containing the git project
		"""
		self.dir = dir

	def add(self, files):
		files = ' '.join(files)
		return sh('cd %s; git add %s' % (self.dir, files))

	def commit(self, message):
		return sh("cd %s; git commit -m '%s'" % (self.dir, message))

	def tag(self, message, version):
		cmd = "cd %s; git tag -sm '%s' v%s" % (self.dir, message, version)
		return sh(cmd)

	def push(self):
		"""
		pushes current branch and tags to remote.
		"""
		# don't call --all here on purpose..
		return sh("cd %s; git push && git push --tags" % self.dir)
<commit_msg>Search for version in current git branch<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""

bump
----

An automated way to follow the Semantic Versioning Specification

"""

__title__ = 'bump'
__package_name__ = 'bump'
__author__ = 'Reuben Cummings'
__description__ = 'An automated way to follow the Semantic Versioning Specification'
__email__ = 'reubano@gmail.com'
__version__ = '1.0.0'
__license__ = 'MIT'
__copyright__ = 'Copyright 2014 Reuben Cummings'

import os
from fnmatch import fnmatch
from subprocess import call, check_output, CalledProcessError

def sh(cmd, output=False):
	if output:
		return check_output(cmd, shell=True)
	else:
		return call(cmd, shell=True) is 0

class Project(object):
	"""
	class representing a project object.
	"""

	def __init__(self, dir, **kwargs):
		"""
		Parameters
		----------
		dir : str
			the project directory
		"""
		self.current_tag = None
		self.bumped = False
		self.dir = dir

	@property
	def has_tag(self):
		# Check if repo has any git tags.
		if os.path.isdir(self.dir):
			return sh('cd %s; git tag' % (self.dir), True)
		else:
			raise Exception('%s is not a directory' % (self.dir))

	@property
	def versioned_files(self):
		# Get list of files with version metadata.
		cmd = "git ls-tree --full-tree --name-only -r HEAD"
		git_files = sh(cmd, True).splitlines()
		versioned_files = []
		file_names = [
			'pearfarm.spec', 'setup.cfg', 'setup.py', '*/__init__.py',
			'*.xml', 'package.json']

		for git_file in git_files:
			if any(fnmatch(git_file, file) for file in file_names):
				versioned_files.append(git_file)

		return versioned_files

	@property
	def version(self):
		# Get the current release version from git.
		if os.path.isdir(self.dir):
			cmd = 'cd %s; git describe --tags --abbrev=0' % (self.dir)
			return sh(cmd, True).lstrip('v').rstrip()
		else:
			raise Exception('%s is not a directory' % (self.dir))

	@property
	def fmt_version(self):
		# split the version into a list of ints.
		return map(int, self.version.split('.'))

	@property
	def is_clean(self):
		"""
		Returns
		-------
		boolean if there is a dirty index.
		"""
		return sh("cd %s; git diff --quiet" % self.dir)

	@property
	def is_dirty(self):
		"""
		Returns
		-------
		boolean if there is a dirty index.
		"""
		return not self.is_clean

	@property
	def dirty_files(self):
		"""
		Returns
		-------
		list of string names of the dirty files.
		"""
		files = sh("cd %s; git diff --minimal --numstat" % self.dir, True)
		return [x.split("\t")[-1] for x in files.splitlines()]

	def set_versions(self, new_version, pattern=None, i=0):
		try:
			file = self.versioned_files[i]
			i += 1
		except IndexError:
			return

		if not self.version:
			if pattern: # find lines in file containing pattern
				cmd = 'cd %s; grep -ine "%s" %s' % (self.dir, pattern, file)
			else: # get all lines in file
				cmd = 'cd %s; grep -ine "" %s' % (self.dir, file)

			try:
				lines = sh(cmd, True)
			except CalledProcessError:
				lines = None

			if lines:
				# escape double quotes
				escaped = lines.replace('"', '\\"')
				# find first line containing a version number
				cmd = 'echo "%s" | grep -m1 "[0-9]*\.[0-9]*\.[0-9]*"' % escaped
				try:
					rep_line = sh(cmd, True)
				except Exception:
					cmd = None
				else:
					rep_line_num = rep_line.split(':')[0]
					# replace with new version number
					sh("cd %s" % self.dir)
					cmd = ("sed -i '' '%ss/[0-9]*\.[0-9]*\.[0-9]*/%s/g' %s"
						% (rep_line_num, new_version, file))
			else:
				cmd = None
		else:
			# search for current version number and replace with new version
			# number
			cmd = ("cd %s; sed -i '' 's/%s/%s/g' %s"
				% (self.dir, self.version, new_version, file))

		sh(cmd) if cmd else None
		self.bumped = self.is_dirty
		return self.set_versions(new_version, pattern, i)

	def check_version(self, new_version):
			cmd = ("echo %s | sed 's/[0-9]*\.[0-9]*\.[0-9]*/@/g'"
				% new_version)
			return sh(cmd, True).splitlines()[0] is '@'

	def bump(self, bump_type):
		"""
		Parameters
		----------
		version_num: string version name.
		bump_type: version bump type. one of:
			m = major - [x].0.0
			n = minor - x.[y].0
			p = patch - x.y.[z]
		Returns
		-------
		concatenated string of the incremented version name.
		"""
		version = self.fmt_version

		try:
			switch = {
				'm': lambda: [version[0] + 1, 0, 0],
				'n': lambda: [version[0], version[1] + 1, 0],
				'p': lambda: [version[0], version[1], version[2] + 1]}
		except ValueError:
			raise Exception(
				'Invalid version: %i. Please use x.y.z format.' % self.version)
		else:
			return '.'.join(map(str, switch.get(bump_type)()))

class Git(object):
	"""
	class representing Git commands.
	"""
	def __init__(self, dir):
		"""
		Parameters
		----------
		dir: directory containing the git project
		"""
		self.dir = dir

	def add(self, files):
		files = ' '.join(files)
		return sh('cd %s; git add %s' % (self.dir, files))

	def commit(self, message):
		return sh("cd %s; git commit -m '%s'" % (self.dir, message))

	def tag(self, message, version):
		cmd = "cd %s; git tag -sm '%s' v%s" % (self.dir, message, version)
		return sh(cmd)

	def push(self):
		"""
		pushes current branch and tags to remote.
		"""
		# don't call --all here on purpose..
		return sh("cd %s; git push && git push --tags" % self.dir)
<|endoftext|>


<commit_before>from django.conf.urls import url

from .views import TeamView

urlpatterns = [
    url(r'^$', TeamView.as_view(), name="teams"),
    url(r'^(?P<team_id>\w+)$', TeamView.as_view(), name="get_team"),
]<commit_msg>feature(urls): fix team urls<commit_after>from django.conf.urls import url

from .views import TeamView

urlpatterns = [
    url(r'^/team$', TeamView.as_view(), name="teams"),
    url(r'^team/(?P<team_id>\w+)$', TeamView.as_view(), name="get_team"),
]<|endoftext|>


<commit_before>import os
import urllib

from google.appengine.api import users
from google.appengine.ext import ndb

from logging import info

import jinja2
import webapp2

import datetime

# model layer

DEFAULT_BUCKET_NAME = 'current_appointments'
ARCHIVE_BUCKET_NAME = 'archive_appointments'
BIT_BUCKET_NAME = 'delete_appointments'

# all entities under this root form the current list
def appointments_key(bucket_name=DEFAULT_BUCKET_NAME):
    return ndb.Key('Appointment', bucket_name)

# all entitties under this root form the archive
def apparchive_key(bucket_name=ARCHIVE_BUCKET_NAME):
    return ndb.Key('Appointment', bucket_name)

def bitbucket_key(bucket_name=BIT_BUCKET_NAME):
    return ndb.Key('Appointment', bucket_name)

class Comment(ndb.Model):
    uname = ndb.StringProperty()
    text = ndb.StringProperty()
    source = ndb.StringProperty()

class Appointment(ndb.Model):
    name = ndb.StringProperty(indexed=False)
    street = ndb.StringProperty(indexed=False)
    city = ndb.StringProperty(indexed=False)
    publictrans = ndb.StringProperty(indexed=False)
    source = ndb.StringProperty(indexed=False)
    entered = ndb.DateTimeProperty(auto_now_add=True)
    setdate = ndb.DateProperty()
    sortorder = ndb.IntegerProperty()
    comments = ndb.LocalStructuredProperty(Comment, repeated=True)
    removed = ndb.StringProperty()

class MailContact(ndb.Model):
    name = ndb.StringProperty()
    email = ndb.StringProperty()

class Nomad(ndb.Model):
    name = ndb.StringProperty()
    mail = ndb.StringProperty()
    moderator = ndb.BooleanProperty()

def clone_entity(e, **extra_args):
    klass = e.__class__
    props = dict((v._code_name, v.__get__(e, klass)) for v in klass._properties.itervalues() if type(v) is not ndb.ComputedProperty)
    props.update(extra_args)
    return klass(**props)

# utility & templates

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__) + '/templates'),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True)

def get_nomad():
    nuser = None
    guser = users.get_current_user()

    if guser:
        mail = guser.email().lower()
        q = Nomad.query(Nomad.mail == mail)
        nuserlis = q.fetch(1)
        if len(nuserlis) > 0:
            nuser = nuserlis[0]

    return nuser

# user format date
def fmt_date(dat):
    return dat.strftime("%d.%m.%Y")

JINJA_ENVIRONMENT.globals.update(fmt_date=fmt_date)

def next_tuesday():
    target = datetime.date.today()
    while target.isoweekday() <> 2:
        target = target + datetime.timedelta(1)
    return target

def previous_tuesday():
    target = datetime.date.today()
    while target.isoweekday() <> 2:
        target = target - datetime.timedelta(1)
    return target

# get a source string for reproduceabiltiy purposes
def generate_source(req):
    ip = req.remote_addr
    now = datetime.datetime.now().isoformat()
    uid = "None"
    if users.get_current_user():
        uid = users.get_current_user().user_id()

    return ip + "$" + now + "$" + uid

# http dispatching

class MainPage(webapp2.RequestHandler):
    def get(self):
        fixed_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate != None).order(Appointment.setdate)

        fixed_list = fixed_query.fetch(4)

        wait_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None).order(Appointment.sortorder)

        wait_list = wait_query.fetch()

        current_username = "not logged in"
        if users.get_current_user():
            current_username = users.get_current_user().nickname()

        loginout_text = "Login"
        loginout_url = users.create_login_url('/')

        if users.get_current_user():
            loginout_text = "Logout"
            loginout_url = users.create_logout_url('/')

        template_values = {
            'username': current_username,
            'fixed_apps': fixed_list,
            'wait_apps': wait_list,
            'loginout_url': loginout_url,
            'loginout_text': loginout_text, }

        nomad = get_nomad()
        if nomad and nomad.moderator:
            template_values['moderator'] = "yes"

        template = JINJA_ENVIRONMENT.get_template('index.html')
        self.response.write(template.render(template_values))

class Archive(webapp2.RequestHandler):
    def get(self):
        archive_query = Appointment.query(ancestor=apparchive_key()).order(Appointment.setdate)
        archive_list = archive_query.fetch()

        template_values = { 'archive_apps': archive_list }

        template = JINJA_ENVIRONMENT.get_template('archive.html')
        self.response.write(template.render(template_values))

class EnterPub(webapp2.RequestHandler):
    def post(self):
        app = Appointment(parent=appointments_key())

        app.name = self.request.get('name')
        app.street = self.request.get('street')
        app.city = self.request.get('city')
        app.publictrans = self.request.get('publictrans')

        app.source = generate_source(self.request)

        if self.request.get('magic') == '4':
            query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None).order(-Appointment.sortorder)

            sorder = 1

            applis = query.fetch(1)
            if len(applis) > 0:
                prev_app = applis[0]
                sorder = prev_app.sortorder + 1

            app.sortorder = sorder

            app.put()

            info("pub entered")

        self.redirect('/')

class CommentPub(webapp2.RequestHandler):
    def post(self):
        appid = self.request.get('id')
        uname = self.request.get('author')
        text = self.request.get('text')
        magic = self.request.get('magic')

        key = ndb.Key(urlsafe=appid)

        app = key.get()

        if app and magic == "4":
            com = Comment()
            com.uname = uname
            com.text = text

            com.source = generate_source(self.request)

            app.comments.append(com)

            app.put()

            info('comment entered on pub id={}'.format(appid))

        self.redirect('/')

class MoveForwardPub(webapp2.RequestHandler):
    def get(self):
        sortid = int(self.request.get('id'))
        query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None, Appointment.sortorder >= sortid - 1, Appointment.sortorder <= sortid).order(Appointment.sortorder)

        applis = query.fetch(2)

        if len(applis) > 1:
            app_a = applis[0]
            app_b = applis[1]

            app_a.sortorder = app_a.sortorder + 1
            app_b.sortorder = app_b.sortorder - 1

            app_a.put()
            app_b.put()

            info('pub moved forward id={}'.format(sortid))

        self.redirect('/')

class DeletePub(webapp2.RequestHandler):
    def get(self):
        nomad = get_nomad()

        if nomad.moderator:
            appid = self.request.get('id')
            app = ndb.Key(urlsafe=appid).get()

            if app:
                newapp = clone_entity(app, parent=bitbucket_key())
                newapp.removed = generate_source(self.request)
                newapp.put()
                app.key.delete()
                info("pub deleted key={}".format(appid))

        self.redirect('/')

class Moderator(webapp2.RequestHandler):
    def get(self):
        q = Nomad.query(Nomad.moderator == True)
        nomads = q.fetch(100)

        template_values = {
            'moderators': nomads,
        }

        template = JINJA_ENVIRONMENT.get_template('moderator.html')
        self.response.write(template.render(template_values))

class ModeratorAdd(webapp2.RequestHandler):
    def get(self):
        name = self.request.get('name')
        mail = self.request.get('mail')

        nomad = Nomad()
        nomad.name = name
        nomad.mail = mail
        nomad.moderator = True
        nomad.put()

        info("moderator created name = {}, mail = {}".format(name, mail))

        self.redirect('/moderator')

class ModeratorDelete(webapp2.RequestHandler):
    def get(self):
        pass

# woechentlicher cronjob
class SchedulePubs(webapp2.RequestHandler):
    def get(self):

        # wir haben drei gruppen

        # die fertig geplanten, feststehenden termine
        archive_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate < datetime.date.today(), Appointment.setdate != None)

        archive_list = archive_query.fetch()

        for app in archive_list:
            newapp = clone_entity(app, parent=apparchive_key())
            newapp.source = None
            newapp.put()

            app.key.delete()

        # die aktuellen, also schon geplanten
        current_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate > datetime.date.today())

        current_list = current_query.fetch()

        current_apps = len(current_list)

        last_date = previous_tuesday()
        for app in current_list:
            if app.setdate > last_date:
                last_date = app.setdate

        # die einzufuegenden, die wir aus der warteliste ziehen
        need_apps = 4 - current_apps

        if need_apps > 0:
            next_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None)

            next_list = next_query.fetch(need_apps)

            for app in next_list:
                last_date = last_date + datetime.timedelta(7)
                app.setdate = last_date
                app.put()

app = webapp2.WSGIApplication([
    ('/', MainPage),
    ('/enterPub', EnterPub),
    ('/schedulePubs', SchedulePubs),
    ('/moveForward', MoveForwardPub),
    ('/delete', DeletePub),
    ('/comment', CommentPub),
    ('/archive', Archive),
    ('/moderator', Moderator),
    ('/moderatorAdd', ModeratorAdd),
    ('/moderatorDel', ModeratorDelete),
], debug=True)
<commit_msg>fix #5 remove source from comments<commit_after>import os
import urllib

from google.appengine.api import users
from google.appengine.ext import ndb

from logging import info

import jinja2
import webapp2

import datetime

# model layer

DEFAULT_BUCKET_NAME = 'current_appointments'
ARCHIVE_BUCKET_NAME = 'archive_appointments'
BIT_BUCKET_NAME = 'delete_appointments'

# all entities under this root form the current list
def appointments_key(bucket_name=DEFAULT_BUCKET_NAME):
    return ndb.Key('Appointment', bucket_name)

# all entitties under this root form the archive
def apparchive_key(bucket_name=ARCHIVE_BUCKET_NAME):
    return ndb.Key('Appointment', bucket_name)

def bitbucket_key(bucket_name=BIT_BUCKET_NAME):
    return ndb.Key('Appointment', bucket_name)

class Comment(ndb.Model):
    uname = ndb.StringProperty()
    text = ndb.StringProperty()
    source = ndb.StringProperty()

class Appointment(ndb.Model):
    name = ndb.StringProperty(indexed=False)
    street = ndb.StringProperty(indexed=False)
    city = ndb.StringProperty(indexed=False)
    publictrans = ndb.StringProperty(indexed=False)
    source = ndb.StringProperty(indexed=False)
    entered = ndb.DateTimeProperty(auto_now_add=True)
    setdate = ndb.DateProperty()
    sortorder = ndb.IntegerProperty()
    comments = ndb.LocalStructuredProperty(Comment, repeated=True)
    removed = ndb.StringProperty()

class MailContact(ndb.Model):
    name = ndb.StringProperty()
    email = ndb.StringProperty()

class Nomad(ndb.Model):
    name = ndb.StringProperty()
    mail = ndb.StringProperty()
    moderator = ndb.BooleanProperty()

def clone_entity(e, **extra_args):
    klass = e.__class__
    props = dict((v._code_name, v.__get__(e, klass)) for v in klass._properties.itervalues() if type(v) is not ndb.ComputedProperty)
    props.update(extra_args)
    return klass(**props)

# utility & templates

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__) + '/templates'),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True)

def get_nomad():
    nuser = None
    guser = users.get_current_user()

    if guser:
        mail = guser.email().lower()
        q = Nomad.query(Nomad.mail == mail)
        nuserlis = q.fetch(1)
        if len(nuserlis) > 0:
            nuser = nuserlis[0]

    return nuser

# user format date
def fmt_date(dat):
    return dat.strftime("%d.%m.%Y")

JINJA_ENVIRONMENT.globals.update(fmt_date=fmt_date)

def next_tuesday():
    target = datetime.date.today()
    while target.isoweekday() <> 2:
        target = target + datetime.timedelta(1)
    return target

def previous_tuesday():
    target = datetime.date.today()
    while target.isoweekday() <> 2:
        target = target - datetime.timedelta(1)
    return target

# get a source string for reproduceabiltiy purposes
def generate_source(req):
    ip = req.remote_addr
    now = datetime.datetime.now().isoformat()
    uid = "None"
    if users.get_current_user():
        uid = users.get_current_user().user_id()

    return ip + "$" + now + "$" + uid

# http dispatching

class MainPage(webapp2.RequestHandler):
    def get(self):
        fixed_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate != None).order(Appointment.setdate)

        fixed_list = fixed_query.fetch(4)

        wait_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None).order(Appointment.sortorder)

        wait_list = wait_query.fetch()

        current_username = "not logged in"
        if users.get_current_user():
            current_username = users.get_current_user().nickname()

        loginout_text = "Login"
        loginout_url = users.create_login_url('/')

        if users.get_current_user():
            loginout_text = "Logout"
            loginout_url = users.create_logout_url('/')

        template_values = {
            'username': current_username,
            'fixed_apps': fixed_list,
            'wait_apps': wait_list,
            'loginout_url': loginout_url,
            'loginout_text': loginout_text, }

        nomad = get_nomad()
        if nomad and nomad.moderator:
            template_values['moderator'] = "yes"

        template = JINJA_ENVIRONMENT.get_template('index.html')
        self.response.write(template.render(template_values))

class Archive(webapp2.RequestHandler):
    def get(self):
        archive_query = Appointment.query(ancestor=apparchive_key()).order(Appointment.setdate)
        archive_list = archive_query.fetch()

        template_values = { 'archive_apps': archive_list }

        template = JINJA_ENVIRONMENT.get_template('archive.html')
        self.response.write(template.render(template_values))

class EnterPub(webapp2.RequestHandler):
    def post(self):
        app = Appointment(parent=appointments_key())

        app.name = self.request.get('name')
        app.street = self.request.get('street')
        app.city = self.request.get('city')
        app.publictrans = self.request.get('publictrans')

        app.source = generate_source(self.request)

        if self.request.get('magic') == '4':
            query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None).order(-Appointment.sortorder)

            sorder = 1

            applis = query.fetch(1)
            if len(applis) > 0:
                prev_app = applis[0]
                sorder = prev_app.sortorder + 1

            app.sortorder = sorder

            app.put()

            info("pub entered")

        self.redirect('/')

class CommentPub(webapp2.RequestHandler):
    def post(self):
        appid = self.request.get('id')
        uname = self.request.get('author')
        text = self.request.get('text')
        magic = self.request.get('magic')

        key = ndb.Key(urlsafe=appid)

        app = key.get()

        if app and magic == "4":
            com = Comment()
            com.uname = uname
            com.text = text

            com.source = generate_source(self.request)

            app.comments.append(com)

            app.put()

            info('comment entered on pub id={}'.format(appid))

        self.redirect('/')

class MoveForwardPub(webapp2.RequestHandler):
    def get(self):
        sortid = int(self.request.get('id'))
        query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None, Appointment.sortorder >= sortid - 1, Appointment.sortorder <= sortid).order(Appointment.sortorder)

        applis = query.fetch(2)

        if len(applis) > 1:
            app_a = applis[0]
            app_b = applis[1]

            app_a.sortorder = app_a.sortorder + 1
            app_b.sortorder = app_b.sortorder - 1

            app_a.put()
            app_b.put()

            info('pub moved forward id={}'.format(sortid))

        self.redirect('/')

class DeletePub(webapp2.RequestHandler):
    def get(self):
        nomad = get_nomad()

        if nomad.moderator:
            appid = self.request.get('id')
            app = ndb.Key(urlsafe=appid).get()

            if app:
                newapp = clone_entity(app, parent=bitbucket_key())
                newapp.removed = generate_source(self.request)
                newapp.put()
                app.key.delete()
                info("pub deleted key={}".format(appid))

        self.redirect('/')

class Moderator(webapp2.RequestHandler):
    def get(self):
        q = Nomad.query(Nomad.moderator == True)
        nomads = q.fetch(100)

        template_values = {
            'moderators': nomads,
        }

        template = JINJA_ENVIRONMENT.get_template('moderator.html')
        self.response.write(template.render(template_values))

class ModeratorAdd(webapp2.RequestHandler):
    def get(self):
        name = self.request.get('name')
        mail = self.request.get('mail')

        nomad = Nomad()
        nomad.name = name
        nomad.mail = mail
        nomad.moderator = True
        nomad.put()

        info("moderator created name = {}, mail = {}".format(name, mail))

        self.redirect('/moderator')

class ModeratorDelete(webapp2.RequestHandler):
    def get(self):
        pass

# woechentlicher cronjob
class SchedulePubs(webapp2.RequestHandler):
    def get(self):

        # wir haben drei gruppen

        # die fertig geplanten, feststehenden termine
        archive_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate < datetime.date.today(), Appointment.setdate != None)

        archive_list = archive_query.fetch()

        for app in archive_list:
            newapp = clone_entity(app, parent=apparchive_key())
            for com in newapp.comments:
                com.source = None
            newapp.source = None
            newapp.put()

            app.key.delete()

        # die aktuellen, also schon geplanten
        current_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate > datetime.date.today())

        current_list = current_query.fetch()

        current_apps = len(current_list)

        last_date = previous_tuesday()
        for app in current_list:
            if app.setdate > last_date:
                last_date = app.setdate

        # die einzufuegenden, die wir aus der warteliste ziehen
        need_apps = 4 - current_apps

        if need_apps > 0:
            next_query = Appointment.query(ancestor=appointments_key()).filter(Appointment.setdate == None)

            next_list = next_query.fetch(need_apps)

            for app in next_list:
                last_date = last_date + datetime.timedelta(7)
                app.setdate = last_date
                app.put()

app = webapp2.WSGIApplication([
    ('/', MainPage),
    ('/enterPub', EnterPub),
    ('/schedulePubs', SchedulePubs),
    ('/moveForward', MoveForwardPub),
    ('/delete', DeletePub),
    ('/comment', CommentPub),
    ('/archive', Archive),
    ('/moderator', Moderator),
    ('/moderatorAdd', ModeratorAdd),
    ('/moderatorDel', ModeratorDelete),
], debug=True)
<|endoftext|>