-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathhydroponics_server.py
99 lines (75 loc) · 3.5 KB
/
hydroponics_server.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
#!/usr/bin/python
""" Hydroponics server that runs as a RPyC service and can thus be controlled
by another process, such as the web application.
You should start the server (by running this script) before starting the
web application.
The web application does not control the hardware directly because we want
only one instance of the HydroponicsController running at the same time,
but the web server creates a new thread for every connection.
"""
import datetime
import logging
logging.basicConfig()
from apscheduler.jobstores.base import JobLookupError
from apscheduler.schedulers.background import BackgroundScheduler
import rpyc
from rpyc.utils.server import ThreadedServer
from hydroponics import HydroponicsController, MockHydroponicsController
from config import (PUMP_PIN, LIGHTS_PIN, PUMP_DEFAULT_ON, LIGHTS_DEFAULT_ON,
PUMP_TIME, LIGHTS_TIME_ON, LIGHTS_TIME_OFF, PORT)
def CustomizedHydroponicsService(hydroponics_controller, scheduler):
state = {"paused": False, "resume_time": None}
class HydroponicsService(rpyc.Service):
def exposed_is_paused(self):
return state["paused"]
def exposed_get_resume_time(self):
return state["resume_time"]
def exposed_resume(self):
"""Resume regular operation of the hydroponics system."""
state["paused"] = False
try:
scheduler.remove_job("resume")
except JobLookupError:
pass
for job in ["pump", "lights on", "lights off"]:
scheduler.resume_job(job)
current_hour = datetime.datetime.now().time()
time_on = datetime.time(LIGHTS_TIME_ON, 0)
time_off = datetime.time(LIGHTS_TIME_OFF, 0)
if current_hour > time_on and current_hour < time_off:
hydroponics_controller.lights_on()
def exposed_pause(self, duration):
"""Pause the hydroponics system for duration seconds."""
state["paused"] = True
state["resume_time"] = self.get_resumption_time(duration)
hydroponics_controller.lights_off()
hydroponics_controller.pump_off()
for job in ["pump", "lights on", "lights off"]:
scheduler.pause_job(job)
scheduler.add_job(self.exposed_resume, 'date',
run_date=state["resume_time"], id="resume")
def get_resumption_time(self, pause_duration):
pause_datetime = datetime.timedelta(minutes=int(pause_duration))
return datetime.datetime.now() + pause_datetime
return HydroponicsService
if __name__ == '__main__':
scheduler = BackgroundScheduler()
kwargs = {"pump_pin": PUMP_PIN,
"lights_pin": LIGHTS_PIN,
"pump_default_on": PUMP_DEFAULT_ON,
"lights_default_on": LIGHTS_DEFAULT_ON}
with HydroponicsController(**kwargs) as h:
scheduler.add_job(h.run_pump, 'interval', hours=1, args=(PUMP_TIME,),
id="pump")
scheduler.add_job(h.lights_on, 'cron', hour=LIGHTS_TIME_ON,
id="lights on")
scheduler.add_job(h.lights_off, 'cron', hour=LIGHTS_TIME_OFF,
id="lights off")
scheduler.start()
cs = CustomizedHydroponicsService(h, scheduler)
t = ThreadedServer(cs, port=PORT,
protocol_config={"allow_public_attrs": True})
try:
t.start()
finally:
scheduler.shutdown()