From 016a20f6b6f886a5421b83d0213d02c7d88a74f5 Mon Sep 17 00:00:00 2001 From: Roy Lee Date: Wed, 8 May 2019 15:41:07 +0800 Subject: [PATCH] [device][accton]Add fan monitor for as7816-64x (#2859) * catch signal SIGINT and SIGTERM to set all fans full-speed before end fan monitor. Signed-off-by: roy_lee * Add fan_control monitor for as7816-64x. Signed-off-by: roy_lee * Fix typo. Signed-off-by: roy_lee * Correct typo and duty setting after verified. Signed-off-by: roy_lee --- .../as5712-54x/utils/accton_as5712_monitor.py | 10 + .../as7312-54x/setup.py | 2 +- .../as7312-54x/utils/accton_as7312_monitor.py | 12 +- .../as7816-64x/classes/fanutil.py | 244 ++++++++++++++++++ .../as7816-64x/classes/thermalutil.py | 128 +++++++++ .../service/as7816-platform-init.service | 6 +- .../as7816-64x/utils/accton_as7816_monitor.py | 163 ++++++++++++ 7 files changed, 560 insertions(+), 5 deletions(-) create mode 100755 platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_monitor.py diff --git a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py index 84ab2d83bab4..d7b372145827 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as5712-54x/utils/accton_as5712_monitor.py @@ -33,6 +33,7 @@ import types import time # this is only being used as part of the example import traceback + import signal from tabulate import tabulate from as5712_54x.fanutil import FanUtil from as5712_54x.thermalutil import ThermalUtil @@ -42,6 +43,7 @@ # Deafults VERSION = '1.0' FUNCTION_NAME = 'accton_as5712_monitor' +DUTY_MAX = 100 global log_file global log_level @@ -166,6 +168,12 @@ def manage_fans(self): return True +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(fan.get_idx_fan_start(), DUTY_MAX) + sys.exit(0) + def main(argv): log_file = '%s.log' % FUNCTION_NAME log_level = logging.INFO @@ -184,6 +192,8 @@ def main(argv): elif opt in ('-l', '--lfile'): log_file = arg + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) monitor = accton_as5712_monitor(log_file, log_level) # Loop forever, doing something useful hopefully: diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py index f0518d07689d..5e862ce15048 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/setup.py @@ -1,4 +1,4 @@ -#!/usr/bin/env pytho +#!/usr/bin/env python import os import sys diff --git a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py index bdab0d4b8bff..19d7470515f9 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7312-54x/utils/accton_as7312_monitor.py @@ -34,6 +34,7 @@ import types import time # this is only being used as part of the example import traceback + import signal from tabulate import tabulate from as7312_54x.fanutil import FanUtil from as7312_54x.thermalutil import ThermalUtil @@ -43,6 +44,7 @@ # Deafults VERSION = '1.0' FUNCTION_NAME = 'accton_as7312_monitor' +DUTY_MAX = 100 global log_file global log_level @@ -98,7 +100,7 @@ def __init__(self, log_file, log_level): logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) def manage_fans(self): - max_duty = 100 + max_duty = DUTY_MAX fan_policy_f2b = { 0: [32, 0, 105000], 1: [50, 105000, 120000], @@ -179,6 +181,12 @@ def manage_fans(self): fan.set_fan_duty_cycle(new_duty_cycle) return True +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + def main(argv): log_file = '%s.log' % FUNCTION_NAME log_level = logging.INFO @@ -197,6 +205,8 @@ def main(argv): elif opt in ('-l', '--lfile'): log_file = arg + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) monitor = accton_as7312_monitor(log_file, log_level) # Loop forever, doing something useful hopefully: diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py index e69de29bb2d1..42ccb17eaa06 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/fanutil.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class FanUtil(object): + """Platform-specific FanUtil class""" + + FAN_NUM_ON_MAIN_BROAD = 4 + FAN_NUM_1_IDX = 1 + FAN_NUM_2_IDX = 2 + FAN_NUM_3_IDX = 3 + FAN_NUM_4_IDX = 4 + + FAN_NODE_NUM_OF_MAP = 2 + FAN_NODE_FAULT_IDX_OF_MAP = 1 + #FAN_NODE_SPEED_IDX_OF_MAP = 2 + FAN_NODE_DIR_IDX_OF_MAP = 2 + #FAN_NODE_DUTY_IDX_OF_MAP = 4 + #FANR_NODE_FAULT_IDX_OF_MAP = 5 + + BASE_VAL_PATH = '/sys/bus/i2c/devices/17-0068/{0}' + FAN_DUTY_PATH = '/sys/bus/i2c/devices/17-0068/fan_duty_cycle_percentage' + + #logfile = '' + #loglevel = logging.INFO + + """ Dictionary where + key1 = fan id index (integer) starting from 1 + key2 = fan node index (interger) starting from 1 + value = path to fan device file (string) """ + _fan_to_device_path_mapping = {} + +#fan1_direction +#fan1_fault +#fan1_present + + #(FAN_NUM_2_IDX, FAN_NODE_DUTY_IDX_OF_MAP): 'fan2_duty_cycle_percentage', + _fan_to_device_node_mapping = { + (FAN_NUM_1_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan1_fault', + (FAN_NUM_1_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan1_direction', + (FAN_NUM_2_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan2_fault', + (FAN_NUM_2_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan2_direction', + + (FAN_NUM_3_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan3_fault', + (FAN_NUM_3_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan3_direction', + + (FAN_NUM_4_IDX, FAN_NODE_FAULT_IDX_OF_MAP): 'fan4_fault', + (FAN_NUM_4_IDX, FAN_NODE_DIR_IDX_OF_MAP): 'fan4_direction', + } + + def _get_fan_to_device_node(self, fan_num, node_num): + return self._fan_to_device_node_mapping[(fan_num, node_num)] + + def _get_fan_node_val(self, fan_num, node_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + + try: + val_file = open(device_path, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + def _set_fan_node_val(self, fan_num, node_num, val): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num:%d', fan_num) + return None + + if node_num < self.FAN_NODE_FAULT_IDX_OF_MAP or node_num > self.FAN_NODE_NUM_OF_MAP: + logging.debug('GET. Parameter error. node_num:%d', node_num) + return None + + content = str(val) + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + device_path = self.get_fan_to_device_path(fan_num, node_num) + try: + val_file = open(device_path, 'w') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + val_file.write(content) + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return True + + def __init__(self): + fan_path = self.BASE_VAL_PATH + + for fan_num in range(self.FAN_NUM_1_IDX, self.FAN_NUM_ON_MAIN_BROAD+1): + for node_num in range(self.FAN_NODE_FAULT_IDX_OF_MAP, self.FAN_NODE_NUM_OF_MAP+1): + self._fan_to_device_path_mapping[(fan_num, node_num)] = fan_path.format( + self._fan_to_device_node_mapping[(fan_num, node_num)]) + + def get_num_fans(self): + return self.FAN_NUM_ON_MAIN_BROAD + + def get_idx_fan_start(self): + return self.FAN_NUM_1_IDX + + def get_num_nodes(self): + return self.FAN_NODE_NUM_OF_MAP + + def get_idx_node_start(self): + return self.FAN_NODE_FAULT_IDX_OF_MAP + + def get_size_node_map(self): + return len(self._fan_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._fan_to_device_path_mapping) + + def get_fan_to_device_path(self, fan_num, node_num): + return self._fan_to_device_path_mapping[(fan_num, node_num)] + + def get_fan_fault(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_FAULT_IDX_OF_MAP) + + #def get_fan_speed(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FAN_NODE_SPEED_IDX_OF_MAP) + + def get_fan_dir(self, fan_num): + return self._get_fan_node_val(fan_num, self.FAN_NODE_DIR_IDX_OF_MAP) + + def get_fan_duty_cycle(self): + #duty_path = self.FAN_DUTY_PATH + try: + val_file = open(self.FAN_DUTY_PATH) + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + + content = val_file.readline().rstrip() + val_file.close() + + return int(content) + #self._get_fan_node_val(fan_num, self.FAN_NODE_DUTY_IDX_OF_MAP) +#static u32 reg_val_to_duty_cycle(u8 reg_val) +#{ +# reg_val &= FAN_DUTY_CYCLE_REG_MASK; +# return ((u32)(reg_val+1) * 625 + 75)/ 100; +#} +# + def set_fan_duty_cycle(self, val): + + try: + fan_file = open(self.FAN_DUTY_PATH, 'r+') + except IOError as e: + print "Error: unable to open file: %s" % str(e) + return False + fan_file.write(str(val)) + fan_file.close() + return True + + #def get_fanr_fault(self, fan_num): + # return self._get_fan_node_val(fan_num, self.FANR_NODE_FAULT_IDX_OF_MAP) + + def get_fanr_speed(self, fan_num): + return self._get_fan_node_val(fan_num, self.FANR_NODE_SPEED_IDX_OF_MAP) + + def get_fan_status(self, fan_num): + if fan_num < self.FAN_NUM_1_IDX or fan_num > self.FAN_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. fan_num, %d', fan_num) + return None + + if self.get_fan_fault(fan_num) is not None and self.get_fan_fault(fan_num) > 0: + logging.debug('GET. FAN fault. fan_num, %d', fan_num) + return False + + #if self.get_fanr_fault(fan_num) is not None and self.get_fanr_fault(fan_num) > 0: + # logging.debug('GET. FANR fault. fan_num, %d', fan_num) + # return False + + return True + +#def main(): +# fan = FanUtil() +# +# print 'get_size_node_map : %d' % fan.get_size_node_map() +# print 'get_size_path_map : %d' % fan.get_size_path_map() +# for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): +# for y in range(fan.get_idx_node_start(), fan.get_num_nodes()+1): +# print fan.get_fan_to_device_path(x, y) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py index e69de29bb2d1..65e872c6beb8 100644 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/classes/thermalutil.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018:Jostar modify for as7716_32x +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import time + import logging + import glob + from collections import namedtuple +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + + +class ThermalUtil(object): + """Platform-specific ThermalUtil class""" + + THERMAL_NUM_ON_MAIN_BROAD = 6 + THERMAL_NUM_1_IDX = 1 + BASE_VAL_PATH = '/sys/bus/i2c/devices/{0}-00{1}/hwmon/hwmon*/temp1_input' + + """ Dictionary where + key1 = thermal id index (integer) starting from 1 + value = path to fan device file (string) """ + _thermal_to_device_path_mapping = {} + + _thermal_to_device_node_mapping = [ + ['18', '48'], + ['18', '49'], + ['18', '4a'], + ['18', '4b'], + ['17', '4d'], + ['17', '4e'], + ] + + def __init__(self): + thermal_path = self.BASE_VAL_PATH + + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + self._thermal_to_device_path_mapping[x+1] = thermal_path.format( + self._thermal_to_device_node_mapping[x][0], + self._thermal_to_device_node_mapping[x][1]) + + def _get_thermal_node_val(self, thermal_num): + if thermal_num < self.THERMAL_NUM_1_IDX or thermal_num > self.THERMAL_NUM_ON_MAIN_BROAD: + logging.debug('GET. Parameter error. thermal_num, %d', thermal_num) + return None + + device_path = self.get_thermal_to_device_path(thermal_num) + for filename in glob.glob(device_path): + try: + val_file = open(filename, 'r') + except IOError as e: + logging.error('GET. unable to open file: %s', str(e)) + return None + + content = val_file.readline().rstrip() + + if content == '': + logging.debug('GET. content is NULL. device_path:%s', device_path) + return None + + try: + val_file.close() + except: + logging.debug('GET. unable to close file. device_path:%s', device_path) + return None + + return int(content) + + + def get_num_thermals(self): + return self.THERMAL_NUM_ON_MAIN_BROAD + + def get_idx_thermal_start(self): + return self.THERMAL_NUM_1_IDX + + def get_size_node_map(self): + return len(self._thermal_to_device_node_mapping) + + def get_size_path_map(self): + return len(self._thermal_to_device_path_mapping) + + def get_thermal_to_device_path(self, thermal_num): + return self._thermal_to_device_path_mapping[thermal_num] + + def get_thermal_2_val(self): + return self._get_thermal_node_val(self.THERMAL_NUM_2_IDX) + + def get_thermal_temp(self): + sum = 0 + o = [] + for x in range(self.THERMAL_NUM_ON_MAIN_BROAD): + sum += self._get_thermal_node_val(x+1) + avg = sum/self.THERMAL_NUM_ON_MAIN_BROAD + avg = (avg/1000)*1000 #round down for hysteresis. + return avg + +#def main(): +# thermal = ThermalUtil() +# +# print 'get_size_node_map : %d' % thermal.get_size_node_map() +# print 'get_size_path_map : %d' % thermal.get_size_path_map() +# for x in range(thermal.get_idx_thermal_start(), thermal.get_num_thermals()+1): +# print thermal.get_thermal_to_device_path(x) +# +#if __name__ == '__main__': +# main() diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service index c1ba30092f1d..486ed74f8243 100755 --- a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/service/as7816-platform-init.service @@ -1,12 +1,12 @@ [Unit] Description=Accton AS7816-64X Platform initialization service Before=pmon.service +After=sysinit.target DefaultDependencies=no [Service] -Type=oneshot -ExecStart=/usr/local/bin/accton_as7816_util.py install -ExecStop=/usr/local/bin/accton_as7816_util.py clean +ExecStartPre=/usr/local/bin/accton_as7816_util.py install +ExecStart=/usr/local/bin/accton_as7816_monitor.py RemainAfterExit=yes [Install] diff --git a/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_monitor.py b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_monitor.py new file mode 100755 index 000000000000..3d9f6fc3ce5e --- /dev/null +++ b/platform/broadcom/sonic-platform-modules-accton/as7816-64x/utils/accton_as7816_monitor.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# +# Copyright (C) 2017 Accton Technology Corporation +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# ------------------------------------------------------------------ +# HISTORY: +# mm/dd/yyyy (A.D.) +# 11/13/2017: Polly Hsu, Create +# 1/10/2018: Jostar modify for as7716_32 +# 5/02/2019: Roy Lee modify for as7816_64x +# ------------------------------------------------------------------ + +try: + import os + import sys, getopt + import subprocess + import click + import imp + import logging + import logging.config + import types + import time # this is only being used as part of the example + import traceback + import signal + from tabulate import tabulate + from as7816_64x.fanutil import FanUtil + from as7816_64x.thermalutil import ThermalUtil +except ImportError as e: + raise ImportError('%s - required module not found' % str(e)) + +# Deafults +VERSION = '1.0' +FUNCTION_NAME = 'accton_as7816_monitor' +DUTY_MAX = 100 +DUTY_DEF = 40 + +global log_file +global log_level + + +# Make a class we can use to capture stdout and sterr in the log +class accton_as7816_monitor(object): + # static temp var + _ori_temp = 0 + _new_perc = 0 + _ori_perc = 0 + + def __init__(self, log_file, log_level): + """Needs a logger and a logger level.""" + # set up logging to file + logging.basicConfig( + filename=log_file, + filemode='w', + level=log_level, + format= '[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s', + datefmt='%H:%M:%S' + ) + + # set up logging to console + if log_level == logging.DEBUG: + console = logging.StreamHandler() + console.setLevel(log_level) + formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s') + console.setFormatter(formatter) + logging.getLogger('').addHandler(console) + + logging.debug('SET. logfile:%s / loglevel:%d', log_file, log_level) + + def manage_fans(self): + max_duty = DUTY_MAX + fan_policy = { + 0: [52, 0, 43000], + 1: [63, 43000, 46000], + 2: [75, 46000, 52000], + 3: [88, 52000, 57000], + 4: [max_duty, 57000, sys.maxsize], + } + + thermal = ThermalUtil() + fan = FanUtil() + for x in range(fan.get_idx_fan_start(), fan.get_num_fans()+1): + fan_status = fan.get_fan_status(x) + if fan_status is None: + logging.debug('INFO. SET new_perc to %d (FAN stauts is None. fan_num:%d)', max_duty, x) + return False + if fan_status is False: + logging.debug('INFO. SET new_perc to %d (FAN fault. fan_num:%d)', max_duty, x) + fan.set_fan_duty_cycle(max_duty) + return True + #logging.debug('INFO. fan_status is True (fan_num:%d)', x) + + #Find if current duty matched any of define duty. + #If not, set it to highest one. + cur_duty_cycle = fan.get_fan_duty_cycle() + new_duty_cycle = DUTY_DEF + for x in range(0, len(fan_policy)): + if cur_duty_cycle == fan_policy[x][0]: + break + if x == len(fan_policy) : + fan.set_fan_duty_cycle(fan_policy[0][0]) + cur_duty_cycle = max_duty + + #Decide fan duty by if sum of sensors falls into any of fan_policy{} + get_temp = thermal.get_thermal_temp() + for x in range(0, len(fan_policy)): + y = len(fan_policy) - x -1 #checked from highest + if get_temp > fan_policy[y][1] and get_temp < fan_policy[y][2] : + new_duty_cycle = fan_policy[y][0] + logging.debug('INFO. Sum of temp %d > %d , new_duty_cycle=%d', get_temp, fan_policy[y][1], new_duty_cycle) + + logging.debug('INFO. Final duty_cycle=%d', new_duty_cycle) + if(new_duty_cycle != cur_duty_cycle): + fan.set_fan_duty_cycle(new_duty_cycle) + return True + +def handler(signum, frame): + fan = FanUtil() + logging.debug('INFO:Cause signal %d, set fan speed max.', signum) + fan.set_fan_duty_cycle(DUTY_MAX) + sys.exit(0) + +def main(argv): + log_file = '%s.log' % FUNCTION_NAME + log_level = logging.INFO + if len(sys.argv) != 1: + try: + opts, args = getopt.getopt(argv,'hdl:',['lfile=']) + except getopt.GetoptError: + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + for opt, arg in opts: + if opt == '-h': + print 'Usage: %s [-d] [-l ]' % sys.argv[0] + return 0 + elif opt in ('-d', '--debug'): + log_level = logging.DEBUG + elif opt in ('-l', '--lfile'): + log_file = arg + + signal.signal(signal.SIGINT, handler) + signal.signal(signal.SIGTERM, handler) + monitor = accton_as7816_monitor(log_file, log_level) + + # Loop forever, doing something useful hopefully: + while True: + monitor.manage_fans() + time.sleep(10) + +if __name__ == '__main__': + main(sys.argv[1:])