From 50db0f47c8584edf33943613739ccc8e11440697 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 13 Jan 2022 15:02:31 -0500 Subject: [PATCH 1/5] inital commit --- mudpi/extensions/ds18b20/__init__.py | 12 +++ mudpi/extensions/ds18b20/extension.json | 9 ++ mudpi/extensions/ds18b20/sensor.py | 129 ++++++++++++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 mudpi/extensions/ds18b20/__init__.py create mode 100644 mudpi/extensions/ds18b20/extension.json create mode 100644 mudpi/extensions/ds18b20/sensor.py diff --git a/mudpi/extensions/ds18b20/__init__.py b/mudpi/extensions/ds18b20/__init__.py new file mode 100644 index 0000000..15b1738 --- /dev/null +++ b/mudpi/extensions/ds18b20/__init__.py @@ -0,0 +1,12 @@ +""" + DS18B20 Extension + Includes sensor interface for DS18B20. + Works for Dallas 1-wire temperature sensors. +""" +from mudpi.extensions import BaseExtension + + +class Extension(BaseExtension): + namespace = 'ds18b20' + update_interval = 60 + diff --git a/mudpi/extensions/ds18b20/extension.json b/mudpi/extensions/ds18b20/extension.json new file mode 100644 index 0000000..a46ca2e --- /dev/null +++ b/mudpi/extensions/ds18b20/extension.json @@ -0,0 +1,9 @@ +{ + "name": "DS18B20 1-Wire Temperature Sensor", + "namespace": "ds18b20", + "details": { + "description": "Provides interface for ds18b20 sensors to take tempurature readings.", + "documentation": "https://mudpi.app/docs/sensors/ds18b20" + }, + "requirements": ["glob2", "python-time"] +} diff --git a/mudpi/extensions/ds18b20/sensor.py b/mudpi/extensions/ds18b20/sensor.py new file mode 100644 index 0000000..3188e7a --- /dev/null +++ b/mudpi/extensions/ds18b20/sensor.py @@ -0,0 +1,129 @@ +""" + DS18B20 Sensor Interface + Connects to a DS18B20 device to get + temperature readings. +""" +import os +import glob +import time + +from mudpi.constants import METRIC_SYSTEM +from mudpi.extensions import BaseInterface +from mudpi.extensions.sensor import Sensor +from mudpi.logger.Logger import Logger, LOG_LEVEL +from mudpi.exceptions import MudPiError, ConfigError + +os.system('modprobe w1-gpio') +os.system('modprobe w1-therm') + + +#device_folder = '/sys/bus/w1/devices/28-01206308503c' +#device_folder = glob.glob(base_dir + '/28*')[0] +#device_file = device_folder + '/w1_slave' + +class Interface(BaseInterface): + + def load(self, config): + """ Load DS18B20 sensor component from configs """ + sensor = ds18b20(self.mudpi, config) + self.add_component(sensor) + return True + + def validate(self, config): + if not isinstance(config, list): + config = [config] + + for conf in config: + """ See if 1-wire ID was passed by the user in the config file """ + if not conf.get('onewireID'): + Logger.log( + LOG_LEVEL["debug"], + 'DS18B20 onewireID not set. Will search for device.' + ) + + return config + +class ds18b20(Sensor): + """ DS18B20 Sensor get readings temperature. """ + + """ Properties """ + @property + def id(self): + """ Return a unique id for the component """ + return self.config['key'] + + @property + def name(self): + """ Return the display name of the component """ + return self.config.get('name') or f"{self.id.replace('_', ' ').title()}" + + @property + def state(self): + """ Return the state of the component (from memory, no IO!) """ + return self._state + + @property + def classifier(self): + """ Classification further describing it, effects the data formatting """ + return 'temperature' + + @property + def onewireID(self): + return self.config['onewireID'] + + + """ Methods """ + def init(self): + """To support multiple 1-wire devices check to see if the ID is set in the config. + If the ID is not set, there should only be a single 28-xxxxxxxxx directory in the base directory, so we use that. """ + + base_dir = '/sys/bus/w1/devices' + + if self.config.get('onewireID') and os.path.isdir(base_dir + '/' + self.config.get('onewireID')): + device_file = base_dir + '/' + self.config.get('onewireID') + '/w1_slave' + else: + Logger.log( + LOG_LEVEL["debug"], + 'DS18B20 onewireID not set or not found.' + ) + """ Make sure 1-wire device directory exists """ + try: + device_folder = glob.glob(base_dir + '/28*')[0] + except: + Logger.log( + LOG_LEVEL["error"], + 'Failed to find 1-wire device directory. Ensure device is connected and onewireID corret..' + ) + else: + self.device_file = device_folder + '/w1_slave' + return True + + def update(self): + + def read_temp_raw(): + f = open(self.device_file, 'r') + lines = f.readlines() + f.close() + return lines + + lines = read_temp_raw() + while lines[0].strip()[-3:] != 'YES': + time.sleep(0.2) + lines = read_temp_raw() + equals_pos = lines[1].find('t=') + if equals_pos != -1: + temp_string = lines[1][equals_pos+2:] + temperature_c = float(temp_string) / 1000.0 + temperature_f = temperature_c * 9.0 / 5.0 + 32.0 + _temperature = round(temperature_c if self.mudpi.unit_system == METRIC_SYSTEM else temperature_f, 2) + readings = { + 'temperature': _temperature, + } + self._state = readings + return readings + else: + Logger.log( + LOG_LEVEL["error"], + 'Failed to get reading [DS18B20]. Try again!' + ) + return None From 81b82c2d1c6fecf376e977bafa493ee478e8763f Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 13 Jan 2022 17:26:11 -0500 Subject: [PATCH 2/5] cleaning up testing bits and adding some logging --- mudpi/extensions/ds18b20/sensor.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/mudpi/extensions/ds18b20/sensor.py b/mudpi/extensions/ds18b20/sensor.py index 3188e7a..2c325ea 100644 --- a/mudpi/extensions/ds18b20/sensor.py +++ b/mudpi/extensions/ds18b20/sensor.py @@ -74,13 +74,17 @@ def onewireID(self): """ Methods """ def init(self): - """To support multiple 1-wire devices check to see if the ID is set in the config. + """To support multiple 1-wire devices check to see if the ID is set in the config. If the ID is not set, there should only be a single 28-xxxxxxxxx directory in the base directory, so we use that. """ base_dir = '/sys/bus/w1/devices' if self.config.get('onewireID') and os.path.isdir(base_dir + '/' + self.config.get('onewireID')): - device_file = base_dir + '/' + self.config.get('onewireID') + '/w1_slave' + self.device_file = base_dir + '/' + self.config.get('onewireID') + '/w1_slave' + Logger.log( + LOG_LEVEL["debug"], + 'Setting device file to ' + self.device_file + ) else: Logger.log( LOG_LEVEL["debug"], From b5c7bca25bb4c0da49d21e3fa8b79fcede0f5357 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 10 Nov 2022 10:43:03 -0500 Subject: [PATCH 3/5] Remove device specific ID --- mudpi/extensions/ds18b20/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mudpi/extensions/ds18b20/sensor.py b/mudpi/extensions/ds18b20/sensor.py index 2c325ea..72d516a 100644 --- a/mudpi/extensions/ds18b20/sensor.py +++ b/mudpi/extensions/ds18b20/sensor.py @@ -17,7 +17,7 @@ os.system('modprobe w1-therm') -#device_folder = '/sys/bus/w1/devices/28-01206308503c' +#device_folder = '/sys/bus/w1/devices/28-XXXXXXXXXXXXX' #device_folder = glob.glob(base_dir + '/28*')[0] #device_file = device_folder + '/w1_slave' From 4dd9c24f9ffd9f159ffc973f2070c5b06f99f247 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 10 Nov 2022 15:03:34 -0500 Subject: [PATCH 4/5] Fixed variable naming and adding docs. --- mudpi/extensions/ds18b20/docs.html | 41 ++++++++++++++++++++++++++++++ mudpi/extensions/ds18b20/sensor.py | 16 ++++++------ 2 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 mudpi/extensions/ds18b20/docs.html diff --git a/mudpi/extensions/ds18b20/docs.html b/mudpi/extensions/ds18b20/docs.html new file mode 100644 index 0000000..97335dd --- /dev/null +++ b/mudpi/extensions/ds18b20/docs.html @@ -0,0 +1,41 @@ +# DS18B20 +The `ds18b20` extension connects to a DS18B20 device to gather temperature readings. The sensor will return `tempurature`. + +This extension does not take an extension level configs and is focused on [interfaces.]({{url('docs/developers-interfaces')}}) + +--- +
+ +## Sensor Interface +Provides a [sensor]({{url('docs/sensors')}}) that returns a DS18B20 readings. + + + + + + + + +
OptionTypeRequiredDescription
key[String]YesUnique slug id for the component
name[String]NoFriendly display name of component. Useful for UI.
one_wire_ID[String]NoThe address of the DS18B20 sensor. This should be set if using mulitple DS18B20 sensors and can be found as a directory in `/sys/bus/w1/devices/` in the format of `28-XXXXXXXXXXXXX` . Default 10
+ +### Config Examples +Here is a config of a complete example sensor. + +```json +"sensor": [{ + "key": "ds18b20_outside", + "interface": "ds18b20", + "name": "Outside temperature", + "one_wire_ID": "28-0000000000001" +}] +``` + +### Data +Here is an example of the data returned by the DS18B20: + +```json +{ + "temperature": 50 +} +``` +--- \ No newline at end of file diff --git a/mudpi/extensions/ds18b20/sensor.py b/mudpi/extensions/ds18b20/sensor.py index 72d516a..95b8e0c 100644 --- a/mudpi/extensions/ds18b20/sensor.py +++ b/mudpi/extensions/ds18b20/sensor.py @@ -35,10 +35,10 @@ def validate(self, config): for conf in config: """ See if 1-wire ID was passed by the user in the config file """ - if not conf.get('onewireID'): + if not conf.get('one_wire_ID'): Logger.log( LOG_LEVEL["debug"], - 'DS18B20 onewireID not set. Will search for device.' + 'DS18B20 one_wire_ID not set. Will search for device.' ) return config @@ -68,8 +68,8 @@ def classifier(self): return 'temperature' @property - def onewireID(self): - return self.config['onewireID'] + def one_wire_ID(self): + return self.config['one_wire_ID'] """ Methods """ @@ -79,8 +79,8 @@ def init(self): base_dir = '/sys/bus/w1/devices' - if self.config.get('onewireID') and os.path.isdir(base_dir + '/' + self.config.get('onewireID')): - self.device_file = base_dir + '/' + self.config.get('onewireID') + '/w1_slave' + if self.config.get('one_wire_ID') and os.path.isdir(base_dir + '/' + self.config.get('one_wire_ID')): + self.device_file = base_dir + '/' + self.config.get('one_wire_ID') + '/w1_slave' Logger.log( LOG_LEVEL["debug"], 'Setting device file to ' + self.device_file @@ -88,7 +88,7 @@ def init(self): else: Logger.log( LOG_LEVEL["debug"], - 'DS18B20 onewireID not set or not found.' + 'DS18B20 one_wire_ID not set or not found.' ) """ Make sure 1-wire device directory exists """ try: @@ -96,7 +96,7 @@ def init(self): except: Logger.log( LOG_LEVEL["error"], - 'Failed to find 1-wire device directory. Ensure device is connected and onewireID corret..' + 'Failed to find 1-wire device directory. Ensure device is connected and one_wire_ID corret..' ) else: self.device_file = device_folder + '/w1_slave' From 91fd7b967bec41dacf46bb2ad441b3f197ed7161 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 10 Nov 2022 15:07:39 -0500 Subject: [PATCH 5/5] Sometimes I can spell, this was not one of those times. --- mudpi/extensions/ds18b20/docs.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mudpi/extensions/ds18b20/docs.html b/mudpi/extensions/ds18b20/docs.html index 97335dd..b5a1f94 100644 --- a/mudpi/extensions/ds18b20/docs.html +++ b/mudpi/extensions/ds18b20/docs.html @@ -1,5 +1,5 @@ # DS18B20 -The `ds18b20` extension connects to a DS18B20 device to gather temperature readings. The sensor will return `tempurature`. +The `ds18b20` extension connects to a DS18B20 device to gather temperature readings. The sensor will return `temperature`. This extension does not take an extension level configs and is focused on [interfaces.]({{url('docs/developers-interfaces')}})