Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
TrystanLea committed Nov 24, 2020
2 parents efec1ac + 317f86e commit c812091
Show file tree
Hide file tree
Showing 14 changed files with 1,227 additions and 87 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# emonHub

emonHub is used in the OpenEnergyMonitor system to read data received over serial from either the EmonPi board or the RFM12/69Pi adapter board then forward the data to emonCMS in a decoded ready-to-use form - based on the configuration in [emonhub.conf](https://github.com/openenergymonitor/emonhub/configuration.md)
emonHub is used in the OpenEnergyMonitor system to read data received over serial from either the EmonPi board or the RFM12/69Pi adapter board then forward the data to emonCMS in a decoded ready-to-use form - based on the configuration in [emonhub.conf](conf/emonhub.conf)

More generally: Emonhub consists of a series of interfacers that can read/subscribe or send/publish data to and from a multitude of services. EmonHub supports decoding data from:

Expand Down Expand Up @@ -84,7 +84,7 @@ journalctl -f -u emonhub

The emonhub configuration guide can be found here:

[emonhub.conf configuration](https://github.com/openenergymonitor/emonhub/configuration.md)
[emonhub.conf configuration](configuration.md)

## EmonHub Emoncms config module

Expand Down
6 changes: 3 additions & 3 deletions configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Hub is a section for emonhub global settings such as the loglevel.

## 2. `interfacers`

Interfacers holds the configuration for the different interfacers that emonhub supports such as the EmonHubJeeInterfacer for reading and writing to the RFM69Pi adapter board or emonPi board via serial, or the EmonHubMqttInterfacer which can be used to publish the data received from EmonHubJeeInterfacer to MQTT topics. For more interfacer examples see [conf/interfacer_examples](https://github.com/openenergymonitor/emonhub/conf/interfacer_examples)
Interfacers holds the configuration for the different interfacers that emonhub supports such as the EmonHubJeeInterfacer for reading and writing to the RFM69Pi adapter board or emonPi board via serial, or the EmonHubMqttInterfacer which can be used to publish the data received from EmonHubJeeInterfacer to MQTT topics. For more interfacer examples see [conf/interfacer_examples](conf/interfacer_examples)

### Channels

Expand Down Expand Up @@ -54,7 +54,7 @@ Nodes holds the decoder configuration for rfm12/69 node data which are sent as b
[nodes]
```

**View full latest [default emonHub.conf](https://github.com/openenergymonitor/emonhub/conf/emonpi.default.emonhub.conf)**
**View full latest [default emonHub.conf](conf/emonpi.default.emonhub.conf)**

***

Expand Down Expand Up @@ -126,7 +126,7 @@ There are two formats that can be used for publishing node data to MQTT:
payload: 100,200,300
```

The 'node only format' is used with the emoncms [Nodes Module](https://github.com/emoncms/nodes) (now deprecated on Emoncms V9+) and the emonPiLCD python service.
The 'node only format' is used with the emoncms Nodes Module (now deprecated on Emoncms V9+) and the emonPiLCD python service.

#### **2. Node variable format**

Expand Down
2 changes: 1 addition & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ if [ "$emonSD_pi_env" = "" ]; then
fi

sudo apt-get install -y python3-serial python3-configobj python3-pip python3-pymodbus bluetooth libbluetooth-dev
sudo pip3 install paho-mqtt requests pybluez
sudo pip3 install paho-mqtt requests pybluez py-sds011 sdm_modbus

if [ "$emonSD_pi_env" = "1" ]; then
# Only install the GPIO library if on a Pi. Used by Pulse interfacer
Expand Down
8 changes: 6 additions & 2 deletions src/emonhub.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,16 @@ def _update_settings(self, settings):
if 'log_backup_count' in settings['hub']:
for handler in self._log.handlers:
if isinstance(handler, logging.handlers.RotatingFileHandler):
handler.backupCount = settings['hub']['log_backup_count']
handler.backupCount = int(settings['hub']['log_backup_count'])
self._log.info("Logging backup count set to %d", handler.backupCount)
if 'log_max_bytes' in settings['hub']:
for handler in self._log.handlers:
if isinstance(handler, logging.handlers.RotatingFileHandler):
handler.maxBytes = settings['hub']['log_max_bytes']
handler.maxBytes = int(settings['hub']['log_max_bytes'])
self._log.info("Logging max file size set to %d bytes", handler.maxBytes)

# Interfacers
interfacers_to_delete = []
for name in self._interfacers:
# Delete interfacers if not listed or have no 'Type' in the settings without further checks
# (This also provides an ability to delete & rebuild by commenting 'Type' in conf)
Expand All @@ -197,6 +198,9 @@ def _update_settings(self, settings):
# Delete interfacers if setting changed or name is unlisted or Type is missing
self._log.info("Deleting interfacer '%s'", name)
self._interfacers[name].stop = True
interfacers_to_delete.append(name)

for name in interfacers_to_delete:
del self._interfacers[name]

for name, I in settings['interfacers'].items():
Expand Down
157 changes: 157 additions & 0 deletions src/interfacers/EmonHubDS18B20Interfacer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import time
import json
import Cargo
import os
import glob
from emonhub_interfacer import EmonHubInterfacer

"""
[[DS18B20]]
Type = EmonHubDS18B20Interfacer
[[[init_settings]]]
[[[runtimesettings]]]
pubchannels = ToEmonCMS,
read_interval = 10
ids = 28-000008e2db06, 28-000009770529, 28-0000096a49b4
names = ambient, cylb, cylt
"""

class DS18B20:
def __init__(self):
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
self._base_dir = '/sys/bus/w1/devices/'

def scan(self):
devices = glob.glob(self._base_dir + '28*')
sensors = []
for device in devices:
sensor = device.replace(self._base_dir,"")
sensors.append(sensor)
return sensors

def _read_raw(self,sensor):
f = open(self._base_dir + sensor + '/w1_slave', 'r')
lines = f.readlines()
f.close()
return lines

def tempC(self,sensor):
lines = self._read_raw(sensor)
# retry = 0
while lines[0].strip()[-3:] != 'YES':
# time.sleep(0.2)
# lines = self._read_raw(sensor)
# retry += 1
# if retry==3: return False
return False

equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
return temp_c

"""class EmonHubDS18B20Interfacer
DS18B20 interfacer for use in development
"""

class EmonHubDS18B20Interfacer(EmonHubInterfacer):

def __init__(self, name):
"""Initialize Interfacer
"""
# Initialization
super(EmonHubDS18B20Interfacer, self).__init__(name)

# This line will stop the default values printing to logfile at start-up
# self._settings.update(self._defaults)

# Interfacer specific settings
self._DS18B20_settings = {'read_interval': 10.0,'nodename':'sensors','ids':[],'names':[]}

self.ds = DS18B20()

self.next_interval = True


def read(self):
"""Read data and process
Return data as a list: [NodeID, val1, val2]
"""

if int(time.time())%self._settings['read_interval']==0:
if self.next_interval:
self.next_interval = False

c = Cargo.new_cargo()
c.names = []
c.realdata = []
c.nodeid = self._settings['nodename']

if self.ds:
for sensor in self.ds.scan():
# Check if user has set a name for given sensor id
name = sensor
try:
index = self._settings['ids'].index(sensor)
if index<len(self._settings['names']):
name = self._settings['names'][index]
except ValueError:
pass

# Read sensor value
value = self.ds.tempC(sensor)

# Add sensor to arrays
c.names.append(name)
c.realdata.append(value)

# Log output
self._log.debug(sensor+": "+name+" "+str(value))

if len(c.realdata)>0:
return c

else:
self.next_interval = True

return False


def set(self, **kwargs):
for key, setting in self._DS18B20_settings.items():
# Decide which setting value to use
if key in kwargs:
setting = kwargs[key]
else:
setting = self._DS18B20_settings[key]

if key in self._settings and self._settings[key] == setting:
continue
elif key == 'read_interval':
self._log.info("Setting %s read_interval: %s", self.name, setting)
self._settings[key] = float(setting)
continue
elif key == 'nodename':
self._log.info("Setting %s nodename: %s", self.name, setting)
self._settings[key] = str(setting)
continue
elif key == 'ids':
self._log.info("Setting %s ids: %s", self.name, ", ".join(setting))
self._settings[key] = setting
continue
elif key == 'names':
self._log.info("Setting %s names: %s", self.name, ", ".join(setting))
self._settings[key] = setting
continue
else:
self._log.warning("'%s' is not valid for %s: %s", setting, self.name, key)

# include kwargs from parent
super().set(**kwargs)
2 changes: 1 addition & 1 deletion src/interfacers/EmonHubGraphiteInterfacer.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def _send_metrics(self, metrics=[]):
try:
sock = socket.socket()
sock.connect((host, port))
sock.sendall(message)
sock.sendall(message.encode())
sock.close()
except socket.error as e:
self._log.error(e)
Expand Down
Loading

0 comments on commit c812091

Please sign in to comment.