This repository has been archived by the owner on Apr 8, 2022. It is now read-only.
/
AutomaticWateringSystem.py
206 lines (159 loc) · 7.91 KB
/
AutomaticWateringSystem.py
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/usr/bin/env python
# coding=utf-8
import uuid
from inspect import currentframe
from threading import Timer
from wiringx86 import GPIOGalileoGen2 as GPIO
from AWS.MagneticValve import MagneticValve
from AWS.Moisture import Moisture
from AWS.Temperature import Temperature
from utils.print_debug import print_debug
from utils import Database
class AutomaticWateringSystem(object):
"""
Main class for the Automatic Watering System (AWS)
Will initiate the classes needed for a plant
"""
instances = {}
def __init__(self, uuid, name, temperature_pin=None, magnetic_valve_pin=None, moisture_pin=None,
debug=False, gpio_debug=False):
"""
Constructor
:type uuid: str
:param uuid: The ID from the database
:type name: str
:param name: The name of the plant
:type temperature_pin: int
:param temperature_pin: Which pin the temperature sensor is attached to
:type magnetic_valve_pin: int
:param magnetic_valve_pin: Which pin the magnetic valve is attached to
:type moisture_pin: int
:param moisture_pin: Which pin the moisture sensor is attached to
:type debug: bool
:param debug:
:type gpio_debug: bool
:param gpio_debug: Specify if the debug should be on/off for the GPIO library
"""
print_debug(debug, currentframe().f_code.co_name, u'Init %s' % name, __name__)
all_params_str = u'UUID: {uuid}. Name: {name}. TP: {tp}. MVP: {mvp}. MP: {mp}'.format(
uuid=uuid,
name=name,
tp=temperature_pin,
mvp=magnetic_valve_pin,
mp=moisture_pin
)
print_debug(debug, currentframe().f_code.co_name, all_params_str, __name__)
# Add the new instance to the instances-list
AutomaticWateringSystem.instances[uuid] = self
self.__name = name
self.__temperature_pin = temperature_pin
self.__magnetic_valve_pin = magnetic_valve_pin
self.__moisture_pin = moisture_pin
self.debug = debug
# Get a uuid for the class so we can identify easier
# self.__uuid = str(uuid4()) # type: uuid4
self.__uuid = uuid
self.DB = Database.Database()
self.db_own_plant = self.DB.get_own_plant_from_id(self.get_uuid)
self.db_plant = self.DB.get_plant_from_id(self.db_own_plant.get('plant_id'))
self.db_pump = self.DB.get_pump_from_id(self.db_own_plant.get('pump_id'))
# Get a new instance of the GPIO
self.gpio = GPIO(debug=gpio_debug) # type: GPIO
# It has to be a magnetic valve connected!
self.MagneticValve = None
if magnetic_valve_pin is not None:
print_debug(debug, currentframe().f_code.co_name,
'Initializing magnetic valve at pin %i' % magnetic_valve_pin, __name__)
self.MagneticValve = MagneticValve(self.gpio, self.__uuid, magnetic_valve_pin,
name, self.db_own_plant.get('pump_id'), debug) # type: MagneticValve
else:
error = EnvironmentError
error.message = 'A magnetic valve is needed!'
raise error
self.TemperatureSensor = None
if temperature_pin is not None:
print_debug(debug, currentframe().f_code.co_name,
'Initializing temperature sensor at pin %i' % temperature_pin, __name__)
self.TemperatureSensor = Temperature(self.gpio, self.__uuid, temperature_pin,
name, 30, debug) # type: Temperature
self.MoistureSensor = None
if moisture_pin is not None:
print_debug(debug, currentframe().f_code.co_name,
'Initializing moisture sensor at pin %i' % moisture_pin, __name__)
self.MoistureSensor = Moisture(self.gpio, self.__uuid, moisture_pin, name,
self.db_plant.get('min_moisture'), self.db_plant.get('max_moisture'),
debug) # type: Moisture
self.__run_count = 0
self.active = True
# Run a check directly when a new instance is created
self.__start_new_timer(0)
def __start_new_timer(self, time=60):
"""
Starts a new timer
:type time: int
:param time: How many seconds the timer should be set to
"""
new_timer_uuid = str(uuid.uuid4())
print_debug(self.debug, currentframe().f_code.co_name,
u'New timer will start after {time} second(s). AWS name: {name}. Timer UUID: {uuid}'
.format(time=time, name=self.get_name, uuid=new_timer_uuid), __name__)
self.timer = Timer(time, self.__run, [new_timer_uuid])
self.timer.start()
def __run(self, timer_id):
"""
Run the different checks, and open the valve if needed!
This function should not be called directly! Call __start_new_timer() instead!
:type timer_id: str
:param timer_id: A unique identifier for each timer
"""
self.__run_count += 1
print_debug(self.debug, currentframe().f_code.co_name,
u'Timer executing. AWS name: {name}. Timer UUID: {timer_id}'
.format(name=self.get_name, timer_id=timer_id), __name__)
print_debug(self.debug, currentframe().f_code.co_name, u'Run count: %s' % self.__run_count, __name__)
temp_exceed = False
moist_deceed = False
stats_dict = {Database.TABLE_STATISTICS_RUN_COUNT: self.__run_count}
if self.TemperatureSensor:
stats_dict[Database.TABLE_STATISTICS_TEMPERATURE_RAW] = self.TemperatureSensor.get_raw_read()
stats_dict[Database.TABLE_STATISTICS_TEMPERATURE_MIN_CELSIUS] = self.TemperatureSensor.min_celsius
stats_dict[Database.TABLE_STATISTICS_TEMPERATURE_MAX_CELSIUS] = self.TemperatureSensor.max_celsius
stats_dict[Database.TABLE_STATISTICS_TEMPERATURE_CELSIUS] = self.TemperatureSensor.get_celsius()
temp_exceed = self.TemperatureSensor.has_exceeded_threshold()
if self.MoistureSensor:
stats_dict[Database.TABLE_STATISTICS_MOISTURE_RAW] = self.MoistureSensor.get_raw_read()
stats_dict[Database.TABLE_STATISTICS_MOISTURE_MIN_PERCENT] = self.MoistureSensor.min_percent
stats_dict[Database.TABLE_STATISTICS_MOISTURE_MAX_PERCENT] = self.MoistureSensor.max_percent
stats_dict[Database.TABLE_STATISTICS_MOISTURE_PERCENT] = self.MoistureSensor.get_percent_read()
moist_deceed = self.MoistureSensor.has_deceeded_threshold()
print_debug(self.debug, currentframe().f_code.co_name, u'Temp exceed: %s' % str(temp_exceed), __name__)
print_debug(self.debug, currentframe().f_code.co_name, u'Moist deceed: %s' % str(moist_deceed), __name__)
# Add statistics
self.DB.add_statistic(self.get_uuid, **stats_dict)
if moist_deceed:
# Try to open the valve
self.MagneticValve.send_open_valve_signal()
print_debug(self.debug, currentframe().f_code.co_name,
u'Timer done. AWS name: {name}. Timer UUID: {timer_id}'
.format(name=self.get_name, timer_id=timer_id), __name__)
self.__start_new_timer(10)
# self.__start_new_timer()
def cleanup(self):
"""
Cleanup all the things!
"""
print_debug(self.debug, currentframe().f_code.co_name,
u'Cleanup ({name}, {uuid})!'.format(name=self.get_name, uuid=self.get_uuid), __name__)
if self.TemperatureSensor:
self.TemperatureSensor.cleanup()
if self.MoistureSensor:
self.MoistureSensor.cleanup()
self.MagneticValve.cleanup()
self.timer.cancel()
self.gpio.cleanup()
@property
def get_name(self):
return self.__name
@property
def get_uuid(self):
return self.__uuid