Skip to content

Commit 56921d8

Browse files
authored
File system based sensors implementation for voltage and current sensors (#426)
* File system based sensors implementation for voltage and current sensors. * Added error handling for missing data in yaml file * Added test code. * Addressed review comments * Fixed missing inclusion * Fixed UT error * Fixed test case failures in other repos. * Addressed review comments * Fixed UT * Review comment * Removed empty line in diff. * Removed changes in chassis base tests
1 parent 3d35404 commit 56921d8

File tree

3 files changed

+227
-0
lines changed

3 files changed

+227
-0
lines changed

sonic_platform_base/sensor_fs.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
"""
2+
sensor_fs.py
3+
4+
File system based sensors implementation.
5+
"""
6+
7+
from sonic_platform_base.sensor_base import SensorBase
8+
from sonic_platform_base.sensor_base import VoltageSensorBase
9+
from sonic_platform_base.sensor_base import CurrentSensorBase
10+
import logging
11+
12+
13+
class SensorFs(SensorBase):
14+
"""Implementation of file system based sensor class"""
15+
16+
__defaults = {
17+
'name': '',
18+
'sensor': '',
19+
'high_thresholds': ['N/A', 'N/A', 'N/A'], #minor, major, critical
20+
'low_thresholds': ['N/A', 'N/A', 'N/A'], #minor, major, critical
21+
'position': -1,
22+
}
23+
24+
def __init__(self, sensor_type='sensor', **kw):
25+
26+
super(SensorFs, self).__init__()
27+
28+
if 'sensor' not in kw:
29+
raise Exception('Failed to initialize sensor')
30+
31+
for k,v in self.__defaults.items():
32+
setattr(self, k, kw.get(k,v))
33+
34+
if (len(self.high_thresholds) != 3 or len(self.low_thresholds) != 3):
35+
raise Exception('{}: Missing sensor thresholds'.format(self.name))
36+
37+
self.minimum_sensor = self.get_value()
38+
self.maximum_sensor = self.minimum_sensor
39+
40+
def get_name(self):
41+
"""Returns the sensor name"""
42+
return self.name
43+
44+
def get_value(self):
45+
"""Returns the sensor measurement"""
46+
try:
47+
with open(self.sensor) as f:
48+
return int(f.readline().rstrip())
49+
except:
50+
return None
51+
52+
def get_high_threshold(self):
53+
"""Returns the sensor high threshold value"""
54+
return self.high_thresholds[1]
55+
56+
def get_low_threshold(self):
57+
"""Returns the sensor low threshold value"""
58+
return self.low_thresholds[1]
59+
60+
def set_high_threshold(self, value):
61+
"""Sets the sensor high threshold value"""
62+
self.high_thresholds[1] = value
63+
return True
64+
65+
def set_low_threshold(self, value):
66+
"""Sets the sensor low threshold value"""
67+
self.low_thresholds[1] = value
68+
return True
69+
70+
def get_high_critical_threshold(self):
71+
"""Returns the sensor critical high threshold value"""
72+
return self.high_thresholds[2]
73+
74+
def get_low_critical_threshold(self):
75+
"""Returns the sensor critical low threshold value"""
76+
return self.low_thresholds[2]
77+
78+
def set_high_critical_threshold(self, value):
79+
"""Sets the sensor critical high threshold value"""
80+
self.high_thresholds[2] = value
81+
return True
82+
83+
def set_low_critical_threshold(self, value):
84+
"""Sets the sensor critical low threshold value"""
85+
self.low_thresholds[2] = value
86+
return True
87+
88+
def get_minimum_recorded(self):
89+
"""Retrieves the minimum recorded sensor measurement"""
90+
tmp = self.get_value()
91+
if tmp is None:
92+
return None
93+
if self.minimum_sensor is None or tmp < self.minimum_sensor:
94+
self.minimum_sensor = tmp
95+
return self.minimum_sensor
96+
97+
def get_maximum_recorded(self):
98+
"""Retrieves the maximum recorded sensor measurement"""
99+
tmp = self.get_value()
100+
if tmp is None:
101+
return None
102+
if self.maximum_sensor is None or tmp > self.maximum_sensor:
103+
self.maximum_sensor = tmp
104+
return self.maximum_sensor
105+
106+
def get_position_in_parent(self):
107+
"""Retrieves 1-based relative physical position in parent device"""
108+
return self.position
109+
110+
@staticmethod
111+
def factory(sensor_cls, sensors_data):
112+
"""Factory method for retrieving a list of Sensor objects"""
113+
logging.basicConfig()
114+
logger = logging.getLogger()
115+
116+
result = []
117+
118+
for idx, sensor in enumerate(sensors_data):
119+
sensor['position'] = idx + 1
120+
try:
121+
result.append(sensor_cls(**sensor))
122+
except Exception as e:
123+
logger.warning('Sensor.factory: {}'.format(e))
124+
125+
return result
126+
127+
128+
class VoltageSensorFs(SensorFs, VoltageSensorBase):
129+
"""File system based voltage sensor class"""
130+
131+
DEVICE_TYPE = "voltage_sensor"
132+
133+
def __init__(self, **kw):
134+
super(VoltageSensorFs, self).__init__(self.DEVICE_TYPE, **kw)
135+
136+
137+
class CurrentSensorFs(SensorFs, CurrentSensorBase):
138+
"""File systems based Current sensor class"""
139+
140+
DEVICE_TYPE = "current_sensor"
141+
142+
def __init__(self, **kw):
143+
super(CurrentSensorFs, self).__init__(self.DEVICE_TYPE, **kw)

tests/sensor_data/VSENSOR1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
900

tests/sensor_fs_test.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
'''
2+
Test Sensor_fs module
3+
'''
4+
5+
import yaml
6+
import os
7+
from unittest import mock
8+
from sonic_platform_base.sensor_fs import VoltageSensorFs
9+
from sonic_platform_base.sensor_fs import CurrentSensorFs
10+
11+
yaml_data = """
12+
voltage_sensors:
13+
- name : VSENSOR1
14+
sensor: 'sensor_data/VSENSOR1'
15+
high_thresholds: [ 1000, 1050, 1080 ]
16+
low_thresholds: [ 800, 850, 890 ]
17+
- name : VSENSOR2
18+
sensor: 'sensor_data/VSENSOR2'
19+
high_thresholds: [ 800, 850, 870 ]
20+
low_thresholds: [ 600, 620, 750 ]
21+
22+
current_sensors:
23+
- name : CSENSOR1
24+
sensor: 'sensor_data/CSENSOR1'
25+
high_thresholds: [ 1000, 1050, 1080 ]
26+
low_thresholds: [ 800, 850, 890 ]
27+
- name : CSENSOR2
28+
sensor: 'sensor_data/CSENSOR2'
29+
high_thresholds: [ 800, 850, 870 ]
30+
low_thresholds: [ 600, 620, 750 ]
31+
"""
32+
33+
class TestSensorFs:
34+
'''
35+
Collection of SensorFs test methods
36+
'''
37+
38+
@staticmethod
39+
def test_sensor_fs():
40+
'''
41+
Test voltage sensors
42+
'''
43+
sensors_data = yaml.safe_load(yaml_data)
44+
45+
vsensors = VoltageSensorFs.factory(VoltageSensorFs, sensors_data['voltage_sensors'])
46+
csensors = CurrentSensorFs.factory(CurrentSensorFs, sensors_data['current_sensors'])
47+
48+
assert(vsensors[0].get_name() == 'VSENSOR1')
49+
assert(vsensors[0].get_position_in_parent() == 1)
50+
51+
vsensors[0].set_high_threshold(800)
52+
assert(vsensors[0].get_high_threshold() == 800)
53+
vsensors[0].set_high_critical_threshold(900)
54+
assert(vsensors[0].get_high_critical_threshold() == 900)
55+
56+
vsensors[0].set_low_threshold(500)
57+
assert(vsensors[0].get_low_threshold() == 500)
58+
vsensors[0].set_low_critical_threshold(400)
59+
assert(vsensors[0].get_low_critical_threshold() == 400)
60+
61+
assert(csensors[0].get_name() == 'CSENSOR1')
62+
assert(csensors[0].get_position_in_parent() == 1)
63+
64+
csensors[0].set_high_threshold(800)
65+
assert(csensors[0].get_high_threshold() == 800)
66+
csensors[0].set_high_critical_threshold(900)
67+
assert(csensors[0].get_high_critical_threshold() == 900)
68+
69+
csensors[0].set_low_threshold(500)
70+
assert(csensors[0].get_low_threshold() == 500)
71+
csensors[0].set_low_critical_threshold(400)
72+
assert(csensors[0].get_low_critical_threshold() == 400)
73+
74+
assert(vsensors[0].get_minimum_recorded() == None)
75+
76+
tests_path = os.path.dirname(os.path.abspath(__file__))
77+
vsensor_path = os.path.join(tests_path, "sensor_data/VSENSOR1")
78+
vsensors[0].sensor = vsensor_path
79+
print(vsensor_path, vsensors[0])
80+
81+
assert(vsensors[0].get_value() == 900)
82+
assert(vsensors[0].get_minimum_recorded() == 900)
83+
assert(vsensors[0].get_maximum_recorded() == 900)

0 commit comments

Comments
 (0)