Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
temperature-daemon
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
External wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
stustanet
temperature-daemon
Commits
47f050d7
Commit
47f050d7
authored
10 years ago
by
Markus Hefele
Browse files
Options
Downloads
Patches
Plain Diff
nearly complete rewrite, temp grad detection, fix missed logging bug
parent
e28d83d4
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
temperdaemon.py
+207
-174
207 additions, 174 deletions
temperdaemon.py
with
207 additions
and
174 deletions
temperdaemon.py
+
207
−
174
View file @
47f050d7
...
...
@@ -13,11 +13,16 @@ import time
import
Queue
import
smtplib
import
ow
import
logging
from
collections
import
deque
,
namedtuple
from
email.mime.text
import
MIMEText
from
email.Utils
import
formatdate
logging
.
basicConfig
(
format
=
'
%(asctime)s:%(name)s:%(levelname)s:%(message)s
'
,
level
=
logging
.
DEBUG
)
logger
=
logging
.
getLogger
(
__name__
)
logger
.
setLevel
(
logging
.
DEBUG
)
READINGINTERVAL
=
10
EXPORTINTERVAL
=
10
UNIX_SOCKET
=
"
/var/run/collectd-unixsock
"
...
...
@@ -30,80 +35,21 @@ MAX_OUTDOOR_DIFF = 10
MAILINTERVAL
=
3600
DEBUG
=
False
#DEBUG = True
SPAM
=
False
#SPAM = True
class
TempReader
(
threading
.
Thread
):
def
__init__
(
self
,
mq
):
def
__init__
(
self
,
export_queue
,
mail_queue
):
threading
.
Thread
.
__init__
(
self
)
self
.
mq
=
mq
self
.
export_queue
=
export_queue
self
.
mail_queue
=
mail_queue
self
.
last_mail
=
0
self
.
iteration
=
0
def
run
(
self
):
while
True
:
try
:
th
=
temper
.
TemperHandler
()
# TODO naming things is hard!
for
i
,
temp_device
in
th
.
_devices
.
iteritems
():
temp_sensor
=
temperature_sensors
.
get
(
i
)
if
temp_sensor
:
try
:
temp_c
=
temp_device
.
get_temperature
(
calibration
=
temp_sensor
.
calibration
)
temp_sensor
.
update
(
temp_c
)
except
:
pass
ow
.
init
(
'
localhost:4304
'
)
for
a
,
owid
in
iter
(
temperature_sensors
):
if
a
==
'
serial
'
:
temp_sensor
=
temperature_sensors
.
get
((
a
,
owid
))
try
:
temp_c
=
float
(
ow
.
Sensor
(
'
/uncached/
'
+
owid
).
temperature
)
if
temp_c
!=
float
(
'
85
'
):
temp_sensor
.
update
(
temp_c
)
except
:
pass
ow
.
finish
()
self
.
iteration
+=
1
except
:
pass
floor
=
temperature_sensors_usb_by_name
[
'
floor
'
].
temperature
floorserial
=
temperature_sensors_serial_by_name
[
'
floorserial
'
].
temperature
ceiling
=
temperature_sensors_usb_by_name
[
'
ceiling
'
].
temperature
ceilserial
=
temperature_sensors_serial_by_name
[
'
ceilserial
'
].
temperature
outdoor
=
temperature_sensors_usb_by_name
[
'
outdoor
'
].
temperature
# error case: some sensor is not working!
if
floor
is
None
:
floor
=
9000
if
ceiling
is
None
:
ceiling
=
9001
if
outdoor
is
None
:
# for the difference ...
outdoor
=
0
if
self
.
iteration
>
1
and
self
.
last_mail
+
MAILINTERVAL
<
time
.
time
()
and
\
((
floor
>
FLOOR_LIMIT
and
floor
-
MAX_OUTDOOR_DIFF
>
outdoor
)
or
\
(
ceiling
>
CEILING_LIMIT
and
ceiling
-
MAX_OUTDOOR_DIFF
>
outdoor
)):
self
.
last_mail
=
time
.
time
()
if
DEBUG
:
print
"
write mail ...
"
def
queue_mail
(
self
,
floor
,
ceiling
,
outdoor
):
logger
.
debug
(
"
write mail ...
"
)
body
=
u
'''
DON
'
T PANIC!
body
=
u
'''
DON
'
T PANIC!
...
aber
die
Temperatur
im
Serverraum
beträgt
:
Boden
:
{:.
2
f
}
℃
...
...
@@ -140,35 +86,120 @@ oo $ $ "$ o$$$$$$$$$ $$$$$$$$$$$$$ $$$$$$$$$o $$$o$$o$
"
$$$
""""
'''
msg
=
MIMEText
(
body
.
format
(
floor
,
ceiling
,
outdoor
),
_charset
=
"
UTF-8
"
)
src
=
"
Temperator <root@hugin.stusta.mhn.de>
"
msg
[
'
Subject
'
]
=
u
"
Temperaturalarm Serverraum
"
msg
[
'
From
'
]
=
src
if
SPAM
:
dst
=
[
"
jn@stusta.de
"
,
"
maxi@stusta.de
"
]
else
:
dst
=
[
"
admins@stustanet.de
"
]
msg
[
'
To
'
]
=
"
,
"
.
join
(
dst
)
msg
[
'
Date
'
]
=
formatdate
(
localtime
=
True
)
msg
=
MIMEText
(
body
.
format
(
floor
,
ceiling
,
outdoor
),
_charset
=
"
UTF-8
"
)
src
=
"
Temperator <root@hugin.stusta.mhn.de>
"
msg
[
'
Subject
'
]
=
u
"
Temperaturalarm Serverraum
"
msg
[
'
From
'
]
=
src
if
SPAM
:
dst
=
[
"
jn@stusta.de
"
,
"
maxi@stusta.de
"
,
"
markus.hefele@stusta.net
"
]
else
:
dst
=
[
"
admins@stustanet.de
"
]
msg
[
'
To
'
]
=
"
,
"
.
join
(
dst
)
msg
[
'
Date
'
]
=
formatdate
(
localtime
=
True
)
self
.
mail_queue
.
put
((
src
,
dst
,
msg
.
as_string
()))
def
run
(
self
):
while
True
:
logger
.
debug
(
"
reading loop
"
)
start
=
time
.
time
()
try
:
th
=
temper
.
TemperHandler
()
# TODO naming things is hard!
for
i
,
temp_device
in
th
.
_devices
.
iteritems
():
temp_sensor
=
temperature_sensors
.
get
(
i
)
if
temp_sensor
:
try
:
temp_c
=
temp_device
.
get_temperature
(
calibration
=
temp_sensor
.
calibration
)
record
=
temp_sensor
.
update
(
temp_c
)
self
.
export_queue
.
put
(
record
)
except
Exception
as
e
:
logger
.
debug
(
e
)
#logger.exception(e)
except
Exception
as
e
:
logger
.
exception
(
e
)
try
:
ow
.
init
(
'
localhost:4304
'
)
for
a
,
owid
in
iter
(
temperature_sensors
):
if
a
==
'
serial
'
:
temp_sensor
=
temperature_sensors
.
get
((
a
,
owid
))
try
:
temp_c
=
float
(
ow
.
Sensor
(
'
/uncached/
'
+
owid
).
temperature
)
if
temp_c
!=
float
(
'
85
'
):
record
=
temp_sensor
.
update
(
temp_c
)
self
.
export_queue
.
put
(
record
)
except
Exception
as
e
:
logger
.
debug
(
e
)
# memory leak?
#ow.finish()
except
Exception
as
e
:
logger
.
exception
(
e
)
self
.
iteration
+=
1
self
.
mq
.
put
((
src
,
dst
,
msg
.
as_string
()))
now
=
time
.
time
()
floor
,
floor_last
,
floor_avg
=
temperature_sensors_usb_by_name
[
'
floor
'
].
get_current_and_average
()
ceiling
,
ceiling_last
,
ceiling_avg
=
temperature_sensors_usb_by_name
[
'
ceiling
'
].
get_current_and_average
()
outdoor
,
outdoor_last
,
outdoor_avg
=
temperature_sensors_usb_by_name
[
'
outdoor
'
].
get_current_and_average
()
falling
=
False
if
(
floor
is
not
None
and
floor_avg
is
not
None
and
floor
<=
floor_avg
and
ceiling
is
not
None
and
ceiling_avg
is
not
None
and
ceiling
<=
ceiling_avg
and
outdoor
is
not
None
and
outdoor_avg
is
not
None
and
outdoor
<=
outdoor_avg
):
falling
=
True
# error case: some sensor is not working!
error
=
False
if
floor
is
None
or
(
floor_last
is
not
None
and
floor_last
+
MAILINTERVAL
<
now
):
error
=
True
floor
=
9000
if
ceiling
is
None
or
(
ceiling_last
is
not
None
and
ceiling_last
+
MAILINTERVAL
<
now
):
error
=
True
ceiling
=
9001
if
outdoor
is
None
or
(
outdoor_last
is
not
None
and
outdoor_last
+
MAILINTERVAL
<
now
):
# for the difference ...
error
=
True
outdoor
=
0
if
(
self
.
iteration
>
1
and
self
.
last_mail
+
MAILINTERVAL
<
now
and
(
error
or
(
not
falling
and
((
floor
>
FLOOR_LIMIT
and
floor
-
MAX_OUTDOOR_DIFF
>
outdoor
)
or
(
ceiling
>
CEILING_LIMIT
and
ceiling
-
MAX_OUTDOOR_DIFF
>
outdoor
))))):
self
.
last_mail
=
now
self
.
queue_mail
(
floor
,
ceiling
,
outdoor
)
sys
.
stdout
.
flush
()
time
.
sleep
(
READINGINTERVAL
)
wait
=
start
+
READINGINTERVAL
-
time
.
time
()
if
wait
>
0
:
time
.
sleep
(
wait
)
class
Mail0r
(
threading
.
Thread
):
def
__init__
(
self
,
m
q
):
def
__init__
(
self
,
m
ail_queue
):
threading
.
Thread
.
__init__
(
self
)
self
.
m
q
=
mq
self
.
m
ail_queue
=
mail_queue
def
run
(
self
):
while
True
:
try
:
sender
,
recipient
,
msg
=
self
.
mq
.
get
(
True
,
3600
)
except
Exception
as
e
:
if
DEBUG
:
print
e
sender
,
recipient
,
msg
=
self
.
mail_queue
.
get
(
True
,
3600
)
except
Queue
.
Empty
as
e
:
logger
.
debug
(
e
)
continue
try
:
...
...
@@ -176,19 +207,29 @@ class Mail0r(threading.Thread):
s
.
sendmail
(
sender
,
recipient
,
msg
)
s
.
quit
()
except
Exception
as
e
:
if
DEBUG
:
print
e
pass
logger
.
debug
(
e
)
CollectdRecord
=
namedtuple
(
"
CollectdRecord
"
,
[
"
hostname
"
,
"
path
"
,
"
interval
"
,
"
epoch
"
,
"
value
"
])
class
Exp0rt0r
(
threading
.
Thread
):
def
__init__
(
self
):
def
__init__
(
self
,
export_queue
):
threading
.
Thread
.
__init__
(
self
)
self
.
socket
=
None
# CollectdRecords
self
.
export_queue
=
export_queue
def
run
(
self
):
while
True
:
record
=
None
try
:
record
=
self
.
export_queue
.
get
(
True
,
3600
)
except
Queue
.
Empty
as
e
:
continue
if
not
self
.
socket
:
s
=
socket
.
socket
(
socket
.
AF_UNIX
)
try
:
...
...
@@ -196,120 +237,112 @@ class Exp0rt0r(threading.Thread):
s
.
setblocking
(
False
)
self
.
socket
=
s
except
Exception
as
e
:
if
DEBUG
:
print
e
pass
for
temp_sensor
in
temperature_sensors
.
values
():
temp_c
,
exported
=
temp_sensor
.
get_export
()
if
self
.
socket
and
not
exported
:
data
=
"
PUTVAL
\"
%s/tail-temperature/temperature-%s
\"
interval=%i N:%f
\n
"
%
\
(
HOSTNAME
,
temp_sensor
.
name
,
EXPORTINTERVAL
,
temp_c
)
try
:
if
DEBUG
:
print
"
socket write
"
,
data
.
strip
()
self
.
socket
.
send
(
data
)
logger
.
debug
(
e
)
time
.
sleep
(
1
)
continue
recv
=
[]
while
True
:
try
:
recv
=
self
.
socket
.
recv
(
2
**
12
)
except
socket
.
error
as
e
:
if
e
.
errno
==
11
:
#EAGAIN
break
raise
e
data
=
"
PUTVAL
\"
%s/%s
\"
interval=%i %i:%s
\n
"
%
\
(
record
.
hostname
,
record
.
path
,
int
(
record
.
interval
),
int
(
record
.
epoch
),
record
.
value
)
recv
=
''
.
join
(
recv
)
try
:
logger
.
debug
(
"
socket write: %s
"
,
data
.
strip
())
self
.
socket
.
send
(
data
)
if
DEBUG
:
print
"
socket read
"
,
recv
.
strip
()
recv
=
[]
while
True
:
try
:
recv
=
self
.
socket
.
recv
(
1
<<
12
)
except
socket
.
error
as
e
:
if
e
.
errno
==
11
:
#EAGAIN
break
raise
e
recv
=
''
.
join
(
recv
)
except
Exception
as
e
:
if
DEBUG
:
print
e
try
:
self
.
socket
.
close
()
except
:
pass
self
.
socket
=
None
logger
.
debug
(
"
socket read: %s
"
,
recv
.
strip
())
time
.
sleep
(
EXPORTINTERVAL
)
except
Exception
as
e
:
logger
.
debug
(
e
)
try
:
self
.
socket
.
close
()
except
:
pass
self
.
socket
=
None
#TODO: baseclass TempSensor?
class
TempSensorUSB
():
def
__init__
(
self
,
name
,
calibration
,
bus
,
device
):
class
TempSensor
(
object
):
def
__init__
(
self
,
name
):
self
.
name
=
name
self
.
calibration
=
calibration
self
.
bus
=
bus
self
.
device
=
device
self
.
_path
=
"
tail-temperature/temperature-%s
"
%
(
name
,
)
self
.
_interval
=
READINGINTERVAL
self
.
last_updated
=
None
self
.
temperature
=
None
self
.
exported
=
True
self
.
history
=
deque
()
self
.
_lock
=
threading
.
RLock
()
@property
def
usb_id
(
self
):
return
self
.
bus
,
self
.
device
def
update
(
self
,
temperature
):
with
self
.
_lock
:
now
=
time
.
time
()
while
self
.
history
and
self
.
history
[
0
][
1
]
<
(
now
-
MAILINTERVAL
):
self
.
history
.
popleft
()
if
self
.
last_updated
is
not
None
and
self
.
temperature
is
not
None
:
self
.
history
.
append
((
self
.
temperature
,
self
.
last_updated
))
self
.
temperature
=
temperature
self
.
exported
=
False
self
.
last_updated
=
time
.
time
()
if
DEBUG
:
print
"
update
"
,
self
self
.
last_updated
=
now
logger
.
debug
(
"
update %s
"
,
self
)
def
get_export
(
self
):
return
CollectdRecord
(
HOSTNAME
,
self
.
_path
,
int
(
self
.
_interval
),
int
(
self
.
last_updated
),
"
%f
"
%
(
self
.
temperature
,))
def
get_current_and_average
(
self
):
with
self
.
_lock
:
exported
=
self
.
exported
self
.
exported
=
True
if
DEBUG
:
print
"
read
"
,
self
return
self
.
temperature
,
exported
avg
=
None
if
self
.
history
:
avg
=
float
(
sum
(
i
[
0
]
for
i
in
self
.
history
))
/
len
(
self
.
history
)
return
self
.
temperature
,
self
.
last_updated
,
avg
def
__str__
(
self
):
with
self
.
_lock
:
return
"
%s (bus:%s, device:%s, calibration:%i) temperature: %s, last_updated:%s, exported:%s
"
%
\
(
self
.
name
,
self
.
bus
,
self
.
device
,
self
.
calibration
,
self
.
temperature
,
self
.
last_updated
,
self
.
exported
)
return
"
%s temperature: %s, last_updated:%s
"
%
\
(
self
.
name
,
self
.
temperature
,
self
.
last_updated
)
class
TempSensorSerial
():
def
__init__
(
self
,
name
,
owid
):
self
.
name
=
name
self
.
owid
=
owid
self
.
last_updated
=
None
self
.
temperature
=
None
s
elf
.
exported
=
True
class
TempSensorUSB
(
TempSensor
):
def
__init__
(
self
,
name
,
calibration
,
bus
,
device
):
s
uper
(
TempSensorUSB
,
self
).
__init__
(
name
)
self
.
_lock
=
threading
.
RLock
()
self
.
calibration
=
calibration
self
.
bus
=
bus
self
.
device
=
device
def
update
(
self
,
temperature
):
with
self
.
_lock
:
self
.
temperature
=
temperature
self
.
exported
=
False
self
.
last_updated
=
time
.
time
()
if
DEBUG
:
print
"
update
"
,
self
@property
def
usb_id
(
self
):
return
self
.
bus
,
self
.
device
def
get_export
(
self
):
def
__str__
(
self
):
with
self
.
_lock
:
exported
=
self
.
exported
self
.
exported
=
True
if
DEBUG
:
print
"
read
"
,
self
return
self
.
temperature
,
exported
return
"
%s (bus:%s, device:%s, calibration:%i) temperature: %s, last_updated:%s
"
%
\
(
self
.
name
,
self
.
bus
,
self
.
device
,
self
.
calibration
,
self
.
temperature
,
self
.
last_updated
)
class
TempSensorSerial
(
TempSensor
):
def
__init__
(
self
,
name
,
owid
):
super
(
TempSensorSerial
,
self
).
__init__
(
name
)
self
.
owid
=
owid
def
__str__
(
self
):
with
self
.
_lock
:
return
"
%s (owid:%s) temperature: %s, last_updated:%s, exported:%s
"
%
\
(
self
.
name
,
self
.
owid
,
self
.
temperature
,
self
.
last_updated
,
self
.
exported
)
return
"
%s (owid:%s) temperature: %s, last_updated:%s
"
%
\
(
self
.
name
,
self
.
owid
,
self
.
temperature
,
self
.
last_updated
)
temperature_sensors
=
{}
#TODO:Type in key, only one dict?
...
...
@@ -327,18 +360,18 @@ for name, owid in [('floorserial', '10.C238A5010800'), ('ceilserial', '10.0C33A5
temperature_sensors_serial_by_name
[
name
]
=
temperature_sensors
[(
'
serial
'
,
owid
)]
if
__name__
==
"
__main__
"
:
mailqueue
=
Queue
.
Queue
()
mail_queue
=
Queue
.
Queue
()
export_queue
=
Queue
.
Queue
()
readerfred
=
TempReader
(
mailqueue
)
readerfred
=
TempReader
(
export_queue
,
mail
_
queue
)
readerfred
.
setDaemon
(
True
)
readerfred
.
start
()
time
.
sleep
(
2
)
exp0rtfred
=
Exp0rt0r
()
exp0rtfred
=
Exp0rt0r
(
export_queue
)
exp0rtfred
.
setDaemon
(
True
)
exp0rtfred
.
start
()
mail0r
=
Mail0r
(
mailqueue
)
mail0r
=
Mail0r
(
mail
_
queue
)
mail0r
.
setDaemon
(
True
)
mail0r
.
start
()
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment