diff --git a/agent_based/cisco_asyncos_bandwidth.py b/agent_based/cisco_asyncos_bandwidth.py
index 0b6374cafb9afc66bdad0b275243960c6392ad45..6fdcc67b92e5f4e6c3d7837e3cf0b8d5e77f0bf0 100644
--- a/agent_based/cisco_asyncos_bandwidth.py
+++ b/agent_based/cisco_asyncos_bandwidth.py
@@ -51,16 +51,32 @@ def discovery_cisco_asyncos_bandwidth(section: CiscoAsyncosBandwidth) -> Discove
 
 def check_cisco_asyncos_bandwidth(params, section: CiscoAsyncosBandwidth) -> CheckResult:
     yield from check_levels(
-        section.bandwidth_now,
+        section.bandwidth_now * 8,
         label='Current bandwidth',
         levels_upper=params.get('upper', None),
         levels_lower=params.get('lower', None),
         metric_name='bandwith_now',
+        render_func=render.networkbandwidth,
+        unit='bits/s'
+    )
+    yield from check_levels(
+        section.bandwidth_hour * 8,
+        label='last hour',
+        # levels_upper=params.get('upper', None),
+        # levels_lower=params.get('lower', None),
+        # metric_name='bandwith_now',
+        render_func=render.networkbandwidth
+    )
+    yield from check_levels(
+        section.bandwidth_day * 8,
+        label='last day',
+        #levels_upper=params.get('upper', None),
+        #levels_lower=params.get('lower', None),
+        #metric_name='bandwith_now',
         render_func=render.networkbandwidth
     )
 
