Add basic tempmon-client command
This commit is contained in:
parent
c1bfa903db
commit
c117f53a82
0
hotcooler/tempmon/__init__.py
Normal file
0
hotcooler/tempmon/__init__.py
Normal file
139
hotcooler/tempmon/client.py
Normal file
139
hotcooler/tempmon/client.py
Normal file
|
@ -0,0 +1,139 @@
|
|||
"""
|
||||
Tempmon Client
|
||||
|
||||
Responsible for reading temperatures from probes, and recording to database
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import time
|
||||
import datetime
|
||||
import random
|
||||
import socket
|
||||
import logging
|
||||
|
||||
from sqlalchemy.orm.exc import NoResultFound
|
||||
|
||||
from websauna.system.devop.cmdline import init_websauna
|
||||
|
||||
from hotcooler import models
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TempmonClient:
|
||||
"""
|
||||
Linux daemon implementation of Tempmon client
|
||||
"""
|
||||
# must set this to a sessionmaker
|
||||
Session = None
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
This method is invoked upon daemon startup. It is meant to run/loop
|
||||
"forever" or until daemon stop.
|
||||
"""
|
||||
# maybe generate random data instead of reading from true probe
|
||||
# self.dummy_probes = self.config.getbool('tempmon.client', 'dummy_probes', default=False)
|
||||
self.dummy_probes = True # TODO
|
||||
|
||||
# figure out which client we are
|
||||
# hostname = self.config.get('tempmon.client', 'hostname', default=socket.gethostname())
|
||||
hostname = 'demo.rattail-tempmon.org' # TODO
|
||||
session = self.Session()
|
||||
try:
|
||||
client = session.query(models.Client)\
|
||||
.filter_by(hostname=hostname)\
|
||||
.one()
|
||||
except NoResultFound:
|
||||
session.close()
|
||||
raise RuntimeError("No tempmon client configured for hostname: {}".format(hostname))
|
||||
client_uuid = client.uuid
|
||||
self.delay = client.delay or 60
|
||||
session.close()
|
||||
|
||||
# main loop: take readings, pause, repeat
|
||||
while True:
|
||||
|
||||
session = self.Session()
|
||||
|
||||
try:
|
||||
client = session.query(models.Client).filter_by(uuid=client_uuid).one()
|
||||
self.delay = client.delay or 60
|
||||
if client.enabled:
|
||||
for probe in client.enabled_probes():
|
||||
self.take_reading(session, probe)
|
||||
|
||||
except:
|
||||
log.exception("Failed to read/record temperature data (but will keep trying)")
|
||||
session.rollback()
|
||||
|
||||
else:
|
||||
# make sure we show as being online
|
||||
if not client.online:
|
||||
client.online = True
|
||||
session.commit()
|
||||
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
time.sleep(self.delay)
|
||||
|
||||
def take_reading(self, session, probe):
|
||||
"""
|
||||
Take a single reading and add to Rattail database.
|
||||
"""
|
||||
reading = models.Reading()
|
||||
reading.client = probe.client
|
||||
reading.probe = probe
|
||||
reading.degrees_f = self.read_temp(probe)
|
||||
reading.taken = datetime.datetime.utcnow()
|
||||
session.add(reading)
|
||||
return reading
|
||||
|
||||
def read_temp(self, probe):
|
||||
"""
|
||||
Check for good reading, then format temperature to our liking
|
||||
"""
|
||||
if self.dummy_probes:
|
||||
return self.random_temp(probe)
|
||||
lines = self.read_temp_raw(probe)
|
||||
while lines[0].strip()[-3:] != 'YES':
|
||||
time.sleep(0.2)
|
||||
lines = self.read_temp_raw(probe)
|
||||
equals_pos = lines[1].find('t=')
|
||||
if equals_pos != -1:
|
||||
temp_string = lines[1][equals_pos+2:]
|
||||
temp_c = float(temp_string) / 1000.0
|
||||
temp_f = temp_c * 9.0 / 5.0 + 32.0
|
||||
return round(temp_f,4)
|
||||
|
||||
def read_temp_raw(self, probe):
|
||||
"""
|
||||
Function that gets the raw temp data
|
||||
"""
|
||||
with open(probe.device_path, 'rt') as therm_file:
|
||||
return therm_file.readlines()
|
||||
|
||||
def random_temp(self, probe):
|
||||
temp = random.uniform(probe.critical_temp_min - 5, probe.critical_temp_max + 5)
|
||||
return round(temp, 4)
|
||||
|
||||
|
||||
def tempmon_client_command(*args):
|
||||
"""
|
||||
Manage the hotcooler tempmon-client daemon
|
||||
"""
|
||||
parser = argparse.ArgumentParser(prog='tempmon-client',
|
||||
description=tempmon_client_command.__doc__.strip())
|
||||
|
||||
parser.add_argument('config_uri', help="Path to main config file")
|
||||
|
||||
args = parser.parse_args(args or sys.argv[1:])
|
||||
request = init_websauna(args.config_uri, console_app=True)
|
||||
session = request.dbsession
|
||||
|
||||
client = TempmonClient()
|
||||
client.Session = request.registry.db_session_maker
|
||||
client.run()
|
18
setup.py
18
setup.py
|
@ -18,7 +18,8 @@ if len(sys.argv) >= 2:
|
|||
raise RuntimeError("It is not possible to install this package with setup.py. Use pip to install this package as instructed in Websauna tutorial.")
|
||||
|
||||
|
||||
setup(name='hotcooler',
|
||||
setup(
|
||||
name='hotcooler',
|
||||
version='0.0',
|
||||
description='hotcooler',
|
||||
long_description=README + '\n\n' + CHANGES,
|
||||
|
@ -55,9 +56,12 @@ setup(name='hotcooler',
|
|||
'dev': ['websauna[dev]'],
|
||||
},
|
||||
|
||||
# Define where this application starts as referred by WSGI web servers
|
||||
entry_points="""\
|
||||
[paste.app_factory]
|
||||
main = hotcooler:main
|
||||
""",
|
||||
)
|
||||
entry_points = {
|
||||
'paste.app_factory': [
|
||||
'main = hotcooler:main',
|
||||
],
|
||||
'console_scripts': [
|
||||
'tempmon-client = hotcooler.tempmon.client:tempmon_client_command',
|
||||
],
|
||||
},
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue