Compare commits
No commits in common. "67a80d5d1ac285cd48d9ea4728c168d8851807a1" and "7d72045d4f7539a74a9bf9cb8a2cb856b57e2bcd" have entirely different histories.
67a80d5d1a
...
7d72045d4f
33 changed files with 297 additions and 2644 deletions
|
@ -1,16 +1,15 @@
|
|||
repos:
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 4.0.1
|
||||
hooks:
|
||||
- id: flake8
|
||||
args:
|
||||
- --count
|
||||
- --max-complexity=10
|
||||
- --max-line-length=100
|
||||
- --show-source
|
||||
- --statistics
|
||||
- repo: https://github.com/pre-commit/mirrors-yapf
|
||||
rev: 'v0.32.0'
|
||||
hooks:
|
||||
- id: yapf
|
||||
additional_dependencies: [ toml ]
|
||||
exclude: 'tsgrain_controller/grpc_generated'
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: tox
|
||||
name: tox
|
||||
entry: tox
|
||||
language: system
|
||||
files: \.py$
|
||||
pass_filenames: false
|
||||
|
|
12
.pylintrc
12
.pylintrc
|
@ -1,12 +0,0 @@
|
|||
[MASTER]
|
||||
ignore=grpc_generated
|
||||
|
||||
extension-pkg-allow-list=smbus
|
||||
|
||||
disable=missing-module-docstring,
|
||||
missing-class-docstring,
|
||||
missing-function-docstring,
|
||||
too-few-public-methods,
|
||||
invalid-name,
|
||||
too-many-instance-attributes,
|
||||
fixme
|
|
@ -1,109 +0,0 @@
|
|||
syntax = "proto3";
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
|
||||
service TSGRain {
|
||||
// Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn
|
||||
// diese bereits läuft).
|
||||
rpc StartTask(TaskRequest) returns (TaskRequestResult) {}
|
||||
|
||||
// Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück.
|
||||
rpc GetTasks(google.protobuf.Empty) returns (TaskList) {}
|
||||
|
||||
// Streamt die aktuelle Warteschlange mit ihren Bewässerungsaufgaben,
|
||||
// d.h. bei Änderung wird die neue Version übertragen.
|
||||
rpc StreamTasks(google.protobuf.Empty) returns (stream TaskList) {}
|
||||
|
||||
// Erstelle einen neuen Bewässerungsjob.
|
||||
rpc CreateJob(Job) returns (JobID) {}
|
||||
|
||||
// Gibt den Bewässerungsjob mit der gegebenen ID zurück.
|
||||
rpc GetJob(JobID) returns (Job) {}
|
||||
|
||||
// Gibt alle gespeicherten Bewässerungsjobs zurück.
|
||||
rpc GetJobs(google.protobuf.Empty) returns (JobList) {}
|
||||
|
||||
// Aktualisiert einen Bewässerungsjob.
|
||||
rpc UpdateJob(Job) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Lösche den Bewässerungsjob mit der gegebenen ID.
|
||||
rpc DeleteJob(JobID) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Gibt zurück, ob der Automatikmodus aktiviert ist.
|
||||
rpc GetAutoMode(google.protobuf.Empty) returns (google.protobuf.BoolValue) {}
|
||||
|
||||
// Aktiviert/deaktiviert den Automatikmodus.
|
||||
rpc SetAutoMode(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Datum/Uhrzeit/Zeitzone abrufen
|
||||
rpc GetConfigTime(google.protobuf.Empty) returns (ConfigTime) {}
|
||||
|
||||
// Datum/Uhrzeit/Zeitzone einstellen
|
||||
rpc SetConfigTime(ConfigTime) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Standardzeit bei manueller Bewässerung abrufen
|
||||
rpc GetDefaultIrrigationTime(google.protobuf.Empty) returns (google.protobuf.Int32Value) {}
|
||||
|
||||
// Standardzeit bei manueller Bewässerung einstellen
|
||||
rpc SetDefaultIrrigationTime(google.protobuf.Int32Value) returns (google.protobuf.Empty) {}
|
||||
}
|
||||
|
||||
// Quelle einer Bewässerungsaufgabe
|
||||
enum TaskSource {
|
||||
MANUAL = 0;
|
||||
SCHEDULE = 1;
|
||||
}
|
||||
|
||||
// Unix-Zeitstempel
|
||||
message Timestamp {
|
||||
int64 seconds = 1;
|
||||
}
|
||||
|
||||
message TaskRequest {
|
||||
TaskSource source = 1;
|
||||
int32 zone_id = 2;
|
||||
int32 duration = 3;
|
||||
bool queuing = 4;
|
||||
bool cancelling = 5;
|
||||
}
|
||||
|
||||
message TaskRequestResult {
|
||||
bool started = 1;
|
||||
bool stopped = 2;
|
||||
}
|
||||
|
||||
message Task {
|
||||
TaskSource source = 1;
|
||||
int32 zone_id = 2;
|
||||
int32 duration = 3;
|
||||
Timestamp datetime_started = 4;
|
||||
Timestamp datetime_finished = 5;
|
||||
}
|
||||
|
||||
message TaskList {
|
||||
repeated Task tasks = 1;
|
||||
Timestamp now = 2;
|
||||
}
|
||||
|
||||
message Job {
|
||||
int32 id = 1;
|
||||
Timestamp date = 2;
|
||||
int32 duration = 3;
|
||||
repeated int32 zones = 4;
|
||||
bool enable = 5;
|
||||
bool repeat = 6;
|
||||
}
|
||||
|
||||
message JobID {
|
||||
int32 id = 1;
|
||||
}
|
||||
|
||||
message JobList {
|
||||
repeated Job jobs = 1;
|
||||
}
|
||||
|
||||
message ConfigTime {
|
||||
Timestamp datetime = 1;
|
||||
string timezone = 2;
|
||||
}
|
|
@ -2,5 +2,3 @@ tinydb~=4.6.1
|
|||
cyra~=1.0.2
|
||||
schedule~=1.1.0
|
||||
smbus~=1.1.post2
|
||||
protobuf~=3.19.3
|
||||
grpcio~=1.43.0
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
grpcio-tools~=1.43.0
|
||||
mypy-protobuf~=3.2.0
|
||||
types-protobuf~=3.19.6
|
||||
grpc-stubs~=1.24.7
|
10
setup.py
10
setup.py
|
@ -22,14 +22,10 @@ setuptools.setup(
|
|||
],
|
||||
py_modules=['tsgrain_controller'],
|
||||
install_requires=[
|
||||
'tinydb~=4.6.1',
|
||||
'cyra~=1.0.2',
|
||||
'schedule~=1.1.0',
|
||||
'smbus~=1.1.post2',
|
||||
'protobuf~=3.19.3',
|
||||
'grpcio~=1.43.0',
|
||||
'tinydb',
|
||||
'cyra',
|
||||
'schedule',
|
||||
],
|
||||
extras_require={'rpi': ['RPi.GPIO~=0.7.0']},
|
||||
packages=setuptools.find_packages(exclude=['tests*']),
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# coding=utf-8
|
||||
from typing import Dict
|
||||
from typing import Optional, Callable, Dict
|
||||
from importlib_resources import files
|
||||
import os
|
||||
|
||||
from tsgrain_controller import io, config, models
|
||||
from tsgrain_controller import io, util, config
|
||||
|
||||
DIR_TESTFILES = str(files('tests.testfiles').joinpath(''))
|
||||
FILE_CFG = os.path.join(DIR_TESTFILES, 'tsgrain.toml')
|
||||
|
@ -11,15 +11,26 @@ FILE_CFG = os.path.join(DIR_TESTFILES, 'tsgrain.toml')
|
|||
|
||||
class TestingIo(io.Io):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, cb_manual: Optional[Callable[[int], None]],
|
||||
cb_mode: Optional[Callable[[], None]]):
|
||||
self.cb_manual = cb_manual
|
||||
self.cb_mode = cb_mode
|
||||
|
||||
self.outputs: Dict[str, bool] = dict()
|
||||
|
||||
def trigger_cb_manual(self, zone_id: int):
|
||||
if self.cb_manual is not None:
|
||||
self.cb_manual(zone_id)
|
||||
|
||||
def trigger_cb_mode(self):
|
||||
if self.cb_mode is not None:
|
||||
self.cb_mode()
|
||||
|
||||
def write_output(self, key: str, val: bool):
|
||||
self.outputs[key] = val
|
||||
|
||||
|
||||
class TestingApp(models.AppInterface):
|
||||
class TestingApp(util.AppInterface):
|
||||
|
||||
def __init__(self, db_file=''):
|
||||
self.auto = False
|
||||
|
@ -27,7 +38,7 @@ class TestingApp(models.AppInterface):
|
|||
self.cfg.load_file(False)
|
||||
self.cfg.db_path = db_file
|
||||
|
||||
def get_auto_mode(self) -> bool:
|
||||
def is_auto_enabled(self) -> bool:
|
||||
return self.auto
|
||||
|
||||
def get_cfg(self) -> config.Config:
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
# coding=utf-8
|
||||
import tempfile
|
||||
import pytest
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from tsgrain_controller import application, models
|
||||
from tests import fixtures
|
||||
|
||||
JOB1_DATA = {
|
||||
'date': datetime(2022, 1, 10, 12, 30),
|
||||
'duration': 60,
|
||||
'enable': True,
|
||||
'repeat': False,
|
||||
'zones': [1, 3]
|
||||
}
|
||||
|
||||
JOB2_DATA = {
|
||||
'date': datetime(2022, 1, 11, 18, 0),
|
||||
'duration': 300,
|
||||
'enable': True,
|
||||
'repeat': True,
|
||||
'zones': [5]
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app(mocker):
|
||||
mocker.patch('tsgrain_controller.io.io_factory.new_io',
|
||||
return_value=fixtures.TestingIo())
|
||||
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
app = application.Application(True, td, fixtures.FILE_CFG)
|
||||
assert not app.is_running()
|
||||
app.start()
|
||||
assert app.is_running()
|
||||
yield app
|
||||
app.stop()
|
||||
assert not app.is_running()
|
||||
|
||||
|
||||
def test_start_task(app):
|
||||
# Manually start a task (like via button press)
|
||||
res = app.start_task(
|
||||
models.TaskRequest(source=models.Source.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=True))
|
||||
assert res.started
|
||||
assert not res.stopped
|
||||
|
||||
# Queue processing time
|
||||
time.sleep(0.1)
|
||||
|
||||
# Try to start the same task again -> nothing happens
|
||||
res = app.start_task(
|
||||
models.TaskRequest(source=models.Source.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=False))
|
||||
assert not res.started
|
||||
assert not res.stopped
|
||||
|
||||
# Try to start the same task again -> task should cancel
|
||||
res = app.start_task(
|
||||
models.TaskRequest(source=models.Source.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=True))
|
||||
assert not res.started
|
||||
assert res.stopped
|
||||
|
||||
|
||||
def test_start_task_queue(app):
|
||||
# Manually start a task (like via button press)
|
||||
res = app.start_task(
|
||||
models.TaskRequest(source=models.Source.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=True))
|
||||
assert res.started
|
||||
assert not res.stopped
|
||||
assert len(app.queue.tasks) == 1
|
||||
assert app.queue.tasks[0].zone_id == 2
|
||||
|
||||
# Duplicate task should not be enqueued
|
||||
res = app.start_task(
|
||||
models.TaskRequest(source=models.Source.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=True,
|
||||
cancelling=False))
|
||||
assert not res.started
|
||||
assert not res.stopped
|
||||
assert len(app.queue.tasks) == 1
|
||||
|
||||
# Enqueue a new task
|
||||
res = app.start_task(
|
||||
models.TaskRequest(source=models.Source.MANUAL,
|
||||
zone_id=3,
|
||||
duration=30,
|
||||
queuing=True,
|
||||
cancelling=False))
|
||||
assert res.started
|
||||
assert not res.stopped
|
||||
|
||||
tasks = app.get_tasks()
|
||||
assert len(tasks) == 2
|
||||
|
||||
assert tasks[0].zone_id == 2
|
||||
assert tasks[1].zone_id == 3
|
||||
|
||||
|
||||
def test_crud_job(app):
|
||||
# Insert jobs
|
||||
job1 = models.Job.deserialize(JOB1_DATA)
|
||||
job2 = models.Job.deserialize(JOB2_DATA)
|
||||
|
||||
assert app.create_job(job1) == job1.id == 1
|
||||
assert app.create_job(job2) == job2.id == 2
|
||||
|
||||
# Get a job
|
||||
got_job = app.get_job(1)
|
||||
assert got_job.id == 1
|
||||
assert got_job.serialize() == JOB1_DATA
|
||||
|
||||
# Get all jobs
|
||||
got_jobs = app.get_jobs()
|
||||
assert len(got_jobs) == 2
|
||||
assert got_jobs[0].zones == [1, 3]
|
||||
assert got_jobs[1].zones == [5]
|
||||
|
||||
# Update job
|
||||
job2.zones = [4, 5]
|
||||
app.update_job(job2)
|
||||
assert app.get_job(2).zones == [4, 5]
|
||||
|
||||
# Delete job
|
||||
app.delete_job(1)
|
||||
assert len(app.get_jobs()) == 1
|
||||
|
||||
# Get job that does not exist
|
||||
with pytest.raises(KeyError):
|
||||
app.get_job(1)
|
||||
|
||||
# Delete job that does not exist
|
||||
with pytest.raises(KeyError):
|
||||
app.delete_job(1)
|
|
@ -1,102 +1,55 @@
|
|||
# coding=utf-8
|
||||
import tempfile
|
||||
import os
|
||||
import pytest
|
||||
from datetime import datetime
|
||||
|
||||
from tests import fixtures
|
||||
from tsgrain_controller import database, util, task_queue, models
|
||||
|
||||
JOB1_DATA = {
|
||||
'date': datetime(2022, 1, 10, 12, 30),
|
||||
'duration': 60,
|
||||
'enable': True,
|
||||
'repeat': False,
|
||||
'zones': [1, 3]
|
||||
}
|
||||
|
||||
JOB2_DATA = {
|
||||
'date': datetime(2022, 1, 11, 18, 0),
|
||||
'duration': 300,
|
||||
'enable': True,
|
||||
'repeat': True,
|
||||
'zones': [5]
|
||||
}
|
||||
from tsgrain_controller import database, util, queue, models
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db():
|
||||
def test_db_init():
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
dbfile = os.path.join(td, 'raindb.json')
|
||||
db = database.RainDB(dbfile)
|
||||
db.close()
|
||||
|
||||
assert os.path.isfile(dbfile)
|
||||
|
||||
|
||||
def test_db_jobs():
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
dbfile = os.path.join(td, 'raindb.json')
|
||||
db = database.RainDB(dbfile)
|
||||
|
||||
job1 = models.Job.deserialize(JOB1_DATA)
|
||||
job2 = models.Job.deserialize(JOB2_DATA)
|
||||
job1 = models.Job(util.datetime_new(2022, 1, 10, 12, 30), 60, [1, 3],
|
||||
True, False)
|
||||
job2 = models.Job(util.datetime_new(2022, 1, 10, 12, 30), 60, [1, 3],
|
||||
True, True)
|
||||
|
||||
db.insert_job(job1)
|
||||
db.insert_job(job2)
|
||||
|
||||
assert job1.id == 1
|
||||
assert job2.id == 2
|
||||
|
||||
yield db
|
||||
# Reopen database
|
||||
db.close()
|
||||
assert os.path.isfile(dbfile)
|
||||
db = database.RainDB(dbfile)
|
||||
|
||||
|
||||
def test_get_jobs(db):
|
||||
jobs = db.get_jobs()
|
||||
assert len(jobs) == 2
|
||||
assert jobs[0].serialize() == JOB1_DATA
|
||||
assert jobs[1].serialize() == JOB2_DATA
|
||||
assert util.to_json(jobs) == '{"1": {"date": "2022-01-10T12:30:00", \
|
||||
"duration": 60, "zones": [1, 3], "enable": [1, 3], "repeat": false}, "2": \
|
||||
{"date": "2022-01-10T12:30:00", "duration": 60, "zones": [1, 3], \
|
||||
"enable": [1, 3], "repeat": true}}'
|
||||
|
||||
|
||||
def test_get_job(db):
|
||||
job1 = db.get_job(1)
|
||||
assert job1.id == 1
|
||||
assert job1.serialize() == JOB1_DATA
|
||||
|
||||
job2 = db.get_job(2)
|
||||
assert job2.id == 2
|
||||
assert job2.serialize() == JOB2_DATA
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
db.get_job(3)
|
||||
|
||||
|
||||
def test_insert_job(db):
|
||||
job3 = models.Job(util.datetime_new(2022, 1, 15, 15, 30), 250, [6], True,
|
||||
True)
|
||||
assert db.insert_job(job3) == 3
|
||||
assert job3.id == 3
|
||||
|
||||
|
||||
def test_update_job(db):
|
||||
job1 = db.get_job(1)
|
||||
job1.zones = [1, 2, 3]
|
||||
db.update_job(job1)
|
||||
|
||||
got_job1 = db.get_job(1)
|
||||
assert got_job1.id == job1.id == 1
|
||||
assert got_job1.zones == [1, 2, 3]
|
||||
|
||||
|
||||
def test_delete_job(db):
|
||||
job2.enable = False
|
||||
db.update_job(2, job2)
|
||||
db.delete_job(1)
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
db.get_job(1)
|
||||
|
||||
assert len(db.get_jobs()) == 1
|
||||
|
||||
with pytest.raises(KeyError):
|
||||
db.delete_job(3)
|
||||
jobs = db.get_jobs()
|
||||
assert util.to_json(jobs) == '{"2": {"date": "2022-01-10T12:30:00", \
|
||||
"duration": 60, "zones": [1, 3], "enable": [1, 3], "repeat": true}}'
|
||||
|
||||
|
||||
def test_queue():
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
app = fixtures.TestingApp(td)
|
||||
q = task_queue.TaskQueue(app)
|
||||
def test_db_queue():
|
||||
app = fixtures.TestingApp()
|
||||
q = queue.TaskQueue(app)
|
||||
|
||||
task1 = models.Task(models.Source.MANUAL, 1, 10)
|
||||
task2 = models.Task(models.Source.SCHEDULE, 1, 5)
|
||||
|
@ -104,6 +57,7 @@ def test_queue():
|
|||
assert q.enqueue(task1)
|
||||
assert q.enqueue(task2)
|
||||
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
dbfile = os.path.join(td, 'raindb.json')
|
||||
app = fixtures.TestingApp(dbfile)
|
||||
|
||||
|
@ -114,7 +68,7 @@ def test_queue():
|
|||
db.close()
|
||||
db = database.RainDB(dbfile)
|
||||
|
||||
read_queue = task_queue.TaskQueue(app)
|
||||
read_queue = queue.TaskQueue(app)
|
||||
db.load_queue(read_queue)
|
||||
|
||||
assert util.to_json(
|
||||
|
@ -123,8 +77,17 @@ def test_queue():
|
|||
"remaining": 5}]'
|
||||
|
||||
|
||||
def test_auto_mode(db):
|
||||
def test_db_auto_mode():
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
dbfile = os.path.join(td, 'raindb.json')
|
||||
|
||||
db = database.RainDB(dbfile)
|
||||
assert db.get_auto_mode() is False
|
||||
|
||||
db.set_auto_mode(True)
|
||||
assert db.get_auto_mode() is True
|
||||
|
||||
# Reopen database
|
||||
db.close()
|
||||
db = database.RainDB(dbfile)
|
||||
assert db.get_auto_mode() is True
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
# coding=utf-8
|
||||
import tempfile
|
||||
import time
|
||||
from datetime import datetime
|
||||
import pytest
|
||||
import grpc
|
||||
from google.protobuf import empty_pb2
|
||||
|
||||
from tsgrain_controller import application, models, util
|
||||
from tsgrain_controller.grpc_generated import tsgrain_pb2, tsgrain_pb2_grpc
|
||||
from tests import fixtures
|
||||
|
||||
JOB1_DATA = {
|
||||
'date': datetime(2022, 1, 10, 12, 30),
|
||||
'duration': 60,
|
||||
'enable': True,
|
||||
'repeat': False,
|
||||
'zones': [1, 3]
|
||||
}
|
||||
|
||||
JOB2_DATA = {
|
||||
'date': datetime(2022, 1, 11, 18, 0),
|
||||
'duration': 300,
|
||||
'enable': True,
|
||||
'repeat': True,
|
||||
'zones': [5]
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def app(mocker):
|
||||
mocker.patch('tsgrain_controller.io.io_factory.new_io',
|
||||
return_value=fixtures.TestingIo())
|
||||
|
||||
with tempfile.TemporaryDirectory() as td:
|
||||
app = application.Application(True, td, fixtures.FILE_CFG)
|
||||
assert not app.is_running()
|
||||
app.start()
|
||||
assert app.is_running()
|
||||
yield app
|
||||
app.stop()
|
||||
assert not app.is_running()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def grpc_client(app):
|
||||
with grpc.insecure_channel('localhost:50051') as channel:
|
||||
client = tsgrain_pb2_grpc.TSGRainStub(channel)
|
||||
yield client
|
||||
|
||||
|
||||
def test_start_task(grpc_client):
|
||||
# Manually start a task (like via button press)
|
||||
res = grpc_client.StartTask(
|
||||
tsgrain_pb2.TaskRequest(source=tsgrain_pb2.TaskSource.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=True))
|
||||
|
||||
assert res.started
|
||||
assert not res.stopped
|
||||
|
||||
# Queue processing time
|
||||
time.sleep(0.1)
|
||||
|
||||
# Try to start the same task again -> nothing happens
|
||||
res = grpc_client.StartTask(
|
||||
tsgrain_pb2.TaskRequest(source=tsgrain_pb2.TaskSource.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=False))
|
||||
assert not res.started
|
||||
assert not res.stopped
|
||||
|
||||
# Try to start the same task again -> task should cancel
|
||||
res = grpc_client.StartTask(
|
||||
tsgrain_pb2.TaskRequest(source=tsgrain_pb2.TaskSource.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=True))
|
||||
assert not res.started
|
||||
assert res.stopped
|
||||
|
||||
|
||||
def test_start_task_queue(grpc_client):
|
||||
# Manually start a task (like via button press)
|
||||
res = grpc_client.StartTask(
|
||||
tsgrain_pb2.TaskRequest(source=tsgrain_pb2.TaskSource.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=False,
|
||||
cancelling=True))
|
||||
assert res.started
|
||||
assert not res.stopped
|
||||
|
||||
task_list = grpc_client.GetTasks(empty_pb2.Empty())
|
||||
assert task_list.now.seconds == pytest.approx(util.datetime_to_proto(
|
||||
datetime.now()).seconds,
|
||||
abs=1)
|
||||
|
||||
assert len(task_list.tasks) == 1
|
||||
assert task_list.tasks[0].zone_id == 2
|
||||
|
||||
# Duplicate task should not be enqueued
|
||||
res = grpc_client.StartTask(
|
||||
tsgrain_pb2.TaskRequest(source=tsgrain_pb2.TaskSource.MANUAL,
|
||||
zone_id=2,
|
||||
duration=30,
|
||||
queuing=True,
|
||||
cancelling=False))
|
||||
assert not res.started
|
||||
assert not res.stopped
|
||||
task_list = grpc_client.GetTasks(empty_pb2.Empty())
|
||||
assert len(task_list.tasks) == 1
|
||||
|
||||
# Enqueue a new task
|
||||
res = grpc_client.StartTask(
|
||||
tsgrain_pb2.TaskRequest(source=tsgrain_pb2.TaskSource.MANUAL,
|
||||
zone_id=3,
|
||||
duration=30,
|
||||
queuing=True,
|
||||
cancelling=False))
|
||||
assert res.started
|
||||
assert not res.stopped
|
||||
|
||||
task_list = grpc_client.GetTasks(empty_pb2.Empty())
|
||||
assert len(task_list.tasks) == 2
|
||||
|
||||
assert task_list.tasks[0].zone_id == 2
|
||||
assert task_list.tasks[1].zone_id == 3
|
||||
|
||||
|
||||
def test_crud_job(grpc_client):
|
||||
# Insert jobs
|
||||
job1 = models.Job.deserialize(JOB1_DATA)
|
||||
job2 = models.Job.deserialize(JOB2_DATA)
|
||||
|
||||
assert grpc_client.CreateJob(job1.serialize_proto()).id == 1
|
||||
assert grpc_client.CreateJob(job2.serialize_proto()).id == 2
|
||||
|
||||
# Get a job
|
||||
got_job = grpc_client.GetJob(tsgrain_pb2.JobID(id=1))
|
||||
assert got_job.id == 1
|
||||
assert models.Job.deserialize_proto(got_job).serialize() == JOB1_DATA
|
||||
|
||||
# Get all jobs
|
||||
job_list = grpc_client.GetJobs(empty_pb2.Empty())
|
||||
assert len(job_list.jobs) == 2
|
||||
assert job_list.jobs[0].zones == [1, 3]
|
||||
assert job_list.jobs[1].zones == [5]
|
||||
|
||||
# Update job
|
||||
job2.id = 2
|
||||
job2.zones = [4, 5]
|
||||
grpc_client.UpdateJob(job2.serialize_proto())
|
||||
assert grpc_client.GetJob(tsgrain_pb2.JobID(id=2)).zones == [4, 5]
|
||||
|
||||
# Delete job
|
||||
grpc_client.DeleteJob(tsgrain_pb2.JobID(id=1))
|
||||
assert len(grpc_client.GetJobs(empty_pb2.Empty()).jobs) == 1
|
||||
|
||||
# Get job that does not exist
|
||||
with pytest.raises(grpc.RpcError):
|
||||
grpc_client.GetJob(tsgrain_pb2.JobID(id=1))
|
||||
|
||||
# Delete job that does not exist
|
||||
with pytest.raises(grpc.RpcError):
|
||||
grpc_client.DeleteJob(tsgrain_pb2.JobID(id=1))
|
|
@ -5,10 +5,10 @@ import defer
|
|||
from unittest import mock
|
||||
|
||||
from tests import fixtures
|
||||
from tsgrain_controller import output, task_queue, models
|
||||
from tsgrain_controller import output, queue, models
|
||||
|
||||
|
||||
class _TaskHolder(task_queue.TaskHolder):
|
||||
class _TaskHolder(queue.TaskHolder):
|
||||
|
||||
def __init__(self, task: Optional[models.Task]):
|
||||
self.task = task
|
||||
|
@ -19,14 +19,14 @@ class _TaskHolder(task_queue.TaskHolder):
|
|||
|
||||
@defer.with_defer
|
||||
def test_zone_outputs():
|
||||
io = fixtures.TestingIo()
|
||||
io = fixtures.TestingIo(None, None)
|
||||
task_holder = _TaskHolder(None)
|
||||
app = fixtures.TestingApp()
|
||||
op = output.Outputs(io, task_holder, app)
|
||||
op.start()
|
||||
defer.defer(op.stop)
|
||||
|
||||
time.sleep(0.02)
|
||||
time.sleep(0.01)
|
||||
|
||||
# Expect all devices initialized to OFF
|
||||
assert io.outputs == {
|
||||
|
@ -41,7 +41,7 @@ def test_zone_outputs():
|
|||
}
|
||||
|
||||
task_holder.task = models.Task(models.Source.MANUAL, 1, 100)
|
||||
time.sleep(0.02)
|
||||
time.sleep(0.01)
|
||||
assert io.outputs == {
|
||||
'VALVE_1': True,
|
||||
'VALVE_2': False,
|
||||
|
@ -55,7 +55,7 @@ def test_zone_outputs():
|
|||
}
|
||||
|
||||
task_holder.task = None
|
||||
time.sleep(0.02)
|
||||
time.sleep(0.01)
|
||||
assert io.outputs == {
|
||||
'VALVE_1': False,
|
||||
'VALVE_2': False,
|
||||
|
|
|
@ -3,7 +3,7 @@ import time
|
|||
from datetime import datetime
|
||||
|
||||
from tests import fixtures
|
||||
from tsgrain_controller import task_queue, util, models
|
||||
from tsgrain_controller import queue, util, models
|
||||
|
||||
|
||||
def test_task():
|
||||
|
@ -50,7 +50,7 @@ def test_task_started(mocker):
|
|||
|
||||
def test_add_tasks():
|
||||
app = fixtures.TestingApp()
|
||||
q = task_queue.TaskQueue(app)
|
||||
q = queue.TaskQueue(app)
|
||||
|
||||
task1 = models.Task(models.Source.MANUAL, 1, 10)
|
||||
task1b = models.Task(models.Source.SCHEDULE, 1, 5)
|
||||
|
@ -63,7 +63,7 @@ def test_add_tasks():
|
|||
|
||||
def test_queue_runner():
|
||||
app = fixtures.TestingApp()
|
||||
q = task_queue.TaskQueue(app)
|
||||
q = queue.TaskQueue(app)
|
||||
|
||||
task1 = models.Task(models.Source.MANUAL, 1, 1)
|
||||
task2 = models.Task(models.Source.MANUAL, 2, 5)
|
||||
|
|
|
@ -1,38 +1 @@
|
|||
n_zones = 3 # Anzahl Bewässerungszonen
|
||||
db_path = "" # Pfad der Datenbankdatei
|
||||
manual_time = 300 # Manuelle Bewaesserungszeit in Sekunden
|
||||
grpc_port = "[::]:50051" # Port für GRPC-Kommunikation
|
||||
log_debug = false # Debug-Ausgaben loggen
|
||||
|
||||
[io]
|
||||
i2c_bus_id = 0 # ID des I2C-Bus
|
||||
gpio_interrupt = 17 # GPIO-Pin, mit dem der Interrupt-Pin des MCP23017 verbunden ist
|
||||
gpio_delay = 0.05 # Entprellzeit in Sekunden
|
||||
|
||||
[output_devices] # Ausgaenge
|
||||
VALVE_1 = "0x27/B0/!"
|
||||
VALVE_2 = "0x27/B1/!"
|
||||
VALVE_3 = "0x27/B2/!"
|
||||
VALVE_4 = "0x27/B3/!"
|
||||
VALVE_5 = "0x27/B4/!"
|
||||
VALVE_6 = "0x27/B5/!"
|
||||
VALVE_7 = "0x27/B6/!"
|
||||
LED_Z_1 = "0x27/A0"
|
||||
LED_Z_2 = "0x27/A1"
|
||||
LED_Z_3 = "0x27/A2"
|
||||
LED_Z_4 = "0x27/A3"
|
||||
LED_Z_5 = "0x27/A4"
|
||||
LED_Z_6 = "0x27/A5"
|
||||
LED_Z_7 = "0x27/A6"
|
||||
LED_M_AUTO = "0x23/B0"
|
||||
LED_M_MAN = "0x23/B1"
|
||||
|
||||
[input_devices] # Eingaenge
|
||||
BT_Z_1 = "0x23/A0/!"
|
||||
BT_Z_2 = "0x23/A1/!"
|
||||
BT_Z_3 = "0x23/A2/!"
|
||||
BT_Z_4 = "0x23/A3/!"
|
||||
BT_Z_5 = "0x23/A4/!"
|
||||
BT_Z_6 = "0x23/A5/!"
|
||||
BT_Z_7 = "0x23/A6/!"
|
||||
BT_MODE = "0x23/A7/!"
|
||||
|
|
20
tox.ini
20
tox.ini
|
@ -11,11 +11,11 @@ commands =
|
|||
pytest tests
|
||||
|
||||
[testenv:lint]
|
||||
description = Lint with pylint
|
||||
deps =
|
||||
pylint
|
||||
description = Lint with flake8
|
||||
skip_install = true
|
||||
deps = flake8
|
||||
commands =
|
||||
pylint tsgrain_controller
|
||||
flake8 tsgrain_controller --count --max-complexity=10 --max-line-length=100 --show-source --statistics
|
||||
|
||||
[testenv:coverage]
|
||||
description = Output HTML coverage report.
|
||||
|
@ -33,15 +33,3 @@ deps = bump2version
|
|||
skip_install = true
|
||||
commands =
|
||||
bump2version {posargs}
|
||||
|
||||
[testenv:protoc]
|
||||
description = Generate protobuf code
|
||||
deps =
|
||||
-r{toxinidir}/requirements_dev.txt
|
||||
skip_install = true
|
||||
commands =
|
||||
python -m grpc_tools.protoc {toxinidir}/proto/tsgrain.proto \
|
||||
--python_out {toxinidir} \
|
||||
--grpc_python_out {toxinidir} \
|
||||
--mypy_out {toxinidir} \
|
||||
--proto_path tsgrain_controller/grpc_generated=./proto/
|
||||
|
|
|
@ -8,13 +8,13 @@ def run():
|
|||
console_flag = False
|
||||
|
||||
if len(sys.argv) > 1:
|
||||
arg1 = sys.argv[1]
|
||||
if arg1.startswith('c'):
|
||||
x = sys.argv[1]
|
||||
if x.startswith('c'):
|
||||
console_flag = True
|
||||
|
||||
app = application.Application(console_flag)
|
||||
|
||||
def _signal_handler(sig, frame): # pylint: disable=unused-argument
|
||||
def _signal_handler(sig, frame):
|
||||
app.stop()
|
||||
|
||||
print('Exited.')
|
||||
|
|
|
@ -1,57 +1,37 @@
|
|||
# coding=utf-8
|
||||
import logging
|
||||
import os.path
|
||||
from typing import List, Optional
|
||||
|
||||
from tsgrain_controller import config, database, jobschedule, output, task_queue, \
|
||||
models, grpc_server
|
||||
from tsgrain_controller.io import io_factory
|
||||
from tsgrain_controller import config, controller, database, io, jobschedule, output, \
|
||||
queue, util
|
||||
|
||||
|
||||
class Application(models.AppInterface):
|
||||
|
||||
def __init__(self,
|
||||
console_flag: bool,
|
||||
workdir: str = '',
|
||||
cfg_path: Optional[str] = None):
|
||||
if cfg_path is None:
|
||||
cfg_path = os.path.join(workdir, 'tsgrain.toml')
|
||||
class Application(util.AppInterface):
|
||||
|
||||
def __init__(self, console_flag: bool):
|
||||
self.logger = logging.getLogger()
|
||||
self.logger.setLevel(logging.DEBUG)
|
||||
|
||||
self.cfg = config.Config(cfg_path)
|
||||
self.cfg = config.Config('tsgrain.toml')
|
||||
self.cfg.load_file()
|
||||
|
||||
if self.cfg.db_path:
|
||||
db_path = self.cfg.db_path
|
||||
else:
|
||||
db_path = os.path.join(workdir, 'raindb.json')
|
||||
self.db = database.RainDB(self.cfg.db_path)
|
||||
|
||||
self.db = database.RainDB(db_path)
|
||||
|
||||
self.queue = task_queue.TaskQueue(self)
|
||||
self.queue = queue.TaskQueue(self)
|
||||
self.db.load_queue(self.queue)
|
||||
|
||||
self.io = io_factory.new_io(self, console_flag)
|
||||
self.io.set_callbacks(self._cb_manual, self._cb_modekey)
|
||||
b_ctrl = controller.ButtonController(self.queue, self.cfg)
|
||||
|
||||
self.io = io.new_io(self, console_flag)
|
||||
self.io.set_callbacks(b_ctrl.cb_manual, self.cb_modekey)
|
||||
|
||||
self.outputs = output.Outputs(self.io, self.queue, self)
|
||||
|
||||
self.scheduler = jobschedule.Scheduler(self)
|
||||
self.scheduler = jobschedule.Scheduler(self.db, self.queue)
|
||||
|
||||
self.grpc_tsgrain_servicer = grpc_server.TSGRainServicer(self)
|
||||
self.grpc_server = grpc_server.new_server(self.grpc_tsgrain_servicer,
|
||||
self.cfg.grpc_port)
|
||||
self.auto_en = self.db.get_auto_mode()
|
||||
|
||||
self._auto_en = self.db.get_auto_mode()
|
||||
self._running = False
|
||||
|
||||
def get_auto_mode(self) -> bool:
|
||||
return self._auto_en
|
||||
|
||||
def set_auto_mode(self, state: bool):
|
||||
self._auto_en = state
|
||||
def is_auto_enabled(self) -> bool:
|
||||
return self.auto_en
|
||||
|
||||
def get_cfg(self) -> config.Config:
|
||||
return self.cfg
|
||||
|
@ -59,83 +39,21 @@ class Application(models.AppInterface):
|
|||
def get_logger(self) -> logging.Logger:
|
||||
return self.logger
|
||||
|
||||
def _cb_manual(self, zone_id: int):
|
||||
self.start_task(
|
||||
models.TaskRequest(source=models.Source.MANUAL,
|
||||
zone_id=zone_id,
|
||||
duration=self.cfg.manual_time,
|
||||
queuing=False,
|
||||
cancelling=True))
|
||||
def cb_modekey(self):
|
||||
self.auto_en = not self.auto_en
|
||||
|
||||
def _cb_modekey(self):
|
||||
self._auto_en = not self._auto_en
|
||||
|
||||
if self._auto_en:
|
||||
if self.auto_en:
|
||||
logging.info('Auto mode ON')
|
||||
else:
|
||||
logging.info('Auto mode OFF')
|
||||
|
||||
def start_task(self,
|
||||
request: models.TaskRequest) -> models.TaskRequestResult:
|
||||
if request.queuing:
|
||||
if request.cancelling:
|
||||
# If a task from this zone is in queue, cancel it
|
||||
for task in self.queue.tasks:
|
||||
if task.zone_id == request.zone_id and task.source == request.source:
|
||||
self.queue.cancel_task(task)
|
||||
return models.TaskRequestResult(False, True)
|
||||
elif request.cancelling:
|
||||
current_task = self.queue.get_current_task()
|
||||
# Cancel manually started tasks
|
||||
if current_task is not None \
|
||||
and current_task.zone_id == request.zone_id \
|
||||
and current_task.source == request.source:
|
||||
self.queue.cancel_current_task()
|
||||
return models.TaskRequestResult(False, True)
|
||||
|
||||
duration = request.duration
|
||||
if duration < 1:
|
||||
duration = self.cfg.manual_time
|
||||
|
||||
task = models.Task(models.Source.MANUAL, request.zone_id, duration)
|
||||
started = self.queue.enqueue(task, not request.queuing)
|
||||
return models.TaskRequestResult(started, False)
|
||||
|
||||
def get_tasks(self) -> List[models.Task]:
|
||||
return self.queue.tasks
|
||||
|
||||
def create_job(self, job: models.Job) -> int:
|
||||
return self.db.insert_job(job)
|
||||
|
||||
def get_job(self, job_id: int) -> models.Job:
|
||||
return self.db.get_job(job_id)
|
||||
|
||||
def get_jobs(self) -> List[models.Job]:
|
||||
return self.db.get_jobs()
|
||||
|
||||
def update_job(self, job: models.Job):
|
||||
self.db.update_job(job)
|
||||
|
||||
def delete_job(self, job_id):
|
||||
self.db.delete_job(job_id)
|
||||
|
||||
def notify_queue_update(self):
|
||||
self.grpc_tsgrain_servicer.queue_update.set()
|
||||
|
||||
def is_running(self) -> bool:
|
||||
return self._running
|
||||
|
||||
def start(self):
|
||||
self._running = True
|
||||
self.io.start()
|
||||
self.outputs.start()
|
||||
self.queue.start()
|
||||
self.scheduler.start()
|
||||
self.grpc_server.start()
|
||||
|
||||
def stop(self):
|
||||
self._running = False
|
||||
self.grpc_server.stop(None)
|
||||
self.scheduler.stop()
|
||||
self.queue.stop()
|
||||
self.outputs.stop()
|
||||
|
@ -143,4 +61,4 @@ class Application(models.AppInterface):
|
|||
|
||||
# Store application state
|
||||
self.db.store_queue(self.queue)
|
||||
self.db.set_auto_mode(self._auto_en)
|
||||
self.db.set_auto_mode(self.auto_en)
|
||||
|
|
|
@ -9,14 +9,11 @@ class Config(cyra.Config):
|
|||
n_zones = builder.define('n_zones', 7)
|
||||
|
||||
builder.comment('Pfad der Datenbankdatei')
|
||||
db_path = builder.define('db_path', '')
|
||||
db_path = builder.define('db_path', 'raindb.json')
|
||||
|
||||
builder.comment('Manuelle Bewaesserungszeit in Sekunden')
|
||||
manual_time = builder.define('manual_time', 300)
|
||||
|
||||
builder.comment('Port für GRPC-Kommunikation')
|
||||
grpc_port = builder.define('grpc_port', '[::]:50051')
|
||||
|
||||
builder.comment('Debug-Ausgaben loggen')
|
||||
log_debug = builder.define('log_debug', False)
|
||||
|
||||
|
|
36
tsgrain_controller/controller.py
Normal file
36
tsgrain_controller/controller.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
# coding=utf-8
|
||||
from typing import Callable, Optional
|
||||
|
||||
from tsgrain_controller import config, models, queue
|
||||
|
||||
|
||||
class ButtonController:
|
||||
|
||||
def __init__(self, task_queue: queue.TaskQueue, cfg: config.Config):
|
||||
self.task_queue = task_queue
|
||||
self.cfg = cfg
|
||||
self.cb_error: Optional[Callable[[], None]] = None
|
||||
|
||||
def cb_manual(self, zone_id: int):
|
||||
current_task = self.task_queue.get_current_task()
|
||||
# Cancel manually started tasks
|
||||
if current_task is not None \
|
||||
and current_task.zone_id == zone_id and current_task.source == models.Source.MANUAL:
|
||||
self.task_queue.cancel_current_task()
|
||||
else:
|
||||
task = models.Task(models.Source.MANUAL, zone_id,
|
||||
self.cfg.manual_time)
|
||||
self.task_queue.enqueue(task, True)
|
||||
|
||||
|
||||
class QueuingButtonController(ButtonController):
|
||||
|
||||
def cb_manual(self, zone_id: int):
|
||||
# If a task from this zone is in queue, cancel it
|
||||
for task in self.task_queue.tasks:
|
||||
if task.zone_id == zone_id and task.source == models.Source.MANUAL:
|
||||
self.task_queue.cancel_task(task)
|
||||
return
|
||||
|
||||
task = models.Task(models.Source.MANUAL, zone_id, self.cfg.manual_time)
|
||||
self.task_queue.enqueue(task)
|
|
@ -1,7 +1,7 @@
|
|||
# coding=utf-8
|
||||
from typing import List
|
||||
import tinydb
|
||||
from tsgrain_controller import task_queue, util, models
|
||||
from typing import Dict, Optional
|
||||
from tsgrain_controller import queue, util, models
|
||||
|
||||
|
||||
class RainDB:
|
||||
|
@ -17,78 +17,74 @@ class RainDB:
|
|||
"""Die Datenbank schließen"""
|
||||
self._db.close()
|
||||
|
||||
def get_jobs(self) -> List[models.Job]:
|
||||
def get_jobs(self) -> Dict[int, models.Job]:
|
||||
"""
|
||||
Gibt alle gespeicherten Bewässerungsjobs zurück
|
||||
|
||||
:return: Bewässerungsjobs: dict(id -> models.Job)
|
||||
"""
|
||||
return [
|
||||
models.Job.deserialize(job_data, job_data.doc_id)
|
||||
for job_data in self._jobs.all()
|
||||
]
|
||||
res = dict()
|
||||
for job_data in self._jobs.all():
|
||||
res[job_data.doc_id] = models.Job.deserialize(job_data)
|
||||
return res
|
||||
|
||||
def get_job(self, job_id: int) -> models.Job:
|
||||
def get_job(self, job_id: int) -> Optional[models.Job]:
|
||||
"""
|
||||
Gibt den Bewässerungsjob mit der gegebenen ID zurück
|
||||
|
||||
:param job_id: ID des Bewässerungsjobs
|
||||
:return: Bewässerungsjob
|
||||
:raise KeyError: wenn Job nicht gefunden
|
||||
"""
|
||||
job = self._jobs.get(None, job_id)
|
||||
if job is None:
|
||||
raise KeyError
|
||||
return None
|
||||
|
||||
return models.Job.deserialize(job, job_id)
|
||||
return models.Job.deserialize(job)
|
||||
|
||||
def insert_job(self, job: models.Job) -> int:
|
||||
def insert_job(self, job: models.Job):
|
||||
"""
|
||||
Fügt der Datenbank einen neuen Bewässerungsjob hinzu
|
||||
|
||||
:param job: Bewässerungsjob
|
||||
:return: ID des neuen Bewässerungsjobs
|
||||
"""
|
||||
job_id = self._jobs.insert(util.serializer(job))
|
||||
job.id = job_id
|
||||
return job_id
|
||||
self._jobs.insert(util.serializer(job))
|
||||
|
||||
def update_job(self, job: models.Job):
|
||||
def update_job(self, job_id: int, job: models.Job):
|
||||
"""
|
||||
Aktualisiert einen Bewässerungsjob
|
||||
|
||||
:param job_id: ID des Bewässerungsjobs
|
||||
:param job: Bewässerungsjob
|
||||
"""
|
||||
self._jobs.update(util.serializer(job), None, [job.id])
|
||||
self._jobs.update(util.serializer(job), None, [job_id])
|
||||
|
||||
def delete_job(self, job_id: int):
|
||||
"""
|
||||
Lösche den Bewässerungsjob mit der gegebenen ID
|
||||
|
||||
:param job_id: ID des Bewässerungsjobs
|
||||
:raise KeyError: wenn Job nicht gefunden
|
||||
"""
|
||||
self._jobs.remove(None, [job_id])
|
||||
|
||||
def store_queue(self, queue: task_queue.TaskQueue):
|
||||
def store_queue(self, task_queue: queue.TaskQueue):
|
||||
"""
|
||||
Speichere die aktuelle Warteschlange in der Datenbank
|
||||
|
||||
:param queue: Warteschlange
|
||||
:param task_queue: Warteschlange
|
||||
"""
|
||||
self.empty_queue()
|
||||
for task in queue.serialize():
|
||||
for task in task_queue.serialize():
|
||||
self._tasks.insert(util.serializer(task))
|
||||
|
||||
def load_queue(self, queue: task_queue.TaskQueue):
|
||||
def load_queue(self, task_queue: queue.TaskQueue):
|
||||
"""
|
||||
Lade die gespeicherten Tasks aus der Datenbank in die Warteschlange
|
||||
|
||||
:param queue: Warteschlange
|
||||
:param task_queue: Warteschlange
|
||||
"""
|
||||
for task_data in self._tasks.all():
|
||||
task = models.Task.deserialize(task_data)
|
||||
queue.tasks.append(task)
|
||||
task_queue.tasks.append(task)
|
||||
self.empty_queue()
|
||||
|
||||
def empty_queue(self):
|
||||
|
|
|
@ -1,700 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: tsgrain_controller/grpc_generated/tsgrain.proto
|
||||
"""Generated protocol buffer code."""
|
||||
from google.protobuf.internal import enum_type_wrapper
|
||||
from google.protobuf import descriptor as _descriptor
|
||||
from google.protobuf import message as _message
|
||||
from google.protobuf import reflection as _reflection
|
||||
from google.protobuf import symbol_database as _symbol_database
|
||||
# @@protoc_insertion_point(imports)
|
||||
|
||||
_sym_db = _symbol_database.Default()
|
||||
|
||||
|
||||
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
|
||||
from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
name='tsgrain_controller/grpc_generated/tsgrain.proto',
|
||||
package='',
|
||||
syntax='proto3',
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
serialized_pb=b'\n/tsgrain_controller/grpc_generated/tsgrain.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1egoogle/protobuf/wrappers.proto\"\x1c\n\tTimestamp\x12\x0f\n\x07seconds\x18\x01 \x01(\x03\"r\n\x0bTaskRequest\x12\x1b\n\x06source\x18\x01 \x01(\x0e\x32\x0b.TaskSource\x12\x0f\n\x07zone_id\x18\x02 \x01(\x05\x12\x10\n\x08\x64uration\x18\x03 \x01(\x05\x12\x0f\n\x07queuing\x18\x04 \x01(\x08\x12\x12\n\ncancelling\x18\x05 \x01(\x08\"5\n\x11TaskRequestResult\x12\x0f\n\x07started\x18\x01 \x01(\x08\x12\x0f\n\x07stopped\x18\x02 \x01(\x08\"\x93\x01\n\x04Task\x12\x1b\n\x06source\x18\x01 \x01(\x0e\x32\x0b.TaskSource\x12\x0f\n\x07zone_id\x18\x02 \x01(\x05\x12\x10\n\x08\x64uration\x18\x03 \x01(\x05\x12$\n\x10\x64\x61tetime_started\x18\x04 \x01(\x0b\x32\n.Timestamp\x12%\n\x11\x64\x61tetime_finished\x18\x05 \x01(\x0b\x32\n.Timestamp\"9\n\x08TaskList\x12\x14\n\x05tasks\x18\x01 \x03(\x0b\x32\x05.Task\x12\x17\n\x03now\x18\x02 \x01(\x0b\x32\n.Timestamp\"l\n\x03Job\x12\n\n\x02id\x18\x01 \x01(\x05\x12\x18\n\x04\x64\x61te\x18\x02 \x01(\x0b\x32\n.Timestamp\x12\x10\n\x08\x64uration\x18\x03 \x01(\x05\x12\r\n\x05zones\x18\x04 \x03(\x05\x12\x0e\n\x06\x65nable\x18\x05 \x01(\x08\x12\x0e\n\x06repeat\x18\x06 \x01(\x08\"\x13\n\x05JobID\x12\n\n\x02id\x18\x01 \x01(\x05\"\x1d\n\x07JobList\x12\x12\n\x04jobs\x18\x01 \x03(\x0b\x32\x04.Job\"<\n\nConfigTime\x12\x1c\n\x08\x64\x61tetime\x18\x01 \x01(\x0b\x32\n.Timestamp\x12\x10\n\x08timezone\x18\x02 \x01(\t*&\n\nTaskSource\x12\n\n\x06MANUAL\x10\x00\x12\x0c\n\x08SCHEDULE\x10\x01\x32\x83\x06\n\x07TSGRain\x12/\n\tStartTask\x12\x0c.TaskRequest\x1a\x12.TaskRequestResult\"\x00\x12/\n\x08GetTasks\x12\x16.google.protobuf.Empty\x1a\t.TaskList\"\x00\x12\x34\n\x0bStreamTasks\x12\x16.google.protobuf.Empty\x1a\t.TaskList\"\x00\x30\x01\x12\x1b\n\tCreateJob\x12\x04.Job\x1a\x06.JobID\"\x00\x12\x18\n\x06GetJob\x12\x06.JobID\x1a\x04.Job\"\x00\x12-\n\x07GetJobs\x12\x16.google.protobuf.Empty\x1a\x08.JobList\"\x00\x12+\n\tUpdateJob\x12\x04.Job\x1a\x16.google.protobuf.Empty\"\x00\x12-\n\tDeleteJob\x12\x06.JobID\x1a\x16.google.protobuf.Empty\"\x00\x12\x43\n\x0bGetAutoMode\x12\x16.google.protobuf.Empty\x1a\x1a.google.protobuf.BoolValue\"\x00\x12\x43\n\x0bSetAutoMode\x12\x1a.google.protobuf.BoolValue\x1a\x16.google.protobuf.Empty\"\x00\x12\x36\n\rGetConfigTime\x12\x16.google.protobuf.Empty\x1a\x0b.ConfigTime\"\x00\x12\x36\n\rSetConfigTime\x12\x0b.ConfigTime\x1a\x16.google.protobuf.Empty\"\x00\x12Q\n\x18GetDefaultIrrigationTime\x12\x16.google.protobuf.Empty\x1a\x1b.google.protobuf.Int32Value\"\x00\x12Q\n\x18SetDefaultIrrigationTime\x12\x1b.google.protobuf.Int32Value\x1a\x16.google.protobuf.Empty\"\x00\x62\x06proto3'
|
||||
,
|
||||
dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,google_dot_protobuf_dot_wrappers__pb2.DESCRIPTOR,])
|
||||
|
||||
_TASKSOURCE = _descriptor.EnumDescriptor(
|
||||
name='TaskSource',
|
||||
full_name='TaskSource',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='MANUAL', index=0, number=0,
|
||||
serialized_options=None,
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SCHEDULE', index=1, number=1,
|
||||
serialized_options=None,
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
containing_type=None,
|
||||
serialized_options=None,
|
||||
serialized_start=746,
|
||||
serialized_end=784,
|
||||
)
|
||||
_sym_db.RegisterEnumDescriptor(_TASKSOURCE)
|
||||
|
||||
TaskSource = enum_type_wrapper.EnumTypeWrapper(_TASKSOURCE)
|
||||
MANUAL = 0
|
||||
SCHEDULE = 1
|
||||
|
||||
|
||||
|
||||
_TIMESTAMP = _descriptor.Descriptor(
|
||||
name='Timestamp',
|
||||
full_name='Timestamp',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='seconds', full_name='Timestamp.seconds', index=0,
|
||||
number=1, type=3, cpp_type=2, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=112,
|
||||
serialized_end=140,
|
||||
)
|
||||
|
||||
|
||||
_TASKREQUEST = _descriptor.Descriptor(
|
||||
name='TaskRequest',
|
||||
full_name='TaskRequest',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='source', full_name='TaskRequest.source', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='zone_id', full_name='TaskRequest.zone_id', index=1,
|
||||
number=2, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='duration', full_name='TaskRequest.duration', index=2,
|
||||
number=3, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='queuing', full_name='TaskRequest.queuing', index=3,
|
||||
number=4, type=8, cpp_type=7, label=1,
|
||||
has_default_value=False, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='cancelling', full_name='TaskRequest.cancelling', index=4,
|
||||
number=5, type=8, cpp_type=7, label=1,
|
||||
has_default_value=False, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=142,
|
||||
serialized_end=256,
|
||||
)
|
||||
|
||||
|
||||
_TASKREQUESTRESULT = _descriptor.Descriptor(
|
||||
name='TaskRequestResult',
|
||||
full_name='TaskRequestResult',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='started', full_name='TaskRequestResult.started', index=0,
|
||||
number=1, type=8, cpp_type=7, label=1,
|
||||
has_default_value=False, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='stopped', full_name='TaskRequestResult.stopped', index=1,
|
||||
number=2, type=8, cpp_type=7, label=1,
|
||||
has_default_value=False, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=258,
|
||||
serialized_end=311,
|
||||
)
|
||||
|
||||
|
||||
_TASK = _descriptor.Descriptor(
|
||||
name='Task',
|
||||
full_name='Task',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='source', full_name='Task.source', index=0,
|
||||
number=1, type=14, cpp_type=8, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='zone_id', full_name='Task.zone_id', index=1,
|
||||
number=2, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='duration', full_name='Task.duration', index=2,
|
||||
number=3, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='datetime_started', full_name='Task.datetime_started', index=3,
|
||||
number=4, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='datetime_finished', full_name='Task.datetime_finished', index=4,
|
||||
number=5, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=314,
|
||||
serialized_end=461,
|
||||
)
|
||||
|
||||
|
||||
_TASKLIST = _descriptor.Descriptor(
|
||||
name='TaskList',
|
||||
full_name='TaskList',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='tasks', full_name='TaskList.tasks', index=0,
|
||||
number=1, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='now', full_name='TaskList.now', index=1,
|
||||
number=2, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=463,
|
||||
serialized_end=520,
|
||||
)
|
||||
|
||||
|
||||
_JOB = _descriptor.Descriptor(
|
||||
name='Job',
|
||||
full_name='Job',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='Job.id', index=0,
|
||||
number=1, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='date', full_name='Job.date', index=1,
|
||||
number=2, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='duration', full_name='Job.duration', index=2,
|
||||
number=3, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='zones', full_name='Job.zones', index=3,
|
||||
number=4, type=5, cpp_type=1, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='enable', full_name='Job.enable', index=4,
|
||||
number=5, type=8, cpp_type=7, label=1,
|
||||
has_default_value=False, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='repeat', full_name='Job.repeat', index=5,
|
||||
number=6, type=8, cpp_type=7, label=1,
|
||||
has_default_value=False, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=522,
|
||||
serialized_end=630,
|
||||
)
|
||||
|
||||
|
||||
_JOBID = _descriptor.Descriptor(
|
||||
name='JobID',
|
||||
full_name='JobID',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='id', full_name='JobID.id', index=0,
|
||||
number=1, type=5, cpp_type=1, label=1,
|
||||
has_default_value=False, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=632,
|
||||
serialized_end=651,
|
||||
)
|
||||
|
||||
|
||||
_JOBLIST = _descriptor.Descriptor(
|
||||
name='JobList',
|
||||
full_name='JobList',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='jobs', full_name='JobList.jobs', index=0,
|
||||
number=1, type=11, cpp_type=10, label=3,
|
||||
has_default_value=False, default_value=[],
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=653,
|
||||
serialized_end=682,
|
||||
)
|
||||
|
||||
|
||||
_CONFIGTIME = _descriptor.Descriptor(
|
||||
name='ConfigTime',
|
||||
full_name='ConfigTime',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
_descriptor.FieldDescriptor(
|
||||
name='datetime', full_name='ConfigTime.datetime', index=0,
|
||||
number=1, type=11, cpp_type=10, label=1,
|
||||
has_default_value=False, default_value=None,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
_descriptor.FieldDescriptor(
|
||||
name='timezone', full_name='ConfigTime.timezone', index=1,
|
||||
number=2, type=9, cpp_type=9, label=1,
|
||||
has_default_value=False, default_value=b"".decode('utf-8'),
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=False, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
extensions=[
|
||||
],
|
||||
nested_types=[],
|
||||
enum_types=[
|
||||
],
|
||||
serialized_options=None,
|
||||
is_extendable=False,
|
||||
syntax='proto3',
|
||||
extension_ranges=[],
|
||||
oneofs=[
|
||||
],
|
||||
serialized_start=684,
|
||||
serialized_end=744,
|
||||
)
|
||||
|
||||
_TASKREQUEST.fields_by_name['source'].enum_type = _TASKSOURCE
|
||||
_TASK.fields_by_name['source'].enum_type = _TASKSOURCE
|
||||
_TASK.fields_by_name['datetime_started'].message_type = _TIMESTAMP
|
||||
_TASK.fields_by_name['datetime_finished'].message_type = _TIMESTAMP
|
||||
_TASKLIST.fields_by_name['tasks'].message_type = _TASK
|
||||
_TASKLIST.fields_by_name['now'].message_type = _TIMESTAMP
|
||||
_JOB.fields_by_name['date'].message_type = _TIMESTAMP
|
||||
_JOBLIST.fields_by_name['jobs'].message_type = _JOB
|
||||
_CONFIGTIME.fields_by_name['datetime'].message_type = _TIMESTAMP
|
||||
DESCRIPTOR.message_types_by_name['Timestamp'] = _TIMESTAMP
|
||||
DESCRIPTOR.message_types_by_name['TaskRequest'] = _TASKREQUEST
|
||||
DESCRIPTOR.message_types_by_name['TaskRequestResult'] = _TASKREQUESTRESULT
|
||||
DESCRIPTOR.message_types_by_name['Task'] = _TASK
|
||||
DESCRIPTOR.message_types_by_name['TaskList'] = _TASKLIST
|
||||
DESCRIPTOR.message_types_by_name['Job'] = _JOB
|
||||
DESCRIPTOR.message_types_by_name['JobID'] = _JOBID
|
||||
DESCRIPTOR.message_types_by_name['JobList'] = _JOBLIST
|
||||
DESCRIPTOR.message_types_by_name['ConfigTime'] = _CONFIGTIME
|
||||
DESCRIPTOR.enum_types_by_name['TaskSource'] = _TASKSOURCE
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
Timestamp = _reflection.GeneratedProtocolMessageType('Timestamp', (_message.Message,), {
|
||||
'DESCRIPTOR' : _TIMESTAMP,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Timestamp)
|
||||
})
|
||||
_sym_db.RegisterMessage(Timestamp)
|
||||
|
||||
TaskRequest = _reflection.GeneratedProtocolMessageType('TaskRequest', (_message.Message,), {
|
||||
'DESCRIPTOR' : _TASKREQUEST,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:TaskRequest)
|
||||
})
|
||||
_sym_db.RegisterMessage(TaskRequest)
|
||||
|
||||
TaskRequestResult = _reflection.GeneratedProtocolMessageType('TaskRequestResult', (_message.Message,), {
|
||||
'DESCRIPTOR' : _TASKREQUESTRESULT,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:TaskRequestResult)
|
||||
})
|
||||
_sym_db.RegisterMessage(TaskRequestResult)
|
||||
|
||||
Task = _reflection.GeneratedProtocolMessageType('Task', (_message.Message,), {
|
||||
'DESCRIPTOR' : _TASK,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Task)
|
||||
})
|
||||
_sym_db.RegisterMessage(Task)
|
||||
|
||||
TaskList = _reflection.GeneratedProtocolMessageType('TaskList', (_message.Message,), {
|
||||
'DESCRIPTOR' : _TASKLIST,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:TaskList)
|
||||
})
|
||||
_sym_db.RegisterMessage(TaskList)
|
||||
|
||||
Job = _reflection.GeneratedProtocolMessageType('Job', (_message.Message,), {
|
||||
'DESCRIPTOR' : _JOB,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:Job)
|
||||
})
|
||||
_sym_db.RegisterMessage(Job)
|
||||
|
||||
JobID = _reflection.GeneratedProtocolMessageType('JobID', (_message.Message,), {
|
||||
'DESCRIPTOR' : _JOBID,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:JobID)
|
||||
})
|
||||
_sym_db.RegisterMessage(JobID)
|
||||
|
||||
JobList = _reflection.GeneratedProtocolMessageType('JobList', (_message.Message,), {
|
||||
'DESCRIPTOR' : _JOBLIST,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:JobList)
|
||||
})
|
||||
_sym_db.RegisterMessage(JobList)
|
||||
|
||||
ConfigTime = _reflection.GeneratedProtocolMessageType('ConfigTime', (_message.Message,), {
|
||||
'DESCRIPTOR' : _CONFIGTIME,
|
||||
'__module__' : 'tsgrain_controller.grpc_generated.tsgrain_pb2'
|
||||
# @@protoc_insertion_point(class_scope:ConfigTime)
|
||||
})
|
||||
_sym_db.RegisterMessage(ConfigTime)
|
||||
|
||||
|
||||
|
||||
_TSGRAIN = _descriptor.ServiceDescriptor(
|
||||
name='TSGRain',
|
||||
full_name='TSGRain',
|
||||
file=DESCRIPTOR,
|
||||
index=0,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
serialized_start=787,
|
||||
serialized_end=1558,
|
||||
methods=[
|
||||
_descriptor.MethodDescriptor(
|
||||
name='StartTask',
|
||||
full_name='TSGRain.StartTask',
|
||||
index=0,
|
||||
containing_service=None,
|
||||
input_type=_TASKREQUEST,
|
||||
output_type=_TASKREQUESTRESULT,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='GetTasks',
|
||||
full_name='TSGRain.GetTasks',
|
||||
index=1,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
output_type=_TASKLIST,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='StreamTasks',
|
||||
full_name='TSGRain.StreamTasks',
|
||||
index=2,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
output_type=_TASKLIST,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='CreateJob',
|
||||
full_name='TSGRain.CreateJob',
|
||||
index=3,
|
||||
containing_service=None,
|
||||
input_type=_JOB,
|
||||
output_type=_JOBID,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='GetJob',
|
||||
full_name='TSGRain.GetJob',
|
||||
index=4,
|
||||
containing_service=None,
|
||||
input_type=_JOBID,
|
||||
output_type=_JOB,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='GetJobs',
|
||||
full_name='TSGRain.GetJobs',
|
||||
index=5,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
output_type=_JOBLIST,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='UpdateJob',
|
||||
full_name='TSGRain.UpdateJob',
|
||||
index=6,
|
||||
containing_service=None,
|
||||
input_type=_JOB,
|
||||
output_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='DeleteJob',
|
||||
full_name='TSGRain.DeleteJob',
|
||||
index=7,
|
||||
containing_service=None,
|
||||
input_type=_JOBID,
|
||||
output_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='GetAutoMode',
|
||||
full_name='TSGRain.GetAutoMode',
|
||||
index=8,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
output_type=google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='SetAutoMode',
|
||||
full_name='TSGRain.SetAutoMode',
|
||||
index=9,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_wrappers__pb2._BOOLVALUE,
|
||||
output_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='GetConfigTime',
|
||||
full_name='TSGRain.GetConfigTime',
|
||||
index=10,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
output_type=_CONFIGTIME,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='SetConfigTime',
|
||||
full_name='TSGRain.SetConfigTime',
|
||||
index=11,
|
||||
containing_service=None,
|
||||
input_type=_CONFIGTIME,
|
||||
output_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='GetDefaultIrrigationTime',
|
||||
full_name='TSGRain.GetDefaultIrrigationTime',
|
||||
index=12,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
output_type=google_dot_protobuf_dot_wrappers__pb2._INT32VALUE,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
_descriptor.MethodDescriptor(
|
||||
name='SetDefaultIrrigationTime',
|
||||
full_name='TSGRain.SetDefaultIrrigationTime',
|
||||
index=13,
|
||||
containing_service=None,
|
||||
input_type=google_dot_protobuf_dot_wrappers__pb2._INT32VALUE,
|
||||
output_type=google_dot_protobuf_dot_empty__pb2._EMPTY,
|
||||
serialized_options=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
),
|
||||
])
|
||||
_sym_db.RegisterServiceDescriptor(_TSGRAIN)
|
||||
|
||||
DESCRIPTOR.services_by_name['TSGRain'] = _TSGRAIN
|
||||
|
||||
# @@protoc_insertion_point(module_scope)
|
|
@ -1,189 +0,0 @@
|
|||
"""
|
||||
@generated by mypy-protobuf. Do not edit manually!
|
||||
isort:skip_file
|
||||
"""
|
||||
import builtins
|
||||
import google.protobuf.descriptor
|
||||
import google.protobuf.internal.containers
|
||||
import google.protobuf.internal.enum_type_wrapper
|
||||
import google.protobuf.message
|
||||
import typing
|
||||
import typing_extensions
|
||||
|
||||
DESCRIPTOR: google.protobuf.descriptor.FileDescriptor
|
||||
|
||||
class _TaskSource:
|
||||
ValueType = typing.NewType('ValueType', builtins.int)
|
||||
V: typing_extensions.TypeAlias = ValueType
|
||||
class _TaskSourceEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[_TaskSource.ValueType], builtins.type):
|
||||
DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor
|
||||
MANUAL: _TaskSource.ValueType # 0
|
||||
SCHEDULE: _TaskSource.ValueType # 1
|
||||
class TaskSource(_TaskSource, metaclass=_TaskSourceEnumTypeWrapper):
|
||||
"""Quelle einer Bewässerungsaufgabe"""
|
||||
pass
|
||||
|
||||
MANUAL: TaskSource.ValueType # 0
|
||||
SCHEDULE: TaskSource.ValueType # 1
|
||||
global___TaskSource = TaskSource
|
||||
|
||||
|
||||
class Timestamp(google.protobuf.message.Message):
|
||||
"""Unix-Zeitstempel"""
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
SECONDS_FIELD_NUMBER: builtins.int
|
||||
seconds: builtins.int
|
||||
def __init__(self,
|
||||
*,
|
||||
seconds: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["seconds",b"seconds"]) -> None: ...
|
||||
global___Timestamp = Timestamp
|
||||
|
||||
class TaskRequest(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
SOURCE_FIELD_NUMBER: builtins.int
|
||||
ZONE_ID_FIELD_NUMBER: builtins.int
|
||||
DURATION_FIELD_NUMBER: builtins.int
|
||||
QUEUING_FIELD_NUMBER: builtins.int
|
||||
CANCELLING_FIELD_NUMBER: builtins.int
|
||||
source: global___TaskSource.ValueType
|
||||
zone_id: builtins.int
|
||||
duration: builtins.int
|
||||
queuing: builtins.bool
|
||||
cancelling: builtins.bool
|
||||
def __init__(self,
|
||||
*,
|
||||
source: global___TaskSource.ValueType = ...,
|
||||
zone_id: builtins.int = ...,
|
||||
duration: builtins.int = ...,
|
||||
queuing: builtins.bool = ...,
|
||||
cancelling: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["cancelling",b"cancelling","duration",b"duration","queuing",b"queuing","source",b"source","zone_id",b"zone_id"]) -> None: ...
|
||||
global___TaskRequest = TaskRequest
|
||||
|
||||
class TaskRequestResult(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
STARTED_FIELD_NUMBER: builtins.int
|
||||
STOPPED_FIELD_NUMBER: builtins.int
|
||||
started: builtins.bool
|
||||
stopped: builtins.bool
|
||||
def __init__(self,
|
||||
*,
|
||||
started: builtins.bool = ...,
|
||||
stopped: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["started",b"started","stopped",b"stopped"]) -> None: ...
|
||||
global___TaskRequestResult = TaskRequestResult
|
||||
|
||||
class Task(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
SOURCE_FIELD_NUMBER: builtins.int
|
||||
ZONE_ID_FIELD_NUMBER: builtins.int
|
||||
DURATION_FIELD_NUMBER: builtins.int
|
||||
DATETIME_STARTED_FIELD_NUMBER: builtins.int
|
||||
DATETIME_FINISHED_FIELD_NUMBER: builtins.int
|
||||
source: global___TaskSource.ValueType
|
||||
zone_id: builtins.int
|
||||
duration: builtins.int
|
||||
@property
|
||||
def datetime_started(self) -> global___Timestamp: ...
|
||||
@property
|
||||
def datetime_finished(self) -> global___Timestamp: ...
|
||||
def __init__(self,
|
||||
*,
|
||||
source: global___TaskSource.ValueType = ...,
|
||||
zone_id: builtins.int = ...,
|
||||
duration: builtins.int = ...,
|
||||
datetime_started: typing.Optional[global___Timestamp] = ...,
|
||||
datetime_finished: typing.Optional[global___Timestamp] = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing_extensions.Literal["datetime_finished",b"datetime_finished","datetime_started",b"datetime_started"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["datetime_finished",b"datetime_finished","datetime_started",b"datetime_started","duration",b"duration","source",b"source","zone_id",b"zone_id"]) -> None: ...
|
||||
global___Task = Task
|
||||
|
||||
class TaskList(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
TASKS_FIELD_NUMBER: builtins.int
|
||||
NOW_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def tasks(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Task]: ...
|
||||
@property
|
||||
def now(self) -> global___Timestamp: ...
|
||||
def __init__(self,
|
||||
*,
|
||||
tasks: typing.Optional[typing.Iterable[global___Task]] = ...,
|
||||
now: typing.Optional[global___Timestamp] = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing_extensions.Literal["now",b"now"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["now",b"now","tasks",b"tasks"]) -> None: ...
|
||||
global___TaskList = TaskList
|
||||
|
||||
class Job(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
ID_FIELD_NUMBER: builtins.int
|
||||
DATE_FIELD_NUMBER: builtins.int
|
||||
DURATION_FIELD_NUMBER: builtins.int
|
||||
ZONES_FIELD_NUMBER: builtins.int
|
||||
ENABLE_FIELD_NUMBER: builtins.int
|
||||
REPEAT_FIELD_NUMBER: builtins.int
|
||||
id: builtins.int
|
||||
@property
|
||||
def date(self) -> global___Timestamp: ...
|
||||
duration: builtins.int
|
||||
@property
|
||||
def zones(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ...
|
||||
enable: builtins.bool
|
||||
repeat: builtins.bool
|
||||
def __init__(self,
|
||||
*,
|
||||
id: builtins.int = ...,
|
||||
date: typing.Optional[global___Timestamp] = ...,
|
||||
duration: builtins.int = ...,
|
||||
zones: typing.Optional[typing.Iterable[builtins.int]] = ...,
|
||||
enable: builtins.bool = ...,
|
||||
repeat: builtins.bool = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing_extensions.Literal["date",b"date"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["date",b"date","duration",b"duration","enable",b"enable","id",b"id","repeat",b"repeat","zones",b"zones"]) -> None: ...
|
||||
global___Job = Job
|
||||
|
||||
class JobID(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
ID_FIELD_NUMBER: builtins.int
|
||||
id: builtins.int
|
||||
def __init__(self,
|
||||
*,
|
||||
id: builtins.int = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["id",b"id"]) -> None: ...
|
||||
global___JobID = JobID
|
||||
|
||||
class JobList(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
JOBS_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def jobs(self) -> google.protobuf.internal.containers.RepeatedCompositeFieldContainer[global___Job]: ...
|
||||
def __init__(self,
|
||||
*,
|
||||
jobs: typing.Optional[typing.Iterable[global___Job]] = ...,
|
||||
) -> None: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["jobs",b"jobs"]) -> None: ...
|
||||
global___JobList = JobList
|
||||
|
||||
class ConfigTime(google.protobuf.message.Message):
|
||||
DESCRIPTOR: google.protobuf.descriptor.Descriptor
|
||||
DATETIME_FIELD_NUMBER: builtins.int
|
||||
TIMEZONE_FIELD_NUMBER: builtins.int
|
||||
@property
|
||||
def datetime(self) -> global___Timestamp: ...
|
||||
timezone: typing.Text
|
||||
def __init__(self,
|
||||
*,
|
||||
datetime: typing.Optional[global___Timestamp] = ...,
|
||||
timezone: typing.Text = ...,
|
||||
) -> None: ...
|
||||
def HasField(self, field_name: typing_extensions.Literal["datetime",b"datetime"]) -> builtins.bool: ...
|
||||
def ClearField(self, field_name: typing_extensions.Literal["datetime",b"datetime","timezone",b"timezone"]) -> None: ...
|
||||
global___ConfigTime = ConfigTime
|
|
@ -1,513 +0,0 @@
|
|||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
||||
"""Client and server classes corresponding to protobuf-defined services."""
|
||||
import grpc
|
||||
|
||||
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
|
||||
from google.protobuf import wrappers_pb2 as google_dot_protobuf_dot_wrappers__pb2
|
||||
from tsgrain_controller.grpc_generated import tsgrain_pb2 as tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2
|
||||
|
||||
|
||||
class TSGRainStub(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def __init__(self, channel):
|
||||
"""Constructor.
|
||||
|
||||
Args:
|
||||
channel: A grpc.Channel.
|
||||
"""
|
||||
self.StartTask = channel.unary_unary(
|
||||
'/TSGRain/StartTask',
|
||||
request_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskRequest.SerializeToString,
|
||||
response_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskRequestResult.FromString,
|
||||
)
|
||||
self.GetTasks = channel.unary_unary(
|
||||
'/TSGRain/GetTasks',
|
||||
request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
response_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskList.FromString,
|
||||
)
|
||||
self.StreamTasks = channel.unary_stream(
|
||||
'/TSGRain/StreamTasks',
|
||||
request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
response_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskList.FromString,
|
||||
)
|
||||
self.CreateJob = channel.unary_unary(
|
||||
'/TSGRain/CreateJob',
|
||||
request_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.SerializeToString,
|
||||
response_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.FromString,
|
||||
)
|
||||
self.GetJob = channel.unary_unary(
|
||||
'/TSGRain/GetJob',
|
||||
request_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.SerializeToString,
|
||||
response_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.FromString,
|
||||
)
|
||||
self.GetJobs = channel.unary_unary(
|
||||
'/TSGRain/GetJobs',
|
||||
request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
response_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobList.FromString,
|
||||
)
|
||||
self.UpdateJob = channel.unary_unary(
|
||||
'/TSGRain/UpdateJob',
|
||||
request_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.SerializeToString,
|
||||
response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
)
|
||||
self.DeleteJob = channel.unary_unary(
|
||||
'/TSGRain/DeleteJob',
|
||||
request_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.SerializeToString,
|
||||
response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
)
|
||||
self.GetAutoMode = channel.unary_unary(
|
||||
'/TSGRain/GetAutoMode',
|
||||
request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
response_deserializer=google_dot_protobuf_dot_wrappers__pb2.BoolValue.FromString,
|
||||
)
|
||||
self.SetAutoMode = channel.unary_unary(
|
||||
'/TSGRain/SetAutoMode',
|
||||
request_serializer=google_dot_protobuf_dot_wrappers__pb2.BoolValue.SerializeToString,
|
||||
response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
)
|
||||
self.GetConfigTime = channel.unary_unary(
|
||||
'/TSGRain/GetConfigTime',
|
||||
request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
response_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.ConfigTime.FromString,
|
||||
)
|
||||
self.SetConfigTime = channel.unary_unary(
|
||||
'/TSGRain/SetConfigTime',
|
||||
request_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.ConfigTime.SerializeToString,
|
||||
response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
)
|
||||
self.GetDefaultIrrigationTime = channel.unary_unary(
|
||||
'/TSGRain/GetDefaultIrrigationTime',
|
||||
request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
response_deserializer=google_dot_protobuf_dot_wrappers__pb2.Int32Value.FromString,
|
||||
)
|
||||
self.SetDefaultIrrigationTime = channel.unary_unary(
|
||||
'/TSGRain/SetDefaultIrrigationTime',
|
||||
request_serializer=google_dot_protobuf_dot_wrappers__pb2.Int32Value.SerializeToString,
|
||||
response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
)
|
||||
|
||||
|
||||
class TSGRainServicer(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
def StartTask(self, request, context):
|
||||
"""Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn
|
||||
diese bereits läuft).
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetTasks(self, request, context):
|
||||
"""Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def StreamTasks(self, request, context):
|
||||
"""Streamt die aktuelle Warteschlange mit ihren Bewässerungsaufgaben,
|
||||
d.h. bei Änderung wird die neue Version übertragen.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def CreateJob(self, request, context):
|
||||
"""Erstelle einen neuen Bewässerungsjob.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetJob(self, request, context):
|
||||
"""Gibt den Bewässerungsjob mit der gegebenen ID zurück.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetJobs(self, request, context):
|
||||
"""Gibt alle gespeicherten Bewässerungsjobs zurück.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def UpdateJob(self, request, context):
|
||||
"""Aktualisiert einen Bewässerungsjob.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def DeleteJob(self, request, context):
|
||||
"""Lösche den Bewässerungsjob mit der gegebenen ID.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetAutoMode(self, request, context):
|
||||
"""Gibt zurück, ob der Automatikmodus aktiviert ist.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def SetAutoMode(self, request, context):
|
||||
"""Aktiviert/deaktiviert den Automatikmodus.
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetConfigTime(self, request, context):
|
||||
"""Datum/Uhrzeit/Zeitzone abrufen
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def SetConfigTime(self, request, context):
|
||||
"""Datum/Uhrzeit/Zeitzone einstellen
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def GetDefaultIrrigationTime(self, request, context):
|
||||
"""Standardzeit bei manueller Bewässerung abrufen
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
def SetDefaultIrrigationTime(self, request, context):
|
||||
"""Standardzeit bei manueller Bewässerung einstellen
|
||||
"""
|
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
||||
context.set_details('Method not implemented!')
|
||||
raise NotImplementedError('Method not implemented!')
|
||||
|
||||
|
||||
def add_TSGRainServicer_to_server(servicer, server):
|
||||
rpc_method_handlers = {
|
||||
'StartTask': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.StartTask,
|
||||
request_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskRequest.FromString,
|
||||
response_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskRequestResult.SerializeToString,
|
||||
),
|
||||
'GetTasks': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetTasks,
|
||||
request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
response_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskList.SerializeToString,
|
||||
),
|
||||
'StreamTasks': grpc.unary_stream_rpc_method_handler(
|
||||
servicer.StreamTasks,
|
||||
request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
response_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskList.SerializeToString,
|
||||
),
|
||||
'CreateJob': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.CreateJob,
|
||||
request_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.FromString,
|
||||
response_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.SerializeToString,
|
||||
),
|
||||
'GetJob': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetJob,
|
||||
request_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.FromString,
|
||||
response_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.SerializeToString,
|
||||
),
|
||||
'GetJobs': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetJobs,
|
||||
request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
response_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobList.SerializeToString,
|
||||
),
|
||||
'UpdateJob': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.UpdateJob,
|
||||
request_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.FromString,
|
||||
response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
),
|
||||
'DeleteJob': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.DeleteJob,
|
||||
request_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.FromString,
|
||||
response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
),
|
||||
'GetAutoMode': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetAutoMode,
|
||||
request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
response_serializer=google_dot_protobuf_dot_wrappers__pb2.BoolValue.SerializeToString,
|
||||
),
|
||||
'SetAutoMode': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SetAutoMode,
|
||||
request_deserializer=google_dot_protobuf_dot_wrappers__pb2.BoolValue.FromString,
|
||||
response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
),
|
||||
'GetConfigTime': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetConfigTime,
|
||||
request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
response_serializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.ConfigTime.SerializeToString,
|
||||
),
|
||||
'SetConfigTime': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SetConfigTime,
|
||||
request_deserializer=tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.ConfigTime.FromString,
|
||||
response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
),
|
||||
'GetDefaultIrrigationTime': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.GetDefaultIrrigationTime,
|
||||
request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
response_serializer=google_dot_protobuf_dot_wrappers__pb2.Int32Value.SerializeToString,
|
||||
),
|
||||
'SetDefaultIrrigationTime': grpc.unary_unary_rpc_method_handler(
|
||||
servicer.SetDefaultIrrigationTime,
|
||||
request_deserializer=google_dot_protobuf_dot_wrappers__pb2.Int32Value.FromString,
|
||||
response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
),
|
||||
}
|
||||
generic_handler = grpc.method_handlers_generic_handler(
|
||||
'TSGRain', rpc_method_handlers)
|
||||
server.add_generic_rpc_handlers((generic_handler,))
|
||||
|
||||
|
||||
# This class is part of an EXPERIMENTAL API.
|
||||
class TSGRain(object):
|
||||
"""Missing associated documentation comment in .proto file."""
|
||||
|
||||
@staticmethod
|
||||
def StartTask(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/StartTask',
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskRequest.SerializeToString,
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskRequestResult.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetTasks(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/GetTasks',
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskList.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def StreamTasks(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_stream(request, target, '/TSGRain/StreamTasks',
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.TaskList.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def CreateJob(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/CreateJob',
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.SerializeToString,
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetJob(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/GetJob',
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.SerializeToString,
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetJobs(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/GetJobs',
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobList.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def UpdateJob(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/UpdateJob',
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.Job.SerializeToString,
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def DeleteJob(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/DeleteJob',
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.JobID.SerializeToString,
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetAutoMode(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/GetAutoMode',
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
google_dot_protobuf_dot_wrappers__pb2.BoolValue.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def SetAutoMode(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/SetAutoMode',
|
||||
google_dot_protobuf_dot_wrappers__pb2.BoolValue.SerializeToString,
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetConfigTime(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/GetConfigTime',
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.ConfigTime.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def SetConfigTime(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/SetConfigTime',
|
||||
tsgrain__controller_dot_grpc__generated_dot_tsgrain__pb2.ConfigTime.SerializeToString,
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def GetDefaultIrrigationTime(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/GetDefaultIrrigationTime',
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
|
||||
google_dot_protobuf_dot_wrappers__pb2.Int32Value.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
||||
|
||||
@staticmethod
|
||||
def SetDefaultIrrigationTime(request,
|
||||
target,
|
||||
options=(),
|
||||
channel_credentials=None,
|
||||
call_credentials=None,
|
||||
insecure=False,
|
||||
compression=None,
|
||||
wait_for_ready=None,
|
||||
timeout=None,
|
||||
metadata=None):
|
||||
return grpc.experimental.unary_unary(request, target, '/TSGRain/SetDefaultIrrigationTime',
|
||||
google_dot_protobuf_dot_wrappers__pb2.Int32Value.SerializeToString,
|
||||
google_dot_protobuf_dot_empty__pb2.Empty.FromString,
|
||||
options, channel_credentials,
|
||||
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
@ -1,151 +0,0 @@
|
|||
# coding=utf-8
|
||||
import threading
|
||||
from concurrent import futures
|
||||
from typing import Generator
|
||||
import logging
|
||||
import grpc
|
||||
from google.protobuf import empty_pb2, wrappers_pb2
|
||||
|
||||
from tsgrain_controller import models, util
|
||||
from tsgrain_controller.grpc_generated import tsgrain_pb2, tsgrain_pb2_grpc
|
||||
|
||||
task_request = tsgrain_pb2.TaskRequest()
|
||||
task_request.zone_id = 2
|
||||
task_request.duration = 30
|
||||
|
||||
|
||||
class TSGRainServicer(tsgrain_pb2_grpc.TSGRainServicer):
|
||||
|
||||
def __init__(self, app: models.AppInterface):
|
||||
self.app = app
|
||||
self.queue_update = threading.Event()
|
||||
|
||||
def StartTask(self, request: tsgrain_pb2.TaskRequest,
|
||||
context) -> tsgrain_pb2.Task:
|
||||
logging.info('GRPC StartTask: %s', request)
|
||||
res = self.app.start_task(
|
||||
models.TaskRequest.deserialize_proto(request))
|
||||
return res.serialize_proto()
|
||||
|
||||
def _get_tasks(self) -> tsgrain_pb2.TaskList:
|
||||
app_tasks = self.app.get_tasks()
|
||||
tasks = [task.serialize_proto() for task in app_tasks]
|
||||
|
||||
return tsgrain_pb2.TaskList(now=util.datetime_to_proto(
|
||||
util.datetime_now()),
|
||||
tasks=tasks)
|
||||
|
||||
def GetTasks(self, request: empty_pb2.Empty,
|
||||
context) -> tsgrain_pb2.TaskList:
|
||||
logging.info('GRPC GetTasks: %s', request)
|
||||
|
||||
return self._get_tasks()
|
||||
|
||||
def StreamTasks(self, request: empty_pb2.Empty,
|
||||
context) -> Generator[tsgrain_pb2.TaskList, None, None]:
|
||||
logging.info('GRPC StreamTasks: %s', request)
|
||||
|
||||
yield self._get_tasks()
|
||||
self.queue_update.clear()
|
||||
|
||||
while self.app.is_running():
|
||||
if self.queue_update.wait(1):
|
||||
yield self._get_tasks()
|
||||
self.queue_update.clear()
|
||||
|
||||
def CreateJob(self, request: tsgrain_pb2.Job,
|
||||
context) -> tsgrain_pb2.JobID:
|
||||
logging.info('GRPC CreateJob: %s', request)
|
||||
|
||||
job = models.Job.deserialize_proto(request)
|
||||
job_id = self.app.create_job(job)
|
||||
return tsgrain_pb2.JobID(id=job_id)
|
||||
|
||||
def GetJob(self, request: tsgrain_pb2.JobID, context) -> tsgrain_pb2.Job:
|
||||
logging.info('GRPC GetJob: %s', request)
|
||||
|
||||
try:
|
||||
job = self.app.get_job(request.id)
|
||||
except KeyError:
|
||||
context.set_code(grpc.StatusCode.NOT_FOUND)
|
||||
raise
|
||||
|
||||
return job.serialize_proto()
|
||||
|
||||
def GetJobs(self, request: empty_pb2.Empty,
|
||||
context) -> tsgrain_pb2.JobList:
|
||||
logging.info('GRPC GetJobs: %s', request)
|
||||
|
||||
jobs = [job.serialize_proto() for job in self.app.get_jobs()]
|
||||
return tsgrain_pb2.JobList(jobs=jobs)
|
||||
|
||||
def UpdateJob(self, request: tsgrain_pb2.Job, context) -> empty_pb2.Empty:
|
||||
logging.info('GRPC UpdateJob: %s', request)
|
||||
|
||||
job = models.Job.deserialize_proto(request)
|
||||
self.app.update_job(job)
|
||||
|
||||
return empty_pb2.Empty()
|
||||
|
||||
def DeleteJob(self, request: tsgrain_pb2.JobID,
|
||||
context) -> empty_pb2.Empty:
|
||||
logging.info('GRPC DeleteJob: %s', request)
|
||||
|
||||
try:
|
||||
self.app.delete_job(request.id)
|
||||
except KeyError:
|
||||
context.set_code(grpc.StatusCode.NOT_FOUND)
|
||||
raise
|
||||
|
||||
return empty_pb2.Empty()
|
||||
|
||||
def GetAutoMode(self, request: empty_pb2.Empty,
|
||||
context) -> wrappers_pb2.BoolValue:
|
||||
logging.info('GRPC GetAutoMode: %s', request)
|
||||
|
||||
return wrappers_pb2.BoolValue(value=self.app.get_auto_mode())
|
||||
|
||||
def SetAutoMode(self, request: wrappers_pb2.BoolValue,
|
||||
context) -> empty_pb2.Empty:
|
||||
logging.info('GRPC SetAutoMode: %s', request)
|
||||
|
||||
self.app.set_auto_mode(request.value)
|
||||
return empty_pb2.Empty()
|
||||
|
||||
def GetConfigTime(self, request: empty_pb2.Empty,
|
||||
context) -> tsgrain_pb2.ConfigTime:
|
||||
logging.info('GRPC GetConfigTime: %s', request)
|
||||
|
||||
# TODO: system time config
|
||||
# return tsgrain_pb2.ConfigTime(
|
||||
# datetime=util.datetime_to_proto(util.datetime_now()),
|
||||
# timezone=
|
||||
# )
|
||||
|
||||
return super().SetConfigTime(request, context)
|
||||
|
||||
def SetConfigTime(self, request: tsgrain_pb2.ConfigTime,
|
||||
context) -> empty_pb2.Empty:
|
||||
logging.info('GRPC SetConfigTime: %s', request)
|
||||
|
||||
return super().SetConfigTime(request, context)
|
||||
|
||||
def GetDefaultIrrigationTime(self, request: empty_pb2.Empty,
|
||||
context) -> wrappers_pb2.Int32Value:
|
||||
logging.info('GRPC GetDefaultIrrigationTime: %s', request)
|
||||
|
||||
return wrappers_pb2.Int32Value(value=self.app.get_cfg().manual_time)
|
||||
|
||||
def SetDefaultIrrigationTime(self, request: wrappers_pb2.Int32Value,
|
||||
context) -> empty_pb2.Empty:
|
||||
logging.info('GRPC SetDefaultIrrigationTime: %s', request)
|
||||
|
||||
self.app.get_cfg().manual_time = request.value
|
||||
return empty_pb2.Empty()
|
||||
|
||||
|
||||
def new_server(servicer: TSGRainServicer, port: str) -> grpc.Server:
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=2))
|
||||
tsgrain_pb2_grpc.add_TSGRainServicer_to_server(servicer, server)
|
||||
server.add_insecure_port(port)
|
||||
return server
|
|
@ -1,25 +1,14 @@
|
|||
# coding=utf-8
|
||||
from typing import Callable, Optional
|
||||
|
||||
from tsgrain_controller import util
|
||||
|
||||
|
||||
class Io:
|
||||
|
||||
def __init__(self):
|
||||
self.cb_manual: Optional[Callable[[int], None]] = None
|
||||
self.cb_mode: Optional[Callable[[], None]] = None
|
||||
|
||||
def set_callbacks(self, cb_manual: Optional[Callable[[int], None]],
|
||||
cb_mode: Optional[Callable[[], None]]):
|
||||
self.cb_manual = cb_manual
|
||||
self.cb_mode = cb_mode
|
||||
|
||||
def _trigger_cb_manual(self, zone_id: int):
|
||||
if self.cb_manual is not None:
|
||||
self.cb_manual(zone_id)
|
||||
|
||||
def _trigger_cb_mode(self):
|
||||
if self.cb_mode is not None:
|
||||
self.cb_mode()
|
||||
pass
|
||||
|
||||
def start(self):
|
||||
pass
|
||||
|
@ -29,3 +18,15 @@ class Io:
|
|||
|
||||
def write_output(self, key: str, val: bool):
|
||||
pass
|
||||
|
||||
|
||||
def new_io(app: util.AppInterface, console_flag: bool) -> Io:
|
||||
if not console_flag:
|
||||
try:
|
||||
from tsgrain_controller.io import mcp23017 as io_mod
|
||||
except ImportError:
|
||||
from tsgrain_controller.io import console as io_mod
|
||||
else:
|
||||
from tsgrain_controller.io import console as io_mod
|
||||
|
||||
return io_mod.Io(app)
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
import curses
|
||||
import logging
|
||||
import math
|
||||
from typing import Dict, Optional
|
||||
from typing import Callable, Dict, Optional
|
||||
|
||||
from tsgrain_controller import io, util, models
|
||||
from tsgrain_controller import io, util
|
||||
|
||||
|
||||
class CursesHandler(logging.Handler):
|
||||
|
@ -28,18 +28,25 @@ class CursesHandler(logging.Handler):
|
|||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
|
||||
except: # pylint: disable=bare-except
|
||||
except: # noqa: E722
|
||||
self.handleError(record)
|
||||
|
||||
|
||||
class Io(util.StoppableThread, io.Io):
|
||||
|
||||
def __init__(self, app: models.AppInterface):
|
||||
def __init__(self, app: util.AppInterface):
|
||||
super().__init__(0.01)
|
||||
self.app = app
|
||||
self.cb_manual: Optional[Callable[[int], None]] = None
|
||||
self.cb_mode: Optional[Callable[[], None]] = None
|
||||
|
||||
self._screen: Optional = None
|
||||
self._outputs: Dict[str, bool] = {}
|
||||
self._outputs: Dict[str, bool] = dict()
|
||||
|
||||
def set_callbacks(self, cb_manual: Optional[Callable[[int], None]],
|
||||
cb_mode: Optional[Callable[[], None]]):
|
||||
self.cb_manual = cb_manual
|
||||
self.cb_mode = cb_mode
|
||||
|
||||
def setup(self):
|
||||
screen = curses.initscr()
|
||||
|
@ -61,9 +68,17 @@ class Io(util.StoppableThread, io.Io):
|
|||
|
||||
self._screen.nodelay(True)
|
||||
|
||||
logging.debug('Window size: max_x=%d, max_y=%d, width_half=%d', max_x,
|
||||
logging.info('Window size: max_x=%d, max_y=%d, width_half=%d', max_x,
|
||||
max_y, width_half)
|
||||
|
||||
def _trigger_cb_manual(self, zone_id: int):
|
||||
if self.cb_manual is not None:
|
||||
self.cb_manual(zone_id)
|
||||
|
||||
def _trigger_cb_mode(self):
|
||||
if self.cb_mode is not None:
|
||||
self.cb_mode()
|
||||
|
||||
def write_output(self, key: str, val: bool):
|
||||
self._outputs[key] = val
|
||||
|
||||
|
@ -73,6 +88,7 @@ class Io(util.StoppableThread, io.Io):
|
|||
def state_str(state: bool) -> str:
|
||||
if state:
|
||||
return '●'
|
||||
else:
|
||||
return '○'
|
||||
|
||||
# Mode key (0)
|
||||
|
@ -88,7 +104,7 @@ class Io(util.StoppableThread, io.Io):
|
|||
|
||||
i = 1
|
||||
for key, output in self._outputs.items():
|
||||
self._screen.addstr(i, 0, f'{key}: {state_str(output)}')
|
||||
self._screen.addstr(i, 0, '%s: %s' % (key, state_str(output)))
|
||||
i += 1
|
||||
|
||||
def cleanup(self):
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
# coding=utf-8
|
||||
from tsgrain_controller import models, io
|
||||
|
||||
|
||||
# pylint: disable=import-outside-toplevel
|
||||
def new_io(app: models.AppInterface, console_flag: bool) -> io.Io:
|
||||
if not console_flag:
|
||||
try:
|
||||
from tsgrain_controller.io import mcp23017 as io_mod
|
||||
except ImportError:
|
||||
from tsgrain_controller.io import console as io_mod
|
||||
else:
|
||||
from tsgrain_controller.io import console as io_mod
|
||||
|
||||
return io_mod.Io(app)
|
|
@ -5,10 +5,10 @@ from dataclasses import dataclass
|
|||
from enum import Enum
|
||||
from typing import Callable, Dict, Optional, Tuple
|
||||
|
||||
from RPi import GPIO # pylint: disable=import-error
|
||||
import RPi.GPIO as GPIO
|
||||
import smbus
|
||||
|
||||
from tsgrain_controller import io, models
|
||||
from tsgrain_controller import io, util
|
||||
|
||||
# MCP-Register
|
||||
# Quelle: https://ww1.microchip.com/downloads/en/devicedoc/20001952c.pdf
|
||||
|
@ -193,7 +193,7 @@ die wiederum die als Output konfigurierten Pins ansteuern.
|
|||
class PinConfigInvalid(Exception):
|
||||
|
||||
def __init__(self, cfg_str: str):
|
||||
super().__init__(f'MCP23017 pin config {cfg_str} invalid')
|
||||
super().__init__('MCP23017 pin config %s invalid' % cfg_str)
|
||||
|
||||
|
||||
class _MCP23017Port(Enum):
|
||||
|
@ -223,18 +223,18 @@ class _MCP23017Device:
|
|||
|
||||
try:
|
||||
i2c_addr = int(i2c_addr_str, 16)
|
||||
except ValueError as e:
|
||||
raise PinConfigInvalid(cfg_str) from e
|
||||
except ValueError:
|
||||
raise PinConfigInvalid(cfg_str)
|
||||
|
||||
try:
|
||||
port = _MCP23017Port[port_str]
|
||||
except KeyError as e:
|
||||
raise PinConfigInvalid(cfg_str) from e
|
||||
except KeyError:
|
||||
raise PinConfigInvalid(cfg_str)
|
||||
|
||||
try:
|
||||
pin = int(pin_str)
|
||||
except ValueError as e:
|
||||
raise PinConfigInvalid(cfg_str) from e
|
||||
except ValueError:
|
||||
raise PinConfigInvalid(cfg_str)
|
||||
|
||||
invert = False
|
||||
|
||||
|
@ -248,20 +248,18 @@ class _MCP23017Device:
|
|||
|
||||
class Io(io.Io):
|
||||
|
||||
def __init__(self, app: models.AppInterface):
|
||||
super().__init__()
|
||||
|
||||
def __init__(self, app: util.AppInterface):
|
||||
self.cb_manual: Optional[Callable[[int], None]] = None
|
||||
self.cb_mode: Optional[Callable[[], None]] = None
|
||||
self.cfg = app.get_cfg()
|
||||
|
||||
self.bus = smbus.SMBus(self.cfg.i2c_bus_id)
|
||||
|
||||
self.i2c_cache: Dict[Tuple[int, int], int] = {}
|
||||
self.i2c_cache: Dict[Tuple[int, int], int] = dict()
|
||||
|
||||
self.mcp_addresses = set()
|
||||
self.output_devices: Dict[str, _MCP23017Device] = {}
|
||||
self.input_devices: Dict[str, _MCP23017Device] = {}
|
||||
self.output_devices: Dict[str, _MCP23017Device] = dict()
|
||||
self.input_devices: Dict[str, _MCP23017Device] = dict()
|
||||
|
||||
# Parse config
|
||||
for key, cfg_str in self.cfg.input_devices.items():
|
||||
|
@ -274,6 +272,19 @@ class Io(io.Io):
|
|||
self.mcp_addresses.add(device.i2c_address)
|
||||
self.output_devices[key] = device
|
||||
|
||||
def _trigger_cb_manual(self, zone_id: int):
|
||||
if self.cb_manual is not None:
|
||||
self.cb_manual(zone_id)
|
||||
|
||||
def _trigger_cb_mode(self):
|
||||
if self.cb_mode is not None:
|
||||
self.cb_mode()
|
||||
|
||||
def set_callbacks(self, cb_manual: Optional[Callable[[int], None]],
|
||||
cb_mode: Optional[Callable[[], None]]):
|
||||
self.cb_manual = cb_manual
|
||||
self.cb_mode = cb_mode
|
||||
|
||||
def _i2c_read_byte(self,
|
||||
i2c_address: int,
|
||||
register: int,
|
||||
|
@ -315,7 +326,7 @@ class Io(io.Io):
|
|||
self._i2c_write_byte(i2c_address, register, data)
|
||||
|
||||
def _i2c_clear_cache(self):
|
||||
self.i2c_cache = {}
|
||||
self.i2c_cache = dict()
|
||||
|
||||
def _configure_mcp(self, i2c_address: int):
|
||||
self._i2c_write_byte(i2c_address, MCP_IODIRA, 0xff)
|
||||
|
@ -364,7 +375,7 @@ class Io(io.Io):
|
|||
return None
|
||||
|
||||
def _read_inputs(self) -> Dict[str, bool]:
|
||||
res = {}
|
||||
res = dict()
|
||||
self._i2c_clear_cache()
|
||||
|
||||
for key, device in self.input_devices.items():
|
||||
|
@ -374,7 +385,7 @@ class Io(io.Io):
|
|||
|
||||
return res
|
||||
|
||||
def _interrupt_handler(self, int_pin: int): # pylint: disable=unused-argument
|
||||
def _interrupt_handler(self, int_pin: int):
|
||||
key = self._read_interrupt()
|
||||
if key is None:
|
||||
return
|
||||
|
|
|
@ -4,26 +4,25 @@ from typing import Optional
|
|||
|
||||
import schedule
|
||||
|
||||
from tsgrain_controller import models, util
|
||||
from tsgrain_controller import database, models, queue, util
|
||||
|
||||
|
||||
class Scheduler(util.StoppableThread):
|
||||
|
||||
def __init__(self, app: models.AppInterface):
|
||||
def __init__(self, db: database.RainDB, task_queue: queue.TaskQueue):
|
||||
super().__init__(1)
|
||||
self.app = app
|
||||
self.db = db
|
||||
self.queue = task_queue
|
||||
self._job: Optional[schedule.Job] = None
|
||||
|
||||
def _minute_handler(self):
|
||||
jobs = self.app.get_jobs()
|
||||
for job in jobs:
|
||||
jobs = self.db.get_jobs()
|
||||
for job in jobs.values():
|
||||
if job.check(datetime.now()):
|
||||
for zone in job.zones:
|
||||
self.app.start_task(
|
||||
models.TaskRequest(source=models.Source.SCHEDULE,
|
||||
zone_id=zone,
|
||||
queuing=True,
|
||||
cancelling=False))
|
||||
task = models.Task(models.Source.SCHEDULE, zone,
|
||||
job.duration)
|
||||
self.queue.enqueue(task)
|
||||
|
||||
def start(self):
|
||||
self._job = schedule.every().minute.at(':00').do(self._minute_handler)
|
||||
|
|
|
@ -1,46 +1,23 @@
|
|||
# coding=utf-8
|
||||
import logging
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
from enum import Enum
|
||||
from typing import List, Optional, Dict, Any
|
||||
|
||||
from tsgrain_controller import util, config
|
||||
from tsgrain_controller.grpc_generated import tsgrain_pb2
|
||||
from tsgrain_controller import util
|
||||
|
||||
|
||||
@dataclass
|
||||
class Job:
|
||||
"""Bewässerungsjob (Zeitsteuerung)"""
|
||||
|
||||
date: datetime
|
||||
"""Startdatum/Uhrzeit"""
|
||||
|
||||
duration: int
|
||||
"""Bewässerungsdauer in Sekunden"""
|
||||
|
||||
zones: List[int]
|
||||
"""Liste der Zonen, die bewässert werden sollen"""
|
||||
|
||||
enable: bool
|
||||
"""Bewässerungsjob aktiviert"""
|
||||
|
||||
repeat: bool
|
||||
"""Bewässerungsjob täglich wiederholen"""
|
||||
|
||||
id: int = 0
|
||||
"""
|
||||
ID, mit der der Bewässerungsjob in der Datenbank gespeichert wird.
|
||||
Ist Null bei neu erstellten Objekten, die sich noch nicht in der Datenbank
|
||||
befinden.
|
||||
"""
|
||||
|
||||
@property
|
||||
def is_active(self) -> bool:
|
||||
"""
|
||||
Gibt True zurück, wenn der Bewässerungsjob in Zukunft ausgeführt werden wird.
|
||||
"""
|
||||
if not self.enable:
|
||||
return False
|
||||
if self.repeat:
|
||||
|
@ -49,12 +26,6 @@ class Job:
|
|||
return self.date > util.datetime_now()
|
||||
|
||||
def check(self, date_now: datetime) -> bool:
|
||||
"""
|
||||
Gibt True zurück, wenn der Bewässerungsjob in dieser Minute
|
||||
gestartet werden soll.
|
||||
|
||||
:param date_now: Aktuelles Datum/Uhrzeit
|
||||
"""
|
||||
if not self.enable:
|
||||
return False
|
||||
|
||||
|
@ -66,59 +37,24 @@ class Job:
|
|||
|
||||
return date_now - check_datetime < timedelta(minutes=1)
|
||||
|
||||
def serialize(self) -> Dict[str, Any]:
|
||||
return {
|
||||
'date': self.date,
|
||||
'duration': self.duration,
|
||||
'zones': self.zones,
|
||||
'enable': self.enable,
|
||||
'repeat': self.repeat,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, data: dict, job_id: int = 0) -> 'Job':
|
||||
def deserialize(cls, data: dict) -> 'Job':
|
||||
return cls(
|
||||
date=util.datetime_deserialize(data['date']),
|
||||
date=datetime.fromisoformat(data['date']),
|
||||
duration=data['duration'],
|
||||
zones=data['zones'],
|
||||
enable=data['enable'],
|
||||
enable=data['zones'],
|
||||
repeat=data['repeat'],
|
||||
id=job_id,
|
||||
)
|
||||
|
||||
def serialize_proto(self) -> tsgrain_pb2.Job:
|
||||
logging.info(self)
|
||||
|
||||
return tsgrain_pb2.Job(id=self.id,
|
||||
date=util.datetime_to_proto(self.date),
|
||||
duration=self.duration,
|
||||
zones=self.zones,
|
||||
enable=self.enable,
|
||||
repeat=self.repeat)
|
||||
|
||||
@classmethod
|
||||
def deserialize_proto(cls, data: tsgrain_pb2.Job) -> 'Job':
|
||||
return cls(
|
||||
date=util.datetime_from_proto(data.date),
|
||||
duration=data.duration,
|
||||
zones=list(data.zones),
|
||||
enable=data.enable,
|
||||
repeat=data.repeat,
|
||||
id=data.id,
|
||||
)
|
||||
|
||||
|
||||
class Source(Enum):
|
||||
"""Quelle einer Bewässerungsaufgabe"""
|
||||
|
||||
MANUAL = 0
|
||||
MANUAL = 2
|
||||
SCHEDULE = 1
|
||||
|
||||
|
||||
@dataclass
|
||||
class Task:
|
||||
"""Bewässerungsaufgabe"""
|
||||
|
||||
source: Source
|
||||
"""Quelle des Tasks (Manuell/Zeitplan)"""
|
||||
|
||||
|
@ -209,14 +145,6 @@ class Task:
|
|||
'datetime_finished': self.datetime_finished
|
||||
}
|
||||
|
||||
def serialize_proto(self) -> tsgrain_pb2.Task:
|
||||
return tsgrain_pb2.Task(
|
||||
source=self.source.value,
|
||||
zone_id=self.zone_id,
|
||||
duration=self.duration,
|
||||
datetime_started=util.datetime_to_proto(self.datetime_started),
|
||||
datetime_finished=util.datetime_to_proto(self.datetime_finished))
|
||||
|
||||
@classmethod
|
||||
def deserialize(cls, data: dict) -> 'Task':
|
||||
task = cls(source=Source[data['source']],
|
||||
|
@ -232,134 +160,5 @@ class Task:
|
|||
return hash(self._id)
|
||||
|
||||
def __str__(self):
|
||||
return f'ZONE {self.zone_id}: {self.duration} {self.source}'
|
||||
|
||||
|
||||
@dataclass
|
||||
class TaskRequest:
|
||||
"""Enthält alle Parameter einer zu erstellenden Bewässerungsaufgabe"""
|
||||
|
||||
source: Source
|
||||
"""Quelle des Tasks (Manuell/Zeitplan)"""
|
||||
|
||||
zone_id: int
|
||||
"""Nummer der Zone"""
|
||||
|
||||
duration: int = 0
|
||||
"""Beregnungsdauer in Sekunden"""
|
||||
|
||||
queuing: bool = False
|
||||
"""
|
||||
Task in die Warteschlange einreihen, wenn er nicht sofort gestartet werden kann.
|
||||
"""
|
||||
|
||||
cancelling: bool = False
|
||||
"""Task aus der Warteschlange entfernen/abbrechen, wenn er bereits exisitiert."""
|
||||
|
||||
@classmethod
|
||||
def deserialize_proto(cls, data: tsgrain_pb2.TaskRequest) -> 'TaskRequest':
|
||||
return cls(source=Source(data.source),
|
||||
zone_id=data.zone_id,
|
||||
duration=data.duration,
|
||||
queuing=data.queuing,
|
||||
cancelling=data.cancelling)
|
||||
|
||||
|
||||
@dataclass
|
||||
class TaskRequestResult:
|
||||
"""
|
||||
Wird beim Versuch, eine neue Bewässerungsaufgabe zu starten, zurückgegeben.
|
||||
Enthält die Information, ob eine Aufgabe gestartet oder gestoppt wurde.
|
||||
"""
|
||||
|
||||
started: bool
|
||||
"""True wenn eine neue Aufgabe gestartet wurde"""
|
||||
|
||||
stopped: bool
|
||||
"""True wenn eine laufende Aufgabe gestoppt wurde"""
|
||||
|
||||
def serialize_proto(self) -> tsgrain_pb2.TaskRequestResult:
|
||||
return tsgrain_pb2.TaskRequestResult(started=self.started,
|
||||
stopped=self.stopped)
|
||||
|
||||
|
||||
class AppInterface:
|
||||
"""Beinhaltet sämtliche Methoden der TSGRain-Anwendung"""
|
||||
|
||||
def get_auto_mode(self) -> bool:
|
||||
"""Gibt den Status des Automatikmodus zurück."""
|
||||
|
||||
def set_auto_mode(self, state: bool):
|
||||
"""Aktiviert/deaktiviert den Automatikmodus."""
|
||||
|
||||
def get_cfg(self) -> config.Config:
|
||||
"""Gibt das Konfigurationsobjekt der Anwendung zurück."""
|
||||
|
||||
def get_logger(self) -> logging.Logger:
|
||||
"""Gibt den Logger der Anwendung zurück."""
|
||||
|
||||
def start_task(self, request: TaskRequest) -> TaskRequestResult:
|
||||
"""
|
||||
Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn
|
||||
diese bereits läuft).
|
||||
|
||||
:param request: Objekt, dass die Parameter der neuen Aufgabe enthält.
|
||||
:return: Statusobjekt (Information, ob eine Aufgabe gestartet oder gestoppt
|
||||
wurde).
|
||||
"""
|
||||
|
||||
def get_tasks(self) -> List[Task]:
|
||||
"""
|
||||
Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück.
|
||||
|
||||
:return: Liste von Bewässerungsaufgaben
|
||||
"""
|
||||
|
||||
def create_job(self, job: Job) -> int:
|
||||
"""
|
||||
Erstelle einen neuen Bewässerungsjob.
|
||||
|
||||
:param job: Bewässerungsjob
|
||||
:return: ID des neuen Bewässerungsjobs
|
||||
"""
|
||||
|
||||
def get_job(self, job_id: int) -> Job:
|
||||
"""
|
||||
Gibt den Bewässerungsjob mit der gegebenen ID zurück.
|
||||
|
||||
:param job_id: ID des Bewässerungsjobs
|
||||
:return: Bewässerungsjob
|
||||
:raise KeyError: wenn Job nicht gefunden
|
||||
"""
|
||||
|
||||
def get_jobs(self) -> List[Job]:
|
||||
"""
|
||||
Gibt alle gespeicherten Bewässerungsjobs zurück.
|
||||
|
||||
:return: Bewässerungsjobs: dict(id -> models.Job)
|
||||
"""
|
||||
|
||||
def update_job(self, job: Job):
|
||||
"""
|
||||
Aktualisiert einen Bewässerungsjob.
|
||||
|
||||
:param job: Bewässerungsjob
|
||||
"""
|
||||
|
||||
def delete_job(self, job_id):
|
||||
"""
|
||||
Lösche den Bewässerungsjob mit der gegebenen ID.
|
||||
|
||||
:param job_id: ID des Bewässerungsjobs
|
||||
:raise KeyError: wenn Job nicht gefunden
|
||||
"""
|
||||
|
||||
def notify_queue_update(self):
|
||||
"""
|
||||
Wird aufgerufen, wenn die Warteschlange aktualisiert wird.
|
||||
Dient dazu, andere Komponenten der Anwendung zu benachrichtigen
|
||||
(momentan den GRPC-Server).
|
||||
"""
|
||||
|
||||
def is_running(self) -> bool:
|
||||
"""Gibt den Status der Anwendung zurück"""
|
||||
return 'ZONE %d: %ds (%s)' % (self.zone_id, self.duration,
|
||||
self.source.name)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from dataclasses import dataclass
|
||||
from typing import Dict
|
||||
from tsgrain_controller import io, util, task_queue, models
|
||||
from tsgrain_controller import io, util, queue, models
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -22,7 +22,7 @@ class OutputState:
|
|||
return 'OFF'
|
||||
if self.blink_freq == 0:
|
||||
return 'ON'
|
||||
return f'(({self.blink_freq}))'
|
||||
return '((%d))' % self.blink_freq
|
||||
|
||||
|
||||
class OutputDevice:
|
||||
|
@ -51,8 +51,8 @@ class Outputs(util.StoppableThread):
|
|||
(Ventilausgänge und LEDs)
|
||||
"""
|
||||
|
||||
def __init__(self, o_io: io.Io, task_holder: task_queue.TaskHolder,
|
||||
app: models.AppInterface):
|
||||
def __init__(self, o_io: io.Io, task_holder: queue.TaskHolder,
|
||||
app: util.AppInterface):
|
||||
super().__init__(0.01)
|
||||
|
||||
self.task_holder = task_holder
|
||||
|
@ -60,11 +60,11 @@ class Outputs(util.StoppableThread):
|
|||
self.n_zones = self.app.get_cfg().n_zones
|
||||
|
||||
self.valve_outputs: Dict[int, OutputDevice] = {
|
||||
i: OutputDevice(f'VALVE_{i}', o_io)
|
||||
i: OutputDevice('VALVE_%d' % i, o_io)
|
||||
for i in range(1, self.n_zones + 1)
|
||||
}
|
||||
self.zone_leds: Dict[int, OutputDevice] = {
|
||||
i: OutputDevice(f'LED_Z_{i}', o_io)
|
||||
i: OutputDevice('LED_Z_%d' % i, o_io)
|
||||
for i in range(1, self.n_zones + 1)
|
||||
}
|
||||
|
||||
|
@ -137,10 +137,10 @@ class Outputs(util.StoppableThread):
|
|||
if task is not None:
|
||||
self._set_zone_time(task.zone_id, task.remaining)
|
||||
self._set_mode_led_manual(task.source == models.Source.MANUAL)
|
||||
self._set_mode_led_auto(self.app.get_auto_mode(),
|
||||
self._set_mode_led_auto(self.app.is_auto_enabled(),
|
||||
task.source == models.Source.SCHEDULE)
|
||||
else:
|
||||
self._set_mode_led_auto(self.app.get_auto_mode(), False)
|
||||
self._set_mode_led_auto(self.app.is_auto_enabled(), False)
|
||||
|
||||
self._update_states()
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ class TaskHolder:
|
|||
|
||||
class TaskQueue(util.StoppableThread, TaskHolder):
|
||||
|
||||
def __init__(self, app: models.AppInterface):
|
||||
def __init__(self, app: util.AppInterface):
|
||||
super().__init__(0.1)
|
||||
self.app = app
|
||||
|
||||
self.tasks: List[models.Task] = []
|
||||
self.tasks: List[models.Task] = list()
|
||||
self.running_task: Optional[models.Task] = None
|
||||
|
||||
def enqueue(self, task: models.Task, exclusive: bool = False) -> bool:
|
||||
|
@ -52,8 +52,6 @@ class TaskQueue(util.StoppableThread, TaskHolder):
|
|||
if self.running_task == task:
|
||||
self.running_task = None
|
||||
|
||||
self.app.notify_queue_update()
|
||||
|
||||
def cancel_current_task(self):
|
||||
"""
|
||||
Bricht den aktuell laufenden Task ab
|
||||
|
@ -63,7 +61,6 @@ class TaskQueue(util.StoppableThread, TaskHolder):
|
|||
self.tasks.remove(self.running_task)
|
||||
logging.info('Running task cancelled (%s)', self.running_task)
|
||||
self.running_task = None
|
||||
self.app.notify_queue_update()
|
||||
|
||||
def serialize(self) -> List[models.Task]:
|
||||
"""Task zur Speicherung in der Datenbank in dict umwandeln."""
|
||||
|
@ -78,30 +75,27 @@ class TaskQueue(util.StoppableThread, TaskHolder):
|
|||
if self.running_task is None:
|
||||
for task in self.tasks:
|
||||
# Only start scheduled tasks if automatic mode is enabled
|
||||
if task.source == models.Source.SCHEDULE and not self.app.get_auto_mode(
|
||||
if task.source == models.Source.SCHEDULE and not self.app.is_auto_enabled(
|
||||
):
|
||||
continue
|
||||
|
||||
self.running_task = task
|
||||
self.running_task.start()
|
||||
logging.info('Queued task started (%s)', self.running_task)
|
||||
self.app.notify_queue_update()
|
||||
break
|
||||
|
||||
# Check currently running task
|
||||
if self.running_task is not None:
|
||||
# Stop scheduled tasks if auto mode is disabled
|
||||
if self.running_task.source == models.Source.SCHEDULE and not self.app.get_auto_mode(
|
||||
if self.running_task.source == models.Source.SCHEDULE and not self.app.is_auto_enabled(
|
||||
):
|
||||
self.running_task.stop()
|
||||
logging.info('Running task stopped (%s)', self.running_task)
|
||||
self.running_task = None
|
||||
self.app.notify_queue_update()
|
||||
elif self.running_task.is_done:
|
||||
self.tasks.remove(self.running_task)
|
||||
logging.info('Running task done (%s)', self.running_task)
|
||||
self.running_task = None
|
||||
self.app.notify_queue_update()
|
||||
|
||||
def cleanup(self):
|
||||
if self.running_task:
|
|
@ -1,13 +1,13 @@
|
|||
# coding=utf-8
|
||||
from datetime import date, datetime
|
||||
import datetime
|
||||
import json
|
||||
import logging
|
||||
import threading
|
||||
import time
|
||||
import math
|
||||
from enum import Enum
|
||||
from typing import Any, Union, Optional
|
||||
from typing import Any, Union
|
||||
|
||||
from tsgrain_controller.grpc_generated import tsgrain_pb2
|
||||
from tsgrain_controller import config
|
||||
|
||||
|
||||
def _get_np_attrs(o) -> dict:
|
||||
|
@ -29,13 +29,13 @@ def serializer(o: Any) -> Union[str, dict, int, float, bool]:
|
|||
"""
|
||||
if hasattr(o, 'serialize'):
|
||||
return o.serialize()
|
||||
if isinstance(o, (datetime, date)):
|
||||
elif isinstance(o, datetime.datetime) or isinstance(o, datetime.date):
|
||||
return o.isoformat()
|
||||
if isinstance(o, Enum):
|
||||
elif isinstance(o, Enum):
|
||||
return o.value
|
||||
if isinstance(o, (bool, float, int)):
|
||||
elif isinstance(o, int) or isinstance(o, float) or isinstance(o, bool):
|
||||
return o
|
||||
if hasattr(o, '__dict__'):
|
||||
elif hasattr(o, '__dict__'):
|
||||
return _get_np_attrs(o)
|
||||
return str(o)
|
||||
|
||||
|
@ -71,47 +71,19 @@ def time_ms() -> int:
|
|||
return round(time.time() * 1000)
|
||||
|
||||
|
||||
def datetime_now() -> datetime:
|
||||
return datetime.now()
|
||||
def datetime_now() -> datetime.datetime:
|
||||
return datetime.datetime.now()
|
||||
|
||||
|
||||
# pylint: disable-next=too-many-arguments
|
||||
def datetime_new(year,
|
||||
month=None,
|
||||
day=None,
|
||||
hour=0,
|
||||
minute=0,
|
||||
second=0,
|
||||
microsecond=0) -> datetime:
|
||||
return datetime(year, month, day, hour, minute, second, microsecond)
|
||||
|
||||
|
||||
def datetime_to_proto(
|
||||
date_time: Optional[datetime]) -> Optional[tsgrain_pb2.Timestamp]:
|
||||
"""Konvertiert ein Python datetime-Object in einen protobuf-Zeitstempel"""
|
||||
if date_time is None:
|
||||
return None
|
||||
|
||||
return tsgrain_pb2.Timestamp(seconds=math.floor(date_time.timestamp()))
|
||||
|
||||
|
||||
def datetime_from_proto(
|
||||
timestamp: Optional[tsgrain_pb2.Timestamp]) -> Optional[datetime]:
|
||||
"""Konvertiert einen protobuf-Zeitstempel in ein Python datetime-Objekt"""
|
||||
if timestamp is None:
|
||||
return None
|
||||
|
||||
return datetime.fromtimestamp(timestamp.seconds)
|
||||
|
||||
|
||||
def datetime_deserialize(date_time: Union[datetime, str]) -> datetime:
|
||||
"""
|
||||
Deserialisiert ein datetime-Objekt, falls es im String-Format (YYYY-MM-DDThh:mm:ss)
|
||||
vorliegt.
|
||||
"""
|
||||
if isinstance(date_time, str):
|
||||
return datetime.fromisoformat(date_time)
|
||||
return date_time
|
||||
microsecond=0) -> datetime.datetime:
|
||||
return datetime.datetime(year, month, day, hour, minute, second,
|
||||
microsecond)
|
||||
|
||||
|
||||
class StoppableThread(threading.Thread):
|
||||
|
@ -144,6 +116,18 @@ class StoppableThread(threading.Thread):
|
|||
self.join()
|
||||
|
||||
|
||||
class AppInterface:
|
||||
|
||||
def is_auto_enabled(self) -> bool:
|
||||
pass
|
||||
|
||||
def get_cfg(self) -> config.Config:
|
||||
pass
|
||||
|
||||
def get_logger(self) -> logging.Logger:
|
||||
pass
|
||||
|
||||
|
||||
class ZoneUnavailableException(Exception):
|
||||
pass
|
||||
|
||||
|
|
Loading…
Reference in a new issue