-    yield Result(state=State.OK,
-                 summary='last hour: %s, last day: %s' % (section.bandwidth_hour, section.bandwidth_day))
+    # yield Result(state=State.OK, summary='last hour: %s, last day: %s' % (section.bandwidth_hour, section.bandwidth_day))
 
 
 register.snmp_section(
diff --git a/agent_based/cisco_asyncos_license.py b/agent_based/cisco_asyncos_license.py
index 3d8bc5aa8e55fc35df297b971a87eebd36e68bea..91f8e4205468cc5e6d00cdd44d3930e08c4e7338 100644
--- a/agent_based/cisco_asyncos_license.py
+++ b/agent_based/cisco_asyncos_license.py
@@ -185,6 +185,7 @@ def parse_cisco_asyncos_license(string_table: List[StringTable]) -> Mapping[str,
 def discovery_cisco_asyncos_license(section: Mapping[str, CiscoAsyncosLicense]) -> DiscoveryResult:
     yield Service()
 
+
 # Parameters({'expire': (400, 360), 'features_ignore': ['Data Loss Prevention']})
 def check_cisco_asyncos_license(params, section: Mapping[str, CiscoAsyncosLicense]) -> CheckResult:
     features_ignore = params.get('features_ignore', [])
@@ -194,10 +195,11 @@ def check_cisco_asyncos_license(params, section: Mapping[str, CiscoAsyncosLicens
         if section[license].perpetual:
             yield Result(state=State.OK, notice='%s is perpetual (will not expire)' % license)
         elif license in features_ignore:
-            yield Result(state=State.OK, notice='%s will expire at %s (%s days). Feature ignored!' % (license, section[license].expiredate, section[license].daysuntilexpire))
+            yield Result(state=State.OK, notice='%s will expire at %s (%s days). Feature ignored!' % (
+            license, section[license].expiredate, section[license].daysuntilexpire))
             ignore_count += 1
         elif section[license].secondsuntilexpire == 0:
-            yield  Result(state=State.CRIT, notice='%s has expired or is not licensed' % license)
+            yield Result(state=State.CRIT, notice='%s has expired or is not licensed' % license)
         else:
             if section[license].daysuntilexpire < crit:
                 state = State.CRIT
@@ -206,10 +208,12 @@ def check_cisco_asyncos_license(params, section: Mapping[str, CiscoAsyncosLicens
             else:
                 state = State.OK
 
-            yield Result(state=state, notice='%s will expire at %s (%s days)' % (license, section[license].expiredate, section[license].daysuntilexpire))
+            yield Result(state=state, notice='%s will expire at %s (%s days)' % (
+            license, section[license].expiredate, section[license].daysuntilexpire))
 
     yield Result(state=State.OK, summary='%d/%d Features found/ignored' % (len(section.keys()), ignore_count))
 
+
 register.snmp_section(
     name='cisco_asyncos_license',
     parse_function=parse_cisco_asyncos_license,
diff --git a/agent_based/cisco_asyncos_update.py b/agent_based/cisco_asyncos_update.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e18099e4a3eefa9410170b9867c9c7661f6002c
--- /dev/null
+++ b/agent_based/cisco_asyncos_update.py
@@ -0,0 +1,312 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# License: GNU General Public License v2
+#
+# Author: thl-cmk[at]outlook[dot]com
+# URL   : https://thl-cmk.hopto.org
+# Date  : 2020-02-19
+#
+# 2020-05-14: added wato oprion to ignore items
+# 2021-03-25: rewrite for CMK2.0
+#
+#
+# sample snmpwalk
+#
+# OMD[cmk16x]:~$ snmpwalk -v2c -c public -m ASYNCOS-MAIL-MIB -ObentU localhost updateEntry
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.1 = INTEGER: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.2 = INTEGER: 2
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.3 = INTEGER: 3
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.4 = INTEGER: 4
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.5 = INTEGER: 5
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.6 = INTEGER: 6
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.7 = INTEGER: 7
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.8 = INTEGER: 8
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.9 = INTEGER: 9
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.10 = INTEGER: 10
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.11 = INTEGER: 11
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.12 = INTEGER: 12
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.13 = INTEGER: 13
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.14 = INTEGER: 14
+# .1.3.6.1.4.1.15497.1.1.1.13.1.1.15 = INTEGER: 15
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.1 = STRING: File Reputation
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.2 = STRING: IronPort Anti-Spam
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.3 = STRING: McAfee
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.4 = STRING: Sophos Anti-Virus
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.5 = STRING: amp
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.6 = STRING: content_scanner
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.7 = STRING: enrollment_client
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.8 = STRING: geo_countries
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.9 = STRING: howto
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.10 = STRING: openssh_key
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.11 = STRING: repeng
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.12 = STRING: sdr_client
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.13 = STRING: smart_agent
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.14 = STRING: support_request
+# .1.3.6.1.4.1.15497.1.1.1.13.1.2.15 = STRING: timezones
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.1 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.2 = Counter32: 10
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.3 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.4 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.5 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.6 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.7 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.8 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.9 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.10 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.11 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.12 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.13 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.14 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.3.15 = Counter32: 1
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.1 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.2 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.3 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.4 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.5 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.6 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.7 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.8 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.9 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.10 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.11 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.12 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.13 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.14 = Counter32: 0
+# .1.3.6.1.4.1.15497.1.1.1.13.1.4.15 = Counter32: 0
+#
+# OMD[cmk16x]:~$ snmpwalk -v2c -c public -m ASYNCOS-MAIL-MIB localhost updateEntry
+# ASYNCOS-MAIL-MIB::updateIndex.1 = INTEGER: 1
+# ASYNCOS-MAIL-MIB::updateIndex.2 = INTEGER: 2
+# ASYNCOS-MAIL-MIB::updateIndex.3 = INTEGER: 3
+# ASYNCOS-MAIL-MIB::updateIndex.4 = INTEGER: 4
+# ASYNCOS-MAIL-MIB::updateIndex.5 = INTEGER: 5
+# ASYNCOS-MAIL-MIB::updateIndex.6 = INTEGER: 6
+# ASYNCOS-MAIL-MIB::updateIndex.7 = INTEGER: 7
+# ASYNCOS-MAIL-MIB::updateIndex.8 = INTEGER: 8
+# ASYNCOS-MAIL-MIB::updateIndex.9 = INTEGER: 9
+# ASYNCOS-MAIL-MIB::updateIndex.10 = INTEGER: 10
+# ASYNCOS-MAIL-MIB::updateIndex.11 = INTEGER: 11
+# ASYNCOS-MAIL-MIB::updateIndex.12 = INTEGER: 12
+# ASYNCOS-MAIL-MIB::updateIndex.13 = INTEGER: 13
+# ASYNCOS-MAIL-MIB::updateIndex.14 = INTEGER: 14
+# ASYNCOS-MAIL-MIB::updateIndex.15 = INTEGER: 15
+# ASYNCOS-MAIL-MIB::updateServiceName.1 = STRING: File Reputation
+# ASYNCOS-MAIL-MIB::updateServiceName.2 = STRING: IronPort Anti-Spam
+# ASYNCOS-MAIL-MIB::updateServiceName.3 = STRING: McAfee
+# ASYNCOS-MAIL-MIB::updateServiceName.4 = STRING: Sophos Anti-Virus
+# ASYNCOS-MAIL-MIB::updateServiceName.5 = STRING: amp
+# ASYNCOS-MAIL-MIB::updateServiceName.6 = STRING: content_scanner
+# ASYNCOS-MAIL-MIB::updateServiceName.7 = STRING: enrollment_client
+# ASYNCOS-MAIL-MIB::updateServiceName.8 = STRING: geo_countries
+# ASYNCOS-MAIL-MIB::updateServiceName.9 = STRING: howto
+# ASYNCOS-MAIL-MIB::updateServiceName.10 = STRING: openssh_key
+# ASYNCOS-MAIL-MIB::updateServiceName.11 = STRING: repeng
+# ASYNCOS-MAIL-MIB::updateServiceName.12 = STRING: sdr_client
+# ASYNCOS-MAIL-MIB::updateServiceName.13 = STRING: smart_agent
+# ASYNCOS-MAIL-MIB::updateServiceName.14 = STRING: support_request
+# ASYNCOS-MAIL-MIB::updateServiceName.15 = STRING: timezones
+# ASYNCOS-MAIL-MIB::updates.1 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.2 = Counter32: 10
+# ASYNCOS-MAIL-MIB::updates.3 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.4 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.5 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.6 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.7 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.8 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.9 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updates.10 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updates.11 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updates.12 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updates.13 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updates.14 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updates.15 = Counter32: 1
+# ASYNCOS-MAIL-MIB::updateFailures.1 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.2 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.3 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.4 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.5 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.6 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.7 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.8 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.9 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.10 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.11 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.12 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.13 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.14 = Counter32: 0
+# ASYNCOS-MAIL-MIB::updateFailures.15 = Counter32: 0
+#
+from typing import Mapping, List, NamedTuple
+
+from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import (
+    DiscoveryResult,
+    CheckResult,
+    StringTable,
+)
+
+from cmk.base.plugins.agent_based.agent_based_api.v1 import (
+    register,
+    Service,
+    check_levels,
+    Result,
+    SNMPTree,
+    contains,
+    State,
+    render,
+)
+
+
+class CiscoAsyncosUpdate(NamedTuple):
+    updates: int
+    updatefailures: int
+
+# [[
+#   ['File Reputation', '6', '38'],
+#   ['IronPort Anti-Spam', '12', '9'],
+#   ['McAfee', '6', '25'],
+#   ['Sophos Anti-Virus', '6', '17'],
+#   ['amp', '1', '0'],
+#   ['content_scanner', '1', '0'],
+#   ['enrollment_client', '1', '0'],
+#   ['geo_countries', '1', '0'],
+#   ['howto', '0', '0'],
+#   ['openssh_key', '0', '0'],
+#   ['repeng', '0', '0'],
+#   ['sdr_client', '0', '0'],
+#   ['smart_agent', '0', '0'],
+#   ['support_request', '1', '0'],
+#   ['timezones', '1', '0']
+# ]]
+def parse_cisco_asyncos_update(string_table: List[StringTable]) -> Mapping[str, CiscoAsyncosUpdate]:
+    features = {}
+    for feature, updates, update_failures in string_table[0]:
+        features.update({feature: CiscoAsyncosUpdate(
+            updates=int(updates),
+            updatefailures=int(update_failures)
+        ) })
+    return features
+
+# {
+#  'File Reputation': CiscoAsyncosUpdate(updates=6, updatefailures=38),
+#  'IronPort Anti-Spam': CiscoAsyncosUpdate(updates=12, updatefailures=9),
+#  'McAfee': CiscoAsyncosUpdate(updates=6, updatefailures=25),
+#  'Sophos Anti-Virus': CiscoAsyncosUpdate(updates=6, updatefailures=17),
+#  'amp': CiscoAsyncosUpdate(updates=1, updatefailures=0),
+#  'content_scanner': CiscoAsyncosUpdate(updates=1, updatefailures=0),
+#  'enrollment_client': CiscoAsyncosUpdate(updates=1, updatefailures=0),
+#  'geo_countries': CiscoAsyncosUpdate(updates=1, updatefailures=0),
+#  'howto': CiscoAsyncosUpdate(updates=0, updatefailures=0),
+#  'openssh_key': CiscoAsyncosUpdate(updates=0, updatefailures=0),
+#  'repeng': CiscoAsyncosUpdate(updates=0, updatefailures=0),
+#  'sdr_client': CiscoAsyncosUpdate(updates=0, updatefailures=0),
+#  'smart_agent': CiscoAsyncosUpdate(updates=0, updatefailures=0),
+#  'support_request': CiscoAsyncosUpdate(updates=1, updatefailures=0),
+#  'timezones': CiscoAsyncosUpdate(updates=1, updatefailures=0)
+# }
+def discovery_cisco_asyncos_update(section:Mapping[str, CiscoAsyncosUpdate])-> DiscoveryResult:
+    yield Service()
+
+def check_cisco_asyncos_update(params, section:Mapping[str, CiscoAsyncosUpdate]) -> CheckResult:
+    features_ignore = params.get('features_ignore', [])
+    warn, crit = params.get('failedLevel')
+    ignore_count = 0
+    for feature in section.keys():
+        if feature in features_ignore:
+            yield Result(state=State.OK, notice='Feature %s: %d/%d updates/update failures. Feature ignored!' % (feature, section[feature].updates, section[feature].updatefailures))
+            ignore_count += 1
+        else:
+            yield Result(state=State.OK, notice='Feature %s: %d/%d updates/update failures. Feature ignored!' % (feature, section[feature].updates, section[feature].updatefailures))
+
+    yield Result(state=State.OK, summary='%d/%d Features found/ignored' % (len(section.keys()), ignore_count))
+
+    # if len(info) > 0:
+    #     infotext = ''
+    #     longoutput = ''
+    #     perfdata = []
+    #     failedItemsWarn = []
+    #     failedItemsCrit = []
+    #     failedWarn, failedCrit = params.get('failedLevel')
+    #     features_ignore = params['features_ignore']
+    #     lastState = 1
+    #
+    #     for line in info:
+    #         name, passed, failed = line
+    #         longoutput += '\n%s: %s/%s passed/failed attempt(s)' % (name, passed, failed)
+    #         # read counters
+    #         passedLast = get_item_state('cisco_asyncos_update_%s_passedLast' % name)
+    #         failedLast = get_item_state('cisco_asyncos_update_%s_failedLast' % name)
+    #         failedAttempts = get_item_state('cisco_asyncos_update_%s_failedAttempts' % name)
+    #
+    #         if (passedLast == None) or (failedLast == None) or (failedAttempts == None):  # or (lastState == None):
+    #             # init counters
+    #             set_item_state('cisco_asyncos_update_%s_passedLast' % name, passed)
+    #             set_item_state('cisco_asyncos_update_%s_failedLast' % name, failed)
+    #             set_item_state('cisco_asyncos_update_%s_failedAttempts' % name, 0)
+    #         else:
+    #             set_item_state('cisco_asyncos_update_%s_passedLast' % name, passed)
+    #             set_item_state('cisco_asyncos_update_%s_failedLast' % name, failed)
+    #             passedLast = int(passedLast)
+    #             failedLast = int(failedLast)
+    #             failedAttempts = int(failedAttempts)
+    #             failed = int(failed)
+    #             passed = int(passed)
+    #             # reset counter if overrun
+    #             if failed < failedLast:
+    #                 set_item_state('cisco_asyncos_update_%s_failedLast' % name, failed)
+    #                 failedLast = failed
+    #             if passed < passedLast:
+    #                 set_item_state('cisco_asyncos_update_%s_passedLast' % name, passed)
+    #                 passedLast = passed
+    #
+    #             if passed > passedLast:
+    #                 # rest error counter after passed update attempt
+    #                 set_item_state('cisco_asyncos_update_%s_failedAttempts' % name, 0)
+    #             else:
+    #                 failedAttempts = failedAttempts + failed - failedLast
+    #                 set_item_state('cisco_asyncos_update_%s_failedAttempts' % name, failedAttempts)
+    #                 if name not in features_ignore:
+    #                     if failedAttempts >= failedCrit:
+    #                         failedItemsCrit.append(name)
+    #                         lastState = -1
+    #                     elif failedAttempts >= failedWarn:
+    #                         failedItemsWarn.append(name)
+    #                         lastState = -1
+    #
+    #         perfdata.append((name.replace(' ', '_'), lastState, None, None, -1, 1))
+    #
+    #     infotext += '%d item(s) found' % len(info)
+    #     if len(failedItemsCrit) > 0:
+    #         yield 2, '%d failed item(s) (%s), failed attempts >= %d' % (len(failedItemsCrit), ', '.join(failedItemsCrit), failedCrit)
+    #     if len(failedItemsWarn) > 0:
+    #         yield 1, '%d failed item(s) (%s), failed attempts >= %d' % (len(failedItemsWarn), ', '.join(failedItemsWarn), failedWarn)
+    #
+    #     yield 0, infotext + longoutput, perfdata
+
+
+
+register.snmp_section(
+    name='cisco_asyncos_update',
+    parse_function=parse_cisco_asyncos_update,
+    fetch=[
+        SNMPTree(
+            base='.1.3.6.1.4.1.15497.1.1.1.13.1',  # ASYNCOS-MAIL-MIB::updateEntry
+            oids=[
+                '2',  # updateServiceName -> A textual name for an update entry
+                '3',  # updates -> The number of successful attempts that have occurred when updating a service
+                '4',  # updateFailures -> "The number of failed attempts that have occurred when updating a service
+            ]
+        ),
+    ],
+    detect=contains('.1.3.6.1.2.1.1.1.0', 'AsyncOS'),
+)
+
+register.check_plugin(
+    name='cisco_asyncos_update',
+    service_name='Update',
+    discovery_function=discovery_cisco_asyncos_update,
+    check_function=check_cisco_asyncos_update,
+    check_default_parameters={'failedLevel': (5, 10)},
+    check_ruleset_name='cisco_asyncos_update',
+)
+
diff --git a/checks/cisco_asyncos_update b/checks/cisco_asyncos_update
deleted file mode 100644
index 333795a342f68678e72603e9970abf71a9c2c4cf..0000000000000000000000000000000000000000
--- a/checks/cisco_asyncos_update
+++ /dev/null
@@ -1,259 +0,0 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
-#
-# Rewriten by: Th.L.
-# Date: 19-02-2020
-#
-# 2020-05-14: added wato oprion to ignore items
-#
-# 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-
-# ails.  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.
-#
-#
-# sample snmpwalk
-#
-# OMD[cmk16x]:~$ snmpwalk -v2c -c public -m ASYNCOS-MAIL-MIB -ObentU localhost updateEntry
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.1 = INTEGER: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.2 = INTEGER: 2
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.3 = INTEGER: 3
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.4 = INTEGER: 4
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.5 = INTEGER: 5
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.6 = INTEGER: 6
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.7 = INTEGER: 7
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.8 = INTEGER: 8
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.9 = INTEGER: 9
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.10 = INTEGER: 10
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.11 = INTEGER: 11
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.12 = INTEGER: 12
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.13 = INTEGER: 13
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.14 = INTEGER: 14
-# .1.3.6.1.4.1.15497.1.1.1.13.1.1.15 = INTEGER: 15
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.1 = STRING: File Reputation
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.2 = STRING: IronPort Anti-Spam
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.3 = STRING: McAfee
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.4 = STRING: Sophos Anti-Virus
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.5 = STRING: amp
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.6 = STRING: content_scanner
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.7 = STRING: enrollment_client
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.8 = STRING: geo_countries
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.9 = STRING: howto
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.10 = STRING: openssh_key
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.11 = STRING: repeng
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.12 = STRING: sdr_client
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.13 = STRING: smart_agent
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.14 = STRING: support_request
-# .1.3.6.1.4.1.15497.1.1.1.13.1.2.15 = STRING: timezones
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.1 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.2 = Counter32: 10
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.3 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.4 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.5 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.6 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.7 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.8 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.9 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.10 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.11 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.12 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.13 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.14 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.3.15 = Counter32: 1
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.1 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.2 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.3 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.4 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.5 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.6 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.7 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.8 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.9 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.10 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.11 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.12 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.13 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.14 = Counter32: 0
-# .1.3.6.1.4.1.15497.1.1.1.13.1.4.15 = Counter32: 0
-#
-# OMD[cmk16x]:~$ snmpwalk -v2c -c public -m ASYNCOS-MAIL-MIB localhost updateEntry
-# ASYNCOS-MAIL-MIB::updateIndex.1 = INTEGER: 1
-# ASYNCOS-MAIL-MIB::updateIndex.2 = INTEGER: 2
-# ASYNCOS-MAIL-MIB::updateIndex.3 = INTEGER: 3
-# ASYNCOS-MAIL-MIB::updateIndex.4 = INTEGER: 4
-# ASYNCOS-MAIL-MIB::updateIndex.5 = INTEGER: 5
-# ASYNCOS-MAIL-MIB::updateIndex.6 = INTEGER: 6
-# ASYNCOS-MAIL-MIB::updateIndex.7 = INTEGER: 7
-# ASYNCOS-MAIL-MIB::updateIndex.8 = INTEGER: 8
-# ASYNCOS-MAIL-MIB::updateIndex.9 = INTEGER: 9
-# ASYNCOS-MAIL-MIB::updateIndex.10 = INTEGER: 10
-# ASYNCOS-MAIL-MIB::updateIndex.11 = INTEGER: 11
-# ASYNCOS-MAIL-MIB::updateIndex.12 = INTEGER: 12
-# ASYNCOS-MAIL-MIB::updateIndex.13 = INTEGER: 13
-# ASYNCOS-MAIL-MIB::updateIndex.14 = INTEGER: 14
-# ASYNCOS-MAIL-MIB::updateIndex.15 = INTEGER: 15
-# ASYNCOS-MAIL-MIB::updateServiceName.1 = STRING: File Reputation
-# ASYNCOS-MAIL-MIB::updateServiceName.2 = STRING: IronPort Anti-Spam
-# ASYNCOS-MAIL-MIB::updateServiceName.3 = STRING: McAfee
-# ASYNCOS-MAIL-MIB::updateServiceName.4 = STRING: Sophos Anti-Virus
-# ASYNCOS-MAIL-MIB::updateServiceName.5 = STRING: amp
-# ASYNCOS-MAIL-MIB::updateServiceName.6 = STRING: content_scanner
-# ASYNCOS-MAIL-MIB::updateServiceName.7 = STRING: enrollment_client
-# ASYNCOS-MAIL-MIB::updateServiceName.8 = STRING: geo_countries
-# ASYNCOS-MAIL-MIB::updateServiceName.9 = STRING: howto
-# ASYNCOS-MAIL-MIB::updateServiceName.10 = STRING: openssh_key
-# ASYNCOS-MAIL-MIB::updateServiceName.11 = STRING: repeng
-# ASYNCOS-MAIL-MIB::updateServiceName.12 = STRING: sdr_client
-# ASYNCOS-MAIL-MIB::updateServiceName.13 = STRING: smart_agent
-# ASYNCOS-MAIL-MIB::updateServiceName.14 = STRING: support_request
-# ASYNCOS-MAIL-MIB::updateServiceName.15 = STRING: timezones
-# ASYNCOS-MAIL-MIB::updates.1 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.2 = Counter32: 10
-# ASYNCOS-MAIL-MIB::updates.3 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.4 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.5 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.6 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.7 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.8 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.9 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updates.10 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updates.11 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updates.12 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updates.13 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updates.14 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updates.15 = Counter32: 1
-# ASYNCOS-MAIL-MIB::updateFailures.1 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.2 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.3 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.4 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.5 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.6 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.7 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.8 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.9 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.10 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.11 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.12 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.13 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.14 = Counter32: 0
-# ASYNCOS-MAIL-MIB::updateFailures.15 = Counter32: 0
-#
-# sample info
-#
-# [[u'File Reputation', u'1', u'0'],
-#  [u'IronPort Anti-Spam', u'10', u'0'],
-#  [u'McAfee', u'1', u'0'],
-#  [u'Sophos Anti-Virus', u'1', u'0'],
-#  [u'amp', u'1', u'0'],
-#  [u'content_scanner', u'1', u'0'],
-#  [u'enrollment_client', u'1', u'0'],
-#  [u'geo_countries', u'1', u'0'],
-#  [u'howto', u'0', u'0'],
-#  [u'openssh_key', u'0', u'0'],
-#  [u'repeng', u'0', u'0'],
-#  [u'sdr_client', u'0', u'0'],
-#  [u'smart_agent', u'0', u'0'],
-#  [u'support_request', u'1', u'0'],
-#  [u'timezones', u'1', u'0']
-# ]
-#
-
-factory_settings['cisco_asyncos_update_default_levels'] = {
-    'failedLevel': (5, 10),
-    'features_ignore': []
-}
-
-
-def inventory_cisco_asyncos_update(info):
-    if len(info) > 0:
-        return [(None, None)]
-
-
-def check_cisco_asyncos_update(_no_item, params, info):
-    if len(info) > 0:           
-        infotext = ''
-        longoutput = ''
-        perfdata = []
-        failedItemsWarn = []
-        failedItemsCrit = []
-        failedWarn, failedCrit = params.get('failedLevel')
-        features_ignore = params['features_ignore']
-        lastState = 1
-        
-        for line in info:
-            name, passed, failed = line
-            longoutput += '\n%s: %s/%s passed/failed attempt(s)' % (name, passed, failed)
-            # read counters
-            passedLast = get_item_state('cisco_asyncos_update_%s_passedLast' % name)
-            failedLast = get_item_state('cisco_asyncos_update_%s_failedLast' % name)
-            failedAttempts = get_item_state('cisco_asyncos_update_%s_failedAttempts' % name)
-
-            if (passedLast == None) or (failedLast == None) or (failedAttempts == None):  # or (lastState == None):
-                # init counters
-                set_item_state('cisco_asyncos_update_%s_passedLast' % name, passed)
-                set_item_state('cisco_asyncos_update_%s_failedLast' % name, failed)
-                set_item_state('cisco_asyncos_update_%s_failedAttempts' % name, 0)
-            else:
-                set_item_state('cisco_asyncos_update_%s_passedLast' % name, passed)
-                set_item_state('cisco_asyncos_update_%s_failedLast' % name, failed)
-                passedLast = int(passedLast)
-                failedLast = int(failedLast)
-                failedAttempts = int(failedAttempts)
-                failed = int(failed)
-                passed = int(passed)
-                # reset counter if overrun
-                if failed < failedLast:
-                    set_item_state('cisco_asyncos_update_%s_failedLast' % name, failed)
-                    failedLast = failed
-                if passed < passedLast:
-                    set_item_state('cisco_asyncos_update_%s_passedLast' % name, passed)
-                    passedLast = passed
-
-                if passed > passedLast:
-                    # rest error counter after passed update attempt
-                    set_item_state('cisco_asyncos_update_%s_failedAttempts' % name, 0)
-                else:
-                    failedAttempts = failedAttempts + failed - failedLast
-                    set_item_state('cisco_asyncos_update_%s_failedAttempts' % name, failedAttempts)
-                    if name not in features_ignore:
-                        if failedAttempts >= failedCrit:
-                            failedItemsCrit.append(name)
-                            lastState = -1
-                        elif failedAttempts >= failedWarn:
-                            failedItemsWarn.append(name)
-                            lastState = -1
-
-            perfdata.append((name.replace(' ', '_'), lastState, None, None, -1, 1))
-
-        infotext += '%d item(s) found' % len(info)
-        if len(failedItemsCrit) > 0:            
-            yield 2, '%d failed item(s) (%s), failed attempts >= %d' % (len(failedItemsCrit), ', '.join(failedItemsCrit), failedCrit)
-        if len(failedItemsWarn) > 0:
-            yield 1, '%d failed item(s) (%s), failed attempts >= %d' % (len(failedItemsWarn), ', '.join(failedItemsWarn), failedWarn)
-
-        yield 0, infotext + longoutput, perfdata
-
-
-check_info['cisco_asyncos_update'] = {
-    'check_function':          check_cisco_asyncos_update,
-    'inventory_function':      inventory_cisco_asyncos_update,
-    'group':                   'cisco_asyncos_update',
-    'service_description':     'Update',
-    'has_perfdata': True,
-    'snmp_info':               ('.1.3.6.1.4.1.15497.1.1.1.13.1', [  # ASYNCOS-MAIL-MIB::updateEntry
-                                '2',  # updateServiceName --> A textual name for an update entry
-                                '3',  # updates --> The number of successful attempts that have occurred when updating a service
-                                '4',  # updateFailures --> "The number of failed attempts that have occurred when updating a service
-                                ]),
-    'default_levels_variable': 'cisco_asyncos_update_default_levels',
-    'snmp_scan_function':  lambda oid: oid('.1.3.6.1.2.1.1.1.0').find('AsyncOS') != -1,
-    # 'snmp_scan_function': scan_cisco_asyncos,
-    # 'includes': ['cisco_asyncos.include'],
-}
-
diff --git a/cisco_asyncos.mkp b/cisco_asyncos.mkp
index 52a40594eff84cafd40e7eaa4496193b65e870ba..fa793cf65e90013d6fbb159691d48f2f33cc7338 100644
Binary files a/cisco_asyncos.mkp and b/cisco_asyncos.mkp differ
diff --git a/packages/cisco_asyncos b/packages/cisco_asyncos
index 96321b665aec7202204d5d85e86e6d1f0a0f8b4d..09191723e0028ac4a00a680683a572f84e2dd008 100644
--- a/packages/cisco_asyncos
+++ b/packages/cisco_asyncos
@@ -37,8 +37,8 @@
                            'cisco_asyncos_messageage.py',
                            'cisco_asyncos_queue.py',
                            'cisco_asyncos_resources.py',
-                           'cisco_asyncos_license.py'],
-           'checks': ['cisco_asyncos_update'],
+                           'cisco_asyncos_license.py',
+                           'cisco_asyncos_update.py'],
            'web': ['plugins/wato/cisco_asyncos_license.py',
                    'plugins/wato/cisco_asyncos_queue.py',
                    'plugins/wato/cisco_asyncos_update.py',
diff --git a/web/plugins/wato/cisco_asyncos_queue.py b/web/plugins/wato/cisco_asyncos_queue.py
index d3bf1472916a93485b7af8b1ad65accd7aab9e98..5b3722c74a7857e257300c2fbf1afb4ee78795ca 100644
--- a/web/plugins/wato/cisco_asyncos_queue.py
+++ b/web/plugins/wato/cisco_asyncos_queue.py
@@ -1,23 +1,41 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
 #
-register_check_parameters(
-    subgroup_applications,
-    'cisco_asyncos_queue',
-    _('Cisco AsyncOS queue'),
-    Dictionary(
-       #  help=_(''),
-        elements=[
-            ('levels',
-             Tuple(
-                 title=_('Levels for nuber of messages in work queue'),
-                 elements=[
-                     Integer(title=_('Warning'), default_value=50, unit=_('# of messages')),
-                     Integer(title=_('Critical'), default_value=100, unit=_('# of messages')),
-                 ])),
-        ],
-    ),
-    None,
-    match_type='dict',
+from cmk.gui.i18n import _
+from cmk.gui.valuespec import (
+    Dictionary,
+    Integer,
+    TextAscii,
+    ListOfStrings,
+    Tuple,
 )
+
+from cmk.gui.plugins.wato import (
+    CheckParameterRulespecWithItem,
+    rulespec_registry,
+    RulespecGroupCheckParametersNetworking,
+)
+
+
+def _parameter_valuespec_cisco_asyncos_queue():
+    return Dictionary(elements=[
+        ('levels',
+         Tuple(
+             title=_('Levels for nuber of messages in work queue'),
+             elements=[
+                 Integer(title=_('Warning'), default_value=50, unit=_('# of messages')),
+                 Integer(title=_('Critical'), default_value=100, unit=_('# of messages')),
+             ])),
+    ])
+
+
+rulespec_registry.register(
+    CheckParameterRulespecWithItem(
+        check_group_name='cisco_asyncos_queue',
+        group=RulespecGroupCheckParametersNetworking,
+        item_spec=lambda: TextAscii(title=_('Cisco AsyncOS queue'), ),
+        match_type='dict',
+        parameter_valuespec=_parameter_valuespec_cisco_asyncos_queue,
+        title=lambda: _('Cisco AsyncOS queue'),
+    ))
diff --git a/web/plugins/wato/cisco_asyncos_update.py b/web/plugins/wato/cisco_asyncos_update.py
index 6701443cc21ab9ca14205d62178382b21d0a6429..930d2a92cbbcac55f760d177f7ab804e30cd54d9 100644
--- a/web/plugins/wato/cisco_asyncos_update.py
+++ b/web/plugins/wato/cisco_asyncos_update.py
@@ -1,31 +1,49 @@
-#!/usr/bin/python
-# -*- encoding: utf-8; py-indent-offset: 4 -*-
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
 #
 #
-register_check_parameters(
-    subgroup_applications,
-    'cisco_asyncos_update',
-    _('Cisco AsyncOS update'),
-    Dictionary(
-       #  help=_(''),
-        elements=[
-            ('features_ignore',
-              ListOfStrings(
-                  title=_('update features to ignore'),
-                  orientation='vertical',
-                  help=_('there will be no warning/critical if this features are not updated'
-                         'Examples: geo_countries, timezones, etc.'),
-              )
-             ),
-            ('failedLevel',
-             Tuple(
-                 title=_('Levels for failed attempts'),
-                 elements=[
-                     Integer(title=_('Warning'), default_value=5, unit=_('# of failed attempts')),
-                     Integer(title=_('Critical'), default_value=10, unit=_('# of failed attempts')),
-                 ])),
-        ],
-    ),
-    None,
-    match_type='dict',
+from cmk.gui.i18n import _
+from cmk.gui.valuespec import (
+    Dictionary,
+    Integer,
+    TextAscii,
+    ListOfStrings,
+    Tuple,
 )
+
+from cmk.gui.plugins.wato import (
+    CheckParameterRulespecWithItem,
+    rulespec_registry,
+    RulespecGroupCheckParametersNetworking,
+)
+
+
+def _parameter_valuespec_cisco_asyncos_license():
+    return Dictionary(elements=[
+        ('features_ignore',
+         ListOfStrings(
+             title=_('Update features to ignore'),
+             orientation='vertical',
+             help=_('there will be no warning/critical if this features are not updated'
+                    'Examples: geo_countries, timezones, etc.'),
+         )
+         ),
+        ('failedLevel',
+         Tuple(
+             title=_('Levels for failed attempts'),
+             elements=[
+                 Integer(title=_('Warning'), default_value=5, unit=_('# of failed attempts')),
+                 Integer(title=_('Critical'), default_value=10, unit=_('# of failed attempts')),
+             ])),
+    ])
+
+
+rulespec_registry.register(
+    CheckParameterRulespecWithItem(
+        check_group_name='cisco_asyncos_update',
+        group=RulespecGroupCheckParametersNetworking,
+        item_spec=lambda: TextAscii(title=_('Cisco AsyncOS update'), ),
+        match_type='dict',
+        parameter_valuespec=_parameter_valuespec_cisco_asyncos_update,
+        title=lambda: _('Cisco AsyncOS update'),
+    ))