1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Module managing temperature in an enclosed space via heater,
turning relay on and off.
Gets temperature from one wire sensor.
Attempts to keep temperature between given min and max.
Writes its own log as well as temperature data with timestamps to CSV file.
"""
import getpass
import pigpio
from math import isnan
import logging
import time
from csv import writer
__author__ = "Franek Ćazarewicz-Muradyan"
__licence__ = "GPL"
__version__ = "0.0.1"
__status__ = "Development"
# One wire temperature sensor settings
W1_SENSOR_ID = '28-0517c1b121ff'
W1_SENSOR_F = f'/sys/devices/w1_bus_master1/{W1_SENSOR_ID}/w1_slave'
# Heater settings
HEATER_PIN = 5
# Other settings
TIMEFORMAT = '%Y-%M-%d %H:%M:%S'
TEMPERATURE_MIN = 20
TEMPERATURE_MAX = 24
# TEMPERATURE_MIN = 28
# TEMPERATURE_MAX = 32
USERNAME = getpass.getuser()
LOGNAME = f'/var/log/{USERNAME}/shroombox.log'
DATA_FILE = f'/var/log/{USERNAME}/shroombox.csv'
pio = pigpio.pi()
logging.basicConfig(
filename=LOGNAME,
encoding='utf-8',
filemode='a',
format='%(asctime)s,%(msecs)d %(name)s%(levelname)s %(message)s', datefmt='%H:%M:%S',
level=logging.DEBUG,
)
logging.info("Starting shroombox")
logger = logging.getLogger()
def read_temp_alt(retry=0) -> float:
"""
Function reading temperature.
:param retry: int
:return: float
"""
# If sensor is physically disconected, opening file will fail
temperature = float('NaN')
if retry > 3:
return temperature
try:
with open(W1_SENSOR_F, 'r') as sensor:
ok = sensor.readline()[-4:].strip('\n')
if ok == 'YES':
try:
temperature = round(int(sensor.readline().split('=')[1])/1000, 1)
except:
return temperature
else:
retry+=1
read_temp_alt(retry=retry)
except:
return temperature
return temperature
def heater_on(temp, on=False) -> bool:
"""
Function turning heater on.
:param temp: int
:param on: bool
:return: bool
"""
status = pio.read(HEATER_PIN)
timestamp = time.strftime(TIMEFORMAT)
# turning it off
if not on:
if status:
retval = 0
else:
try:
pio.write(HEATER_PIN, 1)
message = f"Turning off, temp: {temp}, {timestamp}"
logger.info(message)
retval = 0
except Exception as exc:
logger.warning(exc)
retval = 1
# turning it on
else:
if not status:
retval = 0
else:
try:
pio.write(HEATER_PIN, 0)
message = f"Turning on, temp: {temp}, {timestamp}"
logger.info(message)
retval = 0
except Exception as exc:
logger.warning(exc)
retval = 1
return retval
def callback():
temp = read_temp_alt()
# TODO: Add check ntp is running, else we may go back to the '70-ties
timestamp = time.strftime(TIMEFORMAT)
try:
with open(DATA_FILE, 'a') as _file:
wrtr = writer(_file)
wrtr.writerow((timestamp, temp))
except OSError as exc:
print(f"Error writing data to file: {exc}")
print(temp) # TODO: Remove this line when done with testing.
if temp <= TEMPERATURE_MIN:
if temp < TEMPERATURE_MIN - 5:
print(f"Temperature below minimum: {temp}. Heater not powerful enough?")
logger.warning(f"Heater doesn't work, battery empty?")
state = heater_on(temp, on=True)
if state != 0:
logger.warning(f"heater_on() method returned {state}, {timestamp}")
elif temp >= TEMPERATURE_MAX:
state = heater_on(temp, on=False)
if state != 0:
logger.warning(f"heater_on() method returned {state} {timestamp}")
# Turn off in case can't get temperature reading:
elif isnan(temp):
state = heater_on(temp, on=False)
if state != 0:
logger.warning(f"heater_on() method returned {state} {timestamp}")
logging.warning(f"Cannot read temperature, check your connections! {timestamp}")
if __name__ == '__main__':
while True:
callback()
time.sleep(30)
|