#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2015             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk 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 in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# tails. You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.


# 508 and 604 have the same mib
janitza_umg_device_map = {
    ".1.3.6.1.4.1.34278.8.6"  : "96",
    ".1.3.6.1.4.1.34278.10.1" : "604",
    ".1.3.6.1.4.1.34278.10.4" : "508",
}


def parse_janitza_umg_inphase(info):
    def flatten(line):
        return [x[0] for x in line]

    dev_type = janitza_umg_device_map[info[0][0][0]]

    info_offsets = {
        "508" : {
            "energy":    4,
            "sumenergy": 5,
            "misc":      8,
        },
        "604" : {
            "energy":    4,
            "sumenergy": 5,
            "misc":      8,
        },
        "96"  : {
            "energy":    3,
            "sumenergy": 4,
            "misc":      6,
        }
    }[dev_type]

    rmsphase  = flatten(info[1])
    sumphase  = flatten(info[2])
    energy    = flatten(info[info_offsets["energy"]])
    sumenergy = flatten(info[info_offsets["sumenergy"]])

    if dev_type in ["508", "604"]:
        num_phases = 4
        num_currents = 4
    elif dev_type == "96":
        num_phases = 3
        num_currents = 6

    num_deltas = 3

    # the number of elements in each "block" within the snmp. This differs between
    # devices
    counts = [
        num_phases,   # voltages
        3,            # L1-L2, L2-L3, L3-L1
        num_currents, # umg96 reports voltage for 3 phases and current for 6
        num_phases,   # real power
        num_phases,   # reactive power
        num_phases,   # Power in VA
        num_phases,   # Cos(Phi)
    ]

    def offset(block_id, phase):
        return sum(counts[:block_id], phase)

    # voltages are in 100mv, currents in 1mA, power in Watts / VA
    result = {}

    for phase in range(num_phases):
        result["Phase %d" % (phase + 1)] = {
            "voltage": int(rmsphase[offset(0, phase)]) / 10.0,
            "current": int(rmsphase[offset(2, phase)]) / 1000.0,
            "power"  : int(rmsphase[offset(3, phase)]),
            "appower": int(rmsphase[offset(5, phase)]),
            "energy" : int(energy  [phase]) / 10,
        }

    result["Total"] = {
        "power" : int(sumphase[0]),
        "energy": int(sumenergy[0])
    }

    misc = flatten(info[info_offsets["misc"]])
    result["Frequency"] = int(misc[0])
    # temperature not present in UMG508 and UMG604
    if len(misc) > 1:
        result["Temperature"] = map(int, misc[1:])
    else:
        result["Temperature"] = []
    return result


def inventory_janitza_umg_inphase(parsed):
    for item in parsed.keys():
        if item.startswith("Phase"):
            yield item, {}


check_info['janitza_umg'] = {
    'parse_function'            : parse_janitza_umg_inphase,
    'inventory_function'        : inventory_janitza_umg_inphase,
    'check_function'            : check_elphase,
    'service_description'       : 'Input %s',
    'has_perfdata'              : True,
    'default_levels_variable'   : 'janitza_umg_inphase_default_levels',
    'includes'                  : [ "elphase.include", ],
    'group'                     : 'el_inphase',
    'snmp_info'                 : [
                                    (".1.3.6.1.2.1.1.2",   [ "0" ]), # device id
                                    (".1.3.6.1.4.1.34278", [ "1" ]), # rmsPhase
                                    (".1.3.6.1.4.1.34278", [ "2" ]), # rmsSum
                                    (".1.3.6.1.4.1.34278", [ "3" ]), # device dependent
                                    (".1.3.6.1.4.1.34278", [ "4" ]), #       "
                                    (".1.3.6.1.4.1.34278", [ "5" ]), #       "
                                    (".1.3.6.1.4.1.34278", [ "6" ]), #       "
                                    (".1.3.6.1.4.1.34278", [ "7" ]), #       "
                                    (".1.3.6.1.4.1.34278", [ "8" ]), #       "
                                  ],
    'snmp_scan_function'        : lambda oid: oid(".1.3.6.1.2.1.1.2.0") in
                                                janitza_umg_device_map.keys()
}


def inventory_janitza_umg_freq(parsed):
    # info[0] is frequency, info[1] is first temperature reading, info[2] is second.
    if "Frequency" in parsed:
        yield "1", {}


def check_janitza_umg_freq(item, params, parsed):
    warn, crit = params.get("levels", (0, 0))

    if "Frequency" in parsed:
        reading = float(parsed["Frequency"]) / 100.0
        perfdata = [ ( "in_freq", reading, warn, crit ) ]

        infotext = "Frequency: %.2f Hz" % reading
        levelstext = "(warn/crit at %d/%d Hz)" % (warn, crit)

        if reading <= crit:
            return 2, infotext + " " + levelstext, perfdata
        elif reading <= warn:
            return 1, infotext + " " + levelstext, perfdata
        else:
            return 0, infotext, perfdata


check_info['janitza_umg.freq'] = {
    'inventory_function'      : inventory_janitza_umg_freq,
    'check_function'          : check_janitza_umg_freq,
    'service_description'     : 'Frequency %s',
    'has_perfdata'            : True,
    'default_levels_variable' : 'janitza_umg_freq_default_levels',
    'group'                   : 'efreq',
}


def inventory_janitza_umg_temp(parsed):
    ctr = 1
    for temp in parsed["Temperature"]:
        if temp != -1000:
            yield str(ctr), {}
        ctr += 1


def check_janitza_umg_temp(item, params, parsed):
    idx = int(item) - 1
    if len(parsed["Temperature"]) > idx:
        return check_temperature(float(parsed["Temperature"][idx]) / 10.0, params,
                                 "janitza_umg_%s" % item)


check_info['janitza_umg.temp'] = {
    'inventory_function'      : inventory_janitza_umg_temp,
    'check_function'          : check_janitza_umg_temp,
    'service_description'     : 'Temperature External %s',
    'has_perfdata'            : True,
    'default_levels_variable' : 'janitza_umg_temp_default_levels',
    'includes'                : [ "temperature.include", ],
    'group'                   : 'temperature',
}

