Compare commits
5 commits
834092a101
...
4e53dd9412
Author | SHA1 | Date | |
---|---|---|---|
4e53dd9412 | |||
8e7c63a9fb | |||
65c3cef77f | |||
7e8528eef2 | |||
80ad7a3a3d |
35 changed files with 3887 additions and 981 deletions
|
@ -10,6 +10,9 @@ max_line_length = 88
|
|||
[*.py]
|
||||
indent_style = space
|
||||
|
||||
[*.{jsx,tsx}]
|
||||
indent_size = 2
|
||||
|
||||
[*.{json,md,rst,ini,yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
|
3
Makefile
3
Makefile
|
@ -25,10 +25,11 @@ build-server:
|
|||
build: build-ui build-server
|
||||
|
||||
# Protobuf-API-Definition herunterladen und Code generieren
|
||||
protoc:
|
||||
download-proto:
|
||||
wget "https://code.thetadev.de/TSGRain/Controller/raw/branch/main/proto/tsgrain.proto" -O ${PROTO_FILE}
|
||||
echo 'option go_package = "code.thetadev.de/TSGRain/WebUI/src/tsgrain_rpc";' >> ${PROTO_FILE}
|
||||
|
||||
protoc:
|
||||
protoc --go_out ${SRC_DIR}/tsgrain_rpc --go_opt=paths=source_relative \
|
||||
--go-grpc_out ${SRC_DIR}/tsgrain_rpc --go-grpc_opt=paths=source_relative \
|
||||
${PROTO_FILE}
|
||||
|
|
|
@ -6,7 +6,13 @@ 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) {}
|
||||
rpc RequestTask(TaskRequest) returns (TaskRequestResult) {}
|
||||
|
||||
// Starte eine Bewässerungsaufgabe
|
||||
rpc StartTask(TaskStart) returns (google.protobuf.BoolValue) {}
|
||||
|
||||
// Stoppe eine Bewässerungsaufgabe
|
||||
rpc StopTask(TaskStop) returns (google.protobuf.BoolValue) {}
|
||||
|
||||
// Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück.
|
||||
rpc GetTasks(google.protobuf.Empty) returns (TaskList) {}
|
||||
|
@ -30,6 +36,12 @@ service TSGRain {
|
|||
// Lösche den Bewässerungsjob mit der gegebenen ID.
|
||||
rpc DeleteJob(JobID) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Aktiviere Bewässerungsjob
|
||||
rpc EnableJob(JobID) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Deaktiviere Bewässerungsjob
|
||||
rpc DisableJob(JobID) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Gibt zurück, ob der Automatikmodus aktiviert ist.
|
||||
rpc GetAutoMode(google.protobuf.Empty) returns (google.protobuf.BoolValue) {}
|
||||
|
||||
|
@ -37,10 +49,13 @@ service TSGRain {
|
|||
rpc SetAutoMode(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Datum/Uhrzeit/Zeitzone abrufen
|
||||
rpc GetConfigTime(google.protobuf.Empty) returns (ConfigTime) {}
|
||||
rpc GetSystemTime(google.protobuf.Empty) returns (SystemTime) {}
|
||||
|
||||
// Datum/Uhrzeit/Zeitzone einstellen
|
||||
rpc SetConfigTime(ConfigTime) returns (google.protobuf.Empty) {}
|
||||
// Datum/Uhrzeit einstellen
|
||||
rpc SetSystemTime(Timestamp) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Zeitzone einstellen
|
||||
rpc SetSystemTimezone(google.protobuf.StringValue) returns (google.protobuf.Empty) {}
|
||||
|
||||
// Standardzeit bei manueller Bewässerung abrufen
|
||||
rpc GetDefaultIrrigationTime(google.protobuf.Empty) returns (google.protobuf.Int32Value) {}
|
||||
|
@ -76,6 +91,18 @@ message TaskRequestResult {
|
|||
bool stopped = 2;
|
||||
}
|
||||
|
||||
message TaskStart {
|
||||
TaskSource source = 1;
|
||||
int32 zone_id = 2;
|
||||
int32 duration = 3;
|
||||
bool queuing = 4;
|
||||
}
|
||||
|
||||
message TaskStop {
|
||||
TaskSource source = 1;
|
||||
int32 zone_id = 2;
|
||||
}
|
||||
|
||||
message Task {
|
||||
TaskSource source = 1;
|
||||
int32 zone_id = 2;
|
||||
|
@ -107,7 +134,7 @@ message JobList {
|
|||
repeated Job jobs = 1;
|
||||
}
|
||||
|
||||
message ConfigTime {
|
||||
message SystemTime {
|
||||
Timestamp datetime = 1;
|
||||
string timezone = 2;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ package model
|
|||
//swagger:model AutoMode
|
||||
type AutoMode struct {
|
||||
// required: true
|
||||
State bool `json:"state" binding:"required"`
|
||||
State bool `json:"state"`
|
||||
}
|
||||
|
||||
// DefaultIrrigationTime model
|
||||
|
@ -20,12 +20,32 @@ type DefaultIrrigationTime struct {
|
|||
Time int32 `json:"time" binding:"required"`
|
||||
}
|
||||
|
||||
// ConfigTime model
|
||||
// Timestamp model
|
||||
//
|
||||
// Zeitstempel
|
||||
//
|
||||
//swagger:model Timestamp
|
||||
type Timestamp struct {
|
||||
// required: true
|
||||
Time int64 `json:"time" binding:"required"`
|
||||
}
|
||||
|
||||
// Timezone model
|
||||
//
|
||||
// Systemzeitzone
|
||||
//
|
||||
//swagger:model Timezone
|
||||
type Timezone struct {
|
||||
// required: true
|
||||
Timezone string `json:"timezone" binding:"required"`
|
||||
}
|
||||
|
||||
// SystemTime model
|
||||
//
|
||||
// Aktuelle Systemzeit/Zeitzone
|
||||
//
|
||||
//swagger:model ConfigTime
|
||||
type ConfigTime struct {
|
||||
//swagger:model SystemTime
|
||||
type SystemTime struct {
|
||||
// Aktuelle Systemzeit
|
||||
//
|
||||
// required: true
|
||||
|
|
|
@ -54,12 +54,7 @@ type TaskList struct {
|
|||
AutoMode bool `json:"auto_mode"`
|
||||
}
|
||||
|
||||
// TaskRequestResult model
|
||||
//
|
||||
// TaskRequestResult wird beim Starten eines Tasks zurückgegeben
|
||||
//
|
||||
//swagger:model TaskRequestResult
|
||||
type TaskRequestResult struct {
|
||||
Started bool
|
||||
Stopped bool
|
||||
//swagger:model ZoneID
|
||||
type ZoneID struct {
|
||||
Id int32 `json:"id" binding:"required"`
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"code.thetadev.de/TSGRain/WebUI/src/config"
|
||||
|
@ -84,19 +85,27 @@ func (srv *WebUIServer) getRouter() *gin.Engine {
|
|||
api.GET("/panic", srv.controllerPanic)
|
||||
}
|
||||
|
||||
api.POST("/task/manual", srv.controllerStartTask)
|
||||
api.POST("/task/start", srv.controllerStartTask)
|
||||
api.POST("/task/stop", srv.controllerStopTask)
|
||||
|
||||
api.GET("/tasks", srv.controllerGetTasks)
|
||||
|
||||
api.GET("/jobs", srv.controllerGetJobs)
|
||||
|
||||
api.GET("/job", srv.controllerGetJob)
|
||||
api.POST("/job", srv.controllerCreateJob)
|
||||
api.PUT("/job", srv.controllerUpdateJob)
|
||||
api.DELETE("/job", srv.controllerDeleteJob)
|
||||
|
||||
api.GET("config/auto", srv.controllerGetAutoMode)
|
||||
api.POST("config/auto", srv.controllerSetAutoMode)
|
||||
|
||||
api.GET("config/defaultIrrigationTime", srv.controllerGetDefaultIrrigationTime)
|
||||
api.POST("config/defaultIrrigationTime", srv.controllerSetDefaultIrrigationTime)
|
||||
api.GET("config/time", srv.controllerGetConfigTime)
|
||||
api.POST("config/time", srv.controllerSetConfigTime)
|
||||
|
||||
api.GET("config/time", srv.controllerGetSystemTime)
|
||||
api.POST("config/time", srv.controllerSetSystemTime)
|
||||
api.POST("config/timezone", srv.controllerSetSystemTimezone)
|
||||
|
||||
// UI
|
||||
uiGroup := router.Group("/", middleware.Compression(
|
||||
|
@ -134,85 +143,122 @@ func (srv *WebUIServer) Run() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// swagger:operation POST /task/manual startManualTask
|
||||
// swagger:operation POST /task/start startTask
|
||||
//
|
||||
// Starte/stoppe manuell eine neue Bewässerungsaufgabe
|
||||
// Starte eine neue manuelle Bewässerungsaufgabe
|
||||
// mit der eingestellten Standardzeit.
|
||||
//
|
||||
// ---
|
||||
// consumes: [application/json]
|
||||
// produces: [application/json]
|
||||
// parameters:
|
||||
// - in: body
|
||||
// name: taskRequest
|
||||
// - name: zoneId
|
||||
// in: body
|
||||
// description: ZoneID
|
||||
// schema:
|
||||
// type: object
|
||||
// properties:
|
||||
// zone_id:
|
||||
// description: Nummer der Bewässerungszone
|
||||
// type: integer
|
||||
// duration:
|
||||
// description: "Bewässerungsdauer in Sekunden (0: Standarddauer)"
|
||||
// type: integer
|
||||
// queuing:
|
||||
// description: |
|
||||
// Aufgabe in die Warteschlange einreihen,
|
||||
// wenn sie nicht sofort ausgeführt werden kann.
|
||||
// type: boolean
|
||||
// cancelling:
|
||||
// description: |
|
||||
// Aufgabe stoppen/aus der Warteschlange entfernen,
|
||||
// wenn sie bereits läuft oder sich in der Warteschlange befindet.
|
||||
// type: boolean
|
||||
// required:
|
||||
// - zone_id
|
||||
// - duration
|
||||
// - queuing
|
||||
// - cancelling
|
||||
// $ref: '#/definitions/ZoneID'
|
||||
// responses:
|
||||
// 200:
|
||||
// description: Bewässerungsaufgabe erfolgreich gestarted/gestoppt
|
||||
// description: OK
|
||||
// schema:
|
||||
// $ref: "#/definitions/StatusMessage"
|
||||
// 400:
|
||||
// description: Bewässerungsaufgabe läuft schon und kann nicht gestoppt werden.
|
||||
// schema:
|
||||
// $ref: "#/definitions/Error"
|
||||
// 500:
|
||||
// description: Serverfehler
|
||||
// schema:
|
||||
// $ref: "#/definitions/Error"
|
||||
func (srv *WebUIServer) controllerStartTask(c *gin.Context) {
|
||||
var params struct {
|
||||
ZoneID int32 `json:"zone_id"`
|
||||
Duration int32 `json:"duration"`
|
||||
Queuing bool `json:"queuing"`
|
||||
Cancelling bool `json:"cancelling"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(¶ms); err != nil {
|
||||
var zoneId model.ZoneID
|
||||
if err := c.ShouldBindJSON(&zoneId); err != nil {
|
||||
log.Error().Err(err).Msg("StartTask input error")
|
||||
writeStatus(c, http.StatusBadRequest, "invalid input data")
|
||||
return
|
||||
}
|
||||
if !srv.validateZoneID(params.ZoneID) {
|
||||
writeStatus(c, http.StatusBadRequest, "invalid zone_id")
|
||||
return
|
||||
}
|
||||
|
||||
res, err := srv.rpc.StartManualTask(
|
||||
params.ZoneID, params.Duration, params.Queuing, params.Cancelling)
|
||||
ok, err := srv.rpc.StartManualTask(zoneId.Id, 0)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("StartManualTask")
|
||||
log.Error().Err(err).Msg("StartTask")
|
||||
writeStatus(c, http.StatusInternalServerError, "error starting task")
|
||||
return
|
||||
}
|
||||
|
||||
statusCode := 200
|
||||
if !res.Started && !res.Stopped {
|
||||
statusCode = 400
|
||||
if !ok {
|
||||
log.Error().Msg("StartTask: alrady running")
|
||||
writeStatus(c, http.StatusBadRequest, "task already running")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(statusCode, res)
|
||||
writeStatus(c, http.StatusOK, "task started")
|
||||
}
|
||||
|
||||
// swagger:operation POST /task/stop stopTask
|
||||
//
|
||||
// Stoppe eine manuelle Bewässerungsaufgabe.
|
||||
//
|
||||
// ---
|
||||
// consumes: [application/json]
|
||||
// produces: [application/json]
|
||||
// parameters:
|
||||
// - name: zoneId
|
||||
// in: body
|
||||
// description: ZoneID
|
||||
// schema:
|
||||
// $ref: '#/definitions/ZoneID'
|
||||
// responses:
|
||||
// 200:
|
||||
// description: OK
|
||||
// schema:
|
||||
// $ref: "#/definitions/StatusMessage"
|
||||
// 500:
|
||||
// description: Serverfehler
|
||||
// schema:
|
||||
// $ref: "#/definitions/Error"
|
||||
func (srv *WebUIServer) controllerStopTask(c *gin.Context) {
|
||||
var zoneId model.ZoneID
|
||||
if err := c.ShouldBindJSON(&zoneId); err != nil {
|
||||
log.Error().Err(err).Msg("StopTask input error")
|
||||
writeStatus(c, http.StatusBadRequest, "invalid input data")
|
||||
return
|
||||
}
|
||||
|
||||
ok, err := srv.rpc.StopManualTask(zoneId.Id)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("StopTask")
|
||||
writeStatus(c, http.StatusInternalServerError, "error stopping task")
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
log.Error().Msg("StopTask: no task to stop")
|
||||
writeStatus(c, http.StatusBadRequest, "no task to stop")
|
||||
return
|
||||
}
|
||||
|
||||
writeStatus(c, http.StatusOK, "task stopped")
|
||||
}
|
||||
|
||||
// swagger:operation GET /tasks getTasks
|
||||
//
|
||||
// Rufe alle momentan laufenden Bewässerungsaufgaben ab.
|
||||
//
|
||||
// ---
|
||||
// produces: [application/json]
|
||||
// responses:
|
||||
// 200:
|
||||
// description: Liste der Bewässerungsaufgaben
|
||||
// schema:
|
||||
// "$ref": "#/definitions/TaskList"
|
||||
// 500:
|
||||
// description: Serverfehler
|
||||
// schema:
|
||||
// "$ref": "#/definitions/Error"
|
||||
func (srv *WebUIServer) controllerGetTasks(c *gin.Context) {
|
||||
tasks, err := srv.rpc.GetTasks()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("GetTasks")
|
||||
writeStatus(c, http.StatusInternalServerError, "error getting tasks")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, tasks)
|
||||
}
|
||||
|
||||
// swagger:operation GET /jobs getJobs
|
||||
|
@ -263,17 +309,16 @@ func (srv *WebUIServer) controllerGetJobs(c *gin.Context) {
|
|||
// schema:
|
||||
// $ref: "#/definitions/Error"
|
||||
func (srv *WebUIServer) controllerGetJob(c *gin.Context) {
|
||||
var params struct {
|
||||
Id int32 `uri:"id" binding:"required"`
|
||||
}
|
||||
idStr := c.Query("id")
|
||||
|
||||
if err := c.ShouldBindUri(¶ms); err != nil {
|
||||
id, err := strconv.ParseInt(idStr, 10, 32)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("GetJob input error")
|
||||
writeStatus(c, http.StatusBadRequest, "invalid input data")
|
||||
return
|
||||
}
|
||||
|
||||
job, err := srv.rpc.GetJob(params.Id)
|
||||
job, err := srv.rpc.GetJob(int32(id))
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("GetJob")
|
||||
writeStatus(c, http.StatusInternalServerError, "error getting job")
|
||||
|
@ -373,10 +418,11 @@ func (srv *WebUIServer) controllerUpdateJob(c *gin.Context) {
|
|||
// consumes: [application/json]
|
||||
// produces: [application/json]
|
||||
// parameters:
|
||||
// - name: id
|
||||
// - name: jobId
|
||||
// in: body
|
||||
// description: JobID
|
||||
// schema:
|
||||
// type: integer
|
||||
// $ref: '#/definitions/JobID'
|
||||
// responses:
|
||||
// 200:
|
||||
// description: OK
|
||||
|
@ -442,12 +488,7 @@ func (srv *WebUIServer) controllerGetAutoMode(c *gin.Context) {
|
|||
// name: state
|
||||
// description: Zustand des Automatikmodus
|
||||
// schema:
|
||||
// type: object
|
||||
// properties:
|
||||
// state:
|
||||
// type: boolean
|
||||
// required:
|
||||
// - state
|
||||
// $ref: '#/definitions/AutoMode'
|
||||
// responses:
|
||||
// 200:
|
||||
// description: OK
|
||||
|
@ -475,7 +516,7 @@ func (srv *WebUIServer) controllerSetAutoMode(c *gin.Context) {
|
|||
writeStatus(c, http.StatusOK, "set autoMode")
|
||||
}
|
||||
|
||||
// swagger:operation GET /config/time getConfigTime
|
||||
// swagger:operation GET /config/time getSystemTime
|
||||
//
|
||||
// Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
//
|
||||
|
@ -485,34 +526,34 @@ func (srv *WebUIServer) controllerSetAutoMode(c *gin.Context) {
|
|||
// 200:
|
||||
// description: Aktuelle Systemzeit/Zeitzone
|
||||
// schema:
|
||||
// $ref: "#/definitions/ConfigTime"
|
||||
// $ref: "#/definitions/SystemTime"
|
||||
// 500:
|
||||
// description: Serverfehler
|
||||
// schema:
|
||||
// $ref: "#/definitions/Error"
|
||||
func (srv *WebUIServer) controllerGetConfigTime(c *gin.Context) {
|
||||
configTime, err := srv.rpc.GetConfigTime()
|
||||
func (srv *WebUIServer) controllerGetSystemTime(c *gin.Context) {
|
||||
systemTime, err := srv.rpc.GetSystemTime()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("GetConfigTime")
|
||||
writeStatus(c, http.StatusInternalServerError, "error setting configTime")
|
||||
log.Error().Err(err).Msg("GetSystemTime")
|
||||
writeStatus(c, http.StatusInternalServerError, "error getting system time")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, configTime)
|
||||
c.JSON(200, systemTime)
|
||||
}
|
||||
|
||||
// swagger:operation POST /config/time setConfigTime
|
||||
// swagger:operation POST /config/time setSystemTime
|
||||
//
|
||||
// Automatikmodus aktivieren/deaktivieren
|
||||
// Systemzeit einstellen
|
||||
//
|
||||
// ---
|
||||
// consumes: [application/json]
|
||||
// produces: [application/json]
|
||||
// parameters:
|
||||
// - in: body
|
||||
// name: configTime
|
||||
// name: timestamp
|
||||
// schema:
|
||||
// $ref: "#/definitions/ConfigTime"
|
||||
// $ref: "#/definitions/Timestamp"
|
||||
// responses:
|
||||
// 200:
|
||||
// description: OK
|
||||
|
@ -522,22 +563,61 @@ func (srv *WebUIServer) controllerGetConfigTime(c *gin.Context) {
|
|||
// description: Serverfehler
|
||||
// schema:
|
||||
// $ref: "#/definitions/Error"
|
||||
func (srv *WebUIServer) controllerSetConfigTime(c *gin.Context) {
|
||||
var configTime model.ConfigTime
|
||||
if err := c.ShouldBindJSON(&configTime); err != nil {
|
||||
log.Error().Err(err).Msg("SetConfigTime input error")
|
||||
func (srv *WebUIServer) controllerSetSystemTime(c *gin.Context) {
|
||||
var systemTime model.Timestamp
|
||||
if err := c.ShouldBindJSON(&systemTime); err != nil {
|
||||
log.Error().Err(err).Msg("SetSystemTime input error")
|
||||
writeStatus(c, http.StatusBadRequest, "invalid input data")
|
||||
return
|
||||
}
|
||||
|
||||
err := srv.rpc.SetConfigTime(configTime)
|
||||
err := srv.rpc.SetSystemTime(systemTime.Time)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("SetConfigTime")
|
||||
writeStatus(c, http.StatusInternalServerError, "error setting configTime")
|
||||
log.Error().Err(err).Msg("SetSystemTime")
|
||||
writeStatus(c, http.StatusInternalServerError, "error setting systemTime")
|
||||
return
|
||||
}
|
||||
|
||||
writeStatus(c, http.StatusOK, "set configTime")
|
||||
writeStatus(c, http.StatusOK, "set systemTime")
|
||||
}
|
||||
|
||||
// swagger:operation POST /config/timezone setSystemTimezone
|
||||
//
|
||||
// Systemzeitzone einstellen
|
||||
//
|
||||
// ---
|
||||
// consumes: [application/json]
|
||||
// produces: [application/json]
|
||||
// parameters:
|
||||
// - in: body
|
||||
// name: timezone
|
||||
// schema:
|
||||
// $ref: "#/definitions/Timezone"
|
||||
// responses:
|
||||
// 200:
|
||||
// description: OK
|
||||
// schema:
|
||||
// $ref: "#/definitions/StatusMessage"
|
||||
// 500:
|
||||
// description: Serverfehler
|
||||
// schema:
|
||||
// $ref: "#/definitions/Error"
|
||||
func (srv *WebUIServer) controllerSetSystemTimezone(c *gin.Context) {
|
||||
var timezone model.Timezone
|
||||
if err := c.ShouldBindJSON(&timezone); err != nil {
|
||||
log.Error().Err(err).Msg("SetSystemTimezone input error")
|
||||
writeStatus(c, http.StatusBadRequest, "invalid input data")
|
||||
return
|
||||
}
|
||||
|
||||
err := srv.rpc.SetSystemTimezone(timezone.Timezone)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("SetSystemTimezone")
|
||||
writeStatus(c, http.StatusInternalServerError, "error setting systemTimezone")
|
||||
return
|
||||
}
|
||||
|
||||
writeStatus(c, http.StatusOK, "set systemTimezone")
|
||||
}
|
||||
|
||||
// swagger:operation GET /config/defaultIrrigationTime getDefaultIrrigationTime
|
||||
|
@ -564,7 +644,7 @@ func (srv *WebUIServer) controllerGetDefaultIrrigationTime(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
c.JSON(200, defaultIrrigationTime)
|
||||
c.JSON(200, model.DefaultIrrigationTime{Time: defaultIrrigationTime})
|
||||
}
|
||||
|
||||
// swagger:operation POST /config/defaultIrrigationTime setDefaultIrrigationTime
|
||||
|
|
|
@ -8,21 +8,6 @@ definitions:
|
|||
- state
|
||||
title: AutoMode model
|
||||
type: object
|
||||
ConfigTime:
|
||||
description: Aktuelle Systemzeit/Zeitzone
|
||||
properties:
|
||||
time:
|
||||
description: Aktuelle Systemzeit
|
||||
format: int64
|
||||
type: integer
|
||||
timezone:
|
||||
description: Aktuelle Zeitzone
|
||||
type: string
|
||||
required:
|
||||
- time
|
||||
- timezone
|
||||
title: ConfigTime model
|
||||
type: object
|
||||
DefaultIrrigationTime:
|
||||
description: Manuelle Bewässerungszeit in Sekunden
|
||||
properties:
|
||||
|
@ -158,6 +143,21 @@ definitions:
|
|||
- msg
|
||||
title: StatusMessage model
|
||||
type: object
|
||||
SystemTime:
|
||||
description: Aktuelle Systemzeit/Zeitzone
|
||||
properties:
|
||||
time:
|
||||
description: Aktuelle Systemzeit
|
||||
format: int64
|
||||
type: integer
|
||||
timezone:
|
||||
description: Aktuelle Zeitzone
|
||||
type: string
|
||||
required:
|
||||
- time
|
||||
- timezone
|
||||
title: SystemTime model
|
||||
type: object
|
||||
Task:
|
||||
description: Task stellt eine Bewässerungsaufgabe dar.
|
||||
properties:
|
||||
|
@ -216,14 +216,30 @@ definitions:
|
|||
- auto_mode
|
||||
title: TaskList model
|
||||
type: object
|
||||
TaskRequestResult:
|
||||
description: TaskRequestResult wird beim Starten eines Tasks zurückgegeben
|
||||
Timestamp:
|
||||
description: Zeitstempel
|
||||
properties:
|
||||
Started:
|
||||
type: boolean
|
||||
Stopped:
|
||||
type: boolean
|
||||
title: TaskRequestResult model
|
||||
time:
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- time
|
||||
title: Timestamp model
|
||||
type: object
|
||||
Timezone:
|
||||
description: Systemzeitzone
|
||||
properties:
|
||||
timezone:
|
||||
type: string
|
||||
required:
|
||||
- timezone
|
||||
title: Timezone model
|
||||
type: object
|
||||
ZoneID:
|
||||
properties:
|
||||
id:
|
||||
format: int32
|
||||
type: integer
|
||||
type: object
|
||||
info:
|
||||
description: REST API for the TSGRain WebUI
|
||||
|
@ -257,12 +273,7 @@ paths:
|
|||
in: body
|
||||
name: state
|
||||
schema:
|
||||
properties:
|
||||
state:
|
||||
type: boolean
|
||||
required:
|
||||
- state
|
||||
type: object
|
||||
$ref: "#/definitions/AutoMode"
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
@ -313,14 +324,14 @@ paths:
|
|||
/config/time:
|
||||
get:
|
||||
description: Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
operationId: getConfigTime
|
||||
operationId: getSystemTime
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Aktuelle Systemzeit/Zeitzone
|
||||
schema:
|
||||
$ref: "#/definitions/ConfigTime"
|
||||
$ref: "#/definitions/SystemTime"
|
||||
"500":
|
||||
description: Serverfehler
|
||||
schema:
|
||||
|
@ -328,13 +339,35 @@ paths:
|
|||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Automatikmodus aktivieren/deaktivieren
|
||||
operationId: setConfigTime
|
||||
description: Systemzeit einstellen
|
||||
operationId: setSystemTime
|
||||
parameters:
|
||||
- in: body
|
||||
name: configTime
|
||||
name: timestamp
|
||||
schema:
|
||||
$ref: "#/definitions/ConfigTime"
|
||||
$ref: "#/definitions/Timestamp"
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/StatusMessage"
|
||||
"500":
|
||||
description: Serverfehler
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
/config/timezone:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Systemzeitzone einstellen
|
||||
operationId: setSystemTimezone
|
||||
parameters:
|
||||
- in: body
|
||||
name: timezone
|
||||
schema:
|
||||
$ref: "#/definitions/Timezone"
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
@ -352,10 +385,11 @@ paths:
|
|||
- application/json
|
||||
operationId: deleteJob
|
||||
parameters:
|
||||
- in: body
|
||||
name: id
|
||||
- description: JobID
|
||||
in: body
|
||||
name: jobId
|
||||
schema:
|
||||
type: integer
|
||||
$ref: "#/definitions/JobID"
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
|
@ -449,54 +483,69 @@ paths:
|
|||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
summary: Rufe alle gespeicherten Zeitpläne ab.
|
||||
/task/manual:
|
||||
/task/start:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Starte/stoppe manuell eine neue Bewässerungsaufgabe
|
||||
operationId: startManualTask
|
||||
description: |-
|
||||
Starte eine neue manuelle Bewässerungsaufgabe
|
||||
mit der eingestellten Standardzeit.
|
||||
operationId: startTask
|
||||
parameters:
|
||||
- in: body
|
||||
name: taskRequest
|
||||
- description: ZoneID
|
||||
in: body
|
||||
name: zoneId
|
||||
schema:
|
||||
properties:
|
||||
cancelling:
|
||||
description: |
|
||||
Aufgabe stoppen/aus der Warteschlange entfernen,
|
||||
wenn sie bereits läuft oder sich in der Warteschlange befindet.
|
||||
type: boolean
|
||||
duration:
|
||||
description: "Bewässerungsdauer in Sekunden (0: Standarddauer)"
|
||||
type: integer
|
||||
queuing:
|
||||
description: |
|
||||
Aufgabe in die Warteschlange einreihen,
|
||||
wenn sie nicht sofort ausgeführt werden kann.
|
||||
type: boolean
|
||||
zone_id:
|
||||
description: Nummer der Bewässerungszone
|
||||
type: integer
|
||||
required:
|
||||
- zone_id
|
||||
- duration
|
||||
- queuing
|
||||
- cancelling
|
||||
type: object
|
||||
$ref: "#/definitions/ZoneID"
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Bewässerungsaufgabe erfolgreich gestarted/gestoppt
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/StatusMessage"
|
||||
"400":
|
||||
description: Bewässerungsaufgabe läuft schon und kann nicht gestoppt werden.
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
"500":
|
||||
description: Serverfehler
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
/task/stop:
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
operationId: stopTask
|
||||
parameters:
|
||||
- description: ZoneID
|
||||
in: body
|
||||
name: zoneId
|
||||
schema:
|
||||
$ref: "#/definitions/ZoneID"
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: "#/definitions/StatusMessage"
|
||||
"500":
|
||||
description: Serverfehler
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
summary: Stoppe eine manuelle Bewässerungsaufgabe.
|
||||
/tasks:
|
||||
get:
|
||||
operationId: getTasks
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Liste der Bewässerungsaufgaben
|
||||
schema:
|
||||
$ref: "#/definitions/TaskList"
|
||||
"500":
|
||||
description: Serverfehler
|
||||
schema:
|
||||
$ref: "#/definitions/Error"
|
||||
summary: Rufe alle momentan laufenden Bewässerungsaufgaben ab.
|
||||
schemes:
|
||||
- http
|
||||
- https
|
||||
|
|
|
@ -251,6 +251,132 @@ func (x *TaskRequestResult) GetStopped() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
type TaskStart struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Source TaskSource `protobuf:"varint,1,opt,name=source,proto3,enum=TaskSource" json:"source,omitempty"`
|
||||
ZoneId int32 `protobuf:"varint,2,opt,name=zone_id,json=zoneId,proto3" json:"zone_id,omitempty"`
|
||||
Duration int32 `protobuf:"varint,3,opt,name=duration,proto3" json:"duration,omitempty"`
|
||||
Queuing bool `protobuf:"varint,4,opt,name=queuing,proto3" json:"queuing,omitempty"`
|
||||
}
|
||||
|
||||
func (x *TaskStart) Reset() {
|
||||
*x = TaskStart{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *TaskStart) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*TaskStart) ProtoMessage() {}
|
||||
|
||||
func (x *TaskStart) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use TaskStart.ProtoReflect.Descriptor instead.
|
||||
func (*TaskStart) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *TaskStart) GetSource() TaskSource {
|
||||
if x != nil {
|
||||
return x.Source
|
||||
}
|
||||
return TaskSource_MANUAL
|
||||
}
|
||||
|
||||
func (x *TaskStart) GetZoneId() int32 {
|
||||
if x != nil {
|
||||
return x.ZoneId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *TaskStart) GetDuration() int32 {
|
||||
if x != nil {
|
||||
return x.Duration
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *TaskStart) GetQueuing() bool {
|
||||
if x != nil {
|
||||
return x.Queuing
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type TaskStop struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Source TaskSource `protobuf:"varint,1,opt,name=source,proto3,enum=TaskSource" json:"source,omitempty"`
|
||||
ZoneId int32 `protobuf:"varint,2,opt,name=zone_id,json=zoneId,proto3" json:"zone_id,omitempty"`
|
||||
}
|
||||
|
||||
func (x *TaskStop) Reset() {
|
||||
*x = TaskStop{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *TaskStop) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*TaskStop) ProtoMessage() {}
|
||||
|
||||
func (x *TaskStop) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use TaskStop.ProtoReflect.Descriptor instead.
|
||||
func (*TaskStop) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *TaskStop) GetSource() TaskSource {
|
||||
if x != nil {
|
||||
return x.Source
|
||||
}
|
||||
return TaskSource_MANUAL
|
||||
}
|
||||
|
||||
func (x *TaskStop) GetZoneId() int32 {
|
||||
if x != nil {
|
||||
return x.ZoneId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Task struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
@ -266,7 +392,7 @@ type Task struct {
|
|||
func (x *Task) Reset() {
|
||||
*x = Task{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[3]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -279,7 +405,7 @@ func (x *Task) String() string {
|
|||
func (*Task) ProtoMessage() {}
|
||||
|
||||
func (x *Task) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[3]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -292,7 +418,7 @@ func (x *Task) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use Task.ProtoReflect.Descriptor instead.
|
||||
func (*Task) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{3}
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *Task) GetSource() TaskSource {
|
||||
|
@ -343,7 +469,7 @@ type TaskList struct {
|
|||
func (x *TaskList) Reset() {
|
||||
*x = TaskList{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[4]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -356,7 +482,7 @@ func (x *TaskList) String() string {
|
|||
func (*TaskList) ProtoMessage() {}
|
||||
|
||||
func (x *TaskList) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[4]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[6]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -369,7 +495,7 @@ func (x *TaskList) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use TaskList.ProtoReflect.Descriptor instead.
|
||||
func (*TaskList) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{4}
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *TaskList) GetTasks() []*Task {
|
||||
|
@ -409,7 +535,7 @@ type Job struct {
|
|||
func (x *Job) Reset() {
|
||||
*x = Job{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[5]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -422,7 +548,7 @@ func (x *Job) String() string {
|
|||
func (*Job) ProtoMessage() {}
|
||||
|
||||
func (x *Job) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[5]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[7]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -435,7 +561,7 @@ func (x *Job) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use Job.ProtoReflect.Descriptor instead.
|
||||
func (*Job) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{5}
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *Job) GetId() int32 {
|
||||
|
@ -491,7 +617,7 @@ type JobID struct {
|
|||
func (x *JobID) Reset() {
|
||||
*x = JobID{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[6]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -504,7 +630,7 @@ func (x *JobID) String() string {
|
|||
func (*JobID) ProtoMessage() {}
|
||||
|
||||
func (x *JobID) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[6]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[8]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -517,7 +643,7 @@ func (x *JobID) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use JobID.ProtoReflect.Descriptor instead.
|
||||
func (*JobID) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{6}
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *JobID) GetId() int32 {
|
||||
|
@ -538,7 +664,7 @@ type JobList struct {
|
|||
func (x *JobList) Reset() {
|
||||
*x = JobList{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[7]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[9]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
@ -551,7 +677,7 @@ func (x *JobList) String() string {
|
|||
func (*JobList) ProtoMessage() {}
|
||||
|
||||
func (x *JobList) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[7]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[9]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -564,7 +690,7 @@ func (x *JobList) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use JobList.ProtoReflect.Descriptor instead.
|
||||
func (*JobList) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{7}
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{9}
|
||||
}
|
||||
|
||||
func (x *JobList) GetJobs() []*Job {
|
||||
|
@ -574,7 +700,7 @@ func (x *JobList) GetJobs() []*Job {
|
|||
return nil
|
||||
}
|
||||
|
||||
type ConfigTime struct {
|
||||
type SystemTime struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
@ -583,23 +709,23 @@ type ConfigTime struct {
|
|||
Timezone string `protobuf:"bytes,2,opt,name=timezone,proto3" json:"timezone,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ConfigTime) Reset() {
|
||||
*x = ConfigTime{}
|
||||
func (x *SystemTime) Reset() {
|
||||
*x = SystemTime{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[8]
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ConfigTime) String() string {
|
||||
func (x *SystemTime) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfigTime) ProtoMessage() {}
|
||||
func (*SystemTime) ProtoMessage() {}
|
||||
|
||||
func (x *ConfigTime) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[8]
|
||||
func (x *SystemTime) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_tsgrain_proto_msgTypes[10]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
@ -610,19 +736,19 @@ func (x *ConfigTime) ProtoReflect() protoreflect.Message {
|
|||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ConfigTime.ProtoReflect.Descriptor instead.
|
||||
func (*ConfigTime) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{8}
|
||||
// Deprecated: Use SystemTime.ProtoReflect.Descriptor instead.
|
||||
func (*SystemTime) Descriptor() ([]byte, []int) {
|
||||
return file_proto_tsgrain_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
func (x *ConfigTime) GetDatetime() *Timestamp {
|
||||
func (x *SystemTime) GetDatetime() *Timestamp {
|
||||
if x != nil {
|
||||
return x.Datetime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ConfigTime) GetTimezone() string {
|
||||
func (x *SystemTime) GetTimezone() string {
|
||||
if x != nil {
|
||||
return x.Timezone
|
||||
}
|
||||
|
@ -654,104 +780,134 @@ var file_proto_tsgrain_proto_rawDesc = []byte{
|
|||
0x6c, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73,
|
||||
0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x22, 0xd0, 0x01, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12,
|
||||
0x23, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
|
||||
0x0b, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a,
|
||||
0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||
0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x10, 0x64, 0x61, 0x74,
|
||||
0x65, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
|
||||
0x0f, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64,
|
||||
0x12, 0x37, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6e,
|
||||
0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x22, 0x62, 0x0a, 0x08, 0x54, 0x61, 0x73,
|
||||
0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x05, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73,
|
||||
0x6b, 0x73, 0x12, 0x1c, 0x0a, 0x03, 0x6e, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f, 0x77,
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x97, 0x01,
|
||||
0x0a, 0x03, 0x4a, 0x6f, 0x62, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
|
||||
0x04, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x14, 0x0a, 0x05, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05,
|
||||
0x52, 0x05, 0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12,
|
||||
0x16, 0x0a, 0x06, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x06, 0x72, 0x65, 0x70, 0x65, 0x61, 0x74, 0x22, 0x17, 0x0a, 0x05, 0x4a, 0x6f, 0x62, 0x49, 0x44,
|
||||
0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x22, 0x7f, 0x0a, 0x09, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74,
|
||||
0x61, 0x72, 0x74, 0x12, 0x23, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49,
|
||||
0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a,
|
||||
0x07, 0x71, 0x75, 0x65, 0x75, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
|
||||
0x71, 0x75, 0x65, 0x75, 0x69, 0x6e, 0x67, 0x22, 0x48, 0x0a, 0x08, 0x54, 0x61, 0x73, 0x6b, 0x53,
|
||||
0x74, 0x6f, 0x70, 0x12, 0x23, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65,
|
||||
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49,
|
||||
0x64, 0x22, 0xd0, 0x01, 0x0a, 0x04, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x23, 0x0a, 0x06, 0x73, 0x6f,
|
||||
0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x54, 0x61, 0x73,
|
||||
0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12,
|
||||
0x17, 0x0a, 0x07, 0x7a, 0x6f, 0x6e, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x06, 0x7a, 0x6f, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x35, 0x0a, 0x10, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65,
|
||||
0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x65,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x37, 0x0a, 0x11, 0x64,
|
||||
0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x66, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
|
||||
0x6d, 0x70, 0x52, 0x10, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x46, 0x69, 0x6e, 0x69,
|
||||
0x73, 0x68, 0x65, 0x64, 0x22, 0x62, 0x0a, 0x08, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x12, 0x1b, 0x0a, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x05, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x05, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x1c, 0x0a,
|
||||
0x03, 0x6e, 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x03, 0x6e, 0x6f, 0x77, 0x12, 0x1b, 0x0a, 0x09, 0x61,
|
||||
0x75, 0x74, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08,
|
||||
0x61, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x03, 0x4a, 0x6f, 0x62,
|
||||
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64,
|
||||
0x22, 0x23, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x04, 0x6a,
|
||||
0x6f, 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x52,
|
||||
0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54,
|
||||
0x69, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||
0x70, 0x52, 0x08, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x2a, 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x73, 0x6b, 0x53,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10,
|
||||
0x00, 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x10, 0x01, 0x32,
|
||||
0xc7, 0x06, 0x0a, 0x07, 0x54, 0x53, 0x47, 0x52, 0x61, 0x69, 0x6e, 0x12, 0x2f, 0x0a, 0x09, 0x53,
|
||||
0x74, 0x61, 0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0c, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x08,
|
||||
0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
|
||||
0x1a, 0x09, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x34, 0x0a,
|
||||
0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x16, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x1a, 0x09, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x22,
|
||||
0x00, 0x30, 0x01, 0x12, 0x1b, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62,
|
||||
0x12, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a, 0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x22, 0x00,
|
||||
0x12, 0x18, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, 0x62,
|
||||
0x49, 0x44, 0x1a, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x07, 0x47, 0x65,
|
||||
0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x08, 0x2e,
|
||||
0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x2b, 0x0a, 0x09, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a, 0x16, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
|
||||
0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x6f,
|
||||
0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42,
|
||||
0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x53, 0x65,
|
||||
0x74, 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c,
|
||||
0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12,
|
||||
0x36, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
|
||||
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0b, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x0b, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12,
|
||||
0x51, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x49, 0x72, 0x72,
|
||||
0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x22, 0x00, 0x12, 0x51, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74,
|
||||
0x49, 0x72, 0x72, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b,
|
||||
0x12, 0x1e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65,
|
||||
0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05,
|
||||
0x7a, 0x6f, 0x6e, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x05, 0x7a, 0x6f, 0x6e,
|
||||
0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x06, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65,
|
||||
0x70, 0x65, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x70, 0x65,
|
||||
0x61, 0x74, 0x22, 0x17, 0x0a, 0x05, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x23, 0x0a, 0x07, 0x4a,
|
||||
0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x01,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73,
|
||||
0x22, 0x50, 0x0a, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x26,
|
||||
0x0a, 0x08, 0x64, 0x61, 0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x64, 0x61,
|
||||
0x74, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f,
|
||||
0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f,
|
||||
0x6e, 0x65, 0x2a, 0x26, 0x0a, 0x0a, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
||||
0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08,
|
||||
0x53, 0x43, 0x48, 0x45, 0x44, 0x55, 0x4c, 0x45, 0x10, 0x01, 0x32, 0xe0, 0x08, 0x0a, 0x07, 0x54,
|
||||
0x53, 0x47, 0x52, 0x61, 0x69, 0x6e, 0x12, 0x31, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0c, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x09, 0x53, 0x74, 0x61,
|
||||
0x72, 0x74, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x0a, 0x2e, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61,
|
||||
0x72, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00,
|
||||
0x12, 0x33, 0x0a, 0x08, 0x53, 0x74, 0x6f, 0x70, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x09, 0x2e, 0x54,
|
||||
0x61, 0x73, 0x6b, 0x53, 0x74, 0x6f, 0x70, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x54, 0x61, 0x73, 0x6b,
|
||||
0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x09, 0x2e, 0x54, 0x61, 0x73, 0x6b,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
|
||||
0x54, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x09, 0x2e,
|
||||
0x54, 0x61, 0x73, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a,
|
||||
0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x22, 0x00, 0x12, 0x18, 0x0a, 0x06, 0x47, 0x65, 0x74,
|
||||
0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x44, 0x1a, 0x04, 0x2e, 0x4a, 0x6f,
|
||||
0x62, 0x22, 0x00, 0x12, 0x2d, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x16,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d,
|
||||
0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4e, 0x5a, 0x6f, 0x6e,
|
||||
0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f,
|
||||
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74,
|
||||
0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x42, 0x30, 0x5a, 0x2e, 0x63, 0x6f, 0x64,
|
||||
0x65, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x61, 0x64, 0x65, 0x76, 0x2e, 0x64, 0x65, 0x2f, 0x54, 0x53,
|
||||
0x47, 0x52, 0x61, 0x69, 0x6e, 0x2f, 0x57, 0x65, 0x62, 0x55, 0x49, 0x2f, 0x73, 0x72, 0x63, 0x2f,
|
||||
0x74, 0x73, 0x67, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x08, 0x2e, 0x4a, 0x6f, 0x62, 0x4c, 0x69, 0x73, 0x74,
|
||||
0x22, 0x00, 0x12, 0x2b, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12,
|
||||
0x04, 0x2e, 0x4a, 0x6f, 0x62, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12,
|
||||
0x2d, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a,
|
||||
0x6f, 0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2d,
|
||||
0x0a, 0x09, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f,
|
||||
0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a,
|
||||
0x0a, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x06, 0x2e, 0x4a, 0x6f,
|
||||
0x62, 0x49, 0x44, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x43, 0x0a,
|
||||
0x0b, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4d, 0x6f, 0x64,
|
||||
0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
|
||||
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x79,
|
||||
0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79,
|
||||
0x1a, 0x0b, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x00, 0x12,
|
||||
0x35, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x12, 0x0a, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x1a, 0x16, 0x2e, 0x67,
|
||||
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x4b, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x53, 0x79, 0x73,
|
||||
0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f,
|
||||
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
|
||||
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
|
||||
0x79, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c,
|
||||
0x74, 0x49, 0x72, 0x72, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12,
|
||||
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x18, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66,
|
||||
0x61, 0x75, 0x6c, 0x74, 0x49, 0x72, 0x72, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a,
|
||||
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
|
||||
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x09, 0x47, 0x65, 0x74,
|
||||
0x4e, 0x5a, 0x6f, 0x6e, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1b,
|
||||
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
|
||||
0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x00, 0x42, 0x30, 0x5a,
|
||||
0x2e, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x74, 0x68, 0x65, 0x74, 0x61, 0x64, 0x65, 0x76, 0x2e, 0x64,
|
||||
0x65, 0x2f, 0x54, 0x53, 0x47, 0x52, 0x61, 0x69, 0x6e, 0x2f, 0x57, 0x65, 0x62, 0x55, 0x49, 0x2f,
|
||||
0x73, 0x72, 0x63, 0x2f, 0x74, 0x73, 0x67, 0x72, 0x61, 0x69, 0x6e, 0x5f, 0x72, 0x70, 0x63, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -767,67 +923,82 @@ func file_proto_tsgrain_proto_rawDescGZIP() []byte {
|
|||
}
|
||||
|
||||
var file_proto_tsgrain_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_proto_tsgrain_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||
var file_proto_tsgrain_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
|
||||
var file_proto_tsgrain_proto_goTypes = []interface{}{
|
||||
(TaskSource)(0), // 0: TaskSource
|
||||
(*Timestamp)(nil), // 1: Timestamp
|
||||
(*TaskRequest)(nil), // 2: TaskRequest
|
||||
(*TaskRequestResult)(nil), // 3: TaskRequestResult
|
||||
(*Task)(nil), // 4: Task
|
||||
(*TaskList)(nil), // 5: TaskList
|
||||
(*Job)(nil), // 6: Job
|
||||
(*JobID)(nil), // 7: JobID
|
||||
(*JobList)(nil), // 8: JobList
|
||||
(*ConfigTime)(nil), // 9: ConfigTime
|
||||
(*emptypb.Empty)(nil), // 10: google.protobuf.Empty
|
||||
(*wrapperspb.BoolValue)(nil), // 11: google.protobuf.BoolValue
|
||||
(*wrapperspb.Int32Value)(nil), // 12: google.protobuf.Int32Value
|
||||
(*TaskStart)(nil), // 4: TaskStart
|
||||
(*TaskStop)(nil), // 5: TaskStop
|
||||
(*Task)(nil), // 6: Task
|
||||
(*TaskList)(nil), // 7: TaskList
|
||||
(*Job)(nil), // 8: Job
|
||||
(*JobID)(nil), // 9: JobID
|
||||
(*JobList)(nil), // 10: JobList
|
||||
(*SystemTime)(nil), // 11: SystemTime
|
||||
(*emptypb.Empty)(nil), // 12: google.protobuf.Empty
|
||||
(*wrapperspb.BoolValue)(nil), // 13: google.protobuf.BoolValue
|
||||
(*wrapperspb.StringValue)(nil), // 14: google.protobuf.StringValue
|
||||
(*wrapperspb.Int32Value)(nil), // 15: google.protobuf.Int32Value
|
||||
}
|
||||
var file_proto_tsgrain_proto_depIdxs = []int32{
|
||||
0, // 0: TaskRequest.source:type_name -> TaskSource
|
||||
0, // 1: Task.source:type_name -> TaskSource
|
||||
1, // 2: Task.datetime_started:type_name -> Timestamp
|
||||
1, // 3: Task.datetime_finished:type_name -> Timestamp
|
||||
4, // 4: TaskList.tasks:type_name -> Task
|
||||
1, // 5: TaskList.now:type_name -> Timestamp
|
||||
1, // 6: Job.date:type_name -> Timestamp
|
||||
6, // 7: JobList.jobs:type_name -> Job
|
||||
1, // 8: ConfigTime.datetime:type_name -> Timestamp
|
||||
2, // 9: TSGRain.StartTask:input_type -> TaskRequest
|
||||
10, // 10: TSGRain.GetTasks:input_type -> google.protobuf.Empty
|
||||
10, // 11: TSGRain.StreamTasks:input_type -> google.protobuf.Empty
|
||||
6, // 12: TSGRain.CreateJob:input_type -> Job
|
||||
7, // 13: TSGRain.GetJob:input_type -> JobID
|
||||
10, // 14: TSGRain.GetJobs:input_type -> google.protobuf.Empty
|
||||
6, // 15: TSGRain.UpdateJob:input_type -> Job
|
||||
7, // 16: TSGRain.DeleteJob:input_type -> JobID
|
||||
10, // 17: TSGRain.GetAutoMode:input_type -> google.protobuf.Empty
|
||||
11, // 18: TSGRain.SetAutoMode:input_type -> google.protobuf.BoolValue
|
||||
10, // 19: TSGRain.GetConfigTime:input_type -> google.protobuf.Empty
|
||||
9, // 20: TSGRain.SetConfigTime:input_type -> ConfigTime
|
||||
10, // 21: TSGRain.GetDefaultIrrigationTime:input_type -> google.protobuf.Empty
|
||||
12, // 22: TSGRain.SetDefaultIrrigationTime:input_type -> google.protobuf.Int32Value
|
||||
10, // 23: TSGRain.GetNZones:input_type -> google.protobuf.Empty
|
||||
3, // 24: TSGRain.StartTask:output_type -> TaskRequestResult
|
||||
5, // 25: TSGRain.GetTasks:output_type -> TaskList
|
||||
5, // 26: TSGRain.StreamTasks:output_type -> TaskList
|
||||
7, // 27: TSGRain.CreateJob:output_type -> JobID
|
||||
6, // 28: TSGRain.GetJob:output_type -> Job
|
||||
8, // 29: TSGRain.GetJobs:output_type -> JobList
|
||||
10, // 30: TSGRain.UpdateJob:output_type -> google.protobuf.Empty
|
||||
10, // 31: TSGRain.DeleteJob:output_type -> google.protobuf.Empty
|
||||
11, // 32: TSGRain.GetAutoMode:output_type -> google.protobuf.BoolValue
|
||||
10, // 33: TSGRain.SetAutoMode:output_type -> google.protobuf.Empty
|
||||
9, // 34: TSGRain.GetConfigTime:output_type -> ConfigTime
|
||||
10, // 35: TSGRain.SetConfigTime:output_type -> google.protobuf.Empty
|
||||
12, // 36: TSGRain.GetDefaultIrrigationTime:output_type -> google.protobuf.Int32Value
|
||||
10, // 37: TSGRain.SetDefaultIrrigationTime:output_type -> google.protobuf.Empty
|
||||
12, // 38: TSGRain.GetNZones:output_type -> google.protobuf.Int32Value
|
||||
24, // [24:39] is the sub-list for method output_type
|
||||
9, // [9:24] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
0, // 1: TaskStart.source:type_name -> TaskSource
|
||||
0, // 2: TaskStop.source:type_name -> TaskSource
|
||||
0, // 3: Task.source:type_name -> TaskSource
|
||||
1, // 4: Task.datetime_started:type_name -> Timestamp
|
||||
1, // 5: Task.datetime_finished:type_name -> Timestamp
|
||||
6, // 6: TaskList.tasks:type_name -> Task
|
||||
1, // 7: TaskList.now:type_name -> Timestamp
|
||||
1, // 8: Job.date:type_name -> Timestamp
|
||||
8, // 9: JobList.jobs:type_name -> Job
|
||||
1, // 10: SystemTime.datetime:type_name -> Timestamp
|
||||
2, // 11: TSGRain.RequestTask:input_type -> TaskRequest
|
||||
4, // 12: TSGRain.StartTask:input_type -> TaskStart
|
||||
5, // 13: TSGRain.StopTask:input_type -> TaskStop
|
||||
12, // 14: TSGRain.GetTasks:input_type -> google.protobuf.Empty
|
||||
12, // 15: TSGRain.StreamTasks:input_type -> google.protobuf.Empty
|
||||
8, // 16: TSGRain.CreateJob:input_type -> Job
|
||||
9, // 17: TSGRain.GetJob:input_type -> JobID
|
||||
12, // 18: TSGRain.GetJobs:input_type -> google.protobuf.Empty
|
||||
8, // 19: TSGRain.UpdateJob:input_type -> Job
|
||||
9, // 20: TSGRain.DeleteJob:input_type -> JobID
|
||||
9, // 21: TSGRain.EnableJob:input_type -> JobID
|
||||
9, // 22: TSGRain.DisableJob:input_type -> JobID
|
||||
12, // 23: TSGRain.GetAutoMode:input_type -> google.protobuf.Empty
|
||||
13, // 24: TSGRain.SetAutoMode:input_type -> google.protobuf.BoolValue
|
||||
12, // 25: TSGRain.GetSystemTime:input_type -> google.protobuf.Empty
|
||||
1, // 26: TSGRain.SetSystemTime:input_type -> Timestamp
|
||||
14, // 27: TSGRain.SetSystemTimezone:input_type -> google.protobuf.StringValue
|
||||
12, // 28: TSGRain.GetDefaultIrrigationTime:input_type -> google.protobuf.Empty
|
||||
15, // 29: TSGRain.SetDefaultIrrigationTime:input_type -> google.protobuf.Int32Value
|
||||
12, // 30: TSGRain.GetNZones:input_type -> google.protobuf.Empty
|
||||
3, // 31: TSGRain.RequestTask:output_type -> TaskRequestResult
|
||||
13, // 32: TSGRain.StartTask:output_type -> google.protobuf.BoolValue
|
||||
13, // 33: TSGRain.StopTask:output_type -> google.protobuf.BoolValue
|
||||
7, // 34: TSGRain.GetTasks:output_type -> TaskList
|
||||
7, // 35: TSGRain.StreamTasks:output_type -> TaskList
|
||||
9, // 36: TSGRain.CreateJob:output_type -> JobID
|
||||
8, // 37: TSGRain.GetJob:output_type -> Job
|
||||
10, // 38: TSGRain.GetJobs:output_type -> JobList
|
||||
12, // 39: TSGRain.UpdateJob:output_type -> google.protobuf.Empty
|
||||
12, // 40: TSGRain.DeleteJob:output_type -> google.protobuf.Empty
|
||||
12, // 41: TSGRain.EnableJob:output_type -> google.protobuf.Empty
|
||||
12, // 42: TSGRain.DisableJob:output_type -> google.protobuf.Empty
|
||||
13, // 43: TSGRain.GetAutoMode:output_type -> google.protobuf.BoolValue
|
||||
12, // 44: TSGRain.SetAutoMode:output_type -> google.protobuf.Empty
|
||||
11, // 45: TSGRain.GetSystemTime:output_type -> SystemTime
|
||||
12, // 46: TSGRain.SetSystemTime:output_type -> google.protobuf.Empty
|
||||
12, // 47: TSGRain.SetSystemTimezone:output_type -> google.protobuf.Empty
|
||||
15, // 48: TSGRain.GetDefaultIrrigationTime:output_type -> google.protobuf.Int32Value
|
||||
12, // 49: TSGRain.SetDefaultIrrigationTime:output_type -> google.protobuf.Empty
|
||||
15, // 50: TSGRain.GetNZones:output_type -> google.protobuf.Int32Value
|
||||
31, // [31:51] is the sub-list for method output_type
|
||||
11, // [11:31] is the sub-list for method input_type
|
||||
11, // [11:11] is the sub-list for extension type_name
|
||||
11, // [11:11] is the sub-list for extension extendee
|
||||
0, // [0:11] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proto_tsgrain_proto_init() }
|
||||
|
@ -873,7 +1044,7 @@ func file_proto_tsgrain_proto_init() {
|
|||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Task); i {
|
||||
switch v := v.(*TaskStart); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -885,7 +1056,7 @@ func file_proto_tsgrain_proto_init() {
|
|||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*TaskList); i {
|
||||
switch v := v.(*TaskStop); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -897,7 +1068,7 @@ func file_proto_tsgrain_proto_init() {
|
|||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Job); i {
|
||||
switch v := v.(*Task); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -909,7 +1080,7 @@ func file_proto_tsgrain_proto_init() {
|
|||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*JobID); i {
|
||||
switch v := v.(*TaskList); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -921,7 +1092,7 @@ func file_proto_tsgrain_proto_init() {
|
|||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*JobList); i {
|
||||
switch v := v.(*Job); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -933,7 +1104,31 @@ func file_proto_tsgrain_proto_init() {
|
|||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ConfigTime); i {
|
||||
switch v := v.(*JobID); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*JobList); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_tsgrain_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SystemTime); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
|
@ -951,7 +1146,7 @@ func file_proto_tsgrain_proto_init() {
|
|||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proto_tsgrain_proto_rawDesc,
|
||||
NumEnums: 1,
|
||||
NumMessages: 9,
|
||||
NumMessages: 11,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
|
|
@ -26,7 +26,11 @@ const _ = grpc.SupportPackageIsVersion7
|
|||
type TSGRainClient interface {
|
||||
// Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn
|
||||
// diese bereits läuft).
|
||||
StartTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error)
|
||||
RequestTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error)
|
||||
// Starte eine Bewässerungsaufgabe
|
||||
StartTask(ctx context.Context, in *TaskStart, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error)
|
||||
// Stoppe eine Bewässerungsaufgabe
|
||||
StopTask(ctx context.Context, in *TaskStop, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error)
|
||||
// Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück.
|
||||
GetTasks(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TaskList, error)
|
||||
// Streamt die aktuelle Warteschlange mit ihren Bewässerungsaufgaben,
|
||||
|
@ -42,14 +46,20 @@ type TSGRainClient interface {
|
|||
UpdateJob(ctx context.Context, in *Job, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Lösche den Bewässerungsjob mit der gegebenen ID.
|
||||
DeleteJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Aktiviere Bewässerungsjob
|
||||
EnableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Deaktiviere Bewässerungsjob
|
||||
DisableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Gibt zurück, ob der Automatikmodus aktiviert ist.
|
||||
GetAutoMode(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error)
|
||||
// Aktiviert/deaktiviert den Automatikmodus.
|
||||
SetAutoMode(ctx context.Context, in *wrapperspb.BoolValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Datum/Uhrzeit/Zeitzone abrufen
|
||||
GetConfigTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ConfigTime, error)
|
||||
// Datum/Uhrzeit/Zeitzone einstellen
|
||||
SetConfigTime(ctx context.Context, in *ConfigTime, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
GetSystemTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SystemTime, error)
|
||||
// Datum/Uhrzeit einstellen
|
||||
SetSystemTime(ctx context.Context, in *Timestamp, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Zeitzone einstellen
|
||||
SetSystemTimezone(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// Standardzeit bei manueller Bewässerung abrufen
|
||||
GetDefaultIrrigationTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.Int32Value, error)
|
||||
// Standardzeit bei manueller Bewässerung einstellen
|
||||
|
@ -66,8 +76,17 @@ func NewTSGRainClient(cc grpc.ClientConnInterface) TSGRainClient {
|
|||
return &tSGRainClient{cc}
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) StartTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error) {
|
||||
func (c *tSGRainClient) RequestTask(ctx context.Context, in *TaskRequest, opts ...grpc.CallOption) (*TaskRequestResult, error) {
|
||||
out := new(TaskRequestResult)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/RequestTask", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) StartTask(ctx context.Context, in *TaskStart, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) {
|
||||
out := new(wrapperspb.BoolValue)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/StartTask", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -75,6 +94,15 @@ func (c *tSGRainClient) StartTask(ctx context.Context, in *TaskRequest, opts ...
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) StopTask(ctx context.Context, in *TaskStop, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) {
|
||||
out := new(wrapperspb.BoolValue)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/StopTask", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) GetTasks(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*TaskList, error) {
|
||||
out := new(TaskList)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/GetTasks", in, out, opts...)
|
||||
|
@ -161,6 +189,24 @@ func (c *tSGRainClient) DeleteJob(ctx context.Context, in *JobID, opts ...grpc.C
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) EnableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/EnableJob", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) DisableJob(ctx context.Context, in *JobID, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/DisableJob", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) GetAutoMode(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) {
|
||||
out := new(wrapperspb.BoolValue)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/GetAutoMode", in, out, opts...)
|
||||
|
@ -179,18 +225,27 @@ func (c *tSGRainClient) SetAutoMode(ctx context.Context, in *wrapperspb.BoolValu
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) GetConfigTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*ConfigTime, error) {
|
||||
out := new(ConfigTime)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/GetConfigTime", in, out, opts...)
|
||||
func (c *tSGRainClient) GetSystemTime(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SystemTime, error) {
|
||||
out := new(SystemTime)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/GetSystemTime", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) SetConfigTime(ctx context.Context, in *ConfigTime, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
func (c *tSGRainClient) SetSystemTime(ctx context.Context, in *Timestamp, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/SetConfigTime", in, out, opts...)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/SetSystemTime", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *tSGRainClient) SetSystemTimezone(ctx context.Context, in *wrapperspb.StringValue, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, "/TSGRain/SetSystemTimezone", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -230,7 +285,11 @@ func (c *tSGRainClient) GetNZones(ctx context.Context, in *emptypb.Empty, opts .
|
|||
type TSGRainServer interface {
|
||||
// Starte eine neue Bewässerungsaufgabe (oder stoppe eine laufende, wenn
|
||||
// diese bereits läuft).
|
||||
StartTask(context.Context, *TaskRequest) (*TaskRequestResult, error)
|
||||
RequestTask(context.Context, *TaskRequest) (*TaskRequestResult, error)
|
||||
// Starte eine Bewässerungsaufgabe
|
||||
StartTask(context.Context, *TaskStart) (*wrapperspb.BoolValue, error)
|
||||
// Stoppe eine Bewässerungsaufgabe
|
||||
StopTask(context.Context, *TaskStop) (*wrapperspb.BoolValue, error)
|
||||
// Gibt sämtliche in der Warteschlange befindlichen Bewässerungsaufgaben zurück.
|
||||
GetTasks(context.Context, *emptypb.Empty) (*TaskList, error)
|
||||
// Streamt die aktuelle Warteschlange mit ihren Bewässerungsaufgaben,
|
||||
|
@ -246,14 +305,20 @@ type TSGRainServer interface {
|
|||
UpdateJob(context.Context, *Job) (*emptypb.Empty, error)
|
||||
// Lösche den Bewässerungsjob mit der gegebenen ID.
|
||||
DeleteJob(context.Context, *JobID) (*emptypb.Empty, error)
|
||||
// Aktiviere Bewässerungsjob
|
||||
EnableJob(context.Context, *JobID) (*emptypb.Empty, error)
|
||||
// Deaktiviere Bewässerungsjob
|
||||
DisableJob(context.Context, *JobID) (*emptypb.Empty, error)
|
||||
// Gibt zurück, ob der Automatikmodus aktiviert ist.
|
||||
GetAutoMode(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error)
|
||||
// Aktiviert/deaktiviert den Automatikmodus.
|
||||
SetAutoMode(context.Context, *wrapperspb.BoolValue) (*emptypb.Empty, error)
|
||||
// Datum/Uhrzeit/Zeitzone abrufen
|
||||
GetConfigTime(context.Context, *emptypb.Empty) (*ConfigTime, error)
|
||||
// Datum/Uhrzeit/Zeitzone einstellen
|
||||
SetConfigTime(context.Context, *ConfigTime) (*emptypb.Empty, error)
|
||||
GetSystemTime(context.Context, *emptypb.Empty) (*SystemTime, error)
|
||||
// Datum/Uhrzeit einstellen
|
||||
SetSystemTime(context.Context, *Timestamp) (*emptypb.Empty, error)
|
||||
// Zeitzone einstellen
|
||||
SetSystemTimezone(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error)
|
||||
// Standardzeit bei manueller Bewässerung abrufen
|
||||
GetDefaultIrrigationTime(context.Context, *emptypb.Empty) (*wrapperspb.Int32Value, error)
|
||||
// Standardzeit bei manueller Bewässerung einstellen
|
||||
|
@ -267,9 +332,15 @@ type TSGRainServer interface {
|
|||
type UnimplementedTSGRainServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedTSGRainServer) StartTask(context.Context, *TaskRequest) (*TaskRequestResult, error) {
|
||||
func (UnimplementedTSGRainServer) RequestTask(context.Context, *TaskRequest) (*TaskRequestResult, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RequestTask not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) StartTask(context.Context, *TaskStart) (*wrapperspb.BoolValue, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method StartTask not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) StopTask(context.Context, *TaskStop) (*wrapperspb.BoolValue, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method StopTask not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) GetTasks(context.Context, *emptypb.Empty) (*TaskList, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetTasks not implemented")
|
||||
}
|
||||
|
@ -291,17 +362,26 @@ func (UnimplementedTSGRainServer) UpdateJob(context.Context, *Job) (*emptypb.Emp
|
|||
func (UnimplementedTSGRainServer) DeleteJob(context.Context, *JobID) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteJob not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) EnableJob(context.Context, *JobID) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method EnableJob not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) DisableJob(context.Context, *JobID) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DisableJob not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) GetAutoMode(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetAutoMode not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) SetAutoMode(context.Context, *wrapperspb.BoolValue) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetAutoMode not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) GetConfigTime(context.Context, *emptypb.Empty) (*ConfigTime, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetConfigTime not implemented")
|
||||
func (UnimplementedTSGRainServer) GetSystemTime(context.Context, *emptypb.Empty) (*SystemTime, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetSystemTime not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) SetConfigTime(context.Context, *ConfigTime) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetConfigTime not implemented")
|
||||
func (UnimplementedTSGRainServer) SetSystemTime(context.Context, *Timestamp) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetSystemTime not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) SetSystemTimezone(context.Context, *wrapperspb.StringValue) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method SetSystemTimezone not implemented")
|
||||
}
|
||||
func (UnimplementedTSGRainServer) GetDefaultIrrigationTime(context.Context, *emptypb.Empty) (*wrapperspb.Int32Value, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetDefaultIrrigationTime not implemented")
|
||||
|
@ -325,11 +405,29 @@ func RegisterTSGRainServer(s grpc.ServiceRegistrar, srv TSGRainServer) {
|
|||
s.RegisterService(&TSGRain_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _TSGRain_StartTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
func _TSGRain_RequestTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TaskRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).RequestTask(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/TSGRain/RequestTask",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).RequestTask(ctx, req.(*TaskRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_StartTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TaskStart)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).StartTask(ctx, in)
|
||||
}
|
||||
|
@ -338,7 +436,25 @@ func _TSGRain_StartTask_Handler(srv interface{}, ctx context.Context, dec func(i
|
|||
FullMethod: "/TSGRain/StartTask",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).StartTask(ctx, req.(*TaskRequest))
|
||||
return srv.(TSGRainServer).StartTask(ctx, req.(*TaskStart))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_StopTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(TaskStop)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).StopTask(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/TSGRain/StopTask",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).StopTask(ctx, req.(*TaskStop))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
@ -472,6 +588,42 @@ func _TSGRain_DeleteJob_Handler(srv interface{}, ctx context.Context, dec func(i
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_EnableJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(JobID)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).EnableJob(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/TSGRain/EnableJob",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).EnableJob(ctx, req.(*JobID))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_DisableJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(JobID)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).DisableJob(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/TSGRain/DisableJob",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).DisableJob(ctx, req.(*JobID))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_GetAutoMode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(emptypb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
|
@ -508,38 +660,56 @@ func _TSGRain_SetAutoMode_Handler(srv interface{}, ctx context.Context, dec func
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_GetConfigTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
func _TSGRain_GetSystemTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(emptypb.Empty)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).GetConfigTime(ctx, in)
|
||||
return srv.(TSGRainServer).GetSystemTime(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/TSGRain/GetConfigTime",
|
||||
FullMethod: "/TSGRain/GetSystemTime",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).GetConfigTime(ctx, req.(*emptypb.Empty))
|
||||
return srv.(TSGRainServer).GetSystemTime(ctx, req.(*emptypb.Empty))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_SetConfigTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ConfigTime)
|
||||
func _TSGRain_SetSystemTime_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(Timestamp)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).SetConfigTime(ctx, in)
|
||||
return srv.(TSGRainServer).SetSystemTime(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/TSGRain/SetConfigTime",
|
||||
FullMethod: "/TSGRain/SetSystemTime",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).SetConfigTime(ctx, req.(*ConfigTime))
|
||||
return srv.(TSGRainServer).SetSystemTime(ctx, req.(*Timestamp))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _TSGRain_SetSystemTimezone_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(wrapperspb.StringValue)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(TSGRainServer).SetSystemTimezone(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/TSGRain/SetSystemTimezone",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(TSGRainServer).SetSystemTimezone(ctx, req.(*wrapperspb.StringValue))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
@ -605,10 +775,18 @@ var TSGRain_ServiceDesc = grpc.ServiceDesc{
|
|||
ServiceName: "TSGRain",
|
||||
HandlerType: (*TSGRainServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "RequestTask",
|
||||
Handler: _TSGRain_RequestTask_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "StartTask",
|
||||
Handler: _TSGRain_StartTask_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "StopTask",
|
||||
Handler: _TSGRain_StopTask_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetTasks",
|
||||
Handler: _TSGRain_GetTasks_Handler,
|
||||
|
@ -633,6 +811,14 @@ var TSGRain_ServiceDesc = grpc.ServiceDesc{
|
|||
MethodName: "DeleteJob",
|
||||
Handler: _TSGRain_DeleteJob_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "EnableJob",
|
||||
Handler: _TSGRain_EnableJob_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "DisableJob",
|
||||
Handler: _TSGRain_DisableJob_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetAutoMode",
|
||||
Handler: _TSGRain_GetAutoMode_Handler,
|
||||
|
@ -642,12 +828,16 @@ var TSGRain_ServiceDesc = grpc.ServiceDesc{
|
|||
Handler: _TSGRain_SetAutoMode_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetConfigTime",
|
||||
Handler: _TSGRain_GetConfigTime_Handler,
|
||||
MethodName: "GetSystemTime",
|
||||
Handler: _TSGRain_GetSystemTime_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SetConfigTime",
|
||||
Handler: _TSGRain_SetConfigTime_Handler,
|
||||
MethodName: "SetSystemTime",
|
||||
Handler: _TSGRain_SetSystemTime_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "SetSystemTimezone",
|
||||
Handler: _TSGRain_SetSystemTimezone_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetDefaultIrrigationTime",
|
||||
|
|
|
@ -83,24 +83,30 @@ func mapTaskList(pbTaskList *tsgrain_grpc.TaskList) model.TaskList {
|
|||
return taskList
|
||||
}
|
||||
|
||||
func (c *RPCClient) StartManualTask(
|
||||
zone_id int32, duration int32, queuing bool, cancelling bool) (
|
||||
model.TaskRequestResult, error) {
|
||||
res, err := c.tsgrain.StartTask(c.ctx, &tsgrain_grpc.TaskRequest{
|
||||
func (c *RPCClient) StartManualTask(zone_id int32, duration int32) (bool, error) {
|
||||
res, err := c.tsgrain.StartTask(c.ctx, &tsgrain_grpc.TaskStart{
|
||||
Source: tsgrain_grpc.TaskSource_MANUAL,
|
||||
ZoneId: zone_id,
|
||||
Duration: duration,
|
||||
Queuing: queuing,
|
||||
Cancelling: cancelling,
|
||||
Queuing: true,
|
||||
})
|
||||
if err != nil {
|
||||
return model.TaskRequestResult{}, err
|
||||
return false, err
|
||||
}
|
||||
|
||||
return model.TaskRequestResult{
|
||||
Started: res.Started,
|
||||
Stopped: res.Stopped,
|
||||
}, nil
|
||||
return res.Value, nil
|
||||
}
|
||||
|
||||
func (c *RPCClient) StopManualTask(zone_id int32) (bool, error) {
|
||||
res, err := c.tsgrain.StopTask(c.ctx, &tsgrain_grpc.TaskStop{
|
||||
Source: tsgrain_grpc.TaskSource_MANUAL,
|
||||
ZoneId: zone_id,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return res.Value, nil
|
||||
}
|
||||
|
||||
func (c *RPCClient) GetTasks() (model.TaskList, error) {
|
||||
|
@ -255,30 +261,27 @@ func (c *RPCClient) SetAutoMode(state bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func (c *RPCClient) GetConfigTime() (model.ConfigTime, error) {
|
||||
configTime, err := c.tsgrain.GetConfigTime(c.ctx, &emptypb.Empty{})
|
||||
func (c *RPCClient) GetSystemTime() (model.SystemTime, error) {
|
||||
configTime, err := c.tsgrain.GetSystemTime(c.ctx, &emptypb.Empty{})
|
||||
if err != nil {
|
||||
return model.ConfigTime{}, err
|
||||
return model.SystemTime{}, err
|
||||
}
|
||||
|
||||
return model.ConfigTime{
|
||||
return model.SystemTime{
|
||||
Time: configTime.Datetime.Seconds,
|
||||
Timezone: configTime.Timezone,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *RPCClient) SetConfigTime(configTime model.ConfigTime) error {
|
||||
_, err := c.tsgrain.SetConfigTime(c.ctx, &tsgrain_grpc.ConfigTime{
|
||||
Datetime: &tsgrain_grpc.Timestamp{Seconds: configTime.Time},
|
||||
Timezone: configTime.Timezone,
|
||||
})
|
||||
func (c *RPCClient) SetSystemTime(timestamp int64) error {
|
||||
_, err := c.tsgrain.SetSystemTime(c.ctx,
|
||||
&tsgrain_grpc.Timestamp{Seconds: timestamp})
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *RPCClient) SetSystemTimezone(timezone string) error {
|
||||
_, err := c.tsgrain.SetConfigTime(c.ctx, &tsgrain_grpc.ConfigTime{
|
||||
Timezone: timezone,
|
||||
})
|
||||
_, err := c.tsgrain.SetSystemTimezone(c.ctx,
|
||||
&wrapperspb.StringValue{Value: timezone})
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -9,16 +9,22 @@
|
|||
"format": "prettier --write ../"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mdi/js": "^6.5.95",
|
||||
"axios": "^0.24.0",
|
||||
"preact": "^10.5.15"
|
||||
"@emotion/react": "^11.7.1",
|
||||
"@emotion/styled": "^11.6.0",
|
||||
"@mui/icons-material": "^5.3.1",
|
||||
"@mui/lab": "^5.0.0-alpha.67",
|
||||
"@mui/material": "^5.4.0",
|
||||
"axios": "^0.25.0",
|
||||
"date-fns": "^2.28.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"wouter": "^2.8.0-alpha.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@preact/preset-vite": "^2.1.5",
|
||||
"prettier": "^2.4.1",
|
||||
"sass": "^1.43.4",
|
||||
"@babel/core": "^7.17.0",
|
||||
"@types/react-dom": "^17.0.11",
|
||||
"@vitejs/plugin-react-refresh": "latest",
|
||||
"typescript": "^4.5.2",
|
||||
"vite": "^2.6.14",
|
||||
"@babel/core": ">=7.12.10 <8.0.0"
|
||||
"vite": "latest"
|
||||
}
|
||||
}
|
||||
|
|
1073
ui/pnpm-lock.yaml
1073
ui/pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
36
ui/src/App.tsx
Normal file
36
ui/src/App.tsx
Normal file
|
@ -0,0 +1,36 @@
|
|||
import * as React from "react"
|
||||
import {Box, Typography} from "@mui/material"
|
||||
import {Route} from "wouter"
|
||||
|
||||
import Navbar from "./components/Navbar"
|
||||
import Controls from "./components/Controls"
|
||||
import Jobs from "./components/Jobs"
|
||||
import Settings from "./components/Settings"
|
||||
import NoConnectionBar from "./components/NoConnectionBar"
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
minHeight: "100vh",
|
||||
}}
|
||||
>
|
||||
<Navbar />
|
||||
<NoConnectionBar />
|
||||
|
||||
<Box sx={{m: 2}}>
|
||||
<Route path="">
|
||||
<Controls />
|
||||
</Route>
|
||||
<Route path="/jobs">
|
||||
<Jobs />
|
||||
</Route>
|
||||
<Route path="/settings">
|
||||
<Settings />
|
||||
</Route>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
65
ui/src/components/AutoMode.tsx
Normal file
65
ui/src/components/AutoMode.tsx
Normal file
|
@ -0,0 +1,65 @@
|
|||
import * as React from "react"
|
||||
import {Switch, FormControlLabel} from "@mui/material"
|
||||
import {WebsocketClient} from "../util/websocket"
|
||||
import {TaskList} from "../tsgrain-client"
|
||||
import {tsgrainApi} from "../util/apiUrls"
|
||||
import {handleApiError} from "../util/functions"
|
||||
|
||||
type Props = {}
|
||||
|
||||
type State = {
|
||||
wsConnected: boolean
|
||||
auto: boolean
|
||||
}
|
||||
|
||||
export default class AutoModeSwitch extends React.Component<Props, State> {
|
||||
private ws?: WebsocketClient
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
wsConnected: false,
|
||||
auto: false,
|
||||
}
|
||||
}
|
||||
|
||||
private onWsStatusUpdate = (wsConnected: boolean) => {
|
||||
this.setState({wsConnected: wsConnected})
|
||||
}
|
||||
|
||||
private onWsMessage = (msg: TaskList, date: Date) => {
|
||||
this.setState({auto: msg.auto_mode})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.ws = new WebsocketClient(this.onWsStatusUpdate, this.onWsMessage)
|
||||
this.setState({wsConnected: this.ws.api().isConnected()})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.ws !== undefined) {
|
||||
this.ws.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
private handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const newState = !this.state.auto
|
||||
tsgrainApi.setAutoMode({state: newState}).catch(handleApiError)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
color="secondary"
|
||||
checked={this.state.auto}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
}
|
||||
label="Auto"
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
344
ui/src/components/Controls.tsx
Normal file
344
ui/src/components/Controls.tsx
Normal file
|
@ -0,0 +1,344 @@
|
|||
import * as React from "react"
|
||||
import {
|
||||
Container,
|
||||
Card,
|
||||
CardContent,
|
||||
Typography,
|
||||
CardActions,
|
||||
Button,
|
||||
Box,
|
||||
Grid,
|
||||
LinearProgress,
|
||||
LinearProgressProps,
|
||||
} from "@mui/material"
|
||||
import {
|
||||
TimerOutlined as IconSchedule,
|
||||
PowerSettingsNew as IconManual,
|
||||
} from "@mui/icons-material"
|
||||
import {Config, getConfig} from "../util/config"
|
||||
import {WebsocketClient, WebsocketMessage} from "../util/websocket"
|
||||
import {TaskList, Task} from "../tsgrain-client"
|
||||
import {tsgrainApi} from "../util/apiUrls"
|
||||
import {
|
||||
dateToTimestamp,
|
||||
getTimestamp,
|
||||
handleApiError,
|
||||
secondsToString,
|
||||
} from "../util/functions"
|
||||
|
||||
function startZone(id: number) {
|
||||
tsgrainApi.startTask({id: id}).catch(handleApiError)
|
||||
}
|
||||
|
||||
function stopZone(id: number) {
|
||||
tsgrainApi.stopTask({id: id}).catch(handleApiError)
|
||||
}
|
||||
|
||||
type LinearProgressWithLabelProps = LinearProgressProps & {
|
||||
label?: string
|
||||
icon?: React.ReactElement
|
||||
}
|
||||
|
||||
function LinearProgressWithLabel(props: LinearProgressWithLabelProps) {
|
||||
return (
|
||||
<Box sx={{display: "flex", alignItems: "center", width: "100%", my: 1}}>
|
||||
<Box sx={{minWidth: 35, maxWidth: 120, overflow: "hidden"}}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
{props.icon}
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{props.label}
|
||||
</Typography>
|
||||
</div>
|
||||
</Box>
|
||||
<Box sx={{flexGrow: "1", ml: 1}}>
|
||||
<LinearProgress variant="determinate" {...props} />
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
type TaskProgressProps = {
|
||||
task: Task
|
||||
taskListCliTimestamp: number
|
||||
taskListSrvTimestamp: number
|
||||
}
|
||||
|
||||
type TaskProgressState = {
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
class TaskProgress extends React.Component<TaskProgressProps, TaskProgressState> {
|
||||
private timerID?: number
|
||||
|
||||
constructor(props: TaskProgressProps) {
|
||||
super(props)
|
||||
this.state = {timestamp: getTimestamp()}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.timerID = setInterval(() => this.tick(), 1000)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearInterval(this.timerID)
|
||||
}
|
||||
|
||||
tick() {
|
||||
this.setState({
|
||||
timestamp: getTimestamp(),
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
let icon
|
||||
switch (this.props.task.source) {
|
||||
case 0:
|
||||
icon = <IconManual />
|
||||
break
|
||||
|
||||
case 1:
|
||||
icon = <IconSchedule />
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
let progSeconds = 0,
|
||||
progPercent = 0
|
||||
|
||||
if (this.props.task.datetime_started !== null) {
|
||||
// Calculate the current server time based on current client time,
|
||||
// client time at last TaskList update and server time at last TaskList update
|
||||
const srvTimestamp =
|
||||
this.state.timestamp -
|
||||
this.props.taskListCliTimestamp +
|
||||
this.props.taskListSrvTimestamp
|
||||
|
||||
const srvDuration =
|
||||
this.props.task.datetime_finished - this.props.task.datetime_started
|
||||
|
||||
// If a task is restored from the database (after a server restart),
|
||||
// it will continue at the left-off position.
|
||||
// The 'Headstart' is the amount of irrigation time already completed
|
||||
// in the previous server run. It needs to be added to the progress time.
|
||||
const headstart = this.props.task.duration - srvDuration
|
||||
|
||||
progSeconds = srvTimestamp - this.props.task.datetime_started + headstart
|
||||
|
||||
// Cap progress in case the client is out of sync
|
||||
progSeconds = Math.min(Math.max(progSeconds, 0), this.props.task.duration)
|
||||
|
||||
progPercent = (progSeconds / srvDuration) * 100
|
||||
}
|
||||
|
||||
return (
|
||||
<LinearProgressWithLabel
|
||||
variant="determinate"
|
||||
value={progPercent}
|
||||
label={`${secondsToString(progSeconds)}/${secondsToString(
|
||||
this.props.task.duration
|
||||
)}`}
|
||||
icon={icon}
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type TaskProgressListProps = {
|
||||
tasks: Task[]
|
||||
taskListCliTimestamp: number
|
||||
taskListSrvTimestamp: number
|
||||
}
|
||||
|
||||
const TaskProgressList = (props: TaskProgressListProps) => {
|
||||
let items: React.ReactElement[] = []
|
||||
|
||||
props.tasks.forEach((task, i) => {
|
||||
let icon
|
||||
switch (task.source) {
|
||||
case 0:
|
||||
icon = <IconManual />
|
||||
break
|
||||
|
||||
case 1:
|
||||
icon = <IconSchedule />
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if (task.datetime_started !== null) {
|
||||
}
|
||||
|
||||
items.push(
|
||||
<TaskProgress
|
||||
key={i}
|
||||
task={task}
|
||||
taskListCliTimestamp={props.taskListCliTimestamp}
|
||||
taskListSrvTimestamp={props.taskListSrvTimestamp}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
return <Box>{items}</Box>
|
||||
}
|
||||
|
||||
type ZoneButtonProps = {
|
||||
start: boolean
|
||||
disabled: boolean
|
||||
zoneId: number
|
||||
}
|
||||
|
||||
const ZoneButton = (props: ZoneButtonProps) => {
|
||||
const clickFun = props.start ? startZone : stopZone
|
||||
|
||||
return (
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => clickFun(props.zoneId)}
|
||||
disabled={props.disabled}
|
||||
>
|
||||
{props.start ? "Start" : "Stop"}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
type ZoneCardProps = {
|
||||
zoneId: number
|
||||
tasks?: Task[]
|
||||
taskListCliTimestamp: number
|
||||
taskListSrvTimestamp: number
|
||||
}
|
||||
|
||||
const ZoneCard = (props: ZoneCardProps) => {
|
||||
const tasks = props.tasks === undefined ? [] : props.tasks
|
||||
|
||||
let runningTask
|
||||
let hasManualTask = false
|
||||
|
||||
if (tasks.length > 0) {
|
||||
if (tasks[0].datetime_started !== null) {
|
||||
runningTask = tasks[0]
|
||||
}
|
||||
|
||||
tasks.forEach((task) => {
|
||||
if (task.source === 0) {
|
||||
hasManualTask = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Card sx={{width: 250}}>
|
||||
<CardContent sx={{py: 1.5}}>
|
||||
<Typography variant="h5" component="div">
|
||||
Platz {props.zoneId}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardContent sx={{py: 0}}>
|
||||
<TaskProgressList
|
||||
tasks={tasks}
|
||||
taskListCliTimestamp={props.taskListCliTimestamp}
|
||||
taskListSrvTimestamp={props.taskListSrvTimestamp}
|
||||
/>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<ZoneButton
|
||||
start={!hasManualTask}
|
||||
disabled={false}
|
||||
zoneId={props.zoneId}
|
||||
/>
|
||||
</CardActions>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
type Props = {}
|
||||
|
||||
type State = {
|
||||
wsConnected: boolean
|
||||
taskList: TaskList
|
||||
tasksByZone: {[key: number]: Task[]}
|
||||
taskListTimestamp: number
|
||||
}
|
||||
|
||||
export default class Controls extends React.Component<Props, State> {
|
||||
private cfg: Config
|
||||
private ws?: WebsocketClient
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.cfg = getConfig()
|
||||
|
||||
this.state = {
|
||||
wsConnected: false,
|
||||
taskList: new WebsocketMessage(),
|
||||
tasksByZone: {},
|
||||
taskListTimestamp: getTimestamp(),
|
||||
}
|
||||
}
|
||||
|
||||
private onWsStatusUpdate = (wsConnected: boolean) => {
|
||||
this.setState({wsConnected: wsConnected})
|
||||
}
|
||||
|
||||
private onWsMessage = (msg: TaskList, date: Date) => {
|
||||
const tbz: {[key: number]: Task[]} = {}
|
||||
msg.tasks.forEach((task) => {
|
||||
if (tbz[task.zone_id] === undefined) {
|
||||
tbz[task.zone_id] = []
|
||||
}
|
||||
tbz[task.zone_id].push(task)
|
||||
})
|
||||
|
||||
this.setState({
|
||||
taskList: msg,
|
||||
tasksByZone: tbz,
|
||||
taskListTimestamp: dateToTimestamp(date),
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.ws = new WebsocketClient(this.onWsStatusUpdate, this.onWsMessage)
|
||||
this.setState({wsConnected: this.ws.api().isConnected()})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.ws !== undefined) {
|
||||
this.ws.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let cards = []
|
||||
for (let i = 1; i <= this.cfg.n_zones; i++) {
|
||||
cards.push(
|
||||
<Grid item key={i}>
|
||||
<ZoneCard
|
||||
zoneId={i}
|
||||
tasks={this.state.tasksByZone[i]}
|
||||
taskListCliTimestamp={this.state.taskListTimestamp}
|
||||
taskListSrvTimestamp={this.state.taskList.now}
|
||||
/>
|
||||
</Grid>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Container maxWidth="md">
|
||||
<Grid container spacing={2}>
|
||||
{cards}
|
||||
</Grid>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
}
|
35
ui/src/components/DurationInput.tsx
Normal file
35
ui/src/components/DurationInput.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
import * as React from "react"
|
||||
import {TextField, TextFieldProps} from "@mui/material"
|
||||
|
||||
import {parseTimeString, secondsToString} from "../util/functions"
|
||||
|
||||
type Props = {
|
||||
value: number
|
||||
onChange: (newValue: number) => void
|
||||
textFieldProps: TextFieldProps
|
||||
}
|
||||
|
||||
const DurationInput = (props: Props) => {
|
||||
const [textValue, setTextValue] = React.useState(secondsToString(props.value))
|
||||
|
||||
const handleDurationUpdate = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setTextValue(e.target.value)
|
||||
props.onChange(parseTimeString(e.target.value))
|
||||
}
|
||||
|
||||
const handleDurationBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
||||
setTextValue(secondsToString(props.value))
|
||||
}
|
||||
|
||||
return (
|
||||
<TextField
|
||||
{...props.textFieldProps}
|
||||
value={textValue}
|
||||
onChange={handleDurationUpdate}
|
||||
onBlur={handleDurationBlur}
|
||||
error={!(props.value > 0)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default DurationInput
|
409
ui/src/components/Jobs.tsx
Normal file
409
ui/src/components/Jobs.tsx
Normal file
|
@ -0,0 +1,409 @@
|
|||
import * as React from "react"
|
||||
import {
|
||||
Box,
|
||||
Card,
|
||||
Chip,
|
||||
CircularProgress,
|
||||
Container,
|
||||
Paper,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
IconButton,
|
||||
Fab,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
TextField,
|
||||
FormControlLabel,
|
||||
Checkbox,
|
||||
Typography,
|
||||
} from "@mui/material"
|
||||
import {
|
||||
Add as AddIcon,
|
||||
Edit as EditIcon,
|
||||
Delete as DeleteIcon,
|
||||
Timer as PowerOnIcon,
|
||||
TimerOff as PowerOffIcon,
|
||||
} from "@mui/icons-material"
|
||||
import {DateTimePicker, LocalizationProvider} from "@mui/lab"
|
||||
import AdapterDateFns from "@mui/lab/AdapterDateFns"
|
||||
import {de} from "date-fns/locale"
|
||||
|
||||
import {Job} from "../tsgrain-client"
|
||||
import {tsgrainApi} from "../util/apiUrls"
|
||||
import {
|
||||
dateToTimestamp,
|
||||
getTimestamp,
|
||||
handleApiError,
|
||||
secondsToString,
|
||||
timestampToString,
|
||||
} from "../util/functions"
|
||||
import {getConfig} from "../util/config"
|
||||
import DurationInput from "./DurationInput"
|
||||
|
||||
type ZoneSelectorProps = {
|
||||
defaultSelection?: Set<number>
|
||||
onChange?: (selection: Set<number>) => void
|
||||
}
|
||||
|
||||
function ZoneSelector(props: ZoneSelectorProps) {
|
||||
const [selection, setSelection] = React.useState(
|
||||
props.defaultSelection || new Set([])
|
||||
)
|
||||
|
||||
const handleChange = (zoneId: number) => {
|
||||
const newSelection = new Set(selection)
|
||||
if (newSelection.has(zoneId)) {
|
||||
newSelection.delete(zoneId)
|
||||
} else {
|
||||
newSelection.add(zoneId)
|
||||
}
|
||||
|
||||
setSelection(newSelection)
|
||||
if (props.onChange) {
|
||||
props.onChange(newSelection)
|
||||
}
|
||||
}
|
||||
|
||||
const nZones = getConfig().n_zones
|
||||
let items: React.ReactElement[] = []
|
||||
|
||||
for (let i = 1; i <= nZones; i++) {
|
||||
items.push(
|
||||
<Checkbox
|
||||
key={i}
|
||||
sx={{p: 0, m: 1}}
|
||||
icon={<Chip label={i} color="default" />}
|
||||
checkedIcon={<Chip label={i} color="primary" />}
|
||||
checked={selection.has(i)}
|
||||
onChange={() => handleChange(i)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Typography>Plätze</Typography>
|
||||
{items}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
type JobEditorProps = {
|
||||
job: Job
|
||||
jobEdit: (job: Job) => void
|
||||
getBtn: (handleClickOpen: () => void) => React.ReactElement
|
||||
}
|
||||
|
||||
function JobEditor(props: JobEditorProps) {
|
||||
const [open, setOpen] = React.useState(false)
|
||||
|
||||
const [zones, setZones] = React.useState(new Set(props.job.zones))
|
||||
const [timestamp, setTimestamp] = React.useState<number | null>(props.job.date)
|
||||
const [datetimeInput, setDatetimeInput] = React.useState<Date | null>(
|
||||
new Date((timestamp || 0) * 1000)
|
||||
)
|
||||
const [duration, setDuration] = React.useState(props.job.duration)
|
||||
const [repeat, setRepeat] = React.useState(props.job.repeat)
|
||||
|
||||
const handleClickOpen = () => {
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
const handleOK = () => {
|
||||
// Validate
|
||||
if (zones.size === 0) {
|
||||
return
|
||||
}
|
||||
if (timestamp === null) {
|
||||
return
|
||||
}
|
||||
if (!(duration > 0)) {
|
||||
return
|
||||
}
|
||||
|
||||
const job = props.job
|
||||
job.zones = Array.from(zones)
|
||||
job.date = timestamp
|
||||
job.duration = duration
|
||||
job.repeat = repeat
|
||||
|
||||
props.jobEdit(job)
|
||||
handleClose()
|
||||
}
|
||||
|
||||
const handleDateUpdate = (newValue: Date | null) => {
|
||||
setDatetimeInput(newValue)
|
||||
|
||||
if (newValue === null || isNaN(newValue.getTime())) {
|
||||
setTimestamp(null)
|
||||
} else {
|
||||
setTimestamp(dateToTimestamp(newValue))
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{display: "inline"}}>
|
||||
{props.getBtn(handleClickOpen)}
|
||||
<Dialog open={open} onClose={handleClose}>
|
||||
<DialogTitle>
|
||||
Zeitplan {props.job.id > 0 ? "bearbeiten" : "erstellen"}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<ZoneSelector
|
||||
defaultSelection={zones}
|
||||
onChange={(selection) => setZones(selection)}
|
||||
/>
|
||||
<LocalizationProvider dateAdapter={AdapterDateFns} locale={de}>
|
||||
<DateTimePicker
|
||||
renderInput={(props) => (
|
||||
<TextField
|
||||
variant="standard"
|
||||
fullWidth
|
||||
margin="dense"
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
label="Datum/Zeit"
|
||||
value={datetimeInput}
|
||||
onChange={handleDateUpdate}
|
||||
mask="__.__.____ __:__"
|
||||
/>
|
||||
</LocalizationProvider>
|
||||
|
||||
<DurationInput
|
||||
textFieldProps={{
|
||||
label: "Dauer",
|
||||
fullWidth: true,
|
||||
margin: "dense",
|
||||
variant: "standard",
|
||||
}}
|
||||
value={duration}
|
||||
onChange={(v) => setDuration(v)}
|
||||
/>
|
||||
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
checked={repeat}
|
||||
onChange={() => setRepeat(!repeat)}
|
||||
/>
|
||||
}
|
||||
label="Täglich wiederholen"
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={handleClose}>Abbrechen</Button>
|
||||
<Button onClick={handleOK}>OK</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
type JobTableProps = {
|
||||
jobs: Job[]
|
||||
jobEdit: (job: Job) => void
|
||||
jobDelete: (jobId: number) => void
|
||||
}
|
||||
|
||||
const JobTable = (props: JobTableProps) => {
|
||||
return (
|
||||
<TableContainer component={Paper}>
|
||||
<Table sx={{minWidth: 650}} aria-label="simple table">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Ein/Aus</TableCell>
|
||||
<TableCell>Plätze</TableCell>
|
||||
<TableCell>Datum/Zeit</TableCell>
|
||||
<TableCell>Dauer</TableCell>
|
||||
<TableCell>Wiederholen</TableCell>
|
||||
<TableCell>Bearbeiten</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.jobs.map((job) => {
|
||||
return (
|
||||
<TableRow key={job.id}>
|
||||
<TableCell>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
job.enable = !job.enable
|
||||
props.jobEdit(job)
|
||||
}}
|
||||
>
|
||||
{job.enable ? (
|
||||
<PowerOnIcon color="primary" />
|
||||
) : (
|
||||
<PowerOffIcon />
|
||||
)}
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
<TableCell>{job.zones.join(", ")}</TableCell>
|
||||
<TableCell>{timestampToString(job.date)}</TableCell>
|
||||
<TableCell>{secondsToString(job.duration)}</TableCell>
|
||||
<TableCell>
|
||||
{job.repeat ? (
|
||||
<Chip label="Ja" color="primary" />
|
||||
) : (
|
||||
<Chip label="Nein" color="error" />
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<JobEditor
|
||||
job={job}
|
||||
jobEdit={props.jobEdit}
|
||||
getBtn={(handleClickOpen) => (
|
||||
<IconButton
|
||||
aria-label="edit"
|
||||
onClick={handleClickOpen}
|
||||
>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
/>
|
||||
<IconButton
|
||||
aria-label="delete"
|
||||
onClick={() => props.jobDelete(job.id)}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)
|
||||
}
|
||||
|
||||
type JobsProps = {}
|
||||
|
||||
type JobsState = {
|
||||
loaded: boolean
|
||||
jobs: Job[]
|
||||
}
|
||||
|
||||
export default class Jobs extends React.Component<JobsProps, JobsState> {
|
||||
private updateTimeout: number | undefined
|
||||
|
||||
constructor(props: JobsProps) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
loaded: false,
|
||||
jobs: [],
|
||||
}
|
||||
}
|
||||
|
||||
private clearUpdateTimeout = () => {
|
||||
if (this.updateTimeout !== undefined) {
|
||||
window.clearTimeout(this.updateTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
private updateJobs = () => {
|
||||
this.clearUpdateTimeout()
|
||||
this.setState({loaded: false})
|
||||
tsgrainApi
|
||||
.getJobs()
|
||||
.then((response) => {
|
||||
this.setState({loaded: true, jobs: response.data})
|
||||
})
|
||||
.catch((reason) => {
|
||||
console.log("error fetching info", reason)
|
||||
this.updateTimeout = window.setTimeout(this.updateJobs, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
private jobEdit = (job: Job) => {
|
||||
tsgrainApi
|
||||
.updateJob(job)
|
||||
.then((response) => {
|
||||
this.updateJobs()
|
||||
})
|
||||
.catch(handleApiError)
|
||||
}
|
||||
|
||||
private jobCreate = (job: Job) => {
|
||||
tsgrainApi
|
||||
.createJob(job)
|
||||
.then((response) => {
|
||||
this.updateJobs()
|
||||
})
|
||||
.catch(handleApiError)
|
||||
}
|
||||
|
||||
private jobDelete = (jobId: number) => {
|
||||
tsgrainApi
|
||||
.deleteJob({id: jobId})
|
||||
.then((response) => {
|
||||
this.updateJobs()
|
||||
})
|
||||
.catch(handleApiError)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateJobs()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.clearUpdateTimeout()
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Container maxWidth="md" sx={{px: 0}}>
|
||||
{this.state.loaded ? (
|
||||
<JobTable
|
||||
jobs={this.state.jobs}
|
||||
jobEdit={this.jobEdit}
|
||||
jobDelete={this.jobDelete}
|
||||
/>
|
||||
) : (
|
||||
<Card sx={{p: 1}}>
|
||||
<Box sx={{display: "flex", justifyContent: "center"}}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
</Card>
|
||||
)}
|
||||
<JobEditor
|
||||
job={{
|
||||
id: 0,
|
||||
date: getTimestamp() + 300,
|
||||
duration: 300,
|
||||
enable: true,
|
||||
repeat: false,
|
||||
zones: [],
|
||||
}}
|
||||
jobEdit={this.jobCreate}
|
||||
getBtn={(handleClickOpen) => (
|
||||
<Fab
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 32,
|
||||
right: 32,
|
||||
}}
|
||||
color="primary"
|
||||
aria-label="add"
|
||||
onClick={handleClickOpen}
|
||||
>
|
||||
<AddIcon />
|
||||
</Fab>
|
||||
)}
|
||||
/>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
}
|
124
ui/src/components/Navbar.tsx
Normal file
124
ui/src/components/Navbar.tsx
Normal file
|
@ -0,0 +1,124 @@
|
|||
import * as React from "react"
|
||||
import {
|
||||
AppBar,
|
||||
Box,
|
||||
Toolbar,
|
||||
IconButton,
|
||||
Typography,
|
||||
Menu,
|
||||
Container,
|
||||
Button,
|
||||
MenuItem,
|
||||
Switch,
|
||||
FormControlLabel,
|
||||
} from "@mui/material"
|
||||
import MenuIcon from "@mui/icons-material/Menu"
|
||||
import {useLocation} from "wouter"
|
||||
import {getConfig} from "../util/config"
|
||||
import AutoModeSwitch from "./AutoMode"
|
||||
|
||||
const pages: {[key: string]: string} = {
|
||||
Steuerung: "/",
|
||||
Zeitpläne: "/jobs",
|
||||
Einstellungen: "/settings",
|
||||
}
|
||||
|
||||
const Navbar = () => {
|
||||
const [anchorElNav, setAnchorElNav] = React.useState<Element | null>(null)
|
||||
const [location, setLocation] = useLocation()
|
||||
|
||||
const handleOpenNavMenu = (event: React.MouseEvent) => {
|
||||
setAnchorElNav(event.currentTarget)
|
||||
}
|
||||
|
||||
const handleCloseNavMenu = () => {
|
||||
setAnchorElNav(null)
|
||||
}
|
||||
|
||||
const handleTabClick = (page: string) => {
|
||||
setLocation(pages[page])
|
||||
handleCloseNavMenu()
|
||||
}
|
||||
|
||||
return (
|
||||
<AppBar position="static">
|
||||
<Container maxWidth="xl">
|
||||
<Toolbar disableGutters>
|
||||
{/* Desktop title */}
|
||||
<Typography
|
||||
variant="h6"
|
||||
noWrap
|
||||
component="div"
|
||||
sx={{mr: 2, display: {xs: "none", md: "flex"}}}
|
||||
>
|
||||
TSGRain
|
||||
</Typography>
|
||||
|
||||
<Box sx={{flexGrow: 1, display: {xs: "flex", md: "none"}}}>
|
||||
<IconButton
|
||||
size="large"
|
||||
aria-label="account of current user"
|
||||
aria-controls="menu-appbar"
|
||||
aria-haspopup="true"
|
||||
onClick={handleOpenNavMenu}
|
||||
color="inherit"
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Menu
|
||||
id="menu-appbar"
|
||||
anchorEl={anchorElNav}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "left",
|
||||
}}
|
||||
keepMounted
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "left",
|
||||
}}
|
||||
open={Boolean(anchorElNav)}
|
||||
onClose={handleCloseNavMenu}
|
||||
sx={{
|
||||
display: {xs: "block", md: "none"},
|
||||
}}
|
||||
>
|
||||
{Object.keys(pages).map((page) => (
|
||||
<MenuItem
|
||||
key={page}
|
||||
onClick={() => handleTabClick(page)}
|
||||
>
|
||||
<Typography textAlign="center">{page}</Typography>
|
||||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
</Box>
|
||||
{/* Mobile title */}
|
||||
<Typography
|
||||
variant="h6"
|
||||
noWrap
|
||||
component="div"
|
||||
sx={{flexGrow: 1, display: {xs: "flex", md: "none"}}}
|
||||
>
|
||||
TSGRain
|
||||
</Typography>
|
||||
<Box sx={{flexGrow: 1, display: {xs: "none", md: "flex"}}}>
|
||||
{Object.keys(pages).map((page) => (
|
||||
<Button
|
||||
key={page}
|
||||
onClick={() => handleTabClick(page)}
|
||||
sx={{my: 2, color: "white", display: "block"}}
|
||||
>
|
||||
{page}
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
<Box>
|
||||
<AutoModeSwitch />
|
||||
</Box>
|
||||
</Toolbar>
|
||||
</Container>
|
||||
</AppBar>
|
||||
)
|
||||
}
|
||||
export default Navbar
|
47
ui/src/components/NoConnectionBar.tsx
Normal file
47
ui/src/components/NoConnectionBar.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
import * as React from "react"
|
||||
import {Box, Typography} from "@mui/material"
|
||||
import {WebsocketClient} from "../util/websocket"
|
||||
|
||||
type Props = {}
|
||||
|
||||
type State = {
|
||||
wsConnected: boolean
|
||||
}
|
||||
|
||||
export default class NoConnectionBar extends React.Component<Props, State> {
|
||||
private ws?: WebsocketClient
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
wsConnected: false,
|
||||
}
|
||||
}
|
||||
|
||||
private onWsStatusUpdate = (wsConnected: boolean) => {
|
||||
this.setState({wsConnected: wsConnected})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.ws = new WebsocketClient(this.onWsStatusUpdate)
|
||||
this.setState({wsConnected: this.ws.api().isConnected()})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.ws !== undefined) {
|
||||
this.ws.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.state.wsConnected) {
|
||||
return (
|
||||
<Box sx={{bgcolor: "warning.main"}}>
|
||||
<Typography align="center">Keine Verbindung</Typography>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
315
ui/src/components/Settings.tsx
Normal file
315
ui/src/components/Settings.tsx
Normal file
|
@ -0,0 +1,315 @@
|
|||
import * as React from "react"
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Card,
|
||||
CardActions,
|
||||
CardContent,
|
||||
CircularProgress,
|
||||
Container,
|
||||
TextField,
|
||||
Typography,
|
||||
} from "@mui/material"
|
||||
import {tsgrainApi} from "../util/apiUrls"
|
||||
import {
|
||||
dateToInputString,
|
||||
dateToTimestamp,
|
||||
handleApiError,
|
||||
inputStringToDate,
|
||||
timestampToDate,
|
||||
} from "../util/functions"
|
||||
import {getConfig} from "../util/config"
|
||||
import DurationInput from "./DurationInput"
|
||||
|
||||
type IrrigationSettingsProps = {}
|
||||
|
||||
type IrrigationSettingsState = {
|
||||
loaded: boolean
|
||||
irrigationTime: number
|
||||
}
|
||||
|
||||
class IrrigationSettings extends React.Component<
|
||||
IrrigationSettingsProps,
|
||||
IrrigationSettingsState
|
||||
> {
|
||||
private updateTimeout?: number
|
||||
private initialIrrigationTime?: number
|
||||
|
||||
constructor(props: IrrigationSettingsProps) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
loaded: false,
|
||||
irrigationTime: 0,
|
||||
}
|
||||
}
|
||||
|
||||
private clearUpdateTimeout = () => {
|
||||
if (this.updateTimeout !== undefined) {
|
||||
window.clearTimeout(this.updateTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
private updateSettings = () => {
|
||||
this.clearUpdateTimeout()
|
||||
this.setState({loaded: false})
|
||||
|
||||
tsgrainApi
|
||||
.getDefaultIrrigationTime()
|
||||
.then((response) => {
|
||||
this.initialIrrigationTime = response.data.time
|
||||
|
||||
this.setState({
|
||||
loaded: true,
|
||||
irrigationTime: this.initialIrrigationTime,
|
||||
})
|
||||
})
|
||||
.catch((reason) => {
|
||||
console.log("error fetching irrigation settings", reason)
|
||||
this.updateTimeout = window.setTimeout(this.updateSettings, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
private showSubmit(): boolean {
|
||||
return (
|
||||
this.state.irrigationTime !== this.initialIrrigationTime &&
|
||||
this.state.irrigationTime > 0
|
||||
)
|
||||
}
|
||||
|
||||
private submitSettings = () => {
|
||||
const irrigationTime = this.state.irrigationTime
|
||||
tsgrainApi
|
||||
.setDefaultIrrigationTime({time: irrigationTime})
|
||||
.then((response) => {
|
||||
this.setState({irrigationTime: irrigationTime})
|
||||
})
|
||||
.catch(handleApiError)
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateSettings()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.clearUpdateTimeout()
|
||||
}
|
||||
|
||||
renderSettings() {
|
||||
return (
|
||||
<Box>
|
||||
<Card sx={{mb: 2}}>
|
||||
<CardContent>
|
||||
<Typography variant="h5">Bewässerungssteuerung</Typography>
|
||||
|
||||
<DurationInput
|
||||
textFieldProps={{
|
||||
label: "Manuelle Bewässerungszeit",
|
||||
fullWidth: true,
|
||||
margin: "dense",
|
||||
variant: "standard",
|
||||
}}
|
||||
value={this.state.irrigationTime}
|
||||
onChange={(v) => this.setState({irrigationTime: v})}
|
||||
/>
|
||||
</CardContent>
|
||||
{this.showSubmit() ? (
|
||||
<CardActions>
|
||||
<Button size="small" onClick={this.submitSettings}>
|
||||
OK
|
||||
</Button>
|
||||
</CardActions>
|
||||
) : null}
|
||||
</Card>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.loaded) return this.renderSettings()
|
||||
|
||||
return (
|
||||
<Card sx={{p: 1}}>
|
||||
<Box sx={{display: "flex", justifyContent: "center"}}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
type TimeSettingsProps = {}
|
||||
|
||||
type TimeSettingsState = {
|
||||
loaded: boolean
|
||||
date: Date
|
||||
dateStr: string
|
||||
timezone: string
|
||||
}
|
||||
|
||||
class TimeSettings extends React.Component<TimeSettingsProps, TimeSettingsState> {
|
||||
private updateTimeout?: number
|
||||
private timerID?: number
|
||||
|
||||
private initialDate?: Date
|
||||
private initialTimezone?: string
|
||||
|
||||
constructor(props: TimeSettingsProps) {
|
||||
super(props)
|
||||
|
||||
const now = new Date()
|
||||
this.state = {
|
||||
loaded: false,
|
||||
date: now,
|
||||
dateStr: dateToInputString(now),
|
||||
timezone: "",
|
||||
}
|
||||
}
|
||||
|
||||
private clearUpdateTimeout = () => {
|
||||
if (this.updateTimeout !== undefined) {
|
||||
window.clearTimeout(this.updateTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
private updateSettings = () => {
|
||||
this.clearUpdateTimeout()
|
||||
this.setState({loaded: false})
|
||||
|
||||
tsgrainApi
|
||||
.getSystemTime()
|
||||
.then((response) => {
|
||||
this.initialDate = timestampToDate(response.data.time)
|
||||
this.initialTimezone = response.data.timezone
|
||||
|
||||
this.setState({
|
||||
loaded: true,
|
||||
dateStr: dateToInputString(this.initialDate),
|
||||
timezone: this.initialTimezone,
|
||||
})
|
||||
|
||||
this.timerID = setInterval(this.tick, 1000)
|
||||
})
|
||||
.catch((reason) => {
|
||||
console.log("error fetching time settings", reason)
|
||||
this.updateTimeout = window.setTimeout(this.updateSettings, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
private tick = () => {
|
||||
if (this.state.date !== null) {
|
||||
const newDate = new Date(this.state.date.getTime() + 1000)
|
||||
this.setState({
|
||||
date: newDate,
|
||||
dateStr: dateToInputString(newDate),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private showSubmit(): boolean {
|
||||
return (
|
||||
this.state.date !== this.initialDate ||
|
||||
this.state.timezone !== this.initialTimezone
|
||||
)
|
||||
}
|
||||
|
||||
private submitSettings = () => {
|
||||
const date = this.state.date
|
||||
if (date !== this.initialDate) {
|
||||
tsgrainApi
|
||||
.setSystemTime({time: dateToTimestamp(date)})
|
||||
.then((response) => {
|
||||
this.updateSettings()
|
||||
})
|
||||
.catch(handleApiError)
|
||||
}
|
||||
|
||||
const tz = this.state.timezone
|
||||
if (tz !== this.initialTimezone) {
|
||||
tsgrainApi
|
||||
.setSystemTimezone({timezone: this.state.timezone})
|
||||
.then((response) => {
|
||||
this.initialTimezone = tz
|
||||
this.setState({timezone: tz})
|
||||
})
|
||||
.catch(handleApiError)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateSettings()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.clearUpdateTimeout()
|
||||
clearInterval(this.timerID)
|
||||
}
|
||||
|
||||
renderSettings() {
|
||||
return (
|
||||
<Card sx={{mb: 2}}>
|
||||
<CardContent>
|
||||
<Typography variant="h5">Datum/Uhrzeit</Typography>
|
||||
|
||||
<TextField
|
||||
label="Datum/Zeit"
|
||||
fullWidth
|
||||
margin="dense"
|
||||
variant="standard"
|
||||
type="datetime-local"
|
||||
value={this.state.dateStr}
|
||||
onChange={(e) => {
|
||||
clearInterval(this.timerID)
|
||||
this.setState({
|
||||
dateStr: e.target.value,
|
||||
date: inputStringToDate(e.target.value),
|
||||
})
|
||||
}}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
label="Zeitzone"
|
||||
fullWidth
|
||||
margin="dense"
|
||||
variant="standard"
|
||||
value={this.state.timezone}
|
||||
onChange={(e) => this.setState({timezone: e.target.value})}
|
||||
/>
|
||||
</CardContent>
|
||||
{this.showSubmit() ? (
|
||||
<CardActions>
|
||||
<Button size="small" onClick={this.submitSettings}>
|
||||
OK
|
||||
</Button>
|
||||
</CardActions>
|
||||
) : null}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.loaded) return this.renderSettings()
|
||||
|
||||
return (
|
||||
<Card sx={{p: 1}}>
|
||||
<Box sx={{display: "flex", justifyContent: "center"}}>
|
||||
<CircularProgress />
|
||||
</Box>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const Settings = () => {
|
||||
return (
|
||||
<Container maxWidth="md" sx={{px: 0}}>
|
||||
<IrrigationSettings />
|
||||
<TimeSettings />
|
||||
<Card sx={{mb: 2, p: 1, textAlign: "center"}}>
|
||||
TSGRain WebUI Version: {getConfig().version}
|
||||
</Card>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Settings
|
|
@ -1,10 +0,0 @@
|
|||
import {Component} from "preact"
|
||||
// import UpdaterView from "./Updater/UpdaterView"
|
||||
// import logo from "../assets/logo.svg"
|
||||
import {getConfig} from "../util/config"
|
||||
|
||||
export default class App extends Component {
|
||||
render() {
|
||||
return <div>{getConfig().version}</div>
|
||||
}
|
||||
}
|
|
@ -1,5 +1,17 @@
|
|||
import {render} from "preact"
|
||||
import App from "./components/app"
|
||||
import "./style/index.scss"
|
||||
import * as React from "react"
|
||||
import ReactDOM from "react-dom"
|
||||
import {CssBaseline} from "@mui/material"
|
||||
import {ThemeProvider} from "@mui/material/styles"
|
||||
import App from "./App"
|
||||
import theme from "./theme"
|
||||
|
||||
render(<App />, document.getElementById("app")!)
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<ThemeProvider theme={theme}>
|
||||
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
|
||||
<CssBaseline />
|
||||
<App />
|
||||
</ThemeProvider>
|
||||
</React.StrictMode>,
|
||||
document.getElementById("app")
|
||||
)
|
||||
|
|
1
ui/src/preact.d.ts
vendored
1
ui/src/preact.d.ts
vendored
|
@ -1 +0,0 @@
|
|||
import JSX = preact.JSX
|
19
ui/src/theme.ts
Normal file
19
ui/src/theme.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import {createTheme} from "@mui/material/styles"
|
||||
import {red} from "@mui/material/colors"
|
||||
|
||||
// Create a theme instance.
|
||||
const theme = createTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: "#357a38",
|
||||
},
|
||||
secondary: {
|
||||
main: "#ff3d00",
|
||||
},
|
||||
error: {
|
||||
main: red.A400,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default theme
|
|
@ -1,6 +1,5 @@
|
|||
.gitignore
|
||||
.npmignore
|
||||
.openapi-generator-ignore
|
||||
api.ts
|
||||
base.ts
|
||||
common.ts
|
||||
|
|
|
@ -1 +1 @@
|
|||
5.3.1
|
||||
5.4.0
|
|
@ -50,25 +50,6 @@ export interface AutoMode {
|
|||
*/
|
||||
state: boolean
|
||||
}
|
||||
/**
|
||||
* Aktuelle Systemzeit/Zeitzone
|
||||
* @export
|
||||
* @interface ConfigTime
|
||||
*/
|
||||
export interface ConfigTime {
|
||||
/**
|
||||
* Aktuelle Systemzeit
|
||||
* @type {number}
|
||||
* @memberof ConfigTime
|
||||
*/
|
||||
time: number
|
||||
/**
|
||||
* Aktuelle Zeitzone
|
||||
* @type {string}
|
||||
* @memberof ConfigTime
|
||||
*/
|
||||
timezone: string
|
||||
}
|
||||
/**
|
||||
* Manuelle Bewässerungszeit in Sekunden
|
||||
* @export
|
||||
|
@ -82,50 +63,6 @@ export interface DefaultIrrigationTime {
|
|||
*/
|
||||
time: number
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface InlineObject
|
||||
*/
|
||||
export interface InlineObject {
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof InlineObject
|
||||
*/
|
||||
state: boolean
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface InlineObject1
|
||||
*/
|
||||
export interface InlineObject1 {
|
||||
/**
|
||||
* Aufgabe stoppen/aus der Warteschlange entfernen, wenn sie bereits läuft oder sich in der Warteschlange befindet.
|
||||
* @type {boolean}
|
||||
* @memberof InlineObject1
|
||||
*/
|
||||
cancelling: boolean
|
||||
/**
|
||||
* Bewässerungsdauer in Sekunden (0: Standarddauer)
|
||||
* @type {number}
|
||||
* @memberof InlineObject1
|
||||
*/
|
||||
duration: number
|
||||
/**
|
||||
* Aufgabe in die Warteschlange einreihen, wenn sie nicht sofort ausgeführt werden kann.
|
||||
* @type {boolean}
|
||||
* @memberof InlineObject1
|
||||
*/
|
||||
queuing: boolean
|
||||
/**
|
||||
* Nummer der Bewässerungszone
|
||||
* @type {number}
|
||||
* @memberof InlineObject1
|
||||
*/
|
||||
zone_id: number
|
||||
}
|
||||
/**
|
||||
* Job stellt einen Bewässerungszeitplan dar.
|
||||
* @export
|
||||
|
@ -263,6 +200,25 @@ export interface StatusMessage {
|
|||
*/
|
||||
success: boolean
|
||||
}
|
||||
/**
|
||||
* Aktuelle Systemzeit/Zeitzone
|
||||
* @export
|
||||
* @interface SystemTime
|
||||
*/
|
||||
export interface SystemTime {
|
||||
/**
|
||||
* Aktuelle Systemzeit
|
||||
* @type {number}
|
||||
* @memberof SystemTime
|
||||
*/
|
||||
time: number
|
||||
/**
|
||||
* Aktuelle Zeitzone
|
||||
* @type {string}
|
||||
* @memberof SystemTime
|
||||
*/
|
||||
timezone: string
|
||||
}
|
||||
/**
|
||||
* Task stellt eine Bewässerungsaufgabe dar.
|
||||
* @export
|
||||
|
@ -326,23 +282,43 @@ export interface TaskList {
|
|||
tasks: Array<Task>
|
||||
}
|
||||
/**
|
||||
* TaskRequestResult wird beim Starten eines Tasks zurückgegeben
|
||||
* Zeitstempel
|
||||
* @export
|
||||
* @interface TaskRequestResult
|
||||
* @interface Timestamp
|
||||
*/
|
||||
export interface TaskRequestResult {
|
||||
export interface Timestamp {
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof TaskRequestResult
|
||||
* @type {number}
|
||||
* @memberof Timestamp
|
||||
*/
|
||||
Started?: boolean
|
||||
time: number
|
||||
}
|
||||
/**
|
||||
* Systemzeitzone
|
||||
* @export
|
||||
* @interface Timezone
|
||||
*/
|
||||
export interface Timezone {
|
||||
/**
|
||||
*
|
||||
* @type {boolean}
|
||||
* @memberof TaskRequestResult
|
||||
* @type {string}
|
||||
* @memberof Timezone
|
||||
*/
|
||||
Stopped?: boolean
|
||||
timezone: string
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface ZoneID
|
||||
*/
|
||||
export interface ZoneID {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof ZoneID
|
||||
*/
|
||||
id?: number
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -400,12 +376,12 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
|
|||
/**
|
||||
*
|
||||
* @summary Lösche einen gespeicherten Zeitplan.
|
||||
* @param {number} [id]
|
||||
* @param {JobID} [jobId] JobID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
deleteJob: async (
|
||||
id?: number,
|
||||
jobId?: JobID,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/job`
|
||||
|
@ -435,7 +411,7 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
|
|||
...options.headers,
|
||||
}
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(
|
||||
id,
|
||||
jobId,
|
||||
localVarRequestOptions,
|
||||
configuration
|
||||
)
|
||||
|
@ -478,40 +454,6 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
|
|||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
getConfigTime: async (
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/config/time`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions
|
||||
}
|
||||
|
||||
const localVarRequestOptions = {method: "GET", ...baseOptions, ...options}
|
||||
const localVarHeaderParameter = {} as any
|
||||
const localVarQueryParameter = {} as any
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
...options.headers,
|
||||
}
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Rufe die Standardzeit bei manueller Bewässerung ab.
|
||||
|
@ -623,14 +565,81 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
|
|||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
getSystemTime: async (
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/config/time`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions
|
||||
}
|
||||
|
||||
const localVarRequestOptions = {method: "GET", ...baseOptions, ...options}
|
||||
const localVarHeaderParameter = {} as any
|
||||
const localVarQueryParameter = {} as any
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
...options.headers,
|
||||
}
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
getTasks: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||
const localVarPath = `/tasks`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions
|
||||
}
|
||||
|
||||
const localVarRequestOptions = {method: "GET", ...baseOptions, ...options}
|
||||
const localVarHeaderParameter = {} as any
|
||||
const localVarQueryParameter = {} as any
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
...options.headers,
|
||||
}
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {InlineObject} [state]
|
||||
* @param {AutoMode} [state] Zustand des Automatikmodus
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
setAutoMode: async (
|
||||
state?: InlineObject,
|
||||
state?: AutoMode,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/config/auto`
|
||||
|
@ -666,49 +675,6 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
|
|||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {ConfigTime} [configTime]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
setConfigTime: async (
|
||||
configTime?: ConfigTime,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/config/time`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions
|
||||
}
|
||||
|
||||
const localVarRequestOptions = {method: "POST", ...baseOptions, ...options}
|
||||
const localVarHeaderParameter = {} as any
|
||||
const localVarQueryParameter = {} as any
|
||||
|
||||
localVarHeaderParameter["Content-Type"] = "application/json"
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
...options.headers,
|
||||
}
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(
|
||||
configTime,
|
||||
localVarRequestOptions,
|
||||
configuration
|
||||
)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Setze die die Standardzeit bei manueller Bewässerung.
|
||||
|
@ -754,16 +720,16 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
|
|||
}
|
||||
},
|
||||
/**
|
||||
* Starte/stoppe manuell eine neue Bewässerungsaufgabe
|
||||
* @param {InlineObject1} [taskRequest]
|
||||
* Systemzeit einstellen
|
||||
* @param {Timestamp} [timestamp]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
startManualTask: async (
|
||||
taskRequest?: InlineObject1,
|
||||
setSystemTime: async (
|
||||
timestamp?: Timestamp,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/task/manual`
|
||||
const localVarPath = `/config/time`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
|
@ -786,7 +752,137 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
|
|||
...options.headers,
|
||||
}
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(
|
||||
taskRequest,
|
||||
timestamp,
|
||||
localVarRequestOptions,
|
||||
configuration
|
||||
)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Systemzeitzone einstellen
|
||||
* @param {Timezone} [timezone]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
setSystemTimezone: async (
|
||||
timezone?: Timezone,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/config/timezone`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions
|
||||
}
|
||||
|
||||
const localVarRequestOptions = {method: "POST", ...baseOptions, ...options}
|
||||
const localVarHeaderParameter = {} as any
|
||||
const localVarQueryParameter = {} as any
|
||||
|
||||
localVarHeaderParameter["Content-Type"] = "application/json"
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
...options.headers,
|
||||
}
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(
|
||||
timezone,
|
||||
localVarRequestOptions,
|
||||
configuration
|
||||
)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
startTask: async (
|
||||
zoneId?: ZoneID,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/task/start`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions
|
||||
}
|
||||
|
||||
const localVarRequestOptions = {method: "POST", ...baseOptions, ...options}
|
||||
const localVarHeaderParameter = {} as any
|
||||
const localVarQueryParameter = {} as any
|
||||
|
||||
localVarHeaderParameter["Content-Type"] = "application/json"
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
...options.headers,
|
||||
}
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(
|
||||
zoneId,
|
||||
localVarRequestOptions,
|
||||
configuration
|
||||
)
|
||||
|
||||
return {
|
||||
url: toPathString(localVarUrlObj),
|
||||
options: localVarRequestOptions,
|
||||
}
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Stoppe eine manuelle Bewässerungsaufgabe.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
stopTask: async (
|
||||
zoneId?: ZoneID,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/task/stop`
|
||||
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL)
|
||||
let baseOptions
|
||||
if (configuration) {
|
||||
baseOptions = configuration.baseOptions
|
||||
}
|
||||
|
||||
const localVarRequestOptions = {method: "POST", ...baseOptions, ...options}
|
||||
const localVarHeaderParameter = {} as any
|
||||
const localVarQueryParameter = {} as any
|
||||
|
||||
localVarHeaderParameter["Content-Type"] = "application/json"
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter)
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {}
|
||||
localVarRequestOptions.headers = {
|
||||
...localVarHeaderParameter,
|
||||
...headersFromBaseOptions,
|
||||
...options.headers,
|
||||
}
|
||||
localVarRequestOptions.data = serializeDataIfNeeded(
|
||||
zoneId,
|
||||
localVarRequestOptions,
|
||||
configuration
|
||||
)
|
||||
|
@ -877,18 +973,18 @@ export const DefaultApiFp = function (configuration?: Configuration) {
|
|||
/**
|
||||
*
|
||||
* @summary Lösche einen gespeicherten Zeitplan.
|
||||
* @param {number} [id]
|
||||
* @param {JobID} [jobId] JobID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async deleteJob(
|
||||
id?: number,
|
||||
jobId?: JobID,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.deleteJob(
|
||||
id,
|
||||
jobId,
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
|
@ -919,26 +1015,6 @@ export const DefaultApiFp = function (configuration?: Configuration) {
|
|||
configuration
|
||||
)
|
||||
},
|
||||
/**
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async getConfigTime(
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ConfigTime>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getConfigTime(
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
localVarAxiosArgs,
|
||||
globalAxios,
|
||||
BASE_PATH,
|
||||
configuration
|
||||
)
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Rufe die Standardzeit bei manueller Bewässerung ab.
|
||||
|
@ -1004,19 +1080,16 @@ export const DefaultApiFp = function (configuration?: Configuration) {
|
|||
)
|
||||
},
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {InlineObject} [state]
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async setAutoMode(
|
||||
state?: InlineObject,
|
||||
async getSystemTime(
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SystemTime>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.setAutoMode(
|
||||
state,
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getSystemTime(
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
|
@ -1027,19 +1100,38 @@ export const DefaultApiFp = function (configuration?: Configuration) {
|
|||
)
|
||||
},
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {ConfigTime} [configTime]
|
||||
*
|
||||
* @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async setConfigTime(
|
||||
configTime?: ConfigTime,
|
||||
async getTasks(
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<TaskList>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.getTasks(options)
|
||||
return createRequestFunction(
|
||||
localVarAxiosArgs,
|
||||
globalAxios,
|
||||
BASE_PATH,
|
||||
configuration
|
||||
)
|
||||
},
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {AutoMode} [state] Zustand des Automatikmodus
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async setAutoMode(
|
||||
state?: AutoMode,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.setConfigTime(
|
||||
configTime,
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.setAutoMode(
|
||||
state,
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
|
@ -1075,19 +1167,89 @@ export const DefaultApiFp = function (configuration?: Configuration) {
|
|||
)
|
||||
},
|
||||
/**
|
||||
* Starte/stoppe manuell eine neue Bewässerungsaufgabe
|
||||
* @param {InlineObject1} [taskRequest]
|
||||
* Systemzeit einstellen
|
||||
* @param {Timestamp} [timestamp]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async startManualTask(
|
||||
taskRequest?: InlineObject1,
|
||||
async setSystemTime(
|
||||
timestamp?: Timestamp,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.startManualTask(
|
||||
taskRequest,
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.setSystemTime(
|
||||
timestamp,
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
localVarAxiosArgs,
|
||||
globalAxios,
|
||||
BASE_PATH,
|
||||
configuration
|
||||
)
|
||||
},
|
||||
/**
|
||||
* Systemzeitzone einstellen
|
||||
* @param {Timezone} [timezone]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async setSystemTimezone(
|
||||
timezone?: Timezone,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.setSystemTimezone(
|
||||
timezone,
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
localVarAxiosArgs,
|
||||
globalAxios,
|
||||
BASE_PATH,
|
||||
configuration
|
||||
)
|
||||
},
|
||||
/**
|
||||
* Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async startTask(
|
||||
zoneId?: ZoneID,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.startTask(
|
||||
zoneId,
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
localVarAxiosArgs,
|
||||
globalAxios,
|
||||
BASE_PATH,
|
||||
configuration
|
||||
)
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Stoppe eine manuelle Bewässerungsaufgabe.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
async stopTask(
|
||||
zoneId?: ZoneID,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(axios?: AxiosInstance, basePath?: string) => AxiosPromise<StatusMessage>
|
||||
> {
|
||||
const localVarAxiosArgs = await localVarAxiosParamCreator.stopTask(
|
||||
zoneId,
|
||||
options
|
||||
)
|
||||
return createRequestFunction(
|
||||
|
@ -1150,13 +1312,13 @@ export const DefaultApiFactory = function (
|
|||
/**
|
||||
*
|
||||
* @summary Lösche einen gespeicherten Zeitplan.
|
||||
* @param {number} [id]
|
||||
* @param {JobID} [jobId] JobID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
deleteJob(id?: number, options?: any): AxiosPromise<StatusMessage> {
|
||||
deleteJob(jobId?: JobID, options?: any): AxiosPromise<StatusMessage> {
|
||||
return localVarFp
|
||||
.deleteJob(id, options)
|
||||
.deleteJob(jobId, options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
|
@ -1170,16 +1332,6 @@ export const DefaultApiFactory = function (
|
|||
.getAutoMode(options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
getConfigTime(options?: any): AxiosPromise<ConfigTime> {
|
||||
return localVarFp
|
||||
.getConfigTime(options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Rufe die Standardzeit bei manueller Bewässerung ab.
|
||||
|
@ -1215,28 +1367,35 @@ export const DefaultApiFactory = function (
|
|||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {InlineObject} [state]
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
setAutoMode(state?: InlineObject, options?: any): AxiosPromise<StatusMessage> {
|
||||
getSystemTime(options?: any): AxiosPromise<SystemTime> {
|
||||
return localVarFp
|
||||
.setAutoMode(state, options)
|
||||
.getSystemTime(options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
getTasks(options?: any): AxiosPromise<TaskList> {
|
||||
return localVarFp
|
||||
.getTasks(options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {ConfigTime} [configTime]
|
||||
* @param {AutoMode} [state] Zustand des Automatikmodus
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
setConfigTime(
|
||||
configTime?: ConfigTime,
|
||||
options?: any
|
||||
): AxiosPromise<StatusMessage> {
|
||||
setAutoMode(state?: AutoMode, options?: any): AxiosPromise<StatusMessage> {
|
||||
return localVarFp
|
||||
.setConfigTime(configTime, options)
|
||||
.setAutoMode(state, options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
|
@ -1255,17 +1414,54 @@ export const DefaultApiFactory = function (
|
|||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
* Starte/stoppe manuell eine neue Bewässerungsaufgabe
|
||||
* @param {InlineObject1} [taskRequest]
|
||||
* Systemzeit einstellen
|
||||
* @param {Timestamp} [timestamp]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
startManualTask(
|
||||
taskRequest?: InlineObject1,
|
||||
setSystemTime(
|
||||
timestamp?: Timestamp,
|
||||
options?: any
|
||||
): AxiosPromise<StatusMessage> {
|
||||
return localVarFp
|
||||
.startManualTask(taskRequest, options)
|
||||
.setSystemTime(timestamp, options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
* Systemzeitzone einstellen
|
||||
* @param {Timezone} [timezone]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
setSystemTimezone(
|
||||
timezone?: Timezone,
|
||||
options?: any
|
||||
): AxiosPromise<StatusMessage> {
|
||||
return localVarFp
|
||||
.setSystemTimezone(timezone, options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
* Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
startTask(zoneId?: ZoneID, options?: any): AxiosPromise<StatusMessage> {
|
||||
return localVarFp
|
||||
.startTask(zoneId, options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @summary Stoppe eine manuelle Bewässerungsaufgabe.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
stopTask(zoneId?: ZoneID, options?: any): AxiosPromise<StatusMessage> {
|
||||
return localVarFp
|
||||
.stopTask(zoneId, options)
|
||||
.then((request) => request(axios, basePath))
|
||||
},
|
||||
/**
|
||||
|
@ -1307,14 +1503,14 @@ export class DefaultApi extends BaseAPI {
|
|||
/**
|
||||
*
|
||||
* @summary Lösche einen gespeicherten Zeitplan.
|
||||
* @param {number} [id]
|
||||
* @param {JobID} [jobId] JobID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public deleteJob(id?: number, options?: AxiosRequestConfig) {
|
||||
public deleteJob(jobId?: JobID, options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.deleteJob(id, options)
|
||||
.deleteJob(jobId, options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
|
@ -1331,18 +1527,6 @@ export class DefaultApi extends BaseAPI {
|
|||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
/**
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public getConfigTime(options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.getConfigTime(options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary Rufe die Standardzeit bei manueller Bewässerung ab.
|
||||
|
@ -1384,28 +1568,40 @@ export class DefaultApi extends BaseAPI {
|
|||
}
|
||||
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {InlineObject} [state]
|
||||
* Rufe die aktuelle Systemzeit/Zeitzone ab
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public setAutoMode(state?: InlineObject, options?: AxiosRequestConfig) {
|
||||
public getSystemTime(options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.setAutoMode(state, options)
|
||||
.getSystemTime(options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary Rufe alle momentan laufenden Bewässerungsaufgaben ab.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public getTasks(options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.getTasks(options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatikmodus aktivieren/deaktivieren
|
||||
* @param {ConfigTime} [configTime]
|
||||
* @param {AutoMode} [state] Zustand des Automatikmodus
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public setConfigTime(configTime?: ConfigTime, options?: AxiosRequestConfig) {
|
||||
public setAutoMode(state?: AutoMode, options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.setConfigTime(configTime, options)
|
||||
.setAutoMode(state, options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
|
@ -1427,15 +1623,55 @@ export class DefaultApi extends BaseAPI {
|
|||
}
|
||||
|
||||
/**
|
||||
* Starte/stoppe manuell eine neue Bewässerungsaufgabe
|
||||
* @param {InlineObject1} [taskRequest]
|
||||
* Systemzeit einstellen
|
||||
* @param {Timestamp} [timestamp]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public startManualTask(taskRequest?: InlineObject1, options?: AxiosRequestConfig) {
|
||||
public setSystemTime(timestamp?: Timestamp, options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.startManualTask(taskRequest, options)
|
||||
.setSystemTime(timestamp, options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
/**
|
||||
* Systemzeitzone einstellen
|
||||
* @param {Timezone} [timezone]
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public setSystemTimezone(timezone?: Timezone, options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.setSystemTimezone(timezone, options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
/**
|
||||
* Starte eine neue manuelle Bewässerungsaufgabe mit der eingestellten Standardzeit.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public startTask(zoneId?: ZoneID, options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.startTask(zoneId, options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @summary Stoppe eine manuelle Bewässerungsaufgabe.
|
||||
* @param {ZoneID} [zoneId] ZoneID
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
* @memberof DefaultApi
|
||||
*/
|
||||
public stopTask(zoneId?: ZoneID, options?: AxiosRequestConfig) {
|
||||
return DefaultApiFp(this.configuration)
|
||||
.stopTask(zoneId, options)
|
||||
.then((request) => request(this.axios, this.basePath))
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,6 @@ let apicfg = new Configuration({
|
|||
basePath: apiUrl,
|
||||
})
|
||||
|
||||
const sebraucApi = new DefaultApi(apicfg)
|
||||
const tsgrainApi = new DefaultApi(apicfg)
|
||||
|
||||
export {apiUrl, wsUrl, sebraucApi}
|
||||
export {apiUrl, wsUrl, tsgrainApi}
|
||||
|
|
|
@ -19,9 +19,8 @@ export function getConfig(): Config {
|
|||
return window.config
|
||||
}
|
||||
|
||||
console.error("App config not found")
|
||||
return {
|
||||
version: "dev",
|
||||
n_zones: 0,
|
||||
n_zones: 7,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +1,120 @@
|
|||
import {format, parse, parseISO} from "date-fns"
|
||||
|
||||
const S_YEAR = 31536000
|
||||
const S_DAY = 86400
|
||||
const S_HOUR = 3600
|
||||
const S_MIN = 60
|
||||
|
||||
function secondsToString(seconds: number): string {
|
||||
const numyears = Math.floor(seconds / 31536000)
|
||||
const numdays = Math.floor((seconds % 31536000) / 86400)
|
||||
const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600)
|
||||
const numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60)
|
||||
const numseconds = (((seconds % 31536000) % 86400) % 3600) % 60
|
||||
const numyears = Math.floor(seconds / S_YEAR)
|
||||
const numdays = Math.floor((seconds % S_YEAR) / S_DAY)
|
||||
const numhours = Math.floor(((seconds % S_YEAR) % S_DAY) / S_HOUR)
|
||||
const numminutes = Math.floor((((seconds % S_YEAR) % S_DAY) % S_HOUR) / S_MIN)
|
||||
const numseconds = (((seconds % S_YEAR) % S_DAY) % S_HOUR) % S_MIN
|
||||
|
||||
let res = []
|
||||
if (numyears > 0) res.push(numyears + "yr")
|
||||
if (numdays > 0) res.push(numdays + "d")
|
||||
if (numhours > 0) res.push(numhours + "h")
|
||||
if (numminutes > 0) res.push(numminutes + "m")
|
||||
if (seconds < 60) res.push(numseconds + "s")
|
||||
if (numseconds > 0 || res.length === 0) res.push(numseconds + "s")
|
||||
|
||||
return res.join(" ")
|
||||
}
|
||||
|
||||
export {secondsToString}
|
||||
function parseTimeString(timeString: string): number {
|
||||
const parts = timeString.split(/[ ,;]/)
|
||||
let seconds = 0
|
||||
const regexpPart = /^(\d+)\s*(?:([yjdthms])|$)/i
|
||||
|
||||
parts.forEach((part) => {
|
||||
const match = part.match(regexpPart)
|
||||
if (match) {
|
||||
const n = parseInt(match[1])
|
||||
const unit = match[2] === undefined ? "" : match[2].toLowerCase()
|
||||
|
||||
switch (unit) {
|
||||
case "y":
|
||||
case "j":
|
||||
seconds += n * S_YEAR
|
||||
break
|
||||
case "d":
|
||||
case "t":
|
||||
seconds += n * S_DAY
|
||||
break
|
||||
case "h":
|
||||
seconds += n * S_HOUR
|
||||
break
|
||||
case "m":
|
||||
seconds += n * S_MIN
|
||||
break
|
||||
case "s":
|
||||
seconds += n
|
||||
break
|
||||
default:
|
||||
if (seconds === 0) seconds += n * S_MIN
|
||||
else seconds += n
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return seconds
|
||||
}
|
||||
|
||||
function getTimestamp(): number {
|
||||
return Math.round(Date.now() / 1000)
|
||||
}
|
||||
|
||||
function timestampToDate(timestamp: number): Date {
|
||||
return new Date(timestamp * 1000)
|
||||
}
|
||||
|
||||
function dateToTimestamp(date: Date): number {
|
||||
return Math.round(date.getTime() / 1000)
|
||||
}
|
||||
|
||||
function timestampToString(timestamp: number): string {
|
||||
return dateToString(timestampToDate(timestamp))
|
||||
}
|
||||
|
||||
function dateToString(date: Date): string {
|
||||
return date.toLocaleString("de-DE")
|
||||
}
|
||||
|
||||
const INPUT_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"
|
||||
|
||||
function dateToInputString(date: Date): string {
|
||||
return format(date, INPUT_DATE_FORMAT)
|
||||
}
|
||||
|
||||
function inputStringToDate(inputString: string): Date {
|
||||
return parseISO(inputString)
|
||||
}
|
||||
|
||||
function handleApiError(error: any) {
|
||||
if (error.response) {
|
||||
const msg = error.response.data.msg
|
||||
|
||||
if (msg !== undefined) {
|
||||
alert("Error: " + msg)
|
||||
} else {
|
||||
alert("Error: no response")
|
||||
}
|
||||
} else {
|
||||
alert(String(error))
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
secondsToString,
|
||||
parseTimeString,
|
||||
getTimestamp,
|
||||
timestampToDate,
|
||||
dateToTimestamp,
|
||||
timestampToString,
|
||||
dateToString,
|
||||
dateToInputString,
|
||||
inputStringToDate,
|
||||
handleApiError,
|
||||
}
|
||||
|
|
|
@ -1,10 +1,19 @@
|
|||
import {wsUrl} from "./apiUrls"
|
||||
import {Task, TaskList} from "../tsgrain-client"
|
||||
import {tsgrainApi, wsUrl} from "./apiUrls"
|
||||
|
||||
class WebsocketMessage implements TaskList {
|
||||
auto_mode = false
|
||||
now = 0
|
||||
tasks: Task[] = []
|
||||
}
|
||||
|
||||
class WebsocketAPI {
|
||||
private static ws: WebsocketAPI | undefined
|
||||
private static ws?: WebsocketAPI
|
||||
|
||||
private conn: WebSocket | undefined
|
||||
private conn?: WebSocket
|
||||
private wsConnected: boolean
|
||||
private lastMessage?: WebsocketMessage
|
||||
private lastMessageDate?: Date
|
||||
|
||||
private clients: Set<WebsocketClient>
|
||||
|
||||
|
@ -40,10 +49,24 @@ class WebsocketAPI {
|
|||
window.setTimeout(() => this.connect(), 3000)
|
||||
}
|
||||
this.conn.onmessage = (evt) => {
|
||||
this.clients.forEach((client) => {
|
||||
client.msgCallback(evt)
|
||||
const msg = Object.assign(new WebsocketMessage(), JSON.parse(evt.data))
|
||||
this.broadcastMsg(msg)
|
||||
}
|
||||
|
||||
// Get initial state via REST api
|
||||
tsgrainApi.getTasks().then((response) => {
|
||||
this.broadcastMsg(response.data)
|
||||
})
|
||||
}
|
||||
|
||||
private broadcastMsg(msg: WebsocketMessage) {
|
||||
const date = new Date()
|
||||
this.lastMessage = msg
|
||||
this.lastMessageDate = date
|
||||
|
||||
this.clients.forEach((client) => {
|
||||
client.msgCallback(msg, date)
|
||||
})
|
||||
}
|
||||
|
||||
static Get(): WebsocketAPI {
|
||||
|
@ -58,26 +81,28 @@ class WebsocketAPI {
|
|||
}
|
||||
|
||||
addClient(client: WebsocketClient) {
|
||||
console.log("added client", client)
|
||||
this.clients.add(client)
|
||||
|
||||
if (this.lastMessage !== undefined && this.lastMessageDate !== undefined) {
|
||||
client.msgCallback(this.lastMessage, this.lastMessageDate)
|
||||
}
|
||||
}
|
||||
|
||||
removeClient(client: WebsocketClient) {
|
||||
console.log("removed client", client)
|
||||
this.clients.delete(client)
|
||||
}
|
||||
}
|
||||
|
||||
export default class WebsocketClient {
|
||||
class WebsocketClient {
|
||||
statusCallback: (wsConnected: boolean) => void
|
||||
msgCallback: (evt: MessageEvent) => void
|
||||
msgCallback: (msg: WebsocketMessage, date: Date) => void
|
||||
|
||||
constructor(
|
||||
statusCallback: (wsConnected: boolean) => void,
|
||||
msgCallback: (evt: MessageEvent) => void
|
||||
statusCallback?: (wsConnected: boolean) => void,
|
||||
msgCallback?: (msg: WebsocketMessage, date: Date) => void
|
||||
) {
|
||||
this.statusCallback = statusCallback
|
||||
this.msgCallback = msgCallback
|
||||
this.statusCallback = statusCallback || ((con) => {})
|
||||
this.msgCallback = msgCallback || ((msg, date) => {})
|
||||
|
||||
this.api().addClient(this)
|
||||
}
|
||||
|
@ -90,3 +115,5 @@ export default class WebsocketClient {
|
|||
this.api().removeClient(this)
|
||||
}
|
||||
}
|
||||
|
||||
export {WebsocketMessage, WebsocketClient}
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
/// <reference types="vite/client" />
|
||||
|
||||
export {}
|
|
@ -14,8 +14,6 @@
|
|||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
"jsxFactory": "h",
|
||||
"jsxFragmentFactory": "Fragment"
|
||||
"jsx": "preserve"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {defineConfig} from "vite"
|
||||
import preact from "@preact/preset-vite"
|
||||
import reactRefresh from "@vitejs/plugin-react-refresh"
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [preact()],
|
||||
plugins: [reactRefresh()],
|
||||
})
|
Loading…
Reference in a new issue